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