]> git.wh0rd.org - fontconfig.git/blob - src/fcstr.c
Add some Utf16 support, extract font family and style names from name table
[fontconfig.git] / src / fcstr.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcstr.c,v 1.6 2002/07/06 23:47:44 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 (FcChar8 *src_orig,
129 FcChar32 *dst,
130 int len)
131 {
132 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 (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 (FcChar8 *src_orig,
259 FcEndian endian,
260 FcChar32 *dst,
261 int len) /* in bytes */
262 {
263 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 (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 free (buf->buf);
345 FcStrBufInit (buf, 0, 0);
346 }
347 }
348
349 FcChar8 *
350 FcStrBufDone (FcStrBuf *buf)
351 {
352 FcChar8 *ret;
353
354 ret = malloc (buf->len + 1);
355 if (ret)
356 {
357 memcpy (ret, buf->buf, buf->len);
358 ret[buf->len] = '\0';
359 }
360 FcStrBufDestroy (buf);
361 return ret;
362 }
363
364 FcBool
365 FcStrBufChar (FcStrBuf *buf, FcChar8 c)
366 {
367 if (buf->len == buf->size)
368 {
369 FcChar8 *new;
370 int size;
371
372 if (buf->allocated)
373 {
374 size = buf->size * 2;
375 new = realloc (buf->buf, size);
376 }
377 else
378 {
379 size = buf->size + 1024;
380 new = malloc (size);
381 if (new)
382 {
383 buf->allocated = FcTrue;
384 memcpy (new, buf->buf, buf->len);
385 }
386 }
387 if (!new)
388 {
389 buf->failed = FcTrue;
390 return FcFalse;
391 }
392 buf->size = size;
393 buf->buf = new;
394 }
395 buf->buf[buf->len++] = c;
396 return FcTrue;
397 }
398
399 FcBool
400 FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
401 {
402 FcChar8 c;
403 while ((c = *s++))
404 if (!FcStrBufChar (buf, c))
405 return FcFalse;
406 return FcTrue;
407 }
408
409 FcBool
410 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
411 {
412 while (len-- > 0)
413 if (!FcStrBufChar (buf, *s++))
414 return FcFalse;
415 return FcTrue;
416 }
417
418 FcChar8 *
419 FcStrCopyFilename (const FcChar8 *s)
420 {
421 FcChar8 *new;
422
423 if (*s == '~')
424 {
425 FcChar8 *home = (FcChar8 *) getenv ("HOME");
426 int size = strlen ((char *) home) + strlen ((char *) s);
427 if (!home)
428 return 0;
429 new = (FcChar8 *) malloc (size);
430 if (!new)
431 return 0;
432 FcMemAlloc (FC_MEM_STRING, size);
433 strcpy ((char *) new, (char *) home);
434 strcat ((char *) new, (char *) s + 1);
435 }
436 else
437 {
438 int size = strlen ((char *) s) + 1;
439 new = (FcChar8 *) malloc (size);
440 if (!new)
441 return 0;
442 FcMemAlloc (FC_MEM_STRING, size);
443 strcpy ((char *) new, (const char *) s);
444 }
445 return new;
446 }
447
448 FcChar8 *
449 FcStrDirname (const FcChar8 *file)
450 {
451 FcChar8 *slash;
452 FcChar8 *dir;
453
454 slash = (FcChar8 *) strrchr ((char *) file, '/');
455 if (!slash)
456 return FcStrCopy ((FcChar8 *) ".");
457 dir = malloc ((slash - file) + 1);
458 if (!dir)
459 return 0;
460 FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
461 strncpy ((char *) dir, (const char *) file, slash - file);
462 dir[slash - file] = '\0';
463 return dir;
464 }
465
466 FcChar8 *
467 FcStrBasename (const FcChar8 *file)
468 {
469 FcChar8 *slash;
470
471 slash = (FcChar8 *) strrchr ((char *) file, '/');
472 if (!slash)
473 return FcStrCopy (file);
474 return FcStrCopy (slash + 1);
475 }
476
477 FcStrSet *
478 FcStrSetCreate (void)
479 {
480 FcStrSet *set = malloc (sizeof (FcStrSet));
481 if (!set)
482 return 0;
483 FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
484 set->ref = 1;
485 set->num = 0;
486 set->size = 0;
487 set->strs = 0;
488 return set;
489 }
490
491 static FcBool
492 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
493 {
494 if (FcStrSetMember (set, s))
495 {
496 FcStrFree (s);
497 return FcTrue;
498 }
499 if (set->num == set->size)
500 {
501 FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
502
503 if (!strs)
504 return FcFalse;
505 FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
506 set->size = set->size + 1;
507 if (set->num)
508 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
509 if (set->strs)
510 free (set->strs);
511 set->strs = strs;
512 }
513 set->strs[set->num++] = s;
514 set->strs[set->num] = 0;
515 return FcTrue;
516 }
517
518 FcBool
519 FcStrSetMember (FcStrSet *set, const FcChar8 *s)
520 {
521 int i;
522
523 for (i = 0; i < set->num; i++)
524 if (!FcStrCmp (set->strs[i], s))
525 return FcTrue;
526 return FcFalse;
527 }
528
529 FcBool
530 FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
531 {
532 FcChar8 *new = FcStrCopy (s);
533 if (!new)
534 return FcFalse;
535 if (!_FcStrSetAppend (set, new))
536 {
537 FcStrFree (new);
538 return FcFalse;
539 }
540 return FcTrue;
541 }
542
543 FcBool
544 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
545 {
546 FcChar8 *new = FcStrCopyFilename (s);
547 if (!new)
548 return FcFalse;
549 if (!_FcStrSetAppend (set, new))
550 {
551 FcStrFree (new);
552 return FcFalse;
553 }
554 return FcTrue;
555 }
556
557 FcBool
558 FcStrSetDel (FcStrSet *set, const FcChar8 *s)
559 {
560 int i;
561
562 for (i = 0; i < set->num; i++)
563 if (!FcStrCmp (set->strs[i], s))
564 {
565 FcStrFree (set->strs[i]);
566 /*
567 * copy remaining string pointers and trailing
568 * NULL
569 */
570 memmove (&set->strs[i], &set->strs[i+1],
571 (set->num - i) * sizeof (FcChar8 *));
572 set->num--;
573 return FcTrue;
574 }
575 return FcFalse;
576 }
577
578 void
579 FcStrSetDestroy (FcStrSet *set)
580 {
581 if (--set->ref == 0)
582 {
583 int i;
584
585 for (i = 0; i < set->num; i++)
586 FcStrFree (set->strs[i]);
587 FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
588 if (set->strs)
589 free (set->strs);
590 FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
591 free (set);
592 }
593 }
594
595 FcStrList *
596 FcStrListCreate (FcStrSet *set)
597 {
598 FcStrList *list;
599
600 list = malloc (sizeof (FcStrList));
601 if (!list)
602 return 0;
603 FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
604 list->set = set;
605 set->ref++;
606 list->n = 0;
607 return list;
608 }
609
610 FcChar8 *
611 FcStrListNext (FcStrList *list)
612 {
613 if (list->n >= list->set->num)
614 return 0;
615 return list->set->strs[list->n++];
616 }
617
618 void
619 FcStrListDone (FcStrList *list)
620 {
621 FcStrSetDestroy (list->set);
622 FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
623 free (list);
624 }