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