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.
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