diff options
29 files changed, 3232 insertions, 280 deletions
diff --git a/Classes/PicCastAppDelegate.m b/Classes/PicCastAppDelegate.m index f44c6eb..9e3b744 100644 --- a/Classes/PicCastAppDelegate.m +++ b/Classes/PicCastAppDelegate.m @@ -146,8 +146,8 @@ NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseName]; NSFileManager *fileManager = [NSFileManager defaultManager]; - - if(![fileManager fileExistsAtPath:databasePath]) { + // change this when you are ready to test persistence + if(true || ![fileManager fileExistsAtPath:databasePath]) { NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName]; [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil]; } diff --git a/Classes/Source/CDataScanner.h b/Classes/Source/CDataScanner.h new file mode 100644 index 0000000..41f68e8 --- /dev/null +++ b/Classes/Source/CDataScanner.h @@ -0,0 +1,71 @@ +// +// CDataScanner.h +// TouchCode +// +// Created by Jonathan Wight on 04/16/08. +// Copyright 2008 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import <Foundation/Foundation.h> + +// NSScanner + +@interface CDataScanner : NSObject { + NSData *data; + + u_int8_t *start; + u_int8_t *end; + u_int8_t *current; + NSUInteger length; +} + +@property (readwrite, nonatomic, retain) NSData *data; +@property (readwrite, nonatomic, assign) NSUInteger scanLocation; +@property (readonly, nonatomic, assign) NSUInteger bytesRemaining; +@property (readonly, nonatomic, assign) BOOL isAtEnd; + +- (id)initWithData:(NSData *)inData; + +- (unichar)currentCharacter; +- (unichar)scanCharacter; +- (BOOL)scanCharacter:(unichar)inCharacter; + +- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue; +- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue; +- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters + +- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)outValue; +- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters + +- (BOOL)scanNumber:(NSNumber **)outValue; +- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue; + +- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData; + +- (void)skipWhitespace; + +- (NSString *)remainingString; +- (NSData *)remainingData; + +@end diff --git a/Classes/Source/CDataScanner.m b/Classes/Source/CDataScanner.m new file mode 100644 index 0000000..b3cee6f --- /dev/null +++ b/Classes/Source/CDataScanner.m @@ -0,0 +1,340 @@ +// +// CDataScanner.m +// TouchCode +// +// Created by Jonathan Wight on 04/16/08. +// Copyright 2008 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CDataScanner.h" + +#import "CDataScanner_Extensions.h" + +@interface CDataScanner () +@end + +#pragma mark - + +inline static unichar CharacterAtPointer(void *start, void *end) + { + #pragma unused(end) + + const u_int8_t theByte = *(u_int8_t *)start; + if (theByte & 0x80) + { + // TODO -- UNICODE!!!! (well in theory nothing todo here) + } + const unichar theCharacter = theByte; + return(theCharacter); + } + + static NSCharacterSet *sDoubleCharacters = NULL; + + @implementation CDataScanner + +- (id)init + { + if ((self = [super init]) != NULL) + { + } + return(self); + } + +- (id)initWithData:(NSData *)inData; + { + if ((self = [self init]) != NULL) + { + [self setData:inData]; + } + return(self); + } + + + (void)initialize + { + if (sDoubleCharacters == NULL) + { + sDoubleCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-+."] retain]; + } + } + +- (void)dealloc + { + [data release]; + data = NULL; + // + [super dealloc]; + } + +- (NSUInteger)scanLocation + { + return(current - start); + } + +- (NSUInteger)bytesRemaining + { + return(end - current); + } + +- (NSData *)data + { + return(data); + } + +- (void)setData:(NSData *)inData + { + if (data != inData) + { + [data release]; + data = [inData retain]; + } + + if (data) + { + start = (u_int8_t *)data.bytes; + end = start + data.length; + current = start; + length = data.length; + } + else + { + start = NULL; + end = NULL; + current = NULL; + length = 0; + } + } + +- (void)setScanLocation:(NSUInteger)inScanLocation + { + current = start + inScanLocation; + } + +- (BOOL)isAtEnd + { + return(self.scanLocation >= length); + } + +- (unichar)currentCharacter + { + return(CharacterAtPointer(current, end)); + } + +#pragma mark - + +- (unichar)scanCharacter + { + const unichar theCharacter = CharacterAtPointer(current++, end); + return(theCharacter); + } + +- (BOOL)scanCharacter:(unichar)inCharacter + { + unichar theCharacter = CharacterAtPointer(current, end); + if (theCharacter == inCharacter) + { + ++current; + return(YES); + } + else + return(NO); + } + +- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue + { + const size_t theLength = strlen(inString); + if ((size_t)(end - current) < theLength) + return(NO); + if (strncmp((char *)current, inString, theLength) == 0) + { + current += theLength; + if (outValue) + *outValue = [NSString stringWithUTF8String:inString]; + return(YES); + } + return(NO); + } + +- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue + { + if ((size_t)(end - current) < inString.length) + return(NO); + if (strncmp((char *)current, [inString UTF8String], inString.length) == 0) + { + current += inString.length; + if (outValue) + *outValue = inString; + return(YES); + } + return(NO); + } + +- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue + { + u_int8_t *P; + for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P) + ; + + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = P; + + return(YES); + } + +- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue + { + const char *theToken = [inString UTF8String]; + const char *theResult = strnstr((char *)current, theToken, end - current); + if (theResult == NULL) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = (u_int8_t *)theResult; + + return(YES); + } + +- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue + { + u_int8_t *P; + for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P) + ; + + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = P; + + return(YES); + } + +- (BOOL)scanNumber:(NSNumber **)outValue + { + NSString *theString = NULL; + if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString]) + { + if ([theString rangeOfString:@"."].location != NSNotFound) + { + if (outValue) + { + *outValue = [NSDecimalNumber decimalNumberWithString:theString]; + } + return(YES); + } + else if ([theString rangeOfString:@"-"].location != NSNotFound) + { + if (outValue != NULL) + { + *outValue = [NSNumber numberWithLongLong:[theString longLongValue]]; + } + return(YES); + } + else + { + if (outValue != NULL) + { + *outValue = [NSNumber numberWithUnsignedLongLong:strtoull([theString UTF8String], NULL, 0)]; + } + return(YES); + } + + } + return(NO); + } + +- (BOOL)scanDecimalNumber:(NSDecimalNumber **)outValue; + { + NSString *theString = NULL; + if ([self scanCharactersFromSet:sDoubleCharacters intoString:&theString]) + { + if (outValue) + { + *outValue = [NSDecimalNumber decimalNumberWithString:theString]; + } + return(YES); + } + return(NO); + } + +- (BOOL)scanDataOfLength:(NSUInteger)inLength intoData:(NSData **)outData; + { + if (self.bytesRemaining < inLength) + { + return(NO); + } + + if (outData) + { + *outData = [NSData dataWithBytes:current length:inLength]; + } + + current += inLength; + return(YES); + } + + +- (void)skipWhitespace + { + u_int8_t *P; + for (P = current; P < end && (isspace(*P)); ++P) + ; + + current = P; + } + +- (NSString *)remainingString + { + NSData *theRemainingData = [NSData dataWithBytes:current length:end - current]; + NSString *theString = [[[NSString alloc] initWithData:theRemainingData encoding:NSUTF8StringEncoding] autorelease]; + return(theString); + } + +- (NSData *)remainingData; + { + NSData *theRemainingData = [NSData dataWithBytes:current length:end - current]; + return(theRemainingData); + } + + @end diff --git a/Classes/Source/Experimental/CFilteringJSONSerializer.h b/Classes/Source/Experimental/CFilteringJSONSerializer.h new file mode 100644 index 0000000..f004a79 --- /dev/null +++ b/Classes/Source/Experimental/CFilteringJSONSerializer.h @@ -0,0 +1,25 @@ +// +// CFilteringJSONSerializer.h +// CouchNotes +// +// Created by Jonathan Wight on 06/20/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import "CJSONSerializer.h" + +typedef NSString *(^JSONConversionTest)(id inObject); +typedef id (^JSONConversionConverter)(id inObject); // TODO replace with value transformers. + +@interface CFilteringJSONSerializer : CJSONSerializer { + NSSet *tests; + NSDictionary *convertersByName; +} + +@property (readwrite, nonatomic, retain) NSSet *tests; +@property (readwrite, nonatomic, retain) NSDictionary *convertersByName; + +- (void)addTest:(JSONConversionTest)inTest; +- (void)addConverter:(JSONConversionConverter)inConverter forName:(NSString *)inName; + +@end diff --git a/Classes/Source/Experimental/CFilteringJSONSerializer.m b/Classes/Source/Experimental/CFilteringJSONSerializer.m new file mode 100644 index 0000000..1ee2a3d --- /dev/null +++ b/Classes/Source/Experimental/CFilteringJSONSerializer.m @@ -0,0 +1,87 @@ +// +// CFilteringJSONSerializer.m +// CouchNotes +// +// Created by Jonathan Wight on 06/20/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import "CFilteringJSONSerializer.h" + +@implementation CFilteringJSONSerializer + +@synthesize tests; +@synthesize convertersByName; + +- (void)dealloc + { + [tests release]; + tests = NULL; + // + [convertersByName release]; + convertersByName = NULL; + // + [super dealloc]; + } + +- (NSData *)serializeObject:(id)inObject error:(NSError **)outError + { + NSData *theData = NULL; + for (JSONConversionTest theTest in self.tests) + { + NSString *theName = theTest(inObject); + if (theName != NULL) + { + id theObject = NULL; + JSONConversionConverter theConverter = [self.convertersByName objectForKey:theName]; + if (theConverter) + { + theObject = theConverter(inObject); + } + + if (theObject) + { + if ([theObject isKindOfClass:[NSData class]]) + { + theData = theObject; + break; + } + else + { + NSError *theError = NULL; + theData = [super serializeObject:theObject error:&theError]; + if (theData != NULL) + { + break; + } + } + } + } + } + + if (theData == NULL) + { + theData = [super serializeObject:inObject error:outError]; + } + + return(theData); + } + +- (void)addTest:(JSONConversionTest)inTest + { + inTest = [[inTest copy] autorelease]; + NSSet *theTests = [self.tests setByAddingObject:inTest]; + self.tests = theTests; + } + +- (void)addConverter:(JSONConversionConverter)inConverter forName:(NSString *)inName + { + NSMutableDictionary *theConvertersByName = [[self.convertersByName mutableCopy] autorelease]; + + inConverter = [[inConverter copy] autorelease]; + [theConvertersByName setObject:inConverter forKey:inName]; + self.convertersByName = theConvertersByName; + } + + +@end diff --git a/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.h b/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.h new file mode 100644 index 0000000..17631af --- /dev/null +++ b/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.h @@ -0,0 +1,16 @@ +// +// CJSONDeserializer_BlocksExtensions.h +// TouchJSON +// +// Created by Jonathan Wight on 10/15/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import "CJSONDeserializer.h" + +@interface CJSONDeserializer (CJSONDeserializer_BlocksExtensions) + +- (void)deserializeAsDictionary:(NSData *)inData completionBlock:(void (^)(id result, NSError *error))block; +- (void)deserializeAsArray:(NSData *)inData completionBlock:(void (^)(id result, NSError *error))block; + +@end diff --git a/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.m b/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.m new file mode 100644 index 0000000..7ea774c --- /dev/null +++ b/Classes/Source/Experimental/CJSONDeserializer_BlocksExtensions.m @@ -0,0 +1,63 @@ +// +// CJSONDeserializer_BlocksExtensions.m +// TouchJSON +// +// Created by Jonathan Wight on 10/15/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import "CJSONDeserializer_BlocksExtensions.h" + +#import "CJSONScanner.h" + +@implementation CJSONDeserializer (CJSONDeserializer_BlocksExtensions) + +- (void)deserializeAsDictionary:(NSData *)inData completionBlock:(void (^)(id result, NSError *error))block { + + NSError *noDataError = nil; + if (inData == NULL || [inData length] == 0) { + noDataError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + block(nil, noDataError); + } + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + + NSError *deserializationError = nil; + self.scanner.data = inData; + NSDictionary *theDictionary = NULL; + BOOL successful = [self.scanner scanJSONDictionary:&theDictionary error:&deserializationError]; + + dispatch_async(dispatch_get_main_queue (), ^{ + if (successful) + block(theDictionary, nil); + else + block(nil, deserializationError); + }); + }]; +} + +- (void)deserializeAsArray:(NSData *)inData completionBlock:(void (^)(id result, NSError *error))block { + + NSError *nullInDataError = nil; + if (inData == NULL || [inData length] == 0) { + nullInDataError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + block(nil, nullInDataError); + } + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + + NSError *deserializationError = nil; + self.scanner.data = inData; + NSArray *theArray = NULL; + BOOL successful = [self.scanner scanJSONArray:&theArray error:&deserializationError]; + + dispatch_async(dispatch_get_main_queue(), ^{ + if (successful) + block(theArray, nil); + else + block(nil, deserializationError); + }); + }]; +} + +@end diff --git a/Classes/Source/Experimental/CJSONSerialization.h b/Classes/Source/Experimental/CJSONSerialization.h new file mode 100644 index 0000000..83c9bb2 --- /dev/null +++ b/Classes/Source/Experimental/CJSONSerialization.h @@ -0,0 +1,34 @@ +// +// CJSONSerialization.h +// TouchJSON +// +// Created by Jonathan Wight on 03/04/11. +// Copyright 2011 toxicsoftware.com. All rights reserved. +// + +#import <Foundation/Foundation.h> + +enum { + kCJSONReadingMutableContainers = 0x1, + kCJSONReadingMutableLeaves = 0x2, + kCJSONReadingAllowFragments = 0x04, +}; +typedef NSUInteger EJSONReadingOptions; + +enum { + kCJJSONWritingPrettyPrinted = 0x1 +}; +typedef NSUInteger EJSONWritingOptions; + + +@interface CJSONSerialization : NSObject { + +} + ++ (BOOL)isValidJSONObject:(id)obj; ++ (NSData *)dataWithJSONObject:(id)obj options:(EJSONWritingOptions)opt error:(NSError **)error; ++ (id)JSONObjectWithData:(NSData *)data options:(EJSONReadingOptions)opt error:(NSError **)error; ++ (NSInteger)writeJSONObject:(id)obj toStream:(NSOutputStream *)stream options:(EJSONWritingOptions)opt error:(NSError **)error; ++ (id)JSONObjectWithStream:(NSInputStream *)stream options:(EJSONReadingOptions)opt error:(NSError **)error; + +@end diff --git a/Classes/Source/Experimental/CJSONSerialization.m b/Classes/Source/Experimental/CJSONSerialization.m new file mode 100644 index 0000000..5f603f6 --- /dev/null +++ b/Classes/Source/Experimental/CJSONSerialization.m @@ -0,0 +1,59 @@ +// +// CJSONSerialization.m +// TouchJSON +// +// Created by Jonathan Wight on 03/04/11. +// Copyright 2011 toxicsoftware.com. All rights reserved. +// + +#import "CJSONSerialization.h" + +#import "CJSONDeserializer.h" +#import "CJSONSerializer.h" + +@implementation CJSONSerialization + ++ (BOOL)isValidJSONObject:(id)obj + { + CJSONSerializer *theSerializer = [CJSONSerializer serializer]; + return([theSerializer isValidJSONObject:obj]); + } + ++ (NSData *)dataWithJSONObject:(id)obj options:(EJSONWritingOptions)opt error:(NSError **)error + { + #pragma unused (opt) + + CJSONSerializer *theSerializer = [CJSONSerializer serializer]; + NSData *theData = [theSerializer serializeObject:obj error:error]; + return(theData); + } + ++ (id)JSONObjectWithData:(NSData *)data options:(EJSONReadingOptions)opt error:(NSError **)error + { + CJSONDeserializer *theDeserializer = [CJSONDeserializer deserializer]; + theDeserializer.options = (opt & kCJSONReadingMutableContainers ? 0 : kJSONDeserializationOptions_MutableContainers) + | (opt & kCJSONReadingMutableLeaves ? 0 : kJSONDeserializationOptions_MutableLeaves); + id theObject = [theDeserializer deserialize:data error:error]; + return(theObject); + } + ++ (NSInteger)writeJSONObject:(id)obj toStream:(NSOutputStream *)stream options:(EJSONWritingOptions)opt error:(NSError **)error + { + // TODO -- this is a quick work around. + NSInteger theSize = -1; + NSData *theData = [self dataWithJSONObject:obj options:opt error:error]; + if (theData) + { + theSize = [stream write:[theData bytes] maxLength:[theData length]]; + } + return(theSize); + } + ++ (id)JSONObjectWithStream:(NSInputStream *)stream options:(EJSONReadingOptions)opt error:(NSError **)error + { + #pragma unused (stream, opt, error) + // TODO -- how much to read? Ugh. + return(NULL); + } + +@end diff --git a/Classes/Source/Experimental/CJSONSerializedData.h b/Classes/Source/Experimental/CJSONSerializedData.h new file mode 100644 index 0000000..4bba1be --- /dev/null +++ b/Classes/Source/Experimental/CJSONSerializedData.h @@ -0,0 +1,25 @@ +// +// CJSONSerializedData.h +// TouchMetricsTest +// +// Created by Jonathan Wight on 10/31/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import <Foundation/Foundation.h> + +@protocol CJSONSerializable <NSObject> +@property (readonly, nonatomic, retain) NSData *serializedJSONData; +@end + +#pragma mark - + +@interface CJSONSerializedData : NSObject <CJSONSerializable> { + NSData *data; +} + +@property (readonly, nonatomic, retain) NSData *data; + +- (id)initWithData:(NSData *)inData; + +@end diff --git a/Classes/Source/Experimental/CJSONSerializedData.m b/Classes/Source/Experimental/CJSONSerializedData.m new file mode 100644 index 0000000..881899d --- /dev/null +++ b/Classes/Source/Experimental/CJSONSerializedData.m @@ -0,0 +1,42 @@ +// +// CJSONSerializedData.m +// TouchMetricsTest +// +// Created by Jonathan Wight on 10/31/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import "CJSONSerializedData.h" + +@interface CJSONSerializedData () +@end + +#pragma mark - + +@implementation CJSONSerializedData + +@synthesize data; + +- (id)initWithData:(NSData *)inData + { + if ((self = [super init]) != NULL) + { + data = [inData retain]; + } + return(self); + } + +- (void)dealloc + { + [data release]; + data = NULL; + // + [super dealloc]; + } + +- (NSData *)serializedJSONData + { + return(self.data); + } + +@end diff --git a/Classes/Source/Extensions/CDataScanner_Extensions.h b/Classes/Source/Extensions/CDataScanner_Extensions.h new file mode 100644 index 0000000..cde1dbb --- /dev/null +++ b/Classes/Source/Extensions/CDataScanner_Extensions.h @@ -0,0 +1,40 @@ +// +// CDataScanner_Extensions.h +// TouchCode +// +// Created by Jonathan Wight on 12/08/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CDataScanner.h" + +@interface CDataScanner (CDataScanner_Extensions) + +- (BOOL)scanCStyleComment:(NSString **)outComment; +- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment; + +- (NSUInteger)lineOfScanLocation; +- (NSDictionary *)userInfoForScanLocation; + +@end diff --git a/Classes/Source/Extensions/CDataScanner_Extensions.m b/Classes/Source/Extensions/CDataScanner_Extensions.m new file mode 100644 index 0000000..90dbbda --- /dev/null +++ b/Classes/Source/Extensions/CDataScanner_Extensions.m @@ -0,0 +1,135 @@ +// +// CDataScanner_Extensions.m +// TouchCode +// +// Created by Jonathan Wight on 12/08/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CDataScanner_Extensions.h" + +#define LF 0x000a // Line Feed +#define FF 0x000c // Form Feed +#define CR 0x000d // Carriage Return +#define NEL 0x0085 // Next Line +#define LS 0x2028 // Line Separator +#define PS 0x2029 // Paragraph Separator + +@implementation CDataScanner (CDataScanner_Extensions) + +- (BOOL)scanCStyleComment:(NSString **)outComment +{ +if ([self scanString:@"/*" intoString:NULL] == YES) + { + NSString *theComment = NULL; + if ([self scanUpToString:@"*/" intoString:&theComment] == NO) + [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."]; + + if ([theComment rangeOfString:@"/*"].location != NSNotFound) + [NSException raise:NSGenericException format:@"C style comments should not be nested."]; + + if ([self scanString:@"*/" intoString:NULL] == NO) + [NSException raise:NSGenericException format:@"C style comment did not end correctly."]; + + if (outComment != NULL) + *outComment = theComment; + + return(YES); + } +else + { + return(NO); + } +} + +- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment + { + if ([self scanString:@"//" intoString:NULL] == YES) + { + unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, }; + NSCharacterSet *theLineBreaksCharacterSet = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]]; + + NSString *theComment = NULL; + [self scanUpToCharactersFromSet:theLineBreaksCharacterSet intoString:&theComment]; + [self scanCharactersFromSet:theLineBreaksCharacterSet intoString:NULL]; + + if (outComment != NULL) + *outComment = theComment; + + return(YES); + } + else + { + return(NO); + } + } + +- (NSUInteger)lineOfScanLocation + { + NSUInteger theLine = 0; + for (const u_int8_t *C = start; C < current; ++C) + { + // TODO: JIW What about MS-DOS line endings you bastard! (Also other unicode line endings) + if (*C == '\n' || *C == '\r') + { + ++theLine; + } + } + return(theLine); + } + +- (NSDictionary *)userInfoForScanLocation + { + NSUInteger theLine = 0; + const u_int8_t *theLineStart = start; + for (const u_int8_t *C = start; C < current; ++C) + { + if (*C == '\n' || *C == '\r') + { + theLineStart = C - 1; + ++theLine; + } + } + + NSUInteger theCharacter = current - theLineStart; + + NSRange theStartRange = NSIntersectionRange((NSRange){ .location = MAX((NSInteger)self.scanLocation - 20, 0), .length = 20 + (NSInteger)self.scanLocation - 20 }, (NSRange){ .location = 0, .length = self.data.length }); + NSRange theEndRange = NSIntersectionRange((NSRange){ .location = self.scanLocation, .length = 20 }, (NSRange){ .location = 0, .length = self.data.length }); + + + NSString *theSnippet = [NSString stringWithFormat:@"%@!HERE>!%@", + [[[NSString alloc] initWithData:[self.data subdataWithRange:theStartRange] encoding:NSUTF8StringEncoding] autorelease], + [[[NSString alloc] initWithData:[self.data subdataWithRange:theEndRange] encoding:NSUTF8StringEncoding] autorelease] + ]; + + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedInteger:theLine], @"line", + [NSNumber numberWithUnsignedInteger:theCharacter], @"character", + [NSNumber numberWithUnsignedInteger:self.scanLocation], @"location", + theSnippet, @"snippet", + NULL]; + return(theUserInfo); + } + +@end diff --git a/Classes/Source/Extensions/NSDictionary_JSONExtensions.h b/Classes/Source/Extensions/NSDictionary_JSONExtensions.h new file mode 100644 index 0000000..6e611d0 --- /dev/null +++ b/Classes/Source/Extensions/NSDictionary_JSONExtensions.h @@ -0,0 +1,37 @@ +// +// NSDictionary_JSONExtensions.h +// TouchCode +// +// Created by Jonathan Wight on 04/17/08. +// Copyright 2008 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import <Foundation/Foundation.h> + +@interface NSDictionary (NSDictionary_JSONExtensions) + ++ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError; ++ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError; + +@end diff --git a/Classes/Source/Extensions/NSDictionary_JSONExtensions.m b/Classes/Source/Extensions/NSDictionary_JSONExtensions.m new file mode 100644 index 0000000..c0bb43c --- /dev/null +++ b/Classes/Source/Extensions/NSDictionary_JSONExtensions.m @@ -0,0 +1,47 @@ +// +// NSDictionary_JSONExtensions.m +// TouchCode +// +// Created by Jonathan Wight on 04/17/08. +// Copyright 2008 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "NSDictionary_JSONExtensions.h" + +#import "CJSONDeserializer.h" + +@implementation NSDictionary (NSDictionary_JSONExtensions) + ++ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError + { + return([[CJSONDeserializer deserializer] deserialize:inData error:outError]); + } + ++ (id)dictionaryWithJSONString:(NSString *)inJSON error:(NSError **)outError; + { + NSData *theData = [inJSON dataUsingEncoding:NSUTF8StringEncoding]; + return([self dictionaryWithJSONData:theData error:outError]); + } + +@end diff --git a/Classes/Source/JSON/CJSONDeserializer.h b/Classes/Source/JSON/CJSONDeserializer.h new file mode 100644 index 0000000..0c3ed02 --- /dev/null +++ b/Classes/Source/JSON/CJSONDeserializer.h @@ -0,0 +1,63 @@ +// +// CJSONDeserializer.h +// TouchCode +// +// Created by Jonathan Wight on 12/15/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import <Foundation/Foundation.h> + +#import "CJSONScanner.h" + +extern NSString *const kJSONDeserializerErrorDomain /* = @"CJSONDeserializerErrorDomain" */; + +enum { + kJSONDeserializationOptions_MutableContainers = kJSONScannerOptions_MutableContainers, + kJSONDeserializationOptions_MutableLeaves = kJSONScannerOptions_MutableLeaves, +}; +typedef NSUInteger EJSONDeserializationOptions; + +@class CJSONScanner; + +@interface CJSONDeserializer : NSObject { + CJSONScanner *scanner; + EJSONDeserializationOptions options; +} + +@property (readwrite, nonatomic, retain) CJSONScanner *scanner; +/// Object to return instead when a null encountered in the JSON. Defaults to NSNull. Setting to null causes the scanner to skip null values. +@property (readwrite, nonatomic, retain) id nullObject; +/// JSON must be encoded in Unicode (UTF-8, UTF-16 or UTF-32). Use this if you expect to get the JSON in another encoding. +@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding; +@property (readwrite, nonatomic, assign) EJSONDeserializationOptions options; + ++ (id)deserializer; + +- (id)deserialize:(NSData *)inData error:(NSError **)outError; + +- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError; +- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError; + +@end diff --git a/Classes/Source/JSON/CJSONDeserializer.m b/Classes/Source/JSON/CJSONDeserializer.m new file mode 100644 index 0000000..27a2d03 --- /dev/null +++ b/Classes/Source/JSON/CJSONDeserializer.m @@ -0,0 +1,161 @@ +// +// CJSONDeserializer.m +// TouchCode +// +// Created by Jonathan Wight on 12/15/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CJSONDeserializer.h" + +#import "CJSONScanner.h" +#import "CDataScanner.h" + +NSString *const kJSONDeserializerErrorDomain = @"CJSONDeserializerErrorDomain"; + +@interface CJSONDeserializer () +@end + +@implementation CJSONDeserializer + +@synthesize scanner; +@synthesize options; + ++ (id)deserializer + { + return([[[self alloc] init] autorelease]); + } + +- (id)init + { + if ((self = [super init]) != NULL) + { + } + return(self); + } + +- (void)dealloc + { + [scanner release]; + scanner = NULL; + // + [super dealloc]; + } + +#pragma mark - + +- (CJSONScanner *)scanner + { + if (scanner == NULL) + { + scanner = [[CJSONScanner alloc] init]; + } + return(scanner); + } + +- (id)nullObject + { + return(self.scanner.nullObject); + } + +- (void)setNullObject:(id)inNullObject + { + self.scanner.nullObject = inNullObject; + } + +#pragma mark - + +- (NSStringEncoding)allowedEncoding + { + return(self.scanner.allowedEncoding); + } + +- (void)setAllowedEncoding:(NSStringEncoding)inAllowedEncoding + { + self.scanner.allowedEncoding = inAllowedEncoding; + } + +#pragma mark - + +- (id)deserialize:(NSData *)inData error:(NSError **)outError + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + id theObject = NULL; + if ([self.scanner scanJSONObject:&theObject error:outError] == YES) + return(theObject); + else + return(NULL); + } + +- (id)deserializeAsDictionary:(NSData *)inData error:(NSError **)outError + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + NSDictionary *theDictionary = NULL; + if ([self.scanner scanJSONDictionary:&theDictionary error:outError] == YES) + return(theDictionary); + else + return(NULL); + } + +- (id)deserializeAsArray:(NSData *)inData error:(NSError **)outError + { + if (inData == NULL || [inData length] == 0) + { + if (outError) + *outError = [NSError errorWithDomain:kJSONDeserializerErrorDomain code:kJSONScannerErrorCode_NothingToScan userInfo:NULL]; + + return(NULL); + } + if ([self.scanner setData:inData error:outError] == NO) + { + return(NULL); + } + NSArray *theArray = NULL; + if ([self.scanner scanJSONArray:&theArray error:outError] == YES) + return(theArray); + else + return(NULL); + } + +@end diff --git a/Classes/Source/JSON/CJSONScanner.h b/Classes/Source/JSON/CJSONScanner.h new file mode 100644 index 0000000..d410893 --- /dev/null +++ b/Classes/Source/JSON/CJSONScanner.h @@ -0,0 +1,95 @@ +// +// CJSONScanner.h +// TouchCode +// +// Created by Jonathan Wight on 12/07/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CDataScanner.h" + +enum { + kJSONScannerOptions_MutableContainers = 0x1, + kJSONScannerOptions_MutableLeaves = 0x2, +}; +typedef NSUInteger EJSONScannerOptions; + +/// CDataScanner subclass that understands JSON syntax natively. You should generally use CJSONDeserializer instead of this class. (TODO - this could have been a category?) +@interface CJSONScanner : CDataScanner { + BOOL strictEscapeCodes; + id nullObject; + NSStringEncoding allowedEncoding; + EJSONScannerOptions options; +} + +@property (readwrite, nonatomic, assign) BOOL strictEscapeCodes; +@property (readwrite, nonatomic, retain) id nullObject; +@property (readwrite, nonatomic, assign) NSStringEncoding allowedEncoding; +@property (readwrite, nonatomic, assign) EJSONScannerOptions options; + +- (BOOL)setData:(NSData *)inData error:(NSError **)outError; + +- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError; +- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError; +- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError; +- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError; +- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError; + +@end + +extern NSString *const kJSONScannerErrorDomain /* = @"kJSONScannerErrorDomain" */; + +typedef enum { + + // Fundamental scanning errors + kJSONScannerErrorCode_NothingToScan = -11, + kJSONScannerErrorCode_CouldNotDecodeData = -12, + kJSONScannerErrorCode_CouldNotSerializeData = -13, + kJSONScannerErrorCode_CouldNotSerializeObject = -14, + kJSONScannerErrorCode_CouldNotScanObject = -15, + + // Dictionary scanning + kJSONScannerErrorCode_DictionaryStartCharacterMissing = -101, + kJSONScannerErrorCode_DictionaryKeyScanFailed = -102, + kJSONScannerErrorCode_DictionaryKeyNotTerminated = -103, + kJSONScannerErrorCode_DictionaryValueScanFailed = -104, + kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter = -105, + kJSONScannerErrorCode_DictionaryNotTerminated = -106, + + // Array scanning + kJSONScannerErrorCode_ArrayStartCharacterMissing = -201, + kJSONScannerErrorCode_ArrayValueScanFailed = -202, + kJSONScannerErrorCode_ArrayValueIsNull = -203, + kJSONScannerErrorCode_ArrayNotTerminated = -204, + + // String scanning + kJSONScannerErrorCode_StringNotStartedWithBackslash = -301, + kJSONScannerErrorCode_StringUnicodeNotDecoded = -302, + kJSONScannerErrorCode_StringUnknownEscapeCode = -303, + kJSONScannerErrorCode_StringNotTerminated = -304, + + // Number scanning + kJSONScannerErrorCode_NumberNotScannable = -401 + +} EJSONScannerErrorCode; diff --git a/Classes/Source/JSON/CJSONScanner.m b/Classes/Source/JSON/CJSONScanner.m new file mode 100644 index 0000000..c5ffeb4 --- /dev/null +++ b/Classes/Source/JSON/CJSONScanner.m @@ -0,0 +1,676 @@ +// +// CJSONScanner.m +// TouchCode +// +// Created by Jonathan Wight on 12/07/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CJSONScanner.h" + +#import "CDataScanner_Extensions.h" + +#if !defined(TREAT_COMMENTS_AS_WHITESPACE) +#define TREAT_COMMENTS_AS_WHITESPACE 0 +#endif // !defined(TREAT_COMMENTS_AS_WHITESPACE) + +NSString *const kJSONScannerErrorDomain = @"kJSONScannerErrorDomain"; + +inline static int HexToInt(char inCharacter) + { + int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, }; + if (inCharacter >= '0' && inCharacter <= 'f') + return(theValues[inCharacter - '0']); + else + return(-1); + } + +@interface CJSONScanner () +- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue; +@end + +#pragma mark - + +@implementation CJSONScanner + +@synthesize strictEscapeCodes; +@synthesize nullObject; +@synthesize allowedEncoding; +@synthesize options; + +- (id)init + { + if ((self = [super init]) != NULL) + { + strictEscapeCodes = NO; + nullObject = [[NSNull null] retain]; + } + return(self); + } + +- (void)dealloc + { + [nullObject release]; + nullObject = NULL; + // + [super dealloc]; + } + +#pragma mark - + +- (BOOL)setData:(NSData *)inData error:(NSError **)outError; + { + NSData *theData = inData; + if (theData && theData.length >= 4) + { + // This code is lame, but it works. Because the first character of any JSON string will always be a (ascii) control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt + const char *theChars = theData.bytes; + NSStringEncoding theEncoding = NSUTF8StringEncoding; + if (theChars[0] != 0 && theChars[1] == 0) + { + if (theChars[2] != 0 && theChars[3] == 0) + theEncoding = NSUTF16LittleEndianStringEncoding; + else if (theChars[2] == 0 && theChars[3] == 0) + theEncoding = NSUTF32LittleEndianStringEncoding; + } + else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0) + { + if (theChars[1] == 0) + theEncoding = NSUTF32BigEndianStringEncoding; + else if (theChars[1] != 0) + theEncoding = NSUTF16BigEndianStringEncoding; + } + + NSString *theString = [[NSString alloc] initWithData:theData encoding:theEncoding]; + if (theString == NULL && self.allowedEncoding != 0) + { + theString = [[NSString alloc] initWithData:theData encoding:self.allowedEncoding]; + } + theData = [theString dataUsingEncoding:NSUTF8StringEncoding]; + [theString release]; + } + + if (theData) + { + [super setData:theData]; + return(YES); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan data. Data wasn't encoded properly?", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotDecodeData userInfo:theUserInfo]; + } + return(NO); + } + } + +- (void)setData:(NSData *)inData + { + [self setData:inData error:NULL]; + } + +#pragma mark - + +- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError + { + BOOL theResult = YES; + + [self skipWhitespace]; + + id theObject = NULL; + + const unichar C = [self currentCharacter]; + switch (C) + { + case 't': + if ([self scanUTF8String:"true" intoString:NULL]) + { + theObject = [NSNumber numberWithBool:YES]; + } + break; + case 'f': + if ([self scanUTF8String:"false" intoString:NULL]) + { + theObject = [NSNumber numberWithBool:NO]; + } + break; + case 'n': + if ([self scanUTF8String:"null" intoString:NULL]) + { + theObject = self.nullObject; + } + break; + case '\"': + case '\'': + theResult = [self scanJSONStringConstant:&theObject error:outError]; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + theResult = [self scanJSONNumberConstant:&theObject error:outError]; + break; + case '{': + theResult = [self scanJSONDictionary:&theObject error:outError]; + break; + case '[': + theResult = [self scanJSONArray:&theObject error:outError]; + break; + default: + theResult = NO; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan object. Character not a valid JSON character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_CouldNotScanObject userInfo:theUserInfo]; + } + break; + } + + if (outObject != NULL) + *outObject = theObject; + + return(theResult); + } + +- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + if ([self scanCharacter:'{'] == NO) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Dictionary that does not start with '{' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryStartCharacterMissing userInfo:theUserInfo]; + } + return(NO); + } + + NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init]; + + while ([self currentCharacter] != '}') + { + [self skipWhitespace]; + + if ([self currentCharacter] == '}') + break; + + NSString *theKey = NULL; + if ([self scanJSONStringConstant:&theKey error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Failed to scan a key.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyScanFailed userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + [self skipWhitespace]; + + if ([self scanCharacter:':'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Key was not terminated with a ':' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyNotTerminated userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + id theValue = NULL; + if ([self scanJSONObject:&theValue error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Failed to scan a value.", NSLocalizedDescriptionKey, + NULL]; + + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryValueScanFailed userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + if (theValue == NULL && self.nullObject == NULL) + { + // If the value is a null and nullObject is also null then we're skipping this key/value pair. + } + else + { + [theDictionary setValue:theValue forKey:theKey]; + } + + [self skipWhitespace]; + if ([self scanCharacter:','] == NO) + { + if ([self currentCharacter] != '}') + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Key value pairs not delimited with a ',' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryKeyValuePairNoDelimiter userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + break; + } + else + { + [self skipWhitespace]; + if ([self currentCharacter] == '}') + break; + } + } + + if ([self scanCharacter:'}'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan dictionary. Dictionary not terminated by a '}' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_DictionaryNotTerminated userInfo:theUserInfo]; + } + [theDictionary release]; + return(NO); + } + + if (outDictionary != NULL) + { + if (self.options & kJSONScannerOptions_MutableContainers) + { + *outDictionary = [theDictionary autorelease]; + } + else + { + *outDictionary = [[theDictionary copy] autorelease]; + [theDictionary release]; + } + } + else + { + [theDictionary release]; + } + + return(YES); + } + +- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + if ([self scanCharacter:'['] == NO) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not started by a '[' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayStartCharacterMissing userInfo:theUserInfo]; + } + return(NO); + } + + NSMutableArray *theArray = [[NSMutableArray alloc] init]; + + [self skipWhitespace]; + while ([self currentCharacter] != ']') + { + NSString *theValue = NULL; + if ([self scanJSONObject:&theValue error:outError] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Could not scan a value.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueScanFailed userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + if (theValue == NULL) + { + if (self.nullObject != NULL) + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Value is NULL.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayValueIsNull userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + } + else + { + [theArray addObject:theValue]; + } + + [self skipWhitespace]; + if ([self scanCharacter:','] == NO) + { + [self skipWhitespace]; + if ([self currentCharacter] != ']') + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + break; + } + [self skipWhitespace]; + } + + [self skipWhitespace]; + + if ([self scanCharacter:']'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan array. Array not terminated by a ']' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_ArrayNotTerminated userInfo:theUserInfo]; + } + [theArray release]; + return(NO); + } + + if (outArray != NULL) + { + if (self.options & kJSONScannerOptions_MutableContainers) + { + *outArray = [theArray autorelease]; + } + else + { + *outArray = [[theArray copy] autorelease]; + [theArray release]; + } + } + else + { + [theArray release]; + } + return(YES); + } + +- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError + { + NSUInteger theScanLocation = [self scanLocation]; + + [self skipWhitespace]; + + NSMutableString *theString = [[NSMutableString alloc] init]; + + if ([self scanCharacter:'"'] == NO) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. String not started by a '\"' character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotStartedWithBackslash userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + + while ([self scanCharacter:'"'] == NO) + { + NSString *theStringChunk = NULL; + if ([self scanNotQuoteCharactersIntoString:&theStringChunk]) + { + CFStringAppend((CFMutableStringRef)theString, (CFStringRef)theStringChunk); + } + else if ([self scanCharacter:'\\'] == YES) + { + unichar theCharacter = [self scanCharacter]; + switch (theCharacter) + { + case '"': + case '\\': + case '/': + break; + case 'b': + theCharacter = '\b'; + break; + case 'f': + theCharacter = '\f'; + break; + case 'n': + theCharacter = '\n'; + break; + case 'r': + theCharacter = '\r'; + break; + case 't': + theCharacter = '\t'; + break; + case 'u': + { + theCharacter = 0; + + int theShift; + for (theShift = 12; theShift >= 0; theShift -= 4) + { + const int theDigit = HexToInt([self scanCharacter]); + if (theDigit == -1) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. Unicode character could not be decoded.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnicodeNotDecoded userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + theCharacter |= (theDigit << theShift); + } + } + break; + default: + { + if (strictEscapeCodes == YES) + { + [self setScanLocation:theScanLocation]; + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. Unknown escape code.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringUnknownEscapeCode userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + } + break; + } + CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan string constant. No terminating double quote character.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_StringNotTerminated userInfo:theUserInfo]; + } + [theString release]; + return(NO); + } + } + + if (outStringConstant != NULL) + { + if (self.options & kJSONScannerOptions_MutableLeaves) + { + *outStringConstant = [theString autorelease]; + } + else + { + *outStringConstant = [[theString copy] autorelease]; + [theString release]; + } + } + else + { + [theString release]; + } + + return(YES); + } + +- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError + { + NSNumber *theNumber = NULL; + + [self skipWhitespace]; + + if ([self scanNumber:&theNumber] == YES) + { + if (outNumberConstant != NULL) + *outNumberConstant = theNumber; + return(YES); + } + else + { + if (outError) + { + NSMutableDictionary *theUserInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: + @"Could not scan number constant.", NSLocalizedDescriptionKey, + NULL]; + [theUserInfo addEntriesFromDictionary:self.userInfoForScanLocation]; + *outError = [NSError errorWithDomain:kJSONScannerErrorDomain code:kJSONScannerErrorCode_NumberNotScannable userInfo:theUserInfo]; + } + return(NO); + } + } + +#if TREAT_COMMENTS_AS_WHITESPACE +- (void)skipWhitespace + { + [super skipWhitespace]; + [self scanCStyleComment:NULL]; + [self scanCPlusPlusStyleComment:NULL]; + [super skipWhitespace]; + } +#endif // TREAT_COMMENTS_AS_WHITESPACE + +#pragma mark - + +- (BOOL)scanNotQuoteCharactersIntoString:(NSString **)outValue + { + u_int8_t *P; + for (P = current; P < end && *P != '\"' && *P != '\\'; ++P) + ; + + if (P == current) + { + return(NO); + } + + if (outValue) + { + *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease]; + } + + current = P; + + return(YES); + } + +@end diff --git a/Classes/Source/JSON/CJSONSerializer.h b/Classes/Source/JSON/CJSONSerializer.h new file mode 100644 index 0000000..748a85c --- /dev/null +++ b/Classes/Source/JSON/CJSONSerializer.h @@ -0,0 +1,53 @@ +// +// CJSONSerializer.h +// TouchCode +// +// Created by Jonathan Wight on 12/07/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import <Foundation/Foundation.h> + +@interface CJSONSerializer : NSObject { +} + ++ (id)serializer; + +- (BOOL)isValidJSONObject:(id)inObject; + +/// Take any JSON compatible object (generally NSNull, NSNumber, NSString, NSArray and NSDictionary) and produce an NSData containing the serialized JSON. +- (NSData *)serializeObject:(id)inObject error:(NSError **)outError; + +- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError; +- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError; +- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError; +- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError; +- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError; + +@end + +typedef enum { + CJSONSerializerErrorCouldNotSerializeDataType = -1, + CJSONSerializerErrorCouldNotSerializeObject = -1 +} CJSONSerializerError; diff --git a/Classes/Source/JSON/CJSONSerializer.m b/Classes/Source/JSON/CJSONSerializer.m new file mode 100644 index 0000000..952b3c2 --- /dev/null +++ b/Classes/Source/JSON/CJSONSerializer.m @@ -0,0 +1,342 @@ +// +// CJSONSerializer.m +// TouchCode +// +// Created by Jonathan Wight on 12/07/2005. +// Copyright 2005 toxicsoftware.com. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import "CJSONSerializer.h" + +#import "JSONRepresentation.h" + +static NSData *kNULL = NULL; +static NSData *kFalse = NULL; +static NSData *kTrue = NULL; + +@implementation CJSONSerializer + ++ (void)initialize + { + NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init]; + + if (self == [CJSONSerializer class]) + { + if (kNULL == NULL) + kNULL = [[NSData alloc] initWithBytesNoCopy:(void *)"null" length:4 freeWhenDone:NO]; + if (kFalse == NULL) + kFalse = [[NSData alloc] initWithBytesNoCopy:(void *)"false" length:5 freeWhenDone:NO]; + if (kTrue == NULL) + kTrue = [[NSData alloc] initWithBytesNoCopy:(void *)"true" length:4 freeWhenDone:NO]; + + [thePool release]; + } + } + ++ (id)serializer + { + return([[[self alloc] init] autorelease]); + } + +- (BOOL)isValidJSONObject:(id)inObject + { + if ([inObject isKindOfClass:[NSNull class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSNumber class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSString class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSArray class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSDictionary class]]) + { + return(YES); + } + else if ([inObject isKindOfClass:[NSData class]]) + { + return(YES); + } + else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)]) + { + return(YES); + } + else + { + return(NO); + } + } + +- (NSData *)serializeObject:(id)inObject error:(NSError **)outError + { + NSData *theResult = NULL; + + if ([inObject isKindOfClass:[NSNull class]]) + { + theResult = [self serializeNull:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSNumber class]]) + { + theResult = [self serializeNumber:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSString class]]) + { + theResult = [self serializeString:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSArray class]]) + { + theResult = [self serializeArray:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSDictionary class]]) + { + theResult = [self serializeDictionary:inObject error:outError]; + } + else if ([inObject isKindOfClass:[NSData class]]) + { + NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease]; + theResult = [self serializeString:theString error:outError]; + } + else if ([inObject respondsToSelector:@selector(JSONDataRepresentation)]) + { + theResult = [inObject JSONDataRepresentation]; + } + else + { + if (outError) + { + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])], NSLocalizedDescriptionKey, + NULL]; + *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeDataType userInfo:theUserInfo]; + } + return(NULL); + } + if (theResult == NULL) + { + if (outError) + { + NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat:@"Could not serialize object '%@'", inObject], NSLocalizedDescriptionKey, + NULL]; + *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:CJSONSerializerErrorCouldNotSerializeObject userInfo:theUserInfo]; + } + return(NULL); + } + return(theResult); + } + +- (NSData *)serializeNull:(NSNull *)inNull error:(NSError **)outError + { + #pragma unused (inNull, outError) + return(kNULL); + } + +- (NSData *)serializeNumber:(NSNumber *)inNumber error:(NSError **)outError + { + #pragma unused (outError) + NSData *theResult = NULL; + switch (CFNumberGetType((CFNumberRef)inNumber)) + { + case kCFNumberCharType: + { + int theValue = [inNumber intValue]; + if (theValue == 0) + theResult = kFalse; + else if (theValue == 1) + theResult = kTrue; + else + theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding]; + } + break; + case kCFNumberFloat32Type: + case kCFNumberFloat64Type: + case kCFNumberFloatType: + case kCFNumberDoubleType: + case kCFNumberSInt8Type: + case kCFNumberSInt16Type: + case kCFNumberSInt32Type: + case kCFNumberSInt64Type: + case kCFNumberShortType: + case kCFNumberIntType: + case kCFNumberLongType: + case kCFNumberLongLongType: + case kCFNumberCFIndexType: + default: + theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding]; + break; + } + return(theResult); + } + +- (NSData *)serializeString:(NSString *)inString error:(NSError **)outError + { + #pragma unused (outError) + + const char *theUTF8String = [inString UTF8String]; + + NSMutableData *theData = [NSMutableData dataWithLength:strlen(theUTF8String) * 2 + 2]; + + char *theOutputStart = [theData mutableBytes]; + char *OUT = theOutputStart; + + *OUT++ = '"'; + + for (const char *IN = theUTF8String; IN && *IN != '\0'; ++IN) + { + switch (*IN) + { + case '\\': + { + *OUT++ = '\\'; + *OUT++ = '\\'; + } + break; + case '\"': + { + *OUT++ = '\\'; + *OUT++ = '\"'; + } + break; + case '/': + { + *OUT++ = '\\'; + *OUT++ = '/'; + } + break; + case '\b': + { + *OUT++ = '\\'; + *OUT++ = 'b'; + } + break; + case '\f': + { + *OUT++ = '\\'; + *OUT++ = 'f'; + } + break; + case '\n': + { + *OUT++ = '\\'; + *OUT++ = 'n'; + } + break; + case '\r': + { + *OUT++ = '\\'; + *OUT++ = 'r'; + } + break; + case '\t': + { + *OUT++ = '\\'; + *OUT++ = 't'; + } + break; + default: + { + *OUT++ = *IN; + } + break; + } + } + + *OUT++ = '"'; + + theData.length = OUT - theOutputStart; + return(theData); + } + +- (NSData *)serializeArray:(NSArray *)inArray error:(NSError **)outError + { + NSMutableData *theData = [NSMutableData data]; + + [theData appendBytes:"[" length:1]; + + NSEnumerator *theEnumerator = [inArray objectEnumerator]; + id theValue = NULL; + NSUInteger i = 0; + while ((theValue = [theEnumerator nextObject]) != NULL) + { + NSData *theValueData = [self serializeObject:theValue error:outError]; + if (theValueData == NULL) + { + return(NULL); + } + [theData appendData:theValueData]; + if (++i < [inArray count]) + [theData appendBytes:"," length:1]; + } + + [theData appendBytes:"]" length:1]; + + return(theData); + } + +- (NSData *)serializeDictionary:(NSDictionary *)inDictionary error:(NSError **)outError + { + NSMutableData *theData = [NSMutableData data]; + + [theData appendBytes:"{" length:1]; + + NSArray *theKeys = [inDictionary allKeys]; + NSEnumerator *theEnumerator = [theKeys objectEnumerator]; + NSString *theKey = NULL; + while ((theKey = [theEnumerator nextObject]) != NULL) + { + id theValue = [inDictionary objectForKey:theKey]; + + NSData *theKeyData = [self serializeString:theKey error:outError]; + if (theKeyData == NULL) + { + return(NULL); + } + NSData *theValueData = [self serializeObject:theValue error:outError]; + if (theValueData == NULL) + { + return(NULL); + } + + + [theData appendData:theKeyData]; + [theData appendBytes:":" length:1]; + [theData appendData:theValueData]; + + if (theKey != [theKeys lastObject]) + [theData appendData:[@"," dataUsingEncoding:NSASCIIStringEncoding]]; + } + + [theData appendBytes:"}" length:1]; + + return(theData); + } + +@end diff --git a/Classes/Source/JSON/JSONRepresentation.h b/Classes/Source/JSON/JSONRepresentation.h new file mode 100644 index 0000000..a83d76f --- /dev/null +++ b/Classes/Source/JSON/JSONRepresentation.h @@ -0,0 +1,18 @@ +// +// JSONRepresentation.h +// TouchJSON +// +// Created by Jonathan Wight on 10/15/10. +// Copyright 2010 toxicsoftware.com. All rights reserved. +// + +#import <Foundation/Foundation.h> + +@protocol JSONRepresentation + +@optional +- (id)initWithJSONDataRepresentation:(NSData *)inJSONData; + +- (NSData *)JSONDataRepresentation; + +@end diff --git a/Classes/SourcesEditViewController.h b/Classes/SourcesEditViewController.h index 3e59f63..1506242 100644 --- a/Classes/SourcesEditViewController.h +++ b/Classes/SourcesEditViewController.h @@ -7,11 +7,14 @@ // #import <UIKit/UIKit.h> +#import "SectionDictionary.h" @protocol SourcesEditViewControllerDelegate; -@interface SourcesEditViewController : UIViewController <UITableViewDataSource> { +@interface SourcesEditViewController : UIViewController <UITableViewDataSource, NSURLProtocolClient> { id <SourcesEditViewControllerDelegate> delegate; + NSMutableData *_receivedData; + SectionDictionary *sectionDictionary; } @property (nonatomic, assign) id <SourcesEditViewControllerDelegate> delegate; diff --git a/Classes/SourcesEditViewController.m b/Classes/SourcesEditViewController.m index d0ca382..93007a9 100644 --- a/Classes/SourcesEditViewController.m +++ b/Classes/SourcesEditViewController.m @@ -8,7 +8,8 @@ #import "SourcesEditViewController.h" #import "SourcesEditViewCell.h" - +#import "CJSONDeserializer.h" +#import "PicCastAppDelegate.h" @implementation SourcesEditViewController @@ -21,13 +22,29 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.tableView.rowHeight = 100; + self.tableView.rowHeight = 44; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; //NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; - self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor]; + self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor]; + + sectionDictionary = [[[SectionDictionary alloc] init] retain]; + + _receivedData = [[NSMutableData data] retain]; + NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://piccast.memeschemes.com/json/feeds/"] + cachePolicy:NSURLRequestUseProtocolCachePolicy + timeoutInterval:30.0]; + + if ([NSURLConnection connectionWithRequest:theRequest delegate:self]) { + [_receivedData setLength:0]; + } else { + //[MBProgressHUD hideHUDForView:self.view animated:YES]; + [PicCastAppDelegate prompt:@"Error" withMessage:@"No internet connection" andButtonTitle:@"shucks" withDelegate:self]; + } + + //[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"haveSearched"]; } - (IBAction)done:(id)sender { @@ -67,50 +84,110 @@ } */ +#pragma mark - +#pragma mark url response + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + [_receivedData setLength:0]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + [_receivedData appendData:data]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + + //[_receivedData release]; + + //[MBProgressHUD hideHUDForView:self.view animated:YES]; + [PicCastAppDelegate prompt:@"Error" withMessage:[error localizedDescription] andButtonTitle:@"Aww man..." withDelegate:self]; + //[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]); + +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { +// NSString *json = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding]; +// [_tableData removeAllObjects]; +// [_tableData addObjectsFromArray:[[json JSONValue] objectForKey:@"results"]]; +// [json release]; +// +// if ([_tableData count] > 0) { +// [tableView reloadData]; +// [tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; +// self.tableView.allowsSelection = YES; +// self.tableView.scrollEnabled = YES; +// } + + //[MBProgressHUD hideHUDForView:self.view animated:YES]; + + //[_receivedData release]; + + NSError *theError = nil; + id array = [[CJSONDeserializer deserializer] deserialize:(NSData *)_receivedData error:&theError]; + //NSLog(@"class: %@", [array class]); + for (NSDictionary *obj in array) { + [sectionDictionary appendObject:obj forKey:@"Potpourri"]; + } + + [tableView reloadData]; +} #pragma mark - #pragma mark Table view data source -//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { -// // Return the number of sections. -// return <#number of sections#>; -//} +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + // Return the number of sections. + return [sectionDictionary count]; +} // // - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. - return 10; + return [[sectionDictionary objectForIndex:section] count]; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + return [sectionDictionary keyForIndex:section]; } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *CellIdentifier = @"SourcesEditCell"; + static NSString *CellIdentifier = @"cell"; - SourcesEditViewCell *cell = (SourcesEditViewCell *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { - NSArray *tmpCell = [[NSBundle mainBundle] loadNibNamed:@"TopicTableViewCell" owner:self options:nil]; - - for (id currentObj in tmpCell) { - if ([currentObj isKindOfClass:[TopicTableViewCell class]]) { - cell = (SourcesEditViewCell *)currentObj; - [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; - - UISwitch *mySwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease]; - [cell addSubview:mySwitch]; - cell.accessoryView = mySwitch; - - //cell.accessoryView = cell.switcher; - break; - } - } - //cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; - } +// NSArray *tmpCell = [[NSBundle mainBundle] loadNibNamed:@"TopicTableViewCell" owner:self options:nil]; +// +// for (id currentObj in tmpCell) { +// if ([currentObj isKindOfClass:[TopicTableViewCell class]]) { +// cell = (TopicTableViewCell *)currentObj; +// [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; +// +// UISwitch *mySwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease]; +// [cell addSubview:mySwitch]; +// cell.accessoryView = mySwitch; +// +// //cell.accessoryView = cell.switcher; +// break; +// } +// } + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } // Configure the cell... - + [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; + + + NSDictionary *obj = [[sectionDictionary objectForIndex:indexPath.section] objectAtIndex:indexPath.row]; + [cell setText:[[obj objectForKey:@"fields"] objectForKey:@"title"]]; + + UISwitch *mySwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease]; + [cell addSubview:mySwitch]; + cell.accessoryView = mySwitch; + return cell; } @@ -187,6 +264,8 @@ - (void)dealloc { + [sectionDictionary release]; + [_receivedData release]; [super dealloc]; } diff --git a/Classes/SourcesEditViewController.xib b/Classes/SourcesEditViewController.xib index 47dd98b..774a35b 100644 --- a/Classes/SourcesEditViewController.xib +++ b/Classes/SourcesEditViewController.xib @@ -12,7 +12,7 @@ </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="14"/> + <integer value="8"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -47,9 +47,37 @@ <int key="NSvFlags">274</int> <string key="NSFrame">{{0, 44}, {320, 416}}</string> <reference key="NSSuperview" ref="628665035"/> - <object class="NSColor" key="IBUIBackgroundColor" id="242684625"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MQA</bytes> + <object class="NSColor" key="IBUIBackgroundColor"> + <int key="NSColorSpace">10</int> + <object class="NSImage" key="NSImage"> + <int key="NSImageFlags">549453824</int> + <string key="NSSize">{84, 1}</string> + <object class="NSMutableArray" key="NSReps"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="0"/> + <object class="NSBitmapImageRep"> + <object class="NSData" key="NSTIFFRepresentation"> + <bytes key="NS.bytes">TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ +y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ +xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ +xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ +xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ +xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB +AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES +AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS +AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA</bytes> + </object> + </object> + </object> + </object> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MCAwAA</bytes> + </object> + </object> + <string key="IBUIColorCocoaTouchKeyPath">groupTableViewBackgroundColor</string> </object> <bool key="IBUIOpaque">NO</bool> <bool key="IBUIClipsSubviews">YES</bool> @@ -57,12 +85,13 @@ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> <bool key="IBUIBouncesZoom">NO</bool> - <int key="IBUISeparatorStyle">1</int> + <int key="IBUIStyle">1</int> + <int key="IBUISeparatorStyle">2</int> <int key="IBUISectionIndexMinimumDisplayRowCount">0</int> <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool> <float key="IBUIRowHeight">44</float> - <float key="IBUISectionHeaderHeight">22</float> - <float key="IBUISectionFooterHeight">22</float> + <float key="IBUISectionHeaderHeight">10</float> + <float key="IBUISectionFooterHeight">10</float> </object> <object class="IBUINavigationBar" id="755609719"> <reference key="NSNextResponder" ref="628665035"/> @@ -74,7 +103,7 @@ <int key="NSColorSpace">1</int> <bytes key="NSRGB">MC4wOTMzOTc2Mzk2OSAwLjE3NTQ0MzM4MTEgMC4yNTAzODczMTEAA</bytes> </object> - <object class="NSMutableArray" key="IBUIItems"> + <object class="NSArray" key="IBUIItems"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBUINavigationItem" id="478129613"> <reference key="IBUINavigationBar" ref="755609719"/> @@ -92,7 +121,10 @@ </object> <string key="NSFrameSize">{320, 460}</string> <reference key="NSSuperview"/> - <reference key="IBUIBackgroundColor" ref="242684625"/> + <object class="NSColor" key="IBUIBackgroundColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string> </object> </object> diff --git a/Classes/TopicsViewController.m b/Classes/TopicsViewController.m index d9c2f60..67c8490 100644 --- a/Classes/TopicsViewController.m +++ b/Classes/TopicsViewController.m @@ -30,6 +30,7 @@ [super viewDidLoad]; NSLog(@"viewDidLoad"); self.tableView.rowHeight = 100; + self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor]; //UIBarButtonItem *doneItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(returnToParserChoices)] autorelease]; //self.navigationItem.rightBarButtonItem = doneItem; @@ -323,7 +324,7 @@ // [self.navigationController pushViewController:picDumpViewController animated:YES]; // photoViewController = [[[PhotoViewController alloc] init] autorelease]; - photoViewController.topic = [topics objectAtIndex:indexPath.row]; + photoViewController.topic = [[tableDictionary objectForIndex:indexPath.section] objectAtIndex:indexPath.row]; [self.navigationController pushViewController:photoViewController animated:YES]; } diff --git a/PicCast.xcodeproj/handler.mode1v3 b/PicCast.xcodeproj/handler.mode1v3 index 1a67aeb..508e276 100644 --- a/PicCast.xcodeproj/handler.mode1v3 +++ b/PicCast.xcodeproj/handler.mode1v3 @@ -265,9 +265,8 @@ <array> <string>29B97314FDCFA39411CA2CEA</string> <string>080E96DDFE201D6D7F000001</string> - <string>4EB53EBE136359D5009A5AC5</string> <string>4EB53E6513634D4E009A5AC5</string> - <string>4E68283013594C50001EB808</string> + <string>4ECFB853135FD22C007FAB8D</string> <string>29B97315FDCFA39411CA2CEA</string> <string>29B97317FDCFA39411CA2CEA</string> <string>29B97323FDCFA39411CA2CEA</string> @@ -278,14 +277,13 @@ <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <array> <array> - <integer>29</integer> - <integer>23</integer> + <integer>28</integer> <integer>4</integer> <integer>0</integer> </array> </array> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> - <string>{{0, 27}, {282, 667}}</string> + <string>{{0, 86}, {282, 667}}</string> </dict> <key>PBXTopSmartGroupGIDs</key> <array/> @@ -304,7 +302,7 @@ <real>282</real> </array> <key>RubberWindowFrame</key> - <string>72 107 1268 726 0 0 1440 878 </string> + <string>66 133 1268 726 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXSmartGroupTreeModule</string> @@ -322,7 +320,7 @@ <key>PBXProjectModuleGUID</key> <string>1CE0B20306471E060097A5F4</string> <key>PBXProjectModuleLabel</key> - <string>FMDatabase.m</string> + <string>TopicsViewController.m</string> <key>PBXSplitModuleInNavigatorKey</key> <dict> <key>Split0</key> @@ -330,11 +328,11 @@ <key>PBXProjectModuleGUID</key> <string>1CE0B20406471E060097A5F4</string> <key>PBXProjectModuleLabel</key> - <string>FMDatabase.m</string> + <string>TopicsViewController.m</string> <key>_historyCapacity</key> <integer>0</integer> <key>bookmark</key> - <string>4EB5425913652F4E009A5AC5</string> + <string>4EB542D313654A2B009A5AC5</string> <key>history</key> <array> <string>4E68286F1359595F001EB808</string> @@ -347,12 +345,8 @@ <string>4ECFB6E1135F58D2007FAB8D</string> <string>4ECFB724135F80A7007FAB8D</string> <string>4ECFB73A135F8619007FAB8D</string> - <string>4ECFB8D8135FE005007FAB8D</string> - <string>4ECFB8DE135FE058007FAB8D</string> <string>4ECFB8F2135FE28C007FAB8D</string> <string>4EBFCB481360E786005AC5CC</string> - <string>4EBFCB791360F428005AC5CC</string> - <string>4EBFCBD11360FA86005AC5CC</string> <string>4EBFCBE51360FD85005AC5CC</string> <string>4E067D391361413100D43FE0</string> <string>4E067D3A1361413100D43FE0</string> @@ -376,13 +370,17 @@ <string>4EB53F811364F105009A5AC5</string> <string>4EB53FC71364F84B009A5AC5</string> <string>4EB540061364FED6009A5AC5</string> - <string>4EB540CF13651027009A5AC5</string> <string>4EB5416613651760009A5AC5</string> <string>4EB541BB13651A0D009A5AC5</string> - <string>4EB5424013652BCA009A5AC5</string> - <string>4EB5425213652F31009A5AC5</string> <string>4EB5425713652F4E009A5AC5</string> - <string>4EB5425813652F4E009A5AC5</string> + <string>4EB542A6136541D2009A5AC5</string> + <string>4EB542A7136541D2009A5AC5</string> + <string>4EB542A8136541D2009A5AC5</string> + <string>4EB542A9136541D2009A5AC5</string> + <string>4EB542AB136541D2009A5AC5</string> + <string>4EB542AC136541D2009A5AC5</string> + <string>4EB542D113654A2B009A5AC5</string> + <string>4EB542D213654A2B009A5AC5</string> </array> </dict> <key>SplitCount</key> @@ -396,7 +394,7 @@ <key>Frame</key> <string>{{0, 0}, {964, 680}}</string> <key>RubberWindowFrame</key> - <string>72 107 1268 726 0 0 1440 878 </string> + <string>66 133 1268 726 0 0 1440 878 </string> </dict> <key>Module</key> <string>PBXNavigatorGroup</string> @@ -416,7 +414,7 @@ <key>Frame</key> <string>{{0, 685}, {964, 0}}</string> <key>RubberWindowFrame</key> - <string>72 107 1268 726 0 0 1440 878 </string> + <string>66 133 1268 726 0 0 1440 878 </string> </dict> <key>Module</key> <string>XCDetailModule</string> @@ -580,18 +578,18 @@ <integer>5</integer> <key>WindowOrderList</key> <array> - <string>4EB5425613652F31009A5AC5</string> + <string>4EB542D413654A2B009A5AC5</string> <string>4EB5408213650D7B009A5AC5</string> - <string>1C530D57069F1CE1000CFCEE</string> <string>4EB53EA21363581F009A5AC5</string> <string>4EB53EA31363581F009A5AC5</string> + <string>1CD10A99069EF8BA00B06720</string> <string>4E6827C813593DE3001EB808</string> <string>1C78EAAD065D492600B07095</string> + <string>1C530D57069F1CE1000CFCEE</string> <string>/Users/handler/Documents/code/xCode/PicCast/PicCast.xcodeproj</string> - <string>1CD10A99069EF8BA00B06720</string> </array> <key>WindowString</key> - <string>72 107 1268 726 0 0 1440 878 </string> + <string>66 133 1268 726 0 0 1440 878 </string> <key>WindowToolsV3</key> <array> <dict> @@ -607,14 +605,12 @@ <key>Dock</key> <array> <dict> - <key>BecomeActive</key> - <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> <string>1CD0528F0623707200166675</string> <key>PBXProjectModuleLabel</key> - <string>SectionDictionary.m</string> + <string>SourcesEditViewController.m</string> <key>StatusBarVisibility</key> <true/> </dict> @@ -631,6 +627,8 @@ <string>262pt</string> </dict> <dict> + <key>BecomeActive</key> + <true/> <key>ContentConfiguration</key> <dict> <key>PBXProjectModuleGUID</key> @@ -807,7 +805,7 @@ <key>WindowToolGUID</key> <string>1CD10A99069EF8BA00B06720</string> <key>WindowToolIsVisible</key> - <true/> + <false/> </dict> <dict> <key>FirstTimeWindowDisplayed</key> @@ -830,7 +828,7 @@ <key>PBXProjectModuleGUID</key> <string>1CDD528C0622207200134675</string> <key>PBXProjectModuleLabel</key> - <string>FMDatabase.m</string> + <string>SourcesEditViewController.m</string> <key>StatusBarVisibility</key> <true/> </dict> @@ -898,7 +896,7 @@ <key>WindowToolGUID</key> <string>1C530D57069F1CE1000CFCEE</string> <key>WindowToolIsVisible</key> - <false/> + <true/> </dict> <dict> <key>Identifier</key> diff --git a/PicCast.xcodeproj/handler.pbxuser b/PicCast.xcodeproj/handler.pbxuser index e3fd1e1..8b780a9 100644 --- a/PicCast.xcodeproj/handler.pbxuser +++ b/PicCast.xcodeproj/handler.pbxuser @@ -10,8 +10,8 @@ 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1965, 2522}}"; - sepNavSelRange = "{5831, 0}"; - sepNavVisRange = "{4442, 1711}"; + sepNavSelRange = "{5625, 0}"; + sepNavVisRange = "{552, 1546}"; }; }; 1D6058900D05DD3D006BFB54 /* PicCast */ = { @@ -75,12 +75,12 @@ 4EB541B313651953009A5AC5 /* FMDatabase.m:546 */, 4EB541B513651963009A5AC5 /* FMDatabase.m:561 */, 4EB541B713651964009A5AC5 /* FMDatabase.m:572 */, - 4EB541C713651DC8009A5AC5 /* TopicsViewController.m:128 */, + 4EB541C713651DC8009A5AC5 /* TopicsViewController.m:129 */, 4EB541CF13651E18009A5AC5 /* FMDatabase.m:465 */, 4EB541D313651E3A009A5AC5 /* FMDatabase.m:476 */, 4EB541D513651E59009A5AC5 /* FMDatabase.m:477 */, 4EB541D7136521F2009A5AC5 /* FMDatabase.m:558 */, - 4EB5421E1365280F009A5AC5 /* TopicsViewController.m:54 */, + 4EB5421E1365280F009A5AC5 /* TopicsViewController.m:55 */, 4EB5424413652BFA009A5AC5 /* FMDatabase.m:577 */, 4EB5424E13652E24009A5AC5 /* FMDatabase.m:497 */, ); @@ -501,6 +501,35 @@ 4EB5425713652F4E009A5AC5 /* PBXTextBookmark */ = 4EB5425713652F4E009A5AC5 /* PBXTextBookmark */; 4EB5425813652F4E009A5AC5 /* PBXTextBookmark */ = 4EB5425813652F4E009A5AC5 /* PBXTextBookmark */; 4EB5425913652F4E009A5AC5 /* PBXTextBookmark */ = 4EB5425913652F4E009A5AC5 /* PBXTextBookmark */; + 4EB5428913653AB6009A5AC5 /* PBXTextBookmark */ = 4EB5428913653AB6009A5AC5 /* PBXTextBookmark */; + 4EB5428A13653AB6009A5AC5 /* PBXTextBookmark */ = 4EB5428A13653AB6009A5AC5 /* PBXTextBookmark */; + 4EB54297136540A7009A5AC5 /* PBXTextBookmark */ = 4EB54297136540A7009A5AC5 /* PBXTextBookmark */; + 4EB54298136540A7009A5AC5 /* XCBuildMessageTextBookmark */ = 4EB54298136540A7009A5AC5 /* XCBuildMessageTextBookmark */; + 4EB54299136540A7009A5AC5 /* PBXTextBookmark */ = 4EB54299136540A7009A5AC5 /* PBXTextBookmark */; + 4EB5429A136540A7009A5AC5 /* PBXTextBookmark */ = 4EB5429A136540A7009A5AC5 /* PBXTextBookmark */; + 4EB5429B136540EC009A5AC5 /* PBXTextBookmark */ = 4EB5429B136540EC009A5AC5 /* PBXTextBookmark */; + 4EB5429C136540EC009A5AC5 /* PBXTextBookmark */ = 4EB5429C136540EC009A5AC5 /* PBXTextBookmark */; + 4EB542A6136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542A6136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542A7136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542A7136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542A8136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542A8136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542A9136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542A9136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542AA136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542AA136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542AB136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542AB136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542AC136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542AC136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542AD136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542AD136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542AE136541D2009A5AC5 /* PBXTextBookmark */ = 4EB542AE136541D2009A5AC5 /* PBXTextBookmark */; + 4EB542B31365425B009A5AC5 /* PBXTextBookmark */ = 4EB542B31365425B009A5AC5 /* PBXTextBookmark */; + 4EB542B41365425B009A5AC5 /* PBXTextBookmark */ = 4EB542B41365425B009A5AC5 /* PBXTextBookmark */; + 4EB542B51365425B009A5AC5 /* PBXTextBookmark */ = 4EB542B51365425B009A5AC5 /* PBXTextBookmark */; + 4EB542BB13654359009A5AC5 /* PBXTextBookmark */ = 4EB542BB13654359009A5AC5 /* PBXTextBookmark */; + 4EB542BC13654359009A5AC5 /* PBXTextBookmark */ = 4EB542BC13654359009A5AC5 /* PBXTextBookmark */; + 4EB542BD13654359009A5AC5 /* PBXTextBookmark */ = 4EB542BD13654359009A5AC5 /* PBXTextBookmark */; + 4EB542C413654756009A5AC5 /* PBXTextBookmark */ = 4EB542C413654756009A5AC5 /* PBXTextBookmark */; + 4EB542C513654756009A5AC5 /* PBXTextBookmark */ = 4EB542C513654756009A5AC5 /* PBXTextBookmark */; + 4EB542CD136548E0009A5AC5 /* PBXTextBookmark */ = 4EB542CD136548E0009A5AC5 /* PBXTextBookmark */; + 4EB542D113654A2B009A5AC5 /* PBXTextBookmark */ = 4EB542D113654A2B009A5AC5 /* PBXTextBookmark */; + 4EB542D213654A2B009A5AC5 /* PBXTextBookmark */ = 4EB542D213654A2B009A5AC5 /* PBXTextBookmark */; + 4EB542D313654A2B009A5AC5 /* PBXTextBookmark */ = 4EB542D313654A2B009A5AC5 /* PBXTextBookmark */; 4EBFCB481360E786005AC5CC = 4EBFCB481360E786005AC5CC /* PBXTextBookmark */; 4EBFCB791360F428005AC5CC = 4EBFCB791360F428005AC5CC /* PBXTextBookmark */; 4EBFCBD11360FA86005AC5CC = 4EBFCBD11360FA86005AC5CC /* PBXTextBookmark */; @@ -623,10 +652,10 @@ }; 4E6827E813594115001EB808 /* TopicsViewController.m */ = { uiCtxt = { - sepNavFolds = "{\n c = (\n {\n l = DetailViewController;\n r = \"{6722, 24}\";\n s = 1;\n },\n {\n l = DetailViewController;\n r = \"{6773, 24}\";\n s = 1;\n },\n {\n l = \"Nib name\";\n r = \"{6823, 12}\";\n s = 1;\n }\n );\n r = \"{0, 13207}\";\n s = 0;\n}"; - sepNavIntBoundsRect = "{{0, 0}, {1272, 5343}}"; - sepNavSelRange = "{2314, 0}"; - sepNavVisRange = "{3219, 1505}"; + sepNavFolds = "{\n c = (\n {\n l = DetailViewController;\n r = \"{6791, 24}\";\n s = 1;\n },\n {\n l = DetailViewController;\n r = \"{6842, 24}\";\n s = 1;\n },\n {\n l = \"Nib name\";\n r = \"{6892, 12}\";\n s = 1;\n }\n );\n r = \"{0, 13320}\";\n s = 0;\n}"; + sepNavIntBoundsRect = "{{0, 0}, {1272, 5213}}"; + sepNavSelRange = "{801, 0}"; + sepNavVisRange = "{494, 1855}"; sepNavWindowFrame = "{{15, 323}, {1196, 550}}"; }; }; @@ -667,9 +696,9 @@ }; 4E68282E13594C48001EB808 /* Topic.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1006, 1079}}"; - sepNavSelRange = "{2304, 0}"; - sepNavVisRange = "{1178, 1576}"; + sepNavIntBoundsRect = "{{0, 0}, {1160, 1027}}"; + sepNavSelRange = "{1999, 0}"; + sepNavVisRange = "{1857, 450}"; }; }; 4E68286F1359595F001EB808 /* PBXTextBookmark */ = { @@ -858,7 +887,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 145"; rLen = 0; - rLoc = 7537; + rLoc = 7606; rType = 0; vrLen = 1626; vrLoc = 5222; @@ -916,7 +945,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 182"; rLen = 0; - rLoc = 8742; + rLoc = 8811; rType = 0; vrLen = 2091; vrLoc = 442; @@ -946,7 +975,7 @@ fRef = 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */; name = "PicCastAppDelegate.m: 154"; rLen = 0; - rLoc = 5831; + rLoc = 5892; rType = 0; vrLen = 1711; vrLoc = 4442; @@ -967,9 +996,9 @@ }; 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {908, 10608}}"; - sepNavSelRange = "{15477, 0}"; - sepNavVisRange = "{13777, 1726}"; + sepNavIntBoundsRect = "{{0, 0}, {793, 10764}}"; + sepNavSelRange = "{19911, 0}"; + sepNavVisRange = "{9925, 728}"; }; }; 4EB53EC9136359E3009A5AC5 /* fmdb.m */ = { @@ -994,9 +1023,9 @@ }; 4EB53EE71363773B009A5AC5 /* SectionDictionary.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1160, 923}}"; + sepNavIntBoundsRect = "{{0, 0}, {1160, 884}}"; sepNavSelRange = "{568, 0}"; - sepNavVisRange = "{401, 377}"; + sepNavVisRange = "{401, 494}"; }; }; 4EB53EF013637BF8009A5AC5 /* PBXTextBookmark */ = { @@ -1004,7 +1033,7 @@ fRef = 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */; name = "PicCastAppDelegate.m: 154"; rLen = 0; - rLoc = 5831; + rLoc = 5892; rType = 0; vrLen = 1711; vrLoc = 4442; @@ -1064,7 +1093,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 222"; rLen = 0; - rLoc = 7562; + rLoc = 7631; rType = 0; vrLen = 1553; vrLoc = 5631; @@ -1074,7 +1103,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 222"; rLen = 0; - rLoc = 7582; + rLoc = 7651; rType = 0; vrLen = 1573; vrLoc = 5631; @@ -1114,7 +1143,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 77"; rLen = 0; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1279; vrLoc = 2197; @@ -1195,7 +1224,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; fallbackIsa = XCBuildMessageTextBookmark; rLen = 0; - rLoc = 145; + rLoc = 146; rType = 1; }; 4EB53F3A1364EAD1009A5AC5 /* PBXTextBookmark */ = { @@ -1203,7 +1232,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 530; vrLoc = 3576; @@ -1230,7 +1259,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 530; vrLoc = 3576; @@ -1250,7 +1279,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 547; vrLoc = 2888; @@ -1389,7 +1418,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 87"; rLen = 0; - rLoc = 3041; + rLoc = 3110; rType = 0; vrLen = 1494; vrLoc = 2494; @@ -1429,7 +1458,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 87"; rLen = 0; - rLoc = 3041; + rLoc = 3110; rType = 0; vrLen = 1445; vrLoc = 2888; @@ -1489,7 +1518,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 87"; rLen = 0; - rLoc = 3041; + rLoc = 3110; rType = 0; vrLen = 1512; vrLoc = 2822; @@ -1499,7 +1528,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 124"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1481; vrLoc = 2888; @@ -1509,7 +1538,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 127"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1574; vrLoc = 3135; @@ -1569,7 +1598,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 126"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1606; vrLoc = 3135; @@ -1579,7 +1608,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 224"; rLen = 0; - rLoc = 7536; + rLoc = 7605; rType = 0; vrLen = 1670; vrLoc = 5891; @@ -1589,7 +1618,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 220"; rLen = 0; - rLoc = 7311; + rLoc = 7380; rType = 0; vrLen = 1783; vrLoc = 5891; @@ -1629,7 +1658,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 220"; rLen = 0; - rLoc = 7311; + rLoc = 7380; rType = 0; vrLen = 1783; vrLoc = 5891; @@ -1639,7 +1668,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 200"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1624; vrLoc = 5414; @@ -1669,7 +1698,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 200"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1698; vrLoc = 5502; @@ -1679,7 +1708,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 79"; rLen = 0; - rLoc = 2737; + rLoc = 2806; rType = 0; vrLen = 1423; vrLoc = 2491; @@ -1699,7 +1728,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 79"; rLen = 0; - rLoc = 2737; + rLoc = 2806; rType = 0; vrLen = 1336; vrLoc = 2488; @@ -1709,7 +1738,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 109"; rLen = 0; - rLoc = 3778; + rLoc = 3847; rType = 0; vrLen = 1420; vrLoc = 2491; @@ -1719,7 +1748,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 103"; rLen = 0; - rLoc = 3482; + rLoc = 3551; rType = 0; vrLen = 1481; vrLoc = 2513; @@ -1729,7 +1758,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1545; vrLoc = 2803; @@ -1739,7 +1768,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1456; vrLoc = 2874; @@ -1749,7 +1778,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1836; vrLoc = 8938; @@ -1838,7 +1867,7 @@ isa = PBXTextBookmark; fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; }; 4EB53FC61364F82F009A5AC5 /* PBXTextBookmark */ = { @@ -1846,7 +1875,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 877; vrLoc = 3420; @@ -1876,7 +1905,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1629; vrLoc = 3102; @@ -1886,7 +1915,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 129"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1552; vrLoc = 2601; @@ -1896,7 +1925,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 202"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1825; vrLoc = 5817; @@ -1906,7 +1935,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 202"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1825; vrLoc = 5817; @@ -1936,7 +1965,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 52"; rLen = 0; - rLoc = 1959; + rLoc = 2028; rType = 0; vrLen = 1904; vrLoc = 441; @@ -1976,7 +2005,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 52"; rLen = 0; - rLoc = 1959; + rLoc = 2028; rType = 0; vrLen = 1904; vrLoc = 441; @@ -1986,7 +2015,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 202"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1759; vrLoc = 5672; @@ -2006,7 +2035,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 202"; rLen = 0; - rLoc = 6443; + rLoc = 6512; rType = 0; vrLen = 1904; vrLoc = 441; @@ -2155,7 +2184,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 118"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 891; vrLoc = 3960; @@ -2165,7 +2194,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 105"; rLen = 0; - rLoc = 3547; + rLoc = 3616; rType = 0; vrLen = 1525; vrLoc = 2472; @@ -2204,7 +2233,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 285"; rLen = 0; - rLoc = 9387; + rLoc = 9456; rType = 0; vrLen = 1641; vrLoc = 8003; @@ -2214,7 +2243,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 291"; rLen = 0; - rLoc = 9721; + rLoc = 9790; rType = 0; vrLen = 1627; vrLoc = 8345; @@ -2244,7 +2273,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 291"; rLen = 0; - rLoc = 9721; + rLoc = 9790; rType = 0; vrLen = 1627; vrLoc = 8345; @@ -2254,7 +2283,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1557; vrLoc = 3137; @@ -2264,7 +2293,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 124"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1683; vrLoc = 3192; @@ -2274,7 +2303,7 @@ fRef = 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */; name = "PicCastAppDelegate.m: 154"; rLen = 0; - rLoc = 5831; + rLoc = 5892; rType = 0; vrLen = 1711; vrLoc = 4442; @@ -2284,7 +2313,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 55"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1877; vrLoc = 403; @@ -2304,7 +2333,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1895; vrLoc = 518; @@ -2323,7 +2352,7 @@ isa = PBXTextBookmark; fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; }; 4EB5404F13650A19009A5AC5 /* PBXTextBookmark */ = { @@ -2331,7 +2360,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 121"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 730; vrLoc = 3591; @@ -2341,7 +2370,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 121"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1632; vrLoc = 3203; @@ -2401,7 +2430,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 121"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1632; vrLoc = 3203; @@ -2411,7 +2440,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 131"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1949; vrLoc = 589; @@ -2421,7 +2450,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 131"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1931; vrLoc = 629; @@ -2431,7 +2460,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 60"; rLen = 0; - rLoc = 2022; + rLoc = 2091; rType = 0; vrLen = 1999; vrLoc = 651; @@ -2451,7 +2480,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 45"; rLen = 0; - rLoc = 1600; + rLoc = 1669; rType = 0; vrLen = 1941; vrLoc = 549; @@ -2461,7 +2490,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 45"; rLen = 0; - rLoc = 1600; + rLoc = 1669; rType = 0; vrLen = 1962; vrLoc = 550; @@ -2481,7 +2510,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 58"; rLen = 0; - rLoc = 2022; + rLoc = 2091; rType = 0; vrLen = 1749; vrLoc = 1002; @@ -2491,7 +2520,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 76"; rLen = 0; - rLoc = 2651; + rLoc = 2720; rType = 0; vrLen = 1694; vrLoc = 1080; @@ -2501,7 +2530,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1899; vrLoc = 494; @@ -2521,7 +2550,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 889; vrLoc = 3851; @@ -2541,7 +2570,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 889; vrLoc = 3851; @@ -2551,7 +2580,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 75"; rLen = 1; - rLoc = 2650; + rLoc = 2719; rType = 0; vrLen = 1488; vrLoc = 2851; @@ -2561,7 +2590,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 75"; rLen = 1; - rLoc = 2650; + rLoc = 2719; rType = 0; vrLen = 1476; vrLoc = 2949; @@ -2581,7 +2610,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 939; vrLoc = 3801; @@ -2601,7 +2630,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 939; vrLoc = 3801; @@ -2621,7 +2650,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 939; vrLoc = 3801; @@ -2631,7 +2660,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 75"; rLen = 1; - rLoc = 2650; + rLoc = 2719; rType = 0; vrLen = 1667; vrLoc = 3280; @@ -2641,7 +2670,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 76"; rLen = 0; - rLoc = 2651; + rLoc = 2720; rType = 0; vrLen = 1304; vrLoc = 1958; @@ -2660,7 +2689,7 @@ ignoreCount = 0; lineNumber = 60; location = PicCast; - modificationTime = 325398322.51522; + modificationTime = 325404897.93791; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -2669,7 +2698,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 76"; rLen = 0; - rLoc = 2651; + rLoc = 2720; rType = 0; vrLen = 1570; vrLoc = 3518; @@ -2718,7 +2747,7 @@ ignoreCount = 0; lineNumber = 56; location = PicCast; - modificationTime = 325398322.518585; + modificationTime = 325404897.945237; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -2757,7 +2786,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 375"; rLen = 0; - rLoc = 12939; + rLoc = 13052; rType = 0; vrLen = 1637; vrLoc = 3266; @@ -2767,7 +2796,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 374"; rLen = 0; - rLoc = 12939; + rLoc = 13052; rType = 0; vrLen = 1662; vrLoc = 3267; @@ -2777,7 +2806,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 374"; rLen = 0; - rLoc = 12882; + rLoc = 12995; rType = 0; vrLen = 1662; vrLoc = 3267; @@ -2787,7 +2816,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 373"; rLen = 0; - rLoc = 12882; + rLoc = 12995; rType = 0; vrLen = 1563; vrLoc = 3369; @@ -2797,7 +2826,7 @@ fRef = 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */; name = "PicCastAppDelegate.m: 154"; rLen = 0; - rLoc = 5831; + rLoc = 5892; rType = 0; vrLen = 1711; vrLoc = 4442; @@ -2807,7 +2836,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 58"; rLen = 0; - rLoc = 2022; + rLoc = 2091; rType = 0; vrLen = 1462; vrLoc = 1497; @@ -2817,7 +2846,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 58"; rLen = 0; - rLoc = 2022; + rLoc = 2091; rType = 0; vrLen = 1491; vrLoc = 2848; @@ -2837,7 +2866,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 771; vrLoc = 3798; @@ -2847,7 +2876,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 58"; rLen = 0; - rLoc = 2022; + rLoc = 2091; rType = 0; vrLen = 1480; vrLoc = 2946; @@ -2867,7 +2896,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 657; vrLoc = 3682; @@ -2877,7 +2906,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 0; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1373; vrLoc = 1606; @@ -2897,7 +2926,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 694; vrLoc = 3663; @@ -2907,7 +2936,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 0; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1621; vrLoc = 3138; @@ -2917,7 +2946,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 0; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1535; vrLoc = 3261; @@ -2937,7 +2966,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 781; vrLoc = 3663; @@ -2947,7 +2976,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 0; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1530; vrLoc = 2813; @@ -2967,7 +2996,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 781; vrLoc = 3681; @@ -2977,7 +3006,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1631; vrLoc = 2979; @@ -2997,7 +3026,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 769; vrLoc = 3700; @@ -3007,7 +3036,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1561; vrLoc = 3052; @@ -3027,7 +3056,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 687; vrLoc = 3663; @@ -3037,7 +3066,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1636; vrLoc = 3295; @@ -3057,7 +3086,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 653; vrLoc = 3700; @@ -3067,7 +3096,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 120"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 1636; vrLoc = 3295; @@ -3107,7 +3136,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 660; vrLoc = 3661; @@ -3126,7 +3155,7 @@ isa = PBXTextBookmark; fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; rLen = 0; - rLoc = 145; + rLoc = 146; rType = 1; }; 4EB54123136514A2009A5AC5 /* PBXTextBookmark */ = { @@ -3134,7 +3163,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 117"; rLen = 0; - rLoc = 3912; + rLoc = 3981; rType = 0; vrLen = 1634; vrLoc = 3297; @@ -3144,7 +3173,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1757; vrLoc = 972; @@ -3164,7 +3193,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 122"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 877; vrLoc = 3713; @@ -3174,7 +3203,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1475; vrLoc = 1497; @@ -3184,7 +3213,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1553; vrLoc = 3254; @@ -3193,7 +3222,7 @@ isa = PBXTextBookmark; fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; rLen = 0; - rLoc = 145; + rLoc = 146; rType = 1; }; 4EB541381365154B009A5AC5 /* PBXTextBookmark */ = { @@ -3201,7 +3230,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1600; vrLoc = 3288; @@ -3221,7 +3250,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 121"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 681; vrLoc = 3693; @@ -3231,7 +3260,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1659; vrLoc = 3292; @@ -3246,11 +3275,11 @@ delayBeforeContinue = 0; fileReference = 4E68282E13594C48001EB808 /* Topic.m */; functionName = "-serializeToDatabase:"; - hitCount = 4; + hitCount = 0; ignoreCount = 0; lineNumber = 57; location = PicCast; - modificationTime = 325398347.601292; + modificationTime = 325404897.951378; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3259,7 +3288,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 57"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1659; vrLoc = 3292; @@ -3329,7 +3358,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 134"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 855; vrLoc = 3787; @@ -3349,7 +3378,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 134"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 891; vrLoc = 3861; @@ -3369,7 +3398,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 134"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1696; vrLoc = 3293; @@ -3388,7 +3417,7 @@ ignoreCount = 0; lineNumber = 659; location = PicCast; - modificationTime = 325398322.526002; + modificationTime = 325404897.955788; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3406,7 +3435,7 @@ ignoreCount = 0; lineNumber = 658; location = PicCast; - modificationTime = 325398322.530927; + modificationTime = 325404897.960164; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3424,7 +3453,7 @@ ignoreCount = 0; lineNumber = 660; location = PicCast; - modificationTime = 325398322.534669; + modificationTime = 325404897.965017; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3442,7 +3471,7 @@ ignoreCount = 0; lineNumber = 661; location = PicCast; - modificationTime = 325398322.539318; + modificationTime = 325404897.969718; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3460,7 +3489,7 @@ ignoreCount = 0; lineNumber = 662; location = PicCast; - modificationTime = 325398322.543483; + modificationTime = 325404897.973841; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3489,7 +3518,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 134"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1696; vrLoc = 3293; @@ -3529,7 +3558,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 134"; rLen = 0; - rLoc = 4491; + rLoc = 4560; rType = 0; vrLen = 814; vrLoc = 3827; @@ -3595,7 +3624,7 @@ ignoreCount = 0; lineNumber = 608; location = PicCast; - modificationTime = 325398322.547078; + modificationTime = 325404897.978466; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3613,7 +3642,7 @@ ignoreCount = 0; lineNumber = 609; location = PicCast; - modificationTime = 325398322.570473; + modificationTime = 325404898.001809; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3631,7 +3660,7 @@ ignoreCount = 0; lineNumber = 611; location = PicCast; - modificationTime = 325398322.574508; + modificationTime = 325404898.005883; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3649,7 +3678,7 @@ ignoreCount = 0; lineNumber = 613; location = PicCast; - modificationTime = 325398322.579643; + modificationTime = 325404898.01092; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3667,7 +3696,7 @@ ignoreCount = 0; lineNumber = 614; location = PicCast; - modificationTime = 325398322.58164; + modificationTime = 325404898.016823; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3716,7 +3745,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 59"; rLen = 0; - rLoc = 2021; + rLoc = 2090; rType = 0; vrLen = 1725; vrLoc = 1082; @@ -3765,7 +3794,7 @@ ignoreCount = 0; lineNumber = 462; location = PicCast; - modificationTime = 325398322.583786; + modificationTime = 325404898.018859; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3783,7 +3812,7 @@ ignoreCount = 0; lineNumber = 472; location = PicCast; - modificationTime = 325398322.586177; + modificationTime = 325404898.02191; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3801,7 +3830,7 @@ ignoreCount = 0; lineNumber = 484; location = PicCast; - modificationTime = 325398322.588744; + modificationTime = 325404898.024552; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3819,7 +3848,7 @@ ignoreCount = 0; lineNumber = 496; location = PicCast; - modificationTime = 325398322.592765; + modificationTime = 325404898.027742; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3837,7 +3866,7 @@ ignoreCount = 0; lineNumber = 504; location = PicCast; - modificationTime = 325398322.59553; + modificationTime = 325404898.031836; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3855,7 +3884,7 @@ ignoreCount = 0; lineNumber = 509; location = PicCast; - modificationTime = 325398322.597861; + modificationTime = 325404898.034677; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3873,7 +3902,7 @@ ignoreCount = 0; lineNumber = 518; location = PicCast; - modificationTime = 325398322.600847; + modificationTime = 325404898.03837; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3891,7 +3920,7 @@ ignoreCount = 0; lineNumber = 527; location = PicCast; - modificationTime = 325398322.603303; + modificationTime = 325404898.041941; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3909,7 +3938,7 @@ ignoreCount = 0; lineNumber = 542; location = PicCast; - modificationTime = 325398322.606235; + modificationTime = 325404898.044879; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3927,7 +3956,7 @@ ignoreCount = 0; lineNumber = 553; location = PicCast; - modificationTime = 325398322.620369; + modificationTime = 325404898.06255; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3945,7 +3974,7 @@ ignoreCount = 0; lineNumber = 565; location = PicCast; - modificationTime = 325398331.584812; + modificationTime = 325404898.065395; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3963,7 +3992,7 @@ ignoreCount = 0; lineNumber = 574; location = PicCast; - modificationTime = 325398329.681672; + modificationTime = 325404898.06771; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3981,7 +4010,7 @@ ignoreCount = 0; lineNumber = 586; location = PicCast; - modificationTime = 325398322.628441; + modificationTime = 325404898.074708; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -3999,7 +4028,7 @@ ignoreCount = 0; lineNumber = 599; location = PicCast; - modificationTime = 325398322.630664; + modificationTime = 325404898.077094; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4017,7 +4046,7 @@ ignoreCount = 0; lineNumber = 488; location = PicCast; - modificationTime = 325398322.63295; + modificationTime = 325404898.079368; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4035,7 +4064,7 @@ ignoreCount = 0; lineNumber = 544; location = PicCast; - modificationTime = 325398322.635367; + modificationTime = 325404898.081849; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4053,7 +4082,7 @@ ignoreCount = 0; lineNumber = 546; location = PicCast; - modificationTime = 325398322.639193; + modificationTime = 325404898.084699; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4071,7 +4100,7 @@ ignoreCount = 0; lineNumber = 561; location = PicCast; - modificationTime = 325398322.641558; + modificationTime = 325404898.08815; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4089,7 +4118,7 @@ ignoreCount = 0; lineNumber = 572; location = PicCast; - modificationTime = 325398330.584505; + modificationTime = 325404898.090773; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4155,7 +4184,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 59"; rLen = 0; - rLoc = 2021; + rLoc = 2090; rType = 0; vrLen = 1725; vrLoc = 1082; @@ -4165,12 +4194,12 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1654; vrLoc = 1246; }; - 4EB541C713651DC8009A5AC5 /* TopicsViewController.m:128 */ = { + 4EB541C713651DC8009A5AC5 /* TopicsViewController.m:129 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -4182,9 +4211,9 @@ functionName = "-updateTopicsFromWeb:"; hitCount = 0; ignoreCount = 0; - lineNumber = 128; + lineNumber = 129; location = PicCast; - modificationTime = 325398322.64722; + modificationTime = 325404898.106078; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4203,7 +4232,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1528; vrLoc = 3023; @@ -4213,7 +4242,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1570; vrLoc = 3029; @@ -4232,7 +4261,7 @@ ignoreCount = 0; lineNumber = 465; location = PicCast; - modificationTime = 325398322.661669; + modificationTime = 325404898.108842; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4270,7 +4299,7 @@ ignoreCount = 0; lineNumber = 476; location = PicCast; - modificationTime = 325398322.664376; + modificationTime = 325404898.111146; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4288,7 +4317,7 @@ ignoreCount = 0; lineNumber = 477; location = PicCast; - modificationTime = 325398322.667134; + modificationTime = 325404898.113247; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4306,7 +4335,7 @@ ignoreCount = 0; lineNumber = 558; location = PicCast; - modificationTime = 325398322.669336; + modificationTime = 325404898.116084; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4335,7 +4364,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1533; vrLoc = 3159; @@ -4345,7 +4374,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1472; vrLoc = 3255; @@ -4375,7 +4404,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 67"; rLen = 278; - rLoc = 2372; + rLoc = 2441; rType = 0; vrLen = 1641; vrLoc = 3255; @@ -4385,7 +4414,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 123"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1570; vrLoc = 3310; @@ -4415,7 +4444,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 123"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1562; vrLoc = 3339; @@ -4425,7 +4454,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 126"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1628; vrLoc = 3344; @@ -4445,7 +4474,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 125"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1572; vrLoc = 3344; @@ -4455,7 +4484,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 60"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1211; vrLoc = 2197; @@ -4505,7 +4534,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 124"; rLen = 0; - rLoc = 3913; + rLoc = 3982; rType = 0; vrLen = 1442; vrLoc = 3903; @@ -4515,12 +4544,12 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 62"; rLen = 0; - rLoc = 2021; + rLoc = 2090; rType = 0; vrLen = 1608; vrLoc = 1381; }; - 4EB5421E1365280F009A5AC5 /* TopicsViewController.m:54 */ = { + 4EB5421E1365280F009A5AC5 /* TopicsViewController.m:55 */ = { isa = PBXFileBreakpoint; actions = ( ); @@ -4532,9 +4561,9 @@ functionName = "-viewDidLoad"; hitCount = 0; ignoreCount = 0; - lineNumber = 54; + lineNumber = 55; location = PicCast; - modificationTime = 325398322.671623; + modificationTime = 325404898.118558; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4553,7 +4582,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 63"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1583; vrLoc = 1381; @@ -4563,7 +4592,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 63"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1429; vrLoc = 1606; @@ -4593,7 +4622,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 63"; rLen = 0; - rLoc = 2019; + rLoc = 2088; rType = 0; vrLen = 1429; vrLoc = 1606; @@ -4640,7 +4669,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 62"; rLen = 0; - rLoc = 2023; + rLoc = 2092; rType = 0; vrLen = 1354; vrLoc = 1736; @@ -4680,7 +4709,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 69"; rLen = 0; - rLoc = 2387; + rLoc = 2456; rType = 0; vrLen = 1469; vrLoc = 1497; @@ -4690,7 +4719,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 70"; rLen = 0; - rLoc = 2314; + rLoc = 2383; rType = 0; vrLen = 1151; vrLoc = 1705; @@ -4705,11 +4734,11 @@ delayBeforeContinue = 0; fileReference = 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */; functionName = "-executeUpdate:error:withArgumentsInArray:orVAList:"; - hitCount = 1; + hitCount = 0; ignoreCount = 0; lineNumber = 577; location = PicCast; - modificationTime = 325398328.658263; + modificationTime = 325404898.120866; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4718,7 +4747,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 70"; rLen = 0; - rLoc = 2314; + rLoc = 2383; rType = 0; vrLen = 1498; vrLoc = 3133; @@ -4757,7 +4786,7 @@ ignoreCount = 0; lineNumber = 497; location = PicCast; - modificationTime = 325398322.676031; + modificationTime = 325404898.123209; originalNumberOfMultipleMatches = 1; state = 2; }; @@ -4766,7 +4795,7 @@ fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; name = "TopicsViewController.m: 70"; rLen = 0; - rLoc = 2314; + rLoc = 2383; rType = 0; vrLen = 1505; vrLoc = 3219; @@ -4828,6 +4857,292 @@ vrLen = 1726; vrLoc = 13777; }; + 4EB5428913653AB6009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EE71363773B009A5AC5 /* SectionDictionary.m */; + name = "SectionDictionary.m: 30"; + rLen = 0; + rLoc = 568; + rType = 0; + vrLen = 377; + vrLoc = 401; + }; + 4EB5428A13653AB6009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */; + name = "FMDatabase.m: 816"; + rLen = 0; + rLoc = 19911; + rType = 0; + vrLen = 728; + vrLoc = 9925; + }; + 4EB54297136540A7009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EE71363773B009A5AC5 /* SectionDictionary.m */; + name = "SectionDictionary.m: 30"; + rLen = 0; + rLoc = 568; + rType = 0; + vrLen = 494; + vrLoc = 401; + }; + 4EB54298136540A7009A5AC5 /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "Request for member 'title' in something not a structure or union"; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 184; + rType = 1; + }; + 4EB54299136540A7009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 5983; + rType = 0; + vrLen = 660; + vrLoc = 5593; + }; + 4EB5429A136540A7009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */; + name = "FMDatabase.m: 816"; + rLen = 0; + rLoc = 19911; + rType = 0; + vrLen = 733; + vrLoc = 9925; + }; + 4EB5429B136540EC009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 5983; + rType = 0; + vrLen = 648; + vrLoc = 5593; + }; + 4EB5429C136540EC009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */; + name = "FMDatabase.m: 816"; + rLen = 0; + rLoc = 19911; + rType = 0; + vrLen = 733; + vrLoc = 9925; + }; + 4EB542A6136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4EB53EC5136359E3009A5AC5 /* FMDatabase.m */; + name = "FMDatabase.m: 578"; + rLen = 0; + rLoc = 15477; + rType = 0; + vrLen = 1726; + vrLoc = 13777; + }; + 4EB542A7136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E713594115001EB808 /* TopicsViewController.h */; + name = "TopicsViewController.h: 41"; + rLen = 0; + rLoc = 1436; + rType = 0; + vrLen = 1442; + vrLoc = 0; + }; + 4EB542A8136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1D3623250D0F684500981E51 /* PicCastAppDelegate.m */; + name = "PicCastAppDelegate.m: 149"; + rLen = 0; + rLoc = 5625; + rType = 0; + vrLen = 1546; + vrLoc = 552; + }; + 4EB542A9136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D4135FC4B0007FAB8D /* SourcesEditViewController.h */; + name = "SourcesEditViewController.h: 17"; + rLen = 0; + rLoc = 477; + rType = 0; + vrLen = 801; + vrLoc = 0; + }; + 4EB542AA136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 243"; + rLen = 268; + rLoc = 7445; + rType = 0; + vrLen = 1955; + vrLoc = 6531; + }; + 4EB542AB136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB856135FD34B007FAB8D /* SourcesEditViewCell.h */; + name = "SourcesEditViewCell.h: 13"; + rLen = 0; + rLoc = 265; + rType = 0; + vrLen = 344; + vrLoc = 0; + }; + 4EB542AC136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB857135FD34B007FAB8D /* SourcesEditViewCell.m */; + name = "SourcesEditViewCell.m: 14"; + rLen = 0; + rLoc = 240; + rType = 0; + vrLen = 763; + vrLoc = 0; + }; + 4EB542AD136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 127"; + rLen = 0; + rLoc = 4056; + rType = 0; + vrLen = 1796; + vrLoc = 4483; + }; + 4EB542AE136541D2009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 6051; + rType = 0; + vrLen = 1678; + vrLoc = 4595; + }; + 4EB542B31365425B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 6051; + rType = 0; + vrLen = 1678; + vrLoc = 4595; + }; + 4EB542B41365425B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 243"; + rLen = 268; + rLoc = 7445; + rType = 0; + vrLen = 1955; + vrLoc = 6531; + }; + 4EB542B51365425B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 326"; + rLen = 0; + rLoc = 10459; + rType = 0; + vrLen = 1768; + vrLoc = 9259; + }; + 4EB542BB13654359009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 326"; + rLen = 0; + rLoc = 10459; + rType = 0; + vrLen = 1768; + vrLoc = 9259; + }; + 4EB542BC13654359009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 6051; + rType = 0; + vrLen = 1678; + vrLoc = 4595; + }; + 4EB542BD13654359009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 5983; + rType = 0; + vrLen = 1750; + vrLoc = 4598; + }; + 4EB542C413654756009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + rLen = 15; + rLoc = 5665; + rType = 0; + }; + 4EB542C513654756009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 182"; + rLen = 0; + rLoc = 6051; + rType = 0; + vrLen = 1788; + vrLoc = 4794; + }; + 4EB542CD136548E0009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 26"; + rLen = 0; + rLoc = 489; + rType = 0; + vrLen = 1640; + vrLoc = 150; + }; + 4EB542D113654A2B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; + name = "SourcesEditViewController.m: 31"; + rLen = 69; + rLoc = 737; + rType = 0; + vrLen = 1661; + vrLoc = 153; + }; + 4EB542D213654A2B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 326"; + rLen = 0; + rLoc = 10459; + rType = 0; + vrLen = 1768; + vrLoc = 9259; + }; + 4EB542D313654A2B009A5AC5 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 4E6827E813594115001EB808 /* TopicsViewController.m */; + name = "TopicsViewController.m: 33"; + rLen = 0; + rLoc = 801; + rType = 0; + vrLen = 1855; + vrLoc = 494; + }; 4EBFCB481360E786005AC5CC /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 4EBFCB491360E786005AC5CC /* UIView.h */; @@ -4850,7 +5165,7 @@ fRef = 4ECFB7D4135FC4B0007FAB8D /* SourcesEditViewController.h */; name = "SourcesEditViewController.h: 18"; rLen = 62; - rLoc = 439; + rLoc = 560; rType = 0; vrLen = 680; vrLoc = 0; @@ -4859,8 +5174,8 @@ isa = PBXTextBookmark; fRef = 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */; name = "SourcesEditViewController.m: 81"; - rLen = 156; - rLoc = 1931; + rLen = 204; + rLoc = 4391; rType = 0; vrLen = 894; vrLoc = 93; @@ -4915,24 +5230,24 @@ }; 4ECFB7D4135FC4B0007FAB8D /* SourcesEditViewController.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {903, 444}}"; - sepNavSelRange = "{439, 62}"; - sepNavVisRange = "{0, 680}"; + sepNavIntBoundsRect = "{{0, 0}, {903, 600}}"; + sepNavSelRange = "{477, 0}"; + sepNavVisRange = "{0, 801}"; }; }; 4ECFB7D5135FC4B0007FAB8D /* SourcesEditViewController.m */ = { uiCtxt = { - sepNavFolds = "{\n c = (\n {\n l = DetailViewController;\n r = \"{4775, 24}\";\n s = 1;\n },\n {\n l = DetailViewController;\n r = \"{4826, 24}\";\n s = 1;\n },\n {\n l = \"Nib name\";\n r = \"{4876, 12}\";\n s = 1;\n }\n );\n r = \"{0, 5577}\";\n s = 0;\n}"; - sepNavIntBoundsRect = "{{0, 0}, {903, 2639}}"; - sepNavSelRange = "{1931, 156}"; - sepNavVisRange = "{93, 894}"; + sepNavFolds = "{\n c = (\n {\n l = DetailViewController;\n r = \"{7796, 24}\";\n s = 1;\n },\n {\n l = DetailViewController;\n r = \"{7847, 24}\";\n s = 1;\n },\n {\n l = \"Nib name\";\n r = \"{7897, 12}\";\n s = 1;\n }\n );\n r = \"{0, 8654}\";\n s = 0;\n}"; + sepNavIntBoundsRect = "{{0, 0}, {1027, 3575}}"; + sepNavSelRange = "{737, 69}"; + sepNavVisRange = "{153, 1661}"; }; }; 4ECFB856135FD34B007FAB8D /* SourcesEditViewCell.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1160, 286}}"; - sepNavSelRange = "{253, 0}"; - sepNavVisRange = "{0, 272}"; + sepNavIntBoundsRect = "{{0, 0}, {903, 600}}"; + sepNavSelRange = "{265, 0}"; + sepNavVisRange = "{0, 344}"; }; }; 4ECFB857135FD34B007FAB8D /* SourcesEditViewCell.m */ = { diff --git a/PicCast.xcodeproj/project.pbxproj b/PicCast.xcodeproj/project.pbxproj index b4d1ec5..8c9251b 100644 --- a/PicCast.xcodeproj/project.pbxproj +++ b/PicCast.xcodeproj/project.pbxproj @@ -40,6 +40,16 @@ 4EB53ED213635A22009A5AC5 /* libsqlite3.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EB53ED113635A22009A5AC5 /* libsqlite3.0.dylib */; }; 4EB53EE81363773B009A5AC5 /* SectionDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB53EE71363773B009A5AC5 /* SectionDictionary.m */; }; 4EB541F213652382009A5AC5 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EB541F113652382009A5AC5 /* libsqlite3.dylib */; }; + 4EB5427313653A50009A5AC5 /* CDataScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5425C13653A50009A5AC5 /* CDataScanner.m */; }; + 4EB5427413653A50009A5AC5 /* CFilteringJSONSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5425F13653A50009A5AC5 /* CFilteringJSONSerializer.m */; }; + 4EB5427513653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426113653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.m */; }; + 4EB5427613653A50009A5AC5 /* CJSONSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426313653A50009A5AC5 /* CJSONSerialization.m */; }; + 4EB5427713653A50009A5AC5 /* CJSONSerializedData.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426513653A50009A5AC5 /* CJSONSerializedData.m */; }; + 4EB5427813653A50009A5AC5 /* CDataScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426813653A50009A5AC5 /* CDataScanner_Extensions.m */; }; + 4EB5427913653A50009A5AC5 /* NSDictionary_JSONExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426A13653A50009A5AC5 /* NSDictionary_JSONExtensions.m */; }; + 4EB5427A13653A50009A5AC5 /* CJSONDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426D13653A50009A5AC5 /* CJSONDeserializer.m */; }; + 4EB5427B13653A50009A5AC5 /* CJSONScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5426F13653A50009A5AC5 /* CJSONScanner.m */; }; + 4EB5427C13653A50009A5AC5 /* CJSONSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB5427113653A50009A5AC5 /* CJSONSerializer.m */; }; 4EBFCAD51360D12C005AC5CC /* titleBarBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 4EBFCAD41360D12C005AC5CC /* titleBarBackground.png */; }; 4EBFCB0B1360DDB5005AC5CC /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 4EBFCB0A1360DDB5005AC5CC /* Default.png */; }; 4EBFCB261360E0D2005AC5CC /* PicCast.512.png in Resources */ = {isa = PBXBuildFile; fileRef = 4EBFCB251360E0D2005AC5CC /* PicCast.512.png */; }; @@ -274,6 +284,27 @@ 4EB53EE61363773B009A5AC5 /* SectionDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SectionDictionary.h; sourceTree = "<group>"; }; 4EB53EE71363773B009A5AC5 /* SectionDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SectionDictionary.m; sourceTree = "<group>"; }; 4EB541F113652382009A5AC5 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; + 4EB5425B13653A50009A5AC5 /* CDataScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner.h; sourceTree = "<group>"; }; + 4EB5425C13653A50009A5AC5 /* CDataScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner.m; sourceTree = "<group>"; }; + 4EB5425E13653A50009A5AC5 /* CFilteringJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFilteringJSONSerializer.h; sourceTree = "<group>"; }; + 4EB5425F13653A50009A5AC5 /* CFilteringJSONSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CFilteringJSONSerializer.m; sourceTree = "<group>"; }; + 4EB5426013653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer_BlocksExtensions.h; sourceTree = "<group>"; }; + 4EB5426113653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer_BlocksExtensions.m; sourceTree = "<group>"; }; + 4EB5426213653A50009A5AC5 /* CJSONSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerialization.h; sourceTree = "<group>"; }; + 4EB5426313653A50009A5AC5 /* CJSONSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerialization.m; sourceTree = "<group>"; }; + 4EB5426413653A50009A5AC5 /* CJSONSerializedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerializedData.h; sourceTree = "<group>"; }; + 4EB5426513653A50009A5AC5 /* CJSONSerializedData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerializedData.m; sourceTree = "<group>"; }; + 4EB5426713653A50009A5AC5 /* CDataScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner_Extensions.h; sourceTree = "<group>"; }; + 4EB5426813653A50009A5AC5 /* CDataScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner_Extensions.m; sourceTree = "<group>"; }; + 4EB5426913653A50009A5AC5 /* NSDictionary_JSONExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionary_JSONExtensions.h; sourceTree = "<group>"; }; + 4EB5426A13653A50009A5AC5 /* NSDictionary_JSONExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionary_JSONExtensions.m; sourceTree = "<group>"; }; + 4EB5426C13653A50009A5AC5 /* CJSONDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer.h; sourceTree = "<group>"; }; + 4EB5426D13653A50009A5AC5 /* CJSONDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer.m; sourceTree = "<group>"; }; + 4EB5426E13653A50009A5AC5 /* CJSONScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONScanner.h; sourceTree = "<group>"; }; + 4EB5426F13653A50009A5AC5 /* CJSONScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONScanner.m; sourceTree = "<group>"; }; + 4EB5427013653A50009A5AC5 /* CJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerializer.h; sourceTree = "<group>"; }; + 4EB5427113653A50009A5AC5 /* CJSONSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerializer.m; sourceTree = "<group>"; }; + 4EB5427213653A50009A5AC5 /* JSONRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONRepresentation.h; sourceTree = "<group>"; }; 4EBFCAD41360D12C005AC5CC /* titleBarBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = titleBarBackground.png; sourceTree = "<group>"; }; 4EBFCB0A1360DDB5005AC5CC /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; }; 4EBFCB251360E0D2005AC5CC /* PicCast.512.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PicCast.512.png; sourceTree = SOURCE_ROOT; }; @@ -350,6 +381,7 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 4EB5425A13653A50009A5AC5 /* json */, 4EB53EBE136359D5009A5AC5 /* fmdb */, 4EB53E6513634D4E009A5AC5 /* Data Managers */, 4ECFB853135FD22C007FAB8D /* Cells */, @@ -550,6 +582,59 @@ name = fmdb; sourceTree = "<group>"; }; + 4EB5425A13653A50009A5AC5 /* json */ = { + isa = PBXGroup; + children = ( + 4EB5425B13653A50009A5AC5 /* CDataScanner.h */, + 4EB5425C13653A50009A5AC5 /* CDataScanner.m */, + 4EB5425D13653A50009A5AC5 /* Experimental */, + 4EB5426613653A50009A5AC5 /* Extensions */, + 4EB5426B13653A50009A5AC5 /* JSON */, + ); + name = json; + path = Source; + sourceTree = "<group>"; + }; + 4EB5425D13653A50009A5AC5 /* Experimental */ = { + isa = PBXGroup; + children = ( + 4EB5425E13653A50009A5AC5 /* CFilteringJSONSerializer.h */, + 4EB5425F13653A50009A5AC5 /* CFilteringJSONSerializer.m */, + 4EB5426013653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.h */, + 4EB5426113653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.m */, + 4EB5426213653A50009A5AC5 /* CJSONSerialization.h */, + 4EB5426313653A50009A5AC5 /* CJSONSerialization.m */, + 4EB5426413653A50009A5AC5 /* CJSONSerializedData.h */, + 4EB5426513653A50009A5AC5 /* CJSONSerializedData.m */, + ); + path = Experimental; + sourceTree = "<group>"; + }; + 4EB5426613653A50009A5AC5 /* Extensions */ = { + isa = PBXGroup; + children = ( + 4EB5426713653A50009A5AC5 /* CDataScanner_Extensions.h */, + 4EB5426813653A50009A5AC5 /* CDataScanner_Extensions.m */, + 4EB5426913653A50009A5AC5 /* NSDictionary_JSONExtensions.h */, + 4EB5426A13653A50009A5AC5 /* NSDictionary_JSONExtensions.m */, + ); + path = Extensions; + sourceTree = "<group>"; + }; + 4EB5426B13653A50009A5AC5 /* JSON */ = { + isa = PBXGroup; + children = ( + 4EB5426C13653A50009A5AC5 /* CJSONDeserializer.h */, + 4EB5426D13653A50009A5AC5 /* CJSONDeserializer.m */, + 4EB5426E13653A50009A5AC5 /* CJSONScanner.h */, + 4EB5426F13653A50009A5AC5 /* CJSONScanner.m */, + 4EB5427013653A50009A5AC5 /* CJSONSerializer.h */, + 4EB5427113653A50009A5AC5 /* CJSONSerializer.m */, + 4EB5427213653A50009A5AC5 /* JSONRepresentation.h */, + ); + path = JSON; + sourceTree = "<group>"; + }; 4ECFB751135F8869007FAB8D /* Images */ = { isa = PBXGroup; children = ( @@ -858,6 +943,16 @@ 4EB53ECB136359E3009A5AC5 /* FMDatabase.m in Sources */, 4EB53ECC136359E3009A5AC5 /* FMResultSet.m in Sources */, 4EB53EE81363773B009A5AC5 /* SectionDictionary.m in Sources */, + 4EB5427313653A50009A5AC5 /* CDataScanner.m in Sources */, + 4EB5427413653A50009A5AC5 /* CFilteringJSONSerializer.m in Sources */, + 4EB5427513653A50009A5AC5 /* CJSONDeserializer_BlocksExtensions.m in Sources */, + 4EB5427613653A50009A5AC5 /* CJSONSerialization.m in Sources */, + 4EB5427713653A50009A5AC5 /* CJSONSerializedData.m in Sources */, + 4EB5427813653A50009A5AC5 /* CDataScanner_Extensions.m in Sources */, + 4EB5427913653A50009A5AC5 /* NSDictionary_JSONExtensions.m in Sources */, + 4EB5427A13653A50009A5AC5 /* CJSONDeserializer.m in Sources */, + 4EB5427B13653A50009A5AC5 /* CJSONScanner.m in Sources */, + 4EB5427C13653A50009A5AC5 /* CJSONSerializer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; |