From 9e5538d6a3d6f1ffbee7fad3c821621f17d61494 Mon Sep 17 00:00:00 2001 From: Simon Cozens Date: Fri, 25 Sep 2020 10:04:39 +0100 Subject: [PATCH] Prohibit mixed glyphs/unicode buffers in deserialization --- src/hb-buffer-deserialize-json.hh | 216 +++-- src/hb-buffer-deserialize-json.rl | 28 +- src/hb-buffer-deserialize-text.hh | 130 +-- src/hb-buffer-deserialize-text.rl | 28 +- test/api/test-buffer.c | 1287 +++++++++++++++-------------- 5 files changed, 937 insertions(+), 752 deletions(-) diff --git a/src/hb-buffer-deserialize-json.hh b/src/hb-buffer-deserialize-json.hh index 64fac02c5..14deee982 100644 --- a/src/hb-buffer-deserialize-json.hh +++ b/src/hb-buffer-deserialize-json.hh @@ -39,8 +39,8 @@ static const unsigned char _deserialize_json_trans_keys[] = { 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, - 65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 93u, - 9u, 123u, 0u, 0u, 0 + 65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, + 9u, 93u, 9u, 123u, 0u, 0u, 0 }; static const char _deserialize_json_key_spans[] = { @@ -49,8 +49,8 @@ static const char _deserialize_json_key_spans[] = { 117, 117, 1, 1, 50, 49, 117, 117, 2, 1, 50, 49, 10, 117, 117, 1, 50, 49, 10, 117, 117, 1, 50, 49, - 58, 89, 117, 117, 1, 50, 49, 85, - 115, 0 + 58, 89, 117, 117, 1, 50, 49, 117, + 85, 115, 0 }; static const short _deserialize_json_index_offsets[] = { @@ -60,7 +60,7 @@ static const short _deserialize_json_index_offsets[] = { 1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680, 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083, 2133, 2192, 2282, 2400, 2518, 2520, 2571, 2621, - 2707, 2823 + 2739, 2825, 2941 }; static const char _deserialize_json_indicies[] = { @@ -390,22 +390,37 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 78, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 68, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 1, 79, 79, - 79, 79, 79, 1, 1, 1, 1, 1, + 1, 1, 1, 79, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 1, 73, 73, + 73, 73, 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 79, 1, 1, + 1, 1, 1, 1, 1, 73, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 80, 1, 1, 1, 1, 1, 1, + 1, 74, 1, 1, 1, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 81, 1, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 75, 1, 82, 82, 82, 82, + 82, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 82, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 83, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 84, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -416,22 +431,21 @@ static const char _deserialize_json_indicies[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 1, - 1, 0 + 1, 1, 1, 1, 2, 1, 1, 0 }; static const char _deserialize_json_trans_targs[] = { 1, 0, 2, 2, 3, 4, 18, 24, 37, 44, 5, 12, 6, 7, 8, 9, - 11, 9, 11, 10, 2, 47, 10, 47, + 11, 9, 11, 10, 2, 48, 10, 48, 13, 14, 15, 16, 17, 16, 17, 10, - 2, 47, 19, 20, 21, 22, 23, 10, - 2, 47, 23, 25, 31, 26, 27, 28, - 29, 30, 29, 30, 10, 2, 47, 32, + 2, 48, 19, 20, 21, 22, 23, 10, + 2, 48, 23, 25, 31, 26, 27, 28, + 29, 30, 29, 30, 10, 2, 48, 32, 33, 34, 35, 36, 35, 36, 10, 2, - 47, 38, 39, 40, 42, 43, 41, 10, - 41, 10, 2, 47, 43, 45, 46, 47, - 48, 49 + 48, 38, 39, 40, 42, 43, 41, 10, + 41, 10, 2, 48, 43, 45, 46, 42, + 47, 47, 48, 49, 50 }; static const char _deserialize_json_trans_actions[] = { @@ -443,19 +457,19 @@ static const char _deserialize_json_trans_actions[] = { 8, 9, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 10, 10, 11, 0, 0, 2, 2, 2, 0, 0, 12, 12, - 13, 0, 0, 0, 2, 2, 2, 14, - 0, 15, 15, 16, 0, 0, 0, 0, - 0, 0 + 13, 0, 0, 0, 14, 14, 2, 15, + 0, 16, 16, 17, 18, 0, 0, 19, + 19, 20, 0, 0, 0 }; static const int deserialize_json_start = 1; -static const int deserialize_json_first_final = 47; +static const int deserialize_json_first_final = 48; static const int deserialize_json_error = 0; static const int deserialize_json_en_main = 1; -#line 98 "hb-buffer-deserialize-json.rl" +#line 122 "hb-buffer-deserialize-json.rl" static hb_bool_t @@ -482,12 +496,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; hb_glyph_position_t pos = {0}; -#line 486 "hb-buffer-deserialize-json.hh" +#line 500 "hb-buffer-deserialize-json.hh" { cs = deserialize_json_start; } -#line 491 "hb-buffer-deserialize-json.hh" +#line 505 "hb-buffer-deserialize-json.hh" { int _slen; int _trans; @@ -535,41 +549,117 @@ _resume: tok = p; } break; - case 14: + case 18: #line 55 "hb-buffer-deserialize-json.rl" { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + break; + case 20: +#line 67 "hb-buffer-deserialize-json.rl" + { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } +} + break; + case 16: +#line 86 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +#line 87 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +#line 88 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 89 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +#line 90 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +#line 91 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 14: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} +#line 55 "hb-buffer-deserialize-json.rl" + { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + break; + case 19: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} +#line 67 "hb-buffer-deserialize-json.rl" + { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } +} + break; + case 15: +#line 79 "hb-buffer-deserialize-json.rl" + { if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) return false; +} +#line 55 "hb-buffer-deserialize-json.rl" + { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } } break; - case 15: -#line 62 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.codepoint)) return false; } - break; - case 8: -#line 63 "hb-buffer-deserialize-json.rl" - { if (!parse_uint (tok, p, &info.cluster )) return false; } - break; - case 10: -#line 64 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_offset )) return false; } - break; - case 12: -#line 65 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_offset )) return false; } - break; - case 3: -#line 66 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.x_advance)) return false; } - break; - case 6: -#line 67 "hb-buffer-deserialize-json.rl" - { if (!parse_int (tok, p, &pos.y_advance)) return false; } - break; - case 16: -#line 62 "hb-buffer-deserialize-json.rl" + case 17: +#line 86 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.codepoint)) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -581,7 +671,7 @@ _resume: } break; case 9: -#line 63 "hb-buffer-deserialize-json.rl" +#line 87 "hb-buffer-deserialize-json.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -593,7 +683,7 @@ _resume: } break; case 11: -#line 64 "hb-buffer-deserialize-json.rl" +#line 88 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -605,7 +695,7 @@ _resume: } break; case 13: -#line 65 "hb-buffer-deserialize-json.rl" +#line 89 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -617,7 +707,7 @@ _resume: } break; case 4: -#line 66 "hb-buffer-deserialize-json.rl" +#line 90 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -629,7 +719,7 @@ _resume: } break; case 7: -#line 67 "hb-buffer-deserialize-json.rl" +#line 91 "hb-buffer-deserialize-json.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-json.rl" { @@ -640,7 +730,7 @@ _resume: *end_ptr = p; } break; -#line 644 "hb-buffer-deserialize-json.hh" +#line 734 "hb-buffer-deserialize-json.hh" } _again: @@ -652,7 +742,7 @@ _again: _out: {} } -#line 126 "hb-buffer-deserialize-json.rl" +#line 150 "hb-buffer-deserialize-json.rl" *end_ptr = p; diff --git a/src/hb-buffer-deserialize-json.rl b/src/hb-buffer-deserialize-json.rl index 336a5ea76..14e1bb429 100644 --- a/src/hb-buffer-deserialize-json.rl +++ b/src/hb-buffer-deserialize-json.rl @@ -52,6 +52,30 @@ action tok { tok = p; } +action ensure_glyphs { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + +action ensure_unicode { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } +} + action parse_glyph { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -78,8 +102,8 @@ glyph_name = alpha (alnum|'_'|'.'|'-')*; glyph_string = '"' (glyph_name >tok %parse_glyph) '"'; glyph_number = (glyph_id >tok %parse_gid); -glyph = "\"g\"" colon (glyph_string | glyph_number); -codepoint = "\"u\"" colon glyph_number; +glyph = "\"g\"" colon (glyph_string | glyph_number) @ensure_glyphs; +codepoint = "\"u\"" colon glyph_number @ensure_unicode; cluster = "\"cl\"" colon (unum >tok %parse_cluster); xoffset = "\"dx\"" colon (num >tok %parse_x_offset); yoffset = "\"dy\"" colon (num >tok %parse_y_offset); diff --git a/src/hb-buffer-deserialize-text.hh b/src/hb-buffer-deserialize-text.hh index 90275b8db..c43771870 100644 --- a/src/hb-buffer-deserialize-text.hh +++ b/src/hb-buffer-deserialize-text.hh @@ -409,17 +409,17 @@ static const char _deserialize_text_trans_actions[] = { 2, 2, 2, 0, 0, 5, 0, 6, 5, 5, 0, 0, 0, 7, 7, 7, 0, 8, 9, 9, 9, 8, 8, 0, - 0, 0, 10, 11, 10, 10, 12, 12, - 12, 7, 13, 13, 7, 14, 15, 14, - 14, 0, 0 + 0, 10, 11, 12, 11, 11, 13, 13, + 13, 7, 14, 14, 7, 15, 16, 15, + 15, 0, 10 }; static const char _deserialize_text_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, - 7, 7, 8, 0, 0, 8, 10, 12, - 12, 10, 7, 14, 14, 7, 8 + 7, 7, 8, 0, 0, 8, 11, 13, + 13, 11, 7, 15, 15, 7, 8 }; static const int deserialize_text_start = 1; @@ -429,7 +429,7 @@ static const int deserialize_text_error = 0; static const int deserialize_text_en_main = 1; -#line 100 "hb-buffer-deserialize-text.rl" +#line 124 "hb-buffer-deserialize-text.rl" static hb_bool_t @@ -482,22 +482,29 @@ _resume: goto _again; switch ( _deserialize_text_trans_actions[_trans] ) { - case 1: -#line 38 "hb-buffer-deserialize-text.rl" - { - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); -} - break; case 2: #line 51 "hb-buffer-deserialize-text.rl" { tok = p; } break; - case 9: + case 10: #line 55 "hb-buffer-deserialize-text.rl" { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + break; + case 9: +#line 79 "hb-buffer-deserialize-text.rl" + { if (!hb_font_glyph_from_string (font, tok, p - tok, &info.codepoint)) @@ -505,38 +512,46 @@ _resume: } break; case 6: -#line 62 "hb-buffer-deserialize-text.rl" +#line 86 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } break; - case 13: -#line 64 "hb-buffer-deserialize-text.rl" + case 14: +#line 88 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } break; case 4: -#line 65 "hb-buffer-deserialize-text.rl" +#line 89 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_offset )) return false; } break; - case 15: -#line 66 "hb-buffer-deserialize-text.rl" + case 16: +#line 90 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } break; - case 11: -#line 67 "hb-buffer-deserialize-text.rl" + case 12: +#line 91 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } break; - case 3: + case 1: #line 38 "hb-buffer-deserialize-text.rl" { memset (&info, 0, sizeof (info)); memset (&pos , 0, sizeof (pos )); } -#line 51 "hb-buffer-deserialize-text.rl" +#line 67 "hb-buffer-deserialize-text.rl" { - tok = p; + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } } break; case 8: -#line 55 "hb-buffer-deserialize-text.rl" +#line 79 "hb-buffer-deserialize-text.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -553,7 +568,7 @@ _resume: } break; case 5: -#line 62 "hb-buffer-deserialize-text.rl" +#line 86 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -565,7 +580,7 @@ _resume: } break; case 7: -#line 64 "hb-buffer-deserialize-text.rl" +#line 88 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -576,8 +591,8 @@ _resume: *end_ptr = p; } break; - case 14: -#line 66 "hb-buffer-deserialize-text.rl" + case 15: +#line 90 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -588,8 +603,8 @@ _resume: *end_ptr = p; } break; - case 10: -#line 67 "hb-buffer-deserialize-text.rl" + case 11: +#line 91 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -600,8 +615,8 @@ _resume: *end_ptr = p; } break; - case 12: -#line 68 "hb-buffer-deserialize-text.rl" + case 13: +#line 92 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -612,7 +627,30 @@ _resume: *end_ptr = p; } break; -#line 616 "hb-buffer-deserialize-text.hh" + case 3: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 55 "hb-buffer-deserialize-text.rl" + { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + break; +#line 654 "hb-buffer-deserialize-text.hh" } _again: @@ -625,7 +663,7 @@ _again: { switch ( _deserialize_text_eof_actions[cs] ) { case 8: -#line 55 "hb-buffer-deserialize-text.rl" +#line 79 "hb-buffer-deserialize-text.rl" { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -642,7 +680,7 @@ _again: } break; case 5: -#line 62 "hb-buffer-deserialize-text.rl" +#line 86 "hb-buffer-deserialize-text.rl" {if (!parse_hex (tok, p, &info.codepoint )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -654,7 +692,7 @@ _again: } break; case 7: -#line 64 "hb-buffer-deserialize-text.rl" +#line 88 "hb-buffer-deserialize-text.rl" { if (!parse_uint (tok, p, &info.cluster )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -665,8 +703,8 @@ _again: *end_ptr = p; } break; - case 14: -#line 66 "hb-buffer-deserialize-text.rl" + case 15: +#line 90 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_offset )) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -677,8 +715,8 @@ _again: *end_ptr = p; } break; - case 10: -#line 67 "hb-buffer-deserialize-text.rl" + case 11: +#line 91 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.x_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -689,8 +727,8 @@ _again: *end_ptr = p; } break; - case 12: -#line 68 "hb-buffer-deserialize-text.rl" + case 13: +#line 92 "hb-buffer-deserialize-text.rl" { if (!parse_int (tok, p, &pos.y_advance)) return false; } #line 43 "hb-buffer-deserialize-text.rl" { @@ -701,14 +739,14 @@ _again: *end_ptr = p; } break; -#line 705 "hb-buffer-deserialize-text.hh" +#line 743 "hb-buffer-deserialize-text.hh" } } _out: {} } -#line 124 "hb-buffer-deserialize-text.rl" +#line 148 "hb-buffer-deserialize-text.rl" *end_ptr = p; diff --git a/src/hb-buffer-deserialize-text.rl b/src/hb-buffer-deserialize-text.rl index f01e2d3a1..dd3e972ac 100644 --- a/src/hb-buffer-deserialize-text.rl +++ b/src/hb-buffer-deserialize-text.rl @@ -52,6 +52,30 @@ action tok { tok = p; } +action ensure_glyphs { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + } +} + +action ensure_unicode { + if (unlikely (buffer->content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) + { + if (buffer->content_type != HB_BUFFER_CONTENT_TYPE_INVALID) { + buffer->clear(); + return false; + } + assert (buffer->len == 0); + buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; + } +} + action parse_glyph { if (!hb_font_glyph_from_string (font, tok, p - tok, @@ -73,13 +97,13 @@ num = '-'? unum; glyph_id = unum; glyph_name = alpha (alnum|'_'|'.'|'-')*; -glyph = (glyph_id | glyph_name) >tok %parse_glyph; +glyph = (glyph_id | glyph_name) >tok @ensure_glyphs %parse_glyph; cluster = '=' (unum >tok %parse_cluster); offsets = '@' (num >tok %parse_x_offset) ',' (num >tok %parse_y_offset ); advances= '+' (num >tok %parse_x_advance) (',' (num >tok %parse_y_advance))?; codepoint = xdigit+ >tok %parse_hexdigits; -unicode_id = 'U' '+' >clear_item codepoint cluster? %add_item; +unicode_id = 'U' '+' >clear_item @ensure_unicode codepoint cluster? %add_item; item = ( diff --git a/test/api/test-buffer.c b/test/api/test-buffer.c index 1418cf8fd..b3cd1bf40 100644 --- a/test/api/test-buffer.c +++ b/test/api/test-buffer.c @@ -35,380 +35,380 @@ static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'}; typedef enum { - BUFFER_EMPTY, - BUFFER_ONE_BY_ONE, - BUFFER_UTF32, - BUFFER_UTF16, - BUFFER_UTF8, - BUFFER_NUM_TYPES, + BUFFER_EMPTY, + BUFFER_ONE_BY_ONE, + BUFFER_UTF32, + BUFFER_UTF16, + BUFFER_UTF8, + BUFFER_NUM_TYPES, } buffer_type_t; static const char *buffer_names[] = { - "empty", - "one-by-one", - "utf32", - "utf16", - "utf8" + "empty", + "one-by-one", + "utf32", + "utf16", + "utf8" }; typedef struct { - hb_buffer_t *buffer; + hb_buffer_t *buffer; } fixture_t; static void fixture_init (fixture_t *fixture, gconstpointer user_data) { - hb_buffer_t *b; - unsigned int i; + hb_buffer_t *b; + unsigned int i; - b = fixture->buffer = hb_buffer_create (); + b = fixture->buffer = hb_buffer_create (); - switch (GPOINTER_TO_INT (user_data)) - { - case BUFFER_EMPTY: - break; + switch (GPOINTER_TO_INT (user_data)) + { + case BUFFER_EMPTY: + break; - case BUFFER_ONE_BY_ONE: - for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++) + case BUFFER_ONE_BY_ONE: + for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++) hb_buffer_add (b, utf32[i], i); - break; + break; - case BUFFER_UTF32: - hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); - break; + case BUFFER_UTF32: + hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); + break; - case BUFFER_UTF16: - hb_buffer_add_utf16 (b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2); - break; + case BUFFER_UTF16: + hb_buffer_add_utf16 (b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2); + break; - case BUFFER_UTF8: - hb_buffer_add_utf8 (b, utf8, G_N_ELEMENTS (utf8), 1, G_N_ELEMENTS (utf8) - 2); - break; + case BUFFER_UTF8: + hb_buffer_add_utf8 (b, utf8, G_N_ELEMENTS (utf8), 1, G_N_ELEMENTS (utf8) - 2); + break; - default: - g_assert_not_reached (); - } + default: + g_assert_not_reached (); + } } static void fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED) { - hb_buffer_destroy (fixture->buffer); + hb_buffer_destroy (fixture->buffer); } static void test_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED) { - hb_buffer_t *b = fixture->buffer; - hb_unicode_funcs_t *ufuncs; + hb_buffer_t *b = fixture->buffer; + hb_unicode_funcs_t *ufuncs; - /* test default properties */ + /* test default properties */ - g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); - g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); - g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); - g_assert (hb_buffer_get_language (b) == NULL); + g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); + g_assert (hb_buffer_get_language (b) == NULL); - /* test property changes are retained */ - ufuncs = hb_unicode_funcs_create (NULL); - hb_buffer_set_unicode_funcs (b, ufuncs); - hb_unicode_funcs_destroy (ufuncs); - g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs); + /* test property changes are retained */ + ufuncs = hb_unicode_funcs_create (NULL); + hb_buffer_set_unicode_funcs (b, ufuncs); + hb_unicode_funcs_destroy (ufuncs); + g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs); - hb_buffer_set_direction (b, HB_DIRECTION_RTL); - g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL); + hb_buffer_set_direction (b, HB_DIRECTION_RTL); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL); - hb_buffer_set_script (b, HB_SCRIPT_ARABIC); - g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC); + 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", -1)); - g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); + hb_buffer_set_language (b, hb_language_from_string ("fa", -1)); + g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); - hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT); - g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT); + hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT); + g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT); - hb_buffer_set_replacement_codepoint (b, (unsigned int) -1); - g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1); + hb_buffer_set_replacement_codepoint (b, (unsigned int) -1); + g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1); - /* test clear_contents clears all these properties: */ + /* test clear_contents clears all these properties: */ - hb_buffer_clear_contents (b); + hb_buffer_clear_contents (b); - g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs); - g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); - g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); - g_assert (hb_buffer_get_language (b) == NULL); + g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); + g_assert (hb_buffer_get_language (b) == NULL); - /* but not these: */ + /* but not these: */ - g_assert (hb_buffer_get_flags (b) != HB_BUFFER_FLAGS_DEFAULT); - g_assert (hb_buffer_get_replacement_codepoint (b) != HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT); + g_assert (hb_buffer_get_flags (b) != HB_BUFFER_FLAGS_DEFAULT); + g_assert (hb_buffer_get_replacement_codepoint (b) != HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT); - /* test reset clears all properties */ + /* test reset clears all properties */ - hb_buffer_set_direction (b, HB_DIRECTION_RTL); - g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL); + hb_buffer_set_direction (b, HB_DIRECTION_RTL); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL); - hb_buffer_set_script (b, HB_SCRIPT_ARABIC); - g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC); + 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", -1)); - g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); + hb_buffer_set_language (b, hb_language_from_string ("fa", -1)); + g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); - hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT); - g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT); + hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT); + g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT); - hb_buffer_set_replacement_codepoint (b, (unsigned int) -1); - g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1); + hb_buffer_set_replacement_codepoint (b, (unsigned int) -1); + g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1); - hb_buffer_reset (b); + hb_buffer_reset (b); - g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); - g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); - g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); - g_assert (hb_buffer_get_language (b) == NULL); - g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT); - g_assert (hb_buffer_get_replacement_codepoint (b) == HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT); + g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); + g_assert (hb_buffer_get_language (b) == NULL); + g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAGS_DEFAULT); + g_assert (hb_buffer_get_replacement_codepoint (b) == HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT); } static void test_buffer_contents (fixture_t *fixture, gconstpointer user_data) { - hb_buffer_t *b = fixture->buffer; - unsigned int i, len, len2; - buffer_type_t buffer_type = GPOINTER_TO_INT (user_data); - hb_glyph_info_t *glyphs; + hb_buffer_t *b = fixture->buffer; + unsigned int i, len, len2; + buffer_type_t buffer_type = GPOINTER_TO_INT (user_data); + hb_glyph_info_t *glyphs; - if (buffer_type == BUFFER_EMPTY) { - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - return; - } + if (buffer_type == BUFFER_EMPTY) { + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + return; + } - len = hb_buffer_get_length (b); - hb_buffer_get_glyph_infos (b, NULL); /* test NULL */ - glyphs = hb_buffer_get_glyph_infos (b, &len2); - g_assert_cmpint (len, ==, len2); - g_assert_cmpint (len, ==, 5); + len = hb_buffer_get_length (b); + hb_buffer_get_glyph_infos (b, NULL); /* test NULL */ + glyphs = hb_buffer_get_glyph_infos (b, &len2); + g_assert_cmpint (len, ==, len2); + g_assert_cmpint (len, ==, 5); - for (i = 0; i < len; i++) { - g_assert_cmphex (glyphs[i].mask, ==, 0); - g_assert_cmphex (glyphs[i].var1.u32, ==, 0); - g_assert_cmphex (glyphs[i].var2.u32, ==, 0); - } + for (i = 0; i < len; i++) { + g_assert_cmphex (glyphs[i].mask, ==, 0); + g_assert_cmphex (glyphs[i].var1.u32, ==, 0); + g_assert_cmphex (glyphs[i].var2.u32, ==, 0); + } - for (i = 0; i < len; i++) { - unsigned int cluster; - cluster = 1+i; - if (i >= 2) { - if (buffer_type == BUFFER_UTF16) + for (i = 0; i < len; i++) { + unsigned int cluster; + cluster = 1+i; + if (i >= 2) { + if (buffer_type == BUFFER_UTF16) cluster++; - else if (buffer_type == BUFFER_UTF8) + else if (buffer_type == BUFFER_UTF8) cluster += 3; - } - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - g_assert_cmphex (glyphs[i].cluster, ==, cluster); - } + } + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + g_assert_cmphex (glyphs[i].cluster, ==, cluster); + } - /* reverse, test, and reverse back */ + /* reverse, test, and reverse back */ - hb_buffer_reverse (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); - hb_buffer_reverse (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - /* reverse_clusters works same as reverse for now since each codepoint is - * in its own cluster */ + /* reverse_clusters works same as reverse for now since each codepoint is + * in its own cluster */ - hb_buffer_reverse_clusters (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); - hb_buffer_reverse_clusters (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - /* now form a cluster and test again */ - glyphs[2].cluster = glyphs[1].cluster; + /* now form a cluster and test again */ + glyphs[2].cluster = glyphs[1].cluster; - /* reverse, test, and reverse back */ + /* reverse, test, and reverse back */ - hb_buffer_reverse (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); - hb_buffer_reverse (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - /* reverse_clusters twice still should return the original string, - * but when applied once, the 1-2 cluster should be retained. */ + /* reverse_clusters twice still should return the original string, + * but when applied once, the 1-2 cluster should be retained. */ - hb_buffer_reverse_clusters (b); - for (i = 0; i < len; i++) { - unsigned int j = len-1-i; - if (j == 1) - j = 2; - else if (j == 2) - j = 1; - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]); - } + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) { + unsigned int j = len-1-i; + if (j == 1) + j = 2; + else if (j == 2) + j = 1; + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]); + } - hb_buffer_reverse_clusters (b); - for (i = 0; i < len; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - /* test setting length */ + /* test setting length */ - /* enlarge */ - g_assert (hb_buffer_set_length (b, 10)); - glyphs = hb_buffer_get_glyph_infos (b, NULL); - g_assert_cmpint (hb_buffer_get_length (b), ==, 10); - for (i = 0; i < 5; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - for (i = 5; i < 10; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, 0); - /* shrink */ - g_assert (hb_buffer_set_length (b, 3)); - glyphs = hb_buffer_get_glyph_infos (b, NULL); - g_assert_cmpint (hb_buffer_get_length (b), ==, 3); - for (i = 0; i < 3; i++) - g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + /* enlarge */ + g_assert (hb_buffer_set_length (b, 10)); + glyphs = hb_buffer_get_glyph_infos (b, NULL); + g_assert_cmpint (hb_buffer_get_length (b), ==, 10); + for (i = 0; i < 5; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + for (i = 5; i < 10; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, 0); + /* shrink */ + g_assert (hb_buffer_set_length (b, 3)); + glyphs = hb_buffer_get_glyph_infos (b, NULL); + g_assert_cmpint (hb_buffer_get_length (b), ==, 3); + for (i = 0; i < 3; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); - g_assert (hb_buffer_allocation_successful (b)); + g_assert (hb_buffer_allocation_successful (b)); - /* test reset clears content */ + /* test reset clears content */ - hb_buffer_reset (b); - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + hb_buffer_reset (b); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); } static void test_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED) { - hb_buffer_t *b = fixture->buffer; - unsigned int i, len, len2; - hb_glyph_position_t *positions; + hb_buffer_t *b = fixture->buffer; + unsigned int i, len, len2; + hb_glyph_position_t *positions; - /* Without shaping, positions should all be zero */ - len = hb_buffer_get_length (b); - hb_buffer_get_glyph_positions (b, NULL); /* test NULL */ - positions = hb_buffer_get_glyph_positions (b, &len2); - g_assert_cmpint (len, ==, len2); - for (i = 0; i < len; i++) { - g_assert_cmpint (0, ==, positions[i].x_advance); - g_assert_cmpint (0, ==, positions[i].y_advance); - g_assert_cmpint (0, ==, positions[i].x_offset); - g_assert_cmpint (0, ==, positions[i].y_offset); - g_assert_cmpint (0, ==, positions[i].var.i32); - } + /* Without shaping, positions should all be zero */ + len = hb_buffer_get_length (b); + hb_buffer_get_glyph_positions (b, NULL); /* test NULL */ + positions = hb_buffer_get_glyph_positions (b, &len2); + g_assert_cmpint (len, ==, len2); + for (i = 0; i < len; i++) { + g_assert_cmpint (0, ==, positions[i].x_advance); + g_assert_cmpint (0, ==, positions[i].y_advance); + g_assert_cmpint (0, ==, positions[i].x_offset); + g_assert_cmpint (0, ==, positions[i].y_offset); + g_assert_cmpint (0, ==, positions[i].var.i32); + } - /* test reset clears content */ - hb_buffer_reset (b); - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + /* test reset clears content */ + hb_buffer_reset (b); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); } static void test_buffer_allocation (fixture_t *fixture, gconstpointer user_data HB_UNUSED) { - hb_buffer_t *b = fixture->buffer; + hb_buffer_t *b = fixture->buffer; - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - g_assert (hb_buffer_pre_allocate (b, 100)); - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - g_assert (hb_buffer_allocation_successful (b)); + g_assert (hb_buffer_pre_allocate (b, 100)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (hb_buffer_allocation_successful (b)); - /* lets try a huge allocation, make sure it fails */ - g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1)); - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - g_assert (!hb_buffer_allocation_successful (b)); + /* lets try a huge allocation, make sure it fails */ + g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_allocation_successful (b)); - /* small one again */ - g_assert (hb_buffer_pre_allocate (b, 50)); - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - g_assert (!hb_buffer_allocation_successful (b)); + /* small one again */ + g_assert (hb_buffer_pre_allocate (b, 50)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_allocation_successful (b)); - hb_buffer_reset (b); - g_assert (hb_buffer_allocation_successful (b)); + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); - /* all allocation and size */ - g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1)); - g_assert (!hb_buffer_allocation_successful (b)); + /* all allocation and size */ + g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1)); + g_assert (!hb_buffer_allocation_successful (b)); - hb_buffer_reset (b); - g_assert (hb_buffer_allocation_successful (b)); + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); - /* technically, this one can actually pass on 64bit machines, but - * I'm doubtful that any malloc allows 4GB allocations at a time. - * But let's only enable it on a 32-bit machine. */ - if (sizeof (long) == 4) { - g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1)); - g_assert (!hb_buffer_allocation_successful (b)); - } + /* technically, this one can actually pass on 64bit machines, but + * I'm doubtful that any malloc allows 4GB allocations at a time. + * But let's only enable it on a 32-bit machine. */ + if (sizeof (long) == 4) { + g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1)); + g_assert (!hb_buffer_allocation_successful (b)); + } - hb_buffer_reset (b); - g_assert (hb_buffer_allocation_successful (b)); + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); } typedef struct { - const char utf8[8]; - const uint32_t codepoints[8]; + const char utf8[8]; + const uint32_t codepoints[8]; } utf8_conversion_test_t; /* note: we skip the first and last byte when adding to buffer */ static const utf8_conversion_test_t utf8_conversion_tests[] = { - {"a\303\207", {(hb_codepoint_t) -1}}, - {"a\303\207b", {0xC7}}, - {"ab\303cd", {'b', (hb_codepoint_t) -1, 'c'}}, - {"ab\303\302\301cd", {'b', (hb_codepoint_t) -1, (hb_codepoint_t) -1, (hb_codepoint_t) -1, 'c'}} + {"a\303\207", {(hb_codepoint_t) -1}}, + {"a\303\207b", {0xC7}}, + {"ab\303cd", {'b', (hb_codepoint_t) -1, 'c'}}, + {"ab\303\302\301cd", {'b', (hb_codepoint_t) -1, (hb_codepoint_t) -1, (hb_codepoint_t) -1, 'c'}} }; static void test_buffer_utf8_conversion (void) { - hb_buffer_t *b; - unsigned int chars, i, j, len; + hb_buffer_t *b; + unsigned int chars, i, j, len; - b = hb_buffer_create (); - hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); + b = hb_buffer_create (); + hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); - for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++) - { - unsigned int bytes; - hb_glyph_info_t *glyphs; - const utf8_conversion_test_t *test = &utf8_conversion_tests[i]; - char *escaped; + for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++) + { + unsigned int bytes; + hb_glyph_info_t *glyphs; + const utf8_conversion_test_t *test = &utf8_conversion_tests[i]; + char *escaped; - escaped = g_strescape (test->utf8, NULL); - g_test_message ("UTF-8 test #%d: %s", i, escaped); - g_free (escaped); + escaped = g_strescape (test->utf8, NULL); + g_test_message ("UTF-8 test #%d: %s", i, escaped); + g_free (escaped); - bytes = strlen (test->utf8); - for (chars = 0; test->codepoints[chars]; chars++) - ; + bytes = strlen (test->utf8); + for (chars = 0; test->codepoints[chars]; chars++) + ; - hb_buffer_clear_contents (b); - hb_buffer_add_utf8 (b, test->utf8, bytes, 1, bytes - 2); + hb_buffer_clear_contents (b); + hb_buffer_add_utf8 (b, test->utf8, bytes, 1, bytes - 2); - glyphs = hb_buffer_get_glyph_infos (b, &len); - g_assert_cmpint (len, ==, chars); - for (j = 0; j < chars; j++) - g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); - } + glyphs = hb_buffer_get_glyph_infos (b, &len); + g_assert_cmpint (len, ==, chars); + for (j = 0; j < chars; j++) + g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); + } - hb_buffer_destroy (b); + hb_buffer_destroy (b); } @@ -417,513 +417,522 @@ test_buffer_utf8_conversion (void) * with relicensing permission from Matthias Clasen. */ typedef struct { - const char *utf8; - int max_len; - unsigned int offset; - gboolean valid; + const char *utf8; + int max_len; + unsigned int offset; + gboolean valid; } utf8_validity_test_t; static const utf8_validity_test_t utf8_validity_tests[] = { - /* some tests to check max_len handling */ - /* length 1 */ - { "abcde", -1, 5, TRUE }, - { "abcde", 3, 3, TRUE }, - { "abcde", 5, 5, TRUE }, - /* length 2 */ - { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 1, 0, FALSE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 2, 2, TRUE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 3, 2, FALSE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 4, 4, TRUE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 5, 4, FALSE }, - { "\xc2\xa9\xc2\xa9\xc2\xa9", 6, 6, TRUE }, - /* length 3 */ - { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 1, 0, FALSE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 2, 0, FALSE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 3, 3, TRUE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 4, 3, FALSE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 5, 3, FALSE }, - { "\xe2\x89\xa0\xe2\x89\xa0", 6, 6, TRUE }, + /* some tests to check max_len handling */ + /* length 1 */ + { "abcde", -1, 5, TRUE }, + { "abcde", 3, 3, TRUE }, + { "abcde", 5, 5, TRUE }, + /* length 2 */ + { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 1, 0, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 2, 2, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 3, 2, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 4, 4, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 5, 4, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 6, 6, TRUE }, + /* length 3 */ + { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 1, 0, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 2, 0, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 3, 3, TRUE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 4, 3, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 5, 3, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 6, 6, TRUE }, - /* examples from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */ - /* greek 'kosme' */ - { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE }, - /* first sequence of each length */ - { "\x00", -1, 0, TRUE }, - { "\xc2\x80", -1, 2, TRUE }, - { "\xe0\xa0\x80", -1, 3, TRUE }, - { "\xf0\x90\x80\x80", -1, 4, TRUE }, - { "\xf8\x88\x80\x80\x80", -1, 0, FALSE }, - { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE }, - /* last sequence of each length */ - { "\x7f", -1, 1, TRUE }, - { "\xdf\xbf", -1, 2, TRUE }, - { "\xef\xbf\xbf", -1, 0, TRUE }, - { "\xf4\x8f\xbf\xbf", -1, 0, TRUE }, - { "\xf4\x90\xbf\xbf", -1, 0, FALSE }, - { "\xf7\xbf\xbf\xbf", -1, 0, FALSE }, - { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE }, - { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE }, - /* other boundary conditions */ - { "\xed\x9f\xbf", -1, 3, TRUE }, - { "\xed\xa0\x80", -1, 0, FALSE }, - { "\xed\xbf\xbf", -1, 0, FALSE }, - { "\xee\x80\x80", -1, 3, TRUE }, - { "\xef\xbf\xbd", -1, 3, TRUE }, - { "\xf4\x8f\xbf\xbf", -1, 0, TRUE }, - /* malformed sequences */ - /* continuation bytes */ - { "\x80", -1, 0, FALSE }, - { "\xbf", -1, 0, FALSE }, - { "\x80\xbf", -1, 0, FALSE }, - { "\x80\xbf\x80", -1, 0, FALSE }, - { "\x80\xbf\x80\xbf", -1, 0, FALSE }, - { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, - { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE }, - { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, + /* examples from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */ + /* greek 'kosme' */ + { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE }, + /* first sequence of each length */ + { "\x00", -1, 0, TRUE }, + { "\xc2\x80", -1, 2, TRUE }, + { "\xe0\xa0\x80", -1, 3, TRUE }, + { "\xf0\x90\x80\x80", -1, 4, TRUE }, + { "\xf8\x88\x80\x80\x80", -1, 0, FALSE }, + { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE }, + /* last sequence of each length */ + { "\x7f", -1, 1, TRUE }, + { "\xdf\xbf", -1, 2, TRUE }, + { "\xef\xbf\xbf", -1, 0, TRUE }, + { "\xf4\x8f\xbf\xbf", -1, 0, TRUE }, + { "\xf4\x90\xbf\xbf", -1, 0, FALSE }, + { "\xf7\xbf\xbf\xbf", -1, 0, FALSE }, + { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE }, + { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE }, + /* other boundary conditions */ + { "\xed\x9f\xbf", -1, 3, TRUE }, + { "\xed\xa0\x80", -1, 0, FALSE }, + { "\xed\xbf\xbf", -1, 0, FALSE }, + { "\xee\x80\x80", -1, 3, TRUE }, + { "\xef\xbf\xbd", -1, 3, TRUE }, + { "\xf4\x8f\xbf\xbf", -1, 0, TRUE }, + /* malformed sequences */ + /* continuation bytes */ + { "\x80", -1, 0, FALSE }, + { "\xbf", -1, 0, FALSE }, + { "\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, - /* all possible continuation byte */ - { "\x80", -1, 0, FALSE }, - { "\x81", -1, 0, FALSE }, - { "\x82", -1, 0, FALSE }, - { "\x83", -1, 0, FALSE }, - { "\x84", -1, 0, FALSE }, - { "\x85", -1, 0, FALSE }, - { "\x86", -1, 0, FALSE }, - { "\x87", -1, 0, FALSE }, - { "\x88", -1, 0, FALSE }, - { "\x89", -1, 0, FALSE }, - { "\x8a", -1, 0, FALSE }, - { "\x8b", -1, 0, FALSE }, - { "\x8c", -1, 0, FALSE }, - { "\x8d", -1, 0, FALSE }, - { "\x8e", -1, 0, FALSE }, - { "\x8f", -1, 0, FALSE }, - { "\x90", -1, 0, FALSE }, - { "\x91", -1, 0, FALSE }, - { "\x92", -1, 0, FALSE }, - { "\x93", -1, 0, FALSE }, - { "\x94", -1, 0, FALSE }, - { "\x95", -1, 0, FALSE }, - { "\x96", -1, 0, FALSE }, - { "\x97", -1, 0, FALSE }, - { "\x98", -1, 0, FALSE }, - { "\x99", -1, 0, FALSE }, - { "\x9a", -1, 0, FALSE }, - { "\x9b", -1, 0, FALSE }, - { "\x9c", -1, 0, FALSE }, - { "\x9d", -1, 0, FALSE }, - { "\x9e", -1, 0, FALSE }, - { "\x9f", -1, 0, FALSE }, - { "\xa0", -1, 0, FALSE }, - { "\xa1", -1, 0, FALSE }, - { "\xa2", -1, 0, FALSE }, - { "\xa3", -1, 0, FALSE }, - { "\xa4", -1, 0, FALSE }, - { "\xa5", -1, 0, FALSE }, - { "\xa6", -1, 0, FALSE }, - { "\xa7", -1, 0, FALSE }, - { "\xa8", -1, 0, FALSE }, - { "\xa9", -1, 0, FALSE }, - { "\xaa", -1, 0, FALSE }, - { "\xab", -1, 0, FALSE }, - { "\xac", -1, 0, FALSE }, - { "\xad", -1, 0, FALSE }, - { "\xae", -1, 0, FALSE }, - { "\xaf", -1, 0, FALSE }, - { "\xb0", -1, 0, FALSE }, - { "\xb1", -1, 0, FALSE }, - { "\xb2", -1, 0, FALSE }, - { "\xb3", -1, 0, FALSE }, - { "\xb4", -1, 0, FALSE }, - { "\xb5", -1, 0, FALSE }, - { "\xb6", -1, 0, FALSE }, - { "\xb7", -1, 0, FALSE }, - { "\xb8", -1, 0, FALSE }, - { "\xb9", -1, 0, FALSE }, - { "\xba", -1, 0, FALSE }, - { "\xbb", -1, 0, FALSE }, - { "\xbc", -1, 0, FALSE }, - { "\xbd", -1, 0, FALSE }, - { "\xbe", -1, 0, FALSE }, - { "\xbf", -1, 0, FALSE }, - /* lone start characters */ - { "\xc0\x20", -1, 0, FALSE }, - { "\xc1\x20", -1, 0, FALSE }, - { "\xc2\x20", -1, 0, FALSE }, - { "\xc3\x20", -1, 0, FALSE }, - { "\xc4\x20", -1, 0, FALSE }, - { "\xc5\x20", -1, 0, FALSE }, - { "\xc6\x20", -1, 0, FALSE }, - { "\xc7\x20", -1, 0, FALSE }, - { "\xc8\x20", -1, 0, FALSE }, - { "\xc9\x20", -1, 0, FALSE }, - { "\xca\x20", -1, 0, FALSE }, - { "\xcb\x20", -1, 0, FALSE }, - { "\xcc\x20", -1, 0, FALSE }, - { "\xcd\x20", -1, 0, FALSE }, - { "\xce\x20", -1, 0, FALSE }, - { "\xcf\x20", -1, 0, FALSE }, - { "\xd0\x20", -1, 0, FALSE }, - { "\xd1\x20", -1, 0, FALSE }, - { "\xd2\x20", -1, 0, FALSE }, - { "\xd3\x20", -1, 0, FALSE }, - { "\xd4\x20", -1, 0, FALSE }, - { "\xd5\x20", -1, 0, FALSE }, - { "\xd6\x20", -1, 0, FALSE }, - { "\xd7\x20", -1, 0, FALSE }, - { "\xd8\x20", -1, 0, FALSE }, - { "\xd9\x20", -1, 0, FALSE }, - { "\xda\x20", -1, 0, FALSE }, - { "\xdb\x20", -1, 0, FALSE }, - { "\xdc\x20", -1, 0, FALSE }, - { "\xdd\x20", -1, 0, FALSE }, - { "\xde\x20", -1, 0, FALSE }, - { "\xdf\x20", -1, 0, FALSE }, - { "\xe0\x20", -1, 0, FALSE }, - { "\xe1\x20", -1, 0, FALSE }, - { "\xe2\x20", -1, 0, FALSE }, - { "\xe3\x20", -1, 0, FALSE }, - { "\xe4\x20", -1, 0, FALSE }, - { "\xe5\x20", -1, 0, FALSE }, - { "\xe6\x20", -1, 0, FALSE }, - { "\xe7\x20", -1, 0, FALSE }, - { "\xe8\x20", -1, 0, FALSE }, - { "\xe9\x20", -1, 0, FALSE }, - { "\xea\x20", -1, 0, FALSE }, - { "\xeb\x20", -1, 0, FALSE }, - { "\xec\x20", -1, 0, FALSE }, - { "\xed\x20", -1, 0, FALSE }, - { "\xee\x20", -1, 0, FALSE }, - { "\xef\x20", -1, 0, FALSE }, - { "\xf0\x20", -1, 0, FALSE }, - { "\xf1\x20", -1, 0, FALSE }, - { "\xf2\x20", -1, 0, FALSE }, - { "\xf3\x20", -1, 0, FALSE }, - { "\xf4\x20", -1, 0, FALSE }, - { "\xf5\x20", -1, 0, FALSE }, - { "\xf6\x20", -1, 0, FALSE }, - { "\xf7\x20", -1, 0, FALSE }, - { "\xf8\x20", -1, 0, FALSE }, - { "\xf9\x20", -1, 0, FALSE }, - { "\xfa\x20", -1, 0, FALSE }, - { "\xfb\x20", -1, 0, FALSE }, - { "\xfc\x20", -1, 0, FALSE }, - { "\xfd\x20", -1, 0, FALSE }, - /* missing continuation bytes */ - { "\x20\xc0", -1, 1, FALSE }, - { "\x20\xe0\x80", -1, 1, FALSE }, - { "\x20\xf0\x80\x80", -1, 1, FALSE }, - { "\x20\xf8\x80\x80\x80", -1, 1, FALSE }, - { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE }, - { "\x20\xdf", -1, 1, FALSE }, - { "\x20\xef\xbf", -1, 1, FALSE }, - { "\x20\xf7\xbf\xbf", -1, 1, FALSE }, - { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE }, - { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE }, - /* impossible bytes */ - { "\x20\xfe\x20", -1, 1, FALSE }, - { "\x20\xff\x20", -1, 1, FALSE }, - /* overlong sequences */ - { "\x20\xc0\xaf\x20", -1, 1, FALSE }, - { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE }, - { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE }, - { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE }, - { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE }, - { "\x20\xc1\xbf\x20", -1, 1, FALSE }, - { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE }, - { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xc0\x80\x20", -1, 1, FALSE }, - { "\x20\xe0\x80\x80\x20", -1, 1, FALSE }, - { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE }, - { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE }, - { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE }, - /* illegal code positions */ - { "\x20\xed\xa0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xad\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xae\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xb0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xbe\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, - { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, - { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, + /* all possible continuation byte */ + { "\x80", -1, 0, FALSE }, + { "\x81", -1, 0, FALSE }, + { "\x82", -1, 0, FALSE }, + { "\x83", -1, 0, FALSE }, + { "\x84", -1, 0, FALSE }, + { "\x85", -1, 0, FALSE }, + { "\x86", -1, 0, FALSE }, + { "\x87", -1, 0, FALSE }, + { "\x88", -1, 0, FALSE }, + { "\x89", -1, 0, FALSE }, + { "\x8a", -1, 0, FALSE }, + { "\x8b", -1, 0, FALSE }, + { "\x8c", -1, 0, FALSE }, + { "\x8d", -1, 0, FALSE }, + { "\x8e", -1, 0, FALSE }, + { "\x8f", -1, 0, FALSE }, + { "\x90", -1, 0, FALSE }, + { "\x91", -1, 0, FALSE }, + { "\x92", -1, 0, FALSE }, + { "\x93", -1, 0, FALSE }, + { "\x94", -1, 0, FALSE }, + { "\x95", -1, 0, FALSE }, + { "\x96", -1, 0, FALSE }, + { "\x97", -1, 0, FALSE }, + { "\x98", -1, 0, FALSE }, + { "\x99", -1, 0, FALSE }, + { "\x9a", -1, 0, FALSE }, + { "\x9b", -1, 0, FALSE }, + { "\x9c", -1, 0, FALSE }, + { "\x9d", -1, 0, FALSE }, + { "\x9e", -1, 0, FALSE }, + { "\x9f", -1, 0, FALSE }, + { "\xa0", -1, 0, FALSE }, + { "\xa1", -1, 0, FALSE }, + { "\xa2", -1, 0, FALSE }, + { "\xa3", -1, 0, FALSE }, + { "\xa4", -1, 0, FALSE }, + { "\xa5", -1, 0, FALSE }, + { "\xa6", -1, 0, FALSE }, + { "\xa7", -1, 0, FALSE }, + { "\xa8", -1, 0, FALSE }, + { "\xa9", -1, 0, FALSE }, + { "\xaa", -1, 0, FALSE }, + { "\xab", -1, 0, FALSE }, + { "\xac", -1, 0, FALSE }, + { "\xad", -1, 0, FALSE }, + { "\xae", -1, 0, FALSE }, + { "\xaf", -1, 0, FALSE }, + { "\xb0", -1, 0, FALSE }, + { "\xb1", -1, 0, FALSE }, + { "\xb2", -1, 0, FALSE }, + { "\xb3", -1, 0, FALSE }, + { "\xb4", -1, 0, FALSE }, + { "\xb5", -1, 0, FALSE }, + { "\xb6", -1, 0, FALSE }, + { "\xb7", -1, 0, FALSE }, + { "\xb8", -1, 0, FALSE }, + { "\xb9", -1, 0, FALSE }, + { "\xba", -1, 0, FALSE }, + { "\xbb", -1, 0, FALSE }, + { "\xbc", -1, 0, FALSE }, + { "\xbd", -1, 0, FALSE }, + { "\xbe", -1, 0, FALSE }, + { "\xbf", -1, 0, FALSE }, + /* lone start characters */ + { "\xc0\x20", -1, 0, FALSE }, + { "\xc1\x20", -1, 0, FALSE }, + { "\xc2\x20", -1, 0, FALSE }, + { "\xc3\x20", -1, 0, FALSE }, + { "\xc4\x20", -1, 0, FALSE }, + { "\xc5\x20", -1, 0, FALSE }, + { "\xc6\x20", -1, 0, FALSE }, + { "\xc7\x20", -1, 0, FALSE }, + { "\xc8\x20", -1, 0, FALSE }, + { "\xc9\x20", -1, 0, FALSE }, + { "\xca\x20", -1, 0, FALSE }, + { "\xcb\x20", -1, 0, FALSE }, + { "\xcc\x20", -1, 0, FALSE }, + { "\xcd\x20", -1, 0, FALSE }, + { "\xce\x20", -1, 0, FALSE }, + { "\xcf\x20", -1, 0, FALSE }, + { "\xd0\x20", -1, 0, FALSE }, + { "\xd1\x20", -1, 0, FALSE }, + { "\xd2\x20", -1, 0, FALSE }, + { "\xd3\x20", -1, 0, FALSE }, + { "\xd4\x20", -1, 0, FALSE }, + { "\xd5\x20", -1, 0, FALSE }, + { "\xd6\x20", -1, 0, FALSE }, + { "\xd7\x20", -1, 0, FALSE }, + { "\xd8\x20", -1, 0, FALSE }, + { "\xd9\x20", -1, 0, FALSE }, + { "\xda\x20", -1, 0, FALSE }, + { "\xdb\x20", -1, 0, FALSE }, + { "\xdc\x20", -1, 0, FALSE }, + { "\xdd\x20", -1, 0, FALSE }, + { "\xde\x20", -1, 0, FALSE }, + { "\xdf\x20", -1, 0, FALSE }, + { "\xe0\x20", -1, 0, FALSE }, + { "\xe1\x20", -1, 0, FALSE }, + { "\xe2\x20", -1, 0, FALSE }, + { "\xe3\x20", -1, 0, FALSE }, + { "\xe4\x20", -1, 0, FALSE }, + { "\xe5\x20", -1, 0, FALSE }, + { "\xe6\x20", -1, 0, FALSE }, + { "\xe7\x20", -1, 0, FALSE }, + { "\xe8\x20", -1, 0, FALSE }, + { "\xe9\x20", -1, 0, FALSE }, + { "\xea\x20", -1, 0, FALSE }, + { "\xeb\x20", -1, 0, FALSE }, + { "\xec\x20", -1, 0, FALSE }, + { "\xed\x20", -1, 0, FALSE }, + { "\xee\x20", -1, 0, FALSE }, + { "\xef\x20", -1, 0, FALSE }, + { "\xf0\x20", -1, 0, FALSE }, + { "\xf1\x20", -1, 0, FALSE }, + { "\xf2\x20", -1, 0, FALSE }, + { "\xf3\x20", -1, 0, FALSE }, + { "\xf4\x20", -1, 0, FALSE }, + { "\xf5\x20", -1, 0, FALSE }, + { "\xf6\x20", -1, 0, FALSE }, + { "\xf7\x20", -1, 0, FALSE }, + { "\xf8\x20", -1, 0, FALSE }, + { "\xf9\x20", -1, 0, FALSE }, + { "\xfa\x20", -1, 0, FALSE }, + { "\xfb\x20", -1, 0, FALSE }, + { "\xfc\x20", -1, 0, FALSE }, + { "\xfd\x20", -1, 0, FALSE }, + /* missing continuation bytes */ + { "\x20\xc0", -1, 1, FALSE }, + { "\x20\xe0\x80", -1, 1, FALSE }, + { "\x20\xf0\x80\x80", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE }, + { "\x20\xdf", -1, 1, FALSE }, + { "\x20\xef\xbf", -1, 1, FALSE }, + { "\x20\xf7\xbf\xbf", -1, 1, FALSE }, + { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE }, + { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE }, + /* impossible bytes */ + { "\x20\xfe\x20", -1, 1, FALSE }, + { "\x20\xff\x20", -1, 1, FALSE }, + /* overlong sequences */ + { "\x20\xc0\xaf\x20", -1, 1, FALSE }, + { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xc1\xbf\x20", -1, 1, FALSE }, + { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE }, + { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xc0\x80\x20", -1, 1, FALSE }, + { "\x20\xe0\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE }, + /* illegal code positions */ + { "\x20\xed\xa0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xbe\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, #if 0 /* We don't consider U+FFFE / U+FFFF and similar invalid. */ - { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE }, - { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE }, + { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE }, #endif - { "", -1, 0, TRUE } + { "", -1, 0, TRUE } }; static void test_buffer_utf8_validity (void) { - hb_buffer_t *b; - unsigned int i; + hb_buffer_t *b; + unsigned int i; - b = hb_buffer_create (); - hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); + b = hb_buffer_create (); + hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); - for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++) - { - const utf8_validity_test_t *test = &utf8_validity_tests[i]; - unsigned int text_bytes, segment_bytes, j, len; - hb_glyph_info_t *glyphs; - char *escaped; + for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++) + { + const utf8_validity_test_t *test = &utf8_validity_tests[i]; + unsigned int text_bytes, segment_bytes, j, len; + hb_glyph_info_t *glyphs; + char *escaped; - escaped = g_strescape (test->utf8, NULL); - g_test_message ("UTF-8 test #%d: %s", i, escaped); - g_free (escaped); + escaped = g_strescape (test->utf8, NULL); + g_test_message ("UTF-8 test #%d: %s", i, escaped); + g_free (escaped); - text_bytes = strlen (test->utf8); - if (test->max_len == -1) - segment_bytes = text_bytes; - else - segment_bytes = test->max_len; + text_bytes = strlen (test->utf8); + if (test->max_len == -1) + segment_bytes = text_bytes; + else + segment_bytes = test->max_len; - hb_buffer_clear_contents (b); - hb_buffer_add_utf8 (b, test->utf8, text_bytes, 0, segment_bytes); + hb_buffer_clear_contents (b); + hb_buffer_add_utf8 (b, test->utf8, text_bytes, 0, segment_bytes); - glyphs = hb_buffer_get_glyph_infos (b, &len); - for (j = 0; j < len; j++) - if (glyphs[j].codepoint == (hb_codepoint_t) -1) + glyphs = hb_buffer_get_glyph_infos (b, &len); + for (j = 0; j < len; j++) + if (glyphs[j].codepoint == (hb_codepoint_t) -1) break; - g_assert (test->valid ? j == len : j < len); - if (!test->valid) - g_assert (glyphs[j].cluster == test->offset); - } + g_assert (test->valid ? j == len : j < len); + if (!test->valid) + g_assert (glyphs[j].cluster == test->offset); + } - hb_buffer_destroy (b); + hb_buffer_destroy (b); } typedef struct { - const uint16_t utf16[8]; - const uint32_t codepoints[8]; + const uint16_t utf16[8]; + const uint32_t codepoints[8]; } utf16_conversion_test_t; /* note: we skip the first and last item from utf16 when adding to buffer */ static const utf16_conversion_test_t utf16_conversion_tests[] = { - {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}}, - {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}}, - {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -1}}, - {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -1}}, - {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -1, 0x61}}, - {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -1}}, - {{0x41, 0x61}, {0}} + {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}}, + {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}}, + {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -1}}, + {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -1}}, + {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -1, 0x61}}, + {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -1}}, + {{0x41, 0x61}, {0}} }; static void test_buffer_utf16_conversion (void) { - hb_buffer_t *b; - unsigned int i; + hb_buffer_t *b; + unsigned int i; - b = hb_buffer_create (); - hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); + b = hb_buffer_create (); + hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); - for (i = 0; i < G_N_ELEMENTS (utf16_conversion_tests); i++) - { - const utf16_conversion_test_t *test = &utf16_conversion_tests[i]; - unsigned int u_len, chars, j, len; - hb_glyph_info_t *glyphs; + for (i = 0; i < G_N_ELEMENTS (utf16_conversion_tests); i++) + { + const utf16_conversion_test_t *test = &utf16_conversion_tests[i]; + unsigned int u_len, chars, j, len; + hb_glyph_info_t *glyphs; - g_test_message ("UTF-16 test #%d", i); + g_test_message ("UTF-16 test #%d", i); - for (u_len = 0; test->utf16[u_len]; u_len++) - ; - for (chars = 0; test->codepoints[chars]; chars++) - ; + for (u_len = 0; test->utf16[u_len]; u_len++) + ; + for (chars = 0; test->codepoints[chars]; chars++) + ; - hb_buffer_clear_contents (b); - hb_buffer_add_utf16 (b, test->utf16, u_len, 1, u_len - 2); + hb_buffer_clear_contents (b); + hb_buffer_add_utf16 (b, test->utf16, u_len, 1, u_len - 2); - glyphs = hb_buffer_get_glyph_infos (b, &len); - g_assert_cmpint (len, ==, chars); - for (j = 0; j < chars; j++) - g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); - } + glyphs = hb_buffer_get_glyph_infos (b, &len); + g_assert_cmpint (len, ==, chars); + for (j = 0; j < chars; j++) + g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); + } - hb_buffer_destroy (b); + hb_buffer_destroy (b); } typedef struct { - const uint32_t utf32[8]; - const uint32_t codepoints[8]; + const uint32_t utf32[8]; + const uint32_t codepoints[8]; } utf32_conversion_test_t; /* note: we skip the first and last item from utf32 when adding to buffer */ static const utf32_conversion_test_t utf32_conversion_tests[] = { - {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, (hb_codepoint_t) -3, (hb_codepoint_t) -3}}, - {{0x41, 0x004D, 0x0430, 0x4E8C, 0x10302, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}}, - {{0x41, 0xD800, 0xDF02, 0x61}, {(hb_codepoint_t) -3, (hb_codepoint_t) -3}}, - {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -3}}, - {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -3}}, - {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -3, 0x61}}, - {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -3}}, - {{0x41, 0x10FFFF, 0x61}, {0x10FFFF}}, - {{0x41, 0x110000, 0x61}, {(hb_codepoint_t) -3}}, - {{0x41, 0x61}, {0}} + {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, (hb_codepoint_t) -3, (hb_codepoint_t) -3}}, + {{0x41, 0x004D, 0x0430, 0x4E8C, 0x10302, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}}, + {{0x41, 0xD800, 0xDF02, 0x61}, {(hb_codepoint_t) -3, (hb_codepoint_t) -3}}, + {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -3}}, + {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -3}}, + {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -3, 0x61}}, + {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -3}}, + {{0x41, 0x10FFFF, 0x61}, {0x10FFFF}}, + {{0x41, 0x110000, 0x61}, {(hb_codepoint_t) -3}}, + {{0x41, 0x61}, {0}} }; static void test_buffer_utf32_conversion (void) { - hb_buffer_t *b; - unsigned int i; + hb_buffer_t *b; + unsigned int i; - b = hb_buffer_create (); - hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -3); + b = hb_buffer_create (); + hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -3); - for (i = 0; i < G_N_ELEMENTS (utf32_conversion_tests); i++) - { - const utf32_conversion_test_t *test = &utf32_conversion_tests[i]; - unsigned int u_len, chars, j, len; - hb_glyph_info_t *glyphs; + for (i = 0; i < G_N_ELEMENTS (utf32_conversion_tests); i++) + { + const utf32_conversion_test_t *test = &utf32_conversion_tests[i]; + unsigned int u_len, chars, j, len; + hb_glyph_info_t *glyphs; - g_test_message ("UTF-32 test #%d", i); + g_test_message ("UTF-32 test #%d", i); - for (u_len = 0; test->utf32[u_len]; u_len++) - ; - for (chars = 0; test->codepoints[chars]; chars++) - ; + for (u_len = 0; test->utf32[u_len]; u_len++) + ; + for (chars = 0; test->codepoints[chars]; chars++) + ; - hb_buffer_clear_contents (b); - hb_buffer_add_utf32 (b, test->utf32, u_len, 1, u_len - 2); + hb_buffer_clear_contents (b); + hb_buffer_add_utf32 (b, test->utf32, u_len, 1, u_len - 2); - glyphs = hb_buffer_get_glyph_infos (b, &len); - g_assert_cmpint (len, ==, chars); - for (j = 0; j < chars; j++) - g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); - } + glyphs = hb_buffer_get_glyph_infos (b, &len); + g_assert_cmpint (len, ==, chars); + for (j = 0; j < chars; j++) + g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); + } - hb_buffer_destroy (b); + hb_buffer_destroy (b); } static void test_empty (hb_buffer_t *b) { - g_assert_cmpint (hb_buffer_get_length (b), ==, 0); - g_assert (!hb_buffer_get_glyph_infos (b, NULL)); - g_assert (!hb_buffer_get_glyph_positions (b, NULL)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_get_glyph_infos (b, NULL)); + g_assert (!hb_buffer_get_glyph_positions (b, NULL)); } static void test_buffer_empty (void) { - hb_buffer_t *b = hb_buffer_get_empty (); + hb_buffer_t *b = hb_buffer_get_empty (); - g_assert (hb_buffer_get_empty ()); - g_assert (hb_buffer_get_empty () == b); + g_assert (hb_buffer_get_empty ()); + g_assert (hb_buffer_get_empty () == b); - g_assert (!hb_buffer_allocation_successful (b)); + g_assert (!hb_buffer_allocation_successful (b)); - test_empty (b); + test_empty (b); - hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); + hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); - test_empty (b); + test_empty (b); - hb_buffer_reverse (b); - hb_buffer_reverse_clusters (b); + hb_buffer_reverse (b); + hb_buffer_reverse_clusters (b); - g_assert (!hb_buffer_set_length (b, 10)); + g_assert (!hb_buffer_set_length (b, 10)); - test_empty (b); + test_empty (b); - g_assert (hb_buffer_set_length (b, 0)); + g_assert (hb_buffer_set_length (b, 0)); - test_empty (b); + test_empty (b); - g_assert (!hb_buffer_allocation_successful (b)); + g_assert (!hb_buffer_allocation_successful (b)); - hb_buffer_reset (b); + hb_buffer_reset (b); - test_empty (b); + test_empty (b); - g_assert (!hb_buffer_allocation_successful (b)); + g_assert (!hb_buffer_allocation_successful (b)); } typedef struct { - const char *contents; - hb_buffer_serialize_format_t format; - unsigned int num_items; + const char *contents; + hb_buffer_serialize_format_t format; + unsigned int num_items; + hb_bool_t success; } serialization_test_t; static const serialization_test_t serialization_tests[] = { - { "", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 2 }, - { "[{\"u\":1600,\"cl\":0},{\"u\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 2 }, + { "", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 2, 1 }, + { "[{\"u\":1600,\"cl\":0},{\"u\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 2, 1 }, + + /* Mixed glyphs/Unicodes -> parse fail */ + { "[{\"u\":1600,\"cl\":0},{\"g\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 0, 0 }, + { "", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 0, 0 }, }; static void test_buffer_serialize_deserialize (void) { - hb_buffer_t *b; - unsigned int i; + hb_buffer_t *b; + unsigned int i; - for (i = 0; i < G_N_ELEMENTS (serialization_tests); i++) - { - unsigned int num_glyphs, consumed; - char round_trip[1024]; + for (i = 0; i < G_N_ELEMENTS (serialization_tests); i++) + { + unsigned int num_glyphs, consumed; + char round_trip[1024]; + hb_bool_t retval; - b = hb_buffer_create (); - hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); + b = hb_buffer_create (); + hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1); - const serialization_test_t *test = &serialization_tests[i]; - g_test_message ("serialize test #%d", i); + const serialization_test_t *test = &serialization_tests[i]; + g_test_message ("serialize test #%d", i); - hb_buffer_deserialize_unicode (b, test->contents, -1, NULL, test->format); + retval = hb_buffer_deserialize_unicode (b, test->contents, -1, NULL, test->format); - num_glyphs = hb_buffer_get_length (b); - g_assert_cmpint (num_glyphs, ==, test->num_items); + if (test->success == 0) + continue; // Expected parse failure, got one, don't round-trip - hb_buffer_serialize_unicode(b, 0, num_glyphs, round_trip, - sizeof(round_trip), &consumed, test->format, - HB_BUFFER_SERIALIZE_FLAG_DEFAULT); - g_assert_cmpstr (round_trip, ==, test->contents); + num_glyphs = hb_buffer_get_length (b); + g_assert_cmpint (num_glyphs, ==, test->num_items); - hb_buffer_destroy (b); + hb_buffer_serialize_unicode(b, 0, num_glyphs, round_trip, + sizeof(round_trip), &consumed, test->format, + HB_BUFFER_SERIALIZE_FLAG_DEFAULT); + g_assert_cmpstr (round_trip, ==, test->contents); - } + hb_buffer_destroy (b); + + } } int main (int argc, char **argv) { - unsigned int i; + unsigned int i; - hb_test_init (&argc, &argv); + hb_test_init (&argc, &argv); - for (i = 0; i < BUFFER_NUM_TYPES; i++) - { - const void *buffer_type = GINT_TO_POINTER (i); - const char *buffer_name = buffer_names[i]; + for (i = 0; i < BUFFER_NUM_TYPES; i++) + { + const void *buffer_type = GINT_TO_POINTER (i); + const char *buffer_name = buffer_names[i]; - hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties); - hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents); - hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions); - } + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties); + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents); + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions); + } - hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation); + hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation); - hb_test_add (test_buffer_utf8_conversion); - hb_test_add (test_buffer_utf8_validity); - hb_test_add (test_buffer_utf16_conversion); - hb_test_add (test_buffer_utf32_conversion); - hb_test_add (test_buffer_empty); - hb_test_add (test_buffer_serialize_deserialize); + hb_test_add (test_buffer_utf8_conversion); + hb_test_add (test_buffer_utf8_validity); + hb_test_add (test_buffer_utf16_conversion); + hb_test_add (test_buffer_utf32_conversion); + hb_test_add (test_buffer_empty); + hb_test_add (test_buffer_serialize_deserialize); - return hb_test_run(); + return hb_test_run(); }