// 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.
#defineJK_CACHE_PROBES (4UL)
// JK_INIT_CACHE_AGE must be < (1 << AGE) - 1, where AGE is sizeof(typeof(AGE)) * 8.
#defineJK_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)
#defineJK_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((objectsPtr == NULL) && (NSMaxRange(range) > 0UL)) { [NSExceptionraise:NSRangeExceptionformat:@"*** -[%@%@]: pointer to objects array is NULL but range length is %lu", NSStringFromClass([selfclass]), NSStringFromSelector(_cmd), (unsignedlong)NSMaxRange(range)]; }
[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.
// 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.