6 #define FcChar32 unsigned int
8 #define FcChar16 unsigned short
12 #define FcMemAlloc(group, size)
13 #define FcMemFree(group, size)
14 #define intptr_t unsigned int
16 #define FC_CHARSET_MAP_SIZE (256/32)
17 #define FC_CHARSET_DONE ((FcChar32) -1)
18 #define FC_UTF8_MAX_LEN 6
20 typedef enum { FcEndianBig
, FcEndianLittle
} FcEndian
;
22 typedef struct _FcCaseFold
{
24 unsigned short method
: 2;
25 unsigned short count
: 14;
26 short offset
; /* lower - upper for RANGE, table id for FULL */
29 typedef struct _FcStrBuf
{
35 char buf_static
[16 * sizeof (void *)];
39 int ref
; /* reference count */
40 int num
; /* size of leaves and numbers arrays */
41 intptr_t leaves_offset
;
42 intptr_t numbers_offset
;
46 typedef struct _FcStrSet
{
47 int ref
; /* reference count */
55 #define FC_CASE_FOLD_RANGE 0
56 #define FC_CASE_FOLD_EVEN_ODD 1
57 #define FC_CASE_FOLD_FULL 2
59 static int FcUtf8ToUcs4 (const FcChar8
*src_orig
, FcChar32
*dst
, int len
);
60 static int FcUcs4ToUtf8 (FcChar32 ucs4
, FcChar8 dest
[FC_UTF8_MAX_LEN
]);
61 static FcBool
FcStrBufChar (FcStrBuf
*buf
, FcChar8 c
);
63 static FcChar8
*FcStrCopy (const FcChar8
*s
)
70 len
= strlen ((char *) s
) + 1;
71 r
= (FcChar8
*) malloc (len
);
74 FcMemAlloc (FC_MEM_STRING
, len
);
79 static FcChar8
*FcStrPlus (const FcChar8
*s1
, const FcChar8
*s2
)
81 int l
= strlen ((char *)s1
) + strlen ((char *) s2
) + 1;
82 FcChar8
*s
= malloc (l
);
86 FcMemAlloc (FC_MEM_STRING
, l
);
87 strcpy ((char *) s
, (char *) s1
);
88 strcat ((char *) s
, (char *) s2
);
92 static void FcStrFree (FcChar8
*s
)
94 FcMemFree (FC_MEM_STRING
, strlen ((char *) s
) + 1);
100 #define FcCaseFoldUpperCount(cf) \
101 ((cf)->method == FC_CASE_FOLD_FULL ? 1 : (cf)->count)
104 #define FC_STR_CANON_BUF_LEN 1024
106 typedef struct _FcCaseWalker
{
109 FcChar8 utf8
[FC_MAX_CASE_FOLD_CHARS
+ 1];
112 static void FcStrCaseWalkerInit (const FcChar8
*src
, FcCaseWalker
*w
)
118 static FcChar8
FcStrCaseWalkerLong (FcCaseWalker
*w
, FcChar8 r
)
122 int len
= strlen((char*)w
->src
);
124 slen
= FcUtf8ToUcs4 (w
->src
- 1, &ucs4
, len
+ 1);
127 if (FC_MIN_FOLD_CHAR
<= ucs4
&& ucs4
<= FC_MAX_FOLD_CHAR
)
130 int max
= FC_NUM_CASE_FOLD
;
134 int mid
= (min
+ max
) >> 1;
135 FcChar32 low
= fcCaseFold
[mid
].upper
;
136 FcChar32 high
= low
+ FcCaseFoldUpperCount (&fcCaseFold
[mid
]);
144 const FcCaseFold
*fold
= &fcCaseFold
[mid
];
147 switch (fold
->method
) {
148 case FC_CASE_FOLD_EVEN_ODD
:
149 if ((ucs4
& 1) != (fold
->upper
& 1))
151 /* fall through ... */
153 dlen
= FcUcs4ToUtf8 (ucs4
+ fold
->offset
, w
->utf8
);
155 case FC_CASE_FOLD_FULL
:
157 memcpy (w
->utf8
, fcCaseFoldChars
+ fold
->offset
, dlen
);
161 /* consume rest of src utf-8 bytes */
164 /* read from temp buffer */
165 w
->utf8
[dlen
] = '\0';
174 static FcChar8
FcStrCaseWalkerNext (FcCaseWalker
*w
)
180 if ((r
= *w
->read
++))
186 if ((r
& 0xc0) == 0xc0)
187 return FcStrCaseWalkerLong (w
, r
);
188 if ('A' <= r
&& r
<= 'Z')
193 static FcChar8
FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker
*w
)
199 if ((r
= *w
->read
++))
208 if ((r
& 0xc0) == 0xc0)
209 return FcStrCaseWalkerLong (w
, r
);
210 if ('A' <= r
&& r
<= 'Z')
215 static FcChar8
*FcStrDowncase (const FcChar8
*s
)
221 FcStrCaseWalkerInit (s
, &w
);
222 while (FcStrCaseWalkerNext (&w
))
224 d
= dst
= malloc (len
+ 1);
227 FcMemAlloc (FC_MEM_STRING
, len
+ 1);
228 FcStrCaseWalkerInit (s
, &w
);
229 while ((*d
++ = FcStrCaseWalkerNext (&w
)));
233 static int FcStrCmpIgnoreCase (const FcChar8
*s1
, const FcChar8
*s2
)
238 if (s1
== s2
) return 0;
240 FcStrCaseWalkerInit (s1
, &w1
);
241 FcStrCaseWalkerInit (s2
, &w2
);
245 c1
= FcStrCaseWalkerNext (&w1
);
246 c2
= FcStrCaseWalkerNext (&w2
);
247 if (!c1
|| (c1
!= c2
))
250 return (int) c1
- (int) c2
;
253 static int FcStrCmpIgnoreBlanksAndCase (const FcChar8
*s1
, const FcChar8
*s2
)
258 if (s1
== s2
) return 0;
260 FcStrCaseWalkerInit (s1
, &w1
);
261 FcStrCaseWalkerInit (s2
, &w2
);
265 c1
= FcStrCaseWalkerNextIgnoreBlanks (&w1
);
266 c2
= FcStrCaseWalkerNextIgnoreBlanks (&w2
);
267 if (!c1
|| (c1
!= c2
))
270 return (int) c1
- (int) c2
;
273 static int FcStrCmp (const FcChar8
*s1
, const FcChar8
*s2
)
286 return (int) c1
- (int) c2
;
290 * Return a hash value for a string
293 static FcChar32
FcStrHashIgnoreCase (const FcChar8
*s
)
299 FcStrCaseWalkerInit (s
, &w
);
300 while ((c
= FcStrCaseWalkerNext (&w
)))
301 h
= ((h
<< 3) ^ (h
>> 3)) ^ c
;
306 * Is the head of s1 equal to s2?
310 FcStrIsAtIgnoreBlanksAndCase (const FcChar8
*s1
, const FcChar8
*s2
)
315 FcStrCaseWalkerInit (s1
, &w1
);
316 FcStrCaseWalkerInit (s2
, &w2
);
320 c1
= FcStrCaseWalkerNextIgnoreBlanks (&w1
);
321 c2
= FcStrCaseWalkerNextIgnoreBlanks (&w2
);
322 if (!c1
|| (c1
!= c2
))
325 return c1
== c2
|| !c2
;
329 * Does s1 contain an instance of s2 (ignoring blanks and case)?
332 static const FcChar8
*FcStrContainsIgnoreBlanksAndCase (const FcChar8
*s1
, const FcChar8
*s2
)
336 if (FcStrIsAtIgnoreBlanksAndCase (s1
, s2
))
343 static FcBool
FcCharIsPunct (const FcChar8 c
)
363 * Is the head of s1 equal to s2?
366 static FcBool
FcStrIsAtIgnoreCase (const FcChar8
*s1
, const FcChar8
*s2
)
371 FcStrCaseWalkerInit (s1
, &w1
);
372 FcStrCaseWalkerInit (s2
, &w2
);
376 c1
= FcStrCaseWalkerNext (&w1
);
377 c2
= FcStrCaseWalkerNext (&w2
);
378 if (!c1
|| (c1
!= c2
))
381 return c1
== c2
|| !c2
;
385 * Does s1 contain an instance of s2 (ignoring blanks and case)?
388 static const FcChar8
*FcStrContainsIgnoreCase (const FcChar8
*s1
, const FcChar8
*s2
)
392 if (FcStrIsAtIgnoreCase (s1
, s2
))
400 * Does s1 contain an instance of s2 on a word boundary (ignoring case)?
403 static const FcChar8
*FcStrContainsWord (const FcChar8
*s1
, const FcChar8
*s2
)
405 FcBool wordStart
= FcTrue
;
406 int s1len
= strlen ((char *) s1
);
407 int s2len
= strlen ((char *) s2
);
409 while (s1len
>= s2len
)
412 FcStrIsAtIgnoreCase (s1
, s2
) &&
413 (s1len
== s2len
|| FcCharIsPunct (s1
[s2len
])))
418 if (FcCharIsPunct (*s1
))
426 static const FcChar8
*FcStrStrIgnoreCase (const FcChar8
*s1
, const FcChar8
*s2
)
438 FcStrCaseWalkerInit (s1
, &w1
);
439 FcStrCaseWalkerInit (s2
, &w2
);
441 c2
= FcStrCaseWalkerNext (&w2
);
446 c1
= FcStrCaseWalkerNext (&w1
);
451 FcCaseWalker w1t
= w1
;
452 FcCaseWalker w2t
= w2
;
457 c1t
= FcStrCaseWalkerNext (&w1t
);
458 c2t
= FcStrCaseWalkerNext (&w2t
);
470 static const FcChar8
*FcStrStr (const FcChar8
*s1
, const FcChar8
*s2
)
473 const FcChar8
* p
= s1
;
474 const FcChar8
* b
= s2
;
503 if (c1
&& c2
&& c1
!= c2
)
519 static int FcUtf8ToUcs4 (const FcChar8
*src_orig
,
523 const FcChar8
*src
= src_orig
;
539 else if (!(s
& 0x40))
543 else if (!(s
& 0x20))
548 else if (!(s
& 0x10))
553 else if (!(s
& 0x08))
558 else if (!(s
& 0x04))
563 else if ( ! (s
& 0x02))
580 if ((s
& 0xc0) != 0x80)
586 return src
- src_orig
;
589 static FcBool
FcUtf8Len (const FcChar8
*string
,
603 clen
= FcUtf8ToUcs4 (string
, &c
, len
);
604 if (clen
<= 0) /* malformed UTF8 string */
615 else if (max
> 0x100)
622 static int FcUcs4ToUtf8 (FcChar32 ucs4
,
623 FcChar8 dest
[FC_UTF8_MAX_LEN
])
628 if (ucs4
< 0x80) { *d
++= ucs4
; bits
= -6; }
629 else if (ucs4
< 0x800) { *d
++= ((ucs4
>> 6) & 0x1F) | 0xC0; bits
= 0; }
630 else if (ucs4
< 0x10000) { *d
++= ((ucs4
>> 12) & 0x0F) | 0xE0; bits
= 6; }
631 else if (ucs4
< 0x200000) { *d
++= ((ucs4
>> 18) & 0x07) | 0xF0; bits
= 12; }
632 else if (ucs4
< 0x4000000) { *d
++= ((ucs4
>> 24) & 0x03) | 0xF8; bits
= 18; }
633 else if (ucs4
< 0x80000000) { *d
++= ((ucs4
>> 30) & 0x01) | 0xFC; bits
= 24; }
636 for ( ; bits
>= 0; bits
-= 6) {
637 *d
++= ((ucs4
>> bits
) & 0x3F) | 0x80;
642 #define GetUtf16(src,endian) \
643 ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
644 (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
646 static int FcUtf16ToUcs4 (const FcChar8
*src_orig
,
649 int len
) /* in bytes */
651 const FcChar8
*src
= src_orig
;
658 a
= GetUtf16 (src
, endian
); src
+= 2; len
-= 2;
661 * Check for surrogate
663 if ((a
& 0xfc00) == 0xd800)
667 b
= GetUtf16 (src
, endian
); src
+= 2; len
-= 2;
669 * Check for invalid surrogate sequence
671 if ((b
& 0xfc00) != 0xdc00)
673 result
= ((((FcChar32
) a
& 0x3ff) << 10) |
674 ((FcChar32
) b
& 0x3ff)) + 0x10000;
679 return src
- src_orig
;
682 static FcBool
FcUtf16Len (const FcChar8
*string
,
684 int len
, /* in bytes */
697 clen
= FcUtf16ToUcs4 (string
, endian
, &c
, len
);
698 if (clen
<= 0) /* malformed UTF8 string */
709 else if (max
> 0x100)
716 static void FcStrBufInit (FcStrBuf
*buf
, FcChar8
*init
, int size
)
724 buf
->buf
= buf
->buf_static
;
725 buf
->size
= sizeof (buf
->buf_static
);
727 buf
->allocated
= FcFalse
;
728 buf
->failed
= FcFalse
;
732 static void FcStrBufDestroy (FcStrBuf
*buf
)
736 FcMemFree (FC_MEM_STRBUF
, buf
->size
);
738 FcStrBufInit (buf
, 0, 0);
742 static FcChar8
*FcStrBufDone (FcStrBuf
*buf
)
749 ret
= malloc (buf
->len
+ 1);
752 FcMemAlloc (FC_MEM_STRING
, buf
->len
+ 1);
753 memcpy (ret
, buf
->buf
, buf
->len
);
754 ret
[buf
->len
] = '\0';
756 FcStrBufDestroy (buf
);
760 static FcChar8
*FcStrBufDoneStatic (FcStrBuf
*buf
)
762 FcStrBufChar (buf
, '\0');
770 static FcBool
FcStrBufChar (FcStrBuf
*buf
, FcChar8 c
)
772 if (buf
->len
== buf
->size
)
782 size
= buf
->size
* 2;
783 new = realloc (buf
->buf
, size
);
787 size
= buf
->size
+ 64;
791 buf
->allocated
= FcTrue
;
792 memcpy (new, buf
->buf
, buf
->len
);
797 buf
->failed
= FcTrue
;
801 FcMemFree (FC_MEM_STRBUF
, buf
->size
);
802 FcMemAlloc (FC_MEM_STRBUF
, size
);
806 buf
->buf
[buf
->len
++] = c
;
810 static FcBool
FcStrBufString (FcStrBuf
*buf
, const FcChar8
*s
)
814 if (!FcStrBufChar (buf
, c
))
819 static FcBool
FcStrBufData (FcStrBuf
*buf
, const FcChar8
*s
, int len
)
822 if (!FcStrBufChar (buf
, *s
++))
829 static FcStrSet
*FcStrSetCreate (void)
831 FcStrSet
*set
= malloc (sizeof (FcStrSet
));
834 FcMemAlloc (FC_MEM_STRSET
, sizeof (FcStrSet
));
842 static FcBool
FcStrSetMember (FcStrSet
*set
, const FcChar8
*s
);
845 static FcBool
_FcStrSetAppend (FcStrSet
*set
, FcChar8
*s
)
847 if (FcStrSetMember (set
, s
))
852 if (set
->num
== set
->size
)
854 FcChar8
**strs
= malloc ((set
->size
+ 2) * sizeof (FcChar8
*));
858 FcMemAlloc (FC_MEM_STRSET
, (set
->size
+ 2) * sizeof (FcChar8
*));
860 memcpy (strs
, set
->strs
, set
->num
* sizeof (FcChar8
*));
863 FcMemFree (FC_MEM_STRSET
, (set
->size
+ 1) * sizeof (FcChar8
*));
866 set
->size
= set
->size
+ 1;
869 set
->strs
[set
->num
++] = s
;
870 set
->strs
[set
->num
] = 0;
876 static FcBool
FcStrSetMember (FcStrSet
*set
, const FcChar8
*s
)
880 for (i
= 0; i
< set
->num
; i
++)
881 if (!FcStrCmp (set
->strs
[i
], s
))
886 static FcBool
FcStrSetEqual (FcStrSet
*sa
, FcStrSet
*sb
)
889 if (sa
->num
!= sb
->num
)
891 for (i
= 0; i
< sa
->num
; i
++)
892 if (!FcStrSetMember (sb
, sa
->strs
[i
]))
897 static FcBool
FcStrSetAdd (FcStrSet
*set
, const FcChar8
*s
)
899 FcChar8
*new = FcStrCopy (s
);
902 if (!_FcStrSetAppend (set
, new))
912 FcStrSetAddFilename (FcStrSet
*set
, const FcChar8
*s
)
914 FcChar8
*new = FcStrCopyFilename (s
);
917 if (!_FcStrSetAppend (set
, new))
926 static FcBool
FcStrSetDel (FcStrSet
*set
, const FcChar8
*s
)
930 for (i
= 0; i
< set
->num
; i
++)
931 if (!FcStrCmp (set
->strs
[i
], s
))
933 FcStrFree (set
->strs
[i
]);
935 * copy remaining string pointers and trailing
938 memmove (&set
->strs
[i
], &set
->strs
[i
+1],
939 (set
->num
- i
) * sizeof (FcChar8
*));
946 static void FcStrSetDestroy (FcStrSet
*set
)
952 for (i
= 0; i
< set
->num
; i
++)
953 FcStrFree (set
->strs
[i
]);
956 FcMemFree (FC_MEM_STRSET
, (set
->size
+ 1) * sizeof (FcChar8
*));
959 FcMemFree (FC_MEM_STRSET
, sizeof (FcStrSet
));