首页 > 代码库 > 使用FastCoder写缓存单例
使用FastCoder写缓存单例
使用FastCoder写缓存单例
FastCoder可以存储字典,数组,鄙人将FastCoder封装,CoreData可以缓存的东西,用这个都可以缓存,但是只适合缓存少量的数据(不适合存储几万条数据)。
基于文件的类请参考上一章节内容
使用详情:
源码:
使用的缓存文件
SharedFile.h 与 SharedFile.m
//// SharedFile.h// Array//// Created by YouXianMing on 14/12/1.// Copyright (c) 2014年 YouXianMing. All rights reserved.//#import <Foundation/Foundation.h>@interface SharedFile : NSObject/** * 存储数组 * * @return YES,成功,NO,失败 */+ (BOOL)storeArray;/** * 返回原始的可以修改的数组 * * @return 原始可以修改的数组 */+ (NSMutableArray *)sharedOriginalArray;/** * 返回原始数组的拷贝 * * @return 原始数组的拷贝 */+ (NSMutableArray *)sharedCopiedArray;@end
//// SharedFile.m// Array//// Created by YouXianMing on 14/12/1.// Copyright (c) 2014年 YouXianMing. All rights reserved.//#import "SharedFile.h"#import "NSString+File.h"#import "NSObject+FastCoder.h"static NSString *filePath = @"/Library/Caches/YouXianMing";NSMutableArray *storedArray = nil;@implementation SharedFile+ (void)initialize { if (self == [SharedFile class]) { if ([filePath exist] == NO) { storedArray = [NSMutableArray array]; } else { storedArray = [@"SharedFile" useFastCoderToRecoverFromFilePath:[filePath path]]; } }}+ (BOOL)storeArray { return [storedArray useFastCoderToWriteToFilePath:[filePath path]];}+ (NSMutableArray *)sharedOriginalArray { return storedArray;}+ (NSMutableArray *)sharedCopiedArray { return [NSMutableArray arrayWithArray:storedArray];}@end
FastCoder.h 与 FastCoder.m
//// FastCoding.h//// Version 3.0.2//// Created by Nick Lockwood on 09/12/2013.// Copyright (c) 2013 Charcoal Design//// Distributed under the permissive zlib License// Get the latest version from here://// https://github.com/nicklockwood/FastCoding//// This software is provided ‘as-is‘, without any express or implied// warranty. In no event will the authors be held liable for any damages// arising from the use of this software.//// Permission is granted to anyone to use this software for any purpose,// including commercial applications, and to alter it and redistribute it// freely, subject to the following restrictions://// 1. The origin of this software must not be misrepresented; you must not// claim that you wrote the original software. If you use this software// in a product, an acknowledgment in the product documentation would be// appreciated but is not required.//// 2. Altered source versions must be plainly marked as such, and must not be// misrepresented as being the original software.//// 3. This notice may not be removed or altered from any source distribution.//#import <Foundation/Foundation.h>extern NSString *const FastCodingException;@interface NSObject (FastCoding)+ (NSArray *)fastCodingKeys;- (id)awakeAfterFastCoding;- (Class)classForFastCoding;- (BOOL)preferFastCoding;@end@interface FastCoder : NSObject+ (id)objectWithData:(NSData *)data;+ (id)propertyListWithData:(NSData *)data;+ (NSData *)dataWithRootObject:(id)object;@end
//// FastCoding.m//// Version 3.0.2//// Created by Nick Lockwood on 09/12/2013.// Copyright (c) 2013 Charcoal Design//// Distributed under the permissive zlib License// Get the latest version from here://// https://github.com/nicklockwood/FastCoding//// This software is provided ‘as-is‘, without any express or implied// warranty. In no event will the authors be held liable for any damages// arising from the use of this software.//// Permission is granted to anyone to use this software for any purpose,// including commercial applications, and to alter it and redistribute it// freely, subject to the following restrictions://// 1. The origin of this software must not be misrepresented; you must not// claim that you wrote the original software. If you use this software// in a product, an acknowledgment in the product documentation would be// appreciated but is not required.//// 2. Altered source versions must be plainly marked as such, and must not be// misrepresented as being the original software.//// 3. This notice may not be removed or altered from any source distribution.//#import "FastCoder.h"#import <objc/runtime.h>#import <CoreGraphics/CoreGraphics.h>#import <Availability.h>#if __has_feature(objc_arc)#pragma clang diagnostic ignored "-Wpedantic"#warning FastCoding runs slower under ARC. It is recommended that you disable it for this file#endif#pragma clang diagnostic ignored "-Wgnu"#pragma clang diagnostic ignored "-Wpointer-arith"#pragma clang diagnostic ignored "-Wmissing-prototypes"#pragma clang diagnostic ignored "-Wfour-char-constants"#pragma clang diagnostic ignored "-Wobjc-missing-property-synthesis"#pragma clang diagnostic ignored "-Wdirect-ivar-access"NSString *const FastCodingException = @"FastCodingException";static const uint32_t FCIdentifier = ‘FAST‘;static const uint16_t FCMajorVersion = 3;static const uint16_t FCMinorVersion = 0;typedef struct{ uint32_t identifier; uint16_t majorVersion; uint16_t minorVersion;}FCHeader;typedef NS_ENUM(uint8_t, FCType){ FCTypeNil = 0, FCTypeNull, FCTypeObjectAlias8, FCTypeObjectAlias16, FCTypeObjectAlias32, FCTypeStringAlias8, FCTypeStringAlias16, FCTypeStringAlias32, FCTypeString, FCTypeDictionary, FCTypeArray, FCTypeSet, FCTypeOrderedSet, FCTypeTrue, FCTypeFalse, FCTypeInt8, FCTypeInt16, FCTypeInt32, FCTypeInt64, FCTypeFloat32, FCTypeFloat64, FCTypeData, FCTypeDate, FCTypeMutableString, FCTypeMutableDictionary, FCTypeMutableArray, FCTypeMutableSet, FCTypeMutableOrderedSet, FCTypeMutableData, FCTypeClassDefinition, FCTypeObject8, FCTypeObject16, FCTypeObject32, FCTypeURL, FCTypePoint, FCTypeSize, FCTypeRect, FCTypeRange, FCTypeVector, FCTypeAffineTransform, FCType3DTransform, FCTypeMutableIndexSet, FCTypeIndexSet, FCTypeNSCodedObject, FCTypeCount // sentinel value};#if !__has_feature(objc_arc)#define FC_AUTORELEASE(x) [(x) autorelease]#else#define FC_AUTORELEASE(x) (x)#endif#import <TargetConditionals.h>#if TARGET_OS_IPHONE#define OR_IF_MAC(x)#else#define OR_IF_MAC(x) || (x)#endif#define FC_ASSERT_FITS(length, offset, total) { if ((NSUInteger)((offset) + (length)) > (total)) \[NSException raise:FastCodingException format:@"Unexpected EOF when parsing object starting at %i", (int32_t)(offset)]; }#define FC_READ_VALUE(type, offset, input, total) type value; { \FC_ASSERT_FITS (sizeof(type), offset, total); value = *(type *)(input + offset); offset += sizeof(value); }#define FC_ALIGN_INPUT(type, offset) { \unsigned long align = offset % sizeof(type); if (align) offset += sizeof(type) - align; }#define FC_ALIGN_OUTPUT(type, output) { \unsigned long align = [output length] % sizeof(type); if (align) [output increaseLengthBy:sizeof(type) - align]; }@interface FCNSCoder : NSCoder@end@interface FCNSCoder (){ @public __unsafe_unretained id _rootObject; __unsafe_unretained NSMutableData *_output; __unsafe_unretained NSMutableDictionary *_objectCache; __unsafe_unretained NSMutableDictionary *_classCache; __unsafe_unretained NSMutableDictionary *_stringCache; __unsafe_unretained NSMutableDictionary *_classesByName;}@end@interface FCNSDecoder : NSCoder@endtypedef id FCTypeConstructor(FCNSDecoder *);@interface FCNSDecoder (){ @public NSUInteger *_offset; const void *_input; NSUInteger _total; FCTypeConstructor **_constructors; __unsafe_unretained NSData *_objectCache; __unsafe_unretained NSData *_classCache; __unsafe_unretained NSData *_stringCache; __unsafe_unretained NSMutableArray *_propertyDictionaryPool; __unsafe_unretained NSMutableDictionary *_properties;}@end@interface FCClassDefinition : NSObject@end@interface FCClassDefinition (){@public __unsafe_unretained NSString *_className; __unsafe_unretained NSArray *_propertyKeys;}@end@interface NSObject (FastCoding_Private)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder;@endstatic inline NSUInteger FCCacheReadObject(__unsafe_unretained id object, __unsafe_unretained NSData *cache){ NSUInteger offset = (NSUInteger)CFDataGetLength((__bridge CFMutableDataRef)cache); CFDataAppendBytes((__bridge CFMutableDataRef)cache, (void *)&object, sizeof(id)); return offset;}static inline void FCReplaceCachedObject(NSUInteger index, __unsafe_unretained id object, __unsafe_unretained NSData *cache){ CFDataReplaceBytes((__bridge CFMutableDataRef)cache, CFRangeMake((CFIndex)index, sizeof(id)), (void *)&object, sizeof(id));}static inline id FCCachedObjectAtIndex(NSUInteger index, __unsafe_unretained NSData *cache){ return ((__unsafe_unretained id *)(void *)CFDataGetBytePtr((__bridge CFMutableDataRef)cache))[index];}static id FCReadObject(__unsafe_unretained FCNSDecoder *decoder);static id FCReadObject_2_3(__unsafe_unretained FCNSDecoder *decoder);static inline uint8_t FCReadType(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(uint8_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static inline uint8_t FCReadRawUInt8(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(uint8_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static inline uint16_t FCReadRawUInt16(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(uint16_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static inline uint32_t FCReadRawUInt32(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(uint32_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static inline double FCReadRawDouble(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(double_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static id FCReadRawString(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSString *string = nil; NSUInteger length = strlen(decoder->_input + *decoder->_offset) + 1; FC_ASSERT_FITS(length, *decoder->_offset, decoder->_total); if (length > 1) { string = CFBridgingRelease(CFStringCreateWithBytes(NULL, decoder->_input + *decoder->_offset, (CFIndex)length - 1, kCFStringEncodingUTF8, false)); } else { string = @""; } *decoder->_offset += length; return string;}static id FCReadNil(__unused __unsafe_unretained FCNSDecoder *decoder){ return nil;}static id FCReadNull(__unused __unsafe_unretained FCNSDecoder *decoder){ return [NSNull null];}static id FCReadAlias8(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint8_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt8(decoder), decoder->_objectCache);}static id FCReadAlias16(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint16_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt16(decoder), decoder->_objectCache);}static id FCReadAlias32(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt32(decoder), decoder->_objectCache);}static id FCReadStringAlias8(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint8_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt8(decoder), decoder->_stringCache);}static id FCReadStringAlias16(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint16_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt16(decoder), decoder->_stringCache);}static id FCReadStringAlias32(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); return FCCachedObjectAtIndex(FCReadRawUInt32(decoder), decoder->_stringCache);}static id FCReadString(__unsafe_unretained FCNSDecoder *decoder){ NSString *string = FCReadRawString(decoder); FCCacheReadObject(string, decoder->_stringCache); return string;}static id FCReadMutableString(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSMutableString *string = nil; NSUInteger length = strlen(decoder->_input + *decoder->_offset) + 1; FC_ASSERT_FITS(length, *decoder->_offset, decoder->_total); if (length > 1) { string = FC_AUTORELEASE([[NSMutableString alloc] initWithBytes:decoder->_input + *decoder->_offset length:length - 1 encoding:NSUTF8StringEncoding]); } else { string = [NSMutableString string]; } *decoder->_offset += length; FCCacheReadObject(string, decoder->_objectCache); return string;}static id FCReadDictionary(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSDictionary *dict = nil; if (count) { __autoreleasing id *keys = (__autoreleasing id *)malloc(count * sizeof(id)); __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject(decoder); keys[i] = FCReadObject(decoder); } dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:count]; free(objects); free(keys); } else { dict = @{}; } FCCacheReadObject(dict, decoder->_objectCache); return dict;}static id FCReadMutableDictionary(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSMutableDictionary *dict = CFBridgingRelease(CFDictionaryCreateMutable(NULL, (CFIndex)count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); FCCacheReadObject(dict, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { __autoreleasing id object = FCReadObject(decoder); __autoreleasing id key = FCReadObject(decoder); CFDictionarySetValue((__bridge CFMutableDictionaryRef)dict, (__bridge const void *)key, (__bridge const void *)object); } return dict;}static id FCReadArray(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSArray *array = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject(decoder); } array = [NSArray arrayWithObjects:objects count:count]; free(objects); } else { array = @[]; } FCCacheReadObject(array, decoder->_objectCache); return array;}static id FCReadMutableArray(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; FCCacheReadObject(array, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { CFArrayAppendValue((__bridge CFMutableArrayRef)array, (__bridge void *)FCReadObject(decoder)); } return array;}static id FCReadSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSSet *set = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject(decoder); } set = [NSSet setWithObjects:objects count:count]; free(objects); } else { set = [NSSet set]; } FCCacheReadObject(set, decoder->_objectCache); return set;}static id FCReadMutableSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSMutableSet *set = [NSMutableSet setWithCapacity:count]; FCCacheReadObject(set, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { [set addObject:FCReadObject(decoder)]; } return set;}static id FCReadOrderedSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSOrderedSet *set = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject(decoder); } set = [NSOrderedSet orderedSetWithObjects:objects count:count]; free(objects); } else { set = [NSOrderedSet orderedSet]; } FCCacheReadObject(set, decoder->_objectCache); return set;}static id FCReadMutableOrderedSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); __autoreleasing NSMutableOrderedSet *set = [NSMutableOrderedSet orderedSetWithCapacity:count]; FCCacheReadObject(set, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { [set addObject:FCReadObject(decoder)]; } return set;}static id FCReadTrue(__unused __unsafe_unretained FCNSDecoder *decoder){ return @YES;}static id FCReadFalse(__unused __unsafe_unretained FCNSDecoder *decoder){ return @NO;}static id FCReadInt8(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(int8_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadInt16(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(int16_t, *decoder->_offset); FC_READ_VALUE(int16_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadInt32(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(int32_t, *decoder->_offset); FC_READ_VALUE(int32_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadInt64(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(int64_t, *decoder->_offset); FC_READ_VALUE(int64_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadFloat32(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(float_t, *decoder->_offset); FC_READ_VALUE(float_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadFloat64(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); FC_READ_VALUE(double_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); return number;}static id FCReadData(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t length = FCReadRawUInt32(decoder); NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); __autoreleasing NSData *data = http://www.mamicode.com/[NSData dataWithBytes:(decoder->_input + *decoder->_offset) length:length]; *decoder->_offset += paddedLength; FCCacheReadObject(data, decoder->_objectCache); return data;}static id FCReadMutableData(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t length = FCReadRawUInt32(decoder); NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); __autoreleasing NSMutableData *data = http://www.mamicode.com/[NSMutableData dataWithBytes:(decoder->_input + *decoder->_offset) length:length]; *decoder->_offset += paddedLength; FCCacheReadObject(data, decoder->_objectCache); return data;}static id FCReadDate(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(NSTimeInterval, *decoder->_offset); FC_READ_VALUE(NSTimeInterval, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSDate *date = [NSDate dateWithTimeIntervalSince1970:value]; return date;}static id FCReadClassDefinition(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing FCClassDefinition *definition = FC_AUTORELEASE([[FCClassDefinition alloc] init]); FCCacheReadObject(definition, decoder->_classCache); definition->_className = FCReadRawString(decoder); FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t count = FCReadRawUInt32(decoder); if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadRawString(decoder); } __autoreleasing NSArray *propertyKeys = [NSArray arrayWithObjects:objects count:count]; definition->_propertyKeys = propertyKeys; free(objects); } //now return the actual object instance return FCReadObject(decoder);}static id FCReadObjectInstance(__unsafe_unretained FCNSDecoder *decoder, NSUInteger classIndex){ __autoreleasing FCClassDefinition *definition = FCCachedObjectAtIndex(classIndex, decoder->_classCache); __autoreleasing Class objectClass = NSClassFromString(definition->_className); __autoreleasing id object = nil; if (objectClass) { object = FC_AUTORELEASE([[objectClass alloc] init]); } else if (definition->_className) { object = [NSMutableDictionary dictionaryWithObject:definition->_className forKey:@"$class"]; } else if (object) { object = [NSMutableDictionary dictionary]; } NSUInteger cacheIndex = FCCacheReadObject(object, decoder->_objectCache); for (__unsafe_unretained NSString *key in definition->_propertyKeys) { [object setValue:FCReadObject(decoder) forKey:key]; } id newObject = [object awakeAfterFastCoding]; if (newObject != object) { //TODO: this is only a partial solution, as any objects that referenced //this object between when it was created and now will have received incorrect instance FCReplaceCachedObject(cacheIndex, newObject, decoder->_objectCache); } return newObject;}static id FCReadObject8(__unsafe_unretained FCNSDecoder *decoder){ return FCReadObjectInstance(decoder, FCReadRawUInt8(decoder));}static id FCReadObject16(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint16_t, *decoder->_offset); return FCReadObjectInstance(decoder, FCReadRawUInt16(decoder));}static id FCReadObject32(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); return FCReadObjectInstance(decoder, FCReadRawUInt32(decoder));}static id FCReadURL(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSURL *URL = [NSURL URLWithString:FCReadObject(decoder) relativeToURL:FCReadObject(decoder)]; FCCacheReadObject(URL, decoder->_stringCache); return URL;}static id FCReadPoint(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGPoint point = {(CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&point objCType:@encode(CGPoint)]; return value;}static id FCReadSize(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGSize size = {(CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&size objCType:@encode(CGSize)]; return value;}static id FCReadRect(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGRect rect = { {(CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder)}, {(CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder)} }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&rect objCType:@encode(CGRect)]; return value;}static id FCReadRange(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); NSRange range = {FCReadRawUInt32(decoder), FCReadRawUInt32(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&range objCType:@encode(NSRange)]; return value;}static id FCReadVector(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGVector point = {(CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&point objCType:@encode(CGVector)]; return value;}static id FCReadAffineTransform(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGAffineTransform transform = { (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder) }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)]; return value;}static id FCRead3DTransform(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(double_t, *decoder->_offset); CGFloat transform[] = { (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder), (CGFloat)FCReadRawDouble(decoder) }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&transform objCType:@encode(CGFloat[16])]; return value;}static id FCReadMutableIndexSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t rangeCount = FCReadRawUInt32(decoder); __autoreleasing NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; FCCacheReadObject(indexSet, decoder->_objectCache); for (uint32_t i = 0; i < rangeCount; i++) { NSRange range = {FCReadRawUInt32(decoder), FCReadRawUInt32(decoder)}; [indexSet addIndexesInRange:range]; } return indexSet;}static id FCReadIndexSet(__unsafe_unretained FCNSDecoder *decoder){ FC_ALIGN_INPUT(uint32_t, *decoder->_offset); uint32_t rangeCount = FCReadRawUInt32(decoder); __autoreleasing NSIndexSet *indexSet; if (rangeCount == 1) { //common case optimisation NSRange range = {FCReadRawUInt32(decoder), FCReadRawUInt32(decoder)}; indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; } else { indexSet = [NSMutableIndexSet indexSet]; for (uint32_t i = 0; i < rangeCount; i++) { NSRange range = {FCReadRawUInt32(decoder), FCReadRawUInt32(decoder)}; [(NSMutableIndexSet *)indexSet addIndexesInRange:range]; } indexSet = [indexSet copy]; } FCCacheReadObject(indexSet, decoder->_objectCache); return indexSet;}static id FCReadNSCodedObject(__unsafe_unretained FCNSDecoder *decoder){ NSString *className = FCReadObject(decoder); NSMutableDictionary *oldProperties = decoder->_properties; if ([decoder->_propertyDictionaryPool count]) { decoder->_properties = [decoder->_propertyDictionaryPool lastObject]; [decoder->_propertyDictionaryPool removeLastObject]; [decoder->_properties removeAllObjects]; } else { const CFDictionaryKeyCallBacks stringKeyCallbacks = { 0, NULL, NULL, NULL, CFEqual, CFHash }; decoder->_properties = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, &stringKeyCallbacks, NULL)); } while (true) { id object = FCReadObject(decoder); if (!object) break; NSString *key = FCReadObject(decoder); decoder->_properties[key] = object; } id object = [[NSClassFromString(className) alloc] initWithCoder:decoder]; [decoder->_propertyDictionaryPool addObject:decoder->_properties]; decoder->_properties = oldProperties; FCCacheReadObject(object, decoder->_objectCache); return object;}static id FCReadObject(__unsafe_unretained FCNSDecoder *decoder){ FCType type = FCReadType(decoder); FCTypeConstructor *constructor = NULL; if (type < FCTypeCount) { constructor = decoder->_constructors[type]; } if (!constructor) { [NSException raise:FastCodingException format:@"FastCoding cannot decode object of type: %i", type]; return nil; } return constructor(decoder);}id FCParseData(NSData *data, FCTypeConstructor *constructors[]){ NSUInteger length = [data length]; if (length < sizeof(FCHeader)) { //not a valid FastArchive return nil; } //read header FCHeader header; const void *input = data.bytes; memcpy(&header, input, sizeof(header)); if (header.identifier != FCIdentifier) { //not a FastArchive return nil; } if (header.majorVersion < 2 || header.majorVersion > FCMajorVersion) { //not compatible NSLog(@"This version of the FastCoding library doesn‘t support FastCoding version %i.%i files", header.majorVersion, header.minorVersion); return nil; } //create decoder NSUInteger offset = sizeof(header); FCNSDecoder *decoder = FC_AUTORELEASE([[FCNSDecoder alloc] init]); decoder->_constructors = constructors; decoder->_input = input; decoder->_offset = &offset; decoder->_total = length; //read data __autoreleasing NSMutableData *objectCache = [NSMutableData dataWithCapacity:FCReadRawUInt32(decoder) * sizeof(id)]; decoder->_objectCache = objectCache; if (header.majorVersion < 3) { return FCReadObject_2_3(decoder); } else { __autoreleasing NSMutableData *classCache = [NSMutableData dataWithCapacity:FCReadRawUInt32(decoder) * sizeof(id)]; __autoreleasing NSMutableData *stringCache = [NSMutableData dataWithCapacity:FCReadRawUInt32(decoder) * sizeof(id)]; __autoreleasing NSMutableArray *propertyDictionaryPool = CFBridgingRelease(CFArrayCreateMutable(NULL, 0, NULL)); decoder->_classCache = classCache; decoder->_stringCache = stringCache; decoder->_propertyDictionaryPool = propertyDictionaryPool; @try { return FCReadObject(decoder); } @catch (NSException *exception) { NSLog(@"%@", [exception reason]); return nil; } }}static inline NSUInteger FCCacheWrittenObject(__unsafe_unretained id object, __unsafe_unretained NSMutableDictionary *cache){ NSUInteger count = (NSUInteger)CFDictionaryGetCount((CFMutableDictionaryRef)cache); CFDictionarySetValue((CFMutableDictionaryRef)cache, (__bridge const void *)(object), (const void *)(count + 1)); return count;}static inline NSUInteger FCIndexOfCachedObject(__unsafe_unretained id object, __unsafe_unretained NSMutableDictionary *cache){ const void *index = CFDictionaryGetValue((__bridge CFMutableDictionaryRef)cache, (__bridge const void *)object); if (index) { return ((NSUInteger)index) - 1; } return NSNotFound;}static inline void FCWriteType(FCType value, __unsafe_unretained NSMutableData *output){ [output appendBytes:&value length:sizeof(value)];}static inline void FCWriteUInt8(uint8_t value, __unsafe_unretained NSMutableData *output){ [output appendBytes:&value length:sizeof(value)];}static inline void FCWriteUInt16(uint16_t value, __unsafe_unretained NSMutableData *output){ [output appendBytes:&value length:sizeof(value)];}static inline void FCWriteUInt32(uint32_t value, __unsafe_unretained NSMutableData *output){ [output appendBytes:&value length:sizeof(value)];}static inline void FCWriteDouble(double_t value, __unsafe_unretained NSMutableData *output){ [output appendBytes:&value length:sizeof(value)];}static inline void FCWriteString(__unsafe_unretained NSString *string, __unsafe_unretained NSMutableData *output){ const char *utf8 = [string UTF8String]; NSUInteger length = strlen(utf8) + 1; [output appendBytes:utf8 length:length];}static inline BOOL FCWriteObjectAlias(__unsafe_unretained id object, __unsafe_unretained FCNSCoder *coder){ NSUInteger index = FCIndexOfCachedObject(object, coder->_objectCache); if (index <= UINT8_MAX) { FCWriteType(FCTypeObjectAlias8, coder->_output); FCWriteUInt8((uint8_t)index, coder->_output); return YES; } else if (index <= UINT16_MAX) { FCWriteType(FCTypeObjectAlias16, coder->_output); FC_ALIGN_OUTPUT(uint16_t, coder->_output); FCWriteUInt16((uint16_t)index, coder->_output); return YES; } else if (index != NSNotFound) { FCWriteType(FCTypeObjectAlias32, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)index, coder->_output); return YES; } else { return NO; }}static inline BOOL FCWriteStringAlias(__unsafe_unretained id object, __unsafe_unretained FCNSCoder *coder){ NSUInteger index = FCIndexOfCachedObject(object, coder->_stringCache); if (index <= UINT8_MAX) { FCWriteType(FCTypeStringAlias8, coder->_output); FCWriteUInt8((uint8_t)index, coder->_output); return YES; } else if (index <= UINT16_MAX) { FCWriteType(FCTypeStringAlias16, coder->_output); FC_ALIGN_OUTPUT(uint16_t, coder->_output); FCWriteUInt16((uint16_t)index, coder->_output); return YES; } else if (index != NSNotFound) { FCWriteType(FCTypeStringAlias32, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)index, coder->_output); return YES; } else { return NO; }}static void FCWriteObject(__unsafe_unretained id object, __unsafe_unretained FCNSCoder *coder){ if (object) { [object FC_encodeWithCoder:coder]; } else { FCWriteType(FCTypeNil, coder->_output); }}@implementation FastCoder+ (id)objectWithData:(NSData *)data{ static FCTypeConstructor *constructors[] = { FCReadNil, FCReadNull, FCReadAlias8, FCReadAlias16, FCReadAlias32, FCReadStringAlias8, FCReadStringAlias16, FCReadStringAlias32, FCReadString, FCReadDictionary, FCReadArray, FCReadSet, FCReadOrderedSet, FCReadTrue, FCReadFalse, FCReadInt8, FCReadInt16, FCReadInt32, FCReadInt64, FCReadFloat32, FCReadFloat64, FCReadData, FCReadDate, FCReadMutableString, FCReadMutableDictionary, FCReadMutableArray, FCReadMutableSet, FCReadMutableOrderedSet, FCReadMutableData, FCReadClassDefinition, FCReadObject8, FCReadObject16, FCReadObject32, FCReadURL, FCReadPoint, FCReadSize, FCReadRect, FCReadRange, FCReadVector, FCReadAffineTransform, FCRead3DTransform, FCReadMutableIndexSet, FCReadIndexSet, FCReadNSCodedObject }; return FCParseData(data, constructors);}+ (id)propertyListWithData:(NSData *)data{ static FCTypeConstructor *constructors[] = { NULL, FCReadNull, FCReadAlias8, FCReadAlias16, FCReadAlias32, FCReadStringAlias8, FCReadStringAlias16, FCReadStringAlias32, FCReadString, FCReadDictionary, FCReadArray, FCReadSet, FCReadOrderedSet, FCReadTrue, FCReadFalse, FCReadInt8, FCReadInt16, FCReadInt32, FCReadInt64, FCReadFloat32, FCReadFloat64, FCReadData, FCReadDate, FCReadMutableString, FCReadMutableDictionary, FCReadMutableArray, FCReadMutableSet, FCReadMutableOrderedSet, FCReadMutableData, NULL, NULL, NULL, NULL, FCReadURL, FCReadPoint, FCReadSize, FCReadRect, FCReadRange, FCReadVector, FCReadAffineTransform, FCRead3DTransform, FCReadIndexSet, FCReadIndexSet, NULL }; return FCParseData(data, constructors);}+ (NSData *)dataWithRootObject:(id)object{ if (object) { //write header FCHeader header = {FCIdentifier, FCMajorVersion, FCMinorVersion}; NSMutableData *output = [NSMutableData dataWithLength:sizeof(header)]; memcpy(output.mutableBytes, &header, sizeof(header)); //object count placeholders FCWriteUInt32(0, output); FCWriteUInt32(0, output); FCWriteUInt32(0, output); //set up cache const CFDictionaryKeyCallBacks stringKeyCallbacks = { 0, NULL, NULL, NULL, CFEqual, CFHash }; @autoreleasepool { __autoreleasing id objectCache = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, NULL, NULL)); __autoreleasing id classCache = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, NULL, NULL)); __autoreleasing id stringCache = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, &stringKeyCallbacks, NULL)); __autoreleasing id classesByName = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, &stringKeyCallbacks, NULL)); //create coder FCNSCoder *coder = FC_AUTORELEASE([[FCNSCoder alloc] init]); coder->_rootObject = object; coder->_output = output; coder->_objectCache = objectCache; coder->_classCache = classCache; coder->_stringCache = stringCache; coder->_classesByName = classesByName; //write object FCWriteObject(object, coder); //set object count uint32_t objectCount = (uint32_t)[objectCache count]; [output replaceBytesInRange:NSMakeRange(sizeof(header), sizeof(uint32_t)) withBytes:&objectCount]; //set class count uint32_t classCount = (uint32_t)[classCache count]; [output replaceBytesInRange:NSMakeRange(sizeof(header) + sizeof(uint32_t), sizeof(uint32_t)) withBytes:&classCount]; //set string count uint32_t stringCount = (uint32_t)[stringCache count]; [output replaceBytesInRange:NSMakeRange(sizeof(header) + sizeof(uint32_t) * 2, sizeof(uint32_t)) withBytes:&stringCount]; return output; } } return nil;}@end@implementation FCNSCoder- (BOOL)allowsKeyedCoding{ return YES;}- (void)encodeObject:(__unsafe_unretained id)objv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(objv, self); FCWriteObject(key, self);}- (void)encodeConditionalObject:(id)objv forKey:(__unsafe_unretained NSString *)key{ if (FCIndexOfCachedObject(objv, _objectCache) != NSNotFound) { FCWriteObject(objv, self); FCWriteObject(key, self); }}- (void)encodeBool:(BOOL)boolv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(boolv), self); FCWriteObject(key, self);}- (void)encodeInt:(int)intv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(intv), self); FCWriteObject(key, self);}- (void)encodeInteger:(NSInteger)intv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(intv), self); FCWriteObject(key, self);}- (void)encodeInt32:(int32_t)intv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(intv), self); FCWriteObject(key, self);}- (void)encodeInt64:(int64_t)intv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(intv), self); FCWriteObject(key, self);}- (void)encodeFloat:(float)realv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(realv), self); FCWriteObject(key, self);}- (void)encodeDouble:(double)realv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject(@(realv), self); FCWriteObject(key, self);}- (void)encodeBytes:(const uint8_t *)bytesp length:(NSUInteger)lenv forKey:(__unsafe_unretained NSString *)key{ FCWriteObject([NSData dataWithBytes:bytesp length:lenv], self); FCWriteObject(key, self);}@end@implementation FCNSDecoder- (BOOL)containsValueForKey:(NSString *)key{ return _properties[key] != nil;}- (id)decodeObjectForKey:(__unsafe_unretained NSString *)key{ return _properties[key];}- (BOOL)decodeBoolForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] boolValue];}- (int)decodeIntForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] intValue];}- (NSInteger)decodeIntegerForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] integerValue];}- (int32_t)decodeInt32ForKey:(__unsafe_unretained NSString *)key{ return (int32_t)[_properties[key] longValue];}- (int64_t)decodeInt64ForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] longLongValue];}- (float)decodeFloatForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] floatValue];}- (double)decodeDoubleForKey:(__unsafe_unretained NSString *)key{ return [_properties[key] doubleValue];}- (const uint8_t *)decodeBytesForKey:(__unsafe_unretained NSString *)key returnedLength:(NSUInteger *)lengthp{ __autoreleasing NSData *data =http://www.mamicode.com/ _properties[key]; *lengthp = [data length]; return data.bytes;}@end@implementation FCClassDefinition : NSObject//no encoding implementation needed@end@implementation NSObject (FastCoding)+ (NSArray *)fastCodingKeys{ __autoreleasing NSMutableArray *codableKeys = [NSMutableArray array]; unsigned int propertyCount; objc_property_t *properties = class_copyPropertyList(self, &propertyCount); for (unsigned int i = 0; i < propertyCount; i++) { //get property objc_property_t property = properties[i]; const char *propertyName = property_getName(property); NSString *key = @(propertyName); //see if there is a backing ivar char *ivar = property_copyAttributeValue(property, "V"); if (ivar) { //check if ivar has KVC-compliant name NSString *ivarName = @(ivar); if ([ivarName isEqualToString:key] || [ivarName isEqualToString:[@"_" stringByAppendingString:key]]) { //setValue:forKey: will work [codableKeys addObject:key]; } free(ivar); } } free(properties); return codableKeys;}+ (NSArray *)FC_aggregatePropertyKeys{ __autoreleasing NSArray *codableKeys = nil; codableKeys = objc_getAssociatedObject(self, _cmd); if (codableKeys == nil) { codableKeys = [NSMutableArray array]; Class subclass = [self class]; while (subclass != [NSObject class]) { [(NSMutableArray *)codableKeys addObjectsFromArray:[subclass fastCodingKeys]]; subclass = [subclass superclass]; } codableKeys = [NSArray arrayWithArray:codableKeys]; //make the association atomically so that we don‘t need to bother with an @synchronize objc_setAssociatedObject(self, _cmd, codableKeys, OBJC_ASSOCIATION_RETAIN); } return codableKeys;}- (id)awakeAfterFastCoding{ return self;}- (Class)classForFastCoding{ return [self classForCoder];}- (BOOL)preferFastCoding{ return NO;}- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; //handle NSCoding if (![self preferFastCoding] && [self conformsToProtocol:@protocol(NSCoding)]) { //write object FCWriteType(FCTypeNSCodedObject, coder->_output); FCWriteObject(NSStringFromClass([self classForCoder]), coder); [(id <NSCoding>)self encodeWithCoder:coder]; FCWriteType(FCTypeNil, coder->_output); FCCacheWrittenObject(self, coder->_objectCache); return; } //write class definition Class objectClass = [self classForFastCoding]; NSUInteger classIndex = FCIndexOfCachedObject(objectClass, coder->_classCache); __autoreleasing NSArray *propertyKeys = [objectClass FC_aggregatePropertyKeys]; if (classIndex == NSNotFound) { classIndex = FCCacheWrittenObject(objectClass, coder->_classCache); FCWriteType(FCTypeClassDefinition, coder->_output); FCWriteString(NSStringFromClass(objectClass), coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[propertyKeys count], coder->_output); for (__unsafe_unretained id value in propertyKeys) { FCWriteString(value, coder->_output); } } //write object FCCacheWrittenObject(self, coder->_objectCache); if (classIndex <= UINT8_MAX) { FCWriteType(FCTypeObject8, coder->_output); FCWriteUInt8((uint8_t)classIndex, coder->_output); } else if (classIndex <= UINT16_MAX) { FCWriteType(FCTypeObject16, coder->_output); FC_ALIGN_OUTPUT(uint16_t, coder->_output); FCWriteUInt16((uint16_t)classIndex, coder->_output); } else { FCWriteType(FCTypeObject32, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)classIndex, coder->_output); } for (__unsafe_unretained NSString *key in propertyKeys) { FCWriteObject([self valueForKey:key], coder); }}@end@implementation NSString (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if ([self classForCoder] == [NSMutableString class]) { if (FCWriteObjectAlias(self, coder)) return; FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(FCTypeMutableString, coder->_output); } else { if (FCWriteStringAlias(self, coder)) return; FCCacheWrittenObject(self, coder->_stringCache); FCWriteType(FCTypeString, coder->_output); } FCWriteString(self, coder->_output);}@end@implementation NSNumber (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ switch (CFNumberGetType((CFNumberRef)self)) { case kCFNumberFloat32Type: case kCFNumberFloatType: { FCWriteType(FCTypeFloat32, coder->_output); float_t value = [self floatValue]; FC_ALIGN_OUTPUT(float_t, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; break; } case kCFNumberFloat64Type: case kCFNumberDoubleType: case kCFNumberCGFloatType: { FCWriteType(FCTypeFloat64, coder->_output); double_t value = [self doubleValue]; FC_ALIGN_OUTPUT(double_t, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; break; } case kCFNumberSInt64Type: case kCFNumberLongLongType: case kCFNumberNSIntegerType: { int64_t value = [self longLongValue]; if (value > (int64_t)INT32_MAX || value < (int64_t)INT32_MIN) { FCWriteType(FCTypeInt64, coder->_output); FC_ALIGN_OUTPUT(int64_t, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; break; } //otherwise treat as 32-bit } case kCFNumberSInt32Type: case kCFNumberIntType: case kCFNumberLongType: case kCFNumberCFIndexType: { int32_t value = (int32_t)[self intValue]; if (value > (int32_t)INT16_MAX || value < (int32_t)INT16_MIN) { FCWriteType(FCTypeInt32, coder->_output); FC_ALIGN_OUTPUT(int32_t, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; break; } //otherwise treat as 16-bit } case kCFNumberSInt16Type: case kCFNumberShortType: { int16_t value = (int16_t)[self intValue]; if (value > (int16_t)INT8_MAX || value < (int16_t)INT8_MIN) { FCWriteType(FCTypeInt16, coder->_output); FC_ALIGN_OUTPUT(int16_t, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; break; } //otherwise treat as 8-bit } case kCFNumberSInt8Type: case kCFNumberCharType: { int8_t value = (int8_t)[self intValue]; if (value =http://www.mamicode.com/= 1) { FCWriteType(FCTypeTrue, coder->_output); } else if (value =http://www.mamicode.com/= 0) { FCWriteType(FCTypeFalse, coder->_output); } else { FCWriteType(FCTypeInt8, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)]; } } }}@end@implementation NSDate (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(FCTypeDate, coder->_output); NSTimeInterval value = [self timeIntervalSince1970]; FC_ALIGN_OUTPUT(NSTimeInterval, coder->_output); [coder->_output appendBytes:&value length:sizeof(value)];}@end@implementation NSData (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(([self classForCoder] == [NSMutableData class])? FCTypeMutableData: FCTypeData, coder->_output); uint32_t length = (uint32_t)[self length]; FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32(length, coder->_output); [coder->_output appendData:self]; coder->_output.length += (4 - ((length % 4) ?: 4));}@end@implementation NSNull (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ FCWriteType(FCTypeNull, coder->_output);}@end@implementation NSDictionary (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; //alias keypath __autoreleasing NSString *aliasKeypath = self[@"$alias"]; if ([self count] == 1 && aliasKeypath) { __autoreleasing id node = coder->_rootObject; NSArray *parts = [aliasKeypath componentsSeparatedByString:@"."]; for (__unsafe_unretained NSString *key in parts) { if ([node isKindOfClass:[NSArray class]]) { node = ((NSArray *)node)[(NSUInteger)[key integerValue]]; } else { node = [node valueForKey:key]; } } FCWriteObject(node, coder); return; } //object bootstrapping __autoreleasing NSString *className = self[@"$class"]; if (className) { //get class definition __autoreleasing NSArray *propertyKeys = [[self allKeys] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self != ‘$class‘"]]; __autoreleasing FCClassDefinition *objectClass = coder->_classesByName[className]; if (objectClass) { //check that existing class definition contains all keys __autoreleasing NSMutableArray *keys = nil; for (__unsafe_unretained id key in propertyKeys) { if (![objectClass->_propertyKeys containsObject:key]) { keys = keys ?: [NSMutableArray array]; [keys addObject:key]; } } propertyKeys = objectClass->_propertyKeys; if (keys) { //we need to create a new class definition that includes extra keys propertyKeys = [propertyKeys arrayByAddingObjectsFromArray:keys]; objectClass = nil; } } if (!objectClass) { //create class definition objectClass = FC_AUTORELEASE([[FCClassDefinition alloc] init]); objectClass->_className = className; objectClass->_propertyKeys = propertyKeys; coder->_classesByName[className] = objectClass; } //write class definition NSUInteger classIndex = FCIndexOfCachedObject(objectClass, coder->_classCache); if (classIndex == NSNotFound) { classIndex = FCCacheWrittenObject(objectClass, coder->_classCache); FCWriteType(FCTypeClassDefinition, coder->_output); FCWriteString(objectClass->_className, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[propertyKeys count], coder->_output); for (__unsafe_unretained id key in propertyKeys) { //convert each to a string using -description, just in case FCWriteString([key description], coder->_output); } } //write object FCCacheWrittenObject(self, coder->_objectCache); if (classIndex <= UINT8_MAX) { FCWriteType(FCTypeObject8, coder->_output); FCWriteUInt8((uint8_t)classIndex, coder->_output); } else if (classIndex <= UINT16_MAX) { FCWriteType(FCTypeObject16, coder->_output); FC_ALIGN_OUTPUT(uint16_t, coder->_output); FCWriteUInt16((uint16_t)classIndex, coder->_output); } else { FCWriteType(FCTypeObject32, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)classIndex, coder->_output); } for (__unsafe_unretained NSString *key in propertyKeys) { FCWriteObject(self[key], coder); } return; } //ordinary dictionary BOOL mutable = ([self classForCoder] == [NSMutableDictionary class]); if (mutable) FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(mutable? FCTypeMutableDictionary: FCTypeDictionary, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[self count], coder->_output); [self enumerateKeysAndObjectsUsingBlock:^(__unsafe_unretained id key, __unsafe_unretained id obj, __unused BOOL *stop) { FCWriteObject(obj, coder); FCWriteObject(key, coder); }]; if (!mutable) FCCacheWrittenObject(self, coder->_objectCache);}@end@implementation NSArray (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; BOOL mutable = ([self classForCoder] == [NSMutableArray class]); if (mutable) FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(mutable? FCTypeMutableArray: FCTypeArray, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[self count], coder->_output); for (__unsafe_unretained id value in self) { FCWriteObject(value, coder); } if (!mutable) FCCacheWrittenObject(self, coder->_objectCache);}@end@implementation NSSet (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; BOOL mutable = ([self classForCoder] == [NSMutableSet class]); if (mutable) FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(mutable? FCTypeMutableSet: FCTypeSet, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[self count], coder->_output); for (__unsafe_unretained id value in self) { FCWriteObject(value, coder); } if (!mutable) FCCacheWrittenObject(self, coder->_objectCache);}@end@implementation NSOrderedSet (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; BOOL mutable = ([self classForCoder] == [NSMutableOrderedSet class]); if (mutable) FCCacheWrittenObject(self, coder->_objectCache); FCWriteType(mutable? FCTypeMutableOrderedSet: FCTypeOrderedSet, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)[self count], coder->_output); for (__unsafe_unretained id value in self) { FCWriteObject(value, coder); } if (!mutable) FCCacheWrittenObject(self, coder->_objectCache);}@end@implementation NSIndexSet (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteObjectAlias(self, coder)) return; BOOL mutable = ([self classForCoder] == [NSMutableIndexSet class]); if (mutable) FCCacheWrittenObject(self, coder->_objectCache); uint32_t __block rangeCount = 0; // wish we could get this directly from NSIndexSet... [self enumerateRangesUsingBlock:^(__unused NSRange range, __unused BOOL *stop) { rangeCount ++; }]; FCWriteType(mutable? FCTypeMutableIndexSet: FCTypeIndexSet, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32(rangeCount, coder->_output); [self enumerateRangesUsingBlock:^(NSRange range, __unused BOOL *stop) { FCWriteUInt32((uint32_t)range.location, coder->_output); FCWriteUInt32((uint32_t)range.length, coder->_output); }]; if (!mutable) FCCacheWrittenObject(self, coder->_objectCache);}@end@implementation NSURL (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ if (FCWriteStringAlias(self, coder)) return; FCWriteType(FCTypeURL, coder->_output); FCWriteObject(self.relativeString, coder); FCWriteObject(self.baseURL, coder); FCCacheWrittenObject(self, coder->_stringCache);}@end@implementation NSValue (FastCoding)- (void)FC_encodeWithCoder:(__unsafe_unretained FCNSCoder *)coder{ FCCacheWrittenObject(self, coder->_objectCache); const char *type = [self objCType]; if (strcmp(type, @encode(CGPoint)) == 0 OR_IF_MAC(strcmp(type, @encode(NSPoint)) == 0)) { CGFloat point[2]; [self getValue:&point]; FCWriteType(FCTypePoint, coder->_output); FC_ALIGN_OUTPUT(double_t, coder->_output); FCWriteDouble((double_t)point[0], coder->_output); FCWriteDouble((double_t)point[1], coder->_output); } else if (strcmp(type, @encode(CGSize)) == 0 OR_IF_MAC(strcmp(type, @encode(NSSize)) == 0)) { CGFloat size[2]; [self getValue:&size]; FCWriteType(FCTypeSize, coder->_output); FC_ALIGN_OUTPUT(double_t, coder->_output); FCWriteDouble((double_t)size[0], coder->_output); FCWriteDouble((double_t)size[1], coder->_output); } else if (strcmp(type, @encode(CGRect)) == 0 OR_IF_MAC(strcmp(type, @encode(NSRect)) == 0)) { CGFloat rect[4]; [self getValue:&rect]; FCWriteType(FCTypeRect, coder->_output); FC_ALIGN_OUTPUT(double_t, coder->_output); FCWriteDouble((double_t)rect[0], coder->_output); FCWriteDouble((double_t)rect[1], coder->_output); FCWriteDouble((double_t)rect[2], coder->_output); FCWriteDouble((double_t)rect[3], coder->_output); } else if (strcmp(type, @encode(NSRange)) == 0) { NSUInteger range[2]; [self getValue:&range]; FCWriteType(FCTypeRange, coder->_output); FC_ALIGN_OUTPUT(uint32_t, coder->_output); FCWriteUInt32((uint32_t)range[0], coder->_output); FCWriteUInt32((uint32_t)range[1], coder->_output); } else if (strcmp(type, @encode(CGVector)) == 0) { CGFloat vector[2]; [self getValue:&vector]; FCWriteType(FCTypeVector, coder->_output); FC_ALIGN_OUTPUT(double_t, coder->_output); FCWriteDouble((double_t)vector[0], coder->_output); FCWriteDouble((double_t)vector[1], coder->_output); } else if (strcmp(type, @encode(CGAffineTransform)) == 0) { CGFloat transform[6]; [self getValue:&transform]; FCWriteType(FCTypeAffineTransform, coder->_output); for (NSUInteger i = 0; i < 6; i++) { FCWriteDouble((double_t)transform[i], coder->_output); } } else if ([@(type) hasPrefix:@"{CATransform3D"]) { CGFloat transform[16]; [self getValue:&transform]; FCWriteType(FCType3DTransform, coder->_output); FC_ALIGN_OUTPUT(double_t, coder->_output); for (NSUInteger i = 0; i < 16; i++) { FCWriteDouble((double_t)transform[i], coder->_output); } } else { [NSException raise:FastCodingException format:@"Unable to encode NSValue data of type %@", @(type)]; }}@end#pragma mark -#pragma mark legacy decodingstatic inline uint32_t FCReadRawUInt32_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(uint32_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static inline double FCReadRawDouble_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(double_t, *decoder->_offset, decoder->_input, decoder->_total); return value;}static id FCReadRawString_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSString *string = nil; NSUInteger length = strlen(decoder->_input + *decoder->_offset) + 1; NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); if (length > 1) { string = CFBridgingRelease(CFStringCreateWithBytes(NULL, decoder->_input + *decoder->_offset, (CFIndex)length - 1, kCFStringEncodingUTF8, false)); } else { string = @""; } *decoder->_offset += paddedLength; return string;}static id FCReadNull_2_3(__unused __unsafe_unretained FCNSDecoder *decoder){ return [NSNull null];}static id FCReadAlias_2_3(__unsafe_unretained FCNSDecoder *decoder){ return FCCachedObjectAtIndex(FCReadRawUInt32_2_3(decoder), decoder->_objectCache);}static id FCReadString_2_3(__unsafe_unretained FCNSDecoder *decoder){ NSString *string = FCReadRawString_2_3(decoder); FCCacheReadObject(string, decoder->_objectCache); return string;}static id FCReadMutableString_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSMutableString *string = nil; NSUInteger length = strlen(decoder->_input + *decoder->_offset) + 1; NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); if (length > 1) { string = FC_AUTORELEASE([[NSMutableString alloc] initWithBytes:decoder->_input + *decoder->_offset length:length - 1 encoding:NSUTF8StringEncoding]); } else { string = [NSMutableString string]; } *decoder->_offset += paddedLength; FCCacheReadObject(string, decoder->_objectCache); return string;}static id FCReadDictionary_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSDictionary *dict = nil; if (count) { __autoreleasing id *keys = (__autoreleasing id *)malloc(count * sizeof(id)); __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject_2_3(decoder); keys[i] = FCReadObject_2_3(decoder); } dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:count]; free(objects); free(keys); } else { dict = @{}; } FCCacheReadObject(dict, decoder->_objectCache); return dict;}static id FCReadMutableDictionary_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSMutableDictionary *dict = CFBridgingRelease(CFDictionaryCreateMutable(NULL, (CFIndex)count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); FCCacheReadObject(dict, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { __autoreleasing id object = FCReadObject_2_3(decoder); __autoreleasing id key = FCReadObject_2_3(decoder); CFDictionarySetValue((__bridge CFMutableDictionaryRef)dict, (__bridge const void *)key, (__bridge const void *)object); } return dict;}static id FCReadArray_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSArray *array = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject_2_3(decoder); } array = [NSArray arrayWithObjects:objects count:count]; free(objects); } else { array = @[]; } FCCacheReadObject(array, decoder->_objectCache); return array;}static id FCReadMutableArray_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; FCCacheReadObject(array, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { CFArrayAppendValue((__bridge CFMutableArrayRef)array, (__bridge void *)FCReadObject_2_3(decoder)); } return array;}static id FCReadSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSSet *set = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject_2_3(decoder); } set = [NSSet setWithObjects:objects count:count]; free(objects); } else { set = [NSSet set]; } FCCacheReadObject(set, decoder->_objectCache); return set;}static id FCReadMutableSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSMutableSet *set = [NSMutableSet setWithCapacity:count]; FCCacheReadObject(set, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { [set addObject:FCReadObject_2_3(decoder)]; } return set;}static id FCReadOrderedSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSOrderedSet *set = nil; if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadObject_2_3(decoder); } set = [NSOrderedSet orderedSetWithObjects:objects count:count]; free(objects); } else { set = [NSOrderedSet orderedSet]; } FCCacheReadObject(set, decoder->_objectCache); return set;}static id FCReadMutableOrderedSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t count = FCReadRawUInt32_2_3(decoder); __autoreleasing NSMutableOrderedSet *set = [NSMutableOrderedSet orderedSetWithCapacity:count]; FCCacheReadObject(set, decoder->_objectCache); for (uint32_t i = 0; i < count; i++) { [set addObject:FCReadObject_2_3(decoder)]; } return set;}static id FCReadTrue_2_3(__unused __unsafe_unretained FCNSDecoder *decoder){ return @YES;}static id FCReadFalse_2_3(__unused __unsafe_unretained FCNSDecoder *decoder){ return @NO;}static id FCReadInt32_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(int32_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); FCCacheReadObject(number, decoder->_objectCache); return number;}static id FCReadInt64_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(int64_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); FCCacheReadObject(number, decoder->_objectCache); return number;}static id FCReadfloat_t_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(float_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); FCCacheReadObject(number, decoder->_objectCache); return number;}static id FCReaddouble_t_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(double_t, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSNumber *number = @(value); FCCacheReadObject(number, decoder->_objectCache); return number;}static id FCReadData_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t length = FCReadRawUInt32_2_3(decoder); NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); __autoreleasing NSData *data = http://www.mamicode.com/[NSData dataWithBytes:(decoder->_input + *decoder->_offset) length:length]; *decoder->_offset += paddedLength; FCCacheReadObject(data, decoder->_objectCache); return data;}static id FCReadMutableData_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t length = FCReadRawUInt32_2_3(decoder); NSUInteger paddedLength = length + (4 - ((length % 4) ?: 4)); FC_ASSERT_FITS(paddedLength, *decoder->_offset, decoder->_total); __autoreleasing NSMutableData *data = http://www.mamicode.com/[NSMutableData dataWithBytes:(decoder->_input + *decoder->_offset) length:length]; *decoder->_offset += paddedLength; FCCacheReadObject(data, decoder->_objectCache); return data;}static id FCReadDate_2_3(__unsafe_unretained FCNSDecoder *decoder){ FC_READ_VALUE(NSTimeInterval, *decoder->_offset, decoder->_input, decoder->_total); __autoreleasing NSDate *date = [NSDate dateWithTimeIntervalSince1970:value]; FCCacheReadObject(date, decoder->_objectCache); return date;}static id FCReadClassDefinition_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing FCClassDefinition *definition = FC_AUTORELEASE([[FCClassDefinition alloc] init]); FCCacheReadObject(definition, decoder->_objectCache); definition->_className = FCReadRawString_2_3(decoder); uint32_t count = FCReadRawUInt32_2_3(decoder); if (count) { __autoreleasing id *objects = (__autoreleasing id *)malloc(count * sizeof(id)); for (uint32_t i = 0; i < count; i++) { objects[i] = FCReadRawString_2_3(decoder); } __autoreleasing NSArray *propertyKeys = [NSArray arrayWithObjects:objects count:count]; definition->_propertyKeys = propertyKeys; free(objects); } //now return the actual object instance return FCReadObject_2_3(decoder);}static id FCReadObjectInstance_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing FCClassDefinition *definition = FCCachedObjectAtIndex(FCReadRawUInt32_2_3(decoder), decoder->_objectCache); __autoreleasing Class objectClass = NSClassFromString(definition->_className); __autoreleasing id object = nil; if (objectClass) { object = FC_AUTORELEASE([[objectClass alloc] init]); } else if (definition->_className) { object = [NSMutableDictionary dictionaryWithObject:definition->_className forKey:@"$class"]; } else if (object) { object = [NSMutableDictionary dictionary]; } NSUInteger cacheIndex = FCCacheReadObject(object, decoder->_objectCache); for (__unsafe_unretained NSString *key in definition->_propertyKeys) { [object setValue:FCReadObject_2_3(decoder) forKey:key]; } id newObject = [object awakeAfterFastCoding]; if (newObject != object) { //TODO: this is only a partial solution, as any objects that referenced //this object between when it was created and now will have received incorrect instance FCReplaceCachedObject(cacheIndex, newObject, decoder->_objectCache); } return newObject;}static id FCReadNil_2_3(__unused __unsafe_unretained FCNSDecoder *decoder){ return nil;}static id FCReadURL_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSURL *URL = [NSURL URLWithString:FCReadObject_2_3(decoder) relativeToURL:FCReadObject_2_3(decoder)]; FCCacheReadObject(URL, decoder->_objectCache); return URL;}static id FCReadPoint_2_3(__unsafe_unretained FCNSDecoder *decoder){ CGPoint point = {(CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&point objCType:@encode(CGPoint)]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCReadSize_2_3(__unsafe_unretained FCNSDecoder *decoder){ CGSize size = {(CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&size objCType:@encode(CGSize)]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCReadRect_2_3(__unsafe_unretained FCNSDecoder *decoder){ CGRect rect = { {(CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder)}, {(CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder)} }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&rect objCType:@encode(CGRect)]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCReadRange_2_3(__unsafe_unretained FCNSDecoder *decoder){ NSRange range = {FCReadRawUInt32_2_3(decoder), FCReadRawUInt32_2_3(decoder)}; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&range objCType:@encode(NSRange)]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCReadAffineTransform_2_3(__unsafe_unretained FCNSDecoder *decoder){ CGAffineTransform transform = { (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder) }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCRead3DTransform_2_3(__unsafe_unretained FCNSDecoder *decoder){ CGFloat transform[] = { (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder), (CGFloat)FCReadRawDouble_2_3(decoder) }; NSValue *value = http://www.mamicode.com/[NSValue valueWithBytes:&transform objCType:@encode(CGFloat[16])]; FCCacheReadObject(value, decoder->_objectCache); return value;}static id FCReadMutableIndexSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ uint32_t rangeCount = FCReadRawUInt32_2_3(decoder); __autoreleasing NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; FCCacheReadObject(indexSet, decoder->_objectCache); for (uint32_t i = 0; i < rangeCount; i++) { NSRange range = {FCReadRawUInt32_2_3(decoder), FCReadRawUInt32_2_3(decoder)}; [indexSet addIndexesInRange:range]; } return indexSet;}static id FCReadIndexSet_2_3(__unsafe_unretained FCNSDecoder *decoder){ __autoreleasing NSIndexSet *indexSet; uint32_t rangeCount = FCReadRawUInt32_2_3(decoder); if (rangeCount == 1) { //common case optimisation NSRange range = {FCReadRawUInt32_2_3(decoder), FCReadRawUInt32_2_3(decoder)}; indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; } else { indexSet = [NSMutableIndexSet indexSet]; for (uint32_t i = 0; i < rangeCount; i++) { NSRange range = {FCReadRawUInt32_2_3(decoder), FCReadRawUInt32_2_3(decoder)}; [(NSMutableIndexSet *)indexSet addIndexesInRange:range]; } indexSet = [indexSet copy]; } FCCacheReadObject(indexSet, decoder->_objectCache); return indexSet;}static id FCReadNSCodedObject_2_3(__unsafe_unretained FCNSDecoder *decoder){ NSString *className = FCReadObject_2_3(decoder); NSMutableDictionary *oldProperties = decoder->_properties; decoder->_properties = CFBridgingRelease(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); while (true) { id object = FCReadObject_2_3(decoder); if (!object) break; NSString *key = FCReadObject_2_3(decoder); decoder->_properties[key] = object; } id object = [[NSClassFromString(className) alloc] initWithCoder:decoder]; decoder->_properties = oldProperties; FCCacheReadObject(object, decoder->_objectCache); return object;}static id FCReadObject_2_3(__unsafe_unretained FCNSDecoder *decoder){ static FCTypeConstructor *constructors[] = { FCReadNull_2_3, FCReadAlias_2_3, FCReadString_2_3, FCReadDictionary_2_3, FCReadArray_2_3, FCReadSet_2_3, FCReadOrderedSet_2_3, FCReadTrue_2_3, FCReadFalse_2_3, FCReadInt32_2_3, FCReadInt64_2_3, FCReadfloat_t_2_3, FCReaddouble_t_2_3, FCReadData_2_3, FCReadDate_2_3, FCReadMutableString_2_3, FCReadMutableDictionary_2_3, FCReadMutableArray_2_3, FCReadMutableSet_2_3, FCReadMutableOrderedSet_2_3, FCReadMutableData_2_3, FCReadClassDefinition_2_3, FCReadObjectInstance_2_3, FCReadNil_2_3, FCReadURL_2_3, FCReadPoint_2_3, FCReadSize_2_3, FCReadRect_2_3, FCReadRange_2_3, FCReadAffineTransform_2_3, FCRead3DTransform_2_3, FCReadMutableIndexSet_2_3, FCReadIndexSet_2_3, FCReadNSCodedObject_2_3 }; uint32_t type = FCReadRawUInt32_2_3(decoder); if (type > sizeof(constructors)) { [NSException raise:FastCodingException format:@"FastCoding cannot decode object of type: %i", type]; return nil; } return constructors[type](decoder);}
NSObject+FastCoder.h 与 NSObject+FastCoder.m
//// NSObject+FastCoder.h// Array//// Created by YouXianMing on 14/12/1.// Copyright (c) 2014年 YouXianMing. All rights reserved.//#import <Foundation/Foundation.h>@interface NSObject (FastCoder)/** * 使用FastCoder将对象写文件 * * @param path 文件路径 * * @return YES,成功,NO,失败 */- (BOOL)useFastCoderToWriteToFilePath:(NSString *)filePath;/** * 使用FastCoder从文件路径中恢复对象 * * @param filePath 文件路径 * * @return 对象 */- (id)useFastCoderToRecoverFromFilePath:(NSString *)filePath;/** * 使用FastCoder将对象转换成NSData * * @return NSData */- (NSData *)useFastCoderToCreateData;@end
//// NSObject+FastCoder.m// Array//// Created by YouXianMing on 14/12/1.// Copyright (c) 2014年 YouXianMing. All rights reserved.//#import "NSObject+FastCoder.h"#import "FastCoder.h"@implementation NSObject (FastCoder)- (BOOL)useFastCoderToWriteToFilePath:(NSString *)filePath { BOOL sucess = NO; if (self) { NSData *data =http://www.mamicode.com/ [FastCoder dataWithRootObject:self]; sucess = [data writeToFile:filePath atomically:YES]; } return sucess;}- (id)useFastCoderToRecoverFromFilePath:(NSString *)filePath { NSData *data =http://www.mamicode.com/ [NSData dataWithContentsOfFile:filePath]; return [FastCoder objectWithData:data];}- (NSData *)useFastCoderToCreateData { return [FastCoder dataWithRootObject:self];}@end
使用FastCoder写缓存单例
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。