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