]> git.wh0rd.org - fontconfig.git/blob - src/fcstr.c
Change RCS tag
[fontconfig.git] / src / fcstr.c
1 /*
2 * $RCSId: xc/lib/fontconfig/src/fcstr.c,v 1.10 2002/08/31 22:17:32 keithp Exp $
3 *
4 * Copyright © 2000 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include "fcint.h"
29
30 FcChar8 *
31 FcStrCopy (const FcChar8 *s)
32 {
33 FcChar8 *r;
34
35 if (!s)
36 return 0;
37 r = (FcChar8 *) malloc (strlen ((char *) s) + 1);
38 if (!r)
39 return 0;
40 FcMemAlloc (FC_MEM_STRING, strlen ((char *) s) + 1);
41 strcpy ((char *) r, (char *) s);
42 return r;
43 }
44
45 FcChar8 *
46 FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
47 {
48 int l = strlen ((char *)s1) + strlen ((char *) s2) + 1;
49 FcChar8 *s = malloc (l);
50
51 if (!s)
52 return 0;
53 FcMemAlloc (FC_MEM_STRING, l);
54 strcpy ((char *) s, (char *) s1);
55 strcat ((char *) s, (char *) s2);
56 return s;
57 }
58
59 void
60 FcStrFree (FcChar8 *s)
61 {
62 FcMemFree (FC_MEM_STRING, strlen ((char *) s) + 1);
63 free (s);
64 }
65
66 int
67 FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
68 {
69 FcChar8 c1, c2;
70
71 for (;;)
72 {
73 c1 = *s1++;
74 c2 = *s2++;
75 if (!c1)
76 break;
77 if (c1 != c2)
78 {
79 c1 = FcToLower (c1);
80 c2 = FcToLower (c2);
81 if (c1 != c2)
82 break;
83 }
84 }
85 return (int) c1 - (int) c2;
86 }
87
88 int
89 FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
90 {
91 FcChar8 c1, c2;
92
93 for (;;)
94 {
95 do
96 c1 = *s1++;
97 while (c1 == ' ');
98 do
99 c2 = *s2++;
100 while (c2 == ' ');
101 if (!c1 || !c2)
102 break;
103 c1 = FcToLower (c1);
104 c2 = FcToLower (c2);
105 if (c1 != c2)
106 break;
107 }
108 return (int) c1 - (int) c2;
109 }
110
111 int
112 FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
113 {
114 FcChar8 c1, c2;
115
116 if (s1 == s2)
117 return 0;
118 for (;;)
119 {
120 c1 = *s1++;
121 c2 = *s2++;
122 if (!c1 || !c2)
123 break;
124 if (c1 != c2)
125 break;
126 }
127 return (int) c1 - (int) c2;
128 }
129
130 int
131 FcUtf8ToUcs4 (const FcChar8 *src_orig,
132 FcChar32 *dst,
133 int len)
134 {
135 const FcChar8 *src = src_orig;
136 FcChar8 s;
137 int extra;
138 FcChar32 result;
139
140 if (len == 0)
141 return 0;
142
143 s = *src++;
144 len--;
145
146 if (!(s & 0x80))
147 {
148 result = s;
149 extra = 0;
150 }
151 else if (!(s & 0x40))
152 {
153 return -1;
154 }
155 else if (!(s & 0x20))
156 {
157 result = s & 0x1f;
158 extra = 1;
159 }
160 else if (!(s & 0x10))
161 {
162 result = s & 0xf;
163 extra = 2;
164 }
165 else if (!(s & 0x08))
166 {
167 result = s & 0x07;
168 extra = 3;
169 }
170 else if (!(s & 0x04))
171 {
172 result = s & 0x03;
173 extra = 4;
174 }
175 else if ( ! (s & 0x02))
176 {
177 result = s & 0x01;
178 extra = 5;
179 }
180 else
181 {
182 return -1;
183 }
184 if (extra > len)
185 return -1;
186
187 while (extra--)
188 {
189 result <<= 6;
190 s = *src++;
191
192 if ((s & 0xc0) != 0x80)
193 return -1;
194
195 result |= s & 0x3f;
196 }
197 *dst = result;
198 return src - src_orig;
199 }
200
201 FcBool
202 FcUtf8Len (const FcChar8 *string,
203 int len,
204 int *nchar,
205 int *wchar)
206 {
207 int n;
208 int clen;
209 FcChar32 c;
210 FcChar32 max;
211
212 n = 0;
213 max = 0;
214 while (len)
215 {
216 clen = FcUtf8ToUcs4 (string, &c, len);
217 if (clen <= 0) /* malformed UTF8 string */
218 return FcFalse;
219 if (c > max)
220 max = c;
221 string += clen;
222 len -= clen;
223 n++;
224 }
225 *nchar = n;
226 if (max >= 0x10000)
227 *wchar = 4;
228 else if (max > 0x100)
229 *wchar = 2;
230 else
231 *wchar = 1;
232 return FcTrue;
233 }
234
235 int
236 FcUcs4ToUtf8 (FcChar32 ucs4,
237 FcChar8 dest[FC_UTF8_MAX_LEN])
238 {
239 int bits;
240 FcChar8 *d = dest;
241
242 if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
243 else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
244 else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
245 else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
246 else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
247 else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
248 else return 0;
249
250 for ( ; bits >= 0; bits-= 6) {
251 *d++= ((ucs4 >> bits) & 0x3F) | 0x80;
252 }
253 return d - dest;
254 }
255
256 #define GetUtf16(src,endian) \
257 ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
258 (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
259
260 int
261 FcUtf16ToUcs4 (const FcChar8 *src_orig,
262 FcEndian endian,
263 FcChar32 *dst,
264 int len) /* in bytes */
265 {
266 const FcChar8 *src = src_orig;
267 FcChar16 a, b;
268 FcChar32 result;
269
270 if (len < 2)
271 return 0;
272
273 a = GetUtf16 (src, endian); src += 2; len -= 2;
274
275 /*
276 * Check for surrogate
277 */
278 if ((a & 0xfc00) == 0xd800)
279 {
280 if (len < 2)
281 return 0;
282 b = GetUtf16 (src, endian); src += 2; len -= 2;
283 /*
284 * Check for invalid surrogate sequence
285 */
286 if ((b & 0xfc00) != 0xdc00)
287 return 0;
288 result = ((((FcChar32) a & 0x3ff) << 10) |
289 ((FcChar32) b & 0x3ff)) + 0x10000;
290 }
291 else
292 result = a;
293 *dst = result;
294 return src - src_orig;
295 }
296
297 FcBool
298 FcUtf16Len (const FcChar8 *string,
299 FcEndian endian,
300 int len, /* in bytes */
301 int *nchar,
302 int *wchar)
303 {
304 int n;
305 int clen;
306 FcChar32 c;
307 FcChar32 max;
308
309 n = 0;
310 max = 0;
311 while (len)
312 {
313 clen = FcUtf16ToUcs4 (string, endian, &c, len);
314 if (clen <= 0) /* malformed UTF8 string */
315 return FcFalse;
316 if (c > max)
317 max = c;
318 string += clen;
319 len -= clen;
320 n++;
321 }
322 *nchar = n;
323 if (max >= 0x10000)
324 *wchar = 4;
325 else if (max > 0x100)
326 *wchar = 2;
327 else
328 *wchar = 1;
329 return FcTrue;
330 }
331
332 void
333 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
334 {
335 buf->buf = init;
336 buf->allocated = FcFalse;
337 buf->failed = FcFalse;
338 buf->len = 0;
339 buf->size = size;
340 }
341
342 void
343 FcStrBufDestroy (FcStrBuf *buf)
344 {
345 if (buf->allocated)
346 {
347 FcMemFree (FC_MEM_STRBUF, buf->size);
348 free (buf->buf);
349 FcStrBufInit (buf, 0, 0);
350 }
351 }
352
353 FcChar8 *
354 FcStrBufDone (FcStrBuf *buf)
355 {
356 FcChar8 *ret;
357
358 ret = malloc (buf->len + 1);
359 if (ret)
360 {
361 FcMemAlloc (FC_MEM_STRING, buf->len + 1);
362 memcpy (ret, buf->buf, buf->len);
363 ret[buf->len] = '\0';
364 }
365 FcStrBufDestroy (buf);
366 return ret;
367 }
368
369 FcBool
370 FcStrBufChar (FcStrBuf *buf, FcChar8 c)
371 {
372 if (buf->len == buf->size)
373 {
374 FcChar8 *new;
375 int size;
376
377 if (buf->allocated)
378 {
379 size = buf->size * 2;
380 new = realloc (buf->buf, size);
381 }
382 else
383 {
384 size = buf->size + 1024;
385 new = malloc (size);
386 if (new)
387 {
388 buf->allocated = FcTrue;
389 memcpy (new, buf->buf, buf->len);
390 }
391 }
392 if (!new)
393 {
394 buf->failed = FcTrue;
395 return FcFalse;
396 }
397 if (buf->size)
398 FcMemFree (FC_MEM_STRBUF, buf->size);
399 FcMemAlloc (FC_MEM_STRBUF, size);
400 buf->size = size;
401 buf->buf = new;
402 }
403 buf->buf[buf->len++] = c;
404 return FcTrue;
405 }
406
407 FcBool
408 FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
409 {
410 FcChar8 c;
411 while ((c = *s++))
412 if (!FcStrBufChar (buf, c))
413 return FcFalse;
414 return FcTrue;
415 }
416
417 FcBool
418 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
419 {
420 while (len-- > 0)
421 if (!FcStrBufChar (buf, *s++))
422 return FcFalse;
423 return FcTrue;
424 }
425
426 FcBool
427 FcStrUsesHome (const FcChar8 *s)
428 {
429 return *s == '~';
430 }
431
432 FcChar8 *
433 FcStrCopyFilename (const FcChar8 *s)
434 {
435 FcChar8 *new;
436
437 if (*s == '~')
438 {
439 FcChar8 *home = FcConfigHome ();
440 int size;
441 if (!home)
442 return 0;
443 size = strlen ((char *) home) + strlen ((char *) s);
444 new = (FcChar8 *) malloc (size);
445 if (!new)
446 return 0;
447 FcMemAlloc (FC_MEM_STRING, size);
448 strcpy ((char *) new, (char *) home);
449 strcat ((char *) new, (char *) s + 1);
450 }
451 else
452 {
453 int size = strlen ((char *) s) + 1;
454 new = (FcChar8 *) malloc (size);
455 if (!new)
456 return 0;
457 FcMemAlloc (FC_MEM_STRING, size);
458 strcpy ((char *) new, (const char *) s);
459 }
460 return new;
461 }
462
463 FcChar8 *
464 FcStrDirname (const FcChar8 *file)
465 {
466 FcChar8 *slash;
467 FcChar8 *dir;
468
469 slash = (FcChar8 *) strrchr ((char *) file, '/');
470 if (!slash)
471 return FcStrCopy ((FcChar8 *) ".");
472 dir = malloc ((slash - file) + 1);
473 if (!dir)
474 return 0;
475 FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
476 strncpy ((char *) dir, (const char *) file, slash - file);
477 dir[slash - file] = '\0';
478 return dir;
479 }
480
481 FcChar8 *
482 FcStrBasename (const FcChar8 *file)
483 {
484 FcChar8 *slash;
485
486 slash = (FcChar8 *) strrchr ((char *) file, '/');
487 if (!slash)
488 return FcStrCopy (file);
489 return FcStrCopy (slash + 1);
490 }
491
492 FcStrSet *
493 FcStrSetCreate (void)
494 {
495 FcStrSet *set = malloc (sizeof (FcStrSet));
496 if (!set)
497 return 0;
498 FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
499 set->ref = 1;
500 set->num = 0;
501 set->size = 0;
502 set->strs = 0;
503 return set;
504 }
505
506 static FcBool
507 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
508 {
509 if (FcStrSetMember (set, s))
510 {
511 FcStrFree (s);
512 return FcTrue;
513 }
514 if (set->num == set->size)
515 {
516 FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
517
518 if (!strs)
519 return FcFalse;
520 FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
521 set->size = set->size + 1;
522 if (set->num)
523 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
524 if (set->strs)
525 free (set->strs);
526 set->strs = strs;
527 }
528 set->strs[set->num++] = s;
529 set->strs[set->num] = 0;
530 return FcTrue;
531 }
532
533 FcBool
534 FcStrSetMember (FcStrSet *set, const FcChar8 *s)
535 {
536 int i;
537
538 for (i = 0; i < set->num; i++)
539 if (!FcStrCmp (set->strs[i], s))
540 return FcTrue;
541 return FcFalse;
542 }
543
544 FcBool
545 FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
546 {
547 int i;
548 if (sa->num != sb->num)
549 return FcFalse;
550 for (i = 0; i < sa->num; i++)
551 if (!FcStrSetMember (sb, sa->strs[i]))
552 return FcFalse;
553 return FcTrue;
554 }
555
556 FcBool
557 FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
558 {
559 FcChar8 *new = FcStrCopy (s);
560 if (!new)
561 return FcFalse;
562 if (!_FcStrSetAppend (set, new))
563 {
564 FcStrFree (new);
565 return FcFalse;
566 }
567 return FcTrue;
568 }
569
570 FcBool
571 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
572 {
573 FcChar8 *new = FcStrCopyFilename (s);
574 if (!new)
575 return FcFalse;
576 if (!_FcStrSetAppend (set, new))
577 {
578 FcStrFree (new);
579 return FcFalse;
580 }
581 return FcTrue;
582 }
583
584 FcBool
585 FcStrSetDel (FcStrSet *set, const FcChar8 *s)
586 {
587 int i;
588
589 for (i = 0; i < set->num; i++)
590 if (!FcStrCmp (set->strs[i], s))
591 {
592 FcStrFree (set->strs[i]);
593 /*
594 * copy remaining string pointers and trailing
595 * NULL
596 */
597 memmove (&set->strs[i], &set->strs[i+1],
598 (set->num - i) * sizeof (FcChar8 *));
599 set->num--;
600 return FcTrue;
601 }
602 return FcFalse;
603 }
604
605 void
606 FcStrSetDestroy (FcStrSet *set)
607 {
608 if (--set->ref == 0)
609 {
610 int i;
611
612 for (i = 0; i < set->num; i++)
613 FcStrFree (set->strs[i]);
614 FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
615 if (set->strs)
616 free (set->strs);
617 FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
618 free (set);
619 }
620 }
621
622 FcStrList *
623 FcStrListCreate (FcStrSet *set)
624 {
625 FcStrList *list;
626
627 list = malloc (sizeof (FcStrList));
628 if (!list)
629 return 0;
630 FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
631 list->set = set;
632 set->ref++;
633 list->n = 0;
634 return list;
635 }
636
637 FcChar8 *
638 FcStrListNext (FcStrList *list)
639 {
640 if (list->n >= list->set->num)
641 return 0;
642 return list->set->strs[list->n++];
643 }
644
645 void
646 FcStrListDone (FcStrList *list)
647 {
648 FcStrSetDestroy (list->set);
649 FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
650 free (list);
651 }