iCuke 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +13 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +69 -0
  4. data/Rakefile +80 -0
  5. data/VERSION +1 -0
  6. data/app/iCuke/.gitignore +1 -0
  7. data/app/iCuke/Classes/FlipsideView.h +13 -0
  8. data/app/iCuke/Classes/FlipsideView.m +32 -0
  9. data/app/iCuke/Classes/FlipsideViewController.h +25 -0
  10. data/app/iCuke/Classes/FlipsideViewController.m +54 -0
  11. data/app/iCuke/Classes/MainView.h +15 -0
  12. data/app/iCuke/Classes/MainView.m +32 -0
  13. data/app/iCuke/Classes/MainViewController.h +16 -0
  14. data/app/iCuke/Classes/MainViewController.m +86 -0
  15. data/app/iCuke/Classes/iCukeAppDelegate.h +20 -0
  16. data/app/iCuke/Classes/iCukeAppDelegate.m +33 -0
  17. data/app/iCuke/FlipsideView.xib +444 -0
  18. data/app/iCuke/MainView.xib +520 -0
  19. data/app/iCuke/MainWindow.xib +355 -0
  20. data/app/iCuke/SniffingView.h +20 -0
  21. data/app/iCuke/SniffingView.m +191 -0
  22. data/app/iCuke/iCuke-Info.plist +30 -0
  23. data/app/iCuke/iCuke.xcodeproj/project.pbxproj +313 -0
  24. data/app/iCuke/iCuke_Prefix.pch +14 -0
  25. data/app/iCuke/main.m +16 -0
  26. data/ext/iCuke/.gitignore +2 -0
  27. data/ext/iCuke/DefaultsResponse.h +5 -0
  28. data/ext/iCuke/DefaultsResponse.m +67 -0
  29. data/ext/iCuke/EventResponse.h +5 -0
  30. data/ext/iCuke/EventResponse.m +122 -0
  31. data/ext/iCuke/Rakefile +22 -0
  32. data/ext/iCuke/Recorder.h +15 -0
  33. data/ext/iCuke/Recorder.m +85 -0
  34. data/ext/iCuke/RecorderResponse.h +5 -0
  35. data/ext/iCuke/RecorderResponse.m +59 -0
  36. data/ext/iCuke/SynthesizeSingleton.h +68 -0
  37. data/ext/iCuke/ViewResponse.h +5 -0
  38. data/ext/iCuke/ViewResponse.m +84 -0
  39. data/ext/iCuke/Viewer.h +8 -0
  40. data/ext/iCuke/Viewer.m +153 -0
  41. data/ext/iCuke/iCukeHTTPResponseHandler.h +50 -0
  42. data/ext/iCuke/iCukeHTTPResponseHandler.m +381 -0
  43. data/ext/iCuke/iCukeHTTPServer.h +53 -0
  44. data/ext/iCuke/iCukeHTTPServer.m +365 -0
  45. data/ext/iCuke/iCukeServer.h +16 -0
  46. data/ext/iCuke/iCukeServer.m +46 -0
  47. data/ext/iCuke/json/JSON.h +50 -0
  48. data/ext/iCuke/json/NSObject+SBJSON.h +68 -0
  49. data/ext/iCuke/json/NSObject+SBJSON.m +53 -0
  50. data/ext/iCuke/json/NSString+SBJSON.h +58 -0
  51. data/ext/iCuke/json/NSString+SBJSON.m +55 -0
  52. data/ext/iCuke/json/SBJSON.h +75 -0
  53. data/ext/iCuke/json/SBJSON.m +212 -0
  54. data/ext/iCuke/json/SBJsonBase.h +86 -0
  55. data/ext/iCuke/json/SBJsonBase.m +78 -0
  56. data/ext/iCuke/json/SBJsonParser.h +87 -0
  57. data/ext/iCuke/json/SBJsonParser.m +475 -0
  58. data/ext/iCuke/json/SBJsonWriter.h +129 -0
  59. data/ext/iCuke/json/SBJsonWriter.m +228 -0
  60. data/features/icuke.feature +17 -0
  61. data/features/support/env.rb +3 -0
  62. data/iCuke.gemspec +113 -0
  63. data/lib/icuke/cucumber.rb +211 -0
  64. data/lib/icuke/simulate.rb +132 -0
  65. data/lib/icuke/simulator.rb +107 -0
  66. data/lib/icuke.rb +1 -0
  67. 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