Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: Source/platform/text/BidiTestHarness.h

Issue 39523002: Add harness for running Unicode.org Bidi tests. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: update comments about reference implementations Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2013 Google, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
leviw_travelin_and_unemployed 2013/10/28 21:33:11 Nit: We don't need to use the "Provided by Apple"
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef BidiTestHarness_h
27 #define BidiTestHarness_h
28
29 #include <fstream>
30 #include <iostream>
31 #include <map>
32 #include <sstream>
33 #include <string>
34
35 // Unicode.org provides a reference implmentation, including parser:
36 // http://www.unicode.org/Public/PROGRAMS/BidiReferenceC/6.3.0/source/brtest.c
37 // I failed to notice that until after I had written this one.
38 // This implementation was written in std:: c++ with the intention
39 // of being upstreamed to unicode.org.
40 // FIXME: We should probably replace this implementation with the one from unico de.org.
41
42 // Other C/C++ implementations of this parser:
43 // https://github.com/googlei18n/fribidi-vs-unicode/blob/master/test.c
44 // http://source.icu-project.org/repos/icu/icu/trunk/source/test/intltest/bidico nf.cpp
45 // Both of those are too tied to their respective projects to be use to Blink.
46
47 // There are non-C implmentations to parse BidiTest.txt as well, including:
48 // https://github.com/twitter/twitter-cldr-rb/blob/master/spec/bidi/bidi_spec.rb
49
50 namespace bidi_test {
51
52 enum ParagraphDirection {
53 DirectionAutoLTR = 1,
54 DirectionLTR = 2,
55 DirectionRTL = 4,
56 };
57 const int kMaxParagraphDirection = DirectionAutoLTR | DirectionLTR | DirectionRT L;
58
59 // For error printing:
60 std::string nameFromParagraphDirection(ParagraphDirection paragraphDirection)
61 {
62 switch (paragraphDirection) {
63 case bidi_test::DirectionAutoLTR:
64 return "Auto-LTR";
65 case bidi_test::DirectionLTR:
66 return "LTR";
67 case bidi_test::DirectionRTL:
68 return "RTL";
69 }
70 }
71
72 template<class Runner>
73 class Harness {
74 public:
75 Harness(Runner& runner)
76 : m_runner(runner)
77 {
78 }
79 void parse(std::istream& bidiTestFile);
80
81 private:
82 Runner& m_runner;
83 };
84
85 // This trim() example comes from:
86 // http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstrin g
87 // We could use boost::trim, but no other part of Blink uses boost yet.
88
89 inline std::string& ltrim(std::string& s)
90 {
91 s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<i nt, int>(std::isspace))));
leviw_travelin_and_unemployed 2013/10/28 21:33:11 jyasskin for this and the other std C++ stuff.
92 return s;
93 }
94
95 inline std::string& rtrim(std::string& s)
96 {
97 s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>( std::isspace))).base(), s.end());
98 return s;
99 }
100
101 inline std::string& trim(std::string& s)
102 {
103 return ltrim(rtrim(s));
104 }
105
106 static bool parseStringList(std::string str, std::vector<std::string>& strings)
107 {
108 std::string separators(" \t");
109 strings.clear();
110 size_t lastPos = str.find_first_not_of(separators); // skip leading spaces
111 size_t pos = str.find_first_of(separators, lastPos); // find next space
112
113 while (std::string::npos != pos || std::string::npos != lastPos) {
114 strings.push_back(str.substr(lastPos, pos - lastPos));
115 lastPos = str.find_first_not_of(separators, pos);
116 pos = str.find_first_of(separators, lastPos);
117 }
118 return true;
119 }
120
121 static bool parseIntList(std::string str, std::vector<int>& ints)
122 {
123 ints.clear();
124 std::vector<std::string> strings;
125 if (!parseStringList(str, strings))
126 return false;
127 for (int x = 0; x < strings.size(); x++) {
128 int i;
129 std::istringstream(strings[x]) >> i;
130 ints.push_back(i);
131 }
132 return true;
133 }
134
135 static bool parseLevelRule(std::string line, std::vector<int>& levels)
136 {
137 levels.clear();
138 std::vector<std::string> strings;
139 if (!parseStringList(line, strings))
140 return false;
141 for (int x = 0; x < strings.size(); x++) {
142 const std::string& levelString = strings[x];
143 int i;
144 if (levelString == "x")
145 i = -1;
146 else
147 std::istringstream(levelString) >> i;
148 levels.push_back(i);
149 }
150 return true;}
151
152 static bool parseReorderRule(std::string line, std::vector<int>& reorder)
153 {
154 return parseIntList(line, reorder);
155 }
156
157 static bool parseTestString(std::string line, std::basic_string<UChar>& testStri ng)
158 {
159 testString.clear();
160 static std::map<std::string, UChar> charClassExamples;
161 if (charClassExamples.empty()) {
162 charClassExamples.insert({"L", 0x6c}); // 'l' for L
163 charClassExamples.insert({"R", 0x05D0}); // HEBREW ALEF
164 charClassExamples.insert({"EN", 0x33}); // '3' for EN
165 charClassExamples.insert({"ES", 0x2d}); // '-' for ES
166 charClassExamples.insert({"ET", 0x25}); // '%' for ET
167 charClassExamples.insert({"AN", 0x0660}); // arabic 0
168 charClassExamples.insert({"CS", 0x2c}); // ',' for CS
169 charClassExamples.insert({"B", 0x0A}); // <control-000A>
170 charClassExamples.insert({"S", 0x09}); // <control-0009>
171 charClassExamples.insert({"WS", 0x20}); // ' ' for WS
172 charClassExamples.insert({"ON", 0x3d}); // '=' for ON
173 charClassExamples.insert({"NSM", 0x05BF}); // HEBREW POINT RAFE
174 charClassExamples.insert({"AL", 0x0608}); // ARABIC RAY
175 charClassExamples.insert({"BN", 0x00AD}); // SOFT HYPHEN
176 charClassExamples.insert({"LRE", 0x202A});
177 charClassExamples.insert({"RLE", 0x202B});
178 charClassExamples.insert({"PDF", 0x202C});
179 charClassExamples.insert({"LRO", 0x202D});
180 charClassExamples.insert({"RLO", 0x202E});
181 charClassExamples.insert({"LRI", 0x2066});
182 charClassExamples.insert({"RLI", 0x2067});
183 charClassExamples.insert({"FSI", 0x2068});
184 charClassExamples.insert({"PDI", 0x2069});
185 }
186
187 std::vector<std::string> charClasses;
188 parseStringList(line, charClasses);
189 for (int i = 0; i < charClasses.size(); i++) {
190 testString.push_back(charClassExamples.find(charClasses[i])->second);
191 }
192 return true;
193 }
194
195 static bool parseParagraphDirectionMask(std::string line, int& modeMask)
196 {
197 std::istringstream(line) >> modeMask;
198 return modeMask >= 1 && modeMask <= kMaxParagraphDirection;
199 }
200
201 static void parseError(const std::string& line, size_t lineNumber)
202 {
203 std::cout << "Parse error, line " << lineNumber << ":" << line;
204 }
205
206 template<class Runner>
207 void Harness<Runner>::parse(std::istream& bidiTestFile)
208 {
209 std::string levelsPrefix("@Levels");
210 std::string reorderPrefix("@Reorder");
211
212 // FIXME: UChar is an ICU type and cheating a bit to use here.
213 // uint16_t might be more portable.
214 std::basic_string<UChar> testString;
215 std::vector<int> levels;
216 std::vector<int> reorder;
217 int paragraphDirectionMask;
218
219 std::string originalLine;
220 std::string line;
221 size_t lineNumber = 0;
222 while (std::getline(bidiTestFile, originalLine)) {
223 lineNumber++;
224 line = originalLine;
225 size_t commentStart = originalLine.find_first_of('#');
226 if (commentStart != std::string::npos)
227 line = line.substr(0, commentStart);
228 line = trim(line);
229 if (line.empty())
230 continue;
231 if (line[0] == '@') {
232 if (!line.find(levelsPrefix)) {
233 if (!parseLevelRule(line.substr(levelsPrefix.length() + 1), leve ls))
234 parseError(originalLine, lineNumber);
235 continue;
236 }
237 if (!line.find(reorderPrefix)) {
238 if (!parseReorderRule(line.substr(reorderPrefix.length() + 1), r eorder))
239 parseError(originalLine, lineNumber);
240 continue;
241 }
242 } else {
243 // Assume it's a data line.
244 size_t seperatorIndex = line.find_first_of(';');
245 if (seperatorIndex == std::string::npos) {
246 parseError(originalLine, lineNumber);
247 continue;
248 }
249 if (!parseTestString(line.substr(0, seperatorIndex), testString)) {
250 parseError(originalLine, lineNumber);
251 continue;
252 }
253 if (!parseParagraphDirectionMask(line.substr(seperatorIndex + 1), pa ragraphDirectionMask)) {
254 parseError(originalLine, lineNumber);
255 continue;
256 }
257
258 if (paragraphDirectionMask & DirectionAutoLTR)
259 m_runner.runTest(testString, reorder, levels, DirectionAutoLTR, originalLine, lineNumber);
260 if (paragraphDirectionMask & DirectionLTR)
261 m_runner.runTest(testString, reorder, levels, DirectionLTR, orig inalLine, lineNumber);
262 if (paragraphDirectionMask & DirectionRTL)
263 m_runner.runTest(testString, reorder, levels, DirectionRTL, orig inalLine, lineNumber);
264 }
265 }
266 }
267
268 } // namespace bidi_test
269
270 #endif // BidiTestHarness_h
OLDNEW
« Source/platform/text/BidiResolverTest.cpp ('K') | « Source/platform/text/BidiResolverTest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698