From de678fc66e021742ec95c1efd4122d983e7e2056 Mon Sep 17 00:00:00 2001 From: Dustin Rue Date: Tue, 19 Jun 2012 21:18:30 -0500 Subject: [PATCH 1/3] disable some actions that won't compile under ML --- ControlPlane.xcodeproj/project.pbxproj | 16 ++++++---------- Source/Action.m | 15 ++++++++------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/ControlPlane.xcodeproj/project.pbxproj b/ControlPlane.xcodeproj/project.pbxproj index 90b4504b2..50e656f74 100644 --- a/ControlPlane.xcodeproj/project.pbxproj +++ b/ControlPlane.xcodeproj/project.pbxproj @@ -24,7 +24,6 @@ 8D232FB60BD9D507006A3963 /* RulesPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D232FB40BD9D507006A3963 /* RulesPrefs.png */; }; 8D27ECB00C4456A300AE1929 /* AudioOutputEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D27ECAE0C4456A300AE1929 /* AudioOutputEvidenceSource.m */; }; 8D2BAAAD0C56E26200A50777 /* NetworkLinkEvidenceSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D2BAAAB0C56E26100A50777 /* NetworkLinkEvidenceSource.m */; }; - 8D3453C40C18E5C1006011D0 /* IChatAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3453C20C18E5C1006011D0 /* IChatAction.m */; }; 8D38B66C0C49D50200290F47 /* SliderWithValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D38B66A0C49D50200290F47 /* SliderWithValue.m */; }; 8D3A3D5F0C012565008EBF2A /* EvidenceSourcesPrefs.png in Resources */ = {isa = PBXBuildFile; fileRef = 8D3A3D5E0C012564008EBF2A /* EvidenceSourcesPrefs.png */; }; 8D3BFF3F0C61BE4500B9B910 /* AboutPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D3BFF3D0C61BE4500B9B910 /* AboutPanel.m */; }; @@ -140,7 +139,6 @@ DD8274F91411748C0098FA6E /* LockKeychainAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274F81411748B0098FA6E /* LockKeychainAction.m */; }; DD8274FB141177750098FA6E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD8274FA141177750098FA6E /* Security.framework */; }; DD8274FE14117C590098FA6E /* SpeakAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8274FD14117C580098FA6E /* SpeakAction.m */; }; - DD827507141188890098FA6E /* DisplayBrightnessAction.m in Sources */ = {isa = PBXBuildFile; fileRef = DD827506141188880098FA6E /* DisplayBrightnessAction.m */; }; DDA2013A1411C0FB00DE570E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDA2013C1411C0FB00DE570E /* Localizable.strings */; }; DDA201441411C25A00DE570E /* GenericRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA201461411C25A00DE570E /* GenericRule.xib */; }; DDA2014E1411C32F00DE570E /* IPRule.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDA201501411C32F00DE570E /* IPRule.xib */; }; @@ -1223,7 +1221,6 @@ 8DC4E8000C17891D007E7E41 /* MailSMTPServerAction.m in Sources */, 8D71CAEF0C17BA7900E56526 /* ToggleableAction.m in Sources */, 8D71CB790C17C01700E56526 /* ScreenSaverPasswordAction.m in Sources */, - 8D3453C40C18E5C1006011D0 /* IChatAction.m in Sources */, 8DCBE96C0C1A7ECE008260EF /* MountAction.m in Sources */, 8D8155D00C3A304E00228463 /* ContextsDataSource.m in Sources */, 8D6762170C3B8D8D000B63EC /* NetworkLocationAction.m in Sources */, @@ -1261,7 +1258,6 @@ DD8274F614116CC90098FA6E /* OpenURLAction.m in Sources */, DD8274F91411748C0098FA6E /* LockKeychainAction.m in Sources */, DD8274FE14117C590098FA6E /* SpeakAction.m in Sources */, - DD827507141188890098FA6E /* DisplayBrightnessAction.m in Sources */, DDDF1C2B1411D49300DB0018 /* DefaultBrowserAction.m in Sources */, DDDF1C2F1411E08000DB0018 /* ITunesPlaylistAction.m in Sources */, DA5B01F31412BAEC00E19C50 /* BetterAuthorizationSampleLib.c in Sources */, @@ -1470,7 +1466,7 @@ "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks\"", ); MACOSX_DEPLOYMENT_TARGET = 10.6; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; }; name = Debug; }; @@ -1484,7 +1480,7 @@ "\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks\"", ); MACOSX_DEPLOYMENT_TARGET = 10.6; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; STRIP_INSTALLED_PRODUCT = YES; }; name = Release; @@ -1602,7 +1598,7 @@ isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; }; name = Debug; }; @@ -1610,7 +1606,7 @@ isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; }; name = Release; }; @@ -1618,7 +1614,7 @@ isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; }; name = Debug; }; @@ -1626,7 +1622,7 @@ isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx10.7; + SDKROOT = macosx10.8; }; name = Release; }; diff --git a/Source/Action.m b/Source/Action.m index c4f65257f..8cf73222b 100644 --- a/Source/Action.m +++ b/Source/Action.m @@ -220,10 +220,10 @@ - (NSArray *)executeAppleScriptReturningListOfStrings:(NSString *)script #import "DefaultBrowserAction.h" #import "DefaultPrinterAction.h" #import "DesktopBackgroundAction.h" -#import "DisplayBrightnessAction.h" +//#import "DisplayBrightnessAction.h" #import "DisplaySleepTimeAction.h" #import "FirewallRuleAction.h" -#import "IChatAction.h" +//#import "IChatAction.h" #import "ITunesPlaylistAction.h" #import "LockKeychainAction.h" #import "MailIMAPServerAction.h" @@ -274,9 +274,9 @@ - (id)init [DefaultBrowserAction class], [DefaultPrinterAction class], [DesktopBackgroundAction class], - [DisplayBrightnessAction class], + //[DisplayBrightnessAction class], [DisplaySleepTimeAction class], - [IChatAction class], + //[IChatAction class], [ITunesPlaylistAction class], [LockKeychainAction class], [MailIMAPServerAction class], @@ -316,8 +316,8 @@ - (id)init NSLocalizedString(@"DefaultBrowser", @"Action type"); NSLocalizedString(@"DefaultPrinter", @"Action type"); NSLocalizedString(@"DesktopBackground", @"Action type"); - NSLocalizedString(@"DisplayBrightness", @"Action type"); - NSLocalizedString(@"iChat", @"Action type"); + //NSLocalizedString(@"DisplayBrightness", @"Action type"); + //NSLocalizedString(@"iChat", @"Action type"); NSLocalizedString(@"iTunesPlaylist", @"Action type"); NSLocalizedString(@"LockKeychain", @"Action type"); NSLocalizedString(@"MailIMAPServer", @"Action type"); @@ -346,13 +346,14 @@ - (id)init NSLocalizedString(@"Unmount", @"Action type"); NSLocalizedString(@"VPN", @"Action type"); } - + /* // hack to remove the DisplayBrightnessAction on ML if (major == 10 && minor > 7) { NSMutableArray *tmp = [classes mutableCopy]; [tmp removeObject:[DisplayBrightnessAction class]]; classes = tmp; } + */ if (major == 10 && minor < 7) { NSMutableArray *tmp = [classes mutableCopy]; From af9a7fbdbe729e77ffb5ea65112e1f790eb6e9fd Mon Sep 17 00:00:00 2001 From: Dustin Rue Date: Tue, 19 Jun 2012 21:30:14 -0500 Subject: [PATCH 2/3] update JSONKit --- Source/JSONKit/JSONKit.m | 107 ++++++++++++++++++++++++++------------- Source/JSONKit/README.md | 3 ++ 2 files changed, 75 insertions(+), 35 deletions(-) diff --git a/Source/JSONKit/JSONKit.m b/Source/JSONKit/JSONKit.m index 3ee1dad8c..76a04f021 100644 --- a/Source/JSONKit/JSONKit.m +++ b/Source/JSONKit/JSONKit.m @@ -175,7 +175,7 @@ The code in isValidCodePoint() is derived from the ICU code in #define JK_CACHE_SLOTS (1UL << JK_CACHE_SLOTS_BITS) // JK_CACHE_PROBES is the number of probe attempts. #define JK_CACHE_PROBES (4UL) -// JK_INIT_CACHE_AGE must be (1 << AGE) - 1 +// JK_INIT_CACHE_AGE must be < (1 << AGE) - 1, where AGE is sizeof(typeof(AGE)) * 8. #define JK_INIT_CACHE_AGE (0) // JK_TOKENBUFFER_SIZE is the default stack size for the temporary buffer used to hold "non-simple" strings (i.e., contains \ escapes) @@ -609,7 +609,7 @@ - (void)releaseState; JK_STATIC_INLINE size_t jk_min(size_t a, size_t b); JK_STATIC_INLINE size_t jk_max(size_t a, size_t b); -JK_STATIC_INLINE JKHash calculateHash(JKHash currentHash, unsigned char c); +JK_STATIC_INLINE JKHash jk_calculateHash(JKHash currentHash, unsigned char c); // JSONKit v1.4 used both a JKArray : NSArray and JKMutableArray : NSMutableArray, and the same for the dictionary collection type. // However, Louis Gerbarg (via cocoa-dev) pointed out that Cocoa / Core Foundation actually implements only a single class that inherits from the @@ -692,14 +692,14 @@ + (id)allocWithZone:(NSZone *)zone static void _JKArrayInsertObjectAtIndex(JKArray *array, id newObject, NSUInteger objectIndex) { NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex <= array->count) && (newObject != NULL)); if(!((array != NULL) && (array->objects != NULL) && (objectIndex <= array->count) && (newObject != NULL))) { [newObject autorelease]; return; } - array->count++; - if(array->count >= array->capacity) { - array->capacity += 16UL; + if((array->count + 1UL) >= array->capacity) { id *newObjects = NULL; - if((newObjects = (id *)realloc(array->objects, sizeof(id) * array->capacity)) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; } + if((newObjects = (id *)realloc(array->objects, sizeof(id) * (array->capacity + 16UL))) == NULL) { [NSException raise:NSMallocException format:@"Unable to resize objects array."]; } array->objects = newObjects; + array->capacity += 16UL; memset(&array->objects[array->count], 0, sizeof(id) * (array->capacity - array->count)); } + array->count++; if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex + 1UL], &array->objects[objectIndex], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[objectIndex] = NULL; } array->objects[objectIndex] = newObject; } @@ -714,11 +714,11 @@ static void _JKArrayReplaceObjectAtIndexWithObject(JKArray *array, NSUInteger ob } static void _JKArrayRemoveObjectAtIndex(JKArray *array, NSUInteger objectIndex) { - NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL)); - if(!((array != NULL) && (array->objects != NULL) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; } + NSCParameterAssert((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL)); + if(!((array != NULL) && (array->objects != NULL) && (array->count > 0UL) && (array->count <= array->capacity) && (objectIndex < array->count) && (array->objects[objectIndex] != NULL))) { return; } CFRelease(array->objects[objectIndex]); array->objects[objectIndex] = NULL; - if((objectIndex + 1UL) < array->count) { memmove(&array->objects[objectIndex], &array->objects[objectIndex + 1UL], sizeof(id) * ((array->count - 1UL) - objectIndex)); array->objects[array->count] = NULL; } + 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; } array->count--; } @@ -805,13 +805,13 @@ - (void)replaceObjectAtIndex:(NSUInteger)objectIndex withObject:(id)anObject - (id)copyWithZone:(NSZone *)zone { NSParameterAssert((objects != NULL) && (count <= capacity)); - return((mutations == 0UL) ? [self retain] : [[NSArray allocWithZone:zone] initWithObjects:objects count:count]); + return((mutations == 0UL) ? [self retain] : [(NSArray *)[NSArray allocWithZone:zone] initWithObjects:objects count:count]); } - (id)mutableCopyWithZone:(NSZone *)zone { NSParameterAssert((objects != NULL) && (count <= capacity)); - return([[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]); + return([(NSMutableArray *)[NSMutableArray allocWithZone:zone] initWithObjects:objects count:count]); } @end @@ -848,7 +848,7 @@ - (void)dealloc - (NSArray *)allObjects { NSParameterAssert(collection != NULL); - NSUInteger count = [collection count], atObject = 0UL; + NSUInteger count = [(NSDictionary *)collection count], atObject = 0UL; id objects[count]; while((objects[atObject] = [self nextObject]) != NULL) { NSParameterAssert(atObject < count); atObject++; } @@ -1111,7 +1111,8 @@ - (id)mutableCopyWithZone:(NSZone *)zone JK_STATIC_INLINE size_t jk_min(size_t a, size_t b) { return((a < b) ? a : b); } JK_STATIC_INLINE size_t jk_max(size_t a, size_t b) { return((a > b) ? a : b); } -JK_STATIC_INLINE JKHash calculateHash(JKHash currentHash, unsigned char c) { return(((currentHash << 5) + currentHash) + c); } +JK_STATIC_INLINE JKHash jk_calculateHash(JKHash currentHash, unsigned char c) { return((((currentHash << 5) + currentHash) + (c - 29)) ^ (currentHash >> 19)); } + static void jk_error(JKParseState *parseState, NSString *format, ...) { NSCParameterAssert((parseState != NULL) && (format != NULL)); @@ -1408,7 +1409,7 @@ JK_STATIC_INLINE int jk_string_add_unicodeCodePoint(JKParseState *parseState, ui if((result = ConvertUTF32toUTF8(unicodeCodePoint, &u8s, (parseState->token.tokenBuffer.bytes.ptr + parseState->token.tokenBuffer.bytes.length))) != conversionOK) { if(result == targetExhausted) { return(1); } } size_t utf8len = u8s - &parseState->token.tokenBuffer.bytes.ptr[*tokenBufferIdx], nextIdx = (*tokenBufferIdx) + utf8len; - while(*tokenBufferIdx < nextIdx) { *stringHash = calculateHash(*stringHash, parseState->token.tokenBuffer.bytes.ptr[(*tokenBufferIdx)++]); } + while(*tokenBufferIdx < nextIdx) { *stringHash = jk_calculateHash(*stringHash, parseState->token.tokenBuffer.bytes.ptr[(*tokenBufferIdx)++]); } return(0); } @@ -1442,8 +1443,8 @@ static int jk_parse_string(JKParseState *parseState) { ConversionResult result; if(JK_EXPECT_F((result = ConvertSingleCodePointInUTF8(atStringCharacter - 1, endOfBuffer, (UTF8 const **)&nextValidCharacter, &u32ch)) != conversionOK)) { goto switchToSlowPath; } - stringHash = calculateHash(stringHash, currentChar); - while(atStringCharacter < nextValidCharacter) { NSCParameterAssert(JK_AT_STRING_PTR(parseState) <= JK_END_STRING_PTR(parseState)); stringHash = calculateHash(stringHash, *atStringCharacter++); } + stringHash = jk_calculateHash(stringHash, currentChar); + while(atStringCharacter < nextValidCharacter) { NSCParameterAssert(JK_AT_STRING_PTR(parseState) <= JK_END_STRING_PTR(parseState)); stringHash = jk_calculateHash(stringHash, *atStringCharacter++); } continue; } else { if(JK_EXPECT_F(currentChar == (unsigned long)'"')) { stringState = JSONStringStateFinished; goto finishedParsing; } @@ -1460,7 +1461,7 @@ static int jk_parse_string(JKParseState *parseState) { if(JK_EXPECT_F(currentChar < 0x20UL)) { jk_error(parseState, @"Invalid character < 0x20 found in string: 0x%2.2x.", currentChar); stringState = JSONStringStateError; goto finishedParsing; } - stringHash = calculateHash(stringHash, currentChar); + stringHash = jk_calculateHash(stringHash, currentChar); } } @@ -1478,7 +1479,7 @@ static int jk_parse_string(JKParseState *parseState) { if(JK_EXPECT_T(currentChar < (unsigned long)0x80)) { // Not a UTF8 sequence if(JK_EXPECT_F(currentChar == (unsigned long)'"')) { stringState = JSONStringStateFinished; atStringCharacter++; goto finishedParsing; } if(JK_EXPECT_F(currentChar == (unsigned long)'\\')) { stringState = JSONStringStateEscape; continue; } - stringHash = calculateHash(stringHash, currentChar); + stringHash = jk_calculateHash(stringHash, currentChar); tokenBuffer[tokenBufferIdx++] = currentChar; continue; } else { // UTF8 sequence @@ -1493,7 +1494,7 @@ static int jk_parse_string(JKParseState *parseState) { atStringCharacter = nextValidCharacter - 1; continue; } else { - while(atStringCharacter < nextValidCharacter) { tokenBuffer[tokenBufferIdx++] = *atStringCharacter; stringHash = calculateHash(stringHash, *atStringCharacter++); } + while(atStringCharacter < nextValidCharacter) { tokenBuffer[tokenBufferIdx++] = *atStringCharacter; stringHash = jk_calculateHash(stringHash, *atStringCharacter++); } atStringCharacter--; continue; } @@ -1521,7 +1522,7 @@ static int jk_parse_string(JKParseState *parseState) { parsedEscapedChar: stringState = JSONStringStateParsing; - stringHash = calculateHash(stringHash, escapedChar); + stringHash = jk_calculateHash(stringHash, escapedChar); tokenBuffer[tokenBufferIdx++] = escapedChar; break; @@ -1709,7 +1710,7 @@ static int jk_parse_number(JKParseState *parseState) { if(JK_EXPECT_F(endOfNumber != &numberTempBuf[parseState->token.tokenPtrRange.length]) && JK_EXPECT_F(numberState != JSONNumberStateError)) { numberState = JSONNumberStateError; jk_error(parseState, @"The conversion function did not consume all of the number tokens characters."); } size_t hashIndex = 0UL; - for(hashIndex = 0UL; hashIndex < parseState->token.value.ptrRange.length; hashIndex++) { parseState->token.value.hash = calculateHash(parseState->token.value.hash, parseState->token.value.ptrRange.ptr[hashIndex]); } + for(hashIndex = 0UL; hashIndex < parseState->token.value.ptrRange.length; hashIndex++) { parseState->token.value.hash = jk_calculateHash(parseState->token.value.hash, parseState->token.value.ptrRange.ptr[hashIndex]); } } if(JK_EXPECT_F(numberState != JSONNumberStateFinished)) { jk_error(parseState, @"Invalid number."); } @@ -1972,7 +1973,7 @@ static id json_parse_it(JKParseState *parseState) { #pragma mark Object cache // This uses a Galois Linear Feedback Shift Register (LFSR) PRNG to pick which item in the cache to age. It has a period of (2^32)-1. -// NOTE: A LFSR *MUST* be initialized to a non-zero value and must always have a non-zero value. +// NOTE: A LFSR *MUST* be initialized to a non-zero value and must always have a non-zero value. The LFSR is initalized to 1 in -initWithParseOptions: JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { NSCParameterAssert((parseState != NULL) && (parseState->cache.prng_lfsr != 0U)); parseState->cache.prng_lfsr = (parseState->cache.prng_lfsr >> 1) ^ ((0U - (parseState->cache.prng_lfsr & 1U)) & 0x80200003U); @@ -1983,9 +1984,8 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { // // The hash table is a linear C array of JKTokenCacheItem. The terms "item" and "bucket" are synonymous with the index in to the cache array, i.e. cache.items[bucket]. // -// Items in the cache have an age associated with them. The age is the number of rightmost 1 bits, i.e. 0000 = 0, 0001 = 1, 0011 = 2, 0111 = 3, 1111 = 4. -// This allows us to use left and right shifts to add or subtract from an items age. Add = (age << 1) | 1. Subtract = age >> 0. Subtract is synonymous with "age" (i.e., age an item). -// The reason for this is it allows us to perform saturated adds and subtractions and is branchless. +// Items in the cache have an age associated with them. An items age is incremented using saturating unsigned arithmetic and decremeted using unsigned right shifts. +// Thus, an items age is managed using an AIMD policy- additive increase, multiplicative decrease. All age calculations and manipulations are branchless. // The primitive C type MUST be unsigned. It is currently a "char", which allows (at a minimum and in practice) 8 bits. // // A "useable bucket" is a bucket that is not in use (never populated), or has an age == 0. @@ -2000,12 +2000,12 @@ JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState) { void *parsedAtom = NULL; if(JK_EXPECT_F(parseState->token.value.ptrRange.length == 0UL) && JK_EXPECT_T(parseState->token.value.type == JKValueTypeString)) { return(@""); } - + for(x = 0UL; x < JK_CACHE_PROBES; x++) { if(JK_EXPECT_F(parseState->cache.items[bucket].object == NULL)) { setBucket = 1UL; useableBucket = bucket; break; } - 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))) { - parseState->cache.age[bucket] = (parseState->cache.age[bucket] << 1) | 1U; + 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))) { + parseState->cache.age[bucket] = (((uint32_t)parseState->cache.age[bucket]) + 1U) - (((((uint32_t)parseState->cache.age[bucket]) + 1U) >> 31) ^ 1U); parseState->token.value.cacheItem = &parseState->cache.items[bucket]; NSCParameterAssert(parseState->cache.items[bucket].object != NULL); return((void *)CFRetain(parseState->cache.items[bucket].object)); @@ -2556,20 +2556,57 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object // 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, // 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 - // supported classes, we fail the second type (i.e., double fault error). + // supported classes, we fail the second time (i.e., double fault error). BOOL rerunningAfterClassFormatter = NO; -rerunAfterClassFormatter: + rerunAfterClassFormatter:; + + // XXX XXX XXX XXX + // + // 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. + // + // 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". + // + // This is euphemistically called "tagged pointers". There are a number of highly technical problems with this, most involving long passages from + // 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 + // fundamentally Wrong and Broken, and should have never been implemented. Assuming those points are glossed over, because the change is very clearly + // breaking ABI compatibility, this should have resulted in a minimum of a "minimum version required" bump in various shared libraries to prevent + // causes code that used to work just fine to suddenly break without warning. + // + // 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 + // "lower, unused bits" must be preserved when casting the result to an integer type, but this "works" because for most architectures + // `sizeof(long) == sizeof(void *)` and the compiler uses the same representation for both. (note: this is informal, not meant to be + // normative or pedantically correct). + // + // 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 + // is not required in any way to produce the same results or behavior that earlier versions of the compiler did for the statement below. + // + // Fan-fucking-tastic. + // + // Why not just use `object_getClass()`? Because `object->isa` reduces to (typically) a *single* instruction. Calling `object_getClass()` requires + // that the compiler potentially spill registers, establish a function call frame / environment, and finally execute a "jump subroutine" instruction. + // Then, the called subroutine must spend half a dozen instructions in its prolog, however many instructions doing whatever it does, then half a dozen + // instructions in its prolog. One instruction compared to dozens, maybe a hundred instructions. + // + // 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 + // gains in the two to three percent range. + // + // XXX XXX XXX XXX + + BOOL workAroundMacOSXABIBreakingBug = NO; + if(JK_EXPECT_F(((NSUInteger)object) & 0x1)) { workAroundMacOSXABIBreakingBug = YES; goto slowClassLookup; } + if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.stringClass)) { isClass = JKClassString; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.numberClass)) { isClass = JKClassNumber; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.dictionaryClass)) { isClass = JKClassDictionary; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.arrayClass)) { isClass = JKClassArray; } else if(JK_EXPECT_T(object->isa == encodeState->fastClassLookup.nullClass)) { isClass = JKClassNull; } else { - if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { encodeState->fastClassLookup.stringClass = object->isa; isClass = JKClassString; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { encodeState->fastClassLookup.numberClass = object->isa; isClass = JKClassNumber; } - else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { encodeState->fastClassLookup.dictionaryClass = object->isa; isClass = JKClassDictionary; } - else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { encodeState->fastClassLookup.arrayClass = object->isa; isClass = JKClassArray; } - else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { encodeState->fastClassLookup.nullClass = object->isa; isClass = JKClassNull; } + slowClassLookup: + if(JK_EXPECT_T([object isKindOfClass:[NSString class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.stringClass = object->isa; } isClass = JKClassString; } + else if(JK_EXPECT_T([object isKindOfClass:[NSNumber class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.numberClass = object->isa; } isClass = JKClassNumber; } + else if(JK_EXPECT_T([object isKindOfClass:[NSDictionary class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.dictionaryClass = object->isa; } isClass = JKClassDictionary; } + else if(JK_EXPECT_T([object isKindOfClass:[NSArray class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.arrayClass = object->isa; } isClass = JKClassArray; } + else if(JK_EXPECT_T([object isKindOfClass:[NSNull class]])) { if(workAroundMacOSXABIBreakingBug == NO) { encodeState->fastClassLookup.nullClass = object->isa; } isClass = JKClassNull; } else { if((rerunningAfterClassFormatter == NO) && ( #ifdef __BLOCKS__ diff --git a/Source/JSONKit/README.md b/Source/JSONKit/README.md index 56c5e2a62..8b4a4d94f 100644 --- a/Source/JSONKit/README.md +++ b/Source/JSONKit/README.md @@ -5,6 +5,8 @@ Copyright © 2011, John Engelhart. ### A Very High Performance Objective-C JSON Library +**UPDATE:** (2011/12/18) The benchmarks below were performed before Apples [`NSJSONSerialization`][NSJSONSerialization] was available (as of Mac OS X 10.7 and iOS 5). The obvious question is: Which is faster, [`NSJSONSerialization`][NSJSONSerialization] or JSONKit? According to [this site](http://www.bonto.ch/blog/2011/12/08/json-libraries-for-ios-comparison-updated/), JSONKit is faster than [`NSJSONSerialization`][NSJSONSerialization]. Some quick "back of the envelope" calculations using the numbers reported, JSONKit appears to be approximately 25% to 40% faster than [`NSJSONSerialization`][NSJSONSerialization], which is pretty significant. + Parsing | Serializing :---------:|:-------------: Deserialize from JSON | Serialize to JSON @@ -305,3 +307,4 @@ Example | Result | Argument [strtoull]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/strtoull.3.html [getrusage]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/getrusage.2.html [printf]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/printf.3.html +[NSJSONSerialization]: http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html From cd05cda29e24b131f44aaead7b75f7e1d5811d6f Mon Sep 17 00:00:00 2001 From: Dustin Rue Date: Tue, 19 Jun 2012 22:04:14 -0500 Subject: [PATCH 3/3] enables developer ID (code signing) --- ControlPlane.xcodeproj/project.pbxproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ControlPlane.xcodeproj/project.pbxproj b/ControlPlane.xcodeproj/project.pbxproj index 50e656f74..5ee913c59 100644 --- a/ControlPlane.xcodeproj/project.pbxproj +++ b/ControlPlane.xcodeproj/project.pbxproj @@ -1490,7 +1490,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "Developer ID Application: Dustin Rue"; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1534,6 +1534,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = ControlPlane; + PROVISIONING_PROFILE = ""; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx10.7; VALIDATE_PRODUCT = YES; @@ -1545,7 +1546,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "Developer ID Application: Dustin Rue"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( @@ -1587,6 +1588,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = ControlPlane; + PROVISIONING_PROFILE = ""; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx10.7; VALIDATE_PRODUCT = YES;