summary refs log tree commit diff stats
path: root/libs/TouchJSON/JSON
diff options
context:
space:
mode:
authorStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
committerStarla Insigna <starla4444@gmail.com>2011-07-30 11:19:14 -0400
commit9cd57b731ab1c666d4a1cb725538fdc137763d12 (patch)
tree5bac45ae5157a1cb10c6e45500cbf72789917980 /libs/TouchJSON/JSON
downloadcartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.gz
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.bz2
cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.zip
Initial commit (version 0.2.1)
Diffstat (limited to 'libs/TouchJSON/JSON')
-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
7 files changed, 1408 insertions, 0 deletions
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