2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
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
{
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',
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',
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
])
43 return *p1
== canon_map
[*p2
];
46 struct hb_language_item_t
{
47 struct hb_language_item_t
*next
;
51 static hb_language_t
lang_assign(const char *s
)
55 hb_language_t lang
= (hb_language_t
) strdup(s
);
56 for (p
= (unsigned char *)lang
; *p
; p
++)
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
);
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
))
78 /*Not found; allocate one. */
79 lang_item
= calloc(1, sizeof(*lang_item
));
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
))
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
;
102 len
= MIN(len
, (int)sizeof(strbuf
) - 1);
103 str
= (char *)memcpy(strbuf
, str
, len
);
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
)
116 if (!str
|| !len
|| !*str
)
119 if (len
< 0 || len
> 4)
121 for (i
= 0; i
< (unsigned)len
&& str
[i
]; ++i
)
125 return HB_TAG_CHAR4(tag
);
128 const char *hb_language_to_string(hb_language_t language
)
130 /*This is actually NULL-safe! */
134 hb_bool_t
hb_version_atleast(unsigned int major
,unsigned int minor
,unsigned int micro
)
136 return HB_VERSION_ATLEAST(major
,minor
,micro
);