diff --git a/goodies/basic-contexts/basic_contexts.c b/goodies/basic-contexts/basic_contexts.c index c026e22..a0646ea 100644 --- a/goodies/basic-contexts/basic_contexts.c +++ b/goodies/basic-contexts/basic_contexts.c @@ -291,7 +291,7 @@ void init_file_pack_context (file_pack_context* fpc, unsigned long initial_buffe fpc->pc.return_code = CWP_RC_MALLOC_ERROR; return; } - fpc->fileDescriptor = fileDescriptor; + fpc->fileDescriptor = fileDescriptor; fpc->barrier = NULL; diff --git a/goodies/dump/README.md b/goodies/dump/README.md index cdff3e4..39dd806 100755 --- a/goodies/dump/README.md +++ b/goodies/dump/README.md @@ -4,9 +4,10 @@ Dump is a small program taking a msgpack file as input and produces a human readable file as output. The output is not json as msgpack is more feature-rich. Syntax: -cwpack_dump [-t 9] [-v] [-h] < msgpackFile > humanReadableFile +cwpack_dump [-t 9] [-v][-r] [-h] < msgpackFile > humanReadableFile -t 9 Tab size -v Version +-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. @@ -17,10 +18,10 @@ If Tab size isn't given, structures are written on a single line. ``` 0 [10000000 3.14 "åäöÅÄÖ"] - 1c {"binary": (62696e617279) "extension": (-5,68656c6c6f) "time": '2020-05-20 18:40:00'} + 1c {"binary": <62696e617279> "extension": (-5,<68656c6c6f>) "time": '2020-05-20 18:40:00'} 49 ``` -and `cwpack_dump -t 4 < testdump.msgpack` prints: +and `cwpack_dump -t 4 < testdump.msgpack` prints: ``` 0 [ @@ -29,10 +30,20 @@ and `cwpack_dump -t 4 < testdump.msgpack` prints: f "åäöÅÄÖ" 1c ] 1c { - 1d "binary": (62696e617279) - 2c "extension": (-5,68656c6c6f) + 1d "binary": <62696e617279> + 2c "extension": (-5,<68656c6c6f>) 3e "time": '2020-05-20 18:40:00' 49 } 49 ``` +The -r option makes dump recognize Objective-C objects. `cwpack_dump < testdump2.msgpack` prints: + +``` + 0 [(127,<01>) "MyClass" [(127,<02>) "MyClass" [(127,<01>)]]] +``` +and `cwpack_dump -r < testdump2.msgpack` prints + +``` + 0 1->MyClass(2->MyClass(->1)) +``` diff --git a/goodies/dump/cwpack_dump b/goodies/dump/cwpack_dump new file mode 100755 index 0000000..6684217 Binary files /dev/null and b/goodies/dump/cwpack_dump differ diff --git a/goodies/dump/cwpack_dump.c b/goodies/dump/cwpack_dump.c index 4e28fde..ba786c6 100755 --- a/goodies/dump/cwpack_dump.c +++ b/goodies/dump/cwpack_dump.c @@ -25,8 +25,10 @@ #include #include #include "basic_contexts.h" +#include "numeric_extensions.h" char tabString[21] = " "; +bool recognizeObjects = false; #define NEW_LINE {printf ("\n%6x ",(unsigned)(context->current - context->start)); for (ti=0; tireturn_code) return; + dump_item (context, tabLevel); +} + +static void dump_item( cw_unpack_context* context, int tabLevel) { long long dim =99; @@ -55,20 +64,18 @@ static void dump_next_item( cw_unpack_context* context, int tabLevel) char s[128]; if (!tabLevel) NEW_LINE; - cw_unpack_next (context); - if (context->return_code) return; switch (context->item.type) { case CWP_ITEM_NIL: - printf("null"); + printf("nil"); break; case CWP_ITEM_BOOLEAN: if (context->item.as.boolean) - printf("true"); + printf("YES"); else - printf("false"); + printf("NO"); break; case CWP_ITEM_POSITIVE_INTEGER: @@ -115,24 +122,79 @@ static void dump_next_item( cw_unpack_context* context, int tabLevel) break;} case CWP_ITEM_BIN: - printf("("); + printf("<"); dump_as_hex (context->item.as.bin.start, context->item.as.bin.length); - printf(")"); + printf(">"); break; case CWP_ITEM_ARRAY: - printf("["); + { dim = context->item.as.array.size; - tabLevel++; - for (i = 0; i < dim; i++) + if (!dim) + { + printf("[]"); + break; + } + + cw_unpack_next (context); + if (context->return_code) break; + + if (recognizeObjects && (context->item.type == 127)) + { + long label = get_ext_integer(context); + bool userObject = label >= 0; + if (dim == 1) /* reference */ + { + printf("->%ld",label); + break; + } + if (label) + printf("%ld->",labs(label)); + if (!userObject) + { + if (dim != 2) + { + context->return_code = CWP_RC_MALFORMED_INPUT; + break; + } + dump_next_item(context,tabLevel); + break; + } + cw_unpack_next (context); + if (context->return_code) break; + if (context->item.type != CWP_ITEM_STR) + { + context->return_code = CWP_RC_MALFORMED_INPUT; + break; + } + printf("%.*s(",context->item.as.str.length, context->item.as.str.start); + tabLevel++; + for (i = 2; i < dim; i++) + { + CHECK_NEW_LINE; + dump_next_item(context,tabLevel); + } + tabLevel--; + if(*tabString) NEW_LINE; + printf(")"); + } + else { + printf("["); + tabLevel++; CHECK_NEW_LINE; - dump_next_item(context,tabLevel); + dump_item(context,tabLevel); + for (i = 1; i < dim; i++) + { + CHECK_NEW_LINE; + dump_next_item(context,tabLevel); + } + tabLevel--; + if(*tabString) NEW_LINE; + printf("]"); } - tabLevel--; - if(*tabString) NEW_LINE; - printf("]"); break; + } case CWP_ITEM_MAP: printf("{"); @@ -152,7 +214,8 @@ static void dump_next_item( cw_unpack_context* context, int tabLevel) case CWP_ITEM_TIMESTAMP: printf("'"); - gmtime_r(&context->item.as.time.tv_sec,&tm); + time_t tv_sec = context->item.as.time.tv_sec; + gmtime_r(&tv_sec,&tm); strftime(s,128,"%F %T", &tm); printf("%s",s); if (context->item.as.time.tv_nsec) @@ -200,12 +263,17 @@ int main(int argc, const char * argv[]) printf("cwpack_dump version = 1.0\n"); exit(0); } + else if (!strcmp(argv[i],"-r")) + { + recognizeObjects = true; + } else { - printf("cwpack_dump [-t 9] [-v] [-h]\n"); + printf("cwpack_dump [-t 9] [-r] [-v] [-h]\n"); + printf("-h Help\n"); + printf("-r Recognize records\n"); printf("-t 9 Tab size\n"); printf("-v Version\n"); - printf("-h Help\n"); printf("\nIf Tab size isn't given, structures are written on a single line\n"); printf("\nInput is taken from stdin and output is written to stdout\n"); exit(0); diff --git a/goodies/dump/runCWpack_dump.sh b/goodies/dump/runCWpack_dump.sh index 12d0c2f..d9fc8fc 100755 --- a/goodies/dump/runCWpack_dump.sh +++ b/goodies/dump/runCWpack_dump.sh @@ -1,3 +1,3 @@ -clang -ansi -I ../../src/ -I ../basic-contexts/ -o cwpack_dump *.c ../../src/cwpack.c ../basic-contexts/*.c +clang -ansi -I ../../src/ -I ../basic-contexts/ -I ../numeric-extensions/ -o cwpack_dump *.c ../../src/cwpack.c ../basic-contexts/*.c ../numeric-extensions/numeric_extensions.c ./cwpack_dump < testdump.msgpack ./cwpack_dump -t 4 < testdump.msgpack diff --git a/goodies/numeric-extensions/numeric_extensions.c b/goodies/numeric-extensions/numeric_extensions.c index 68c26a4..b6078f2 100644 --- a/goodies/numeric-extensions/numeric_extensions.c +++ b/goodies/numeric-extensions/numeric_extensions.c @@ -121,6 +121,9 @@ int64_t get_ext_integer (cw_unpack_context* unpack_context) } switch (unpack_context->item.as.ext.length) { + case 0: + return 0; + case 1: return *(int8_t*)unpack_context->item.as.ext.start; diff --git a/goodies/objC/cwpack_objc.h b/goodies/objC/cwpack_objc.h index 8e8ce0e..d02a05c 100755 --- a/goodies/objC/cwpack_objc.h +++ b/goodies/objC/cwpack_objc.h @@ -33,6 +33,6 @@ - (void) packIn:(cw_pack_context*) buff; /* *********************** U N P A C K *************************/ +- (id) initFromContext:(cw_unpack_context*) buff; + (instancetype) unpackFrom:(cw_unpack_context*) buff; - @end diff --git a/goodies/objC/cwpack_objc.m b/goodies/objC/cwpack_objc.m index 11773eb..8d55674 100755 --- a/goodies/objC/cwpack_objc.m +++ b/goodies/objC/cwpack_objc.m @@ -24,6 +24,8 @@ software and associated documentation files (the "Software"), to deal in the Sof #import "cwpack_objc.h" #import "cwpack_utils.h" +#define CWP_ITEM_CLASS_NAME 127 + id cwObjectFromBuffer (cw_unpack_context* inbuf); @@ -32,8 +34,8 @@ @implementation NSObject (cwPack) - (void) packIn:(cw_pack_context*) buff { - buff->return_code = CWP_RC_ILLEGAL_CALL; // No pack defined for this object type - [NSException raise:@"[NSObject packIn:]" format:@"PackIn not defined for class: %@", [self class]]; + const char *className= object_getClassName(self); + cw_pack_ext (buff, CWP_ITEM_CLASS_NAME, className, (uint32_t)strlen(className)); } @@ -61,6 +63,16 @@ + (instancetype) unpackFrom:(cw_unpack_context*) buff return result; } + +- (id) initFromContext:(cw_unpack_context*) buff +{ + self = [self init]; // satisfy compiler + buff->return_code = CWP_RC_ILLEGAL_CALL; // No unpack defined for this object type + [NSException raise:@"Not defined" format:@"[%@ initFromContext:]", [self class]]; + return nil; +} + + @end @@ -192,6 +204,8 @@ - (void) packIn:(cw_pack_context*) buff NSTimeInterval ti = self.timeIntervalSince1970; cw_pack_time_interval (buff, ti); } + + @end @@ -227,7 +241,7 @@ id cwObjectFromBuffer (cw_unpack_context* inbuf) return [NSNumber numberWithDouble:inbuf->item.as.long_real]; case CWP_ITEM_STR: - return [[[NSString alloc] initWithBytes:inbuf->item.as.str.start length:inbuf->item.as.str.length encoding:NSUTF8StringEncoding] autorelease]; + return [[NSString alloc] initWithBytes:inbuf->item.as.str.start length:inbuf->item.as.str.length encoding:NSUTF8StringEncoding]; case CWP_ITEM_BIN: return [NSData dataWithBytes:inbuf->item.as.bin.start length:inbuf->item.as.bin.length]; @@ -263,6 +277,19 @@ id cwObjectFromBuffer (cw_unpack_context* inbuf) { return [NSDate dateWithTimeIntervalSince1970:inbuf->item.as.time.tv_sec + inbuf->item.as.time.tv_nsec / 1000000000.0]; } + + case CWP_ITEM_CLASS_NAME: + { + NSString *cName = [[NSString alloc] initWithBytes:inbuf->item.as.ext.start length:inbuf->item.as.ext.length encoding:NSUTF8StringEncoding]; + Class objectClass = NSClassFromString(cName); + if (objectClass == NULL) + { + [NSException raise:@"cwObjectFromBuffer" format:@"Class not defined for class: %@", cName]; + } + else + return [[objectClass alloc] initFromContext:inbuf]; + } + default: return nil; diff --git a/src/cwpack.h b/src/cwpack.h index c347ab9..36d3d64 100644 --- a/src/cwpack.h +++ b/src/cwpack.h @@ -104,7 +104,136 @@ typedef enum CWP_ITEM_TIMESTAMP = -1, CWP_ITEM_MAX_RESERVED_EXT = -1, CWP_ITEM_MIN_USER_EXT = 0, + CWP_ITEM_USER_EXT_0 = 0, + CWP_ITEM_USER_EXT_1 = 1, + CWP_ITEM_USER_EXT_2 = 2, + CWP_ITEM_USER_EXT_3 = 3, + CWP_ITEM_USER_EXT_4 = 4, + CWP_ITEM_USER_EXT_5 = 5, + CWP_ITEM_USER_EXT_6 = 6, + CWP_ITEM_USER_EXT_7 = 7, + CWP_ITEM_USER_EXT_8 = 8, + CWP_ITEM_USER_EXT_9 = 9, + CWP_ITEM_USER_EXT_10 = 10, + CWP_ITEM_USER_EXT_11 = 11, + CWP_ITEM_USER_EXT_12 = 12, + CWP_ITEM_USER_EXT_13 = 13, + CWP_ITEM_USER_EXT_14 = 14, + CWP_ITEM_USER_EXT_15 = 15, + CWP_ITEM_USER_EXT_16 = 16, + CWP_ITEM_USER_EXT_17 = 17, + CWP_ITEM_USER_EXT_18 = 18, + CWP_ITEM_USER_EXT_19 = 19, + CWP_ITEM_USER_EXT_20 = 20, + CWP_ITEM_USER_EXT_21 = 21, + CWP_ITEM_USER_EXT_22 = 22, + CWP_ITEM_USER_EXT_23 = 23, + CWP_ITEM_USER_EXT_24 = 24, + CWP_ITEM_USER_EXT_25 = 25, + CWP_ITEM_USER_EXT_26 = 26, + CWP_ITEM_USER_EXT_27 = 27, + CWP_ITEM_USER_EXT_28 = 28, + CWP_ITEM_USER_EXT_29 = 29, + CWP_ITEM_USER_EXT_30 = 30, + CWP_ITEM_USER_EXT_31 = 31, + CWP_ITEM_USER_EXT_32 = 32, + CWP_ITEM_USER_EXT_33 = 33, + CWP_ITEM_USER_EXT_34 = 34, + CWP_ITEM_USER_EXT_35 = 35, + CWP_ITEM_USER_EXT_36 = 36, + CWP_ITEM_USER_EXT_37 = 37, + CWP_ITEM_USER_EXT_38 = 38, + CWP_ITEM_USER_EXT_39 = 39, + CWP_ITEM_USER_EXT_40 = 40, + CWP_ITEM_USER_EXT_41 = 41, + CWP_ITEM_USER_EXT_42 = 42, + CWP_ITEM_USER_EXT_43 = 43, + CWP_ITEM_USER_EXT_44 = 44, + CWP_ITEM_USER_EXT_45 = 45, + CWP_ITEM_USER_EXT_46 = 46, + CWP_ITEM_USER_EXT_47 = 47, + CWP_ITEM_USER_EXT_48 = 48, + CWP_ITEM_USER_EXT_49 = 49, + CWP_ITEM_USER_EXT_50 = 50, + CWP_ITEM_USER_EXT_51 = 51, + CWP_ITEM_USER_EXT_52 = 52, + CWP_ITEM_USER_EXT_53 = 53, + CWP_ITEM_USER_EXT_54 = 54, + CWP_ITEM_USER_EXT_55 = 55, + CWP_ITEM_USER_EXT_56 = 56, + CWP_ITEM_USER_EXT_57 = 57, + CWP_ITEM_USER_EXT_58 = 58, + CWP_ITEM_USER_EXT_59 = 59, + CWP_ITEM_USER_EXT_60 = 60, + CWP_ITEM_USER_EXT_61 = 61, + CWP_ITEM_USER_EXT_62 = 62, + CWP_ITEM_USER_EXT_63 = 63, + CWP_ITEM_USER_EXT_64 = 64, + CWP_ITEM_USER_EXT_65 = 65, + CWP_ITEM_USER_EXT_66 = 66, + CWP_ITEM_USER_EXT_67 = 67, + CWP_ITEM_USER_EXT_68 = 68, + CWP_ITEM_USER_EXT_69 = 69, + CWP_ITEM_USER_EXT_70 = 70, + CWP_ITEM_USER_EXT_71 = 71, + CWP_ITEM_USER_EXT_72 = 72, + CWP_ITEM_USER_EXT_73 = 73, + CWP_ITEM_USER_EXT_74 = 74, + CWP_ITEM_USER_EXT_75 = 75, + CWP_ITEM_USER_EXT_76 = 76, + CWP_ITEM_USER_EXT_77 = 77, + CWP_ITEM_USER_EXT_78 = 78, + CWP_ITEM_USER_EXT_79 = 79, + CWP_ITEM_USER_EXT_80 = 80, + CWP_ITEM_USER_EXT_81 = 81, + CWP_ITEM_USER_EXT_82 = 82, + CWP_ITEM_USER_EXT_83 = 83, + CWP_ITEM_USER_EXT_84 = 84, + CWP_ITEM_USER_EXT_85 = 85, + CWP_ITEM_USER_EXT_86 = 86, + CWP_ITEM_USER_EXT_87 = 87, + CWP_ITEM_USER_EXT_88 = 88, + CWP_ITEM_USER_EXT_89 = 89, + CWP_ITEM_USER_EXT_90 = 90, + CWP_ITEM_USER_EXT_91 = 91, + CWP_ITEM_USER_EXT_92 = 92, + CWP_ITEM_USER_EXT_93 = 93, + CWP_ITEM_USER_EXT_94 = 94, + CWP_ITEM_USER_EXT_95 = 95, + CWP_ITEM_USER_EXT_96 = 96, + CWP_ITEM_USER_EXT_97 = 97, + CWP_ITEM_USER_EXT_98 = 98, + CWP_ITEM_USER_EXT_99 = 99, + CWP_ITEM_USER_EXT_100 = 100, + CWP_ITEM_USER_EXT_101 = 101, + CWP_ITEM_USER_EXT_102 = 102, + CWP_ITEM_USER_EXT_103 = 103, + CWP_ITEM_USER_EXT_104 = 104, + CWP_ITEM_USER_EXT_105 = 105, + CWP_ITEM_USER_EXT_106 = 106, + CWP_ITEM_USER_EXT_107 = 107, + CWP_ITEM_USER_EXT_108 = 108, + CWP_ITEM_USER_EXT_109 = 109, + CWP_ITEM_USER_EXT_110 = 110, + CWP_ITEM_USER_EXT_111 = 111, + CWP_ITEM_USER_EXT_112 = 112, + CWP_ITEM_USER_EXT_113 = 113, + CWP_ITEM_USER_EXT_114 = 114, + CWP_ITEM_USER_EXT_115 = 115, + CWP_ITEM_USER_EXT_116 = 116, + CWP_ITEM_USER_EXT_117 = 117, + CWP_ITEM_USER_EXT_118 = 118, + CWP_ITEM_USER_EXT_119 = 119, + CWP_ITEM_USER_EXT_120 = 120, + CWP_ITEM_USER_EXT_121 = 121, + CWP_ITEM_USER_EXT_122 = 122, + CWP_ITEM_USER_EXT_123 = 123, + CWP_ITEM_USER_EXT_124 = 124, + CWP_ITEM_USER_EXT_125 = 125, + CWP_ITEM_USER_EXT_126 = 126, + CWP_ITEM_USER_EXT_127 = 127, CWP_ITEM_MAX_USER_EXT = 127, + CWP_ITEM_NIL = 300, CWP_ITEM_BOOLEAN = 301, CWP_ITEM_POSITIVE_INTEGER = 302,