Fix many const compiler warnings.
[nivanova/samba-autobuild/.git] / lib / util / charset / util_unistr_w.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    Copyright (C) Jeremy Allison 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 /* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */
25 #define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((const unsigned char *)(src))[0],\
26                                 ((unsigned char *)(dest))[1] = ((const unsigned char *)(src))[1], (dest))
27
28
29 /* return an ascii version of a ucs2 character */
30 #define UCS2_TO_CHAR(c) (((c) >> UCS2_SHIFT) & 0xff)
31
32 static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len);
33
34 /*******************************************************************
35  Count the number of two-byte pairs in a UTF16 string.
36 ********************************************************************/
37
38 size_t strlen_w(const smb_ucs2_t *src)
39 {
40         size_t len;
41         smb_ucs2_t c;
42
43         for(len = 0; *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
44                 ;
45         }
46
47         return len;
48 }
49
50 /*******************************************************************
51  Count up to max number of characters in a smb_ucs2_t string.
52 ********************************************************************/
53
54 size_t strnlen_w(const smb_ucs2_t *src, size_t max)
55 {
56         size_t len;
57         smb_ucs2_t c;
58
59         for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
60                 ;
61         }
62
63         return len;
64 }
65
66 /*******************************************************************
67  Wide strchr().
68 ********************************************************************/
69
70 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
71 {
72         smb_ucs2_t cp;
73         while (*(COPY_UCS2_CHAR(&cp,s))) {
74                 if (c == cp) {
75                         return discard_const_p(smb_ucs2_t, s);
76                 }
77                 s++;
78         }
79         if (c == cp) {
80                 return discard_const_p(smb_ucs2_t, s);
81         }
82
83         return NULL;
84 }
85
86 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
87 {
88         return strchr_w(s, UCS2_CHAR(c));
89 }
90
91 /*******************************************************************
92  Wide strrchr().
93 ********************************************************************/
94
95 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
96 {
97         smb_ucs2_t cp;
98         const smb_ucs2_t *p = s;
99         int len = strlen_w(s);
100
101         if (len == 0) {
102                 return NULL;
103         }
104         p += (len - 1);
105         do {
106                 if (c == *(COPY_UCS2_CHAR(&cp,p))) {
107                         return discard_const_p(smb_ucs2_t, p);
108                 }
109         } while (p-- != s);
110         return NULL;
111 }
112
113 /*******************************************************************
114  Wide version of strrchr that returns after doing strrchr 'n' times.
115 ********************************************************************/
116
117 smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n)
118 {
119         smb_ucs2_t cp;
120         const smb_ucs2_t *p = s;
121         int len = strlen_w(s);
122
123         if (len == 0 || !n) {
124                 return NULL;
125         }
126         p += (len - 1);
127         do {
128                 if (c == *(COPY_UCS2_CHAR(&cp,p))) {
129                         n--;
130                 }
131
132                 if (!n) {
133                         return (smb_ucs2_t *)p;
134                 }
135         } while (p-- != s);
136         return NULL;
137 }
138
139 /*******************************************************************
140  Wide strstr().
141 ********************************************************************/
142
143 smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
144 {
145         smb_ucs2_t *r;
146         size_t inslen;
147
148         if (!s || !*s || !ins || !*ins) {
149                 return NULL;
150         }
151
152         inslen = strlen_w(ins);
153         r = (smb_ucs2_t *)s;
154
155         while ((r = strchr_w(r, *ins))) {
156                 if (strncmp_w(r, ins, inslen) == 0) {
157                         return r;
158                 }
159                 r++;
160         }
161
162         return NULL;
163 }
164
165 /*******************************************************************
166  Convert a string to lower case.
167  return True if any char is converted
168
169  This is unsafe for any string involving a UTF16 character
170 ********************************************************************/
171
172 bool strlower_w(smb_ucs2_t *s)
173 {
174         smb_ucs2_t cp;
175         bool ret = false;
176
177         while (*(COPY_UCS2_CHAR(&cp,s))) {
178                 smb_ucs2_t v = tolower_m(cp);
179                 if (v != cp) {
180                         COPY_UCS2_CHAR(s,&v);
181                         ret = true;
182                 }
183                 s++;
184         }
185         return ret;
186 }
187
188 /*******************************************************************
189  Convert a string to upper case.
190  return True if any char is converted
191
192  This is unsafe for any string involving a UTF16 character
193 ********************************************************************/
194
195 bool strupper_w(smb_ucs2_t *s)
196 {
197         smb_ucs2_t cp;
198         bool ret = false;
199         while (*(COPY_UCS2_CHAR(&cp,s))) {
200                 smb_ucs2_t v = toupper_m(cp);
201                 if (v != cp) {
202                         COPY_UCS2_CHAR(s,&v);
203                         ret = true;
204                 }
205                 s++;
206         }
207         return ret;
208 }
209
210 int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
211 {
212         smb_ucs2_t cpa, cpb;
213
214         while ((*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) {
215                 a++;
216                 b++;
217         }
218         return (*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b)));
219         /* warning: if *a != *b and both are not 0 we return a random
220                 greater or lesser than 0 number not realted to which
221                 string is longer */
222 }
223
224 static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
225 {
226         smb_ucs2_t cpa, cpb;
227         size_t n = 0;
228
229         while ((n < len) && (*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) {
230                 a++;
231                 b++;
232                 n++;
233         }
234         return (len - n)?(*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b))):0;
235 }
236
237 /*******************************************************************
238  Case insensitive string comparison.
239 ********************************************************************/
240
241 int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
242 {
243         smb_ucs2_t cpa, cpb;
244
245         while ((*COPY_UCS2_CHAR(&cpb,b)) && toupper_m(*(COPY_UCS2_CHAR(&cpa,a))) == toupper_m(cpb)) {
246                 a++;
247                 b++;
248         }
249         return (tolower_m(*(COPY_UCS2_CHAR(&cpa,a))) - tolower_m(*(COPY_UCS2_CHAR(&cpb,b))));
250 }
251
252 /*******************************************************************
253  Case insensitive string comparison, length limited.
254 ********************************************************************/
255
256 int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
257 {
258         smb_ucs2_t cpa, cpb;
259         size_t n = 0;
260
261         while ((n < len) && *COPY_UCS2_CHAR(&cpb,b) && (toupper_m(*(COPY_UCS2_CHAR(&cpa,a))) == toupper_m(cpb))) {
262                 a++;
263                 b++;
264                 n++;
265         }
266         return (len - n)?(tolower_m(*(COPY_UCS2_CHAR(&cpa,a))) - tolower_m(*(COPY_UCS2_CHAR(&cpb,b)))):0;
267 }
268
269 /*
270   The *_wa() functions take a combination of 7 bit ascii
271   and wide characters They are used so that you can use string
272   functions combining C string constants with ucs2 strings
273
274   The char* arguments must NOT be multibyte - to be completely sure
275   of this only pass string constants */
276
277 int strcmp_wa(const smb_ucs2_t *a, const char *b)
278 {
279         smb_ucs2_t cp = 0;
280
281         while (*b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) {
282                 a++;
283                 b++;
284         }
285         return (*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b));
286 }
287
288 /*************************************************************
289  ascii only toupper - saves the need for smbd to be in C locale.
290 *************************************************************/
291
292 int toupper_ascii(int c)
293 {
294         smb_ucs2_t uc = toupper_m(UCS2_CHAR(c));
295         return UCS2_TO_CHAR(uc);
296 }
297
298 /*************************************************************
299  ascii only tolower - saves the need for smbd to be in C locale.
300 *************************************************************/
301
302 int tolower_ascii(int c)
303 {
304         smb_ucs2_t uc = tolower_m(UCS2_CHAR(c));
305         return UCS2_TO_CHAR(uc);
306 }
307
308 /*************************************************************
309  ascii only isupper - saves the need for smbd to be in C locale.
310 *************************************************************/
311
312 int isupper_ascii(int c)
313 {
314         return isupper_m(UCS2_CHAR(c));
315 }
316
317 /*************************************************************
318  ascii only islower - saves the need for smbd to be in C locale.
319 *************************************************************/
320
321 int islower_ascii(int c)
322 {
323         return islower_m(UCS2_CHAR(c));
324 }