summary refs log tree commit diff stats
path: root/libs/TouchJSON
diff options
context:
space:
mode:
Diffstat (limited to 'libs/TouchJSON')
-rwxr-xr-xlibs/TouchJSON/CDataScanner.h71
-rwxr-xr-xlibs/TouchJSON/CDataScanner.m340
-rwxr-xr-xlibs/TouchJSON/Extensions/CDataScanner_Extensions.h40
-rwxr-xr-xlibs/TouchJSON/Extensions/CDataScanner_Extensions.m135
-rwxr-xr-xlibs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h37
-rwxr-xr-xlibs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m47
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONDeserializer.h63
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONDeserializer.m161
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONScanner.h95
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONScanner.m676
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONSerializer.h53
-rwxr-xr-xlibs/TouchJSON/JSON/CJSONSerializer.m342
-rwxr-xr-xlibs/TouchJSON/JSON/JSONRepresentation.h18
13 files changed, 2078 insertions, 0 deletions
diff --git a/libs/TouchJSON/CDataScanner.h b/libs/TouchJSON/CDataScanner.h new file mode 100755 index 0000000..41f68e8 --- /dev/null +++ b/libs/TouchJSON/CDataScanner.h
@@ -0,0 +1,71 @@
1//
2// CDataScanner.h
3// TouchCode
4//
5// Created by Jonathan Wight on 04/16/08.
6// Copyright 2008 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 <Foundation/Foundation.h>
31
32// NSScanner
33
34@interface CDataScanner : NSObject {
35 NSData *data;
36
37 u_int8_t *start;
38 u_int8_t *end;
39 u_int8_t *current;
40 NSUInteger length;
41}
42
43@property (readwrite, nonatomic, retain) NSData *data;
44@property (readwrite, nonatomic, assign) NSUInteger scanLocation;
45@property (readonly, nonatomic, assign) NSUInteger bytesRemaining;
46@property (readonly, nonatomic, assign) BOOL isAtEnd;
47
48- (id)initWithData:(NSData *)inData;
49
50- (unichar)currentCharacter;
51- (unichar)scanCharacter;
52- (BOOL)scanCharacter:(unichar)inCharacter;
53
54- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue;
55- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue;
56- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
57
58- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)outValue;
59- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
60
61- (BOOL)scanNumber:(NSNumber **)outValue;
62- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue;
63
64- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData;
65
66- (void)skipWhitespace;
67
68- (NSString *)remainingString;
69- (NSData *)remainingData;
70
71@end
diff --git a/libs/TouchJSON/CDataScanner.m b/libs/TouchJSON/CDataScanner.m new file mode 100755 index 0000000..b3cee6f --- /dev/null +++ b/libs/TouchJSON/CDataScanner.m
@@ -0,0 +1,340 @@
1//
2// CDataScanner.m
3// TouchCode
4//
5// Created by Jonathan Wight on 04/16/08.
6// Copyright 2008 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 "CDataScanner.h"
31
32#import "CDataScanner_Extensions.h"
33
34@interface CDataScanner ()
35@end
36
37#pragma mark -
38
39inline static unichar CharacterAtPointer(void *start, void *end)
40 {
41 #pragma unused(end)
42
43 const u_int8_t theByte = *(u_int8_t *)start;
44 if (theByte & 0x80)
45 {
46 // TODO -- UNICODE!!!! (well in theory nothing todo here)
47 }
48 const unichar theCharacter = theByte;
49 return(theCharacter);
50 }
51
52 static NSCharacterSet *sDoubleCharacters = NULL;
53
54 @implementation CDataScanner
55
56- (id)init
57 {
58 if ((self = [super init]) != NULL)
59 {
60 }
61 return(self);
62 }
63
64- (id)initWithData:(NSData *)inData;
65 {
66 if ((self = [self init]) != NULL)
67 {
68 [self setData:inData];
69 }
70 return(self);
71 }
72
73 + (void)initialize
74 {
75 if (sDoubleCharacters == NULL)
76 {
77 sDoubleCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-+."] retain];
78 }
79 }
80
81- (void)dealloc
82 {
83 [data release];
84 data = NULL;
85 //
86 [super dealloc];
87 }
88
89- (NSUInteger)scanLocation
90 {
91 return(current - start);
92 }
93
94- (NSUInteger)bytesRemaining
95 {
96 return(end - current);
97 }
98
99- (NSData *)data
100 {
101 return(data);
102 }
103
104- (void)setData:(NSData *)inData
105 {
106 if (data != inData)
107 {
108 [data release];
109 data = [inData retain];
110 }
111
112 if (data)
113 {
114 start = (u_int8_t *)data.bytes;
115 end = start + data.length;
116 current = start;
117 length = data.length;
118 }
119 else
120 {
121 start = NULL;
122 end = NULL;
123 current = NULL;
124 length = 0;
125 }
126 }
127
128- (void)setScanLocation:(NSUInteger)inScanLocation
129 {
130 current = start + inScanLocation;
131 }
132
133- (BOOL)isAtEnd
134 {
135 return(self.scanLocation >= length);
136 }
137
138- (unichar)currentCharacter
139 {
140 return(CharacterAtPointer(current, end));
141 }
142
143#pragma mark -
144
145- (unichar)scanCharacter
146 {
147 const unichar theCharacter = CharacterAtPointer(current++, end);
148 return(theCharacter);
149 }
150
151- (BOOL)scanCharacter:(unichar)inCharacter
152 {
153 unichar theCharacter = CharacterAtPointer(current, end);
154 if (theCharacter == inCharacter)
155 {
156 ++current;
157 return(YES);
158 }
159 else
160 return(NO);
161 }
162
163- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue
164 {
165 const size_t theLength = strlen(inString);
166 if ((size_t)(end - current) < theLength)
167 return(NO);
168 if (strncmp((char *)current, inString, theLength) == 0)
169 {
170 current += theLength;
171 if (outValue)
172 *outValue = [NSString stringWithUTF8String:inString];
173 return(YES);
174 }
175 return(NO);
176 }
177
178- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue
179 {
180 if ((size_t)(end - current) < inString.length)
181 return(NO);
182 if (strncmp((char *)current, [inString UTF8String], inString.length) == 0)
183 {
184 current += inString.length;
185 if (outValue)
186 *outValue = inString;
187 return(YES);
188 }
189 return(NO);
190 }
191
192- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
193 {
194 u_int8_t *P;
195 for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P)
196 ;
197
198 if (P == current)
199 {
200 return(NO);
201 }
202
203 if (outValue)
204 {
205 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
206 }
207
208 current = P;
209
210 return(YES);
211 }
212
213- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue
214 {
215 const char *theToken = [inString UTF8String];
216 const char *theResult = strnstr((char *)current, theToken, end - current);
217 if (theResult == NULL)
218 {
219 return(NO);
220 }
221
222 if (outValue)
223 {
224 *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease];
225 }
226
227 current = (u_int8_t *)theResult;
228
229 return(YES);
230 }
231
232- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
233 {
234 u_int8_t *P;
235 for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P)
236 ;
237
238 if (P == current)
239 {
240 return(NO);
241 }
242
243 if (outValue)
244 {
245 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
246 }
247
248 current = P;
249
250 return(YES);
251 }
252
253- (BOOL)scanNumber:(NSNumber **)outValue
254 {
255 NSString *theString = NULL;
256 if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString])
257 {
258 if ([theString rangeOfString:@"."].location != NSNotFound)
259 {
260 if (outValue)
261 {
262 *outValue = [NSDecimalNumber decimalNumberWithString:theString];
263 }
264 return(YES);
265 }
266 else if ([theString rangeOfString:@"-"].location != NSNotFound)
267 {
268 if (outValue != NULL)
269 {
270 *outValue = [NSNumber numberWithLongLong:[theString longLongValue]];
271 }
272 return(YES);
273 }
274 else
275 {
276 if (outValue != NULL)
277 {
278 *outValue = [NSNumber numberWithUnsignedLongLong:strtoull([theString UTF8String], NULL, 0)];
279 }
280 return(YES);
281 }
282
283 }
284 return(NO);
285 }
286
287- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue;
288 {
289 NSString *theString = NULL;
290 if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString])
291 {
292 if (outValue)
293 {
294 *outValue = [NSDecimalNumber decimalNumberWithString:theString];
295 }
296 return(YES);
297 }
298 return(NO);
299 }
300
301- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData;
302 {
303 if (self.bytesRemaining < inLength)
304 {
305 return(NO);
306 }
307
308 if (outData)
309 {
310 *outData = [NSData dataWithBytes:current length:inLength];
311 }
312
313 current += inLength;
314 return(YES);
315 }
316
317
318- (void)skipWhitespace
319 {
320 u_int8_t *P;
321 for (P = current; P < end && (isspace(*P)); ++P)
322 ;
323
324 current = P;
325 }
326
327- (NSString *)remainingString
328 {
329 NSData *theRemainingData = [NSData dataWithBytes:current length:end - current];
330 NSString *theString = [[[NSString alloc] initWithData:theRemainingData encoding:NSUTF8StringEncoding] autorelease];
331 return(theString);
332 }
333
334- (NSData *)remainingData;
335 {
336 NSData *theRemainingData = [NSData dataWithBytes:current length:end - current];
337 return(theRemainingData);
338 }
339
340 @end
diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.h b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h new file mode 100755 index 0000000..cde1dbb --- /dev/null +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.h
@@ -0,0 +1,40 @@
1//
2// CDataScanner_Extensions.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/08/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 "CDataScanner.h"
31
32@interface CDataScanner (CDataScanner_Extensions)
33
34- (BOOL)scanCStyleComment:(NSString **)outComment;
35- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment;
36
37- (NSUInteger)lineOfScanLocation;
38- (NSDictionary *)userInfoForScanLocation;
39
40@end
diff --git a/libs/TouchJSON/Extensions/CDataScanner_Extensions.m b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m new file mode 100755 index 0000000..90dbbda --- /dev/null +++ b/libs/TouchJSON/Extensions/CDataScanner_Extensions.m
@@ -0,0 +1,135 @@
1//
2// CDataScanner_Extensions.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/08/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 "CDataScanner_Extensions.h"
31
32#define LF 0x000a // Line Feed
33#define FF 0x000c // Form Feed
34#define CR 0x000d // Carriage Return
35#define NEL 0x0085 // Next Line
36#define LS 0x2028 // Line Separator
37#define PS 0x2029 // Paragraph Separator
38
39@implementation CDataScanner (CDataScanner_Extensions)
40
41- (BOOL)scanCStyleComment:(NSString **)outComment
42{
43if ([self scanString:@"/*" intoString:NULL] == YES)
44 {
45 NSString *theComment = NULL;
46 if ([self scanUpToString:@"*/" intoString:&theComment] == NO)
47 [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."];
48
49 if ([theComment rangeOfString:@"/*"].location != NSNotFound)
50 [NSException raise:NSGenericException format:@"C style comments should not be nested."];
51
52 if ([self scanString:@"*/" intoString:NULL] == NO)
53 [NSException raise:NSGenericException format:@"C style comment did not end correctly."];
54
55 if (outComment != NULL)
56 *outComment = theComment;
57
58 return(YES);
59 }
60else
61 {
62 return(NO);
63 }
64}
65
66- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment
67 {
68 if ([self scanString:@"//" intoString:NULL] == YES)
69 {
70 unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, };
71 NSCharacterSet *theLineBreaksCharacterSet = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]];
72
73 NSString *theComment = NULL;
74 [self scanUpToCharactersFromSet:theLineBreaksCharacterSet intoString:&theComment];
75 [self scanCharactersFromSet:theLineBreaksCharacterSet intoString:NULL];
76
77 if (outComment != NULL)
78 *outComment = theComment;
79
80 return(YES);
81 }
82 else
83 {
84 return(NO);
85 }
86 }
87
88- (NSUInteger)lineOfScanLocation
89 {
90 NSUInteger theLine = 0;
91 for (const u_int8_t *C = start; C < current; ++C)
92 {
93 // TODO: JIW What about MS-DOS line endings you bastard! (Also other unicode line endings)
94 if (*C == '\n' || *C == '\r')
95 {
96 ++theLine;
97 }
98 }
99 return(theLine);
100 }
101
102- (NSDictionary *)userInfoForScanLocation
103 {
104 NSUInteger theLine = 0;
105 const u_int8_t *theLineStart = start;
106 for (const u_int8_t *C = start; C < current; ++C)
107 {
108 if (*C == '\n' || *C == '\r')
109 {
110 theLineStart = C - 1;
111 ++theLine;
112 }
113 }
114
115 NSUInteger theCharacter = current - theLineStart;
116
117 NSRange theStartRange = NSIntersectionRange((NSRange){ .location = MAX((NSInteger)self.scanLocation - 20, 0), .length = 20 + (NSInteger)self.scanLocation - 20 }, (NSRange){ .location = 0, .length = self.data.length });
118 NSRange theEndRange = NSIntersectionRange((NSRange){ .location = self.scanLocation, .length = 20 }, (NSRange){ .location = 0, .length = self.data.length });
119
120
121 NSString *theSnippet = [NSString stringWithFormat:@"%@!HERE>!%@",
122 [[[NSString alloc] initWithData:[self.data subdataWithRange:theStartRange] encoding:NSUTF8StringEncoding] autorelease],
123 [[[NSString alloc] initWithData:[self.data subdataWithRange:theEndRange] encoding:NSUTF8StringEncoding] autorelease]
124 ];
125
126 NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
127 [NSNumber numberWithUnsignedInteger:theLine], @"line",
128 [NSNumber numberWithUnsignedInteger:theCharacter], @"character",
129 [NSNumber numberWithUnsignedInteger:self.scanLocation], @"location",
130 theSnippet, @"snippet",
131 NULL];
132 return(theUserInfo);
133 }
134
135@end
diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h new file mode 100755 index 0000000..6e611d0 --- /dev/null +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.h
@@ -0,0 +1,37 @@
1//
2// NSDictionary_JSONExtensions.h
3// TouchCode
4//
5// Created by Jonathan Wight on 04/17/08.
6// Copyright 2008 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 <Foundation/Foundation.h>
31
32@interface NSDictionary (NSDictionary_JSONExtensions)
33
34+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError;
35+ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError;
36
37@end
diff --git a/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m new file mode 100755 index 0000000..c0bb43c --- /dev/null +++ b/libs/TouchJSON/Extensions/NSDictionary_JSONExtensions.m
@@ -0,0 +1,47 @@
1//
2// NSDictionary_JSONExtensions.m
3// TouchCode
4//
5// Created by Jonathan Wight on 04/17/08.
6// Copyright 2008 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 "NSDictionary_JSONExtensions.h"
31
32#import "CJSONDeserializer.h"
33
34@implementation NSDictionary (NSDictionary_JSONExtensions)
35
36+ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError
37 {
38 return([[CJSONDeserializer deserializer] deserialize:inData error:outError]);
39 }
40
41+ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError;
42 {
43 NSData *theData = [inJSON dataUsingEncoding:NSUTF8StringEncoding];
44 return([self dictionaryWithJSONData:theData error:outError]);
45 }
46
47@end
diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.h b/libs/TouchJSON/JSON/CJSONDeserializer.h new file mode 100755 index 0000000..0c3ed02 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONDeserializer.h
@@ -0,0 +1,63 @@
1//
2// CJSONDeserializer.h
3// TouchCode
4//
5// Created by Jonathan Wight on 12/15/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 <Foundation/Foundation.h>
31
32#import "CJSONScanner.h"
33
34extern NSString *const kJSONDeserializerErrorDomain /* = @"CJSONDeserializerErrorDomain" */;
35
36enum {
37 kJSONDeserializationOptions_MutableContainers = kJSONScannerOptions_MutableContainers,
38 kJSONDeserializationOptions_MutableLeaves = kJSONScannerOptions_MutableLeaves,
39};
40typedef NSUInteger EJSONDeserializationOptions;
41
42@class CJSONScanner;
43
44@interface CJSONDeserializer : NSObject {
45 CJSONScanner *scanner;
46 EJSONDeserializationOptions options;
47}
48
49@property (readwrite, nonatomic, retain) CJSONScanner *scanner;
50/// Object to return instead when a null encountered in the JSON. Defaults to NSNull. Setting to null causes the scanner to skip null values.
51@property (readwrite, nonatomic, retain) id nullObject;
52/// JSON must be encoded in Unicode (UTF-8, UTF-16 or UTF-32). Use this if you expect to get the JSON in another encoding.
53@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding;
54@property (readwrite, nonatomic, assign) EJSONDeserializationOptions options;
55
56+ (id)deserializer;
57
58- (id)deserialize:(NSData *)inData error:(NSError **)outError;
59
60- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError;
61- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError;
62
63@end
diff --git a/libs/TouchJSON/JSON/CJSONDeserializer.m b/libs/TouchJSON/JSON/CJSONDeserializer.m new file mode 100755 index 0000000..27a2d03 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONDeserializer.m
@@ -0,0 +1,161 @@
1//
2// CJSONDeserializer.m
3// TouchCode
4//
5// Created by Jonathan Wight on 12/15/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 "CJSONDeserializer.h"
31
32#import "CJSONScanner.h"
33#import "CDataScanner.h"
34
35NSString *const kJSONDeserializerErrorDomain = @"CJSONDeserializerErrorDomain";
36
37@interface CJSONDeserializer ()
38@end
39
40@implementation CJSONDeserializer
41
42@synthesize scanner;
43@synthesize options;
44
45+ (id)deserializer
46 {
47 return([[[self alloc] init] autorelease]);
48 }
49
50- (id)init
51 {
52 if ((self = [super init]) != NULL)
53 {
54 }
55 return(self);
56 }
57
58- (void)dealloc
59 {
60 [scanner release];
61 scanner = NULL;
62 //
63 [super dealloc];
64 }
65
66#pragma mark -
67
68- (CJSONScanner *)scanner
69 {
70 if (scanner == NULL)
71 {
72 scanner = [[CJSONScanner alloc] init];
73 }
74 return(scanner);
75 }
76
77- (id)nullObject
78 {
79 return(self.scanner.nullObject);
80 }
81
82- (void)setNullObject:(id)inNullObject
83 {
84 self.scanner.nullObject = inNullObject;
85 }
86
87#pragma mark -
88
89- (NSStringEncoding)allowedEncoding
90 {
91 return(self.scanner.allowedEncoding);
92 }
93
94- (void)setAllowedEncoding:(NSStringEncoding)inAllowedEncoding
95 {
96 self.scanner.allowedEncoding = inAllowedEncoding;
97 }
98
99#pragma mark -
100
101- (id)deserialize:(NSData *)inData error:(NSError **)outError
102 {
103 if (inData == NULL || [inData length] == 0)
104 {
105 if (outError)
106 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
107
108 return(NULL);
109 }
110 if ([self.scanner setData:inData error:outError] == NO)
111 {
112 return(NULL);
113 }
114 id theObject = NULL;
115 if ([self.scanner scanJSONObject:&theObject error:outError] == YES)
116 return(theObject);
117 else
118 return(NULL);
119 }
120
121- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError
122 {
123 if (inData == NULL || [inData length] == 0)
124 {
125 if (outError)
126 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
127
128 return(NULL);
129 }
130 if ([self.scanner setData:inData error:outError] == NO)
131 {
132 return(NULL);
133 }
134 NSDictionary *theDictionary = NULL;
135 if ([self.scanner scanJSONDictionary:&theDictionary error:outError] == YES)
136 return(theDictionary);
137 else
138 return(NULL);
139 }
140
141- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError
142 {
143 if (inData == NULL || [inData length] == 0)
144 {
145 if (outError)
146 *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL];
147
148 return(NULL);
149 }
150 if ([self.scanner setData:inData error:outError] == NO)
151 {
152 return(NULL);
153 }
154 NSArray *theArray = NULL;
155 if ([self.scanner scanJSONArray:&theArray error:outError] == YES)
156 return(theArray);
157 else
158 return(NULL);
159 }
160
161@end
diff --git a/libs/TouchJSON/JSON/CJSONScanner.h b/libs/TouchJSON/JSON/CJSONScanner.h new file mode 100755 index 0000000..d410893 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONScanner.h
@@ -0,0 +1,95 @@
1//
2// CJSONScanner.h
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 "CDataScanner.h"
31
32enum {
33 kJSONScannerOptions_MutableContainers = 0x1,
34 kJSONScannerOptions_MutableLeaves = 0x2,
35};
36typedef NSUInteger EJSONScannerOptions;
37
38/// CDataScanner subclass that understands JSON syntax natively. You should generally use CJSONDeserializer instead of this class. (TODO - this could have been a category?)
39@interface CJSONScanner : CDataScanner {
40 BOOL strictEscapeCodes;
41 id nullObject;
42 NSStringEncoding allowedEncoding;
43 EJSONScannerOptions options;
44}
45
46@property (readwrite, nonatomic, assign) BOOL strictEscapeCodes;
47@property (readwrite, nonatomic, retain) id nullObject;
48@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding;
49@property (readwrite, nonatomic, assign) EJSONScannerOptions options;
50
51- (BOOL)setData:(NSData *)inData error:(NSError **)outError;
52
53- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError;
54- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError;
55- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError;
56- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError;
57- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError;
58
59@end
60
61extern NSString *const kJSONScannerErrorDomain /* = @"kJSONScannerErrorDomain" */;
62
63typedef enum {
64
65 // Fundamental scanning errors
66 kJSONScannerErrorCode_NothingToScan = -11,
67 kJSONScannerErrorCode_CouldNotDecodeData = -12,
68 kJSONScannerErrorCode_CouldNotSerializeData = -13,
69 kJSONScannerErrorCode_CouldNotSerializeObject = -14,
70 kJSONScannerErrorCode_CouldNotScanObject = -15,
71
72 // Dictionary scanning
73 kJSONScannerErrorCode_DictionaryStartCharacterMissing = -101,
74 kJSONScannerErrorCode_DictionaryKeyScanFailed = -102,
75 kJSONScannerErrorCode_DictionaryKeyNotTerminated = -103,
76 kJSONScannerErrorCode_DictionaryValueScanFailed = -104,
77 kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter = -105,
78 kJSONScannerErrorCode_DictionaryNotTerminated = -106,
79
80 // Array scanning
81 kJSONScannerErrorCode_ArrayStartCharacterMissing = -201,
82 kJSONScannerErrorCode_ArrayValueScanFailed = -202,
83 kJSONScannerErrorCode_ArrayValueIsNull = -203,
84 kJSONScannerErrorCode_ArrayNotTerminated = -204,
85
86 // String scanning
87 kJSONScannerErrorCode_StringNotStartedWithBackslash = -301,
88 kJSONScannerErrorCode_StringUnicodeNotDecoded = -302,
89 kJSONScannerErrorCode_StringUnknownEscapeCode = -303,
90 kJSONScannerErrorCode_StringNotTerminated = -304,
91
92 // Number scanning
93 kJSONScannerErrorCode_NumberNotScannable = -401
94
95} EJSONScannerErrorCode;
diff --git a/libs/TouchJSON/JSON/CJSONScanner.m b/libs/TouchJSON/JSON/CJSONScanner.m new file mode 100755 index 0000000..c5ffeb4 --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONScanner.m
@@ -0,0 +1,676 @@
1//
2// CJSONScanner.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 "CJSONScanner.h"
31
32#import "CDataScanner_Extensions.h"
33
34#if !defined(TREAT_COMMENTS_AS_WHITESPACE)
35#define TREAT_COMMENTS_AS_WHITESPACE 0
36#endif // !defined(TREAT_COMMENTS_AS_WHITESPACE)
37
38NSString *const kJSONScannerErrorDomain = @"kJSONScannerErrorDomain";
39
40inline static int HexToInt(char inCharacter)
41 {
42 int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, };
43 if (inCharacter >= '0' && inCharacter <= 'f')
44 return(theValues[inCharacter - '0']);
45 else
46 return(-1);
47 }
48
49@interface CJSONScanner ()
50- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue;
51@end
52
53#pragma mark -
54
55@implementation CJSONScanner
56
57@synthesize strictEscapeCodes;
58@synthesize nullObject;
59@synthesize allowedEncoding;
60@synthesize options;
61
62- (id)init
63 {
64 if ((self = [super init]) != NULL)
65 {
66 strictEscapeCodes = NO;
67 nullObject = [[NSNull null] retain];
68 }
69 return(self);
70 }
71
72- (void)dealloc
73 {
74 [nullObject release];
75 nullObject = NULL;
76 //
77 [super dealloc];
78 }
79
80#pragma mark -
81
82- (BOOL)setData:(NSData *)inData error:(NSError **)outError;
83 {
84 NSData *theData = inData;
85 if (theData && theData.length >= 4)
86 {
87 // This code is lame, but it works. Because the first character of any JSON string will always be a (ascii) control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt
88 const char *theChars = theData.bytes;
89 NSStringEncoding theEncoding = NSUTF8StringEncoding;
90 if (theChars[0] != 0 && theChars[1] == 0)
91 {
92 if (theChars[2] != 0 && theChars[3] == 0)
93 theEncoding = NSUTF16LittleEndianStringEncoding;
94 else if (theChars[2] == 0 && theChars[3] == 0)
95 theEncoding = NSUTF32LittleEndianStringEncoding;
96 }
97 else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0)
98 {
99 if (theChars[1] == 0)
100 theEncoding = NSUTF32BigEndianStringEncoding;
101 else if (theChars[1] != 0)
102 theEncoding = NSUTF16BigEndianStringEncoding;
103 }
104
105 NSString *theString = [[NSString alloc] initWithData:theData encoding:theEncoding];
106 if (theString == NULL && self.allowedEncoding != 0)
107 {
108 theString = [[NSString alloc] initWithData:theData encoding:self.allowedEncoding];
109 }
110 theData = [theString dataUsingEncoding:NSUTF8StringEncoding];
111 [theString release];
112 }
113
114 if (theData)
115 {
116 [super setData:theData];
117 return(YES);
118 }
119 else
120 {
121 if (outError)
122 {
123 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
124 @"Could not scan data. Data wasn't encoded properly?", NSLocalizedDescriptionKey,
125 NULL];
126 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
127 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotDecodeData userInfo:theUserInfo];
128 }
129 return(NO);
130 }
131 }
132
133- (void)setData:(NSData *)inData
134 {
135 [self setData:inData error:NULL];
136 }
137
138#pragma mark -
139
140- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError
141 {
142 BOOL theResult = YES;
143
144 [self skipWhitespace];
145
146 id theObject = NULL;
147
148 const unichar C = [self currentCharacter];
149 switch (C)
150 {
151 case 't':
152 if ([self scanUTF8String:"true" intoString:NULL])
153 {
154 theObject = [NSNumber numberWithBool:YES];
155 }
156 break;
157 case 'f':
158 if ([self scanUTF8String:"false" intoString:NULL])
159 {
160 theObject = [NSNumber numberWithBool:NO];
161 }
162 break;
163 case 'n':
164 if ([self scanUTF8String:"null" intoString:NULL])
165 {
166 theObject = self.nullObject;
167 }
168 break;
169 case '\"':
170 case '\'':
171 theResult = [self scanJSONStringConstant:&theObject error:outError];
172 break;
173 case '0':
174 case '1':
175 case '2':
176 case '3':
177 case '4':
178 case '5':
179 case '6':
180 case '7':
181 case '8':
182 case '9':
183 case '-':
184 theResult = [self scanJSONNumberConstant:&theObject error:outError];
185 break;
186 case '{':
187 theResult = [self scanJSONDictionary:&theObject error:outError];
188 break;
189 case '[':
190 theResult = [self scanJSONArray:&theObject error:outError];
191 break;
192 default:
193 theResult = NO;
194 if (outError)
195 {
196 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
197 @"Could not scan object. Character not a valid JSON character.", NSLocalizedDescriptionKey,
198 NULL];
199 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
200 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotScanObject userInfo:theUserInfo];
201 }
202 break;
203 }
204
205 if (outObject != NULL)
206 *outObject = theObject;
207
208 return(theResult);
209 }
210
211- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError
212 {
213 NSUInteger theScanLocation = [self scanLocation];
214
215 [self skipWhitespace];
216
217 if ([self scanCharacter:'{'] == NO)
218 {
219 if (outError)
220 {
221 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
222 @"Could not scan dictionary. Dictionary that does not start with '{' character.", NSLocalizedDescriptionKey,
223 NULL];
224 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
225 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryStartCharacterMissing userInfo:theUserInfo];
226 }
227 return(NO);
228 }
229
230 NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init];
231
232 while ([self currentCharacter] != '}')
233 {
234 [self skipWhitespace];
235
236 if ([self currentCharacter] == '}')
237 break;
238
239 NSString *theKey = NULL;
240 if ([self scanJSONStringConstant:&theKey error:outError] == NO)
241 {
242 [self setScanLocation:theScanLocation];
243 if (outError)
244 {
245 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
246 @"Could not scan dictionary. Failed to scan a key.", NSLocalizedDescriptionKey,
247 NULL];
248 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
249 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyScanFailed userInfo:theUserInfo];
250 }
251 [theDictionary release];
252 return(NO);
253 }
254
255 [self skipWhitespace];
256
257 if ([self scanCharacter:':'] == NO)
258 {
259 [self setScanLocation:theScanLocation];
260 if (outError)
261 {
262 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
263 @"Could not scan dictionary. Key was not terminated with a ':' character.", NSLocalizedDescriptionKey,
264 NULL];
265 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
266 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyNotTerminated userInfo:theUserInfo];
267 }
268 [theDictionary release];
269 return(NO);
270 }
271
272 id theValue = NULL;
273 if ([self scanJSONObject:&theValue error:outError] == NO)
274 {
275 [self setScanLocation:theScanLocation];
276 if (outError)
277 {
278 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
279 @"Could not scan dictionary. Failed to scan a value.", NSLocalizedDescriptionKey,
280 NULL];
281
282 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
283 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryValueScanFailed userInfo:theUserInfo];
284 }
285 [theDictionary release];
286 return(NO);
287 }
288
289 if (theValue == NULL && self.nullObject == NULL)
290 {
291 // If the value is a null and nullObject is also null then we're skipping this key/value pair.
292 }
293 else
294 {
295 [theDictionary setValue:theValue forKey:theKey];
296 }
297
298 [self skipWhitespace];
299 if ([self scanCharacter:','] == NO)
300 {
301 if ([self currentCharacter] != '}')
302 {
303 [self setScanLocation:theScanLocation];
304 if (outError)
305 {
306 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
307 @"Could not scan dictionary. Key value pairs not delimited with a ',' character.", NSLocalizedDescriptionKey,
308 NULL];
309 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
310 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter userInfo:theUserInfo];
311 }
312 [theDictionary release];
313 return(NO);
314 }
315 break;
316 }
317 else
318 {
319 [self skipWhitespace];
320 if ([self currentCharacter] == '}')
321 break;
322 }
323 }
324
325 if ([self scanCharacter:'}'] == NO)
326 {
327 [self setScanLocation:theScanLocation];
328 if (outError)
329 {
330 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
331 @"Could not scan dictionary. Dictionary not terminated by a '}' character.", NSLocalizedDescriptionKey,
332 NULL];
333 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
334 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryNotTerminated userInfo:theUserInfo];
335 }
336 [theDictionary release];
337 return(NO);
338 }
339
340 if (outDictionary != NULL)
341 {
342 if (self.options & kJSONScannerOptions_MutableContainers)
343 {
344 *outDictionary = [theDictionary autorelease];
345 }
346 else
347 {
348 *outDictionary = [[theDictionary copy] autorelease];
349 [theDictionary release];
350 }
351 }
352 else
353 {
354 [theDictionary release];
355 }
356
357 return(YES);
358 }
359
360- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError
361 {
362 NSUInteger theScanLocation = [self scanLocation];
363
364 [self skipWhitespace];
365
366 if ([self scanCharacter:'['] == NO)
367 {
368 if (outError)
369 {
370 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
371 @"Could not scan array. Array not started by a '[' character.", NSLocalizedDescriptionKey,
372 NULL];
373 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
374 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayStartCharacterMissing userInfo:theUserInfo];
375 }
376 return(NO);
377 }
378
379 NSMutableArray *theArray = [[NSMutableArray alloc] init];
380
381 [self skipWhitespace];
382 while ([self currentCharacter] != ']')
383 {
384 NSString *theValue = NULL;
385 if ([self scanJSONObject:&theValue error:outError] == NO)
386 {
387 [self setScanLocation:theScanLocation];
388 if (outError)
389 {
390 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
391 @"Could not scan array. Could not scan a value.", NSLocalizedDescriptionKey,
392 NULL];
393 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
394 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueScanFailed userInfo:theUserInfo];
395 }
396 [theArray release];
397 return(NO);
398 }
399
400 if (theValue == NULL)
401 {
402 if (self.nullObject != NULL)
403 {
404 if (outError)
405 {
406 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
407 @"Could not scan array. Value is NULL.", NSLocalizedDescriptionKey,
408 NULL];
409 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
410 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueIsNull userInfo:theUserInfo];
411 }
412 [theArray release];
413 return(NO);
414 }
415 }
416 else
417 {
418 [theArray addObject:theValue];
419 }
420
421 [self skipWhitespace];
422 if ([self scanCharacter:','] == NO)
423 {
424 [self skipWhitespace];
425 if ([self currentCharacter] != ']')
426 {
427 [self setScanLocation:theScanLocation];
428 if (outError)
429 {
430 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
431 @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey,
432 NULL];
433 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
434 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo];
435 }
436 [theArray release];
437 return(NO);
438 }
439
440 break;
441 }
442 [self skipWhitespace];
443 }
444
445 [self skipWhitespace];
446
447 if ([self scanCharacter:']'] == NO)
448 {
449 [self setScanLocation:theScanLocation];
450 if (outError)
451 {
452 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
453 @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey,
454 NULL];
455 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
456 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo];
457 }
458 [theArray release];
459 return(NO);
460 }
461
462 if (outArray != NULL)
463 {
464 if (self.options & kJSONScannerOptions_MutableContainers)
465 {
466 *outArray = [theArray autorelease];
467 }
468 else
469 {
470 *outArray = [[theArray copy] autorelease];
471 [theArray release];
472 }
473 }
474 else
475 {
476 [theArray release];
477 }
478 return(YES);
479 }
480
481- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError
482 {
483 NSUInteger theScanLocation = [self scanLocation];
484
485 [self skipWhitespace];
486
487 NSMutableString *theString = [[NSMutableString alloc] init];
488
489 if ([self scanCharacter:'"'] == NO)
490 {
491 [self setScanLocation:theScanLocation];
492 if (outError)
493 {
494 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
495 @"Could not scan string constant. String not started by a '\"' character.", NSLocalizedDescriptionKey,
496 NULL];
497 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
498 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotStartedWithBackslash userInfo:theUserInfo];
499 }
500 [theString release];
501 return(NO);
502 }
503
504 while ([self scanCharacter:'"'] == NO)
505 {
506 NSString *theStringChunk = NULL;
507 if ([self scanNotQuoteCharactersIntoString:&theStringChunk])
508 {
509 CFStringAppend((CFMutableStringRef)theString, (CFStringRef)theStringChunk);
510 }
511 else if ([self scanCharacter:'\\'] == YES)
512 {
513 unichar theCharacter = [self scanCharacter];
514 switch (theCharacter)
515 {
516 case '"':
517 case '\\':
518 case '/':
519 break;
520 case 'b':
521 theCharacter = '\b';
522 break;
523 case 'f':
524 theCharacter = '\f';
525 break;
526 case 'n':
527 theCharacter = '\n';
528 break;
529 case 'r':
530 theCharacter = '\r';
531 break;
532 case 't':
533 theCharacter = '\t';
534 break;
535 case 'u':
536 {
537 theCharacter = 0;
538
539 int theShift;
540 for (theShift = 12; theShift >= 0; theShift -= 4)
541 {
542 const int theDigit = HexToInt([self scanCharacter]);
543 if (theDigit == -1)
544 {
545 [self setScanLocation:theScanLocation];
546 if (outError)
547 {
548 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
549 @"Could not scan string constant. Unicode character could not be decoded.", NSLocalizedDescriptionKey,
550 NULL];
551 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
552 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnicodeNotDecoded userInfo:theUserInfo];
553 }
554 [theString release];
555 return(NO);
556 }
557 theCharacter |= (theDigit << theShift);
558 }
559 }
560 break;
561 default:
562 {
563 if (strictEscapeCodes == YES)
564 {
565 [self setScanLocation:theScanLocation];
566 if (outError)
567 {
568 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
569 @"Could not scan string constant. Unknown escape code.", NSLocalizedDescriptionKey,
570 NULL];
571 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
572 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnknownEscapeCode userInfo:theUserInfo];
573 }
574 [theString release];
575 return(NO);
576 }
577 }
578 break;
579 }
580 CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1);
581 }
582 else
583 {
584 if (outError)
585 {
586 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
587 @"Could not scan string constant. No terminating double quote character.", NSLocalizedDescriptionKey,
588 NULL];
589 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
590 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotTerminated userInfo:theUserInfo];
591 }
592 [theString release];
593 return(NO);
594 }
595 }
596
597 if (outStringConstant != NULL)
598 {
599 if (self.options & kJSONScannerOptions_MutableLeaves)
600 {
601 *outStringConstant = [theString autorelease];
602 }
603 else
604 {
605 *outStringConstant = [[theString copy] autorelease];
606 [theString release];
607 }
608 }
609 else
610 {
611 [theString release];
612 }
613
614 return(YES);
615 }
616
617- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError
618 {
619 NSNumber *theNumber = NULL;
620
621 [self skipWhitespace];
622
623 if ([self scanNumber:&theNumber] == YES)
624 {
625 if (outNumberConstant != NULL)
626 *outNumberConstant = theNumber;
627 return(YES);
628 }
629 else
630 {
631 if (outError)
632 {
633 NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
634 @"Could not scan number constant.", NSLocalizedDescriptionKey,
635 NULL];
636 [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation];
637 *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_NumberNotScannable userInfo:theUserInfo];
638 }
639 return(NO);
640 }
641 }
642
643#if TREAT_COMMENTS_AS_WHITESPACE
644- (void)skipWhitespace
645 {
646 [super skipWhitespace];
647 [self scanCStyleComment:NULL];
648 [self scanCPlusPlusStyleComment:NULL];
649 [super skipWhitespace];
650 }
651#endif // TREAT_COMMENTS_AS_WHITESPACE
652
653#pragma mark -
654
655- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue
656 {
657 u_int8_t *P;
658 for (P = current; P < end && *P != '\"' && *P != '\\'; ++P)
659 ;
660
661 if (P == current)
662 {
663 return(NO);
664 }
665
666 if (outValue)
667 {
668 *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
669 }
670
671 current = P;
672
673 return(YES);
674 }
675
676@end
diff --git a/libs/TouchJSON/JSON/CJSONSerializer.h b/libs/TouchJSON/JSON/CJSONSerializer.h new file mode 100755 index 0000000..748a85c --- /dev/null +++ b/libs/TouchJSON/JSON/CJSONSerializer.h
@@ -0,0 +1,53 @@
1//
2// CJSONSerializer.h
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 <Foundation/Foundation.h>
31
32@interface CJSONSerializer : NSObject {
33}
34
35+ (id)serializer;
36
37- (BOOL)isValidJSONObject:(id)inObject;
38
39/// Take any JSON compatible object (generally NSNull, NSNumber, NSString, NSArray and NSDictionary) and produce an NSData containing the serialized JSON.
40- (NSData *)serializeObject:(id)inObject error:(NSError **)outError;
41
42- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError;
43- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError;
44- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError;
45- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError;
46- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError;
47
48@end
49
50typedef enum {
51 CJSONSerializerErrorCouldNotSerializeDataType = -1,
52 CJSONSerializerErrorCouldNotSerializeObject = -1
53} CJSONSerializerError;
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
diff --git a/libs/TouchJSON/JSON/JSONRepresentation.h b/libs/TouchJSON/JSON/JSONRepresentation.h new file mode 100755 index 0000000..a83d76f --- /dev/null +++ b/libs/TouchJSON/JSON/JSONRepresentation.h
@@ -0,0 +1,18 @@
1//
2// JSONRepresentation.h
3// TouchJSON
4//
5// Created by Jonathan Wight on 10/15/10.
6// Copyright 2010 toxicsoftware.com. All rights reserved.
7//
8
9#import <Foundation/Foundation.h>
10
11@protocol JSONRepresentation
12
13@optional
14- (id)initWithJSONDataRepresentation:(NSData *)inJSONData;
15
16- (NSData *)JSONDataRepresentation;
17
18@end