]> arthur.barton.de Git - netatalk.git/blob - libatalk/unicode/util_unistr.c
unicode endian fixes
[netatalk.git] / libatalk / unicode / util_unistr.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif /* HAVE_CONFIG_H */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/param.h>
9 #include <sys/stat.h>
10 #include <atalk/logger.h>
11 #include <errno.h>
12
13 #include <netatalk/endian.h>
14
15 #include <atalk/unicode.h>
16 #include "ucs2_casetable.h"
17 #include "precompose.h"
18 #include "byteorder.h"
19
20
21 ucs2_t toupper_w(ucs2_t val)
22 {
23         if ( val >= 0x0040 && val <= 0x007F)
24                 return upcase_table_1[val-0x0040];
25         if ( val >= 0x00C0 && val <= 0x02BF)
26                 return upcase_table_2[val-0x00C0];
27         if ( val >= 0x0380 && val <= 0x04FF)
28                 return upcase_table_3[val-0x0380];
29         if ( val >= 0x0540 && val <= 0x05BF)
30                 return upcase_table_4[val-0x0540];
31         if ( val >= 0x1E00 && val <= 0x1FFF)
32                 return upcase_table_5[val-0x1E00];
33         if ( val >= 0x2140 && val <= 0x217F)
34                 return upcase_table_6[val-0x2140];
35         if ( val >= 0x24C0 && val <= 0x24FF)
36                 return upcase_table_7[val-0x24C0];
37         if ( val >= 0xFF40 && val <= 0xFF7F)
38                 return upcase_table_8[val-0xFF40];
39
40         return (val);
41 }
42
43
44 ucs2_t tolower_w(ucs2_t val)
45 {
46         if ( val >= 0x0040 && val <= 0x007F)
47                 return lowcase_table_1[val-0x0040];
48         if ( val >= 0x00C0 && val <= 0x023F)
49                 return lowcase_table_2[val-0x00C0];
50         if ( val >= 0x0380 && val <= 0x057F)
51                 return lowcase_table_3[val-0x0380];
52         if ( val >= 0x1E00 && val <= 0x1FFF)
53                 return lowcase_table_4[val-0x1E00];
54         if ( val >= 0x2140 && val <= 0x217F)
55                 return lowcase_table_5[val-0x2140];
56         if ( val >= 0x2480 && val <= 0x24FF)
57                 return lowcase_table_6[val-0x2480];
58         if ( val >= 0xFF00 && val <= 0xFF3F)
59                 return lowcase_table_7[val-0xFF00];
60
61         return (val);
62 }
63
64 /*******************************************************************
65  Convert a string to lower case.
66  return True if any char is converted
67 ********************************************************************/
68 int strlower_w(ucs2_t *s)
69 {
70         int ret = 0;
71         while (*s) {
72                 ucs2_t v = tolower_w(*s);
73                 if (v != *s) {
74                         *s = v;
75                         ret = 1;
76                 }
77                 s++;
78         }
79         return ret;
80 }
81
82 /*******************************************************************
83  Convert a string to upper case.
84  return True if any char is converted
85 ********************************************************************/
86 int strupper_w(ucs2_t *s)
87 {
88         int ret = 0;
89         while (*s) {
90                 ucs2_t v = toupper_w(*s);
91                 if (v != *s) {
92                         *s = v;
93                         ret = 1;
94                 }
95                 s++;
96         }
97         return ret;
98 }
99
100
101 /*******************************************************************
102 determine if a character is lowercase
103 ********************************************************************/
104 int islower_w(ucs2_t c)
105 {
106         return ( c == tolower_w(c));
107 }
108
109 /*******************************************************************
110 determine if a character is uppercase
111 ********************************************************************/
112 int isupper_w(ucs2_t c)
113 {
114         return ( c == toupper_w(c));
115 }
116
117
118 /*******************************************************************
119  Count the number of characters in a ucs2_t string.
120 ********************************************************************/
121 size_t strlen_w(const ucs2_t *src)
122 {
123         size_t len;
124
125         for(len = 0; *src++; len++) ;
126
127         return len;
128 }
129
130 /*******************************************************************
131  Count up to max number of characters in a ucs2_t string.
132 ********************************************************************/
133 size_t strnlen_w(const ucs2_t *src, size_t max)
134 {
135         size_t len;
136
137         for(len = 0; *src++ && (len < max); len++) ;
138
139         return len;
140 }
141
142 /*******************************************************************
143 wide strchr()
144 ********************************************************************/
145 ucs2_t *strchr_w(const ucs2_t *s, ucs2_t c)
146 {
147         while (*s != 0) {
148                 if (c == *s) return (ucs2_t *)s;
149                 s++;
150         }
151         if (c == *s) return (ucs2_t *)s;
152
153         return NULL;
154 }
155
156 ucs2_t *strcasechr_w(const ucs2_t *s, ucs2_t c)
157 {
158         while (*s != 0) {
159 /*              LOG(log_debug, logtype_default, "Comparing %X to %X (%X - %X)", c, *s, toupper_w(c), toupper_w(*s));*/
160                 if (toupper_w(c) == toupper_w(*s)) return (ucs2_t *)s;
161                 s++;
162         }
163         if (c == *s) return (ucs2_t *)s;
164
165         return NULL;
166 }
167
168
169 int strcmp_w(const ucs2_t *a, const ucs2_t *b)
170 {
171         while (*b && *a == *b) { a++; b++; }
172         return (*a - *b);
173         /* warning: if *a != *b and both are not 0 we retrun a random
174                 greater or lesser than 0 number not realted to which
175                 string is longer */
176 }
177
178 int strncmp_w(const ucs2_t *a, const ucs2_t *b, size_t len)
179 {
180         size_t n = 0;
181         while ((n < len) && *b && *a == *b) { a++; b++; n++;}
182         return (len - n)?(*a - *b):0;
183 }
184
185 /*******************************************************************
186 wide strstr()
187 ********************************************************************/
188 ucs2_t *strstr_w(const ucs2_t *s, const ucs2_t *ins)
189 {
190         ucs2_t *r;
191         size_t slen, inslen;
192
193         if (!s || !*s || !ins || !*ins) return NULL;
194         slen = strlen_w(s);
195         inslen = strlen_w(ins);
196         r = (ucs2_t *)s;
197         while ((r = strchr_w(r, *ins))) {
198                 if (strncmp_w(r, ins, inslen) == 0) return r;
199                 r++;
200         }
201         return NULL;
202 }
203
204 ucs2_t *strcasestr_w(const ucs2_t *s, const ucs2_t *ins)
205 {
206         ucs2_t *r;
207         size_t slen, inslen;
208
209         if (!s || !*s || !ins || !*ins) return NULL;
210         slen = strlen_w(s);
211         inslen = strlen_w(ins);
212         r = (ucs2_t *)s;
213         while ((r = strcasechr_w(r, *ins))) {
214                 if (strncasecmp_w(r, ins, inslen) == 0) return r;
215                 r++;
216         }
217         return NULL;
218 }
219
220
221
222
223 /*******************************************************************
224 case insensitive string comparison
225 ********************************************************************/
226 int strcasecmp_w(const ucs2_t *a, const ucs2_t *b)
227 {
228         while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; }
229         return (tolower_w(*a) - tolower_w(*b));
230 }
231
232 /*******************************************************************
233 case insensitive string comparison, lenght limited
234 ********************************************************************/
235 int strncasecmp_w(const ucs2_t *a, const ucs2_t *b, size_t len)
236 {
237         size_t n = 0;
238         while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; }
239         return (len - n)?(tolower_w(*a) - tolower_w(*b)):0;
240 }
241
242 /*******************************************************************
243 duplicate string
244 ********************************************************************/
245 /* if len == 0 then duplicate the whole string */
246 ucs2_t *strndup_w(const ucs2_t *src, size_t len)
247 {
248         ucs2_t *dest;
249
250         if (!len) len = strlen_w(src);
251         dest = (ucs2_t *)malloc((len + 1) * sizeof(ucs2_t));
252         if (!dest) {
253                 LOG (log_error, logtype_default, "strdup_w: out of memory!\n");
254                 return NULL;
255         }
256
257         memcpy(dest, src, len * sizeof(ucs2_t));
258         dest[len] = 0;
259
260         return dest;
261 }
262
263 ucs2_t *strdup_w(const ucs2_t *src)
264 {
265         return strndup_w(src, 0);
266 }
267
268 /*******************************************************************
269 copy a string with max len
270 ********************************************************************/
271
272 ucs2_t *strncpy_w(ucs2_t *dest, const ucs2_t *src, const size_t max)
273 {
274         size_t len;
275
276         if (!dest || !src) return NULL;
277
278         for (len = 0; (src[len] != 0) && (len < max); len++)
279                 dest[len] = src[len];
280         while (len < max)
281                 dest[len++] = 0;
282
283         return dest;
284 }
285
286
287 /*******************************************************************
288 append a string of len bytes and add a terminator
289 ********************************************************************/
290
291 ucs2_t *strncat_w(ucs2_t *dest, const ucs2_t *src, const size_t max)
292 {
293         size_t start;
294         size_t len;
295
296         if (!dest || !src) return NULL;
297
298         start = strlen_w(dest);
299         len = strnlen_w(src, max);
300
301         memcpy(&dest[start], src, len*sizeof(ucs2_t));
302         dest[start+len] = 0;
303
304         return dest;
305 }
306
307
308 ucs2_t *strcat_w(ucs2_t *dest, const ucs2_t *src)
309 {
310         size_t start;
311         size_t len;
312
313         if (!dest || !src) return NULL;
314
315         start = strlen_w(dest);
316         len = strlen_w(src);
317
318         memcpy(&dest[start], src, len*sizeof(ucs2_t));
319         dest[start+len] = 0;
320
321         return dest;
322 }
323
324
325 /* ------------------------ */
326 ucs2_t do_precomposition(unsigned int base, unsigned int comb) 
327 {
328         int min = 0;
329         int max = sizeof(precompositions) / sizeof(precompositions[0]) - 1;
330         int mid;
331         u_int32_t sought = (base << 16) | comb, that;
332
333         /* binary search */
334         while (max >= min) {
335                 mid = (min + max) / 2;
336                 that = (precompositions[mid].base << 16) | (precompositions[mid].comb);
337                 if (that < sought) {
338                         min = mid + 1;
339                 } else if (that > sought) {
340                         max = mid - 1;
341                 } else {
342                         return precompositions[mid].replacement;
343                 }
344         }
345         /* no match */
346         return 0;
347 }
348
349 /* -------------------------- */
350 u_int32_t do_decomposition(ucs2_t base) 
351 {
352         int min = 0;
353         int max = sizeof(decompositions) / sizeof(decompositions[0]) - 1;
354         int mid;
355         u_int32_t sought = base;
356         u_int32_t result, that;
357
358         /* binary search */
359         while (max >= min) {
360                 mid = (min + max) / 2;
361                 that = decompositions[mid].replacement;
362                 if (that < sought) {
363                         min = mid + 1;
364                 } else if (that > sought) {
365                         max = mid - 1;
366                 } else {
367                         result = (decompositions[mid].base << 16) | (decompositions[mid].comb);
368                         return result;
369                 }
370         }
371         /* no match */
372         return 0;
373 }
374
375 /* we can't use static, this stuff needs to be reentrant */
376 /* static char comp[MAXPATHLEN +1]; */
377
378 size_t precompose_w (ucs2_t *name, size_t inplen, ucs2_t *comp, size_t *outlen)
379 {
380         size_t i;
381         ucs2_t base, comb;
382         ucs2_t *in, *out;
383         ucs2_t result;
384         size_t o_len = *outlen;
385
386         if (!inplen || (inplen & 1) || inplen > o_len)
387                 return (size_t)-1;
388         i = 0;
389         in  = name;
390         out = (ucs2_t *)comp;
391     
392         base = *in;
393         while (*outlen > 2) {
394                 i += 2;
395                 in++;
396                 if (i == inplen) {
397                         *out++ = base;
398                         *out = 0;
399                         *outlen -= 2;
400                         return o_len - *outlen;
401                 }
402                 comb = *in;
403                 if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
404                         *out = result;
405                         out++;
406                         *outlen -= 2;
407                         i += 2;
408                         in++;
409                         if (i == inplen) {
410                                 *out = 0;
411                                 return o_len - *outlen;
412                         }
413                         base = *in;
414                 }
415                 else {
416                         *out = base;
417                         out++;
418                         *outlen -= 2;
419                         base = comb;
420                 }
421         }
422         
423         errno = E2BIG;
424         return (size_t)-1;
425 }
426
427 /* --------------- */
428
429 size_t decompose_w (ucs2_t *name, size_t inplen, ucs2_t *comp, size_t *outlen)
430 {
431         size_t i;
432         ucs2_t base;
433         ucs2_t *in, *out;
434         unsigned int result;
435         size_t o_len = *outlen;
436
437         if (!inplen || (inplen & 1))
438                 return (size_t)-1;
439         i = 0;
440         in  = name;
441         out = (ucs2_t *)comp;
442     
443         while (i < inplen) {
444                 if (*outlen < 2) {
445                         errno = E2BIG;
446                         return (size_t)-1;
447                 }
448                 base = *in;
449                 if ( (base > 0x1fff && base < 0x3000) || (base > 0xfe2f && base < 0xfe50)) {
450                         /* exclude these ranges from decomposition according to AFP 3.1 spec */
451                         /* page 97 */
452                         *out = base;
453                         *out++;
454                         *outlen -= 2;
455                 }
456                 if ((result = do_decomposition(base))) {
457                         if ( *outlen < 4 ) {
458                                 errno = E2BIG;
459                                 return (size_t)-1;
460                         }
461                         *out = result  >> 16;
462                         out++;
463                         *outlen -= 2;
464                         *out = result & 0xffff;
465                         out++;
466                         *outlen -= 2;
467                 }
468                 else {
469                         *out = base;
470                         out++;
471                         *outlen -= 2;
472                 }
473                 i += 2;
474                 in++;
475         }
476
477         *out = 0;
478         return o_len-*outlen;
479 }
480
481 size_t utf8_charlen ( char* utf8 )
482 {
483         unsigned char *p;
484
485         p = (unsigned char*) utf8;
486         
487         if ( *p < 0x80 )
488                 return (1);
489         else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
490                 return (2);
491         else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
492                 return (3);
493         else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
494                 return (3);
495         else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
496                 return (4);
497         else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
498                 return (4);
499         else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
500                 return (4);
501         else
502                 return ((size_t) -1);
503 }
504
505
506 size_t utf8_strlen_validate ( char * utf8 )
507 {
508         size_t len;
509         unsigned char *p;
510
511         p = (unsigned char*) utf8;
512         len = 0;
513
514         /* see http://www.unicode.org/unicode/reports/tr27/ for an explanation */
515
516         while ( *p != '\0')
517         {
518                 if ( *p < 0x80 )
519                         p++;
520
521                 else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
522                         p += 2;
523
524                 else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
525                         p += 3;
526
527                 else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
528                         p += 3;
529
530                 else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
531                         p += 4;
532
533                 else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
534                         p += 4;
535
536                 else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
537                         p += 4;
538
539                 else
540                         return ((size_t) -1);
541
542                 len++;
543         }
544
545         return (len);
546 }
547