Index: src/OFMutableString_UTF8.m ================================================================== --- src/OFMutableString_UTF8.m +++ src/OFMutableString_UTF8.m @@ -56,10 +56,12 @@ if (!s->UTF8) { assert(tableSize >= 1); uint8_t *p = (uint8_t*)s->cString + s->cStringLength; uint8_t t; + + s->hashed = NO; while (--p >= (uint8_t*)s->cString) if ((t = table[0][*p]) != 0) *p = t; @@ -131,10 +133,11 @@ assert(j == newCStringLength); newCString[j] = 0; [self freeMemory: unicodeString]; [self freeMemory: s->cString]; + s->hashed = NO; s->cString = newCString; s->cStringLength = newCStringLength; /* * Even though cStringLength can change, length cannot, therefore no @@ -152,10 +155,11 @@ if (s->UTF8) index = of_string_index_to_position(s->cString, index, s->cStringLength); if (!(character & 0x80) && !(s->cString[index] & 0x80)) { + s->hashed = NO; s->cString[index] = character; return; } if ((length = of_string_unicode_to_utf8(character, buffer)) == 0) @@ -162,10 +166,12 @@ @throw [OFInvalidEncodingException exceptionWithClass: isa]; if ((oldLength = of_string_utf8_to_unicode(s->cString + index, s->cStringLength - index, &c)) == 0) @throw [OFInvalidEncodingException exceptionWithClass: isa]; + + s->hashed = NO; if (length == oldLength) { memcpy(s->cString + index, buffer, length); return; } @@ -229,10 +235,11 @@ break; case -1: @throw [OFInvalidEncodingException exceptionWithClass: isa]; } + s->hashed = NO; s->cString = [self resizeMemory: s->cString toSize: s->cStringLength + UTF8StringLength + 1]; memcpy(s->cString + s->cStringLength, UTF8String, UTF8StringLength + 1); @@ -256,10 +263,11 @@ break; case -1: @throw [OFInvalidEncodingException exceptionWithClass: isa]; } + s->hashed = NO; s->cString = [self resizeMemory: s->cString toSize: s->cStringLength + UTF8StringLength + 1]; memcpy(s->cString + s->cStringLength, UTF8String, UTF8StringLength); @@ -302,10 +310,11 @@ @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; UTF8StringLength = [string UTF8StringLength]; + s->hashed = NO; s->cString = [self resizeMemory: s->cString toSize: s->cStringLength + UTF8StringLength + 1]; memcpy(s->cString + s->cStringLength, [string UTF8String], UTF8StringLength); @@ -346,10 +355,12 @@ } - (void)reverse { size_t i, j; + + s->hashed = NO; /* We reverse all bytes and restore UTF-8 later, if necessary */ for (i = 0, j = s->cStringLength - 1; i < s->cStringLength / 2; i++, j--) { s->cString[i] ^= s->cString[j]; @@ -438,10 +449,11 @@ if (s->UTF8) index = of_string_index_to_position(s->cString, index, s->cStringLength); newCStringLength = s->cStringLength + [string UTF8StringLength]; + s->hashed = NO; s->cString = [self resizeMemory: s->cString toSize: newCStringLength + 1]; memmove(s->cString + index + [string UTF8StringLength], s->cString + index, s->cStringLength - index); @@ -470,10 +482,11 @@ selector: _cmd]; if (end > s->length) @throw [OFOutOfRangeException exceptionWithClass: isa]; + s->hashed = NO; s->length -= end - start; if (s->UTF8) { start = of_string_index_to_position(s->cString, start, s->cStringLength); @@ -516,10 +529,11 @@ s->cStringLength); } newCStringLength = s->cStringLength - (end - start) + [replacement UTF8StringLength]; + s->hashed = NO; s->cString = [self resizeMemory: s->cString toSize: newCStringLength + 1]; memmove(s->cString + end, s->cString + start + [replacement UTF8StringLength], s->cStringLength - end); @@ -586,10 +600,11 @@ s->cStringLength - last); newCStringLength += s->cStringLength - last; newCString[newCStringLength] = 0; [self freeMemory: s->cString]; + s->hashed = NO; s->cString = newCString; s->cStringLength = newCStringLength; s->length = newLength; } @@ -601,10 +616,11 @@ if (s->cString[i] != ' ' && s->cString[i] != '\t' && s->cString[i] != '\n' && s->cString[i] != '\r' && s->cString[i] != '\f') break; + s->hashed = NO; s->cStringLength -= i; s->length -= i; memmove(s->cString, s->cString + i, s->cStringLength); s->cString[s->cStringLength] = '\0'; @@ -619,10 +635,12 @@ - (void)deleteTrailingWhitespaces { size_t d; char *p; + + s->hashed = NO; d = 0; for (p = s->cString + s->cStringLength - 1; p >= s->cString; p--) { if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' && *p != '\f') @@ -645,10 +663,12 @@ - (void)deleteEnclosingWhitespaces { size_t d, i; char *p; + + s->hashed = NO; d = 0; for (p = s->cString + s->cStringLength - 1; p >= s->cString; p--) { if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' && *p != '\f') Index: src/OFString_UTF8.h ================================================================== --- src/OFString_UTF8.h +++ src/OFString_UTF8.h @@ -18,12 +18,14 @@ @interface OFString_UTF8: OFString { @public struct of_string_utf8_ivars { - char *cString; - size_t cStringLength; - BOOL UTF8; - size_t length; + char *cString; + size_t cStringLength; + BOOL UTF8; + size_t length; + BOOL hashed; + uint32_t hash; } *restrict s; } @end Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -727,10 +727,13 @@ - (uint32_t)hash { size_t i; uint32_t hash; + if (s->hashed) + return s->hash; + OF_HASH_INIT(hash); for (i = 0; i < s->cStringLength; i++) { of_unichar_t c; size_t length; @@ -747,10 +750,13 @@ i += length - 1; } OF_HASH_FINALIZE(hash); + s->hash = hash; + s->hashed = YES; + return hash; } - (of_unichar_t)characterAtIndex: (size_t)index {