Muscovy updated to Lion, Xcode 4.3.x and a new code signing cert.
//
// JSONKit.m
// http://github.com/johnezang/JSONKit
// Dual licensed under either the terms of the BSD License, or alternatively
// under the terms of the Apache License, Version 2.0, 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.
*/
/*
Copyright 2011 John Engelhart
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
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>
#include<limits.h>
#include<objc/runtime.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/NSAutoreleasePool.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSObjCRuntime.h>
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#ifdef JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS
#warning As of JSONKit v1.4, JK_ENABLE_CF_TRANSFER_OWNERSHIP_CALLBACKS is no longer required. It is no longer a valid option.
#endif
#ifdef __OBJC_GC__
#error JSONKit does not support Objective-C Garbage Collection
#endif
#if __has_feature(objc_arc)
#error JSONKit does not support Objective-C Automatic Reference Counting (ARC)
#endif
// The following checks are really nothing more than sanity checks.
// JSONKit technically has a few problems from a "strictly C99 conforming" standpoint, though they are of the pedantic nitpicking variety.
// In practice, though, for the compilers and architectures we can reasonably expect this code to be compiled for, these pedantic nitpicks aren't really a problem.
// Since we're limited as to what we can do with pre-processor #if checks, these checks are not nearly as through as they should be.
#error JSONKit requires the C 'int' and 'long' types to be the same on 32-bit architectures.
#endif
// Cocoa / Foundation uses NS*Integer as the type for a lot of arguments. We make sure that NS*Integer is something we are expecting and is reasonably compatible with size_t / ssize_t
// 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 (0)
// 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.
// 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
// mutable version, and keeps an ivar bit for whether or not that instance is mutable. This means that the immutable versions of the collection
// classes receive the mutating methods, but this is handled by having those methods throw an exception when the ivar bit is set to immutable.
// We adopt the same strategy here. It's both cleaner and gets rid of the method swizzling hackery used in JSONKit v1.4.
// This is a workaround for issue #23 https://github.com/johnezang/JSONKit/pull/23
// Basically, there seem to be a problem with using +load in static libraries on iOS. However, __attribute__ ((constructor)) does work correctly.
// Since we do not require anything "special" that +load provides, and we can accomplish the same thing using __attribute__ ((constructor)), the +load logic was moved here.
NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];// Though technically not required, the run time environment at load time initialization may be less than ideal.
[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** - [%@ %@]: The %@ class is private to JSONKit and should not be used in this fashion.",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),NSStringFromClass([selfclass])];
if((newObjects=(id*)realloc(array->objects,sizeof(id)*(array->capacity+16UL)))==NULL){[NSExceptionraise:NSMallocExceptionformat:@"Unable to resize objects array."];}
if((objectsPtr==NULL)&&(NSMaxRange(range)>0UL)){[NSExceptionraise:NSRangeExceptionformat:@"*** -[%@ %@]: pointer to objects array is NULL but range length is %lu",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),NSMaxRange(range)];}
if((range.location>count)||(NSMaxRange(range)>count)){[NSExceptionraise:NSRangeExceptionformat:@"*** -[%@ %@]: index (%lu) beyond bounds (%lu)",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),NSMaxRange(range),count];}
if(mutations==0UL){[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"*** -[%@ %@]: mutating method sent to immutable object",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(anObject==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** -[%@ %@]: attempt to insert nil",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(objectIndex>count){[NSExceptionraise:NSRangeExceptionformat:@"*** -[%@ %@]: index (%lu) beyond bounds (%lu)",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),objectIndex,count+1UL];}
if(mutations==0UL){[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"*** -[%@ %@]: mutating method sent to immutable object",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(objectIndex>=count){[NSExceptionraise:NSRangeExceptionformat:@"*** -[%@ %@]: index (%lu) beyond bounds (%lu)",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),objectIndex,count];}
if(mutations==0UL){[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"*** -[%@ %@]: mutating method sent to immutable object",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(anObject==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** -[%@ %@]: attempt to insert nil",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(objectIndex>=count){[NSExceptionraise:NSRangeExceptionformat:@"*** -[%@ %@]: index (%lu) beyond bounds (%lu)",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),objectIndex,count];}
[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** - [%@ %@]: The %@ class is private to JSONKit and should not be used in this fashion.",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),NSStringFromClass([selfclass])];
return(NULL);
}
// These values are taken from Core Foundation CF-550 CFBasicHash.m. As a bonus, they align very well with our JKHashTableEntry struct too.
if(JK_EXPECT_F((dictionary->entry=(JKHashTableEntry*)calloc(1UL,sizeof(JKHashTableEntry)*capacityForCount))==NULL)){[NSExceptionraise:NSMallocExceptionformat:@"Unable to allocate memory for hash table."];}
// 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.
if(JK_EXPECT_F(atEntry->key==NULL)){NSCParameterAssert(atEntry->object==NULL);return(NULL);break;}// If the key was in the table, we would have found it by now.
if(mutations==0UL){[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"*** -[%@ %@]: mutating method sent to immutable object",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(aKey==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** -[%@ %@]: attempt to insert nil key",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(anObject==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** -[%@ %@]: attempt to insert nil value (key: %@)",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd),aKey];}
_JKDictionaryResizeIfNeccessary(self);
#ifndef __clang_analyzer__
aKey=[aKeycopy];// Why on earth would clang complain that this -copy "might leak",
anObject=[anObjectretain];// but this -retain doesn't!?
if(mutations==0UL){[NSExceptionraise:NSInternalInconsistencyExceptionformat:@"*** -[%@ %@]: mutating method sent to immutable object",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(aKey==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"*** -[%@ %@]: attempt to remove nil key",NSStringFromClass([selfclass]),NSStringFromSelector(_cmd)];}
if(JK_EXPECT_F((tokenBufferIdx+16UL)>parseState->token.tokenBuffer.bytes.length)){if((tokenBuffer=jk_managedBuffer_resize(&parseState->token.tokenBuffer,tokenBufferIdx+1024UL))==NULL){jk_error(parseState,@"Internal error: Unable to resize temporary buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}}
memcpy(tokenBuffer,stringStart,tokenBufferIdx);
gotoslowMatch;
}
if(JK_EXPECT_F(currentChar<0x20UL)){jk_error(parseState,@"Invalid character < 0x20 found in string: 0x%2.2x.",currentChar);stringState=JSONStringStateError;gotofinishedParsing;}
if((tokenBufferIdx+16UL)>parseState->token.tokenBuffer.bytes.length){if((tokenBuffer=jk_managedBuffer_resize(&parseState->token.tokenBuffer,tokenBufferIdx+1024UL))==NULL){jk_error(parseState,@"Internal error: Unable to resize temporary buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}}
if((result==sourceIllegal)&&((parseState->parseOptionFlags&JKParseOptionLooseUnicode)==0)){jk_error(parseState,@"Illegal UTF8 sequence found in \"\" string.");stringState=JSONStringStateError;gotofinishedParsing;}
if(result==sourceExhausted){jk_error(parseState,@"End of buffer reached while parsing UTF8 in \"\" string.");stringState=JSONStringStateError;gotofinishedParsing;}
if(jk_string_add_unicodeCodePoint(parseState,u32ch,&tokenBufferIdx,&stringHash)){jk_error(parseState,@"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}
if(jk_string_add_unicodeCodePoint(parseState,escapedUnicodeCodePoint,&tokenBufferIdx,&stringHash)){jk_error(parseState,@"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}
default:jk_error(parseState,@"Unexpected character found in \\u Unicode escape sequence. Found '%c', expected [0-9a-fA-F].",currentChar);stringState=JSONStringStateError;gotofinishedParsing;break;
if((parseState->parseOptionFlags&JKParseOptionLooseUnicode)==0){jk_error(parseState,@"Required a second \\u Unicode escape sequence following a surrogate \\u Unicode escape sequence.");stringState=JSONStringStateError;gotofinishedParsing;}
else{stringState=JSONStringStateParsing;atStringCharacter--;if(jk_string_add_unicodeCodePoint(parseState,UNI_REPLACEMENT_CHAR,&tokenBufferIdx,&stringHash)){jk_error(parseState,@"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}}
if((parseState->parseOptionFlags&JKParseOptionLooseUnicode)==0){jk_error(parseState,@"Required a second \\u Unicode escape sequence following a surrogate \\u Unicode escape sequence.");stringState=JSONStringStateError;gotofinishedParsing;}
else{stringState=JSONStringStateParsing;atStringCharacter-=2;if(jk_string_add_unicodeCodePoint(parseState,UNI_REPLACEMENT_CHAR,&tokenBufferIdx,&stringHash)){jk_error(parseState,@"Internal error: Unable to add UTF8 sequence to internal string buffer. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;}}
}
break;
default:jk_error(parseState,@"Internal error: Unknown stringState. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);stringState=JSONStringStateError;gotofinishedParsing;break;
parseState->token.value.number.doubleValue=strtod((constchar*)numberTempBuf,(char**)&endOfNumber);// strtod is documented to return U+2261 (identical to) 0.0 on an underflow error (along with setting errno to ERANGE).
caseJKValueTypeDouble:jk_error(parseState,@"The value '%s' could not be represented as a 'double' due to %s.",numberTempBuf,(parseState->token.value.number.doubleValue==0.0)?"underflow":"overflow");break;// see above for == 0.0.
caseJKValueTypeLongLong:jk_error(parseState,@"The value '%s' exceeded the minimum value that could be represented: %lld.",numberTempBuf,parseState->token.value.number.longLongValue);break;
caseJKValueTypeUnsignedLongLong:jk_error(parseState,@"The value '%s' exceeded the maximum value that could be represented: %llu.",numberTempBuf,parseState->token.value.number.unsignedLongLongValue);break;
default:jk_error(parseState,@"Internal error: Unknown token value type. %@ line #%ld",[NSStringstringWithUTF8String:__FILE__],(long)__LINE__);break;
}
}
}
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.");}
if(acceptIdx==1){jk_error(parseState,@"Expected %@, not '%*.*s'",acceptStrings[0],(int)parseState->token.tokenPtrRange.length,(int)parseState->token.tokenPtrRange.length,parseState->token.tokenPtrRange.ptr);}
elseif(acceptIdx==2){jk_error(parseState,@"Expected %@ or %@, not '%*.*s'",acceptStrings[0],acceptStrings[1],(int)parseState->token.tokenPtrRange.length,(int)parseState->token.tokenPtrRange.length,parseState->token.tokenPtrRange.ptr);}
elseif(acceptIdx==3){jk_error(parseState,@"Expected %@, %@, or %@, not '%*.*s",acceptStrings[0],acceptStrings[1],acceptStrings[2],(int)parseState->token.tokenPtrRange.length,(int)parseState->token.tokenPtrRange.length,parseState->token.tokenPtrRange.ptr);}
// The object cache is nothing more than a hash table with open addressing collision resolution that is bounded by JK_CACHE_PROBES attempts.
//
// 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.
// 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.
//
// When an item is found in the cache, it's age is incremented.
// If a useable bucket hasn't been found, the current item (bucket) is aged along with two random items.
//
// If a value is not found in the cache, and no useable bucket has been found, that value is not added to the cache.
// This is the open addressing function. The values length and type are used as a form of "double hashing" to distribute values with the same effective value hash across different object cache buckets.
// The values type is a prime number that is relatively coprime to the other primes in the set of value types and the number of hash table buckets.
// This is here primarily to support the NSString and NSData convenience functions so the autoreleased JSONDecoder can release most of its resources before the pool pops.
if(JK_EXPECT_F(convertedCount!=stringLength)||JK_EXPECT_F(usedBytes<0L)){if(error!=NULL){*error=[NSErrorerrorWithDomain:@"JKErrorDomain"code:-1LuserInfo:[NSDictionarydictionaryWithObject:@"An error occurred converting the contents of a NSString to UTF8."forKey:NSLocalizedDescriptionKey]];}gotoexitNow;}
if(JK_EXPECT_F(((encodeState->atIndex+(formattedStringLength*2UL)+256UL)>encodeState->stringBuffer.bytes.length))&&JK_EXPECT_F((jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+(formattedStringLength*2UL)+4096UL)==NULL))){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");returnValue=1;gotoexitNow;}
if(JK_EXPECT_F(((encodeState->atIndex+strlen(format)+256UL)>encodeState->stringBuffer.bytes.length))&&JK_EXPECT_F((jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+strlen(format)+1024UL)==NULL))){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F((encodeState->atIndex+((encodeState->depth+1UL)*2UL)+16UL)>encodeState->stringBuffer.bytes.length)&&JK_EXPECT_T(jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+((encodeState->depth+1UL)*2UL)+4096UL)==NULL)){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F((encodeState->atIndex+((encodeState->depth+1UL)*2UL)+16UL)>encodeState->stringBuffer.bytes.length)&&JK_EXPECT_F(jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+((encodeState->depth+1UL)*2UL)+4096UL)==NULL)){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F((encodeState->stringBuffer.bytes.length-encodeState->atIndex)<(length+4UL))){if(jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+4096UL+length)==NULL){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}}
if(JK_EXPECT_F(((encodeState->atIndex+cacheSlot->length+256UL)>encodeState->stringBuffer.bytes.length))&&JK_EXPECT_F((jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+cacheSlot->length+1024UL)==NULL))){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(rerunningAfterClassFormatter==NO){jk_encode_error(encodeState,@"Unable to serialize object class %@.",NSStringFromClass([encodeCacheObjectclass]));return(1);}
else{jk_encode_error(encodeState,@"Unable to serialize object class %@ that was returned by the unsupported class formatter. Original object class was %@.",(object==NULL)?@"NULL":NSStringFromClass([objectclass]),NSStringFromClass([encodeCacheObjectclass]));return(1);}
}
}
// This is here for the benefit of the optimizer. It allows the optimizer to do loop invariant code motion for the JKClassArray
// and JKClassDictionary cases when printing simple, single characters via jk_encode_write(), which is actually a macro:
if(JK_EXPECT_F(((encodeState->atIndex+(stringLength*2UL)+256UL)>encodeState->stringBuffer.bytes.length))&&JK_EXPECT_F((jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+(stringLength*2UL)+1024UL)==NULL))){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F((size_t)maxStringUTF8Length>encodeState->utf8ConversionBuffer.bytes.length)&&JK_EXPECT_F(jk_managedBuffer_resize(&encodeState->utf8ConversionBuffer,maxStringUTF8Length+1024UL)==NULL)){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F(convertedCount!=stringLength)||JK_EXPECT_F(usedBytes<0L)){jk_encode_error(encodeState,@"An error occurred converting the contents of a NSString to UTF8.");return(1);}
if(JK_EXPECT_F((encodeState->atIndex+(maxStringUTF8Length*2UL)+256UL)>encodeState->stringBuffer.bytes.length)&&JK_EXPECT_F(jk_managedBuffer_resize(&encodeState->stringBuffer,encodeState->atIndex+(maxStringUTF8Length*2UL)+1024UL)==NULL)){jk_encode_error(encodeState,@"Unable to resize temporary buffer.");return(1);}
if(JK_EXPECT_F(!isfinite(dv))){jk_encode_error(encodeState,@"Floating point values must be finite. JSON does not support NaN or Infinity.");return(1);}
if(JK_EXPECT_F((keyObject->isa!=encodeState->fastClassLookup.stringClass))&&JK_EXPECT_F(([keyObjectisKindOfClass:[NSStringclass]]==NO))){jk_encode_error(encodeState,@"Key must be a string object.");return(1);}
if(JK_EXPECT_F(((id)keys[idx])->isa!=encodeState->fastClassLookup.stringClass)&&JK_EXPECT_F([(id)keys[idx]isKindOfClass:[NSStringclass]]==NO)){jk_encode_error(encodeState,@"Key must be a string object.");return(1);}
if((encodeState=(structJKEncodeState*)calloc(1UL,sizeof(JKEncodeState)))==NULL){[NSExceptionraise:NSMallocExceptionformat:@"Unable to allocate state structure."];return(NULL);}
if((error!=NULL)&&(*error!=NULL)){*error=NULL;}
if(delegate!=NULL){
if(selector==NULL){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"The delegate argument is not NULL, but the selector argument is NULL."];}
if([delegaterespondsToSelector:selector]==NO){[NSExceptionraise:NSInvalidArgumentExceptionformat:@"The serializeUnsupportedClassesUsingDelegate: delegate does not respond to the selector argument."];}
if(((encodeOption&JKEncodeOptionCollectionObj)!=0UL)&&(([objectisKindOfClass:[NSArrayclass]]==NO)&&([objectisKindOfClass:[NSDictionaryclass]]==NO))){jk_encode_error(encodeState,@"Unable to serialize object class %@, expected a NSArray or NSDictionary.",NSStringFromClass([objectclass]));gotoerrorExit;}
if(((encodeOption&JKEncodeOptionStringObj)!=0UL)&&([objectisKindOfClass:[NSStringclass]]==NO)){jk_encode_error(encodeState,@"Unable to serialize object class %@, expected a NSString.",NSStringFromClass([objectclass]));gotoerrorExit;}
if((stackBuffer==NO)&&((encodeState->stringBuffer.bytes.ptr=(unsignedchar*)reallocf(encodeState->stringBuffer.bytes.ptr,encodeState->atIndex+16UL))==NULL)){jk_encode_error(encodeState,@"Unable to realloc buffer");gotoerrorExit;}
switch((encodeOption&JKEncodeOptionAsTypeMask)){
caseJKEncodeOptionAsData:
if(stackBuffer==YES){if((returnObject=[(id)CFDataCreate(NULL,encodeState->stringBuffer.bytes.ptr,(CFIndex)encodeState->atIndex)autorelease])==NULL){jk_encode_error(encodeState,@"Unable to create NSData object");}}
else{if((returnObject=[(id)CFDataCreateWithBytesNoCopy(NULL,encodeState->stringBuffer.bytes.ptr,(CFIndex)encodeState->atIndex,NULL)autorelease])==NULL){jk_encode_error(encodeState,@"Unable to create NSData object");}}
break;
caseJKEncodeOptionAsString:
if(stackBuffer==YES){if((returnObject=[(id)CFStringCreateWithBytes(NULL,(constUInt8*)encodeState->stringBuffer.bytes.ptr,(CFIndex)encodeState->atIndex,kCFStringEncodingUTF8,NO)autorelease])==NULL){jk_encode_error(encodeState,@"Unable to create NSString object");}}
else{if((returnObject=[(id)CFStringCreateWithBytesNoCopy(NULL,(constUInt8*)encodeState->stringBuffer.bytes.ptr,(CFIndex)encodeState->atIndex,kCFStringEncodingUTF8,NO,NULL)autorelease])==NULL){jk_encode_error(encodeState,@"Unable to create NSString object");}}
break;
default:jk_encode_error(encodeState,@"Unknown encode as type.");break;
#pragma mark Methods for serializing a single NSString.
////////////
// Useful for those who need to serialize just a NSString. Otherwise you would have to do something like [NSArray arrayWithObject:stringToBeJSONSerialized], serializing the array, and then chopping of the extra ^\[.*\]$ square brackets.