iCuke 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +13 -0
- data/LICENSE +20 -0
- data/README.rdoc +69 -0
- data/Rakefile +80 -0
- data/VERSION +1 -0
- data/app/iCuke/.gitignore +1 -0
- data/app/iCuke/Classes/FlipsideView.h +13 -0
- data/app/iCuke/Classes/FlipsideView.m +32 -0
- data/app/iCuke/Classes/FlipsideViewController.h +25 -0
- data/app/iCuke/Classes/FlipsideViewController.m +54 -0
- data/app/iCuke/Classes/MainView.h +15 -0
- data/app/iCuke/Classes/MainView.m +32 -0
- data/app/iCuke/Classes/MainViewController.h +16 -0
- data/app/iCuke/Classes/MainViewController.m +86 -0
- data/app/iCuke/Classes/iCukeAppDelegate.h +20 -0
- data/app/iCuke/Classes/iCukeAppDelegate.m +33 -0
- data/app/iCuke/FlipsideView.xib +444 -0
- data/app/iCuke/MainView.xib +520 -0
- data/app/iCuke/MainWindow.xib +355 -0
- data/app/iCuke/SniffingView.h +20 -0
- data/app/iCuke/SniffingView.m +191 -0
- data/app/iCuke/iCuke-Info.plist +30 -0
- data/app/iCuke/iCuke.xcodeproj/project.pbxproj +313 -0
- data/app/iCuke/iCuke_Prefix.pch +14 -0
- data/app/iCuke/main.m +16 -0
- data/ext/iCuke/.gitignore +2 -0
- data/ext/iCuke/DefaultsResponse.h +5 -0
- data/ext/iCuke/DefaultsResponse.m +67 -0
- data/ext/iCuke/EventResponse.h +5 -0
- data/ext/iCuke/EventResponse.m +122 -0
- data/ext/iCuke/Rakefile +22 -0
- data/ext/iCuke/Recorder.h +15 -0
- data/ext/iCuke/Recorder.m +85 -0
- data/ext/iCuke/RecorderResponse.h +5 -0
- data/ext/iCuke/RecorderResponse.m +59 -0
- data/ext/iCuke/SynthesizeSingleton.h +68 -0
- data/ext/iCuke/ViewResponse.h +5 -0
- data/ext/iCuke/ViewResponse.m +84 -0
- data/ext/iCuke/Viewer.h +8 -0
- data/ext/iCuke/Viewer.m +153 -0
- data/ext/iCuke/iCukeHTTPResponseHandler.h +50 -0
- data/ext/iCuke/iCukeHTTPResponseHandler.m +381 -0
- data/ext/iCuke/iCukeHTTPServer.h +53 -0
- data/ext/iCuke/iCukeHTTPServer.m +365 -0
- data/ext/iCuke/iCukeServer.h +16 -0
- data/ext/iCuke/iCukeServer.m +46 -0
- data/ext/iCuke/json/JSON.h +50 -0
- data/ext/iCuke/json/NSObject+SBJSON.h +68 -0
- data/ext/iCuke/json/NSObject+SBJSON.m +53 -0
- data/ext/iCuke/json/NSString+SBJSON.h +58 -0
- data/ext/iCuke/json/NSString+SBJSON.m +55 -0
- data/ext/iCuke/json/SBJSON.h +75 -0
- data/ext/iCuke/json/SBJSON.m +212 -0
- data/ext/iCuke/json/SBJsonBase.h +86 -0
- data/ext/iCuke/json/SBJsonBase.m +78 -0
- data/ext/iCuke/json/SBJsonParser.h +87 -0
- data/ext/iCuke/json/SBJsonParser.m +475 -0
- data/ext/iCuke/json/SBJsonWriter.h +129 -0
- data/ext/iCuke/json/SBJsonWriter.m +228 -0
- data/features/icuke.feature +17 -0
- data/features/support/env.rb +3 -0
- data/iCuke.gemspec +113 -0
- data/lib/icuke/cucumber.rb +211 -0
- data/lib/icuke/simulate.rb +132 -0
- data/lib/icuke/simulator.rb +107 -0
- data/lib/icuke.rb +1 -0
- metadata +163 -0
@@ -0,0 +1,365 @@
|
|
1
|
+
//
|
2
|
+
// HTTPServer.m
|
3
|
+
// TextTransfer
|
4
|
+
//
|
5
|
+
// Created by Matt Gallagher on 2009/07/13.
|
6
|
+
// Copyright 2009 Matt Gallagher. All rights reserved.
|
7
|
+
//
|
8
|
+
// Permission is given to use this source code file, free of charge, in any
|
9
|
+
// project, commercial or otherwise, entirely at your risk, with the condition
|
10
|
+
// that any redistribution (in part or whole) of source code must retain
|
11
|
+
// this copyright and permission notice. Attribution in compiled projects is
|
12
|
+
// appreciated but not required.
|
13
|
+
//
|
14
|
+
|
15
|
+
#import "iCukeHTTPServer.h"
|
16
|
+
#import "SynthesizeSingleton.h"
|
17
|
+
#import <sys/socket.h>
|
18
|
+
#import <netinet/in.h>
|
19
|
+
#if TARGET_OS_IPHONE
|
20
|
+
#import <CFNetwork/CFNetwork.h>
|
21
|
+
#endif
|
22
|
+
#import "iCukeHTTPResponseHandler.h"
|
23
|
+
|
24
|
+
#define HTTP_SERVER_PORT 50000
|
25
|
+
|
26
|
+
NSString * const iCukeHTTPServerNotificationStateChanged = @"ServerNotificationStateChanged";
|
27
|
+
|
28
|
+
//
|
29
|
+
// Internal methods and properties:
|
30
|
+
// The "lastError" and "state" are only writable by the server itself.
|
31
|
+
//
|
32
|
+
@interface iCukeHTTPServer ()
|
33
|
+
@property (nonatomic, readwrite, retain) NSError *lastError;
|
34
|
+
@property (readwrite, assign) iCukeHTTPServerState state;
|
35
|
+
@end
|
36
|
+
|
37
|
+
@implementation iCukeHTTPServer
|
38
|
+
|
39
|
+
@synthesize lastError;
|
40
|
+
@synthesize state;
|
41
|
+
|
42
|
+
SYNTHESIZE_SINGLETON_FOR_CLASS(iCukeHTTPServer);
|
43
|
+
|
44
|
+
//
|
45
|
+
// init
|
46
|
+
//
|
47
|
+
// Set the initial state and allocate the responseHandlers and incomingRequests
|
48
|
+
// collections.
|
49
|
+
//
|
50
|
+
// returns the initialized server object.
|
51
|
+
//
|
52
|
+
- (id)init
|
53
|
+
{
|
54
|
+
self = [super init];
|
55
|
+
if (self != nil)
|
56
|
+
{
|
57
|
+
self.state = SERVER_STATE_IDLE;
|
58
|
+
responseHandlers = [[NSMutableSet alloc] init];
|
59
|
+
incomingRequests =
|
60
|
+
CFDictionaryCreateMutable(
|
61
|
+
kCFAllocatorDefault,
|
62
|
+
0,
|
63
|
+
&kCFTypeDictionaryKeyCallBacks,
|
64
|
+
&kCFTypeDictionaryValueCallBacks);
|
65
|
+
}
|
66
|
+
return self;
|
67
|
+
}
|
68
|
+
|
69
|
+
//
|
70
|
+
// setLastError:
|
71
|
+
//
|
72
|
+
// Custom setter method. Stops the server and
|
73
|
+
//
|
74
|
+
// Parameters:
|
75
|
+
// anError - the new error value (nil to clear)
|
76
|
+
//
|
77
|
+
- (void)setLastError:(NSError *)anError
|
78
|
+
{
|
79
|
+
[anError retain];
|
80
|
+
[lastError release];
|
81
|
+
lastError = anError;
|
82
|
+
|
83
|
+
if (lastError == nil)
|
84
|
+
{
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
[self stop];
|
89
|
+
|
90
|
+
self.state = SERVER_STATE_IDLE;
|
91
|
+
NSLog(@"HTTPServer error: %@", self.lastError);
|
92
|
+
}
|
93
|
+
|
94
|
+
//
|
95
|
+
// errorWithName:
|
96
|
+
//
|
97
|
+
// Stops the server and sets the last error to "errorName", localized using the
|
98
|
+
// HTTPServerErrors.strings file (if present).
|
99
|
+
//
|
100
|
+
// Parameters:
|
101
|
+
// errorName - the description used for the error
|
102
|
+
//
|
103
|
+
- (void)errorWithName:(NSString *)errorName
|
104
|
+
{
|
105
|
+
self.lastError = [NSError
|
106
|
+
errorWithDomain:@"HTTPServerError"
|
107
|
+
code:0
|
108
|
+
userInfo:
|
109
|
+
[NSDictionary dictionaryWithObject:
|
110
|
+
NSLocalizedStringFromTable(
|
111
|
+
errorName,
|
112
|
+
@"",
|
113
|
+
@"HTTPServerErrors")
|
114
|
+
forKey:NSLocalizedDescriptionKey]];
|
115
|
+
}
|
116
|
+
|
117
|
+
//
|
118
|
+
// setState:
|
119
|
+
//
|
120
|
+
// Changes the server state and posts a notification (if the state changes).
|
121
|
+
//
|
122
|
+
// Parameters:
|
123
|
+
// newState - the new state for the server
|
124
|
+
//
|
125
|
+
- (void)setState:(iCukeHTTPServerState)newState
|
126
|
+
{
|
127
|
+
if (state == newState)
|
128
|
+
{
|
129
|
+
return;
|
130
|
+
}
|
131
|
+
|
132
|
+
state = newState;
|
133
|
+
|
134
|
+
[[NSNotificationCenter defaultCenter]
|
135
|
+
postNotificationName:iCukeHTTPServerNotificationStateChanged
|
136
|
+
object:self];
|
137
|
+
}
|
138
|
+
|
139
|
+
//
|
140
|
+
// start
|
141
|
+
//
|
142
|
+
// Creates the socket and starts listening for connections on it.
|
143
|
+
//
|
144
|
+
- (void)start
|
145
|
+
{
|
146
|
+
self.lastError = nil;
|
147
|
+
self.state = SERVER_STATE_STARTING;
|
148
|
+
|
149
|
+
socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM,
|
150
|
+
IPPROTO_TCP, 0, NULL, NULL);
|
151
|
+
if (!socket)
|
152
|
+
{
|
153
|
+
[self errorWithName:@"Unable to create socket."];
|
154
|
+
return;
|
155
|
+
}
|
156
|
+
|
157
|
+
int reuse = true;
|
158
|
+
int fileDescriptor = CFSocketGetNative(socket);
|
159
|
+
if (setsockopt(fileDescriptor, SOL_SOCKET, SO_REUSEADDR,
|
160
|
+
(void *)&reuse, sizeof(int)) != 0)
|
161
|
+
{
|
162
|
+
[self errorWithName:@"Unable to set socket options."];
|
163
|
+
return;
|
164
|
+
}
|
165
|
+
|
166
|
+
struct sockaddr_in address;
|
167
|
+
memset(&address, 0, sizeof(address));
|
168
|
+
address.sin_len = sizeof(address);
|
169
|
+
address.sin_family = AF_INET;
|
170
|
+
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
171
|
+
address.sin_port = htons(HTTP_SERVER_PORT);
|
172
|
+
CFDataRef addressData =
|
173
|
+
CFDataCreate(NULL, (const UInt8 *)&address, sizeof(address));
|
174
|
+
[(id)addressData autorelease];
|
175
|
+
|
176
|
+
if (CFSocketSetAddress(socket, addressData) != kCFSocketSuccess)
|
177
|
+
{
|
178
|
+
[self errorWithName:@"Unable to bind socket to address."];
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
|
182
|
+
listeningHandle = [[NSFileHandle alloc]
|
183
|
+
initWithFileDescriptor:fileDescriptor
|
184
|
+
closeOnDealloc:YES];
|
185
|
+
|
186
|
+
[[NSNotificationCenter defaultCenter]
|
187
|
+
addObserver:self
|
188
|
+
selector:@selector(receiveIncomingConnectionNotification:)
|
189
|
+
name:NSFileHandleConnectionAcceptedNotification
|
190
|
+
object:nil];
|
191
|
+
[listeningHandle acceptConnectionInBackgroundAndNotify];
|
192
|
+
|
193
|
+
self.state = SERVER_STATE_RUNNING;
|
194
|
+
}
|
195
|
+
|
196
|
+
//
|
197
|
+
// stopReceivingForFileHandle:close:
|
198
|
+
//
|
199
|
+
// If a file handle is accumulating the header for a new connection, this
|
200
|
+
// method will close the handle, stop listening to it and release the
|
201
|
+
// accumulated memory.
|
202
|
+
//
|
203
|
+
// Parameters:
|
204
|
+
// incomingFileHandle - the file handle for the incoming request
|
205
|
+
// closeFileHandle - if YES, the file handle will be closed, if no it is
|
206
|
+
// assumed that an HTTPResponseHandler will close it when done.
|
207
|
+
//
|
208
|
+
- (void)stopReceivingForFileHandle:(NSFileHandle *)incomingFileHandle
|
209
|
+
close:(BOOL)closeFileHandle
|
210
|
+
{
|
211
|
+
if (closeFileHandle)
|
212
|
+
{
|
213
|
+
[incomingFileHandle closeFile];
|
214
|
+
}
|
215
|
+
|
216
|
+
[[NSNotificationCenter defaultCenter]
|
217
|
+
removeObserver:self
|
218
|
+
name:NSFileHandleDataAvailableNotification
|
219
|
+
object:incomingFileHandle];
|
220
|
+
CFDictionaryRemoveValue(incomingRequests, incomingFileHandle);
|
221
|
+
}
|
222
|
+
|
223
|
+
//
|
224
|
+
// stop
|
225
|
+
//
|
226
|
+
// Stops the server.
|
227
|
+
//
|
228
|
+
- (void)stop
|
229
|
+
{
|
230
|
+
self.state = SERVER_STATE_STOPPING;
|
231
|
+
|
232
|
+
[[NSNotificationCenter defaultCenter]
|
233
|
+
removeObserver:self
|
234
|
+
name:NSFileHandleConnectionAcceptedNotification
|
235
|
+
object:nil];
|
236
|
+
|
237
|
+
[responseHandlers removeAllObjects];
|
238
|
+
|
239
|
+
[listeningHandle closeFile];
|
240
|
+
[listeningHandle release];
|
241
|
+
listeningHandle = nil;
|
242
|
+
|
243
|
+
for (NSFileHandle *incomingFileHandle in
|
244
|
+
[[(NSDictionary *)incomingRequests copy] autorelease])
|
245
|
+
{
|
246
|
+
[self stopReceivingForFileHandle:incomingFileHandle close:YES];
|
247
|
+
}
|
248
|
+
|
249
|
+
if (socket)
|
250
|
+
{
|
251
|
+
CFSocketInvalidate(socket);
|
252
|
+
CFRelease(socket);
|
253
|
+
socket = nil;
|
254
|
+
}
|
255
|
+
|
256
|
+
self.state = SERVER_STATE_IDLE;
|
257
|
+
}
|
258
|
+
|
259
|
+
//
|
260
|
+
// receiveIncomingConnectionNotification:
|
261
|
+
//
|
262
|
+
// Receive the notification for a new incoming request. This method starts
|
263
|
+
// receiving data from the incoming request's file handle and creates a
|
264
|
+
// new CFHTTPMessageRef to store the incoming data..
|
265
|
+
//
|
266
|
+
// Parameters:
|
267
|
+
// notification - the new connection notification
|
268
|
+
//
|
269
|
+
- (void)receiveIncomingConnectionNotification:(NSNotification *)notification
|
270
|
+
{
|
271
|
+
NSDictionary *userInfo = [notification userInfo];
|
272
|
+
NSFileHandle *incomingFileHandle =
|
273
|
+
[userInfo objectForKey:NSFileHandleNotificationFileHandleItem];
|
274
|
+
|
275
|
+
if(incomingFileHandle)
|
276
|
+
{
|
277
|
+
CFDictionaryAddValue(
|
278
|
+
incomingRequests,
|
279
|
+
incomingFileHandle,
|
280
|
+
[(id)CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE) autorelease]);
|
281
|
+
|
282
|
+
[[NSNotificationCenter defaultCenter]
|
283
|
+
addObserver:self
|
284
|
+
selector:@selector(receiveIncomingDataNotification:)
|
285
|
+
name:NSFileHandleDataAvailableNotification
|
286
|
+
object:incomingFileHandle];
|
287
|
+
|
288
|
+
[incomingFileHandle waitForDataInBackgroundAndNotify];
|
289
|
+
}
|
290
|
+
|
291
|
+
[listeningHandle acceptConnectionInBackgroundAndNotify];
|
292
|
+
}
|
293
|
+
|
294
|
+
//
|
295
|
+
// receiveIncomingDataNotification:
|
296
|
+
//
|
297
|
+
// Receive new data for an incoming connection.
|
298
|
+
//
|
299
|
+
// Once enough data is received to fully parse the HTTP headers,
|
300
|
+
// a HTTPResponseHandler will be spawned to generate a response.
|
301
|
+
//
|
302
|
+
// Parameters:
|
303
|
+
// notification - data received notification
|
304
|
+
//
|
305
|
+
- (void)receiveIncomingDataNotification:(NSNotification *)notification
|
306
|
+
{
|
307
|
+
NSFileHandle *incomingFileHandle = [notification object];
|
308
|
+
NSData *data = [incomingFileHandle availableData];
|
309
|
+
|
310
|
+
if ([data length] == 0)
|
311
|
+
{
|
312
|
+
[self stopReceivingForFileHandle:incomingFileHandle close:NO];
|
313
|
+
return;
|
314
|
+
}
|
315
|
+
|
316
|
+
CFHTTPMessageRef incomingRequest =
|
317
|
+
(CFHTTPMessageRef)CFDictionaryGetValue(incomingRequests, incomingFileHandle);
|
318
|
+
if (!incomingRequest)
|
319
|
+
{
|
320
|
+
[self stopReceivingForFileHandle:incomingFileHandle close:YES];
|
321
|
+
return;
|
322
|
+
}
|
323
|
+
|
324
|
+
if (!CFHTTPMessageAppendBytes(
|
325
|
+
incomingRequest,
|
326
|
+
[data bytes],
|
327
|
+
[data length]))
|
328
|
+
{
|
329
|
+
[self stopReceivingForFileHandle:incomingFileHandle close:YES];
|
330
|
+
return;
|
331
|
+
}
|
332
|
+
|
333
|
+
if(CFHTTPMessageIsHeaderComplete(incomingRequest))
|
334
|
+
{
|
335
|
+
iCukeHTTPResponseHandler *handler =
|
336
|
+
[iCukeHTTPResponseHandler
|
337
|
+
handlerForRequest:incomingRequest
|
338
|
+
fileHandle:incomingFileHandle
|
339
|
+
server:self];
|
340
|
+
|
341
|
+
[responseHandlers addObject:handler];
|
342
|
+
[self stopReceivingForFileHandle:incomingFileHandle close:NO];
|
343
|
+
|
344
|
+
[handler startResponse];
|
345
|
+
return;
|
346
|
+
}
|
347
|
+
|
348
|
+
[incomingFileHandle waitForDataInBackgroundAndNotify];
|
349
|
+
}
|
350
|
+
|
351
|
+
//
|
352
|
+
// closeHandler:
|
353
|
+
//
|
354
|
+
// Shuts down a response handler and removes it from the set of handlers.
|
355
|
+
//
|
356
|
+
// Parameters:
|
357
|
+
// aHandler - the handler to shut down.
|
358
|
+
//
|
359
|
+
- (void)closeHandler:(iCukeHTTPResponseHandler *)aHandler
|
360
|
+
{
|
361
|
+
[aHandler endResponse];
|
362
|
+
[responseHandlers removeObject:aHandler];
|
363
|
+
}
|
364
|
+
|
365
|
+
@end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
//
|
2
|
+
// iCukeServer.h
|
3
|
+
// iCuke
|
4
|
+
//
|
5
|
+
// Created by Rob Holland on 01/03/2010.
|
6
|
+
// Copyright 2010 The IT Refinery. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#import "iCukeHTTPServer.h"
|
10
|
+
|
11
|
+
@interface iCukeServer : iCukeHTTPServer {
|
12
|
+
}
|
13
|
+
|
14
|
+
+ (void) start;
|
15
|
+
|
16
|
+
@end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
//
|
2
|
+
// iCukeServer.m
|
3
|
+
// iCuke
|
4
|
+
//
|
5
|
+
// Created by Rob Holland on 01/03/2010.
|
6
|
+
// Copyright 2010 The IT Refinery. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#import "iCukeServer.h"
|
10
|
+
#include <unistd.h>
|
11
|
+
|
12
|
+
@implementation iCukeServer
|
13
|
+
|
14
|
+
+ (void)start {
|
15
|
+
[[iCukeHTTPServer sharediCukeHTTPServer] start];
|
16
|
+
|
17
|
+
NSFileManager *fileManager= [[NSFileManager alloc] init];
|
18
|
+
NSArray *paths;
|
19
|
+
|
20
|
+
NSString *preferences = [NSHomeDirectory() stringByAppendingPathComponent: @"Library/Preferences"];
|
21
|
+
|
22
|
+
paths = [fileManager contentsOfDirectoryAtPath: preferences error: NULL];
|
23
|
+
for (NSString *path in paths) {
|
24
|
+
if (![path hasPrefix: @"."]) {
|
25
|
+
NSLog(@"Removing: %@", path);
|
26
|
+
unlink([[preferences stringByAppendingPathComponent: path] cStringUsingEncoding: [NSString defaultCStringEncoding]]);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
NSString *documents = [NSHomeDirectory() stringByAppendingPathComponent: @"Documents"];
|
31
|
+
paths = [fileManager contentsOfDirectoryAtPath: documents error: NULL];
|
32
|
+
for (NSString *path in paths) {
|
33
|
+
if (![path hasPrefix: @"."]) {
|
34
|
+
NSLog(@"Removing: %@", path);
|
35
|
+
unlink([[documents stringByAppendingPathComponent: path] cStringUsingEncoding: [NSString defaultCStringEncoding]]);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
@end
|
41
|
+
|
42
|
+
void start_server(void) __attribute__((constructor));
|
43
|
+
void start_server(void)
|
44
|
+
{
|
45
|
+
[iCukeServer start];
|
46
|
+
}
|
@@ -0,0 +1,50 @@
|
|
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
|
+
/**
|
31
|
+
@mainpage A strict JSON parser and generator for Objective-C
|
32
|
+
|
33
|
+
JSON (JavaScript Object Notation) is a lightweight data-interchange
|
34
|
+
format. This framework provides two apis for parsing and generating
|
35
|
+
JSON. One standard object-based and a higher level api consisting of
|
36
|
+
categories added to existing Objective-C classes.
|
37
|
+
|
38
|
+
Learn more on the http://code.google.com/p/json-framework project site.
|
39
|
+
|
40
|
+
This framework does its best to be as strict as possible, both in what it
|
41
|
+
accepts and what it generates. For example, it does not support trailing commas
|
42
|
+
in arrays or objects. Nor does it support embedded comments, or
|
43
|
+
anything else not in the JSON specification. This is considered a feature.
|
44
|
+
|
45
|
+
*/
|
46
|
+
|
47
|
+
#import "SBJSON.h"
|
48
|
+
#import "NSObject+SBJSON.h"
|
49
|
+
#import "NSString+SBJSON.h"
|
50
|
+
|
@@ -0,0 +1,68 @@
|
|
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 <Foundation/Foundation.h>
|
31
|
+
|
32
|
+
|
33
|
+
/**
|
34
|
+
@brief Adds JSON generation to Foundation classes
|
35
|
+
|
36
|
+
This is a category on NSObject that adds methods for returning JSON representations
|
37
|
+
of standard objects to the objects themselves. This means you can call the
|
38
|
+
-JSONRepresentation method on an NSArray object and it'll do what you want.
|
39
|
+
*/
|
40
|
+
@interface NSObject (NSObject_SBJSON)
|
41
|
+
|
42
|
+
/**
|
43
|
+
@brief Returns a string containing the receiver encoded as a JSON fragment.
|
44
|
+
|
45
|
+
This method is added as a category on NSObject but is only actually
|
46
|
+
supported for the following objects:
|
47
|
+
@li NSDictionary
|
48
|
+
@li NSArray
|
49
|
+
@li NSString
|
50
|
+
@li NSNumber (also used for booleans)
|
51
|
+
@li NSNull
|
52
|
+
|
53
|
+
@deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
|
54
|
+
*/
|
55
|
+
- (NSString *)JSONFragment;
|
56
|
+
|
57
|
+
/**
|
58
|
+
@brief Returns a string containing the receiver encoded in JSON.
|
59
|
+
|
60
|
+
This method is added as a category on NSObject but is only actually
|
61
|
+
supported for the following objects:
|
62
|
+
@li NSDictionary
|
63
|
+
@li NSArray
|
64
|
+
*/
|
65
|
+
- (NSString *)JSONRepresentation;
|
66
|
+
|
67
|
+
@end
|
68
|
+
|
@@ -0,0 +1,53 @@
|
|
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 "NSObject+SBJSON.h"
|
31
|
+
#import "SBJsonWriter.h"
|
32
|
+
|
33
|
+
@implementation NSObject (NSObject_SBJSON)
|
34
|
+
|
35
|
+
- (NSString *)JSONFragment {
|
36
|
+
SBJsonWriter *jsonWriter = [SBJsonWriter new];
|
37
|
+
NSString *json = [jsonWriter stringWithFragment:self];
|
38
|
+
if (!json)
|
39
|
+
NSLog(@"-JSONFragment failed. Error trace is: %@", [jsonWriter errorTrace]);
|
40
|
+
[jsonWriter release];
|
41
|
+
return json;
|
42
|
+
}
|
43
|
+
|
44
|
+
- (NSString *)JSONRepresentation {
|
45
|
+
SBJsonWriter *jsonWriter = [SBJsonWriter new];
|
46
|
+
NSString *json = [jsonWriter stringWithObject:self];
|
47
|
+
if (!json)
|
48
|
+
NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]);
|
49
|
+
[jsonWriter release];
|
50
|
+
return json;
|
51
|
+
}
|
52
|
+
|
53
|
+
@end
|
@@ -0,0 +1,58 @@
|
|
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 <Foundation/Foundation.h>
|
31
|
+
|
32
|
+
/**
|
33
|
+
@brief Adds JSON parsing methods to NSString
|
34
|
+
|
35
|
+
This is a category on NSString that adds methods for parsing the target string.
|
36
|
+
*/
|
37
|
+
@interface NSString (NSString_SBJSON)
|
38
|
+
|
39
|
+
|
40
|
+
/**
|
41
|
+
@brief Returns the object represented in the receiver, or nil on error.
|
42
|
+
|
43
|
+
Returns a a scalar object represented by the string's JSON fragment representation.
|
44
|
+
|
45
|
+
@deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
|
46
|
+
*/
|
47
|
+
- (id)JSONFragmentValue;
|
48
|
+
|
49
|
+
/**
|
50
|
+
@brief Returns the NSDictionary or NSArray represented by the current string's JSON representation.
|
51
|
+
|
52
|
+
Returns the dictionary or array represented in the receiver, or nil on error.
|
53
|
+
|
54
|
+
Returns the NSDictionary or NSArray represented by the current string's JSON representation.
|
55
|
+
*/
|
56
|
+
- (id)JSONValue;
|
57
|
+
|
58
|
+
@end
|