diff options
Diffstat (limited to 'libs/TouchJSON/CDataScanner.m')
-rwxr-xr-x | libs/TouchJSON/CDataScanner.m | 340 |
1 files changed, 340 insertions, 0 deletions
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 | |||
39 | inline 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 | ||