2 * Copyright (C) 2015, 2017 Dov Grobgeld
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library, in a file named COPYING; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA
30 #define LINE_SIZE 2048 /* Size of biggest line in test file */
32 /* Glib like arrays */
45 #define ARRAY_CHUNK_SIZE 32
46 int_array_t *new_int_array()
48 int_array_t *arr = (int_array_t*)malloc(sizeof(int_array_t));
50 arr->capacity = ARRAY_CHUNK_SIZE;
51 arr->data = (int*)malloc(arr->capacity * sizeof(int));
56 void int_array_add(int_array_t *arr, int val)
58 if (arr->len == arr->capacity)
60 arr->capacity += ARRAY_CHUNK_SIZE;
61 arr->data = (int*)realloc(arr->data, arr->capacity*sizeof(int));
63 arr->data[arr->len++] = val;
66 int *int_array_free(int_array_t *arr, int free_data)
68 int *data = arr->data;
77 char_array_t *new_char_array()
79 char_array_t *arr = (char_array_t*)malloc(sizeof(char_array_t));
81 arr->capacity = ARRAY_CHUNK_SIZE;
82 arr->data = (char*)malloc(arr->capacity);
87 void char_array_add(char_array_t *arr, char val)
89 if (arr->len == arr->capacity)
91 arr->capacity += ARRAY_CHUNK_SIZE;
92 arr->data = (char*)realloc(arr->data, arr->capacity * sizeof(char));
94 arr->data[arr->len++] = val;
97 char *char_array_free(char_array_t *arr, int free_data)
99 char *data = arr->data;
108 static void die(const char *fmt, ...)
113 vfprintf(stderr, fmt, ap);
118 FriBidiChar parse_uni_char(const char *start, int len)
120 return strtoul(start, NULL, 16);
124 void parse_test_line (char *line,
126 FriBidiChar **code_points, /* Field 0 */
127 int *code_points_len,
128 int *paragraph_dir, /* Field 1 */
129 int *resolved_paragraph_embedding_level, /* Field 2 */
130 FriBidiLevel **resolved_levels, /* Field 3 */
131 int **visual_ordering, /* Field 4 */
132 int *visual_ordering_len
135 int_array_t *code_points_array, *visual_ordering_array;
136 char_array_t *levels_array;
140 code_points_array = new_int_array ();
141 levels_array = new_char_array ();
143 /* Field 0. Code points */
147 while (isspace (*line))
150 while (isxdigit (*end))
155 c = parse_uni_char (line, end - line);
156 int_array_add(code_points_array, c);
161 *code_points_len = code_points_array->len;
162 *code_points = (FriBidiChar *) int_array_free (code_points_array, FALSE);
167 die("Oops! Didn't find expected ;\n");
169 /* Field 1. Paragraph direction */
171 while (isdigit (*end))
173 *paragraph_dir = atoi(line);
179 die("Oops! Didn't find expected ;\n");
181 /* Field 2. resolved paragraph_dir */
183 while (isdigit (*end))
185 *resolved_paragraph_embedding_level = atoi(line);
191 die("Oops! Didn't find expected ; at line %d\n", line_no);
199 level = strtol (line, &end, 10);
200 if (errno != EINVAL && line != end)
202 char_array_add (levels_array, level);
207 while (isspace (*line))
212 level = (FriBidiLevel) -1;
213 char_array_add (levels_array, level);
221 die("Oops! I shouldn't be here!\n");
224 if (levels_array->len != *code_points_len)
225 die("Oops! Different lengths for levels and codepoints at line %d!\n", line_no);
227 *resolved_levels = (FriBidiLevel*)char_array_free (levels_array, FALSE);
232 die("Oops! Didn't find expected ; at line %d\n", line_no);
234 /* Field 4 - resulting visual ordering */
235 visual_ordering_array = new_int_array ();
236 for(; errno = 0, level = strtol (line, &end, 10), line != end && errno != EINVAL; line = end) {
237 int_array_add (visual_ordering_array, level);
240 *visual_ordering_len = visual_ordering_array->len;
241 *visual_ordering = (int*)int_array_free (visual_ordering_array, FALSE);
245 main (int argc, char **argv)
249 const char *filename;
250 char line[LINE_SIZE];
253 FriBidiChar *code_points = NULL;
254 int code_points_len = 0;
255 int expected_ltor_len = 0;
256 int base_dir_mode = 0, paragraph_dir;
257 FriBidiLevel *expected_levels = NULL;
258 int *expected_ltor = NULL;
259 int resolved_paragraph_embedding_level;
260 FriBidiLevel *levels = NULL;
261 FriBidiCharType *types = NULL;
262 FriBidiBracketType *bracket_types = NULL;
263 FriBidiStrIndex *ltor = NULL;
269 fprintf (stderr, "usage: %s [--debug] test-file-name\n", argv[0]);
274 while(next_arg < argc && argv[next_arg][0]=='-')
276 const char *arg = argv[next_arg++];
277 if (strcmp(arg, "--debug")==0)
282 die("Unknown option %s!\n", arg);
285 filename = argv[next_arg++];
287 channel = fopen(filename, "r");
289 die ("Failed opening %s\n", filename);
291 while (!feof(channel)) {
292 fgets(line, LINE_SIZE, channel);
293 int len = strlen(line);
294 if (len == LINE_SIZE-1)
295 die("LINE_SIZE=%d too small at line %d!\n", LINE_SIZE, line_no);
299 if (line[0] == '#' || line[0] == '\n')
303 free (expected_levels);
304 free (expected_ltor);
305 free (bracket_types);
310 parse_test_line (line,
312 &code_points, /* Field 0 */
314 ¶graph_dir, /* Field 1 */
315 &resolved_paragraph_embedding_level, /* Field 2 */
316 &expected_levels, /* Field 3 */
317 &expected_ltor, /* Field 4 */
322 bracket_types = malloc ( sizeof(FriBidiBracketType) * code_points_len);
323 types = malloc ( sizeof(FriBidiCharType) * code_points_len);
324 levels = malloc (sizeof (FriBidiLevel) * code_points_len);
325 ltor = malloc (sizeof (FriBidiStrIndex) * code_points_len);
329 FriBidiParType base_dir;
332 int types_len = code_points_len;
333 int levels_len = types_len;
334 FriBidiBracketType NoBracket = FRIBIDI_NO_BRACKET;
336 for (i=0; i<code_points_len; i++)
338 types[i] = fribidi_get_bidi_type(code_points[i]);
340 /* Note the optimization that a bracket is always
342 if (types[i] == FRIBIDI_TYPE_ON)
343 bracket_types[i] = fribidi_get_bracket(code_points[i]);
345 bracket_types[i] = NoBracket;
348 if ((paragraph_dir & (1<<base_dir_mode)) == 0)
351 switch (paragraph_dir)
353 case 0: base_dir = FRIBIDI_PAR_LTR; break;
354 case 1: base_dir = FRIBIDI_PAR_RTL; break;
355 case 2: base_dir = FRIBIDI_PAR_ON; break;
358 if (fribidi_get_par_embedding_levels_ex (types,
365 for (i = 0; i < types_len; i++)
368 if (fribidi_reorder_line (0 /*FRIBIDI_FLAG_REORDER_NSM*/,
377 for (i = 0; i < types_len; i++)
378 if (!FRIBIDI_IS_EXPLICIT_OR_BN (types[ltor[i]]))
385 for (i = 0; i < code_points_len; i++)
386 if (levels[i] != expected_levels[i] &&
387 expected_levels[i] != (FriBidiLevel) -1) {
392 if (ltor_len != expected_ltor_len)
395 for (i = 0; i < ltor_len; i++)
396 if (ltor[i] != expected_ltor[i]) {
405 fprintf (stderr, "failure on line %d\n", line_no);
406 fprintf (stderr, "input is: %s\n", line);
407 fprintf (stderr, "base dir: %s\n", paragraph_dir==0 ? "LTR"
408 : paragraph_dir==1 ? "RTL" : "AUTO");
410 fprintf (stderr, "expected levels:");
411 for (i = 0; i < code_points_len; i++)
412 if (expected_levels[i] == (FriBidiLevel) -1)
413 fprintf (stderr, " x");
415 fprintf (stderr, " %d", expected_levels[i]);
416 fprintf (stderr, "\n");
417 fprintf (stderr, "returned levels:");
418 for (i = 0; i < levels_len; i++)
419 fprintf (stderr, " %d", levels[i]);
420 fprintf (stderr, "\n");
422 fprintf (stderr, "expected order:");
423 for (i = 0; i < expected_ltor_len; i++)
424 fprintf (stderr, " %d", expected_ltor[i]);
425 fprintf (stderr, "\n");
426 fprintf (stderr, "returned order:");
427 for (i = 0; i < ltor_len; i++)
428 fprintf (stderr, " %d", ltor[i]);
429 fprintf (stderr, "\n");
433 FriBidiParType base_dir;
435 fribidi_set_debug (1);
437 switch (base_dir_mode)
439 case 0: base_dir = FRIBIDI_PAR_ON; break;
440 case 1: base_dir = FRIBIDI_PAR_LTR; break;
441 case 2: base_dir = FRIBIDI_PAR_RTL; break;
444 if (fribidi_get_par_embedding_levels_ex (types,
451 fribidi_set_debug (0);
454 fprintf (stderr, "\n");
460 fprintf (stderr, "%d errors\n", numerrs);
462 printf("No errors found! :-)\n");
465 free (expected_levels);
466 free (expected_ltor);
467 free (bracket_types);