New module 'unistr/u16-strcoll'.
[gnulib.git] / lib / unistr / u-strcoll.h
1 /* Compare UTF-8/UTF-16/UTF-32 strings using the collation rules of the current
2    locale.
3    Copyright (C) 2009 Free Software Foundation, Inc.
4    Written by Bruno Haible <bruno@clisp.org>, 2009.
5
6    This program is free software: you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as published
8    by the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 int
20 FUNC (const UNIT *s1, const UNIT *s2)
21 {
22   /* When this function succeeds, it sets errno back to its original value.
23      When it fails, it sets errno, but also returns a meaningful return value,
24      for the sake of callers which ignore errno.  */
25   int final_errno = errno;
26   char *sl1;
27   char *sl2;
28   int result;
29
30   sl1 = U_STRCONV_TO_LOCALE (s1);
31   if (sl1 != NULL)
32     {
33       sl2 = U_STRCONV_TO_LOCALE (s2);
34       if (sl2 != NULL)
35         {
36           /* Compare sl1 and sl2.  */
37           errno = 0;
38           result = strcoll (sl1, sl2);
39           if (errno == 0)
40             {
41               /* strcoll succeeded.  */
42               free (sl1);
43               free (sl2);
44             }
45           else
46             {
47               /* strcoll failed.  */
48               final_errno = errno;
49               free (sl1);
50               free (sl2);
51               result = U_STRCMP (s1, s2);
52             }
53         }
54       else
55         {
56           /* s1 could be converted to locale encoding, s2 not.  */
57           final_errno = errno;
58           free (sl1);
59           result = -1;
60         }
61     }
62   else
63     {
64       final_errno = errno;
65       sl2 = U_STRCONV_TO_LOCALE (s2);
66       if (sl2 != NULL)
67         {
68           /* s2 could be converted to locale encoding, s1 not.  */
69           free (sl2);
70           result = 1;
71         }
72       else
73         {
74           /* Neither s1 nor s2 could be converted to locale encoding.  */
75           result = U_STRCMP (s1, s2);
76         }
77     }
78
79   errno = final_errno;
80   return result;
81 }