2 *******************************************************************************
4 * © 2016 and later: Unicode, Inc. and others.
5 * License & terms of use: http://www.unicode.org/copyright.html#License
7 *******************************************************************************
8 *******************************************************************************
10 * Copyright (C) 1999-2013, International Business Machines
11 * Corporation and others. All Rights Reserved.
13 *******************************************************************************
16 #include "unicode/utypes.h"
17 #include "unicode/uclean.h"
18 #include "unicode/uchar.h"
19 #include "unicode/unistr.h"
20 #include "unicode/uscript.h"
21 #include "unicode/putil.h"
22 #include "unicode/ctest.h"
24 #include "layout/LETypes.h"
25 #include "layout/LEScripts.h"
30 #include "xmlreader.h"
32 #include "xmlparser.h"
40 #define CH_COMMA 0x002C
42 static le_uint32
*getHexArray(const UnicodeString
&numbers
, int32_t &arraySize
)
47 while((offset
= numbers
.indexOf(CH_COMMA
, offset
+ 1)) >= 0) {
51 le_uint32
*array
= NEW_ARRAY(le_uint32
, arraySize
);
54 le_int32 start
= 0, end
= 0;
57 // trim leading whitespace
58 while(u_isUWhiteSpace(numbers
[start
])) {
62 while((end
= numbers
.indexOf(CH_COMMA
, start
)) >= 0) {
63 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
67 sscanf(number
, "%x", &array
[count
++]);
69 // trim whitespace following the comma
70 while(u_isUWhiteSpace(numbers
[start
])) {
75 // trim trailing whitespace
76 end
= numbers
.length();
77 while(u_isUWhiteSpace(numbers
[end
- 1])) {
81 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
83 sscanf(number
, "%x", &array
[count
]);
88 static float *getFloatArray(const UnicodeString
&numbers
, int32_t &arraySize
)
93 while((offset
= numbers
.indexOf(CH_COMMA
, offset
+ 1)) >= 0) {
97 float *array
= NEW_ARRAY(float, arraySize
);
100 le_int32 start
= 0, end
= 0;
103 // trim leading whitespace
104 while(u_isUWhiteSpace(numbers
[start
])) {
108 while((end
= numbers
.indexOf(CH_COMMA
, start
)) >= 0) {
109 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
113 sscanf(number
, "%f", &array
[count
++]);
115 // trim whiteapce following the comma
116 while(u_isUWhiteSpace(numbers
[start
])) {
121 while(u_isUWhiteSpace(numbers
[start
])) {
125 // trim trailing whitespace
126 end
= numbers
.length();
127 while(u_isUWhiteSpace(numbers
[end
- 1])) {
131 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
133 sscanf(number
, "%f", &array
[count
]);
139 void readTestFile(const char *testFilePath
, TestCaseCallback callback
)
141 #if !UCONFIG_NO_REGULAR_EXPRESSIONS
142 UErrorCode status
= U_ZERO_ERROR
;
143 UXMLParser
*parser
= UXMLParser::createParser(status
);
144 UXMLElement
*root
= parser
->parseFile(testFilePath
, status
);
147 log_err("Could not open the test data file: %s\n", testFilePath
);
152 UnicodeString test_case
= UNICODE_STRING_SIMPLE("test-case");
153 UnicodeString test_text
= UNICODE_STRING_SIMPLE("test-text");
154 UnicodeString test_font
= UNICODE_STRING_SIMPLE("test-font");
155 UnicodeString result_glyphs
= UNICODE_STRING_SIMPLE("result-glyphs");
156 UnicodeString result_indices
= UNICODE_STRING_SIMPLE("result-indices");
157 UnicodeString result_positions
= UNICODE_STRING_SIMPLE("result-positions");
159 // test-case attributes
160 UnicodeString id_attr
= UNICODE_STRING_SIMPLE("id");
161 UnicodeString script_attr
= UNICODE_STRING_SIMPLE("script");
162 UnicodeString lang_attr
= UNICODE_STRING_SIMPLE("lang");
164 // test-font attributes
165 UnicodeString name_attr
= UNICODE_STRING_SIMPLE("name");
166 UnicodeString ver_attr
= UNICODE_STRING_SIMPLE("version");
167 UnicodeString cksum_attr
= UNICODE_STRING_SIMPLE("checksum");
169 const UXMLElement
*testCase
;
172 while((testCase
= root
->nextChildElement(tc
)) != NULL
) {
173 if (testCase
->getTagName().compare(test_case
) == 0) {
174 char *id
= getCString(testCase
->getAttribute(id_attr
));
175 char *script
= getCString(testCase
->getAttribute(script_attr
));
176 char *lang
= getCString(testCase
->getAttribute(lang_attr
));
177 char *fontName
= NULL
;
178 char *fontVer
= NULL
;
179 char *fontCksum
= NULL
;
180 const UXMLElement
*element
;
182 int32_t charCount
= 0;
183 int32_t typoFlags
= 3; // kerning + ligatures...
184 UScriptCode scriptCode
;
185 le_int32 languageCode
= -1;
186 UnicodeString text
, glyphs
, indices
, positions
;
187 int32_t glyphCount
= 0, indexCount
= 0, positionCount
= 0;
188 TestResult expected
= {0, NULL
, NULL
, NULL
};
190 uscript_getCode(script
, &scriptCode
, 1, &status
);
191 if (LE_FAILURE(status
)) {
192 log_err("invalid script name: %s.\n", script
);
197 languageCode
= getLanguageCode(lang
);
199 if (languageCode
< 0) {
200 log_err("invalid language name: %s.\n", lang
);
205 while((element
= testCase
->nextChildElement(ec
)) != NULL
) {
206 UnicodeString tag
= element
->getTagName();
208 // TODO: make sure that each element is only used once.
209 if (tag
.compare(test_font
) == 0) {
210 fontName
= getCString(element
->getAttribute(name_attr
));
211 fontVer
= getCString(element
->getAttribute(ver_attr
));
212 fontCksum
= getCString(element
->getAttribute(cksum_attr
));
214 } else if (tag
.compare(test_text
) == 0) {
215 text
= element
->getText(TRUE
);
216 charCount
= text
.length();
217 } else if (tag
.compare(result_glyphs
) == 0) {
218 glyphs
= element
->getText(TRUE
);
219 } else if (tag
.compare(result_indices
) == 0) {
220 indices
= element
->getText(TRUE
);
221 } else if (tag
.compare(result_positions
) == 0) {
222 positions
= element
->getText(TRUE
);
225 char *cTag
= getCString(&tag
);
227 log_info("Test %s: unknown element with tag \"%s\"\n", id
, cTag
);
232 expected
.glyphs
= (LEGlyphID
*) getHexArray(glyphs
, glyphCount
);
233 expected
.indices
= (le_int32
*) getHexArray(indices
, indexCount
);
234 expected
.positions
= getFloatArray(positions
, positionCount
);
236 expected
.glyphCount
= glyphCount
;
238 if (glyphCount
< charCount
|| indexCount
!= glyphCount
|| positionCount
< glyphCount
* 2 + 2) {
239 log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
240 id
, charCount
, glyphCount
, indexCount
, positionCount
);
244 (*callback
)(id
, fontName
, fontVer
, fontCksum
, scriptCode
, languageCode
, text
.getBuffer(), charCount
, &expected
);
247 DELETE_ARRAY(expected
.positions
);
248 DELETE_ARRAY(expected
.indices
);
249 DELETE_ARRAY(expected
.glyphs
);
252 freeCString(fontCksum
);
253 freeCString(fontVer
);
254 freeCString(fontName
);