@@ -40,10 +40,30 @@ @interface OFNumberPlaceholder: OFNumber @end @interface OFNumberSingleton: OFNumber @end + +#ifdef OF_OBJFW_RUNTIME +enum { + TAG_CHAR, + TAG_SHORT, + TAG_INT, + TAG_LONG, + TAG_LONG_LONG, + TAG_UNSIGNED_CHAR, + TAG_UNSIGNED_SHORT, + TAG_UNSIGNED_INT, + TAG_UNSIGNED_LONG, + TAG_UNSIGNED_LONG_LONG, +}; +# define TAG_BITS 4 +# define TAG_MASK 0xF + +@interface OFTaggedPointerNumber: OFNumberSingleton +@end +#endif static struct { Class isa; } placeholder; @@ -68,10 +88,67 @@ SINGLETON(unsignedLongZeroNumber, initWithUnsignedLong:, 0) SINGLETON(unsignedLongLongZeroNumber, initWithUnsignedLongLong:, 0) SINGLETON(floatZeroNumber, initWithFloat:, 0) SINGLETON(doubleZeroNumber, initWithDouble:, 0) #undef SINGLETON + +#ifdef OF_OBJFW_RUNTIME +static int numberTag; +#endif + +static bool +isUnsigned(OFNumber *number) +{ + switch (*number.objCType) { + case 'B': + return true; + case 'C': + return true; + case 'S': + return true; + case 'I': + return true; + case 'L': + return true; + case 'Q': + return true; + default: + return false; + } +} + +static bool +isSigned(OFNumber *number) +{ + switch (*number.objCType) { + case 'c': + return true; + case 's': + return true; + case 'i': + return true; + case 'l': + return true; + case 'q': + return true; + default: + return false; + } +} + +static bool +isFloat(OFNumber *number) +{ + switch (*number.objCType) { + case 'f': + return true; + case 'd': + return true; + default: + return false; + } +} @implementation OFNumberPlaceholder - (instancetype)initWithBool: (bool)value { if (value) { @@ -83,16 +160,28 @@ of_once(&once, falseNumberInit); return (id)falseNumber; } } +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif - (instancetype)initWithChar: (signed char)value { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, charZeroNumberInit); return (id)charZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if ((unsigned char)value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned char)value << TAG_BITS) | TAG_CHAR); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithChar: value]; } @@ -100,10 +189,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, shortZeroNumberInit); return (id)shortZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if ((unsigned short)value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned short)value << TAG_BITS) | TAG_SHORT); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithShort: value]; } @@ -111,10 +208,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, intZeroNumberInit); return (id)intZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if ((unsigned int)value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned int)value << TAG_BITS) | TAG_INT); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithInt: value]; } @@ -122,10 +227,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, longZeroNumberInit); return (id)longZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if ((unsigned long)value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned long)value << TAG_BITS) | TAG_LONG); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithLong: value]; } @@ -133,10 +246,19 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, longLongZeroNumberInit); return (id)longLongZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if ((unsigned long long)value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned long long)value << TAG_BITS) | + TAG_LONG_LONG); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithLongLong: value]; } @@ -144,10 +266,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, unsignedCharZeroNumberInit); return (id)unsignedCharZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if (value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_CHAR); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithUnsignedChar: value]; } @@ -155,10 +285,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, unsignedShortZeroNumberInit); return (id)unsignedShortZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if (value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_SHORT); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithUnsignedShort: value]; } @@ -166,10 +304,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, unsignedIntZeroNumberInit); return (id)unsignedIntZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if (value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_INT); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithUnsignedInt: value]; } @@ -177,10 +323,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, unsignedLongZeroNumberInit); return (id)unsignedLongZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if (value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_LONG); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithUnsignedLong: value]; } @@ -188,10 +342,18 @@ { if (value == 0) { static of_once_t once = OF_ONCE_INIT; of_once(&once, unsignedLongLongZeroNumberInit); return (id)unsignedLongLongZeroNumber; +#ifdef OF_OBJFW_RUNTIME + } else if (value <= (UINTPTR_MAX >> TAG_BITS)) { + id ret = objc_createTaggedPointer(numberTag, + ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_LONG_LONG); + + if (ret != nil) + return ret; +#endif } return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: value]; } @@ -219,10 +381,13 @@ - (instancetype)initWithSerialization: (OFXMLElement *)element { return (id)[[OFNumber of_alloc] initWithSerialization: element]; } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif @end @implementation OFNumberSingleton - (instancetype)autorelease { @@ -241,16 +406,100 @@ - (unsigned int)retainCount { return OF_RETAIN_COUNT_MAX; } @end + +#ifdef OF_OBJFW_RUNTIME +@implementation OFTaggedPointerNumber +- (const char *)objCType +{ + uintptr_t value = object_getTaggedPointerValue(self); + + switch (value & TAG_MASK) { + case TAG_CHAR: + return @encode(signed char); + case TAG_SHORT: + return @encode(short); + case TAG_INT: + return @encode(int); + case TAG_LONG: + return @encode(long); + case TAG_LONG_LONG: + return @encode(long long); + case TAG_UNSIGNED_CHAR: + return @encode(unsigned char); + case TAG_UNSIGNED_SHORT: + return @encode(unsigned short); + case TAG_UNSIGNED_INT: + return @encode(unsigned int); + case TAG_UNSIGNED_LONG: + return @encode(unsigned long); + case TAG_UNSIGNED_LONG_LONG: + return @encode(unsigned long long); + default: + @throw [OFInvalidArgumentException exception]; + } +} + +# define RETURN_VALUE \ + uintptr_t value = object_getTaggedPointerValue(self); \ + \ + switch (value & TAG_MASK) { \ + case TAG_CHAR: \ + return (signed char)(unsigned char)(value >> TAG_BITS); \ + case TAG_SHORT: \ + return (short)(unsigned short)(value >> TAG_BITS); \ + case TAG_INT: \ + return (int)(unsigned int)(value >> TAG_BITS); \ + case TAG_LONG: \ + return (long)(unsigned long)(value >> TAG_BITS); \ + case TAG_LONG_LONG: \ + return (long long)(unsigned long long)(value >> TAG_BITS); \ + case TAG_UNSIGNED_CHAR: \ + return (unsigned char)(value >> TAG_BITS); \ + case TAG_UNSIGNED_SHORT: \ + return (unsigned short)(value >> TAG_BITS); \ + case TAG_UNSIGNED_INT: \ + return (unsigned int)(value >> TAG_BITS); \ + case TAG_UNSIGNED_LONG: \ + return (unsigned long)(value >> TAG_BITS); \ + case TAG_UNSIGNED_LONG_LONG: \ + return (unsigned long long)(value >> TAG_BITS); \ + default: \ + @throw [OFInvalidArgumentException exception]; \ + } +- (long long)longLongValue +{ + RETURN_VALUE +} + +- (unsigned long long)unsignedLongLongValue +{ + RETURN_VALUE +} + +- (double)doubleValue +{ + RETURN_VALUE +} +@end +# undef RETURN_VALUE +#endif @implementation OFNumber + (void)initialize { - if (self == [OFNumber class]) - placeholder.isa = [OFNumberPlaceholder class]; + if (self != [OFNumber class]) + return; + + placeholder.isa = [OFNumberPlaceholder class]; + +#ifdef OF_OBJFW_RUNTIME + numberTag = + objc_registerTaggedPointerClass([OFTaggedPointerNumber class]); +#endif } + (instancetype)of_alloc { return [super alloc]; @@ -337,11 +586,10 @@ - (instancetype)initWithBool: (bool)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(bool); return self; } @@ -348,11 +596,10 @@ - (instancetype)initWithChar: (signed char)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(signed char); return self; } @@ -359,11 +606,10 @@ - (instancetype)initWithShort: (short)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(short); return self; } @@ -370,11 +616,10 @@ - (instancetype)initWithInt: (int)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(int); return self; } @@ -381,11 +626,10 @@ - (instancetype)initWithLong: (long)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(long); return self; } @@ -392,11 +636,10 @@ - (instancetype)initWithLongLong: (long long)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(long long); return self; } @@ -403,11 +646,10 @@ - (instancetype)initWithUnsignedChar: (unsigned char)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(unsigned long); return self; } @@ -414,11 +656,10 @@ - (instancetype)initWithUnsignedShort: (unsigned short)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(unsigned short); return self; } @@ -425,11 +666,10 @@ - (instancetype)initWithUnsignedInt: (unsigned int)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(unsigned int); return self; } @@ -436,11 +676,10 @@ - (instancetype)initWithUnsignedLong: (unsigned long)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(unsigned long); return self; } @@ -447,11 +686,10 @@ - (instancetype)initWithUnsignedLongLong: (unsigned long long)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(unsigned long long); return self; } @@ -458,11 +696,10 @@ - (instancetype)initWithPtrDiff: (ptrdiff_t)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(ptrdiff_t); return self; } @@ -469,11 +706,10 @@ - (instancetype)initWithIntPtr: (intptr_t)value { self = [super init]; _value.signed_ = value; - _type = OF_NUMBER_TYPE_SIGNED; _typeEncoding = @encode(intptr_t); return self; } @@ -480,11 +716,10 @@ - (instancetype)initWithUIntPtr: (uintptr_t)value { self = [super init]; _value.unsigned_ = value; - _type = OF_NUMBER_TYPE_UNSIGNED; _typeEncoding = @encode(uintptr_t); return self; } @@ -491,11 +726,10 @@ - (instancetype)initWithFloat: (float)value { self = [super init]; _value.float_ = value; - _type = OF_NUMBER_TYPE_FLOAT; _typeEncoding = @encode(float); return self; } @@ -502,11 +736,10 @@ - (instancetype)initWithDouble: (double)value { self = [super init]; _value.float_ = value; - _type = OF_NUMBER_TYPE_FLOAT; _typeEncoding = @encode(double); return self; } @@ -516,11 +749,11 @@ @try { void *pool = objc_autoreleasePoolPush(); OFString *typeString; - if (![element.name isEqual: self.className] || + if (![element.name isEqual: @"OFNumber"] || ![element.namespace isEqual: OF_SERIALIZATION_NS]) @throw [OFInvalidArgumentException exception]; typeString = [element attributeForName: @"type"].stringValue; @@ -564,116 +797,125 @@ } - (void)getValue: (void *)value size: (size_t)size { - switch (*_typeEncoding) { -#define CASE(enc, type, field) \ + switch (*self.objCType) { +#define CASE(enc, type, property) \ case enc: { \ - type tmp = (type)_value.field; \ + type tmp = (type)self.property; \ \ if (size != sizeof(type)) \ @throw [OFOutOfRangeException exception]; \ \ memcpy(value, &tmp, size); \ break; \ } - CASE('B', bool, unsigned_) - CASE('c', signed char, signed_) - CASE('s', short, signed_) - CASE('i', int, signed_) - CASE('l', long, signed_) - CASE('q', long long, signed_) - CASE('C', unsigned char, unsigned_) - CASE('S', unsigned short, unsigned_) - CASE('I', unsigned int, unsigned_) - CASE('L', unsigned long, unsigned_) - CASE('Q', unsigned long long, unsigned_) - CASE('f', float, float_) - CASE('d', double, float_) + CASE('B', bool, unsignedLongLongValue) + CASE('c', signed char, longLongValue) + CASE('s', short, longLongValue) + CASE('i', int, longLongValue) + CASE('l', long, longLongValue) + CASE('q', long long, longLongValue) + CASE('C', unsigned char, unsignedLongLongValue) + CASE('S', unsigned short, unsignedLongLongValue) + CASE('I', unsigned int, unsignedLongLongValue) + CASE('L', unsigned long, unsignedLongLongValue) + CASE('Q', unsigned long long, unsignedLongLongValue) + CASE('f', float, doubleValue) + CASE('d', double, doubleValue) #undef CASE default: @throw [OFInvalidFormatException exception]; } } -#define RETURN_AS(t) \ - switch (_type) { \ - case OF_NUMBER_TYPE_FLOAT: \ - return (t)_value.float_; \ - case OF_NUMBER_TYPE_SIGNED: \ - return (t)_value.signed_; \ - case OF_NUMBER_TYPE_UNSIGNED: \ - return (t)_value.unsigned_; \ - default: \ - @throw [OFInvalidFormatException exception]; \ - } +- (long long)longLongValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} + +- (unsigned long long)unsignedLongLongValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} + +- (double)doubleValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} + - (bool)boolValue { - RETURN_AS(bool) + return (bool)self.unsignedLongLongValue; } - (signed char)charValue { - RETURN_AS(signed char) + return (signed char)self.longLongValue; } - (short)shortValue { - RETURN_AS(short) + return (short)self.longLongValue; } - (int)intValue { - RETURN_AS(int) + return (int)self.longLongValue; } - (long)longValue { - RETURN_AS(long) -} - -- (long long)longLongValue -{ - RETURN_AS(long long) + return (long)self.longLongValue; } - (unsigned char)unsignedCharValue { - RETURN_AS(unsigned char) + return (unsigned char)self.unsignedLongLongValue; } - (unsigned short)unsignedShortValue { - RETURN_AS(unsigned short) + return (unsigned short)self.unsignedLongLongValue; } - (unsigned int)unsignedIntValue { - RETURN_AS(unsigned int) + return (unsigned int)self.unsignedLongLongValue; } - (unsigned long)unsignedLongValue { - RETURN_AS(unsigned long) -} - -- (unsigned long long)unsignedLongLongValue -{ - RETURN_AS(unsigned long long) + return (unsigned long)self.unsignedLongLongValue; } - (float)floatValue { - RETURN_AS(float) -} - -- (double)doubleValue -{ - RETURN_AS(double) -} -#undef RETURN_AS + return (float)self.doubleValue; +} - (bool)isEqual: (id)object { OFNumber *number; @@ -683,12 +925,11 @@ if (![object isKindOfClass: [OFNumber class]]) return false; number = object; - if (_type == OF_NUMBER_TYPE_FLOAT || - number->_type == OF_NUMBER_TYPE_FLOAT) { + if (isFloat(self) || isFloat(number)) { double value1 = number.doubleValue; double value2 = self.doubleValue; if (isnan(value1) && isnan(value2)) return true; @@ -696,12 +937,11 @@ return false; return (value1 == value2); } - if (_type == OF_NUMBER_TYPE_SIGNED || - number->_type == OF_NUMBER_TYPE_SIGNED) + if (isSigned(self) || isSigned(number)) return (number.longLongValue == self.longLongValue); return (number.unsignedLongLongValue == self.unsignedLongLongValue); } @@ -712,23 +952,21 @@ if (![(id)object isKindOfClass: [OFNumber class]]) @throw [OFInvalidArgumentException exception]; number = (OFNumber *)object; - if (_type == OF_NUMBER_TYPE_FLOAT || - number->_type == OF_NUMBER_TYPE_FLOAT) { + if (isFloat(self) || isFloat(number)) { double double1 = self.doubleValue; double double2 = number.doubleValue; if (double1 > double2) return OF_ORDERED_DESCENDING; if (double1 < double2) return OF_ORDERED_ASCENDING; return OF_ORDERED_SAME; - } else if (_type == OF_NUMBER_TYPE_SIGNED || - number->_type == OF_NUMBER_TYPE_SIGNED) { + } else if (isSigned(self) || isSigned(number)) { long long int1 = self.longLongValue; long long int2 = number.longLongValue; if (int1 > int2) return OF_ORDERED_DESCENDING; @@ -749,27 +987,25 @@ } } - (uint32_t)hash { - enum of_number_type type = _type; uint32_t hash; OF_HASH_INIT(hash); - if (type == OF_NUMBER_TYPE_FLOAT) { + if (isFloat(self)) { double d; if (isnan(self.doubleValue)) return 0; d = OF_BSWAP_DOUBLE_IF_BE(self.doubleValue); for (uint_fast8_t i = 0; i < sizeof(double); i++) OF_HASH_ADD(hash, ((char *)&d)[i]); - } else if (type == OF_NUMBER_TYPE_SIGNED || - type == OF_NUMBER_TYPE_UNSIGNED) { + } else if (isSigned(self) || isUnsigned(self)) { unsigned long long value = self.unsignedLongLongValue; while (value != 0) { OF_HASH_ADD(hash, value & 0xFF); value >>= 8; @@ -792,45 +1028,46 @@ return [self stringValue]; } - (OFString *)stringValue { - if (*_typeEncoding == 'B') - return (_value.unsigned_ ? @"true" : @"false"); - if (_type == OF_NUMBER_TYPE_FLOAT) - return [OFString stringWithFormat: @"%g", _value.float_]; - if (_type == OF_NUMBER_TYPE_SIGNED) - return [OFString stringWithFormat: @"%lld", _value.signed_]; - if (_type == OF_NUMBER_TYPE_UNSIGNED) - return [OFString stringWithFormat: @"%llu", _value.unsigned_]; + if (*self.objCType == 'B') + return (self.boolValue ? @"true" : @"false"); + if (isFloat(self)) + return [OFString stringWithFormat: @"%g", self.doubleValue]; + if (isSigned(self)) + return [OFString stringWithFormat: @"%lld", self.longLongValue]; + if (isUnsigned(self)) + return [OFString stringWithFormat: @"%llu", + self.unsignedLongLongValue]; @throw [OFInvalidFormatException exception]; } - (OFXMLElement *)XMLElementBySerializing { void *pool = objc_autoreleasePoolPush(); OFXMLElement *element; - element = [OFXMLElement elementWithName: self.className + element = [OFXMLElement elementWithName: @"OFNumber" namespace: OF_SERIALIZATION_NS stringValue: self.description]; - if (*_typeEncoding == 'B') + if (*self.objCType == 'B') [element addAttributeWithName: @"type" stringValue: @"bool"]; - else if (_type == OF_NUMBER_TYPE_FLOAT) { + else if (isFloat(self)) { [element addAttributeWithName: @"type" stringValue: @"float"]; element.stringValue = [OFString stringWithFormat: @"%016" PRIx64, OF_BSWAP64_IF_LE(OF_DOUBLE_TO_INT_RAW(OF_BSWAP_DOUBLE_IF_LE( - _value.float_)))]; - } else if (_type == OF_NUMBER_TYPE_SIGNED) + self.doubleValue)))]; + } else if (isSigned(self)) [element addAttributeWithName: @"type" stringValue: @"signed"]; - else if (_type == OF_NUMBER_TYPE_UNSIGNED) + else if (isUnsigned(self)) [element addAttributeWithName: @"type" stringValue: @"unsigned"]; else @throw [OFInvalidFormatException exception]; @@ -856,12 +1093,12 @@ - (OFString *)of_JSONRepresentationWithOptions: (int)options depth: (size_t)depth { double doubleValue; - if (*_typeEncoding == 'B') - return (_value.unsigned_ ? @"true" : @"false"); + if (*self.objCType == 'B') + return (self.boolValue ? @"true" : @"false"); doubleValue = self.doubleValue; if (isinf(doubleValue)) { if (options & OF_JSON_REPRESENTATION_JSON5) { if (doubleValue > 0) @@ -876,37 +1113,38 @@ } - (OFData *)messagePackRepresentation { OFMutableData *data; + const char *typeEncoding = self.objCType; - if (*_typeEncoding == 'B') { - uint8_t type = (_value.unsigned_ ? 0xC3 : 0xC2); + if (*typeEncoding == 'B') { + uint8_t type = (self.boolValue ? 0xC3 : 0xC2); data = [OFMutableData dataWithItems: &type count: 1]; - } else if (*_typeEncoding == 'f') { + } else if (*typeEncoding == 'f') { uint8_t type = 0xCA; - float tmp = OF_BSWAP_FLOAT_IF_LE(_value.float_); + float tmp = OF_BSWAP_FLOAT_IF_LE(self.floatValue); data = [OFMutableData dataWithItemSize: 1 capacity: 5]; [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; - } else if (*_typeEncoding == 'd') { + } else if (*typeEncoding == 'd') { uint8_t type = 0xCB; - double tmp = OF_BSWAP_DOUBLE_IF_LE(_value.float_); + double tmp = OF_BSWAP_DOUBLE_IF_LE(self.doubleValue); data = [OFMutableData dataWithItemSize: 1 capacity: 9]; [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; - } else if (_type == OF_NUMBER_TYPE_SIGNED) { + } else if (isSigned(self)) { long long value = self.longLongValue; if (value >= -32 && value < 0) { uint8_t tmp = 0xE0 | ((uint8_t)(value - 32) & 0x1F); @@ -951,11 +1189,11 @@ [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; } else @throw [OFOutOfRangeException exception]; - } else if (_type == OF_NUMBER_TYPE_UNSIGNED) { + } else if (isUnsigned(self)) { unsigned long long value = self.unsignedLongLongValue; if (value <= 127) { uint8_t tmp = ((uint8_t)value & 0x7F);