1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 1999-2014, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
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"
20 #include "layout/LETypes.h"
21 #include "layout/LEScripts.h"
26 #include "xmlreader.h"
28 #include "xmlparser.h"
36 #define CH_COMMA 0x002C
38 static le_uint32
*getHexArray(const UnicodeString
&numbers
, int32_t &arraySize
)
43 while((offset
= numbers
.indexOf(CH_COMMA
, offset
+ 1)) >= 0) {
47 le_uint32
*array
= NEW_ARRAY(le_uint32
, arraySize
);
50 le_int32 start
= 0, end
= 0;
53 // trim leading whitespace
54 while(u_isUWhiteSpace(numbers
[start
])) {
58 while((end
= numbers
.indexOf(CH_COMMA
, start
)) >= 0) {
59 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
63 sscanf(number
, "%x", &array
[count
++]);
65 // trim whitespace following the comma
66 while(u_isUWhiteSpace(numbers
[start
])) {
71 // trim trailing whitespace
72 end
= numbers
.length();
73 while(u_isUWhiteSpace(numbers
[end
- 1])) {
77 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
79 sscanf(number
, "%x", &array
[count
]);
84 static float *getFloatArray(const UnicodeString
&numbers
, int32_t &arraySize
)
89 while((offset
= numbers
.indexOf(CH_COMMA
, offset
+ 1)) >= 0) {
93 float *array
= NEW_ARRAY(float, arraySize
);
96 le_int32 start
= 0, end
= 0;
99 // trim leading whitespace
100 while(u_isUWhiteSpace(numbers
[start
])) {
104 while((end
= numbers
.indexOf(CH_COMMA
, start
)) >= 0) {
105 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
109 sscanf(number
, "%f", &array
[count
++]);
111 // trim whiteapce following the comma
112 while(u_isUWhiteSpace(numbers
[start
])) {
117 while(u_isUWhiteSpace(numbers
[start
])) {
121 // trim trailing whitespace
122 end
= numbers
.length();
123 while(u_isUWhiteSpace(numbers
[end
- 1])) {
127 len
= numbers
.extract(start
, end
- start
, number
, ARRAY_SIZE(number
), US_INV
);
129 sscanf(number
, "%f", &array
[count
]);
135 void readTestFile(const char *testFilePath
, TestCaseCallback callback
)
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
);
143 log_err("Could not open the test data file: %s\n", testFilePath
);
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");
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");
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");
165 const UXMLElement
*testCase
;
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
;
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
};
186 uscript_getCode(script
, &scriptCode
, 1, &status
);
187 if (LE_FAILURE(status
)) {
188 log_err("invalid script name: %s.\n", script
);
193 languageCode
= getLanguageCode(lang
);
195 if (languageCode
< 0) {
196 log_err("invalid language name: %s.\n", lang
);
201 while((element
= testCase
->nextChildElement(ec
)) != NULL
) {
202 UnicodeString tag
= element
->getTagName();
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
));
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
);
221 char *cTag
= getCString(&tag
);
223 log_info("Test %s: unknown element with tag \"%s\"\n", id
, cTag
);
228 expected
.glyphs
= (LEGlyphID
*) getHexArray(glyphs
, glyphCount
);
229 expected
.indices
= (le_int32
*) getHexArray(indices
, indexCount
);
230 expected
.positions
= getFloatArray(positions
, positionCount
);
232 expected
.glyphCount
= glyphCount
;
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
);
240 (*callback
)(id
, fontName
, fontVer
, fontCksum
, scriptCode
, languageCode
, text
.getBuffer(), charCount
, &expected
);
243 DELETE_ARRAY(expected
.positions
);
244 DELETE_ARRAY(expected
.indices
);
245 DELETE_ARRAY(expected
.glyphs
);
248 freeCString(fontCksum
);
249 freeCString(fontVer
);
250 freeCString(fontName
);