]> git.wh0rd.org - fontconfig.git/blob - src/fcstr.c
Optimize after profiling. Fix FcStrCmp to return correct sign
[fontconfig.git] / src / fcstr.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcstr.c,v 1.4 2002/05/21 17:06:22 keithp Exp $
3 *
4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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 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.
15 *
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.
23 */
24
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include "fcint.h"
29
30 FcChar8 *
31 FcStrCopy (const FcChar8 *s)
32 {
33 FcChar8 *r;
34
35 if (!s)
36 return 0;
37 r = (FcChar8 *) malloc (strlen ((char *) s) + 1);
38 if (!r)
39 return 0;
40 FcMemAlloc (FC_MEM_STRING, strlen ((char *) s) + 1);
41 strcpy ((char *) r, (char *) s);
42 return r;
43 }
44
45 FcChar8 *
46 FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
47 {
48 int l = strlen ((char *)s1) + strlen ((char *) s2) + 1;
49 FcChar8 *s = malloc (l);
50
51 if (!s)
52 return 0;
53 FcMemAlloc (FC_MEM_STRING, l);
54 strcpy ((char *) s, (char *) s1);
55 strcat ((char *) s, (char *) s2);
56 return s;
57 }
58
59 void
60 FcStrFree (FcChar8 *s)
61 {
62 FcMemFree (FC_MEM_STRING, strlen ((char *) s) + 1);
63 free (s);
64 }
65
66 int
67 FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
68 {
69 FcChar8 c1, c2;
70
71 for (;;)
72 {
73 c1 = *s1++;
74 c2 = *s2++;
75 if (!c1 || !c2)
76 break;
77 c1 = FcToLower (c1);
78 c2 = FcToLower (c2);
79 if (c1 != c2)
80 break;
81 }
82 return (int) c1 - (int) c2;
83 }
84
85 int
86 FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
87 {
88 FcChar8 c1, c2;
89
90 if (s1 == s2)
91 return 0;
92 for (;;)
93 {
94 c1 = *s1++;
95 c2 = *s2++;
96 if (!c1 || !c2)
97 break;
98 if (c1 != c2)
99 break;
100 }
101 return (int) c1 - (int) c2;
102 }
103
104 int
105 FcUtf8ToUcs4 (FcChar8 *src_orig,
106 FcChar32 *dst,
107 int len)
108 {
109 FcChar8 *src = src_orig;
110 FcChar8 s;
111 int extra;
112 FcChar32 result;
113
114 if (len == 0)
115 return 0;
116
117 s = *src++;
118 len--;
119
120 if (!(s & 0x80))
121 {
122 result = s;
123 extra = 0;
124 }
125 else if (!(s & 0x40))
126 {
127 return -1;
128 }
129 else if (!(s & 0x20))
130 {
131 result = s & 0x1f;
132 extra = 1;
133 }
134 else if (!(s & 0x10))
135 {
136 result = s & 0xf;
137 extra = 2;
138 }
139 else if (!(s & 0x08))
140 {
141 result = s & 0x07;
142 extra = 3;
143 }
144 else if (!(s & 0x04))
145 {
146 result = s & 0x03;
147 extra = 4;
148 }
149 else if ( ! (s & 0x02))
150 {
151 result = s & 0x01;
152 extra = 5;
153 }
154 else
155 {
156 return -1;
157 }
158 if (extra > len)
159 return -1;
160
161 while (extra--)
162 {
163 result <<= 6;
164 s = *src++;
165
166 if ((s & 0xc0) != 0x80)
167 return -1;
168
169 result |= s & 0x3f;
170 }
171 *dst = result;
172 return src - src_orig;
173 }
174
175 FcBool
176 FcUtf8Len (FcChar8 *string,
177 int len,
178 int *nchar,
179 int *wchar)
180 {
181 int n;
182 int clen;
183 FcChar32 c;
184 FcChar32 max;
185
186 n = 0;
187 max = 0;
188 while (len)
189 {
190 clen = FcUtf8ToUcs4 (string, &c, len);
191 if (clen <= 0) /* malformed UTF8 string */
192 return FcFalse;
193 if (c > max)
194 max = c;
195 string += clen;
196 len -= clen;
197 n++;
198 }
199 *nchar = n;
200 if (max >= 0x10000)
201 *wchar = 4;
202 else if (max > 0x100)
203 *wchar = 2;
204 else
205 *wchar = 1;
206 return FcTrue;
207 }
208
209 void
210 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
211 {
212 buf->buf = init;
213 buf->allocated = FcFalse;
214 buf->failed = FcFalse;
215 buf->len = 0;
216 buf->size = size;
217 }
218
219 void
220 FcStrBufDestroy (FcStrBuf *buf)
221 {
222 if (buf->allocated)
223 {
224 free (buf->buf);
225 FcStrBufInit (buf, 0, 0);
226 }
227 }
228
229 FcChar8 *
230 FcStrBufDone (FcStrBuf *buf)
231 {
232 FcChar8 *ret;
233
234 ret = malloc (buf->len + 1);
235 if (ret)
236 {
237 memcpy (ret, buf->buf, buf->len);
238 ret[buf->len] = '\0';
239 }
240 FcStrBufDestroy (buf);
241 return ret;
242 }
243
244 FcBool
245 FcStrBufChar (FcStrBuf *buf, FcChar8 c)
246 {
247 if (buf->len == buf->size)
248 {
249 FcChar8 *new;
250 int size;
251
252 if (buf->allocated)
253 {
254 size = buf->size * 2;
255 new = realloc (buf->buf, size);
256 }
257 else
258 {
259 size = buf->size + 1024;
260 new = malloc (size);
261 if (new)
262 {
263 buf->allocated = FcTrue;
264 memcpy (new, buf->buf, buf->len);
265 }
266 }
267 if (!new)
268 {
269 buf->failed = FcTrue;
270 return FcFalse;
271 }
272 buf->size = size;
273 buf->buf = new;
274 }
275 buf->buf[buf->len++] = c;
276 return FcTrue;
277 }
278
279 FcBool
280 FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
281 {
282 FcChar8 c;
283 while ((c = *s++))
284 if (!FcStrBufChar (buf, c))
285 return FcFalse;
286 return FcTrue;
287 }
288
289 FcBool
290 FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
291 {
292 while (len-- > 0)
293 if (!FcStrBufChar (buf, *s++))
294 return FcFalse;
295 return FcTrue;
296 }
297
298 FcChar8 *
299 FcStrCopyFilename (const FcChar8 *s)
300 {
301 FcChar8 *new;
302
303 if (*s == '~')
304 {
305 FcChar8 *home = (FcChar8 *) getenv ("HOME");
306 int size = strlen ((char *) home) + strlen ((char *) s);
307 if (!home)
308 return 0;
309 new = (FcChar8 *) malloc (size);
310 if (!new)
311 return 0;
312 FcMemAlloc (FC_MEM_STRING, size);
313 strcpy ((char *) new, (char *) home);
314 strcat ((char *) new, (char *) s + 1);
315 }
316 else
317 {
318 int size = strlen ((char *) s) + 1;
319 new = (FcChar8 *) malloc (size);
320 if (!new)
321 return 0;
322 FcMemAlloc (FC_MEM_STRING, size);
323 strcpy ((char *) new, (const char *) s);
324 }
325 return new;
326 }
327
328 FcChar8 *
329 FcStrDirname (const FcChar8 *file)
330 {
331 FcChar8 *slash;
332 FcChar8 *dir;
333
334 slash = (FcChar8 *) strrchr ((char *) file, '/');
335 if (!slash)
336 return FcStrCopy ((FcChar8 *) ".");
337 dir = malloc ((slash - file) + 1);
338 if (!dir)
339 return 0;
340 FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
341 strncpy ((char *) dir, (const char *) file, slash - file);
342 dir[slash - file] = '\0';
343 return dir;
344 }
345
346 FcChar8 *
347 FcStrBasename (const FcChar8 *file)
348 {
349 FcChar8 *slash;
350
351 slash = (FcChar8 *) strrchr ((char *) file, '/');
352 if (!slash)
353 return FcStrCopy (file);
354 return FcStrCopy (slash + 1);
355 }
356
357 FcStrSet *
358 FcStrSetCreate (void)
359 {
360 FcStrSet *set = malloc (sizeof (FcStrSet));
361 if (!set)
362 return 0;
363 FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
364 set->ref = 1;
365 set->num = 0;
366 set->size = 0;
367 set->strs = 0;
368 return set;
369 }
370
371 static FcBool
372 _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
373 {
374 if (FcStrSetMember (set, s))
375 {
376 FcStrFree (s);
377 return FcTrue;
378 }
379 if (set->num == set->size)
380 {
381 FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
382
383 if (!strs)
384 return FcFalse;
385 FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
386 set->size = set->size + 1;
387 if (set->num)
388 memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
389 if (set->strs)
390 free (set->strs);
391 set->strs = strs;
392 }
393 set->strs[set->num++] = s;
394 set->strs[set->num] = 0;
395 return FcTrue;
396 }
397
398 FcBool
399 FcStrSetMember (FcStrSet *set, const FcChar8 *s)
400 {
401 int i;
402
403 for (i = 0; i < set->num; i++)
404 if (!FcStrCmp (set->strs[i], s))
405 return FcTrue;
406 return FcFalse;
407 }
408
409 FcBool
410 FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
411 {
412 FcChar8 *new = FcStrCopy (s);
413 if (!new)
414 return FcFalse;
415 if (!_FcStrSetAppend (set, new))
416 {
417 FcStrFree (new);
418 return FcFalse;
419 }
420 return FcTrue;
421 }
422
423 FcBool
424 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
425 {
426 FcChar8 *new = FcStrCopyFilename (s);
427 if (!new)
428 return FcFalse;
429 if (!_FcStrSetAppend (set, new))
430 {
431 FcStrFree (new);
432 return FcFalse;
433 }
434 return FcTrue;
435 }
436
437 FcBool
438 FcStrSetDel (FcStrSet *set, const FcChar8 *s)
439 {
440 int i;
441
442 for (i = 0; i < set->num; i++)
443 if (!FcStrCmp (set->strs[i], s))
444 {
445 FcStrFree (set->strs[i]);
446 /*
447 * copy remaining string pointers and trailing
448 * NULL
449 */
450 memmove (&set->strs[i], &set->strs[i+1],
451 (set->num - i) * sizeof (FcChar8 *));
452 set->num--;
453 return FcTrue;
454 }
455 return FcFalse;
456 }
457
458 void
459 FcStrSetDestroy (FcStrSet *set)
460 {
461 if (--set->ref == 0)
462 {
463 int i;
464
465 for (i = 0; i < set->num; i++)
466 FcStrFree (set->strs[i]);
467 FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
468 if (set->strs)
469 free (set->strs);
470 FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
471 free (set);
472 }
473 }
474
475 FcStrList *
476 FcStrListCreate (FcStrSet *set)
477 {
478 FcStrList *list;
479
480 list = malloc (sizeof (FcStrList));
481 if (!list)
482 return 0;
483 FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
484 list->set = set;
485 set->ref++;
486 list->n = 0;
487 return list;
488 }
489
490 FcChar8 *
491 FcStrListNext (FcStrList *list)
492 {
493 if (list->n >= list->set->num)
494 return 0;
495 return list->set->strs[list->n++];
496 }
497
498 void
499 FcStrListDone (FcStrList *list)
500 {
501 FcStrSetDestroy (list->set);
502 FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
503 free (list);
504 }