xref: /aosp_15_r20/external/harfbuzz_ng/test/api/test-buffer.c (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2011  Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  *
24*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #include "hb-test.h"
28*2d1272b8SAndroid Build Coastguard Worker 
29*2d1272b8SAndroid Build Coastguard Worker /* Unit tests for hb-buffer.h */
30*2d1272b8SAndroid Build Coastguard Worker 
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker static const char utf8[10] = "ab\360\240\200\200defg";
33*2d1272b8SAndroid Build Coastguard Worker static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
34*2d1272b8SAndroid Build Coastguard Worker static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
35*2d1272b8SAndroid Build Coastguard Worker 
36*2d1272b8SAndroid Build Coastguard Worker 
37*2d1272b8SAndroid Build Coastguard Worker typedef enum {
38*2d1272b8SAndroid Build Coastguard Worker   BUFFER_EMPTY,
39*2d1272b8SAndroid Build Coastguard Worker   BUFFER_ONE_BY_ONE,
40*2d1272b8SAndroid Build Coastguard Worker   BUFFER_UTF32,
41*2d1272b8SAndroid Build Coastguard Worker   BUFFER_UTF16,
42*2d1272b8SAndroid Build Coastguard Worker   BUFFER_UTF8,
43*2d1272b8SAndroid Build Coastguard Worker   BUFFER_NUM_TYPES,
44*2d1272b8SAndroid Build Coastguard Worker } buffer_type_t;
45*2d1272b8SAndroid Build Coastguard Worker 
46*2d1272b8SAndroid Build Coastguard Worker static const char *buffer_names[] = {
47*2d1272b8SAndroid Build Coastguard Worker   "empty",
48*2d1272b8SAndroid Build Coastguard Worker   "one-by-one",
49*2d1272b8SAndroid Build Coastguard Worker   "utf32",
50*2d1272b8SAndroid Build Coastguard Worker   "utf16",
51*2d1272b8SAndroid Build Coastguard Worker   "utf8"
52*2d1272b8SAndroid Build Coastguard Worker };
53*2d1272b8SAndroid Build Coastguard Worker 
54*2d1272b8SAndroid Build Coastguard Worker typedef struct
55*2d1272b8SAndroid Build Coastguard Worker {
56*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *buffer;
57*2d1272b8SAndroid Build Coastguard Worker } fixture_t;
58*2d1272b8SAndroid Build Coastguard Worker 
59*2d1272b8SAndroid Build Coastguard Worker static void
fixture_init(fixture_t * fixture,gconstpointer user_data)60*2d1272b8SAndroid Build Coastguard Worker fixture_init (fixture_t *fixture, gconstpointer user_data)
61*2d1272b8SAndroid Build Coastguard Worker {
62*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
63*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
64*2d1272b8SAndroid Build Coastguard Worker 
65*2d1272b8SAndroid Build Coastguard Worker   b = fixture->buffer = hb_buffer_create ();
66*2d1272b8SAndroid Build Coastguard Worker 
67*2d1272b8SAndroid Build Coastguard Worker   switch (GPOINTER_TO_INT (user_data))
68*2d1272b8SAndroid Build Coastguard Worker   {
69*2d1272b8SAndroid Build Coastguard Worker     case BUFFER_EMPTY:
70*2d1272b8SAndroid Build Coastguard Worker       break;
71*2d1272b8SAndroid Build Coastguard Worker 
72*2d1272b8SAndroid Build Coastguard Worker     case BUFFER_ONE_BY_ONE:
73*2d1272b8SAndroid Build Coastguard Worker       for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++)
74*2d1272b8SAndroid Build Coastguard Worker       hb_buffer_add (b, utf32[i], i);
75*2d1272b8SAndroid Build Coastguard Worker       break;
76*2d1272b8SAndroid Build Coastguard Worker 
77*2d1272b8SAndroid Build Coastguard Worker     case BUFFER_UTF32:
78*2d1272b8SAndroid Build Coastguard Worker       hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
79*2d1272b8SAndroid Build Coastguard Worker       break;
80*2d1272b8SAndroid Build Coastguard Worker 
81*2d1272b8SAndroid Build Coastguard Worker     case BUFFER_UTF16:
82*2d1272b8SAndroid Build Coastguard Worker       hb_buffer_add_utf16 (b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2);
83*2d1272b8SAndroid Build Coastguard Worker       break;
84*2d1272b8SAndroid Build Coastguard Worker 
85*2d1272b8SAndroid Build Coastguard Worker     case BUFFER_UTF8:
86*2d1272b8SAndroid Build Coastguard Worker       hb_buffer_add_utf8  (b, utf8,  G_N_ELEMENTS (utf8),  1, G_N_ELEMENTS (utf8)  - 2);
87*2d1272b8SAndroid Build Coastguard Worker       break;
88*2d1272b8SAndroid Build Coastguard Worker 
89*2d1272b8SAndroid Build Coastguard Worker     default:
90*2d1272b8SAndroid Build Coastguard Worker       g_assert_not_reached ();
91*2d1272b8SAndroid Build Coastguard Worker   }
92*2d1272b8SAndroid Build Coastguard Worker }
93*2d1272b8SAndroid Build Coastguard Worker 
94*2d1272b8SAndroid Build Coastguard Worker static void
fixture_finish(fixture_t * fixture,gconstpointer user_data HB_UNUSED)95*2d1272b8SAndroid Build Coastguard Worker fixture_finish (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
96*2d1272b8SAndroid Build Coastguard Worker {
97*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_destroy (fixture->buffer);
98*2d1272b8SAndroid Build Coastguard Worker }
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker 
101*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_properties(fixture_t * fixture,gconstpointer user_data HB_UNUSED)102*2d1272b8SAndroid Build Coastguard Worker test_buffer_properties (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
103*2d1272b8SAndroid Build Coastguard Worker {
104*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b = fixture->buffer;
105*2d1272b8SAndroid Build Coastguard Worker   hb_unicode_funcs_t *ufuncs;
106*2d1272b8SAndroid Build Coastguard Worker 
107*2d1272b8SAndroid Build Coastguard Worker   /* test default properties */
108*2d1272b8SAndroid Build Coastguard Worker 
109*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
110*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
111*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
112*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_language (b) == NULL);
113*2d1272b8SAndroid Build Coastguard Worker 
114*2d1272b8SAndroid Build Coastguard Worker 
115*2d1272b8SAndroid Build Coastguard Worker   /* test property changes are retained */
116*2d1272b8SAndroid Build Coastguard Worker   ufuncs = hb_unicode_funcs_create (NULL);
117*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_unicode_funcs (b, ufuncs);
118*2d1272b8SAndroid Build Coastguard Worker   hb_unicode_funcs_destroy (ufuncs);
119*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
120*2d1272b8SAndroid Build Coastguard Worker 
121*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_direction (b, HB_DIRECTION_RTL);
122*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
123*2d1272b8SAndroid Build Coastguard Worker 
124*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
125*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
128*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
129*2d1272b8SAndroid Build Coastguard Worker 
130*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
131*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
132*2d1272b8SAndroid Build Coastguard Worker 
133*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (unsigned int) -1);
134*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1);
135*2d1272b8SAndroid Build Coastguard Worker 
136*2d1272b8SAndroid Build Coastguard Worker 
137*2d1272b8SAndroid Build Coastguard Worker   /* test clear_contents clears all these properties: */
138*2d1272b8SAndroid Build Coastguard Worker 
139*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_clear_contents (b);
140*2d1272b8SAndroid Build Coastguard Worker 
141*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs);
142*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
143*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
144*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_language (b) == NULL);
145*2d1272b8SAndroid Build Coastguard Worker 
146*2d1272b8SAndroid Build Coastguard Worker   /* but not these: */
147*2d1272b8SAndroid Build Coastguard Worker 
148*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_flags (b) != HB_BUFFER_FLAG_DEFAULT);
149*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_replacement_codepoint (b) != HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
150*2d1272b8SAndroid Build Coastguard Worker 
151*2d1272b8SAndroid Build Coastguard Worker 
152*2d1272b8SAndroid Build Coastguard Worker   /* test reset clears all properties */
153*2d1272b8SAndroid Build Coastguard Worker 
154*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_direction (b, HB_DIRECTION_RTL);
155*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL);
156*2d1272b8SAndroid Build Coastguard Worker 
157*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_script (b, HB_SCRIPT_ARABIC);
158*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC);
159*2d1272b8SAndroid Build Coastguard Worker 
160*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_language (b, hb_language_from_string ("fa", -1));
161*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1));
162*2d1272b8SAndroid Build Coastguard Worker 
163*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_flags (b, HB_BUFFER_FLAG_BOT);
164*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_BOT);
165*2d1272b8SAndroid Build Coastguard Worker 
166*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (unsigned int) -1);
167*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_replacement_codepoint (b) == (unsigned int) -1);
168*2d1272b8SAndroid Build Coastguard Worker 
169*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
170*2d1272b8SAndroid Build Coastguard Worker 
171*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ());
172*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID);
173*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID);
174*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_language (b) == NULL);
175*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_flags (b) == HB_BUFFER_FLAG_DEFAULT);
176*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_replacement_codepoint (b) == HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
177*2d1272b8SAndroid Build Coastguard Worker }
178*2d1272b8SAndroid Build Coastguard Worker 
179*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_contents(fixture_t * fixture,gconstpointer user_data)180*2d1272b8SAndroid Build Coastguard Worker test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
181*2d1272b8SAndroid Build Coastguard Worker {
182*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b = fixture->buffer;
183*2d1272b8SAndroid Build Coastguard Worker   unsigned int i, len, len2;
184*2d1272b8SAndroid Build Coastguard Worker   buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
185*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t *glyphs;
186*2d1272b8SAndroid Build Coastguard Worker 
187*2d1272b8SAndroid Build Coastguard Worker   if (buffer_type == BUFFER_EMPTY) {
188*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
189*2d1272b8SAndroid Build Coastguard Worker     return;
190*2d1272b8SAndroid Build Coastguard Worker   }
191*2d1272b8SAndroid Build Coastguard Worker 
192*2d1272b8SAndroid Build Coastguard Worker   len = hb_buffer_get_length (b);
193*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_get_glyph_infos (b, NULL); /* test NULL */
194*2d1272b8SAndroid Build Coastguard Worker   glyphs = hb_buffer_get_glyph_infos (b, &len2);
195*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (len, ==, len2);
196*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (len, ==, 5);
197*2d1272b8SAndroid Build Coastguard Worker 
198*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++) {
199*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].mask,      ==, 0);
200*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].var1.u32,  ==, 0);
201*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].var2.u32,  ==, 0);
202*2d1272b8SAndroid Build Coastguard Worker   }
203*2d1272b8SAndroid Build Coastguard Worker 
204*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++) {
205*2d1272b8SAndroid Build Coastguard Worker     unsigned int cluster;
206*2d1272b8SAndroid Build Coastguard Worker     cluster = 1+i;
207*2d1272b8SAndroid Build Coastguard Worker     if (i >= 2) {
208*2d1272b8SAndroid Build Coastguard Worker       if (buffer_type == BUFFER_UTF16)
209*2d1272b8SAndroid Build Coastguard Worker 	cluster++;
210*2d1272b8SAndroid Build Coastguard Worker       else if (buffer_type == BUFFER_UTF8)
211*2d1272b8SAndroid Build Coastguard Worker 	cluster += 3;
212*2d1272b8SAndroid Build Coastguard Worker     }
213*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
214*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].cluster,   ==, cluster);
215*2d1272b8SAndroid Build Coastguard Worker   }
216*2d1272b8SAndroid Build Coastguard Worker 
217*2d1272b8SAndroid Build Coastguard Worker   /* reverse, test, and reverse back */
218*2d1272b8SAndroid Build Coastguard Worker 
219*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse (b);
220*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
221*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
222*2d1272b8SAndroid Build Coastguard Worker 
223*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse (b);
224*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
225*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
226*2d1272b8SAndroid Build Coastguard Worker 
227*2d1272b8SAndroid Build Coastguard Worker   /* reverse_clusters works same as reverse for now since each codepoint is
228*2d1272b8SAndroid Build Coastguard Worker    * in its own cluster */
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse_clusters (b);
231*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
232*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
233*2d1272b8SAndroid Build Coastguard Worker 
234*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse_clusters (b);
235*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
236*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
237*2d1272b8SAndroid Build Coastguard Worker 
238*2d1272b8SAndroid Build Coastguard Worker   /* now form a cluster and test again */
239*2d1272b8SAndroid Build Coastguard Worker   glyphs[2].cluster = glyphs[1].cluster;
240*2d1272b8SAndroid Build Coastguard Worker 
241*2d1272b8SAndroid Build Coastguard Worker   /* reverse, test, and reverse back */
242*2d1272b8SAndroid Build Coastguard Worker 
243*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse (b);
244*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
245*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
246*2d1272b8SAndroid Build Coastguard Worker 
247*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse (b);
248*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
249*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker   /* reverse_clusters twice still should return the original string,
252*2d1272b8SAndroid Build Coastguard Worker    * but when applied once, the 1-2 cluster should be retained. */
253*2d1272b8SAndroid Build Coastguard Worker 
254*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse_clusters (b);
255*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++) {
256*2d1272b8SAndroid Build Coastguard Worker     unsigned int j = len-1-i;
257*2d1272b8SAndroid Build Coastguard Worker     if (j == 1)
258*2d1272b8SAndroid Build Coastguard Worker       j = 2;
259*2d1272b8SAndroid Build Coastguard Worker     else if (j == 2)
260*2d1272b8SAndroid Build Coastguard Worker       j = 1;
261*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
262*2d1272b8SAndroid Build Coastguard Worker   }
263*2d1272b8SAndroid Build Coastguard Worker 
264*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse_clusters (b);
265*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++)
266*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
267*2d1272b8SAndroid Build Coastguard Worker 
268*2d1272b8SAndroid Build Coastguard Worker 
269*2d1272b8SAndroid Build Coastguard Worker   /* test setting length */
270*2d1272b8SAndroid Build Coastguard Worker 
271*2d1272b8SAndroid Build Coastguard Worker   /* enlarge */
272*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_set_length (b, 10));
273*2d1272b8SAndroid Build Coastguard Worker   glyphs = hb_buffer_get_glyph_infos (b, NULL);
274*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 10);
275*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < 5; i++)
276*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
277*2d1272b8SAndroid Build Coastguard Worker   for (i = 5; i < 10; i++)
278*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, 0);
279*2d1272b8SAndroid Build Coastguard Worker   /* shrink */
280*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_set_length (b, 3));
281*2d1272b8SAndroid Build Coastguard Worker   glyphs = hb_buffer_get_glyph_infos (b, NULL);
282*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 3);
283*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < 3; i++)
284*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
285*2d1272b8SAndroid Build Coastguard Worker 
286*2d1272b8SAndroid Build Coastguard Worker 
287*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_allocation_successful (b));
288*2d1272b8SAndroid Build Coastguard Worker 
289*2d1272b8SAndroid Build Coastguard Worker 
290*2d1272b8SAndroid Build Coastguard Worker   /* test reset clears content */
291*2d1272b8SAndroid Build Coastguard Worker 
292*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
293*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
294*2d1272b8SAndroid Build Coastguard Worker }
295*2d1272b8SAndroid Build Coastguard Worker 
296*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_positions(fixture_t * fixture,gconstpointer user_data HB_UNUSED)297*2d1272b8SAndroid Build Coastguard Worker test_buffer_positions (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
298*2d1272b8SAndroid Build Coastguard Worker {
299*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b = fixture->buffer;
300*2d1272b8SAndroid Build Coastguard Worker   unsigned int i, len, len2;
301*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_position_t *positions;
302*2d1272b8SAndroid Build Coastguard Worker 
303*2d1272b8SAndroid Build Coastguard Worker   /* Without shaping, positions should all be zero */
304*2d1272b8SAndroid Build Coastguard Worker   len = hb_buffer_get_length (b);
305*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_get_glyph_positions (b, NULL); /* test NULL */
306*2d1272b8SAndroid Build Coastguard Worker   positions = hb_buffer_get_glyph_positions (b, &len2);
307*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (len, ==, len2);
308*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < len; i++) {
309*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (0, ==, positions[i].x_advance);
310*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (0, ==, positions[i].y_advance);
311*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (0, ==, positions[i].x_offset);
312*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (0, ==, positions[i].y_offset);
313*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (0, ==, positions[i].var.i32);
314*2d1272b8SAndroid Build Coastguard Worker   }
315*2d1272b8SAndroid Build Coastguard Worker 
316*2d1272b8SAndroid Build Coastguard Worker   /* test reset clears content */
317*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
318*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
319*2d1272b8SAndroid Build Coastguard Worker }
320*2d1272b8SAndroid Build Coastguard Worker 
321*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_allocation(fixture_t * fixture,gconstpointer user_data HB_UNUSED)322*2d1272b8SAndroid Build Coastguard Worker test_buffer_allocation (fixture_t *fixture, gconstpointer user_data HB_UNUSED)
323*2d1272b8SAndroid Build Coastguard Worker {
324*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b = fixture->buffer;
325*2d1272b8SAndroid Build Coastguard Worker 
326*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
327*2d1272b8SAndroid Build Coastguard Worker 
328*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_pre_allocate (b, 100));
329*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
330*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_allocation_successful (b));
331*2d1272b8SAndroid Build Coastguard Worker 
332*2d1272b8SAndroid Build Coastguard Worker   /* lets try a huge allocation, make sure it fails */
333*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1));
334*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
335*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
336*2d1272b8SAndroid Build Coastguard Worker 
337*2d1272b8SAndroid Build Coastguard Worker   /* small one again */
338*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_pre_allocate (b, 50));
339*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
340*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
341*2d1272b8SAndroid Build Coastguard Worker 
342*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
343*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_allocation_successful (b));
344*2d1272b8SAndroid Build Coastguard Worker 
345*2d1272b8SAndroid Build Coastguard Worker   /* all allocation and size  */
346*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1));
347*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
348*2d1272b8SAndroid Build Coastguard Worker 
349*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
350*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_allocation_successful (b));
351*2d1272b8SAndroid Build Coastguard Worker 
352*2d1272b8SAndroid Build Coastguard Worker   /* technically, this one can actually pass on 64bit machines, but
353*2d1272b8SAndroid Build Coastguard Worker    * I'm doubtful that any malloc allows 4GB allocations at a time.
354*2d1272b8SAndroid Build Coastguard Worker    * But let's only enable it on a 32-bit machine. */
355*2d1272b8SAndroid Build Coastguard Worker   if (sizeof (long) == 4) {
356*2d1272b8SAndroid Build Coastguard Worker     g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1));
357*2d1272b8SAndroid Build Coastguard Worker     g_assert (!hb_buffer_allocation_successful (b));
358*2d1272b8SAndroid Build Coastguard Worker   }
359*2d1272b8SAndroid Build Coastguard Worker 
360*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
361*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_allocation_successful (b));
362*2d1272b8SAndroid Build Coastguard Worker }
363*2d1272b8SAndroid Build Coastguard Worker 
364*2d1272b8SAndroid Build Coastguard Worker 
365*2d1272b8SAndroid Build Coastguard Worker typedef struct {
366*2d1272b8SAndroid Build Coastguard Worker   const char utf8[8];
367*2d1272b8SAndroid Build Coastguard Worker   const uint32_t codepoints[8];
368*2d1272b8SAndroid Build Coastguard Worker } utf8_conversion_test_t;
369*2d1272b8SAndroid Build Coastguard Worker 
370*2d1272b8SAndroid Build Coastguard Worker /* note: we skip the first and last byte when adding to buffer */
371*2d1272b8SAndroid Build Coastguard Worker static const utf8_conversion_test_t utf8_conversion_tests[] = {
372*2d1272b8SAndroid Build Coastguard Worker   {"a\303\207", {(hb_codepoint_t) -1}},
373*2d1272b8SAndroid Build Coastguard Worker   {"a\303\207b", {0xC7}},
374*2d1272b8SAndroid Build Coastguard Worker   {"ab\303cd", {'b', (hb_codepoint_t) -1, 'c'}},
375*2d1272b8SAndroid Build Coastguard Worker   {"ab\303\302\301cd", {'b', (hb_codepoint_t) -1, (hb_codepoint_t) -1, (hb_codepoint_t) -1, 'c'}}
376*2d1272b8SAndroid Build Coastguard Worker };
377*2d1272b8SAndroid Build Coastguard Worker 
378*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_utf8_conversion(void)379*2d1272b8SAndroid Build Coastguard Worker test_buffer_utf8_conversion (void)
380*2d1272b8SAndroid Build Coastguard Worker {
381*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
382*2d1272b8SAndroid Build Coastguard Worker   unsigned int chars, i, j, len;
383*2d1272b8SAndroid Build Coastguard Worker 
384*2d1272b8SAndroid Build Coastguard Worker   b = hb_buffer_create ();
385*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
386*2d1272b8SAndroid Build Coastguard Worker 
387*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++)
388*2d1272b8SAndroid Build Coastguard Worker   {
389*2d1272b8SAndroid Build Coastguard Worker     unsigned int bytes;
390*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t *glyphs;
391*2d1272b8SAndroid Build Coastguard Worker     const utf8_conversion_test_t *test = &utf8_conversion_tests[i];
392*2d1272b8SAndroid Build Coastguard Worker     char *escaped;
393*2d1272b8SAndroid Build Coastguard Worker 
394*2d1272b8SAndroid Build Coastguard Worker     escaped = g_strescape (test->utf8, NULL);
395*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("UTF-8 test #%d: %s", i, escaped);
396*2d1272b8SAndroid Build Coastguard Worker     g_free (escaped);
397*2d1272b8SAndroid Build Coastguard Worker 
398*2d1272b8SAndroid Build Coastguard Worker     bytes = strlen (test->utf8);
399*2d1272b8SAndroid Build Coastguard Worker     for (chars = 0; test->codepoints[chars]; chars++)
400*2d1272b8SAndroid Build Coastguard Worker       ;
401*2d1272b8SAndroid Build Coastguard Worker 
402*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_clear_contents (b);
403*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_add_utf8 (b, test->utf8, bytes,  1, bytes - 2);
404*2d1272b8SAndroid Build Coastguard Worker 
405*2d1272b8SAndroid Build Coastguard Worker     glyphs = hb_buffer_get_glyph_infos (b, &len);
406*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (len, ==, chars);
407*2d1272b8SAndroid Build Coastguard Worker     for (j = 0; j < chars; j++)
408*2d1272b8SAndroid Build Coastguard Worker       g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
409*2d1272b8SAndroid Build Coastguard Worker   }
410*2d1272b8SAndroid Build Coastguard Worker 
411*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_destroy (b);
412*2d1272b8SAndroid Build Coastguard Worker }
413*2d1272b8SAndroid Build Coastguard Worker 
414*2d1272b8SAndroid Build Coastguard Worker 
415*2d1272b8SAndroid Build Coastguard Worker 
416*2d1272b8SAndroid Build Coastguard Worker /* Following test table is adapted from glib/glib/tests/utf8-validate.c
417*2d1272b8SAndroid Build Coastguard Worker  * with relicensing permission from Matthias Clasen. */
418*2d1272b8SAndroid Build Coastguard Worker 
419*2d1272b8SAndroid Build Coastguard Worker typedef struct {
420*2d1272b8SAndroid Build Coastguard Worker   const char *utf8;
421*2d1272b8SAndroid Build Coastguard Worker   int max_len;
422*2d1272b8SAndroid Build Coastguard Worker   unsigned int offset;
423*2d1272b8SAndroid Build Coastguard Worker   gboolean valid;
424*2d1272b8SAndroid Build Coastguard Worker } utf8_validity_test_t;
425*2d1272b8SAndroid Build Coastguard Worker 
426*2d1272b8SAndroid Build Coastguard Worker static const utf8_validity_test_t utf8_validity_tests[] = {
427*2d1272b8SAndroid Build Coastguard Worker   /* some tests to check max_len handling */
428*2d1272b8SAndroid Build Coastguard Worker   /* length 1 */
429*2d1272b8SAndroid Build Coastguard Worker   { "abcde", -1, 5, TRUE },
430*2d1272b8SAndroid Build Coastguard Worker   { "abcde", 3, 3, TRUE },
431*2d1272b8SAndroid Build Coastguard Worker   { "abcde", 5, 5, TRUE },
432*2d1272b8SAndroid Build Coastguard Worker   /* length 2 */
433*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE },
434*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  1, 0, FALSE },
435*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  2, 2, TRUE },
436*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  3, 2, FALSE },
437*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  4, 4, TRUE },
438*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  5, 4, FALSE },
439*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\xa9\xc2\xa9\xc2\xa9",  6, 6, TRUE },
440*2d1272b8SAndroid Build Coastguard Worker   /* length 3 */
441*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE },
442*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  1, 0, FALSE },
443*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  2, 0, FALSE },
444*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  3, 3, TRUE },
445*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  4, 3, FALSE },
446*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  5, 3, FALSE },
447*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x89\xa0\xe2\x89\xa0",  6, 6, TRUE },
448*2d1272b8SAndroid Build Coastguard Worker 
449*2d1272b8SAndroid Build Coastguard Worker   /* examples from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */
450*2d1272b8SAndroid Build Coastguard Worker   /* greek 'kosme' */
451*2d1272b8SAndroid Build Coastguard Worker   { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE },
452*2d1272b8SAndroid Build Coastguard Worker   /* first sequence of each length */
453*2d1272b8SAndroid Build Coastguard Worker   { "\x00", -1, 0, TRUE },
454*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\x80", -1, 2, TRUE },
455*2d1272b8SAndroid Build Coastguard Worker   { "\xe0\xa0\x80", -1, 3, TRUE },
456*2d1272b8SAndroid Build Coastguard Worker   { "\xf0\x90\x80\x80", -1, 4, TRUE },
457*2d1272b8SAndroid Build Coastguard Worker   { "\xf8\x88\x80\x80\x80", -1, 0, FALSE },
458*2d1272b8SAndroid Build Coastguard Worker   { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE },
459*2d1272b8SAndroid Build Coastguard Worker   /* last sequence of each length */
460*2d1272b8SAndroid Build Coastguard Worker   { "\x7f", -1, 1, TRUE },
461*2d1272b8SAndroid Build Coastguard Worker   { "\xdf\xbf", -1, 2, TRUE },
462*2d1272b8SAndroid Build Coastguard Worker   { "\xef\xbf\xbf", -1, 0, TRUE },
463*2d1272b8SAndroid Build Coastguard Worker   { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
464*2d1272b8SAndroid Build Coastguard Worker   { "\xf4\x90\xbf\xbf", -1, 0, FALSE },
465*2d1272b8SAndroid Build Coastguard Worker   { "\xf7\xbf\xbf\xbf", -1, 0, FALSE },
466*2d1272b8SAndroid Build Coastguard Worker   { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE },
467*2d1272b8SAndroid Build Coastguard Worker   { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE },
468*2d1272b8SAndroid Build Coastguard Worker   /* other boundary conditions */
469*2d1272b8SAndroid Build Coastguard Worker   { "\xed\x9f\xbf", -1, 3, TRUE },
470*2d1272b8SAndroid Build Coastguard Worker   { "\xed\xa0\x80", -1, 0, FALSE },
471*2d1272b8SAndroid Build Coastguard Worker   { "\xed\xbf\xbf", -1, 0, FALSE },
472*2d1272b8SAndroid Build Coastguard Worker   { "\xee\x80\x80", -1, 3, TRUE },
473*2d1272b8SAndroid Build Coastguard Worker   { "\xef\xbf\xbd", -1, 3, TRUE },
474*2d1272b8SAndroid Build Coastguard Worker   { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
475*2d1272b8SAndroid Build Coastguard Worker   /* malformed sequences */
476*2d1272b8SAndroid Build Coastguard Worker   /* continuation bytes */
477*2d1272b8SAndroid Build Coastguard Worker   { "\x80", -1, 0, FALSE },
478*2d1272b8SAndroid Build Coastguard Worker   { "\xbf", -1, 0, FALSE },
479*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf", -1, 0, FALSE },
480*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf\x80", -1, 0, FALSE },
481*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf\x80\xbf", -1, 0, FALSE },
482*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
483*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE },
484*2d1272b8SAndroid Build Coastguard Worker   { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
485*2d1272b8SAndroid Build Coastguard Worker 
486*2d1272b8SAndroid Build Coastguard Worker   /* all possible continuation byte */
487*2d1272b8SAndroid Build Coastguard Worker   { "\x80", -1, 0, FALSE },
488*2d1272b8SAndroid Build Coastguard Worker   { "\x81", -1, 0, FALSE },
489*2d1272b8SAndroid Build Coastguard Worker   { "\x82", -1, 0, FALSE },
490*2d1272b8SAndroid Build Coastguard Worker   { "\x83", -1, 0, FALSE },
491*2d1272b8SAndroid Build Coastguard Worker   { "\x84", -1, 0, FALSE },
492*2d1272b8SAndroid Build Coastguard Worker   { "\x85", -1, 0, FALSE },
493*2d1272b8SAndroid Build Coastguard Worker   { "\x86", -1, 0, FALSE },
494*2d1272b8SAndroid Build Coastguard Worker   { "\x87", -1, 0, FALSE },
495*2d1272b8SAndroid Build Coastguard Worker   { "\x88", -1, 0, FALSE },
496*2d1272b8SAndroid Build Coastguard Worker   { "\x89", -1, 0, FALSE },
497*2d1272b8SAndroid Build Coastguard Worker   { "\x8a", -1, 0, FALSE },
498*2d1272b8SAndroid Build Coastguard Worker   { "\x8b", -1, 0, FALSE },
499*2d1272b8SAndroid Build Coastguard Worker   { "\x8c", -1, 0, FALSE },
500*2d1272b8SAndroid Build Coastguard Worker   { "\x8d", -1, 0, FALSE },
501*2d1272b8SAndroid Build Coastguard Worker   { "\x8e", -1, 0, FALSE },
502*2d1272b8SAndroid Build Coastguard Worker   { "\x8f", -1, 0, FALSE },
503*2d1272b8SAndroid Build Coastguard Worker   { "\x90", -1, 0, FALSE },
504*2d1272b8SAndroid Build Coastguard Worker   { "\x91", -1, 0, FALSE },
505*2d1272b8SAndroid Build Coastguard Worker   { "\x92", -1, 0, FALSE },
506*2d1272b8SAndroid Build Coastguard Worker   { "\x93", -1, 0, FALSE },
507*2d1272b8SAndroid Build Coastguard Worker   { "\x94", -1, 0, FALSE },
508*2d1272b8SAndroid Build Coastguard Worker   { "\x95", -1, 0, FALSE },
509*2d1272b8SAndroid Build Coastguard Worker   { "\x96", -1, 0, FALSE },
510*2d1272b8SAndroid Build Coastguard Worker   { "\x97", -1, 0, FALSE },
511*2d1272b8SAndroid Build Coastguard Worker   { "\x98", -1, 0, FALSE },
512*2d1272b8SAndroid Build Coastguard Worker   { "\x99", -1, 0, FALSE },
513*2d1272b8SAndroid Build Coastguard Worker   { "\x9a", -1, 0, FALSE },
514*2d1272b8SAndroid Build Coastguard Worker   { "\x9b", -1, 0, FALSE },
515*2d1272b8SAndroid Build Coastguard Worker   { "\x9c", -1, 0, FALSE },
516*2d1272b8SAndroid Build Coastguard Worker   { "\x9d", -1, 0, FALSE },
517*2d1272b8SAndroid Build Coastguard Worker   { "\x9e", -1, 0, FALSE },
518*2d1272b8SAndroid Build Coastguard Worker   { "\x9f", -1, 0, FALSE },
519*2d1272b8SAndroid Build Coastguard Worker   { "\xa0", -1, 0, FALSE },
520*2d1272b8SAndroid Build Coastguard Worker   { "\xa1", -1, 0, FALSE },
521*2d1272b8SAndroid Build Coastguard Worker   { "\xa2", -1, 0, FALSE },
522*2d1272b8SAndroid Build Coastguard Worker   { "\xa3", -1, 0, FALSE },
523*2d1272b8SAndroid Build Coastguard Worker   { "\xa4", -1, 0, FALSE },
524*2d1272b8SAndroid Build Coastguard Worker   { "\xa5", -1, 0, FALSE },
525*2d1272b8SAndroid Build Coastguard Worker   { "\xa6", -1, 0, FALSE },
526*2d1272b8SAndroid Build Coastguard Worker   { "\xa7", -1, 0, FALSE },
527*2d1272b8SAndroid Build Coastguard Worker   { "\xa8", -1, 0, FALSE },
528*2d1272b8SAndroid Build Coastguard Worker   { "\xa9", -1, 0, FALSE },
529*2d1272b8SAndroid Build Coastguard Worker   { "\xaa", -1, 0, FALSE },
530*2d1272b8SAndroid Build Coastguard Worker   { "\xab", -1, 0, FALSE },
531*2d1272b8SAndroid Build Coastguard Worker   { "\xac", -1, 0, FALSE },
532*2d1272b8SAndroid Build Coastguard Worker   { "\xad", -1, 0, FALSE },
533*2d1272b8SAndroid Build Coastguard Worker   { "\xae", -1, 0, FALSE },
534*2d1272b8SAndroid Build Coastguard Worker   { "\xaf", -1, 0, FALSE },
535*2d1272b8SAndroid Build Coastguard Worker   { "\xb0", -1, 0, FALSE },
536*2d1272b8SAndroid Build Coastguard Worker   { "\xb1", -1, 0, FALSE },
537*2d1272b8SAndroid Build Coastguard Worker   { "\xb2", -1, 0, FALSE },
538*2d1272b8SAndroid Build Coastguard Worker   { "\xb3", -1, 0, FALSE },
539*2d1272b8SAndroid Build Coastguard Worker   { "\xb4", -1, 0, FALSE },
540*2d1272b8SAndroid Build Coastguard Worker   { "\xb5", -1, 0, FALSE },
541*2d1272b8SAndroid Build Coastguard Worker   { "\xb6", -1, 0, FALSE },
542*2d1272b8SAndroid Build Coastguard Worker   { "\xb7", -1, 0, FALSE },
543*2d1272b8SAndroid Build Coastguard Worker   { "\xb8", -1, 0, FALSE },
544*2d1272b8SAndroid Build Coastguard Worker   { "\xb9", -1, 0, FALSE },
545*2d1272b8SAndroid Build Coastguard Worker   { "\xba", -1, 0, FALSE },
546*2d1272b8SAndroid Build Coastguard Worker   { "\xbb", -1, 0, FALSE },
547*2d1272b8SAndroid Build Coastguard Worker   { "\xbc", -1, 0, FALSE },
548*2d1272b8SAndroid Build Coastguard Worker   { "\xbd", -1, 0, FALSE },
549*2d1272b8SAndroid Build Coastguard Worker   { "\xbe", -1, 0, FALSE },
550*2d1272b8SAndroid Build Coastguard Worker   { "\xbf", -1, 0, FALSE },
551*2d1272b8SAndroid Build Coastguard Worker   /* lone start characters */
552*2d1272b8SAndroid Build Coastguard Worker   { "\xc0\x20", -1, 0, FALSE },
553*2d1272b8SAndroid Build Coastguard Worker   { "\xc1\x20", -1, 0, FALSE },
554*2d1272b8SAndroid Build Coastguard Worker   { "\xc2\x20", -1, 0, FALSE },
555*2d1272b8SAndroid Build Coastguard Worker   { "\xc3\x20", -1, 0, FALSE },
556*2d1272b8SAndroid Build Coastguard Worker   { "\xc4\x20", -1, 0, FALSE },
557*2d1272b8SAndroid Build Coastguard Worker   { "\xc5\x20", -1, 0, FALSE },
558*2d1272b8SAndroid Build Coastguard Worker   { "\xc6\x20", -1, 0, FALSE },
559*2d1272b8SAndroid Build Coastguard Worker   { "\xc7\x20", -1, 0, FALSE },
560*2d1272b8SAndroid Build Coastguard Worker   { "\xc8\x20", -1, 0, FALSE },
561*2d1272b8SAndroid Build Coastguard Worker   { "\xc9\x20", -1, 0, FALSE },
562*2d1272b8SAndroid Build Coastguard Worker   { "\xca\x20", -1, 0, FALSE },
563*2d1272b8SAndroid Build Coastguard Worker   { "\xcb\x20", -1, 0, FALSE },
564*2d1272b8SAndroid Build Coastguard Worker   { "\xcc\x20", -1, 0, FALSE },
565*2d1272b8SAndroid Build Coastguard Worker   { "\xcd\x20", -1, 0, FALSE },
566*2d1272b8SAndroid Build Coastguard Worker   { "\xce\x20", -1, 0, FALSE },
567*2d1272b8SAndroid Build Coastguard Worker   { "\xcf\x20", -1, 0, FALSE },
568*2d1272b8SAndroid Build Coastguard Worker   { "\xd0\x20", -1, 0, FALSE },
569*2d1272b8SAndroid Build Coastguard Worker   { "\xd1\x20", -1, 0, FALSE },
570*2d1272b8SAndroid Build Coastguard Worker   { "\xd2\x20", -1, 0, FALSE },
571*2d1272b8SAndroid Build Coastguard Worker   { "\xd3\x20", -1, 0, FALSE },
572*2d1272b8SAndroid Build Coastguard Worker   { "\xd4\x20", -1, 0, FALSE },
573*2d1272b8SAndroid Build Coastguard Worker   { "\xd5\x20", -1, 0, FALSE },
574*2d1272b8SAndroid Build Coastguard Worker   { "\xd6\x20", -1, 0, FALSE },
575*2d1272b8SAndroid Build Coastguard Worker   { "\xd7\x20", -1, 0, FALSE },
576*2d1272b8SAndroid Build Coastguard Worker   { "\xd8\x20", -1, 0, FALSE },
577*2d1272b8SAndroid Build Coastguard Worker   { "\xd9\x20", -1, 0, FALSE },
578*2d1272b8SAndroid Build Coastguard Worker   { "\xda\x20", -1, 0, FALSE },
579*2d1272b8SAndroid Build Coastguard Worker   { "\xdb\x20", -1, 0, FALSE },
580*2d1272b8SAndroid Build Coastguard Worker   { "\xdc\x20", -1, 0, FALSE },
581*2d1272b8SAndroid Build Coastguard Worker   { "\xdd\x20", -1, 0, FALSE },
582*2d1272b8SAndroid Build Coastguard Worker   { "\xde\x20", -1, 0, FALSE },
583*2d1272b8SAndroid Build Coastguard Worker   { "\xdf\x20", -1, 0, FALSE },
584*2d1272b8SAndroid Build Coastguard Worker   { "\xe0\x20", -1, 0, FALSE },
585*2d1272b8SAndroid Build Coastguard Worker   { "\xe1\x20", -1, 0, FALSE },
586*2d1272b8SAndroid Build Coastguard Worker   { "\xe2\x20", -1, 0, FALSE },
587*2d1272b8SAndroid Build Coastguard Worker   { "\xe3\x20", -1, 0, FALSE },
588*2d1272b8SAndroid Build Coastguard Worker   { "\xe4\x20", -1, 0, FALSE },
589*2d1272b8SAndroid Build Coastguard Worker   { "\xe5\x20", -1, 0, FALSE },
590*2d1272b8SAndroid Build Coastguard Worker   { "\xe6\x20", -1, 0, FALSE },
591*2d1272b8SAndroid Build Coastguard Worker   { "\xe7\x20", -1, 0, FALSE },
592*2d1272b8SAndroid Build Coastguard Worker   { "\xe8\x20", -1, 0, FALSE },
593*2d1272b8SAndroid Build Coastguard Worker   { "\xe9\x20", -1, 0, FALSE },
594*2d1272b8SAndroid Build Coastguard Worker   { "\xea\x20", -1, 0, FALSE },
595*2d1272b8SAndroid Build Coastguard Worker   { "\xeb\x20", -1, 0, FALSE },
596*2d1272b8SAndroid Build Coastguard Worker   { "\xec\x20", -1, 0, FALSE },
597*2d1272b8SAndroid Build Coastguard Worker   { "\xed\x20", -1, 0, FALSE },
598*2d1272b8SAndroid Build Coastguard Worker   { "\xee\x20", -1, 0, FALSE },
599*2d1272b8SAndroid Build Coastguard Worker   { "\xef\x20", -1, 0, FALSE },
600*2d1272b8SAndroid Build Coastguard Worker   { "\xf0\x20", -1, 0, FALSE },
601*2d1272b8SAndroid Build Coastguard Worker   { "\xf1\x20", -1, 0, FALSE },
602*2d1272b8SAndroid Build Coastguard Worker   { "\xf2\x20", -1, 0, FALSE },
603*2d1272b8SAndroid Build Coastguard Worker   { "\xf3\x20", -1, 0, FALSE },
604*2d1272b8SAndroid Build Coastguard Worker   { "\xf4\x20", -1, 0, FALSE },
605*2d1272b8SAndroid Build Coastguard Worker   { "\xf5\x20", -1, 0, FALSE },
606*2d1272b8SAndroid Build Coastguard Worker   { "\xf6\x20", -1, 0, FALSE },
607*2d1272b8SAndroid Build Coastguard Worker   { "\xf7\x20", -1, 0, FALSE },
608*2d1272b8SAndroid Build Coastguard Worker   { "\xf8\x20", -1, 0, FALSE },
609*2d1272b8SAndroid Build Coastguard Worker   { "\xf9\x20", -1, 0, FALSE },
610*2d1272b8SAndroid Build Coastguard Worker   { "\xfa\x20", -1, 0, FALSE },
611*2d1272b8SAndroid Build Coastguard Worker   { "\xfb\x20", -1, 0, FALSE },
612*2d1272b8SAndroid Build Coastguard Worker   { "\xfc\x20", -1, 0, FALSE },
613*2d1272b8SAndroid Build Coastguard Worker   { "\xfd\x20", -1, 0, FALSE },
614*2d1272b8SAndroid Build Coastguard Worker   /* missing continuation bytes */
615*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xc0", -1, 1, FALSE },
616*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xe0\x80", -1, 1, FALSE },
617*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf0\x80\x80", -1, 1, FALSE },
618*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf8\x80\x80\x80", -1, 1, FALSE },
619*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE },
620*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xdf", -1, 1, FALSE },
621*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xef\xbf", -1, 1, FALSE },
622*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf7\xbf\xbf", -1, 1, FALSE },
623*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE },
624*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE },
625*2d1272b8SAndroid Build Coastguard Worker   /* impossible bytes */
626*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfe\x20", -1, 1, FALSE },
627*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xff\x20", -1, 1, FALSE },
628*2d1272b8SAndroid Build Coastguard Worker   /* overlong sequences */
629*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xc0\xaf\x20", -1, 1, FALSE },
630*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE },
631*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE },
632*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE },
633*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE },
634*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xc1\xbf\x20", -1, 1, FALSE },
635*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE },
636*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE },
637*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE },
638*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE },
639*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xc0\x80\x20", -1, 1, FALSE },
640*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xe0\x80\x80\x20", -1, 1, FALSE },
641*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE },
642*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE },
643*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE },
644*2d1272b8SAndroid Build Coastguard Worker   /* illegal code positions */
645*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xa0\x80\x20", -1, 1, FALSE },
646*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xad\xbf\x20", -1, 1, FALSE },
647*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xae\x80\x20", -1, 1, FALSE },
648*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE },
649*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xb0\x80\x20", -1, 1, FALSE },
650*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xbe\x80\x20", -1, 1, FALSE },
651*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE },
652*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE },
653*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
654*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
655*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
656*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE },
657*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
658*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
659*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
660*2d1272b8SAndroid Build Coastguard Worker #if 0 /* We don't consider U+FFFE / U+FFFF and similar invalid. */
661*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE },
662*2d1272b8SAndroid Build Coastguard Worker   { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE },
663*2d1272b8SAndroid Build Coastguard Worker #endif
664*2d1272b8SAndroid Build Coastguard Worker   { "", -1, 0, TRUE }
665*2d1272b8SAndroid Build Coastguard Worker };
666*2d1272b8SAndroid Build Coastguard Worker 
667*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_utf8_validity(void)668*2d1272b8SAndroid Build Coastguard Worker test_buffer_utf8_validity (void)
669*2d1272b8SAndroid Build Coastguard Worker {
670*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
671*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
672*2d1272b8SAndroid Build Coastguard Worker 
673*2d1272b8SAndroid Build Coastguard Worker   b = hb_buffer_create ();
674*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
675*2d1272b8SAndroid Build Coastguard Worker 
676*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++)
677*2d1272b8SAndroid Build Coastguard Worker   {
678*2d1272b8SAndroid Build Coastguard Worker     const utf8_validity_test_t *test = &utf8_validity_tests[i];
679*2d1272b8SAndroid Build Coastguard Worker     unsigned int text_bytes, segment_bytes, j, len;
680*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t *glyphs;
681*2d1272b8SAndroid Build Coastguard Worker     char *escaped;
682*2d1272b8SAndroid Build Coastguard Worker 
683*2d1272b8SAndroid Build Coastguard Worker     escaped = g_strescape (test->utf8, NULL);
684*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("UTF-8 test #%d: %s", i, escaped);
685*2d1272b8SAndroid Build Coastguard Worker     g_free (escaped);
686*2d1272b8SAndroid Build Coastguard Worker 
687*2d1272b8SAndroid Build Coastguard Worker     text_bytes = strlen (test->utf8);
688*2d1272b8SAndroid Build Coastguard Worker     if (test->max_len == -1)
689*2d1272b8SAndroid Build Coastguard Worker       segment_bytes = text_bytes;
690*2d1272b8SAndroid Build Coastguard Worker     else
691*2d1272b8SAndroid Build Coastguard Worker       segment_bytes = test->max_len;
692*2d1272b8SAndroid Build Coastguard Worker 
693*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_clear_contents (b);
694*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_add_utf8 (b, test->utf8, text_bytes,  0, segment_bytes);
695*2d1272b8SAndroid Build Coastguard Worker 
696*2d1272b8SAndroid Build Coastguard Worker     glyphs = hb_buffer_get_glyph_infos (b, &len);
697*2d1272b8SAndroid Build Coastguard Worker     for (j = 0; j < len; j++)
698*2d1272b8SAndroid Build Coastguard Worker       if (glyphs[j].codepoint == (hb_codepoint_t) -1)
699*2d1272b8SAndroid Build Coastguard Worker 	break;
700*2d1272b8SAndroid Build Coastguard Worker 
701*2d1272b8SAndroid Build Coastguard Worker     g_assert (test->valid ? j == len : j < len);
702*2d1272b8SAndroid Build Coastguard Worker     if (!test->valid)
703*2d1272b8SAndroid Build Coastguard Worker       g_assert (glyphs[j].cluster == test->offset);
704*2d1272b8SAndroid Build Coastguard Worker   }
705*2d1272b8SAndroid Build Coastguard Worker 
706*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_destroy (b);
707*2d1272b8SAndroid Build Coastguard Worker }
708*2d1272b8SAndroid Build Coastguard Worker 
709*2d1272b8SAndroid Build Coastguard Worker 
710*2d1272b8SAndroid Build Coastguard Worker typedef struct {
711*2d1272b8SAndroid Build Coastguard Worker   const uint16_t utf16[8];
712*2d1272b8SAndroid Build Coastguard Worker   const uint32_t codepoints[8];
713*2d1272b8SAndroid Build Coastguard Worker } utf16_conversion_test_t;
714*2d1272b8SAndroid Build Coastguard Worker 
715*2d1272b8SAndroid Build Coastguard Worker /* note: we skip the first and last item from utf16 when adding to buffer */
716*2d1272b8SAndroid Build Coastguard Worker static const utf16_conversion_test_t utf16_conversion_tests[] = {
717*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
718*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}},
719*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -1}},
720*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -1}},
721*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -1, 0x61}},
722*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -1}},
723*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x61}, {0}}
724*2d1272b8SAndroid Build Coastguard Worker };
725*2d1272b8SAndroid Build Coastguard Worker 
726*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_utf16_conversion(void)727*2d1272b8SAndroid Build Coastguard Worker test_buffer_utf16_conversion (void)
728*2d1272b8SAndroid Build Coastguard Worker {
729*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
730*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
731*2d1272b8SAndroid Build Coastguard Worker 
732*2d1272b8SAndroid Build Coastguard Worker   b = hb_buffer_create ();
733*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
734*2d1272b8SAndroid Build Coastguard Worker 
735*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < G_N_ELEMENTS (utf16_conversion_tests); i++)
736*2d1272b8SAndroid Build Coastguard Worker   {
737*2d1272b8SAndroid Build Coastguard Worker     const utf16_conversion_test_t *test = &utf16_conversion_tests[i];
738*2d1272b8SAndroid Build Coastguard Worker     unsigned int u_len, chars, j, len;
739*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t *glyphs;
740*2d1272b8SAndroid Build Coastguard Worker 
741*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("UTF-16 test #%d", i);
742*2d1272b8SAndroid Build Coastguard Worker 
743*2d1272b8SAndroid Build Coastguard Worker     for (u_len = 0; test->utf16[u_len]; u_len++)
744*2d1272b8SAndroid Build Coastguard Worker       ;
745*2d1272b8SAndroid Build Coastguard Worker     for (chars = 0; test->codepoints[chars]; chars++)
746*2d1272b8SAndroid Build Coastguard Worker       ;
747*2d1272b8SAndroid Build Coastguard Worker 
748*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_clear_contents (b);
749*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_add_utf16 (b, test->utf16, u_len,  1, u_len - 2);
750*2d1272b8SAndroid Build Coastguard Worker 
751*2d1272b8SAndroid Build Coastguard Worker     glyphs = hb_buffer_get_glyph_infos (b, &len);
752*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (len, ==, chars);
753*2d1272b8SAndroid Build Coastguard Worker     for (j = 0; j < chars; j++)
754*2d1272b8SAndroid Build Coastguard Worker       g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
755*2d1272b8SAndroid Build Coastguard Worker   }
756*2d1272b8SAndroid Build Coastguard Worker 
757*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_destroy (b);
758*2d1272b8SAndroid Build Coastguard Worker }
759*2d1272b8SAndroid Build Coastguard Worker 
760*2d1272b8SAndroid Build Coastguard Worker 
761*2d1272b8SAndroid Build Coastguard Worker typedef struct {
762*2d1272b8SAndroid Build Coastguard Worker   const uint32_t utf32[8];
763*2d1272b8SAndroid Build Coastguard Worker   const uint32_t codepoints[8];
764*2d1272b8SAndroid Build Coastguard Worker } utf32_conversion_test_t;
765*2d1272b8SAndroid Build Coastguard Worker 
766*2d1272b8SAndroid Build Coastguard Worker /* note: we skip the first and last item from utf32 when adding to buffer */
767*2d1272b8SAndroid Build Coastguard Worker static const utf32_conversion_test_t utf32_conversion_tests[] = {
768*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, (hb_codepoint_t) -3, (hb_codepoint_t) -3}},
769*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x004D, 0x0430, 0x4E8C, 0x10302, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
770*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0xDF02, 0x61}, {(hb_codepoint_t) -3, (hb_codepoint_t) -3}},
771*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0xDF02}, {(hb_codepoint_t) -3}},
772*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, (hb_codepoint_t) -3}},
773*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xD800, 0x61, 0xDF02}, {(hb_codepoint_t) -3, 0x61}},
774*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0xDF00, 0x61}, {(hb_codepoint_t) -3}},
775*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x10FFFF, 0x61}, {0x10FFFF}},
776*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x110000, 0x61}, {(hb_codepoint_t) -3}},
777*2d1272b8SAndroid Build Coastguard Worker   {{0x41, 0x61}, {0}}
778*2d1272b8SAndroid Build Coastguard Worker };
779*2d1272b8SAndroid Build Coastguard Worker 
780*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_utf32_conversion(void)781*2d1272b8SAndroid Build Coastguard Worker test_buffer_utf32_conversion (void)
782*2d1272b8SAndroid Build Coastguard Worker {
783*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
784*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
785*2d1272b8SAndroid Build Coastguard Worker 
786*2d1272b8SAndroid Build Coastguard Worker   b = hb_buffer_create ();
787*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -3);
788*2d1272b8SAndroid Build Coastguard Worker 
789*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < G_N_ELEMENTS (utf32_conversion_tests); i++)
790*2d1272b8SAndroid Build Coastguard Worker   {
791*2d1272b8SAndroid Build Coastguard Worker     const utf32_conversion_test_t *test = &utf32_conversion_tests[i];
792*2d1272b8SAndroid Build Coastguard Worker     unsigned int u_len, chars, j, len;
793*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t *glyphs;
794*2d1272b8SAndroid Build Coastguard Worker 
795*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("UTF-32 test #%d", i);
796*2d1272b8SAndroid Build Coastguard Worker 
797*2d1272b8SAndroid Build Coastguard Worker     for (u_len = 0; test->utf32[u_len]; u_len++)
798*2d1272b8SAndroid Build Coastguard Worker       ;
799*2d1272b8SAndroid Build Coastguard Worker     for (chars = 0; test->codepoints[chars]; chars++)
800*2d1272b8SAndroid Build Coastguard Worker       ;
801*2d1272b8SAndroid Build Coastguard Worker 
802*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_clear_contents (b);
803*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_add_utf32 (b, test->utf32, u_len,  1, u_len - 2);
804*2d1272b8SAndroid Build Coastguard Worker 
805*2d1272b8SAndroid Build Coastguard Worker     glyphs = hb_buffer_get_glyph_infos (b, &len);
806*2d1272b8SAndroid Build Coastguard Worker     g_assert_cmpint (len, ==, chars);
807*2d1272b8SAndroid Build Coastguard Worker     for (j = 0; j < chars; j++)
808*2d1272b8SAndroid Build Coastguard Worker       g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]);
809*2d1272b8SAndroid Build Coastguard Worker   }
810*2d1272b8SAndroid Build Coastguard Worker 
811*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_destroy (b);
812*2d1272b8SAndroid Build Coastguard Worker }
813*2d1272b8SAndroid Build Coastguard Worker 
814*2d1272b8SAndroid Build Coastguard Worker 
815*2d1272b8SAndroid Build Coastguard Worker static void
test_empty(hb_buffer_t * b)816*2d1272b8SAndroid Build Coastguard Worker test_empty (hb_buffer_t *b)
817*2d1272b8SAndroid Build Coastguard Worker {
818*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpint (hb_buffer_get_length (b), ==, 0);
819*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_get_glyph_infos (b, NULL));
820*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_get_glyph_positions (b, NULL));
821*2d1272b8SAndroid Build Coastguard Worker }
822*2d1272b8SAndroid Build Coastguard Worker 
823*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_empty(void)824*2d1272b8SAndroid Build Coastguard Worker test_buffer_empty (void)
825*2d1272b8SAndroid Build Coastguard Worker {
826*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b = hb_buffer_get_empty ();
827*2d1272b8SAndroid Build Coastguard Worker 
828*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_empty ());
829*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_get_empty () == b);
830*2d1272b8SAndroid Build Coastguard Worker 
831*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
832*2d1272b8SAndroid Build Coastguard Worker 
833*2d1272b8SAndroid Build Coastguard Worker   test_empty (b);
834*2d1272b8SAndroid Build Coastguard Worker 
835*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2);
836*2d1272b8SAndroid Build Coastguard Worker 
837*2d1272b8SAndroid Build Coastguard Worker   test_empty (b);
838*2d1272b8SAndroid Build Coastguard Worker 
839*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse (b);
840*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reverse_clusters (b);
841*2d1272b8SAndroid Build Coastguard Worker 
842*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_set_length (b, 10));
843*2d1272b8SAndroid Build Coastguard Worker 
844*2d1272b8SAndroid Build Coastguard Worker   test_empty (b);
845*2d1272b8SAndroid Build Coastguard Worker 
846*2d1272b8SAndroid Build Coastguard Worker   g_assert (hb_buffer_set_length (b, 0));
847*2d1272b8SAndroid Build Coastguard Worker 
848*2d1272b8SAndroid Build Coastguard Worker   test_empty (b);
849*2d1272b8SAndroid Build Coastguard Worker 
850*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
851*2d1272b8SAndroid Build Coastguard Worker 
852*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_reset (b);
853*2d1272b8SAndroid Build Coastguard Worker 
854*2d1272b8SAndroid Build Coastguard Worker   test_empty (b);
855*2d1272b8SAndroid Build Coastguard Worker 
856*2d1272b8SAndroid Build Coastguard Worker   g_assert (!hb_buffer_allocation_successful (b));
857*2d1272b8SAndroid Build Coastguard Worker }
858*2d1272b8SAndroid Build Coastguard Worker 
859*2d1272b8SAndroid Build Coastguard Worker typedef struct {
860*2d1272b8SAndroid Build Coastguard Worker   const char *contents;
861*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_serialize_format_t format;
862*2d1272b8SAndroid Build Coastguard Worker   unsigned int num_items;
863*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t success;
864*2d1272b8SAndroid Build Coastguard Worker } serialization_test_t;
865*2d1272b8SAndroid Build Coastguard Worker 
866*2d1272b8SAndroid Build Coastguard Worker static const serialization_test_t serialization_tests[] = {
867*2d1272b8SAndroid Build Coastguard Worker   { "<U+0640=0|U+0635=1>", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 2, 1 },
868*2d1272b8SAndroid Build Coastguard Worker   { "[{\"u\":1600,\"cl\":0},{\"u\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 2, 1 },
869*2d1272b8SAndroid Build Coastguard Worker 
870*2d1272b8SAndroid Build Coastguard Worker   /* Mixed glyphs/Unicodes -> parse fail */
871*2d1272b8SAndroid Build Coastguard Worker   { "[{\"u\":1600,\"cl\":0},{\"g\":1589,\"cl\":1}]", HB_BUFFER_SERIALIZE_FORMAT_JSON, 0, 0 },
872*2d1272b8SAndroid Build Coastguard Worker   { "<U+0640=0|uni0635=1>", HB_BUFFER_SERIALIZE_FORMAT_TEXT, 0, 0 },
873*2d1272b8SAndroid Build Coastguard Worker };
874*2d1272b8SAndroid Build Coastguard Worker 
875*2d1272b8SAndroid Build Coastguard Worker static void
test_buffer_serialize_deserialize(void)876*2d1272b8SAndroid Build Coastguard Worker test_buffer_serialize_deserialize (void)
877*2d1272b8SAndroid Build Coastguard Worker {
878*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *b;
879*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
880*2d1272b8SAndroid Build Coastguard Worker 
881*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < G_N_ELEMENTS (serialization_tests); i++)
882*2d1272b8SAndroid Build Coastguard Worker   {
883*2d1272b8SAndroid Build Coastguard Worker     unsigned int consumed;
884*2d1272b8SAndroid Build Coastguard Worker     char round_trip[1024];
885*2d1272b8SAndroid Build Coastguard Worker 
886*2d1272b8SAndroid Build Coastguard Worker     b = hb_buffer_create ();
887*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_set_replacement_codepoint (b, (hb_codepoint_t) -1);
888*2d1272b8SAndroid Build Coastguard Worker 
889*2d1272b8SAndroid Build Coastguard Worker     const serialization_test_t *test = &serialization_tests[i];
890*2d1272b8SAndroid Build Coastguard Worker     g_test_message ("serialize test #%d", i);
891*2d1272b8SAndroid Build Coastguard Worker 
892*2d1272b8SAndroid Build Coastguard Worker     (void) hb_buffer_deserialize_unicode (b, test->contents, -1, NULL, test->format);
893*2d1272b8SAndroid Build Coastguard Worker 
894*2d1272b8SAndroid Build Coastguard Worker     // Expected parse failure, got one, don't round-trip
895*2d1272b8SAndroid Build Coastguard Worker     if (test->success != 0)
896*2d1272b8SAndroid Build Coastguard Worker     {
897*2d1272b8SAndroid Build Coastguard Worker       unsigned int num_glyphs = hb_buffer_get_length (b);
898*2d1272b8SAndroid Build Coastguard Worker       g_assert_cmpint (num_glyphs, ==, test->num_items);
899*2d1272b8SAndroid Build Coastguard Worker 
900*2d1272b8SAndroid Build Coastguard Worker       hb_buffer_serialize_unicode (b, 0, num_glyphs, round_trip,
901*2d1272b8SAndroid Build Coastguard Worker 				   sizeof(round_trip), &consumed, test->format,
902*2d1272b8SAndroid Build Coastguard Worker 				   HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
903*2d1272b8SAndroid Build Coastguard Worker       g_assert_cmpstr (round_trip, ==, test->contents);
904*2d1272b8SAndroid Build Coastguard Worker     }
905*2d1272b8SAndroid Build Coastguard Worker 
906*2d1272b8SAndroid Build Coastguard Worker     hb_buffer_destroy (b);
907*2d1272b8SAndroid Build Coastguard Worker 
908*2d1272b8SAndroid Build Coastguard Worker   }
909*2d1272b8SAndroid Build Coastguard Worker 
910*2d1272b8SAndroid Build Coastguard Worker   char test[1024];
911*2d1272b8SAndroid Build Coastguard Worker   unsigned int consumed;
912*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_t *indeterminate = hb_buffer_get_empty ();
913*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_serialize (indeterminate, 0, (unsigned) -1,
914*2d1272b8SAndroid Build Coastguard Worker 		       test, sizeof(test), &consumed, NULL,
915*2d1272b8SAndroid Build Coastguard Worker 		       HB_BUFFER_SERIALIZE_FORMAT_JSON,
916*2d1272b8SAndroid Build Coastguard Worker 		       HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
917*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpstr ( test, ==, "[]");
918*2d1272b8SAndroid Build Coastguard Worker 
919*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_serialize (indeterminate, 0, (unsigned) - 1,
920*2d1272b8SAndroid Build Coastguard Worker 		       test, sizeof(test), &consumed, NULL,
921*2d1272b8SAndroid Build Coastguard Worker 		       HB_BUFFER_SERIALIZE_FORMAT_TEXT,
922*2d1272b8SAndroid Build Coastguard Worker 		       HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
923*2d1272b8SAndroid Build Coastguard Worker   g_assert_cmpstr ( test, ==, "!!");
924*2d1272b8SAndroid Build Coastguard Worker 
925*2d1272b8SAndroid Build Coastguard Worker }
926*2d1272b8SAndroid Build Coastguard Worker 
927*2d1272b8SAndroid Build Coastguard Worker int
main(int argc,char ** argv)928*2d1272b8SAndroid Build Coastguard Worker main (int argc, char **argv)
929*2d1272b8SAndroid Build Coastguard Worker {
930*2d1272b8SAndroid Build Coastguard Worker   unsigned int i;
931*2d1272b8SAndroid Build Coastguard Worker 
932*2d1272b8SAndroid Build Coastguard Worker   hb_test_init (&argc, &argv);
933*2d1272b8SAndroid Build Coastguard Worker 
934*2d1272b8SAndroid Build Coastguard Worker   for (i = 0; i < BUFFER_NUM_TYPES; i++)
935*2d1272b8SAndroid Build Coastguard Worker   {
936*2d1272b8SAndroid Build Coastguard Worker     const void *buffer_type = GINT_TO_POINTER (i);
937*2d1272b8SAndroid Build Coastguard Worker     const char *buffer_name = buffer_names[i];
938*2d1272b8SAndroid Build Coastguard Worker 
939*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties);
940*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents);
941*2d1272b8SAndroid Build Coastguard Worker     hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions);
942*2d1272b8SAndroid Build Coastguard Worker   }
943*2d1272b8SAndroid Build Coastguard Worker 
944*2d1272b8SAndroid Build Coastguard Worker   hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation);
945*2d1272b8SAndroid Build Coastguard Worker 
946*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_utf8_conversion);
947*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_utf8_validity);
948*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_utf16_conversion);
949*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_utf32_conversion);
950*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_empty);
951*2d1272b8SAndroid Build Coastguard Worker   hb_test_add (test_buffer_serialize_deserialize);
952*2d1272b8SAndroid Build Coastguard Worker 
953*2d1272b8SAndroid Build Coastguard Worker   return hb_test_run();
954*2d1272b8SAndroid Build Coastguard Worker }
955