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