]> git.wh0rd.org - fontconfig.git/blob - src/fcstr.c
More complete memory tracking. Install always overwrites header files
[fontconfig.git] / src / fcstr.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcstr.c,v 1.7 2002/07/13 05:43:25 keithp Exp $
3 *
4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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 || !c2)
76 break;
77 c1 = FcToLower (c1);
78 c2 = FcToLower (c2);
79 if (c1 != c2)
80 break;
81 }
82 return (int) c1 - (int) c2;
83 }
84
85 int
86 FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
87 {
88 FcChar8 c1, c2;
89
90 for (;;)
91 {
92 do
93 c1 = *s1++;
94 while (c1 == ' ');
95 do
96 c2 = *s2++;
97 while (c2 == ' ');
98 if (!c1 || !c2)
99 break;
100 c1 = FcToLower (c1);
101 c2 = FcToLower (c2);
102 if (c1 != c2)
103 break;
104 }
105 return (int) c1 - (int) c2;
106 }
107
108 int
109 FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
110 {
111 FcChar8 c1, c2;
112
113 if (s1 == s2)
114 return 0;
115 for (;;)
116 {
117 c1 = *s1++;
118 c2 = *s2++;
119 if (!c1 || !c2)
120 break;
121 if (c1 != c2)
122 break;
123 }
124 return (int) c1 - (int) c2;
125 }
126
127 int
128 FcUtf8ToUcs4 (const FcChar8 *src_orig,
129 FcChar32 *dst,
130 int len)
131 {
132 const FcChar8 *src = src_orig;
133 FcChar8 s;
134 int extra;
135 FcChar32 result;
136
137 if (len == 0)
138 return 0;
139
140 s = *src++;
141 len--;
142
143 if (!(s & 0x80))
144 {
145 result = s;
146 extra = 0;
147 }
148 else if (!(s & 0x40))
149 {
150 return -1;
151 }
152 else if (!(s & 0x20))
153 {
154 result = s & 0x1f;
155 extra = 1;
156 }
157 else if (!(s & 0x10))
158 {
159 result = s & 0xf;
160 extra = 2;
161 }
162 else if (!(s & 0x08))
163 {
164 result = s & 0x07;
165 extra = 3;
166 }
167 else if (!(s & 0x04))
168 {
169 result = s & 0x03;
170 extra = 4;
171 }
172 else if ( ! (s & 0x02))
173 {
174 result = s & 0x01;
175 extra = 5;
176 }
177 else
178 {
179 return -1;
180 }
181 if (extra > len)
182 return -1;
183
184 while (extra--)
185 {
186 result <<= 6;
187 s = *src++;
188
189 if ((s & 0xc0) != 0x80)
190 return -1;
191
192 result |= s & 0x3f;
193 }
194 *dst = result;
195 return src - src_orig;
196 }
197
198 FcBool
199 FcUtf8Len (const FcChar8 *string,
200 int len,
201 int *nchar,
202 int *wchar)
203 {
204 int n;
205 int clen;
206 FcChar32 c;
207 FcChar32 max;
208
209 n = 0;
210 max = 0;
211 while (len)
212 {
213 clen = FcUtf8ToUcs4 (string, &c, len);
214 if (clen <= 0) /* malformed UTF8 string */
215 return FcFalse;
216 if (c > max)
217 max = c;
218 string += clen;
219 len -= clen;
220 n++;
221 }
222 *nchar = n;
223 if (max >= 0x10000)
224 *wchar = 4;
225 else if (max > 0x100)
226 *wchar = 2;
227 else
228 *wchar = 1;
229 return FcTrue;
230 }
231
232 int
233 FcUcs4ToUtf8 (FcChar32 ucs4,
234 FcChar8 dest[FC_UTF8_MAX_LEN])
235 {
236 int bits;
237 FcChar8 *d = dest;
238
239 if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
240 else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
241 else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
242 else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
243 else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
244 else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
245 else return 0;
246
247 for ( ; bits >= 0; bits-= 6) {
248 *d++= ((ucs4 >> bits) & 0x3F) | 0x80;
249 }
250 return d - dest;
251 }
252
253 #define GetUtf16(src,endian) \
254 ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
255 (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
256
257 int
258 FcUtf16ToUcs4 (const FcChar8 *src_orig,
259 FcEndian endian,
260 FcChar32 *dst,
261 int len) /* in bytes */
262 {
263 const FcChar8 *src = src_orig;
264 FcChar16 a, b;
265 FcChar32 result;
266
267 if (len < 2)
268 return 0;
269
270 a = GetUtf16 (src, endian); src += 2; len -= 2;
271
272 /*
273 * Check for surrogate
274 */
275 if ((a & 0xfc00) == 0xd800)
276 {
277 if (len < 2)
278 return 0;
279 b = GetUtf16 (src, endian); src += 2; len -= 2;
280 /*
281 * Check for invalid surrogate sequence
282 */
283 if ((b & 0xfc00) != 0xdc00)
284 return 0;
285 result = ((((FcChar32) a & 0x3ff) << 10) |
286 ((FcChar32) b & 0x3ff)) | 0x10000;
287 }
288 else
289 result = a;
290 *dst = result;
291 return src - src_orig;
292 }
293
294 FcBool
295 FcUtf16Len (const FcChar8 *string,
296 FcEndian endian,
297 int len, /* in bytes */
298 int *nchar,
299 int *wchar)
300 {
301 int n;
302 int clen;
303 FcChar32 c;
304 FcChar32 max;
305
306 n = 0;
307 max = 0;
308 while (len)
309 {
310 clen = FcUtf16ToUcs4 (string, endian, &c, len);
311 if (clen <= 0) /* malformed UTF8 string */
312 return FcFalse;
313 if (c > max)
314 max = c;
315 string += clen;
316 len -= clen;
317 n++;
318 }
319 *nchar = n;
320 if (max >= 0x10000)
321 *wchar = 4;
322 else if (max > 0x100)
323 *wchar = 2;
324 else
325 *wchar = 1;
326 return FcTrue;
327 }
328
329 void
330 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
331 {
332 buf->buf = init;
333 buf->allocated = FcFalse;
334 buf->failed = FcFalse;
335 buf->len = 0;
336 buf->size = size;
337 }
338
339 void
340 FcStrBufDestroy (FcStrBuf *buf)
341 {
342 if (buf->allocated)
343 {
344 FcMemFree (FC_MEM_STRBUF, buf->size);
345 free (buf->buf);
346 FcStrBufInit (buf, 0, 0);
347 }
348 }
349
350 FcChar8 *
351 FcStrBufDone (FcStrBuf *buf)
352 {
353 FcChar8 *ret;
354
355 ret = malloc (buf->len + 1);
356 if (ret)
357 {
358 FcMemAlloc (FC_MEM_STRING, buf->len + 1);
359 memcpy (ret, buf->buf, buf->len);
360 ret[buf->len] = '\0';
361 }
362 FcStrBufDestroy (buf);
363 return ret;
364 }
365
366 FcBool
367 FcStrBufChar (FcStrBuf *buf, FcChar8 c)
368 {
369 if (buf->len == buf->size)
370 {
371 FcChar8 *new;
372 int size;
373
374 if (buf->allocated)
375 {
376 size = buf->size * 2;
377 new = realloc (buf->buf, size);
378 }
379 else
380 {
381 size = buf->size + 1024;
382 new = malloc (size);
383 if (new)
384 {
385 buf->allocated = FcTrue;
386 memcpy (new, buf->buf, buf->len);
387 }
388 }
389 if (!new)
390 {
391 buf->failed = FcTrue;
392 return FcFalse;
393 }
394 if (buf->size)
395 FcMemFree (FC_MEM_STRBUF, buf->size);
396 FcMemAlloc (FC_MEM_STRBUF, size);
397 buf->size = size;
398 buf->buf = new;
399 }
400 buf->buf[buf->len++] = c;
401 return FcTrue;
402 }
403
404 FcBool
405 FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
406 {
407 FcChar8 c;
408 while ((c = *s++))
409 if (!FcStrBufChar (buf, c))
410 return FcFalse;
411 return FcTrue;
412 }
413
414 FcBool
415 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
416 {
417 while (len-- > 0)
418 if (!FcStrBufChar (buf, *s++))
419 return FcFalse;
420 return FcTrue;
421 }
422
423 FcChar8 *
424 FcStrCopyFilename (const FcChar8 *s)
425 {
426 FcChar8 *new;
427
428 if (*s == '~')
429 {
430 FcChar8 *home = (FcChar8 *) getenv ("HOME");
431 int size = strlen ((char *) home) + strlen ((char *) s);
432 if (!home)
433 return 0;
434 new = (FcChar8 *) malloc (size);
435 if (!new)
436 return 0;
437 FcMemAlloc (FC_MEM_STRING, size);
438 strcpy ((char *) new, (char *) home);
439 strcat ((char *) new, (char *) s + 1);
440 }
441 else
442 {
443 int size = strlen ((char *) s) + 1;
444 new = (FcChar8 *) malloc (size);
445 if (!new)
446 return 0;
447 FcMemAlloc (FC_MEM_STRING, size);
448 strcpy ((char *) new, (const char *) s);
449 }
450 return new;
451 }
452
453 FcChar8 *
454 FcStrDirname (const FcChar8 *file)
455 {
456 FcChar8 *slash;
457 FcChar8 *dir;
458
459 slash = (FcChar8 *) strrchr ((char *) file, '/');
460 if (!slash)
461 return FcStrCopy ((FcChar8 *) ".");
462 dir = malloc ((slash - file) + 1);
463 if (!dir)
464 return 0;
465 FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
466 strncpy ((char *) dir, (const char *) file, slash - file);
467 dir[slash - file] = '\0';
468 return dir;
469 }
470
471 FcChar8 *
472 FcStrBasename (const FcChar8 *file)
473 {
474 FcChar8 *slash;
475
476 slash = (FcChar8 *) strrchr ((char *) file, '/');
477 if (!slash)
478 return FcStrCopy (file);
479 return FcStrCopy (slash + 1);
480 }
481
482 FcStrSet *
483 FcStrSetCreate (void)
484 {
485 FcStrSet *set = malloc (sizeof (FcStrSet));
486 if (!set)
487 return 0;
488 FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
489 set->ref = 1;
490 set->num = 0;
491 set->size = 0;
492 set->strs = 0;
493 return set;
494 }
495
496 static FcBool
497 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
498 {
499 if (FcStrSetMember (set, s))
500 {
501 FcStrFree (s);
502 return FcTrue;
503 }
504 if (set->num == set->size)
505 {
506 FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
507
508 if (!strs)
509 return FcFalse;
510 FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
511 set->size = set->size + 1;
512 if (set->num)
513 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
514 if (set->strs)
515 free (set->strs);
516 set->strs = strs;
517 }
518 set->strs[set->num++] = s;
519 set->strs[set->num] = 0;
520 return FcTrue;
521 }
522
523 FcBool
524 FcStrSetMember (FcStrSet *set, const FcChar8 *s)
525 {
526 int i;
527
528 for (i = 0; i < set->num; i++)
529 if (!FcStrCmp (set->strs[i], s))
530 return FcTrue;
531 return FcFalse;
532 }
533
534 FcBool
535 FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
536 {
537 int i;
538 if (sa->num != sb->num)
539 return FcFalse;
540 for (i = 0; i < sa->num; i++)
541 if (!FcStrSetMember (sb, sa->strs[i]))
542 return FcFalse;
543 return FcTrue;
544 }
545
546 FcBool
547 FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
548 {
549 FcChar8 *new = FcStrCopy (s);
550 if (!new)
551 return FcFalse;
552 if (!_FcStrSetAppend (set, new))
553 {
554 FcStrFree (new);
555 return FcFalse;
556 }
557 return FcTrue;
558 }
559
560 FcBool
561 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
562 {
563 FcChar8 *new = FcStrCopyFilename (s);
564 if (!new)
565 return FcFalse;
566 if (!_FcStrSetAppend (set, new))
567 {
568 FcStrFree (new);
569 return FcFalse;
570 }
571 return FcTrue;
572 }
573
574 FcBool
575 FcStrSetDel (FcStrSet *set, const FcChar8 *s)
576 {
577 int i;
578
579 for (i = 0; i < set->num; i++)
580 if (!FcStrCmp (set->strs[i], s))
581 {
582 FcStrFree (set->strs[i]);
583 /*
584 * copy remaining string pointers and trailing
585 * NULL
586 */
587 memmove (&set->strs[i], &set->strs[i+1],
588 (set->num - i) * sizeof (FcChar8 *));
589 set->num--;
590 return FcTrue;
591 }
592 return FcFalse;
593 }
594
595 void
596 FcStrSetDestroy (FcStrSet *set)
597 {
598 if (--set->ref == 0)
599 {
600 int i;
601
602 for (i = 0; i < set->num; i++)
603 FcStrFree (set->strs[i]);
604 FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
605 if (set->strs)
606 free (set->strs);
607 FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
608 free (set);
609 }
610 }
611
612 FcStrList *
613 FcStrListCreate (FcStrSet *set)
614 {
615 FcStrList *list;
616
617 list = malloc (sizeof (FcStrList));
618 if (!list)
619 return 0;
620 FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
621 list->set = set;
622 set->ref++;
623 list->n = 0;
624 return list;
625 }
626
627 FcChar8 *
628 FcStrListNext (FcStrList *list)
629 {
630 if (list->n >= list->set->num)
631 return 0;
632 return list->set->strs[list->n++];
633 }
634
635 void
636 FcStrListDone (FcStrList *list)
637 {
638 FcStrSetDestroy (list->set);
639 FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
640 free (list);
641 }