Skip to content

Commit 0aff3de

Browse files
committed
Merge branch 'master' of github.com:johnezang/JSONKit
2 parents 2388b6f + e3f9017 commit 0aff3de

File tree

1 file changed

+55
-18
lines changed

1 file changed

+55
-18
lines changed

JSONKit.m

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -692,14 +692,14 @@ + (id)allocWithZone:(NSZone *)zone
692692
static void _JKArrayInsertObjectAtIndex(JKArray *array, id newObject, NSUInteger objectIndex) {
693693
NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex <= array->count) && (newObject != NULL));
694694
if(!((array != NULL) && (array->objects != NULL) && (objectIndex <= array->count) && (newObject != NULL))) { [newObject autorelease]; return; }
695-
array->count++;
696-
if(array->count >= array->capacity) {
697-
array->capacity += 16UL;
695+
if((array->count + 1UL) >= array->capacity) {
698696
id *newObjects = NULL;
699-
if((newObjects = (id *)realloc(array->objects, sizeof(id) * array->capacity)) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; }
697+
if((newObjects = (id *)realloc(array->objects, sizeof(id) * (array->capacity + 16UL))) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; }
700698
array->objects = newObjects;
699+
array->capacity += 16UL;
701700
memset(&array->objects[array->count], 0, sizeof(id) * (array->capacity - array->count));
702701
}
702+
array->count++;
703703
if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex + 1UL], &array->objects[objectIndex], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[objectIndex] = NULL; }
704704
array->objects[objectIndex] = newObject;
705705
}
@@ -714,11 +714,11 @@ static void _JKArrayReplaceObjectAtIndexWithObject(JKArray *array, NSUInteger ob
714714
}
715715

716716
static void _JKArrayRemoveObjectAtIndex(JKArray *array, NSUInteger objectIndex) {
717-
NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL));
718-
if(!((array != NULL) && (array->objects != NULL) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; }
717+
NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL));
718+
if(!((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; }
719719
CFRelease(array->objects[objectIndex]);
720720
array->objects[objectIndex] = NULL;
721-
if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex], &array->objects[objectIndex + 1UL], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[array->count] = NULL; }
721+
if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex], &array->objects[objectIndex + 1UL], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[array->count - 1UL] = NULL; }
722722
array->count--;
723723
}
724724

@@ -805,13 +805,13 @@ - (void)replaceObjectAtIndex:(NSUInteger)objectIndex withObject:(id)anObject
805805
- (id)copyWithZone:(NSZone *)zone
806806
{
807807
NSParameterAssert((objects != NULL) && (count <= capacity));
808-
return((mutations == 0UL) ? [self retain] : [[NSArray allocWithZone:zone] initWithObjects:objects count:count]);
808+
return((mutations == 0UL) ? [self retain] : [(NSArray *)[NSArray allocWithZone:zone] initWithObjects:objects count:count]);
809809
}
810810

811811
- (id)mutableCopyWithZone:(NSZone *)zone
812812
{
813813
NSParameterAssert((objects != NULL) && (count <= capacity));
814-
return([[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]);
814+
return([(NSMutableArray *)[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]);
815815
}
816816

817817
@end
@@ -848,7 +848,7 @@ - (void)dealloc
848848
- (NSArray *)allObjects
849849
{
850850
NSParameterAssert(collection != NULL);
851-
NSUInteger count = [collection count], atObject = 0UL;
851+
NSUInteger count = [(NSDictionary *)collection count], atObject = 0UL;
852852
id objects[count];
853853

854854
while((objects[atObject] = [self nextObject]) != NULL) { NSParameterAssert(atObject < count); atObject++; }
@@ -2004,7 +2004,7 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) {
20042004
for(x = 0UL; x < JK_CACHE_PROBES; x++) {
20052005
if(JK_EXPECT_F(parseState->cache.items[bucket].object == NULL)) { setBucket = 1UL; useableBucket = bucket; break; }
20062006

2007-
if((JK_EXPECT_T(parseState->cache.items[bucket].hash == parseState->token.value.hash)) && (JK_EXPECT_T(parseState->cache.items[bucket].size == parseState->token.value.ptrRange.length)) && (JK_EXPECT_T(parseState->cache.items[bucket].type == parseState->token.value.type)) && (JK_EXPECT_T(parseState->cache.items[bucket].bytes != NULL)) && (JK_EXPECT_T(strncmp((const char *)parseState->cache.items[bucket].bytes, (const char *)parseState->token.value.ptrRange.ptr, parseState->token.value.ptrRange.length) == 0U))) {
2007+
if((JK_EXPECT_T(parseState->cache.items[bucket].hash == parseState->token.value.hash)) && (JK_EXPECT_T(parseState->cache.items[bucket].size == parseState->token.value.ptrRange.length)) && (JK_EXPECT_T(parseState->cache.items[bucket].type == parseState->token.value.type)) && (JK_EXPECT_T(parseState->cache.items[bucket].bytes != NULL)) && (JK_EXPECT_T(memcmp(parseState->cache.items[bucket].bytes, parseState->token.value.ptrRange.ptr, parseState->token.value.ptrRange.length) == 0U))) {
20082008
parseState->cache.age[bucket] = (parseState->cache.age[bucket] << 1) | 1U;
20092009
parseState->token.value.cacheItem = &parseState->cache.items[bucket];
20102010
NSCParameterAssert(parseState->cache.items[bucket].object != NULL);
@@ -2556,20 +2556,57 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
25562556

25572557
// When we encounter a class that we do not handle, and we have either a delegate or block that the user supplied to format unsupported classes,
25582558
// we "re-run" the object check. However, we re-run the object check exactly ONCE. If the user supplies an object that isn't one of the
2559-
// supported classes, we fail the second type (i.e., double fault error).
2559+
// supported classes, we fail the second time (i.e., double fault error).
25602560
BOOL rerunningAfterClassFormatter = NO;
2561-
rerunAfterClassFormatter:
2561+
rerunAfterClassFormatter:;
2562+
2563+
// XXX XXX XXX XXX
2564+
//
2565+
// We need to work around a bug in 10.7, which breaks ABI compatibility with Objective-C going back not just to 10.0, but OpenStep and even NextStep.
2566+
//
2567+
// It has long been documented that "the very first thing that a pointer to an Objective-C object "points to" is a pointer to that objects class".
2568+
//
2569+
// This is euphemistically called "tagged pointers". There are a number of highly technical problems with this, most involving long passages from
2570+
// the C standard(s). In short, one can make a strong case, couched from the perspective of the C standard(s), that that 10.7 "tagged pointers" are
2571+
// fundamentally Wrong and Broken, and should have never been implemented. Assuming those points are glossed over, because the change is very clearly
2572+
// breaking ABI compatibility, this should have resulted in a minimum of a "minimum version required" bump in various shared libraries to prevent
2573+
// causes code that used to work just fine to suddenly break without warning.
2574+
//
2575+
// In fact, the C standard says that the hack below is "undefined behavior"- there is no requirement that the 10.7 tagged pointer hack of setting the
2576+
// "lower, unused bits" must be preserved when casting the result to an integer type, but this "works" because for most architectures
2577+
// `sizeof(long) == sizeof(void *)` and the compiler uses the same representation for both. (note: this is informal, not meant to be
2578+
// normative or pedantically correct).
2579+
//
2580+
// In other words, while this "works" for now, technically the compiler is not obligated to do "what we want", and a later version of the compiler
2581+
// is not required in any way to produce the same results or behavior that earlier versions of the compiler did for the statement below.
2582+
//
2583+
// Fan-fucking-tastic.
2584+
//
2585+
// Why not just use `object_getClass()`? Because `object->isa` reduces to (typically) a *single* instruction. Calling `object_getClass()` requires
2586+
// that the compiler potentially spill registers, establish a function call frame / environment, and finally execute a "jump subroutine" instruction.
2587+
// Then, the called subroutine must spend half a dozen instructions in its prolog, however many instructions doing whatever it does, then half a dozen
2588+
// instructions in its prolog. One instruction compared to dozens, maybe a hundred instructions.
2589+
//
2590+
// Yes, that's one to two orders of magnitude difference. Which is compelling in its own right. When going for performance, you're often happy with
2591+
// gains in the two to three percent range.
2592+
//
2593+
// XXX XXX XXX XXX
2594+
2595+
BOOL workAroundMacOSXABIBreakingBug = NO;
2596+
if(JK_EXPECT_F(((NSUInteger)object) & 0x1)) { workAroundMacOSXABIBreakingBug = YES; goto slowClassLookup; }
2597+
25622598
if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; }
25632599
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.numberClass)) { isClass = JKClassNumber; }
25642600
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.dictionaryClass)) { isClass = JKClassDictionary; }
25652601
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.arrayClass)) { isClass = JKClassArray; }
25662602
else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.nullClass)) { isClass = JKClassNull; }
25672603
else {
2568-
if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { encodeState->fastClassLookup.stringClass = object->isa; isClass = JKClassString; }
2569-
else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { encodeState->fastClassLookup.numberClass = object->isa; isClass = JKClassNumber; }
2570-
else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { encodeState->fastClassLookup.dictionaryClass = object->isa; isClass = JKClassDictionary; }
2571-
else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { encodeState->fastClassLookup.arrayClass = object->isa; isClass = JKClassArray; }
2572-
else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { encodeState->fastClassLookup.nullClass = object->isa; isClass = JKClassNull; }
2604+
slowClassLookup:
2605+
if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.stringClass = object->isa; } isClass = JKClassString; }
2606+
else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.numberClass = object->isa; } isClass = JKClassNumber; }
2607+
else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.dictionaryClass = object->isa; } isClass = JKClassDictionary; }
2608+
else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.arrayClass = object->isa; } isClass = JKClassArray; }
2609+
else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.nullClass = object->isa; } isClass = JKClassNull; }
25732610
else {
25742611
if((rerunningAfterClassFormatter == NO) && (
25752612
#ifdef __BLOCKS__

0 commit comments

Comments
 (0)