119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)/* 219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * 419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * modification, are permitted provided that the following conditions are 619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * met: 719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * 819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 1019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 1119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 1219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * in the documentation and/or other materials provided with the 1319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * distribution. 1419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 1519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 1619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * this software without specific prior written permission. 1719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * 1819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) */ 3019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 3119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#ifndef BidiTestHarness_h 3219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#define BidiTestHarness_h 3319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 3419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include <istream> 3519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include <map> 3619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include <stdio.h> 3719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include <string> 3819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include <vector> 3919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 4019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// FIXME: We don't have any business owning this code. We should try to 4119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// upstream this to unicode.org if possible (for other implementations to use). 4219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// Unicode.org provides a reference implmentation, including parser: 4319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// http://www.unicode.org/Public/PROGRAMS/BidiReferenceC/6.3.0/source/brtest.c 4419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// But it, like the other implementations I've found, is rather tied to 4519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// the algorithms it is testing. This file seeks to only implement the parser bits. 4619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 4719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// Other C/C++ implementations of this parser: 4819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// https://github.com/googlei18n/fribidi-vs-unicode/blob/master/test.c 4919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// http://source.icu-project.org/repos/icu/icu/trunk/source/test/intltest/bidiconf.cpp 5019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// Both of those are too tied to their respective projects to be use to Blink. 5119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 5219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// There are non-C implmentations to parse BidiTest.txt as well, including: 5319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// https://github.com/twitter/twitter-cldr-rb/blob/master/spec/bidi/bidi_spec.rb 5419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 5519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// NOTE: None of this file is currently written to be thread-safe. 5619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 5719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)namespace bidi_test { 5819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 5919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)enum ParagraphDirection { 6019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) DirectionAutoLTR = 1, 6119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) DirectionLTR = 2, 6219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) DirectionRTL = 4, 6319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)}; 6419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)const int kMaxParagraphDirection = DirectionAutoLTR | DirectionLTR | DirectionRTL; 6519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 6619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// For error printing: 6719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)std::string nameFromParagraphDirection(ParagraphDirection paragraphDirection) 6819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 6919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) switch (paragraphDirection) { 7019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) case bidi_test::DirectionAutoLTR: 7119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return "Auto-LTR"; 7219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) case bidi_test::DirectionLTR: 7319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return "LTR"; 7419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) case bidi_test::DirectionRTL: 7519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return "RTL"; 7619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 7719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // This should never be reached. 7819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return ""; 7919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 8019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 8119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)template<class Runner> 8219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)class Harness { 8319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)public: 8419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) Harness(Runner& runner) 8519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) : m_runner(runner) 8619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) { 8719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 8819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) void parse(std::istream& bidiTestFile); 8919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 9019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)private: 9119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) Runner& m_runner; 9219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)}; 9319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 9419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// We could use boost::trim, but no other part of Blink uses boost yet. 9519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)inline void ltrim(std::string& s) 9619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 9719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static const std::string separators(" \t"); 9819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) s.erase(0, s.find_first_not_of(separators)); 9919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 10019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 10119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)inline void rtrim(std::string& s) 10219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 10319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static const std::string separators(" \t"); 10419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t lastNonSpace = s.find_last_not_of(separators); 10519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (lastNonSpace == std::string::npos) { 10619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) s.erase(); 10719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return; 10819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 10919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t firstSpaceAtEndOfString = lastNonSpace + 1; 11019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (firstSpaceAtEndOfString >= s.size()) 11119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return; // lastNonSpace was the last char. 11219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) s.erase(firstSpaceAtEndOfString, std::string::npos); // erase to the end of the string. 11319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 11419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 11519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)inline void trim(std::string& s) 11619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 11719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) rtrim(s); 11819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) ltrim(s); 11919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 12019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 12119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static std::vector<std::string> parseStringList(const std::string& str) 12219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 12319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<std::string> strings; 12419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static const std::string separators(" \t"); 12519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t lastPos = str.find_first_not_of(separators); // skip leading spaces 12619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t pos = str.find_first_of(separators, lastPos); // find next space 12719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 12819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) while (std::string::npos != pos || std::string::npos != lastPos) { 12919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) strings.push_back(str.substr(lastPos, pos - lastPos)); 13019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) lastPos = str.find_first_not_of(separators, pos); 13119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) pos = str.find_first_of(separators, lastPos); 13219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 13319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return strings; 13419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 13519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 13619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static std::vector<int> parseIntList(const std::string& str) 13719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 13819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<int> ints; 13919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<std::string> strings = parseStringList(str); 14019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) for (size_t x = 0; x < strings.size(); x++) { 14119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) int i = atoi(strings[x].c_str()); 14219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) ints.push_back(i); 14319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 14419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return ints; 14519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 14619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 14719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static std::vector<int> parseLevels(const std::string& line) 14819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 14919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<int> levels; 15019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<std::string> strings = parseStringList(line); 15119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) for (size_t x = 0; x < strings.size(); x++) { 15219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) const std::string& levelString = strings[x]; 15319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) int i; 15419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (levelString == "x") 15519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) i = -1; 15619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) else 15719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) i = atoi(levelString.c_str()); 15819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) levels.push_back(i); 15919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 16019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return levels; 16119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 16219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 16319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)// This is not thread-safe as written. 16419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static std::basic_string<UChar> parseTestString(const std::string& line) 16519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 16619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::basic_string<UChar> testString; 16719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static std::map<std::string, UChar> charClassExamples; 16819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (charClassExamples.empty()) { 16919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // FIXME: Explicit make_pair is ugly, but required for C++98 compat. 17019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("L", 0x6c)); // 'l' for L 17119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("R", 0x05D0)); // HEBREW ALEF 17219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("EN", 0x33)); // '3' for EN 17319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("ES", 0x2d)); // '-' for ES 17419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("ET", 0x25)); // '%' for ET 17519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("AN", 0x0660)); // arabic 0 17619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("CS", 0x2c)); // ',' for CS 17719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("B", 0x0A)); // <control-000A> 17819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("S", 0x09)); // <control-0009> 17919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("WS", 0x20)); // ' ' for WS 18019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("ON", 0x3d)); // '=' for ON 18119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("NSM", 0x05BF)); // HEBREW POINT RAFE 18219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("AL", 0x0608)); // ARABIC RAY 18319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("BN", 0x00AD)); // SOFT HYPHEN 18419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("LRE", 0x202A)); 18519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("RLE", 0x202B)); 18619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("PDF", 0x202C)); 18719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("LRO", 0x202D)); 18819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("RLO", 0x202E)); 18919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("LRI", 0x2066)); 19019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("RLI", 0x2067)); 19119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("FSI", 0x2068)); 19219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) charClassExamples.insert(std::make_pair("PDI", 0x2069)); 19319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 19419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 19519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<std::string> charClasses = parseStringList(line); 19619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) for (size_t i = 0; i < charClasses.size(); i++) { 19719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // FIXME: If the lookup failed we could return false for a parse error. 19819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) testString.push_back(charClassExamples.find(charClasses[i])->second); 19919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 20019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return testString; 20119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 20219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 20319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static bool parseParagraphDirectionMask(const std::string& line, int& modeMask) 20419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 20519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) modeMask = atoi(line.c_str()); 20619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) return modeMask >= 1 && modeMask <= kMaxParagraphDirection; 20719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 20819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 20919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static void parseError(const std::string& line, size_t lineNumber) 21019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 21119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // Use printf to avoid the expense of std::cout. 21219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) printf("Parse error, line %zu : %s\n", lineNumber, line.c_str()); 21319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 21419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 21519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)template<class Runner> 21619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)void Harness<Runner>::parse(std::istream& bidiTestFile) 21719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 21819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static const std::string levelsPrefix("@Levels"); 21919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) static const std::string reorderPrefix("@Reorder"); 22019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 22119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // FIXME: UChar is an ICU type and cheating a bit to use here. 22219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // uint16_t might be more portable. 22319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::basic_string<UChar> testString; 22419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<int> levels; 22519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::vector<int> reorder; 22619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) int paragraphDirectionMask; 22719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 22819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) std::string line; 22919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t lineNumber = 0; 23019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) while (std::getline(bidiTestFile, line)) { 23119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) lineNumber++; 23219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) const std::string originalLine = line; 23319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t commentStart = line.find_first_of('#'); 23419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (commentStart != std::string::npos) 23519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) line = line.substr(0, commentStart); 23619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) trim(line); 23719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (line.empty()) 23819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 23919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (line[0] == '@') { 24019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (!line.find(levelsPrefix)) { 24119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) levels = parseLevels(line.substr(levelsPrefix.length() + 1)); 24219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 24319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 24419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (!line.find(reorderPrefix)) { 24519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) reorder = parseIntList(line.substr(reorderPrefix.length() + 1)); 24619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 24719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 24819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } else { 24919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // Assume it's a data line. 25019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) size_t seperatorIndex = line.find_first_of(';'); 25119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (seperatorIndex == std::string::npos) { 25219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) parseError(originalLine, lineNumber); 25319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 25419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 25519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) testString = parseTestString(line.substr(0, seperatorIndex)); 25619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (!parseParagraphDirectionMask(line.substr(seperatorIndex + 1), paragraphDirectionMask)) { 25719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) parseError(originalLine, lineNumber); 25819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) continue; 25919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 26019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 26119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (paragraphDirectionMask & DirectionAutoLTR) 26219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) m_runner.runTest(testString, reorder, levels, DirectionAutoLTR, originalLine, lineNumber); 26319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (paragraphDirectionMask & DirectionLTR) 26419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) m_runner.runTest(testString, reorder, levels, DirectionLTR, originalLine, lineNumber); 26519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (paragraphDirectionMask & DirectionRTL) 26619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) m_runner.runTest(testString, reorder, levels, DirectionRTL, originalLine, lineNumber); 26719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 26819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 26919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} 27019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 27119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)} // namespace bidi_test 27219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) 27319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#endif // BidiTestHarness_h 274