@@ -18,16 +18,17 @@ #include "config.h" #include #import "OFData+MessagePackValue.h" -#import "OFNumber.h" -#import "OFNull.h" -#import "OFString.h" #import "OFArray.h" +#import "OFDate.h" #import "OFDictionary.h" #import "OFMessagePackExtension.h" +#import "OFNull.h" +#import "OFNumber.h" +#import "OFString.h" #import "OFInvalidFormatException.h" int _OFData_MessagePackValue_reference; @@ -150,17 +151,68 @@ objc_autoreleasePoolPop(pool); } return pos; } + +static OFDate * +createDate(OFData *data) +{ + switch ([data count]) { + case 4: { + uint32_t timestamp; + + memcpy(×tamp, [data items], 4); + timestamp = OF_BSWAP32_IF_LE(timestamp); + + return [OFDate dateWithTimeIntervalSince1970: timestamp]; + } + case 8: { + uint64_t combined; + + memcpy(&combined, [data items], 8); + combined = OF_BSWAP64_IF_LE(combined); + + return [OFDate dateWithTimeIntervalSince1970: + (double)(combined & 0x3FFFFFFFF) + + (double)(combined >> 34) / 1000000000]; + } + case 12: { + uint32_t nanoseconds; + int64_t seconds; + + memcpy(&nanoseconds, [data items], 4); + memcpy(&seconds, (char *)[data items] + 4, 8); + + nanoseconds = OF_BSWAP32_IF_LE(nanoseconds); + seconds = OF_BSWAP64_IF_LE(seconds); + + return [OFDate dateWithTimeIntervalSince1970: + (double)seconds + (double)nanoseconds / 1000000000]; + } + default: + @throw [OFInvalidFormatException exception]; + } +} + +static id +createExtension(int8_t type, OFData *data) +{ + switch (type) { + case -1: + return createDate(data); + default: + return [OFMessagePackExtension extensionWithType: type + data: data]; + } +} static size_t parseObject(const uint8_t *buffer, size_t length, id *object, size_t depthLimit) { size_t count; - int8_t type; OFData *data; if (length < 1) goto error; @@ -339,18 +391,14 @@ count = buffer[1]; if (length < count + 3) goto error; - type = buffer[2]; - data = [[OFData alloc] initWithItems: buffer + 3 count: count]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[2], data); } @finally { [data release]; } return count + 3; @@ -361,18 +409,14 @@ count = readUInt16(buffer + 1); if (length < count + 4) goto error; - type = buffer[3]; - data = [[OFData alloc] initWithItems: buffer + 4 count: count]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[3], data); } @finally { [data release]; } return count + 4; @@ -383,103 +427,79 @@ count = readUInt32(buffer + 1); if (length < count + 6) goto error; - type = buffer[5]; - data = [[OFData alloc] initWithItems: buffer + 6 count: count]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[5], data); } @finally { [data release]; } return count + 6; case 0xD4: /* fixext 1 */ if (length < 3) goto error; - type = buffer[1]; - data = [[OFData alloc] initWithItems: buffer + 2 count: 1]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[1], data); } @finally { [data release]; } return 3; case 0xD5: /* fixext 2 */ if (length < 4) goto error; - type = buffer[1]; - data = [[OFData alloc] initWithItems: buffer + 2 count: 2]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[1], data); } @finally { [data release]; } return 4; case 0xD6: /* fixext 4 */ if (length < 6) goto error; - type = buffer[1]; - data = [[OFData alloc] initWithItems: buffer + 2 count: 4]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[1], data); } @finally { [data release]; } return 6; case 0xD7: /* fixext 8 */ if (length < 10) goto error; - type = buffer[1]; - data = [[OFData alloc] initWithItems: buffer + 2 count: 8]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[1], data); } @finally { [data release]; } return 10; case 0xD8: /* fixext 16 */ if (length < 18) goto error; - type = buffer[1]; - data = [[OFData alloc] initWithItems: buffer + 2 count: 16]; @try { - *object = [OFMessagePackExtension - extensionWithType: type - data: data]; + *object = createExtension(buffer[1], data); } @finally { [data release]; } return 18;