1 --- wcscoll.c.orig 2004-11-25 11:38:47.000000000 -0800
2 +++ wcscoll.c 2005-04-11 15:44:35.000000000 -0700
5 __FBSDID("$FreeBSD: src/lib/libc/string/wcscoll.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
7 +#include "xlocale_private.h"
15 -static char *__mbsdup(const wchar_t *);
16 +#define NOTFORWARD (DIRECTIVE_BACKWARD | DIRECTIVE_POSITION)
19 - * Placeholder implementation of wcscoll(). Attempts to use the single-byte
20 - * collation ordering where possible, and falls back on wcscmp() in locales
21 - * with extended character sets.
24 -wcscoll(const wchar_t *ws1, const wchar_t *ws2)
25 +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc)
30 + int len, len2, prim, prim2, sec, sec2, ret, ret2;
31 + const wchar_t *t, *t2;
32 + wchar_t *tt = NULL, *tt2 = NULL;
33 + wchar_t *tr = NULL, *tr2 = NULL;
35 + struct __collate_st_info *info;
37 - if (__collate_load_error || MB_CUR_MAX > 1)
38 + NORMALIZE_LOCALE(loc);
39 + if (loc->__collate_load_error)
41 - * Locale has no special collating order, could not be
42 - * loaded, or has an extended character set; do a fast binary
44 + * Locale has no special collating order or could not be
45 + * loaded, do a fast binary comparison.
47 return (wcscmp(ws1, ws2));
49 - if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
51 - * Out of memory or illegal wide chars; fall back to wcscmp()
52 - * but leave errno indicating the error. Callers that don't
53 - * check for error will get a reasonable but often slightly
59 - return (wcscmp(ws1, ws2));
60 + info = &loc->__lc_collate->__info;
64 + if ((info->directive[0] & NOTFORWARD) ||
65 + (info->directive[1] & NOTFORWARD) ||
66 + (!(info->flags && COLLATE_SUBST_DUP) &&
67 + (info->subst_count[0] > 0 || info->subst_count[1] > 0))) {
69 + for(pass = 0; pass < info->directive_count; pass++) {
70 + direc = info->directive[pass];
71 + if (pass == 0 || !(info->flags & COLLATE_SUBST_DUP)) {
73 + tt = __collate_substitute(ws1, pass, loc);
75 + tt2 = tt ? __collate_substitute(ws2, pass, loc) : NULL;
77 + if (direc & DIRECTIVE_BACKWARD) {
78 + wchar_t *bp, *fp, c;
79 + tr = __collate_wcsdup(tt ? tt : ws1);
81 + fp = tr + wcslen(tr) - 1;
87 + tr2 = __collate_wcsdup(tt2 ? tt2 : ws2);
89 + fp = tr2 + wcslen(tr2) - 1;
95 + t = (const wchar_t *)tr;
96 + t2 = (const wchar_t *)tr2;
98 + t = (const wchar_t *)tt;
99 + t2 = (const wchar_t *)tt2;
101 + t = (const wchar_t *)ws1;
102 + t2 = (const wchar_t *)ws2;
104 + if(direc & DIRECTIVE_POSITION) {
107 + __collate_lookup_which(t, &len, &prim, pass, loc);
114 + prim = COLLATE_MAX_PRIORITY;
116 + __collate_lookup_which(t2, &len2, &prim2, pass, loc);
123 + prim2 = COLLATE_MAX_PRIORITY;
125 + if(prim != prim2) {
126 + ret = prim - prim2;
136 + __collate_lookup_which(t, &len, &prim, pass, loc);
147 + __collate_lookup_which(t2, &len2, &prim2, pass, loc);
157 + if(!prim || !prim2)
159 + if(prim != prim2) {
160 + ret = prim - prim2;
181 - diff = strcoll(mbs1, mbs2);
182 + /* optimized common case: order_start forward;forward and duplicate
183 + * (or no) substitute tables */
184 + tt = __collate_substitute(ws1, 0, loc);
187 + t = (const wchar_t *)ws1;
188 + t2 = (const wchar_t *)ws2;
190 + tt2 = __collate_substitute(ws2, 0, loc);
191 + t = (const wchar_t *)tt;
192 + t2 = (const wchar_t *)tt2;
197 + __collate_lookup_l(t, &len, &prim, &sec, loc);
208 + __collate_lookup_l(t2, &len2, &prim2, &sec2, loc);
218 + if(!prim || !prim2)
220 + if(prim != prim2) {
221 + ret = prim - prim2;
231 + else if(*t && !*t2)
233 + else if(!*t && !*t2)
250 -__mbsdup(const wchar_t *ws)
252 +wcscoll(const wchar_t *ws1, const wchar_t *ws2)
254 - static const mbstate_t initial;
256 - const wchar_t *wcp;
262 - if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
264 - if ((mbs = malloc(len + 1)) == NULL)
267 - wcsrtombs(mbs, &ws, len + 1, &st);
270 + return wcscoll_l(ws1, ws2, __current_locale());