• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4  *******************************************************************************
5  *
6  *   Copyright (C) 1999-2014, International Business Machines
7  *   Corporation and others.  All Rights Reserved.
8  *
9  *******************************************************************************
10  */
11 
12 #include "unicode/utypes.h"
13 #include "unicode/uclean.h"
14 #include "unicode/uchar.h"
15 #include "unicode/unistr.h"
16 #include "unicode/uscript.h"
17 #include "unicode/putil.h"
18 #include "unicode/ctest.h"
19 
20 #include "layout/LETypes.h"
21 #include "layout/LEScripts.h"
22 
23 #include "letsutil.h"
24 #include "letest.h"
25 
26 #include "xmlreader.h"
27 
28 #include "xmlparser.h"
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 
34 //U_NAMESPACE_USE
35 
36 #define CH_COMMA 0x002C
37 
getHexArray(const UnicodeString & numbers,int32_t & arraySize)38 static le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize)
39 {
40     int32_t offset = -1;
41 
42     arraySize = 1;
43     while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
44         arraySize += 1;
45     }
46 
47     le_uint32 *array = NEW_ARRAY(le_uint32, arraySize);
48     char number[16];
49     le_int32 count = 0;
50     le_int32 start = 0, end = 0;
51     le_int32 len = 0;
52 
53     // trim leading whitespace
54     while(u_isUWhiteSpace(numbers[start])) {
55         start += 1;
56     }
57 
58     while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
59         len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
60         number[len] = '\0';
61         start = end + 1;
62 
63         sscanf(number, "%x", &array[count++]);
64 
65         // trim whitespace following the comma
66         while(u_isUWhiteSpace(numbers[start])) {
67             start += 1;
68         }
69     }
70 
71     // trim trailing whitespace
72     end = numbers.length();
73     while(u_isUWhiteSpace(numbers[end - 1])) {
74         end -= 1;
75     }
76 
77     len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
78     number[len] = '\0';
79     sscanf(number, "%x", &array[count]);
80 
81     return array;
82 }
83 
getFloatArray(const UnicodeString & numbers,int32_t & arraySize)84 static float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize)
85 {
86     int32_t offset = -1;
87 
88     arraySize = 1;
89     while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
90         arraySize += 1;
91     }
92 
93     float *array = NEW_ARRAY(float, arraySize);
94     char number[32];
95     le_int32 count = 0;
96     le_int32 start = 0, end = 0;
97     le_int32 len = 0;
98 
99     // trim leading whitespace
100     while(u_isUWhiteSpace(numbers[start])) {
101         start += 1;
102     }
103 
104     while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
105         len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
106         number[len] = '\0';
107         start = end + 1;
108 
109         sscanf(number, "%f", &array[count++]);
110 
111         // trim whiteapce following the comma
112         while(u_isUWhiteSpace(numbers[start])) {
113             start += 1;
114         }
115     }
116 
117     while(u_isUWhiteSpace(numbers[start])) {
118         start += 1;
119     }
120 
121     // trim trailing whitespace
122     end = numbers.length();
123     while(u_isUWhiteSpace(numbers[end - 1])) {
124         end -= 1;
125     }
126 
127     len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
128     number[len] = '\0';
129     sscanf(number, "%f", &array[count]);
130 
131     return array;
132 }
133 
134 U_CDECL_BEGIN
readTestFile(const char * testFilePath,TestCaseCallback callback)135 void readTestFile(const char *testFilePath, TestCaseCallback callback)
136 {
137 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
138     UErrorCode status = U_ZERO_ERROR;
139     UXMLParser  *parser = UXMLParser::createParser(status);
140     UXMLElement *root   = parser->parseFile(testFilePath, status);
141 
142     if (root == NULL) {
143         log_err("Could not open the test data file: %s\n", testFilePath);
144         delete parser;
145         return;
146     }
147 
148     UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
149     UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
150     UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
151     UnicodeString result_glyphs    = UNICODE_STRING_SIMPLE("result-glyphs");
152     UnicodeString result_indices   = UNICODE_STRING_SIMPLE("result-indices");
153     UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions");
154 
155     // test-case attributes
156     UnicodeString id_attr     = UNICODE_STRING_SIMPLE("id");
157     UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
158     UnicodeString lang_attr   = UNICODE_STRING_SIMPLE("lang");
159 
160     // test-font attributes
161     UnicodeString name_attr   = UNICODE_STRING_SIMPLE("name");
162     UnicodeString ver_attr    = UNICODE_STRING_SIMPLE("version");
163     UnicodeString cksum_attr  = UNICODE_STRING_SIMPLE("checksum");
164 
165     const UXMLElement *testCase;
166     int32_t tc = 0;
167 
168     while((testCase = root->nextChildElement(tc)) != NULL) {
169         if (testCase->getTagName().compare(test_case) == 0) {
170             char *id = getCString(testCase->getAttribute(id_attr));
171             char *script    = getCString(testCase->getAttribute(script_attr));
172             char *lang      = getCString(testCase->getAttribute(lang_attr));
173             char *fontName  = NULL;
174 			char *fontVer   = NULL;
175 			char *fontCksum = NULL;
176             const UXMLElement *element;
177             int32_t ec = 0;
178             int32_t charCount = 0;
179             // int32_t typoFlags = 3; // kerning + ligatures...
180             UScriptCode scriptCode;
181             le_int32 languageCode = -1;
182             UnicodeString text, glyphs, indices, positions;
183             int32_t glyphCount = 0, indexCount = 0, positionCount = 0;
184             TestResult expected = {0, NULL, NULL, NULL};
185 
186             uscript_getCode(script, &scriptCode, 1, &status);
187             if (LE_FAILURE(status)) {
188                 log_err("invalid script name: %s.\n", script);
189                 goto free_c_strings;
190             }
191 
192             if (lang != NULL) {
193                 languageCode = getLanguageCode(lang);
194 
195                 if (languageCode < 0) {
196                     log_err("invalid language name: %s.\n", lang);
197                     goto free_c_strings;
198                 }
199             }
200 
201             while((element = testCase->nextChildElement(ec)) != NULL) {
202                 UnicodeString tag = element->getTagName();
203 
204                 // TODO: make sure that each element is only used once.
205                 if (tag.compare(test_font) == 0) {
206                     fontName  = getCString(element->getAttribute(name_attr));
207                     fontVer   = getCString(element->getAttribute(ver_attr));
208                     fontCksum = getCString(element->getAttribute(cksum_attr));
209 
210                 } else if (tag.compare(test_text) == 0) {
211                     text = element->getText(TRUE);
212                     charCount = text.length();
213                 } else if (tag.compare(result_glyphs) == 0) {
214                     glyphs = element->getText(TRUE);
215                 } else if (tag.compare(result_indices) == 0) {
216                     indices = element->getText(TRUE);
217                 } else if (tag.compare(result_positions) == 0) {
218                     positions = element->getText(TRUE);
219                 } else {
220                     // an unknown tag...
221                     char *cTag = getCString(&tag);
222 
223                     log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag);
224                     freeCString(cTag);
225                 }
226             }
227 
228             expected.glyphs    = (LEGlyphID *) getHexArray(glyphs, glyphCount);
229             expected.indices   = (le_int32 *)  getHexArray(indices, indexCount);
230             expected.positions = getFloatArray(positions, positionCount);
231 
232             expected.glyphCount = glyphCount;
233 
234             if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
235                 log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
236                     id, charCount, glyphCount, indexCount, positionCount);
237                 goto free_expected;
238             };
239 
240 			(*callback)(id, fontName, fontVer, fontCksum, scriptCode, languageCode, text.getBuffer(), charCount, &expected);
241 
242 free_expected:
243             DELETE_ARRAY(expected.positions);
244             DELETE_ARRAY(expected.indices);
245             DELETE_ARRAY(expected.glyphs);
246 
247 free_c_strings:
248 			freeCString(fontCksum);
249 			freeCString(fontVer);
250 			freeCString(fontName);
251             freeCString(lang);
252             freeCString(script);
253             freeCString(id);
254         }
255     }
256 
257     delete root;
258     delete parser;
259 #endif
260 }
261 U_CDECL_END
262