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