From 748097d4136e90182194e214c8009bde0a4236d5 Mon Sep 17 00:00:00 2001 From: clwi Date: Wed, 10 Mar 2021 21:49:32 +0100 Subject: [PATCH] 20210310 --- .gitignore | 1 - README.md | 12 + goodies/dump/README.md | 10 +- goodies/dump/cwpack_dump | Bin 102872 -> 0 bytes goodies/dump/cwpack_dump.c | 29 +- goodies/dump/testdump.msgpack | Bin 0 -> 73 bytes goodies/dump/testdump2.msgpack | 2 + goodies/objC/CWPackContext.h | 97 +++ goodies/objC/CWPackContext.m | 693 ++++++++++++++++++++++ goodies/objC/README.md | 106 +++- goodies/objC/Technique.md | 60 ++ goodies/objC/obsolete/README.md | 40 ++ goodies/objC/{ => obsolete}/cwpack_objc.h | 0 goodies/objC/{ => obsolete}/cwpack_objc.m | 0 14 files changed, 1009 insertions(+), 41 deletions(-) delete mode 100755 goodies/dump/cwpack_dump create mode 100644 goodies/dump/testdump.msgpack create mode 100644 goodies/dump/testdump2.msgpack create mode 100644 goodies/objC/CWPackContext.h create mode 100644 goodies/objC/CWPackContext.m create mode 100755 goodies/objC/Technique.md create mode 100755 goodies/objC/obsolete/README.md rename goodies/objC/{ => obsolete}/cwpack_objc.h (100%) rename goodies/objC/{ => obsolete}/cwpack_objc.m (100%) diff --git a/.gitignore b/.gitignore index def5edb..f350fff 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,4 @@ cwpackModuleTest json2cwpack2json # Data files -*.msgpack *.msgpack.json diff --git a/README.md b/README.md index 60e1693..b1faa02 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,15 @@ CWPack has no dependencies to other libraries. ## Test Included in the test folder are a module test and a performance test and shell scripts to run them. + +# Objective-C + +CWPack also contains an Objective-C interface. The MessagePack home page example would look as: + +```C +CWPackContext *pc = [CWPackContext newWithContext:my_cw_pack_context]; +[pc packObject:@{@"compact":@YES, @"schema":@0}]; + +CWUnpackContext *uc = [CWUnpackContext newWithContext:my_cw_unpack_context]; +NSDictionary *dict = [uc unpackNextObject]; +``` diff --git a/goodies/dump/README.md b/goodies/dump/README.md index 57ba2dc..69990f1 100755 --- a/goodies/dump/README.md +++ b/goodies/dump/README.md @@ -7,7 +7,7 @@ Syntax: cwpack_dump [-t 9] [-v][-r] [-h] < msgpackFile > humanReadableFile -t 9 Tab size -v Version --r Recognize records +-r Recognize records -h Help Each topmost msgpack item in the file starts on a new line. Each line starts with a file offset (hex) of the first item on the line. @@ -39,11 +39,15 @@ and `cwpack_dump -t 4 < testdump.msgpack` prints: The -r option makes dump recognize Objective-C objects. `cwpack_dump < testdump2.msgpack` prints: ``` - 0 [(127,<01>) "MyClass" [(127,<02>) "MyClass" [(127,<01>)]]] + 0 [(127,) [[(127,)]]] + 9 [(127,<01>) "MyClass" 10 [(127,<02>) "MyClass" 20 [(127,<01>)]]] + 27 ``` and `cwpack_dump -r < testdump2.msgpack` prints ``` - 0 1->MyClass(2->MyClass(->1)) + 0 -1->[->-1] + 9 1->MyClass(10 2->MyClass(20 ->1)) + 27 ``` diff --git a/goodies/dump/cwpack_dump b/goodies/dump/cwpack_dump deleted file mode 100755 index 6684217048ce8ddd87bf873caba0db018ea59dce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102872 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 QEYhIrF2=kLy@qA|KPWST1poj5 diff --git a/goodies/dump/cwpack_dump.c b/goodies/dump/cwpack_dump.c index e706a6f..d57ad8d 100755 --- a/goodies/dump/cwpack_dump.c +++ b/goodies/dump/cwpack_dump.c @@ -1,4 +1,6 @@ -/* CWPack/goodies - cwpack_dump.c */ + +/* CWPack/goodies/dump - cwpack_dump.c */ + /* The MIT License (MIT) @@ -30,8 +32,8 @@ char tabString[21] = " "; bool recognizeObjects = false; -#define NEW_LINE {printf ("\n%6x ",(unsigned)(context->current - context->start)); for (ti=0; ticurrent - context->start)); for (ti=0; ti"); } static void dump_item( cw_unpack_context* context, int tabLevel); @@ -62,8 +66,6 @@ static void dump_item( cw_unpack_context* context, int tabLevel) struct tm tm; char s[128]; - if (!tabLevel) NEW_LINE; - switch (context->item.type) { case CWP_ITEM_NIL: @@ -121,9 +123,7 @@ static void dump_item( cw_unpack_context* context, int tabLevel) break;} case CWP_ITEM_BIN: - printf("<"); dump_as_hex (context->item.as.bin.start, context->item.as.bin.length); - printf(">"); break; case CWP_ITEM_ARRAY: @@ -148,7 +148,7 @@ static void dump_item( cw_unpack_context* context, int tabLevel) break; } if (label) - printf("%ld->",labs(label)); + printf("%ld->",label); if (!userObject) { if (dim != 2) @@ -168,19 +168,20 @@ static void dump_item( cw_unpack_context* context, int tabLevel) } printf("%.*s(",context->item.as.str.length, context->item.as.str.start); tabLevel++; - for (i = 2; i < dim; i++) + for (i = 0; i < dim-2; i++) { CHECK_NEW_LINE; dump_next_item(context,tabLevel); } tabLevel--; - if(*tabString) NEW_LINE; + if(*tabString) NEW_LINE(tabLevel); printf(")"); } else { printf("["); tabLevel++; + i = 0; CHECK_NEW_LINE; dump_item(context,tabLevel); for (i = 1; i < dim; i++) @@ -189,7 +190,7 @@ static void dump_item( cw_unpack_context* context, int tabLevel) dump_next_item(context,tabLevel); } tabLevel--; - if(*tabString) NEW_LINE; + if(*tabString) NEW_LINE(tabLevel); printf("]"); } break; @@ -203,11 +204,11 @@ static void dump_item( cw_unpack_context* context, int tabLevel) { CHECK_NEW_LINE; dump_next_item(context,tabLevel); - printf(": "); + printf(":"); dump_next_item(context,tabLevel); } tabLevel--; - if(*tabString) NEW_LINE; + if(*tabString) NEW_LINE(tabLevel); printf("}"); break; @@ -288,6 +289,8 @@ int main(int argc, const char * argv[]) while (!context->return_code) { + int ti; + NEW_LINE(0); dump_next_item(context,0); } printf("\n"); diff --git a/goodies/dump/testdump.msgpack b/goodies/dump/testdump.msgpack new file mode 100644 index 0000000000000000000000000000000000000000..0ddfac0e41b5a867418276df3d8cbfb9dc9e0db1 GIT binary patch literal 73 zcmbPyj$y{MhSLt5aytTFx5}?My!7yr!`lwG9&R~2t$A5eW?o`Z+g)zoSgh6C7HRY*Z#*Ht!w}QZhIwI literal 0 HcmV?d00001 diff --git a/goodies/dump/testdump2.msgpack b/goodies/dump/testdump2.msgpack new file mode 100644 index 0000000..6e565bc --- /dev/null +++ b/goodies/dump/testdump2.msgpack @@ -0,0 +1,2 @@ +’Ôÿ‘‘Ôÿ”Ô§MyClass +”Ô§MyClass‘Ô \ No newline at end of file diff --git a/goodies/objC/CWPackContext.h b/goodies/objC/CWPackContext.h new file mode 100644 index 0000000..69513f1 --- /dev/null +++ b/goodies/objC/CWPackContext.h @@ -0,0 +1,97 @@ + +/* CWPack/goodies/ObjC - CWPackContext.h */ + +/* + The MIT License (MIT) + + Copyright (c) 2021 Claes Wihlborg + + 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 +#include "cwpack.h" + +NS_ASSUME_NONNULL_BEGIN + + + + + +@interface CWPackContext : NSObject + +@property (readonly) cw_pack_context *context; +@property (readwrite) BOOL useLabels; // default NO + ++ (instancetype) newWithContext:(cw_pack_context*)context; +- (void) packObject:(nullable NSObject*)object; + +@end + + + + + +@interface CWUnpackContext : NSObject + +@property (readonly) cw_unpack_context *context; + ++ (instancetype) newWithContext:(cw_unpack_context*)context; +- (id) unpackNextObject; + +@end + + + + +@protocol CWPackable + +@required +@property (readonly) int persistentAttributeCount; +- (void) cwPackSub:(CWPackContext*)ctx; +- (void) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes; + +@optional +- (instancetype) cwUnpackSubInit:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes; + +@end + + + + +@interface CWPackExternalItem : NSObject + +@property (readonly) int type; +@property (readwrite, strong) NSData* data; + ++ (instancetype) itemWithType:(int)type data:(NSData*)data; + +@end + + + + +@interface CWPackGenericClass : NSObject + +@property (readwrite,strong) NSString *packerClassName; +@property (readwrite,strong) NSMutableArray *attributes; + ++ (instancetype) newWithClassName:(NSString*)className; +@end + + +NS_ASSUME_NONNULL_END diff --git a/goodies/objC/CWPackContext.m b/goodies/objC/CWPackContext.m new file mode 100644 index 0000000..3038d1b --- /dev/null +++ b/goodies/objC/CWPackContext.m @@ -0,0 +1,693 @@ + +/* CWPack/goodies/ObjC - CWPackContext.m */ + +/* + The MIT License (MIT) + + Copyright (c) 2021 Claes Wihlborg + + 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. + */ + + +#include "cwpack_internals.h" +#include "numeric_extensions.h" +#include "cwpack_utils.h" + +#import "CWPackContext.h" + + +#define CWP_ITEM_OBJECT_MARKER CWP_ITEM_USER_EXT_127 + + + + +@protocol CWPackPackerClasses +@required +- (void) cwPackPackerTo:(CWPackContext*)ctx; +@end + + +@interface CWUnpackContext () +- (id) cwUnpackNextObjectSub:(long)label; +@end + + +@interface NSObject (CWPackable) +- (void) cwPackTo:(CWPackContext*)ctx; +@end + + + + +#pragma mark - +#pragma mark ************************************** CWPackContext + + +@implementation CWPackContext +{ + CFMutableDictionaryRef _labelMap; + long userLabelGenerator; + long packerLabelGenerator; +} + +- (instancetype)initWithContext:(cw_pack_context*)context +{ + self = [super init]; + if (self) { + _context = context; + _labelMap = CFDictionaryCreateMutable(nil, 0, nil, nil); + } + return self; +} + + ++ (instancetype) newWithContext:(cw_pack_context*)context { + return [self.alloc initWithContext:context]; +} + + +- (long) labelForObject:(id)object { + return (long)CFDictionaryGetValue (_labelMap, (const void *)object); +} + + +- (long) assignLabelForObject:(id)object isMsgpackObject:(BOOL)isMsgpackObject +{ + long label = isMsgpackObject ? --packerLabelGenerator : ++userLabelGenerator; + CFDictionarySetValue (_labelMap, (const void *)object,(const void *)label); + return label; +} + + +- (void) packUserObject:(id)object +{ + [object cwPackTo:self]; +} + + +- (void) packObject:(nullable NSObject*)object +{ + if (!object) + { + cw_pack_nil(_context); + return; + } + + BOOL isMsgpackObject = [object conformsToProtocol:@protocol(CWPackPackerClasses)]; + + if (_useLabels) + { + long label = [self labelForObject:object]; + if (label) // object already packed, just pack a reference. + { + cw_pack_array_size(_context,1); + cw_pack_ext_integer(_context, CWP_ITEM_OBJECT_MARKER, label); + return; + } + + cw_pack_array_size(_context, 2 + object.persistentAttributeCount); + label = [self assignLabelForObject:object isMsgpackObject:isMsgpackObject]; + cw_pack_ext_integer (_context, CWP_ITEM_OBJECT_MARKER, label); + if (isMsgpackObject) { + [(NSObject*)object cwPackPackerTo:self]; + } + else { + [self packUserObject:object]; + } + } + else if (isMsgpackObject) + { + [(NSObject*)object cwPackPackerTo:self]; + } + else + { + cw_pack_array_size(_context, 2 + object.persistentAttributeCount); + cw_pack_ext_integer (_context, CWP_ITEM_OBJECT_MARKER, 0); + [self packUserObject:object]; + } +} + +@end + + + +#pragma mark - +#pragma mark ************************************** CWUnpackContext + + + +@implementation CWUnpackContext +{ + NSMutableArray *_userReferences; + NSMutableArray *_packerReferences; +} + +- (instancetype)initWithContext:(cw_unpack_context*)context +{ + self = [super init]; + if (self) { + _context = context; + _userReferences = [NSMutableArray arrayWithObject:NSNull.null]; //no reference has value 0 + _packerReferences = [NSMutableArray arrayWithObject:NSNull.null]; //no reference has value 0 + } + return self; +} + + ++ (instancetype) newWithContext:(cw_unpack_context*)context +{ + return [self.alloc initWithContext:context]; +} + + +- (id) cwUnpackObject:(long)label +{ + id object; + + switch (_context->item.type) + { + case CWP_ITEM_NIL: + object = [NSNull null]; + break; + + case CWP_ITEM_BOOLEAN: + object = [NSNumber numberWithBool:_context->item.as.boolean]; + break; + + case CWP_ITEM_POSITIVE_INTEGER: + object = [NSNumber numberWithUnsignedLongLong:_context->item.as.u64]; + break; + + case CWP_ITEM_NEGATIVE_INTEGER: + object = [NSNumber numberWithLongLong:_context->item.as.i64]; + break; + + case CWP_ITEM_FLOAT: + object = [[NSNumber alloc] initWithFloat:_context->item.as.real]; + break; + + case CWP_ITEM_DOUBLE: + object = [NSNumber numberWithDouble:_context->item.as.long_real]; + break; + + case CWP_ITEM_STR: + { + object = [NSString.alloc initWithBytes:_context->item.as.str.start length:_context->item.as.str.length encoding:NSUTF8StringEncoding]; + if (!object) { + _context->return_code = CWP_RC_VALUE_ERROR; + return nil; + } + break; + } + + case CWP_ITEM_BIN: + { + object = [NSData dataWithBytes:_context->item.as.bin.start length:_context->item.as.bin.length]; + break; + } + + case CWP_ITEM_TIMESTAMP: + object = [NSDate dateWithTimeIntervalSince1970:_context->item.as.time.tv_sec + _context->item.as.time.tv_nsec / 1000000000.0]; + break; + + case CWP_ITEM_MAP: + { + int i, dim = _context->item.as.map.size; + NSMutableDictionary *dict = NSMutableDictionary.new; + if (label) [_packerReferences addObject:dict]; + for(i = 0; i < dim; i++) + { + id key = [self cwUnpackNextObjectSub:0]; + id val = [self cwUnpackNextObjectSub:0]; + if (_context->return_code == CWP_RC_OK) + dict[key] = val; + } + return dict; + } + + case CWP_ITEM_ARRAY: + { + int dim = _context->item.as.array.size; + if (dim == 0) + { + object = NSMutableArray.new; + } + else + { + cw_unpack_next(_context); + if (_context->item.type == CWP_ITEM_OBJECT_MARKER) //object + { + long idx = get_ext_integer(_context); + if (dim == 1) // object reference + { + if ((idx<0)? (-idx >= _packerReferences.count) : (idx >= _userReferences.count)) + { + _context->return_code = CWP_RC_VALUE_ERROR; + return nil; + } + return idx>0 ? _userReferences[idx] : _packerReferences[-idx]; + } + if (idx < 0) // we had a labeled MessagePack object + { + if (dim != 2) + { + _context->return_code = CWP_RC_VALUE_ERROR; + return nil; + } + return [self cwUnpackNextObjectSub:idx]; + } + + NSString *objClassName = [self cwUnpackNextObjectSub:0]; + Class objClass = NSClassFromString(objClassName); + + if (!objClass) + object = [CWPackGenericClass newWithClassName:objClassName]; + else + object = [objClass alloc]; + object = [object cwUnpackSubInit:self remainingAttributes:dim - 2]; + if (idx == _userReferences.count) + { + [_userReferences addObject:object]; + } + else + { + if (idx != 0) + { + _context->return_code = CWP_RC_VALUE_ERROR; + return nil; + } + } + [object cwUnpackSub:self remainingAttributes:dim - 2]; + return object; + } + else // standard MsgPack array + { + int i; + NSMutableArray *arr = NSMutableArray.new; + if (label) [_packerReferences addObject:arr]; + id item = [self cwUnpackObject:0]; + if (_context->return_code == CWP_RC_OK) + [arr addObject:item]; + for(i = 1; i < dim; i++) + { + id item = [self cwUnpackNextObjectSub:0]; + if (_context->return_code == CWP_RC_OK) + [arr addObject:item]; + } + return arr; + } + } + } + + default: + object = [CWPackExternalItem itemWithType:_context->item.type + data:[NSData dataWithBytes:_context->item.as.ext.start length:_context->item.as.ext.length]]; + } + if (label) + { + if (label != -_packerReferences.count) + _context->return_code = CWP_RC_MALFORMED_INPUT; + else + [_packerReferences addObject:object]; + } + return object; +} + + +- (id) cwUnpackNextObjectSub:(long)label +{ + cw_unpack_next(_context); + if (_context->return_code) + return nil; + return [self cwUnpackObject:label]; +} + + +- (id) unpackNextObject +{ + id result = [self cwUnpackNextObjectSub:0]; + if (result == [NSNull null]) + return nil; + return result; +} + +@end + + + +#pragma mark ************************************** NSObject + + + +@implementation NSObject (CWPackable) + +- (int) persistentAttributeCount {return 0;} + +- (NSString*) packerClassName {return self.className;} + +- (void) cwPackTo:(CWPackContext*)ctx +{ + cw_pack_cstr(ctx.context, self.packerClassName.UTF8String); + [self cwPackSub:ctx]; +} + +- (void) cwPackSub:(CWPackContext*)ctx; +{ + [NSException raise:@"Object Not Packable" format:@"Class \"%s\" does not conform to protocol \n", object_getClassName(self)]; +} + +- (void) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + [NSException raise:@"Object Not Unpackable" format:@"Class \"%s\" does not conform to protocol \n", object_getClassName(self)]; +} + +- (instancetype) cwUnpackSubInit:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + return self.init; +} + +@end + + +#pragma mark ************************************** NSNull + +@interface NSNull (CWPackable) +@end + + +@implementation NSNull (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + cw_pack_nil (ctx.context); +} +@end + + + +#pragma mark ************************************** NSString, NSMutableString + + +@interface NSString (CWPackable) +@end + + +@implementation NSString (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + cw_pack_cstr (ctx.context, self.UTF8String); +} +@end + + +#pragma mark ************************************** NSData + +@interface NSData (CWPackable) +@end + +@implementation NSData (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + cw_pack_bin(ctx.context, self.bytes, (uint32_t)self.length); +} +@end + + + +#pragma mark ************************************** NSDate + +@interface NSDate (CWPackable) +@end + +@implementation NSDate (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + NSTimeInterval ti = self.timeIntervalSince1970; + cw_pack_time_interval (ctx.context, ti); +} +@end + + +#pragma mark ************************************** NSNumber + +@interface NSNumber (CWPackable) +@end + +@implementation NSNumber (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + CFNumberType numberType = CFNumberGetType((CFNumberRef)self); + switch (numberType) + { + case kCFNumberSInt8Type: + case kCFNumberSInt16Type: + case kCFNumberSInt32Type: + case kCFNumberSInt64Type: + case kCFNumberShortType: + case kCFNumberIntType: + case kCFNumberLongType: + case kCFNumberCFIndexType: + case kCFNumberNSIntegerType: + case kCFNumberLongLongType: + cw_pack_signed(ctx.context, self.longLongValue); + return; + + case kCFNumberFloat32Type: + case kCFNumberFloatType: + case kCFNumberCGFloatType: + cw_pack_float(ctx.context, self.floatValue); + return; + + case kCFNumberFloat64Type: + case kCFNumberDoubleType: + cw_pack_double(ctx.context, self.doubleValue); + return; + + case kCFNumberCharType: + { + int theValue = self.intValue; + if (theValue == 0) + { + cw_pack_boolean(ctx.context, NO); + } + if (theValue == 1) + { + cw_pack_boolean(ctx.context, YES); + } + else + { + cw_pack_signed(ctx.context, theValue); + } + return; + } + default: + ctx.context->return_code = CWP_RC_ILLEGAL_CALL; // No pack defined for this object type + [NSException raise:@"[NSNumber packIn:]" format:@"Cannot recognise type (%ld) of: %@", (long)numberType, self]; + } +} +@end + + +#pragma mark ************************************** NSArray + +@interface NSArray (CWPackable) +@end + +@implementation NSArray (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + uint32_t i, cnt = (uint32_t)self.count; + cw_pack_array_size(ctx.context, cnt); + for (i = 0; i < cnt; i++) + [ctx packObject:self[i]]; +} +@end + + +#pragma mark ************************************** NSDictionary + + +@interface NSDictionary (CWPackable) +@end + + +@implementation NSDictionary (CWPackable) + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + cw_pack_map_size(ctx.context, (uint32_t)self.count); + for (id obj in self) + { + [ctx packObject:obj]; + [ctx packObject:self[obj]]; + } +} +@end + + +#pragma mark ************************************** CWPackExternalItem + + +@interface CWPackExternalItem (CWPackable) +@end + + +@implementation CWPackExternalItem + +- (instancetype) initWithType:(int)type data:(NSData*)data +{ + self = [super init]; + if (self) { + _type = type; + _data = data; + } + return self; +} + + ++ (instancetype) itemWithType:(int)type data:(NSData*)data; +{ + return [[self alloc] initWithType:type data:data]; +} + + +- (void) cwPackPackerTo:(CWPackContext*)ctx +{ + cw_pack_ext(ctx.context, _type, _data.bytes, (int)_data.length); +} + +@end + + +#pragma mark - +#pragma mark ************************************** CWPackGenericClass + + +@implementation CWPackGenericClass + +- (instancetype)initWithClassName:(NSString*)className +{ + self = [self init]; + if (self) { + _packerClassName = className; + } + return self; +} + ++ (instancetype) newWithClassName:(NSString*)className {return [self.alloc initWithClassName:className];} + +- (int) persistentAttributeCount {return (int)_attributes.count;} + +- (void) cwPackSub:(CWPackContext*)ctx +{ + for (id o in _attributes) {[ctx packObject:o];} +} + +- (void) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + _attributes = NSMutableArray.new; + int i; + for (i = 0; i < remainingAttributes; i++) { + id item = [ctx cwUnpackNextObjectSub:0]; + if (ctx.context->return_code == CWP_RC_OK) + [_attributes addObject:item]; + } +} + +@end + + +#pragma mark ************************************** NSSet + +@interface NSSet (CWPackable) +@end + +@implementation NSSet (CWPackable) +- (int) persistentAttributeCount {return (int)self.count + super.persistentAttributeCount;} + +- (NSString*) packerClassName {return @"NSSet";} + +- (void) cwPackSub:(CWPackContext*)ctx +{ + for (id object in self) + [ctx packObject:object]; +} + +- (instancetype) cwUnpackSubInit:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + return NSMutableSet.new; +} + +@end + + +@interface NSMutableSet (CWPackable) +@end + +@implementation NSMutableSet (CWPackable) +- (instancetype) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + int i; + for (i=0; i + +@interface NSCountedSet (CWPackable) +@end + +@implementation NSCountedSet (CWPackable) +- (int) persistentAttributeCount {return 2*(int)self.count + super.persistentAttributeCount;} + +- (void) cwPackSub:(CWPackContext*)ctx +{ + for (id object in self) + { + [ctx packObject:object]; + cw_pack_signed(ctx.context, [self countForObject:object]); + } +} + +- (instancetype) cwUnpackSubInit:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + return [self initWithCapacity:remainingAttributes/2]; +} + +- (instancetype) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes +{ + long count = remainingAttributes/2; + int i; + for (i=0; i +@property int level; +@property MyClass *link; +- (instancetype) initWithLevel:(int)level link:(MyClass*)link; @end +``` +Note first, one attribute is a link to another instance, so here we should set useLabels to YES. Our pack method could be like this: -@implementation myClass -- (void) packIn:(cw_pack_context*) buff -{ - cw_pack_signed( buff, theInt ); - [theSet packIn:buff]; +```C +- (void) cwPackSub:(CWPackContext*)ctx { + [super cwPackSub:ctx]; + cw_pack_signed(ctx.context, level); + [ctx packObject:link]; } -+ (instancetype) unpackFrom:(cw_unpack_context*) buff -{ - int anInt = cw_unpack_next_signed32( buff ); - NSMutableSet aSet = [NSMutableSet unpackFrom:buff]; - return [[self alloc] initWithInt:anInt set:aSet]; +``` +If the immediate ancestor to MyClass is NSObject, then super must not be called. + +Unpacking can be a little more tangled due to the possibility of circular references, that is a referenced object has a reference back to the root object. Unpacking happens in two steps: first the object is allocated and in the next step the attributes are set. + +Step 1: Allocation & Initiating + +##### - (instancetype) cwUnpackSubInit:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes + + +When `cwUnpackSubInit` is called, self is allocated but not inited. The sole purpose of the method is to return a suitable inited object. It is not neccesary to be the same object as self. If it is sufficient to sent init to the preallocated object (self), this method could be skipped, it's optional. + +Step 2: Fetching attributes. + +##### - (void) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes + +In the pack example an unpack method could be: + +```C +- (void) cwUnpackSub:(CWUnpackContext*)ctx remainingAttributes:(int)remainingAttributes { + [super cwUnpackSub:ctx remainingAttributes:remainingAttributes - 2] + level = cw_unpack_next_signed32 (ctx.context); + link = [ctx unpackNextObject]; } -@end ``` +As usual, don't call super on NSObject. + +### Packable system objects +(Un)packing of the following system classes is predefined in ObjC: +NSArray, NSDictionary, NSData, NSDate, NSNull, NSNumber, NSSet, NSCountableSet and NSString. In most cases they are mapped at their corresponding MessagePack item. !WARNING! MessagePack has an arbitrary type as key in map. Objective-C demands a string key in the corresponding NSDictionary. + +Of those who have both mutable and immutable versions, NSData and NSString are created immutable, and NSArray, NSDictionary and NSSet are created mutable at unpack. + +### Special +There are two special cases. + +First, when the MessagePack item is of an unknown EXT type, it will be unpacked as an instance of the `CWPackExternalItem` class. +Second, when the object to be unpacked is of unknown user class, it is unpacked as an instance of the class `CWPackGenericClass`. diff --git a/goodies/objC/Technique.md b/goodies/objC/Technique.md new file mode 100755 index 0000000..34851ee --- /dev/null +++ b/goodies/objC/Technique.md @@ -0,0 +1,60 @@ +# CWPack / Goodies / ObjC / Technique + +We have choosen to represent objects as arrays. To be able to differentiate objects from normal arrays we have put an object marker as the first slot of the array. The object marker is an EXT item with type 127. The second array slot is kept by the class name. The rest of the array slots are kept by the objects attributes. + +### User objects + +We have an example: + +```C +@interface MyClass: NSObject +@property int level; +@property MyClass *link; +- (instancetype) initWithLevel:(int)level link:(MyClass*)link; +@end +``` +When packed into a MessagePack stream it may look like: + +```C +[(127,<00>) "MyClass" 37 NULL] +``` +This was the simple example where the link was nil. But look at this code fragment: + +```C +MyClass *a = [MyClass.alloc initWithLevel:10 link:nil]; +MyClass *b = [MyClass.alloc initWithLevel:20 link:a]; +a.link = b; +[myContext packObject:a]; +``` +To not fall into eternal recursion we need to break the circular reference in some way. We do it by giving the objects labels (set useLabel = YES on pack context). The labels are just consecutive numbers starting at 1. We store the label in the objects markers payload. Let´s start packing: + +```C +[(127,<01>) // object a got the label 1, we note that in a table +[(127,<01>) "MyClass" 10 [(127,<02>) "MyClass" 20 +``` +Now it is time to insert object *a* again. But this time we have the object in our table and instead of packing the object we just pack a reference to it. A reference is an array with a single slot that is the object marker. The final result becomes: + +```C +[(127,<01>) "MyClass" 10 [(127,<02>) "MyClass" 20 [(127,<01>)]]] +``` +The cwpack dump utility "knows" object markers and prints the above message as: + +1->MyClass(10 2->MyClass(20 ->1)) + +### MessagePack objects + +It is not just user objects that can contain circular references. Take this example: + +```C +NSMutableArray *a = NSMutableArray.new; +[a addObject:a]; +[myContext packObject:a]; +``` +Obviously we need a way to label MessagePack objects also. We do as for user objects, but instead for a class-name in the second slot we put the MessagePack object. In this case, there are just 2 slots. + +There is one problem here. If the MessagePack object is a string, it looks exactly like an user object with no attributes. We solve this ambiguity by letting MessagePack objects have negative labels starting with -1. So the packing above becomes: + +```C +[(127,) [[(127,)]]] +``` +Or prettyprinted: -1->[-> -1] diff --git a/goodies/objC/obsolete/README.md b/goodies/objC/obsolete/README.md new file mode 100755 index 0000000..a2aa1cf --- /dev/null +++ b/goodies/objC/obsolete/README.md @@ -0,0 +1,40 @@ +# CWPack / Goodies / ObjC + + +ObjC contains a wrapper for objective-C in the form of a category to NSObject. +The category contains two methods: + +```C +/* *********************** P A C K *****************************/ +- (void) packIn:(cw_pack_context*) buff; + +/* *********************** U N P A C K *************************/ ++ (instancetype) unpackFrom:(cw_unpack_context*) buff; +``` + +The methods are defined for the standard classes NSString, NSData, NSNumber, NSDate, NSNull, NSDictionary, NSArray and NSSet. + +For other classes you need to define the methods yourself. E.g. + +```C +@interface myClass: NSObject { + int theInt; + NSMutableSet theSet; +} +@end + +@implementation myClass +- (void) packIn:(cw_pack_context*) buff +{ + cw_pack_signed( buff, theInt ); + [theSet packIn:buff]; +} ++ (instancetype) unpackFrom:(cw_unpack_context*) buff +{ + int anInt = cw_unpack_next_signed32( buff ); + NSMutableSet aSet = [NSMutableSet unpackFrom:buff]; + return [[self alloc] initWithInt:anInt set:aSet]; +} +@end +``` + diff --git a/goodies/objC/cwpack_objc.h b/goodies/objC/obsolete/cwpack_objc.h similarity index 100% rename from goodies/objC/cwpack_objc.h rename to goodies/objC/obsolete/cwpack_objc.h diff --git a/goodies/objC/cwpack_objc.m b/goodies/objC/obsolete/cwpack_objc.m similarity index 100% rename from goodies/objC/cwpack_objc.m rename to goodies/objC/obsolete/cwpack_objc.m