]> arthur.barton.de Git - netatalk.git/blob - libatalk/unicode/util_unistr.c
remove '\n' char in log messages.
[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!");
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++;
399                         *out = 0;
400                         *outlen -= 2;
401                         return o_len - *outlen;
402                 }
403                 comb = *in;
404                 if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
405                         *out = result;
406                         out++;
407                         *outlen -= 2;
408                         i += 2;
409                         in++;
410                         if (i == inplen) {
411                                 *out = 0;
412                                 return o_len - *outlen;
413                         }
414                         base = *in;
415                 }
416                 else {
417                         *out = base;
418                         out++;
419                         *outlen -= 2;
420                         base = comb;
421                 }
422         }
423         
424         errno = E2BIG;
425         return (size_t)-1;
426 }
427
428 /* --------------- */
429
430 size_t decompose_w (ucs2_t *name, size_t inplen, ucs2_t *comp, size_t *outlen)
431 {
432         size_t i;
433         ucs2_t base;
434         ucs2_t *in, *out;
435         unsigned int result;
436         size_t o_len = *outlen;
437
438         if (!inplen || (inplen & 1))
439                 return (size_t)-1;
440         i = 0;
441         in  = name;
442         out = (ucs2_t *)comp;
443     
444         while (i < inplen) {
445                 if (*outlen < 2) {
446                         errno = E2BIG;
447                         return (size_t)-1;
448                 }
449                 base = *in;
450                 if ( (base > 0x1fff && base < 0x3000) || (base > 0xfe2f && base < 0xfe50)) {
451                         /* exclude these ranges from decomposition according to AFP 3.1 spec */
452                         /* page 97 */
453                         *out = base;
454                         out++;
455                         *outlen -= 2;
456                 }
457                 else if ((result = do_decomposition(base))) {
458                         if ( *outlen < 4 ) {
459                                 errno = E2BIG;
460                                 return (size_t)-1;
461                         }
462                         *out = result  >> 16;
463                         out++;
464                         *outlen -= 2;
465                         *out = result & 0xffff;
466                         out++;
467                         *outlen -= 2;
468                 }
469                 else {
470                         *out = base;
471                         out++;
472                         *outlen -= 2;
473                 }
474                 i += 2;
475                 in++;
476         }
477
478         *out = 0;
479         return o_len-*outlen;
480 }
481
482 size_t utf8_charlen ( char* utf8 )
483 {
484         unsigned char *p;
485
486         p = (unsigned char*) utf8;
487         
488         if ( *p < 0x80 )
489                 return (1);
490         else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
491                 return (2);
492         else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
493                 return (3);
494         else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
495                 return (3);
496         else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
497                 return (4);
498         else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
499                 return (4);
500         else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
501                 return (4);
502         else
503                 return ((size_t) -1);
504 }
505
506
507 size_t utf8_strlen_validate ( char * utf8 )
508 {
509         size_t len;
510         unsigned char *p;
511
512         p = (unsigned char*) utf8;
513         len = 0;
514
515         /* see http://www.unicode.org/unicode/reports/tr27/ for an explanation */
516
517         while ( *p != '\0')
518         {
519                 if ( *p < 0x80 )
520                         p++;
521
522                 else if ( *p > 0xC1 && *p < 0xe0 && *(p+1) > 0x7f && *(p+1) < 0xC0)
523                         p += 2;
524
525                 else if ( *p == 0xe0 && *(p+1) > 0x9f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
526                         p += 3;
527
528                 else if ( *p > 0xe0  && *p < 0xf0 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0)
529                         p += 3;
530
531                 else if ( *p == 0xf0 && *(p+1) > 0x8f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
532                         p += 4;
533
534                 else if ( *p > 0xf0 && *p < 0xf4 && *(p+1) > 0x7f && *(p+1) < 0xc0 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
535                         p += 4;
536
537                 else if ( *p == 0xf4 && *(p+1) > 0x7f && *(p+1) < 0x90 && *(p+2) > 0x7f && *(p+2) < 0xc0 && *(p+3) > 0x7f && *(p+3) < 0xc0 )
538                         p += 4;
539
540                 else
541                         return ((size_t) -1);
542
543                 len++;
544         }
545
546         return (len);
547 }
548