+2007-12-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/SOGo/NSScanner+BSJSONAdditions.m ([NSScanner
+ -scanJSONStringDelimiterString]): new category module taken from
+ BSJSONAdditions 1.3.
+
+ * SoObjects/SOGo/NSDictionary+BSJSONAdditions.[hm]: new category
+ module taken from BSJSONAdditions 1.3.
+ http://blakeseely.com/downloads.html
+
2007-12-12 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/NSString+Utilities.m ([NSString
SOGoMailer.h \
SOGoUser.h \
\
+ NSDictionary+BSJSONAdditions.h \
+ NSScanner+BSJSONAdditions.h \
+ \
WORequest+SOGo.h
libSOGo_OBJC_FILES = \
SOGoMailer.m \
SOGoUser.m \
\
+ NSDictionary+BSJSONAdditions.m \
+ NSScanner+BSJSONAdditions.m \
+ \
WORequest+SOGo.m
# tools
--- /dev/null
+//
+// BSJSONAdditions
+//
+// Created by Blake Seely on 2/1/06.
+// Copyright 2006 Blake Seely - http://www.blakeseely.com All rights reserved.
+// Permission to use this code:
+//
+// Feel free to use this code in your software, either as-is or
+// in a modified form. Either way, please include a credit in
+// your software's "About" box or similar, mentioning at least
+// my name (Blake Seely).
+//
+// Permission to redistribute this code:
+//
+// You can redistribute this code, as long as you keep these
+// comments. You can also redistribute modified versions of the
+// code, as long as you add comments to say that you've made
+// modifications (keeping these original comments too).
+//
+// If you do use or redistribute this code, an email would be
+// appreciated, just to let me know that people are finding my
+// code useful. You can reach me at blakeseely@mac.com
+
+#import <Foundation/NSDictionary.h>
+
+extern NSString *jsonIndentString;
+extern const int jsonDoNotIndent;
+
+@interface NSDictionary (BSJSONAdditions)
+
++ (NSDictionary *)dictionaryWithJSONString:(NSString *)jsonString;
+- (NSString *)jsonStringValue;
+
+@end
+
+
+@interface NSDictionary (PrivateBSJSONAdditions)
+
+- (NSString *)jsonStringValueWithIndentLevel:(int)level;
+- (NSString *)jsonStringForValue:(id)value withIndentLevel:(int)level;
+- (NSString *)jsonStringForArray:(NSArray *)array withIndentLevel:(int)level;
+- (NSString *)jsonStringForString:(NSString *)string;
+- (NSString *)jsonIndentStringForLevel:(int)level;
+
+@end
--- /dev/null
+//
+// BSJSONAdditions
+//
+// Created by Blake Seely on 2/1/06.
+// Copyright 2006 Blake Seely - http://www.blakeseely.com All rights reserved.
+// Permission to use this code:
+//
+// Feel free to use this code in your software, either as-is or
+// in a modified form. Either way, please include a credit in
+// your software's "About" box or similar, mentioning at least
+// my name (Blake Seely).
+//
+// Permission to redistribute this code:
+//
+// You can redistribute this code, as long as you keep these
+// comments. You can also redistribute modified versions of the
+// code, as long as you add comments to say that you've made
+// modifications (keeping these original comments too).
+//
+// If you do use or redistribute this code, an email would be
+// appreciated, just to let me know that people are finding my
+// code useful. You can reach me at blakeseely@mac.com
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDecimalNumber.h>
+#import <Foundation/NSEnumerator.h>
+#import <Foundation/NSNull.h>
+#import <Foundation/NSValue.h>
+
+#import "NSDictionary+BSJSONAdditions.h"
+#import "NSScanner+BSJSONAdditions.h"
+
+NSString *jsonIndentString = @"\t"; // Modify this string to change how the output formats.
+const int jsonDoNotIndent = -1;
+
+@implementation NSDictionary (BSJSONAdditions)
+
++ (NSDictionary *)dictionaryWithJSONString:(NSString *)jsonString
+{
+ NSScanner *scanner = [[NSScanner alloc] initWithString:jsonString];
+ NSDictionary *dictionary = nil;
+ [scanner scanJSONObject:&dictionary];
+ [scanner release];
+ return dictionary;
+}
+
+- (NSString *)jsonStringValue
+{
+ return [self jsonStringValueWithIndentLevel:0];
+}
+
+@end
+
+@implementation NSDictionary (PrivateBSJSONAdditions)
+
+- (NSString *)jsonStringValueWithIndentLevel:(int)level
+{
+ NSMutableString *jsonString = [[NSMutableString alloc] init];
+ [jsonString appendString:jsonObjectStartString];
+
+ NSEnumerator *keyEnum = [self keyEnumerator];
+ NSString *keyString = [keyEnum nextObject];
+ NSString *valueString;
+ if (keyString != nil) {
+ valueString = [self jsonStringForValue:[self objectForKey:keyString] withIndentLevel:level];
+ if (level != jsonDoNotIndent) { // indent before each key
+ [jsonString appendString:[self jsonIndentStringForLevel:level]];
+ }
+ [jsonString appendFormat:@" %@ %@ %@", [self jsonStringForString:keyString], jsonKeyValueSeparatorString, valueString];
+ }
+
+ while ((keyString = [keyEnum nextObject])) {
+ valueString = [self jsonStringForValue:[self objectForKey:keyString] withIndentLevel:level]; // TODO bail if valueString is nil? How to bail successfully from here?
+ [jsonString appendString:jsonValueSeparatorString];
+ if (level != jsonDoNotIndent) { // indent before each key
+ [jsonString appendFormat:@"%@", [self jsonIndentStringForLevel:level]];
+ }
+ [jsonString appendFormat:@" %@ %@ %@", [self jsonStringForString:keyString], jsonKeyValueSeparatorString, valueString];
+ }
+
+ //[jsonString appendString:@"\n"];
+ [jsonString appendString:jsonObjectEndString];
+
+ return [jsonString autorelease];
+}
+
+- (NSString *)jsonStringForValue:(id)value withIndentLevel:(int)level
+{
+ NSString *jsonString;
+ if ([value respondsToSelector:@selector(characterAtIndex:)]) // String
+ jsonString = [self jsonStringForString:(NSString *)value];
+ else if ([value respondsToSelector:@selector(keyEnumerator)]) // Dictionary
+ jsonString = [(NSDictionary *)value jsonStringValueWithIndentLevel:(level + 1)];
+ else if ([value respondsToSelector:@selector(objectAtIndex:)]) // Array
+ jsonString = [self jsonStringForArray:(NSArray *)value withIndentLevel:level];
+ else if (value == [NSNull null]) // null
+ jsonString = jsonNullString;
+ else if ([value respondsToSelector:@selector(objCType)]) { // NSNumber - representing true, false, and any form of numeric
+ NSNumber *number = (NSNumber *)value;
+ if (((*[number objCType]) == 'c') && ([number boolValue] == YES)) // true
+ jsonString = jsonTrueString;
+ else if (((*[number objCType]) == 'c') && ([number boolValue] == NO)) // false
+ jsonString = jsonFalseString;
+ else // attempt to handle as a decimal number - int, fractional, exponential
+ // TODO: values converted from exponential json to dict and back to json do not format as exponential again
+ jsonString = [[NSDecimalNumber decimalNumberWithDecimal:[number decimalValue]] stringValue];
+ } else {
+ // TODO: error condition - it's not any of the types that I know about.
+ return nil;
+ }
+
+ return jsonString;
+}
+
+- (NSString *)jsonStringForArray:(NSArray *)array withIndentLevel:(int)level
+{
+ NSMutableString *jsonString = [[NSMutableString alloc] init];
+ [jsonString appendString:jsonArrayStartString];
+
+ if ([array count] > 0) {
+ [jsonString appendString:[self jsonStringForValue:[array objectAtIndex:0] withIndentLevel:level]];
+ }
+
+ int i;
+ for (i = 1; i < [array count]; i++) {
+ [jsonString appendFormat:@"%@ %@", jsonValueSeparatorString, [self jsonStringForValue:[array objectAtIndex:i] withIndentLevel:level]];
+ }
+
+ [jsonString appendString:jsonArrayEndString];
+ return [jsonString autorelease];
+}
+
+- (NSString *)jsonStringForString:(NSString *)string
+{
+ NSMutableString *jsonString = [[NSMutableString alloc] init];
+ [jsonString appendString:jsonStringDelimiterString];
+
+ // Build the result one character at a time, inserting escaped characters as necessary
+ int i;
+ unichar nextChar;
+ for (i = 0; i < [string length]; i++) {
+ nextChar = [string characterAtIndex:i];
+ switch (nextChar) {
+ case '\"':
+ [jsonString appendString:@"\\\""];
+ break;
+ case '\\':
+ [jsonString appendString:@"\\n"];
+ break;
+ /* TODO: email out to json group on this - spec says to handlt his, examples and example code don't handle this.
+ case '\/':
+ [jsonString appendString:@"\\/"];
+ break;
+ */
+ case '\b':
+ [jsonString appendString:@"\\b"];
+ break;
+ case '\f':
+ [jsonString appendString:@"\\f"];
+ break;
+ case '\n':
+ [jsonString appendString:@"\\n"];
+ break;
+ case '\r':
+ [jsonString appendString:@"\\r"];
+ break;
+ case '\t':
+ [jsonString appendString:@"\\t"];
+ break;
+ /* TODO: Find and encode unicode characters here?
+ case '\u':
+ [jsonString appendString:@"\\n"];
+ break;
+ */
+ default:
+ [jsonString appendString:[NSString stringWithCharacters:&nextChar length:1]];
+ break;
+ }
+ }
+ [jsonString appendString:jsonStringDelimiterString];
+ return [jsonString autorelease];
+}
+
+- (NSString *)jsonIndentStringForLevel:(int)level
+{
+ NSMutableString *indentString = [[NSMutableString alloc] init];
+ if (level != jsonDoNotIndent) {
+ [indentString appendString:@"\n"];
+ int i;
+ for (i = 0; i < level; i++) {
+ [indentString appendString:jsonIndentString];
+ }
+ }
+
+ return [indentString autorelease];
+}
+
+@end
--- /dev/null
+//
+// BSJSONAdditions
+//
+// Created by Blake Seely on 2/1/06.
+// Copyright 2006 Blake Seely - http://www.blakeseely.com All rights reserved.
+// Permission to use this code:
+//
+// Feel free to use this code in your software, either as-is or
+// in a modified form. Either way, please include a credit in
+// your software's "About" box or similar, mentioning at least
+// my name (Blake Seely).
+//
+// Permission to redistribute this code:
+//
+// You can redistribute this code, as long as you keep these
+// comments. You can also redistribute modified versions of the
+// code, as long as you add comments to say that you've made
+// modifications (keeping these original comments too).
+//
+// If you do use or redistribute this code, an email would be
+// appreciated, just to let me know that people are finding my
+// code useful. You can reach me at blakeseely@mac.com
+//
+
+#import <Foundation/NSScanner.h>
+
+@class NSArray;
+@class NSDictionary;
+@class NSNumber;
+@class NSString;
+
+extern NSString *jsonObjectStartString;
+extern NSString *jsonObjectEndString;
+extern NSString *jsonArrayStartString;
+extern NSString *jsonArrayEndString;
+extern NSString *jsonKeyValueSeparatorString;
+extern NSString *jsonValueSeparatorString;
+extern NSString *jsonStringDelimiterString;
+extern NSString *jsonStringEscapedDoubleQuoteString;
+extern NSString *jsonStringEscapedSlashString;
+extern NSString *jsonTrueString;
+extern NSString *jsonFalseString;
+extern NSString *jsonNullString;
+
+
+@interface NSScanner (PrivateBSJSONAdditions)
+
+- (BOOL)scanJSONObject:(NSDictionary **)dictionary;
+- (BOOL)scanJSONArray:(NSArray **)array;
+- (BOOL)scanJSONString:(NSString **)string;
+- (BOOL)scanJSONValue:(id *)value;
+- (BOOL)scanJSONNumber:(NSNumber **)number;
+
+- (BOOL)scanJSONWhiteSpace;
+- (BOOL)scanJSONKeyValueSeparator;
+- (BOOL)scanJSONValueSeparator;
+- (BOOL)scanJSONObjectStartString;
+- (BOOL)scanJSONObjectEndString;
+- (BOOL)scanJSONArrayStartString;
+- (BOOL)scanJSONArrayEndString;
+- (BOOL)scanJSONArrayEndString;
+- (BOOL)scanJSONStringDelimiterString;
+
+@end
--- /dev/null
+//
+// BSJSONAdditions
+//
+// Created by Blake Seely on 2/1/06.
+// Copyright 2006 Blake Seely - http://www.blakeseely.com All rights reserved.
+// Permission to use this code:
+//
+// Feel free to use this code in your software, either as-is or
+// in a modified form. Either way, please include a credit in
+// your software's "About" box or similar, mentioning at least
+// my name (Blake Seely).
+//
+// Permission to redistribute this code:
+//
+// You can redistribute this code, as long as you keep these
+// comments. You can also redistribute modified versions of the
+// code, as long as you add comments to say that you've made
+// modifications (keeping these original comments too).
+//
+// If you do use or redistribute this code, an email would be
+// appreciated, just to let me know that people are finding my
+// code useful. You can reach me at blakeseely@mac.com
+//
+//
+// Version 1.2: Includes modifications by Bill Garrison: http://www.standardorbit.com , which included
+// Unit Tests adapted from Jonathan Wight's CocoaJSON code: http://www.toxicsoftware.com
+// I have included those adapted unit tests in this package.
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDecimalNumber.h>
+#import <Foundation/NSNull.h>
+#import <Foundation/NSValue.h>
+
+#import "NSScanner+BSJSONAdditions.h"
+
+NSString *jsonObjectStartString = @"{";
+NSString *jsonObjectEndString = @"}";
+NSString *jsonArrayStartString = @"[";
+NSString *jsonArrayEndString = @"]";
+NSString *jsonKeyValueSeparatorString = @":";
+NSString *jsonValueSeparatorString = @",";
+NSString *jsonStringDelimiterString = @"\"";
+NSString *jsonStringEscapedDoubleQuoteString = @"\\\"";
+NSString *jsonStringEscapedSlashString = @"\\\\";
+NSString *jsonTrueString = @"true";
+NSString *jsonFalseString = @"false";
+NSString *jsonNullString = @"null";
+
+@implementation NSScanner (PrivateBSJSONAdditions)
+
+- (BOOL)scanJSONObject:(NSDictionary **)dictionary
+{
+ //[self setCharactersToBeSkipped:nil];
+
+ BOOL result = NO;
+
+ /* START - April 21, 2006 - Updated to bypass irrelevant characters at the beginning of a JSON string */
+ NSString *ignoredString;
+ [self scanUpToString:jsonObjectStartString intoString:&ignoredString];
+ /* END - April 21, 2006 */
+
+ if (![self scanJSONObjectStartString]) {
+ // TODO: Error condition. For now, return false result, do nothing with the dictionary handle
+ } else {
+ NSMutableDictionary *jsonKeyValues = [[[NSMutableDictionary alloc] init] autorelease];
+ NSString *key = nil;
+ id value;
+ [self scanJSONWhiteSpace];
+ while (([self scanJSONString:&key]) && ([self scanJSONKeyValueSeparator]) && ([self scanJSONValue:&value])) {
+ [jsonKeyValues setObject:value forKey:key];
+ [self scanJSONWhiteSpace];
+ // check to see if the character at scan location is a value separator. If it is, do nothing.
+ if ([[[self string] substringWithRange:NSMakeRange([self scanLocation], 1)] isEqualToString:jsonValueSeparatorString]) {
+ [self scanJSONValueSeparator];
+ }
+ }
+ if ([self scanJSONObjectEndString]) {
+ // whether or not we found a key-val pair, we found open and close brackets - completing an object
+ result = YES;
+ *dictionary = jsonKeyValues;
+ }
+ }
+ return result;
+}
+
+- (BOOL)scanJSONArray:(NSArray **)array
+{
+ BOOL result = NO;
+ NSMutableArray *values = [[[NSMutableArray alloc] init] autorelease];
+ [self scanJSONArrayStartString];
+ id value = nil;
+
+ while ([self scanJSONValue:&value]) {
+ [values addObject:value];
+ [self scanJSONWhiteSpace];
+ if ([[[self string] substringWithRange:NSMakeRange([self scanLocation], 1)] isEqualToString:jsonValueSeparatorString]) {
+ [self scanJSONValueSeparator];
+ }
+ }
+ if ([self scanJSONArrayEndString]) {
+ result = YES;
+ *array = values;
+ }
+
+ return result;
+}
+
+- (BOOL)scanJSONString:(NSString **)string
+{
+ BOOL result = NO;
+ if ([self scanJSONStringDelimiterString]) {
+ NSMutableString *chars = [[[NSMutableString alloc] init] autorelease];
+ NSString *characterFormat = @"%C";
+
+ // process character by character until we finish the string or reach another double-quote
+ while ((![self isAtEnd]) && ([[self string] characterAtIndex:[self scanLocation]] != '\"')) {
+ unichar currentChar = [[self string] characterAtIndex:[self scanLocation]];
+ unichar nextChar;
+ if (currentChar != '\\') {
+ [chars appendFormat:characterFormat, currentChar];
+ [self setScanLocation:([self scanLocation] + 1)];
+ } else {
+ nextChar = [[self string] characterAtIndex:([self scanLocation] + 1)];
+ switch (nextChar) {
+ case '\"':
+ [chars appendString:@"\""];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case '\\':
+ [chars appendString:@"\\"]; // debugger shows result as having two slashes, but final output is correct. Possible debugger error?
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ /* TODO: json.org docs mention this seq, so does yahoo, but not recognized here by xcode, note from crockford: not a required escape
+ case '\/':
+ [chars appendString:@"\/"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ */
+ case 'b':
+ [chars appendString:@"\b"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case 'f':
+ [chars appendString:@"\f"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case 'n':
+ [chars appendString:@"\n"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case 'r':
+ [chars appendString:@"\r"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case 't':
+ [chars appendString:@"\t"];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ case 'u': // unicode sequence - get string of hex chars, convert to int, convert to unichar, append
+ [self setScanLocation:([self scanLocation] + 2)]; // advance past '\u'
+ NSString *digits = [[self string] substringWithRange:NSMakeRange([self scanLocation], 4)];
+ /* START Updated code modified from code fix submitted by Bill Garrison - March 28, 2006 - http://www.standardorbit.net */
+ NSScanner *hexScanner = [NSScanner scannerWithString:digits];
+ NSString *verifiedHexDigits;
+ NSCharacterSet *hexDigitSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"];
+ if (NO == [hexScanner scanCharactersFromSet:hexDigitSet intoString:&verifiedHexDigits])
+ return NO;
+ if (4 != [verifiedHexDigits length])
+ return NO;
+
+ // Read in the hex value
+ [hexScanner setScanLocation:0];
+ unsigned unicodeHexValue;
+ if (NO == [hexScanner scanHexInt:&unicodeHexValue]) {
+ return NO;
+ }
+ [chars appendFormat:characterFormat, unicodeHexValue];
+ /* END update - March 28, 2006 */
+ [self setScanLocation:([self scanLocation] + 4)];
+ break;
+ default:
+ [chars appendFormat:@"\\%C", nextChar];
+ [self setScanLocation:([self scanLocation] + 2)];
+ break;
+ }
+ }
+ }
+
+ if (![self isAtEnd]) {
+ result = [self scanJSONStringDelimiterString];
+ *string = chars;
+ }
+
+ return result;
+
+ /* this code is more appropriate if you have a separate method to unescape the found string
+ for example, between inputting json and outputting it, it may make more sense to have a category on NSString to perform
+ escaping and unescaping. Keeping this code and looking into this for a future update.
+ unsigned int searchLength = [[self string] length] - [self scanLocation];
+ unsigned int quoteLocation = [[self string] rangeOfString:jsonStringDelimiterString options:0 range:NSMakeRange([self scanLocation], searchLength)].location;
+ searchLength = [[self string] length] - quoteLocation;
+ while (([[[self string] substringWithRange:NSMakeRange((quoteLocation - 1), 2)] isEqualToString:jsonStringEscapedDoubleQuoteString]) &&
+ (quoteLocation != NSNotFound) &&
+ (![[[self string] substringWithRange:NSMakeRange((quoteLocation -2), 2)] isEqualToString:jsonStringEscapedSlashString])){
+ searchLength = [[self string] length] - (quoteLocation + 1);
+ quoteLocation = [[self string] rangeOfString:jsonStringDelimiterString options:0 range:NSMakeRange((quoteLocation + 1), searchLength)].location;
+ }
+
+ *string = [[self string] substringWithRange:NSMakeRange([self scanLocation], (quoteLocation - [self scanLocation]))];
+ // TODO: process escape sequences out of the string - replacing with their actual characters. a function that does just this belongs
+ // in another class. So it may make more sense to change this whole implementation to just go character by character instead.
+ [self setScanLocation:(quoteLocation + 1)];
+ */
+ result = YES;
+
+ }
+
+ return result;
+}
+
+- (BOOL)scanJSONValue:(id *)value
+{
+ BOOL result = NO;
+
+ [self scanJSONWhiteSpace];
+ NSString *substring = [[self string] substringWithRange:NSMakeRange([self scanLocation], 1)];
+ unsigned int trueLocation = [[self string] rangeOfString:jsonTrueString options:0 range:NSMakeRange([self scanLocation], ([[self string] length] - [self scanLocation]))].location;
+ unsigned int falseLocation = [[self string] rangeOfString:jsonFalseString options:0 range:NSMakeRange([self scanLocation], ([[self string] length] - [self scanLocation]))].location;
+ unsigned int nullLocation = [[self string] rangeOfString:jsonNullString options:0 range:NSMakeRange([self scanLocation], ([[self string] length] - [self scanLocation]))].location;
+
+ if ([substring isEqualToString:jsonStringDelimiterString]) {
+ result = [self scanJSONString:value];
+ } else if ([substring isEqualToString:jsonObjectStartString]) {
+ result = [self scanJSONObject:value];
+ } else if ([substring isEqualToString:jsonArrayStartString]) {
+ result = [self scanJSONArray:value];
+ } else if ([self scanLocation] == trueLocation) {
+ result = YES;
+ *value = [NSNumber numberWithBool:YES];
+ [self setScanLocation:([self scanLocation] + [jsonTrueString length])];
+ } else if ([self scanLocation] == falseLocation) {
+ result = YES;
+ *value = [NSNumber numberWithBool:NO];
+ [self setScanLocation:([self scanLocation] + [jsonFalseString length])];
+ } else if ([self scanLocation] == nullLocation) {
+ result = YES;
+ *value = [NSNull null];
+ [self setScanLocation:([self scanLocation] + [jsonNullString length])];
+ } else if (([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[[self string] characterAtIndex:[self scanLocation]]]) ||
+ ([[self string] characterAtIndex:[self scanLocation]] == '-')){ // check to make sure it's a digit or -
+ result = [self scanJSONNumber:value];
+ }
+ return result;
+}
+
+- (BOOL)scanJSONNumber:(NSNumber **)number
+{
+ NSDecimal decimal;
+ BOOL result = [self scanDecimal:&decimal];
+ *number = [NSDecimalNumber decimalNumberWithDecimal:decimal];
+ return result;
+}
+
+- (BOOL)scanJSONWhiteSpace
+{
+ //NSLog(@"Scanning white space - here are the next ten chars ---%@---", [[self string] substringWithRange:NSMakeRange([self scanLocation], 10)]);
+ BOOL result = NO;
+ NSCharacterSet *space = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+ while ([space characterIsMember:[[self string] characterAtIndex:[self scanLocation]]]) {
+ [self setScanLocation:([self scanLocation] + 1)];
+ result = YES;
+ }
+ //NSLog(@"Done Scanning white space - here are the next ten chars ---%@---", [[self string] substringWithRange:NSMakeRange([self scanLocation], 10)]);
+ return result;
+}
+
+- (BOOL)scanJSONKeyValueSeparator
+{
+ return [self scanString:jsonKeyValueSeparatorString intoString:nil];
+}
+
+- (BOOL)scanJSONValueSeparator
+{
+ return [self scanString:jsonValueSeparatorString intoString:nil];
+}
+
+- (BOOL)scanJSONObjectStartString
+{
+ return [self scanString:jsonObjectStartString intoString:nil];
+}
+
+- (BOOL)scanJSONObjectEndString
+{
+ return [self scanString:jsonObjectEndString intoString:nil];
+}
+
+- (BOOL)scanJSONArrayStartString
+{
+ return [self scanString:jsonArrayStartString intoString:nil];
+}
+
+- (BOOL)scanJSONArrayEndString
+{
+ return [self scanString:jsonArrayEndString intoString:nil];
+}
+
+- (BOOL)scanJSONStringDelimiterString;
+{
+ return [self scanString:jsonStringDelimiterString intoString:nil];
+}
+
+@end