226 lines
6.7 KiB
Objective-C
226 lines
6.7 KiB
Objective-C
//
|
|
// CJSONDataSerializer.m
|
|
// TouchCode
|
|
//
|
|
// Created by Jonathan Wight on 12/07/2005.
|
|
// Copyright 2005 toxicsoftware.com. All rights reserved.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person
|
|
// obtaining a copy of this software and associated documentation
|
|
// files (the "Software"), to deal in the Software without
|
|
// restriction, including without limitation the rights to use,
|
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following
|
|
// conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
#import "CJSONDataSerializer.h"
|
|
|
|
#import "CSerializedJSONData.h"
|
|
|
|
static NSData *kNULL = NULL;
|
|
static NSData *kFalse = NULL;
|
|
static NSData *kTrue = NULL;
|
|
|
|
@implementation CJSONDataSerializer
|
|
|
|
+ (void)initialize
|
|
{
|
|
NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
|
|
|
|
@synchronized(@"CJSONDataSerializer")
|
|
{
|
|
if (kNULL == NULL)
|
|
kNULL = [[NSData alloc] initWithBytesNoCopy:"null" length:4 freeWhenDone:NO];
|
|
if (kFalse == NULL)
|
|
kFalse = [[NSData alloc] initWithBytesNoCopy:"false" length:5 freeWhenDone:NO];
|
|
if (kTrue == NULL)
|
|
kTrue = [[NSData alloc] initWithBytesNoCopy:"true" length:4 freeWhenDone:NO];
|
|
}
|
|
|
|
[thePool release];
|
|
}
|
|
|
|
+ (id)serializer
|
|
{
|
|
return([[[self alloc] init] autorelease]);
|
|
}
|
|
|
|
- (NSData *)serializeObject:(id)inObject;
|
|
{
|
|
NSData *theResult = NULL;
|
|
|
|
if ([inObject isKindOfClass:[NSNull class]])
|
|
{
|
|
theResult = [self serializeNull:inObject];
|
|
}
|
|
else if ([inObject isKindOfClass:[NSNumber class]])
|
|
{
|
|
theResult = [self serializeNumber:inObject];
|
|
}
|
|
else if ([inObject isKindOfClass:[NSString class]])
|
|
{
|
|
theResult = [self serializeString:inObject];
|
|
}
|
|
else if ([inObject isKindOfClass:[NSArray class]])
|
|
{
|
|
theResult = [self serializeArray:inObject];
|
|
}
|
|
else if ([inObject isKindOfClass:[NSDictionary class]])
|
|
{
|
|
theResult = [self serializeDictionary:inObject];
|
|
}
|
|
else if ([inObject isKindOfClass:[NSData class]])
|
|
{
|
|
NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease];
|
|
theResult = [self serializeString:theString];
|
|
}
|
|
else if ([inObject isKindOfClass:[CSerializedJSONData class]])
|
|
{
|
|
theResult = [inObject data];
|
|
}
|
|
else
|
|
{
|
|
[NSException raise:NSGenericException format:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])];
|
|
}
|
|
if (theResult == NULL)
|
|
[NSException raise:NSGenericException format:@"Could not serialize object '%@'", inObject];
|
|
return(theResult);
|
|
}
|
|
|
|
- (NSData *)serializeNull:(NSNull *)inNull
|
|
{
|
|
#pragma unused (inNull)
|
|
return(kNULL);
|
|
}
|
|
|
|
- (NSData *)serializeNumber:(NSNumber *)inNumber
|
|
{
|
|
NSData *theResult = NULL;
|
|
switch (CFNumberGetType((CFNumberRef)inNumber))
|
|
{
|
|
case kCFNumberCharType:
|
|
{
|
|
int theValue = [inNumber intValue];
|
|
if (theValue == 0)
|
|
theResult = kFalse;
|
|
else if (theValue == 1)
|
|
theResult = kTrue;
|
|
else
|
|
theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
|
|
}
|
|
break;
|
|
case kCFNumberFloat32Type:
|
|
case kCFNumberFloat64Type:
|
|
case kCFNumberFloatType:
|
|
case kCFNumberDoubleType:
|
|
case kCFNumberSInt8Type:
|
|
case kCFNumberSInt16Type:
|
|
case kCFNumberSInt32Type:
|
|
case kCFNumberSInt64Type:
|
|
case kCFNumberShortType:
|
|
case kCFNumberIntType:
|
|
case kCFNumberLongType:
|
|
case kCFNumberLongLongType:
|
|
case kCFNumberCFIndexType:
|
|
default:
|
|
theResult = [[inNumber stringValue] dataUsingEncoding:NSASCIIStringEncoding];
|
|
break;
|
|
}
|
|
return(theResult);
|
|
}
|
|
|
|
- (NSData *)serializeString:(NSString *)inString
|
|
{
|
|
NSMutableString *theMutableCopy = [[inString mutableCopy] autorelease];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"/" withString:@"\\/" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\b" withString:@"\\b" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\f" withString:@"\\f" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\r" withString:@"\\r" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
[theMutableCopy replaceOccurrencesOfString:@"\t" withString:@"\\t" options:0 range:NSMakeRange(0, [theMutableCopy length])];
|
|
/*
|
|
case 'u':
|
|
{
|
|
theCharacter = 0;
|
|
|
|
int theShift;
|
|
for (theShift = 12; theShift >= 0; theShift -= 4)
|
|
{
|
|
int theDigit = HexToInt([self scanCharacter]);
|
|
if (theDigit == -1)
|
|
{
|
|
[self setScanLocation:theScanLocation];
|
|
return(NO);
|
|
}
|
|
theCharacter |= (theDigit << theShift);
|
|
}
|
|
}
|
|
*/
|
|
return([[NSString stringWithFormat:@"\"%@\"", theMutableCopy] dataUsingEncoding:NSUTF8StringEncoding]);
|
|
}
|
|
|
|
- (NSData *)serializeArray:(NSArray *)inArray
|
|
{
|
|
NSMutableData *theData = [NSMutableData data];
|
|
|
|
[theData appendBytes:"[" length:1];
|
|
|
|
NSEnumerator *theEnumerator = [inArray objectEnumerator];
|
|
id theValue = NULL;
|
|
NSUInteger i = 0;
|
|
while ((theValue = [theEnumerator nextObject]) != NULL)
|
|
{
|
|
[theData appendData:[self serializeObject:theValue]];
|
|
if (++i < [inArray count])
|
|
[theData appendBytes:"," length:1];
|
|
}
|
|
|
|
[theData appendBytes:"]" length:1];
|
|
|
|
return(theData);
|
|
}
|
|
|
|
- (NSData *)serializeDictionary:(NSDictionary *)inDictionary
|
|
{
|
|
NSMutableData *theData = [NSMutableData data];
|
|
|
|
[theData appendBytes:"{" length:1];
|
|
|
|
NSArray *theKeys = [inDictionary allKeys];
|
|
NSEnumerator *theEnumerator = [theKeys objectEnumerator];
|
|
NSString *theKey = NULL;
|
|
while ((theKey = [theEnumerator nextObject]) != NULL)
|
|
{
|
|
id theValue = [inDictionary objectForKey:theKey];
|
|
|
|
[theData appendData:[self serializeString:theKey]];
|
|
[theData appendBytes:":" length:1];
|
|
[theData appendData:[self serializeObject:theValue]];
|
|
|
|
if (theKey != [theKeys lastObject])
|
|
[theData appendData:[@"," dataUsingEncoding:NSASCIIStringEncoding]];
|
|
}
|
|
|
|
[theData appendBytes:"}" length:1];
|
|
|
|
return(theData);
|
|
}
|
|
|
|
@end
|