]> git.ipfire.org Git - thirdparty/glibc.git/blame - string/strcoll.c
Update.
[thirdparty/glibc.git] / string / strcoll.c
CommitLineData
4b10dd6c 1/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
c84142e8
UD
2 This file is part of the GNU C Library.
3 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
28f540f4 4
c84142e8
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
28f540f4 9
c84142e8
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
28f540f4 14
c84142e8
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
28f540f4 19
c84142e8 20#include <endian.h>
28f540f4 21#include <stddef.h>
0d4acd0f 22#include <stdint.h>
28f540f4
RM
23#include <stdlib.h>
24#include <string.h>
19bc17a9
RM
25
26#ifndef STRING_TYPE
27# define STRING_TYPE char
28# define USTRING_TYPE unsigned char
c84142e8
UD
29# ifdef USE_IN_EXTENDED_LOCALE_MODEL
30# define STRCOLL __strcoll_l
31# else
32# define STRCOLL strcoll
33# endif
75cd5204 34# define STRCMP strcmp
19bc17a9
RM
35#endif
36
4b10dd6c
UD
37#ifndef USE_IN_EXTENDED_LOCALE_MODEL
38int
39STRCOLL (s1, s2)
40 const STRING_TYPE *s1;
41 const STRING_TYPE *s2;
42#else
43int
44STRCOLL (s1, s2, l)
45 const STRING_TYPE *s1;
46 const STRING_TYPE *s2;
47 __locale_t l;
48#endif
49{
50 return STRCMP (s1, s2);
51}
52
53#if 0
19bc17a9
RM
54/* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
55 these functions. */
0393dfd6 56#include "../locale/weight.h"
28f540f4
RM
57
58
59/* Compare S1 and S2, returning less than, equal to or
19bc17a9 60 greater than zero if the collated form of S1 is lexicographically
28f540f4 61 less than, equal to or greater than the collated form of S2. */
c84142e8 62#ifndef USE_IN_EXTENDED_LOCALE_MODEL
28f540f4 63int
19bc17a9
RM
64STRCOLL (s1, s2)
65 const STRING_TYPE *s1;
66 const STRING_TYPE *s2;
c84142e8
UD
67#else
68int
69STRCOLL (s1, s2, l)
70 const STRING_TYPE *s1;
71 const STRING_TYPE *s2;
72 __locale_t l;
73#endif
28f540f4 74{
c84142e8
UD
75#ifdef USE_IN_EXTENDED_LOCALE_MODEL
76 struct locale_data *current = l->__locales[LC_COLLATE];
77# if BYTE_ORDER == BIG_ENDIAN
0d4acd0f 78 const uint32_t *collate_table = (const uint32_t *)
c84142e8 79 current->values[_NL_ITEM_INDEX (_NL_COLLATE_TABLE_EB)].string;
0d4acd0f 80 const uint32_t *collate_extra = (const uint32_t *)
c84142e8
UD
81 current->values[_NL_ITEM_INDEX (_NL_COLLATE_EXTRA_EB)].string;
82# elif BYTE_ORDER == LITTLE_ENDIAN
0d4acd0f 83 const uint32_t *collate_table = (const uint32_t *)
c84142e8 84 current->values[_NL_ITEM_INDEX (_NL_COLLATE_TABLE_EL)].string;
0d4acd0f 85 const uint32_t *collate_extra = (const uint32_t *)
c84142e8
UD
86 current->values[_NL_ITEM_INDEX (_NL_COLLATE_EXTRA_EL)].string;
87# else
88# error bizarre byte order
89# endif
90#endif
19bc17a9
RM
91 weight_t *s1forw = NULL;
92 weight_t *s1backw = NULL;
93 weight_t *s2forw = NULL;
94 weight_t *s2backw = NULL;
95 size_t pass;
96
97 /* If the current locale does not specify locale data we use normal
98 8-bit string comparison. */
99 if (collate_nrules == 0)
75cd5204 100 return STRCMP (s1, s2);
19bc17a9 101
a7ab2023
UD
102 /* Handle empty strings as a special case. */
103 if (*s1 == '\0')
104 return *s2 == '\0' ? 0 : -1;
105 else if (*s2 == '\0')
106 return 1;
107
19bc17a9
RM
108 /* Get full information about the strings. This means we get
109 information for all passes in a special data structure. */
110 get_string (s1, s1forw, s1backw);
111 get_string (s2, s2forw, s2backw);
112
113 /* Now we have all the information. In at most the given number of
114 passes we can finally decide about the order. */
115 for (pass = 0; pass < collate_nrules; ++pass)
116 {
117 int forward = (collate_rules[pass] & sort_forward) != 0;
118 const weight_t *s1run = forward ? s1forw : s1backw;
119 const weight_t *s2run = forward ? s2forw : s2backw;
120 int s1idx = forward ? 0 : s1run->data[pass].number - 1;
121 int s2idx = forward ? 0 : s2run->data[pass].number - 1;
122
5a97622d 123 while (1)
19bc17a9
RM
124 {
125 int s1ignore = 0;
126 int s2ignore = 0;
0d4acd0f
UD
127 uint32_t w1 = 0;
128 uint32_t w2 = 0;
19bc17a9
RM
129
130 /* Here we have to check for IGNORE entries. If these are
e4cf5070 131 found we count them and go on with the next value. */
5a97622d
UD
132 while (s1run != NULL
133 && ((w1 = s1run->data[pass].value[s1idx])
0d4acd0f 134 == (uint32_t) IGNORE_CHAR))
19bc17a9
RM
135 {
136 ++s1ignore;
6e4c40ba
UD
137 if (forward
138 ? ++s1idx >= s1run->data[pass].number
139 : --s1idx < 0)
19bc17a9
RM
140 {
141 weight_t *nextp = forward ? s1run->next : s1run->prev;
142 if (nextp == NULL)
143 {
144 w1 = 0;
5a97622d
UD
145 /* No more non-INGOREd elements means lowest
146 possible value. */
147 s1ignore = -1;
19bc17a9 148 }
5a97622d
UD
149 else
150 s1idx = forward ? 0 : nextp->data[pass].number - 1;
19bc17a9 151 s1run = nextp;
19bc17a9
RM
152 }
153 }
154
5a97622d
UD
155 while (s2run != NULL
156 && ((w2 = s2run->data[pass].value[s2idx])
0d4acd0f 157 == (uint32_t) IGNORE_CHAR))
19bc17a9
RM
158 {
159 ++s2ignore;
6e4c40ba
UD
160 if (forward
161 ? ++s2idx >= s2run->data[pass].number
162 : --s2idx < 0)
19bc17a9
RM
163 {
164 weight_t *nextp = forward ? s2run->next : s2run->prev;
165 if (nextp == NULL)
166 {
167 w2 = 0;
5a97622d
UD
168 /* No more non-INGOREd elements means lowest
169 possible value. */
170 s2ignore = -1;
19bc17a9 171 }
5a97622d
UD
172 else
173 s2idx = forward ? 0 : nextp->data[pass].number - 1;
19bc17a9 174 s2run = nextp;
19bc17a9
RM
175 }
176 }
177
5a97622d
UD
178 /* If one string is completely processed stop. */
179 if (s1run == NULL || s2run == NULL)
180 break;
181
19bc17a9
RM
182 /* Now we have information of the number of ignored
183 weights and the value of the next weight. */
184 if ((collate_rules[pass] & sort_position) != 0
185 && s1ignore != s2ignore && (w1 != 0 || w2 != 0))
186 return s1ignore < s2ignore ? -1 : 1;
187
188 if (w1 != w2)
189 return w1 < w2 ? -1 : 1;
190
191 /* We have to increment the index counters. */
04795ad9 192 if (forward)
94b78bb2 193 {
04795ad9 194 if (++s1idx >= s1run->data[pass].number)
94b78bb2
UD
195 {
196 s1run = s1run->next;
197 s1idx = 0;
198 }
04795ad9 199 if (++s2idx >= s2run->data[pass].number)
94b78bb2 200 {
04795ad9
UD
201 s2run = s2run->next;
202 s2idx = 0;
94b78bb2
UD
203 }
204 }
04795ad9 205 else
94b78bb2 206 {
04795ad9 207 if (--s1idx < 0)
94b78bb2 208 {
04795ad9
UD
209 s1run = s1run->prev;
210 if (s1run != NULL)
211 s1idx = s1run->data[pass].number - 1;
94b78bb2 212 }
04795ad9 213 if (--s2idx < 0)
94b78bb2
UD
214 {
215 s2run = s2run->prev;
216 if (s2run != NULL)
217 s2idx = s2run->data[pass].number - 1;
218 }
219 }
19bc17a9 220 }
19bc17a9
RM
221
222 if (s1run != s2run)
223 return s1run != NULL ? 1 : -1;
224 }
225
226 return 0;
28f540f4 227}
4b10dd6c 228#endif