summary refs log tree commit diff stats
path: root/libs/TouchJSON/JSON/CJSONSerializer.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/TouchJSON/JSON/CJSONSerializer.m')
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONSerializer.m342
1 files changed, 342 insertions, 0 deletions
diff --git a/libs/TouchJSON/JSON/CJSONSerializer.m b/libs/TouchJSON/JSON/CJSONSerializer.m new file mode 100755 index 0000000..952b3c2 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONSerializer.m
@@ -0,0 +1,342 @@
1//
2// CJSONSerializer.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/07/2005.
6// Copyright 2005 toxicsoftware.com. All rights reserved.
7//
8// Permission is hereby granted, free of charge, to any person
9// obtaining a copy of this software and associated documentation
10// files (the "Software"), to deal in the Software without
11// restriction, including without limitation the rights to use,
12// copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the
14// Software is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27// OTHER DEALINGS IN THE SOFTWARE.
28//
29
30#import "CJSONSerializer.h"
31
32#import "JSONRepresentation.h"
33
34static NSData *kNULL = NULL;
35static NSData *kFalse = NULL;
36static NSData *kTrue = NULL;
37
38@implementation CJSONSerializer
39
40+ (void)initialize
41 {
42 NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
43
44 if (self == [CJSONSerializer class])
45 {
46 if (kNULL == NULL)
47 kNULL = [[NSData alloc] initWithBytesNoCopy:(void *)"null" length:4 freeWhenDone:NO];
48 if (kFalse == NULL)
49 kFalse = [[NSData alloc] initWithBytesNoCopy:(void *)"false" length:5 freeWhenDone:NO];
50 if (kTrue == NULL)
51 kTrue = [[NSData alloc] initWithBytesNoCopy:(void *)"true" length:4 freeWhenDone:NO];
52
53 [thePool release];
54 }
55 }
56
57+ (id)serializer
58 {
59 return([[[self alloc] init] autorelease]);
60 }
61
62- (BOOL)isValidJSONObject:(id)inObject
63 {
64 if ([inObject isKindOfClass:[NSNull class]])
65 {
66 return(YES);
67 }
68 else if ([inObject isKindOfClass:[NSNumber class]])
69 {
70 return(YES);
71 }
72 else if ([inObject isKindOfClass:[NSString class]])
73 {
74 return(YES);
75 }
76 else if ([inObject isKindOfClass:[NSArray class]])
77 {
78 return(YES);
79 }
80 else if ([inObject isKindOfClass:[NSDictionary class]])
81 {
82 return(YES);
83 }
84 else if ([inObject isKindOfClass:[NSData class]])
85 {
86 return(YES);
87 }
88 else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)])
89 {
90 return(YES);
91 }
92 else
93 {
94 return(NO);
95 }
96 }
97
98- (NSData *)serializeObject:(id)inObject error:(NSError **)outError
99 {
100 NSData *theResult = NULL;
101
102 if ([inObject isKindOfClass:[NSNull class]])
103 {
104 theResult = [self serializeNull:inObject error:outError];
105 }
106 else if ([inObject isKindOfClass:[NSNumber class]])
107 {
108 theResult = [self serializeNumber:inObject error:outError];
109 }
110 else if ([inObject isKindOfClass:[NSString class]])
111 {
112 theResult = [self serializeString:inObject error:outError];
113 }
114 else if ([inObject isKindOfClass:[NSArray class]])
115 {
116 theResult = [self serializeArray:inObject error:outError];
117 }
118 else if ([inObject isKindOfClass:[NSDictionary class]])
119 {
120 theResult = [self serializeDictionary:inObject error:outError];
121 }
122 else if ([inObject isKindOfClass:[NSData class]])
123 {
124 NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease];
125 theResult = [self serializeString:theString error:outError];
126 }
127 else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)])
128 {
129 theResult = [inObject JSONDataRepresentation];
130 }
131 else
132 {
133 if (outError)
134 {
135 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
136 [NSString stringWithFormat:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])], NSLocalizedDescriptionKey,
137 NULL];
138 *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeDataType userInfo:theUserInfo];
139 }
140 return(NULL);
141 }
142 if (theResult == NULL)
143 {
144 if (outError)
145 {
146 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
147 [NSString stringWithFormat:@"Could not serialize object '%@'", inObject], NSLocalizedDescriptionKey,
148 NULL];
149 *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeObject userInfo:theUserInfo];
150 }
151 return(NULL);
152 }
153 return(theResult);
154 }
155
156- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError
157 {
158 #pragma unused (inNull, outError)
159 return(kNULL);
160 }
161
162- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError
163 {
164 #pragma unused (outError)
165 NSData *theResult = NULL;
166 switch (CFNumberGetType((CFNumberRef)inNumber))
167 {
168 case kCFNumberCharType:
169 {
170 int theValue = [inNumber intValue];
171 if (theValue == 0)
172 theResult = kFalse;
173 else if (theValue == 1)
174 theResult = kTrue;
175 else
176 theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
177 }
178 break;
179 case kCFNumberFloat32Type:
180 case kCFNumberFloat64Type:
181 case kCFNumberFloatType:
182 case kCFNumberDoubleType:
183 case kCFNumberSInt8Type:
184 case kCFNumberSInt16Type:
185 case kCFNumberSInt32Type:
186 case kCFNumberSInt64Type:
187 case kCFNumberShortType:
188 case kCFNumberIntType:
189 case kCFNumberLongType:
190 case kCFNumberLongLongType:
191 case kCFNumberCFIndexType:
192 default:
193 theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
194 break;
195 }
196 return(theResult);
197 }
198
199- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError
200 {
201 #pragma unused (outError)
202
203 const char *theUTF8String = [inString UTF8String];
204
205 NSMutableData *theData = [NSMutableData dataWithLength:strlen(theUTF8String) * 2 + 2];
206
207 char *theOutputStart = [theData mutableBytes];
208 char *OUT = theOutputStart;
209
210 *OUT++ = '"';
211
212 for (const char *IN = theUTF8String; IN && *IN != '\0'; ++IN)
213 {
214 switch (*IN)
215 {
216 case '\\':
217 {
218 *OUT++ = '\\';
219 *OUT++ = '\\';
220 }
221 break;
222 case '\"':
223 {
224 *OUT++ = '\\';
225 *OUT++ = '\"';
226 }
227 break;
228 case '/':
229 {
230 *OUT++ = '\\';
231 *OUT++ = '/';
232 }
233 break;
234 case '\b':
235 {
236 *OUT++ = '\\';
237 *OUT++ = 'b';
238 }
239 break;
240 case '\f':
241 {
242 *OUT++ = '\\';
243 *OUT++ = 'f';
244 }
245 break;
246 case '\n':
247 {
248 *OUT++ = '\\';
249 *OUT++ = 'n';
250 }
251 break;
252 case '\r':
253 {
254 *OUT++ = '\\';
255 *OUT++ = 'r';
256 }
257 break;
258 case '\t':
259 {
260 *OUT++ = '\\';
261 *OUT++ = 't';
262 }
263 break;
264 default:
265 {
266 *OUT++ = *IN;
267 }
268 break;
269 }
270 }
271
272 *OUT++ = '"';
273
274 theData.length = OUT - theOutputStart;
275 return(theData);
276 }
277
278- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError
279 {
280 NSMutableData *theData = [NSMutableData data];
281
282 [theData appendBytes:"[" length:1];
283
284 NSEnumerator *theEnumerator = [inArray objectEnumerator];
285 id theValue = NULL;
286 NSUInteger i = 0;
287 while ((theValue = [theEnumerator nextObject]) != NULL)
288 {
289 NSData *theValueData = [self serializeObject:theValue error:outError];
290 if (theValueData == NULL)
291 {
292 return(NULL);
293 }
294 [theData appendData:theValueData];
295 if (++i < [inArray count])
296 [theData appendBytes:"," length:1];
297 }
298
299 [theData appendBytes:"]" length:1];
300
301 return(theData);
302 }
303
304- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError
305 {
306 NSMutableData *theData = [NSMutableData data];
307
308 [theData appendBytes:"{" length:1];
309
310 NSArray *theKeys = [inDictionary allKeys];
311 NSEnumerator *theEnumerator = [theKeys objectEnumerator];
312 NSString *theKey = NULL;
313 while ((theKey = [theEnumerator nextObject]) != NULL)
314 {
315 id theValue = [inDictionary objectForKey:theKey];
316
317 NSData *theKeyData = [self serializeString:theKey error:outError];
318 if (theKeyData == NULL)
319 {
320 return(NULL);
321 }
322 NSData *theValueData = [self serializeObject:theValue error:outError];
323 if (theValueData == NULL)
324 {
325 return(NULL);
326 }
327
328
329 [theData appendData:theKeyData];
330 [theData appendBytes:":" length:1];
331 [theData appendData:theValueData];
332
333 if (theKey != [theKeys lastObject])
334 [theData appendData:[@"," dataUsingEncoding:NSASCIIStringEncoding]];
335 }
336
337 [theData appendBytes:"}" length:1];
338
339 return(theData);
340 }
341
342@end