/** * Compares two strings using case insensitive natural sort. * * @param s1 First string to compare. * @param s2 Second string to compare. * @param ignore_garbage_at_front Skip punctuation characters in the front * @return Less than zero if s1 < s2, zero if s1 == s2, greater than zero if s1 > s2. */ int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front) { if (ignore_garbage_at_front) { s1 = SkipGarbage(s1); s2 = SkipGarbage(s2); } #ifdef WITH_ICU if (_current_collator != NULL) { UErrorCode status = U_ZERO_ERROR; int result; /* We want to use the new faster method for ICU 4.2 and higher. */ #if U_ICU_VERSION_MAJOR_NUM > 4 || (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM >= 2) /* The StringPiece parameter gets implicitly constructed from the char *. */ result = _current_collator->compareUTF8(s1, s2, status); #else /* The following for 4.0 and lower. */ UChar buffer1[DRAW_STRING_BUFFER]; u_strFromUTF8Lenient(buffer1, lengthof(buffer1), NULL, s1, -1, &status); UChar buffer2[DRAW_STRING_BUFFER]; u_strFromUTF8Lenient(buffer2, lengthof(buffer2), NULL, s2, -1, &status); result = _current_collator->compare(buffer1, buffer2, status); #endif /* ICU version check. */ if (U_SUCCESS(status)) return result; } #endif /* WITH_ICU */ /* Do a normal comparison if ICU is missing or if we cannot create a collator. */ return strcasecmp(s1, s2); }
void fts_icu_utf8_to_utf16(buffer_t *dest_utf16, const char *src_utf8) { UErrorCode err = U_ZERO_ERROR; unsigned int src_bytes = strlen(src_utf8); int32_t utf16_len; UChar *dest_data, *retp = NULL; int32_t avail_uchars = 0; /* try to encode with the current buffer size */ avail_uchars = buffer_get_writable_size(dest_utf16) / sizeof(UChar); dest_data = buffer_get_space_unsafe(dest_utf16, 0, buffer_get_writable_size(dest_utf16)); retp = u_strFromUTF8Lenient(dest_data, avail_uchars, &utf16_len, src_utf8, src_bytes, &err); if (err == U_BUFFER_OVERFLOW_ERROR) { /* try again with a larger buffer */ dest_data = buffer_get_space_unsafe(dest_utf16, 0, utf16_len * sizeof(UChar)); err = U_ZERO_ERROR; retp = u_strFromUTF8Lenient(dest_data, utf16_len, &utf16_len, src_utf8, src_bytes, &err); } if (U_FAILURE(err)) { i_panic("LibICU u_strFromUTF8Lenient() failed: %s", u_errorName(err)); } buffer_set_used_size(dest_utf16, utf16_len * sizeof(UChar)); i_assert(retp == dest_data); }