7e0ece383f209021086d5382d7ccc4ebc4c7456b
[obnox/samba/samba-obnox.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   The *_wa() functions take a combination of 7 bit ascii
239   and wide characters They are used so that you can use string
240   functions combining C string constants with ucs2 strings
241
242   The char* arguments must NOT be multibyte - to be completely sure
243   of this only pass string constants */
244
245 int strcmp_wa(const smb_ucs2_t *a, const char *b)
246 {
247         smb_ucs2_t cp = 0;
248
249         while (*b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) {
250                 a++;
251                 b++;
252         }
253         return (*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b));
254 }
255
256 smb_ucs2_t toupper_w(smb_ucs2_t v)
257 {
258         smb_ucs2_t ret;
259         /* LE to native. */
260         codepoint_t cp = SVAL(&v,0);
261         cp = toupper_m(cp);
262         /* native to LE. */
263         SSVAL(&ret,0,cp);
264         return ret;
265 }