1 /* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
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.
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.
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. */
25 # define STRING_TYPE char
26 # define USTRING_TYPE unsigned char
28 # ifdef USE_IN_EXTENDED_LOCALE_MODEL
29 # define STRXFRM __strxfrm_l
31 # define STRXFRM strxfrm
33 # define STRLEN strlen
34 # define STPNCPY __stpncpy
37 #ifndef USE_IN_EXTENDED_LOCALE_MODEL
39 STRXFRM (STRING_TYPE
*dest
, const STRING_TYPE
*src
, size_t n
)
42 STRXFRM (STRING_TYPE
*dest
, const STRING_TYPE
*src
, size_t n
, __locale_t l
)
46 STPNCPY (dest
, src
, n
);
52 /* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
54 #include "../locale/weight.h"
58 /* Write 32 bit value UTF-8 encoded but only if enough space is left. */
59 static __inline
size_t
60 print_val (u_int32_t value
, char *dest
, size_t max
, size_t act
)
66 tmp
[idx
++] = (char) value
;
69 tmp
[idx
++] = '\x80' + (char) (value
& 0x3f);
73 tmp
[idx
++] = '\xc0' + (char) value
;
76 tmp
[idx
++] = '\x80' + (char) (value
& 0x3f);
80 tmp
[idx
++] = '\xe0' + (char) value
;
83 tmp
[idx
++] = '\x80' + (char) (value
& 0x3f);
87 tmp
[idx
++] = '\xf0' + (char) value
;
90 tmp
[idx
++] = '\x80' + (char) (value
& 0x3f);
94 tmp
[idx
++] = '\xf8' + (char) value
;
97 tmp
[idx
++] = '\x80' + (char) (value
& 0x3f);
98 tmp
[idx
++] = '\xfc' + (char) (value
>> 6);
108 dest
[act
] = tmp
[idx
];
115 static __inline
size_t
116 print_val (u_int32_t value
, wchar_t *dest
, size_t max
, size_t act
)
118 /* We cannot really assume wchar_t is 32 bits wide. But it is for
119 GCC and so we don't do much optimization for the other case. */
120 if (sizeof (wchar_t) == 4)
123 dest
[act
] = (wchar_t) value
;
132 tmp
[idx
++] = (wchar_t) act
;
135 tmp
[idx
++] = (wchar_t) (0x8000 + (value
& 0x3fff));
138 tmp
[idx
++] = (wchar_t) (0xc000 + value
);
141 tmp
[idx
++] = (wchar_t) (0x8000 + (value
& 0x3fff));
143 tmp
[idx
++] = (wchar_t) (0xe000 + value
);
149 dest
[act
] = tmp
[idx
];
158 /* Transform SRC into a form such that the result of strcmp
159 on two strings that have been transformed by strxfrm is
160 the same as the result of strcoll on the two strings before
161 their transformation. The transformed string is put in at
162 most N characters of DEST and its length is returned. */
163 #ifndef USE_IN_EXTENDED_LOCALE_MODEL
165 STRXFRM (STRING_TYPE
*dest
, const STRING_TYPE
*src
, size_t n
)
168 STRXFRM (STRING_TYPE
*dest
, const STRING_TYPE
*src
, size_t n
, __locale_t l
)
171 #ifdef USE_IN_EXTENDED_LOCALE_MODEL
172 struct locale_data
*current
= l
->__locales
[LC_COLLATE
];
173 # if BYTE_ORDER == BIG_ENDIAN
174 const u_int32_t
*collate_table
= (const u_int32_t
*)
175 current
->values
[_NL_ITEM_INDEX (_NL_COLLATE_TABLE_EB
)].string
;
176 const u_int32_t
*collate_extra
= (const u_int32_t
*)
177 current
->values
[_NL_ITEM_INDEX (_NL_COLLATE_EXTRA_EB
)].string
;
178 # elif BYTE_ORDER == LITTLE_ENDIAN
179 const u_int32_t
*collate_table
= (const u_int32_t
*)
180 current
->values
[_NL_ITEM_INDEX (_NL_COLLATE_TABLE_EL
)].string
;
181 const u_int32_t
*collate_extra
= (const u_int32_t
*)
182 current
->values
[_NL_ITEM_INDEX (_NL_COLLATE_EXTRA_EL
)].string
;
184 # error bizarre byte order
187 weight_t
*forw
= NULL
;
188 weight_t
*backw
= NULL
;
192 /* If the current locale does not specify locale data we use normal
193 8-bit string comparison. */
194 if (collate_nrules
== 0)
197 STPNCPY (dest
, src
, n
);
202 /* Handle an empty string as a special case. */
210 /* Get full information about the string. This means we get
211 information for all passes in a special data structure. */
212 get_string (src
, forw
, backw
);
214 /* Now we have all the information. In at most the given number of
215 passes we can finally decide about the order. */
217 for (pass
= 0; pass
< collate_nrules
; ++pass
)
219 int forward
= (collate_rules
[pass
] & sort_forward
) != 0;
220 const weight_t
*run
= forward
? forw
: backw
;
221 int idx
= forward
? 0 : run
->data
[pass
].number
- 1;
228 /* Here we have to check for IGNORE entries. If these are
229 found we count them and go on with he next value. */
231 && ((w
= run
->data
[pass
].value
[idx
])
232 == (u_int32_t
) IGNORE_CHAR
))
236 ? ++idx
>= run
->data
[pass
].number
239 weight_t
*nextp
= forward
? run
->next
: run
->prev
;
243 /* No more non-INGOREd elements means lowest
248 idx
= forward
? 0 : nextp
->data
[pass
].number
- 1;
253 /* Stop if all characters are processed. */
257 /* Now we have information of the number of ignored weights
258 and the value of the next weight. We have to add 2
259 because 0 means EOS and 1 is the intermediate string end. */
260 if ((collate_rules
[pass
] & sort_position
) != 0)
261 written
= print_val (ignore
+ 2, dest
, n
, written
);
264 written
= print_val (w
, dest
, n
, written
);
266 /* We have to increment the index counters. */
269 if (++idx
>= run
->data
[pass
].number
)
281 idx
= run
->data
[pass
].number
- 1;
286 /* Write marker for end of word. */
287 if (pass
+ 1 < collate_nrules
)
288 written
= print_val (1, dest
, n
, written
);
291 /* Terminate string. */
293 dest
[written
] = L_('\0');
295 /* Return length without counting the terminating '\0'. */