add explicit freetype2 linking
[charfbuzz.git] / hb-common.c
blob92b54dbaf82493e6f281bb20231df3e1ecb9d63c
1 /*
2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
4 <sylware@legeek.net>
5 */
6 #define _GNU_SOURCE
7 #include <string.h>
8 #include <stdlib.h>
10 #include "hb.h"
11 #include "hb-private.h"
12 #include "hb-atomic-private.h"
14 /*this is actually hb_language_t type*/
15 struct hb_language_impl_t {
16 const char s[1];
19 /*XXX:should go in lib "global init"*/
20 static const char canon_map[256] = {
21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0,
24 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
25 '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
26 'n', 'o',
27 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-',
28 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
29 'o',
30 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0
33 static hb_bool_t lang_equal(hb_language_t v1, const void *v2)
35 const unsigned char *p1;
36 const unsigned char *p2;
38 p1 = (const unsigned char *)v1;
39 p2 = (const unsigned char *)v2;
41 while (*p1 && *p1 == canon_map[*p2])
42 p1++, p2++;
43 return *p1 == canon_map[*p2];
46 struct hb_language_item_t {
47 struct hb_language_item_t *next;
48 hb_language_t lang;
51 static hb_language_t lang_assign(const char *s)
53 unsigned char *p;
55 hb_language_t lang = (hb_language_t) strdup(s);
56 for (p = (unsigned char *)lang; *p; p++)
57 *p = canon_map[*p];
58 return lang;
61 /*Thread-safe lock-free language list*/
63 static struct hb_language_item_t *lang_items;
65 static struct hb_language_item_t *language_item_find_or_insert(const char *key)
67 struct hb_language_item_t *first_lang_item =
68 hb_atomic_ptr_get(&lang_items);
70 while (1) {
71 struct hb_language_item_t *lang_item;
73 for (lang_item = first_lang_item; lang_item;
74 lang_item = lang_item->next)
75 if (lang_equal(lang_item->lang, key))
76 return lang_item;
78 /*Not found; allocate one. */
79 lang_item = calloc(1, sizeof(*lang_item));
80 if (!lang_item)
81 return NULL;
82 lang_item->next = first_lang_item;
83 lang_item->lang = lang_assign(key);
85 if (hb_atomic_ptr_cmpexch
86 (&lang_items, &first_lang_item, &lang_item))
87 return lang_item;
88 free(lang_item);
92 hb_language_t hb_language_from_string(const char *str, int len)
94 struct hb_language_item_t *item;
96 if (!str || !len || !*str)
97 return HB_LANGUAGE_INVALID;
99 if (len >= 0) {
100 char strbuf[64];
102 len = MIN(len, (int)sizeof(strbuf) - 1);
103 str = (char *)memcpy(strbuf, str, len);
104 strbuf[len] = '\0';
107 item = language_item_find_or_insert(str);
108 return item ? item->lang : HB_LANGUAGE_INVALID;
111 hb_tag_t hb_tag_from_string(const char *str, int len)
113 char tag[4];
114 unsigned i;
116 if (!str || !len || !*str)
117 return HB_TAG_NONE;
119 if (len < 0 || len > 4)
120 len = 4;
121 for (i = 0; i < (unsigned)len && str[i]; ++i)
122 tag[i] = str[i];
123 for (; i < 4; ++i)
124 tag[i] = ' ';
125 return HB_TAG_CHAR4(tag);
128 const char *hb_language_to_string(hb_language_t language)
130 /*This is actually NULL-safe! */
131 return language->s;
134 hb_bool_t hb_version_atleast(unsigned int major,unsigned int minor,unsigned int micro)
136 return HB_VERSION_ATLEAST(major,minor,micro);