@@ -14,10 +14,11 @@ #define _GNU_SOURCE #include #include #include #include +#include #include #ifdef HAVE_MADVISE # include #else @@ -34,10 +35,25 @@ #import "asprintf.h" #import "unicode.h" extern const uint16_t of_iso_8859_15[256]; extern const uint16_t of_windows_1252[256]; + +static inline int +memcasecmp(const char *s1, const char *s2, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (tolower(s1[i]) > tolower(s2[i])) + return OF_ORDERED_DESCENDING; + if (tolower(s1[i]) < tolower(s2[i])) + return OF_ORDERED_ASCENDING; + } + + return OF_ORDERED_SAME; +} /* References for static linking */ void _references_to_categories_of_OFString() { _OFString_Hashing_reference = 1; @@ -700,10 +716,15 @@ - (size_t)cStringLength { return length; } + +- (BOOL)isUTF8 +{ + return isUTF8; +} - (BOOL)isEqual: (OFObject*)obj { if (![obj isKindOfClass: [OFString class]]) return NO; @@ -723,12 +744,12 @@ return [[OFMutableString alloc] initWithString: self]; } - (of_comparison_result_t)compare: (OFString*)str { - int cmp; size_t str_len, min_len; + int cmp; if (![str isKindOfClass: [OFString class]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; @@ -750,18 +771,36 @@ } - (of_comparison_result_t)caseInsensitiveCompare: (OFString*)str { const char *str_cstr; - size_t i, j, str_len; + size_t i, j, str_len, min_len; + int cmp; if (![str isKindOfClass: [OFString class]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; str_cstr = [str cString]; str_len = [str cStringLength]; + + if (![self isUTF8]) { + min_len = (length > str_len ? str_len : length); + + if ((cmp = memcasecmp(string, [str cString], min_len)) == 0) { + if (length > str_len) + return OF_ORDERED_DESCENDING; + if (length < str_len) + return OF_ORDERED_ASCENDING; + return OF_ORDERED_SAME; + } + + if (cmp > 0) + return OF_ORDERED_DESCENDING; + else + return OF_ORDERED_ASCENDING; + } i = j = 0; while (i < length && j < str_len) { of_unichar_t c1, c2; @@ -820,10 +859,17 @@ } - (of_unichar_t)characterAtIndex: (size_t)index { of_unichar_t c; + + if (![self isUTF8]) { + if (index >= length) + @throw [OFOutOfRangeException newWithClass: isa]; + + return string[index]; + } index = of_string_index_to_position(string, index, length); if (index >= length) @throw [OFOutOfRangeException newWithClass: isa]; @@ -876,12 +922,14 @@ } - (OFString*)substringFromIndex: (size_t)start toIndex: (size_t)end { - start = of_string_index_to_position(string, start, length); - end = of_string_index_to_position(string, end, length); + if ([self isUTF8]) { + start = of_string_index_to_position(string, start, length); + end = of_string_index_to_position(string, end, length); + } if (start > end) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd];