[API] Make all _from_string() functions take a len parameter

Can be -1 for NUL-terminated string.  This is useful for passing parts
of a larger string to a function without having to copy or modify the
string first.

Affected functions:

	hb_tag_t hb_tag_from_string()
	hb_direction_from_string()
	hb_language_from_string()
	hb_script_from_string()
This commit is contained in:
Behdad Esfahbod 2011-08-26 09:18:53 +02:00
parent a499bdea5c
commit 4c9fe88d30
10 changed files with 94 additions and 71 deletions

View File

@ -40,15 +40,17 @@
/* hb_tag_t */
hb_tag_t
hb_tag_from_string (const char *s)
hb_tag_from_string (const char *s, int len)
{
char tag[4];
unsigned int i;
if (!s || !*s)
if (!s || !len || !*s)
return HB_TAG_NONE;
for (i = 0; i < 4 && s[i]; i++)
if (len < 0 || len > 4)
len = 4;
for (i = 0; i < (unsigned) len && s[i]; i++)
tag[i] = s[i];
for (; i < 4; i++)
tag[i] = ' ';
@ -67,9 +69,9 @@ const char direction_strings[][4] = {
};
hb_direction_t
hb_direction_from_string (const char *str)
hb_direction_from_string (const char *str, int len)
{
if (unlikely (!str || !*str))
if (unlikely (!str || !len || !*str))
return HB_DIRECTION_INVALID;
/* Lets match loosely: just match the first letter, such that
@ -167,11 +169,18 @@ static struct hb_static_lang_set_t : hb_lockable_set_t<hb_language_item_t, hb_st
} langs;
hb_language_t
hb_language_from_string (const char *str)
hb_language_from_string (const char *str, int len)
{
if (!str || !*str)
if (!str || !len || !*str)
return HB_LANGUAGE_INVALID;
char strbuf[32];
if (len >= 0) {
len = MIN (len, (int) sizeof (strbuf) - 1);
str = (char *) memcpy (strbuf, str, len);
strbuf[len] = '\0';
}
hb_language_item_t *item = langs.find_or_insert (str, langs.lock);
return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
@ -197,7 +206,7 @@ hb_language_get_default (void)
/* I hear that setlocale() doesn't honor env vars on Windows,
* but for now we ignore that. */
default_language = hb_language_from_string (setlocale (LC_CTYPE, NULL));
default_language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
}
return default_language;
@ -241,9 +250,9 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
}
hb_script_t
hb_script_from_string (const char *s)
hb_script_from_string (const char *s, int len)
{
return hb_script_from_iso15924_tag (hb_tag_from_string (s));
return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
}
hb_tag_t

View File

@ -89,7 +89,8 @@ typedef uint32_t hb_tag_t;
#define HB_TAG_NONE HB_TAG(0,0,0,0)
hb_tag_t hb_tag_from_string (const char *s);
/* len=-1 means s is NUL-terminated */
hb_tag_t hb_tag_from_string (const char *s, int len);
/* hb_direction_t */
@ -102,8 +103,9 @@ typedef enum {
HB_DIRECTION_BTT
} hb_direction_t;
/* len=-1 means s is NUL-terminated */
hb_direction_t
hb_direction_from_string (const char *str);
hb_direction_from_string (const char *str, int len);
const char *
hb_direction_to_string (hb_direction_t direction);
@ -119,8 +121,9 @@ hb_direction_to_string (hb_direction_t direction);
typedef struct _hb_language_t *hb_language_t;
/* len=-1 means s is NUL-terminated */
hb_language_t
hb_language_from_string (const char *str);
hb_language_from_string (const char *str, int len);
const char *
hb_language_to_string (hb_language_t language);
@ -293,8 +296,9 @@ hb_script_t
hb_script_from_iso15924_tag (hb_tag_t tag);
/* suger for tag_from_string() then script_from_iso15924_tag */
/* len=-1 means s is NUL-terminated */
hb_script_t
hb_script_from_string (const char *s);
hb_script_from_string (const char *s, int len);
hb_tag_t
hb_script_to_iso15924_tag (hb_script_t script);

View File

@ -238,7 +238,7 @@ hb_graphite_shape (hb_font_t *font,
/* XXX(behdad): Do we need OT lang tag here? */
const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
gr_feature_val *feats = gr_face_featureval_for_lang (data->grface, lang ? hb_tag_from_string (lang) : 0);
gr_feature_val *feats = gr_face_featureval_for_lang (data->grface, lang ? hb_tag_from_string (lang, -1) : 0);
while (num_features--)
{

View File

@ -46,7 +46,7 @@ hb_icu_script_to_script (UScriptCode script)
if (unlikely (script == USCRIPT_INVALID_CODE))
return HB_SCRIPT_INVALID;
return hb_script_from_string (uscript_getShortName (script));
return hb_script_from_string (uscript_getShortName (script), -1);
}
UScriptCode

View File

@ -664,12 +664,12 @@ hb_ot_tag_to_language (hb_tag_t tag)
for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
if (ot_languages[i].tag == tag)
return hb_language_from_string (ot_languages[i].language);
return hb_language_from_string (ot_languages[i].language, -1);
/* If tag starts with ZH, it's Chinese */
if ((tag & 0xFFFF0000) == 0x5A480000) {
switch (tag) {
case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk"); /* Hong Kong */
case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
default: {
/* Encode the tag... */
unsigned char buf[14] = "zh-x-hbot";
@ -680,7 +680,7 @@ hb_ot_tag_to_language (hb_tag_t tag)
if (buf[12] == 0x20)
buf[12] = '\0';
buf[13] = '\0';
return hb_language_from_string ((char *) buf);
return hb_language_from_string ((char *) buf, -1);
}
}
}
@ -695,7 +695,7 @@ hb_ot_tag_to_language (hb_tag_t tag)
if (buf[9] == 0x20)
buf[9] = '\0';
buf[10] = '\0';
return hb_language_from_string ((char *) buf);
return hb_language_from_string ((char *) buf, -1);
}
}

View File

@ -124,8 +124,8 @@ test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
hb_buffer_set_language (b, hb_language_from_string ("fa"));
g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa"));
hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
/* test reset clears properties */

View File

@ -79,14 +79,15 @@ test_types_direction (void)
g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_TTB), ==, HB_DIRECTION_BTT);
g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_BTT), ==, HB_DIRECTION_TTB);
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string (NULL));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string (""));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("x"));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("r"));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("rtl"));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("RtL"));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("right-to-left"));
g_assert_cmpint (HB_DIRECTION_TTB, ==, hb_direction_from_string ("ttb"));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string (NULL, -1));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("", -1));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("t", 0));
g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("x", -1));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("r", -1));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("rtl", -1));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("RtL", -1));
g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("right-to-left", -1));
g_assert_cmpint (HB_DIRECTION_TTB, ==, hb_direction_from_string ("ttb", -1));
g_assert (0 == strcmp ("ltr", hb_direction_to_string (HB_DIRECTION_LTR)));
g_assert (0 == strcmp ("rtl", hb_direction_to_string (HB_DIRECTION_RTL)));
@ -102,14 +103,20 @@ test_types_tag (void)
g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBcDe"), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBcD"), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBc"), ==, 0x61426320);
g_assert_cmphex (hb_tag_from_string ("aB"), ==, 0x61422020);
g_assert_cmphex (hb_tag_from_string ("a"), ==, 0x61202020);
g_assert_cmphex (hb_tag_from_string ("aBcDe", -1), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBcD", -1), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBc", -1), ==, 0x61426320);
g_assert_cmphex (hb_tag_from_string ("aB", -1), ==, 0x61422020);
g_assert_cmphex (hb_tag_from_string ("a", -1), ==, 0x61202020);
g_assert_cmphex (hb_tag_from_string ("aBcDe", 1), ==, 0x61202020);
g_assert_cmphex (hb_tag_from_string ("aBcDe", 2), ==, 0x61422020);
g_assert_cmphex (hb_tag_from_string ("aBcDe", 3), ==, 0x61426320);
g_assert_cmphex (hb_tag_from_string ("aBcDe", 4), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string ("aBcDe", 4), ==, 0x61426344);
g_assert_cmphex (hb_tag_from_string (""), ==, HB_TAG_NONE);
g_assert_cmphex (hb_tag_from_string (NULL), ==, HB_TAG_NONE);
g_assert_cmphex (hb_tag_from_string ("", -1), ==, HB_TAG_NONE);
g_assert_cmphex (hb_tag_from_string ("x", 0), ==, HB_TAG_NONE);
g_assert_cmphex (hb_tag_from_string (NULL, -1), ==, HB_TAG_NONE);
}
static void
@ -127,23 +134,26 @@ test_types_script (void)
g_assert_cmpint (HB_SCRIPT_INVALID, ==, (hb_script_t) HB_TAG_NONE);
g_assert_cmphex (HB_SCRIPT_ARABIC, !=, HB_SCRIPT_LATIN);
g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string (NULL));
g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string (""));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x"));
g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string (NULL, -1));
g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string ("", -1));
g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string ("x", 0));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x", -1));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("arab"));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("Arab"));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("ARAB"));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("arab", -1));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("Arab", -1));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("ARAB", -1));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("Arabic", 6));
g_assert_cmphex (HB_SCRIPT_ARABIC, !=, hb_script_from_string ("Arabic", 3));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (arab));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (Arab));
g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (ARAB));
/* Arbitrary tags that look like may be valid ISO 15924 should be preserved. */
g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_string ("wWyZ"));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_string ("wWyZ", -1));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_iso15924_tag (wWyZ));
/* Otherwise, UNKNOWN should be returned. */
g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x123"));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x123", -1));
g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_iso15924_tag (x123));
g_assert_cmphex (hb_script_to_iso15924_tag (HB_SCRIPT_ARABIC), ==, Arab);
@ -157,10 +167,10 @@ test_types_script (void)
static void
test_types_language (void)
{
hb_language_t fa = hb_language_from_string ("fa");
hb_language_t fa_IR = hb_language_from_string ("fa_IR");
hb_language_t fa_ir = hb_language_from_string ("fa-ir");
hb_language_t en = hb_language_from_string ("en");
hb_language_t fa = hb_language_from_string ("fa", -1);
hb_language_t fa_IR = hb_language_from_string ("fa_IR", -1);
hb_language_t fa_ir = hb_language_from_string ("fa-ir", -1);
hb_language_t en = hb_language_from_string ("en", -1);
g_assert (HB_LANGUAGE_INVALID == NULL);
@ -172,11 +182,14 @@ test_types_language (void)
g_assert (en != fa);
/* Test recall */
g_assert (en == hb_language_from_string ("en"));
g_assert (en == hb_language_from_string ("eN"));
g_assert (en == hb_language_from_string ("en", -1));
g_assert (en == hb_language_from_string ("eN", -1));
g_assert (en == hb_language_from_string ("Enx", 2));
g_assert (HB_LANGUAGE_INVALID == hb_language_from_string (NULL));
g_assert (HB_LANGUAGE_INVALID == hb_language_from_string (""));
g_assert (HB_LANGUAGE_INVALID == hb_language_from_string (NULL, -1));
g_assert (HB_LANGUAGE_INVALID == hb_language_from_string ("", -1));
g_assert (HB_LANGUAGE_INVALID == hb_language_from_string ("en", 0));
g_assert (HB_LANGUAGE_INVALID != hb_language_from_string ("en", 1));
g_assert (NULL == hb_language_to_string (HB_LANGUAGE_INVALID));
/* Not sure how to test this better. Setting env vars

View File

@ -40,7 +40,7 @@ test_simple_tags (const char *s, hb_script_t script)
hb_script_t t1, t2;
g_test_message ("Testing script %c%c%c%c: tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s);
tag = hb_tag_from_string (s);
tag = hb_tag_from_string (s, -1);
hb_ot_tags_from_script (script, &t1, &t2);
@ -57,8 +57,8 @@ test_indic_tags (const char *s1, const char *s2, hb_script_t script)
hb_script_t t1, t2;
g_test_message ("Testing script %c%c%c%c: new tag %s, old tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s1, s2);
tag1 = hb_tag_from_string (s1);
tag2 = hb_tag_from_string (s2);
tag1 = hb_tag_from_string (s1, -1);
tag2 = hb_tag_from_string (s2, -1);
hb_ot_tags_from_script (script, &t1, &t2);
@ -85,14 +85,14 @@ test_ot_tag_script_degenerate (void)
test_simple_tags ("DFLT", HB_SCRIPT_INVALID);
/* Spaces are replaced */
g_assert_cmphex (hb_ot_tag_to_script (HB_TAG_CHAR4 ("be ")), ==, hb_script_from_string ("Beee"));
g_assert_cmphex (hb_ot_tag_to_script (HB_TAG_CHAR4 ("be ")), ==, hb_script_from_string ("Beee", -1));
}
static void
test_ot_tag_script_simple (void)
{
/* Arbitrary non-existent script */
test_simple_tags ("wwyz", hb_script_from_string ("wWyZ"));
test_simple_tags ("wwyz", hb_script_from_string ("wWyZ", -1));
/* These we don't really care about */
test_simple_tags ("zyyy", HB_SCRIPT_COMMON);
@ -141,8 +141,8 @@ test_ot_tag_script_indic (void)
static void
test_language_two_way (const char *tag_s, const char *lang_s)
{
hb_language_t lang = hb_language_from_string (lang_s);
hb_tag_t tag = hb_tag_from_string (tag_s);
hb_language_t lang = hb_language_from_string (lang_s, -1);
hb_tag_t tag = hb_tag_from_string (tag_s, -1);
g_test_message ("Testing language %s <-> tag %s", lang_s, tag_s);
@ -153,8 +153,8 @@ test_language_two_way (const char *tag_s, const char *lang_s)
static void
test_tag_from_language (const char *tag_s, const char *lang_s)
{
hb_language_t lang = hb_language_from_string (lang_s);
hb_tag_t tag = hb_tag_from_string (tag_s);
hb_language_t lang = hb_language_from_string (lang_s, -1);
hb_tag_t tag = hb_tag_from_string (tag_s, -1);
g_test_message ("Testing language %s -> tag %s", lang_s, tag_s);
@ -164,8 +164,8 @@ test_tag_from_language (const char *tag_s, const char *lang_s)
static void
test_tag_to_language (const char *tag_s, const char *lang_s)
{
hb_language_t lang = hb_language_from_string (lang_s);
hb_tag_t tag = hb_tag_from_string (tag_s);
hb_language_t lang = hb_language_from_string (lang_s, -1);
hb_tag_t tag = hb_tag_from_string (tag_s, -1);
g_test_message ("Testing tag %s -> language %s", tag_s, lang_s);

View File

@ -62,11 +62,11 @@ _hb_cr_text_glyphs (cairo_t *cr,
hb_buffer = hb_buffer_create ();
if (shape_opts->direction)
hb_buffer_set_direction (hb_buffer, hb_direction_from_string (shape_opts->direction));
hb_buffer_set_direction (hb_buffer, hb_direction_from_string (shape_opts->direction, -1));
if (shape_opts->script)
hb_buffer_set_script (hb_buffer, hb_script_from_string (shape_opts->script));
hb_buffer_set_script (hb_buffer, hb_script_from_string (shape_opts->script, -1));
if (shape_opts->language)
hb_buffer_set_language (hb_buffer, hb_language_from_string (shape_opts->language));
hb_buffer_set_language (hb_buffer, hb_language_from_string (shape_opts->language, -1));
if (len < 0)
len = strlen (utf8);

View File

@ -133,10 +133,7 @@ parse_feature_tag (char **pp, hb_feature_t *feature)
if (p == *pp)
return FALSE;
**pp = '\0';
feature->tag = hb_tag_from_string (p);
**pp = c;
feature->tag = hb_tag_from_string (p, *pp - p);
return TRUE;
}