2 * $RCSId: xc/lib/fontconfig/src/fcstr.c,v 1.10 2002/08/31 22:17:32 keithp Exp $
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
31 FcStrCopy (const FcChar8 *s)
37 r = (FcChar8 *) malloc (strlen ((char *) s) + 1);
40 FcMemAlloc (FC_MEM_STRING, strlen ((char *) s) + 1);
41 strcpy ((char *) r, (char *) s);
46 FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
48 int l = strlen ((char *)s1) + strlen ((char *) s2) + 1;
49 FcChar8 *s = malloc (l);
53 FcMemAlloc (FC_MEM_STRING, l);
54 strcpy ((char *) s, (char *) s1);
55 strcat ((char *) s, (char *) s2);
60 FcStrFree (FcChar8 *s)
62 FcMemFree (FC_MEM_STRING, strlen ((char *) s) + 1);
67 #include "../fc-case/fccase.h"
69 #define FcCaseFoldUpperCount(cf) \
70 ((cf)->method == FC_CASE_FOLD_FULL ? 1 : (cf)->count)
72 #define FC_STR_CANON_BUF_LEN 1024
74 typedef struct _FcCaseWalker {
78 FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS + 1];
82 FcStrCaseWalkerInit (const FcChar8 *src, FcCaseWalker *w)
86 w->len = strlen (src);
90 FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
95 slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, w->len);
98 if (FC_MIN_FOLD_CHAR <= ucs4 && ucs4 <= FC_MAX_FOLD_CHAR)
101 int max = FC_NUM_CASE_FOLD;
105 int mid = (min + max) >> 1;
106 FcChar32 low = fcCaseFold[mid].upper;
107 FcChar32 high = low + FcCaseFoldUpperCount (&fcCaseFold[mid]);
115 const FcCaseFold *fold = &fcCaseFold[mid];
118 switch (fold->method) {
119 case FC_CASE_FOLD_EVEN_ODD:
120 if ((ucs4 & 1) != (fold->upper & 1))
122 /* fall through ... */
124 dlen = FcUcs4ToUtf8 (ucs4 + fold->offset, w->utf8);
126 case FC_CASE_FOLD_FULL:
128 memcpy (w->utf8, fcCaseFoldChars + fold->offset, dlen);
132 /* consume rest of src utf-8 bytes */
136 /* read from temp buffer */
137 w->utf8[dlen] = '\0';
147 FcStrCaseWalkerNext (FcCaseWalker *w)
153 if ((r = *w->read++))
160 if ((r & 0xc0) == 0xc0)
161 return FcStrCaseWalkerLong (w, r);
162 if ('A' <= r && r <= 'Z')
168 FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker *w)
174 if ((r = *w->read++))
184 if ((r & 0xc0) == 0xc0)
185 return FcStrCaseWalkerLong (w, r);
186 if ('A' <= r && r <= 'Z')
192 FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
197 if (s1 == s2) return 0;
199 FcStrCaseWalkerInit (s1, &w1);
200 FcStrCaseWalkerInit (s2, &w2);
204 c1 = FcStrCaseWalkerNext (&w1);
205 c2 = FcStrCaseWalkerNext (&w2);
206 if (!c1 || (c1 != c2))
209 return (int) c1 - (int) c2;
213 FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
218 if (s1 == s2) return 0;
220 FcStrCaseWalkerInit (s1, &w1);
221 FcStrCaseWalkerInit (s2, &w2);
225 c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
226 c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
227 if (!c1 || (c1 != c2))
230 return (int) c1 - (int) c2;
234 FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
247 return (int) c1 - (int) c2;
251 * Return a hash value for a string
255 FcStrHashIgnoreCase (const FcChar8 *s)
261 FcStrCaseWalkerInit (s, &w);
262 while ((c = FcStrCaseWalkerNext (&w)))
263 h = ((h << 3) ^ (h >> 3)) ^ c;
268 * Is the head of s1 equal to s2?
272 FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
277 FcStrCaseWalkerInit (s1, &w1);
278 FcStrCaseWalkerInit (s2, &w2);
282 c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
283 c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
284 if (!c1 || (c1 != c2))
287 return c1 == c2 || !c2;
291 * Does s1 contain an instance of s2 (ignoring blanks and case)?
295 FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
299 if (FcStrIsAtIgnoreBlanksAndCase (s1, s2))
307 * Is the head of s1 equal to s2?
311 FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
316 FcStrCaseWalkerInit (s1, &w1);
317 FcStrCaseWalkerInit (s2, &w2);
321 c1 = FcStrCaseWalkerNext (&w1);
322 c2 = FcStrCaseWalkerNext (&w2);
323 if (!c1 || (c1 != c2))
326 return c1 == c2 || !c2;
330 * Does s1 contain an instance of s2 (ignoring blanks and case)?
334 FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
338 if (FcStrIsAtIgnoreCase (s1, s2))
346 FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
358 FcStrCaseWalkerInit (s1, &w1);
359 FcStrCaseWalkerInit (s2, &w2);
361 c2 = FcStrCaseWalkerNext (&w2);
366 c1 = FcStrCaseWalkerNext (&w1);
371 FcCaseWalker w1t = w1;
372 FcCaseWalker w2t = w2;
377 c1t = FcStrCaseWalkerNext (&w1t);
378 c2t = FcStrCaseWalkerNext (&w2t);
391 FcStrStr (const FcChar8 *s1, const FcChar8 *s2)
394 const FcChar8 * p = s1;
395 const FcChar8 * b = s2;
424 if (c1 && c2 && c1 != c2)
442 FcUtf8ToUcs4 (const FcChar8 *src_orig,
446 const FcChar8 *src = src_orig;
462 else if (!(s & 0x40))
466 else if (!(s & 0x20))
471 else if (!(s & 0x10))
476 else if (!(s & 0x08))
481 else if (!(s & 0x04))
486 else if ( ! (s & 0x02))
503 if ((s & 0xc0) != 0x80)
509 return src - src_orig;
513 FcUtf8Len (const FcChar8 *string,
527 clen = FcUtf8ToUcs4 (string, &c, len);
528 if (clen <= 0) /* malformed UTF8 string */
539 else if (max > 0x100)
547 FcUcs4ToUtf8 (FcChar32 ucs4,
548 FcChar8 dest[FC_UTF8_MAX_LEN])
553 if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
554 else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
555 else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
556 else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
557 else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
558 else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
561 for ( ; bits >= 0; bits-= 6) {
562 *d++= ((ucs4 >> bits) & 0x3F) | 0x80;
567 #define GetUtf16(src,endian) \
568 ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
569 (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
572 FcUtf16ToUcs4 (const FcChar8 *src_orig,
575 int len) /* in bytes */
577 const FcChar8 *src = src_orig;
584 a = GetUtf16 (src, endian); src += 2; len -= 2;
587 * Check for surrogate
589 if ((a & 0xfc00) == 0xd800)
593 b = GetUtf16 (src, endian); src += 2; len -= 2;
595 * Check for invalid surrogate sequence
597 if ((b & 0xfc00) != 0xdc00)
599 result = ((((FcChar32) a & 0x3ff) << 10) |
600 ((FcChar32) b & 0x3ff)) + 0x10000;
605 return src - src_orig;
609 FcUtf16Len (const FcChar8 *string,
611 int len, /* in bytes */
624 clen = FcUtf16ToUcs4 (string, endian, &c, len);
625 if (clen <= 0) /* malformed UTF8 string */
636 else if (max > 0x100)
644 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
647 buf->allocated = FcFalse;
648 buf->failed = FcFalse;
654 FcStrBufDestroy (FcStrBuf *buf)
658 FcMemFree (FC_MEM_STRBUF, buf->size);
660 FcStrBufInit (buf, 0, 0);
665 FcStrBufDone (FcStrBuf *buf)
669 ret = malloc (buf->len + 1);
672 FcMemAlloc (FC_MEM_STRING, buf->len + 1);
673 memcpy (ret, buf->buf, buf->len);
674 ret[buf->len] = '\0';
676 FcStrBufDestroy (buf);
681 FcStrBufChar (FcStrBuf *buf, FcChar8 c)
683 if (buf->len == buf->size)
690 size = buf->size * 2;
691 new = realloc (buf->buf, size);
695 size = buf->size + 1024;
699 buf->allocated = FcTrue;
700 memcpy (new, buf->buf, buf->len);
705 buf->failed = FcTrue;
709 FcMemFree (FC_MEM_STRBUF, buf->size);
710 FcMemAlloc (FC_MEM_STRBUF, size);
714 buf->buf[buf->len++] = c;
719 FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
723 if (!FcStrBufChar (buf, c))
729 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
732 if (!FcStrBufChar (buf, *s++))
738 FcStrUsesHome (const FcChar8 *s)
744 FcStrCopyFilename (const FcChar8 *s)
750 FcChar8 *home = FcConfigHome ();
754 size = strlen ((char *) home) + strlen ((char *) s);
755 new = (FcChar8 *) malloc (size);
758 FcMemAlloc (FC_MEM_STRING, size);
759 strcpy ((char *) new, (char *) home);
760 strcat ((char *) new, (char *) s + 1);
764 int size = strlen ((char *) s) + 1;
765 new = (FcChar8 *) malloc (size);
768 FcMemAlloc (FC_MEM_STRING, size);
769 strcpy ((char *) new, (const char *) s);
775 FcStrLastSlash (const FcChar8 *path)
779 slash = (FcChar8 *) strrchr ((const char *) path, '/');
784 backslash = (FcChar8 *) strrchr ((const char *) path, '\\');
785 if (!slash || (backslash && backslash > slash))
794 FcStrDirname (const FcChar8 *file)
799 slash = FcStrLastSlash (file);
801 return FcStrCopy ((FcChar8 *) ".");
802 dir = malloc ((slash - file) + 1);
805 FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
806 strncpy ((char *) dir, (const char *) file, slash - file);
807 dir[slash - file] = '\0';
812 FcStrBasename (const FcChar8 *file)
816 slash = FcStrLastSlash (file);
818 return FcStrCopy (file);
819 return FcStrCopy (slash + 1);
823 FcStrSetCreate (void)
825 FcStrSet *set = malloc (sizeof (FcStrSet));
828 FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
837 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
839 if (FcStrSetMember (set, s))
844 if (set->num == set->size)
846 FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
850 FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
851 set->size = set->size + 1;
853 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
858 set->strs[set->num++] = s;
859 set->strs[set->num] = 0;
864 FcStrSetMember (FcStrSet *set, const FcChar8 *s)
868 for (i = 0; i < set->num; i++)
869 if (!FcStrCmp (set->strs[i], s))
875 FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
878 if (sa->num != sb->num)
880 for (i = 0; i < sa->num; i++)
881 if (!FcStrSetMember (sb, sa->strs[i]))
887 FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
889 FcChar8 *new = FcStrCopy (s);
892 if (!_FcStrSetAppend (set, new))
901 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
903 FcChar8 *new = FcStrCopyFilename (s);
906 if (!_FcStrSetAppend (set, new))
915 FcStrSetDel (FcStrSet *set, const FcChar8 *s)
919 for (i = 0; i < set->num; i++)
920 if (!FcStrCmp (set->strs[i], s))
922 FcStrFree (set->strs[i]);
924 * copy remaining string pointers and trailing
927 memmove (&set->strs[i], &set->strs[i+1],
928 (set->num - i) * sizeof (FcChar8 *));
936 FcStrSetDestroy (FcStrSet *set)
942 for (i = 0; i < set->num; i++)
943 FcStrFree (set->strs[i]);
944 FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
947 FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
953 FcStrListCreate (FcStrSet *set)
957 list = malloc (sizeof (FcStrList));
960 FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
968 FcStrListNext (FcStrList *list)
970 if (list->n >= list->set->num)
972 return list->set->strs[list->n++];
976 FcStrListDone (FcStrList *list)
978 FcStrSetDestroy (list->set);
979 FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));