iCuke 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +1 -1
- data/Gemfile +12 -0
- data/Gemfile.lock +41 -0
- data/README.markdown +126 -0
- data/Rakefile +34 -12
- data/VERSION +1 -1
- data/bin/icuke +12 -10
- data/ext/Rakefile +6 -0
- data/ext/iCuke/{sdk3.1/DefaultsResponse.h → DefaultsResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/DefaultsResponse.m → DefaultsResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/EventResponse.h → EventResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/EventResponse.m → EventResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/ModuleResponse.h → ModuleResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/ModuleResponse.m → ModuleResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/QuitResponse.h → QuitResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/QuitResponse.m → QuitResponse.m} +0 -0
- data/ext/iCuke/Rakefile +14 -13
- data/ext/iCuke/{sdk3.1/Recorder.h → Recorder.h} +0 -0
- data/ext/iCuke/{sdk3.1/Recorder.m → Recorder.m} +0 -0
- data/ext/iCuke/{sdk3.1/RecorderResponse.h → RecorderResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/RecorderResponse.m → RecorderResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/SynthesizeSingleton.h → SynthesizeSingleton.h} +0 -0
- data/ext/iCuke/{sdk3.1/ViewResponse.h → ViewResponse.h} +0 -0
- data/ext/iCuke/{sdk3.1/ViewResponse.m → ViewResponse.m} +0 -0
- data/ext/iCuke/{sdk3.1/Viewer.h → Viewer.h} +0 -0
- data/ext/iCuke/{sdk4.0/Viewer.m → Viewer.m} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.h → iCukeHTTPResponseHandler.h} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPResponseHandler.m → iCukeHTTPResponseHandler.m} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeHTTPServer.h → iCukeHTTPServer.h} +0 -0
- data/ext/iCuke/{sdk4.0/iCukeHTTPServer.m → iCukeHTTPServer.m} +4 -2
- data/ext/iCuke/{sdk3.1/iCukeServer.h → iCukeServer.h} +0 -0
- data/ext/iCuke/{sdk3.1/iCukeServer.m → iCukeServer.m} +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/JSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSObject+SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/NSString+SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJSON.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJSON.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonBase.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonParser.m +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.h +0 -0
- data/ext/iCuke/{sdk3.1/json → json}/SBJsonWriter.m +0 -0
- data/features/starting_project.feature +18 -0
- data/features/step_definitions/shell.rb +41 -0
- data/features/support/env.rb +2 -0
- data/features/support/environment.rb +40 -0
- data/features/supported_sdks.feature +12 -0
- data/iCuke.gemspec +149 -161
- data/lib/icuke/configuration.rb +19 -0
- data/lib/icuke/core_ext.rb +27 -0
- data/lib/icuke/cucumber.rb +29 -265
- data/lib/icuke/cucumber_compat.rb +4 -0
- data/lib/icuke/icuke_world.rb +149 -0
- data/lib/icuke/sdk.rb +5 -13
- data/lib/icuke/simulator_driver.rb +201 -0
- data/lib/icuke/waxsim.rb +47 -9
- data/spec/cucumber_spec.rb +130 -0
- data/spec/fixtures/controls_page.xml +252 -0
- data/spec/process_spec.rb +76 -0
- data/spec/screen_spec.rb +173 -0
- data/spec/simulate_spec.rb +75 -0
- data/spec/simulator_spec.rb +28 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +67 -0
- metadata +222 -121
- data/.gitignore +0 -15
- data/README.rdoc +0 -68
- data/ext/WaxSim/Simulator.h +0 -31
- data/ext/WaxSim/Simulator.m +0 -131
- data/ext/WaxSim/WaxSim.m +0 -110
- data/ext/WaxSim/WaxSim.xcodeproj/project.pbxproj +0 -238
- data/ext/WaxSim/WaxSim_Prefix.pch +0 -7
- data/ext/WaxSim/build/Release/waxsim +0 -0
- data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Info.plist +0 -20
- data/ext/WaxSim/build/Release/waxsim.dSYM/Contents/Resources/DWARF/waxsim +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/Simulator.o +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/WaxSim.o +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/Objects-normal/x86_64/waxsim.LinkFileList +0 -2
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim.dep +0 -6
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/WaxSim~.dep +0 -6
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state.dat +0 -227
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/build-state~.dat +0 -227
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-all-target-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-generated-files.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-own-target-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim-project-headers.hmap +0 -0
- data/ext/WaxSim/build/WaxSim.build/Release/WaxSim.build/waxsim.hmap +0 -0
- data/ext/WaxSim/iPhoneSimulatorRemoteClient/iPhoneSimulatorRemoteClient.h +0 -126
- data/ext/iCuke/sdk3.1/Rakefile +0 -20
- data/ext/iCuke/sdk3.1/Viewer.m +0 -203
- data/ext/iCuke/sdk3.1/iCukeHTTPServer.m +0 -365
- data/ext/iCuke/sdk4.0/DefaultsResponse.h +0 -5
- data/ext/iCuke/sdk4.0/DefaultsResponse.m +0 -66
- data/ext/iCuke/sdk4.0/EventResponse.h +0 -5
- data/ext/iCuke/sdk4.0/EventResponse.m +0 -130
- data/ext/iCuke/sdk4.0/ModuleResponse.h +0 -5
- data/ext/iCuke/sdk4.0/ModuleResponse.m +0 -76
- data/ext/iCuke/sdk4.0/QuitResponse.h +0 -5
- data/ext/iCuke/sdk4.0/QuitResponse.m +0 -23
- data/ext/iCuke/sdk4.0/Rakefile +0 -20
- data/ext/iCuke/sdk4.0/Recorder.h +0 -17
- data/ext/iCuke/sdk4.0/Recorder.m +0 -90
- data/ext/iCuke/sdk4.0/RecorderResponse.h +0 -6
- data/ext/iCuke/sdk4.0/RecorderResponse.m +0 -68
- data/ext/iCuke/sdk4.0/SynthesizeSingleton.h +0 -68
- data/ext/iCuke/sdk4.0/ViewResponse.h +0 -5
- data/ext/iCuke/sdk4.0/ViewResponse.m +0 -84
- data/ext/iCuke/sdk4.0/Viewer.h +0 -8
- data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.h +0 -50
- data/ext/iCuke/sdk4.0/iCukeHTTPResponseHandler.m +0 -381
- data/ext/iCuke/sdk4.0/iCukeHTTPServer.h +0 -53
- data/ext/iCuke/sdk4.0/iCukeServer.h +0 -14
- data/ext/iCuke/sdk4.0/iCukeServer.m +0 -65
- data/ext/iCuke/sdk4.0/json/JSON.h +0 -50
- data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.h +0 -68
- data/ext/iCuke/sdk4.0/json/NSObject+SBJSON.m +0 -53
- data/ext/iCuke/sdk4.0/json/NSString+SBJSON.h +0 -58
- data/ext/iCuke/sdk4.0/json/NSString+SBJSON.m +0 -55
- data/ext/iCuke/sdk4.0/json/SBJSON.h +0 -75
- data/ext/iCuke/sdk4.0/json/SBJSON.m +0 -212
- data/ext/iCuke/sdk4.0/json/SBJsonBase.h +0 -86
- data/ext/iCuke/sdk4.0/json/SBJsonBase.m +0 -78
- data/ext/iCuke/sdk4.0/json/SBJsonParser.h +0 -87
- data/ext/iCuke/sdk4.0/json/SBJsonParser.m +0 -475
- data/ext/iCuke/sdk4.0/json/SBJsonWriter.h +0 -129
- data/ext/iCuke/sdk4.0/json/SBJsonWriter.m +0 -228
@@ -1,475 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
Copyright (C) 2009 Stig Brautaset. All rights reserved.
|
3
|
-
|
4
|
-
Redistribution and use in source and binary forms, with or without
|
5
|
-
modification, are permitted provided that the following conditions are met:
|
6
|
-
|
7
|
-
* Redistributions of source code must retain the above copyright notice, this
|
8
|
-
list of conditions and the following disclaimer.
|
9
|
-
|
10
|
-
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
this list of conditions and the following disclaimer in the documentation
|
12
|
-
and/or other materials provided with the distribution.
|
13
|
-
|
14
|
-
* Neither the name of the author nor the names of its contributors may be used
|
15
|
-
to endorse or promote products derived from this software without specific
|
16
|
-
prior written permission.
|
17
|
-
|
18
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
-
*/
|
29
|
-
|
30
|
-
#import "SBJsonParser.h"
|
31
|
-
|
32
|
-
@interface SBJsonParser ()
|
33
|
-
|
34
|
-
- (BOOL)scanValue:(NSObject **)o;
|
35
|
-
|
36
|
-
- (BOOL)scanRestOfArray:(NSMutableArray **)o;
|
37
|
-
- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o;
|
38
|
-
- (BOOL)scanRestOfNull:(NSNull **)o;
|
39
|
-
- (BOOL)scanRestOfFalse:(NSNumber **)o;
|
40
|
-
- (BOOL)scanRestOfTrue:(NSNumber **)o;
|
41
|
-
- (BOOL)scanRestOfString:(NSMutableString **)o;
|
42
|
-
|
43
|
-
// Cannot manage without looking at the first digit
|
44
|
-
- (BOOL)scanNumber:(NSNumber **)o;
|
45
|
-
|
46
|
-
- (BOOL)scanHexQuad:(unichar *)x;
|
47
|
-
- (BOOL)scanUnicodeChar:(unichar *)x;
|
48
|
-
|
49
|
-
- (BOOL)scanIsAtEnd;
|
50
|
-
|
51
|
-
@end
|
52
|
-
|
53
|
-
#define skipWhitespace(c) while (isspace(*c)) c++
|
54
|
-
#define skipDigits(c) while (isdigit(*c)) c++
|
55
|
-
|
56
|
-
|
57
|
-
@implementation SBJsonParser
|
58
|
-
|
59
|
-
static char ctrl[0x22];
|
60
|
-
|
61
|
-
+ (void)initialize
|
62
|
-
{
|
63
|
-
ctrl[0] = '\"';
|
64
|
-
ctrl[1] = '\\';
|
65
|
-
for (int i = 1; i < 0x20; i++)
|
66
|
-
ctrl[i+1] = i;
|
67
|
-
ctrl[0x21] = 0;
|
68
|
-
}
|
69
|
-
|
70
|
-
/**
|
71
|
-
@deprecated This exists in order to provide fragment support in older APIs in one more version.
|
72
|
-
It should be removed in the next major version.
|
73
|
-
*/
|
74
|
-
- (id)fragmentWithString:(id)repr {
|
75
|
-
[self clearErrorTrace];
|
76
|
-
|
77
|
-
if (!repr) {
|
78
|
-
[self addErrorWithCode:EINPUT description:@"Input was 'nil'"];
|
79
|
-
return nil;
|
80
|
-
}
|
81
|
-
|
82
|
-
depth = 0;
|
83
|
-
c = [repr UTF8String];
|
84
|
-
|
85
|
-
id o;
|
86
|
-
if (![self scanValue:&o]) {
|
87
|
-
return nil;
|
88
|
-
}
|
89
|
-
|
90
|
-
// We found some valid JSON. But did it also contain something else?
|
91
|
-
if (![self scanIsAtEnd]) {
|
92
|
-
[self addErrorWithCode:ETRAILGARBAGE description:@"Garbage after JSON"];
|
93
|
-
return nil;
|
94
|
-
}
|
95
|
-
|
96
|
-
NSAssert1(o, @"Should have a valid object from %@", repr);
|
97
|
-
return o;
|
98
|
-
}
|
99
|
-
|
100
|
-
- (id)objectWithString:(NSString *)repr {
|
101
|
-
|
102
|
-
id o = [self fragmentWithString:repr];
|
103
|
-
if (!o)
|
104
|
-
return nil;
|
105
|
-
|
106
|
-
// Check that the object we've found is a valid JSON container.
|
107
|
-
if (![o isKindOfClass:[NSDictionary class]] && ![o isKindOfClass:[NSArray class]]) {
|
108
|
-
[self addErrorWithCode:EFRAGMENT description:@"Valid fragment, but not JSON"];
|
109
|
-
return nil;
|
110
|
-
}
|
111
|
-
|
112
|
-
return o;
|
113
|
-
}
|
114
|
-
|
115
|
-
/*
|
116
|
-
In contrast to the public methods, it is an error to omit the error parameter here.
|
117
|
-
*/
|
118
|
-
- (BOOL)scanValue:(NSObject **)o
|
119
|
-
{
|
120
|
-
skipWhitespace(c);
|
121
|
-
|
122
|
-
switch (*c++) {
|
123
|
-
case '{':
|
124
|
-
return [self scanRestOfDictionary:(NSMutableDictionary **)o];
|
125
|
-
break;
|
126
|
-
case '[':
|
127
|
-
return [self scanRestOfArray:(NSMutableArray **)o];
|
128
|
-
break;
|
129
|
-
case '"':
|
130
|
-
return [self scanRestOfString:(NSMutableString **)o];
|
131
|
-
break;
|
132
|
-
case 'f':
|
133
|
-
return [self scanRestOfFalse:(NSNumber **)o];
|
134
|
-
break;
|
135
|
-
case 't':
|
136
|
-
return [self scanRestOfTrue:(NSNumber **)o];
|
137
|
-
break;
|
138
|
-
case 'n':
|
139
|
-
return [self scanRestOfNull:(NSNull **)o];
|
140
|
-
break;
|
141
|
-
case '-':
|
142
|
-
case '0'...'9':
|
143
|
-
c--; // cannot verify number correctly without the first character
|
144
|
-
return [self scanNumber:(NSNumber **)o];
|
145
|
-
break;
|
146
|
-
case '+':
|
147
|
-
[self addErrorWithCode:EPARSENUM description: @"Leading + disallowed in number"];
|
148
|
-
return NO;
|
149
|
-
break;
|
150
|
-
case 0x0:
|
151
|
-
[self addErrorWithCode:EEOF description:@"Unexpected end of string"];
|
152
|
-
return NO;
|
153
|
-
break;
|
154
|
-
default:
|
155
|
-
[self addErrorWithCode:EPARSE description: @"Unrecognised leading character"];
|
156
|
-
return NO;
|
157
|
-
break;
|
158
|
-
}
|
159
|
-
|
160
|
-
NSAssert(0, @"Should never get here");
|
161
|
-
return NO;
|
162
|
-
}
|
163
|
-
|
164
|
-
- (BOOL)scanRestOfTrue:(NSNumber **)o
|
165
|
-
{
|
166
|
-
if (!strncmp(c, "rue", 3)) {
|
167
|
-
c += 3;
|
168
|
-
*o = [NSNumber numberWithBool:YES];
|
169
|
-
return YES;
|
170
|
-
}
|
171
|
-
[self addErrorWithCode:EPARSE description:@"Expected 'true'"];
|
172
|
-
return NO;
|
173
|
-
}
|
174
|
-
|
175
|
-
- (BOOL)scanRestOfFalse:(NSNumber **)o
|
176
|
-
{
|
177
|
-
if (!strncmp(c, "alse", 4)) {
|
178
|
-
c += 4;
|
179
|
-
*o = [NSNumber numberWithBool:NO];
|
180
|
-
return YES;
|
181
|
-
}
|
182
|
-
[self addErrorWithCode:EPARSE description: @"Expected 'false'"];
|
183
|
-
return NO;
|
184
|
-
}
|
185
|
-
|
186
|
-
- (BOOL)scanRestOfNull:(NSNull **)o {
|
187
|
-
if (!strncmp(c, "ull", 3)) {
|
188
|
-
c += 3;
|
189
|
-
*o = [NSNull null];
|
190
|
-
return YES;
|
191
|
-
}
|
192
|
-
[self addErrorWithCode:EPARSE description: @"Expected 'null'"];
|
193
|
-
return NO;
|
194
|
-
}
|
195
|
-
|
196
|
-
- (BOOL)scanRestOfArray:(NSMutableArray **)o {
|
197
|
-
if (maxDepth && ++depth > maxDepth) {
|
198
|
-
[self addErrorWithCode:EDEPTH description: @"Nested too deep"];
|
199
|
-
return NO;
|
200
|
-
}
|
201
|
-
|
202
|
-
*o = [NSMutableArray arrayWithCapacity:8];
|
203
|
-
|
204
|
-
for (; *c ;) {
|
205
|
-
id v;
|
206
|
-
|
207
|
-
skipWhitespace(c);
|
208
|
-
if (*c == ']' && c++) {
|
209
|
-
depth--;
|
210
|
-
return YES;
|
211
|
-
}
|
212
|
-
|
213
|
-
if (![self scanValue:&v]) {
|
214
|
-
[self addErrorWithCode:EPARSE description:@"Expected value while parsing array"];
|
215
|
-
return NO;
|
216
|
-
}
|
217
|
-
|
218
|
-
[*o addObject:v];
|
219
|
-
|
220
|
-
skipWhitespace(c);
|
221
|
-
if (*c == ',' && c++) {
|
222
|
-
skipWhitespace(c);
|
223
|
-
if (*c == ']') {
|
224
|
-
[self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in array"];
|
225
|
-
return NO;
|
226
|
-
}
|
227
|
-
}
|
228
|
-
}
|
229
|
-
|
230
|
-
[self addErrorWithCode:EEOF description: @"End of input while parsing array"];
|
231
|
-
return NO;
|
232
|
-
}
|
233
|
-
|
234
|
-
- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o
|
235
|
-
{
|
236
|
-
if (maxDepth && ++depth > maxDepth) {
|
237
|
-
[self addErrorWithCode:EDEPTH description: @"Nested too deep"];
|
238
|
-
return NO;
|
239
|
-
}
|
240
|
-
|
241
|
-
*o = [NSMutableDictionary dictionaryWithCapacity:7];
|
242
|
-
|
243
|
-
for (; *c ;) {
|
244
|
-
id k, v;
|
245
|
-
|
246
|
-
skipWhitespace(c);
|
247
|
-
if (*c == '}' && c++) {
|
248
|
-
depth--;
|
249
|
-
return YES;
|
250
|
-
}
|
251
|
-
|
252
|
-
if (!(*c == '\"' && c++ && [self scanRestOfString:&k])) {
|
253
|
-
[self addErrorWithCode:EPARSE description: @"Object key string expected"];
|
254
|
-
return NO;
|
255
|
-
}
|
256
|
-
|
257
|
-
skipWhitespace(c);
|
258
|
-
if (*c != ':') {
|
259
|
-
[self addErrorWithCode:EPARSE description: @"Expected ':' separating key and value"];
|
260
|
-
return NO;
|
261
|
-
}
|
262
|
-
|
263
|
-
c++;
|
264
|
-
if (![self scanValue:&v]) {
|
265
|
-
NSString *string = [NSString stringWithFormat:@"Object value expected for key: %@", k];
|
266
|
-
[self addErrorWithCode:EPARSE description: string];
|
267
|
-
return NO;
|
268
|
-
}
|
269
|
-
|
270
|
-
[*o setObject:v forKey:k];
|
271
|
-
|
272
|
-
skipWhitespace(c);
|
273
|
-
if (*c == ',' && c++) {
|
274
|
-
skipWhitespace(c);
|
275
|
-
if (*c == '}') {
|
276
|
-
[self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in object"];
|
277
|
-
return NO;
|
278
|
-
}
|
279
|
-
}
|
280
|
-
}
|
281
|
-
|
282
|
-
[self addErrorWithCode:EEOF description: @"End of input while parsing object"];
|
283
|
-
return NO;
|
284
|
-
}
|
285
|
-
|
286
|
-
- (BOOL)scanRestOfString:(NSMutableString **)o
|
287
|
-
{
|
288
|
-
*o = [NSMutableString stringWithCapacity:16];
|
289
|
-
do {
|
290
|
-
// First see if there's a portion we can grab in one go.
|
291
|
-
// Doing this caused a massive speedup on the long string.
|
292
|
-
size_t len = strcspn(c, ctrl);
|
293
|
-
if (len) {
|
294
|
-
// check for
|
295
|
-
id t = [[NSString alloc] initWithBytesNoCopy:(char*)c
|
296
|
-
length:len
|
297
|
-
encoding:NSUTF8StringEncoding
|
298
|
-
freeWhenDone:NO];
|
299
|
-
if (t) {
|
300
|
-
[*o appendString:t];
|
301
|
-
[t release];
|
302
|
-
c += len;
|
303
|
-
}
|
304
|
-
}
|
305
|
-
|
306
|
-
if (*c == '"') {
|
307
|
-
c++;
|
308
|
-
return YES;
|
309
|
-
|
310
|
-
} else if (*c == '\\') {
|
311
|
-
unichar uc = *++c;
|
312
|
-
switch (uc) {
|
313
|
-
case '\\':
|
314
|
-
case '/':
|
315
|
-
case '"':
|
316
|
-
break;
|
317
|
-
|
318
|
-
case 'b': uc = '\b'; break;
|
319
|
-
case 'n': uc = '\n'; break;
|
320
|
-
case 'r': uc = '\r'; break;
|
321
|
-
case 't': uc = '\t'; break;
|
322
|
-
case 'f': uc = '\f'; break;
|
323
|
-
|
324
|
-
case 'u':
|
325
|
-
c++;
|
326
|
-
if (![self scanUnicodeChar:&uc]) {
|
327
|
-
[self addErrorWithCode:EUNICODE description: @"Broken unicode character"];
|
328
|
-
return NO;
|
329
|
-
}
|
330
|
-
c--; // hack.
|
331
|
-
break;
|
332
|
-
default:
|
333
|
-
[self addErrorWithCode:EESCAPE description: [NSString stringWithFormat:@"Illegal escape sequence '0x%x'", uc]];
|
334
|
-
return NO;
|
335
|
-
break;
|
336
|
-
}
|
337
|
-
CFStringAppendCharacters((CFMutableStringRef)*o, &uc, 1);
|
338
|
-
c++;
|
339
|
-
|
340
|
-
} else if (*c < 0x20) {
|
341
|
-
[self addErrorWithCode:ECTRL description: [NSString stringWithFormat:@"Unescaped control character '0x%x'", *c]];
|
342
|
-
return NO;
|
343
|
-
|
344
|
-
} else {
|
345
|
-
NSLog(@"should not be able to get here");
|
346
|
-
}
|
347
|
-
} while (*c);
|
348
|
-
|
349
|
-
[self addErrorWithCode:EEOF description:@"Unexpected EOF while parsing string"];
|
350
|
-
return NO;
|
351
|
-
}
|
352
|
-
|
353
|
-
- (BOOL)scanUnicodeChar:(unichar *)x
|
354
|
-
{
|
355
|
-
unichar hi, lo;
|
356
|
-
|
357
|
-
if (![self scanHexQuad:&hi]) {
|
358
|
-
[self addErrorWithCode:EUNICODE description: @"Missing hex quad"];
|
359
|
-
return NO;
|
360
|
-
}
|
361
|
-
|
362
|
-
if (hi >= 0xd800) { // high surrogate char?
|
363
|
-
if (hi < 0xdc00) { // yes - expect a low char
|
364
|
-
|
365
|
-
if (!(*c == '\\' && ++c && *c == 'u' && ++c && [self scanHexQuad:&lo])) {
|
366
|
-
[self addErrorWithCode:EUNICODE description: @"Missing low character in surrogate pair"];
|
367
|
-
return NO;
|
368
|
-
}
|
369
|
-
|
370
|
-
if (lo < 0xdc00 || lo >= 0xdfff) {
|
371
|
-
[self addErrorWithCode:EUNICODE description:@"Invalid low surrogate char"];
|
372
|
-
return NO;
|
373
|
-
}
|
374
|
-
|
375
|
-
hi = (hi - 0xd800) * 0x400 + (lo - 0xdc00) + 0x10000;
|
376
|
-
|
377
|
-
} else if (hi < 0xe000) {
|
378
|
-
[self addErrorWithCode:EUNICODE description:@"Invalid high character in surrogate pair"];
|
379
|
-
return NO;
|
380
|
-
}
|
381
|
-
}
|
382
|
-
|
383
|
-
*x = hi;
|
384
|
-
return YES;
|
385
|
-
}
|
386
|
-
|
387
|
-
- (BOOL)scanHexQuad:(unichar *)x
|
388
|
-
{
|
389
|
-
*x = 0;
|
390
|
-
for (int i = 0; i < 4; i++) {
|
391
|
-
unichar uc = *c;
|
392
|
-
c++;
|
393
|
-
int d = (uc >= '0' && uc <= '9')
|
394
|
-
? uc - '0' : (uc >= 'a' && uc <= 'f')
|
395
|
-
? (uc - 'a' + 10) : (uc >= 'A' && uc <= 'F')
|
396
|
-
? (uc - 'A' + 10) : -1;
|
397
|
-
if (d == -1) {
|
398
|
-
[self addErrorWithCode:EUNICODE description:@"Missing hex digit in quad"];
|
399
|
-
return NO;
|
400
|
-
}
|
401
|
-
*x *= 16;
|
402
|
-
*x += d;
|
403
|
-
}
|
404
|
-
return YES;
|
405
|
-
}
|
406
|
-
|
407
|
-
- (BOOL)scanNumber:(NSNumber **)o
|
408
|
-
{
|
409
|
-
const char *ns = c;
|
410
|
-
|
411
|
-
// The logic to test for validity of the number formatting is relicensed
|
412
|
-
// from JSON::XS with permission from its author Marc Lehmann.
|
413
|
-
// (Available at the CPAN: http://search.cpan.org/dist/JSON-XS/ .)
|
414
|
-
|
415
|
-
if ('-' == *c)
|
416
|
-
c++;
|
417
|
-
|
418
|
-
if ('0' == *c && c++) {
|
419
|
-
if (isdigit(*c)) {
|
420
|
-
[self addErrorWithCode:EPARSENUM description: @"Leading 0 disallowed in number"];
|
421
|
-
return NO;
|
422
|
-
}
|
423
|
-
|
424
|
-
} else if (!isdigit(*c) && c != ns) {
|
425
|
-
[self addErrorWithCode:EPARSENUM description: @"No digits after initial minus"];
|
426
|
-
return NO;
|
427
|
-
|
428
|
-
} else {
|
429
|
-
skipDigits(c);
|
430
|
-
}
|
431
|
-
|
432
|
-
// Fractional part
|
433
|
-
if ('.' == *c && c++) {
|
434
|
-
|
435
|
-
if (!isdigit(*c)) {
|
436
|
-
[self addErrorWithCode:EPARSENUM description: @"No digits after decimal point"];
|
437
|
-
return NO;
|
438
|
-
}
|
439
|
-
skipDigits(c);
|
440
|
-
}
|
441
|
-
|
442
|
-
// Exponential part
|
443
|
-
if ('e' == *c || 'E' == *c) {
|
444
|
-
c++;
|
445
|
-
|
446
|
-
if ('-' == *c || '+' == *c)
|
447
|
-
c++;
|
448
|
-
|
449
|
-
if (!isdigit(*c)) {
|
450
|
-
[self addErrorWithCode:EPARSENUM description: @"No digits after exponent"];
|
451
|
-
return NO;
|
452
|
-
}
|
453
|
-
skipDigits(c);
|
454
|
-
}
|
455
|
-
|
456
|
-
id str = [[NSString alloc] initWithBytesNoCopy:(char*)ns
|
457
|
-
length:c - ns
|
458
|
-
encoding:NSUTF8StringEncoding
|
459
|
-
freeWhenDone:NO];
|
460
|
-
[str autorelease];
|
461
|
-
if (str && (*o = [NSDecimalNumber decimalNumberWithString:str]))
|
462
|
-
return YES;
|
463
|
-
|
464
|
-
[self addErrorWithCode:EPARSENUM description: @"Failed creating decimal instance"];
|
465
|
-
return NO;
|
466
|
-
}
|
467
|
-
|
468
|
-
- (BOOL)scanIsAtEnd
|
469
|
-
{
|
470
|
-
skipWhitespace(c);
|
471
|
-
return !*c;
|
472
|
-
}
|
473
|
-
|
474
|
-
|
475
|
-
@end
|