Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <fontforge-config.h>
28 :
29 : #include <stddef.h>
30 : #include "ustring.h"
31 : #include "utype.h"
32 :
33 0 : long uc_strcmp(const unichar_t *str1,const char *str2) {
34 : long ch1, ch2;
35 : for (;;) {
36 0 : ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
37 0 : if ( ch1!=ch2 || ch1=='\0' )
38 0 : return(ch1-ch2);
39 0 : }
40 : }
41 :
42 0 : long uc_strncmp(const unichar_t *str1,const char *str2,int n) {
43 : long ch1, ch2;
44 0 : while ( --n>=0 ) {
45 0 : ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
46 0 : if ( ch1!=ch2 || ch1=='\0' )
47 0 : return(ch1-ch2);
48 : }
49 0 : return( 0 );
50 : }
51 :
52 0 : long uc_strmatch(const unichar_t *str1, const char *str2) {
53 : long ch1, ch2;
54 : for (;;) {
55 0 : ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
56 0 : ch1 = tolower(ch1);
57 0 : ch2 = tolower(ch2);
58 0 : if ( ch1!=ch2 || ch1=='\0' )
59 0 : return(ch1-ch2);
60 0 : }
61 : }
62 :
63 0 : long uc_strnmatch(const unichar_t *str1, const char *str2, int len) {
64 : long ch1, ch2;
65 0 : for (;--len>=0;) {
66 0 : ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
67 0 : ch1 = tolower(ch1);
68 0 : ch2 = tolower(ch2);
69 0 : if ( ch1!=ch2 || ch1=='\0' || len<=0 )
70 0 : return(ch1-ch2);
71 : }
72 0 : return( 0 );
73 : }
74 :
75 0 : long u_strnmatch(const unichar_t *str1, const unichar_t *str2, int len) {
76 : long ch1, ch2;
77 0 : for (;--len>=0;) {
78 0 : ch1 = *str1++; ch2 = *str2++ ;
79 0 : ch1 = tolower(ch1);
80 0 : ch2 = tolower(ch2);
81 0 : if ( ch1!=ch2 || ch1=='\0' || len<=0 )
82 0 : return(ch1-ch2);
83 : }
84 0 : return( 0 );
85 : }
86 :
87 0 : long u_strcmp(const unichar_t *str1,const unichar_t *str2) {
88 : long ch1, ch2;
89 : for (;;) {
90 0 : ch1 = *str1++; ch2 = *str2++ ;
91 0 : if ( ch1!=ch2 || ch1=='\0' )
92 0 : return(ch1-ch2);
93 0 : }
94 : }
95 :
96 0 : long u_strncmp(const unichar_t *str1,const unichar_t *str2,int n) {
97 : long ch1, ch2;
98 0 : while ( --n>=0 ) {
99 0 : ch1 = *str1++; ch2 = *str2++ ;
100 0 : if ( ch1!=ch2 || ch1=='\0' )
101 0 : return(ch1-ch2);
102 : }
103 0 : return( 0 );
104 : }
105 :
106 0 : long u_strmatch(const unichar_t *str1, const unichar_t *str2) {
107 : long ch1, ch2;
108 : for (;;) {
109 0 : ch1 = *str1++; ch2 = *str2++ ;
110 0 : ch1 = tolower(ch1);
111 0 : ch2 = tolower(ch2);
112 0 : if ( ch1!=ch2 || ch1=='\0' )
113 0 : return(ch1-ch2);
114 0 : }
115 : }
116 :
117 0 : void cu_strcpy(char *to, const unichar_t *from) {
118 : register unichar_t ch;
119 0 : while ( (ch = *from++) != '\0' )
120 0 : *(to++) = ch;
121 0 : *to = 0;
122 0 : }
123 :
124 0 : void uc_strcpy(unichar_t *to, const char *from) {
125 : register unichar_t ch;
126 0 : while ( (ch = *(unsigned char *) from++) != '\0' )
127 0 : *(to++) = ch;
128 0 : *to = 0;
129 0 : }
130 :
131 0 : void u_strcpy(unichar_t *to, const unichar_t *from) {
132 : register unichar_t ch;
133 0 : while ( (ch = *from++) != '\0' )
134 0 : *(to++) = ch;
135 0 : *to = 0;
136 0 : }
137 :
138 0 : char *cc_strncpy(char *to, const char *from, int len) {
139 0 : if( !from ) {
140 0 : to[0] = '\0';
141 0 : return to;
142 : }
143 0 : strncpy( to, from, len );
144 0 : return to;
145 : }
146 :
147 :
148 0 : void u_strncpy(register unichar_t *to, const unichar_t *from, int len) {
149 : register unichar_t ch;
150 0 : while ( (ch = *from++) != '\0' && --len>=0 )
151 0 : *(to++) = ch;
152 0 : *to = 0;
153 0 : }
154 :
155 0 : void cu_strncpy(register char *to, const unichar_t *from, int len) {
156 : register unichar_t ch;
157 0 : while ( (ch = *from++) != '\0' && --len>=0 )
158 0 : *(to++) = ch;
159 0 : *to = 0;
160 0 : }
161 :
162 0 : void uc_strncpy(register unichar_t *to, const char *from, int len) {
163 : register unichar_t ch;
164 0 : while ( (ch = *(unsigned char *) from++) != '\0' && --len>=0 )
165 0 : *(to++) = ch;
166 0 : *to = 0;
167 0 : }
168 :
169 0 : void uc_strcat(unichar_t *to, const char *from) {
170 0 : uc_strcpy(to+u_strlen(to),from);
171 0 : }
172 :
173 0 : void uc_strncat(unichar_t *to, const char *from,int len) {
174 0 : uc_strncpy(to+u_strlen(to),from,len);
175 0 : }
176 :
177 0 : void cu_strcat(char *to, const unichar_t *from) {
178 0 : cu_strcpy(to+strlen(to),from);
179 0 : }
180 :
181 0 : void cu_strncat(char *to, const unichar_t *from, int len) {
182 0 : cu_strncpy(to+strlen(to),from,len);
183 0 : }
184 :
185 0 : void u_strcat(unichar_t *to, const unichar_t *from) {
186 0 : u_strcpy(to+u_strlen(to),from);
187 0 : }
188 :
189 0 : void u_strncat(unichar_t *to, const unichar_t *from, int len) {
190 0 : u_strncpy(to+u_strlen(to),from,len);
191 0 : }
192 :
193 :
194 203033 : int u_strlen(register const unichar_t *str) {
195 203033 : register int len = 0;
196 :
197 12160828 : while ( *str++!='\0' )
198 11754762 : ++len;
199 203033 : return( len );
200 : }
201 :
202 0 : int c_strlen( const char * p )
203 : {
204 0 : if(!p)
205 0 : return 0;
206 0 : return strlen(p);
207 : }
208 :
209 :
210 0 : unichar_t *u_strchr(const unichar_t *str ,unichar_t ch) {
211 : register unichar_t test;
212 :
213 0 : while ( (test=*(str++))!='\0' )
214 0 : if ( test==ch )
215 0 : return( (unichar_t *) str-1 );
216 :
217 0 : return( NULL );
218 : }
219 :
220 0 : unichar_t *u_strrchr(const unichar_t *str ,unichar_t ch) {
221 0 : register unichar_t test, *last = NULL;
222 :
223 0 : while ( (test=*(str++))!='\0' )
224 0 : if ( test==ch )
225 0 : last = (unichar_t *) str-1;
226 :
227 0 : return( last );
228 : }
229 :
230 0 : unichar_t *uc_strstr(const unichar_t *longer, const char *substr) {
231 : long ch1, ch2;
232 : const unichar_t *lpt, *str1; const char *str2;
233 :
234 0 : for ( lpt=longer; *lpt!='\0'; ++lpt ) {
235 0 : str1 = lpt; str2 = substr;
236 : for (;;) {
237 0 : ch1 = *str1++; ch2 = *(unsigned char *) str2++ ;
238 0 : if ( ch2=='\0' )
239 0 : return((unichar_t *) lpt);
240 0 : if ( ch1!=ch2 )
241 0 : break;
242 0 : }
243 : }
244 0 : return( NULL );
245 : }
246 :
247 0 : unichar_t *u_strstr(const unichar_t *longer, const unichar_t *substr) {
248 : long ch1, ch2;
249 : const unichar_t *lpt, *str1, *str2;
250 :
251 0 : for ( lpt=longer; *lpt!='\0'; ++lpt ) {
252 0 : str1 = lpt; str2 = substr;
253 : for (;;) {
254 0 : ch1 = *str1++; ch2 = *str2++ ;
255 0 : if ( ch2=='\0' )
256 0 : return((unichar_t *) lpt);
257 0 : if ( ch1!=ch2 )
258 0 : break;
259 0 : }
260 : }
261 0 : return( NULL );
262 : }
263 :
264 0 : unichar_t *uc_strstrmatch(const unichar_t *longer, const char *substr) {
265 : long ch1, ch2;
266 : const unichar_t *lpt, *str1; const unsigned char *str2;
267 :
268 0 : for ( lpt=longer; *lpt!='\0'; ++lpt ) {
269 0 : str1 = lpt; str2 = (unsigned char *) substr;
270 : for (;;) {
271 0 : ch1 = *str1++; ch2 = *str2++ ;
272 0 : ch1 = tolower(ch1);
273 0 : ch2 = tolower(ch2);
274 0 : if ( ch2=='\0' )
275 0 : return((unichar_t *) lpt);
276 0 : if ( ch1!=ch2 )
277 0 : break;
278 0 : }
279 : }
280 0 : return( NULL );
281 : }
282 :
283 0 : unichar_t *u_strstrmatch(const unichar_t *longer, const unichar_t *substr) {
284 : long ch1, ch2;
285 : const unichar_t *lpt, *str1, *str2;
286 :
287 0 : for ( lpt=longer; *lpt!='\0'; ++lpt ) {
288 0 : str1 = lpt; str2 = substr;
289 : for (;;) {
290 0 : ch1 = *str1++; ch2 = *str2++ ;
291 0 : ch1 = tolower(ch1);
292 0 : ch2 = tolower(ch2);
293 0 : if ( ch2=='\0' )
294 0 : return((unichar_t *) lpt);
295 0 : if ( ch1!=ch2 )
296 0 : break;
297 0 : }
298 : }
299 0 : return( NULL );
300 : }
301 :
302 0 : unichar_t *u_copyn(const unichar_t *pt, long n) {
303 : unichar_t *res;
304 : #ifdef MEMORY_MASK
305 : if ( n*sizeof(unichar_t)>=MEMORY_MASK )
306 : n = MEMORY_MASK/sizeof(unichar_t)-1;
307 : #endif
308 0 : res = (unichar_t *) malloc((n+1)*sizeof(unichar_t));
309 0 : memcpy(res,pt,n*sizeof(unichar_t));
310 0 : res[n]='\0';
311 0 : return(res);
312 : }
313 :
314 0 : unichar_t *u_copynallocm(const unichar_t *pt, long n, long m) {
315 : unichar_t *res;
316 : #ifdef MEMORY_MASK
317 : if ( n*sizeof(unichar_t)>=MEMORY_MASK )
318 : n = MEMORY_MASK/sizeof(unichar_t)-1;
319 : #endif
320 0 : res = malloc((m+1)*sizeof(unichar_t));
321 0 : memcpy(res,pt,n*sizeof(unichar_t));
322 0 : res[n]='\0';
323 0 : return(res);
324 : }
325 :
326 0 : unichar_t *u_copy(const unichar_t *pt) {
327 0 : if(pt)
328 0 : return u_copyn(pt,u_strlen(pt));
329 :
330 0 : return((unichar_t *)0);
331 : }
332 :
333 0 : unichar_t *u_concat(const unichar_t *s1, const unichar_t *s2) {
334 : long len1, len2;
335 : unichar_t *pt;
336 :
337 0 : if ( s1==NULL )
338 0 : return( u_copy( s2 ));
339 0 : else if ( s2==NULL )
340 0 : return( u_copy( s1 ));
341 0 : len1 = u_strlen(s1); len2 = u_strlen(s2);
342 0 : pt = (unichar_t *) malloc((len1+len2+1)*sizeof(unichar_t));
343 0 : u_strcpy(pt,s1);
344 0 : u_strcpy(pt+len1,s2);
345 0 : return( pt );
346 : }
347 :
348 0 : unichar_t *uc_copyn(const char *pt,int len) {
349 : unichar_t *res, *rpt;
350 :
351 0 : if(!pt)
352 0 : return((unichar_t *)0);
353 :
354 : #ifdef MEMORY_MASK
355 : if ( (len+1)*sizeof(unichar_t)>=MEMORY_MASK )
356 : len = MEMORY_MASK/sizeof(unichar_t)-1;
357 : #endif
358 0 : res = (unichar_t *) malloc((len+1)*sizeof(unichar_t));
359 0 : for ( rpt=res; --len>=0 ; *rpt++ = *(unsigned char *) pt++ );
360 0 : *rpt = '\0';
361 0 : return(res);
362 : }
363 :
364 3 : unichar_t *uc_copy(const char *pt) {
365 : unichar_t *res, *rpt;
366 : int n;
367 :
368 3 : if(!pt)
369 0 : return((unichar_t *)0);
370 :
371 3 : n = strlen(pt);
372 : #ifdef MEMORY_MASK
373 : if ( (n+1)*sizeof(unichar_t)>=MEMORY_MASK )
374 : n = MEMORY_MASK/sizeof(unichar_t)-1;
375 : #endif
376 3 : res = (unichar_t *) malloc((n+1)*sizeof(unichar_t));
377 3 : for ( rpt=res; --n>=0 ; *rpt++ = *(unsigned char *) pt++ );
378 3 : *rpt = '\0';
379 3 : return(res);
380 : }
381 :
382 0 : char *cu_copyn(const unichar_t *pt,int len) {
383 : char *res, *rpt;
384 :
385 0 : if(!pt)
386 0 : return(NULL);
387 :
388 : #ifdef MEMORY_MASK
389 : if ( (len+1)>=MEMORY_MASK )
390 : len = MEMORY_MASK-1;
391 : #endif
392 0 : res = (char *) malloc(len+1);
393 0 : for ( rpt=res; --len>=0 ; *rpt++ = *pt++ );
394 0 : *rpt = '\0';
395 0 : return(res);
396 : }
397 :
398 0 : char *cu_copy(const unichar_t *pt) {
399 : char *res, *rpt;
400 : int n;
401 :
402 0 : if(!pt)
403 0 : return((char *)0);
404 :
405 0 : n = u_strlen(pt);
406 : #ifdef MEMORY_MASK
407 : if ( (n+1)>=MEMORY_MASK )
408 : n = MEMORY_MASK/sizeof(unichar_t)-1;
409 : #endif
410 0 : res = (char *) malloc(n+1);
411 0 : for ( rpt=res; --n>=0 ; *rpt++ = *pt++ );
412 0 : *rpt = '\0';
413 0 : return(res);
414 : }
415 :
416 0 : double u_strtod(const unichar_t *str, unichar_t **ptr) {
417 : char buf[60], *pt, *ret;
418 : const unichar_t *upt;
419 : double val;
420 :
421 0 : for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt-buf<(ptrdiff_t)(sizeof(buf)-1); )
422 0 : *pt++ = *upt++;
423 0 : *pt = '\0';
424 0 : val = strtod(buf,&ret);
425 0 : if ( ptr!=NULL ) {
426 0 : if ( pt==ret )
427 0 : *ptr = (unichar_t *) upt;
428 : else
429 0 : *ptr = (unichar_t *) (str + (ret-buf));
430 : }
431 0 : return( val );
432 : }
433 :
434 0 : long u_strtol(const unichar_t *str, unichar_t **ptr, int base) {
435 : char buf[60], *pt, *ret;
436 : const unichar_t *upt;
437 : long val;
438 :
439 0 : for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
440 0 : *pt++ = *upt++;
441 0 : *pt = '\0';
442 0 : val = strtol(buf,&ret,base);
443 0 : if ( ptr!=NULL ) {
444 0 : if ( pt==ret )
445 0 : *ptr = (unichar_t *) upt;
446 : else
447 0 : *ptr = (unichar_t *) (str + (ret-buf));
448 : }
449 0 : return( val );
450 : }
451 :
452 0 : unsigned long u_strtoul(const unichar_t *str, unichar_t **ptr, int base) {
453 : char buf[60], *pt, *ret;
454 : const unichar_t *upt;
455 : unsigned long val;
456 :
457 0 : for ( upt=str, pt=buf; *upt<128 && *upt!='\0' && pt<buf+sizeof(buf)-1; )
458 0 : *pt++ = *upt++;
459 0 : *pt = '\0';
460 0 : val = strtoul(buf,&ret,base);
461 0 : if ( ptr!=NULL ) {
462 0 : if ( pt==ret )
463 0 : *ptr = (unichar_t *) upt;
464 : else
465 0 : *ptr = (unichar_t *) (str + (ret-buf));
466 : }
467 0 : return( val );
468 : }
469 :
470 0 : unichar_t *cu_strstartmatch(const char *key,const unichar_t *str) {
471 0 : if ( key && str ) {
472 0 : while( *key ) {
473 0 : if(tolower(*key) != tolower(*str))
474 0 : return 0;
475 0 : key++;
476 0 : str++;
477 : }
478 : }
479 0 : return (unichar_t *)str;
480 : }
481 :
482 0 : unichar_t *u_strstartmatch(const unichar_t *initial, const unichar_t *full) {
483 : int ch1, ch2;
484 : for (;;) {
485 0 : ch1 = *initial++; ch2 = *full++ ;
486 0 : if ( ch1=='\0' )
487 0 : return( (unichar_t *) full );
488 0 : ch1 = tolower(ch1);
489 0 : ch2 = tolower(ch2);
490 0 : if ( ch1!=ch2 || ch1=='\0' )
491 0 : return(NULL);
492 0 : }
493 : }
494 :
495 0 : char *u_to_c(const unichar_t *ubuf) {
496 0 : if( !ubuf )
497 0 : return 0;
498 : static char buf[400];
499 0 : cu_strncpy(buf,ubuf,sizeof(buf));
500 0 : return( buf );
501 : }
502 :
503 0 : unichar_t *c_to_u(const char *buf) {
504 : static unichar_t ubuf[400];
505 0 : uc_strncpy(ubuf,buf,sizeof(ubuf));
506 0 : return( ubuf );
507 : }
508 :
509 203460 : unichar_t *utf82u_strncpy(unichar_t *ubuf,const char *utf8buf,int len) {
510 203460 : unichar_t *upt=ubuf, *uend=ubuf+len-1;
511 203460 : const uint8 *pt = (const uint8 *) utf8buf, *end = pt+strlen(utf8buf);
512 : int w, w2;
513 :
514 12172982 : while ( pt<end && *pt!='\0' && upt<uend ) {
515 11766062 : if ( *pt<=127 )
516 11764154 : *upt = *pt++;
517 1908 : else if ( *pt<=0xdf ) {
518 1892 : *upt = ((*pt&0x1f)<<6) | (pt[1]&0x3f);
519 1892 : pt += 2;
520 16 : } else if ( *pt<=0xef ) {
521 16 : *upt = ((*pt&0xf)<<12) | ((pt[1]&0x3f)<<6) | (pt[2]&0x3f);
522 16 : pt += 3;
523 : } else {
524 0 : w = ( ((*pt&0x7)<<2) | ((pt[1]&0x30)>>4) )-1;
525 0 : w = (w<<6) | ((pt[1]&0xf)<<2) | ((pt[2]&0x30)>>4);
526 0 : w2 = ((pt[2]&0xf)<<6) | (pt[3]&0x3f);
527 0 : *upt = w*0x400 + w2 + 0x10000;
528 0 : pt += 4;
529 : }
530 11766062 : ++upt;
531 : }
532 203460 : *upt = '\0';
533 203460 : return( ubuf );
534 : }
535 :
536 0 : unichar_t *utf82u_strcpy(unichar_t *ubuf,const char *utf8buf) {
537 0 : return( utf82u_strncpy(ubuf,utf8buf,strlen(utf8buf)+1));
538 : }
539 :
540 0 : unichar_t *utf82u_copyn(const char *utf8buf,int len) {
541 0 : unichar_t *ubuf = (unichar_t *) malloc((len+1)*sizeof(unichar_t));
542 0 : return( utf82u_strncpy(ubuf,utf8buf,len+1));
543 : }
544 :
545 203480 : unichar_t *utf82u_copy(const char *utf8buf) {
546 : int len;
547 : unichar_t *ubuf;
548 :
549 203480 : if ( utf8buf==NULL )
550 20 : return( NULL );
551 :
552 203460 : len = strlen(utf8buf);
553 203460 : ubuf = (unichar_t *) malloc((len+1)*sizeof(unichar_t));
554 203460 : return( utf82u_strncpy(ubuf,utf8buf,len+1));
555 : }
556 :
557 0 : void utf82u_strcat(unichar_t *to,const char *from) {
558 0 : utf82u_strcpy(to+u_strlen(to),from);
559 0 : }
560 :
561 0 : char *u2utf8_strcpy(char *utf8buf,const unichar_t *ubuf) {
562 : /* Copy unichar string 'ubuf' into utf8 buffer string 'utf8buf' */
563 0 : char *pt = utf8buf;
564 :
565 0 : if ( ubuf!=NULL ) {
566 0 : while ( *ubuf && (pt=utf8_idpb(pt,*ubuf++,0)) );
567 0 : if ( pt ) {
568 0 : *pt = '\0';
569 0 : return( utf8buf );
570 : }
571 : }
572 0 : return( NULL );
573 : }
574 :
575 0 : char *utf8_strchr(const char *str, int search) {
576 : int ch;
577 0 : const char *old = str;
578 :
579 0 : while ( (ch = utf8_ildb(&str))!=0 ) {
580 0 : if ( ch==search )
581 0 : return( (char *) old );
582 0 : old = str;
583 : }
584 0 : return( NULL );
585 : }
586 :
587 15 : char *latin1_2_utf8_strcpy(char *utf8buf,const char *lbuf) {
588 15 : char *pt = utf8buf;
589 15 : const unsigned char *lpt = (const unsigned char *) lbuf;
590 :
591 511 : while ( *lpt ) {
592 481 : if ( *lpt<0x80 )
593 478 : *pt++ = *lpt;
594 : else {
595 3 : *pt++ = 0xc0 | (*lpt>>6);
596 3 : *pt++ = 0x80 | (*lpt&0x3f);
597 : }
598 481 : ++lpt;
599 : }
600 15 : *pt = '\0';
601 15 : return( utf8buf );
602 : }
603 :
604 15 : char *latin1_2_utf8_copy(const char *lbuf) {
605 : int len;
606 : char *utf8buf;
607 :
608 15 : if ( lbuf==NULL )
609 0 : return( NULL );
610 :
611 15 : len = strlen(lbuf);
612 15 : utf8buf = (char *) malloc(2*len+1);
613 15 : return( latin1_2_utf8_strcpy(utf8buf,lbuf));
614 : }
615 :
616 0 : char *utf8_2_latin1_copy(const char *utf8buf) {
617 : int len;
618 : int ch;
619 : char *lbuf, *pt; const char *upt;
620 :
621 0 : if ( utf8buf==NULL )
622 0 : return( NULL );
623 :
624 0 : len = strlen(utf8buf);
625 0 : pt = lbuf = (char *) malloc(len+1);
626 0 : for ( upt=utf8buf; (ch=utf8_ildb(&upt))!='\0'; )
627 0 : if ( ch>=0xff )
628 0 : *pt++ = '?';
629 : else
630 0 : *pt++ = ch;
631 0 : *pt = '\0';
632 0 : return( lbuf );
633 : }
634 :
635 637 : char *u2utf8_copy(const unichar_t *ubuf) {
636 : /* Make a utf8 string copy of unichar string ubuf */
637 :
638 637 : if ( ubuf==NULL )
639 0 : return( NULL );
640 :
641 637 : return( u2utf8_copyn(ubuf,u_strlen(ubuf)+1) );
642 : }
643 :
644 637 : char *u2utf8_copyn(const unichar_t *ubuf,int len) {
645 : /* Make a utf8 string copy of unichar string ubuf[0..len] */
646 : char *utf8buf, *pt;
647 :
648 637 : if ( ubuf==NULL || len<=0 || (utf8buf=pt=(char *)malloc(len*6+1))==NULL )
649 0 : return( NULL );
650 :
651 637 : while ( (pt=utf8_idpb(pt,*ubuf++,0)) && --len );
652 637 : if ( pt ) {
653 637 : *pt = '\0';
654 637 : return( utf8buf );
655 : }
656 0 : free( utf8buf );
657 0 : return( NULL );
658 : }
659 :
660 63376 : int32 utf8_ildb(const char **_text) {
661 63376 : int32 val= -1;
662 : int ch;
663 63376 : const uint8 *text = (const uint8 *) *_text;
664 : /* Increment and load character */
665 :
666 63376 : if ( text==NULL )
667 0 : return( val );
668 63376 : else if ( (ch = *text++)<0x80 ) {
669 61313 : val = ch;
670 2063 : } else if ( ch<=0xbf ) {
671 : /* error */
672 2061 : } else if ( ch<=0xdf ) {
673 2026 : if ( *text>=0x80 && *text<0xc0 )
674 2026 : val = ((ch&0x1f)<<6) | (*text++&0x3f);
675 35 : } else if ( ch<=0xef ) {
676 34 : if ( *text>=0x80 && *text<0xc0 && text[1]>=0x80 && text[1]<0xc0 ) {
677 34 : val = ((ch&0xf)<<12) | ((text[0]&0x3f)<<6) | (text[1]&0x3f);
678 34 : text += 2;
679 : }
680 : } else {
681 1 : int w = ( ((ch&0x7)<<2) | ((text[0]&0x30)>>4) )-1, w2;
682 1 : w = (w<<6) | ((text[0]&0xf)<<2) | ((text[1]&0x30)>>4);
683 1 : w2 = ((text[1]&0xf)<<6) | (text[2]&0x3f);
684 1 : val = w*0x400 + w2 + 0x10000;
685 1 : if ( *text<0x80 || text[1]<0x80 || text[2]<0x80 ||
686 0 : *text>=0xc0 || text[1]>=0xc0 || text[2]>=0xc0 )
687 1 : val = -1;
688 : else
689 0 : text += 3;
690 : }
691 63376 : *_text = (const char *) text;
692 63376 : return( val );
693 : }
694 :
695 74896 : char *utf8_idpb(char *utf8_text,uint32 ch,int flags) {
696 : /* Increment and deposit character, no '\0' appended */
697 : /* NOTE: Unicode only needs range of 17x65535 values */
698 : /* and strings must be long enough to hold +4 chars. */
699 : /* ISO/IEC 10646 description of UTF8 allows encoding */
700 : /* character values up to U+7FFFFFFF before RFC3629. */
701 :
702 149792 : if ( ch>0x7fffffff || \
703 149792 : (!(flags&UTF8IDPB_OLDLIMIT) && ((ch>=0xd800 && ch<=0xdfff) || ch>=17*65536)) )
704 0 : return( 0 ); /* Error, ch is out of range */
705 :
706 74896 : if ( (flags&(UTF8IDPB_UCS2|UTF8IDPB_UTF16|UTF8IDPB_UTF32)) ) {
707 0 : if ( (flags&UTF8IDPB_UCS2) && ch>0xffff )
708 0 : return( 0 ); /* Error, ch is out of range */
709 0 : if ( (flags&UTF8IDPB_UTF32) ) {
710 0 : *utf8_text++ = ((ch>>24)&0xff);
711 0 : *utf8_text++ = ((ch>>16)&0xff);
712 0 : ch &= 0xffff;
713 : }
714 0 : if ( ch>0xffff ) {
715 : /* ...here if a utf16 encoded value */
716 : unsigned long us;
717 0 : ch -= 0x10000;
718 0 : us = (ch>>10)+0xd800;
719 0 : *utf8_text++ = us>>8;
720 0 : *utf8_text++ = us&0xff;
721 0 : ch = (ch&0x3ff)+0xdc00;
722 : }
723 0 : *utf8_text++ = ch>>8;
724 0 : ch &= 0xff;
725 74896 : } else if ( ch>127 || (ch==0 && (flags&UTF8IDPB_NOZERO)) ) {
726 3724 : if ( ch<=0x7ff )
727 : /* ch>=0x80 && ch<=0x7ff */
728 3692 : *utf8_text++ = 0xc0 | (ch>>6);
729 : else {
730 32 : if ( ch<=0xffff )
731 : /* ch>=0x800 && ch<=0xffff */
732 32 : *utf8_text++ = 0xe0 | (ch>>12);
733 : else {
734 0 : if ( ch<=0x1fffff )
735 : /* ch>=0x10000 && ch<=0x1fffff */
736 0 : *utf8_text++ = 0xf0 | (ch>>18);
737 : else {
738 0 : if ( ch<=0x3ffffff )
739 : /* ch>=0x200000 && ch<=0x3ffffff */
740 0 : *utf8_text++ = 0xf8 | (ch>>24);
741 : else {
742 : /* ch>=0x4000000 && ch<=0x7fffffff */
743 0 : *utf8_text++ = 0xfc | (ch>>30);
744 0 : *utf8_text++ = 0x80 | ((ch>>24)&0x3f);
745 : }
746 0 : *utf8_text++ = 0x80 | ((ch>>18)&0x3f);
747 : }
748 0 : *utf8_text++ = 0x80 | ((ch>>12)&0x3f);
749 : }
750 32 : *utf8_text++ = 0x80 | ((ch>>6)&0x3f);
751 : }
752 3724 : ch = 0x80 | (ch&0x3f);
753 : }
754 74896 : *utf8_text++ = ch;
755 74896 : return( utf8_text );
756 : }
757 :
758 0 : char *utf8_ib(char *utf8_text) {
759 : /* Increment to next utf8 character */
760 : unsigned char ch;
761 :
762 0 : if ( (ch = (unsigned char) *utf8_text)=='\0' )
763 0 : return( utf8_text );
764 0 : else if ( ch<=127 )
765 0 : return( utf8_text+1 );
766 0 : else if ( ch<0xe0 )
767 0 : return( utf8_text+2 );
768 0 : else if ( ch<0xf0 )
769 0 : return( utf8_text+3 );
770 0 : else if ( ch<0xf8 )
771 0 : return( utf8_text+4 );
772 0 : else if ( ch<0xfc )
773 0 : return( utf8_text+5 );
774 : else
775 0 : return( utf8_text+6 );
776 : }
777 :
778 279 : int utf8_valid(const char *str) {
779 : /* Is this a valid utf8 string? */
780 : int ch;
781 :
782 9641 : while ( (ch=utf8_ildb(&str))!='\0' )
783 9086 : if ( ch==-1 )
784 3 : return( false );
785 :
786 276 : return( true );
787 : }
788 :
789 0 : void utf8_truncatevalid(char *str) {
790 : /* There are certain cases where we have a fixed amount of space to display */
791 : /* something, and if it doesn't fit in that, then we truncate it. But... */
792 : /* that can leave us with a half completed utf8 byte sequence. So truncate*/
793 : /* again, right before the start of the bad sequence */
794 : int ch;
795 : char *old;
796 :
797 0 : old = str;
798 0 : while ( (ch=utf8_ildb((const char **) &str))!='\0' ) {
799 0 : if ( ch==-1 ) {
800 0 : *old = '\0';
801 0 : return;
802 : }
803 0 : old = str;
804 : }
805 : }
806 :
807 0 : char *utf8_db(char *utf8_text) {
808 : /* Decrement utf8 pointer to previous utf8 character.*/
809 : /* NOTE: This should never happen but if the pointer */
810 : /* was looking at an intermediate character, it will */
811 : /* be properly positioned at the start of a new char */
812 : /* and not the previous character. */
813 0 : unsigned char *pt = (unsigned char *) utf8_text;
814 :
815 0 : --pt;
816 0 : if ( *pt>=0x80 && *pt<0xc0 ) {
817 0 : --pt;
818 0 : if ( *pt>=0x80 && *pt<0xc0 ) {
819 0 : --pt;
820 0 : if ( *pt>=0x80 && *pt<0xc0 ) {
821 0 : --pt;
822 0 : if ( *pt>=0x80 && *pt<0xc0 ) {
823 0 : --pt;
824 0 : if ( *pt>=0x80 && *pt<0xc0 )
825 0 : --pt;
826 : }
827 : }
828 : }
829 : }
830 0 : return( (char *) pt );
831 : }
832 :
833 0 : long utf8_strlen(const char *utf8_str) {
834 : /* Count how many characters in the string NOT bytes */
835 0 : long len = 0;
836 :
837 0 : while ( utf8_ildb(&utf8_str)>0 && ++len>0 );
838 0 : return( len );
839 : }
840 :
841 480 : long utf82u_strlen(const char *utf8_str) {
842 : /* Count how many shorts needed to represent in UCS2 */
843 : int32 ch;
844 480 : long len = 0;
845 :
846 28812 : while ( (ch = utf8_ildb(&utf8_str))>0 && ++len>0 )
847 27852 : if ( ch>=0x10000 )
848 0 : ++len;
849 480 : return( len );
850 : }
851 :
852 0 : void utf8_strncpy(register char *to, const char *from, int len) {
853 : /* copy n characters NOT bytes */
854 0 : const char *old = from;
855 0 : while ( len && *old ) {
856 0 : utf8_ildb(&old);
857 0 : len--;
858 : }
859 0 : strncpy(to, from, old-from);
860 0 : to[old-from] = 0;
861 0 : }
862 :
863 : #include <chardata.h>
864 4 : char *StripToASCII(const char *utf8_str) {
865 : /* Remove any non-ascii characters: Special case, convert the copyright symbol to (c) */
866 : char *newcr, *pt, *end;
867 : int len, ch;
868 : const unichar_t *alt;
869 :
870 4 : len = strlen(utf8_str);
871 4 : pt = newcr = (char *) malloc(len+1);
872 4 : end = pt+len;
873 181 : while ( (ch= utf8_ildb(&utf8_str))!='\0' ) {
874 173 : if ( pt>=end ) {
875 4 : int off = pt-newcr;
876 4 : newcr = (char *) realloc(newcr,(off+10)+1);
877 4 : pt = newcr+off;
878 4 : end = pt+10;
879 : }
880 173 : if ( (ch>=' ' && ch<'\177' ) || ch=='\n' || ch=='\t' )
881 169 : *pt++ = ch;
882 4 : else if ( ch=='\r' && *utf8_str!='\n' )
883 0 : *pt++ = '\n';
884 4 : else if ( ch==0xa9 /* Copyright sign */ ) {
885 4 : const char *str = "(c)";
886 4 : if ( pt+strlen(str)>=end ) {
887 0 : int off = pt-newcr;
888 0 : newcr = (char *) realloc(newcr,(off+10+strlen(str))+1);
889 0 : pt = newcr+off;
890 0 : end = pt+10;
891 : }
892 20 : while ( *str )
893 12 : *pt++ = *str++;
894 0 : } else if ( unicode_alternates[ch>>8]!=NULL &&
895 0 : (alt = unicode_alternates[ch>>8][ch&0xff])!=NULL ) {
896 0 : while ( *alt!='\0' ) {
897 0 : if ( pt>=end ) {
898 0 : int off = pt-newcr;
899 0 : newcr = (char *) realloc(newcr,(off+10)+1);
900 0 : pt = newcr+off;
901 0 : end = pt+10;
902 : }
903 0 : if ( *alt>=' ' && *alt<'\177' )
904 0 : *pt++ = *alt;
905 0 : else if ( *alt==0x300 )
906 0 : *pt++ = '`';
907 0 : else if ( *alt==0x301 )
908 0 : *pt++ = '\'';
909 0 : else if ( *alt==0x302 )
910 0 : *pt++ = '^';
911 0 : else if ( *alt==0x303 )
912 0 : *pt++ = '~';
913 0 : else if ( *alt==0x308 )
914 0 : *pt++ = ':';
915 0 : ++alt;
916 : }
917 : }
918 : }
919 4 : *pt = '\0';
920 4 : return( newcr );
921 : }
922 :
923 2477 : int AllAscii(const char *txt) {
924 23574 : for ( ; *txt!='\0'; ++txt ) {
925 21101 : if ( *txt=='\t' || *txt=='\n' || *txt=='\r' )
926 : /* All right */;
927 21094 : else if ( *txt<' ' || *txt>='\177' )
928 4 : return( false );
929 : }
930 2473 : return( true );
931 : }
932 :
933 0 : int uAllAscii(const unichar_t *txt) {
934 0 : for ( ; *txt!='\0'; ++txt ) {
935 0 : if ( *txt=='\t' || *txt=='\n' || *txt=='\r' )
936 : /* All right */;
937 0 : else if ( *txt<' ' || *txt>='\177' )
938 0 : return( false );
939 : }
940 0 : return( true );
941 : }
942 :
943 0 : char* chomp( char* line ) {
944 0 : if( !line )
945 0 : return line;
946 0 : if ( line[strlen(line)-1]=='\n' )
947 0 : line[strlen(line)-1] = '\0';
948 0 : if ( line[strlen(line)-1]=='\r' )
949 0 : line[strlen(line)-1] = '\0';
950 0 : return line;
951 : }
952 :
953 0 : char *copytolower(const char *input)
954 : {
955 0 : char* ret = copy(input);
956 0 : char* p = ret;
957 0 : for( ; *p; ++p ) {
958 0 : *p = tolower(*p);
959 : }
960 0 : return ret;
961 : }
962 :
963 :
964 0 : int endswith(const char *haystack,const char *needle) {
965 0 : int haylen = strlen( haystack );
966 0 : int nedlen = strlen( needle );
967 0 : if( haylen < nedlen )
968 0 : return 0;
969 0 : char* p = strstr( haystack + haylen - nedlen, needle );
970 0 : return p == ( haystack + haylen - nedlen );
971 : }
972 :
973 0 : int endswithi(const char *haystackZ,const char *needleZ) {
974 0 : char* haystack = copytolower(haystackZ);
975 0 : char* needle = copytolower(needleZ);
976 0 : int ret = endswith( haystack, needle );
977 0 : free( haystack );
978 0 : free( needle );
979 0 : return ret;
980 : }
981 :
982 0 : int endswithi_partialExtension( const char *haystackZ,const char *needleZ) {
983 0 : int nedlen = strlen(needleZ);
984 0 : if( nedlen == 0 ) {
985 0 : return 0;
986 : }
987 0 : char* haystack = copytolower(haystackZ);
988 0 : char* needle = copytolower(needleZ);
989 0 : int ret = 0;
990 0 : int i = nedlen-1;
991 0 : ret |= endswith( haystack, needle );
992 0 : for( ; i>=0 && !ret ; --i ) {
993 0 : needle[i] = '\0';
994 0 : ret |= endswith( haystack, needle );
995 : }
996 0 : free( haystack );
997 0 : free( needle );
998 0 : return ret;
999 : }
1000 :
1001 0 : int u_endswith(const unichar_t *haystack,const unichar_t *needle) {
1002 0 : int haylen = u_strlen( haystack );
1003 0 : int nedlen = u_strlen( needle );
1004 0 : if( haylen < nedlen )
1005 0 : return 0;
1006 0 : unichar_t* p = u_strstr( haystack + haylen - nedlen, needle );
1007 0 : return p == ( haystack + haylen - nedlen );
1008 : }
1009 :
1010 0 : int u_startswith(const unichar_t *haystack,const unichar_t *needle) {
1011 :
1012 0 : if( !haystack || !needle )
1013 0 : return 0;
1014 :
1015 0 : unichar_t* p = u_strstr( haystack, needle );
1016 0 : return p == ( haystack );
1017 : }
1018 :
1019 0 : int uc_startswith(const unichar_t *haystack,const char* needle)
1020 : {
1021 0 : return u_startswith( haystack, c_to_u(needle));
1022 : }
1023 :
1024 :
1025 0 : char* c_itostr( int v )
1026 : {
1027 : static char ret[100+1];
1028 0 : snprintf(ret,100,"%d",v );
1029 0 : return ret;
1030 : }
1031 :
1032 0 : char* str_replace_all( char* s, char* orig, char* replacement, int free_s )
1033 : {
1034 0 : char* p = strstr( s, orig );
1035 0 : if( !p )
1036 : {
1037 0 : if( free_s )
1038 0 : return s;
1039 0 : return copy( s );
1040 : }
1041 :
1042 0 : int count = 0;
1043 0 : p = s;
1044 0 : while( p )
1045 : {
1046 0 : p = strstr( p, orig );
1047 0 : if( !p )
1048 0 : break;
1049 0 : p++;
1050 0 : count++;
1051 : }
1052 0 : count++;
1053 :
1054 : // more than strictly needed, but always enough RAM.
1055 0 : int retsz = strlen(s) + count*strlen(replacement) + 1;
1056 0 : char* ret = (char *) malloc( retsz );
1057 0 : memset( ret, '\0', retsz );
1058 0 : char* output = ret;
1059 0 : char* remains = s;
1060 0 : p = remains;
1061 0 : while( p )
1062 : {
1063 0 : p = strstr( remains, orig );
1064 0 : if( !p )
1065 : {
1066 0 : strcpy( output, remains );
1067 0 : break;
1068 : }
1069 0 : if( p > remains )
1070 0 : strncpy( output, remains, p-remains );
1071 0 : strcat( output, replacement );
1072 0 : output += strlen(output);
1073 0 : remains = p + strlen(orig);
1074 : }
1075 :
1076 0 : if( free_s )
1077 0 : free(s);
1078 0 : return ret;
1079 : }
1080 :
1081 0 : int toint( char* v )
1082 : {
1083 0 : if( !v )
1084 0 : return 0;
1085 0 : return atoi(v);
1086 : }
1087 0 : char* tostr( int v )
1088 : {
1089 0 : const int bufsz = 100;
1090 : static char buf[101];
1091 0 : snprintf(buf,bufsz,"%d",v);
1092 0 : return buf;
1093 : }
|