summary refs log tree commit diff stats
path: root/libs/TouchJSON/CDataScanner.m
diff options
context:
space:
mode:
Diffstat (limited to 'libs/TouchJSON/CDataScanner.m')
-rwxr-xr-xlibs/TouchJSON/CDataScanner.m340
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
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