7640978c05911c8a78dca43c50c1a13231557441
[atutor.git] / mods / atsocial_iphone_app / TouchJSON / CDataScanner.m
1 //
2 //  CDataScanner.m
3 //  TouchJSON
4 //
5 //  Created by Jonathan Wight on 04/16/08.
6 //  Copyright 2008 toxicsoftware.com. All rights reserved.
7 //
8
9 #import "CDataScanner.h"
10
11 #import "CDataScanner_Extensions.h"
12
13 @interface CDataScanner ()
14 @property (readwrite, retain) NSCharacterSet *doubleCharacters;
15 @end
16
17 #pragma mark -
18
19 inline static unichar CharacterAtPointer(void *start, void *end)
20 {
21
22         const u_int8_t theByte = *(u_int8_t *)start;
23 if (theByte & 0x80)
24         {
25         // TODO -- UNICODE!!!!
26         }
27 const unichar theCharacter = theByte;
28 return(theCharacter);
29 }
30
31 @implementation CDataScanner
32
33 @dynamic data;
34 @dynamic scanLocation;
35 @dynamic isAtEnd;
36 @synthesize doubleCharacters;
37
38 + (id)scannerWithData:(NSData *)inData
39 {
40 CDataScanner *theScanner = [[[self alloc] init] autorelease];
41 theScanner.data = inData;
42 return(theScanner);
43 }
44
45 - (id)init
46 {
47 if ((self = [super init]) != nil)
48         {
49         self.doubleCharacters = [NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-."];
50         }
51 return(self);
52 }
53
54 - (void)dealloc
55 {
56 self.data = NULL;
57 self.doubleCharacters = NULL;
58 //
59 [super dealloc];
60 }
61
62 - (NSInteger)scanLocation
63 {
64 return current - start;
65 }
66
67 - (NSData *)data
68 {
69 return(data); 
70 }
71
72 - (void)setData:(NSData *)inData
73 {
74 if (data != inData)
75         {
76         if (data)
77                 {
78                 [data autorelease];
79                 data = NULL;
80                 }
81         
82         if (inData)
83                 {
84                 data = [inData retain];
85                 //
86                 start = (u_int8_t *)data.bytes;
87                 end = start + data.length;
88                 current = start;
89                 length = data.length;
90                 }
91     }
92 }
93
94 - (void)setScanLocation:(NSInteger)inScanLocation
95 {
96 current = start + inScanLocation;
97 }
98
99 - (BOOL)isAtEnd
100 {
101 return(self.scanLocation >= length);
102 }
103
104 - (unichar)currentCharacter
105 {
106 return(CharacterAtPointer(current, end));
107 }
108
109 - (unichar)scanCharacter
110 {
111 const unichar theCharacter = CharacterAtPointer(current++, end);
112 return(theCharacter);
113 }
114
115 - (BOOL)scanCharacter:(unichar)inCharacter
116 {
117 unichar theCharacter = CharacterAtPointer(current, end);
118 if (theCharacter == inCharacter)
119         {
120         ++current;
121         return(YES);
122         }
123 else
124         return(NO);
125 }
126
127 - (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue;
128 {
129 const size_t theLength = strlen(inString);
130 if (end - current < theLength)
131         return(NO);
132 if (strncmp((char *)current, inString, theLength) == 0)
133         {
134         current += theLength;
135         if (outValue)
136                 *outValue = [NSString stringWithUTF8String:inString];
137         return(YES);
138         }
139 return(NO);
140 }
141
142 - (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue
143 {
144 if (end - current < inString.length)
145         return(NO);
146 if (strncmp((char *)current, [inString UTF8String], inString.length) == 0)
147         {
148         current += inString.length;
149         if (outValue)
150                 *outValue = inString;
151         return(YES);
152         }
153 return(NO);
154 }
155
156 - (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
157 {
158 u_int8_t *P;
159 for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P)
160         ;
161
162 if (P == current)
163         {
164         return(NO);
165         }
166
167 if (outValue)
168         {
169         *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
170         }
171         
172 current = P;
173
174 return(YES);
175 }
176
177 - (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue
178 {
179 const char *theToken = [inString UTF8String];
180 const char *theResult = strnstr((char *)current, theToken, end - current);
181 if (theResult == NULL)
182         {
183         return(NO);
184         }
185
186 if (outValue)
187         {
188         *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease];
189         }
190
191 current = (u_int8_t *)theResult;
192
193 return(YES);
194 }
195
196 - (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
197 {
198 u_int8_t *P;
199 for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P)
200         ;
201
202 if (P == current)
203         {
204         return(NO);
205         }
206
207 if (outValue)
208         {
209         *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
210         }
211         
212 current = P;
213
214 return(YES);
215 }
216
217 - (BOOL)scanNumber:(NSNumber **)outValue
218 {
219 // Replace all of this with a strtod call
220 NSString *theString = NULL;
221 if ([self scanCharactersFromSet:doubleCharacters intoString:&theString])
222         {
223         if (outValue)
224                 *outValue = [NSNumber numberWithDouble:[theString doubleValue]]; // TODO dont use doubleValue
225         return(YES);
226         }
227 return(NO);
228 }
229
230 @end