Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -366,13 +366,13 @@ uint32_t hash; union { double d; uint8_t b[sizeof(double)]; } d; - uint8_t i; + uint_fast8_t i; - d.d = OF_BSWAP_DOUBLE_IF_LE(seconds); + d.d = OF_BSWAP_DOUBLE_IF_BE(seconds); OF_HASH_INIT(hash); for (i = 0; i < sizeof(double); i++) OF_HASH_ADD(hash, d.b[i]); Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -1038,49 +1038,66 @@ } } - (uint32_t)hash { + of_number_type_t type_ = type; uint32_t hash; - uint8_t i; - - switch (type) { - case OF_NUMBER_FLOAT:; - union { - float f; - uint8_t b[sizeof(float)]; - } f; - - f.f = OF_BSWAP_FLOAT_IF_LE(value.float_); - - OF_HASH_INIT(hash); - - for (i = 0; i < sizeof(float); i++) - OF_HASH_ADD(hash, f.b[i]); - - OF_HASH_FINALIZE(hash); - - return hash; - case OF_NUMBER_DOUBLE:; + + /* Do we really need signed to represent this number? */ + if (type_ & OF_NUMBER_SIGNED && [self intMaxValue] >= 0) + type_ &= ~OF_NUMBER_SIGNED; + + /* Do we really need floating point to represent this number? */ + if (type_ & OF_NUMBER_FLOAT) { + double v = [self doubleValue]; + + if (v < 0) { + if (v == [self intMaxValue]) { + type_ &= ~OF_NUMBER_FLOAT; + type_ |= OF_NUMBER_SIGNED; + } + } else { + if (v == [self uIntMaxValue]) + type_ &= ~OF_NUMBER_FLOAT; + } + } + + OF_HASH_INIT(hash); + + if (type_ & OF_NUMBER_FLOAT) { union { double d; uint8_t b[sizeof(double)]; } d; - - d.d = OF_BSWAP_DOUBLE_IF_LE(value.double_); + uint_fast8_t i; - OF_HASH_INIT(hash); + d.d = OF_BSWAP_DOUBLE_IF_BE([self doubleValue]); for (i = 0; i < sizeof(double); i++) OF_HASH_ADD(hash, d.b[i]); + } else if (type_ & OF_NUMBER_SIGNED) { + intmax_t v = [self intMaxValue] * -1; + + while (v != 0) { + OF_HASH_ADD(hash, v & 0xFF); + v >>= 8; + } - OF_HASH_FINALIZE(hash); + OF_HASH_ADD(hash, 1); + } else { + uintmax_t v = [self uIntMaxValue]; - return hash; - default: - return [self uInt32Value]; + while (v != 0) { + OF_HASH_ADD(hash, v & 0xFF); + v >>= 8; + } } + + OF_HASH_FINALIZE(hash); + + return hash; } - (OFNumber*)numberByAddingNumber: (OFNumber*)num { CALCULATE(+, num) Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -842,16 +842,30 @@ } - (uint32_t)hash { /* Classes containing data should reimplement this! */ - return (uint32_t)(uintptr_t)self; + + uintptr_t ptr = (uintptr_t)self; + uint32_t hash; + + OF_HASH_INIT(hash); + + while (ptr != 0) { + OF_HASH_ADD(hash, ptr & 0xFF); + ptr <<= 8; + } + + OF_HASH_FINALIZE(hash); + + return hash; } - (OFString*)description { /* Classes containing data should reimplement this! */ + return [OFString stringWithFormat: @"<%@: %p>", [self className], self]; } - (void*)allocMemoryWithSize: (size_t)size { Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -325,15 +325,15 @@ #define OF_ROL(value, bits) \ (((value) << ((bits) % (sizeof(value) * 8))) | \ (value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) #define OF_HASH_INIT(hash) hash = of_hash_seed -#define OF_HASH_ADD(hash, byte) \ - { \ - hash += (uint8_t)byte; \ - hash += (hash << 10); \ - hash ^= (hash >> 6); \ +#define OF_HASH_ADD(hash, byte) \ + { \ + hash += (uint8_t)(byte); \ + hash += (hash << 10); \ + hash ^= (hash >> 6); \ } #define OF_HASH_FINALIZE(hash) \ { \ hash += (hash << 3); \ hash ^= (hash >> 11); \ Index: tests/OFNumberTests.m ================================================================== --- tests/OFNumberTests.m +++ tests/OFNumberTests.m @@ -34,13 +34,13 @@ (num = [OFNumber numberWithIntMax: 123456789])) TEST(@"-[isEqual:]", [num isEqual: [OFNumber numberWithUInt32: 123456789]]) - TEST(@"-[hash]", [num hash] == 123456789) + TEST(@"-[hash]", [num hash] == 0x82D8BC42) - TEST(@"-[asDouble]", [num doubleValue] == 123456789.L) + TEST(@"-[doubleValue]", [num doubleValue] == 123456789.L) TEST(@"-[numberByDecreasing]", [[num numberByDecreasing] isEqual: [OFNumber numberWithInt32: 123456788]]) Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -118,11 +118,11 @@ R([s[1] appendUTF8String: "1๐„ž"]) && R([s[1] appendString: @"3"]) && R([s[0] appendString: s[1]]) && [s[0] isEqual: @"tรคsโ‚ฌ1๐„ž3"]) TEST(@"-[length]", [s[0] length] == 7) TEST(@"-[UTF8StringLength]", [s[0] UTF8StringLength] == 13) - TEST(@"-[hash]", [s[0] hash] == 0x2E623BD1) + TEST(@"-[hash]", [s[0] hash] == 0x705583C0) TEST(@"-[characterAtIndex:]", [s[0] characterAtIndex: 0] == 't' && [s[0] characterAtIndex: 1] == 0xE4 && [s[0] characterAtIndex: 3] == 0x20AC && [s[0] characterAtIndex: 5] == 0x1D11E) Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ tests/serialization.xml @@ -1,34 +1,15 @@ - - Qu"xbar -test - 1234 - 40934a456d5cfaad - asd - 40934a456d5cfaad - - - - Hello - - Blub B"la - MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla - - - data - - Hello Wo ld! How are you? https://webkeks.org/ @@ -55,7 +36,26 @@ list + + MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla + + + data + + + + Qu"xbar +test + 1234 + 40934a456d5cfaad + asd + 40934a456d5cfaad + + + + Hello +