]> git.wh0rd.org Git - fontconfig.git/blob - src/fcstr.c
Trim ideographic punctuation and Suzhou numerals from zh-tw orthography.
[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 }