150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho******************************************************************************* 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* 4f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius* Copyright (C) 2009-2014, International Business Machines 550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Corporation and others. All Rights Reserved. 650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* 750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho******************************************************************************* 850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* file name: bidiconf.cpp 950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* encoding: US-ASCII 1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* tab size: 8 (not used) 1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* indentation:4 1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* 1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* created on: 2009oct16 1450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* created by: Markus W. Scherer 1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* 1659d709d503bab6e2b61931737e662dd293b40578ccornelius* BiDi conformance test, using the Unicode BidiTest.txt and BidiCharacterTest.txt files. 1750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*/ 1850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <stdio.h> 2050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <stdlib.h> 2150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <string.h> 2250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/utypes.h" 2350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/ubidi.h" 2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/errorcode.h" 2550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/localpointer.h" 2650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/putil.h" 2750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/unistr.h" 2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "intltest.h" 2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uparse.h" 3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 3150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass BiDiConformanceTest : public IntlTest { 3250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic: 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho BiDiConformanceTest() : 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho directionBits(0), lineNumber(0), levelsCount(0), orderingCount(0), 3550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errorCount(0) {} 3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 3750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=NULL); 3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho void TestBidiTest(); 4059d709d503bab6e2b61931737e662dd293b40578ccornelius void TestBidiCharacterTest(); 4150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoprivate: 4259d709d503bab6e2b61931737e662dd293b40578ccornelius UBool parseLevels(const char *&start); 4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool parseOrdering(const char *start); 4450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool parseInputStringFromBiDiClasses(const char *&start); 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4659d709d503bab6e2b61931737e662dd293b40578ccornelius UBool checkLevels(const UBiDiLevel actualLevels[], int32_t actualCount); 4759d709d503bab6e2b61931737e662dd293b40578ccornelius UBool checkOrdering(UBiDi *ubidi); 4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4959d709d503bab6e2b61931737e662dd293b40578ccornelius void printErrorLine(); 5050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char line[10000]; 5250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBiDiLevel levels[1000]; 5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t directionBits; 5450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t ordering[1000]; 5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t lineNumber; 5650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t levelsCount; 5750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t orderingCount; 5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t errorCount; 5950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString inputString; 6059d709d503bab6e2b61931737e662dd293b40578ccornelius const char *paraLevelName; 6159d709d503bab6e2b61931737e662dd293b40578ccornelius char levelNameString[12]; 6250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 6350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 6450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoextern IntlTest *createBiDiConformanceTest() { 6550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return new BiDiConformanceTest(); 6650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 6750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 6827f654740f2a26ad62a5c155af9199af9e69b889clairehovoid BiDiConformanceTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) { 6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(exec) { 7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho logln("TestSuite BiDiConformanceTest: "); 7150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 7259d709d503bab6e2b61931737e662dd293b40578ccornelius TESTCASE_AUTO_BEGIN; 7359d709d503bab6e2b61931737e662dd293b40578ccornelius TESTCASE_AUTO(TestBidiTest); 7459d709d503bab6e2b61931737e662dd293b40578ccornelius TESTCASE_AUTO(TestBidiCharacterTest); 7559d709d503bab6e2b61931737e662dd293b40578ccornelius TESTCASE_AUTO_END; 7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 7850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_DEFINE_LOCAL_OPEN_POINTER(LocalStdioFilePointer, FILE, fclose); 7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 8059d709d503bab6e2b61931737e662dd293b40578ccorneliusUBool BiDiConformanceTest::parseLevels(const char *&start) { 8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho directionBits=0; 8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho levelsCount=0; 8359d709d503bab6e2b61931737e662dd293b40578ccornelius while(*start!=0 && *(start=u_skipWhitespace(start))!=0 && *start!=';') { 8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(*start=='x') { 8550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho levels[levelsCount++]=UBIDI_DEFAULT_LTR; 8650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++start; 8750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 8850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *end; 8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t value=(uint32_t)strtoul(start, &end, 10); 9059d709d503bab6e2b61931737e662dd293b40578ccornelius if(end<=start || (!U_IS_INV_WHITESPACE(*end) && *end!=0 && *end!=';') 9159d709d503bab6e2b61931737e662dd293b40578ccornelius || value>(UBIDI_MAX_EXPLICIT_LEVEL+1)) { 9259d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Levels parse error at %s", (int)lineNumber, start); 9359d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 9450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho levels[levelsCount++]=(UBiDiLevel)value; 9750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho directionBits|=(1<<(value&1)); 9850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start=end; 9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 10150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 10350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 10450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool BiDiConformanceTest::parseOrdering(const char *start) { 10550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho orderingCount=0; 10659d709d503bab6e2b61931737e662dd293b40578ccornelius while(*start!=0 && *(start=u_skipWhitespace(start))!=0 && *start!=';') { 10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *end; 10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t value=(uint32_t)strtoul(start, &end, 10); 10959d709d503bab6e2b61931737e662dd293b40578ccornelius if(end<=start || (!U_IS_INV_WHITESPACE(*end) && *end!=0 && *end!=';') || value>=1000) { 11059d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Reorder parse error at %s", (int)lineNumber, start); 11159d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 11250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 11450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ordering[orderingCount++]=(int32_t)value; 11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start=end; 11650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 11750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 11850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 11950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 12050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar charFromBiDiClass[U_CHAR_DIRECTION_COUNT]={ 12150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x6c, // 'l' for L 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x52, // 'R' for R 12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x33, // '3' for EN 12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x2d, // '-' for ES 12550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x25, // '%' for ET 12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x39, // '9' for AN 12750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x2c, // ',' for CS 12850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x2f, // '/' for B 12950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x5f, // '_' for S 13050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, // ' ' for WS 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x3d, // '=' for ON 13250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x65, // 'e' for LRE 13350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x6f, // 'o' for LRO 13450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x41, // 'A' for AL 13550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x45, // 'E' for RLE 13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x4f, // 'O' for RLO 13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x2a, // '*' for PDF 13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x60, // '`' for NSM 13959d709d503bab6e2b61931737e662dd293b40578ccornelius 0x7c, // '|' for BN 14059d709d503bab6e2b61931737e662dd293b40578ccornelius // new in Unicode 6.3/ICU 52 14159d709d503bab6e2b61931737e662dd293b40578ccornelius 0x53, // 'S' for FSI 14259d709d503bab6e2b61931737e662dd293b40578ccornelius 0x69, // 'i' for LRI 14359d709d503bab6e2b61931737e662dd293b40578ccornelius 0x49, // 'I' for RLI 14459d709d503bab6e2b61931737e662dd293b40578ccornelius 0x2e // '.' for PDI 14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 14650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 14750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_BEGIN 14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 14950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UCharDirection U_CALLCONV 15027f654740f2a26ad62a5c155af9199af9e69b889clairehobiDiConfUBiDiClassCallback(const void * /*context*/, UChar32 c) { 15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(int i=0; i<U_CHAR_DIRECTION_COUNT; ++i) { 15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(c==charFromBiDiClass[i]) { 15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (UCharDirection)i; 15450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Character not in our hardcoded table. 15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Should not occur during testing. 15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return U_BIDI_CLASS_DEFAULT; 15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 16150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_END 16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 16350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const int8_t biDiClassNameLengths[U_CHAR_DIRECTION_COUNT+1]={ 16459d709d503bab6e2b61931737e662dd293b40578ccornelius 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 2, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 0 16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 16750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool BiDiConformanceTest::parseInputStringFromBiDiClasses(const char *&start) { 16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho inputString.remove(); 16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Lengthy but fast BiDi class parser. 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * A simple parser could terminate or extract the name string and use 17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * int32_t biDiClassInt=u_getPropertyValueEnum(UCHAR_BIDI_CLASS, bidiClassString); 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * but that makes this test take significantly more time. 17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while(*start!=0 && *(start=u_skipWhitespace(start))!=0 && *start!=';') { 17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UCharDirection biDiClass=U_CHAR_DIRECTION_COUNT; 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Compare each character once until we have a match on 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // a complete, short BiDi class name. 17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[0]=='L') { 18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[1]=='R') { 18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[2]=='E') { 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_LEFT_TO_RIGHT_EMBEDDING; 18359d709d503bab6e2b61931737e662dd293b40578ccornelius } else if(start[2]=='I') { 18459d709d503bab6e2b61931737e662dd293b40578ccornelius biDiClass=U_LEFT_TO_RIGHT_ISOLATE; 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[2]=='O') { 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_LEFT_TO_RIGHT_OVERRIDE; 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_LEFT_TO_RIGHT; 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='R') { 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[1]=='L') { 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[2]=='E') { 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_RIGHT_TO_LEFT_EMBEDDING; 19559d709d503bab6e2b61931737e662dd293b40578ccornelius } else if(start[2]=='I') { 19659d709d503bab6e2b61931737e662dd293b40578ccornelius biDiClass=U_RIGHT_TO_LEFT_ISOLATE; 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[2]=='O') { 19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_RIGHT_TO_LEFT_OVERRIDE; 19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_RIGHT_TO_LEFT; 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='E') { 20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[1]=='N') { 20550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_EUROPEAN_NUMBER; 20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[1]=='S') { 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_EUROPEAN_NUMBER_SEPARATOR; 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[1]=='T') { 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_EUROPEAN_NUMBER_TERMINATOR; 21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='A') { 21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[1]=='L') { 21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_RIGHT_TO_LEFT_ARABIC; 21450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[1]=='N') { 21550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_ARABIC_NUMBER; 21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='C' && start[1]=='S') { 21850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_COMMON_NUMBER_SEPARATOR; 21950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='B') { 22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(start[1]=='N') { 22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_BOUNDARY_NEUTRAL; 22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_BLOCK_SEPARATOR; 22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='S') { 22650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_SEGMENT_SEPARATOR; 22750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='W' && start[1]=='S') { 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_WHITE_SPACE_NEUTRAL; 22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='O' && start[1]=='N') { 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_OTHER_NEUTRAL; 23159d709d503bab6e2b61931737e662dd293b40578ccornelius } else if(start[0]=='P' && start[1]=='D') { 23259d709d503bab6e2b61931737e662dd293b40578ccornelius if(start[2]=='F') { 23359d709d503bab6e2b61931737e662dd293b40578ccornelius biDiClass=U_POP_DIRECTIONAL_FORMAT; 23459d709d503bab6e2b61931737e662dd293b40578ccornelius } else if(start[2]=='I') { 23559d709d503bab6e2b61931737e662dd293b40578ccornelius biDiClass=U_POP_DIRECTIONAL_ISOLATE; 23659d709d503bab6e2b61931737e662dd293b40578ccornelius } 23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(start[0]=='N' && start[1]=='S' && start[2]=='M') { 23850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho biDiClass=U_DIR_NON_SPACING_MARK; 23959d709d503bab6e2b61931737e662dd293b40578ccornelius } else if(start[0]=='F' && start[1]=='S' && start[2]=='I') { 24059d709d503bab6e2b61931737e662dd293b40578ccornelius biDiClass=U_FIRST_STRONG_ISOLATE; 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Now we verify that the class name is terminated properly, 24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // and not just the start of a longer word. 24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int8_t biDiClassNameLength=biDiClassNameLengths[biDiClass]; 24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char c=start[biDiClassNameLength]; 24659d709d503bab6e2b61931737e662dd293b40578ccornelius if(biDiClass<U_CHAR_DIRECTION_COUNT && (U_IS_INV_WHITESPACE(c) || c==';' || c==0)) { 24759d709d503bab6e2b61931737e662dd293b40578ccornelius inputString.append(charFromBiDiClass[biDiClass]); 24859d709d503bab6e2b61931737e662dd293b40578ccornelius start+=biDiClassNameLength; 24959d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 25159d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: BiDi class string not recognized at %s", (int)lineNumber, start); 25259d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 25359d709d503bab6e2b61931737e662dd293b40578ccornelius return FALSE; 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 25850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid BiDiConformanceTest::TestBidiTest() { 25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho IcuTestErrorCode errorCode(*this, "TestBidiTest"); 26050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *sourceTestDataPath=getSourceTestData(errorCode); 26150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(errorCode.logIfFailureAndReset("unable to find the source/test/testdata " 26250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho "folder (getSourceTestData())")) { 26350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 26450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 26550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char bidiTestPath[400]; 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcpy(bidiTestPath, sourceTestDataPath); 26750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho strcat(bidiTestPath, "BidiTest.txt"); 26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho LocalStdioFilePointer bidiTestFile(fopen(bidiTestPath, "r")); 26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(bidiTestFile.isNull()) { 27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("unable to open %s", bidiTestPath); 27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 27350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho LocalUBiDiPointer ubidi(ubidi_open()); 27450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ubidi_setClassCallback(ubidi.getAlias(), biDiConfUBiDiClassCallback, NULL, 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho NULL, NULL, errorCode); 27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(errorCode.logIfFailureAndReset("ubidi_setClassCallback()")) { 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho lineNumber=0; 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho levelsCount=0; 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho orderingCount=0; 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errorCount=0; 2831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // paraLevelName must be initialized in case the first non-comment line is in error 2841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert paraLevelName="N/A"; 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while(errorCount<10 && fgets(line, (int)sizeof(line), bidiTestFile.getAlias())!=NULL) { 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++lineNumber; 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Remove trailing comments and whitespace. 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *commentStart=strchr(line, '#'); 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(commentStart!=NULL) { 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *commentStart=0; 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_rtrim(line); 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *start=u_skipWhitespace(line); 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(*start==0) { 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; // Skip empty and comment-only lines. 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(*start=='@') { 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++start; 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(0==strncmp(start, "Levels:", 7)) { 30059d709d503bab6e2b61931737e662dd293b40578ccornelius start+=7; 30159d709d503bab6e2b61931737e662dd293b40578ccornelius if(!parseLevels(start)) { 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if(0==strncmp(start, "Reorder:", 8)) { 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(!parseOrdering(start+8)) { 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Skip unknown @Xyz: ... 31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(!parseInputStringFromBiDiClasses(start)) { 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start=u_skipWhitespace(start); 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(*start!=';') { 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("missing ; separator on input line %s", line); 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start=u_skipWhitespace(start+1); 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *end; 32127f654740f2a26ad62a5c155af9199af9e69b889claireho uint32_t bitset=(uint32_t)strtoul(start, &end, 16); 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(end<=start || (!U_IS_INV_WHITESPACE(*end) && *end!=';' && *end!=0)) { 32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("input bitset parse error at %s", start); 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Loop over the bitset. 32727f654740f2a26ad62a5c155af9199af9e69b889claireho static const UBiDiLevel paraLevels[]={ UBIDI_DEFAULT_LTR, 0, 1, UBIDI_DEFAULT_RTL }; 32827f654740f2a26ad62a5c155af9199af9e69b889claireho static const char *const paraLevelNames[]={ "auto/LTR", "LTR", "RTL", "auto/RTL" }; 32927f654740f2a26ad62a5c155af9199af9e69b889claireho for(int i=0; i<=3; ++i) { 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(bitset&(1<<i)) { 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ubidi_setPara(ubidi.getAlias(), inputString.getBuffer(), inputString.length(), 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho paraLevels[i], NULL, errorCode); 33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UBiDiLevel *actualLevels=ubidi_getLevels(ubidi.getAlias(), errorCode); 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(errorCode.logIfFailureAndReset("ubidi_setPara() or ubidi_getLevels()")) { 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("Input line %d: %s", (int)lineNumber, line); 33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 33859d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName=paraLevelNames[i]; 33959d709d503bab6e2b61931737e662dd293b40578ccornelius if(!checkLevels(actualLevels, ubidi_getProcessedLength(ubidi.getAlias()))) { 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // continue outerLoop; does not exist in C++ 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // so just break out of the inner loop. 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 34459d709d503bab6e2b61931737e662dd293b40578ccornelius if(!checkOrdering(ubidi.getAlias())) { 34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // continue outerLoop; does not exist in C++ 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // so just break out of the inner loop. 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 35559d709d503bab6e2b61931737e662dd293b40578ccornelius/* 35659d709d503bab6e2b61931737e662dd293b40578ccornelius******************************************************************************* 35759d709d503bab6e2b61931737e662dd293b40578ccornelius* 35859d709d503bab6e2b61931737e662dd293b40578ccornelius* created on: 2013jul01 35959d709d503bab6e2b61931737e662dd293b40578ccornelius* created by: Matitiahu Allouche 36059d709d503bab6e2b61931737e662dd293b40578ccornelius 36159d709d503bab6e2b61931737e662dd293b40578ccorneliusThis function performs a conformance test for implementations of the 36259d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicode Bidirectional Algorithm, specified in UAX #9: Unicode 36359d709d503bab6e2b61931737e662dd293b40578ccorneliusBidirectional Algorithm, at http://www.unicode.org/unicode/reports/tr9/ 36459d709d503bab6e2b61931737e662dd293b40578ccornelius 36559d709d503bab6e2b61931737e662dd293b40578ccorneliusEach test case is represented in a single line which is read from a file 36659d709d503bab6e2b61931737e662dd293b40578ccorneliusnamed BidiCharacter.txt. Empty, blank and comment lines may also appear 36759d709d503bab6e2b61931737e662dd293b40578ccorneliusin this file. 36859d709d503bab6e2b61931737e662dd293b40578ccornelius 36959d709d503bab6e2b61931737e662dd293b40578ccorneliusThe format of the test data is specified below. Note that each test 37059d709d503bab6e2b61931737e662dd293b40578ccorneliuscase constitutes a single line of text; reordering is applied within a 37159d709d503bab6e2b61931737e662dd293b40578ccorneliussingle line and independently of a rendering engine, and rules L3 and L4 37259d709d503bab6e2b61931737e662dd293b40578ccorneliusare out of scope. 37359d709d503bab6e2b61931737e662dd293b40578ccornelius 37459d709d503bab6e2b61931737e662dd293b40578ccorneliusThe number sign '#' is the comment character: everything is ignored from 37559d709d503bab6e2b61931737e662dd293b40578ccorneliusthe occurrence of '#' until the end of the line, 37659d709d503bab6e2b61931737e662dd293b40578ccorneliusEmpty lines and lines containing only spaces and/or comments are ignored. 37759d709d503bab6e2b61931737e662dd293b40578ccornelius 37859d709d503bab6e2b61931737e662dd293b40578ccorneliusLines which represent test cases consist of 4 or 5 fields separated by a 37959d709d503bab6e2b61931737e662dd293b40578ccorneliussemicolon. Each field consists of tokens separated by whitespace (space 38059d709d503bab6e2b61931737e662dd293b40578ccorneliusor Tab). Whitespace before and after semicolons is optional. 38159d709d503bab6e2b61931737e662dd293b40578ccornelius 38259d709d503bab6e2b61931737e662dd293b40578ccorneliusField 0: A sequence of hexadecimal code point values separated by space 38359d709d503bab6e2b61931737e662dd293b40578ccornelius 38459d709d503bab6e2b61931737e662dd293b40578ccorneliusField 1: A value representing the paragraph direction, as follows: 38559d709d503bab6e2b61931737e662dd293b40578ccornelius - 0 represents left-to-right 38659d709d503bab6e2b61931737e662dd293b40578ccornelius - 1 represents right-to-left 38759d709d503bab6e2b61931737e662dd293b40578ccornelius - 2 represents auto-LTR according to rules P2 and P3 of the algorithm 38859d709d503bab6e2b61931737e662dd293b40578ccornelius - 3 represents auto-RTL according to rules P2 and P3 of the algorithm 38959d709d503bab6e2b61931737e662dd293b40578ccornelius - a negative number whose absolute value is taken as paragraph level; 39059d709d503bab6e2b61931737e662dd293b40578ccornelius this may be useful to test cases where the embedding level approaches 39159d709d503bab6e2b61931737e662dd293b40578ccornelius or exceeds the maximum embedding level. 39259d709d503bab6e2b61931737e662dd293b40578ccornelius 39359d709d503bab6e2b61931737e662dd293b40578ccorneliusField 2: The resolved paragraph embedding level. If the input (field 0) 39459d709d503bab6e2b61931737e662dd293b40578ccornelius includes more than one paragraph, this field represents the 39559d709d503bab6e2b61931737e662dd293b40578ccornelius resolved level of the first paragraph. 39659d709d503bab6e2b61931737e662dd293b40578ccornelius 39759d709d503bab6e2b61931737e662dd293b40578ccorneliusField 3: An ordered list of resulting levels for each token in field 0 39859d709d503bab6e2b61931737e662dd293b40578ccornelius (each token represents one source character). 39959d709d503bab6e2b61931737e662dd293b40578ccornelius The UBA does not assign levels to certain characters (e.g. LRO); 40059d709d503bab6e2b61931737e662dd293b40578ccornelius characters removed in rule X9 are indicated with an 'x'. 40159d709d503bab6e2b61931737e662dd293b40578ccornelius 40259d709d503bab6e2b61931737e662dd293b40578ccorneliusField 4: An ordered list of indices showing the resulting visual ordering 40359d709d503bab6e2b61931737e662dd293b40578ccornelius from left to right; characters with a resolved level of 'x' are 40459d709d503bab6e2b61931737e662dd293b40578ccornelius skipped. The number are zero-based. Each index corresponds to 40559d709d503bab6e2b61931737e662dd293b40578ccornelius a character in the reordered (visual) string. It represents the 40659d709d503bab6e2b61931737e662dd293b40578ccornelius index of the source character in the input (field 0). 40759d709d503bab6e2b61931737e662dd293b40578ccornelius This field is optional. When it is absent, the visual ordering 40859d709d503bab6e2b61931737e662dd293b40578ccornelius is not verified. 40959d709d503bab6e2b61931737e662dd293b40578ccornelius 41059d709d503bab6e2b61931737e662dd293b40578ccorneliusExamples: 41159d709d503bab6e2b61931737e662dd293b40578ccornelius 41259d709d503bab6e2b61931737e662dd293b40578ccornelius# This is a comment line. 41359d709d503bab6e2b61931737e662dd293b40578ccorneliusL L ON R ; 0 ; 0 ; 0 0 0 1 ; 0 1 2 3 41459d709d503bab6e2b61931737e662dd293b40578ccorneliusL L ON R;0;0;0 0 0 1;0 1 2 3 41559d709d503bab6e2b61931737e662dd293b40578ccornelius 41659d709d503bab6e2b61931737e662dd293b40578ccornelius# Note: in the next line, 'B' represents a block separator, not the letter 'B'. 41759d709d503bab6e2b61931737e662dd293b40578ccorneliusLRE A B C PDF;2;0;x 2 0 0 x;1 2 3 41859d709d503bab6e2b61931737e662dd293b40578ccornelius# Note: in the next line, 'b' represents the letter 'b', not a block separator. 41959d709d503bab6e2b61931737e662dd293b40578ccorneliusa b c 05d0 05d1 x ; 0 ; 0 ; 0 0 0 1 1 0 ; 0 1 2 4 3 5 42059d709d503bab6e2b61931737e662dd293b40578ccornelius 42159d709d503bab6e2b61931737e662dd293b40578ccorneliusa R R x ; 1 ; 1 ; 2 1 1 2 42259d709d503bab6e2b61931737e662dd293b40578ccorneliusL L R R R B R R L L L B ON ON ; 3 ; 0 ; 0 0 1 1 1 0 1 1 2 2 2 1 1 1 42359d709d503bab6e2b61931737e662dd293b40578ccornelius 42459d709d503bab6e2b61931737e662dd293b40578ccornelius* 42559d709d503bab6e2b61931737e662dd293b40578ccornelius******************************************************************************* 42659d709d503bab6e2b61931737e662dd293b40578ccornelius*/ 42759d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid BiDiConformanceTest::TestBidiCharacterTest() { 42859d709d503bab6e2b61931737e662dd293b40578ccornelius IcuTestErrorCode errorCode(*this, "TestBidiCharacterTest"); 42959d709d503bab6e2b61931737e662dd293b40578ccornelius const char *sourceTestDataPath=getSourceTestData(errorCode); 43059d709d503bab6e2b61931737e662dd293b40578ccornelius if(errorCode.logIfFailureAndReset("unable to find the source/test/testdata " 43159d709d503bab6e2b61931737e662dd293b40578ccornelius "folder (getSourceTestData())")) { 43259d709d503bab6e2b61931737e662dd293b40578ccornelius return; 43359d709d503bab6e2b61931737e662dd293b40578ccornelius } 43459d709d503bab6e2b61931737e662dd293b40578ccornelius char bidiTestPath[400]; 43559d709d503bab6e2b61931737e662dd293b40578ccornelius strcpy(bidiTestPath, sourceTestDataPath); 43659d709d503bab6e2b61931737e662dd293b40578ccornelius strcat(bidiTestPath, "BidiCharacterTest.txt"); 43759d709d503bab6e2b61931737e662dd293b40578ccornelius LocalStdioFilePointer bidiTestFile(fopen(bidiTestPath, "r")); 43859d709d503bab6e2b61931737e662dd293b40578ccornelius if(bidiTestFile.isNull()) { 43959d709d503bab6e2b61931737e662dd293b40578ccornelius errln("unable to open %s", bidiTestPath); 44059d709d503bab6e2b61931737e662dd293b40578ccornelius return; 44159d709d503bab6e2b61931737e662dd293b40578ccornelius } 44259d709d503bab6e2b61931737e662dd293b40578ccornelius LocalUBiDiPointer ubidi(ubidi_open()); 44359d709d503bab6e2b61931737e662dd293b40578ccornelius lineNumber=0; 44459d709d503bab6e2b61931737e662dd293b40578ccornelius levelsCount=0; 44559d709d503bab6e2b61931737e662dd293b40578ccornelius orderingCount=0; 44659d709d503bab6e2b61931737e662dd293b40578ccornelius errorCount=0; 44759d709d503bab6e2b61931737e662dd293b40578ccornelius while(errorCount<20 && fgets(line, (int)sizeof(line), bidiTestFile.getAlias())!=NULL) { 44859d709d503bab6e2b61931737e662dd293b40578ccornelius ++lineNumber; 44959d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName="N/A"; 45059d709d503bab6e2b61931737e662dd293b40578ccornelius inputString="N/A"; 45159d709d503bab6e2b61931737e662dd293b40578ccornelius // Remove trailing comments and whitespace. 45259d709d503bab6e2b61931737e662dd293b40578ccornelius char *commentStart=strchr(line, '#'); 45359d709d503bab6e2b61931737e662dd293b40578ccornelius if(commentStart!=NULL) { 45459d709d503bab6e2b61931737e662dd293b40578ccornelius *commentStart=0; 45559d709d503bab6e2b61931737e662dd293b40578ccornelius } 45659d709d503bab6e2b61931737e662dd293b40578ccornelius u_rtrim(line); 45759d709d503bab6e2b61931737e662dd293b40578ccornelius const char *start=u_skipWhitespace(line); 45859d709d503bab6e2b61931737e662dd293b40578ccornelius if(*start==0) { 45959d709d503bab6e2b61931737e662dd293b40578ccornelius continue; // Skip empty and comment-only lines. 46059d709d503bab6e2b61931737e662dd293b40578ccornelius } 46159d709d503bab6e2b61931737e662dd293b40578ccornelius // Parse the code point string in field 0. 46259d709d503bab6e2b61931737e662dd293b40578ccornelius UChar *buffer=inputString.getBuffer(200); 46359d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t length=u_parseString(start, buffer, inputString.getCapacity(), NULL, errorCode); 46459d709d503bab6e2b61931737e662dd293b40578ccornelius if(errorCode.logIfFailureAndReset("Invalid string in field 0")) { 46559d709d503bab6e2b61931737e662dd293b40578ccornelius errln("Input line %d: %s", (int)lineNumber, line); 46659d709d503bab6e2b61931737e662dd293b40578ccornelius inputString.remove(); 46759d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 46859d709d503bab6e2b61931737e662dd293b40578ccornelius } 46959d709d503bab6e2b61931737e662dd293b40578ccornelius inputString.releaseBuffer(length); 47059d709d503bab6e2b61931737e662dd293b40578ccornelius start=strchr(start, ';'); 47159d709d503bab6e2b61931737e662dd293b40578ccornelius if(start==NULL) { 47259d709d503bab6e2b61931737e662dd293b40578ccornelius errorCount++; 47359d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Missing ; separator on line: %s", (int)lineNumber, line); 47459d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 47559d709d503bab6e2b61931737e662dd293b40578ccornelius } 47659d709d503bab6e2b61931737e662dd293b40578ccornelius start=u_skipWhitespace(start+1); 47759d709d503bab6e2b61931737e662dd293b40578ccornelius char *end; 47859d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t paraDirection=(int32_t)strtol(start, &end, 10); 47959d709d503bab6e2b61931737e662dd293b40578ccornelius UBiDiLevel paraLevel=UBIDI_MAX_EXPLICIT_LEVEL+2; 48059d709d503bab6e2b61931737e662dd293b40578ccornelius if(paraDirection==0) { 48159d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel=0; 48259d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName="LTR"; 48359d709d503bab6e2b61931737e662dd293b40578ccornelius } 48459d709d503bab6e2b61931737e662dd293b40578ccornelius else if(paraDirection==1) { 48559d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel=1; 48659d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName="RTL"; 48759d709d503bab6e2b61931737e662dd293b40578ccornelius } 48859d709d503bab6e2b61931737e662dd293b40578ccornelius else if(paraDirection==2) { 48959d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel=UBIDI_DEFAULT_LTR; 49059d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName="Auto/LTR"; 49159d709d503bab6e2b61931737e662dd293b40578ccornelius } 49259d709d503bab6e2b61931737e662dd293b40578ccornelius else if(paraDirection==3) { 49359d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel=UBIDI_DEFAULT_RTL; 49459d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName="Auto/RTL"; 49559d709d503bab6e2b61931737e662dd293b40578ccornelius } 49659d709d503bab6e2b61931737e662dd293b40578ccornelius else if(paraDirection<0 && -paraDirection<=(UBIDI_MAX_EXPLICIT_LEVEL+1)) { 49759d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel=(UBiDiLevel)(-paraDirection); 49859d709d503bab6e2b61931737e662dd293b40578ccornelius sprintf(levelNameString, "%d", (int)paraLevel); 49959d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevelName=levelNameString; 50059d709d503bab6e2b61931737e662dd293b40578ccornelius } 50159d709d503bab6e2b61931737e662dd293b40578ccornelius if(end<=start || (!U_IS_INV_WHITESPACE(*end) && *end!=';' && *end!=0) || 50259d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel==(UBIDI_MAX_EXPLICIT_LEVEL+2)) { 50359d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Input paragraph direction incorrect at %s", (int)lineNumber, start); 50459d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 50559d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 50659d709d503bab6e2b61931737e662dd293b40578ccornelius } 50759d709d503bab6e2b61931737e662dd293b40578ccornelius start=u_skipWhitespace(end); 50859d709d503bab6e2b61931737e662dd293b40578ccornelius if(*start!=';') { 50959d709d503bab6e2b61931737e662dd293b40578ccornelius errorCount++; 51059d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Missing ; separator on line: %s", (int)lineNumber, line); 51159d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 51259d709d503bab6e2b61931737e662dd293b40578ccornelius } 51359d709d503bab6e2b61931737e662dd293b40578ccornelius start++; 51459d709d503bab6e2b61931737e662dd293b40578ccornelius uint32_t resolvedParaLevel=(uint32_t)strtoul(start, &end, 10); 51559d709d503bab6e2b61931737e662dd293b40578ccornelius if(end<=start || (!U_IS_INV_WHITESPACE(*end) && *end!=';' && *end!=0) || 51659d709d503bab6e2b61931737e662dd293b40578ccornelius resolvedParaLevel>1) { 51759d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Resolved paragraph level incorrect at %s", (int)lineNumber, start); 51859d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 51959d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 52059d709d503bab6e2b61931737e662dd293b40578ccornelius } 52159d709d503bab6e2b61931737e662dd293b40578ccornelius start=u_skipWhitespace(end); 52259d709d503bab6e2b61931737e662dd293b40578ccornelius if(*start!=';') { 52359d709d503bab6e2b61931737e662dd293b40578ccornelius errorCount++; 52459d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Missing ; separator on line: %s", (int)lineNumber, line); 52559d709d503bab6e2b61931737e662dd293b40578ccornelius return; 52659d709d503bab6e2b61931737e662dd293b40578ccornelius } 52759d709d503bab6e2b61931737e662dd293b40578ccornelius start++; 52859d709d503bab6e2b61931737e662dd293b40578ccornelius if(!parseLevels(start)) { 52959d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 53059d709d503bab6e2b61931737e662dd293b40578ccornelius } 53159d709d503bab6e2b61931737e662dd293b40578ccornelius start=u_skipWhitespace(start); 53259d709d503bab6e2b61931737e662dd293b40578ccornelius if(*start==';') { 53359d709d503bab6e2b61931737e662dd293b40578ccornelius if(!parseOrdering(start+1)) { 53459d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 53559d709d503bab6e2b61931737e662dd293b40578ccornelius } 53659d709d503bab6e2b61931737e662dd293b40578ccornelius } 53759d709d503bab6e2b61931737e662dd293b40578ccornelius else 53859d709d503bab6e2b61931737e662dd293b40578ccornelius orderingCount=-1; 53959d709d503bab6e2b61931737e662dd293b40578ccornelius 54059d709d503bab6e2b61931737e662dd293b40578ccornelius ubidi_setPara(ubidi.getAlias(), inputString.getBuffer(), inputString.length(), 54159d709d503bab6e2b61931737e662dd293b40578ccornelius paraLevel, NULL, errorCode); 54259d709d503bab6e2b61931737e662dd293b40578ccornelius const UBiDiLevel *actualLevels=ubidi_getLevels(ubidi.getAlias(), errorCode); 54359d709d503bab6e2b61931737e662dd293b40578ccornelius if(errorCode.logIfFailureAndReset("ubidi_setPara() or ubidi_getLevels()")) { 54459d709d503bab6e2b61931737e662dd293b40578ccornelius errln("Input line %d: %s", (int)lineNumber, line); 54559d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 54659d709d503bab6e2b61931737e662dd293b40578ccornelius } 54759d709d503bab6e2b61931737e662dd293b40578ccornelius UBiDiLevel actualLevel; 54859d709d503bab6e2b61931737e662dd293b40578ccornelius if((actualLevel=ubidi_getParaLevel(ubidi.getAlias()))!=resolvedParaLevel) { 54959d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 55059d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Wrong resolved paragraph level; expected %d actual %d", 55159d709d503bab6e2b61931737e662dd293b40578ccornelius (int)lineNumber, resolvedParaLevel, actualLevel); 55259d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 55359d709d503bab6e2b61931737e662dd293b40578ccornelius } 55459d709d503bab6e2b61931737e662dd293b40578ccornelius if(!checkLevels(actualLevels, ubidi_getProcessedLength(ubidi.getAlias()))) { 55559d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 55659d709d503bab6e2b61931737e662dd293b40578ccornelius } 55759d709d503bab6e2b61931737e662dd293b40578ccornelius if(orderingCount>=0 && !checkOrdering(ubidi.getAlias())) { 55859d709d503bab6e2b61931737e662dd293b40578ccornelius continue; 55959d709d503bab6e2b61931737e662dd293b40578ccornelius } 56059d709d503bab6e2b61931737e662dd293b40578ccornelius } 56159d709d503bab6e2b61931737e662dd293b40578ccornelius} 56259d709d503bab6e2b61931737e662dd293b40578ccornelius 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UChar printLevel(UBiDiLevel level) { 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(level<UBIDI_DEFAULT_LTR) { 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0x30+level; 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0x78; // 'x' 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 57150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uint32_t getDirectionBits(const UBiDiLevel actualLevels[], int32_t actualCount) { 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t actualDirectionBits=0; 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(int32_t i=0; i<actualCount; ++i) { 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho actualDirectionBits|=(1<<(actualLevels[i]&1)); 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return actualDirectionBits; 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 57959d709d503bab6e2b61931737e662dd293b40578ccorneliusUBool BiDiConformanceTest::checkLevels(const UBiDiLevel actualLevels[], int32_t actualCount) { 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isOk=TRUE; 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(levelsCount!=actualCount) { 58259d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Wrong number of level values; expected %d actual %d", 58359d709d503bab6e2b61931737e662dd293b40578ccornelius (int)lineNumber, (int)levelsCount, (int)actualCount); 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isOk=FALSE; 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(int32_t i=0; i<actualCount; ++i) { 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(levels[i]!=actualLevels[i] && levels[i]<UBIDI_DEFAULT_LTR) { 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(directionBits!=3 && directionBits==getDirectionBits(actualLevels, actualCount)) { 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // ICU used a shortcut: 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Since the text is unidirectional, it did not store the resolved 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // levels but just returns all levels as the paragraph level 0 or 1. 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // The reordering result is the same, so this is fine. 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 59559d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Wrong level value at index %d; expected %d actual %d", 59659d709d503bab6e2b61931737e662dd293b40578ccornelius (int)lineNumber, (int)i, levels[i], actualLevels[i]); 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isOk=FALSE; 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(!isOk) { 60459d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString els("Expected levels: "); 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t i; 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i=0; i<levelsCount; ++i) { 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho els.append((UChar)0x20).append(printLevel(levels[i])); 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString als("Actual levels: "); 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i=0; i<actualCount; ++i) { 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho als.append((UChar)0x20).append(printLevel(actualLevels[i])); 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln(els); 61550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln(als); 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return isOk; 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Note: ubidi_setReorderingOptions(ubidi, UBIDI_OPTION_REMOVE_CONTROLS); 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// does not work for custom BiDi class assignments 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// and anyway also removes LRM/RLM/ZWJ/ZWNJ which is not desirable here. 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Therefore we just skip the indexes for BiDi controls while comparing 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// with the expected ordering that has them omitted. 62559d709d503bab6e2b61931737e662dd293b40578ccorneliusUBool BiDiConformanceTest::checkOrdering(UBiDi *ubidi) { 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isOk=TRUE; 62759d709d503bab6e2b61931737e662dd293b40578ccornelius IcuTestErrorCode errorCode(*this, "checkOrdering()"); 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t resultLength=ubidi_getResultLength(ubidi); // visual length including BiDi controls 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t i, visualIndex; 63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Note: It should be faster to call ubidi_countRuns()/ubidi_getVisualRun() 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // and loop over each run's indexes, but that seems unnecessary for this test code. 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i=visualIndex=0; i<resultLength; ++i) { 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t logicalIndex=ubidi_getLogicalIndex(ubidi, i, errorCode); 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(errorCode.logIfFailureAndReset("ubidi_getLogicalIndex()")) { 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("Input line %d: %s", (int)lineNumber, line); 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(levels[logicalIndex]>=UBIDI_DEFAULT_LTR) { 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; // BiDi control, omitted from expected ordering. 64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(visualIndex<orderingCount && logicalIndex!=ordering[visualIndex]) { 64259d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Wrong ordering value at visual index %d; expected %d actual %d", 64359d709d503bab6e2b61931737e662dd293b40578ccornelius (int)lineNumber, (int)visualIndex, ordering[visualIndex], logicalIndex); 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isOk=FALSE; 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++visualIndex; 64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // visualIndex is now the visual length minus the BiDi controls, 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // which should match the length of the BidiTest.txt ordering. 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(isOk && orderingCount!=visualIndex) { 65259d709d503bab6e2b61931737e662dd293b40578ccornelius errln("\nError on line %d: Wrong number of ordering values; expected %d actual %d", 65359d709d503bab6e2b61931737e662dd293b40578ccornelius (int)lineNumber, (int)orderingCount, (int)visualIndex); 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isOk=FALSE; 65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(!isOk) { 65759d709d503bab6e2b61931737e662dd293b40578ccornelius printErrorLine(); 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString eord("Expected ordering: "); 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i=0; i<orderingCount; ++i) { 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho eord.append((UChar)0x20).append((UChar)(0x30+ordering[i])); 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString aord("Actual ordering: "); 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i=0; i<resultLength; ++i) { 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t logicalIndex=ubidi_getLogicalIndex(ubidi, i, errorCode); 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(levels[logicalIndex]<UBIDI_DEFAULT_LTR) { 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho aord.append((UChar)0x20).append((UChar)(0x30+logicalIndex)); 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln(eord); 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln(aord); 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return isOk; 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 67559d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid BiDiConformanceTest::printErrorLine() { 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++errorCount; 67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("Input line %5d: %s", (int)lineNumber, line); 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln(UnicodeString("Input string: ")+inputString); 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho errln("Para level: %s", paraLevelName); 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 681