File: | src/fcstr.c |
Location: | line 701, column 40 |
Description: | Value stored to 'len' is never read |
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 | |
33 | FcChar8 * |
34 | FcStrCopy (const FcChar8 *s) |
35 | { |
36 | return FcStrdup (s)((FcChar8 *) strdup ((const char *) (s))); |
37 | } |
38 | |
39 | FcChar8 * |
40 | FcStrPlus (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 | |
54 | void |
55 | FcStrFree (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 | |
66 | typedef struct _FcCaseWalker { |
67 | const FcChar8 *read; |
68 | const FcChar8 *src; |
69 | FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS6 + 1]; |
70 | } FcCaseWalker; |
71 | |
72 | static void |
73 | FcStrCaseWalkerInit (const FcChar8 *src, FcCaseWalker *w) |
74 | { |
75 | w->src = src; |
76 | w->read = 0; |
77 | } |
78 | |
79 | static FcChar8 |
80 | FcStrCaseWalkerLong (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 | |
136 | static FcChar8 |
137 | FcStrCaseWalkerNext (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 | |
159 | FcChar8 * |
160 | FcStrDowncase (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 | |
177 | int |
178 | FcStrCmpIgnoreCase (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 | |
198 | int |
199 | FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2) |
200 | { |
201 | return FcStrCmpIgnoreCaseAndDelims (s1, s2, (const FcChar8 *)" "); |
202 | } |
203 | |
204 | int |
205 | FcStrCmpIgnoreCaseAndDelims (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 | |
225 | int |
226 | FcStrCmp (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 | |
246 | FcChar32 |
247 | FcStrHashIgnoreCase (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 | |
263 | static FcBool |
264 | FcStrIsAtIgnoreBlanksAndCase (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 | |
286 | const FcChar8 * |
287 | FcStrContainsIgnoreBlanksAndCase (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 | |
298 | static FcBool |
299 | FcCharIsPunct (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 | |
322 | static FcBool |
323 | FcStrIsAtIgnoreCase (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 | |
345 | const FcChar8 * |
346 | FcStrContainsIgnoreCase (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 | |
361 | const FcChar8 * |
362 | FcStrContainsWord (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 | |
389 | int |
390 | FcStrMatchIgnoreCaseAndDelims (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 | |
410 | FcBool |
411 | FcStrGlobMatch (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 | |
454 | const FcChar8 * |
455 | FcStrStrIgnoreCase (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 | |
499 | const FcChar8 * |
500 | FcStrStr (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 | |
512 | again: |
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 | |
549 | int |
550 | FcUtf8ToUcs4 (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 | |
620 | FcBool |
621 | FcUtf8Len (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 | |
654 | int |
655 | FcUcs4ToUtf8 (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 | |
679 | int |
680 | FcUtf16ToUcs4 (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 | |
716 | FcBool |
717 | FcUtf16Len (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 | |
751 | void |
752 | FcStrBufInit (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 | |
768 | void |
769 | FcStrBufDestroy (FcStrBuf *buf) |
770 | { |
771 | if (buf->allocated) |
772 | { |
773 | free (buf->buf); |
774 | FcStrBufInit (buf, 0, 0); |
775 | } |
776 | } |
777 | |
778 | FcChar8 * |
779 | FcStrBufDone (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 | |
796 | FcChar8 * |
797 | FcStrBufDoneStatic (FcStrBuf *buf) |
798 | { |
799 | FcStrBufChar (buf, '\0'); |
800 | |
801 | if (buf->failed) |
802 | return NULL((void*)0); |
803 | |
804 | return buf->buf; |
805 | } |
806 | |
807 | FcBool |
808 | FcStrBufChar (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 | |
845 | FcBool |
846 | FcStrBufString (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 | |
855 | FcBool |
856 | FcStrBufData (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 | |
864 | FcBool |
865 | FcStrUsesHome (const FcChar8 *s) |
866 | { |
867 | return *s == '~'; |
868 | } |
869 | |
870 | FcChar8 * |
871 | FcStrBuildFilename (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 | |
922 | bail2: |
923 | FcStrListDone (list); |
924 | bail1: |
925 | va_end (ap)__builtin_va_end(ap); |
926 | bail0: |
927 | FcStrSetDestroy (sset); |
928 | |
929 | return ret; |
930 | } |
931 | |
932 | FcChar8 * |
933 | FcStrCopyFilename (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 | |
959 | FcChar8 * |
960 | FcStrLastSlash (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 | |
978 | FcChar8 * |
979 | FcStrDirname (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 | |
995 | FcChar8 * |
996 | FcStrBasename (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 | |
1006 | static FcChar8 * |
1007 | FcStrCanonAbsoluteFilename (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 | */ |
1063 | static void |
1064 | FcConvertDosPath (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 | |
1097 | FcChar8 * |
1098 | FcStrCanonFilename (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 | |
1130 | FcStrSet * |
1131 | FcStrSetCreate (void) |
1132 | { |
1133 | return FcStrSetCreateEx (FCSS_DEFAULT0); |
1134 | } |
1135 | |
1136 | FcStrSet * |
1137 | FcStrSetCreateEx (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 | |
1150 | static 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 | |
1166 | static 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 | |
1188 | FcBool |
1189 | FcStrSetMember (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 | |
1199 | FcBool |
1200 | FcStrSetEqual (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 | |
1211 | FcBool |
1212 | FcStrSetAdd (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 | |
1225 | FcBool |
1226 | FcStrSetAddFilename (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 | |
1239 | FcBool |
1240 | FcStrSetAddLangs (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 | |
1283 | FcBool |
1284 | FcStrSetDel (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 */ |
1305 | static FcStrSet * |
1306 | FcStrSetReference (FcStrSet *set) |
1307 | { |
1308 | if (FcRefIsConst (&set->ref)) |
1309 | return set; |
1310 | |
1311 | FcRefInc (&set->ref); |
1312 | return set; |
1313 | } |
1314 | |
1315 | void |
1316 | FcStrSetDestroy (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 | |
1334 | FcStrList * |
1335 | FcStrListCreate (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 | |
1348 | void |
1349 | FcStrListFirst (FcStrList *list) |
1350 | { |
1351 | list->n = 0; |
1352 | } |
1353 | |
1354 | FcChar8 * |
1355 | FcStrListNext (FcStrList *list) |
1356 | { |
1357 | if (list->n >= list->set->num) |
1358 | return 0; |
1359 | return list->set->strs[list->n++]; |
1360 | } |
1361 | |
1362 | void |
1363 | FcStrListDone (FcStrList *list) |
1364 | { |
1365 | FcStrSetDestroy (list->set); |
1366 | free (list); |
1367 | } |
1368 | |
1369 | #define __fcstr__ |
1370 | #include "fcaliastail.h" |
1371 | #undef __fcstr__ |