Skip to content

Commit

Permalink
Merge branch 'master' of github.com:playup/JSONKit
Browse files Browse the repository at this point in the history
* 'master' of github.com:playup/JSONKit:
  Adds a serializing option to backslash escape forward slashes.  This is for issue johnezang#21.
  Change a NSException from exceptionWithName: to raise:.  Closes johnezang#20.
  Fixes a bug when removing items from a JKDictionary.  Since JKDictionary is implemented using a hash table that uses linear probing, the removal function needs to "re-add" items that follow the removed item so that linear probe hash collisions are not "lost".  Closes johnezang#17
  • Loading branch information
aussiegeek committed May 4, 2011
2 parents 02f6242 + b8359c6 commit 85a4377
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
9 changes: 5 additions & 4 deletions JSONKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ enum {
typedef JKFlags JKParseOptionFlags;

enum {
JKSerializeOptionNone = 0,
JKSerializeOptionPretty = (1 << 0),
JKSerializeOptionEscapeUnicode = (1 << 1),
JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode),
JKSerializeOptionNone = 0,
JKSerializeOptionPretty = (1 << 0),
JKSerializeOptionEscapeUnicode = (1 << 1),
JKSerializeOptionEscapeForwardSlashes = (1 << 4),
JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode | JKSerializeOptionEscapeForwardSlashes),
};
typedef JKFlags JKSerializeOptionFlags;

Expand Down
29 changes: 24 additions & 5 deletions JSONKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -937,11 +937,30 @@ static NSUInteger _JKDictionaryCapacity(JKDictionary *dictionary) {
}

static void _JKDictionaryRemoveObjectWithEntry(JKDictionary *dictionary, JKHashTableEntry *entry) {
NSCParameterAssert((dictionary != NULL) && (entry != NULL) && (entry->key != NULL) && (entry->object != NULL) && (dictionary->count > 0UL));
NSCParameterAssert((dictionary != NULL) && (entry != NULL) && (entry->key != NULL) && (entry->object != NULL) && (dictionary->count > 0UL) && (dictionary->count <= dictionary->capacity));
CFRelease(entry->key); entry->key = NULL;
CFRelease(entry->object); entry->object = NULL;
entry->keyHash = 0UL;
dictionary->count--;
// In order for certain invariants that are used to speed up the search for a particular key, we need to "re-add" all the entries in the hash table following this entry until we hit a NULL entry.
NSUInteger removeIdx = entry - dictionary->entry, idx = 0UL;
NSCParameterAssert((removeIdx < dictionary->capacity));
for(idx = 0UL; idx < dictionary->capacity; idx++) {
NSUInteger entryIdx = (removeIdx + idx + 1UL) % dictionary->capacity;
JKHashTableEntry *atEntry = &dictionary->entry[entryIdx];
if(atEntry->key == NULL) { break; }
NSUInteger keyHash = atEntry->keyHash;
id key = atEntry->key, object = atEntry->object;
NSCParameterAssert(object != NULL);
atEntry->keyHash = 0UL;
atEntry->key = NULL;
atEntry->object = NULL;
NSUInteger addKeyEntry = keyHash % dictionary->capacity, addIdx = 0UL;
for(addIdx = 0UL; addIdx < dictionary->capacity; addIdx++) {
JKHashTableEntry *atAddEntry = &dictionary->entry[((addKeyEntry + addIdx) % dictionary->capacity)];
if(JK_EXPECT_T(atAddEntry->key == NULL)) { NSCParameterAssert((atAddEntry->keyHash == 0UL) && (atAddEntry->object == NULL)); atAddEntry->key = key; atAddEntry->object = object; atAddEntry->keyHash = keyHash; break; }
}
}
}

static void _JKDictionaryAddObject(JKDictionary *dictionary, NSUInteger keyHash, id key, id object) {
Expand All @@ -951,7 +970,7 @@ static void _JKDictionaryAddObject(JKDictionary *dictionary, NSUInteger keyHash,
NSUInteger entryIdx = (keyEntry + idx) % dictionary->capacity;
JKHashTableEntry *atEntry = &dictionary->entry[entryIdx];
if(JK_EXPECT_F(atEntry->keyHash == keyHash) && JK_EXPECT_T(atEntry->key != NULL) && (JK_EXPECT_F(key == atEntry->key) || JK_EXPECT_F(CFEqual(atEntry->key, key)))) { _JKDictionaryRemoveObjectWithEntry(dictionary, atEntry); }
if(JK_EXPECT_T(atEntry->key == NULL)) { atEntry->key = key; atEntry->object = object; atEntry->keyHash = keyHash; dictionary->count++; return; }
if(JK_EXPECT_T(atEntry->key == NULL)) { NSCParameterAssert((atEntry->keyHash == 0UL) && (atEntry->object == NULL)); atEntry->key = key; atEntry->object = object; atEntry->keyHash = keyHash; dictionary->count++; return; }
}

// We should never get here. If we do, we -release the key / object because it's our responsibility.
Expand Down Expand Up @@ -2585,7 +2604,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
default: if(JK_EXPECT_F(jk_encode_printf(encodeState, NULL, 0UL, NULL, "\\u%4.4x", utf8String[utf8Idx]))) { return(1); } break;
}
} else {
if(JK_EXPECT_F(utf8String[utf8Idx] == '\"') || JK_EXPECT_F(utf8String[utf8Idx] == '\\')) { encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = '\\'; }
if(JK_EXPECT_F(utf8String[utf8Idx] == '\"') || JK_EXPECT_F(utf8String[utf8Idx] == '\\') || (JK_EXPECT_F(encodeState->serializeOptionFlags & JKSerializeOptionEscapeForwardSlashes) && JK_EXPECT_F(utf8String[utf8Idx] == '/'))) { encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = '\\'; }
encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = utf8String[utf8Idx];
}
}
Expand Down Expand Up @@ -2639,7 +2658,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
else { if(JK_EXPECT_F(jk_encode_printf(encodeState, NULL, 0UL, NULL, "\\u%4.4x\\u%4.4x", (0xd7c0U + (u32ch >> 10)), (0xdc00U + (u32ch & 0x3ffU))))) { return(1); } }
}
} else {
if(JK_EXPECT_F(utf8String[utf8Idx] == '\"') || JK_EXPECT_F(utf8String[utf8Idx] == '\\')) { encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = '\\'; }
if(JK_EXPECT_F(utf8String[utf8Idx] == '\"') || JK_EXPECT_F(utf8String[utf8Idx] == '\\') || (JK_EXPECT_F(encodeState->serializeOptionFlags & JKSerializeOptionEscapeForwardSlashes) && JK_EXPECT_F(utf8String[utf8Idx] == '/'))) { encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = '\\'; }
encodeState->stringBuffer.bytes.ptr[encodeState->atIndex++] = utf8String[utf8Idx];
}
}
Expand Down Expand Up @@ -2771,7 +2790,7 @@ - (id)serializeObject:(id)object options:(JKSerializeOptionFlags)optionFlags enc
id returnObject = NULL;

if(encodeState != NULL) { [self releaseState]; }
if((encodeState = (struct JKEncodeState *)calloc(1UL, sizeof(JKEncodeState))) == NULL) { [NSException exceptionWithName:NSMallocException reason:@"Unable to allocate state structure." userInfo:NULL]; return(NULL); }
if((encodeState = (struct JKEncodeState *)calloc(1UL, sizeof(JKEncodeState))) == NULL) { [NSException raise:NSMallocException format:@"Unable to allocate state structure."]; return(NULL); }

if((error != NULL) && (*error != NULL)) { *error = NULL; }

Expand Down

0 comments on commit 85a4377

Please sign in to comment.