From dd0aab14dec486ad63f45b405e2f71518f255f81 Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Tue, 26 Aug 2014 10:32:06 -0500 Subject: [PATCH 1/6] Error handling for mismatched collection types. --- JSONKit.m | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) mode change 100644 => 100755 JSONKit.m diff --git a/JSONKit.m b/JSONKit.m old mode 100644 new mode 100755 index 0e9331f..6b37077 --- a/JSONKit.m +++ b/JSONKit.m @@ -677,7 +677,7 @@ + (id)allocWithZone:(NSZone *)zone NSCParameterAssert((objects != NULL) && (_JKArrayClass != NULL) && (_JKArrayInstanceSize > 0UL)); JKArray *array = NULL; if(JK_EXPECT_T((array = (JKArray *)calloc(1UL, _JKArrayInstanceSize)) != NULL)) { // Directly allocate the JKArray instance via calloc. - array->isa = _JKArrayClass; + object_setClass(array, _JKArrayClass); if((array = [array init]) == NULL) { return(NULL); } array->capacity = count; array->count = count; @@ -790,6 +790,10 @@ - (void)removeObjectAtIndex:(NSUInteger)objectIndex mutations = (mutations == NSUIntegerMax) ? 1UL : mutations + 1UL; } +- (void)addObject:(id)anObject { + [self insertObject: anObject atIndex: count]; +} + - (void)replaceObjectAtIndex:(NSUInteger)objectIndex withObject:(id)anObject { if(mutations == 0UL) { [NSException raise:NSInternalInconsistencyException format:@"*** -[%@ %@]: mutating method sent to immutable object", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; } @@ -816,6 +820,11 @@ - (id)mutableCopyWithZone:(NSZone *)zone return([(NSMutableArray *)[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]); } +- (id)objectForKey:(NSString *)key { + NSLog(@"JSONKit.m-JKArray:objectForKey: - Who is calling this?"); + NSAssert(NO, @"Someone is mistaking an NSArray for an NSDictionary, calling objectForKey: %@", self); + return nil; +} @end @@ -928,7 +937,7 @@ static void _JKDictionaryResizeIfNeccessary(JKDictionary *dictionary) { NSCParameterAssert((keys != NULL) && (keyHashes != NULL) && (objects != NULL) && (_JKDictionaryClass != NULL) && (_JKDictionaryInstanceSize > 0UL)); JKDictionary *dictionary = NULL; if(JK_EXPECT_T((dictionary = (JKDictionary *)calloc(1UL, _JKDictionaryInstanceSize)) != NULL)) { // Directly allocate the JKDictionary instance via calloc. - dictionary->isa = _JKDictionaryClass; + object_setClass(dictionary, _JKDictionaryClass); if((dictionary = [dictionary init]) == NULL) { return(NULL); } dictionary->capacity = _JKDictionaryCapacityForCount(count); dictionary->count = 0UL; @@ -1103,7 +1112,13 @@ - (id)mutableCopyWithZone:(NSZone *)zone NSParameterAssert((entry != NULL) && (count <= capacity)); return([[NSMutableDictionary allocWithZone:zone] initWithDictionary:self]); } - +/* +- (id)objectAtIndex:(NSInteger)index { + NSLog(@"JSONKit.m-JKDictionary:objectAtIndex: - Who is calling this?"); + NSAssert(NO, @"Someone is mistaking an NSDictionary for an NSArray, calling objectAtIndex: %@", self); + return nil; +} +*/ @end @@ -2594,9 +2609,12 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object // // XXX XXX XXX XXX +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection" + BOOL workAroundMacOSXABIBreakingBug = (JK_EXPECT_F(((NSUInteger)object) & 0x1)) ? YES : NO; +#pragma clang diagnostic pop - BOOL workAroundMacOSXABIBreakingBug = (JK_EXPECT_F(((NSUInteger)object) & 0x1)) ? YES : NO; - void *objectISA = (JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) ? NULL : *((void **)objectPtr); + void *objectISA = (JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) ? NULL : *((void **)object); if(JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) { goto slowClassLookup; } if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; } From d08778eb471d0b0868486d47100fd5076982745d Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Mon, 11 May 2015 12:44:42 -0500 Subject: [PATCH 2/6] Updated to Xcode 6.3, fixing new warnings. --- JSONKit.m | 75 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/JSONKit.m b/JSONKit.m index 6b37077..591477b 100755 --- a/JSONKit.m +++ b/JSONKit.m @@ -2036,7 +2036,12 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { } switch(parseState->token.value.type) { - case JKValueTypeString: parsedAtom = (void *)CFStringCreateWithBytes(NULL, parseState->token.value.ptrRange.ptr, parseState->token.value.ptrRange.length, kCFStringEncodingUTF8, 0); break; + case JKValueTypeString: + { + JKConstPtrRange parsedValue = parseState->token.value.ptrRange; + parsedAtom = (void *)CFStringCreateWithBytes(NULL, parsedValue.ptr, parsedValue.length, kCFStringEncodingUTF8, 0); + break; + } case JKValueTypeLongLong: parsedAtom = (void *)CFNumberCreate(NULL, kCFNumberLongLongType, &parseState->token.value.number.longLongValue); break; case JKValueTypeUnsignedLongLong: if(parseState->token.value.number.unsignedLongLongValue <= LLONG_MAX) { parsedAtom = (void *)CFNumberCreate(NULL, kCFNumberLongLongType, &parseState->token.value.number.unsignedLongLongValue); } @@ -2608,38 +2613,38 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object // gains in the two to three percent range. // // XXX XXX XXX XXX - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-objc-pointer-introspection" - BOOL workAroundMacOSXABIBreakingBug = (JK_EXPECT_F(((NSUInteger)object) & 0x1)) ? YES : NO; -#pragma clang diagnostic pop - - void *objectISA = (JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) ? NULL : *((void **)object); - if(JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) { goto slowClassLookup; } - - if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; } - else if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.numberClass)) { isClass = JKClassNumber; } - else if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.dictionaryClass)) { isClass = JKClassDictionary; } - else if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.arrayClass)) { isClass = JKClassArray; } - else if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.nullClass)) { isClass = JKClassNull; } - else { - slowClassLookup: - if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.stringClass = objectISA; } isClass = JKClassString; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.numberClass = objectISA; } isClass = JKClassNumber; } - else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.dictionaryClass = objectISA; } isClass = JKClassDictionary; } - else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.arrayClass = objectISA; } isClass = JKClassArray; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.nullClass = objectISA; } isClass = JKClassNull; } + + if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { + isClass = JKClassString; + } + else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { + isClass = JKClassNumber; + } + else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { + isClass = JKClassDictionary; + } + else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { + isClass = JKClassArray; + } + else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { + isClass = JKClassNull; + } else { - if((rerunningAfterClassFormatter == NO) && ( -#ifdef __BLOCKS__ - ((encodeState->classFormatterBlock) && ((object = encodeState->classFormatterBlock(object)) != NULL)) || -#endif - ((encodeState->classFormatterIMP) && ((object = encodeState->classFormatterIMP(encodeState->classFormatterDelegate, encodeState->classFormatterSelector, object)) != NULL)) )) { rerunningAfterClassFormatter = YES; goto rerunAfterClassFormatter; } - - if(rerunningAfterClassFormatter == NO) { jk_encode_error(encodeState, @"Unable to serialize object class %@.", NSStringFromClass([encodeCacheObject class])); return(1); } - else { jk_encode_error(encodeState, @"Unable to serialize object class %@ that was returned by the unsupported class formatter. Original object class was %@.", (object == NULL) ? @"NULL" : NSStringFromClass([object class]), NSStringFromClass([encodeCacheObject class])); return(1); } + if((rerunningAfterClassFormatter == NO) && + (((encodeState->classFormatterBlock) && + ((object = encodeState->classFormatterBlock(object)) != NULL)) || + ((encodeState->classFormatterIMP) && ((object = encodeState->classFormatterIMP(encodeState->classFormatterDelegate, encodeState->classFormatterSelector, object)) != NULL)) )) + { + rerunningAfterClassFormatter = YES; goto rerunAfterClassFormatter; + } + + if(rerunningAfterClassFormatter == NO) { + jk_encode_error(encodeState, @"Unable to serialize object class %@.", NSStringFromClass([encodeCacheObject class])); return(1); + } + else { + jk_encode_error(encodeState, @"Unable to serialize object class %@ that was returned by the unsupported class formatter. Original object class was %@.", (object == NULL) ? @"NULL" : NSStringFromClass([object class]), NSStringFromClass([encodeCacheObject class])); return(1); + } } - } // This is here for the benefit of the optimizer. It allows the optimizer to do loop invariant code motion for the JKClassArray // and JKClassDictionary cases when printing simple, single characters via jk_encode_write(), which is actually a macro: @@ -2810,9 +2815,8 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object for(id keyObject in enumerateObject) { if(JK_EXPECT_T(printComma)) { if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ","))) { return(1); } } printComma = 1; - void *keyObjectISA = *((void **)keyObject); - if(JK_EXPECT_F((keyObjectISA != encodeState->fastClassLookup.stringClass)) && JK_EXPECT_F(([keyObject isKindOfClass:[NSString class]] == NO))) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); } - if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, keyObject))) { return(1); } + if(JK_EXPECT_F(([keyObject isKindOfClass:[NSString class]] == NO))) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); } + if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, keyObject))) { return(1); } if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ":"))) { return(1); } if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, (void *)CFDictionaryGetValue((CFDictionaryRef)object, keyObject)))) { return(1); } } @@ -2822,8 +2826,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object for(idx = 0L; idx < dictionaryCount; idx++) { if(JK_EXPECT_T(printComma)) { if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ","))) { return(1); } } printComma = 1; - void *keyObjectISA = *((void **)keys[idx]); - if(JK_EXPECT_F(keyObjectISA != encodeState->fastClassLookup.stringClass) && JK_EXPECT_F([(id)keys[idx] isKindOfClass:[NSString class]] == NO)) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); } + if(JK_EXPECT_F([(id)keys[idx] isKindOfClass:[NSString class]] == NO)) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); } if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, keys[idx]))) { return(1); } if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ":"))) { return(1); } if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, objects[idx]))) { return(1); } From 4a095e3886cdecc7e8545f7da80148c2fc4c6116 Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Thu, 3 Nov 2016 17:28:23 -0500 Subject: [PATCH 3/6] Updated to modern Obj-C syntax --- JSONKit.h | 32 ++++++++++---------- JSONKit.m | 87 ++++++++++++++++++++++++++----------------------------- 2 files changed, 56 insertions(+), 63 deletions(-) diff --git a/JSONKit.h b/JSONKit.h index 71bd0c3..73ba711 100644 --- a/JSONKit.h +++ b/JSONKit.h @@ -114,7 +114,7 @@ typedef NSUInteger JKFlags; Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER". */ -enum { +typedef NS_OPTIONS(NSUInteger, JKParseOptionFlags) { JKParseOptionNone = 0, JKParseOptionStrict = 0, JKParseOptionComments = (1 << 0), @@ -123,16 +123,14 @@ enum { JKParseOptionPermitTextAfterValidJSON = (1 << 3), JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON), }; -typedef JKFlags JKParseOptionFlags; -enum { +typedef NS_OPTIONS(NSUInteger, JKSerializeOptionFlags) { JKSerializeOptionNone = 0, JKSerializeOptionPretty = (1 << 0), JKSerializeOptionEscapeUnicode = (1 << 1), JKSerializeOptionEscapeForwardSlashes = (1 << 4), JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode | JKSerializeOptionEscapeForwardSlashes), }; -typedef JKFlags JKSerializeOptionFlags; #ifdef __OBJC__ @@ -143,9 +141,9 @@ typedef struct JKParseState JKParseState; // Opaque internal, private type. @interface JSONDecoder : NSObject { JKParseState *parseState; } -+ (id)decoder; -+ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags; -- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags; ++ (instancetype)decoder; ++ (instancetype)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags; +- (instancetype)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags NS_DESIGNATED_INITIALIZER; - (void)clearCache; // The parse... methods were deprecated in v1.4 in favor of the v1.4 objectWith... methods. @@ -176,20 +174,20 @@ typedef struct JKParseState JKParseState; // Opaque internal, private type. //////////// @interface NSString (JSONKitDeserializing) -- (id)objectFromJSONString; +@property (NS_NONATOMIC_IOSONLY, readonly, strong) id objectFromJSONString; - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; -- (id)mutableObjectFromJSONString; +@property (NS_NONATOMIC_IOSONLY, readonly, strong) id mutableObjectFromJSONString; - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; @end @interface NSData (JSONKitDeserializing) // The NSData MUST be UTF8 encoded JSON. -- (id)objectFromJSONData; +@property (NS_NONATOMIC_IOSONLY, readonly, strong) id objectFromJSONData; - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; -- (id)mutableObjectFromJSONData; +@property (NS_NONATOMIC_IOSONLY, readonly, strong) id mutableObjectFromJSONData; - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; @end @@ -203,26 +201,26 @@ typedef struct JKParseState JKParseState; // Opaque internal, private type. // Normally, a string that is serialized to JSON has quotation marks surrounding it, which you may or may not want when serializing a single string, and can be controlled with includeQuotes: // includeQuotes:YES `a "test"...` -> `"a \"test\"..."` // includeQuotes:NO `a "test"...` -> `a \"test\"...` -- (NSData *)JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSData *JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error; -- (NSString *)JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error; @end @interface NSArray (JSONKitSerializing) -- (NSData *)JSONData; +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSData *JSONData; - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; -- (NSString *)JSONString; +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *JSONString; - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; @end @interface NSDictionary (JSONKitSerializing) -- (NSData *)JSONData; +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSData *JSONData; - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; - (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; -- (NSString *)JSONString; +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *JSONString; - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error; - (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions serializeUnsupportedClassesUsingDelegate:(id)delegate selector:(SEL)selector error:(NSError **)error; @end diff --git a/JSONKit.m b/JSONKit.m index 591477b..bb4f42e 100755 --- a/JSONKit.m +++ b/JSONKit.m @@ -276,7 +276,7 @@ The code in isValidCodePoint() is derived from the ICU code in JKClassNull = 5, }; -enum { +typedef NS_OPTIONS(NSUInteger, JKManagedBufferFlags) { JKManagedBufferOnStack = 1, JKManagedBufferOnHeap = 2, JKManagedBufferLocationMask = (0x3), @@ -284,9 +284,8 @@ The code in isValidCodePoint() is derived from the ICU code in JKManagedBufferMustFree = (1 << 2), }; -typedef JKFlags JKManagedBufferFlags; -enum { +typedef NS_OPTIONS(NSUInteger, JKObjectStackFlags) { JKObjectStackOnStack = 1, JKObjectStackOnHeap = 2, JKObjectStackLocationMask = (0x3), @@ -294,9 +293,8 @@ The code in isValidCodePoint() is derived from the ICU code in JKObjectStackMustFree = (1 << 2), }; -typedef JKFlags JKObjectStackFlags; -enum { +typedef NS_ENUM(NSUInteger, JKTokenType) { JKTokenTypeInvalid = 0, JKTokenTypeNumber = 1, JKTokenTypeString = 2, @@ -311,19 +309,17 @@ The code in isValidCodePoint() is derived from the ICU code in JKTokenTypeNull = 11, JKTokenTypeWhiteSpace = 12, }; -typedef NSUInteger JKTokenType; // These are prime numbers to assist with hash slot probing. -enum { +typedef NS_ENUM(NSUInteger, JKValueType) { JKValueTypeNone = 0, JKValueTypeString = 5, JKValueTypeLongLong = 7, JKValueTypeUnsignedLongLong = 11, JKValueTypeDouble = 13, }; -typedef NSUInteger JKValueType; -enum { +typedef NS_OPTIONS(NSUInteger, JKEncodeOptionType) { JKEncodeOptionAsData = 1, JKEncodeOptionAsString = 2, JKEncodeOptionAsTypeMask = 0x7, @@ -332,7 +328,6 @@ The code in isValidCodePoint() is derived from the ICU code in JKEncodeOptionStringObjTrimQuotes = (1 << 5), }; -typedef NSUInteger JKEncodeOptionType; typedef NSUInteger JKHash; @@ -510,12 +505,12 @@ - (void)releaseState; typedef uint16_t UTF16; /* at least 16 bits */ typedef uint8_t UTF8; /* typically 8 bits */ -typedef enum { +typedef NS_ENUM(unsigned int, ConversionResult) { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ targetExhausted, /* insuff. room in target for conversion */ sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; +}; #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD #define UNI_MAX_BMP (UTF32)0x0000FFFF @@ -834,15 +829,21 @@ @interface JKDictionaryEnumerator : NSEnumerator { NSUInteger nextObject; } -- (id)initWithJKDictionary:(JKDictionary *)initDictionary; -- (NSArray *)allObjects; -- (id)nextObject; +- (instancetype)initWithJKDictionary:(JKDictionary *)initDictionary NS_DESIGNATED_INITIALIZER; +@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSArray *allObjects; +@property (NS_NONATOMIC_IOSONLY, readonly, strong) id nextObject; @end @implementation JKDictionaryEnumerator -- (id)initWithJKDictionary:(JKDictionary *)initDictionary +- (instancetype)init +{ + self = [self initWithJKDictionary:nil]; // throws an exception on nil, so don't use this + return self; +} + +- (instancetype)initWithJKDictionary:(JKDictionary *)initDictionary { NSParameterAssert(initDictionary != NULL); if((self = [super init]) == NULL) { return(NULL); } @@ -859,7 +860,7 @@ - (void)dealloc - (NSArray *)allObjects { NSParameterAssert(collection != NULL); - NSUInteger count = [(NSDictionary *)collection count], atObject = 0UL; + NSUInteger count = ((NSDictionary *)collection).count, atObject = 0UL; id objects[count]; while((objects[atObject] = [self nextObject]) != NULL) { NSParameterAssert(atObject < count); atObject++; } @@ -1155,13 +1156,9 @@ static void jk_error(JKParseState *parseState, NSString *format, ...) { if(parseState->error == NULL) { parseState->error = [NSError errorWithDomain:@"JKErrorDomain" code:-1L userInfo: - [NSDictionary dictionaryWithObjectsAndKeys: - formatString, NSLocalizedDescriptionKey, - [NSNumber numberWithUnsignedLong:parseState->atIndex], @"JKAtIndexKey", - [NSNumber numberWithUnsignedLong:parseState->lineNumber], @"JKLineNumberKey", - //lineString, @"JKErrorLine0Key", - //carretString, @"JKErrorLine1Key", - NULL]]; + @{NSLocalizedDescriptionKey: formatString, + @"JKAtIndexKey": @(parseState->atIndex), + @"JKLineNumberKey": @(parseState->lineNumber)}]; } } @@ -1471,7 +1468,7 @@ static int jk_parse_string(JKParseState *parseState) { onlySimpleString = 0; stringState = JSONStringStateParsing; tokenBufferIdx = (atStringCharacter - stringStart) - 1L; - if(JK_EXPECT_F((tokenBufferIdx + 16UL) > parseState->token.tokenBuffer.bytes.length)) { if((tokenBuffer = jk_managedBuffer_resize(&parseState->token.tokenBuffer, tokenBufferIdx + 1024UL)) == NULL) { jk_error(parseState, @"Internal error: Unable to resize temporary buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } + if(JK_EXPECT_F((tokenBufferIdx + 16UL) > parseState->token.tokenBuffer.bytes.length)) { if((tokenBuffer = jk_managedBuffer_resize(&parseState->token.tokenBuffer, tokenBufferIdx + 1024UL)) == NULL) { jk_error(parseState, @"Internal error: Unable to resize temporary buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } memcpy(tokenBuffer, stringStart, tokenBufferIdx); goto slowMatch; } @@ -1485,7 +1482,7 @@ static int jk_parse_string(JKParseState *parseState) { slowMatch: for(atStringCharacter = (stringStart + ((atStringCharacter - stringStart) - 1L)); (atStringCharacter < endOfBuffer) && (tokenBufferIdx < parseState->token.tokenBuffer.bytes.length); atStringCharacter++) { - if((tokenBufferIdx + 16UL) > parseState->token.tokenBuffer.bytes.length) { if((tokenBuffer = jk_managedBuffer_resize(&parseState->token.tokenBuffer, tokenBufferIdx + 1024UL)) == NULL) { jk_error(parseState, @"Internal error: Unable to resize temporary buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } + if((tokenBufferIdx + 16UL) > parseState->token.tokenBuffer.bytes.length) { if((tokenBuffer = jk_managedBuffer_resize(&parseState->token.tokenBuffer, tokenBufferIdx + 1024UL)) == NULL) { jk_error(parseState, @"Internal error: Unable to resize temporary buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } NSCParameterAssert(tokenBufferIdx < parseState->token.tokenBuffer.bytes.length); @@ -1507,7 +1504,7 @@ static int jk_parse_string(JKParseState *parseState) { if(JK_EXPECT_F((result = ConvertSingleCodePointInUTF8(atStringCharacter, endOfBuffer, (UTF8 const **)&nextValidCharacter, &u32ch)) != conversionOK)) { if((result == sourceIllegal) && ((parseState->parseOptionFlags & JKParseOptionLooseUnicode) == 0)) { jk_error(parseState, @"Illegal UTF8 sequence found in \"\" string."); stringState = JSONStringStateError; goto finishedParsing; } if(result == sourceExhausted) { jk_error(parseState, @"End of buffer reached while parsing UTF8 in \"\" string."); stringState = JSONStringStateError; goto finishedParsing; } - if(jk_string_add_unicodeCodePoint(parseState, u32ch, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } + if(jk_string_add_unicodeCodePoint(parseState, u32ch, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } atStringCharacter = nextValidCharacter - 1; continue; } else { @@ -1588,7 +1585,7 @@ static int jk_parse_string(JKParseState *parseState) { if((stringState == JSONStringStateEscapedUnicode4) || (stringState == JSONStringStateEscapedUnicodeSurrogate4)) { if((isValidCodePoint(&escapedUnicodeCodePoint) == sourceIllegal) && ((parseState->parseOptionFlags & JKParseOptionLooseUnicode) == 0)) { jk_error(parseState, @"Illegal \\u Unicode escape sequence."); stringState = JSONStringStateError; goto finishedParsing; } stringState = JSONStringStateParsing; - if(jk_string_add_unicodeCodePoint(parseState, escapedUnicodeCodePoint, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } + if(jk_string_add_unicodeCodePoint(parseState, escapedUnicodeCodePoint, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } else if((stringState >= JSONStringStateEscapedUnicode1) && (stringState <= JSONStringStateEscapedUnicodeSurrogate4)) { stringState++; } break; @@ -1602,7 +1599,7 @@ static int jk_parse_string(JKParseState *parseState) { if(currentChar == '\\') { stringState = JSONStringStateEscapedNeedEscapedUForSurrogate; } else { if((parseState->parseOptionFlags & JKParseOptionLooseUnicode) == 0) { jk_error(parseState, @"Required a second \\u Unicode escape sequence following a surrogate \\u Unicode escape sequence."); stringState = JSONStringStateError; goto finishedParsing; } - else { stringState = JSONStringStateParsing; atStringCharacter--; if(jk_string_add_unicodeCodePoint(parseState, UNI_REPLACEMENT_CHAR, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } + else { stringState = JSONStringStateParsing; atStringCharacter--; if(jk_string_add_unicodeCodePoint(parseState, UNI_REPLACEMENT_CHAR, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } } break; @@ -1610,11 +1607,11 @@ static int jk_parse_string(JKParseState *parseState) { if(currentChar == 'u') { stringState = JSONStringStateEscapedUnicodeSurrogate1; } else { if((parseState->parseOptionFlags & JKParseOptionLooseUnicode) == 0) { jk_error(parseState, @"Required a second \\u Unicode escape sequence following a surrogate \\u Unicode escape sequence."); stringState = JSONStringStateError; goto finishedParsing; } - else { stringState = JSONStringStateParsing; atStringCharacter -= 2; if(jk_string_add_unicodeCodePoint(parseState, UNI_REPLACEMENT_CHAR, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } + else { stringState = JSONStringStateParsing; atStringCharacter -= 2; if(jk_string_add_unicodeCodePoint(parseState, UNI_REPLACEMENT_CHAR, &tokenBufferIdx, &stringHash)) { jk_error(parseState, @"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; } } } break; - default: jk_error(parseState, @"Internal error: Unknown stringState. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; break; + default: jk_error(parseState, @"Internal error: Unknown stringState. %@ line #%ld", @__FILE__, (long)__LINE__); stringState = JSONStringStateError; goto finishedParsing; break; } } } @@ -1720,7 +1717,7 @@ static int jk_parse_number(JKParseState *parseState) { case JKValueTypeDouble: jk_error(parseState, @"The value '%s' could not be represented as a 'double' due to %s.", numberTempBuf, (parseState->token.value.number.doubleValue == 0.0) ? "underflow" : "overflow"); break; // see above for == 0.0. case JKValueTypeLongLong: jk_error(parseState, @"The value '%s' exceeded the minimum value that could be represented: %lld.", numberTempBuf, parseState->token.value.number.longLongValue); break; case JKValueTypeUnsignedLongLong: jk_error(parseState, @"The value '%s' exceeded the maximum value that could be represented: %llu.", numberTempBuf, parseState->token.value.number.unsignedLongLongValue); break; - default: jk_error(parseState, @"Internal error: Unknown token value type. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); break; + default: jk_error(parseState, @"Internal error: Unknown token value type. %@ line #%ld", @__FILE__, (long)__LINE__); break; } } } @@ -1848,7 +1845,7 @@ static void jk_error_parse_accept_or3(JKParseState *parseState, int state, NSStr void *parsedArray = NULL; while(JK_EXPECT_T((JK_EXPECT_T(stopParsing == 0)) && (JK_EXPECT_T(parseState->atIndex < parseState->stringBuffer.bytes.length)))) { - if(JK_EXPECT_F(parseState->objectStack.index > (parseState->objectStack.count - 4UL))) { if(jk_objectStack_resize(&parseState->objectStack, parseState->objectStack.count + 128UL)) { jk_error(parseState, @"Internal error: [array] objectsIndex > %zu, resize failed? %@ line %#ld", (parseState->objectStack.count - 4UL), [NSString stringWithUTF8String:__FILE__], (long)__LINE__); break; } } + if(JK_EXPECT_F(parseState->objectStack.index > (parseState->objectStack.count - 4UL))) { if(jk_objectStack_resize(&parseState->objectStack, parseState->objectStack.count + 128UL)) { jk_error(parseState, @"Internal error: [array] objectsIndex > %zu, resize failed? %@ line %#ld", (parseState->objectStack.count - 4UL), @__FILE__, (long)__LINE__); break; } } if(JK_EXPECT_T((stopParsing = jk_parse_next_token(parseState)) == 0)) { void *object = NULL; @@ -1899,7 +1896,7 @@ static void jk_error_parse_accept_or3(JKParseState *parseState, int state, NSStr void *parsedDictionary = NULL; while(JK_EXPECT_T((JK_EXPECT_T(stopParsing == 0)) && (JK_EXPECT_T(parseState->atIndex < parseState->stringBuffer.bytes.length)))) { - if(JK_EXPECT_F(parseState->objectStack.index > (parseState->objectStack.count - 4UL))) { if(jk_objectStack_resize(&parseState->objectStack, parseState->objectStack.count + 128UL)) { jk_error(parseState, @"Internal error: [dictionary] objectsIndex > %zu, resize failed? %@ line #%ld", (parseState->objectStack.count - 4UL), [NSString stringWithUTF8String:__FILE__], (long)__LINE__); break; } } + if(JK_EXPECT_F(parseState->objectStack.index > (parseState->objectStack.count - 4UL))) { if(jk_objectStack_resize(&parseState->objectStack, parseState->objectStack.count + 128UL)) { jk_error(parseState, @"Internal error: [dictionary] objectsIndex > %zu, resize failed? %@ line #%ld", (parseState->objectStack.count - 4UL), @__FILE__, (long)__LINE__); break; } } size_t objectStackIndex = parseState->objectStack.index++; parseState->objectStack.keys[objectStackIndex] = NULL; @@ -2048,7 +2045,7 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { else { parsedAtom = (void *)parseState->objCImpCache.NSNumberInitWithUnsignedLongLong(parseState->objCImpCache.NSNumberAlloc(parseState->objCImpCache.NSNumberClass, @selector(alloc)), @selector(initWithUnsignedLongLong:), parseState->token.value.number.unsignedLongLongValue); } break; case JKValueTypeDouble: parsedAtom = (void *)CFNumberCreate(NULL, kCFNumberDoubleType, &parseState->token.value.number.doubleValue); break; - default: jk_error(parseState, @"Internal error: Unknown token value type. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); break; + default: jk_error(parseState, @"Internal error: Unknown token value type. %@ line #%ld", @__FILE__, (long)__LINE__); break; } if(JK_EXPECT_T(setBucket) && (JK_EXPECT_T(parsedAtom != NULL))) { @@ -2088,7 +2085,7 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { case JKTokenTypeTrue: parsedAtom = (void *)kCFBooleanTrue; break; case JKTokenTypeFalse: parsedAtom = (void *)kCFBooleanFalse; break; case JKTokenTypeNull: parsedAtom = (void *)kCFNull; break; - default: jk_error(parseState, @"Internal error: Unknown token type. %@ line #%ld", [NSString stringWithUTF8String:__FILE__], (long)__LINE__); break; + default: jk_error(parseState, @"Internal error: Unknown token type. %@ line #%ld", @__FILE__, (long)__LINE__); break; } return(parsedAtom); @@ -2097,22 +2094,22 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { #pragma mark - @implementation JSONDecoder -+ (id)decoder ++ (instancetype)decoder { return([self decoderWithParseOptions:JKParseOptionStrict]); } -+ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags ++ (instancetype)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags { return([[[self alloc] initWithParseOptions:parseOptionFlags] autorelease]); } -- (id)init +- (instancetype)init { return([self initWithParseOptions:JKParseOptionStrict]); } -- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags +- (instancetype)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags { if((self = [super init]) == NULL) { return(NULL); } @@ -2272,7 +2269,7 @@ - (id)objectWithData:(NSData *)jsonData - (id)objectWithData:(NSData *)jsonData error:(NSError **)error { if(jsonData == NULL) { [NSException raise:NSInvalidArgumentException format:@"The jsonData argument is NULL."]; } - return([self objectWithUTF8String:(const unsigned char *)[jsonData bytes] length:[jsonData length] error:error]); + return([self objectWithUTF8String:(const unsigned char *)jsonData.bytes length:jsonData.length error:error]); } //////////// @@ -2300,7 +2297,7 @@ - (id)mutableObjectWithData:(NSData *)jsonData - (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error { if(jsonData == NULL) { [NSException raise:NSInvalidArgumentException format:@"The jsonData argument is NULL."]; } - return([self mutableObjectWithUTF8String:(const unsigned char *)[jsonData bytes] length:[jsonData length] error:error]); + return([self mutableObjectWithUTF8String:(const unsigned char *)jsonData.bytes length:jsonData.length error:error]); } @end @@ -2355,7 +2352,7 @@ static id _NSStringObjectFromJSONString(NSString *jsonString, JKParseOptionFlags CFIndex usedBytes = 0L, convertedCount = 0L; convertedCount = CFStringGetBytes((CFStringRef)jsonString, CFRangeMake(0L, stringLength), kCFStringEncodingUTF8, '?', NO, utf8String, (NSUInteger)stringUTF8Length, &usedBytes); - if(JK_EXPECT_F(convertedCount != stringLength) || JK_EXPECT_F(usedBytes < 0L)) { if(error != NULL) { *error = [NSError errorWithDomain:@"JKErrorDomain" code:-1L userInfo:[NSDictionary dictionaryWithObject:@"An error occurred converting the contents of a NSString to UTF8." forKey:NSLocalizedDescriptionKey]]; } goto exitNow; } + if(JK_EXPECT_F(convertedCount != stringLength) || JK_EXPECT_F(usedBytes < 0L)) { if(error != NULL) { *error = [NSError errorWithDomain:@"JKErrorDomain" code:-1L userInfo:@{NSLocalizedDescriptionKey: @"An error occurred converting the contents of a NSString to UTF8."}]; } goto exitNow; } if(mutableCollection == NO) { returnObject = [(decoder = [JSONDecoder decoderWithParseOptions:parseOptionFlags]) objectWithUTF8String:(const unsigned char *)utf8String length:(size_t)usedBytes error:error]; } else { returnObject = [(decoder = [JSONDecoder decoderWithParseOptions:parseOptionFlags]) mutableObjectWithUTF8String:(const unsigned char *)utf8String length:(size_t)usedBytes error:error]; } @@ -2455,9 +2452,7 @@ static void jk_encode_error(JKEncodeState *encodeState, NSString *format, ...) { if(encodeState->error == NULL) { encodeState->error = [NSError errorWithDomain:@"JKErrorDomain" code:-1L userInfo: - [NSDictionary dictionaryWithObjectsAndKeys: - formatString, NSLocalizedDescriptionKey, - NULL]]; + @{NSLocalizedDescriptionKey: formatString}]; } } From fb95639b503f04067ae163a102cfef46e4a99fe4 Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Sat, 5 Nov 2016 01:38:09 -0500 Subject: [PATCH 4/6] Switch to @autoreleasepool --- JSONKit.m | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/JSONKit.m b/JSONKit.m index bb4f42e..c45fde3 100755 --- a/JSONKit.m +++ b/JSONKit.m @@ -117,7 +117,6 @@ The code in isValidCodePoint() is derived from the ICU code in //#import #import -#import #import #import #import @@ -630,31 +629,29 @@ typedef NS_ENUM(unsigned int, ConversionResult) { extern void jk_collectionClassLoadTimeInitialization(void) __attribute__ ((constructor)); void jk_collectionClassLoadTimeInitialization(void) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Though technically not required, the run time environment at load time initialization may be less than ideal. - - _JKArrayClass = objc_getClass("JKArray"); - _JKArrayInstanceSize = jk_max(16UL, class_getInstanceSize(_JKArrayClass)); - - _JKDictionaryClass = objc_getClass("JKDictionary"); - _JKDictionaryInstanceSize = jk_max(16UL, class_getInstanceSize(_JKDictionaryClass)); - - // For JSONDecoder... - _jk_NSNumberClass = [NSNumber class]; - _jk_NSNumberAllocImp = (NSNumberAllocImp)[NSNumber methodForSelector:@selector(alloc)]; - - // Hacktacular. Need to do it this way due to the nature of class clusters. - id temp_NSNumber = [NSNumber alloc]; - _jk_NSNumberInitWithUnsignedLongLongImp = (NSNumberInitWithUnsignedLongLongImp)[temp_NSNumber methodForSelector:@selector(initWithUnsignedLongLong:)]; - [[temp_NSNumber init] release]; - temp_NSNumber = NULL; - - [pool release]; pool = NULL; + @autoreleasepool { + _JKArrayClass = objc_getClass("JKArray"); + _JKArrayInstanceSize = jk_max(16UL, class_getInstanceSize(_JKArrayClass)); + + _JKDictionaryClass = objc_getClass("JKDictionary"); + _JKDictionaryInstanceSize = jk_max(16UL, class_getInstanceSize(_JKDictionaryClass)); + + // For JSONDecoder... + _jk_NSNumberClass = [NSNumber class]; + _jk_NSNumberAllocImp = (NSNumberAllocImp)[NSNumber methodForSelector:@selector(alloc)]; + + // Hacktacular. Need to do it this way due to the nature of class clusters. + id temp_NSNumber = [NSNumber alloc]; + _jk_NSNumberInitWithUnsignedLongLongImp = (NSNumberInitWithUnsignedLongLongImp)[temp_NSNumber methodForSelector:@selector(initWithUnsignedLongLong:)]; + [[temp_NSNumber init] release]; + temp_NSNumber = NULL; + } } #pragma mark - @interface JKArray : NSMutableArray { - id *objects; + id *objects; NSUInteger count, capacity, mutations; } @end From cf0f812005559da9b673525f896a2196443d4f00 Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Fri, 6 Jan 2017 08:59:14 -0600 Subject: [PATCH 5/6] Help stop multiple #imports --- JSONKit.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/JSONKit.h b/JSONKit.h index 73ba711..53caed3 100644 --- a/JSONKit.h +++ b/JSONKit.h @@ -53,6 +53,9 @@ limitations under the License. */ +#ifndef JSONKit_h +#define JSONKit_h "JSONKit.h" + #include #include #include @@ -247,3 +250,5 @@ typedef struct JKParseState JKParseState; // Opaque internal, private type. #ifdef __cplusplus } // extern "C" #endif + +#endif From efb9628aade6f770434d445789b6cb389f5f9f9e Mon Sep 17 00:00:00 2001 From: Greg Combs Date: Fri, 3 Feb 2017 11:25:50 -0600 Subject: [PATCH 6/6] OCD-related cleanup --- JSONKit.h | 8 ++++---- JSONKit.m | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/JSONKit.h b/JSONKit.h index 53caed3..4fdf6cc 100644 --- a/JSONKit.h +++ b/JSONKit.h @@ -177,20 +177,20 @@ typedef struct JKParseState JKParseState; // Opaque internal, private type. //////////// @interface NSString (JSONKitDeserializing) -@property (NS_NONATOMIC_IOSONLY, readonly, strong) id objectFromJSONString; +- (id)objectFromJSONString; - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; -@property (NS_NONATOMIC_IOSONLY, readonly, strong) id mutableObjectFromJSONString; +- (id)mutableObjectFromJSONString; - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; @end @interface NSData (JSONKitDeserializing) // The NSData MUST be UTF8 encoded JSON. -@property (NS_NONATOMIC_IOSONLY, readonly, strong) id objectFromJSONData; +- (id)objectFromJSONData; - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; -@property (NS_NONATOMIC_IOSONLY, readonly, strong) id mutableObjectFromJSONData; +- (id)mutableObjectFromJSONData; - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags; - (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error; @end diff --git a/JSONKit.m b/JSONKit.m index c45fde3..6533a4f 100755 --- a/JSONKit.m +++ b/JSONKit.m @@ -628,7 +628,8 @@ typedef NS_ENUM(unsigned int, ConversionResult) { extern void jk_collectionClassLoadTimeInitialization(void) __attribute__ ((constructor)); -void jk_collectionClassLoadTimeInitialization(void) { +void jk_collectionClassLoadTimeInitialization(void) +{ @autoreleasepool { _JKArrayClass = objc_getClass("JKArray"); _JKArrayInstanceSize = jk_max(16UL, class_getInstanceSize(_JKArrayClass)); @@ -650,7 +651,8 @@ void jk_collectionClassLoadTimeInitialization(void) { #pragma mark - -@interface JKArray : NSMutableArray { +@interface JKArray : NSMutableArray +{ id *objects; NSUInteger count, capacity, mutations; }