]> git.saurik.com Git - apple/libc.git/blame - string/FreeBSD/wcscoll.c.patch
Libc-594.9.5.tar.gz
[apple/libc.git] / string / FreeBSD / wcscoll.c.patch
CommitLineData
3d9156a7 1--- wcscoll.c.orig 2004-11-25 11:38:47.000000000 -0800
224c7076
A
2+++ wcscoll.c 2005-04-11 15:44:35.000000000 -0700
3@@ -27,72 +27,222 @@
3d9156a7
A
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD: src/lib/libc/string/wcscoll.c,v 1.3 2004/04/07 09:47:56 tjr Exp $");
6
7+#include "xlocale_private.h"
8+
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <wchar.h>
13 #include "collate.h"
14
15-static char *__mbsdup(const wchar_t *);
224c7076 16+#define NOTFORWARD (DIRECTIVE_BACKWARD | DIRECTIVE_POSITION)
3d9156a7 17
224c7076
A
18-/*
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.
22- */
3d9156a7
A
23 int
24-wcscoll(const wchar_t *ws1, const wchar_t *ws2)
25+wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t loc)
26 {
224c7076
A
27- char *mbs1, *mbs2;
28- int diff, sverrno;
29+ int sverrno;
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;
34+ wchar_t w, w2;
35+ struct __collate_st_info *info;
3d9156a7
A
36
37- if (__collate_load_error || MB_CUR_MAX > 1)
38+ NORMALIZE_LOCALE(loc);
224c7076 39+ if (loc->__collate_load_error)
3d9156a7 40 /*
224c7076
A
41- * Locale has no special collating order, could not be
42- * loaded, or has an extended character set; do a fast binary
43- * comparison.
44+ * Locale has no special collating order or could not be
45+ * loaded, do a fast binary comparison.
3d9156a7
A
46 */
47 return (wcscmp(ws1, ws2));
48
49- if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
224c7076
A
50- /*
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
54- * incorrect result.
55- */
56- sverrno = errno;
57- free(mbs1);
58- errno = sverrno;
59- return (wcscmp(ws1, ws2));
60+ info = &loc->__lc_collate->__info;
61+ len = len2 = 1;
62+ ret = ret2 = 0;
63+
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))) {
68+ int direc, pass;
69+ for(pass = 0; pass < info->directive_count; pass++) {
70+ direc = info->directive[pass];
71+ if (pass == 0 || !(info->flags & COLLATE_SUBST_DUP)) {
72+ free(tt);
73+ tt = __collate_substitute(ws1, pass, loc);
74+ free(tt2);
75+ tt2 = tt ? __collate_substitute(ws2, pass, loc) : NULL;
76+ }
77+ if (direc & DIRECTIVE_BACKWARD) {
78+ wchar_t *bp, *fp, c;
79+ tr = __collate_wcsdup(tt ? tt : ws1);
80+ bp = tr;
81+ fp = tr + wcslen(tr) - 1;
82+ while(bp < fp) {
83+ c = *bp;
84+ *bp++ = *fp;
85+ *fp-- = c;
86+ }
87+ tr2 = __collate_wcsdup(tt2 ? tt2 : ws2);
88+ bp = tr2;
89+ fp = tr2 + wcslen(tr2) - 1;
90+ while(bp < fp) {
91+ c = *bp;
92+ *bp++ = *fp;
93+ *fp-- = c;
94+ }
95+ t = (const wchar_t *)tr;
96+ t2 = (const wchar_t *)tr2;
97+ } else if (tt) {
98+ t = (const wchar_t *)tt;
99+ t2 = (const wchar_t *)tt2;
100+ } else {
101+ t = (const wchar_t *)ws1;
102+ t2 = (const wchar_t *)ws2;
103+ }
104+ if(direc & DIRECTIVE_POSITION) {
105+ while(*t && *t2) {
106+ prim = prim2 = 0;
107+ __collate_lookup_which(t, &len, &prim, pass, loc);
108+ if (prim <= 0) {
109+ if (prim < 0) {
110+ errno = EINVAL;
111+ ret = -1;
112+ goto end;
113+ }
114+ prim = COLLATE_MAX_PRIORITY;
115+ }
116+ __collate_lookup_which(t2, &len2, &prim2, pass, loc);
117+ if (prim2 <= 0) {
118+ if (prim2 < 0) {
119+ errno = EINVAL;
120+ ret = -1;
121+ goto end;
122+ }
123+ prim2 = COLLATE_MAX_PRIORITY;
124+ }
125+ if(prim != prim2) {
126+ ret = prim - prim2;
127+ goto end;
128+ }
129+ t += len;
130+ t2 += len2;
131+ }
132+ } else {
133+ while(*t && *t2) {
134+ prim = prim2 = 0;
135+ while(*t) {
136+ __collate_lookup_which(t, &len, &prim, pass, loc);
137+ if(prim > 0)
138+ break;
139+ if (prim < 0) {
140+ errno = EINVAL;
141+ ret = -1;
142+ goto end;
143+ }
144+ t += len;
145+ }
146+ while(*t2) {
147+ __collate_lookup_which(t2, &len2, &prim2, pass, loc);
148+ if(prim2 > 0)
149+ break;
150+ if (prim2 < 0) {
151+ errno = EINVAL;
152+ ret = -1;
153+ goto end;
154+ }
155+ t2 += len2;
156+ }
157+ if(!prim || !prim2)
158+ break;
159+ if(prim != prim2) {
160+ ret = prim - prim2;
161+ goto end;
162+ }
163+ t += len;
164+ t2 += len2;
165+ }
166+ }
167+ if(!*t) {
168+ if(*t2) {
169+ ret = -(int)*t2;
170+ goto end;
171+ }
172+ } else {
173+ ret = *t;
174+ goto end;
175+ }
176+ }
177+ ret = 0;
178+ goto end;
3d9156a7
A
179 }
180
181- diff = strcoll(mbs1, mbs2);
224c7076
A
182+ /* optimized common case: order_start forward;forward and duplicate
183+ * (or no) substitute tables */
184+ tt = __collate_substitute(ws1, 0, loc);
185+ if (tt == NULL) {
186+ tt2 = NULL;
187+ t = (const wchar_t *)ws1;
188+ t2 = (const wchar_t *)ws2;
189+ } else {
190+ tt2 = __collate_substitute(ws2, 0, loc);
191+ t = (const wchar_t *)tt;
192+ t2 = (const wchar_t *)tt2;
193+ }
194+ while(*t && *t2) {
195+ prim = prim2 = 0;
196+ while(*t) {
197+ __collate_lookup_l(t, &len, &prim, &sec, loc);
198+ if (prim > 0)
199+ break;
200+ if (prim < 0) {
201+ errno = EINVAL;
202+ ret = -1;
203+ goto end;
204+ }
205+ t += len;
206+ }
207+ while(*t2) {
208+ __collate_lookup_l(t2, &len2, &prim2, &sec2, loc);
209+ if (prim2 > 0)
210+ break;
211+ if (prim2 < 0) {
212+ errno = EINVAL;
213+ ret = -1;
214+ goto end;
215+ }
216+ t2 += len2;
217+ }
218+ if(!prim || !prim2)
219+ break;
220+ if(prim != prim2) {
221+ ret = prim - prim2;
222+ goto end;
223+ }
224+ if(!ret2)
225+ ret2 = sec - sec2;
226+ t += len;
227+ t2 += len2;
228+ }
229+ if(!*t && *t2)
230+ ret = -(int)*t2;
231+ else if(*t && !*t2)
232+ ret = *t;
233+ else if(!*t && !*t2)
234+ ret = ret2;
235+ end:
3d9156a7 236 sverrno = errno;
224c7076
A
237- free(mbs1);
238- free(mbs2);
239+ free(tt);
240+ free(tt2);
241+ free(tr);
242+ free(tr2);
243 errno = sverrno;
244
245- return (diff);
246+ return ret;
3d9156a7
A
247 }
248
224c7076
A
249-static char *
250-__mbsdup(const wchar_t *ws)
3d9156a7
A
251+int
252+wcscoll(const wchar_t *ws1, const wchar_t *ws2)
3d9156a7 253 {
224c7076
A
254- static const mbstate_t initial;
255- mbstate_t st;
256- const wchar_t *wcp;
257- size_t len;
258- char *mbs;
259-
260- wcp = ws;
261- st = initial;
3d9156a7 262- if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
224c7076
A
263- return (NULL);
264- if ((mbs = malloc(len + 1)) == NULL)
265- return (NULL);
266- st = initial;
3d9156a7 267- wcsrtombs(mbs, &ws, len + 1, &st);
224c7076
A
268-
269- return (mbs);
270+ return wcscoll_l(ws1, ws2, __current_locale());
3d9156a7 271 }