diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c index 79bcf3abce98..d0ed152934a1 100644 --- a/lib/libc/locale/collate.c +++ b/lib/libc/locale/collate.c @@ -202,7 +202,6 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table) table->large_pri_table = NULL; table->__collate_load_error = 0; - return (_LDP_LOADED); } @@ -226,27 +225,18 @@ substsearch(struct xlocale_collate *table, const wchar_t key, int pass) return (p->pri); } -/* - * Note: for performance reasons, we have expanded bsearch here. This avoids - * function call overhead with each comparison. - */ - static collate_chain_t * chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len) { - int low; - int high; + int low = 0; + int high = table->info->chain_count - 1;; int next, compar, l; collate_chain_t *p; - collate_chain_t *tab; + collate_chain_t *tab = table->chain_pri_table; - if (table->info->chain_count == 0) + if (high < 0) return (NULL); - low = 0; - high = table->info->chain_count - 1; - tab = table->chain_pri_table; - while (low <= high) { next = (low + high) / 2; p = tab + next; @@ -276,7 +266,7 @@ largesearch(struct xlocale_collate *table, const wchar_t key) collate_large_t *p; collate_large_t *tab = table->large_pri_table; - if (table->info->large_count == 0) + if (high < 0) return (NULL); while (low <= high) { @@ -320,7 +310,10 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, if ((sptr = *state) != NULL) { *pri = *sptr; sptr++; - *state = *sptr ? sptr : NULL; + if ((sptr == *state) || (sptr == NULL)) + *state = NULL; + else + *state = sptr; *len = 0; return; } @@ -381,7 +374,7 @@ _collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len, * code ensures this for us. */ if ((sptr = substsearch(table, *pri, which)) != NULL) { - if ((*pri = *sptr) != 0) { + if ((*pri = *sptr) > 0) { sptr++; *state = *sptr ? sptr : NULL; } diff --git a/lib/libc/string/wcscoll.c b/lib/libc/string/wcscoll.c index acb127787b3a..ee0e72a4d364 100644 --- a/lib/libc/string/wcscoll.c +++ b/lib/libc/string/wcscoll.c @@ -77,6 +77,7 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) const int32_t *st2 = NULL; const wchar_t *w1 = ws1; const wchar_t *w2 = ws2; + int check1, check2; /* special pass for UNDEFINED */ if (pass == table->info->directive_count) { @@ -110,25 +111,36 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) } if (direc & DIRECTIVE_POSITION) { - while ((*w1 || st1) && (*w2 || st2)) { + while (*w1 && *w2) { pri1 = pri2 = 0; - _collate_lookup(table, w1, &len1, &pri1, pass, - &st1); - if (pri1 <= 0) { - if (pri1 < 0) { - errno = EINVAL; - goto fail; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + if (check1) { + _collate_lookup(table, w1, &len1, + &pri1, pass, &st1); + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri1) { + pri1 = COLLATE_MAX_PRIORITY; + st1 = NULL; + } + check1 = (st1 != NULL); } - pri1 = COLLATE_MAX_PRIORITY; - } - _collate_lookup(table, w2, &len2, &pri2, pass, - &st2); - if (pri2 <= 0) { - if (pri2 < 0) { - errno = EINVAL; - goto fail; + if (check2) { + _collate_lookup(table, w2, &len2, + &pri2, pass, &st2); + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + if (!pri2) { + pri2 = COLLATE_MAX_PRIORITY; + st2 = NULL; + } + check2 = (st2 != NULL); } - pri2 = COLLATE_MAX_PRIORITY; } if (pri1 != pri2) { ret = pri1 - pri2; @@ -138,29 +150,38 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) w2 += len2; } } else { - while ((*w1 || st1) && (*w2 || st2)) { + while (*w1 && *w2) { pri1 = pri2 = 0; - while (*w1) { - _collate_lookup(table, w1, &len1, - &pri1, pass, &st1); - if (pri1 > 0) - break; - if (pri1 < 0) { - errno = EINVAL; - goto fail; + check1 = check2 = 1; + while ((pri1 == pri2) && (check1 || check2)) { + while (check1 && *w1) { + _collate_lookup(table, w1, + &len1, &pri1, pass, &st1); + if (pri1 > 0) + break; + if (pri1 < 0) { + errno = EINVAL; + goto fail; + } + st1 = NULL; + w1 += 1; } - w1 += len1; - } - while (*w2) { - _collate_lookup(table, w2, &len2, - &pri2, pass, &st2); - if (pri2 > 0) - break; - if (pri2 < 0) { - errno = EINVAL; - goto fail; + check1 = (st1 != NULL); + while (check2 && *w2) { + _collate_lookup(table, w2, + &len2, &pri2, pass, &st2); + if (pri2 > 0) + break; + if (pri2 < 0) { + errno = EINVAL; + goto fail; + } + st2 = NULL; + w2 += 1; } - w2 += len2; + check2 = (st2 != NULL); + if (!pri1 || !pri2) + break; } if (!pri1 || !pri2) break; @@ -185,10 +206,8 @@ wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) ret = 0; end: - if (tr1) - free(tr1); - if (tr2) - free(tr2); + free(tr1); + free(tr2); return (ret);