diff --git a/ChangeLog b/ChangeLog index c0cf8e7b6..ef45ef7ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-12-13 Wolfgang Sourdeau + + * 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 * SoObjects/SOGo/NSString+Utilities.m ([NSString diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile index 889b653fd..c99c714e0 100644 --- a/SoObjects/SOGo/GNUmakefile +++ b/SoObjects/SOGo/GNUmakefile @@ -50,6 +50,9 @@ libSOGo_HEADER_FILES = \ SOGoMailer.h \ SOGoUser.h \ \ + NSDictionary+BSJSONAdditions.h \ + NSScanner+BSJSONAdditions.h \ + \ WORequest+SOGo.h libSOGo_OBJC_FILES = \ @@ -84,6 +87,9 @@ libSOGo_OBJC_FILES = \ SOGoMailer.m \ SOGoUser.m \ \ + NSDictionary+BSJSONAdditions.m \ + NSScanner+BSJSONAdditions.m \ + \ WORequest+SOGo.m # tools diff --git a/SoObjects/SOGo/NSDictionary+BSJSONAdditions.h b/SoObjects/SOGo/NSDictionary+BSJSONAdditions.h new file mode 100644 index 000000000..5cbfa1b05 --- /dev/null +++ b/SoObjects/SOGo/NSDictionary+BSJSONAdditions.h @@ -0,0 +1,45 @@ +// +// 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 + +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 diff --git a/SoObjects/SOGo/NSDictionary+BSJSONAdditions.m b/SoObjects/SOGo/NSDictionary+BSJSONAdditions.m new file mode 100644 index 000000000..1bc0e7530 --- /dev/null +++ b/SoObjects/SOGo/NSDictionary+BSJSONAdditions.m @@ -0,0 +1,198 @@ +// +// 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 +#import +#import +#import +#import + +#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 diff --git a/SoObjects/SOGo/NSScanner+BSJSONAdditions.h b/SoObjects/SOGo/NSScanner+BSJSONAdditions.h new file mode 100644 index 000000000..1505c9228 --- /dev/null +++ b/SoObjects/SOGo/NSScanner+BSJSONAdditions.h @@ -0,0 +1,64 @@ +// +// 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 + +@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 diff --git a/SoObjects/SOGo/NSScanner+BSJSONAdditions.m b/SoObjects/SOGo/NSScanner+BSJSONAdditions.m new file mode 100644 index 000000000..33bf5847b --- /dev/null +++ b/SoObjects/SOGo/NSScanner+BSJSONAdditions.m @@ -0,0 +1,312 @@ +// +// 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 +#import +#import +#import + +#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