2 * Copyright 2013 Garrett D'Amore <garrett@damore.org>
3 * Copyright 2017 Nexenta Systems, Inc.
4 * Copyright (c) 2002 Tim J. Robbins
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "localeimpl.h"
39 wcscoll_l(const wchar_t *ws1
, const wchar_t *ws2
, locale_t loc
)
41 int len1
, len2
, pri1
, pri2
;
42 wchar_t *tr1
= NULL
, *tr2
= NULL
;
44 const struct lc_collate
*lcc
= loc
->collate
;
45 int ret
= wcscmp(ws1
, ws2
);
47 if (lcc
->lc_is_posix
|| ret
== 0)
50 if (*ws1
== 0 && *ws2
!= 0)
52 if (*ws1
!= 0 && *ws2
== 0)
56 * Once upon a time we had code to try to optimize this, but
57 * it turns out that you really can't make many assumptions
58 * safely. You absolutely have to run this pass by pass,
59 * because some passes will be ignored for a given character,
60 * while others will not. Simpler locales will benefit from
61 * having fewer passes, and most comparisions should resolve
62 * during the primary pass anyway.
64 * Note that we do one final extra pass at the end to pick
65 * up UNDEFINED elements. There is special handling for them.
67 for (pass
= 0; pass
<= lcc
->lc_directive_count
; pass
++) {
68 const int32_t *st1
= NULL
;
69 const int32_t *st2
= NULL
;
70 const wchar_t *w1
= ws1
;
71 const wchar_t *w2
= ws2
;
73 /* special pass for UNDEFINED */
74 if (pass
== lcc
->lc_directive_count
) {
75 direc
= DIRECTIVE_FORWARD
;
77 direc
= lcc
->lc_directive
[pass
];
80 if (direc
& DIRECTIVE_BACKWARD
) {
83 if ((tr1
= wcsdup(w1
)) == NULL
)
86 fp
= tr1
+ wcslen(tr1
) - 1;
93 if ((tr2
= wcsdup(w2
)) == NULL
)
96 fp
= tr2
+ wcslen(tr2
) - 1;
106 if (direc
& DIRECTIVE_POSITION
) {
111 while ((pri1
== pri2
) && (check1
|| check2
)) {
113 _collate_lookup(lcc
, w1
, &len1
,
121 pri1
= COLLATE_MAX_PRIORITY
;
124 check1
= (st1
!= NULL
);
127 _collate_lookup(lcc
, w2
, &len2
,
135 pri2
= COLLATE_MAX_PRIORITY
;
138 check2
= (st2
!= NULL
);
158 int vpri1
= 0, vpri2
= 0;
159 while (*w1
|| *w2
|| st1
|| st2
) {
162 _collate_lookup(lcc
, w1
, &len1
, &pri1
,
177 _collate_lookup(lcc
, w2
, &len2
, &pri2
,
190 if ((!pri1
|| !pri2
) && (vpri1
== vpri2
))
197 if (vpri1
&& !vpri2
) {
201 if (!vpri1
&& vpri2
) {
217 wcscoll(const wchar_t *ws1
, const wchar_t *ws2
)
219 return (wcscoll_l(ws1
, ws2
, uselocale(NULL
)));