├── .DS_Store ├── .gitignore ├── PSGoogleReader.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── danielair.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── isenhower.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── danielair.xcuserdatad │ └── xcschemes │ │ ├── PSGoogleReader.xcscheme │ │ └── xcschememanagement.plist │ └── isenhower.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── PSGoogleReader.xcscheme │ └── xcschememanagement.plist ├── PSGoogleReader ├── DetailViewController.h ├── DetailViewController.m ├── GTMDefines.h ├── GTMNSString+HTML.h ├── GTMNSString+HTML.m ├── PSGoogleReader-Info.plist ├── PSGoogleReader-Prefix.pch ├── PSGoogleReader.h ├── PSGoogleReader.m ├── PSGoogleReaderAppDelegate.h ├── PSGoogleReaderAppDelegate.m ├── README ├── RegexKitLite.h ├── RegexKitLite.m ├── RootViewController.h ├── RootViewController.m ├── SBJSON │ ├── .svn │ │ ├── all-wcprops │ │ ├── entries │ │ └── text-base │ │ │ ├── JSON.h.svn-base │ │ │ ├── NSObject+SBJSON.h.svn-base │ │ │ ├── NSObject+SBJSON.m.svn-base │ │ │ ├── NSString+SBJSON.h.svn-base │ │ │ ├── NSString+SBJSON.m.svn-base │ │ │ ├── SBJSON.h.svn-base │ │ │ ├── SBJSON.m.svn-base │ │ │ ├── SBJsonBase.h.svn-base │ │ │ ├── SBJsonBase.m.svn-base │ │ │ ├── SBJsonParser.h.svn-base │ │ │ ├── SBJsonParser.m.svn-base │ │ │ ├── SBJsonWriter.h.svn-base │ │ │ └── SBJsonWriter.m.svn-base │ ├── NSObject+SBJson.h │ ├── NSObject+SBJson.m │ ├── SBJson.h │ ├── SBJsonParser.h │ ├── SBJsonParser.m │ ├── SBJsonStreamParser.h │ ├── SBJsonStreamParser.m │ ├── SBJsonStreamParserAccumulator.h │ ├── SBJsonStreamParserAccumulator.m │ ├── SBJsonStreamParserState.h │ ├── SBJsonStreamParserState.m │ ├── SBJsonStreamWriter.h │ ├── SBJsonStreamWriter.m │ ├── SBJsonStreamWriterAccumulator.h │ ├── SBJsonStreamWriterAccumulator.m │ ├── SBJsonStreamWriterState.h │ ├── SBJsonStreamWriterState.m │ ├── SBJsonTokeniser.h │ ├── SBJsonTokeniser.m │ ├── SBJsonUTF8Stream.h │ ├── SBJsonUTF8Stream.m │ ├── SBJsonWriter.h │ └── SBJsonWriter.m ├── en.lproj │ ├── DetailView.xib │ ├── InfoPlist.strings │ └── MainWindow.xib └── main.m └── README /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/perspecdev/PSGoogleReader/c2cb32bb3befd78f165dd3a8320a54ffc501c3bf/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/project.xcworkspace/xcuserdata/isenhower.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/perspecdev/PSGoogleReader/c2cb32bb3befd78f165dd3a8320a54ffc501c3bf/PSGoogleReader.xcodeproj/project.xcworkspace/xcuserdata/isenhower.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/project.xcworkspace/xcuserdata/isenhower.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/xcuserdata/danielair.xcuserdatad/xcschemes/PSGoogleReader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/xcuserdata/danielair.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PSGoogleReader.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 34295800138BB27D00F8352F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/xcuserdata/isenhower.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/xcuserdata/isenhower.xcuserdatad/xcschemes/PSGoogleReader.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /PSGoogleReader.xcodeproj/xcuserdata/isenhower.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PSGoogleReader.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 34295800138BB27D00F8352F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PSGoogleReader/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController { 12 | 13 | } 14 | 15 | 16 | @property (nonatomic, retain) IBOutlet UIToolbar *toolbar; 17 | 18 | @property (nonatomic, retain) id detailItem; 19 | 20 | @property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /PSGoogleReader/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | 11 | #import "RootViewController.h" 12 | 13 | @interface DetailViewController () 14 | @property (nonatomic, strong) UIPopoverController *popoverController; 15 | - (void)configureView; 16 | @end 17 | 18 | @implementation DetailViewController 19 | 20 | @synthesize toolbar=_toolbar; 21 | 22 | @synthesize detailItem=_detailItem; 23 | 24 | @synthesize detailDescriptionLabel=_detailDescriptionLabel; 25 | 26 | @synthesize popoverController=_myPopoverController; 27 | 28 | #pragma mark - Managing the detail item 29 | 30 | /* 31 | When setting the detail item, update the view and dismiss the popover controller if it's showing. 32 | */ 33 | - (void)setDetailItem:(id)newDetailItem 34 | { 35 | if (_detailItem != newDetailItem) { 36 | _detailItem = newDetailItem; 37 | 38 | // Update the view. 39 | [self configureView]; 40 | } 41 | 42 | if (self.popoverController != nil) { 43 | [self.popoverController dismissPopoverAnimated:YES]; 44 | } 45 | } 46 | 47 | - (void)configureView 48 | { 49 | // Update the user interface for the detail item. 50 | 51 | self.detailDescriptionLabel.text = [self.detailItem description]; 52 | } 53 | 54 | - (void)viewWillAppear:(BOOL)animated 55 | { 56 | [super viewWillAppear:animated]; 57 | } 58 | 59 | - (void)viewDidAppear:(BOOL)animated 60 | { 61 | [super viewDidAppear:animated]; 62 | } 63 | 64 | - (void)viewWillDisappear:(BOOL)animated 65 | { 66 | [super viewWillDisappear:animated]; 67 | } 68 | 69 | - (void)viewDidDisappear:(BOOL)animated 70 | { 71 | [super viewDidDisappear:animated]; 72 | } 73 | 74 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 75 | return YES; 76 | } 77 | 78 | #pragma mark - Split view support 79 | 80 | - (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController: (UIPopoverController *)pc 81 | { 82 | barButtonItem.title = @"Events"; 83 | NSMutableArray *items = [[self.toolbar items] mutableCopy]; 84 | [items insertObject:barButtonItem atIndex:0]; 85 | [self.toolbar setItems:items animated:YES]; 86 | self.popoverController = pc; 87 | } 88 | 89 | // Called when the view is shown again in the split view, invalidating the button and popover controller. 90 | - (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem 91 | { 92 | NSMutableArray *items = [[self.toolbar items] mutableCopy]; 93 | [items removeObjectAtIndex:0]; 94 | [self.toolbar setItems:items animated:YES]; 95 | self.popoverController = nil; 96 | } 97 | 98 | /* 99 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 100 | - (void)viewDidLoad 101 | { 102 | [super viewDidLoad]; 103 | } 104 | */ 105 | 106 | - (void)viewDidUnload 107 | { 108 | [super viewDidUnload]; 109 | 110 | // Release any retained subviews of the main view. 111 | // e.g. self.myOutlet = nil; 112 | self.popoverController = nil; 113 | } 114 | 115 | #pragma mark - Memory management 116 | 117 | - (void)didReceiveMemoryWarning 118 | { 119 | // Releases the view if it doesn't have a superview. 120 | [super didReceiveMemoryWarning]; 121 | 122 | // Release any cached data, images, etc that aren't in use. 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /PSGoogleReader/GTMDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMDefines.h 3 | // 4 | // Copyright 2008 Google Inc. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations under 16 | // the License. 17 | // 18 | 19 | // ============================================================================ 20 | 21 | #include 22 | #include 23 | 24 | #if TARGET_OS_IPHONE 25 | #include 26 | #endif // TARGET_OS_IPHONE 27 | 28 | // Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs 29 | #ifndef MAC_OS_X_VERSION_10_5 30 | #define MAC_OS_X_VERSION_10_5 1050 31 | #endif 32 | #ifndef MAC_OS_X_VERSION_10_6 33 | #define MAC_OS_X_VERSION_10_6 1060 34 | #endif 35 | 36 | // Not all __IPHONE_X macros defined in past SDKs 37 | #ifndef __IPHONE_2_1 38 | #define __IPHONE_2_1 20100 39 | #endif 40 | #ifndef __IPHONE_2_2 41 | #define __IPHONE_2_2 20200 42 | #endif 43 | #ifndef __IPHONE_3_0 44 | #define __IPHONE_3_0 30000 45 | #endif 46 | #ifndef __IPHONE_3_1 47 | #define __IPHONE_3_1 30100 48 | #endif 49 | #ifndef __IPHONE_3_2 50 | #define __IPHONE_3_2 30200 51 | #endif 52 | #ifndef __IPHONE_4_0 53 | #define __IPHONE_4_0 40000 54 | #endif 55 | 56 | // ---------------------------------------------------------------------------- 57 | // CPP symbols that can be overridden in a prefix to control how the toolbox 58 | // is compiled. 59 | // ---------------------------------------------------------------------------- 60 | 61 | 62 | // By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and 63 | // GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens 64 | // when a validation fails. If you implement your own validators, you may want 65 | // to control their internals using the same macros for consistency. 66 | #ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 67 | #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 68 | #endif 69 | 70 | // Give ourselves a consistent way to do inlines. Apple's macros even use 71 | // a few different actual definitions, so we're based off of the foundation 72 | // one. 73 | #if !defined(GTM_INLINE) 74 | #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__) 75 | #define GTM_INLINE static __inline__ __attribute__((always_inline)) 76 | #else 77 | #define GTM_INLINE static __inline__ 78 | #endif 79 | #endif 80 | 81 | // Give ourselves a consistent way of doing externs that links up nicely 82 | // when mixing objc and objc++ 83 | #if !defined (GTM_EXTERN) 84 | #if defined __cplusplus 85 | #define GTM_EXTERN extern "C" 86 | #define GTM_EXTERN_C_BEGIN extern "C" { 87 | #define GTM_EXTERN_C_END } 88 | #else 89 | #define GTM_EXTERN extern 90 | #define GTM_EXTERN_C_BEGIN 91 | #define GTM_EXTERN_C_END 92 | #endif 93 | #endif 94 | 95 | // Give ourselves a consistent way of exporting things if we have visibility 96 | // set to hidden. 97 | #if !defined (GTM_EXPORT) 98 | #define GTM_EXPORT __attribute__((visibility("default"))) 99 | #endif 100 | 101 | // Give ourselves a consistent way of declaring something as unused. This 102 | // doesn't use __unused because that is only supported in gcc 4.2 and greater. 103 | #if !defined (GTM_UNUSED) 104 | #define GTM_UNUSED(x) ((void)(x)) 105 | #endif 106 | 107 | // _GTMDevLog & _GTMDevAssert 108 | // 109 | // _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for 110 | // developer level errors. This implementation simply macros to NSLog/NSAssert. 111 | // It is not intended to be a general logging/reporting system. 112 | // 113 | // Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert 114 | // for a little more background on the usage of these macros. 115 | // 116 | // _GTMDevLog log some error/problem in debug builds 117 | // _GTMDevAssert assert if conditon isn't met w/in a method/function 118 | // in all builds. 119 | // 120 | // To replace this system, just provide different macro definitions in your 121 | // prefix header. Remember, any implementation you provide *must* be thread 122 | // safe since this could be called by anything in what ever situtation it has 123 | // been placed in. 124 | // 125 | 126 | // We only define the simple macros if nothing else has defined this. 127 | #ifndef _GTMDevLog 128 | 129 | #ifdef DEBUG 130 | #define _GTMDevLog(...) NSLog(__VA_ARGS__) 131 | #else 132 | #define _GTMDevLog(...) do { } while (0) 133 | #endif 134 | 135 | #endif // _GTMDevLog 136 | 137 | #ifndef _GTMDevAssert 138 | // we directly invoke the NSAssert handler so we can pass on the varargs 139 | // (NSAssert doesn't have a macro we can use that takes varargs) 140 | #if !defined(NS_BLOCK_ASSERTIONS) 141 | #define _GTMDevAssert(condition, ...) \ 142 | do { \ 143 | if (!(condition)) { \ 144 | [[NSAssertionHandler currentHandler] \ 145 | handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ 146 | file:[NSString stringWithUTF8String:__FILE__] \ 147 | lineNumber:__LINE__ \ 148 | description:__VA_ARGS__]; \ 149 | } \ 150 | } while(0) 151 | #else // !defined(NS_BLOCK_ASSERTIONS) 152 | #define _GTMDevAssert(condition, ...) do { } while (0) 153 | #endif // !defined(NS_BLOCK_ASSERTIONS) 154 | 155 | #endif // _GTMDevAssert 156 | 157 | // _GTMCompileAssert 158 | // _GTMCompileAssert is an assert that is meant to fire at compile time if you 159 | // want to check things at compile instead of runtime. For example if you 160 | // want to check that a wchar is 4 bytes instead of 2 you would use 161 | // _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) 162 | // Note that the second "arg" is not in quotes, and must be a valid processor 163 | // symbol in it's own right (no spaces, punctuation etc). 164 | 165 | // Wrapping this in an #ifndef allows external groups to define their own 166 | // compile time assert scheme. 167 | #ifndef _GTMCompileAssert 168 | // We got this technique from here: 169 | // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html 170 | 171 | #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg 172 | #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) 173 | #define _GTMCompileAssert(test, msg) \ 174 | typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] 175 | #endif // _GTMCompileAssert 176 | 177 | // ---------------------------------------------------------------------------- 178 | // CPP symbols defined based on the project settings so the GTM code has 179 | // simple things to test against w/o scattering the knowledge of project 180 | // setting through all the code. 181 | // ---------------------------------------------------------------------------- 182 | 183 | // Provide a single constant CPP symbol that all of GTM uses for ifdefing 184 | // iPhone code. 185 | #if TARGET_OS_IPHONE // iPhone SDK 186 | // For iPhone specific stuff 187 | #define GTM_IPHONE_SDK 1 188 | #if TARGET_IPHONE_SIMULATOR 189 | #define GTM_IPHONE_SIMULATOR 1 190 | #else 191 | #define GTM_IPHONE_DEVICE 1 192 | #endif // TARGET_IPHONE_SIMULATOR 193 | // By default, GTM has provided it's own unittesting support, define this 194 | // to use the support provided by Xcode, especially for the Xcode4 support 195 | // for unittesting. 196 | #ifndef GTM_IPHONE_USE_SENTEST 197 | #define GTM_IPHONE_USE_SENTEST 0 198 | #endif 199 | #else 200 | // For MacOS specific stuff 201 | #define GTM_MACOS_SDK 1 202 | #endif 203 | 204 | // Some of our own availability macros 205 | #if GTM_MACOS_SDK 206 | #define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE 207 | #define GTM_AVAILABLE_ONLY_ON_MACOS 208 | #else 209 | #define GTM_AVAILABLE_ONLY_ON_IPHONE 210 | #define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE 211 | #endif 212 | 213 | // Provide a symbol to include/exclude extra code for GC support. (This mainly 214 | // just controls the inclusion of finalize methods). 215 | #ifndef GTM_SUPPORT_GC 216 | #if GTM_IPHONE_SDK 217 | // iPhone never needs GC 218 | #define GTM_SUPPORT_GC 0 219 | #else 220 | // We can't find a symbol to tell if GC is supported/required, so best we 221 | // do on Mac targets is include it if we're on 10.5 or later. 222 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 223 | #define GTM_SUPPORT_GC 0 224 | #else 225 | #define GTM_SUPPORT_GC 1 226 | #endif 227 | #endif 228 | #endif 229 | 230 | // To simplify support for 64bit (and Leopard in general), we provide the type 231 | // defines for non Leopard SDKs 232 | #if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 233 | // NSInteger/NSUInteger and Max/Mins 234 | #ifndef NSINTEGER_DEFINED 235 | #if __LP64__ || NS_BUILD_32_LIKE_64 236 | typedef long NSInteger; 237 | typedef unsigned long NSUInteger; 238 | #else 239 | typedef int NSInteger; 240 | typedef unsigned int NSUInteger; 241 | #endif 242 | #define NSIntegerMax LONG_MAX 243 | #define NSIntegerMin LONG_MIN 244 | #define NSUIntegerMax ULONG_MAX 245 | #define NSINTEGER_DEFINED 1 246 | #endif // NSINTEGER_DEFINED 247 | // CGFloat 248 | #ifndef CGFLOAT_DEFINED 249 | #if defined(__LP64__) && __LP64__ 250 | // This really is an untested path (64bit on Tiger?) 251 | typedef double CGFloat; 252 | #define CGFLOAT_MIN DBL_MIN 253 | #define CGFLOAT_MAX DBL_MAX 254 | #define CGFLOAT_IS_DOUBLE 1 255 | #else /* !defined(__LP64__) || !__LP64__ */ 256 | typedef float CGFloat; 257 | #define CGFLOAT_MIN FLT_MIN 258 | #define CGFLOAT_MAX FLT_MAX 259 | #define CGFLOAT_IS_DOUBLE 0 260 | #endif /* !defined(__LP64__) || !__LP64__ */ 261 | #define CGFLOAT_DEFINED 1 262 | #endif // CGFLOAT_DEFINED 263 | #endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 264 | 265 | // Some support for advanced clang static analysis functionality 266 | // See http://clang-analyzer.llvm.org/annotations.html 267 | #ifndef __has_feature // Optional. 268 | #define __has_feature(x) 0 // Compatibility with non-clang compilers. 269 | #endif 270 | 271 | #ifndef NS_RETURNS_RETAINED 272 | #if __has_feature(attribute_ns_returns_retained) 273 | #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) 274 | #else 275 | #define NS_RETURNS_RETAINED 276 | #endif 277 | #endif 278 | 279 | #ifndef NS_RETURNS_NOT_RETAINED 280 | #if __has_feature(attribute_ns_returns_not_retained) 281 | #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) 282 | #else 283 | #define NS_RETURNS_NOT_RETAINED 284 | #endif 285 | #endif 286 | 287 | #ifndef CF_RETURNS_RETAINED 288 | #if __has_feature(attribute_cf_returns_retained) 289 | #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) 290 | #else 291 | #define CF_RETURNS_RETAINED 292 | #endif 293 | #endif 294 | 295 | #ifndef CF_RETURNS_NOT_RETAINED 296 | #if __has_feature(attribute_cf_returns_not_retained) 297 | #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) 298 | #else 299 | #define CF_RETURNS_NOT_RETAINED 300 | #endif 301 | #endif 302 | 303 | #ifndef NS_CONSUMED 304 | #if __has_feature(attribute_ns_consumed) 305 | #define NS_CONSUMED __attribute__((ns_consumed)) 306 | #else 307 | #define NS_CONSUMED 308 | #endif 309 | #endif 310 | 311 | #ifndef CF_CONSUMED 312 | #if __has_feature(attribute_cf_consumed) 313 | #define CF_CONSUMED __attribute__((cf_consumed)) 314 | #else 315 | #define CF_CONSUMED 316 | #endif 317 | #endif 318 | 319 | #ifndef NS_CONSUMES_SELF 320 | #if __has_feature(attribute_ns_consumes_self) 321 | #define NS_CONSUMES_SELF __attribute__((ns_consumes_self)) 322 | #else 323 | #define NS_CONSUMES_SELF 324 | #endif 325 | #endif 326 | 327 | // Defined on 10.6 and above. 328 | #ifndef NS_FORMAT_ARGUMENT 329 | #define NS_FORMAT_ARGUMENT(A) 330 | #endif 331 | 332 | // Defined on 10.6 and above. 333 | #ifndef NS_FORMAT_FUNCTION 334 | #define NS_FORMAT_FUNCTION(F,A) 335 | #endif 336 | 337 | // Defined on 10.6 and above. 338 | #ifndef CF_FORMAT_ARGUMENT 339 | #define CF_FORMAT_ARGUMENT(A) 340 | #endif 341 | 342 | // Defined on 10.6 and above. 343 | #ifndef CF_FORMAT_FUNCTION 344 | #define CF_FORMAT_FUNCTION(F,A) 345 | #endif 346 | 347 | #ifndef GTM_NONNULL 348 | #define GTM_NONNULL(x) __attribute__((nonnull(x))) 349 | #endif 350 | 351 | #ifdef __OBJC__ 352 | 353 | // Declared here so that it can easily be used for logging tracking if 354 | // necessary. See GTMUnitTestDevLog.h for details. 355 | @class NSString; 356 | GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...); 357 | 358 | // Macro to allow you to create NSStrings out of other macros. 359 | // #define FOO foo 360 | // NSString *fooString = GTM_NSSTRINGIFY(FOO); 361 | #if !defined (GTM_NSSTRINGIFY) 362 | #define GTM_NSSTRINGIFY_INNER(x) @#x 363 | #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x) 364 | #endif 365 | 366 | // Macro to allow fast enumeration when building for 10.5 or later, and 367 | // reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration 368 | // does keys, so pick the right thing, nothing is done on the FastEnumeration 369 | // side to be sure you're getting what you wanted. 370 | #ifndef GTM_FOREACH_OBJECT 371 | #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) 372 | #define GTM_FOREACH_ENUMEREE(element, enumeration) \ 373 | for (element in enumeration) 374 | #define GTM_FOREACH_OBJECT(element, collection) \ 375 | for (element in collection) 376 | #define GTM_FOREACH_KEY(element, collection) \ 377 | for (element in collection) 378 | #else 379 | #define GTM_FOREACH_ENUMEREE(element, enumeration) \ 380 | for (NSEnumerator *_ ## element ## _enum = enumeration; \ 381 | (element = [_ ## element ## _enum nextObject]) != nil; ) 382 | #define GTM_FOREACH_OBJECT(element, collection) \ 383 | GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator]) 384 | #define GTM_FOREACH_KEY(element, collection) \ 385 | GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator]) 386 | #endif 387 | #endif 388 | 389 | // ============================================================================ 390 | 391 | // To simplify support for both Leopard and Snow Leopard we declare 392 | // the Snow Leopard protocols that we need here. 393 | #if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 394 | #define GTM_10_6_PROTOCOLS_DEFINED 1 395 | @protocol NSConnectionDelegate 396 | @end 397 | @protocol NSAnimationDelegate 398 | @end 399 | @protocol NSImageDelegate 400 | @end 401 | @protocol NSTabViewDelegate 402 | @end 403 | #endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 404 | 405 | // GTM_SEL_STRING is for specifying selector (usually property) names to KVC 406 | // or KVO methods. 407 | // In debug it will generate warnings for undeclared selectors if 408 | // -Wunknown-selector is turned on. 409 | // In release it will have no runtime overhead. 410 | #ifndef GTM_SEL_STRING 411 | #ifdef DEBUG 412 | #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName)) 413 | #else 414 | #define GTM_SEL_STRING(selName) @#selName 415 | #endif // DEBUG 416 | #endif // GTM_SEL_STRING 417 | 418 | #endif // __OBJC__ -------------------------------------------------------------------------------- /PSGoogleReader/GTMNSString+HTML.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMNSString+HTML.h 3 | // Dealing with NSStrings that contain HTML 4 | // 5 | // Copyright 2006-2008 Google Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | // use this file except in compliance with the License. You may obtain a copy 9 | // of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | // License for the specific language governing permissions and limitations under 17 | // the License. 18 | // 19 | 20 | #import 21 | 22 | /// Utilities for NSStrings containing HTML 23 | @interface NSString (GTMNSStringHTMLAdditions) 24 | 25 | /// Get a string where internal characters that need escaping for HTML are escaped 26 | // 27 | /// For example, '&' become '&'. This will only cover characters from table 28 | /// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters 29 | /// which is what you want for a unicode encoded webpage. If you have a ascii 30 | /// or non-encoded webpage, please use stringByEscapingAsciiHTML which will 31 | /// encode all characters. 32 | /// 33 | /// For obvious reasons this call is only safe once. 34 | // 35 | // Returns: 36 | // Autoreleased NSString 37 | // 38 | - (NSString *)gtm_stringByEscapingForHTML; 39 | 40 | /// Get a string where internal characters that need escaping for HTML are escaped 41 | // 42 | /// For example, '&' become '&' 43 | /// All non-mapped characters (unicode that don't have a &keyword; mapping) 44 | /// will be converted to the appropriate &#xxx; value. If your webpage is 45 | /// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is 46 | /// faster, and produces less bloated and more readable HTML (as long as you 47 | /// are using a unicode compliant HTML reader). 48 | /// 49 | /// For obvious reasons this call is only safe once. 50 | // 51 | // Returns: 52 | // Autoreleased NSString 53 | // 54 | - (NSString *)gtm_stringByEscapingForAsciiHTML; 55 | 56 | /// Get a string where internal characters that are escaped for HTML are unescaped 57 | // 58 | /// For example, '&' becomes '&' 59 | /// Handles and 2 cases as well 60 | /// 61 | // Returns: 62 | // Autoreleased NSString 63 | // 64 | - (NSString *)gtm_stringByUnescapingFromHTML; 65 | 66 | @end -------------------------------------------------------------------------------- /PSGoogleReader/PSGoogleReader-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.perspecdev.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.1 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 2 27 | LSRequiresIPhoneOS 28 | 29 | NSMainNibFile 30 | MainWindow 31 | UISupportedInterfaceOrientations~ipad 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /PSGoogleReader/PSGoogleReader-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PSGoogleReader' target in the 'PSGoogleReader' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /PSGoogleReader/PSGoogleReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSGoogleReader.h 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | /* 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | * Redistributions of source code must retain the above copyright notice, this 14 | list of conditions and the following disclaimer. 15 | 16 | * Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | * Neither the name of the author nor the names of its contributors may be used 21 | to endorse or promote products derived from this software without specific 22 | prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 28 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | #import 37 | 38 | @class SBJsonParser; 39 | 40 | @protocol PSGoogleReaderDelegate 41 | 42 | - (void)googleReaderIncrementNetworkActivity; 43 | - (void)googleReaderDecrementNetworkActivity; 44 | - (void)googleReaderInitializedAndReady; 45 | - (void)googleReaderNeedsLogin; 46 | - (void)googleReaderReadingListData:(NSArray *)items isLastBatch:(BOOL)isLastBatch; 47 | - (BOOL)googleReaderIsReadyForMoreItems; 48 | - (void)googleReaderReadingListDataWillComplete; 49 | - (void)googleReaderReadingListDataDidComplete; 50 | - (void)googleReaderCouldNotGetReadingList; 51 | - (void)googleReaderSubscriptionList:(NSArray *)aSubscriptionList; 52 | - (void)googleReaderIsReadSynced:(NSString *)itemId; 53 | - (void)googleReaderSubscriptionAdded; 54 | - (void)googleReaderCouldNotAddSubscription; 55 | - (void)googleReaderSubscriptionRemoved; 56 | - (void)googleReaderCouldNotRemoveSubscription; 57 | - (void)googleReaderURLError:(NSError *)error; 58 | 59 | @end 60 | 61 | @interface PSGoogleReader : NSObject { 62 | NSString *SID; 63 | NSTimeInterval lastUpdate; 64 | BOOL gettingReadingList; 65 | id __weak delegate; 66 | 67 | NSString *URLFormatGetSID; 68 | NSString *URLFormatGetToken; 69 | NSString *URLFormatQuickAddFeed; 70 | NSString *URLFormatAddFeed; 71 | NSString *URLFormatEditFeed; 72 | NSString *URLFormatRemoveFeed; 73 | NSString *URLFormatSetFeedLabel; 74 | NSString *URLFormatGetUnreadCount; 75 | NSString *URLFormatGetUserInfo; 76 | NSString *URLFormatGetFeed; 77 | NSString *URLFormatGetLabel; 78 | NSString *URLFormatGetReadingListIds; 79 | NSString *URLFormatGetStarredIds; 80 | NSString *URLFormatGetReadingListContents; 81 | NSString *URLFormatGetSubscriptionList; 82 | NSString *URLFormatGetStarred; 83 | NSString *URLFormatGetBroadcasted; 84 | NSString *URLFormatGetNotes; 85 | NSString *URLFormatAddTag; 86 | NSString *URLFormatRemoveTag; 87 | NSString *URLFormatSetRead; 88 | NSString *URLFormatSetNotRead; 89 | NSString *URLFormatSetFeedRead; 90 | NSString *URLFormatSetStarred; 91 | NSString *URLFormatSetNotStarred; 92 | NSString *URLFormatSetLike; 93 | NSString *URLFormatSetNotLike; 94 | NSString *URLFormatSetBroadcast; 95 | NSString *URLFormatSetNotBroadcast; 96 | NSString *URLFormatEmail; 97 | 98 | NSMutableDictionary *postFields; 99 | 100 | NSString *username; 101 | NSString *password; 102 | NSString *token; 103 | NSString *unixTimeCutoff; 104 | NSString *excludeTarget; 105 | NSString *numResults; 106 | NSString *continuationString; 107 | NSString *client; 108 | NSString *sortOrder; 109 | NSString *itemIdentifier; 110 | NSString *feedURL; 111 | NSString *feedId; 112 | BOOL needsLogin; 113 | BOOL processingItemsToModify; 114 | 115 | NSMutableDictionary *cookieInfo; 116 | NSMutableSet *connections; 117 | NSMutableDictionary *connectionIdentifiers; 118 | NSMutableDictionary *responseData; 119 | NSMutableArray *tokenSelectors; 120 | NSMutableArray *itemsToModify; 121 | SBJsonParser *json; 122 | } 123 | 124 | @property (nonatomic, weak) id delegate; 125 | @property (nonatomic, strong) NSString *SID; 126 | @property (nonatomic, readonly) NSString *username; 127 | @property (nonatomic, readonly) NSString *password; 128 | @property (nonatomic) NSTimeInterval lastUpdate; 129 | @property (nonatomic) BOOL gettingReadingList; 130 | 131 | - (id)init; 132 | - (id)initWithSID:(NSString *)anSID; 133 | - (void)resetForNewRequest; 134 | - (void)setURLFormats; 135 | - (void)loginWithUsername:(NSString *)aUsername withPassword:(NSString *)aPassword; 136 | - (void)logout; 137 | - (void)retrieveTokenWithSelectorName:(NSString *)selectorName; 138 | - (void)retrieveSubscriptionList; 139 | - (void)retrieveUnreadCount; 140 | - (void)retrieveReadingList; 141 | - (void)markAsRead:(NSString *)itemId; 142 | - (void)markAsUnread:(NSString *)itemId; 143 | - (void)markAsStarred:(NSString *)itemId; 144 | - (void)markAsUnstarred:(NSString *)itemId; 145 | - (void)markFeedAsRead:(NSString *)aFeedId; 146 | - (void)quickAddFeed:(NSString *)aFeedURL; 147 | - (void)quickAddFeedFromPresetURL; 148 | - (void)removeFeed:(NSString *)aFeedId; 149 | - (void)removeFeedFromPresetId; 150 | - (void)processItemsToModify; 151 | - (void)rerunActionForConnectionIdentifier:(NSString *)identifier; 152 | - (void)cancelAllConnections; 153 | 154 | @end -------------------------------------------------------------------------------- /PSGoogleReader/PSGoogleReaderAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSGoogleReaderAppDelegate.h 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "PSGoogleReader.h" 12 | 13 | @class RootViewController; 14 | 15 | @class DetailViewController; 16 | 17 | @interface PSGoogleReaderAppDelegate : NSObject { 18 | PSGoogleReader *googleReader; 19 | int networkActivityCounter; 20 | } 21 | 22 | @property (nonatomic, strong) IBOutlet UIWindow *window; 23 | 24 | @property (nonatomic, weak) IBOutlet UISplitViewController *splitViewController; 25 | 26 | @property (nonatomic, weak) IBOutlet RootViewController *rootViewController; 27 | 28 | @property (nonatomic, weak) IBOutlet DetailViewController *detailViewController; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /PSGoogleReader/PSGoogleReaderAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TODO: Add UITableView, etc to make a cleaner demo UI, rather than just spitting everything out via NSLog 3 | // 4 | // PSGoogleReaderAppDelegate.m 5 | // PSGoogleReader 6 | // 7 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 8 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 9 | // 10 | 11 | #import "PSGoogleReaderAppDelegate.h" 12 | 13 | #import "RootViewController.h" 14 | 15 | @implementation PSGoogleReaderAppDelegate 16 | 17 | 18 | @synthesize window=_window; 19 | 20 | @synthesize splitViewController=_splitViewController; 21 | 22 | @synthesize rootViewController=_rootViewController; 23 | 24 | @synthesize detailViewController=_detailViewController; 25 | 26 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 27 | // Override point for customization after application launch. 28 | // Add the split view controller's view to the window and display. 29 | self.window.rootViewController = self.splitViewController; 30 | [self.window makeKeyAndVisible]; 31 | 32 | networkActivityCounter = 0; 33 | 34 | NSString *username = @"google-acount-username"; 35 | NSString *password = @"google-account-password"; 36 | googleReader = [[PSGoogleReader alloc] init]; 37 | // you should store googleReader.SID when the googleReaderInitializedAndReady method returns, then 38 | // pass that value to initWithSID: rather than always logging in with the user's username & password 39 | [googleReader loginWithUsername:username withPassword:password]; 40 | googleReader.delegate = self; // see below for delegate methods 41 | 42 | return YES; 43 | } 44 | 45 | - (void)applicationWillResignActive:(UIApplication *)application { 46 | /* 47 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 48 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 49 | */ 50 | } 51 | 52 | - (void)applicationDidEnterBackground:(UIApplication *)application { 53 | /* 54 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 55 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 56 | */ 57 | } 58 | 59 | - (void)applicationWillEnterForeground:(UIApplication *)application { 60 | /* 61 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 62 | */ 63 | } 64 | 65 | - (void)applicationDidBecomeActive:(UIApplication *)application { 66 | /* 67 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 68 | */ 69 | } 70 | 71 | - (void)applicationWillTerminate:(UIApplication *)application { 72 | /* 73 | Called when the application is about to terminate. 74 | Save data if appropriate. 75 | See also applicationDidEnterBackground:. 76 | */ 77 | } 78 | 79 | # pragma mark - PSGoogleReaderDelegate methods 80 | 81 | - (void)googleReaderIncrementNetworkActivity { 82 | if (networkActivityCounter++ == 0) { 83 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 84 | } 85 | } 86 | 87 | - (void)googleReaderDecrementNetworkActivity { 88 | if (--networkActivityCounter <= 0) { 89 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 90 | networkActivityCounter = 0; // just in case 91 | } 92 | } 93 | 94 | - (void)googleReaderInitializedAndReady { 95 | NSLog(@"PSGoogleReader initialized and ready"); 96 | NSLog(@"Retrieving reading list..."); 97 | [googleReader retrieveReadingList]; 98 | } 99 | 100 | - (void)googleReaderNeedsLogin { 101 | NSLog(@"Google Reader needs login"); 102 | } 103 | 104 | - (void)googleReaderReadingListData:(NSArray *)items isLastBatch:(BOOL)isLastBatch { 105 | for (NSDictionary *item in items) { 106 | NSLog(@"%@", [item objectForKey:@"title"]); 107 | } 108 | } 109 | 110 | - (BOOL)googleReaderIsReadyForMoreItems { 111 | return YES; 112 | } 113 | 114 | - (void)googleReaderReadingListDataDidComplete { 115 | NSLog(@"Reading list data complete"); 116 | } 117 | 118 | - (void)googleReaderReadingListDataWillComplete { 119 | // 120 | } 121 | 122 | - (void)googleReaderCouldNotGetReadingList { 123 | NSLog(@"Could not get reading list"); 124 | } 125 | 126 | - (void)googleReaderSubscriptionList:(NSArray *)aSubscriptionList { 127 | // 128 | } 129 | 130 | - (void)googleReaderIsReadSynced:(NSString *)itemId { 131 | // 132 | } 133 | 134 | - (void)googleReaderSubscriptionAdded { 135 | // 136 | } 137 | 138 | - (void)googleReaderCouldNotAddSubscription { 139 | // 140 | } 141 | 142 | - (void)googleReaderSubscriptionRemoved { 143 | // 144 | } 145 | 146 | - (void)googleReaderCouldNotRemoveSubscription { 147 | // 148 | } 149 | 150 | - (void)googleReaderURLError:(NSError *)error { 151 | NSLog(@"URL Error: %@", [error description]); 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /PSGoogleReader/README: -------------------------------------------------------------------------------- 1 | PSGoogleReader is a class that connects to Google Reader. I don't have a pretty 2 | demo UI set up, so you won't see much in the simulator when you run this app. Check 3 | NSLog output to see very simplified demo results. 4 | 5 | Be sure to set your client (app) name in PSGoogleReader.m 6 | Set your Google Reader username/password in PSGoogleReaderAppDelegate.m 7 | 8 | Code license is pretty generous. See comments at the top of PSGoogleReader.m for details. 9 | 10 | Email me if you have any questions: daniel@perspecdev.com -------------------------------------------------------------------------------- /PSGoogleReader/RootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RootViewController.h 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DetailViewController; 12 | 13 | @interface RootViewController : UITableViewController { 14 | 15 | } 16 | 17 | 18 | @property (nonatomic, strong) IBOutlet DetailViewController *detailViewController; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /PSGoogleReader/RootViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RootViewController.m 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ). 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import "RootViewController.h" 10 | 11 | #import "DetailViewController.h" 12 | 13 | @implementation RootViewController 14 | 15 | @synthesize detailViewController; 16 | 17 | - (void)viewDidLoad 18 | { 19 | [super viewDidLoad]; 20 | self.clearsSelectionOnViewWillAppear = NO; 21 | self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); 22 | } 23 | 24 | 25 | - (void)viewWillAppear:(BOOL)animated 26 | { 27 | [super viewWillAppear:animated]; 28 | } 29 | 30 | - (void)viewDidAppear:(BOOL)animated 31 | { 32 | [super viewDidAppear:animated]; 33 | } 34 | 35 | - (void)viewWillDisappear:(BOOL)animated 36 | { 37 | [super viewWillDisappear:animated]; 38 | } 39 | 40 | - (void)viewDidDisappear:(BOOL)animated 41 | { 42 | [super viewDidDisappear:animated]; 43 | } 44 | 45 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 46 | return YES; 47 | } 48 | 49 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 50 | { 51 | return 1; 52 | 53 | } 54 | 55 | 56 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 57 | { 58 | return 0; 59 | 60 | } 61 | 62 | 63 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 64 | { 65 | static NSString *CellIdentifier = @"Cell"; 66 | 67 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 68 | if (cell == nil) { 69 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 70 | } 71 | 72 | // Configure the cell. 73 | 74 | return cell; 75 | } 76 | 77 | /* 78 | // Override to support conditional editing of the table view. 79 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 80 | { 81 | // Return NO if you do not want the specified item to be editable. 82 | return YES; 83 | } 84 | */ 85 | 86 | /* 87 | // Override to support editing the table view. 88 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 89 | { 90 | 91 | if (editingStyle == UITableViewCellEditingStyleDelete) { 92 | // Delete the row from the data source. 93 | [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 94 | } 95 | else if (editingStyle == UITableViewCellEditingStyleInsert) { 96 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. 97 | } 98 | } 99 | */ 100 | 101 | /* 102 | // Override to support rearranging the table view. 103 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 104 | { 105 | } 106 | */ 107 | 108 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 109 | { 110 | // Navigation logic may go here -- for example, create and push another view controller. 111 | /* 112 | <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; 113 | NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath]; 114 | // ... 115 | // Pass the selected object to the new view controller. 116 | [self.navigationController pushViewController:detailViewController animated:YES]; 117 | [detailViewController release]; 118 | */ 119 | } 120 | 121 | - (void)didReceiveMemoryWarning 122 | { 123 | // Releases the view if it doesn't have a superview. 124 | [super didReceiveMemoryWarning]; 125 | 126 | // Relinquish ownership any cached data, images, etc that aren't in use. 127 | } 128 | 129 | - (void)viewDidUnload 130 | { 131 | // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. 132 | // For example: self.myOutlet = nil; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 44 4 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON 5 | END 6 | JSON.h 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 51 10 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/JSON.h 11 | END 12 | SBJsonBase.h 13 | K 25 14 | svn:wc:ra_dav:version-url 15 | V 57 16 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonBase.h 17 | END 18 | SBJsonParser.h 19 | K 25 20 | svn:wc:ra_dav:version-url 21 | V 59 22 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonParser.h 23 | END 24 | SBJsonWriter.h 25 | K 25 26 | svn:wc:ra_dav:version-url 27 | V 59 28 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonWriter.h 29 | END 30 | SBJSON.h 31 | K 25 32 | svn:wc:ra_dav:version-url 33 | V 53 34 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJSON.h 35 | END 36 | SBJsonBase.m 37 | K 25 38 | svn:wc:ra_dav:version-url 39 | V 57 40 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonBase.m 41 | END 42 | SBJsonParser.m 43 | K 25 44 | svn:wc:ra_dav:version-url 45 | V 59 46 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonParser.m 47 | END 48 | SBJsonWriter.m 49 | K 25 50 | svn:wc:ra_dav:version-url 51 | V 59 52 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJsonWriter.m 53 | END 54 | NSObject+SBJSON.h 55 | K 25 56 | svn:wc:ra_dav:version-url 57 | V 62 58 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/NSObject+SBJSON.h 59 | END 60 | NSString+SBJSON.h 61 | K 25 62 | svn:wc:ra_dav:version-url 63 | V 62 64 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/NSString+SBJSON.h 65 | END 66 | SBJSON.m 67 | K 25 68 | svn:wc:ra_dav:version-url 69 | V 53 70 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/SBJSON.m 71 | END 72 | NSObject+SBJSON.m 73 | K 25 74 | svn:wc:ra_dav:version-url 75 | V 62 76 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/NSObject+SBJSON.m 77 | END 78 | NSString+SBJSON.m 79 | K 25 80 | svn:wc:ra_dav:version-url 81 | V 62 82 | /newsstand/!svn/ver/4/Newsstand/Classes/JSON/NSString+SBJSON.m 83 | END 84 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 4 5 | http://daniel@svn.gummydev.com:80/newsstand/Newsstand/Classes/JSON 6 | http://daniel@svn.gummydev.com:80/newsstand 7 | 8 | 9 | 10 | 2010-05-16T16:38:25.051850Z 11 | 4 12 | daniel 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 6832bc1b-7a86-0410-95ef-da82e53b28ac 28 | 29 | JSON.h 30 | file 31 | 32 | 33 | 34 | 35 | 2010-05-16T16:12:47.000000Z 36 | ae257619c962a55d5fa93b7825837756 37 | 2010-05-16T16:38:25.051850Z 38 | 4 39 | daniel 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 2297 62 | 63 | SBJsonBase.h 64 | file 65 | 66 | 67 | 68 | 69 | 2010-05-16T16:12:47.000000Z 70 | 048b288f47c5a61c084536c82c81f9af 71 | 2010-05-16T16:38:25.051850Z 72 | 4 73 | daniel 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 2946 96 | 97 | SBJsonParser.h 98 | file 99 | 100 | 101 | 102 | 103 | 2010-05-16T16:12:47.000000Z 104 | a144e6967ed27047ee00fba36f60b848 105 | 2010-05-16T16:38:25.051850Z 106 | 4 107 | daniel 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 3083 130 | 131 | SBJsonWriter.h 132 | file 133 | 134 | 135 | 136 | 137 | 2010-05-16T16:12:47.000000Z 138 | 37d52748720cd2c19cd2cfa16baa6f14 139 | 2010-05-16T16:38:25.051850Z 140 | 4 141 | daniel 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 4416 164 | 165 | SBJSON.h 166 | file 167 | 168 | 169 | 170 | 171 | 2010-05-16T16:12:47.000000Z 172 | 23022b462daf29618e033215c58aac94 173 | 2010-05-16T16:38:25.051850Z 174 | 4 175 | daniel 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 2797 198 | 199 | SBJsonBase.m 200 | file 201 | 202 | 203 | 204 | 205 | 2010-05-16T16:12:47.000000Z 206 | 4885652fed0a995c1aff1cf47c15117c 207 | 2010-05-16T16:38:25.051850Z 208 | 4 209 | daniel 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 2753 232 | 233 | SBJsonParser.m 234 | file 235 | 236 | 237 | 238 | 239 | 2010-05-16T16:12:47.000000Z 240 | 9dac8ca97a24ae84b56fc9ede4651d5c 241 | 2010-05-16T16:38:25.051850Z 242 | 4 243 | daniel 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 14032 266 | 267 | SBJsonWriter.m 268 | file 269 | 270 | 271 | 272 | 273 | 2010-05-16T16:12:47.000000Z 274 | 92548eb6ea5c890522c2d342b41d9682 275 | 2010-05-16T16:38:25.051850Z 276 | 4 277 | daniel 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 7974 300 | 301 | NSObject+SBJSON.h 302 | file 303 | 304 | 305 | 306 | 307 | 2010-05-16T16:12:47.000000Z 308 | f7f559bceafad09d4253aaf5048d33e6 309 | 2010-05-16T16:38:25.051850Z 310 | 4 311 | daniel 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 2561 334 | 335 | NSString+SBJSON.h 336 | file 337 | 338 | 339 | 340 | 341 | 2010-05-16T16:12:47.000000Z 342 | b133112104c190709fbbd07da0ee7b2c 343 | 2010-05-16T16:38:25.051850Z 344 | 4 345 | daniel 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 2326 368 | 369 | SBJSON.m 370 | file 371 | 372 | 373 | 374 | 375 | 2010-05-16T16:12:47.000000Z 376 | 53d1eb806d6cc3dab7e82238b29c8f4e 377 | 2010-05-16T16:38:25.051850Z 378 | 4 379 | daniel 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 6844 402 | 403 | NSObject+SBJSON.m 404 | file 405 | 406 | 407 | 408 | 409 | 2010-05-16T16:12:47.000000Z 410 | c7db91f721f715e70b26e88a2a2da90e 411 | 2010-05-16T16:38:25.051850Z 412 | 4 413 | daniel 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 2206 436 | 437 | NSString+SBJSON.m 438 | file 439 | 440 | 441 | 442 | 443 | 2010-05-16T16:12:47.000000Z 444 | 8b741eab04ec172ec1d8629b923fc9a8 445 | 2010-05-16T16:38:25.051850Z 446 | 4 447 | daniel 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 2173 470 | 471 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/JSON.h.svn-base: -------------------------------------------------------------------------------- 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 | 51 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/NSObject+SBJSON.h.svn-base: -------------------------------------------------------------------------------- 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 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 | 69 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/NSObject+SBJSON.m.svn-base: -------------------------------------------------------------------------------- 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 54 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/NSString+SBJSON.h.svn-base: -------------------------------------------------------------------------------- 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 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 59 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/NSString+SBJSON.m.svn-base: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2007-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 "NSString+SBJSON.h" 31 | #import "SBJsonParser.h" 32 | 33 | @implementation NSString (NSString_SBJSON) 34 | 35 | - (id)JSONFragmentValue 36 | { 37 | SBJsonParser *jsonParser = [SBJsonParser new]; 38 | id repr = [jsonParser fragmentWithString:self]; 39 | if (!repr) 40 | NSLog(@"-JSONFragmentValue failed. Error trace is: %@", [jsonParser errorTrace]); 41 | [jsonParser release]; 42 | return repr; 43 | } 44 | 45 | - (id)JSONValue 46 | { 47 | SBJsonParser *jsonParser = [SBJsonParser new]; 48 | id repr = [jsonParser objectWithString:self]; 49 | if (!repr) 50 | NSLog(@"-JSONValue failed. Error trace is: %@", [jsonParser errorTrace]); 51 | [jsonParser release]; 52 | return repr; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJSON.h.svn-base: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2007-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 31 | #import "SBJsonParser.h" 32 | #import "SBJsonWriter.h" 33 | 34 | /** 35 | @brief Facade for SBJsonWriter/SBJsonParser. 36 | 37 | Requests are forwarded to instances of SBJsonWriter and SBJsonParser. 38 | */ 39 | @interface SBJSON : SBJsonBase { 40 | 41 | @private 42 | SBJsonParser *jsonParser; 43 | SBJsonWriter *jsonWriter; 44 | } 45 | 46 | 47 | /// Return the fragment represented by the given string 48 | - (id)fragmentWithString:(NSString*)jsonrep 49 | error:(NSError**)error; 50 | 51 | /// Return the object represented by the given string 52 | - (id)objectWithString:(NSString*)jsonrep 53 | error:(NSError**)error; 54 | 55 | /// Parse the string and return the represented object (or scalar) 56 | - (id)objectWithString:(id)value 57 | allowScalar:(BOOL)x 58 | error:(NSError**)error; 59 | 60 | 61 | /// Return JSON representation of an array or dictionary 62 | - (NSString*)stringWithObject:(id)value 63 | error:(NSError**)error; 64 | 65 | /// Return JSON representation of any legal JSON value 66 | - (NSString*)stringWithFragment:(id)value 67 | error:(NSError**)error; 68 | 69 | /// Return JSON representation (or fragment) for the given object 70 | - (NSString*)stringWithObject:(id)value 71 | allowScalar:(BOOL)x 72 | error:(NSError**)error; 73 | 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJSON.m.svn-base: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2007-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 "SBJSON.h" 31 | 32 | @implementation SBJSON 33 | 34 | - (id)init { 35 | self = [super init]; 36 | if (self) { 37 | jsonWriter = [SBJsonWriter new]; 38 | jsonParser = [SBJsonParser new]; 39 | [self setMaxDepth:512]; 40 | 41 | } 42 | return self; 43 | } 44 | 45 | - (void)dealloc { 46 | [jsonWriter release]; 47 | [jsonParser release]; 48 | [super dealloc]; 49 | } 50 | 51 | #pragma mark Writer 52 | 53 | 54 | - (NSString *)stringWithObject:(id)obj { 55 | NSString *repr = [jsonWriter stringWithObject:obj]; 56 | if (repr) 57 | return repr; 58 | 59 | [errorTrace release]; 60 | errorTrace = [[jsonWriter errorTrace] mutableCopy]; 61 | return nil; 62 | } 63 | 64 | /** 65 | Returns a string containing JSON representation of the passed in value, or nil on error. 66 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 67 | 68 | @param value any instance that can be represented as a JSON fragment 69 | @param allowScalar wether to return json fragments for scalar objects 70 | @param error used to return an error by reference (pass NULL if this is not desired) 71 | 72 | @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. 73 | */ 74 | - (NSString*)stringWithObject:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { 75 | 76 | NSString *json = allowScalar ? [jsonWriter stringWithFragment:value] : [jsonWriter stringWithObject:value]; 77 | if (json) 78 | return json; 79 | 80 | [errorTrace release]; 81 | errorTrace = [[jsonWriter errorTrace] mutableCopy]; 82 | 83 | if (error) 84 | *error = [errorTrace lastObject]; 85 | return nil; 86 | } 87 | 88 | /** 89 | Returns a string containing JSON representation of the passed in value, or nil on error. 90 | If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. 91 | 92 | @param value any instance that can be represented as a JSON fragment 93 | @param error used to return an error by reference (pass NULL if this is not desired) 94 | 95 | @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. 96 | */ 97 | - (NSString*)stringWithFragment:(id)value error:(NSError**)error { 98 | return [self stringWithObject:value 99 | allowScalar:YES 100 | error:error]; 101 | } 102 | 103 | /** 104 | Returns a string containing JSON representation of the passed in value, or nil on error. 105 | If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. 106 | 107 | @param value a NSDictionary or NSArray instance 108 | @param error used to return an error by reference (pass NULL if this is not desired) 109 | */ 110 | - (NSString*)stringWithObject:(id)value error:(NSError**)error { 111 | return [self stringWithObject:value 112 | allowScalar:NO 113 | error:error]; 114 | } 115 | 116 | #pragma mark Parsing 117 | 118 | - (id)objectWithString:(NSString *)repr { 119 | id obj = [jsonParser objectWithString:repr]; 120 | if (obj) 121 | return obj; 122 | 123 | [errorTrace release]; 124 | errorTrace = [[jsonParser errorTrace] mutableCopy]; 125 | 126 | return nil; 127 | } 128 | 129 | /** 130 | Returns the object represented by the passed-in string or nil on error. The returned object can be 131 | a string, number, boolean, null, array or dictionary. 132 | 133 | @param value the json string to parse 134 | @param allowScalar whether to return objects for JSON fragments 135 | @param error used to return an error by reference (pass NULL if this is not desired) 136 | 137 | @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. 138 | */ 139 | - (id)objectWithString:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { 140 | 141 | id obj = allowScalar ? [jsonParser fragmentWithString:value] : [jsonParser objectWithString:value]; 142 | if (obj) 143 | return obj; 144 | 145 | [errorTrace release]; 146 | errorTrace = [[jsonParser errorTrace] mutableCopy]; 147 | 148 | if (error) 149 | *error = [errorTrace lastObject]; 150 | return nil; 151 | } 152 | 153 | /** 154 | Returns the object represented by the passed-in string or nil on error. The returned object can be 155 | a string, number, boolean, null, array or dictionary. 156 | 157 | @param repr the json string to parse 158 | @param error used to return an error by reference (pass NULL if this is not desired) 159 | 160 | @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. 161 | */ 162 | - (id)fragmentWithString:(NSString*)repr error:(NSError**)error { 163 | return [self objectWithString:repr 164 | allowScalar:YES 165 | error:error]; 166 | } 167 | 168 | /** 169 | Returns the object represented by the passed-in string or nil on error. The returned object 170 | will be either a dictionary or an array. 171 | 172 | @param repr the json string to parse 173 | @param error used to return an error by reference (pass NULL if this is not desired) 174 | */ 175 | - (id)objectWithString:(NSString*)repr error:(NSError**)error { 176 | return [self objectWithString:repr 177 | allowScalar:NO 178 | error:error]; 179 | } 180 | 181 | 182 | 183 | #pragma mark Properties - parsing 184 | 185 | - (NSUInteger)maxDepth { 186 | return jsonParser.maxDepth; 187 | } 188 | 189 | - (void)setMaxDepth:(NSUInteger)d { 190 | jsonWriter.maxDepth = jsonParser.maxDepth = d; 191 | } 192 | 193 | 194 | #pragma mark Properties - writing 195 | 196 | - (BOOL)humanReadable { 197 | return jsonWriter.humanReadable; 198 | } 199 | 200 | - (void)setHumanReadable:(BOOL)x { 201 | jsonWriter.humanReadable = x; 202 | } 203 | 204 | - (BOOL)sortKeys { 205 | return jsonWriter.sortKeys; 206 | } 207 | 208 | - (void)setSortKeys:(BOOL)x { 209 | jsonWriter.sortKeys = x; 210 | } 211 | 212 | @end 213 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJsonBase.h.svn-base: -------------------------------------------------------------------------------- 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 31 | 32 | extern NSString * SBJSONErrorDomain; 33 | 34 | 35 | enum { 36 | EUNSUPPORTED = 1, 37 | EPARSENUM, 38 | EPARSE, 39 | EFRAGMENT, 40 | ECTRL, 41 | EUNICODE, 42 | EDEPTH, 43 | EESCAPE, 44 | ETRAILCOMMA, 45 | ETRAILGARBAGE, 46 | EEOF, 47 | EINPUT 48 | }; 49 | 50 | /** 51 | @brief Common base class for parsing & writing. 52 | 53 | This class contains the common error-handling code and option between the parser/writer. 54 | */ 55 | @interface SBJsonBase : NSObject { 56 | NSMutableArray *errorTrace; 57 | 58 | @protected 59 | NSUInteger depth, maxDepth; 60 | } 61 | 62 | /** 63 | @brief The maximum recursing depth. 64 | 65 | Defaults to 512. If the input is nested deeper than this the input will be deemed to be 66 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 67 | turn off this security feature by setting the maxDepth value to 0. 68 | */ 69 | @property NSUInteger maxDepth; 70 | 71 | /** 72 | @brief Return an error trace, or nil if there was no errors. 73 | 74 | Note that this method returns the trace of the last method that failed. 75 | You need to check the return value of the call you're making to figure out 76 | if the call actually failed, before you know call this method. 77 | */ 78 | @property(copy,readonly) NSArray* errorTrace; 79 | 80 | /// @internal for use in subclasses to add errors to the stack trace 81 | - (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str; 82 | 83 | /// @internal for use in subclasess to clear the error before a new parsing attempt 84 | - (void)clearErrorTrace; 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJsonBase.m.svn-base: -------------------------------------------------------------------------------- 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 "SBJsonBase.h" 31 | NSString * SBJSONErrorDomain = @"org.brautaset.JSON.ErrorDomain"; 32 | 33 | 34 | @implementation SBJsonBase 35 | 36 | @synthesize errorTrace; 37 | @synthesize maxDepth; 38 | 39 | - (id)init { 40 | self = [super init]; 41 | if (self) 42 | self.maxDepth = 512; 43 | return self; 44 | } 45 | 46 | - (void)dealloc { 47 | [errorTrace release]; 48 | [super dealloc]; 49 | } 50 | 51 | - (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str { 52 | NSDictionary *userInfo; 53 | if (!errorTrace) { 54 | errorTrace = [NSMutableArray new]; 55 | userInfo = [NSDictionary dictionaryWithObject:str forKey:NSLocalizedDescriptionKey]; 56 | 57 | } else { 58 | userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 59 | str, NSLocalizedDescriptionKey, 60 | [errorTrace lastObject], NSUnderlyingErrorKey, 61 | nil]; 62 | } 63 | 64 | NSError *error = [NSError errorWithDomain:SBJSONErrorDomain code:code userInfo:userInfo]; 65 | 66 | [self willChangeValueForKey:@"errorTrace"]; 67 | [errorTrace addObject:error]; 68 | [self didChangeValueForKey:@"errorTrace"]; 69 | } 70 | 71 | - (void)clearErrorTrace { 72 | [self willChangeValueForKey:@"errorTrace"]; 73 | [errorTrace release]; 74 | errorTrace = nil; 75 | [self didChangeValueForKey:@"errorTrace"]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJsonParser.h.svn-base: -------------------------------------------------------------------------------- 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 31 | #import "SBJsonBase.h" 32 | 33 | /** 34 | @brief Options for the parser class. 35 | 36 | This exists so the SBJSON facade can implement the options in the parser without having to re-declare them. 37 | */ 38 | @protocol SBJsonParser 39 | 40 | /** 41 | @brief Return the object represented by the given string. 42 | 43 | Returns the object represented by the passed-in string or nil on error. The returned object can be 44 | a string, number, boolean, null, array or dictionary. 45 | 46 | @param repr the json string to parse 47 | */ 48 | - (id)objectWithString:(NSString *)repr; 49 | 50 | @end 51 | 52 | 53 | /** 54 | @brief The JSON parser class. 55 | 56 | JSON is mapped to Objective-C types in the following way: 57 | 58 | @li Null -> NSNull 59 | @li String -> NSMutableString 60 | @li Array -> NSMutableArray 61 | @li Object -> NSMutableDictionary 62 | @li Boolean -> NSNumber (initialised with -initWithBool:) 63 | @li Number -> NSDecimalNumber 64 | 65 | Since Objective-C doesn't have a dedicated class for boolean values, these turns into NSNumber 66 | instances. These are initialised with the -initWithBool: method, and 67 | round-trip back to JSON properly. (They won't silently suddenly become 0 or 1; they'll be 68 | represented as 'true' and 'false' again.) 69 | 70 | JSON numbers turn into NSDecimalNumber instances, 71 | as we can thus avoid any loss of precision. (JSON allows ridiculously large numbers.) 72 | 73 | */ 74 | @interface SBJsonParser : SBJsonBase { 75 | 76 | @private 77 | const char *c; 78 | } 79 | 80 | @end 81 | 82 | // don't use - exists for backwards compatibility with 2.1.x only. Will be removed in 2.3. 83 | @interface SBJsonParser (Private) 84 | - (id)fragmentWithString:(id)repr; 85 | @end 86 | 87 | 88 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJsonWriter.h.svn-base: -------------------------------------------------------------------------------- 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 31 | #import "SBJsonBase.h" 32 | 33 | /** 34 | @brief Options for the writer class. 35 | 36 | This exists so the SBJSON facade can implement the options in the writer without having to re-declare them. 37 | */ 38 | @protocol SBJsonWriter 39 | 40 | /** 41 | @brief Whether we are generating human-readable (multiline) JSON. 42 | 43 | Set whether or not to generate human-readable JSON. The default is NO, which produces 44 | JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable 45 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 46 | spaces per nesting level. 47 | */ 48 | @property BOOL humanReadable; 49 | 50 | /** 51 | @brief Whether or not to sort the dictionary keys in the output. 52 | 53 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 54 | (This is useful if you need to compare two structures, for example.) The default is NO. 55 | */ 56 | @property BOOL sortKeys; 57 | 58 | /** 59 | @brief Return JSON representation (or fragment) for the given object. 60 | 61 | Returns a string containing JSON representation of the passed in value, or nil on error. 62 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 63 | 64 | @param value any instance that can be represented as a JSON fragment 65 | 66 | */ 67 | - (NSString*)stringWithObject:(id)value; 68 | 69 | @end 70 | 71 | 72 | /** 73 | @brief The JSON writer class. 74 | 75 | Objective-C types are mapped to JSON types in the following way: 76 | 77 | @li NSNull -> Null 78 | @li NSString -> String 79 | @li NSArray -> Array 80 | @li NSDictionary -> Object 81 | @li NSNumber (-initWithBool:) -> Boolean 82 | @li NSNumber -> Number 83 | 84 | In JSON the keys of an object must be strings. NSDictionary keys need 85 | not be, but attempting to convert an NSDictionary with non-string keys 86 | into JSON will throw an exception. 87 | 88 | NSNumber instances created with the +initWithBool: method are 89 | converted into the JSON boolean "true" and "false" values, and vice 90 | versa. Any other NSNumber instances are converted to a JSON number the 91 | way you would expect. 92 | 93 | */ 94 | @interface SBJsonWriter : SBJsonBase { 95 | 96 | @private 97 | BOOL sortKeys, humanReadable; 98 | } 99 | 100 | @end 101 | 102 | // don't use - exists for backwards compatibility. Will be removed in 2.3. 103 | @interface SBJsonWriter (Private) 104 | - (NSString*)stringWithFragment:(id)value; 105 | @end 106 | 107 | /** 108 | @brief Allows generation of JSON for otherwise unsupported classes. 109 | 110 | If you have a custom class that you want to create a JSON representation for you can implement 111 | this method in your class. It should return a representation of your object defined 112 | in terms of objects that can be translated into JSON. For example, a Person 113 | object might implement it like this: 114 | 115 | @code 116 | - (id)jsonProxyObject { 117 | return [NSDictionary dictionaryWithObjectsAndKeys: 118 | name, @"name", 119 | phone, @"phone", 120 | email, @"email", 121 | nil]; 122 | } 123 | @endcode 124 | 125 | */ 126 | @interface NSObject (SBProxyForJson) 127 | - (id)proxyForJson; 128 | @end 129 | 130 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/.svn/text-base/SBJsonWriter.m.svn-base: -------------------------------------------------------------------------------- 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 "SBJsonWriter.h" 31 | 32 | @interface SBJsonWriter () 33 | 34 | - (BOOL)appendValue:(id)fragment into:(NSMutableString*)json; 35 | - (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json; 36 | - (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json; 37 | - (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json; 38 | 39 | - (NSString*)indent; 40 | 41 | @end 42 | 43 | @implementation SBJsonWriter 44 | 45 | static NSMutableCharacterSet *kEscapeChars; 46 | 47 | + (void)initialize { 48 | kEscapeChars = [[NSMutableCharacterSet characterSetWithRange: NSMakeRange(0,32)] retain]; 49 | [kEscapeChars addCharactersInString: @"\"\\"]; 50 | } 51 | 52 | 53 | @synthesize sortKeys; 54 | @synthesize humanReadable; 55 | 56 | /** 57 | @deprecated This exists in order to provide fragment support in older APIs in one more version. 58 | It should be removed in the next major version. 59 | */ 60 | - (NSString*)stringWithFragment:(id)value { 61 | [self clearErrorTrace]; 62 | depth = 0; 63 | NSMutableString *json = [NSMutableString stringWithCapacity:128]; 64 | 65 | if ([self appendValue:value into:json]) 66 | return json; 67 | 68 | return nil; 69 | } 70 | 71 | 72 | - (NSString*)stringWithObject:(id)value { 73 | 74 | if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]) { 75 | return [self stringWithFragment:value]; 76 | } 77 | 78 | if ([value respondsToSelector:@selector(proxyForJson)]) { 79 | NSString *tmp = [self stringWithObject:[value proxyForJson]]; 80 | if (tmp) 81 | return tmp; 82 | } 83 | 84 | 85 | [self clearErrorTrace]; 86 | [self addErrorWithCode:EFRAGMENT description:@"Not valid type for JSON"]; 87 | return nil; 88 | } 89 | 90 | 91 | - (NSString*)indent { 92 | return [@"\n" stringByPaddingToLength:1 + 2 * depth withString:@" " startingAtIndex:0]; 93 | } 94 | 95 | - (BOOL)appendValue:(id)fragment into:(NSMutableString*)json { 96 | if ([fragment isKindOfClass:[NSDictionary class]]) { 97 | if (![self appendDictionary:fragment into:json]) 98 | return NO; 99 | 100 | } else if ([fragment isKindOfClass:[NSArray class]]) { 101 | if (![self appendArray:fragment into:json]) 102 | return NO; 103 | 104 | } else if ([fragment isKindOfClass:[NSString class]]) { 105 | if (![self appendString:fragment into:json]) 106 | return NO; 107 | 108 | } else if ([fragment isKindOfClass:[NSNumber class]]) { 109 | if ('c' == *[fragment objCType]) 110 | [json appendString:[fragment boolValue] ? @"true" : @"false"]; 111 | else 112 | [json appendString:[fragment stringValue]]; 113 | 114 | } else if ([fragment isKindOfClass:[NSNull class]]) { 115 | [json appendString:@"null"]; 116 | } else if ([fragment respondsToSelector:@selector(proxyForJson)]) { 117 | [self appendValue:[fragment proxyForJson] into:json]; 118 | 119 | } else { 120 | [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"JSON serialisation not supported for %@", [fragment class]]]; 121 | return NO; 122 | } 123 | return YES; 124 | } 125 | 126 | - (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json { 127 | if (maxDepth && ++depth > maxDepth) { 128 | [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; 129 | return NO; 130 | } 131 | [json appendString:@"["]; 132 | 133 | BOOL addComma = NO; 134 | for (id value in fragment) { 135 | if (addComma) 136 | [json appendString:@","]; 137 | else 138 | addComma = YES; 139 | 140 | if ([self humanReadable]) 141 | [json appendString:[self indent]]; 142 | 143 | if (![self appendValue:value into:json]) { 144 | return NO; 145 | } 146 | } 147 | 148 | depth--; 149 | if ([self humanReadable] && [fragment count]) 150 | [json appendString:[self indent]]; 151 | [json appendString:@"]"]; 152 | return YES; 153 | } 154 | 155 | - (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json { 156 | if (maxDepth && ++depth > maxDepth) { 157 | [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; 158 | return NO; 159 | } 160 | [json appendString:@"{"]; 161 | 162 | NSString *colon = [self humanReadable] ? @" : " : @":"; 163 | BOOL addComma = NO; 164 | NSArray *keys = [fragment allKeys]; 165 | if (self.sortKeys) 166 | keys = [keys sortedArrayUsingSelector:@selector(compare:)]; 167 | 168 | for (id value in keys) { 169 | if (addComma) 170 | [json appendString:@","]; 171 | else 172 | addComma = YES; 173 | 174 | if ([self humanReadable]) 175 | [json appendString:[self indent]]; 176 | 177 | if (![value isKindOfClass:[NSString class]]) { 178 | [self addErrorWithCode:EUNSUPPORTED description: @"JSON object key must be string"]; 179 | return NO; 180 | } 181 | 182 | if (![self appendString:value into:json]) 183 | return NO; 184 | 185 | [json appendString:colon]; 186 | if (![self appendValue:[fragment objectForKey:value] into:json]) { 187 | [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"Unsupported value for key %@ in object", value]]; 188 | return NO; 189 | } 190 | } 191 | 192 | depth--; 193 | if ([self humanReadable] && [fragment count]) 194 | [json appendString:[self indent]]; 195 | [json appendString:@"}"]; 196 | return YES; 197 | } 198 | 199 | - (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json { 200 | 201 | [json appendString:@"\""]; 202 | 203 | NSRange esc = [fragment rangeOfCharacterFromSet:kEscapeChars]; 204 | if ( !esc.length ) { 205 | // No special chars -- can just add the raw string: 206 | [json appendString:fragment]; 207 | 208 | } else { 209 | NSUInteger length = [fragment length]; 210 | for (NSUInteger i = 0; i < length; i++) { 211 | unichar uc = [fragment characterAtIndex:i]; 212 | switch (uc) { 213 | case '"': [json appendString:@"\\\""]; break; 214 | case '\\': [json appendString:@"\\\\"]; break; 215 | case '\t': [json appendString:@"\\t"]; break; 216 | case '\n': [json appendString:@"\\n"]; break; 217 | case '\r': [json appendString:@"\\r"]; break; 218 | case '\b': [json appendString:@"\\b"]; break; 219 | case '\f': [json appendString:@"\\f"]; break; 220 | default: 221 | if (uc < 0x20) { 222 | [json appendFormat:@"\\u%04x", uc]; 223 | } else { 224 | CFStringAppendCharacters((CFMutableStringRef)json, &uc, 1); 225 | } 226 | break; 227 | 228 | } 229 | } 230 | } 231 | 232 | [json appendString:@"\""]; 233 | return YES; 234 | } 235 | 236 | 237 | @end 238 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/NSObject+SBJson.h: -------------------------------------------------------------------------------- 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 31 | 32 | #pragma mark JSON Writing 33 | 34 | /// Adds JSON generation to NSObject 35 | @interface NSObject (NSObject_SBJsonWriting) 36 | 37 | /** 38 | @brief Encodes the receiver into a JSON string 39 | 40 | Although defined as a category on NSObject it is only defined for NSArray and NSDictionary. 41 | 42 | @return the receiver encoded in JSON, or nil on error. 43 | 44 | @see @ref objc2json 45 | */ 46 | - (NSString *)JSONRepresentation; 47 | 48 | @end 49 | 50 | 51 | #pragma mark JSON Parsing 52 | 53 | /// Adds JSON parsing methods to NSString 54 | @interface NSString (NSString_SBJsonParsing) 55 | 56 | /** 57 | @brief Decodes the receiver's JSON text 58 | 59 | @return the NSDictionary or NSArray represented by the receiver, or nil on error. 60 | 61 | @see @ref json2objc 62 | */ 63 | - (id)JSONValue; 64 | 65 | @end 66 | 67 | 68 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/NSObject+SBJson.m: -------------------------------------------------------------------------------- 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 | #import "SBJsonParser.h" 33 | 34 | @implementation NSObject (NSObject_SBJsonWriting) 35 | 36 | - (NSString *)JSONRepresentation { 37 | SBJsonWriter *writer = [[SBJsonWriter alloc] init]; 38 | NSString *json = [writer stringWithObject:self]; 39 | if (!json) 40 | NSLog(@"-JSONRepresentation failed. Error is: %@", writer.error); 41 | return json; 42 | } 43 | 44 | @end 45 | 46 | 47 | 48 | @implementation NSString (NSString_SBJsonParsing) 49 | 50 | - (id)JSONValue { 51 | SBJsonParser *parser = [[SBJsonParser alloc] init]; 52 | id repr = [parser objectWithString:self]; 53 | if (!repr) 54 | NSLog(@"-JSONValue failed. Error is: %@", parser.error); 55 | return repr; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009-2011 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 | @page json2objc JSON to Objective-C 32 | 33 | JSON is mapped to Objective-C types in the following way: 34 | 35 | @li null -> NSNull 36 | @li string -> NSString 37 | @li array -> NSMutableArray 38 | @li object -> NSMutableDictionary 39 | @li true -> NSNumber's -numberWithBool:YES 40 | @li false -> NSNumber's -numberWithBool:NO 41 | @li integer up to 19 digits -> NSNumber's -numberWithLongLong: 42 | @li all other numbers -> NSDecimalNumber 43 | 44 | Since Objective-C doesn't have a dedicated class for boolean values, 45 | these turns into NSNumber instances. However, since these are 46 | initialised with the -initWithBool: method they round-trip back to JSON 47 | properly. In other words, they won't silently suddenly become 0 or 1; 48 | they'll be represented as 'true' and 'false' again. 49 | 50 | As an optimisation integers up to 19 digits in length (the max length 51 | for signed long long integers) turn into NSNumber instances, while 52 | complex ones turn into NSDecimalNumber instances. We can thus avoid any 53 | loss of precision as JSON allows ridiculously large numbers. 54 | 55 | @page objc2json Objective-C to JSON 56 | 57 | Objective-C types are mapped to JSON types in the following way: 58 | 59 | @li NSNull -> null 60 | @li NSString -> string 61 | @li NSArray -> array 62 | @li NSDictionary -> object 63 | @li NSNumber's -initWithBool:YES -> true 64 | @li NSNumber's -initWithBool:NO -> false 65 | @li NSNumber -> number 66 | 67 | @note In JSON the keys of an object must be strings. NSDictionary 68 | keys need not be, but attempting to convert an NSDictionary with 69 | non-string keys into JSON will throw an exception. 70 | 71 | NSNumber instances created with the -numberWithBool: method are 72 | converted into the JSON boolean "true" and "false" values, and vice 73 | versa. Any other NSNumber instances are converted to a JSON number the 74 | way you would expect. 75 | 76 | */ 77 | 78 | #import "SBJsonParser.h" 79 | #import "SBJsonWriter.h" 80 | #import "SBJsonStreamParser.h" 81 | #import "SBJsonStreamWriter.h" 82 | #import "NSObject+SBJson.h" 83 | 84 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonParser.h: -------------------------------------------------------------------------------- 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 31 | 32 | /** 33 | @brief Parse JSON Strings and NSData objects 34 | 35 | This uses SBJsonStreamParser internally. 36 | 37 | @see @ref objc2json 38 | 39 | */ 40 | 41 | @interface SBJsonParser : NSObject 42 | 43 | /** 44 | @brief The maximum recursing depth. 45 | 46 | Defaults to 32. If the input is nested deeper than this the input will be deemed to be 47 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 48 | turn off this security feature by setting the maxDepth value to 0. 49 | */ 50 | @property NSUInteger maxDepth; 51 | 52 | /** 53 | @brief Description of parse error 54 | 55 | This method returns the trace of the last method that failed. 56 | You need to check the return value of the call you're making to figure out 57 | if the call actually failed, before you know call this method. 58 | 59 | @return A string describing the error encountered, or nil if no error occured. 60 | 61 | */ 62 | @property(copy) NSString *error; 63 | 64 | /** 65 | @brief Return the object represented by the given NSData object. 66 | 67 | The data *must* be UTF8 encoded. 68 | 69 | @param data An NSData containing UTF8 encoded data to parse. 70 | @return The NSArray or NSDictionary represented by the object, or nil if an error occured. 71 | 72 | */ 73 | - (id)objectWithData:(NSData*)data; 74 | 75 | /** 76 | @brief Return the object represented by the given string 77 | 78 | This method converts its input to an NSData object containing UTF8 and calls -objectWithData: with it. 79 | 80 | @return The NSArray or NSDictionary represented by the object, or nil if an error occured. 81 | */ 82 | - (id)objectWithString:(NSString *)repr; 83 | 84 | /** 85 | @brief Return the object represented by the given string 86 | 87 | This method calls objectWithString: internally. If an error occurs, and if @p error 88 | is not nil, it creates an NSError object and returns this through its second argument. 89 | 90 | @param jsonText the json string to parse 91 | @param error pointer to an NSError object to populate on error 92 | 93 | @return The NSArray or NSDictionary represented by the object, or nil if an error occured. 94 | */ 95 | 96 | - (id)objectWithString:(NSString*)jsonText 97 | error:(NSError**)error; 98 | 99 | @end 100 | 101 | 102 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonParser.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009,2010 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "SBJsonParser.h" 31 | #import "SBJsonStreamParser.h" 32 | #import "SBJsonStreamParserAccumulator.h" 33 | 34 | @implementation SBJsonParser 35 | 36 | @synthesize maxDepth; 37 | @synthesize error; 38 | 39 | - (id)init { 40 | self = [super init]; 41 | if (self) 42 | self.maxDepth = 32u; 43 | return self; 44 | } 45 | 46 | 47 | #pragma mark Methods 48 | 49 | - (id)objectWithData:(NSData *)data { 50 | 51 | if (!data) { 52 | self.error = @"Input was 'nil'"; 53 | return nil; 54 | } 55 | 56 | SBJsonStreamParserAccumulator *accumulator = [[SBJsonStreamParserAccumulator alloc] init]; 57 | 58 | SBJsonStreamParser *parser = [[SBJsonStreamParser alloc] init]; 59 | parser.maxDepth = self.maxDepth; 60 | parser.delegate = accumulator; 61 | 62 | switch ([parser parse:data]) { 63 | case SBJsonStreamParserComplete: 64 | return accumulator.value; 65 | break; 66 | 67 | case SBJsonStreamParserWaitingForData: 68 | self.error = @"Unexpected end of input"; 69 | break; 70 | 71 | case SBJsonStreamParserError: 72 | self.error = parser.error; 73 | break; 74 | } 75 | 76 | return nil; 77 | } 78 | 79 | - (id)objectWithString:(NSString *)repr { 80 | return [self objectWithData:[repr dataUsingEncoding:NSUTF8StringEncoding]]; 81 | } 82 | 83 | - (id)objectWithString:(NSString*)repr error:(NSError**)error_ { 84 | id tmp = [self objectWithString:repr]; 85 | if (tmp) 86 | return tmp; 87 | 88 | if (error_) { 89 | NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil]; 90 | *error_ = [NSError errorWithDomain:@"org.brautaset.SBJsonParser.ErrorDomain" code:0 userInfo:ui]; 91 | } 92 | 93 | return nil; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | @class SBJsonTokeniser; 36 | @class SBJsonStreamParser; 37 | @class SBJsonStreamParserState; 38 | 39 | typedef enum { 40 | SBJsonStreamParserComplete, 41 | SBJsonStreamParserWaitingForData, 42 | SBJsonStreamParserError, 43 | } SBJsonStreamParserStatus; 44 | 45 | 46 | /** 47 | @brief SBJsonStreamParserDelegate protocol adapter 48 | 49 | @see SBJsonStreamParser 50 | */ 51 | @protocol SBJsonStreamParserDelegate 52 | 53 | /** 54 | @brief Called if a JSON array is found 55 | 56 | This method is called if a JSON array is found. 57 | 58 | */ 59 | - (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray*)array; 60 | 61 | /** 62 | @brief Called when a JSON object is found 63 | 64 | This method is called if a JSON object is found. 65 | */ 66 | - (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary*)dict; 67 | 68 | @end 69 | 70 | typedef enum { 71 | SBJsonStreamParserNone, 72 | SBJsonStreamParserArray, 73 | SBJsonStreamParserObject, 74 | } SBJsonStreamParserType; 75 | 76 | /** 77 | @brief Parse a stream of JSON data. 78 | 79 | Using this class directly you can reduce the apparent latency for each 80 | download/parse cycle of documents over a slow connection. You can start 81 | parsing *and return chunks of the parsed document* before the entire 82 | document is downloaded. Using this class is also useful to parse huge 83 | documents on disk bit by bit so you don't have to keep them all in memory. 84 | 85 | The default behaviour is that the delegate only receives one call from 86 | either the -parser:foundArray: or -parser:foundObject: method when the 87 | document is fully parsed. However, if your inputs contains multiple JSON 88 | documents and you set the parser's -supportMultipleDocuments property to YES 89 | you will get one call for each full method. 90 | 91 | @code 92 | SBJsonStreamParser *parser = [[SBJsonStreamParser alloc] init]; 93 | parser.delegate = self; 94 | parser.supportMultipleDocuments = YES; 95 | 96 | // Note that this input contains multiple top-level JSON documents 97 | NSData *json = [@"[]{}[]{}" dataWithEncoding:NSUTF8StringEncoding]; 98 | [parser parse:data]; 99 | @endcode 100 | 101 | In the above example @p self will have the following sequence of methods called on it: 102 | 103 | @li -parser:foundArray: 104 | @li -parser:foundObject: 105 | @li -parser:foundArray: 106 | @li -parser:foundObject: 107 | 108 | Often you won't have control over the input you're parsing, so can't make use of 109 | this feature. But, all is not lost: this class will let you get the same effect by 110 | allowing you to skip one or more of the outer enclosing objects. Thus, the next 111 | example results in the same sequence of -parser:foundArray: / -parser:foundObject: 112 | being called on your delegate. 113 | 114 | @code 115 | SBJsonStreamParser *parser = [[SBJsonStreamParser alloc] init]; 116 | parser.delegate = self; 117 | parser.levelsToSkip = 1; 118 | 119 | // Note that this input contains A SINGLE top-level document 120 | NSData *json = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding]; 121 | [parser parse:data]; 122 | @endcode 123 | 124 | @see SBJsonStreamParserDelegate 125 | @see @ref objc2json 126 | 127 | */ 128 | @interface SBJsonStreamParser : NSObject { 129 | @private 130 | SBJsonTokeniser *tokeniser; 131 | 132 | NSUInteger depth; 133 | NSMutableArray *array; 134 | NSMutableDictionary *dict; 135 | NSMutableArray *keyStack; 136 | NSMutableArray *stack; 137 | 138 | SBJsonStreamParserType currentType; 139 | } 140 | 141 | @property (nonatomic, unsafe_unretained) SBJsonStreamParserState *state; // Private 142 | @property (nonatomic, readonly, strong) NSMutableArray *stateStack; // Private 143 | 144 | 145 | /** 146 | @brief How many levels to skip 147 | 148 | This is useful for parsing huge JSON documents, or documents coming in over a very slow link. 149 | 150 | If you set this to N it will skip the outer N levels and call the -parser:foundArray: 151 | or -parser:foundObject: methods for each of the inner objects, as appropriate. 152 | 153 | @see The StreamParserIntegrationTest.m file for examples 154 | */ 155 | @property NSUInteger levelsToSkip; 156 | 157 | /** 158 | @brief Expect multiple documents separated by whitespace 159 | 160 | Normally the @p -parse: method returns SBJsonStreamParserComplete when it's found a complete JSON document. 161 | Attempting to parse any more data at that point is considered an error. ("Garbage after JSON".) 162 | 163 | If you set this property to true the parser will never return SBJsonStreamParserComplete. Rather, 164 | once an object is completed it will expect another object to immediately follow, separated 165 | only by (optional) whitespace. 166 | 167 | @see The TweetStream app in the Examples 168 | */ 169 | @property BOOL supportMultipleDocuments; 170 | 171 | /** 172 | @brief Delegate to receive messages 173 | 174 | The object set here receives a series of messages as the parser breaks down the JSON stream 175 | into valid tokens. 176 | 177 | @note 178 | Usually this should be an instance of SBJsonStreamParser, but you can 179 | substitute your own implementation of the SBJsonStreamParserDelegate protocol if you need to. 180 | */ 181 | @property (unsafe_unretained) id delegate; 182 | 183 | /** 184 | @brief The max parse depth 185 | 186 | If the input is nested deeper than this the parser will halt parsing and return an error. 187 | 188 | Defaults to 32. 189 | */ 190 | @property NSUInteger maxDepth; 191 | 192 | /// Holds the error after SBJsonStreamParserError was returned 193 | @property (copy) NSString *error; 194 | 195 | /** 196 | @brief Parse some JSON 197 | 198 | The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one. 199 | 200 | @param data An NSData object containing the next chunk of JSON 201 | 202 | @return 203 | @li SBJsonStreamParserComplete if a full document was found 204 | @li SBJsonStreamParserWaitingForData if a partial document was found and more data is required to complete it 205 | @li SBJsonStreamParserError if an error occured. (See the error property for details in this case.) 206 | 207 | */ 208 | - (SBJsonStreamParserStatus)parse:(NSData*)data; 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParser.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import "SBJsonStreamParser.h" 34 | #import "SBJsonTokeniser.h" 35 | #import "SBJsonStreamParserState.h" 36 | #import 37 | 38 | static NSNumber *kTrue; 39 | static NSNumber *kFalse; 40 | static NSNull *kNull; 41 | 42 | @interface SBJsonStreamParser () 43 | 44 | - (void)pop; 45 | - (void)parserFoundObject:(id)obj; 46 | 47 | @end 48 | 49 | @implementation SBJsonStreamParser 50 | 51 | @synthesize levelsToSkip; 52 | @synthesize supportMultipleDocuments; 53 | @synthesize error; 54 | @synthesize delegate; 55 | @synthesize maxDepth; 56 | @synthesize state; 57 | @synthesize stateStack; 58 | 59 | #pragma mark Housekeeping 60 | 61 | + (void)initialize { 62 | kTrue = [[NSNumber alloc] initWithBool:YES]; 63 | kFalse = [[NSNumber alloc] initWithBool:NO]; 64 | kNull = [NSNull null]; 65 | } 66 | 67 | - (id)init { 68 | self = [super init]; 69 | if (self) { 70 | maxDepth = 32u; 71 | stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth]; 72 | state = [SBJsonStreamParserStateStart sharedInstance]; 73 | tokeniser = [[SBJsonTokeniser alloc] init]; 74 | 75 | keyStack = [[NSMutableArray alloc] initWithCapacity:32]; 76 | stack = [[NSMutableArray alloc] initWithCapacity:32]; 77 | currentType = SBJsonStreamParserNone; 78 | 79 | } 80 | return self; 81 | } 82 | 83 | 84 | #pragma mark Methods 85 | 86 | - (NSString*)tokenName:(sbjson_token_t)token { 87 | switch (token) { 88 | case sbjson_token_array_start: 89 | return @"start of array"; 90 | break; 91 | 92 | case sbjson_token_array_end: 93 | return @"end of array"; 94 | break; 95 | 96 | case sbjson_token_number: 97 | return @"number"; 98 | break; 99 | 100 | case sbjson_token_string: 101 | return @"string"; 102 | break; 103 | 104 | case sbjson_token_true: 105 | case sbjson_token_false: 106 | return @"boolean"; 107 | break; 108 | 109 | case sbjson_token_null: 110 | return @"null"; 111 | break; 112 | 113 | case sbjson_token_keyval_separator: 114 | return @"key-value separator"; 115 | break; 116 | 117 | case sbjson_token_separator: 118 | return @"value separator"; 119 | break; 120 | 121 | case sbjson_token_object_start: 122 | return @"start of object"; 123 | break; 124 | 125 | case sbjson_token_object_end: 126 | return @"end of object"; 127 | break; 128 | 129 | case sbjson_token_eof: 130 | case sbjson_token_error: 131 | break; 132 | } 133 | NSAssert(NO, @"Should not get here"); 134 | return @""; 135 | } 136 | 137 | - (void)maxDepthError { 138 | self.error = [NSString stringWithFormat:@"Input depth exceeds max depth of %lu", maxDepth]; 139 | self.state = [SBJsonStreamParserStateError sharedInstance]; 140 | } 141 | 142 | 143 | - (void)pop { 144 | [stack removeLastObject]; 145 | array = nil; 146 | dict = nil; 147 | currentType = SBJsonStreamParserNone; 148 | 149 | id value = [stack lastObject]; 150 | 151 | if ([value isKindOfClass:[NSArray class]]) { 152 | array = value; 153 | currentType = SBJsonStreamParserArray; 154 | } else if ([value isKindOfClass:[NSDictionary class]]) { 155 | dict = value; 156 | currentType = SBJsonStreamParserObject; 157 | } 158 | } 159 | 160 | - (void)parserFoundObject:(id)obj { 161 | NSParameterAssert(obj); 162 | 163 | switch (currentType) { 164 | case SBJsonStreamParserArray: 165 | [array addObject:obj]; 166 | break; 167 | 168 | case SBJsonStreamParserObject: 169 | NSParameterAssert(keyStack.count); 170 | [dict setObject:obj forKey:[keyStack lastObject]]; 171 | [keyStack removeLastObject]; 172 | break; 173 | 174 | case SBJsonStreamParserNone: 175 | if ([obj isKindOfClass:[NSArray class]]) { 176 | [delegate parser:self foundArray:obj]; 177 | } else { 178 | [delegate parser:self foundObject:obj]; 179 | } 180 | break; 181 | 182 | default: 183 | break; 184 | } 185 | } 186 | 187 | - (void)handleObjectStart { 188 | if (depth >= maxDepth) { 189 | [self maxDepthError]; 190 | return; 191 | } 192 | 193 | [stateStack addObject:state]; 194 | self.state = [SBJsonStreamParserStateObjectStart sharedInstance]; 195 | 196 | if (++depth > levelsToSkip) { 197 | dict = [[NSMutableDictionary alloc] init]; 198 | [stack addObject:dict]; 199 | 200 | currentType = SBJsonStreamParserObject; 201 | } 202 | } 203 | 204 | - (void)handleObjectEnd: (sbjson_token_t) tok { 205 | self.state = [stateStack lastObject]; 206 | [stateStack removeLastObject]; 207 | [state parser:self shouldTransitionTo:tok]; 208 | 209 | if (depth-- > levelsToSkip) { 210 | id value = dict; 211 | [self pop]; 212 | [self parserFoundObject:value]; 213 | } 214 | } 215 | 216 | - (void)handleArrayStart { 217 | 218 | if (depth >= maxDepth) { 219 | [self maxDepthError]; 220 | return; 221 | } 222 | 223 | [stateStack addObject:state]; 224 | self.state = [SBJsonStreamParserStateArrayStart sharedInstance]; 225 | 226 | if (++depth > levelsToSkip) { 227 | array = [[NSMutableArray alloc] init]; 228 | [stack addObject:array]; 229 | 230 | currentType = SBJsonStreamParserArray; 231 | } 232 | } 233 | 234 | - (void)handleArrayEnd: (sbjson_token_t) tok { 235 | self.state = [stateStack lastObject]; 236 | [stateStack removeLastObject]; 237 | [state parser:self shouldTransitionTo:tok]; 238 | 239 | if (depth-- > levelsToSkip) { 240 | id value = array; 241 | [self pop]; 242 | [self parserFoundObject:value]; 243 | } 244 | } 245 | 246 | - (void) handleTokenNotExpectedHere: (sbjson_token_t) tok { 247 | NSString *tokenName = [self tokenName:tok]; 248 | NSString *stateName = [state name]; 249 | 250 | self.error = [NSString stringWithFormat:@"Token '%@' not expected %@", tokenName, stateName]; 251 | self.state = [SBJsonStreamParserStateError sharedInstance]; 252 | } 253 | 254 | - (SBJsonStreamParserStatus)parse:(NSData *)data_ { 255 | [tokeniser appendData:data_]; 256 | 257 | for (;;) { 258 | 259 | if ([state isError]) 260 | return SBJsonStreamParserError; 261 | 262 | NSObject *token; 263 | sbjson_token_t tok = [tokeniser getToken:&token]; 264 | switch (tok) { 265 | case sbjson_token_eof: 266 | return [state parserShouldReturn:self]; 267 | break; 268 | 269 | case sbjson_token_error: 270 | self.state = [SBJsonStreamParserStateError sharedInstance]; 271 | self.error = tokeniser.error; 272 | return SBJsonStreamParserError; 273 | break; 274 | 275 | default: 276 | 277 | if (![state parser:self shouldAcceptToken:tok]) { 278 | [self handleTokenNotExpectedHere: tok]; 279 | return SBJsonStreamParserError; 280 | } 281 | 282 | switch (tok) { 283 | case sbjson_token_object_start: 284 | [self handleObjectStart]; 285 | break; 286 | 287 | case sbjson_token_object_end: 288 | [self handleObjectEnd: tok]; 289 | break; 290 | 291 | case sbjson_token_array_start: 292 | [self handleArrayStart]; 293 | break; 294 | 295 | case sbjson_token_array_end: 296 | [self handleArrayEnd: tok]; 297 | break; 298 | 299 | case sbjson_token_separator: 300 | case sbjson_token_keyval_separator: 301 | [state parser:self shouldTransitionTo:tok]; 302 | break; 303 | 304 | case sbjson_token_true: 305 | [self parserFoundObject:kTrue]; 306 | [state parser:self shouldTransitionTo:tok]; 307 | break; 308 | 309 | case sbjson_token_false: 310 | [self parserFoundObject:kFalse]; 311 | [state parser:self shouldTransitionTo:tok]; 312 | break; 313 | 314 | case sbjson_token_null: 315 | [self parserFoundObject:kNull]; 316 | [state parser:self shouldTransitionTo:tok]; 317 | break; 318 | 319 | case sbjson_token_number: 320 | [self parserFoundObject:token]; 321 | [state parser:self shouldTransitionTo:tok]; 322 | break; 323 | 324 | case sbjson_token_string: 325 | if ([state needKey]) 326 | [keyStack addObject:token]; 327 | else 328 | [self parserFoundObject:token]; 329 | [state parser:self shouldTransitionTo:tok]; 330 | break; 331 | 332 | default: 333 | break; 334 | } 335 | break; 336 | } 337 | } 338 | return SBJsonStreamParserComplete; 339 | } 340 | 341 | 342 | @end 343 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParserAccumulator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 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 31 | #import "SBJsonStreamParser.h" 32 | 33 | @interface SBJsonStreamParserAccumulator : NSObject 34 | 35 | @property (copy) id value; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParserAccumulator.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 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 "SBJsonStreamParserAccumulator.h" 31 | 32 | @implementation SBJsonStreamParserAccumulator 33 | 34 | @synthesize value; 35 | 36 | 37 | #pragma mark SBJsonStreamParserDelegate 38 | 39 | - (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray *)array { 40 | value = array; 41 | } 42 | 43 | - (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary *)dict { 44 | value = dict; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParserState.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | #import "SBJsonTokeniser.h" 36 | #import "SBJsonStreamParser.h" 37 | 38 | @interface SBJsonStreamParserState : NSObject 39 | + (id)sharedInstance; 40 | 41 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token; 42 | - (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser; 43 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok; 44 | - (BOOL)needKey; 45 | - (BOOL)isError; 46 | 47 | - (NSString*)name; 48 | 49 | @end 50 | 51 | @interface SBJsonStreamParserStateStart : SBJsonStreamParserState 52 | @end 53 | 54 | @interface SBJsonStreamParserStateComplete : SBJsonStreamParserState 55 | @end 56 | 57 | @interface SBJsonStreamParserStateError : SBJsonStreamParserState 58 | @end 59 | 60 | 61 | @interface SBJsonStreamParserStateObjectStart : SBJsonStreamParserState 62 | @end 63 | 64 | @interface SBJsonStreamParserStateObjectGotKey : SBJsonStreamParserState 65 | @end 66 | 67 | @interface SBJsonStreamParserStateObjectSeparator : SBJsonStreamParserState 68 | @end 69 | 70 | @interface SBJsonStreamParserStateObjectGotValue : SBJsonStreamParserState 71 | @end 72 | 73 | @interface SBJsonStreamParserStateObjectNeedKey : SBJsonStreamParserState 74 | @end 75 | 76 | @interface SBJsonStreamParserStateArrayStart : SBJsonStreamParserState 77 | @end 78 | 79 | @interface SBJsonStreamParserStateArrayGotValue : SBJsonStreamParserState 80 | @end 81 | 82 | @interface SBJsonStreamParserStateArrayNeedValue : SBJsonStreamParserState 83 | @end 84 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamParserState.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import "SBJsonStreamParserState.h" 34 | #import "SBJsonStreamParser.h" 35 | 36 | #define SINGLETON \ 37 | + (id)sharedInstance { \ 38 | static id state; \ 39 | if (!state) state = [[self alloc] init]; \ 40 | return state; \ 41 | } 42 | 43 | @implementation SBJsonStreamParserState 44 | 45 | + (id)sharedInstance { return nil; } 46 | 47 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 48 | return NO; 49 | } 50 | 51 | - (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser { 52 | return SBJsonStreamParserWaitingForData; 53 | } 54 | 55 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok {} 56 | 57 | - (BOOL)needKey { 58 | return NO; 59 | } 60 | 61 | - (NSString*)name { 62 | return @""; 63 | } 64 | 65 | - (BOOL)isError { 66 | return NO; 67 | } 68 | 69 | @end 70 | 71 | #pragma mark - 72 | 73 | @implementation SBJsonStreamParserStateStart 74 | 75 | SINGLETON 76 | 77 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 78 | return token == sbjson_token_array_start || token == sbjson_token_object_start; 79 | } 80 | 81 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 82 | 83 | SBJsonStreamParserState *state = nil; 84 | switch (tok) { 85 | case sbjson_token_array_start: 86 | state = [SBJsonStreamParserStateArrayStart sharedInstance]; 87 | break; 88 | 89 | case sbjson_token_object_start: 90 | state = [SBJsonStreamParserStateObjectStart sharedInstance]; 91 | break; 92 | 93 | case sbjson_token_array_end: 94 | case sbjson_token_object_end: 95 | if (parser.supportMultipleDocuments) 96 | state = parser.state; 97 | else 98 | state = [SBJsonStreamParserStateComplete sharedInstance]; 99 | break; 100 | 101 | case sbjson_token_eof: 102 | return; 103 | 104 | default: 105 | state = [SBJsonStreamParserStateError sharedInstance]; 106 | break; 107 | } 108 | 109 | 110 | parser.state = state; 111 | } 112 | 113 | - (NSString*)name { return @"before outer-most array or object"; } 114 | 115 | @end 116 | 117 | #pragma mark - 118 | 119 | @implementation SBJsonStreamParserStateComplete 120 | 121 | SINGLETON 122 | 123 | - (NSString*)name { return @"after outer-most array or object"; } 124 | 125 | - (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser { 126 | return SBJsonStreamParserComplete; 127 | } 128 | 129 | @end 130 | 131 | #pragma mark - 132 | 133 | @implementation SBJsonStreamParserStateError 134 | 135 | SINGLETON 136 | 137 | - (NSString*)name { return @"in error"; } 138 | 139 | - (SBJsonStreamParserStatus)parserShouldReturn:(SBJsonStreamParser*)parser { 140 | return SBJsonStreamParserError; 141 | } 142 | 143 | - (BOOL)isError { 144 | return YES; 145 | } 146 | 147 | @end 148 | 149 | #pragma mark - 150 | 151 | @implementation SBJsonStreamParserStateObjectStart 152 | 153 | SINGLETON 154 | 155 | - (NSString*)name { return @"at beginning of object"; } 156 | 157 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 158 | switch (token) { 159 | case sbjson_token_object_end: 160 | case sbjson_token_string: 161 | return YES; 162 | break; 163 | default: 164 | return NO; 165 | break; 166 | } 167 | } 168 | 169 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 170 | parser.state = [SBJsonStreamParserStateObjectGotKey sharedInstance]; 171 | } 172 | 173 | - (BOOL)needKey { 174 | return YES; 175 | } 176 | 177 | @end 178 | 179 | #pragma mark - 180 | 181 | @implementation SBJsonStreamParserStateObjectGotKey 182 | 183 | SINGLETON 184 | 185 | - (NSString*)name { return @"after object key"; } 186 | 187 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 188 | return token == sbjson_token_keyval_separator; 189 | } 190 | 191 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 192 | parser.state = [SBJsonStreamParserStateObjectSeparator sharedInstance]; 193 | } 194 | 195 | @end 196 | 197 | #pragma mark - 198 | 199 | @implementation SBJsonStreamParserStateObjectSeparator 200 | 201 | SINGLETON 202 | 203 | - (NSString*)name { return @"as object value"; } 204 | 205 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 206 | switch (token) { 207 | case sbjson_token_object_start: 208 | case sbjson_token_array_start: 209 | case sbjson_token_true: 210 | case sbjson_token_false: 211 | case sbjson_token_null: 212 | case sbjson_token_number: 213 | case sbjson_token_string: 214 | return YES; 215 | break; 216 | 217 | default: 218 | return NO; 219 | break; 220 | } 221 | } 222 | 223 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 224 | parser.state = [SBJsonStreamParserStateObjectGotValue sharedInstance]; 225 | } 226 | 227 | @end 228 | 229 | #pragma mark - 230 | 231 | @implementation SBJsonStreamParserStateObjectGotValue 232 | 233 | SINGLETON 234 | 235 | - (NSString*)name { return @"after object value"; } 236 | 237 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 238 | switch (token) { 239 | case sbjson_token_object_end: 240 | case sbjson_token_separator: 241 | return YES; 242 | break; 243 | default: 244 | return NO; 245 | break; 246 | } 247 | } 248 | 249 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 250 | parser.state = [SBJsonStreamParserStateObjectNeedKey sharedInstance]; 251 | } 252 | 253 | 254 | @end 255 | 256 | #pragma mark - 257 | 258 | @implementation SBJsonStreamParserStateObjectNeedKey 259 | 260 | SINGLETON 261 | 262 | - (NSString*)name { return @"in place of object key"; } 263 | 264 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 265 | return sbjson_token_string == token; 266 | } 267 | 268 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 269 | parser.state = [SBJsonStreamParserStateObjectGotKey sharedInstance]; 270 | } 271 | 272 | - (BOOL)needKey { 273 | return YES; 274 | } 275 | 276 | @end 277 | 278 | #pragma mark - 279 | 280 | @implementation SBJsonStreamParserStateArrayStart 281 | 282 | SINGLETON 283 | 284 | - (NSString*)name { return @"at array start"; } 285 | 286 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 287 | switch (token) { 288 | case sbjson_token_object_end: 289 | case sbjson_token_keyval_separator: 290 | case sbjson_token_separator: 291 | return NO; 292 | break; 293 | 294 | default: 295 | return YES; 296 | break; 297 | } 298 | } 299 | 300 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 301 | parser.state = [SBJsonStreamParserStateArrayGotValue sharedInstance]; 302 | } 303 | 304 | @end 305 | 306 | #pragma mark - 307 | 308 | @implementation SBJsonStreamParserStateArrayGotValue 309 | 310 | SINGLETON 311 | 312 | - (NSString*)name { return @"after array value"; } 313 | 314 | 315 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 316 | return token == sbjson_token_array_end || token == sbjson_token_separator; 317 | } 318 | 319 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 320 | if (tok == sbjson_token_separator) 321 | parser.state = [SBJsonStreamParserStateArrayNeedValue sharedInstance]; 322 | } 323 | 324 | @end 325 | 326 | #pragma mark - 327 | 328 | @implementation SBJsonStreamParserStateArrayNeedValue 329 | 330 | SINGLETON 331 | 332 | - (NSString*)name { return @"as array value"; } 333 | 334 | 335 | - (BOOL)parser:(SBJsonStreamParser*)parser shouldAcceptToken:(sbjson_token_t)token { 336 | switch (token) { 337 | case sbjson_token_array_end: 338 | case sbjson_token_keyval_separator: 339 | case sbjson_token_object_end: 340 | case sbjson_token_separator: 341 | return NO; 342 | break; 343 | 344 | default: 345 | return YES; 346 | break; 347 | } 348 | } 349 | 350 | - (void)parser:(SBJsonStreamParser*)parser shouldTransitionTo:(sbjson_token_t)tok { 351 | parser.state = [SBJsonStreamParserStateArrayGotValue sharedInstance]; 352 | } 353 | 354 | @end 355 | 356 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | /// Enable JSON writing for non-native objects 36 | @interface NSObject (SBProxyForJson) 37 | 38 | /** 39 | @brief Allows generation of JSON for otherwise unsupported classes. 40 | 41 | If you have a custom class that you want to create a JSON representation 42 | for you can implement this method in your class. It should return a 43 | representation of your object defined in terms of objects that can be 44 | translated into JSON. For example, a Person object might implement it like this: 45 | 46 | @code 47 | - (id)proxyForJson { 48 | return [NSDictionary dictionaryWithObjectsAndKeys: 49 | name, @"name", 50 | phone, @"phone", 51 | email, @"email", 52 | nil]; 53 | } 54 | @endcode 55 | 56 | */ 57 | - (id)proxyForJson; 58 | 59 | @end 60 | 61 | @class SBJsonStreamWriter; 62 | 63 | @protocol SBJsonStreamWriterDelegate 64 | 65 | - (void)writer:(SBJsonStreamWriter*)writer appendBytes:(const void *)bytes length:(NSUInteger)length; 66 | 67 | @end 68 | 69 | @class SBJsonStreamWriterState; 70 | 71 | /** 72 | @brief The Stream Writer class. 73 | 74 | Accepts a stream of messages and writes JSON of these to its delegate object. 75 | 76 | This class provides a range of high-, mid- and low-level methods. You can mix 77 | and match calls to these. For example, you may want to call -writeArrayOpen 78 | to start an array and then repeatedly call -writeObject: with various objects 79 | before finishing off with a -writeArrayClose call. 80 | 81 | @see @ref json2objc 82 | 83 | */ 84 | 85 | @interface SBJsonStreamWriter : NSObject { 86 | NSMutableDictionary *cache; 87 | } 88 | 89 | @property (nonatomic, unsafe_unretained) SBJsonStreamWriterState *state; // Internal 90 | @property (nonatomic, readonly, strong) NSMutableArray *stateStack; // Internal 91 | 92 | /** 93 | @brief delegate to receive JSON output 94 | Delegate that will receive messages with output. 95 | */ 96 | @property (unsafe_unretained) id delegate; 97 | 98 | /** 99 | @brief The maximum recursing depth. 100 | 101 | Defaults to 512. If the input is nested deeper than this the input will be deemed to be 102 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 103 | turn off this security feature by setting the maxDepth value to 0. 104 | */ 105 | @property NSUInteger maxDepth; 106 | 107 | /** 108 | @brief Whether we are generating human-readable (multiline) JSON. 109 | 110 | Set whether or not to generate human-readable JSON. The default is NO, which produces 111 | JSON without any whitespace between tokens. If set to YES, generates human-readable 112 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 113 | spaces per nesting level. 114 | */ 115 | @property BOOL humanReadable; 116 | 117 | /** 118 | @brief Whether or not to sort the dictionary keys in the output. 119 | 120 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 121 | (This is useful if you need to compare two structures, for example.) The default is NO. 122 | */ 123 | @property BOOL sortKeys; 124 | 125 | /// Contains the error description after an error has occured. 126 | @property (copy) NSString *error; 127 | 128 | /** 129 | Write an NSDictionary to the JSON stream. 130 | @return YES if successful, or NO on failure 131 | */ 132 | - (BOOL)writeObject:(NSDictionary*)dict; 133 | 134 | /** 135 | Write an NSArray to the JSON stream. 136 | @return YES if successful, or NO on failure 137 | */ 138 | - (BOOL)writeArray:(NSArray *)array; 139 | 140 | /** 141 | Start writing an Object to the stream 142 | @return YES if successful, or NO on failure 143 | */ 144 | - (BOOL)writeObjectOpen; 145 | 146 | /** 147 | Close the current object being written 148 | @return YES if successful, or NO on failure 149 | */ 150 | - (BOOL)writeObjectClose; 151 | 152 | /** Start writing an Array to the stream 153 | @return YES if successful, or NO on failure 154 | */ 155 | - (BOOL)writeArrayOpen; 156 | 157 | /** Close the current Array being written 158 | @return YES if successful, or NO on failure 159 | */ 160 | - (BOOL)writeArrayClose; 161 | 162 | /** Write a null to the stream 163 | @return YES if successful, or NO on failure 164 | */ 165 | - (BOOL)writeNull; 166 | 167 | /** Write a boolean to the stream 168 | @return YES if successful, or NO on failure 169 | */ 170 | - (BOOL)writeBool:(BOOL)x; 171 | 172 | /** Write a Number to the stream 173 | @return YES if successful, or NO on failure 174 | */ 175 | - (BOOL)writeNumber:(NSNumber*)n; 176 | 177 | /** Write a String to the stream 178 | @return YES if successful, or NO on failure 179 | */ 180 | - (BOOL)writeString:(NSString*)s; 181 | 182 | @end 183 | 184 | @interface SBJsonStreamWriter (Private) 185 | - (BOOL)writeValue:(id)v; 186 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length; 187 | @end 188 | 189 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriter.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import "SBJsonStreamWriter.h" 34 | #import "SBJsonStreamWriterState.h" 35 | 36 | static NSNumber *kNotANumber; 37 | static NSNumber *kTrue; 38 | static NSNumber *kFalse; 39 | static NSNumber *kPositiveInfinity; 40 | static NSNumber *kNegativeInfinity; 41 | 42 | 43 | @implementation SBJsonStreamWriter 44 | 45 | @synthesize error; 46 | @synthesize maxDepth; 47 | @synthesize state; 48 | @synthesize stateStack; 49 | @synthesize humanReadable; 50 | @synthesize sortKeys; 51 | 52 | + (void)initialize { 53 | kNotANumber = [NSDecimalNumber notANumber]; 54 | kPositiveInfinity = [NSNumber numberWithDouble:+INFINITY]; 55 | kNegativeInfinity = [NSNumber numberWithDouble:-INFINITY]; 56 | kTrue = [NSNumber numberWithBool:YES]; 57 | kFalse = [NSNumber numberWithBool:NO]; 58 | } 59 | 60 | #pragma mark Housekeeping 61 | 62 | @synthesize delegate; 63 | 64 | - (id)init { 65 | self = [super init]; 66 | if (self) { 67 | maxDepth = 32u; 68 | stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth]; 69 | state = [SBJsonStreamWriterStateStart sharedInstance]; 70 | cache = [[NSMutableDictionary alloc] initWithCapacity:32]; 71 | } 72 | return self; 73 | } 74 | 75 | - (void)dealloc { 76 | self.state = nil; 77 | } 78 | 79 | #pragma mark Methods 80 | 81 | - (void)appendBytes:(const void *)bytes length:(NSUInteger)length { 82 | [delegate writer:self appendBytes:bytes length:length]; 83 | } 84 | 85 | - (BOOL)writeObject:(NSDictionary *)dict { 86 | if (![self writeObjectOpen]) 87 | return NO; 88 | 89 | NSArray *keys = [dict allKeys]; 90 | if (sortKeys) 91 | keys = [keys sortedArrayUsingSelector:@selector(compare:)]; 92 | 93 | for (id k in keys) { 94 | if (![k isKindOfClass:[NSString class]]) { 95 | self.error = [NSString stringWithFormat:@"JSON object key must be string: %@", k]; 96 | return NO; 97 | } 98 | 99 | if (![self writeString:k]) 100 | return NO; 101 | if (![self writeValue:[dict objectForKey:k]]) 102 | return NO; 103 | } 104 | 105 | return [self writeObjectClose]; 106 | } 107 | 108 | - (BOOL)writeArray:(NSArray*)array { 109 | if (![self writeArrayOpen]) 110 | return NO; 111 | for (id v in array) 112 | if (![self writeValue:v]) 113 | return NO; 114 | return [self writeArrayClose]; 115 | } 116 | 117 | 118 | - (BOOL)writeObjectOpen { 119 | if ([state isInvalidState:self]) return NO; 120 | if ([state expectingKey:self]) return NO; 121 | [state appendSeparator:self]; 122 | if (humanReadable && stateStack.count) [state appendWhitespace:self]; 123 | 124 | [stateStack addObject:state]; 125 | self.state = [SBJsonStreamWriterStateObjectStart sharedInstance]; 126 | 127 | if (maxDepth && stateStack.count > maxDepth) { 128 | self.error = @"Nested too deep"; 129 | return NO; 130 | } 131 | 132 | [delegate writer:self appendBytes:"{" length:1]; 133 | return YES; 134 | } 135 | 136 | - (BOOL)writeObjectClose { 137 | if ([state isInvalidState:self]) return NO; 138 | 139 | SBJsonStreamWriterState *prev = state; 140 | 141 | self.state = [stateStack lastObject]; 142 | [stateStack removeLastObject]; 143 | 144 | if (humanReadable) [prev appendWhitespace:self]; 145 | [delegate writer:self appendBytes:"}" length:1]; 146 | 147 | [state transitionState:self]; 148 | return YES; 149 | } 150 | 151 | - (BOOL)writeArrayOpen { 152 | if ([state isInvalidState:self]) return NO; 153 | if ([state expectingKey:self]) return NO; 154 | [state appendSeparator:self]; 155 | if (humanReadable && stateStack.count) [state appendWhitespace:self]; 156 | 157 | [stateStack addObject:state]; 158 | self.state = [SBJsonStreamWriterStateArrayStart sharedInstance]; 159 | 160 | if (maxDepth && stateStack.count > maxDepth) { 161 | self.error = @"Nested too deep"; 162 | return NO; 163 | } 164 | 165 | [delegate writer:self appendBytes:"[" length:1]; 166 | return YES; 167 | } 168 | 169 | - (BOOL)writeArrayClose { 170 | if ([state isInvalidState:self]) return NO; 171 | if ([state expectingKey:self]) return NO; 172 | 173 | SBJsonStreamWriterState *prev = state; 174 | 175 | self.state = [stateStack lastObject]; 176 | [stateStack removeLastObject]; 177 | 178 | if (humanReadable) [prev appendWhitespace:self]; 179 | [delegate writer:self appendBytes:"]" length:1]; 180 | 181 | [state transitionState:self]; 182 | return YES; 183 | } 184 | 185 | - (BOOL)writeNull { 186 | if ([state isInvalidState:self]) return NO; 187 | if ([state expectingKey:self]) return NO; 188 | [state appendSeparator:self]; 189 | if (humanReadable) [state appendWhitespace:self]; 190 | 191 | [delegate writer:self appendBytes:"null" length:4]; 192 | [state transitionState:self]; 193 | return YES; 194 | } 195 | 196 | - (BOOL)writeBool:(BOOL)x { 197 | if ([state isInvalidState:self]) return NO; 198 | if ([state expectingKey:self]) return NO; 199 | [state appendSeparator:self]; 200 | if (humanReadable) [state appendWhitespace:self]; 201 | 202 | if (x) 203 | [delegate writer:self appendBytes:"true" length:4]; 204 | else 205 | [delegate writer:self appendBytes:"false" length:5]; 206 | [state transitionState:self]; 207 | return YES; 208 | } 209 | 210 | 211 | - (BOOL)writeValue:(id)o { 212 | if ([o isKindOfClass:[NSDictionary class]]) { 213 | return [self writeObject:o]; 214 | 215 | } else if ([o isKindOfClass:[NSArray class]]) { 216 | return [self writeArray:o]; 217 | 218 | } else if ([o isKindOfClass:[NSString class]]) { 219 | [self writeString:o]; 220 | return YES; 221 | 222 | } else if ([o isKindOfClass:[NSNumber class]]) { 223 | return [self writeNumber:o]; 224 | 225 | } else if ([o isKindOfClass:[NSNull class]]) { 226 | return [self writeNull]; 227 | 228 | } else if ([o respondsToSelector:@selector(proxyForJson)]) { 229 | return [self writeValue:[o proxyForJson]]; 230 | 231 | } 232 | 233 | self.error = [NSString stringWithFormat:@"JSON serialisation not supported for %@", [o class]]; 234 | return NO; 235 | } 236 | 237 | static const char *strForChar(int c) { 238 | switch (c) { 239 | case 0: return "\\u0000"; break; 240 | case 1: return "\\u0001"; break; 241 | case 2: return "\\u0002"; break; 242 | case 3: return "\\u0003"; break; 243 | case 4: return "\\u0004"; break; 244 | case 5: return "\\u0005"; break; 245 | case 6: return "\\u0006"; break; 246 | case 7: return "\\u0007"; break; 247 | case 8: return "\\b"; break; 248 | case 9: return "\\t"; break; 249 | case 10: return "\\n"; break; 250 | case 11: return "\\u000b"; break; 251 | case 12: return "\\f"; break; 252 | case 13: return "\\r"; break; 253 | case 14: return "\\u000e"; break; 254 | case 15: return "\\u000f"; break; 255 | case 16: return "\\u0010"; break; 256 | case 17: return "\\u0011"; break; 257 | case 18: return "\\u0012"; break; 258 | case 19: return "\\u0013"; break; 259 | case 20: return "\\u0014"; break; 260 | case 21: return "\\u0015"; break; 261 | case 22: return "\\u0016"; break; 262 | case 23: return "\\u0017"; break; 263 | case 24: return "\\u0018"; break; 264 | case 25: return "\\u0019"; break; 265 | case 26: return "\\u001a"; break; 266 | case 27: return "\\u001b"; break; 267 | case 28: return "\\u001c"; break; 268 | case 29: return "\\u001d"; break; 269 | case 30: return "\\u001e"; break; 270 | case 31: return "\\u001f"; break; 271 | case 34: return "\\\""; break; 272 | case 92: return "\\\\"; break; 273 | } 274 | NSLog(@"FUTFUTFUT: -->'%c'<---", c); 275 | return "FUTFUTFUT"; 276 | } 277 | 278 | - (BOOL)writeString:(NSString*)string { 279 | if ([state isInvalidState:self]) return NO; 280 | [state appendSeparator:self]; 281 | if (humanReadable) [state appendWhitespace:self]; 282 | 283 | NSMutableData *buf = [cache objectForKey:string]; 284 | if (!buf) { 285 | 286 | NSUInteger len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 287 | const char *utf8 = [string UTF8String]; 288 | NSUInteger written = 0, i = 0; 289 | 290 | buf = [NSMutableData dataWithCapacity:(NSUInteger)(len * 1.1f)]; 291 | [buf appendBytes:"\"" length:1]; 292 | 293 | for (i = 0; i < len; i++) { 294 | int c = utf8[i]; 295 | BOOL isControlChar = c >= 0 && c < 32; 296 | if (isControlChar || c == '"' || c == '\\') { 297 | if (i - written) 298 | [buf appendBytes:utf8 + written length:i - written]; 299 | written = i + 1; 300 | 301 | const char *t = strForChar(c); 302 | [buf appendBytes:t length:strlen(t)]; 303 | } 304 | } 305 | 306 | if (i - written) 307 | [buf appendBytes:utf8 + written length:i - written]; 308 | 309 | [buf appendBytes:"\"" length:1]; 310 | [cache setObject:buf forKey:string]; 311 | } 312 | 313 | [delegate writer:self appendBytes:[buf bytes] length:[buf length]]; 314 | [state transitionState:self]; 315 | return YES; 316 | } 317 | 318 | - (BOOL)writeNumber:(NSNumber*)number { 319 | if (number == kTrue || number == kFalse) 320 | return [self writeBool:[number boolValue]]; 321 | 322 | if ([state isInvalidState:self]) return NO; 323 | if ([state expectingKey:self]) return NO; 324 | [state appendSeparator:self]; 325 | if (humanReadable) [state appendWhitespace:self]; 326 | 327 | if ([kPositiveInfinity isEqualToNumber:number]) { 328 | self.error = @"+Infinity is not a valid number in JSON"; 329 | return NO; 330 | 331 | } else if ([kNegativeInfinity isEqualToNumber:number]) { 332 | self.error = @"-Infinity is not a valid number in JSON"; 333 | return NO; 334 | 335 | } else if ([kNotANumber isEqualToNumber:number]) { 336 | self.error = @"NaN is not a valid number in JSON"; 337 | return NO; 338 | } 339 | 340 | const char *objcType = [number objCType]; 341 | char num[128]; 342 | size_t len; 343 | 344 | switch (objcType[0]) { 345 | case 'c': case 'i': case 's': case 'l': case 'q': 346 | len = snprintf(num, sizeof num, "%lld", [number longLongValue]); 347 | break; 348 | case 'C': case 'I': case 'S': case 'L': case 'Q': 349 | len = snprintf(num, sizeof num, "%llu", [number unsignedLongLongValue]); 350 | break; 351 | case 'f': case 'd': default: 352 | if ([number isKindOfClass:[NSDecimalNumber class]]) { 353 | char const *utf8 = [[number stringValue] UTF8String]; 354 | [delegate writer:self appendBytes:utf8 length: strlen(utf8)]; 355 | [state transitionState:self]; 356 | return YES; 357 | } 358 | len = snprintf(num, sizeof num, "%.17g", [number doubleValue]); 359 | break; 360 | } 361 | [delegate writer:self appendBytes:num length: len]; 362 | [state transitionState:self]; 363 | return YES; 364 | } 365 | 366 | @end 367 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriterAccumulator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 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 "SBJsonStreamWriter.h" 31 | 32 | @interface SBJsonStreamWriterAccumulator : NSObject 33 | 34 | @property (readonly, copy) NSMutableData* data; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriterAccumulator.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 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 "SBJsonStreamWriterAccumulator.h" 31 | 32 | 33 | @implementation SBJsonStreamWriterAccumulator 34 | 35 | @synthesize data; 36 | 37 | - (id)init { 38 | self = [super init]; 39 | if (self) { 40 | data = [[NSMutableData alloc] initWithCapacity:8096u]; 41 | } 42 | return self; 43 | } 44 | 45 | 46 | #pragma mark SBJsonStreamWriterDelegate 47 | 48 | - (void)writer:(SBJsonStreamWriter *)writer appendBytes:(const void *)bytes length:(NSUInteger)length { 49 | [data appendBytes:bytes length:length]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriterState.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | @class SBJsonStreamWriter; 36 | 37 | @interface SBJsonStreamWriterState : NSObject 38 | + (id)sharedInstance; 39 | - (BOOL)isInvalidState:(SBJsonStreamWriter*)writer; 40 | - (void)appendSeparator:(SBJsonStreamWriter*)writer; 41 | - (BOOL)expectingKey:(SBJsonStreamWriter*)writer; 42 | - (void)transitionState:(SBJsonStreamWriter*)writer; 43 | - (void)appendWhitespace:(SBJsonStreamWriter*)writer; 44 | @end 45 | 46 | @interface SBJsonStreamWriterStateObjectStart : SBJsonStreamWriterState 47 | @end 48 | 49 | @interface SBJsonStreamWriterStateObjectKey : SBJsonStreamWriterStateObjectStart 50 | @end 51 | 52 | @interface SBJsonStreamWriterStateObjectValue : SBJsonStreamWriterState 53 | @end 54 | 55 | @interface SBJsonStreamWriterStateArrayStart : SBJsonStreamWriterState 56 | @end 57 | 58 | @interface SBJsonStreamWriterStateArrayValue : SBJsonStreamWriterState 59 | @end 60 | 61 | @interface SBJsonStreamWriterStateStart : SBJsonStreamWriterState 62 | @end 63 | 64 | @interface SBJsonStreamWriterStateComplete : SBJsonStreamWriterState 65 | @end 66 | 67 | @interface SBJsonStreamWriterStateError : SBJsonStreamWriterState 68 | @end 69 | 70 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonStreamWriterState.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import "SBJsonStreamWriterState.h" 34 | #import "SBJsonStreamWriter.h" 35 | 36 | #define SINGLETON \ 37 | + (id)sharedInstance { \ 38 | static id state; \ 39 | if (!state) state = [[self alloc] init]; \ 40 | return state; \ 41 | } 42 | 43 | 44 | @implementation SBJsonStreamWriterState 45 | + (id)sharedInstance { return nil; } 46 | - (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { return NO; } 47 | - (void)appendSeparator:(SBJsonStreamWriter*)writer {} 48 | - (BOOL)expectingKey:(SBJsonStreamWriter*)writer { return NO; } 49 | - (void)transitionState:(SBJsonStreamWriter *)writer {} 50 | - (void)appendWhitespace:(SBJsonStreamWriter*)writer { 51 | [writer appendBytes:"\n" length:1]; 52 | for (NSUInteger i = 0; i < writer.stateStack.count; i++) 53 | [writer appendBytes:" " length:2]; 54 | } 55 | @end 56 | 57 | @implementation SBJsonStreamWriterStateObjectStart 58 | 59 | SINGLETON 60 | 61 | - (void)transitionState:(SBJsonStreamWriter *)writer { 62 | writer.state = [SBJsonStreamWriterStateObjectValue sharedInstance]; 63 | } 64 | - (BOOL)expectingKey:(SBJsonStreamWriter *)writer { 65 | writer.error = @"JSON object key must be string"; 66 | return YES; 67 | } 68 | @end 69 | 70 | @implementation SBJsonStreamWriterStateObjectKey 71 | 72 | SINGLETON 73 | 74 | - (void)appendSeparator:(SBJsonStreamWriter *)writer { 75 | [writer appendBytes:"," length:1]; 76 | } 77 | @end 78 | 79 | @implementation SBJsonStreamWriterStateObjectValue 80 | 81 | SINGLETON 82 | 83 | - (void)appendSeparator:(SBJsonStreamWriter *)writer { 84 | [writer appendBytes:":" length:1]; 85 | } 86 | - (void)transitionState:(SBJsonStreamWriter *)writer { 87 | writer.state = [SBJsonStreamWriterStateObjectKey sharedInstance]; 88 | } 89 | - (void)appendWhitespace:(SBJsonStreamWriter *)writer { 90 | [writer appendBytes:" " length:1]; 91 | } 92 | @end 93 | 94 | @implementation SBJsonStreamWriterStateArrayStart 95 | 96 | SINGLETON 97 | 98 | - (void)transitionState:(SBJsonStreamWriter *)writer { 99 | writer.state = [SBJsonStreamWriterStateArrayValue sharedInstance]; 100 | } 101 | @end 102 | 103 | @implementation SBJsonStreamWriterStateArrayValue 104 | 105 | SINGLETON 106 | 107 | - (void)appendSeparator:(SBJsonStreamWriter *)writer { 108 | [writer appendBytes:"," length:1]; 109 | } 110 | @end 111 | 112 | @implementation SBJsonStreamWriterStateStart 113 | 114 | SINGLETON 115 | 116 | 117 | - (void)transitionState:(SBJsonStreamWriter *)writer { 118 | writer.state = [SBJsonStreamWriterStateComplete sharedInstance]; 119 | } 120 | - (void)appendSeparator:(SBJsonStreamWriter *)writer { 121 | } 122 | @end 123 | 124 | @implementation SBJsonStreamWriterStateComplete 125 | 126 | SINGLETON 127 | 128 | - (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { 129 | writer.error = @"Stream is closed"; 130 | return YES; 131 | } 132 | @end 133 | 134 | @implementation SBJsonStreamWriterStateError 135 | 136 | SINGLETON 137 | 138 | @end 139 | 140 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonTokeniser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | typedef enum { 36 | sbjson_token_error = -1, 37 | sbjson_token_eof, 38 | 39 | sbjson_token_array_start, 40 | sbjson_token_array_end, 41 | 42 | sbjson_token_object_start, 43 | sbjson_token_object_end, 44 | 45 | sbjson_token_separator, 46 | sbjson_token_keyval_separator, 47 | 48 | sbjson_token_number, 49 | sbjson_token_string, 50 | sbjson_token_true, 51 | sbjson_token_false, 52 | sbjson_token_null, 53 | 54 | } sbjson_token_t; 55 | 56 | @class SBJsonUTF8Stream; 57 | 58 | @interface SBJsonTokeniser : NSObject 59 | 60 | @property (strong) SBJsonUTF8Stream *stream; 61 | @property (copy) NSString *error; 62 | 63 | - (void)appendData:(NSData*)data_; 64 | 65 | - (sbjson_token_t)getToken:(NSObject**)token; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonTokeniser.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010-2011, 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 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the the author nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #import "SBJsonTokeniser.h" 33 | #import "SBJsonUTF8Stream.h" 34 | 35 | #define SBStringIsIllegalSurrogateHighCharacter(character) (((character) >= 0xD800UL) && ((character) <= 0xDFFFUL)) 36 | #define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL)) 37 | #define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL)) 38 | 39 | @implementation SBJsonTokeniser 40 | 41 | @synthesize error = _error; 42 | @synthesize stream = _stream; 43 | 44 | - (id)init { 45 | self = [super init]; 46 | if (self) { 47 | _stream = [[SBJsonUTF8Stream alloc] init]; 48 | 49 | } 50 | 51 | return self; 52 | } 53 | 54 | 55 | - (void)appendData:(NSData *)data_ { 56 | [_stream appendData:data_]; 57 | } 58 | 59 | 60 | - (sbjson_token_t)match:(const char *)pattern length:(NSUInteger)len retval:(sbjson_token_t)token { 61 | if (![_stream haveRemainingCharacters:len]) 62 | return sbjson_token_eof; 63 | 64 | if ([_stream skipCharacters:pattern length:len]) 65 | return token; 66 | 67 | self.error = [NSString stringWithFormat:@"Expected '%s' after initial '%.1s'", pattern, pattern]; 68 | return sbjson_token_error; 69 | } 70 | 71 | - (BOOL)decodeEscape:(unichar)ch into:(unichar*)decoded { 72 | switch (ch) { 73 | case '\\': 74 | case '/': 75 | case '"': 76 | *decoded = ch; 77 | break; 78 | 79 | case 'b': 80 | *decoded = '\b'; 81 | break; 82 | 83 | case 'n': 84 | *decoded = '\n'; 85 | break; 86 | 87 | case 'r': 88 | *decoded = '\r'; 89 | break; 90 | 91 | case 't': 92 | *decoded = '\t'; 93 | break; 94 | 95 | case 'f': 96 | *decoded = '\f'; 97 | break; 98 | 99 | default: 100 | self.error = @"Illegal escape character"; 101 | return NO; 102 | break; 103 | } 104 | return YES; 105 | } 106 | 107 | - (BOOL)decodeHexQuad:(unichar*)quad { 108 | unichar c, tmp = 0; 109 | 110 | for (int i = 0; i < 4; i++) { 111 | (void)[_stream getNextUnichar:&c]; 112 | tmp *= 16; 113 | switch (c) { 114 | case '0' ... '9': 115 | tmp += c - '0'; 116 | break; 117 | 118 | case 'a' ... 'f': 119 | tmp += 10 + c - 'a'; 120 | break; 121 | 122 | case 'A' ... 'F': 123 | tmp += 10 + c - 'A'; 124 | break; 125 | 126 | default: 127 | return NO; 128 | } 129 | } 130 | *quad = tmp; 131 | return YES; 132 | } 133 | 134 | - (sbjson_token_t)getStringToken:(NSObject**)token { 135 | NSMutableString *acc = nil; 136 | 137 | for (;;) { 138 | [_stream skip]; 139 | 140 | unichar ch; 141 | { 142 | NSMutableString *string = nil; 143 | if (![_stream getSimpleString:&string]) 144 | return sbjson_token_eof; 145 | 146 | if (!string) { 147 | self.error = @"Broken Unicode encoding"; 148 | return sbjson_token_error; 149 | } 150 | 151 | 152 | if (![_stream getUnichar:&ch]) 153 | return sbjson_token_eof; 154 | 155 | if (acc) { 156 | [acc appendString:string]; 157 | 158 | } else if (ch == '"') { 159 | *token = string; 160 | [_stream skip]; 161 | return sbjson_token_string; 162 | 163 | } else { 164 | acc = [string mutableCopy]; 165 | } 166 | } 167 | 168 | switch (ch) { 169 | case 0 ... 0x1F: 170 | self.error = [NSString stringWithFormat:@"Unescaped control character [0x%0.2X]", (int)ch]; 171 | return sbjson_token_error; 172 | break; 173 | 174 | case '"': 175 | *token = acc; 176 | [_stream skip]; 177 | return sbjson_token_string; 178 | break; 179 | 180 | case '\\': 181 | if (![_stream getNextUnichar:&ch]) 182 | return sbjson_token_eof; 183 | 184 | if (ch == 'u') { 185 | if (![_stream haveRemainingCharacters:5]) 186 | return sbjson_token_eof; 187 | 188 | unichar hi; 189 | if (![self decodeHexQuad:&hi]) { 190 | self.error = @"Invalid hex quad"; 191 | return sbjson_token_error; 192 | } 193 | 194 | if (SBStringIsSurrogateHighCharacter(hi)) { 195 | unichar lo; 196 | 197 | if (![_stream haveRemainingCharacters:6]) 198 | return sbjson_token_eof; 199 | 200 | (void)[_stream getNextUnichar:&ch]; 201 | (void)[_stream getNextUnichar:&lo]; 202 | if (ch != '\\' || lo != 'u' || ![self decodeHexQuad:&lo]) { 203 | self.error = @"Missing low character in surrogate pair"; 204 | return sbjson_token_error; 205 | } 206 | 207 | if (!SBStringIsSurrogateLowCharacter(lo)) { 208 | self.error = @"Invalid low character in surrogate pair"; 209 | return sbjson_token_error; 210 | } 211 | 212 | [acc appendFormat:@"%C%C", hi, lo]; 213 | } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) { 214 | self.error = @"Invalid high character in surrogate pair"; 215 | return sbjson_token_error; 216 | } else { 217 | [acc appendFormat:@"%C", hi]; 218 | } 219 | 220 | 221 | } else { 222 | unichar decoded; 223 | if (![self decodeEscape:ch into:&decoded]) 224 | return sbjson_token_error; 225 | [acc appendFormat:@"%C", decoded]; 226 | } 227 | 228 | break; 229 | 230 | default: { 231 | self.error = [NSString stringWithFormat:@"Invalid UTF-8: '%x'", (int)ch]; 232 | return sbjson_token_error; 233 | break; 234 | } 235 | } 236 | } 237 | return sbjson_token_eof; 238 | } 239 | 240 | - (sbjson_token_t)getNumberToken:(NSObject**)token { 241 | 242 | NSUInteger numberStart = _stream.index; 243 | NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet]; 244 | 245 | unichar ch; 246 | if (![_stream getUnichar:&ch]) 247 | return sbjson_token_eof; 248 | 249 | BOOL isNegative = NO; 250 | if (ch == '-') { 251 | isNegative = YES; 252 | if (![_stream getNextUnichar:&ch]) 253 | return sbjson_token_eof; 254 | } 255 | 256 | unsigned long long mantissa = 0; 257 | int mantissa_length = 0; 258 | 259 | if (ch == '0') { 260 | mantissa_length++; 261 | if (![_stream getNextUnichar:&ch]) 262 | return sbjson_token_eof; 263 | 264 | if ([digits characterIsMember:ch]) { 265 | self.error = @"Leading zero is illegal in number"; 266 | return sbjson_token_error; 267 | } 268 | } 269 | 270 | while ([digits characterIsMember:ch]) { 271 | mantissa *= 10; 272 | mantissa += (ch - '0'); 273 | mantissa_length++; 274 | 275 | if (![_stream getNextUnichar:&ch]) 276 | return sbjson_token_eof; 277 | } 278 | 279 | short exponent = 0; 280 | BOOL isFloat = NO; 281 | 282 | if (ch == '.') { 283 | isFloat = YES; 284 | if (![_stream getNextUnichar:&ch]) 285 | return sbjson_token_eof; 286 | 287 | while ([digits characterIsMember:ch]) { 288 | mantissa *= 10; 289 | mantissa += (ch - '0'); 290 | mantissa_length++; 291 | exponent--; 292 | 293 | if (![_stream getNextUnichar:&ch]) 294 | return sbjson_token_eof; 295 | } 296 | 297 | if (!exponent) { 298 | self.error = @"No digits after decimal point"; 299 | return sbjson_token_error; 300 | } 301 | } 302 | 303 | BOOL hasExponent = NO; 304 | if (ch == 'e' || ch == 'E') { 305 | hasExponent = YES; 306 | 307 | if (![_stream getNextUnichar:&ch]) 308 | return sbjson_token_eof; 309 | 310 | BOOL expIsNegative = NO; 311 | if (ch == '-') { 312 | expIsNegative = YES; 313 | if (![_stream getNextUnichar:&ch]) 314 | return sbjson_token_eof; 315 | 316 | } else if (ch == '+') { 317 | if (![_stream getNextUnichar:&ch]) 318 | return sbjson_token_eof; 319 | } 320 | 321 | short explicit_exponent = 0; 322 | short explicit_exponent_length = 0; 323 | while ([digits characterIsMember:ch]) { 324 | explicit_exponent *= 10; 325 | explicit_exponent += (ch - '0'); 326 | explicit_exponent_length++; 327 | 328 | if (![_stream getNextUnichar:&ch]) 329 | return sbjson_token_eof; 330 | } 331 | 332 | if (explicit_exponent_length == 0) { 333 | self.error = @"No digits in exponent"; 334 | return sbjson_token_error; 335 | } 336 | 337 | if (expIsNegative) 338 | exponent -= explicit_exponent; 339 | else 340 | exponent += explicit_exponent; 341 | } 342 | 343 | if (!mantissa_length && isNegative) { 344 | self.error = @"No digits after initial minus"; 345 | return sbjson_token_error; 346 | 347 | } else if (mantissa_length >= 19) { 348 | 349 | NSString *number = [_stream stringWithRange:NSMakeRange(numberStart, _stream.index - numberStart)]; 350 | *token = [NSDecimalNumber decimalNumberWithString:number]; 351 | 352 | } else if (!isFloat && !hasExponent) { 353 | if (!isNegative) 354 | *token = [NSNumber numberWithUnsignedLongLong:mantissa]; 355 | else 356 | *token = [NSNumber numberWithLongLong:-mantissa]; 357 | } else { 358 | *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa 359 | exponent:exponent 360 | isNegative:isNegative]; 361 | } 362 | 363 | return sbjson_token_number; 364 | } 365 | 366 | - (sbjson_token_t)getToken:(NSObject **)token { 367 | 368 | [_stream skipWhitespace]; 369 | 370 | unichar ch; 371 | if (![_stream getUnichar:&ch]) 372 | return sbjson_token_eof; 373 | 374 | NSUInteger oldIndexLocation = _stream.index; 375 | sbjson_token_t tok; 376 | 377 | switch (ch) { 378 | case '[': 379 | tok = sbjson_token_array_start; 380 | [_stream skip]; 381 | break; 382 | 383 | case ']': 384 | tok = sbjson_token_array_end; 385 | [_stream skip]; 386 | break; 387 | 388 | case '{': 389 | tok = sbjson_token_object_start; 390 | [_stream skip]; 391 | break; 392 | 393 | case ':': 394 | tok = sbjson_token_keyval_separator; 395 | [_stream skip]; 396 | break; 397 | 398 | case '}': 399 | tok = sbjson_token_object_end; 400 | [_stream skip]; 401 | break; 402 | 403 | case ',': 404 | tok = sbjson_token_separator; 405 | [_stream skip]; 406 | break; 407 | 408 | case 'n': 409 | tok = [self match:"null" length:4 retval:sbjson_token_null]; 410 | break; 411 | 412 | case 't': 413 | tok = [self match:"true" length:4 retval:sbjson_token_true]; 414 | break; 415 | 416 | case 'f': 417 | tok = [self match:"false" length:5 retval:sbjson_token_false]; 418 | break; 419 | 420 | case '"': 421 | tok = [self getStringToken:token]; 422 | break; 423 | 424 | case '0' ... '9': 425 | case '-': 426 | tok = [self getNumberToken:token]; 427 | break; 428 | 429 | case '+': 430 | self.error = @"Leading + is illegal in number"; 431 | tok = sbjson_token_error; 432 | break; 433 | 434 | default: 435 | self.error = [NSString stringWithFormat:@"Illegal start of token [%c]", ch]; 436 | tok = sbjson_token_error; 437 | break; 438 | } 439 | 440 | if (tok == sbjson_token_eof) { 441 | // We ran out of bytes in the middle of a token. 442 | // We don't know how to restart in mid-flight, so 443 | // rewind to the start of the token for next attempt. 444 | // Hopefully we'll have more data then. 445 | _stream.index = oldIndexLocation; 446 | } 447 | 448 | return tok; 449 | } 450 | 451 | 452 | @end 453 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonUTF8Stream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, 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 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the the author nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #import 33 | 34 | 35 | @interface SBJsonUTF8Stream : NSObject { 36 | @private 37 | const char *_bytes; 38 | NSMutableData *_data; 39 | NSUInteger _length; 40 | } 41 | 42 | @property (assign) NSUInteger index; 43 | 44 | - (void)appendData:(NSData*)data_; 45 | 46 | - (BOOL)haveRemainingCharacters:(NSUInteger)chars; 47 | 48 | - (void)skip; 49 | - (void)skipWhitespace; 50 | - (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len; 51 | 52 | - (BOOL)getUnichar:(unichar*)ch; 53 | - (BOOL)getNextUnichar:(unichar*)ch; 54 | - (BOOL)getSimpleString:(NSString**)string; 55 | 56 | - (NSString*)stringWithRange:(NSRange)range; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonUTF8Stream.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, 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 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the the author nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #import "SBJsonUTF8Stream.h" 33 | 34 | 35 | @implementation SBJsonUTF8Stream 36 | 37 | @synthesize index = _index; 38 | 39 | - (id)init { 40 | self = [super init]; 41 | if (self) { 42 | _data = [[NSMutableData alloc] initWithCapacity:4096u]; 43 | } 44 | return self; 45 | } 46 | 47 | 48 | - (void)appendData:(NSData *)data_ { 49 | 50 | if (_index) { 51 | // Discard data we've already parsed 52 | [_data replaceBytesInRange:NSMakeRange(0, _index) withBytes:"" length:0]; 53 | 54 | // Reset index to point to current position 55 | _index = 0; 56 | } 57 | 58 | [_data appendData:data_]; 59 | 60 | // This is an optimisation. 61 | _bytes = [_data bytes]; 62 | _length = [_data length]; 63 | } 64 | 65 | 66 | - (BOOL)getUnichar:(unichar*)ch { 67 | if (_index < _length) { 68 | *ch = (unichar)_bytes[_index]; 69 | return YES; 70 | } 71 | return NO; 72 | } 73 | 74 | - (BOOL)getNextUnichar:(unichar*)ch { 75 | if (++_index < _length) { 76 | *ch = (unichar)_bytes[_index]; 77 | return YES; 78 | } 79 | return NO; 80 | } 81 | 82 | - (BOOL)getSimpleString:(NSString **)string { 83 | NSUInteger start = _index; 84 | while (_index < _length) { 85 | switch (_bytes[_index]) { 86 | case '"': 87 | case '\\': 88 | case 0 ... 0x1f: 89 | *string = [[NSString alloc] initWithBytes:(_bytes + start) length:(_index - start) encoding:NSUTF8StringEncoding]; 90 | return YES; 91 | break; 92 | default: 93 | _index++; 94 | break; 95 | } 96 | } 97 | return NO; 98 | } 99 | 100 | - (void)skip { 101 | _index++; 102 | } 103 | 104 | - (void)skipWhitespace { 105 | while (_index < _length) { 106 | switch (_bytes[_index]) { 107 | case ' ': 108 | case '\t': 109 | case '\r': 110 | case '\n': 111 | _index++; 112 | break; 113 | default: 114 | return; 115 | break; 116 | } 117 | } 118 | } 119 | 120 | - (BOOL)haveRemainingCharacters:(NSUInteger)chars { 121 | return [_data length] - _index >= chars; 122 | } 123 | 124 | - (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len { 125 | const void *bytes = [_data bytes] + _index; 126 | if (!memcmp(bytes, chars, len)) { 127 | _index += len; 128 | return YES; 129 | } 130 | return NO; 131 | } 132 | 133 | - (NSString*)stringWithRange:(NSRange)range { 134 | return [[NSString alloc] initWithBytes:_bytes + range.location length:range.length encoding:NSUTF8StringEncoding]; 135 | 136 | } 137 | 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonWriter.h: -------------------------------------------------------------------------------- 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 31 | 32 | /** 33 | @brief The JSON writer class. 34 | 35 | This uses SBJsonStreamWriter internally. 36 | 37 | @see @ref json2objc 38 | */ 39 | 40 | @interface SBJsonWriter : NSObject 41 | 42 | /** 43 | @brief The maximum recursing depth. 44 | 45 | Defaults to 32. If the input is nested deeper than this the input will be deemed to be 46 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 47 | turn off this security feature by setting the maxDepth value to 0. 48 | */ 49 | @property NSUInteger maxDepth; 50 | 51 | /** 52 | @brief Return an error trace, or nil if there was no errors. 53 | 54 | Note that this method returns the trace of the last method that failed. 55 | You need to check the return value of the call you're making to figure out 56 | if the call actually failed, before you know call this method. 57 | */ 58 | @property (readonly, copy) NSString *error; 59 | 60 | /** 61 | @brief Whether we are generating human-readable (multiline) JSON. 62 | 63 | Set whether or not to generate human-readable JSON. The default is NO, which produces 64 | JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable 65 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 66 | spaces per nesting level. 67 | */ 68 | @property BOOL humanReadable; 69 | 70 | /** 71 | @brief Whether or not to sort the dictionary keys in the output. 72 | 73 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 74 | (This is useful if you need to compare two structures, for example.) The default is NO. 75 | */ 76 | @property BOOL sortKeys; 77 | 78 | /** 79 | @brief Return JSON representation for the given object. 80 | 81 | Returns a string containing JSON representation of the passed in value, or nil on error. 82 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 83 | 84 | @param value any instance that can be represented as JSON text. 85 | */ 86 | - (NSString*)stringWithObject:(id)value; 87 | 88 | /** 89 | @brief Return JSON representation for the given object. 90 | 91 | Returns an NSData object containing JSON represented as UTF8 text, or nil on error. 92 | 93 | @param value any instance that can be represented as JSON text. 94 | */ 95 | - (NSData*)dataWithObject:(id)value; 96 | 97 | /** 98 | @brief Return JSON representation (or fragment) for the given object. 99 | 100 | Returns a string containing JSON representation of the passed in value, or nil on error. 101 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 102 | 103 | @param value any instance that can be represented as a JSON fragment 104 | @param error pointer to object to be populated with NSError on failure 105 | 106 | */- (NSString*)stringWithObject:(id)value 107 | error:(NSError**)error; 108 | 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /PSGoogleReader/SBJSON/SBJsonWriter.m: -------------------------------------------------------------------------------- 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 "SBJsonWriter.h" 31 | #import "SBJsonStreamWriter.h" 32 | #import "SBJsonStreamWriterAccumulator.h" 33 | 34 | 35 | @interface SBJsonWriter () 36 | @property (copy) NSString *error; 37 | @end 38 | 39 | @implementation SBJsonWriter 40 | 41 | @synthesize sortKeys; 42 | @synthesize humanReadable; 43 | 44 | @synthesize error; 45 | @synthesize maxDepth; 46 | 47 | - (id)init { 48 | self = [super init]; 49 | if (self) { 50 | self.maxDepth = 32u; 51 | } 52 | return self; 53 | } 54 | 55 | 56 | - (NSString*)stringWithObject:(id)value { 57 | NSData *data = [self dataWithObject:value]; 58 | if (data) 59 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 60 | return nil; 61 | } 62 | 63 | - (NSString*)stringWithObject:(id)value error:(NSError**)error_ { 64 | NSString *tmp = [self stringWithObject:value]; 65 | if (tmp) 66 | return tmp; 67 | 68 | if (error_) { 69 | NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil]; 70 | *error_ = [NSError errorWithDomain:@"org.brautaset.SBJsonWriter.ErrorDomain" code:0 userInfo:ui]; 71 | } 72 | 73 | return nil; 74 | } 75 | 76 | - (NSData*)dataWithObject:(id)object { 77 | self.error = nil; 78 | 79 | SBJsonStreamWriterAccumulator *accumulator = [[SBJsonStreamWriterAccumulator alloc] init]; 80 | 81 | SBJsonStreamWriter *streamWriter = [[SBJsonStreamWriter alloc] init]; 82 | streamWriter.sortKeys = self.sortKeys; 83 | streamWriter.maxDepth = self.maxDepth; 84 | streamWriter.humanReadable = self.humanReadable; 85 | streamWriter.delegate = accumulator; 86 | 87 | BOOL ok = NO; 88 | if ([object isKindOfClass:[NSDictionary class]]) 89 | ok = [streamWriter writeObject:object]; 90 | 91 | else if ([object isKindOfClass:[NSArray class]]) 92 | ok = [streamWriter writeArray:object]; 93 | 94 | else if ([object respondsToSelector:@selector(proxyForJson)]) 95 | return [self dataWithObject:[object proxyForJson]]; 96 | else { 97 | self.error = @"Not valid type for JSON"; 98 | return nil; 99 | } 100 | 101 | if (ok) 102 | return accumulator.data; 103 | 104 | self.error = streamWriter.error; 105 | return nil; 106 | } 107 | 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /PSGoogleReader/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /PSGoogleReader/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PSGoogleReader 4 | // 5 | // Created by Daniel Isenhower ( daniel@perspecdev.com ) on 5/24/11. 6 | // Copyright 2011 PerspecDev Solutions, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "PSGoogleReaderAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([PSGoogleReaderAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PSGoogleReader is a class that connects to Google Reader. I don't have a pretty 2 | demo UI set up, so you won't see much in the simulator when you run this app. Check 3 | NSLog output to see very simplified demo results. 4 | 5 | Be sure to set your client (app) name in PSGoogleReader.m 6 | Set your Google Reader username/password in PSGoogleReaderAppDelegate.m 7 | 8 | Code license is pretty generous. See comments at the top of PSGoogleReader.m for details. 9 | 10 | Email me if you have any questions: daniel@perspecdev.com --------------------------------------------------------------------------------