adium-1.4 3419:b78df89f2741: Move to from SBJSON to JSONKit -- l...
commits at adium.im
commits at adium.im
Wed Mar 16 15:47:04 UTC 2011
details: http://hg.adium.im/adium-1.4/rev/b78df89f2741
revision: 3419:b78df89f2741
branch: facebook-xmpp
author: Colin Barrett <colin at springsandstruts.com>
date: Tue Mar 15 20:43:15 2011 -0700
Move to from SBJSON to JSONKit -- less files FTW
Subject: adium-1.4 3420:c3c7a69e75ee: AIFacebookXMPPOAuthWebViewWindowController should only be responsible for getting the OAuth token; the account should get the rest of the data.
details: http://hg.adium.im/adium-1.4/rev/c3c7a69e75ee
revision: 3420:c3c7a69e75ee
branch: facebook-xmpp
author: Colin Barrett <colin at springsandstruts.com>
date: Tue Mar 15 22:01:45 2011 -0700
AIFacebookXMPPOAuthWebViewWindowController should only be responsible for getting the OAuth token; the account should get the rest of the data.
diffs (truncated from 8865 to 1000 lines):
diff -r 4b731f6f7972 -r c3c7a69e75ee Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj Fri Mar 11 19:48:12 2011 -0600
+++ b/Adium.xcodeproj/project.pbxproj Tue Mar 15 22:01:45 2011 -0700
@@ -410,9 +410,7 @@
346BA3450774C2D200628F06 /* ESGlobalEventsPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 346BA3430774C2D200628F06 /* ESGlobalEventsPreferences.m */; };
346BA3640774C35500628F06 /* GlobalEventsPreferences.nib in Resources */ = {isa = PBXBuildFile; fileRef = 346BA3630774C35400628F06 /* GlobalEventsPreferences.nib */; };
346CE8071294B53F00439BF2 /* fbapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 346CE8051294B53F00439BF2 /* fbapi.c */; };
- 346CE8081294B53F00439BF2 /* fbapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 346CE8061294B53F00439BF2 /* fbapi.h */; };
346CE80A1294B59900439BF2 /* auth_fb.c in Sources */ = {isa = PBXBuildFile; fileRef = 346CE8091294B59900439BF2 /* auth_fb.c */; };
- 346CE80E1294B5B000439BF2 /* auth_fb.h in Headers */ = {isa = PBXBuildFile; fileRef = 346CE80D1294B5B000439BF2 /* auth_fb.h */; };
346F5D3208A43E7B0055C610 /* CurrentTunes.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 346F5CB308A418FB0055C610 /* CurrentTunes.scpt */; };
3470BF600BC6F18500388232 /* AIMessageHistoryPreferencesWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3470BF5E0BC6F18500388232 /* AIMessageHistoryPreferencesWindowController.h */; };
3470BF610BC6F18500388232 /* AIMessageHistoryPreferencesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3470BF5F0BC6F18500388232 /* AIMessageHistoryPreferencesWindowController.m */; };
@@ -1509,11 +1507,10 @@
EE147A800896B33400A21377 /* OWABSearchWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE147A7E0896B33400A21377 /* OWABSearchWindowController.m */; };
EE5754ED0B3D7A7A00100989 /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 638392F609D4D67A0067B9B7 /* Sparkle.framework */; };
EEC461B6096D68580028632F /* OWSpellingPerContactPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC461B4096D68580028632F /* OWSpellingPerContactPlugin.m */; };
- EF3472611324653700CE4177 /* JSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF3464B61324593800CE4177 /* JSON.framework */; };
- EF34726B1324654800CE4177 /* JSON.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = EF3464B61324593800CE4177 /* JSON.framework */; };
- EF34740013247E3C00CE4177 /* JSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF3464B61324593800CE4177 /* JSON.framework */; };
EFA39C0B1296658B00B36EBB /* AIFacebookXMPPAccountView.xib in Resources */ = {isa = PBXBuildFile; fileRef = EFA39C051296658B00B36EBB /* AIFacebookXMPPAccountView.xib */; };
EFA39CF612966F5D00B36EBB /* AIFacebookXMPPOauthWebViewWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = EFA39CF512966F5D00B36EBB /* AIFacebookXMPPOauthWebViewWindow.xib */; };
+ EFB036A413305E9B00CB421E /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB036A313305E8800CB421E /* JSONKit.m */; };
+ EFB036A613305EC500CB421E /* AIFacebookXMPPAccount.h in Headers */ = {isa = PBXBuildFile; fileRef = EFA39C031296658B00B36EBB /* AIFacebookXMPPAccount.h */; };
EFB1C3140DDBDA3100B3973D /* AITwitterIMPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB1C3130DDBDA3100B3973D /* AITwitterIMPlugin.m */; };
F51BCD3B0A156261000FDC06 /* AutoHyperlinks.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 3496A8EA07CE6CA30055BBAB /* AutoHyperlinks.framework */; };
F51BCEEA0A15793E000FDC06 /* AutoHyperlinks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3496A8EA07CE6CA30055BBAB /* AutoHyperlinks.framework */; };
@@ -1697,41 +1694,6 @@
remoteGlobalIDString = 7EA3B0440DD1153F002A18D1;
remoteInfo = Test;
};
- EF3464B51324593800CE4177 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = 53D229810C96121600276605;
- remoteInfo = JSON;
- };
- EF3464B71324593800CE4177 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = 53D2298D0C96122A00276605;
- remoteInfo = Tests;
- };
- EF3464B91324593800CE4177 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = FE2BBD800D8B0D3900184787;
- remoteInfo = libjson;
- };
- EF3464BB1324593800CE4177 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = FE2BBDAB0D8B0EE000184787;
- remoteInfo = libjsontests;
- };
- EF34659613245CCB00CE4177 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- proxyType = 1;
- remoteGlobalIDString = 53D229800C96121600276605;
- remoteInfo = JSON;
- };
EFB1C3D70DDCA0A900B3973D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 3496A8E707CE6CA30055BBAB /* AutoHyperlinks.framework.xcodeproj */;
@@ -1756,7 +1718,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
- EF34726B1324654800CE4177 /* JSON.framework in Copy Frameworks */,
116E33AF10B7263C002EDB0F /* Growl.framework in Copy Frameworks */,
118A44540FEEA82E008153C0 /* libjson-glib.framework in Copy Frameworks */,
633404710F9C18EF003C77A9 /* AIUtilities.framework in Copy Frameworks */,
@@ -4852,7 +4813,6 @@
EE147A7F0896B33400A21377 /* OWABSearchWindowController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = OWABSearchWindowController.h; path = Source/OWABSearchWindowController.h; sourceTree = "<group>"; };
EEC461B4096D68580028632F /* OWSpellingPerContactPlugin.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = OWSpellingPerContactPlugin.m; path = Source/OWSpellingPerContactPlugin.m; sourceTree = "<group>"; };
EEC461B5096D68580028632F /* OWSpellingPerContactPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = OWSpellingPerContactPlugin.h; path = Source/OWSpellingPerContactPlugin.h; sourceTree = "<group>"; };
- EF3464AD1324593800CE4177 /* JSON.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = JSON.xcodeproj; path = "Frameworks/json-framework/JSON.xcodeproj"; sourceTree = "<group>"; };
EFA39C031296658B00B36EBB /* AIFacebookXMPPAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIFacebookXMPPAccount.h; path = "Plugins/Purple Service/AIFacebookXMPPAccount.h"; sourceTree = "<group>"; };
EFA39C041296658B00B36EBB /* AIFacebookXMPPAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIFacebookXMPPAccount.m; path = "Plugins/Purple Service/AIFacebookXMPPAccount.m"; sourceTree = "<group>"; };
EFA39C051296658B00B36EBB /* AIFacebookXMPPAccountView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AIFacebookXMPPAccountView.xib; path = "Plugins/Purple Service/AIFacebookXMPPAccountView.xib"; sourceTree = "<group>"; };
@@ -4863,6 +4823,8 @@
EFA39C2F12966B2600B36EBB /* AIFacebookXMPPOAuthWebViewWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIFacebookXMPPOAuthWebViewWindowController.h; path = "Plugins/Purple Service/AIFacebookXMPPOAuthWebViewWindowController.h"; sourceTree = "<group>"; };
EFA39C3012966B2600B36EBB /* AIFacebookXMPPOAuthWebViewWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIFacebookXMPPOAuthWebViewWindowController.m; path = "Plugins/Purple Service/AIFacebookXMPPOAuthWebViewWindowController.m"; sourceTree = "<group>"; };
EFA39CF512966F5D00B36EBB /* AIFacebookXMPPOauthWebViewWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AIFacebookXMPPOauthWebViewWindow.xib; path = "Plugins/Purple Service/AIFacebookXMPPOauthWebViewWindow.xib"; sourceTree = "<group>"; };
+ EFB036A213305E8800CB421E /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONKit.h; path = Frameworks/JSONKit/JSONKit.h; sourceTree = SOURCE_ROOT; };
+ EFB036A313305E8800CB421E /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSONKit.m; path = Frameworks/JSONKit/JSONKit.m; sourceTree = SOURCE_ROOT; };
EFB1C3120DDBDA3100B3973D /* AITwitterIMPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AITwitterIMPlugin.h; path = Source/AITwitterIMPlugin.h; sourceTree = "<group>"; };
EFB1C3130DDBDA3100B3973D /* AITwitterIMPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AITwitterIMPlugin.m; path = Source/AITwitterIMPlugin.m; sourceTree = "<group>"; };
F11B9621051CDB3B0000000E /* AIMessageAliasPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AIMessageAliasPlugin.h; path = "Plugins/Message Alias Support/AIMessageAliasPlugin.h"; sourceTree = "<group>"; };
@@ -4945,7 +4907,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- EF34740013247E3C00CE4177 /* JSON.framework in Frameworks */,
811034050CDE216F00EC6038 /* Security.framework in Frameworks */,
81E45D760C15BFF800B7381B /* SystemConfiguration.framework in Frameworks */,
3485D8EA09EB446900232CC4 /* Cocoa.framework in Frameworks */,
@@ -4979,7 +4940,6 @@
639DF9140F97E639003C9A32 /* AdiumLibpurple.framework in Frameworks */,
3448758E06D1EBDF00DA778C /* Cocoa.framework in Frameworks */,
3419F7760531512200C68BA3 /* Adium.framework in Frameworks */,
- EF3472611324653700CE4177 /* JSON.framework in Frameworks */,
639DF9150F97E639003C9A32 /* libglib.framework in Frameworks */,
639DF9160F97E639003C9A32 /* libgmodule.framework in Frameworks */,
639DF9170F97E639003C9A32 /* libgobject.framework in Frameworks */,
@@ -5314,7 +5274,6 @@
34D1AB510D693DEB00470520 /* RBSplitView.xcodeproj */,
3496A8E707CE6CA30055BBAB /* AutoHyperlinks.framework.xcodeproj */,
346636860D41541A006C9034 /* FriBidi.xcodeproj */,
- EF3464AD1324593800CE4177 /* JSON.xcodeproj */,
341BDBBA0968BC9A00CF83F5 /* OTR.framework */,
348E5ACA06D2A74C004C051C /* AddressBook.framework */,
F5819CE9032124CE01A8010A /* AppKit.framework */,
@@ -8752,20 +8711,10 @@
name = "Spelling Per Contact";
sourceTree = "<group>";
};
- EF3464AE1324593800CE4177 /* Products */ = {
- isa = PBXGroup;
- children = (
- EF3464B61324593800CE4177 /* JSON.framework */,
- EF3464B81324593800CE4177 /* Tests.octest */,
- EF3464BA1324593800CE4177 /* libjson.a */,
- EF3464BC1324593800CE4177 /* libjsontests.octest */,
- );
- name = Products;
- sourceTree = "<group>";
- };
EFA39B5C1294F9FB00B36EBB /* FB XMPP */ = {
isa = PBXGroup;
children = (
+ EFB036A113305E6500CB421E /* JSONKit */,
346CE8091294B59900439BF2 /* auth_fb.c */,
346CE80D1294B5B000439BF2 /* auth_fb.h */,
346CE8051294B53F00439BF2 /* fbapi.c */,
@@ -8786,6 +8735,15 @@
name = "FB XMPP";
sourceTree = "<group>";
};
+ EFB036A113305E6500CB421E /* JSONKit */ = {
+ isa = PBXGroup;
+ children = (
+ EFB036A213305E8800CB421E /* JSONKit.h */,
+ EFB036A313305E8800CB421E /* JSONKit.m */,
+ );
+ name = JSONKit;
+ sourceTree = "<group>";
+ };
F1D0C631051AC2380000000E /* Message Alias Support */ = {
isa = PBXGroup;
children = (
@@ -9268,8 +9226,7 @@
345D68A20F1FD59F002F2D01 /* PurpleFacebookService.h in Headers */,
345D68A80F1FD5AA002F2D01 /* PurpleFacebookAccount.h in Headers */,
34064D110F21B34200AA6FE3 /* PurpleFacebookAccountViewController.h in Headers */,
- 346CE8081294B53F00439BF2 /* fbapi.h in Headers */,
- 346CE80E1294B5B000439BF2 /* auth_fb.h in Headers */,
+ EFB036A613305EC500CB421E /* AIFacebookXMPPAccount.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -9547,7 +9504,6 @@
);
dependencies = (
340BAB4F09EC6FA7000EC441 /* PBXTargetDependency */,
- EF34659713245CCB00CE4177 /* PBXTargetDependency */,
);
name = AdiumLibpurple;
productName = AdiumLibpurple;
@@ -9722,10 +9678,6 @@
ProjectRef = 346636860D41541A006C9034 /* FriBidi.xcodeproj */;
},
{
- ProductGroup = EF3464AE1324593800CE4177 /* Products */;
- ProjectRef = EF3464AD1324593800CE4177 /* JSON.xcodeproj */;
- },
- {
ProductGroup = 34D1AB520D693DEB00470520 /* Products */;
ProjectRef = 34D1AB510D693DEB00470520 /* RBSplitView.xcodeproj */;
},
@@ -9810,34 +9762,6 @@
remoteRef = 7E78DA9B0DD135DE00B9388F /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
- EF3464B61324593800CE4177 /* JSON.framework */ = {
- isa = PBXReferenceProxy;
- fileType = wrapper.framework;
- path = JSON.framework;
- remoteRef = EF3464B51324593800CE4177 /* PBXContainerItemProxy */;
- sourceTree = BUILT_PRODUCTS_DIR;
- };
- EF3464B81324593800CE4177 /* Tests.octest */ = {
- isa = PBXReferenceProxy;
- fileType = wrapper.cfbundle;
- path = Tests.octest;
- remoteRef = EF3464B71324593800CE4177 /* PBXContainerItemProxy */;
- sourceTree = BUILT_PRODUCTS_DIR;
- };
- EF3464BA1324593800CE4177 /* libjson.a */ = {
- isa = PBXReferenceProxy;
- fileType = archive.ar;
- path = libjson.a;
- remoteRef = EF3464B91324593800CE4177 /* PBXContainerItemProxy */;
- sourceTree = BUILT_PRODUCTS_DIR;
- };
- EF3464BC1324593800CE4177 /* libjsontests.octest */ = {
- isa = PBXReferenceProxy;
- fileType = wrapper.cfbundle;
- path = libjsontests.octest;
- remoteRef = EF3464BB1324593800CE4177 /* PBXContainerItemProxy */;
- sourceTree = BUILT_PRODUCTS_DIR;
- };
EFB1C3D80DDCA0A900B3973D /* LinkDriver.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
@@ -10495,6 +10419,7 @@
5ACDB4DD130872AB0058322A /* AIFacebookXMPPAccountViewController.m in Sources */,
5ABEADCD1308889F00DA4C56 /* AIFacebookXMPPService.m in Sources */,
5ABEADCE130888A800DA4C56 /* AIFacebookXMPPOAuthWebViewWindowController.m in Sources */,
+ EFB036A413305E9B00CB421E /* JSONKit.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -11158,11 +11083,6 @@
target = F53C25AE0A2F95F100F7B73D /* Setup Build Directory */;
targetProxy = 63DE4C520F9C77D50034ED3A /* PBXContainerItemProxy */;
};
- EF34659713245CCB00CE4177 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- name = JSON;
- targetProxy = EF34659613245CCB00CE4177 /* PBXContainerItemProxy */;
- };
F5B17CDF0A16C767004AE99E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F5B17CCF0A16C6AC004AE99E /* Plist Macros */;
diff -r 4b731f6f7972 -r c3c7a69e75ee Frameworks/JSONKit/.github_commit_id
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/JSONKit/.github_commit_id Tue Mar 15 22:01:45 2011 -0700
@@ -0,0 +1,1 @@
+7c66203
diff -r 4b731f6f7972 -r c3c7a69e75ee Frameworks/JSONKit/CHANGELOG.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/JSONKit/CHANGELOG.md Tue Mar 15 22:01:45 2011 -0700
@@ -0,0 +1,69 @@
+# JSONKit Changelog
+
+## Version 1.3 2011/05/04
+
+### New Features
+
+* Added the `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` pre-processor define flag.
+
+ This is typically enabled by adding <span style="white-space: nowrap;">`-DJK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS`</span> to the compilers command line arguments or in `Xcode.app` by adding `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` to a projects / targets `Pre-Processor Macros` settings.
+
+ The `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` option enables the use of custom Core Foundation collection call backs which omit the [`CFRetain`][CFRetain] calls. This results in saving several [`CFRetain`][CFRetain] and [`CFRelease`][CFRelease] calls typically needed for every single object from the parsed JSON. While the author has used this technique for years without any issues, an unexpected interaction with the Foundation [`-mutableCopy`][-mutableCopy] method and Core Foundation Toll-Free Bridging resulting in a condition in which the objects contained in the collection to be over released. This problem does not occur with the use of [`-copy`][-copy] due to the fact that the objects created by JSONKit are immutable, and therefore [`-copy`][-copy] does not require creating a completely new object and copying the contents, instead [`-copy`][-copy] simply returns a [`-retain`][-retain]'d version of the immutable object which is significantly faster along with the!
obvious reduction in memory usage.
+
+ Prior to version 1.3, JSONKit always used custom "Transfer of Ownership Collection Callbacks", and thus `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` was effectively implicitly defined.
+
+ Beginning with version 1.3, the default behavior of JSONKit is to use the standard Core Foundation collection callbacks ([`kCFTypeArrayCallBacks`][kCFTypeArrayCallBacks], [`kCFTypeDictionaryKeyCallBacks`][kCFTypeDictionaryKeyCallBacks], and [`kCFTypeDictionaryValueCallBacks`][kCFTypeDictionaryValueCallBacks]). The intention is to follow "the principle of least surprise", and the author believes the use of the standard Core Foundation collection callbacks as the default behavior for JSONKit results in the least surprise.
+
+ **NOTE**: `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` is only applicable to `(CF|NS)` `Dictionary` and `Array` class objects.
+
+ For the vast majority of users, the author believes JSONKits custom "Transfer of Ownership Collection Callbacks" will not cause any problems. As previously stated, the author has used this technique in performance critical code for years and has never had a problem. Until a user reported a problem with [`-mutableCopy`][-mutableCopy], the author was unaware that the use of the custom callbacks could even cause a problem. This is probably due to the fact that the vast majority of time the typical usage pattern tends to be "iterate the contents of the collection" and very rarely mutate the returned collection directly (although this last part is likely to vary significantly from programmer to programmer). The author tends to avoid the use of [`-mutableCopy`][-mutableCopy] as it results in a significant performance and memory consumption penalty. The reason for this is in "typical" Cocoa coding patterns, using [`-mutableCopy`][-mutableCopy] will instantiate an identica!
l, albeit mutable, version of the original object. This requires both memory for the new object and time to iterate the contents of the original object and add them to the new object. Furthermore, under "typical" Cocoa coding patterns, the original collection object continues to consume memory until the autorelease pool is released. However, clearly there are cases where the use of [`-mutableCopy`][-mutableCopy] makes sense or may be used by an external library which is out of your direct control.
+
+ The use of the standard Core Foundation collection callbacks results in a 9% to 23% reduction in parsing performance, with an "eye-balled average" of around 13% according to some benchmarking done by the author using Real World™ JSON (i.e., actual JSON from various web services, such as Twitter, etc) using `gcc-4.2 -arch x86_64 -O3 -DNS_BLOCK_ASSERTIONS` with the only change being the addition of <span style="white-space: nowrap;">`-DJK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS`</span>.
+
+ `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS` is only applicable to parsing / deserializing (i.e. converting from) of JSON. Serializing (i.e., converting to JSON) is completely unaffected by this change.
+
+### Bug Fixes
+
+* Fixed a [bug report regarding `-mutableCopy`](https://github.com/johnezang/JSONKit/issues#issue/3). This is related to the addition of the pre-processor define flag `JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS`.
+
+### Other Changes
+
+* Added `JK_EXPECTED` optimization hints around several conditionals.
+* When serializing objects, JSONKit first starts with a small, on stack buffer. If the encoded JSON exceeds the size of the stack buffer, JSONKit switches to a heap allocated buffer. If JSONKit switched to a heap allocated buffer, [`CFDataCreateWithBytesNoCopy`][CFDataCreateWithBytesNoCopy] is used to create the [`NSData`][NSData] object, which in most cases causes the heap allocated buffer to "transfer" to the [`NSData`][NSData] object which is substantially faster than allocating a new buffer and copying the bytes.
+* Added a pre-processor check in `JSONKit.m` to see if Objective-C Garbage Collection is enabled and issue a `#error` notice that JSONKit does not support Objective-C Garbage Collection.
+* Various other minor or trivial modifications, such as updating `README.md`.
+
+### Other Issues
+
+* When using the `clang` static analyzer (the version used at the time of this writing was `Apple clang version 1.5 (tags/Apple/clang-60)`), the static analyzer reports a number of problems with `JSONKit.m`.
+
+ The author has investigated these issues and determined that the problems reported by the current version of the static analyzer are "false positives". Not only that, the reported problems are not only "false positives", they are very clearly and obviously wrong. Therefore, the author has made the decision that no action will be taken on these non-problems, which includes not modifying the code for the sole purpose of silencing the static analyzer. The justification for this is "the dog wags the tail, not the other way around."
+
+## Version 1.2 2011/01/08
+
+### Bug Fixes
+
+* When JSONKit attempted to parse and decode JSON that contained `{"key": value}` dictionaries that contained the same key more than once would likely result in a crash. This was a serious bug.
+* Under some conditions, JSONKit could potentially leak memory.
+* There was an off by one error in the code that checked whether or not the parser was at the end of the `UTF8` buffer. This could result in JSONKit reading one by past the buffer bounds in some cases.
+
+### Other Changes
+
+* Some of the methods were missing `NULL` pointer checks for some of their arguments. This was fixed. In generally, when JSONKit encounters invalid arguments, it throws a `NSInvalidArgumentException` exception.
+* Various other minor changes such as tightening up numeric literals with `UL` or `L` qualification, assertion check tweaks and additions, etc.
+* The README.md file was updated with additional information.
+
+### Version 1.1
+
+No change log information was kept for versions prior to 1.2.
+
+[kCFTypeArrayCallBacks]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFArrayRef/Reference/reference.html#//apple_ref/c/data/kCFTypeArrayCallBacks
+[kCFTypeDictionaryKeyCallBacks]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFDictionaryRef/Reference/reference.html#//apple_ref/c/data/kCFTypeDictionaryKeyCallBacks
+[kCFTypeDictionaryValueCallBacks]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFDictionaryRef/Reference/reference.html#//apple_ref/c/data/kCFTypeDictionaryValueCallBacks
+[-mutableCopy]: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html%23//apple_ref/occ/instm/NSObject/mutableCopy
+[-copy]: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html%23//apple_ref/occ/instm/NSObject/copy
+[-retain]: http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/retain
+[CFRetain]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/Reference/reference.html#//apple_ref/c/func/CFRetain
+[CFRelease]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/Reference/reference.html#//apple_ref/c/func/CFRelease
+[CFDataCreateWithBytesNoCopy]: http://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFDataRef/Reference/reference.html#//apple_ref/c/func/CFDataCreateWithBytesNoCopy
+[NSData]: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/index.html
diff -r 4b731f6f7972 -r c3c7a69e75ee Frameworks/JSONKit/JSONKit.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/JSONKit/JSONKit.h Tue Mar 15 22:01:45 2011 -0700
@@ -0,0 +1,263 @@
+//
+// JSONKit.h
+// http://github.com/johnezang/JSONKit
+// Licensed under the terms of the BSD License, as specified below.
+//
+
+/*
+ Copyright (c) 2011, John Engelhart
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the Zang Industries nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stddef.h>
+#include <stdint.h>
+#include <limits.h>
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+
+#ifdef __OBJC__
+#import <Foundation/NSArray.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSError.h>
+#import <Foundation/NSObjCRuntime.h>
+#import <Foundation/NSString.h>
+#endif // __OBJC__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// For Mac OS X < 10.5.
+#ifndef NSINTEGER_DEFINED
+#define NSINTEGER_DEFINED
+#if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+#define NSIntegerMin LONG_MIN
+#define NSIntegerMax LONG_MAX
+#define NSUIntegerMax ULONG_MAX
+#else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
+typedef int NSInteger;
+typedef unsigned int NSUInteger;
+#define NSIntegerMin INT_MIN
+#define NSIntegerMax INT_MAX
+#define NSUIntegerMax UINT_MAX
+#endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
+#endif // NSINTEGER_DEFINED
+
+
+#ifndef _JSONKIT_H_
+#define _JSONKIT_H_
+
+#define JSONKIT_VERSION_MAJOR 1
+#define JSONKIT_VERSION_MINOR 3
+
+typedef NSUInteger JKHash;
+typedef NSUInteger JKFlags;
+typedef NSUInteger JKTokenType;
+typedef JKFlags JKManagedBufferFlags;
+typedef JKFlags JKObjectStackFlags;
+
+typedef struct {
+ unsigned char *ptr;
+ size_t length;
+} JKPtrRange;
+
+typedef struct {
+ const unsigned char *ptr;
+ size_t length;
+} JKConstPtrRange;
+
+typedef struct {
+ size_t location, length;
+} JKRange;
+
+typedef struct {
+ JKPtrRange bytes;
+ JKManagedBufferFlags flags;
+ size_t roundSizeUpToMultipleOf;
+} JKManagedBuffer;
+
+typedef struct {
+ void **objects, **keys;
+ JKHash *hashes;
+ size_t *sizes;
+ size_t count, index, roundSizeUpToMultipleOf;
+ JKObjectStackFlags flags;
+} JKObjectStack;
+
+typedef struct {
+ JKPtrRange bytes;
+} JKBuffer;
+
+typedef struct {
+ JKConstPtrRange bytes;
+} JKConstBuffer;
+
+typedef NSUInteger JKValueType;
+
+typedef struct {
+ JKConstPtrRange ptrRange;
+ JKHash hash;
+ JKValueType type;
+ union {
+ long long longLongValue;
+ unsigned long long unsignedLongLongValue;
+ double doubleValue;
+ } number;
+} JKTokenValue;
+
+typedef struct {
+ JKConstPtrRange tokenPtrRange;
+ JKTokenType type;
+ JKTokenValue value;
+ JKManagedBuffer tokenBuffer;
+} JKParseToken;
+
+
+typedef struct {
+ void *object;
+ JKHash hash;
+ size_t size;
+ unsigned char *bytes;
+ JKValueType type;
+ unsigned char age;
+} JKTokenCacheItem;
+
+typedef struct {
+ JKTokenCacheItem *items;
+ size_t count, clockIdx;
+} JKTokenCache;
+
+/*
+ JKParseOptionComments : Allow C style // and /_* ... *_/ (without a _, obviously) comments in JSON.
+ JKParseOptionUnicodeNewlines : Allow Unicode recommended (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}]) newlines.
+ JKParseOptionLooseUnicode : Normally the decoder will stop with an error at any malformed Unicode.
+ This option allows JSON with malformed Unicode to be parsed without reporting an error.
+ Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER".
+ */
+
+enum {
+ JKParseOptionNone = 0,
+ JKParseOptionStrict = 0,
+ JKParseOptionComments = (1 << 0),
+ JKParseOptionUnicodeNewlines = (1 << 1),
+ JKParseOptionLooseUnicode = (1 << 2),
+ JKParseOptionPermitTextAfterValidJSON = (1 << 3),
+ JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON),
+};
+typedef JKFlags JKParseOptionFlags;
+
+typedef id (*NSNumberAllocImp)(id object, SEL selector);
+typedef id (*NSNumberInitWithUnsignedLongLongImp)(id object, SEL selector, unsigned long long value);
+
+typedef struct {
+ Class NSNumberClass;
+ NSNumberAllocImp NSNumberAlloc;
+ NSNumberInitWithUnsignedLongLongImp NSNumberInitWithUnsignedLongLong;
+} JKObjCImpCache;
+
+typedef struct {
+ JKParseOptionFlags parseOptionFlags;
+ JKConstBuffer stringBuffer;
+ size_t atIndex, lineNumber, lineStartIndex;
+ size_t prev_atIndex, prev_lineNumber, prev_lineStartIndex;
+ int errorIsPrev;
+ JKParseToken token;
+ JKObjectStack objectStack;
+ JKTokenCache cache;
+ JKObjCImpCache objCImpCache;
+ NSError *error;
+} JKParseState;
+
+
+enum {
+ JKSerializeOptionNone = 0,
+ JKSerializeOptionPretty = (1 << 0), // Not implemented yet...
+ JKSerializeOptionEscapeUnicode = (1 << 1),
+ JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode),
+};
+typedef JKFlags JKSerializeOptionFlags;
+
+
+#ifdef __OBJC__
+
+// As a general rule of thumb, if you use a method that doesn't accept a JKParseOptionFlags argument, it defaults to JKParseOptionStrict
+
+ at interface JSONDecoder : NSObject {
+ JKParseState parseState;
+}
++ (id)decoder;
++ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
+- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
+- (void)clearCache;
+- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length;
+- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error;
+// The NSData MUST be UTF8 encoded JSON.
+- (id)parseJSONData:(NSData *)jsonData;
+- (id)parseJSONData:(NSData *)jsonData error:(NSError **)error;
+ at end
+
+ at interface NSString (JSONKit)
+- (id)objectFromJSONString;
+- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
+- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
+ at end
+
+ at interface NSData (JSONKit)
+// The NSData MUST be UTF8 encoded JSON.
+- (id)objectFromJSONData;
+- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
+- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
+ at end
+
+ at interface NSArray (JSONKit)
+- (NSData *)JSONData;
+- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
+- (NSString *)JSONString;
+- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
+ at end
+
+ at interface NSDictionary (JSONKit)
+- (NSData *)JSONData;
+- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
+- (NSString *)JSONString;
+- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
+ at end
+
+#endif // __OBJC__
+
+#endif // _JSONKIT_H_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff -r 4b731f6f7972 -r c3c7a69e75ee Frameworks/JSONKit/JSONKit.m
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frameworks/JSONKit/JSONKit.m Tue Mar 15 22:01:45 2011 -0700
@@ -0,0 +1,1889 @@
+//
+// JSONKit.m
+// http://github.com/johnezang/JSONKit
+// Licensed under the terms of the BSD License, as specified below.
+//
+
+/*
+ Copyright (c) 2011, John Engelhart
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the Zang Industries nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*
+ Acknowledgments:
+
+ The bulk of the UTF8 / UTF32 conversion and verification comes
+ from ConvertUTF.[hc]. It has been modified from the original sources.
+
+ The original sources were obtained from http://www.unicode.org/.
+ However, the web site no longer seems to host the files. Instead,
+ the Unicode FAQ http://www.unicode.org/faq//utf_bom.html#gen4
+ points to International Components for Unicode (ICU)
+ http://site.icu-project.org/ as an example of how to write a UTF
+ converter.
+
+ The decision to use the ConvertUTF.[ch] code was made to leverage
+ "proven" code. Hopefully the local modifications are bug free.
+
+ The code in isValidCodePoint() is derived from the ICU code in
+ utf.h for the macros U_IS_UNICODE_NONCHAR and U_IS_UNICODE_CHAR.
+
+ From the original ConvertUTF.[ch]:
+
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/errno.h>
+#include <math.h>
+
+#import "JSONKit.h"
+
+//#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFArray.h>
+#include <CoreFoundation/CFDictionary.h>
+#include <CoreFoundation/CFNumber.h>
+
+//#import <Foundation/Foundation.h>
+#import <Foundation/NSArray.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSException.h>
+#import <Foundation/NSNull.h>
+#import <Foundation/NSObjCRuntime.h>
+
+#ifdef __OBJC_GC__
+#error JSONKit does not support Objective-C Garbage Collection
+#endif
+
+// For DJB hash.
+#define JK_HASH_INIT (1402737925UL)
+
+// Use __builtin_clz() instead of trailingBytesForUTF8[] table lookup.
+#define JK_FAST_TRAILING_BYTES
+
+// JK_CACHE_SLOTS must be a power of 2. Default size is 1024 slots.
+#define JK_CACHE_SLOTS_BITS (10)
+#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
+#define JK_INIT_CACHE_AGE (31)
+
+// JK_TOKENBUFFER_SIZE is the default stack size for the temporary buffer used to hold "non-simple" strings (i.e., contains \ escapes)
+#define JK_TOKENBUFFER_SIZE (1024UL * 2UL)
+
+// JK_STACK_OBJS is the default number of spaces reserved on the stack for temporarily storing pointers to Obj-C objects before they can be transferred to a NSArray / NSDictionary.
+#define JK_STACK_OBJS (1024UL * 1UL)
+
+#define JK_JSONBUFFER_SIZE (1024UL * 4UL)
+#define JK_UTF8BUFFER_SIZE (1024UL * 16UL)
+
+
+
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#define JK_ATTRIBUTES(attr, ...) __attribute__((attr, ##__VA_ARGS__))
+#define JK_EXPECTED(cond, expect) __builtin_expect((long)(cond), (expect))
+#define JK_PREFETCH(ptr) __builtin_prefetch(ptr)
+#else // defined (__GNUC__) && (__GNUC__ >= 4)
+#define JK_ATTRIBUTES(attr, ...)
+#define JK_EXPECTED(cond, expect) (cond)
+#define JK_PREFETCH(ptr)
+#endif // defined (__GNUC__) && (__GNUC__ >= 4)
+
+#define JK_STATIC_INLINE static __inline__ JK_ATTRIBUTES(always_inline)
+#define JK_ALIGNED(arg) JK_ATTRIBUTES(aligned(arg))
+#define JK_UNUSED_ARG JK_ATTRIBUTES(unused)
+#define JK_WARN_UNUSED JK_ATTRIBUTES(warn_unused_result)
+#define JK_WARN_UNUSED_CONST JK_ATTRIBUTES(warn_unused_result, const)
+#define JK_WARN_UNUSED_PURE JK_ATTRIBUTES(warn_unused_result, pure)
+#define JK_WARN_UNUSED_SENTINEL JK_ATTRIBUTES(warn_unused_result, sentinel)
+#define JK_NONNULL_ARGS(arg, ...) JK_ATTRIBUTES(nonnull(arg, ##__VA_ARGS__))
+#define JK_WARN_UNUSED_NONNULL_ARGS(arg, ...) JK_ATTRIBUTES(warn_unused_result, nonnull(arg, ##__VA_ARGS__))
+#define JK_WARN_UNUSED_CONST_NONNULL_ARGS(arg, ...) JK_ATTRIBUTES(warn_unused_result, const, nonnull(arg, ##__VA_ARGS__))
+#define JK_WARN_UNUSED_PURE_NONNULL_ARGS(arg, ...) JK_ATTRIBUTES(warn_unused_result, pure, nonnull(arg, ##__VA_ARGS__))
+
+#if defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
+#define JK_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) JK_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__), alloc_size(as))
+#else // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
+#define JK_ALLOC_SIZE_NON_NULL_ARGS_WARN_UNUSED(as, nn, ...) JK_ATTRIBUTES(warn_unused_result, nonnull(nn, ##__VA_ARGS__))
+#endif // defined (__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
+
+typedef uint32_t UTF32; /* at least 32 bits */
+typedef uint16_t UTF16; /* at least 16 bits */
+typedef uint8_t UTF8; /* typically 8 bits */
+
+typedef enum {
+ 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;
+
+enum {
+ JKTokenTypeInvalid = 0,
+ JKTokenTypeNumber = 1,
+ JKTokenTypeString = 2,
+ JKTokenTypeObjectBegin = 3,
+ JKTokenTypeObjectEnd = 4,
+ JKTokenTypeArrayBegin = 5,
+ JKTokenTypeArrayEnd = 6,
+ JKTokenTypeSeparator = 7,
+ JKTokenTypeComma = 8,
+ JKTokenTypeTrue = 9,
+ JKTokenTypeFalse = 10,
+ JKTokenTypeNull = 11,
+ JKTokenTypeWhiteSpace = 12,
+};
+
+enum {
+ JKManagedBufferOnStack = 1,
+ JKManagedBufferOnHeap = 2,
+ JKManagedBufferLocationMask = (0x3),
+ JKManagedBufferLocationShift = (0),
+
+ JKManagedBufferMustFree = (1 << 2),
+};
+
+enum {
+ JKObjectStackOnStack = 1,
+ JKObjectStackOnHeap = 2,
+ JKObjectStackLocationMask = (0x3),
+ JKObjectStackLocationShift = (0),
+
+ JKObjectStackMustFree = (1 << 2),
+};
+
+// These are prime numbers to assist with hash slot probing.
+enum {
+ JKValueTypeNone = 0,
+ JKValueTypeString = 5,
+ JKValueTypeLongLong = 7,
+ JKValueTypeUnsignedLongLong = 11,
+ JKValueTypeDouble = 13,
+};
+
+enum {
+ JSONNumberStateStart = 0,
+ JSONNumberStateFinished = 1,
+ JSONNumberStateError = 2,
+ JSONNumberStateWholeNumberStart = 3,
+ JSONNumberStateWholeNumberMinus = 4,
+ JSONNumberStateWholeNumberZero = 5,
+ JSONNumberStateWholeNumber = 6,
+ JSONNumberStatePeriod = 7,
+ JSONNumberStateFractionalNumberStart = 8,
+ JSONNumberStateFractionalNumber = 9,
+ JSONNumberStateExponentStart = 10,
+ JSONNumberStateExponentPlusMinus = 11,
+ JSONNumberStateExponent = 12,
+};
+
+enum {
+ JSONStringStateStart = 0,
+ JSONStringStateParsing = 1,
+ JSONStringStateFinished = 2,
+ JSONStringStateError = 3,
+ JSONStringStateEscape = 4,
+ JSONStringStateEscapedUnicode1 = 5,
+ JSONStringStateEscapedUnicode2 = 6,
+ JSONStringStateEscapedUnicode3 = 7,
+ JSONStringStateEscapedUnicode4 = 8,
+ JSONStringStateEscapedUnicodeSurrogate1 = 9,
+ JSONStringStateEscapedUnicodeSurrogate2 = 10,
+ JSONStringStateEscapedUnicodeSurrogate3 = 11,
+ JSONStringStateEscapedUnicodeSurrogate4 = 12,
+ JSONStringStateEscapedNeedEscapeForSurrogate = 13,
+ JSONStringStateEscapedNeedEscapedUForSurrogate = 14,
+};
+
+enum {
+ JKParseAcceptValue = (1 << 0),
+ JKParseAcceptComma = (1 << 1),
+ JKParseAcceptEnd = (1 << 2),
+ JKParseAcceptValueOrEnd = (JKParseAcceptValue | JKParseAcceptEnd),
+ JKParseAcceptCommaOrEnd = (JKParseAcceptComma | JKParseAcceptEnd),
+};
+
+typedef struct {
+ void *stringClass;
+ void *numberClass;
+ void *arrayClass;
+ void *dictionaryClass;
+ void *nullClass;
+} JKFastClassLookup;
+
+enum {
+ JKClassUnknown = 0,
+ JKClassString = 1,
+ JKClassNumber = 2,
+ JKClassArray = 3,
+ JKClassDictionary = 4,
+ JKClassNull = 5,
+};
+
+typedef struct {
+ JKManagedBuffer utf8ConversionBuffer;
+ JKManagedBuffer stringBuffer;
+ size_t atIndex;
+ JKFastClassLookup fastClassLookup;
+ JKSerializeOptionFlags serializeOptionFlags;
+ NSError *error;
+} JKEncodeState;
+
+
+
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+
+
+#if !defined(JK_FAST_TRAILING_BYTES)
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+#endif
+
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+#ifdef JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS
+
+static void jk_CFCallbackRelease(CFAllocatorRef allocator JK_UNUSED_ARG, const void *ptr) { CFRelease((CFTypeRef)ptr); }
+static const CFArrayCallBacks jk_transferOwnershipArrayCallBacks = { (CFIndex)0L, NULL, jk_CFCallbackRelease, CFCopyDescription, CFEqual };
+static const CFDictionaryKeyCallBacks jk_transferOwnershipDictionaryKeyCallBacks = { (CFIndex)0L, NULL, jk_CFCallbackRelease, CFCopyDescription, CFEqual, CFHash };
+static const CFDictionaryValueCallBacks jk_transferOwnershipDictionaryValueCallBacks = { (CFIndex)0L, NULL, jk_CFCallbackRelease, CFCopyDescription, CFEqual };
+
+#define jk_kArrayCallbacks jk_transferOwnershipArrayCallBacks
+#define jk_kDictionaryKeyCallBacks jk_transferOwnershipDictionaryKeyCallBacks
+#define jk_kDictionaryValueCallBacks jk_transferOwnershipDictionaryValueCallBacks
+#define JK_RELEASE_COLLECTION_OBJECTS 0
+
+#else // JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS defined
+
+#define jk_kArrayCallbacks kCFTypeArrayCallBacks
+#define jk_kDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks
+#define jk_kDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks
+#define JK_RELEASE_COLLECTION_OBJECTS 1
+
+#endif // JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS
+
+
+#define JK_AT_STRING_PTR(x) (&((x)->stringBuffer.bytes.ptr[(x)->atIndex]))
+#define JK_END_STRING_PTR(x) (&((x)->stringBuffer.bytes.ptr[(x)->stringBuffer.bytes.length]))
+
+
+static void jk_managedBuffer_release(JKManagedBuffer *managedBuffer);
+static void jk_managedBuffer_setToStackBuffer(JKManagedBuffer *managedBuffer, unsigned char *ptr, size_t length);
+static unsigned char *jk_managedBuffer_resize(JKManagedBuffer *managedBuffer, size_t newSize);
+static void jk_objectStack_release(JKObjectStack *objectStack);
+static void jk_objectStack_setToStackBuffer(JKObjectStack *objectStack, void **objects, void **keys, JKHash *hashes, size_t *sizes, size_t count);
+static int jk_objectStack_resize(JKObjectStack *objectStack, size_t newCount);
+
+static void jk_error(JKParseState *parseState, NSString *format, ...);
+static int jk_parse_string(JKParseState *parseState);
+static int jk_parse_number(JKParseState *parseState);
+static size_t jk_parse_is_newline(JKParseState *parseState, const unsigned char *atCharacterPtr);
+JK_STATIC_INLINE int jk_parse_skip_newline(JKParseState *parseState);
+JK_STATIC_INLINE void jk_parse_skip_whitespace(JKParseState *parseState);
+static int jk_parse_next_token(JKParseState *parseState);
+static void jk_error_parse_accept_or3(JKParseState *parseState, int state, NSString *or1String, NSString *or2String, NSString *or3String);
+static void *jk_create_dictionary(JKParseState *parseState, size_t startingObjectIndex);
+static void *jk_parse_dictionary(JKParseState *parseState);
+static void *jk_parse_array(JKParseState *parseState);
+static void *jk_object_for_token(JKParseState *parseState);
+static void *jk_cachedObjects(JKParseState *parseState);
+JK_STATIC_INLINE void jk_cache_age(JKParseState *parseState);
+JK_STATIC_INLINE void jk_set_parsed_token(JKParseState *parseState, const unsigned char *ptr, size_t length, JKTokenType type, size_t advanceBy);
+
+
+static void jk_encode_error(JKEncodeState *encodeState, NSString *format, ...);
+static int jk_encode_printf(JKEncodeState *encodeState, const char *format, ...);
+static int jk_encode_write(JKEncodeState *encodeState, const char *format);
+static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *objectPtr);
+static NSData *jk_encode(void *object, JKSerializeOptionFlags optionFlags, NSError **error);
+
+
+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 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); }
+
+static void jk_error(JKParseState *parseState, NSString *format, ...) {
+ NSCParameterAssert((parseState != NULL) && (format != NULL));
+
+ va_list varArgsList;
+ va_start(varArgsList, format);
+ NSString *formatString = [[[NSString alloc] initWithFormat:format arguments:varArgsList] autorelease];
+ va_end(varArgsList);
+
+#if 0
+ const unsigned char *lineStart = parseState->stringBuffer.bytes.ptr + parseState->lineStartIndex;
+ const unsigned char *lineEnd = lineStart;
+ const unsigned char *atCharacterPtr = NULL;
+
+ for(atCharacterPtr = lineStart; atCharacterPtr < JK_END_STRING_PTR(parseState); atCharacterPtr++) { lineEnd = atCharacterPtr; if(jk_parse_is_newline(parseState, atCharacterPtr)) { break; } }
+
+ NSString *lineString = @"", *carretString = @"";
+ if(lineStart < JK_END_STRING_PTR(parseState)) {
+ lineString = [[[NSString alloc] initWithBytes:lineStart length:(lineEnd - lineStart) encoding:NSUTF8StringEncoding] autorelease];
+ carretString = [NSString stringWithFormat:@"%*.*s^", (int)(parseState->atIndex - parseState->lineStartIndex), (int)(parseState->atIndex - parseState->lineStartIndex), " "];
+ }
+#endif
+
+ 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",
More information about the commits
mailing list