mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 11:33:49 +02:00
287 lines
6.1 KiB
Objective-C
287 lines
6.1 KiB
Objective-C
/*
|
|
* CSJSONPrinter.m
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#import "CSJSONPrinter.h"
|
|
#import "NSStringPrinting.h"
|
|
|
|
@implementation CSJSONPrinter
|
|
|
|
-(id)init
|
|
{
|
|
if((self=[super init]))
|
|
{
|
|
indentlevel=0;
|
|
indentstring=[@"\n" retain];
|
|
needseparator=NO;
|
|
excludedKeys=nil;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)dealloc
|
|
{
|
|
[indentstring release];
|
|
[excludedKeys release];
|
|
[super dealloc];
|
|
}
|
|
|
|
|
|
|
|
|
|
-(void)setIndentString:(NSString *)string
|
|
{
|
|
[indentstring autorelease];
|
|
indentstring=[string retain];
|
|
}
|
|
|
|
-(void)setASCIIMode:(BOOL)ascii
|
|
{
|
|
asciimode=ascii;
|
|
}
|
|
|
|
-(void)setExcludedKeys:(NSArray*)keysToExclude
|
|
{
|
|
[excludedKeys autorelease];
|
|
excludedKeys=[keysToExclude retain];
|
|
}
|
|
|
|
|
|
|
|
|
|
-(void)printObject:(id)object
|
|
{
|
|
if(object==[NSNull null]) [self printNull];
|
|
else if([object isKindOfClass:[NSNumber class]]) [self printNumber:object];
|
|
else if([object isKindOfClass:[NSString class]]) [self printString:object];
|
|
else if([object isKindOfClass:[NSData class]]) [self printData:object];
|
|
else if([object isKindOfClass:[NSValue class]]) [self printValue:object];
|
|
else if([object isKindOfClass:[NSArray class]]) [self printArray:object];
|
|
else if([object isKindOfClass:[NSDictionary class]]) [self printDictionary:object];
|
|
else [self printString:[object description]];
|
|
}
|
|
|
|
-(void)printNull
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[@"null" print];
|
|
needseparator=YES;
|
|
}
|
|
|
|
-(void)printNumber:(NSNumber *)number
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
if(strcmp([number objCType],"c")==0)
|
|
{
|
|
if([number boolValue]) [@"true" print];
|
|
else [@"false" print];
|
|
}
|
|
else
|
|
{
|
|
[[number description] print];
|
|
}
|
|
needseparator=YES;
|
|
}
|
|
|
|
-(void)printString:(NSString *)string
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[@"\"" print];
|
|
[[self stringByEscapingString:string] print];
|
|
[@"\"" print];
|
|
needseparator=YES;
|
|
}
|
|
|
|
-(void)printData:(NSData *)data
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[@"\"" print];
|
|
[[self stringByEncodingBytes:[data bytes] length:[data length]] print];
|
|
[@"\"" print];
|
|
needseparator=YES;
|
|
}
|
|
|
|
-(void)printValue:(NSValue *)value
|
|
{
|
|
NSUInteger length;
|
|
NSGetSizeAndAlignment([value objCType],&length,NULL);
|
|
uint8_t bytes[length];
|
|
[value getValue:bytes];
|
|
|
|
[self printSeparatorIfNeeded];
|
|
[@"\"" print];
|
|
[[self stringByEncodingBytes:bytes length:length] print];
|
|
[@"\"" print];
|
|
needseparator=YES;
|
|
}
|
|
|
|
-(void)printArray:(NSArray *)array
|
|
{
|
|
[self startPrintingArray];
|
|
[self printArrayObjects:array];
|
|
[self endPrintingArray];
|
|
}
|
|
|
|
-(void)printDictionary:(NSDictionary *)dictionary
|
|
{
|
|
[self startPrintingDictionary];
|
|
[self printDictionaryKeysAndObjects:dictionary];
|
|
[self endPrintingDictionary];
|
|
}
|
|
|
|
|
|
|
|
-(void)startPrintingArray
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[@"[" print];
|
|
indentlevel++;
|
|
}
|
|
|
|
-(void)startPrintingArrayObject
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[self startNewLine];
|
|
}
|
|
|
|
-(void)printArrayObject:(id)object
|
|
{
|
|
[self startPrintingArrayObject];
|
|
[self printObject:object];
|
|
}
|
|
|
|
-(void)endPrintingArray
|
|
{
|
|
needseparator=YES;
|
|
|
|
indentlevel--;
|
|
[self startNewLine];
|
|
[@"]" print];
|
|
}
|
|
|
|
-(void)printArrayObjects:(NSArray *)array
|
|
{
|
|
NSEnumerator *enumerator=[array objectEnumerator];
|
|
id object;
|
|
while((object=[enumerator nextObject])) [self printArrayObject:object];
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)startPrintingDictionary
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[@"{" print];
|
|
indentlevel++;
|
|
}
|
|
|
|
-(void)startPrintingDictionaryObjectForKey:(id)key
|
|
{
|
|
[self printSeparatorIfNeeded];
|
|
[self startNewLine];
|
|
[@"\"" print];
|
|
[[self stringByEscapingString:[key description]] print];
|
|
[@"\": " print];
|
|
}
|
|
|
|
-(void)printDictionaryObject:(id)object forKey:(id)key
|
|
{
|
|
[self startPrintingDictionaryObjectForKey:key];
|
|
[self printObject:object];
|
|
}
|
|
|
|
-(void)endPrintingDictionary
|
|
{
|
|
needseparator=YES;
|
|
|
|
indentlevel--;
|
|
[self startNewLine];
|
|
[@"}" print];
|
|
}
|
|
|
|
-(void)printDictionaryKeysAndObjects:(NSDictionary *)dictionary
|
|
{
|
|
NSEnumerator *enumerator=[dictionary keyEnumerator];
|
|
id key;
|
|
while((key=[enumerator nextObject])) {
|
|
if (excludedKeys && [excludedKeys containsObject:key]) continue;
|
|
[self printDictionaryObject:[dictionary objectForKey:key] forKey:key];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-(void)startNewLine
|
|
{
|
|
[@"\n" print];
|
|
for(int i=0;i<indentlevel;i++) [indentstring print];
|
|
}
|
|
|
|
-(void)printSeparatorIfNeeded
|
|
{
|
|
// Generally we should call this method from other methods of
|
|
// this class which have direct print calls, before those print
|
|
// calls. This ensures all needed comma separators are printed.
|
|
// The exceptions are (a) before printing only whitespace; and
|
|
// (b) when printing the end of a JSON Array or Object. This is
|
|
// to ensure we print no trailing commas.
|
|
if(needseparator)
|
|
{
|
|
[@"," print];
|
|
needseparator=NO;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-(NSString *)stringByEscapingString:(NSString *)string
|
|
{
|
|
int length=[string length];
|
|
NSMutableString *res=[NSMutableString stringWithCapacity:length];
|
|
|
|
for(int i=0;i<length;i++)
|
|
{
|
|
unichar c=[string characterAtIndex:i];
|
|
if(c=='"'||c=='\\') [res appendFormat:@"\\%C",c];
|
|
else if(c=='\b') [res appendString:@"\\b"];
|
|
else if(c=='\f') [res appendString:@"\\f"];
|
|
else if(c=='\n') [res appendString:@"\\n"];
|
|
else if(c=='\r') [res appendString:@"\\r"];
|
|
else if(c=='\t') [res appendString:@"\\t"];
|
|
else if(c<32) [res appendFormat:@"\\u%04x",c];
|
|
else if(asciimode&&c>=128) [res appendFormat:@"\\u%04x",c];
|
|
else [res appendFormat:@"%C",c];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
-(NSString *)stringByEncodingBytes:(const uint8_t *)bytes length:(int)length
|
|
{
|
|
NSMutableString *res=[NSMutableString stringWithCapacity:length*6];
|
|
|
|
for(int i=0;i<length;i++) [res appendFormat:@"\\u%04x",bytes[i]];
|
|
|
|
return res;
|
|
}
|
|
|
|
@end
|