iCuke 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|