Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2010, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /*   file name:  cbiditst.cpp
      7 *   encoding:   US-ASCII
      8 *   tab size:   8 (not used)
      9 *   indentation:4
     10 *
     11 *   created on: 1999sep27
     12 *   created by: Markus W. Scherer, updated by Matitiahu Allouche
     13 */
     14 
     15 #include "cintltst.h"
     16 #include "unicode/utypes.h"
     17 #include "unicode/uchar.h"
     18 #include "unicode/ustring.h"
     19 #include "unicode/ubidi.h"
     20 #include "unicode/ushape.h"
     21 #include "cbiditst.h"
     22 #include "cstring.h"
     23 /* the following include is needed for sprintf */
     24 #include <stdio.h>
     25 
     26 #define MAXLEN      MAX_STRING_LENGTH
     27 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
     28 
     29 /* prototypes ---------------------------------------------------------------*/
     30 
     31 void addComplexTest(TestNode** root);
     32 
     33 static void testCharFromDirProp(void);
     34 
     35 static void testBidi(void);
     36 
     37 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
     38 
     39 static void doMisc(void);
     40 
     41 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
     42                    int32_t lineStart, UBool countRunsFirst);
     43 
     44 static void _testReordering(UBiDi *pBiDi, int testNumber);
     45 
     46 static void testInverse(void);
     47 
     48 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
     49 
     50 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
     51                              UBiDiLevel direction, UErrorCode *pErrorCode);
     52 
     53 static void _testWriteReverse(void);
     54 
     55 static void _testManyAddedPoints(void);
     56 
     57 static void _testMisc(void);
     58 
     59 static void doArabicShapingTest(void);
     60 
     61 static void doLamAlefSpecialVLTRArabicShapingTest(void);
     62 
     63 static void doTashkeelSpecialVLTRArabicShapingTest(void);
     64 
     65 static void doLOGICALArabicDeShapingTest(void);
     66 
     67 static void doArabicShapingTestForBug5421(void);
     68 
     69 static void testReorder(void);
     70 
     71 static void testFailureRecovery(void);
     72 
     73 static void testMultipleParagraphs(void);
     74 
     75 static void testGetBaseDirection(void);
     76 
     77 /* new BIDI API */
     78 static void testReorderingMode(void);
     79 static void testReorderRunsOnly(void);
     80 static void testStreaming(void);
     81 static void testClassOverride(void);
     82 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
     83                                 uint32_t option, UBiDiLevel level, char *result);
     84 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
     85                              const char *srcChars, const char *destChars,
     86                              const UChar *dest, int32_t destLen, int mode,
     87                              int option, UBiDiLevel level);
     88 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
     89                                const char *destChars,
     90                                int32_t destLen, const char *mode,
     91                                const char *option, UBiDiLevel level);
     92 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
     93                        const char *dest, const char *mode, const char* option,
     94                        UBiDiLevel level, UBool forward);
     95 
     96 /* helpers ------------------------------------------------------------------ */
     97 
     98 static const char *levelString="...............................................................";
     99 
    100 static void initCharFromDirProps(void);
    101 
    102 static UChar *
    103 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
    104 
    105 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
    106 
    107 /* regression tests ---------------------------------------------------------*/
    108 
    109 void
    110 addComplexTest(TestNode** root) {
    111     addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
    112     addTest(root, testBidi, "complex/bidi/TestBidi");
    113     addTest(root, testInverse, "complex/bidi/TestInverse");
    114     addTest(root, testReorder,"complex/bidi/TestReorder");
    115     addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
    116     addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
    117     addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
    118     addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
    119     addTest(root, testStreaming, "complex/bidi/TestStreaming");
    120     addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
    121 
    122     addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
    123     addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
    124     addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
    125     addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
    126     addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
    127     addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection");
    128 }
    129 
    130 static void
    131 testCharFromDirProp(void) {
    132     /* verify that the exemplar characters have the expected bidi classes */
    133     int32_t i;
    134 
    135     log_verbose("\nEntering TestCharFromDirProp\n\n");
    136     initCharFromDirProps();
    137 
    138     for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
    139         if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
    140             log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
    141                     i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
    142         }
    143     }
    144     log_verbose("\nExiting TestCharFromDirProp\n\n");
    145 }
    146 
    147 static void
    148 testBidi(void) {
    149     UBiDi *pBiDi, *pLine=NULL;
    150     UErrorCode errorCode=U_ZERO_ERROR;
    151 
    152     log_verbose("\nEntering TestBidi\n\n");
    153 
    154     pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
    155     if(pBiDi!=NULL) {
    156         pLine=ubidi_open();
    157         if(pLine!=NULL) {
    158             doTests(pBiDi, pLine, FALSE);
    159             doTests(pBiDi, pLine, TRUE);
    160         } else {
    161             log_err("ubidi_open() returned NULL, out of memory\n");
    162         }
    163     } else {
    164         log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
    165     }
    166     doMisc();
    167 
    168     if(pLine!=NULL) {
    169         ubidi_close(pLine);
    170     }
    171     if(pBiDi!=NULL) {
    172         ubidi_close(pBiDi);
    173     }
    174 
    175     log_verbose("\nExiting TestBidi\n\n");
    176 }
    177 
    178 static void
    179 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
    180     int testNumber;
    181     UChar string[MAXLEN];
    182     UErrorCode errorCode;
    183     int32_t lineStart;
    184     UBiDiLevel paraLevel;
    185 
    186     for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
    187         errorCode=U_ZERO_ERROR;
    188         getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
    189         paraLevel=tests[testNumber].paraLevel;
    190         ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
    191         if(U_SUCCESS(errorCode)) {
    192             log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
    193                     testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
    194             lineStart=tests[testNumber].lineStart;
    195             if(lineStart==-1) {
    196                 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
    197             } else {
    198                 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
    199                 if(U_SUCCESS(errorCode)) {
    200                     log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
    201                             lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
    202                     doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
    203                 } else {
    204                     log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
    205                             testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
    206                 }
    207             }
    208         } else {
    209             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    210                     testNumber, paraLevel, myErrorName(errorCode));
    211         }
    212     }
    213 }
    214 
    215 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    216 
    217 #define TABLE_SIZE  256
    218 static UBool   tablesInitialized = FALSE;
    219 static UChar   pseudoToUChar[TABLE_SIZE];
    220 static uint8_t UCharToPseudo[TABLE_SIZE];    /* used for Unicode chars < 0x0100 */
    221 static uint8_t UCharToPseud2[TABLE_SIZE];    /* used for Unicode chars >=0x0100 */
    222 
    223 static void buildPseudoTables(void)
    224 /*
    225     The rules for pseudo-Bidi are as follows:
    226     - [ == LRE
    227     - ] == RLE
    228     - { == LRO
    229     - } == RLO
    230     - ^ == PDF
    231     - @ == LRM
    232     - & == RLM
    233     - A-F == Arabic Letters 0631-0636
    234     - G-V == Hebrew letters 05d7-05e6
    235     - W-Z == Unassigned RTL 08d0-08d3
    236     - 0-5 == western digits 0030-0035
    237     - 6-9 == Arabic-Indic digits 0666-0669
    238     - ` == Combining Grave Accent 0300 (NSM)
    239     - ~ == Delete 007f (BN)
    240     - | == Paragraph Separator 2029 (B)
    241     - _ == Info Separator 1 001f (S)
    242     All other characters represent themselves as Latin-1, with the corresponding
    243     Bidi properties.
    244 */
    245 {
    246     int             i;
    247     UChar           uchar;
    248     uint8_t         c;
    249     /* initialize all tables to unknown */
    250     for (i=0; i < TABLE_SIZE; i++) {
    251         pseudoToUChar[i] = 0xFFFD;
    252         UCharToPseudo[i] = '?';
    253         UCharToPseud2[i] = '?';
    254     }
    255     /* initialize non letters or digits */
    256     pseudoToUChar[(uint8_t) 0 ] = 0x0000;    UCharToPseudo[0x00] = (uint8_t) 0 ;
    257     pseudoToUChar[(uint8_t)' '] = 0x0020;    UCharToPseudo[0x20] = (uint8_t)' ';
    258     pseudoToUChar[(uint8_t)'!'] = 0x0021;    UCharToPseudo[0x21] = (uint8_t)'!';
    259     pseudoToUChar[(uint8_t)'"'] = 0x0022;    UCharToPseudo[0x22] = (uint8_t)'"';
    260     pseudoToUChar[(uint8_t)'#'] = 0x0023;    UCharToPseudo[0x23] = (uint8_t)'#';
    261     pseudoToUChar[(uint8_t)'$'] = 0x0024;    UCharToPseudo[0x24] = (uint8_t)'$';
    262     pseudoToUChar[(uint8_t)'%'] = 0x0025;    UCharToPseudo[0x25] = (uint8_t)'%';
    263     pseudoToUChar[(uint8_t)'\'']= 0x0027;    UCharToPseudo[0x27] = (uint8_t)'\'';
    264     pseudoToUChar[(uint8_t)'('] = 0x0028;    UCharToPseudo[0x28] = (uint8_t)'(';
    265     pseudoToUChar[(uint8_t)')'] = 0x0029;    UCharToPseudo[0x29] = (uint8_t)')';
    266     pseudoToUChar[(uint8_t)'*'] = 0x002A;    UCharToPseudo[0x2A] = (uint8_t)'*';
    267     pseudoToUChar[(uint8_t)'+'] = 0x002B;    UCharToPseudo[0x2B] = (uint8_t)'+';
    268     pseudoToUChar[(uint8_t)','] = 0x002C;    UCharToPseudo[0x2C] = (uint8_t)',';
    269     pseudoToUChar[(uint8_t)'-'] = 0x002D;    UCharToPseudo[0x2D] = (uint8_t)'-';
    270     pseudoToUChar[(uint8_t)'.'] = 0x002E;    UCharToPseudo[0x2E] = (uint8_t)'.';
    271     pseudoToUChar[(uint8_t)'/'] = 0x002F;    UCharToPseudo[0x2F] = (uint8_t)'/';
    272     pseudoToUChar[(uint8_t)':'] = 0x003A;    UCharToPseudo[0x3A] = (uint8_t)':';
    273     pseudoToUChar[(uint8_t)';'] = 0x003B;    UCharToPseudo[0x3B] = (uint8_t)';';
    274     pseudoToUChar[(uint8_t)'<'] = 0x003C;    UCharToPseudo[0x3C] = (uint8_t)'<';
    275     pseudoToUChar[(uint8_t)'='] = 0x003D;    UCharToPseudo[0x3D] = (uint8_t)'=';
    276     pseudoToUChar[(uint8_t)'>'] = 0x003E;    UCharToPseudo[0x3E] = (uint8_t)'>';
    277     pseudoToUChar[(uint8_t)'?'] = 0x003F;    UCharToPseudo[0x3F] = (uint8_t)'?';
    278     pseudoToUChar[(uint8_t)'\\']= 0x005C;    UCharToPseudo[0x5C] = (uint8_t)'\\';
    279     /* initialize specially used characters */
    280     pseudoToUChar[(uint8_t)'`'] = 0x0300;    UCharToPseud2[0x00] = (uint8_t)'`';  /* NSM */
    281     pseudoToUChar[(uint8_t)'@'] = 0x200E;    UCharToPseud2[0x0E] = (uint8_t)'@';  /* LRM */
    282     pseudoToUChar[(uint8_t)'&'] = 0x200F;    UCharToPseud2[0x0F] = (uint8_t)'&';  /* RLM */
    283     pseudoToUChar[(uint8_t)'_'] = 0x001F;    UCharToPseudo[0x1F] = (uint8_t)'_';  /* S   */
    284     pseudoToUChar[(uint8_t)'|'] = 0x2029;    UCharToPseud2[0x29] = (uint8_t)'|';  /* B   */
    285     pseudoToUChar[(uint8_t)'['] = 0x202A;    UCharToPseud2[0x2A] = (uint8_t)'[';  /* LRE */
    286     pseudoToUChar[(uint8_t)']'] = 0x202B;    UCharToPseud2[0x2B] = (uint8_t)']';  /* RLE */
    287     pseudoToUChar[(uint8_t)'^'] = 0x202C;    UCharToPseud2[0x2C] = (uint8_t)'^';  /* PDF */
    288     pseudoToUChar[(uint8_t)'{'] = 0x202D;    UCharToPseud2[0x2D] = (uint8_t)'{';  /* LRO */
    289     pseudoToUChar[(uint8_t)'}'] = 0x202E;    UCharToPseud2[0x2E] = (uint8_t)'}';  /* RLO */
    290     pseudoToUChar[(uint8_t)'~'] = 0x007F;    UCharToPseudo[0x7F] = (uint8_t)'~';  /* BN  */
    291     /* initialize western digits */
    292     for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
    293         c = (uint8_t)columns[i];
    294         pseudoToUChar[c] = uchar;
    295         UCharToPseudo[uchar & 0x00ff] = c;
    296     }
    297     /* initialize Hindi digits */
    298     for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
    299         c = (uint8_t)columns[i];
    300         pseudoToUChar[c] = uchar;
    301         UCharToPseud2[uchar & 0x00ff] = c;
    302     }
    303     /* initialize Arabic letters */
    304     for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
    305         c = (uint8_t)columns[i];
    306         pseudoToUChar[c] = uchar;
    307         UCharToPseud2[uchar & 0x00ff] = c;
    308     }
    309     /* initialize Hebrew letters */
    310     for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
    311         c = (uint8_t)columns[i];
    312         pseudoToUChar[c] = uchar;
    313         UCharToPseud2[uchar & 0x00ff] = c;
    314     }
    315     /* initialize Unassigned code points */
    316     for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
    317         c = (uint8_t)columns[i];
    318         pseudoToUChar[c] = uchar;
    319         UCharToPseud2[uchar & 0x00ff] = c;
    320     }
    321     /* initialize Latin lower case letters */
    322     for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
    323         c = (uint8_t)columns[i];
    324         pseudoToUChar[c] = uchar;
    325         UCharToPseudo[uchar & 0x00ff] = c;
    326     }
    327     tablesInitialized = TRUE;
    328 }
    329 
    330 /*----------------------------------------------------------------------*/
    331 
    332 static int pseudoToU16(const int length, const char * input, UChar * output)
    333 /*  This function converts a pseudo-Bidi string into a UChar string.
    334     It returns the length of the UChar string.
    335 */
    336 {
    337     int             i;
    338     if (!tablesInitialized) {
    339         buildPseudoTables();
    340     }
    341     for (i = 0; i < length; i++)
    342         output[i] = pseudoToUChar[(uint8_t)input[i]];
    343     return length;
    344 }
    345 
    346 /*----------------------------------------------------------------------*/
    347 
    348 static int u16ToPseudo(const int length, const UChar * input, char * output)
    349 /*  This function converts a UChar string into a pseudo-Bidi string.
    350     It returns the length of the pseudo-Bidi string.
    351 */
    352 {
    353     int             i;
    354     UChar           uchar;
    355     if (!tablesInitialized) {
    356         buildPseudoTables();
    357     }
    358     for (i = 0; i < length; i++)
    359     {
    360         uchar = input[i];
    361         output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
    362                                         UCharToPseud2[uchar & 0x00ff];
    363     }
    364     output[length] = '\0';
    365     return length;
    366 }
    367 
    368 static char * formatLevels(UBiDi *bidi, char *buffer) {
    369     UErrorCode ec = U_ZERO_ERROR;
    370     const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
    371     int len = ubidi_getLength(bidi);
    372     char c;
    373     int i, k;
    374 
    375     if(U_FAILURE(ec)) {
    376         strcpy(buffer, "BAD LEVELS");
    377         return buffer;
    378     }
    379     for (i=0; i<len; i++) {
    380         k = gotLevels[i];
    381         if (k >= sizeof(columns))
    382             c = '+';
    383         else
    384             c = columns[k];
    385         buffer[i] = c;
    386     }
    387     buffer[len] = '\0';
    388     return buffer;
    389 }
    390 static const char *reorderingModeNames[] = {
    391     "UBIDI_REORDER_DEFAULT",
    392     "UBIDI_REORDER_NUMBERS_SPECIAL",
    393     "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
    394     "UBIDI_REORDER_RUNS_ONLY",
    395     "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
    396     "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
    397     "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
    398 
    399 static char *reorderingOptionNames(char *buffer, int options) {
    400     buffer[0] = 0;
    401     if (options & UBIDI_OPTION_INSERT_MARKS) {
    402         strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
    403     }
    404     if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
    405         strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
    406     }
    407     if (options & UBIDI_OPTION_STREAMING) {
    408         strcat(buffer, " UBIDI_OPTION_STREAMING");
    409     }
    410     return buffer;
    411 }
    412 
    413 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
    414 /* src and dst are char arrays encoded as pseudo Bidi */
    415 {
    416     /* Since calls to log_err with a \n within the pattern increment the
    417      * error count, new lines are issued via fputs, except when we want the
    418      * increment to happen.
    419      */
    420     UErrorCode errorCode=U_ZERO_ERROR;
    421     int32_t i, length = ubidi_getProcessedLength(bidi);
    422     const UBiDiLevel *levels;
    423     char levelChars[MAXLEN];
    424     UBiDiLevel lev;
    425     int32_t runCount;
    426     char buffer[100];
    427     log_err("========================================"); fputs("\n", stderr);
    428     levels = ubidi_getLevels(bidi, &errorCode);
    429     if (U_FAILURE(errorCode)) {
    430         strcpy(levelChars, "BAD LEVELS");
    431     } else {
    432         log_err("Processed length: %d", length); fputs("\n", stderr);
    433         for (i = 0; i < length; i++) {
    434             lev = levels[i];
    435             if (lev < sizeof(columns)) {
    436                 levelChars[i] = columns[lev];
    437             } else {
    438                 levelChars[i] = '+';
    439             }
    440         }
    441         levelChars[length] = 0;
    442     }
    443     log_err("Levels: %s", levelChars); fputs("\n", stderr);
    444     log_err("Source: %s", src); fputs("\n", stderr);
    445     log_err("Result: %s", dst); fputs("\n", stderr);
    446     log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
    447     log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
    448     i = ubidi_getReorderingMode(bidi);
    449     log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
    450     fputs("\n", stderr);
    451     i = ubidi_getReorderingOptions(bidi);
    452     log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
    453     fputs("\n", stderr);
    454     runCount = ubidi_countRuns(bidi, &errorCode);
    455     if (U_FAILURE(errorCode)) {
    456         log_err( "BAD RUNS");
    457     } else {
    458         log_err("Runs: %d => logicalStart.length/level: ", runCount);
    459         for (i = 0; i < runCount; i++) {
    460             UBiDiDirection dir;
    461             int32_t start, len;
    462             dir = ubidi_getVisualRun(bidi, i, &start, &len);
    463             log_err(" %d.%d/%d", start, len, dir);
    464         }
    465     }
    466     fputs("\n", stderr);
    467 }
    468 
    469 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
    470 {
    471     /* No test for []{} since they have special meaning for pseudo Bidi */
    472     static char mates1Chars[] = "<>()";
    473     static char mates2Chars[] = "><)(";
    474     UBiDiLevel level;
    475     int k, len;
    476 
    477     if (c1 == c2) {
    478         return TRUE;
    479     }
    480     /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
    481        so we use the appropriate run's level, which is good for all cases.
    482      */
    483     ubidi_getLogicalRun(bidi, i, NULL, &level);
    484     if ((level & 1) == 0) {
    485         return FALSE;
    486     }
    487     len = strlen(mates1Chars);
    488     for (k = 0; k < len; k++) {
    489         if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
    490             return TRUE;
    491         }
    492     }
    493     return FALSE;
    494 }
    495 
    496 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
    497 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
    498 {
    499     int32_t i, idx, logLimit, visLimit;
    500     UBool testOK, errMap, errDst;
    501     UErrorCode errorCode=U_ZERO_ERROR;
    502     int32_t visMap[MAXLEN];
    503     int32_t logMap[MAXLEN];
    504     char accumSrc[MAXLEN];
    505     char accumDst[MAXLEN];
    506     ubidi_getVisualMap(bidi, visMap, &errorCode);
    507     ubidi_getLogicalMap(bidi, logMap, &errorCode);
    508     if (U_FAILURE(errorCode)) {
    509         log_err("Error #1 invoking ICU within checkWhatYouCan\n");
    510         return FALSE;
    511     }
    512 
    513     testOK = TRUE;
    514     errMap = errDst = FALSE;
    515     logLimit = ubidi_getProcessedLength(bidi);
    516     visLimit = ubidi_getResultLength(bidi);
    517     memset(accumSrc, '?', logLimit);
    518     memset(accumDst, '?', visLimit);
    519 
    520     for (i = 0; i < logLimit; i++) {
    521         idx = ubidi_getVisualIndex(bidi, i, &errorCode);
    522         if (idx != logMap[i]) {
    523             errMap = TRUE;
    524         }
    525         if (idx == UBIDI_MAP_NOWHERE) {
    526             continue;
    527         }
    528         if (idx >= visLimit) {
    529             continue;
    530         }
    531         accumDst[idx] = srcChars[i];
    532         if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
    533             errDst = TRUE;
    534         }
    535     }
    536     accumDst[visLimit] = 0;
    537     if (U_FAILURE(errorCode)) {
    538         log_err("Error #2 invoking ICU within checkWhatYouCan\n");
    539         return FALSE;
    540     }
    541     if (errMap) {
    542         if (testOK) {
    543             printCaseInfo(bidi, srcChars, dstChars);
    544             testOK = FALSE;
    545         }
    546         log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
    547         log_err("Map    :");
    548         for (i = 0; i < logLimit; i++) {
    549             log_err(" %d", logMap[i]);
    550         }
    551         fputs("\n", stderr);
    552         log_err("Indexes:");
    553         for (i = 0; i < logLimit; i++) {
    554             log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
    555         }
    556         fputs("\n", stderr);
    557     }
    558     if (errDst) {
    559         if (testOK) {
    560             printCaseInfo(bidi, srcChars, dstChars);
    561             testOK = FALSE;
    562         }
    563         log_err("Source does not map to Result\n");
    564         log_err("We got: %s", accumDst); fputs("\n", stderr);
    565     }
    566 
    567     errMap = errDst = FALSE;
    568     for (i = 0; i < visLimit; i++) {
    569         idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
    570         if (idx != visMap[i]) {
    571             errMap = TRUE;
    572         }
    573         if (idx == UBIDI_MAP_NOWHERE) {
    574             continue;
    575         }
    576         if (idx >= logLimit) {
    577             continue;
    578         }
    579         accumSrc[idx] = dstChars[i];
    580         if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
    581             errDst = TRUE;
    582         }
    583     }
    584     accumSrc[logLimit] = 0;
    585     if (U_FAILURE(errorCode)) {
    586         log_err("Error #3 invoking ICU within checkWhatYouCan\n");
    587         return FALSE;
    588     }
    589     if (errMap) {
    590         if (testOK) {
    591             printCaseInfo(bidi, srcChars, dstChars);
    592             testOK = FALSE;
    593         }
    594         log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
    595         log_err("Map    :");
    596         for (i = 0; i < visLimit; i++) {
    597             log_err(" %d", visMap[i]);
    598         }
    599         fputs("\n", stderr);
    600         log_err("Indexes:");
    601         for (i = 0; i < visLimit; i++) {
    602             log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
    603         }
    604         fputs("\n", stderr);
    605     }
    606     if (errDst) {
    607         if (testOK) {
    608             printCaseInfo(bidi, srcChars, dstChars);
    609             testOK = FALSE;
    610         }
    611         log_err("Result does not map to Source\n");
    612         log_err("We got: %s", accumSrc);
    613         fputs("\n", stderr);
    614     }
    615     return testOK;
    616 }
    617 
    618 static void
    619 testReorder(void) {
    620     static const char* const logicalOrder[] ={
    621             "del(KC)add(K.C.&)",
    622             "del(QDVT) add(BVDL)",
    623             "del(PQ)add(R.S.)T)U.&",
    624             "del(LV)add(L.V.) L.V.&",
    625             "day  0  R  DPDHRVR dayabbr",
    626             "day  1  H  DPHPDHDA dayabbr",
    627             "day  2   L  DPBLENDA dayabbr",
    628             "day  3  J  DPJQVM  dayabbr",
    629             "day  4   I  DPIQNF    dayabbr",
    630             "day  5  M  DPMEG  dayabbr",
    631             "helloDPMEG",
    632             "hello WXYZ"
    633     };
    634     static const char* const visualOrder[]={
    635             "del(CK)add(&.C.K)",
    636             "del(TVDQ) add(LDVB)",
    637             "del(QP)add(&.U(T(.S.R",
    638             "del(VL)add(&.V.L (.V.L",
    639             "day  0  RVRHDPD  R dayabbr",
    640             "day  1  ADHDPHPD  H dayabbr",
    641             "day  2   ADNELBPD  L dayabbr",
    642             "day  3  MVQJPD  J  dayabbr",
    643             "day  4   FNQIPD  I    dayabbr",
    644             "day  5  GEMPD  M  dayabbr",
    645             "helloGEMPD",
    646             "hello ZYXW"
    647     };
    648     static const char* const visualOrder1[]={
    649             ")K.C.&(dda)KC(led",
    650             ")BVDL(dda )QDVT(led",
    651             "R.S.(T(U.&(dda)PQ(led",
    652             "L.V.( L.V.&(dda)LV(led",
    653             "rbbayad R  DPDHRVR  0  yad",
    654             "rbbayad H  DPHPDHDA  1  yad",
    655             "rbbayad L  DPBLENDA   2  yad",
    656             "rbbayad  J  DPJQVM  3  yad",
    657             "rbbayad    I  DPIQNF   4  yad",
    658             "rbbayad  M  DPMEG  5  yad",
    659             "DPMEGolleh",
    660             "WXYZ olleh"
    661     };
    662 
    663     static const char* const visualOrder2[]={
    664             "@)@K.C.&@(dda)@KC@(led",
    665             "@)@BVDL@(dda )@QDVT@(led",
    666             "R.S.)T)U.&@(dda)@PQ@(led",
    667             "L.V.) L.V.&@(dda)@LV@(led",
    668             "rbbayad @R  DPDHRVR@  0  yad",
    669             "rbbayad @H  DPHPDHDA@  1  yad",
    670             "rbbayad @L  DPBLENDA@   2  yad",
    671             "rbbayad  @J  DPJQVM@  3  yad",
    672             "rbbayad    @I  DPIQNF@   4  yad",
    673             "rbbayad  @M  DPMEG@  5  yad",
    674             "DPMEGolleh",
    675             "WXYZ@ olleh"
    676     };
    677     static const char* const visualOrder3[]={
    678             ")K.C.&(KC)dda(led",
    679             ")BVDL(ddaQDVT) (led",
    680             "R.S.)T)U.&(PQ)dda(led",
    681             "L.V.) L.V.&(LV)dda(led",
    682             "rbbayad DPDHRVR   R  0 yad",
    683             "rbbayad DPHPDHDA   H  1 yad",
    684             "rbbayad DPBLENDA     L 2 yad",
    685             "rbbayad  DPJQVM   J  3 yad",
    686             "rbbayad    DPIQNF     I 4 yad",
    687             "rbbayad  DPMEG   M  5 yad",
    688             "DPMEGolleh",
    689             "WXYZ olleh"
    690     };
    691     static const char* const visualOrder4[]={
    692             "del(add(CK(.C.K)",
    693             "del( (TVDQadd(LDVB)",
    694             "del(add(QP(.U(T(.S.R",
    695             "del(add(VL(.V.L (.V.L",
    696             "day 0  R   RVRHDPD dayabbr",
    697             "day 1  H   ADHDPHPD dayabbr",
    698             "day 2 L     ADNELBPD dayabbr",
    699             "day 3  J   MVQJPD  dayabbr",
    700             "day 4 I     FNQIPD    dayabbr",
    701             "day 5  M   GEMPD  dayabbr",
    702             "helloGEMPD",
    703             "hello ZYXW"
    704     };
    705     char formatChars[MAXLEN];
    706     UErrorCode ec = U_ZERO_ERROR;
    707     UBiDi* bidi = ubidi_open();
    708     int i;
    709 
    710     log_verbose("\nEntering TestReorder\n\n");
    711 
    712     for(i=0;i<LENGTHOF(logicalOrder);i++){
    713         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    714         int32_t destSize = srcSize*2;
    715         UChar src[MAXLEN];
    716         UChar dest[MAXLEN];
    717         char chars[MAXLEN];
    718         log_verbose("Testing L2V #1 for case %d\n", i);
    719         pseudoToU16(srcSize,logicalOrder[i],src);
    720         ec = U_ZERO_ERROR;
    721         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    722         if(U_FAILURE(ec)){
    723             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    724                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    725         }
    726         /* try pre-flighting */
    727         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
    728         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    729             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    730         }else if(destSize!=srcSize){
    731             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    732         }else{
    733             ec= U_ZERO_ERROR;
    734         }
    735         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
    736         u16ToPseudo(destSize,dest,chars);
    737         if(destSize!=srcSize){
    738             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    739         }else if(strcmp(visualOrder[i],chars)!=0){
    740             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
    741                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    742                     logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
    743         }
    744         checkWhatYouCan(bidi, logicalOrder[i], chars);
    745     }
    746 
    747     for(i=0;i<LENGTHOF(logicalOrder);i++){
    748         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    749         int32_t destSize = srcSize*2;
    750         UChar src[MAXLEN];
    751         UChar dest[MAXLEN];
    752         char chars[MAXLEN];
    753         log_verbose("Testing L2V #2 for case %d\n", i);
    754         pseudoToU16(srcSize,logicalOrder[i],src);
    755         ec = U_ZERO_ERROR;
    756         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    757         if(U_FAILURE(ec)){
    758             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    759                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    760         }
    761         /* try pre-flighting */
    762         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    763         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    764             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    765         }else if(destSize!=srcSize){
    766             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    767         }else{
    768             ec= U_ZERO_ERROR;
    769         }
    770         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    771         u16ToPseudo(destSize,dest,chars);
    772         if(destSize!=srcSize){
    773             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    774         }else if(strcmp(visualOrder1[i],chars)!=0){
    775             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
    776                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    777                     logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
    778         }
    779     }
    780 
    781     for(i=0;i<LENGTHOF(logicalOrder);i++){
    782         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    783         int32_t destSize = srcSize*2;
    784         UChar src[MAXLEN];
    785         UChar dest[MAXLEN];
    786         char chars[MAXLEN];
    787         log_verbose("Testing V2L #3 for case %d\n", i);
    788         pseudoToU16(srcSize,logicalOrder[i],src);
    789         ec = U_ZERO_ERROR;
    790         ubidi_setInverse(bidi,TRUE);
    791         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    792         if(U_FAILURE(ec)){
    793             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    794                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    795         }
    796                 /* try pre-flighting */
    797         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    798         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    799             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    800         }else{
    801             ec= U_ZERO_ERROR;
    802         }
    803         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    804         u16ToPseudo(destSize,dest,chars);
    805         if(strcmp(visualOrder2[i],chars)!=0){
    806             log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
    807                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    808                     logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
    809         }
    810     }
    811         /* Max Explicit level */
    812     for(i=0;i<LENGTHOF(logicalOrder);i++){
    813         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    814         int32_t destSize = srcSize*2;
    815         UChar src[MAXLEN];
    816         UChar dest[MAXLEN];
    817         char chars[MAXLEN];
    818         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    819         log_verbose("Testing V2L #4 for case %d\n", i);
    820         pseudoToU16(srcSize,logicalOrder[i],src);
    821         ec = U_ZERO_ERROR;
    822         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    823         if(U_FAILURE(ec)){
    824             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    825                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    826         }
    827                 /* try pre-flighting */
    828         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
    829         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    830             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    831         }else if(destSize!=srcSize){
    832             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    833         }else{
    834             ec = U_ZERO_ERROR;
    835         }
    836         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
    837         u16ToPseudo(destSize,dest,chars);
    838         if(destSize!=srcSize){
    839             log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
    840         }else if(strcmp(visualOrder3[i],chars)!=0){
    841             log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
    842                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    843                     logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
    844         }
    845     }
    846     for(i=0;i<LENGTHOF(logicalOrder);i++){
    847         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    848         int32_t destSize = srcSize*2;
    849         UChar src[MAXLEN];
    850         UChar dest[MAXLEN];
    851         char chars[MAXLEN];
    852         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    853         log_verbose("Testing V2L #5 for case %d\n", i);
    854         pseudoToU16(srcSize,logicalOrder[i],src);
    855         ec = U_ZERO_ERROR;
    856         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    857         if(U_FAILURE(ec)){
    858             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    859                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    860         }
    861         /* try pre-flighting */
    862         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    863         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    864             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    865         }else{
    866             ec= U_ZERO_ERROR;
    867         }
    868         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    869         u16ToPseudo(destSize,dest,chars);
    870         if(strcmp(visualOrder4[i],chars)!=0){
    871             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
    872                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    873                     logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
    874         }
    875     }
    876     ubidi_close(bidi);
    877 
    878     log_verbose("\nExiting TestReorder\n\n");
    879 }
    880 
    881 static void
    882 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
    883     const uint8_t *dirProps=test->text+lineStart;
    884     const UBiDiLevel *levels=test->levels;
    885     const uint8_t *visualMap=test->visualMap;
    886     int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
    887     UErrorCode errorCode=U_ZERO_ERROR;
    888     UBiDiLevel level, level2;
    889 
    890     if (countRunsFirst) {
    891         log_verbose("Calling ubidi_countRuns() first.\n");
    892 
    893         runCount = ubidi_countRuns(pBiDi, &errorCode);
    894 
    895         if(U_FAILURE(errorCode)) {
    896             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
    897             return;
    898         }
    899     } else {
    900         log_verbose("Calling ubidi_getLogicalMap() first.\n");
    901     }
    902 
    903     _testReordering(pBiDi, testNumber);
    904 
    905     for(i=0; i<len; ++i) {
    906         log_verbose("%3d %3d %.*s%-3s @%d\n",
    907                 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
    908                 dirPropNames[dirProps[i]],
    909                 ubidi_getVisualIndex(pBiDi, i, &errorCode));
    910     }
    911 
    912     log_verbose("\n-----levels:");
    913     for(i=0; i<len; ++i) {
    914         if(i>0) {
    915             log_verbose(",");
    916         }
    917         log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
    918     }
    919 
    920     log_verbose("\n--reordered:");
    921     for(i=0; i<len; ++i) {
    922         if(i>0) {
    923             log_verbose(",");
    924         }
    925         log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
    926     }
    927     log_verbose("\n");
    928 
    929     if(test->direction!=ubidi_getDirection(pBiDi)) {
    930         log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
    931     }
    932 
    933     if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
    934         log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
    935     }
    936 
    937     for(i=0; i<len; ++i) {
    938         if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
    939             log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
    940             return;
    941         }
    942     }
    943 
    944     for(i=0; i<len; ++i) {
    945         logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
    946         if(U_FAILURE(errorCode)) {
    947             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
    948             return;
    949         }
    950         if(visualMap[i]!=logicalIndex) {
    951             log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
    952             return;
    953         }
    954     }
    955 
    956     if (! countRunsFirst) {
    957         runCount=ubidi_countRuns(pBiDi, &errorCode);
    958         if(U_FAILURE(errorCode)) {
    959             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
    960             return;
    961         }
    962     }
    963 
    964     for(logicalIndex=0; logicalIndex<len;) {
    965         level=ubidi_getLevelAt(pBiDi, logicalIndex);
    966         ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
    967         if(level!=level2) {
    968             log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
    969                     "wrong level %d instead of %d\n",
    970                     testNumber, logicalIndex, level, level2);
    971         }
    972         if(--runCount<0) {
    973             log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
    974                     "compared to %d=ubidi_countRuns()\n",
    975                     testNumber, ubidi_countRuns(pBiDi, &errorCode));
    976             return;
    977         }
    978     }
    979     if(runCount!=0) {
    980         log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
    981                 "compared to %d=ubidi_getRunCount()\n",
    982                 testNumber, ubidi_countRuns(pBiDi, &errorCode));
    983         return;
    984     }
    985 
    986     log_verbose("\n\n");
    987 }
    988 
    989 static void
    990 _testReordering(UBiDi *pBiDi, int testNumber) {
    991     int32_t
    992         logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
    993         visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
    994     UErrorCode errorCode=U_ZERO_ERROR;
    995     const UBiDiLevel *levels;
    996     int32_t i, length=ubidi_getLength(pBiDi),
    997                destLength=ubidi_getResultLength(pBiDi);
    998     int32_t runCount, visualIndex, logicalStart, runLength;
    999     UBool odd;
   1000 
   1001     if(length<=0) {
   1002         return;
   1003     }
   1004 
   1005     /* get the logical and visual maps from the object */
   1006     ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
   1007     if(U_FAILURE(errorCode)) {
   1008         log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1009         return;
   1010     }
   1011 
   1012     ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
   1013     if(U_FAILURE(errorCode)) {
   1014         log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1015         return;
   1016     }
   1017 
   1018     /* invert them both */
   1019     ubidi_invertMap(logicalMap1, visualMap2, length);
   1020     ubidi_invertMap(visualMap1, logicalMap2, destLength);
   1021 
   1022     /* get them from the levels array, too */
   1023     levels=ubidi_getLevels(pBiDi, &errorCode);
   1024 
   1025     if(U_FAILURE(errorCode)) {
   1026         log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1027         return;
   1028     }
   1029 
   1030     ubidi_reorderLogical(levels, length, logicalMap3);
   1031     ubidi_reorderVisual(levels, length, visualMap3);
   1032 
   1033     /* get the visual map from the runs, too */
   1034     runCount=ubidi_countRuns(pBiDi, &errorCode);
   1035     if(U_FAILURE(errorCode)) {
   1036         log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1037         return;
   1038     }
   1039     log_verbose("\n----%2d runs:", runCount);
   1040     visualIndex=0;
   1041     for(i=0; i<runCount; ++i) {
   1042         odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
   1043         log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
   1044         if(UBIDI_LTR==odd) {
   1045             do { /* LTR */
   1046                 visualMap4[visualIndex++]=logicalStart++;
   1047             } while(--runLength>0);
   1048         } else {
   1049             logicalStart+=runLength;   /* logicalLimit */
   1050             do { /* RTL */
   1051                 visualMap4[visualIndex++]=--logicalStart;
   1052             } while(--runLength>0);
   1053         }
   1054     }
   1055     log_verbose("\n");
   1056 
   1057     /* print all the maps */
   1058     log_verbose("logical maps:\n");
   1059     for(i=0; i<length; ++i) {
   1060         log_verbose("%4d", logicalMap1[i]);
   1061     }
   1062     log_verbose("\n");
   1063     for(i=0; i<length; ++i) {
   1064         log_verbose("%4d", logicalMap2[i]);
   1065     }
   1066     log_verbose("\n");
   1067     for(i=0; i<length; ++i) {
   1068         log_verbose("%4d", logicalMap3[i]);
   1069     }
   1070 
   1071     log_verbose("\nvisual maps:\n");
   1072     for(i=0; i<destLength; ++i) {
   1073         log_verbose("%4d", visualMap1[i]);
   1074     }
   1075     log_verbose("\n");
   1076     for(i=0; i<destLength; ++i) {
   1077         log_verbose("%4d", visualMap2[i]);
   1078     }
   1079     log_verbose("\n");
   1080     for(i=0; i<length; ++i) {
   1081         log_verbose("%4d", visualMap3[i]);
   1082     }
   1083     log_verbose("\n");
   1084     for(i=0; i<length; ++i) {
   1085         log_verbose("%4d", visualMap4[i]);
   1086     }
   1087     log_verbose("\n");
   1088 
   1089     /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
   1090     for(i=0; i<length; ++i) {
   1091         if(logicalMap1[i]!=logicalMap2[i]) {
   1092             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
   1093             break;
   1094         }
   1095         if(logicalMap1[i]!=logicalMap3[i]) {
   1096             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
   1097             break;
   1098         }
   1099 
   1100         if(visualMap1[i]!=visualMap2[i]) {
   1101             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
   1102             break;
   1103         }
   1104         if(visualMap1[i]!=visualMap3[i]) {
   1105             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
   1106             break;
   1107         }
   1108         if(visualMap1[i]!=visualMap4[i]) {
   1109             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
   1110             break;
   1111         }
   1112 
   1113         if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
   1114             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
   1115             break;
   1116         }
   1117         if(U_FAILURE(errorCode)) {
   1118             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1119             break;
   1120         }
   1121         if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
   1122             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
   1123             break;
   1124         }
   1125         if(U_FAILURE(errorCode)) {
   1126             log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1127             break;
   1128         }
   1129     }
   1130 }
   1131 
   1132 #define RETURN_IF_BAD_ERRCODE(x)    \
   1133     if (U_FAILURE(errorCode)) {      \
   1134         log_err("\nbad errorCode %d at %s\n", errorCode, (x));  \
   1135         return;     \
   1136     }               \
   1137 
   1138 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
   1139 
   1140 static void testGetBaseDirection(void) {
   1141     UBiDiDirection dir;
   1142     int i;
   1143 
   1144 /* Test Data */
   1145     static const UChar
   1146 /*Mixed Start with L*/
   1147     stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
   1148 /*Mixed Start with AL*/
   1149     stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1150 /*Mixed Start with R*/
   1151     stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1152 /*All AL (Arabic. Persian)*/
   1153     stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1154 /*All R (Hebrew etc.)*/
   1155     stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1156 /*All L (English)*/
   1157     stringEnglish[]={0x71, 0x61, 0x66, 0},
   1158 /*Mixed Start with weak AL an then L*/
   1159     stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
   1160 /*Mixed Start with weak L and then AL*/
   1161     stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1162 /*Empty*/
   1163     stringEmpty[]={0},
   1164 /*Surrogate Char.*/
   1165     stringSurrogateChar[]={0xD800, 0xDC00, 0},
   1166 /*Invalid UChar*/
   1167     stringInvalidUchar[]={-1},
   1168 /*All weak L (English Digits)*/
   1169     stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
   1170 /*All weak AL (Arabic Digits)*/
   1171     stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
   1172 /*First L (English) others are R (Hebrew etc.) */
   1173     stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1174 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
   1175     stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
   1176 
   1177     static const struct {
   1178         const UChar *s;
   1179         int32_t length;
   1180     } testCases[]={
   1181         STRING_TEST_CASE(stringMixedEnglishFirst),
   1182         STRING_TEST_CASE(stringMixedArabicFirst),
   1183         STRING_TEST_CASE(stringMixedHebrewFirst),
   1184         STRING_TEST_CASE(stringPersian),
   1185         STRING_TEST_CASE(stringHebrew),
   1186         STRING_TEST_CASE(stringEnglish),
   1187         STRING_TEST_CASE(stringStartWeakAL),
   1188         STRING_TEST_CASE(stringStartWeakL),
   1189         STRING_TEST_CASE(stringEmpty),
   1190         STRING_TEST_CASE(stringSurrogateChar),
   1191         STRING_TEST_CASE(stringInvalidUchar),
   1192         STRING_TEST_CASE(stringAllEnglishDigits),
   1193         STRING_TEST_CASE(stringAllArabicDigits),
   1194         STRING_TEST_CASE(stringFirstL),
   1195         STRING_TEST_CASE(stringLastR),
   1196     };
   1197 
   1198 /* Expected results */
   1199     static const UBiDiDirection expectedDir[] ={
   1200         UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
   1201         UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
   1202         UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
   1203         UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
   1204         UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
   1205     };
   1206 
   1207     log_verbose("testGetBaseDirection() with %u test cases ---\n",
   1208     LENGTHOF(testCases));
   1209 /* Run Tests */
   1210      for(i=0; i<LENGTHOF(testCases); ++i) {
   1211         dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
   1212         log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
   1213         if (dir != expectedDir[i])
   1214             log_err("\nFailed getBaseDirection case %d Expected  %d \tReceived %d\n",
   1215             i, expectedDir[i], dir);
   1216     }
   1217 
   1218 /* Misc. tests */
   1219 /* NULL string */
   1220     dir = ubidi_getBaseDirection(NULL, 3);
   1221     if (dir != UBIDI_NEUTRAL )
   1222         log_err("\nFailed getBaseDirection for NULL string " ,
   1223         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1224 /*All L- English string and length=-3 */
   1225     dir = ubidi_getBaseDirection( stringEnglish, -3);
   1226     if (dir != UBIDI_NEUTRAL )
   1227         log_err("\nFailed getBaseDirection for string w length= -3 ",
   1228         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1229 /*All L- English string and length=-1 */
   1230     dir = ubidi_getBaseDirection( stringEnglish, -1);
   1231     if (dir != UBIDI_LTR )
   1232         log_err("\nFailed getBaseDirection for English string w length= -1 ",
   1233         "\nExpected  %d \nReceived %d", UBIDI_LTR, dir);
   1234 /*All AL- Persian string and length=-1 */
   1235     dir = ubidi_getBaseDirection( stringPersian, -1);
   1236     if (dir != UBIDI_RTL )
   1237         log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
   1238         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1239 /*All R- Hebrew string and length=-1 */
   1240     dir = ubidi_getBaseDirection( stringHebrew, -1);
   1241     if (dir != UBIDI_RTL )
   1242         log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
   1243         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1244 /*All weak L- English digits string and length=-1 */
   1245     dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
   1246     if (dir != UBIDI_NEUTRAL )
   1247         log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
   1248         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1249 /*All weak AL- Arabic digits string and length=-1 */
   1250     dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
   1251     if (dir != UBIDI_NEUTRAL )
   1252         log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
   1253         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1254 
   1255 }
   1256 
   1257 
   1258 static void doMisc(void) {
   1259 /* Miscellaneous tests to exercize less popular code paths */
   1260     UBiDi *bidi, *bidiLine;
   1261     UChar src[MAXLEN], dest[MAXLEN];
   1262     int32_t srcLen, destLen, runCount, i;
   1263     UBiDiLevel level;
   1264     UBiDiDirection dir;
   1265     int32_t map[MAXLEN];
   1266     UErrorCode errorCode=U_ZERO_ERROR;
   1267     static const int32_t srcMap[6] = {0,1,-1,5,4};
   1268     static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
   1269 
   1270     bidi = ubidi_openSized(120, 66, &errorCode);
   1271     if (bidi == NULL) {
   1272         log_err("Error with openSized(120, 66)\n");
   1273         return;
   1274     }
   1275     bidiLine = ubidi_open();
   1276     if (bidi == NULL) {
   1277         log_err("Error with open()\n");
   1278         return;
   1279     }
   1280 
   1281     destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
   1282     if (destLen != 0) {
   1283         log_err("\nwriteReverse should return zero length, ",
   1284                 "returned %d instead\n", destLen);
   1285     }
   1286     RETURN_IF_BAD_ERRCODE("#1#");
   1287 
   1288     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1289     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1290     if (destLen != 0) {
   1291         log_err("\nwriteReordered should return zero length, ",
   1292                 "returned %d instead\n", destLen);
   1293     }
   1294     RETURN_IF_BAD_ERRCODE("#2#");
   1295 
   1296     srcLen = u_unescape("abc       ", src, MAXLEN);
   1297     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1298     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1299     for (i = 3; i < 6; i++) {
   1300         level = ubidi_getLevelAt(bidiLine, i);
   1301         if (level != UBIDI_RTL) {
   1302             log_err("\nTrailing space at index %d should get paragraph level"
   1303                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1304         }
   1305     }
   1306     RETURN_IF_BAD_ERRCODE("#3#");
   1307 
   1308     srcLen = u_unescape("abc       def", src, MAXLEN);
   1309     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1310     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1311     for (i = 3; i < 6; i++) {
   1312         level = ubidi_getLevelAt(bidiLine, i);
   1313         if (level != UBIDI_RTL) {
   1314             log_err("\nTrailing space at index %d should get paragraph level"
   1315                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1316         }
   1317     }
   1318     RETURN_IF_BAD_ERRCODE("#4#");
   1319 
   1320     srcLen = u_unescape("abcdefghi    ", src, MAXLEN);
   1321     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1322     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1323     for (i = 3; i < 6; i++) {
   1324         level = ubidi_getLevelAt(bidiLine, i);
   1325         if (level != 2) {
   1326             log_err("\nTrailing char at index %d should get level 2, "
   1327                     "got %d instead\n", i, level);
   1328         }
   1329     }
   1330     RETURN_IF_BAD_ERRCODE("#5#");
   1331 
   1332     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
   1333     srcLen = u_unescape("\\u200eabc       def", src, MAXLEN);
   1334     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1335     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1336     destLen = ubidi_getResultLength(bidiLine);
   1337     if (destLen != 5) {
   1338         log_err("\nWrong result length, should be 5, got %d\n", destLen);
   1339     }
   1340     RETURN_IF_BAD_ERRCODE("#6#");
   1341 
   1342     srcLen = u_unescape("abcdefghi", src, MAXLEN);
   1343     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1344     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1345     dir = ubidi_getDirection(bidiLine);
   1346     if (dir != UBIDI_LTR) {
   1347         log_err("\nWrong direction #1, should be %d, got %d\n",
   1348                 UBIDI_LTR, dir);
   1349     }
   1350     RETURN_IF_BAD_ERRCODE("#7#");
   1351 
   1352     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1353     runCount = ubidi_countRuns(bidi, &errorCode);
   1354     if (runCount != 0) {
   1355         log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
   1356     }
   1357     RETURN_IF_BAD_ERRCODE("#8#");
   1358 
   1359     srcLen = u_unescape("          ", src, MAXLEN);
   1360     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1361     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1362     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1363     if (runCount != 1) {
   1364         log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
   1365     }
   1366     RETURN_IF_BAD_ERRCODE("#9#");
   1367 
   1368     srcLen = u_unescape("a\\u05d0        bc", src, MAXLEN);
   1369     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1370     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1371     dir = ubidi_getDirection(bidi);
   1372     if (dir != UBIDI_MIXED) {
   1373         log_err("\nWrong direction #2, should be %d, got %d\n",
   1374                 UBIDI_MIXED, dir);
   1375     }
   1376     dir = ubidi_getDirection(bidiLine);
   1377     if (dir != UBIDI_MIXED) {
   1378         log_err("\nWrong direction #3, should be %d, got %d\n",
   1379                 UBIDI_MIXED, dir);
   1380     }
   1381     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1382     if (runCount != 2) {
   1383         log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
   1384     }
   1385     RETURN_IF_BAD_ERRCODE("#10#");
   1386 
   1387     ubidi_invertMap(srcMap, map, 5);
   1388     if (memcmp(dstMap, map, sizeof(dstMap))) {
   1389         log_err("\nUnexpected inverted Map, got ");
   1390         for (i = 0; i < 6; i++) {
   1391             log_err("%d ", map[i]);
   1392         }
   1393         log_err("\n");
   1394     }
   1395 
   1396     /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
   1397     srcLen = u_unescape("abc\\u200e", src, MAXLEN);
   1398     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1399     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   1400               UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
   1401     if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
   1402         log_err("\nWrong result #1, should be 'abc', got '%s'\n",
   1403                 aescstrdup(dest, destLen));
   1404     }
   1405     RETURN_IF_BAD_ERRCODE("#11#");
   1406 
   1407     /* test inverse Bidi with marks and contextual orientation */
   1408     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1409     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   1410     ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1411     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1412     if (destLen != 0) {
   1413         log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
   1414     }
   1415     RETURN_IF_BAD_ERRCODE("#12#");
   1416     srcLen = u_unescape("   ", src, MAXLEN);
   1417     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1418     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1419     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1420         log_err("\nWrong result #3, should be '   ', got '%s'\n",
   1421                 aescstrdup(dest, destLen));
   1422     }
   1423     RETURN_IF_BAD_ERRCODE("#13#");
   1424     srcLen = u_unescape("abc", src, MAXLEN);
   1425     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1426     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1427     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1428         log_err("\nWrong result #4, should be 'abc', got '%s'\n",
   1429                 aescstrdup(dest, destLen));
   1430     }
   1431     RETURN_IF_BAD_ERRCODE("#14#");
   1432     srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
   1433     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1434     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1435     srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
   1436     if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1437         log_err("\nWrong result #5, should be '%s', got '%s'\n",
   1438                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1439     }
   1440     RETURN_IF_BAD_ERRCODE("#15#");
   1441     srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
   1442     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1443     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1444     srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
   1445     if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1446         log_err("\nWrong result #6, should be '%s', got '%s'\n",
   1447                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1448     }
   1449     RETURN_IF_BAD_ERRCODE("#16#");
   1450     srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
   1451     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1452     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1453     srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
   1454     if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1455         log_err("\nWrong result #7, should be '%s', got '%s'\n",
   1456                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1457     }
   1458     RETURN_IF_BAD_ERRCODE("#17#");
   1459     srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
   1460     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1461     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1462     srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
   1463     if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1464         log_err("\nWrong result #8, should be '%s', got '%s'\n",
   1465                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1466     }
   1467     RETURN_IF_BAD_ERRCODE("#18#");
   1468     ubidi_orderParagraphsLTR(bidi, TRUE);
   1469     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
   1470                         "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
   1471                         "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
   1472     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1473     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1474     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
   1475                         "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
   1476                         "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
   1477     if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1478         log_err("\nWrong result #9, should be '%s', got '%s'\n",
   1479                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1480     }
   1481     RETURN_IF_BAD_ERRCODE("#19#");
   1482     srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
   1483     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1484     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1485     srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
   1486     if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1487         log_err("\nWrong result #10, should be '%s', got '%s'\n",
   1488                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1489     }
   1490     RETURN_IF_BAD_ERRCODE("#20#");
   1491     srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
   1492     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1493     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1494     srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
   1495     if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1496         log_err("\nWrong result #11, should be '%s', got '%s'\n",
   1497                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1498     }
   1499     RETURN_IF_BAD_ERRCODE("#21#");
   1500     srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
   1501     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1502     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1503     srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
   1504     if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1505         log_err("\nWrong result #12, should be '%s', got '%s'\n",
   1506                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1507     }
   1508     RETURN_IF_BAD_ERRCODE("#22#");
   1509     srcLen = u_unescape("ab \t", src, MAXLEN);
   1510     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1511     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1512     srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
   1513     if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1514         log_err("\nWrong result #13, should be '%s', got '%s'\n",
   1515                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1516     }
   1517     RETURN_IF_BAD_ERRCODE("#23#");
   1518 
   1519     /* check exceeding para level */
   1520     ubidi_close(bidi);
   1521     bidi = ubidi_open();
   1522     srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
   1523     ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
   1524     level = ubidi_getLevelAt(bidi, 2);
   1525     if (level != 61) {
   1526         log_err("\nWrong level at index 2\n, should be 61, got %d\n", level);
   1527     }
   1528     RETURN_IF_BAD_ERRCODE("#24#");
   1529 
   1530     /* check 1-char runs with RUNS_ONLY */
   1531     ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
   1532     srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
   1533     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1534     runCount = ubidi_countRuns(bidi, &errorCode);
   1535     if (runCount != 14) {
   1536         log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
   1537     }
   1538     RETURN_IF_BAD_ERRCODE("#25#");
   1539 
   1540     ubidi_close(bidi);
   1541     ubidi_close(bidiLine);
   1542 }
   1543 
   1544 static void
   1545 testFailureRecovery(void) {
   1546     UErrorCode errorCode;
   1547     UBiDi *bidi, *bidiLine;
   1548     UChar src[MAXLEN];
   1549     int32_t srcLen;
   1550     UBiDiLevel level;
   1551     UBiDiReorderingMode rm;
   1552     static UBiDiLevel myLevels[3] = {6,5,4};
   1553 
   1554     log_verbose("\nEntering TestFailureRecovery\n\n");
   1555     errorCode = U_FILE_ACCESS_ERROR;
   1556     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
   1557         log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
   1558     }
   1559     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
   1560         log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
   1561     }
   1562     errorCode = U_ZERO_ERROR;
   1563     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1564         log_err("ubidi_writeReordered did not fail as expected\n");
   1565     }
   1566 
   1567     bidi = ubidi_open();
   1568     srcLen = u_unescape("abc", src, MAXLEN);
   1569     errorCode = U_ZERO_ERROR;
   1570     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
   1571     if (U_SUCCESS(errorCode)) {
   1572         log_err("\nubidi_setPara did not fail when passed too big para level\n");
   1573     }
   1574     errorCode = U_ZERO_ERROR;
   1575     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1576         log_err("ubidi_writeReverse did not fail as expected\n");
   1577     }
   1578     bidiLine = ubidi_open();
   1579     errorCode = U_ZERO_ERROR;
   1580     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1581     if (U_SUCCESS(errorCode)) {
   1582         log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
   1583     }
   1584     errorCode = U_ZERO_ERROR;
   1585     srcLen = u_unescape("abc", src, MAXLEN);
   1586     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
   1587     level = ubidi_getLevelAt(bidi, 3);
   1588     if (level != 0) {
   1589         log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
   1590     }
   1591     errorCode = U_ZERO_ERROR;
   1592     ubidi_close(bidi);
   1593     bidi = ubidi_openSized(-1, 0, &errorCode);
   1594     if (U_SUCCESS(errorCode)) {
   1595         log_err("\nubidi_openSized did not fail when called with bad argument\n");
   1596     }
   1597     ubidi_close(bidi);
   1598     bidi = ubidi_openSized(2, 1, &errorCode);
   1599     errorCode = U_ZERO_ERROR;
   1600     srcLen = u_unescape("abc", src, MAXLEN);
   1601     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1602     if (U_SUCCESS(errorCode)) {
   1603         log_err("\nsetPara did not fail when called with text too long\n");
   1604     }
   1605     errorCode = U_ZERO_ERROR;
   1606     srcLen = u_unescape("=2", src, MAXLEN);
   1607     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1608     ubidi_countRuns(bidi, &errorCode);
   1609     if (U_SUCCESS(errorCode)) {
   1610         log_err("\nsetPara did not fail when called for too many runs\n");
   1611     }
   1612     ubidi_close(bidi);
   1613     bidi = ubidi_open();
   1614     rm = ubidi_getReorderingMode(bidi);
   1615     ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
   1616     if (rm != ubidi_getReorderingMode(bidi)) {
   1617         log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
   1618     }
   1619     ubidi_setReorderingMode(bidi, 9999);
   1620     if (rm != ubidi_getReorderingMode(bidi)) {
   1621         log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
   1622     }
   1623 
   1624     /* Try a surrogate char */
   1625     errorCode = U_ZERO_ERROR;
   1626     srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
   1627     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1628     if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
   1629         log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
   1630     }
   1631     errorCode = U_ZERO_ERROR;
   1632     srcLen = u_unescape("abc", src, MAXLEN);
   1633     ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
   1634     if (U_SUCCESS(errorCode)) {
   1635         log_err("\nsetPara did not fail when called with bad levels\n");
   1636     }
   1637     ubidi_close(bidi);
   1638     ubidi_close(bidiLine);
   1639 
   1640     log_verbose("\nExiting TestFailureRecovery\n\n");
   1641 }
   1642 
   1643 static void
   1644 testMultipleParagraphs(void) {
   1645     static const char* const text = "__ABC\\u001c"          /* Para #0 offset 0 */
   1646                                     "__\\u05d0DE\\u001c"    /*       1        6 */
   1647                                     "__123\\u001c"          /*       2       12 */
   1648                                     "\\u000d\\u000a"        /*       3       18 */
   1649                                     "FG\\u000d"             /*       4       20 */
   1650                                     "\\u000d"               /*       5       23 */
   1651                                     "HI\\u000d\\u000a"      /*       6       24 */
   1652                                     "\\u000d\\u000a"        /*       7       28 */
   1653                                     "\\u000a"               /*       8       30 */
   1654                                     "\\u000a"               /*       9       31 */
   1655                                     "JK\\u001c";            /*      10       32 */
   1656     static const int32_t paraCount=11;
   1657     static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
   1658     static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
   1659     static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1660                                                   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
   1661                                                   {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1662                                                   {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
   1663                                                   {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
   1664                                                   {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
   1665     static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
   1666     static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
   1667     static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
   1668     static const UChar multiparaTestString[] = {
   1669         0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da,
   1670         0x20,  0xa,   0xa,   0x41,  0x72,  0x74,  0x69,  0x73,
   1671         0x74,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
   1672         0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,   0x41,  0x6c,
   1673         0x62,  0x75,  0x6d,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1,
   1674         0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,
   1675         0x54,  0x69,  0x6d,  0x65,  0x3a,  0x20,  0x32,  0x3a,
   1676         0x32,  0x37,  0xa,  0xa
   1677     };
   1678     static const UBiDiLevel multiparaTestLevels[] = {
   1679         1, 1, 1, 1, 1, 1, 1, 1,
   1680         1, 1, 0, 0, 0, 0, 0, 0,
   1681         0, 0, 0, 1, 1, 1, 1, 1,
   1682         1, 1, 1, 0, 0, 0, 0, 0,
   1683         0, 0, 0, 0, 0, 1, 1, 1,
   1684         1, 1, 1, 1, 1, 0, 0, 0,
   1685         0, 0, 0, 0, 0, 0, 0, 0,
   1686         0, 0, 0, 0
   1687     };
   1688     UBiDiLevel gotLevel;
   1689     const UBiDiLevel* gotLevels;
   1690     UBool orderParagraphsLTR;
   1691     UChar src[MAXLEN], dest[MAXLEN];
   1692     UErrorCode errorCode=U_ZERO_ERROR;
   1693     UBiDi* pBidi=ubidi_open();
   1694     UBiDi* pLine;
   1695     int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
   1696     int32_t srcLen, destLen;
   1697     int i, j, k;
   1698 
   1699     log_verbose("\nEntering TestMultipleParagraphs\n\n");
   1700     u_unescape(text, src, MAXLEN);
   1701     srcSize=u_strlen(src);
   1702     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1703     if(U_FAILURE(errorCode)){
   1704         log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1705                 UBIDI_LTR, u_errorName(errorCode));
   1706         ubidi_close(pBidi);
   1707         return;
   1708     }
   1709     /* check paragraph count and boundaries */
   1710     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1711         log_err("ubidi_countParagraphs returned %d, should be %d\n",
   1712                 count, paraCount);
   1713     }
   1714     for (i=0; i<paraCount; i++) {
   1715         ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1716         if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1717             log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1718                     i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1719         }
   1720     }
   1721     errorCode=U_ZERO_ERROR;
   1722     /* check with last paragraph not terminated by B */
   1723     src[srcSize-1]='L';
   1724     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1725     if(U_FAILURE(errorCode)){
   1726         log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1727                 UBIDI_LTR, u_errorName(errorCode));
   1728         ubidi_close(pBidi);
   1729         return;
   1730     }
   1731     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1732         log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
   1733                 count, paraCount);
   1734     }
   1735     i=paraCount-1;
   1736     ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1737     if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1738         log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1739                 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1740     }
   1741     errorCode=U_ZERO_ERROR;
   1742     /* check paraLevel for all paragraphs under various paraLevel specs */
   1743     for (k=0; k<6; k++) {
   1744         ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
   1745         for (i=0; i<paraCount; i++) {
   1746             paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
   1747             if (paraIndex!=i) {
   1748                 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
   1749                         paraLevels[k], i, paraIndex, i);
   1750             }
   1751             if (gotLevel!=multiLevels[k][i]) {
   1752                 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
   1753                         paraLevels[k], i, gotLevel, multiLevels[k][i]);
   1754             }
   1755         }
   1756         gotLevel=ubidi_getParaLevel(pBidi);
   1757         if (gotLevel!=multiLevels[k][0]) {
   1758             log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
   1759                     paraLevels[k], gotLevel, multiLevels[k][0]);
   1760         }
   1761     }
   1762     errorCode=U_ZERO_ERROR;
   1763     /* check that the result of ubidi_getParaLevel changes if the first
   1764      * paragraph has a different level
   1765      */
   1766     src[0]=0x05d2;                      /* Hebrew letter Gimel */
   1767     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1768     gotLevel=ubidi_getParaLevel(pBidi);
   1769     if (gotLevel!=UBIDI_RTL) {
   1770         log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
   1771                         gotLevel, UBIDI_RTL);
   1772     }
   1773     errorCode=U_ZERO_ERROR;
   1774     /* check that line cannot overlap paragraph boundaries */
   1775     pLine=ubidi_open();
   1776     i=paraBounds[1];
   1777     k=paraBounds[2]+1;
   1778     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1779     if (U_SUCCESS(errorCode)) {
   1780         log_err("For line limits %d-%d got success %s\n",
   1781                 i, k, u_errorName(errorCode));
   1782     }
   1783     errorCode=U_ZERO_ERROR;
   1784     i=paraBounds[1];
   1785     k=paraBounds[2];
   1786     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1787     if (U_FAILURE(errorCode)) {
   1788         log_err("For line limits %d-%d got error %s\n",
   1789                 i, k, u_errorName(errorCode));
   1790         errorCode=U_ZERO_ERROR;
   1791     }
   1792     /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
   1793     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1794     /* get levels through para Bidi block */
   1795     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1796     if (U_FAILURE(errorCode)) {
   1797         log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
   1798         ubidi_close(pLine);
   1799         ubidi_close(pBidi);
   1800         return;
   1801     }
   1802     for (i=26; i<32; i++) {
   1803         if (gotLevels[i]!=UBIDI_RTL) {
   1804             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1805                     i, src[i], gotLevels[i], UBIDI_RTL);
   1806         }
   1807     }
   1808     /* get levels through para Line block */
   1809     i=paraBounds[1];
   1810     k=paraBounds[2];
   1811     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1812     if (U_FAILURE(errorCode)) {
   1813         log_err("For line limits %d-%d got error %s\n",
   1814                 i, k, u_errorName(errorCode));
   1815         ubidi_close(pLine);
   1816         ubidi_close(pBidi);
   1817         return;
   1818     }
   1819     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1820     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1821     if (U_FAILURE(errorCode)) {
   1822         log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
   1823         ubidi_close(pLine);
   1824         ubidi_close(pBidi);
   1825         return;
   1826     }
   1827     length=ubidi_getLength(pLine);
   1828     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
   1829         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1830                 "level of separator=%d expected=%d\n",
   1831                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
   1832     }
   1833     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1834     if (orderParagraphsLTR) {
   1835         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
   1836     }
   1837     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1838     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1839     if (!orderParagraphsLTR) {
   1840         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
   1841     }
   1842     /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
   1843     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1844     /* get levels through para Bidi block */
   1845     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1846     for (i=26; i<32; i++) {
   1847         if (gotLevels[i]!=0) {
   1848             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1849                     i, src[i], gotLevels[i], 0);
   1850         }
   1851     }
   1852     errorCode=U_ZERO_ERROR;
   1853     /* get levels through para Line block */
   1854     i=paraBounds[1];
   1855     k=paraBounds[2];
   1856     ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
   1857     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1858     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1859     length=ubidi_getLength(pLine);
   1860     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
   1861         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1862                 "level of separator=%d expected=%d\n",
   1863                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
   1864         log_verbose("levels=");
   1865         for (count=0; count<length; count++) {
   1866             log_verbose(" %d", gotLevels[count]);
   1867         }
   1868         log_verbose("\n");
   1869     }
   1870 
   1871     /* test that the concatenation of separate invocations of the bidi code
   1872      * on each individual paragraph in order matches the levels array that
   1873      * results from invoking bidi once over the entire multiparagraph tests
   1874      * (with orderParagraphsLTR false, of course)
   1875      */
   1876     u_unescape(text, src, MAXLEN);      /* restore original content */
   1877     srcSize=u_strlen(src);
   1878     ubidi_orderParagraphsLTR(pBidi, FALSE);
   1879     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1880     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1881     for (i=0; i<paraCount; i++) {
   1882         /* use pLine for individual paragraphs */
   1883         paraStart = paraBounds[i];
   1884         length = paraBounds[i+1] - paraStart;
   1885         ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1886         for (j=0; j<length; j++) {
   1887             if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
   1888                 log_err("Checking paragraph concatenation: for paragraph=%d, "
   1889                         "char=%d(%04x), level=%d, expected=%d\n",
   1890                         i, j, src[paraStart+j], k, gotLevel);
   1891             }
   1892         }
   1893     }
   1894 
   1895     /* ensure that leading numerics in a paragraph are not treated as arabic
   1896        numerals because of arabic text in a preceding paragraph
   1897      */
   1898     u_unescape(text2, src, MAXLEN);
   1899     srcSize=u_strlen(src);
   1900     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1901     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1902     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1903     if (U_FAILURE(errorCode)) {
   1904         log_err("Can't get levels. %s\n", u_errorName(errorCode));
   1905         return;
   1906     }
   1907     for (i=0; i<srcSize; i++) {
   1908         if (gotLevels[i]!=levels2[i]) {
   1909             log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
   1910                     i, src[i], gotLevels[i], levels2[i]);
   1911         }
   1912     }
   1913 
   1914     /* check handling of whitespace before end of paragraph separator when
   1915      * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
   1916      */
   1917     u_memset(src, 0x0020, MAXLEN);
   1918     srcSize = 5;
   1919     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1920     for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
   1921         src[4]=(UChar)i;                /* with and without terminating B */
   1922         for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
   1923             src[0]=(UChar)j;            /* leading 'A' or Alef */
   1924             for (gotLevel=4; gotLevel<=5; gotLevel++) {
   1925                 /* test even and odd paraLevel */
   1926                 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
   1927                 gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1928                 for (k=1; k<=3; k++) {
   1929                     if (gotLevels[k]!=gotLevel) {
   1930                         log_err("Checking trailing spaces: for leading_char=%04x, "
   1931                                 "last_char=%04x, index=%d, level=%d, expected=%d\n",
   1932                                 src[0], src[4], k, gotLevels[k], gotLevel);
   1933                     }
   1934                 }
   1935             }
   1936         }
   1937     }
   1938 
   1939     /* check default orientation when inverse bidi and paragraph starts
   1940      * with LTR strong char and ends with RTL strong char, with and without
   1941      * a terminating B
   1942      */
   1943     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1944     srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
   1945     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1946     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1947     srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
   1948     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1949         log_err("\nInvalid output #0, should be '%s', got '%s'\n",
   1950                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1951     }
   1952     srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
   1953     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1954     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1955     srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
   1956     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1957         log_err("\nInvalid output #1, should be '%s', got '%s'\n",
   1958                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1959     }
   1960 
   1961     /* check multiple paragraphs together with explicit levels
   1962      */
   1963     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
   1964     srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
   1965     ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
   1966     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   1967     srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
   1968     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   1969         log_err("\nInvalid output #2, should be '%s', got '%s'\n",
   1970                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1971     }
   1972     count = ubidi_countParagraphs(pBidi);
   1973     if (count != 2) {
   1974         log_err("\nInvalid number of paras, should be 2, got %d\n", count);
   1975     }
   1976 
   1977     ubidi_close(pLine);
   1978     ubidi_close(pBidi);
   1979     log_verbose("\nExiting TestMultipleParagraphs\n\n");
   1980 
   1981     /* check levels in multiple paragraphs with default para level
   1982      */
   1983     pBidi = ubidi_open();
   1984     errorCode = U_ZERO_ERROR;
   1985     ubidi_setPara(pBidi, multiparaTestString, LENGTHOF(multiparaTestString),
   1986                   UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1987     if (U_FAILURE(errorCode)) {
   1988         log_err("ubidi_setPara failed for multiparaTestString\n");
   1989         ubidi_close(pBidi);
   1990         return;
   1991     }
   1992     gotLevels = ubidi_getLevels(pBidi, &errorCode);
   1993     if (U_FAILURE(errorCode)) {
   1994         log_err("ubidi_getLevels failed for multiparaTestString\n");
   1995         ubidi_close(pBidi);
   1996         return;
   1997     }
   1998     for (i = 0; i < LENGTHOF(multiparaTestString); i++) {
   1999         if (gotLevels[i] != multiparaTestLevels[i]) {
   2000             log_err("Error on level for multiparaTestString at index %d, "
   2001                     "expected=%d, actual=%d\n",
   2002                     i, multiparaTestLevels[i], gotLevels[i]);
   2003         }
   2004     }
   2005     ubidi_close(pBidi);
   2006 
   2007 }
   2008 
   2009 
   2010 /* inverse BiDi ------------------------------------------------------------- */
   2011 
   2012 static int countRoundtrips=0, countNonRoundtrips=0;
   2013 
   2014 #define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
   2015 
   2016 static void
   2017 testInverse(void) {
   2018     static const UChar
   2019         string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
   2020         string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
   2021         string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
   2022         string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
   2023         string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
   2024 
   2025     static const struct {
   2026         const UChar *s;
   2027         int32_t length;
   2028     } testCases[]={
   2029         STRING_TEST_CASE(string0),
   2030         STRING_TEST_CASE(string1),
   2031         STRING_TEST_CASE(string2),
   2032         STRING_TEST_CASE(string3),
   2033         STRING_TEST_CASE(string4)
   2034     };
   2035 
   2036     UBiDi *pBiDi;
   2037     UErrorCode errorCode;
   2038     int i;
   2039 
   2040     log_verbose("\nEntering TestInverse\n\n");
   2041     pBiDi=ubidi_open();
   2042     if(pBiDi==NULL) {
   2043         log_err("unable to open a UBiDi object (out of memory)\n");
   2044         return;
   2045     }
   2046 
   2047     log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases));
   2048      for(i=0; i<LENGTHOF(testCases); ++i) {
   2049         log_verbose("Testing case %d\n", i);
   2050         errorCode=U_ZERO_ERROR;
   2051         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
   2052     }
   2053 
   2054     log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases));
   2055     for(i=0; i<LENGTHOF(testCases); ++i) {
   2056         log_verbose("Testing case %d\n", i);
   2057         errorCode=U_ZERO_ERROR;
   2058         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
   2059     }
   2060 
   2061     _testManyInverseBidi(pBiDi, 0);
   2062     _testManyInverseBidi(pBiDi, 1);
   2063 
   2064     ubidi_close(pBiDi);
   2065 
   2066     log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
   2067 
   2068     _testWriteReverse();
   2069 
   2070     _testManyAddedPoints();
   2071 
   2072     _testMisc();
   2073 
   2074     log_verbose("\nExiting TestInverse\n\n");
   2075 }
   2076 
   2077 #define COUNT_REPEAT_SEGMENTS 6
   2078 
   2079 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
   2080     { 0x61, 0x62 },     /* L */
   2081     { 0x5d0, 0x5d1 },   /* R */
   2082     { 0x627, 0x628 },   /* AL */
   2083     { 0x31, 0x32 },     /* EN */
   2084     { 0x661, 0x662 },   /* AN */
   2085     { 0x20, 0x20 }      /* WS (N) */
   2086 };
   2087 
   2088 static void
   2089 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
   2090     UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
   2091     int i, j, k;
   2092     UErrorCode errorCode;
   2093 
   2094     log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
   2095                  direction==0 ? 'L' : 'R');
   2096     for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
   2097         text[0]=repeatSegments[i][0];
   2098         text[1]=repeatSegments[i][1];
   2099         for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
   2100             text[3]=repeatSegments[j][0];
   2101             text[4]=repeatSegments[j][1];
   2102             for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
   2103                 text[6]=repeatSegments[k][0];
   2104                 text[7]=repeatSegments[k][1];
   2105 
   2106                 errorCode=U_ZERO_ERROR;
   2107                 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
   2108                 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
   2109             }
   2110         }
   2111     }
   2112 }
   2113 
   2114 static void
   2115 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
   2116                 UBiDiLevel direction, UErrorCode *pErrorCode) {
   2117     UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
   2118     int32_t ltrLength, logicalLength, visualLength;
   2119 
   2120     if(direction==0) {
   2121         log_verbose("inverse Bidi: testInverse(L)\n");
   2122 
   2123         /* convert visual to logical */
   2124         ubidi_setInverse(pBiDi, TRUE);
   2125         if (!ubidi_isInverse(pBiDi)) {
   2126             log_err("Error while doing ubidi_setInverse(TRUE)\n");
   2127         }
   2128         ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
   2129         if (src != ubidi_getText(pBiDi)) {
   2130             log_err("Wrong value returned by ubidi_getText\n");
   2131         }
   2132         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
   2133                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2134         log_verbose("  v ");
   2135         printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
   2136         log_verbose("\n");
   2137 
   2138         /* convert back to visual LTR */
   2139         ubidi_setInverse(pBiDi, FALSE);
   2140         if (ubidi_isInverse(pBiDi)) {
   2141             log_err("Error while doing ubidi_setInverse(FALSE)\n");
   2142         }
   2143         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2144         visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
   2145                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
   2146     } else {
   2147         log_verbose("inverse Bidi: testInverse(R)\n");
   2148 
   2149         /* reverse visual from RTL to LTR */
   2150         ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode);
   2151         log_verbose("  vr");
   2152         printUnicode(src, srcLength, NULL);
   2153         log_verbose("\n");
   2154 
   2155         /* convert visual RTL to logical */
   2156         ubidi_setInverse(pBiDi, TRUE);
   2157         ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
   2158         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
   2159                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2160         log_verbose("  vl");
   2161         printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
   2162         log_verbose("\n");
   2163 
   2164         /* convert back to visual RTL */
   2165         ubidi_setInverse(pBiDi, FALSE);
   2166         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2167         visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
   2168                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
   2169     }
   2170     log_verbose("  l ");
   2171     printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
   2172     log_verbose("\n");
   2173     log_verbose("  v ");
   2174     printUnicode(visualDest, visualLength, NULL);
   2175     log_verbose("\n");
   2176 
   2177     /* check and print results */
   2178     if(U_FAILURE(*pErrorCode)) {
   2179         log_err("inverse BiDi: *** error %s\n"
   2180                 "                 turn on verbose mode to see details\n", u_errorName(*pErrorCode));
   2181     } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
   2182         ++countRoundtrips;
   2183         log_verbose(" + roundtripped\n");
   2184     } else {
   2185         ++countNonRoundtrips;
   2186         log_verbose(" * did not roundtrip\n");
   2187         log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
   2188                 "                 turn on verbose mode to see details\n");
   2189     }
   2190 }
   2191 
   2192 static void
   2193 _testWriteReverse(void) {
   2194     /* U+064e and U+0650 are combining marks (Mn) */
   2195     static const UChar forward[]={
   2196         0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
   2197     }, reverseKeepCombining[]={
   2198         0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
   2199     }, reverseRemoveControlsKeepCombiningDoMirror[]={
   2200         0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
   2201     };
   2202     UChar reverse[10];
   2203     UErrorCode errorCode;
   2204     int32_t length;
   2205 
   2206     /* test ubidi_writeReverse() with "interesting" options */
   2207     errorCode=U_ZERO_ERROR;
   2208     length=ubidi_writeReverse(forward, LENGTHOF(forward),
   2209                               reverse, LENGTHOF(reverse),
   2210                               UBIDI_KEEP_BASE_COMBINING,
   2211                               &errorCode);
   2212     if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
   2213         log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
   2214                 length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
   2215     }
   2216 
   2217     memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR);
   2218     errorCode=U_ZERO_ERROR;
   2219     length=ubidi_writeReverse(forward, LENGTHOF(forward),
   2220                               reverse, LENGTHOF(reverse),
   2221                               UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
   2222                               &errorCode);
   2223     if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
   2224         log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
   2225                 "    length=%d (should be %d), error code %s\n",
   2226                 length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
   2227     }
   2228 }
   2229 
   2230 static void _testManyAddedPoints(void) {
   2231     UErrorCode errorCode = U_ZERO_ERROR;
   2232     UBiDi *bidi = ubidi_open();
   2233     UChar text[90], dest[MAXLEN], expected[120];
   2234     int destLen, i;
   2235     for (i = 0; i < LENGTHOF(text); i+=3) {
   2236         text[i] = 0x0061; /* 'a' */
   2237         text[i+1] = 0x05d0;
   2238         text[i+2] = 0x0033; /* '3' */
   2239     }
   2240     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2241     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   2242     ubidi_setPara(bidi, text, LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
   2243     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   2244     for (i = 0; i < LENGTHOF(expected); i+=4) {
   2245         expected[i] = 0x0061; /* 'a' */
   2246         expected[i+1] = 0x05d0;
   2247         expected[i+2] = 0x200e;
   2248         expected[i+3] = 0x0033; /* '3' */
   2249     }
   2250     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2251         log_err("\nInvalid output with many added points, "
   2252                 "expected '%s', got '%s'\n",
   2253                 aescstrdup(expected, LENGTHOF(expected)),
   2254                 aescstrdup(dest, destLen));
   2255     }
   2256     ubidi_close(bidi);
   2257 }
   2258 
   2259 static void _testMisc(void) {
   2260     UErrorCode errorCode = U_ZERO_ERROR;
   2261     UBiDi *bidi = ubidi_open();
   2262     UChar src[3], dest[MAXLEN], expected[5];
   2263     int destLen;
   2264     ubidi_setInverse(bidi, TRUE);
   2265     src[0] = src[1] = src[2] = 0x0020;
   2266     ubidi_setPara(bidi, src, LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
   2267     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   2268               UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
   2269               &errorCode);
   2270     u_unescape("\\u200f   \\u200f", expected, 5);
   2271     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2272         log_err("\nInvalid output with RLM at both sides, "
   2273                 "expected '%s', got '%s'\n",
   2274                 aescstrdup(expected, LENGTHOF(expected)),
   2275                 aescstrdup(dest, destLen));
   2276     }
   2277     ubidi_close(bidi);
   2278 }
   2279 
   2280 /* arabic shaping ----------------------------------------------------------- */
   2281 
   2282 static void
   2283 doArabicShapingTest(void) {
   2284     static const UChar
   2285     source[]={
   2286         0x31,   /* en:1 */
   2287         0x627,  /* arabic:alef */
   2288         0x32,   /* en:2 */
   2289         0x6f3,  /* an:3 */
   2290         0x61,   /* latin:a */
   2291         0x34,   /* en:4 */
   2292         0
   2293     }, en2an[]={
   2294         0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
   2295     }, an2en[]={
   2296         0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
   2297     }, logical_alen2an_init_lr[]={
   2298         0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
   2299     }, logical_alen2an_init_al[]={
   2300         0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
   2301     }, reverse_alen2an_init_lr[]={
   2302         0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
   2303     }, reverse_alen2an_init_al[]={
   2304         0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
   2305     }, lamalef[]={
   2306         0xfefb, 0
   2307     };
   2308     UChar dest[8];
   2309     UErrorCode errorCode;
   2310     int32_t length;
   2311 
   2312     /* test number shaping */
   2313 
   2314     /* european->arabic */
   2315     errorCode=U_ZERO_ERROR;
   2316     length=u_shapeArabic(source, LENGTHOF(source),
   2317                          dest, LENGTHOF(dest),
   2318                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2319                          &errorCode);
   2320     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
   2321         log_err("failure in u_shapeArabic(en2an)\n");
   2322     }
   2323 
   2324     /* arabic->european */
   2325     errorCode=U_ZERO_ERROR;
   2326     length=u_shapeArabic(source, -1,
   2327                          dest, LENGTHOF(dest),
   2328                          U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2329                          &errorCode);
   2330     if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
   2331         log_err("failure in u_shapeArabic(an2en)\n");
   2332     }
   2333 
   2334     /* european->arabic with context, logical order, initial state not AL */
   2335     errorCode=U_ZERO_ERROR;
   2336     length=u_shapeArabic(source, LENGTHOF(source),
   2337                          dest, LENGTHOF(dest),
   2338                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
   2339                          &errorCode);
   2340     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2341         log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
   2342     }
   2343 
   2344     /* european->arabic with context, logical order, initial state AL */
   2345     errorCode=U_ZERO_ERROR;
   2346     length=u_shapeArabic(source, LENGTHOF(source),
   2347                          dest, LENGTHOF(dest),
   2348                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2349                          &errorCode);
   2350     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2351         log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
   2352     }
   2353 
   2354     /* european->arabic with context, reverse order, initial state not AL */
   2355     errorCode=U_ZERO_ERROR;
   2356     length=u_shapeArabic(source, LENGTHOF(source),
   2357                          dest, LENGTHOF(dest),
   2358                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2359                          &errorCode);
   2360     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2361         log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
   2362     }
   2363 
   2364     /* european->arabic with context, reverse order, initial state AL */
   2365     errorCode=U_ZERO_ERROR;
   2366     length=u_shapeArabic(source, LENGTHOF(source),
   2367                          dest, LENGTHOF(dest),
   2368                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2369                          &errorCode);
   2370     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2371         log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
   2372     }
   2373 
   2374     /* test noop */
   2375     errorCode=U_ZERO_ERROR;
   2376     length=u_shapeArabic(source, LENGTHOF(source),
   2377                          dest, LENGTHOF(dest),
   2378                          0,
   2379                          &errorCode);
   2380     if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
   2381         log_err("failure in u_shapeArabic(noop)\n");
   2382     }
   2383 
   2384     errorCode=U_ZERO_ERROR;
   2385     length=u_shapeArabic(source, 0,
   2386                          dest, LENGTHOF(dest),
   2387                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2388                          &errorCode);
   2389     if(U_FAILURE(errorCode) || length!=0) {
   2390         log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source));
   2391     }
   2392 
   2393     /* preflight digit shaping */
   2394     errorCode=U_ZERO_ERROR;
   2395     length=u_shapeArabic(source, LENGTHOF(source),
   2396                          NULL, 0,
   2397                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2398                          &errorCode);
   2399     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) {
   2400         log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
   2401                 length, u_errorName(errorCode), LENGTHOF(source));
   2402     }
   2403 
   2404     /* test illegal arguments */
   2405     errorCode=U_ZERO_ERROR;
   2406     length=u_shapeArabic(NULL, LENGTHOF(source),
   2407                          dest, LENGTHOF(dest),
   2408                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2409                          &errorCode);
   2410     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2411         log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2412     }
   2413 
   2414     errorCode=U_ZERO_ERROR;
   2415     length=u_shapeArabic(source, -2,
   2416                          dest, LENGTHOF(dest),
   2417                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2418                          &errorCode);
   2419     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2420         log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2421     }
   2422 
   2423     errorCode=U_ZERO_ERROR;
   2424     length=u_shapeArabic(source, LENGTHOF(source),
   2425                          NULL, LENGTHOF(dest),
   2426                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2427                          &errorCode);
   2428     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2429         log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2430     }
   2431 
   2432     errorCode=U_ZERO_ERROR;
   2433     length=u_shapeArabic(source, LENGTHOF(source),
   2434                          dest, -1,
   2435                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2436                          &errorCode);
   2437     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2438         log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2439     }
   2440 
   2441     errorCode=U_ZERO_ERROR;
   2442     length=u_shapeArabic(source, LENGTHOF(source),
   2443                          dest, LENGTHOF(dest),
   2444                          U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
   2445                          &errorCode);
   2446     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2447         log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2448     }
   2449 
   2450     errorCode=U_ZERO_ERROR;
   2451     length=u_shapeArabic(source, LENGTHOF(source),
   2452                          dest, LENGTHOF(dest),
   2453                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
   2454                          &errorCode);
   2455     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2456         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2457     }
   2458 
   2459     errorCode=U_ZERO_ERROR;
   2460     length=u_shapeArabic(source, LENGTHOF(source),
   2461                          (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */
   2462                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2463                          &errorCode);
   2464     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2465         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2466     }
   2467 
   2468     errorCode=U_ZERO_ERROR;
   2469     length=u_shapeArabic(lamalef, LENGTHOF(lamalef),
   2470                          dest, LENGTHOF(dest),
   2471                          U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2472                          &errorCode);
   2473     if(U_FAILURE(errorCode) || length == LENGTHOF(lamalef)) {
   2474         log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
   2475         log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length);
   2476     }
   2477 }
   2478 
   2479 static void
   2480 doLamAlefSpecialVLTRArabicShapingTest(void) {
   2481     static const UChar
   2482     source[]={
   2483 /*a*/   0x20 ,0x646,0x622,0x644,0x627,0x20,
   2484 /*b*/   0x646,0x623,0x64E,0x644,0x627,0x20,
   2485 /*c*/   0x646,0x627,0x670,0x644,0x627,0x20,
   2486 /*d*/   0x646,0x622,0x653,0x644,0x627,0x20,
   2487 /*e*/   0x646,0x625,0x655,0x644,0x627,0x20,
   2488 /*f*/   0x646,0x622,0x654,0x644,0x627,0x20,
   2489 /*g*/   0xFEFC,0x639
   2490     }, shape_near[]={
   2491         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2492         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2493         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2494         0xfefc,0xfecb
   2495     }, shape_at_end[]={
   2496         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2497         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2498         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
   2499     }, shape_at_begin[]={
   2500         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2501         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2502         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2503     }, shape_grow_shrink[]={
   2504         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2505         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2506         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2507     }, shape_excepttashkeel_near[]={
   2508         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2509         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2510         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2511         0xfefc,0xfecb
   2512     }, shape_excepttashkeel_at_end[]={
   2513         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2514         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2515         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
   2516         0x20,0x20,0x20
   2517     }, shape_excepttashkeel_at_begin[]={
   2518         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2519         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2520         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2521     }, shape_excepttashkeel_grow_shrink[]={
   2522         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2523         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2524         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2525     };
   2526 
   2527     UChar dest[38];
   2528     UErrorCode errorCode;
   2529     int32_t length;
   2530 
   2531     errorCode=U_ZERO_ERROR;
   2532 
   2533     length=u_shapeArabic(source, LENGTHOF(source),
   2534                          dest, LENGTHOF(dest),
   2535                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2536                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2537                          &errorCode);
   2538 
   2539     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2540         log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
   2541     }
   2542 
   2543     errorCode=U_ZERO_ERROR;
   2544 
   2545     length=u_shapeArabic(source, LENGTHOF(source),
   2546                          dest, LENGTHOF(dest),
   2547                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2548                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2549                          &errorCode);
   2550 
   2551     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2552         log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
   2553     }
   2554 
   2555     errorCode=U_ZERO_ERROR;
   2556 
   2557     length=u_shapeArabic(source, LENGTHOF(source),
   2558                          dest, LENGTHOF(dest),
   2559                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2560                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2561                          &errorCode);
   2562 
   2563     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2564         log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
   2565     }
   2566 
   2567     errorCode=U_ZERO_ERROR;
   2568 
   2569     length=u_shapeArabic(source, LENGTHOF(source),
   2570                          dest, LENGTHOF(dest),
   2571                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2572                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2573                          &errorCode);
   2574 
   2575     if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2576         log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
   2577     }
   2578 
   2579     /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
   2580 
   2581     errorCode=U_ZERO_ERROR;
   2582 
   2583     length=u_shapeArabic(source, LENGTHOF(source),
   2584                          dest, LENGTHOF(dest),
   2585                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2586                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2587                          &errorCode);
   2588 
   2589     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2590         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
   2591     }
   2592 
   2593     errorCode=U_ZERO_ERROR;
   2594 
   2595     length=u_shapeArabic(source, LENGTHOF(source),
   2596                          dest, LENGTHOF(dest),
   2597                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2598                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2599                          &errorCode);
   2600 
   2601     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
   2602         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
   2603     }
   2604 
   2605     errorCode=U_ZERO_ERROR;
   2606 
   2607     length=u_shapeArabic(source, LENGTHOF(source),
   2608                          dest, LENGTHOF(dest),
   2609                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2610                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2611                          &errorCode);
   2612 
   2613     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2614         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
   2615     }
   2616 
   2617     errorCode=U_ZERO_ERROR;
   2618 
   2619     length=u_shapeArabic(source, LENGTHOF(source),
   2620                          dest, LENGTHOF(dest),
   2621                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
   2622                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2623                          &errorCode);
   2624 
   2625     if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2626         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
   2627     }
   2628 }
   2629 
   2630 static void
   2631 doTashkeelSpecialVLTRArabicShapingTest(void) {
   2632     static const UChar
   2633     source[]={
   2634         0x64A,0x628,0x631,0x639,0x20,
   2635         0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
   2636         0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
   2637         0x628,0x670,0x631,0x670,0x639,0x20,
   2638         0x628,0x653,0x631,0x653,0x639,0x20,
   2639         0x628,0x654,0x631,0x654,0x639,0x20,
   2640         0x628,0x655,0x631,0x655,0x639,0x20,
   2641     }, shape_near[]={
   2642         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
   2643         0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
   2644         0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
   2645         0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2646     }, shape_excepttashkeel_near[]={
   2647         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
   2648         0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
   2649         0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
   2650         0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2651     };
   2652 
   2653     UChar dest[43];
   2654     UErrorCode errorCode;
   2655     int32_t length;
   2656 
   2657     errorCode=U_ZERO_ERROR;
   2658 
   2659     length=u_shapeArabic(source, LENGTHOF(source),
   2660                          dest, LENGTHOF(dest),
   2661                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2662                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2663                          &errorCode);
   2664 
   2665     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2666         log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
   2667     }
   2668 
   2669     errorCode=U_ZERO_ERROR;
   2670 
   2671     length=u_shapeArabic(source, LENGTHOF(source),
   2672                          dest, LENGTHOF(dest),
   2673                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2674                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2675                          &errorCode);
   2676 
   2677     if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2678         log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
   2679     }
   2680 }
   2681 
   2682 static void
   2683 doLOGICALArabicDeShapingTest(void) {
   2684     static const UChar
   2685     source[]={
   2686         0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
   2687         0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
   2688         0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
   2689     }, unshape_near[]={
   2690         0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
   2691         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2692         0x629,0x20,0x20,0x20,0x20
   2693     }, unshape_at_end[]={
   2694         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2695         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2696         0x644,0x62d,0x631,0x629,0x20
   2697     }, unshape_at_begin[]={
   2698         0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
   2699         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2700         0x629,0x20,0x20,0x20,0x20
   2701     }, unshape_grow_shrink[]={
   2702         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2703         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2704         0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
   2705     };
   2706 
   2707     UChar dest[36];
   2708     UErrorCode errorCode;
   2709     int32_t length;
   2710 
   2711     errorCode=U_ZERO_ERROR;
   2712 
   2713     length=u_shapeArabic(source, LENGTHOF(source),
   2714                          dest, LENGTHOF(dest),
   2715                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2716                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2717                          &errorCode);
   2718 
   2719     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
   2720         log_err("failure in u_shapeArabic(unshape_near)\n");
   2721     }
   2722 
   2723     errorCode=U_ZERO_ERROR;
   2724 
   2725     length=u_shapeArabic(source, LENGTHOF(source),
   2726                          dest, LENGTHOF(dest),
   2727                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2728                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2729                          &errorCode);
   2730 
   2731     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2732         log_err("failure in u_shapeArabic(unshape_at_end)\n");
   2733     }
   2734 
   2735     errorCode=U_ZERO_ERROR;
   2736 
   2737     length=u_shapeArabic(source, LENGTHOF(source),
   2738                          dest, LENGTHOF(dest),
   2739                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2740                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2741                          &errorCode);
   2742 
   2743     if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2744         log_err("failure in u_shapeArabic(unshape_at_begin)\n");
   2745     }
   2746 
   2747     errorCode=U_ZERO_ERROR;
   2748 
   2749     length=u_shapeArabic(source, LENGTHOF(source),
   2750                          dest, LENGTHOF(dest),
   2751                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2752                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2753                          &errorCode);
   2754 
   2755     if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2756         log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
   2757     }
   2758 
   2759 }
   2760 
   2761 static void
   2762 doArabicShapingTestForBug5421(void) {
   2763     static const UChar
   2764     persian_letters_source[]={
   2765         0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
   2766     }, persian_letters[]={
   2767         0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
   2768     }, tashkeel_aggregation_source[]={
   2769         0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
   2770         0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
   2771     }, tashkeel_aggregation[]={
   2772         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
   2773         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
   2774     }, untouched_presentation_source[]={
   2775         0x0020 ,0x0627, 0xfe90,0x0020
   2776     }, untouched_presentation[]={
   2777         0x0020,0xfe8D, 0xfe90,0x0020
   2778     }, untouched_presentation_r_source[]={
   2779         0x0020 ,0xfe90, 0x0627, 0x0020
   2780     }, untouched_presentation_r[]={
   2781         0x0020, 0xfe90,0xfe8D,0x0020
   2782     };
   2783 
   2784     UChar dest[38];
   2785     UErrorCode errorCode;
   2786     int32_t length;
   2787 
   2788     errorCode=U_ZERO_ERROR;
   2789 
   2790     length=u_shapeArabic(persian_letters_source, LENGTHOF(persian_letters_source),
   2791                          dest, LENGTHOF(dest),
   2792                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2793                          &errorCode);
   2794 
   2795     if(U_FAILURE(errorCode) || length!=LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
   2796         log_err("failure in u_shapeArabic(persian_letters)\n");
   2797     }
   2798 
   2799     errorCode=U_ZERO_ERROR;
   2800 
   2801     length=u_shapeArabic(tashkeel_aggregation_source, LENGTHOF(tashkeel_aggregation_source),
   2802                          dest, LENGTHOF(dest),
   2803                          U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
   2804                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2805                          &errorCode);
   2806 
   2807     if(U_FAILURE(errorCode) || length!=LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
   2808         log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
   2809     }
   2810 
   2811     errorCode=U_ZERO_ERROR;
   2812 
   2813     length=u_shapeArabic(untouched_presentation_source, LENGTHOF(untouched_presentation_source),
   2814                          dest, LENGTHOF(dest),
   2815                          U_SHAPE_PRESERVE_PRESENTATION|
   2816                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2817                          &errorCode);
   2818 
   2819     if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
   2820         log_err("failure in u_shapeArabic(untouched_presentation)\n");
   2821     }
   2822 
   2823     errorCode=U_ZERO_ERROR;
   2824 
   2825     length=u_shapeArabic(untouched_presentation_r_source, LENGTHOF(untouched_presentation_r_source),
   2826                          dest, LENGTHOF(dest),
   2827                          U_SHAPE_PRESERVE_PRESENTATION|
   2828                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2829                          &errorCode);
   2830 
   2831     if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
   2832         log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
   2833     }
   2834 }
   2835 
   2836 /* helpers ------------------------------------------------------------------ */
   2837 
   2838 static void initCharFromDirProps(void) {
   2839     static const UVersionInfo ucd401={ 4, 0, 1, 0 };
   2840     static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
   2841 
   2842     /* lazy initialization */
   2843     if(ucdVersion[0]>0) {
   2844         return;
   2845     }
   2846 
   2847     u_getUnicodeVersion(ucdVersion);
   2848     if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
   2849         /* Unicode 4.0.1 changes bidi classes for +-/ */
   2850         charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
   2851     }
   2852 }
   2853 
   2854 /* return a string with characters according to the desired directional properties */
   2855 static UChar *
   2856 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
   2857     int32_t i;
   2858 
   2859     initCharFromDirProps();
   2860 
   2861     /* this part would have to be modified for UTF-x */
   2862     for(i=0; i<length; ++i) {
   2863         buffer[i]=charFromDirProp[dirProps[i]];
   2864     }
   2865     buffer[length]=0;
   2866     return buffer;
   2867 }
   2868 
   2869 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
   2870     int32_t i;
   2871 
   2872     log_verbose("{ ");
   2873     for(i=0; i<length; ++i) {
   2874         if(levels!=NULL) {
   2875             log_verbose("%4x.%u  ", s[i], levels[i]);
   2876         } else {
   2877             log_verbose("%4x    ", s[i]);
   2878         }
   2879     }
   2880     log_verbose(" }");
   2881 }
   2882 
   2883 /* new BIDI API */
   2884 
   2885 /* Reordering Mode BiDi --------------------------------------------------------- */
   2886 
   2887 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
   2888 
   2889 static UBool
   2890 assertSuccessful(const char* message, UErrorCode* rc) {
   2891     if (rc != NULL && U_FAILURE(*rc)) {
   2892         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   2893         return FALSE;
   2894     }
   2895     return TRUE;
   2896 }
   2897 
   2898 static UBool
   2899 assertStringsEqual(const char* expected, const char* actual, const char* src,
   2900                    const char* mode, const char* option, UBiDi* pBiDi) {
   2901     if (uprv_strcmp(expected, actual)) {
   2902         char formatChars[MAXLEN];
   2903         log_err("\nActual and expected output mismatch.\n"
   2904             "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
   2905             "Input:", src,
   2906             "Actual output:", actual,
   2907             "Expected output:", expected,
   2908             "Levels:", formatLevels(pBiDi, formatChars),
   2909             "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
   2910             "Paragraph level:", ubidi_getParaLevel(pBiDi),
   2911             "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
   2912         return FALSE;
   2913     }
   2914     return TRUE;
   2915 }
   2916 
   2917 static UBiDi*
   2918 getBiDiObject(void) {
   2919     UBiDi* pBiDi = ubidi_open();
   2920     if (pBiDi == NULL) {
   2921         log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
   2922     }
   2923     return pBiDi;
   2924 }
   2925 
   2926 #define MAKE_ITEMS(val) val, #val
   2927 
   2928 static const struct {
   2929     UBiDiReorderingMode value;
   2930     const char* description;
   2931 }
   2932 modes[] = {
   2933     { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
   2934     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
   2935     { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
   2936     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
   2937     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
   2938 };
   2939 static const struct {
   2940     uint32_t value;
   2941     const char* description;
   2942 }
   2943 options[] = {
   2944     { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
   2945     { MAKE_ITEMS(0) }
   2946 };
   2947 
   2948 #define TC_COUNT                LENGTHOF(textIn)
   2949 #define MODES_COUNT             LENGTHOF(modes)
   2950 #define OPTIONS_COUNT           LENGTHOF(options)
   2951 #define LEVELS_COUNT            LENGTHOF(paraLevels)
   2952 
   2953 static const char* const textIn[] = {
   2954 /* (0) 123 */
   2955     "123",
   2956 /* (1) .123->4.5 */
   2957     ".123->4.5",
   2958 /* (2) 678 */
   2959     "678",
   2960 /* (3) .678->8.9 */
   2961     ".678->8.9",
   2962 /* (4) JIH1.2,3MLK */
   2963     "JIH1.2,3MLK",
   2964 /* (5) FE.>12-> */
   2965     "FE.>12->",
   2966 /* (6) JIH.>12->a */
   2967     "JIH.>12->a",
   2968 /* (7) CBA.>67->89=a */
   2969     "CBA.>67->89=a",
   2970 /* (8) CBA.123->xyz */
   2971     "CBA.123->xyz",
   2972 /* (9) .>12->xyz */
   2973     ".>12->xyz",
   2974 /* (10) a.>67->xyz */
   2975     "a.>67->xyz",
   2976 /* (11) 123JIH */
   2977     "123JIH",
   2978 /* (12) 123 JIH */
   2979     "123 JIH"
   2980 };
   2981 
   2982 static const char* const textOut[] = {
   2983 /* TC 0: 123 */
   2984     "123",                                                              /* (0) */
   2985 /* TC 1: .123->4.5 */
   2986     ".123->4.5",                                                        /* (1) */
   2987     "4.5<-123.",                                                        /* (2) */
   2988 /* TC 2: 678 */
   2989     "678",                                                              /* (3) */
   2990 /* TC 3: .678->8.9 */
   2991     ".8.9<-678",                                                        /* (4) */
   2992     "8.9<-678.",                                                        /* (5) */
   2993     ".678->8.9",                                                        /* (6) */
   2994 /* TC 4: MLK1.2,3JIH */
   2995     "KLM1.2,3HIJ",                                                      /* (7) */
   2996 /* TC 5: FE.>12-> */
   2997     "12<.EF->",                                                         /* (8) */
   2998     "<-12<.EF",                                                         /* (9) */
   2999     "EF.>@12->",                                                        /* (10) */
   3000 /* TC 6: JIH.>12->a */
   3001     "12<.HIJ->a",                                                       /* (11) */
   3002     "a<-12<.HIJ",                                                       /* (12) */
   3003     "HIJ.>@12->a",                                                      /* (13) */
   3004     "a&<-12<.HIJ",                                                      /* (14) */
   3005 /* TC 7: CBA.>67->89=a */
   3006     "ABC.>@67->89=a",                                                   /* (15) */
   3007     "a=89<-67<.ABC",                                                    /* (16) */
   3008     "a&=89<-67<.ABC",                                                   /* (17) */
   3009     "89<-67<.ABC=a",                                                    /* (18) */
   3010 /* TC 8: CBA.123->xyz */
   3011     "123.ABC->xyz",                                                     /* (19) */
   3012     "xyz<-123.ABC",                                                     /* (20) */
   3013     "ABC.@123->xyz",                                                    /* (21) */
   3014     "xyz&<-123.ABC",                                                    /* (22) */
   3015 /* TC 9: .>12->xyz */
   3016     ".>12->xyz",                                                        /* (23) */
   3017     "xyz<-12<.",                                                        /* (24) */
   3018     "xyz&<-12<.",                                                       /* (25) */
   3019 /* TC 10: a.>67->xyz */
   3020     "a.>67->xyz",                                                       /* (26) */
   3021     "a.>@67@->xyz",                                                     /* (27) */
   3022     "xyz<-67<.a",                                                       /* (28) */
   3023 /* TC 11: 123JIH */
   3024     "123HIJ",                                                           /* (29) */
   3025     "HIJ123",                                                           /* (30) */
   3026 /* TC 12: 123 JIH */
   3027     "123 HIJ",                                                          /* (31) */
   3028     "HIJ 123",                                                          /* (32) */
   3029 };
   3030 
   3031 #define NO                  UBIDI_MAP_NOWHERE
   3032 #define MAX_MAP_LENGTH      20
   3033 
   3034 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
   3035 /* TC 0: 123 */
   3036     { 0, 1, 2 },                                                        /* (0) */
   3037 /* TC 1: .123->4.5 */
   3038     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3039     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (2) */
   3040 /* TC 2: 678 */
   3041     { 0, 1, 2 },                                                        /* (3) */
   3042 /* TC 3: .678->8.9 */
   3043     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3044     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (5) */
   3045     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3046 /* TC 4: MLK1.2,3JIH */
   3047     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3048 /* TC 5: FE.>12-> */
   3049     { 5, 4, 3, 2, 0, 1, 6, 7 },                                         /* (8) */
   3050     { 7, 6, 5, 4, 2, 3, 1, 0 },                                         /* (9) */
   3051     { 1, 0, 2, 3, 5, 6, 7, 8 },                                         /* (10) */
   3052 /* TC 6: JIH.>12->a */
   3053     { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 },                                   /* (11) */
   3054     { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 },                                   /* (12) */
   3055     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 },                                  /* (13) */
   3056     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 },                                  /* (14) */
   3057 /* TC 7: CBA.>67->89=a */
   3058     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 },                      /* (15) */
   3059     { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 },                       /* (16) */
   3060     { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 },                      /* (17) */
   3061     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 },                       /* (18) */
   3062 /* TC 8: CBA.123->xyz */
   3063     { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 },                           /* (19) */
   3064     { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 },                           /* (20) */
   3065     { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 },                          /* (21) */
   3066     { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 },                          /* (22) */
   3067 /* TC 9: .>12->xyz */
   3068     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3069     { 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                      /* (24) */
   3070     { 9, 8, 6, 7, 5, 4, 0, 1, 2 },                                      /* (25) */
   3071 /* TC 10: a.>67->xyz */
   3072     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3073     { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 },                                 /* (27) */
   3074     { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                   /* (28) */
   3075 /* TC 11: 123JIH */
   3076     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3077     { 3, 4, 5, 2, 1, 0 },                                               /* (30) */
   3078 /* TC 12: 123 JIH */
   3079     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3080     { 4, 5, 6, 3, 2, 1, 0 },                                            /* (32) */
   3081 };
   3082 
   3083 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
   3084 /* TC 0: 123 */
   3085     { 0, 1, 2 },                                                        /* (0) */
   3086 /* TC 1: .123->4.5 */
   3087     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3088     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (2) */
   3089 /* TC 2: 678 */
   3090     { 0, 1, 2 },                                                        /* (3) */
   3091 /* TC 3: .678->8.9 */
   3092     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3093     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (5) */
   3094     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3095 /* TC 4: MLK1.2,3JIH */
   3096     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3097 /* TC 5: FE.>12-> */
   3098     { 4, 5, 3, 2, 1, 0, 6, 7 },                                         /* (8) */
   3099     { 7, 6, 4, 5, 3, 2, 1, 0 },                                         /* (9) */
   3100     { 1, 0, 2, 3, NO, 4, 5, 6, 7 },                                     /* (10) */
   3101 /* TC 6: JIH.>12->a */
   3102     { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 },                                   /* (11) */
   3103     { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                                   /* (12) */
   3104     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 },                               /* (13) */
   3105     { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                               /* (14) */
   3106 /* TC 7: CBA.>67->89=a */
   3107     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 },                   /* (15) */
   3108     { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                       /* (16) */
   3109     { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                   /* (17) */
   3110     { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 },                       /* (18) */
   3111 /* TC 8: CBA.123->xyz */
   3112     { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 },                           /* (19) */
   3113     { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                           /* (20) */
   3114     { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 },                       /* (21) */
   3115     { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                       /* (22) */
   3116 /* TC 9: .>12->xyz */
   3117     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3118     { 6, 7, 8, 5, 4, 2, 3, 1, 0 },                                      /* (24) */
   3119     { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 },                                  /* (25) */
   3120 /* TC 10: a.>67->xyz */
   3121     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3122     { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 },                           /* (27) */
   3123     { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 },                                   /* (28) */
   3124 /* TC 11: 123JIH */
   3125     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3126     { 5, 4, 3, 0, 1, 2 },                                               /* (30) */
   3127 /* TC 12: 123 JIH */
   3128     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3129     { 6, 5, 4, 3, 0, 1, 2 },                                            /* (32) */
   3130 };
   3131 
   3132 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
   3133             [LEVELS_COUNT] = {
   3134     { /* TC 0: 123 */
   3135         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3136         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3137         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3138         {{ 0,  0}, { 0,  0}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3139     },
   3140     { /* TC 1: .123->4.5 */
   3141         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3142         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3143         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3144         {{ 1,  2}, { 1,  2}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3145     },
   3146     { /* TC 2: 678 */
   3147         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3148         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3149         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3150         {{ 3,  3}, { 3,  3}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3151     },
   3152     { /* TC 3: .678->8.9 */
   3153         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3154         {{ 4,  5}, { 4,  5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3155         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3156         {{ 6,  5}, { 6,  5}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3157     },
   3158     { /* TC 4: MLK1.2,3JIH */
   3159         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3160         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3161         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3162         {{ 7,  7}, { 7,  7}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3163     },
   3164     { /* TC 5: FE.>12-> */
   3165         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3166         {{10,  9}, { 8,  9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3167         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3168         {{10,  9}, { 8,  9}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3169     },
   3170     { /* TC 6: JIH.>12->a */
   3171         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3172         {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3173         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3174         {{13, 14}, {11, 12}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3175     },
   3176     { /* TC 7: CBA.>67->89=a */
   3177         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3178         {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3179         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3180         {{15, 17}, {18, 16}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3181     },
   3182     { /* TC 8: CBA.>124->xyz */
   3183         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3184         {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3185         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3186         {{21, 22}, {19, 20}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3187     },
   3188     { /* TC 9: .>12->xyz */
   3189         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3190         {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3191         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3192         {{23, 25}, {23, 24}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3193     },
   3194     { /* TC 10: a.>67->xyz */
   3195         {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3196         {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3197         {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3198         {{26, 27}, {26, 28}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3199     },
   3200     { /* TC 11: 124JIH */
   3201         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3202         {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3203         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3204         {{30, 30}, {30, 30}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3205     },
   3206     { /* TC 12: 124 JIH */
   3207         {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3208         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3209         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3210         {{31, 32}, {31, 32}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3211     }
   3212 };
   3213 
   3214 static UBool
   3215 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
   3216                 const char *destChars, const UChar *dest, int32_t destLen,
   3217                 int mode, int option, UBiDiLevel level) {
   3218 
   3219     static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
   3220                 [LEVELS_COUNT] = {
   3221         { /* TC 0: 123 */
   3222             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3223             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3224             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3225             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3226             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3227         },
   3228         { /* TC 1: .123->4.5 */
   3229             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3230             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3231             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3232             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3233             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3234         },
   3235         { /* TC 2: 678 */
   3236             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3237             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3238             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3239             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3240             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3241         },
   3242         { /* TC 3: .678->8.9 */
   3243             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3244             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3245             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3246             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3247             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3248         },
   3249         { /* TC 4: MLK1.2,3JIH */
   3250             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3251             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3252             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3253             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3254             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3255         },
   3256         { /* TC 5: FE.>12-> */
   3257             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3258             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3259             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3260             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3261             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3262         },
   3263         { /* TC 6: JIH.>12->a */
   3264             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3265             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3266             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3267             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3268             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3269         },
   3270         { /* TC 7: CBA.>67->89=a */
   3271             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3272             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3273             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3274             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3275             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3276         },
   3277         { /* TC 8: CBA.>123->xyz */
   3278             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3279             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3280             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3281             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3282             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3283         },
   3284         { /* TC 9: .>12->xyz */
   3285             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3286             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3287             {{ 1,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3288             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3289             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3290         },
   3291         { /* TC 10: a.>67->xyz */
   3292             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3293             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3294             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3295             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3296             {{ 1,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3297         },
   3298         { /* TC 11: 123JIH */
   3299             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3300             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3301             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3302             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3303             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3304         },
   3305         { /* TC 12: 123 JIH */
   3306             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3307             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3308             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3309             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3310             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3311         }
   3312     };
   3313 
   3314     #define SET_ROUND_TRIP_MODE(mode) \
   3315         ubidi_setReorderingMode(pBiDi, mode); \
   3316         desc = #mode; \
   3317         break;
   3318 
   3319     UErrorCode rc = U_ZERO_ERROR;
   3320     UChar dest2[MAXLEN];
   3321     int32_t destLen2;
   3322     const char* desc;
   3323     char destChars2[MAXLEN];
   3324     char destChars3[MAXLEN];
   3325 
   3326     switch (modes[mode].value) {
   3327         case UBIDI_REORDER_NUMBERS_SPECIAL:
   3328             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
   3329         case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
   3330             SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
   3331         case UBIDI_REORDER_RUNS_ONLY:
   3332             SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
   3333         case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
   3334             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   3335         case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
   3336             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   3337         case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
   3338             SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
   3339         default:
   3340             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
   3341     }
   3342     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   3343 
   3344     ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
   3345     assertSuccessful("ubidi_setPara", &rc);
   3346     *dest2 = 0;
   3347     destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
   3348                                     &rc);
   3349     assertSuccessful("ubidi_writeReordered", &rc);
   3350 
   3351     u16ToPseudo(destLen, dest, destChars3);
   3352     u16ToPseudo(destLen2, dest2, destChars2);
   3353     checkWhatYouCan(pBiDi, destChars3, destChars2);
   3354     if (strcmp(srcChars, destChars2)) {
   3355         if (roundtrip[tc][mode][option][level]) {
   3356             log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
   3357                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   3358                     "\n%20s %u\n", tc, mode, option,
   3359                     "Original text:", srcChars,
   3360                     "Round-tripped text:", destChars2,
   3361                     "Intermediate  text:", destChars3,
   3362                     "Reordering mode:", modes[mode].description,
   3363                     "Reordering option:", options[option].description,
   3364                     "Paragraph level:", level);
   3365         }
   3366         else {
   3367             log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
   3368                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   3369                     "\n%20s %u\n", tc, mode, option,
   3370                     "Original text:", srcChars,
   3371                     "Round-tripped text:", destChars2,
   3372                     "Intermediate  text:", destChars3,
   3373                     "Reordering mode:", modes[mode].description,
   3374                     "Reordering option:", options[option].description,
   3375                     "Paragraph level:", level);
   3376         }
   3377         return FALSE;
   3378     }
   3379     if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
   3380                            desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
   3381         return FALSE;
   3382     }
   3383     if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
   3384                                     desc, "UBIDI_OPTION_REMOVE_CONTROLS",
   3385                                     level, FALSE)) {
   3386         return FALSE;
   3387     }
   3388     return TRUE;
   3389 }
   3390 
   3391 static UBool
   3392 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
   3393                   int32_t destLen, const char* mode,
   3394                   const char* option, UBiDiLevel level) {
   3395     int32_t actualLen;
   3396     if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
   3397         actualLen = strlen(destChars);
   3398     else
   3399         actualLen = ubidi_getResultLength(pBiDi);
   3400     if (actualLen != destLen) {
   3401         log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
   3402                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
   3403                 "Expected:", destLen, "Actual:", actualLen,
   3404                 "Input:", srcChars, "Output:", destChars,
   3405                 "Reordering mode:", mode, "Reordering option:", option,
   3406                 "Paragraph level:", level);
   3407         return FALSE;
   3408     }
   3409     return TRUE;
   3410 }
   3411 
   3412 static void
   3413 testReorderRunsOnly(void) {
   3414     static const struct {
   3415         const char* textIn;
   3416         const char* textOut[2][2];
   3417         const char noroundtrip[2];
   3418     } testCases[] = {
   3419         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*0*/
   3420                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   3421         {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}},        /*1*/
   3422         {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}},   /*2*/
   3423         {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"},                            /*3*/
   3424                         {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
   3425         {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"},                   /*4*/
   3426                            {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
   3427         {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"},                   /*5*/
   3428                            {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
   3429         {"123->abc", {{"abc<-123", "abc<-123"},                                  /*6*/
   3430                       {"abc&<-123", "abc<-123"}}, {1, 0}},
   3431         {"123->JKL", {{"JKL<-123", "123->JKL"},                                  /*7*/
   3432                       {"JKL<-123", "JKL<-@123"}}, {0, 1}},
   3433         {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"},                   /*8*/
   3434                            {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
   3435         {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"},                   /*9*/
   3436                            {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
   3437         {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"},                   /*10*/
   3438                            {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
   3439         {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"},                   /*11*/
   3440                            {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
   3441         {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"},                   /*12*/
   3442                            {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
   3443         {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"},                   /*13*/
   3444                            {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
   3445         {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"},                   /*14*/
   3446                            {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
   3447         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*15*/
   3448                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   3449         {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"},          /*16*/
   3450                               {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
   3451         {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"},                       /*17*/
   3452                            {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
   3453         {"123", {{"123", "123"},                /* just one run */               /*18*/
   3454                  {"123", "123"}}, {0, 0}}
   3455     };
   3456     UBiDi *pBiDi = getBiDiObject();
   3457     UBiDi *pL2VBiDi = getBiDiObject();
   3458     UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
   3459     char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
   3460     int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
   3461     UErrorCode rc = U_ZERO_ERROR;
   3462     UBiDiLevel level;
   3463 
   3464     log_verbose("\nEntering TestReorderRunsOnly\n\n");
   3465 
   3466     if(!pL2VBiDi) {
   3467         ubidi_close(pBiDi);             /* in case this one was allocated */
   3468         return;
   3469     }
   3470     ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
   3471     ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   3472 
   3473     for (option = 0; option < 2; option++) {
   3474         ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
   3475                                                     : UBIDI_OPTION_INSERT_MARKS);
   3476         for (i = 0, nCases = LENGTHOF(testCases); i < nCases; i++) {
   3477             srcLen = strlen(testCases[i].textIn);
   3478             pseudoToU16(srcLen, testCases[i].textIn, src);
   3479             for(j = 0; j < 2; j++) {
   3480                 log_verbose("Now doing test for option %d, case %d, level %d\n",
   3481                             i, option, j);
   3482                 level = paraLevels[j];
   3483                 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   3484                 assertSuccessful("ubidi_setPara", &rc);
   3485                 *dest = 0;
   3486                 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3487                 assertSuccessful("ubidi_writeReordered", &rc);
   3488                 u16ToPseudo(destLen, dest, destChars);
   3489                 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
   3490                 assertStringsEqual(testCases[i].textOut[option][level], destChars,
   3491                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
   3492                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   3493                         pBiDi);
   3494 
   3495                 if((option==0) && testCases[i].noroundtrip[level]) {
   3496                     continue;
   3497                 }
   3498                 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
   3499                 assertSuccessful("ubidi_setPara1", &rc);
   3500                 *visual1 = 0;
   3501                 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3502                 assertSuccessful("ubidi_writeReordered1", &rc);
   3503                 u16ToPseudo(vis1Len, visual1, vis1Chars);
   3504                 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
   3505                 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
   3506                 assertSuccessful("ubidi_setPara2", &rc);
   3507                 *visual2 = 0;
   3508                 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   3509                 assertSuccessful("ubidi_writeReordered2", &rc);
   3510                 u16ToPseudo(vis2Len, visual2, vis2Chars);
   3511                 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
   3512                 assertStringsEqual(vis1Chars, vis2Chars,
   3513                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
   3514                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   3515                         pBiDi);
   3516             }
   3517         }
   3518     }
   3519 
   3520     /* test with null or empty text */
   3521     ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
   3522     assertSuccessful("ubidi_setPara3", &rc);
   3523     paras = ubidi_countParagraphs(pBiDi);
   3524     if (paras != 0) {
   3525         log_err("\nInvalid number of paras (should be 0): %d\n", paras);
   3526     }
   3527 
   3528     ubidi_close(pBiDi);
   3529     ubidi_close(pL2VBiDi);
   3530 
   3531     log_verbose("\nExiting TestReorderRunsOnly\n\n");
   3532 }
   3533 
   3534 static void
   3535 testReorderingMode(void) {
   3536 
   3537     UChar src[MAXLEN], dest[MAXLEN];
   3538     char destChars[MAXLEN];
   3539     UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
   3540     UErrorCode rc;
   3541     int tc, mode, option, level;
   3542     uint32_t optionValue, optionBack;
   3543     UBiDiReorderingMode modeValue, modeBack;
   3544     int32_t srcLen, destLen, index;
   3545     const char *expectedChars;
   3546     UBool testOK = TRUE;
   3547 
   3548     log_verbose("\nEntering TestReorderingMode\n\n");
   3549 
   3550     pBiDi = getBiDiObject();
   3551     pBiDi2 = getBiDiObject();
   3552     pBiDi3 = getBiDiObject();
   3553     if(!pBiDi3) {
   3554         ubidi_close(pBiDi);             /* in case this one was allocated */
   3555         ubidi_close(pBiDi2);            /* in case this one was allocated */
   3556         return;
   3557     }
   3558 
   3559     ubidi_setInverse(pBiDi2, TRUE);
   3560 
   3561     for (tc = 0; tc < TC_COUNT; tc++) {
   3562         const char *srcChars = textIn[tc];
   3563         srcLen = strlen(srcChars);
   3564         pseudoToU16(srcLen, srcChars, src);
   3565 
   3566         for (mode = 0; mode < MODES_COUNT; mode++) {
   3567             modeValue = modes[mode].value;
   3568             ubidi_setReorderingMode(pBiDi, modeValue);
   3569             modeBack = ubidi_getReorderingMode(pBiDi);
   3570             if (modeValue != modeBack) {
   3571                 log_err("Error while setting reordering mode to %d, returned %d\n",
   3572                         modeValue, modeBack);
   3573             }
   3574 
   3575             for (option = 0; option < OPTIONS_COUNT; option++) {
   3576                 optionValue = options[option].value;
   3577                 ubidi_setReorderingOptions(pBiDi, optionValue);
   3578                 optionBack = ubidi_getReorderingOptions(pBiDi);
   3579                 if (optionValue != optionBack) {
   3580                     log_err("Error while setting reordering option to %d, returned %d\n",
   3581                             optionValue, optionBack);
   3582                 }
   3583 
   3584                 for (level = 0; level < LEVELS_COUNT; level++) {
   3585                     log_verbose("starting test %d mode=%d option=%d level=%d\n",
   3586                                 tc, modes[mode].value, options[option].value, level);
   3587                     rc = U_ZERO_ERROR;
   3588                     ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
   3589                     assertSuccessful("ubidi_setPara", &rc);
   3590 
   3591                     *dest = 0;
   3592                     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   3593                                                    UBIDI_DO_MIRRORING, &rc);
   3594                     assertSuccessful("ubidi_writeReordered", &rc);
   3595                     u16ToPseudo(destLen, dest, destChars);
   3596                     if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
   3597                           (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
   3598                         checkWhatYouCan(pBiDi, srcChars, destChars);
   3599                     }
   3600 
   3601                     if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
   3602                         index = -1;
   3603                         expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
   3604                                 options[option].value, paraLevels[level], destChars);
   3605                     }
   3606                     else {
   3607                         index = outIndices[tc][mode][option][level];
   3608                         expectedChars = textOut[index];
   3609                     }
   3610                     if (!assertStringsEqual(expectedChars, destChars, srcChars,
   3611                                 modes[mode].description,
   3612                                 options[option].description,
   3613                                 pBiDi)) {
   3614                         testOK = FALSE;
   3615                     }
   3616                     if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
   3617                              !assertRoundTrip(pBiDi3, tc, index, srcChars,
   3618                                               destChars, dest, destLen,
   3619                                               mode, option, paraLevels[level])) {
   3620                         testOK = FALSE;
   3621                     }
   3622                     else if (!checkResultLength(pBiDi, srcChars, destChars,
   3623                                 destLen, modes[mode].description,
   3624                                 options[option].description,
   3625                                 paraLevels[level])) {
   3626                         testOK = FALSE;
   3627                     }
   3628                     else if (index > -1 && !checkMaps(pBiDi, index, srcChars,
   3629                             destChars, modes[mode].description,
   3630                             options[option].description, paraLevels[level],
   3631                             TRUE)) {
   3632                         testOK = FALSE;
   3633                     }
   3634                 }
   3635             }
   3636         }
   3637     }
   3638     if (testOK == TRUE) {
   3639         log_verbose("\nReordering mode test OK\n");
   3640     }
   3641     ubidi_close(pBiDi3);
   3642     ubidi_close(pBiDi2);
   3643     ubidi_close(pBiDi);
   3644 
   3645     log_verbose("\nExiting TestReorderingMode\n\n");
   3646 }
   3647 
   3648 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
   3649                                 uint32_t option, UBiDiLevel level, char *result) {
   3650     UErrorCode rc = U_ZERO_ERROR;
   3651     int32_t destLen;
   3652     UChar src[MAXLEN], dest2[MAXLEN];
   3653 
   3654     if (pBiDi == NULL || src == NULL) {
   3655         return NULL;
   3656     }
   3657     ubidi_setReorderingOptions(pBiDi, option);
   3658     pseudoToU16(srcLen, srcChars, src);
   3659     ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   3660     assertSuccessful("ubidi_setPara", &rc);
   3661 
   3662     *dest2 = 0;
   3663     destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
   3664                                    UBIDI_DO_MIRRORING, &rc);
   3665     assertSuccessful("ubidi_writeReordered", &rc);
   3666     u16ToPseudo(destLen, dest2, result);
   3667     if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
   3668         checkWhatYouCan(pBiDi, srcChars, result);
   3669     }
   3670     return result;
   3671 }
   3672 
   3673 #define NULL_CHAR '\0'
   3674 
   3675 static void
   3676 testStreaming(void) {
   3677 #define MAXPORTIONS 10
   3678 
   3679     static const struct {
   3680         const char* textIn;
   3681         short int chunk;
   3682         short int nPortions[2];
   3683         char  portionLens[2][MAXPORTIONS];
   3684         const char* message[2];
   3685     } testData[] = {
   3686         {   "123\\u000A"
   3687             "abc45\\u000D"
   3688             "67890\\u000A"
   3689             "\\u000D"
   3690             "02468\\u000D"
   3691             "ghi",
   3692             6, { 6, 6 }, {{ 6, 4, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
   3693             {"6, 4, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
   3694         },
   3695         {   "abcd\\u000Afgh\\u000D12345\\u000A456",
   3696             6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
   3697             {"6, 3, 6, 3", "5, 4, 6, 3"}
   3698         },
   3699         {   "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
   3700             6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
   3701             {"6, 3, 6, 3", "5, 4, 6, 3"}
   3702         },
   3703         {   "abcde\\u000Afghi",
   3704             10, { 1, 2 }, {{ 10 }, { 6, 4 }},
   3705             {"10", "6, 4"}
   3706         }
   3707     };
   3708     UChar src[MAXLEN];
   3709     UBiDi *pBiDi = NULL;
   3710     UChar *pSrc;
   3711     UErrorCode rc = U_ZERO_ERROR;
   3712     int32_t srcLen, processedLen, chunk, len, nPortions;
   3713     int i, j, levelIndex;
   3714     UBiDiLevel level;
   3715     int nTests = LENGTHOF(testData), nLevels = LENGTHOF(paraLevels);
   3716     UBool mismatch, testOK = TRUE;
   3717     char processedLenStr[MAXPORTIONS * 5];
   3718 
   3719     log_verbose("\nEntering TestStreaming\n\n");
   3720 
   3721     pBiDi = getBiDiObject();
   3722 
   3723     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   3724 
   3725     for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
   3726         for (i = 0; i < nTests; i++) {
   3727             srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
   3728             chunk = testData[i].chunk;
   3729             nPortions = testData[i].nPortions[levelIndex];
   3730             level = paraLevels[levelIndex];
   3731             *processedLenStr = NULL_CHAR;
   3732             log_verbose("Testing level %d, case %d\n", level, i);
   3733 
   3734             mismatch = FALSE;
   3735 
   3736             ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   3737             for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
   3738 
   3739                 len = chunk < srcLen ? chunk : srcLen;
   3740                 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
   3741                 if (!assertSuccessful("ubidi_setPara", &rc)) {
   3742                     break;
   3743                 }
   3744 
   3745                 processedLen = ubidi_getProcessedLength(pBiDi);
   3746                 if (processedLen == 0) {
   3747                     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
   3748                     j--;
   3749                     continue;
   3750                 }
   3751                 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   3752 
   3753                 mismatch = (UBool)(j >= nPortions ||
   3754                            processedLen != testData[i].portionLens[levelIndex][j]);
   3755 
   3756                 sprintf(processedLenStr + j * 4, "%4d", processedLen);
   3757                 srcLen -= processedLen, pSrc += processedLen;
   3758             }
   3759 
   3760             if (mismatch || j != nPortions) {
   3761                 testOK = FALSE;
   3762                 log_err("\nProcessed lengths mismatch.\n"
   3763                     "\tParagraph level: %u\n"
   3764                     "\tInput string: %s\n"
   3765                     "\tActually processed portion lengths: { %s }\n"
   3766                     "\tExpected portion lengths          : { %s }\n",
   3767                     paraLevels[levelIndex], testData[i].textIn,
   3768                     processedLenStr, testData[i].message[levelIndex]);
   3769             }
   3770         }
   3771     }
   3772     ubidi_close(pBiDi);
   3773     if (testOK == TRUE) {
   3774         log_verbose("\nBiDi streaming test OK\n");
   3775     }
   3776     log_verbose("\nExiting TestStreaming\n\n");
   3777 }
   3778 
   3779 U_CDECL_BEGIN
   3780 
   3781 static UCharDirection U_CALLCONV
   3782 overrideBidiClass(const void *context, UChar32 c) {
   3783 
   3784 #define DEF U_BIDI_CLASS_DEFAULT
   3785 
   3786     static const UCharDirection customClasses[] = {
   3787        /* 0/8    1/9    2/A    3/B    4/C    5/D    6/E    7/F  */
   3788           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 00-07 */
   3789           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 08-0F */
   3790           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 10-17 */
   3791           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 18-1F */
   3792           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,     R,   DEF, /* 20-27 */
   3793           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 28-2F */
   3794            EN,    EN,    EN,    EN,    EN,    EN,    AN,    AN, /* 30-37 */
   3795            AN,    AN,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 38-3F */
   3796             L,    AL,    AL,    AL,    AL,    AL,    AL,     R, /* 40-47 */
   3797             R,     R,     R,     R,     R,     R,     R,     R, /* 48-4F */
   3798             R,     R,     R,     R,     R,     R,     R,     R, /* 50-57 */
   3799             R,     R,     R,   LRE,   DEF,   RLE,   PDF,     S, /* 58-5F */
   3800           NSM,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 60-67 */
   3801           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 68-6F */
   3802           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 70-77 */
   3803           DEF,   DEF,   DEF,   LRO,     B,   RLO,    BN,   DEF  /* 78-7F */
   3804     };
   3805     static const int nEntries = LENGTHOF(customClasses);
   3806     const char *dummy = context;        /* just to avoid a compiler warning */
   3807     dummy++;
   3808 
   3809     return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
   3810 }
   3811 
   3812 U_CDECL_END
   3813 
   3814 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
   3815                                  UBiDiClassCallback* expectedFn,
   3816                                  const void* expectedContext,
   3817                                  int32_t sizeOfContext) {
   3818     if (fn != expectedFn) {
   3819         log_err("Class callback pointer is not set properly.\n");
   3820     }
   3821     if (context != expectedContext) {
   3822         log_err("Class callback context is not set properly.\n");
   3823     }
   3824     else if (context != NULL &&
   3825             memcmp(context, expectedContext, sizeOfContext)) {
   3826         log_err("Callback context content doesn't match the expected one.\n");
   3827     }
   3828 }
   3829 
   3830 static void
   3831 testClassOverride(void) {
   3832     static const char* const textSrc  = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
   3833     static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
   3834 
   3835     UChar src[MAXLEN], dest[MAXLEN];
   3836     UErrorCode rc = U_ZERO_ERROR;
   3837     UBiDi *pBiDi = NULL;
   3838     UBiDiClassCallback* oldFn = NULL;
   3839     UBiDiClassCallback* newFn = overrideBidiClass;
   3840     const void* oldContext = NULL;
   3841     int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
   3842     char* destChars = NULL;
   3843 
   3844     log_verbose("\nEntering TestClassOverride\n\n");
   3845 
   3846     pBiDi = getBiDiObject();
   3847     if(!pBiDi) {
   3848         return;
   3849     }
   3850 
   3851     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   3852     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   3853 
   3854     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   3855     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   3856         ubidi_close(pBiDi);
   3857         return;
   3858     }
   3859     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   3860 
   3861     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   3862     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   3863 
   3864     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   3865     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   3866         ubidi_close(pBiDi);
   3867         return;
   3868     }
   3869     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   3870 
   3871     srcLen = u_unescape(textSrc, src, MAXLEN);
   3872     ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
   3873     assertSuccessful("ubidi_setPara", &rc);
   3874 
   3875     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   3876                                    UBIDI_DO_MIRRORING, &rc);
   3877     assertSuccessful("ubidi_writeReordered", &rc);
   3878 
   3879     destChars = aescstrdup(dest, destLen);
   3880     if (uprv_strcmp(textResult, destChars)) {
   3881         log_err("\nActual and expected output mismatch.\n"
   3882             "%20s %s\n%20s %s\n%20s %s\n",
   3883             "Input:", textSrc, "Actual output:", destChars,
   3884             "Expected output:", textResult);
   3885     }
   3886     else {
   3887         log_verbose("\nClass override test OK\n");
   3888     }
   3889     ubidi_close(pBiDi);
   3890     log_verbose("\nExiting TestClassOverride\n\n");
   3891 }
   3892 
   3893 static char * formatMap(const int32_t * map, int len, char * buffer)
   3894 {
   3895     int32_t i, k;
   3896     char c;
   3897     for (i = 0; i < len; i++) {
   3898         k = map[i];
   3899         if (k < 0)
   3900             c = '-';
   3901         else if (k >= sizeof(columns))
   3902             c = '+';
   3903         else
   3904             c = columns[k];
   3905         buffer[i] = c;
   3906     }
   3907     buffer[len] = '\0';
   3908     return buffer;
   3909 }
   3910 
   3911 static UBool
   3912 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
   3913           const char *mode, const char* option, UBiDiLevel level, UBool forward)
   3914 {
   3915     int32_t actualLogicalMap[MAX_MAP_LENGTH];
   3916     int32_t actualVisualMap[MAX_MAP_LENGTH];
   3917     int32_t getIndexMap[MAX_MAP_LENGTH];
   3918     int32_t i, srcLen, resLen, index;
   3919     const int32_t *expectedLogicalMap, *expectedVisualMap;
   3920     UErrorCode rc = U_ZERO_ERROR;
   3921     UBool testOK = TRUE;
   3922 
   3923     if (forward) {
   3924         expectedLogicalMap = forwardMap[stringIndex];
   3925         expectedVisualMap  = inverseMap[stringIndex];
   3926     }
   3927     else {
   3928         expectedLogicalMap = inverseMap[stringIndex];
   3929         expectedVisualMap  = forwardMap[stringIndex];
   3930     }
   3931     ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
   3932     if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
   3933         testOK = FALSE;
   3934     }
   3935     srcLen = ubidi_getProcessedLength(pBiDi);
   3936     if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
   3937         char expChars[MAX_MAP_LENGTH];
   3938         char actChars[MAX_MAP_LENGTH];
   3939         log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
   3940                 "index %d\n"
   3941                 "source: %s\n"
   3942                 "dest  : %s\n"
   3943                 "Scale : %s\n"
   3944                 "ExpMap: %s\n"
   3945                 "Actual: %s\n"
   3946                 "Paragraph level  : %d == %d\n"
   3947                 "Reordering mode  : %s == %d\n"
   3948                 "Reordering option: %s == %d\n"
   3949                 "Forward flag     : %d\n",
   3950                 stringIndex, src, dest, columns,
   3951                 formatMap(expectedLogicalMap, srcLen, expChars),
   3952                 formatMap(actualLogicalMap, srcLen, actChars),
   3953                 level, ubidi_getParaLevel(pBiDi),
   3954                 mode, ubidi_getReorderingMode(pBiDi),
   3955                 option, ubidi_getReorderingOptions(pBiDi),
   3956                 forward
   3957                 );
   3958         testOK = FALSE;
   3959     }
   3960     resLen = ubidi_getResultLength(pBiDi);
   3961     ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
   3962     assertSuccessful("ubidi_getVisualMap", &rc);
   3963     if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
   3964         char expChars[MAX_MAP_LENGTH];
   3965         char actChars[MAX_MAP_LENGTH];
   3966         log_err("\nubidi_getVisualMap() returns unexpected map for output string "
   3967                 "index %d\n"
   3968                 "source: %s\n"
   3969                 "dest  : %s\n"
   3970                 "Scale : %s\n"
   3971                 "ExpMap: %s\n"
   3972                 "Actual: %s\n"
   3973                 "Paragraph level  : %d == %d\n"
   3974                 "Reordering mode  : %s == %d\n"
   3975                 "Reordering option: %s == %d\n"
   3976                 "Forward flag     : %d\n",
   3977                 stringIndex, src, dest, columns,
   3978                 formatMap(expectedVisualMap, resLen, expChars),
   3979                 formatMap(actualVisualMap, resLen, actChars),
   3980                 level, ubidi_getParaLevel(pBiDi),
   3981                 mode, ubidi_getReorderingMode(pBiDi),
   3982                 option, ubidi_getReorderingOptions(pBiDi),
   3983                 forward
   3984                 );
   3985         testOK = FALSE;
   3986     }
   3987     for (i = 0; i < srcLen; i++) {
   3988         index = ubidi_getVisualIndex(pBiDi, i, &rc);
   3989         assertSuccessful("ubidi_getVisualIndex", &rc);
   3990         getIndexMap[i] = index;
   3991     }
   3992     if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
   3993         char actChars[MAX_MAP_LENGTH];
   3994         char gotChars[MAX_MAP_LENGTH];
   3995         log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
   3996                 "index %d\n"
   3997                 "source: %s\n"
   3998                 "dest  : %s\n"
   3999                 "Scale : %s\n"
   4000                 "ActMap: %s\n"
   4001                 "IdxMap: %s\n"
   4002                 "Paragraph level  : %d == %d\n"
   4003                 "Reordering mode  : %s == %d\n"
   4004                 "Reordering option: %s == %d\n"
   4005                 "Forward flag     : %d\n",
   4006                 stringIndex, src, dest, columns,
   4007                 formatMap(actualLogicalMap, srcLen, actChars),
   4008                 formatMap(getIndexMap, srcLen, gotChars),
   4009                 level, ubidi_getParaLevel(pBiDi),
   4010                 mode, ubidi_getReorderingMode(pBiDi),
   4011                 option, ubidi_getReorderingOptions(pBiDi),
   4012                 forward
   4013                 );
   4014         testOK = FALSE;
   4015     }
   4016     for (i = 0; i < resLen; i++) {
   4017         index = ubidi_getLogicalIndex(pBiDi, i, &rc);
   4018         assertSuccessful("ubidi_getLogicalIndex", &rc);
   4019         getIndexMap[i] = index;
   4020     }
   4021     if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
   4022         char actChars[MAX_MAP_LENGTH];
   4023         char gotChars[MAX_MAP_LENGTH];
   4024         log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
   4025                 "index %d\n"
   4026                 "source: %s\n"
   4027                 "dest  : %s\n"
   4028                 "Scale : %s\n"
   4029                 "ActMap: %s\n"
   4030                 "IdxMap: %s\n"
   4031                 "Paragraph level  : %d == %d\n"
   4032                 "Reordering mode  : %s == %d\n"
   4033                 "Reordering option: %s == %d\n"
   4034                 "Forward flag     : %d\n",
   4035                 stringIndex, src, dest, columns,
   4036                 formatMap(actualVisualMap, resLen, actChars),
   4037                 formatMap(getIndexMap, resLen, gotChars),
   4038                 level, ubidi_getParaLevel(pBiDi),
   4039                 mode, ubidi_getReorderingMode(pBiDi),
   4040                 option, ubidi_getReorderingOptions(pBiDi),
   4041                 forward
   4042                 );
   4043         testOK = FALSE;
   4044     }
   4045     return testOK;
   4046 }
   4047 
   4048