Bug Summary

File:src/fcstr.c
Location:line 701, column 40
Description:Value stored to 'len' is never read

Annotated Source Code

1/*
2 * fontconfig/src/fcstr.c
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 the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make 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 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) 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 "fcint.h"
26#include <stdlib.h>
27#include <ctype.h>
28#include <string.h>
29
30
31/* Objects MT-safe for readonly access. */
32
33FcChar8 *
34FcStrCopy (const FcChar8 *s)
35{
36 return FcStrdup (s)((FcChar8 *) strdup ((const char *) (s)));
37}
38
39FcChar8 *
40FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
41{
42 int s1l = strlen ((char *) s1);
43 int s2l = strlen ((char *) s2);
44 int l = s1l + s2l + 1;
45 FcChar8 *s = malloc (l);
46
47 if (!s)
48 return 0;
49 memcpy (s, s1, s1l)__builtin___memcpy_chk (s, s1, s1l, __builtin_object_size (s,
0))
;
50 memcpy (s + s1l, s2, s2l + 1)__builtin___memcpy_chk (s + s1l, s2, s2l + 1, __builtin_object_size
(s + s1l, 0))
;
51 return s;
52}
53
54void
55FcStrFree (FcChar8 *s)
56{
57 free (s);
58}
59
60
61#include "../fc-case/fccase.h"
62
63#define FcCaseFoldUpperCount(cf)((cf)->method == 2 ? 1 : (cf)->count) \
64 ((cf)->method == FC_CASE_FOLD_FULL2 ? 1 : (cf)->count)
65
66typedef struct _FcCaseWalker {
67 const FcChar8 *read;
68 const FcChar8 *src;
69 FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS6 + 1];
70} FcCaseWalker;
71
72static void
73FcStrCaseWalkerInit (const FcChar8 *src, FcCaseWalker *w)
74{
75 w->src = src;
76 w->read = 0;
77}
78
79static FcChar8
80FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
81{
82 FcChar32 ucs4;
83 int slen;
84 int len = strlen((char*)w->src);
85
86 slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, len + 1);
87 if (slen <= 0)
88 return r;
89 if (FC_MIN_FOLD_CHAR0x00000041 <= ucs4 && ucs4 <= FC_MAX_FOLD_CHAR0x000118bf)
90 {
91 int min = 0;
92 int max = FC_NUM_CASE_FOLD277;
93
94 while (min <= max)
95 {
96 int mid = (min + max) >> 1;
97 FcChar32 low = fcCaseFold[mid].upper;
98 FcChar32 high = low + FcCaseFoldUpperCount (&fcCaseFold[mid])((&fcCaseFold[mid])->method == 2 ? 1 : (&fcCaseFold
[mid])->count)
;
99
100 if (high <= ucs4)
101 min = mid + 1;
102 else if (ucs4 < low)
103 max = mid - 1;
104 else
105 {
106 const FcCaseFold *fold = &fcCaseFold[mid];
107 int dlen;
108
109 switch (fold->method) {
110 case FC_CASE_FOLD_EVEN_ODD1:
111 if ((ucs4 & 1) != (fold->upper & 1))
112 return r;
113 /* fall through ... */
114 default:
115 dlen = FcUcs4ToUtf8 (ucs4 + fold->offset, w->utf8);
116 break;
117 case FC_CASE_FOLD_FULL2:
118 dlen = fold->count;
119 memcpy (w->utf8, fcCaseFoldChars + fold->offset, dlen)__builtin___memcpy_chk (w->utf8, fcCaseFoldChars + fold->
offset, dlen, __builtin_object_size (w->utf8, 0))
;
120 break;
121 }
122
123 /* consume rest of src utf-8 bytes */
124 w->src += slen - 1;
125
126 /* read from temp buffer */
127 w->utf8[dlen] = '\0';
128 w->read = w->utf8;
129 return *w->read++;
130 }
131 }
132 }
133 return r;
134}
135
136static FcChar8
137FcStrCaseWalkerNext (FcCaseWalker *w, const char *delims)
138{
139 FcChar8 r;
140
141 if (w->read)
142 {
143 if ((r = *w->read++))
144 return r;
145 w->read = 0;
146 }
147 do
148 {
149 r = *w->src++;
150 } while (r != 0 && delims && strchr (delims, r));
151
152 if ((r & 0xc0) == 0xc0)
153 return FcStrCaseWalkerLong (w, r);
154 if ('A' <= r && r <= 'Z')
155 r = r - 'A' + 'a';
156 return r;
157}
158
159FcChar8 *
160FcStrDowncase (const FcChar8 *s)
161{
162 FcCaseWalker w;
163 int len = 0;
164 FcChar8 *dst, *d;
165
166 FcStrCaseWalkerInit (s, &w);
167 while (FcStrCaseWalkerNext (&w, NULL((void*)0)))
168 len++;
169 d = dst = malloc (len + 1);
170 if (!d)
171 return 0;
172 FcStrCaseWalkerInit (s, &w);
173 while ((*d++ = FcStrCaseWalkerNext (&w, NULL((void*)0))));
174 return dst;
175}
176
177int
178FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
179{
180 FcCaseWalker w1, w2;
181 FcChar8 c1, c2;
182
183 if (s1 == s2) return 0;
184
185 FcStrCaseWalkerInit (s1, &w1);
186 FcStrCaseWalkerInit (s2, &w2);
187
188 for (;;)
189 {
190 c1 = FcStrCaseWalkerNext (&w1, NULL((void*)0));
191 c2 = FcStrCaseWalkerNext (&w2, NULL((void*)0));
192 if (!c1 || (c1 != c2))
193 break;
194 }
195 return (int) c1 - (int) c2;
196}
197
198int
199FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
200{
201 return FcStrCmpIgnoreCaseAndDelims (s1, s2, (const FcChar8 *)" ");
202}
203
204int
205FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
206{
207 FcCaseWalker w1, w2;
208 FcChar8 c1, c2;
209
210 if (s1 == s2) return 0;
211
212 FcStrCaseWalkerInit (s1, &w1);
213 FcStrCaseWalkerInit (s2, &w2);
214
215 for (;;)
216 {
217 c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
218 c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
219 if (!c1 || (c1 != c2))
220 break;
221 }
222 return (int) c1 - (int) c2;
223}
224
225int
226FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
227{
228 FcChar8 c1, c2;
229
230 if (s1 == s2)
231 return 0;
232 for (;;)
233 {
234 c1 = *s1++;
235 c2 = *s2++;
236 if (!c1 || c1 != c2)
237 break;
238 }
239 return (int) c1 - (int) c2;
240}
241
242/*
243 * Return a hash value for a string
244 */
245
246FcChar32
247FcStrHashIgnoreCase (const FcChar8 *s)
248{
249 FcChar32 h = 0;
250 FcCaseWalker w;
251 FcChar8 c;
252
253 FcStrCaseWalkerInit (s, &w);
254 while ((c = FcStrCaseWalkerNext (&w, NULL((void*)0))))
255 h = ((h << 3) ^ (h >> 3)) ^ c;
256 return h;
257}
258
259/*
260 * Is the head of s1 equal to s2?
261 */
262
263static FcBool
264FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
265{
266 FcCaseWalker w1, w2;
267 FcChar8 c1, c2;
268
269 FcStrCaseWalkerInit (s1, &w1);
270 FcStrCaseWalkerInit (s2, &w2);
271
272 for (;;)
273 {
274 c1 = FcStrCaseWalkerNext (&w1, " ");
275 c2 = FcStrCaseWalkerNext (&w2, " ");
276 if (!c1 || (c1 != c2))
277 break;
278 }
279 return c1 == c2 || !c2;
280}
281
282/*
283 * Does s1 contain an instance of s2 (ignoring blanks and case)?
284 */
285
286const FcChar8 *
287FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
288{
289 while (*s1)
290 {
291 if (FcStrIsAtIgnoreBlanksAndCase (s1, s2))
292 return s1;
293 s1++;
294 }
295 return 0;
296}
297
298static FcBool
299FcCharIsPunct (const FcChar8 c)
300{
301 if (c < '0')
302 return FcTrue1;
303 if (c <= '9')
304 return FcFalse0;
305 if (c < 'A')
306 return FcTrue1;
307 if (c <= 'Z')
308 return FcFalse0;
309 if (c < 'a')
310 return FcTrue1;
311 if (c <= 'z')
312 return FcFalse0;
313 if (c <= '~')
314 return FcTrue1;
315 return FcFalse0;
316}
317
318/*
319 * Is the head of s1 equal to s2?
320 */
321
322static FcBool
323FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
324{
325 FcCaseWalker w1, w2;
326 FcChar8 c1, c2;
327
328 FcStrCaseWalkerInit (s1, &w1);
329 FcStrCaseWalkerInit (s2, &w2);
330
331 for (;;)
332 {
333 c1 = FcStrCaseWalkerNext (&w1, NULL((void*)0));
334 c2 = FcStrCaseWalkerNext (&w2, NULL((void*)0));
335 if (!c1 || (c1 != c2))
336 break;
337 }
338 return c1 == c2 || !c2;
339}
340
341/*
342 * Does s1 contain an instance of s2 (ignoring blanks and case)?
343 */
344
345const FcChar8 *
346FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
347{
348 while (*s1)
349 {
350 if (FcStrIsAtIgnoreCase (s1, s2))
351 return s1;
352 s1++;
353 }
354 return 0;
355}
356
357/*
358 * Does s1 contain an instance of s2 on a word boundary (ignoring case)?
359 */
360
361const FcChar8 *
362FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2)
363{
364 FcBool wordStart = FcTrue1;
365 int s1len = strlen ((char *) s1);
366 int s2len = strlen ((char *) s2);
367
368 while (s1len >= s2len)
369 {
370 if (wordStart &&
371 FcStrIsAtIgnoreCase (s1, s2) &&
372 (s1len == s2len || FcCharIsPunct (s1[s2len])))
373 {
374 return s1;
375 }
376 wordStart = FcFalse0;
377 if (FcCharIsPunct (*s1))
378 wordStart = FcTrue1;
379 s1++;
380 s1len--;
381 }
382 return 0;
383}
384
385/*
386 * returns the number of strings (ignoring delimitors and case) being matched
387 */
388
389int
390FcStrMatchIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
391{
392 FcCaseWalker w1, w2;
393 FcChar8 c1, c2;
394
395 if (s1 == s2) return 0;
396
397 FcStrCaseWalkerInit (s1, &w1);
398 FcStrCaseWalkerInit (s2, &w2);
399
400 for (;;)
401 {
402 c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
403 c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
404 if (!c1 || (c1 != c2))
405 break;
406 }
407 return w1.src - s1 - 1;
408}
409
410FcBool
411FcStrGlobMatch (const FcChar8 *glob,
412 const FcChar8 *string)
413{
414 FcChar8 c;
415
416 while ((c = *glob++))
417 {
418 switch (c) {
419 case '*':
420 /* short circuit common case */
421 if (!*glob)
422 return FcTrue1;
423 /* short circuit another common case */
424 if (strchr ((char *) glob, '*') == 0)
425 {
426 size_t l1, l2;
427
428 l1 = strlen ((char *) string);
429 l2 = strlen ((char *) glob);
430 if (l1 < l2)
431 return FcFalse0;
432 string += (l1 - l2);
433 }
434 while (*string)
435 {
436 if (FcStrGlobMatch (glob, string))
437 return FcTrue1;
438 string++;
439 }
440 return FcFalse0;
441 case '?':
442 if (*string++ == '\0')
443 return FcFalse0;
444 break;
445 default:
446 if (*string++ != c)
447 return FcFalse0;
448 break;
449 }
450 }
451 return *string == '\0';
452}
453
454const FcChar8 *
455FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
456{
457 FcCaseWalker w1, w2;
458 FcChar8 c1, c2;
459 const FcChar8 *cur;
460
461 if (!s1 || !s2)
462 return 0;
463
464 if (s1 == s2)
465 return s1;
466
467 FcStrCaseWalkerInit (s1, &w1);
468 FcStrCaseWalkerInit (s2, &w2);
469
470 c2 = FcStrCaseWalkerNext (&w2, NULL((void*)0));
471
472 for (;;)
473 {
474 cur = w1.src;
475 c1 = FcStrCaseWalkerNext (&w1, NULL((void*)0));
476 if (!c1)
477 break;
478 if (c1 == c2)
479 {
480 FcCaseWalker w1t = w1;
481 FcCaseWalker w2t = w2;
482 FcChar8 c1t, c2t;
483
484 for (;;)
485 {
486 c1t = FcStrCaseWalkerNext (&w1t, NULL((void*)0));
487 c2t = FcStrCaseWalkerNext (&w2t, NULL((void*)0));
488
489 if (!c2t)
490 return cur;
491 if (c2t != c1t)
492 break;
493 }
494 }
495 }
496 return 0;
497}
498
499const FcChar8 *
500FcStrStr (const FcChar8 *s1, const FcChar8 *s2)
501{
502 FcChar8 c1, c2;
503 const FcChar8 * p = s1;
504 const FcChar8 * b = s2;
505
506 if (!s1 || !s2)
507 return 0;
508
509 if (s1 == s2)
510 return s1;
511
512again:
513 c2 = *s2++;
514
515 if (!c2)
516 return 0;
517
518 for (;;)
519 {
520 p = s1;
521 c1 = *s1++;
522 if (!c1 || c1 == c2)
523 break;
524 }
525
526 if (c1 != c2)
527 return 0;
528
529 for (;;)
530 {
531 c1 = *s1;
532 c2 = *s2;
533 if (c1 && c2 && c1 != c2)
534 {
535 s1 = p + 1;
536 s2 = b;
537 goto again;
538 }
539 if (!c2)
540 return p;
541 if (!c1)
542 return 0;
543 ++ s1;
544 ++ s2;
545 }
546 /* never reached. */
547}
548
549int
550FcUtf8ToUcs4 (const FcChar8 *src_orig,
551 FcChar32 *dst,
552 int len)
553{
554 const FcChar8 *src = src_orig;
555 FcChar8 s;
556 int extra;
557 FcChar32 result;
558
559 if (len == 0)
560 return 0;
561
562 s = *src++;
563 len--;
564
565 if (!(s & 0x80))
566 {
567 result = s;
568 extra = 0;
569 }
570 else if (!(s & 0x40))
571 {
572 return -1;
573 }
574 else if (!(s & 0x20))
575 {
576 result = s & 0x1f;
577 extra = 1;
578 }
579 else if (!(s & 0x10))
580 {
581 result = s & 0xf;
582 extra = 2;
583 }
584 else if (!(s & 0x08))
585 {
586 result = s & 0x07;
587 extra = 3;
588 }
589 else if (!(s & 0x04))
590 {
591 result = s & 0x03;
592 extra = 4;
593 }
594 else if ( ! (s & 0x02))
595 {
596 result = s & 0x01;
597 extra = 5;
598 }
599 else
600 {
601 return -1;
602 }
603 if (extra > len)
604 return -1;
605
606 while (extra--)
607 {
608 result <<= 6;
609 s = *src++;
610
611 if ((s & 0xc0) != 0x80)
612 return -1;
613
614 result |= s & 0x3f;
615 }
616 *dst = result;
617 return src - src_orig;
618}
619
620FcBool
621FcUtf8Len (const FcChar8 *string,
622 int len,
623 int *nchar,
624 int *wchar)
625{
626 int n;
627 int clen;
628 FcChar32 c;
629 FcChar32 max;
630
631 n = 0;
632 max = 0;
633 while (len)
634 {
635 clen = FcUtf8ToUcs4 (string, &c, len);
636 if (clen <= 0) /* malformed UTF8 string */
637 return FcFalse0;
638 if (c > max)
639 max = c;
640 string += clen;
641 len -= clen;
642 n++;
643 }
644 *nchar = n;
645 if (max >= 0x10000)
646 *wchar = 4;
647 else if (max > 0x100)
648 *wchar = 2;
649 else
650 *wchar = 1;
651 return FcTrue1;
652}
653
654int
655FcUcs4ToUtf8 (FcChar32 ucs4,
656 FcChar8 dest[FC_UTF8_MAX_LEN6])
657{
658 int bits;
659 FcChar8 *d = dest;
660
661 if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
662 else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
663 else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
664 else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
665 else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
666 else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
667 else return 0;
668
669 for ( ; bits >= 0; bits-= 6) {
670 *d++= ((ucs4 >> bits) & 0x3F) | 0x80;
671 }
672 return d - dest;
673}
674
675#define GetUtf16(src,endian)((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8)
| (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
\
676 ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
677 (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
678
679int
680FcUtf16ToUcs4 (const FcChar8 *src_orig,
681 FcEndian endian,
682 FcChar32 *dst,
683 int len) /* in bytes */
684{
685 const FcChar8 *src = src_orig;
686 FcChar16 a, b;
687 FcChar32 result;
688
689 if (len < 2)
690 return 0;
691
692 a = GetUtf16 (src, endian)((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8)
| (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
; src += 2; len -= 2;
693
694 /*
695 * Check for surrogate
696 */
697 if ((a & 0xfc00) == 0xd800)
698 {
699 if (len < 2)
700 return 0;
701 b = GetUtf16 (src, endian)((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8)
| (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
; src += 2; len -= 2;
Value stored to 'len' is never read
702 /*
703 * Check for invalid surrogate sequence
704 */
705 if ((b & 0xfc00) != 0xdc00)
706 return 0;
707 result = ((((FcChar32) a & 0x3ff) << 10) |
708 ((FcChar32) b & 0x3ff)) + 0x10000;
709 }
710 else
711 result = a;
712 *dst = result;
713 return src - src_orig;
714}
715
716FcBool
717FcUtf16Len (const FcChar8 *string,
718 FcEndian endian,
719 int len, /* in bytes */
720 int *nchar,
721 int *wchar)
722{
723 int n;
724 int clen;
725 FcChar32 c;
726 FcChar32 max;
727
728 n = 0;
729 max = 0;
730 while (len)
731 {
732 clen = FcUtf16ToUcs4 (string, endian, &c, len);
733 if (clen <= 0) /* malformed UTF8 string */
734 return FcFalse0;
735 if (c > max)
736 max = c;
737 string += clen;
738 len -= clen;
739 n++;
740 }
741 *nchar = n;
742 if (max >= 0x10000)
743 *wchar = 4;
744 else if (max > 0x100)
745 *wchar = 2;
746 else
747 *wchar = 1;
748 return FcTrue1;
749}
750
751void
752FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
753{
754 if (init)
755 {
756 buf->buf = init;
757 buf->size = size;
758 } else
759 {
760 buf->buf = buf->buf_static;
761 buf->size = sizeof (buf->buf_static);
762 }
763 buf->allocated = FcFalse0;
764 buf->failed = FcFalse0;
765 buf->len = 0;
766}
767
768void
769FcStrBufDestroy (FcStrBuf *buf)
770{
771 if (buf->allocated)
772 {
773 free (buf->buf);
774 FcStrBufInit (buf, 0, 0);
775 }
776}
777
778FcChar8 *
779FcStrBufDone (FcStrBuf *buf)
780{
781 FcChar8 *ret;
782
783 if (buf->failed)
784 ret = NULL((void*)0);
785 else
786 ret = malloc (buf->len + 1);
787 if (ret)
788 {
789 memcpy (ret, buf->buf, buf->len)__builtin___memcpy_chk (ret, buf->buf, buf->len, __builtin_object_size
(ret, 0))
;
790 ret[buf->len] = '\0';
791 }
792 FcStrBufDestroy (buf);
793 return ret;
794}
795
796FcChar8 *
797FcStrBufDoneStatic (FcStrBuf *buf)
798{
799 FcStrBufChar (buf, '\0');
800
801 if (buf->failed)
802 return NULL((void*)0);
803
804 return buf->buf;
805}
806
807FcBool
808FcStrBufChar (FcStrBuf *buf, FcChar8 c)
809{
810 if (buf->len == buf->size)
811 {
812 FcChar8 *new;
813 int size;
814
815 if (buf->failed)
816 return FcFalse0;
817
818 if (buf->allocated)
819 {
820 size = buf->size * 2;
821 new = realloc (buf->buf, size);
822 }
823 else
824 {
825 size = buf->size + 64;
826 new = malloc (size);
827 if (new)
828 {
829 buf->allocated = FcTrue1;
830 memcpy (new, buf->buf, buf->len)__builtin___memcpy_chk (new, buf->buf, buf->len, __builtin_object_size
(new, 0))
;
831 }
832 }
833 if (!new)
834 {
835 buf->failed = FcTrue1;
836 return FcFalse0;
837 }
838 buf->size = size;
839 buf->buf = new;
840 }
841 buf->buf[buf->len++] = c;
842 return FcTrue1;
843}
844
845FcBool
846FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
847{
848 FcChar8 c;
849 while ((c = *s++))
850 if (!FcStrBufChar (buf, c))
851 return FcFalse0;
852 return FcTrue1;
853}
854
855FcBool
856FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
857{
858 while (len-- > 0)
859 if (!FcStrBufChar (buf, *s++))
860 return FcFalse0;
861 return FcTrue1;
862}
863
864FcBool
865FcStrUsesHome (const FcChar8 *s)
866{
867 return *s == '~';
868}
869
870FcChar8 *
871FcStrBuildFilename (const FcChar8 *path,
872 ...)
873{
874 va_list ap;
875 FcStrSet *sset;
876 FcStrList *list;
877 FcChar8 *s, *ret = NULL((void*)0), *p;
878 size_t len = 0;
879
880 if (!path)
881 return NULL((void*)0);
882
883 sset = FcStrSetCreateEx (FCSS_ALLOW_DUPLICATES1 | FCSS_GROW_BY_642);
884 if (!sset)
885 return NULL((void*)0);
886
887 if (!FcStrSetAdd (sset, path))
888 goto bail0;
889
890 va_start (ap, path)__builtin_va_start(ap, path);
891 while (1)
892 {
893 s = (FcChar8 *)va_arg (ap, FcChar8 *)__builtin_va_arg(ap, FcChar8 *);
894 if (!s)
895 break;
896 if (!FcStrSetAdd (sset, s))
897 goto bail1;
898 }
899 list = FcStrListCreate (sset);
900 while ((s = FcStrListNext (list)))
901 {
902 len += strlen ((const char *)s) + 1;
903 }
904 list->n = 0;
905 ret = malloc (sizeof (FcChar8) * (len + 1));
906 if (!ret)
907 goto bail2;
908 p = ret;
909 while ((s = FcStrListNext (list)))
910 {
911 if (p != ret)
912 {
913 p[0] = FC_DIR_SEPARATOR'/';
914 p++;
915 }
916 len = strlen ((const char *)s);
917 memcpy (p, s, len)__builtin___memcpy_chk (p, s, len, __builtin_object_size (p, 0
))
;
918 p += len;
919 }
920 *p = 0;
921
922bail2:
923 FcStrListDone (list);
924bail1:
925 va_end (ap)__builtin_va_end(ap);
926bail0:
927 FcStrSetDestroy (sset);
928
929 return ret;
930}
931
932FcChar8 *
933FcStrCopyFilename (const FcChar8 *s)
934{
935 FcChar8 *new;
936
937 if (*s == '~')
938 {
939 FcChar8 *home = FcConfigHome ();
940 FcChar8 *full;
941 int size;
942 if (!home)
943 return NULL((void*)0);
944 size = strlen ((char *) home) + strlen ((char *) s);
945 full = (FcChar8 *) malloc (size);
946 if (!full)
947 return NULL((void*)0);
948 strcpy ((char *) full, (char *) home)__builtin___strcpy_chk ((char *) full, (char *) home, __builtin_object_size
((char *) full, 2 > 1 ? 1 : 0))
;
949 strcat ((char *) full, (char *) s + 1)__builtin___strcat_chk ((char *) full, (char *) s + 1, __builtin_object_size
((char *) full, 2 > 1 ? 1 : 0))
;
950 new = FcStrCanonFilename (full);
951 free (full);
952 }
953 else
954 new = FcStrCanonFilename (s);
955
956 return new;
957}
958
959FcChar8 *
960FcStrLastSlash (const FcChar8 *path)
961{
962 FcChar8 *slash;
963
964 slash = (FcChar8 *) strrchr ((const char *) path, '/');
965#ifdef _WIN32
966 {
967 FcChar8 *backslash;
968
969 backslash = (FcChar8 *) strrchr ((const char *) path, '\\');
970 if (!slash || (backslash && backslash > slash))
971 slash = backslash;
972 }
973#endif
974
975 return slash;
976}
977
978FcChar8 *
979FcStrDirname (const FcChar8 *file)
980{
981 FcChar8 *slash;
982 FcChar8 *dir;
983
984 slash = FcStrLastSlash (file);
985 if (!slash)
986 return FcStrCopy ((FcChar8 *) ".");
987 dir = malloc ((slash - file) + 1);
988 if (!dir)
989 return 0;
990 strncpy ((char *) dir, (const char *) file, slash - file)__builtin___strncpy_chk ((char *) dir, (const char *) file, slash
- file, __builtin_object_size ((char *) dir, 2 > 1 ? 1 : 0
))
;
991 dir[slash - file] = '\0';
992 return dir;
993}
994
995FcChar8 *
996FcStrBasename (const FcChar8 *file)
997{
998 FcChar8 *slash;
999
1000 slash = FcStrLastSlash (file);
1001 if (!slash)
1002 return FcStrCopy (file);
1003 return FcStrCopy (slash + 1);
1004}
1005
1006static FcChar8 *
1007FcStrCanonAbsoluteFilename (const FcChar8 *s)
1008{
1009 FcChar8 *file;
1010 FcChar8 *f;
1011 const FcChar8 *slash;
1012 int size;
1013
1014 size = strlen ((char *) s) + 1;
1015 file = malloc (size);
1016 if (!file)
1017 return NULL((void*)0);
1018 slash = NULL((void*)0);
1019 f = file;
1020#ifdef _WIN32
1021 if (*s == '/' && *(s+1) == '/') /* Network path, do not squash // */
1022 *f++ = *s++;
1023#endif
1024 for (;;) {
1025 if (*s == '/' || *s == '\0')
1026 {
1027 if (slash)
1028 {
1029 switch (s - slash) {
1030 case 1:
1031 f -= 1; /* squash // and trim final / from file */
1032 break;
1033 case 2:
1034 if (!strncmp ((char *) slash, "/.", 2))
1035 {
1036 f -= 2; /* trim /. from file */
1037 }
1038 break;
1039 case 3:
1040 if (!strncmp ((char *) slash, "/..", 3))
1041 {
1042 f -= 3; /* trim /.. from file */
1043 while (f > file) {
1044 if (*--f == '/')
1045 break;
1046 }
1047 }
1048 break;
1049 }
1050 }
1051 slash = s;
1052 }
1053 if (!(*f++ = *s++))
1054 break;
1055 }
1056 return file;
1057}
1058
1059#ifdef _WIN32
1060/*
1061 * Convert '\\' to '/' , remove double '/'
1062 */
1063static void
1064FcConvertDosPath (char *str)
1065{
1066 size_t len = strlen (str);
1067 char *p = str;
1068 char *dest = str;
1069 char *end = str + len;
1070 char last = 0;
1071
1072 if (*p == '\\')
1073 {
1074 *p = '/';
1075 p++;
1076 dest++;
1077 }
1078 while (p < end)
1079 {
1080 if (*p == '\\')
1081 *p = '/';
1082
1083 if (*p != '/'
1084 || last != '/')
1085 {
1086 *dest++ = *p;
1087 }
1088
1089 last = *p;
1090 p++;
1091 }
1092
1093 *dest = 0;
1094}
1095#endif
1096
1097FcChar8 *
1098FcStrCanonFilename (const FcChar8 *s)
1099{
1100#ifdef _WIN32
1101 FcChar8 full[FC_MAX_FILE_LEN4096 + 2];
1102 int size = GetFullPathName ((LPCSTR) s, sizeof (full) -1,
1103 (LPSTR) full, NULL((void*)0));
1104
1105 if (size == 0)
1106 perror ("GetFullPathName");
1107
1108 FcConvertDosPath ((char *) full);
1109 return FcStrCanonAbsoluteFilename (full);
1110#else
1111 if (s[0] == '/')
1112 return FcStrCanonAbsoluteFilename (s);
1113 else
1114 {
1115 FcChar8 *full;
1116 FcChar8 *file;
1117
1118 FcChar8 cwd[FC_MAX_FILE_LEN4096 + 2];
1119 if (getcwd ((char *) cwd, FC_MAX_FILE_LEN4096) == NULL((void*)0))
1120 return NULL((void*)0);
1121 full = FcStrBuildFilename (cwd, s, NULL((void*)0));
1122 file = FcStrCanonAbsoluteFilename (full);
1123 FcStrFree (full);
1124 return file;
1125 }
1126#endif
1127}
1128
1129
1130FcStrSet *
1131FcStrSetCreate (void)
1132{
1133 return FcStrSetCreateEx (FCSS_DEFAULT0);
1134}
1135
1136FcStrSet *
1137FcStrSetCreateEx (unsigned int control)
1138{
1139 FcStrSet *set = malloc (sizeof (FcStrSet));
1140 if (!set)
1141 return 0;
1142 FcRefInit (&set->ref, 1);
1143 set->num = 0;
1144 set->size = 0;
1145 set->strs = 0;
1146 set->control = control;
1147 return set;
1148}
1149
1150static FcBool
1151_FcStrSetGrow (FcStrSet *set, int growElements)
1152{
1153 /* accommodate an additional NULL entry at the end of the array */
1154 FcChar8 **strs = malloc ((set->size + growElements + 1) * sizeof (FcChar8 *));
1155 if (!strs)
1156 return FcFalse0;
1157 if (set->num)
1158 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *))__builtin___memcpy_chk (strs, set->strs, set->num * sizeof
(FcChar8 *), __builtin_object_size (strs, 0))
;
1159 if (set->strs)
1160 free (set->strs);
1161 set->size = set->size + growElements;
1162 set->strs = strs;
1163 return FcTrue1;
1164}
1165
1166static FcBool
1167_FcStrSetAppend (FcStrSet *set, FcChar8 *s)
1168{
1169 if (!FcStrSetHasControlBit (set, FCSS_ALLOW_DUPLICATES)(set->control & 1))
1170 {
1171 if (FcStrSetMember (set, s))
1172 {
1173 FcStrFree (s);
1174 return FcTrue1;
1175 }
1176 }
1177 if (set->num == set->size)
1178 {
1179 int growElements = FcStrSetHasControlBit (set, FCSS_GROW_BY_64)(set->control & 2) ? 64 : 1;
1180 if (!_FcStrSetGrow(set, growElements))
1181 return FcFalse0;
1182 }
1183 set->strs[set->num++] = s;
1184 set->strs[set->num] = 0;
1185 return FcTrue1;
1186}
1187
1188FcBool
1189FcStrSetMember (FcStrSet *set, const FcChar8 *s)
1190{
1191 int i;
1192
1193 for (i = 0; i < set->num; i++)
1194 if (!FcStrCmp (set->strs[i], s))
1195 return FcTrue1;
1196 return FcFalse0;
1197}
1198
1199FcBool
1200FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
1201{
1202 int i;
1203 if (sa->num != sb->num)
1204 return FcFalse0;
1205 for (i = 0; i < sa->num; i++)
1206 if (!FcStrSetMember (sb, sa->strs[i]))
1207 return FcFalse0;
1208 return FcTrue1;
1209}
1210
1211FcBool
1212FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
1213{
1214 FcChar8 *new = FcStrCopy (s);
1215 if (!new)
1216 return FcFalse0;
1217 if (!_FcStrSetAppend (set, new))
1218 {
1219 FcStrFree (new);
1220 return FcFalse0;
1221 }
1222 return FcTrue1;
1223}
1224
1225FcBool
1226FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
1227{
1228 FcChar8 *new = FcStrCopyFilename (s);
1229 if (!new)
1230 return FcFalse0;
1231 if (!_FcStrSetAppend (set, new))
1232 {
1233 FcStrFree (new);
1234 return FcFalse0;
1235 }
1236 return FcTrue1;
1237}
1238
1239FcBool
1240FcStrSetAddLangs (FcStrSet *strs, const char *languages)
1241{
1242 const char *p = languages, *next;
1243 FcChar8 lang[128] = {0}, *normalized_lang;
1244 size_t len;
1245 FcBool ret = FcFalse0;
1246
1247 if (!languages)
1248 return FcFalse0;
1249
1250 while ((next = strchr (p, ':')))
1251 {
1252 len = next - p;
1253 len = FC_MIN (len, 127)((len) < (127) ? (len) : (127));
1254 strncpy ((char *) lang, p, len)__builtin___strncpy_chk ((char *) lang, p, len, __builtin_object_size
((char *) lang, 2 > 1 ? 1 : 0))
;
1255 lang[len] = 0;
1256 /* ignore an empty item */
1257 if (*lang)
1258 {
1259 normalized_lang = FcLangNormalize ((const FcChar8 *) lang);
1260 if (normalized_lang)
1261 {
1262 FcStrSetAdd (strs, normalized_lang);
1263 FcStrFree (normalized_lang);
1264 ret = FcTrue1;
1265 }
1266 }
1267 p = next + 1;
1268 }
1269 if (*p)
1270 {
1271 normalized_lang = FcLangNormalize ((const FcChar8 *) p);
1272 if (normalized_lang)
1273 {
1274 FcStrSetAdd (strs, normalized_lang);
1275 FcStrFree (normalized_lang);
1276 ret = FcTrue1;
1277 }
1278 }
1279
1280 return ret;
1281}
1282
1283FcBool
1284FcStrSetDel (FcStrSet *set, const FcChar8 *s)
1285{
1286 int i;
1287
1288 for (i = 0; i < set->num; i++)
1289 if (!FcStrCmp (set->strs[i], s))
1290 {
1291 FcStrFree (set->strs[i]);
1292 /*
1293 * copy remaining string pointers and trailing
1294 * NULL
1295 */
1296 memmove (&set->strs[i], &set->strs[i+1],__builtin___memmove_chk (&set->strs[i], &set->strs
[i+1], (set->num - i) * sizeof (FcChar8 *), __builtin_object_size
(&set->strs[i], 0))
1297 (set->num - i) * sizeof (FcChar8 *))__builtin___memmove_chk (&set->strs[i], &set->strs
[i+1], (set->num - i) * sizeof (FcChar8 *), __builtin_object_size
(&set->strs[i], 0))
;
1298 set->num--;
1299 return FcTrue1;
1300 }
1301 return FcFalse0;
1302}
1303
1304/* TODO Make public */
1305static FcStrSet *
1306FcStrSetReference (FcStrSet *set)
1307{
1308 if (FcRefIsConst (&set->ref))
1309 return set;
1310
1311 FcRefInc (&set->ref);
1312 return set;
1313}
1314
1315void
1316FcStrSetDestroy (FcStrSet *set)
1317{
1318 int i;
1319
1320 /* We rely on this in FcGetDefaultLangs for caching. */
1321 if (FcRefIsConst (&set->ref))
1322 return;
1323
1324 if (FcRefDec (&set->ref) != 1)
1325 return;
1326
1327 for (i = 0; i < set->num; i++)
1328 FcStrFree (set->strs[i]);
1329 if (set->strs)
1330 free (set->strs);
1331 free (set);
1332}
1333
1334FcStrList *
1335FcStrListCreate (FcStrSet *set)
1336{
1337 FcStrList *list;
1338
1339 list = malloc (sizeof (FcStrList));
1340 if (!list)
1341 return 0;
1342 list->set = set;
1343 FcStrSetReference (set);
1344 list->n = 0;
1345 return list;
1346}
1347
1348void
1349FcStrListFirst (FcStrList *list)
1350{
1351 list->n = 0;
1352}
1353
1354FcChar8 *
1355FcStrListNext (FcStrList *list)
1356{
1357 if (list->n >= list->set->num)
1358 return 0;
1359 return list->set->strs[list->n++];
1360}
1361
1362void
1363FcStrListDone (FcStrList *list)
1364{
1365 FcStrSetDestroy (list->set);
1366 free (list);
1367}
1368
1369#define __fcstr__
1370#include "fcaliastail.h"
1371#undef __fcstr__