Home | History | Annotate | Download | only in cintltst
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /********************************************************************
      4  * COPYRIGHT:
      5  * Copyright (c) 1997-2014, International Business Machines Corporation and
      6  * others. All Rights Reserved.
      7  ********************************************************************/
      8 /*   file name:  cbiditst.c
      9 *   encoding:   UTF-8
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 1999sep27
     14 *   created by: Markus W. Scherer, updated by Matitiahu Allouche
     15 */
     16 
     17 #include "cintltst.h"
     18 #include "unicode/utypes.h"
     19 #include "unicode/uchar.h"
     20 #include "unicode/ustring.h"
     21 #include "unicode/ubidi.h"
     22 #include "unicode/ushape.h"
     23 #include "cbiditst.h"
     24 #include "cstring.h"
     25 /* the following include is needed for sprintf */
     26 #include <stdio.h>
     27 
     28 #define MAXLEN      MAX_STRING_LENGTH
     29 
     30 /* prototypes ---------------------------------------------------------------*/
     31 
     32 void addComplexTest(TestNode** root);
     33 
     34 static void testCharFromDirProp(void);
     35 
     36 static void testBidi(void);
     37 
     38 static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
     39 
     40 static void doMisc(void);
     41 
     42 static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
     43                    int32_t lineStart, UBool countRunsFirst);
     44 
     45 static void _testReordering(UBiDi *pBiDi, int testNumber);
     46 
     47 static void testInverse(void);
     48 
     49 static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
     50 
     51 static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
     52                              UBiDiLevel direction, UErrorCode *pErrorCode);
     53 
     54 static void _testWriteReverse(void);
     55 
     56 static void _testManyAddedPoints(void);
     57 
     58 static void _testMisc(void);
     59 
     60 static void doArabicShapingTest(void);
     61 
     62 static void doLamAlefSpecialVLTRArabicShapingTest(void);
     63 
     64 static void doTashkeelSpecialVLTRArabicShapingTest(void);
     65 
     66 static void doLOGICALArabicDeShapingTest(void);
     67 
     68 static void doArabicShapingTestForBug5421(void);
     69 
     70 static void doArabicShapingTestForBug8703(void);
     71 
     72 static void doArabicShapingTestForBug9024(void);
     73 
     74 static void _testPresentationForms(const UChar *in);
     75 
     76 static void doArabicShapingTestForNewCharacters(void);
     77 
     78 static void testReorder(void);
     79 
     80 static void testReorderArabicMathSymbols(void);
     81 
     82 static void testFailureRecovery(void);
     83 
     84 static void testMultipleParagraphs(void);
     85 
     86 static void testGetBaseDirection(void);
     87 
     88 static void testContext(void);
     89 
     90 static void doTailTest(void);
     91 
     92 static void testBracketOverflow(void);
     93 static void TestExplicitLevel0();
     94 
     95 /* new BIDI API */
     96 static void testReorderingMode(void);
     97 static void testReorderRunsOnly(void);
     98 static void testStreaming(void);
     99 static void testClassOverride(void);
    100 static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
    101                                 uint32_t option, UBiDiLevel level, char *result);
    102 static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
    103                              const char *srcChars, const char *destChars,
    104                              const UChar *dest, int32_t destLen, int mode,
    105                              int option, UBiDiLevel level);
    106 static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
    107                                const char *destChars,
    108                                int32_t destLen, const char *mode,
    109                                const char *option, UBiDiLevel level);
    110 static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
    111                        const char *dest, const char *mode, const char* option,
    112                        UBiDiLevel level, UBool forward);
    113 
    114 /* helpers ------------------------------------------------------------------ */
    115 
    116 static const char *levelString="...............................................................";
    117 
    118 static void initCharFromDirProps(void);
    119 
    120 static UChar *
    121 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
    122 
    123 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
    124 
    125 /* regression tests ---------------------------------------------------------*/
    126 
    127 void
    128 addComplexTest(TestNode** root) {
    129     addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
    130     addTest(root, testBidi, "complex/bidi/TestBidi");
    131     addTest(root, testInverse, "complex/bidi/TestInverse");
    132     addTest(root, testReorder,"complex/bidi/TestReorder");
    133     addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
    134     addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
    135     addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
    136     addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
    137     addTest(root, testStreaming, "complex/bidi/TestStreaming");
    138     addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
    139     addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection");
    140     addTest(root, testContext, "complex/bidi/testContext");
    141     addTest(root, testBracketOverflow, "complex/bidi/TestBracketOverflow");
    142     addTest(root, &TestExplicitLevel0, "complex/bidi/TestExplicitLevel0");
    143 
    144     addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
    145     addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
    146     addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
    147     addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
    148     addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
    149     addTest(root, doTailTest, "complex/arabic-shaping/tailtest");
    150     addTest(root, doArabicShapingTestForBug8703, "complex/arabic-shaping/bug-8703");
    151     addTest(root, testReorderArabicMathSymbols, "complex/bidi/bug-9024");
    152     addTest(root, doArabicShapingTestForBug9024, "complex/arabic-shaping/bug-9024");
    153     addTest(root, doArabicShapingTestForNewCharacters, "complex/arabic-shaping/shaping2");
    154 }
    155 
    156 static void
    157 testCharFromDirProp(void) {
    158     /* verify that the exemplar characters have the expected bidi classes */
    159     int32_t i;
    160 
    161     log_verbose("\nEntering TestCharFromDirProp\n\n");
    162     initCharFromDirProps();
    163 
    164     for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
    165         if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
    166             log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
    167                     i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
    168         }
    169     }
    170     log_verbose("\nExiting TestCharFromDirProp\n\n");
    171 }
    172 
    173 static void
    174 testBidi(void) {
    175     UBiDi *pBiDi, *pLine=NULL;
    176     UErrorCode errorCode=U_ZERO_ERROR;
    177 
    178     log_verbose("\nEntering TestBidi\n\n");
    179 
    180     pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
    181     if(pBiDi!=NULL) {
    182         pLine=ubidi_open();
    183         if(pLine!=NULL) {
    184             doTests(pBiDi, pLine, FALSE);
    185             doTests(pBiDi, pLine, TRUE);
    186         } else {
    187             log_err("ubidi_open() returned NULL, out of memory\n");
    188         }
    189     } else {
    190         log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
    191     }
    192     doMisc();
    193 
    194     if(pLine!=NULL) {
    195         ubidi_close(pLine);
    196     }
    197     if(pBiDi!=NULL) {
    198         ubidi_close(pBiDi);
    199     }
    200 
    201     log_verbose("\nExiting TestBidi\n\n");
    202 }
    203 
    204 static void
    205 doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
    206     int testNumber;
    207     UChar string[MAXLEN];
    208     UErrorCode errorCode;
    209     int32_t lineStart;
    210     UBiDiLevel paraLevel;
    211 
    212     for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
    213         errorCode=U_ZERO_ERROR;
    214         getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
    215         paraLevel=tests[testNumber].paraLevel;
    216         ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
    217         if(U_SUCCESS(errorCode)) {
    218             log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
    219                     testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
    220             lineStart=tests[testNumber].lineStart;
    221             if(lineStart==-1) {
    222                 doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
    223             } else {
    224                 ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
    225                 if(U_SUCCESS(errorCode)) {
    226                     log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
    227                             lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
    228                     doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
    229                 } else {
    230                     log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
    231                             testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
    232                 }
    233             }
    234         } else {
    235             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    236                     testNumber, paraLevel, myErrorName(errorCode));
    237         }
    238     }
    239 }
    240 
    241 static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    242 
    243 #define TABLE_SIZE  256
    244 static UBool   tablesInitialized = FALSE;
    245 static UChar   pseudoToUChar[TABLE_SIZE];
    246 static uint8_t UCharToPseudo[TABLE_SIZE];    /* used for Unicode chars < 0x0100 */
    247 static uint8_t UCharToPseud2[TABLE_SIZE];    /* used for Unicode chars >=0x0100 */
    248 
    249 static void buildPseudoTables(void)
    250 /*
    251     The rules for pseudo-Bidi are as follows:
    252     - [ == LRE
    253     - ] == RLE
    254     - { == LRO
    255     - } == RLO
    256     - ^ == PDF
    257     - @ == LRM
    258     - & == RLM
    259     - A-F == Arabic Letters 0631-0636
    260     - G-V == Hebrew letters 05d7-05e6
    261     - W-Z == Unassigned RTL 08d0-08d3
    262     - 0-5 == western digits 0030-0035
    263     - 6-9 == Arabic-Indic digits 0666-0669
    264     - ` == Combining Grave Accent 0300 (NSM)
    265     - ~ == Delete 007f (BN)
    266     - | == Paragraph Separator 2029 (B)
    267     - _ == Info Separator 1 001f (S)
    268     All other characters represent themselves as Latin-1, with the corresponding
    269     Bidi properties.
    270 */
    271 {
    272     int             i;
    273     UChar           uchar;
    274     uint8_t         c;
    275     /* initialize all tables to unknown */
    276     for (i=0; i < TABLE_SIZE; i++) {
    277         pseudoToUChar[i] = 0xFFFD;
    278         UCharToPseudo[i] = '?';
    279         UCharToPseud2[i] = '?';
    280     }
    281     /* initialize non letters or digits */
    282     pseudoToUChar[(uint8_t) 0 ] = 0x0000;    UCharToPseudo[0x00] = (uint8_t) 0 ;
    283     pseudoToUChar[(uint8_t)' '] = 0x0020;    UCharToPseudo[0x20] = (uint8_t)' ';
    284     pseudoToUChar[(uint8_t)'!'] = 0x0021;    UCharToPseudo[0x21] = (uint8_t)'!';
    285     pseudoToUChar[(uint8_t)'"'] = 0x0022;    UCharToPseudo[0x22] = (uint8_t)'"';
    286     pseudoToUChar[(uint8_t)'#'] = 0x0023;    UCharToPseudo[0x23] = (uint8_t)'#';
    287     pseudoToUChar[(uint8_t)'$'] = 0x0024;    UCharToPseudo[0x24] = (uint8_t)'$';
    288     pseudoToUChar[(uint8_t)'%'] = 0x0025;    UCharToPseudo[0x25] = (uint8_t)'%';
    289     pseudoToUChar[(uint8_t)'\'']= 0x0027;    UCharToPseudo[0x27] = (uint8_t)'\'';
    290     pseudoToUChar[(uint8_t)'('] = 0x0028;    UCharToPseudo[0x28] = (uint8_t)'(';
    291     pseudoToUChar[(uint8_t)')'] = 0x0029;    UCharToPseudo[0x29] = (uint8_t)')';
    292     pseudoToUChar[(uint8_t)'*'] = 0x002A;    UCharToPseudo[0x2A] = (uint8_t)'*';
    293     pseudoToUChar[(uint8_t)'+'] = 0x002B;    UCharToPseudo[0x2B] = (uint8_t)'+';
    294     pseudoToUChar[(uint8_t)','] = 0x002C;    UCharToPseudo[0x2C] = (uint8_t)',';
    295     pseudoToUChar[(uint8_t)'-'] = 0x002D;    UCharToPseudo[0x2D] = (uint8_t)'-';
    296     pseudoToUChar[(uint8_t)'.'] = 0x002E;    UCharToPseudo[0x2E] = (uint8_t)'.';
    297     pseudoToUChar[(uint8_t)'/'] = 0x002F;    UCharToPseudo[0x2F] = (uint8_t)'/';
    298     pseudoToUChar[(uint8_t)':'] = 0x003A;    UCharToPseudo[0x3A] = (uint8_t)':';
    299     pseudoToUChar[(uint8_t)';'] = 0x003B;    UCharToPseudo[0x3B] = (uint8_t)';';
    300     pseudoToUChar[(uint8_t)'<'] = 0x003C;    UCharToPseudo[0x3C] = (uint8_t)'<';
    301     pseudoToUChar[(uint8_t)'='] = 0x003D;    UCharToPseudo[0x3D] = (uint8_t)'=';
    302     pseudoToUChar[(uint8_t)'>'] = 0x003E;    UCharToPseudo[0x3E] = (uint8_t)'>';
    303     pseudoToUChar[(uint8_t)'?'] = 0x003F;    UCharToPseudo[0x3F] = (uint8_t)'?';
    304     pseudoToUChar[(uint8_t)'\\']= 0x005C;    UCharToPseudo[0x5C] = (uint8_t)'\\';
    305     /* initialize specially used characters */
    306     pseudoToUChar[(uint8_t)'`'] = 0x0300;    UCharToPseud2[0x00] = (uint8_t)'`';  /* NSM */
    307     pseudoToUChar[(uint8_t)'@'] = 0x200E;    UCharToPseud2[0x0E] = (uint8_t)'@';  /* LRM */
    308     pseudoToUChar[(uint8_t)'&'] = 0x200F;    UCharToPseud2[0x0F] = (uint8_t)'&';  /* RLM */
    309     pseudoToUChar[(uint8_t)'_'] = 0x001F;    UCharToPseudo[0x1F] = (uint8_t)'_';  /* S   */
    310     pseudoToUChar[(uint8_t)'|'] = 0x2029;    UCharToPseud2[0x29] = (uint8_t)'|';  /* B   */
    311     pseudoToUChar[(uint8_t)'['] = 0x202A;    UCharToPseud2[0x2A] = (uint8_t)'[';  /* LRE */
    312     pseudoToUChar[(uint8_t)']'] = 0x202B;    UCharToPseud2[0x2B] = (uint8_t)']';  /* RLE */
    313     pseudoToUChar[(uint8_t)'^'] = 0x202C;    UCharToPseud2[0x2C] = (uint8_t)'^';  /* PDF */
    314     pseudoToUChar[(uint8_t)'{'] = 0x202D;    UCharToPseud2[0x2D] = (uint8_t)'{';  /* LRO */
    315     pseudoToUChar[(uint8_t)'}'] = 0x202E;    UCharToPseud2[0x2E] = (uint8_t)'}';  /* RLO */
    316     pseudoToUChar[(uint8_t)'~'] = 0x007F;    UCharToPseudo[0x7F] = (uint8_t)'~';  /* BN  */
    317     /* initialize western digits */
    318     for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
    319         c = (uint8_t)columns[i];
    320         pseudoToUChar[c] = uchar;
    321         UCharToPseudo[uchar & 0x00ff] = c;
    322     }
    323     /* initialize Hindi digits */
    324     for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
    325         c = (uint8_t)columns[i];
    326         pseudoToUChar[c] = uchar;
    327         UCharToPseud2[uchar & 0x00ff] = c;
    328     }
    329     /* initialize Arabic letters */
    330     for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
    331         c = (uint8_t)columns[i];
    332         pseudoToUChar[c] = uchar;
    333         UCharToPseud2[uchar & 0x00ff] = c;
    334     }
    335     /* initialize Hebrew letters */
    336     for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
    337         c = (uint8_t)columns[i];
    338         pseudoToUChar[c] = uchar;
    339         UCharToPseud2[uchar & 0x00ff] = c;
    340     }
    341     /* initialize Unassigned code points */
    342     for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
    343         c = (uint8_t)columns[i];
    344         pseudoToUChar[c] = uchar;
    345         UCharToPseud2[uchar & 0x00ff] = c;
    346     }
    347     /* initialize Latin lower case letters */
    348     for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
    349         c = (uint8_t)columns[i];
    350         pseudoToUChar[c] = uchar;
    351         UCharToPseudo[uchar & 0x00ff] = c;
    352     }
    353     tablesInitialized = TRUE;
    354 }
    355 
    356 /*----------------------------------------------------------------------*/
    357 
    358 static int pseudoToU16(const int length, const char * input, UChar * output)
    359 /*  This function converts a pseudo-Bidi string into a UChar string.
    360     It returns the length of the UChar string.
    361 */
    362 {
    363     int             i;
    364     if (!tablesInitialized) {
    365         buildPseudoTables();
    366     }
    367     for (i = 0; i < length; i++)
    368         output[i] = pseudoToUChar[(uint8_t)input[i]];
    369     output[length] = 0;
    370     return length;
    371 }
    372 
    373 /*----------------------------------------------------------------------*/
    374 
    375 static int u16ToPseudo(const int length, const UChar * input, char * output)
    376 /*  This function converts a UChar string into a pseudo-Bidi string.
    377     It returns the length of the pseudo-Bidi string.
    378 */
    379 {
    380     int             i;
    381     UChar           uchar;
    382     if (!tablesInitialized) {
    383         buildPseudoTables();
    384     }
    385     for (i = 0; i < length; i++)
    386     {
    387         uchar = input[i];
    388         output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
    389                                         UCharToPseud2[uchar & 0x00ff];
    390     }
    391     output[length] = '\0';
    392     return length;
    393 }
    394 
    395 static char * formatLevels(UBiDi *bidi, char *buffer) {
    396     UErrorCode ec = U_ZERO_ERROR;
    397     const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
    398     int len = ubidi_getLength(bidi);
    399     char c;
    400     int i, k;
    401 
    402     if(U_FAILURE(ec)) {
    403         strcpy(buffer, "BAD LEVELS");
    404         return buffer;
    405     }
    406     for (i=0; i<len; i++) {
    407         k = gotLevels[i];
    408         if (k >= sizeof(columns))
    409             c = '+';
    410         else
    411             c = columns[k];
    412         buffer[i] = c;
    413     }
    414     buffer[len] = '\0';
    415     return buffer;
    416 }
    417 static const char *reorderingModeNames[] = {
    418     "UBIDI_REORDER_DEFAULT",
    419     "UBIDI_REORDER_NUMBERS_SPECIAL",
    420     "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
    421     "UBIDI_REORDER_RUNS_ONLY",
    422     "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
    423     "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
    424     "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
    425 
    426 static char *reorderingOptionNames(char *buffer, int options) {
    427     buffer[0] = 0;
    428     if (options & UBIDI_OPTION_INSERT_MARKS) {
    429         strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
    430     }
    431     if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
    432         strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
    433     }
    434     if (options & UBIDI_OPTION_STREAMING) {
    435         strcat(buffer, " UBIDI_OPTION_STREAMING");
    436     }
    437     return buffer;
    438 }
    439 
    440 static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
    441 /* src and dst are char arrays encoded as pseudo Bidi */
    442 {
    443     /* Since calls to log_err with a \n within the pattern increment the
    444      * error count, new lines are issued via fputs, except when we want the
    445      * increment to happen.
    446      */
    447     UErrorCode errorCode=U_ZERO_ERROR;
    448     int32_t i, length = ubidi_getProcessedLength(bidi);
    449     const UBiDiLevel *levels;
    450     char levelChars[MAXLEN];
    451     UBiDiLevel lev;
    452     int32_t runCount;
    453     char buffer[100];
    454     log_err("========================================"); fputs("\n", stderr);
    455     levels = ubidi_getLevels(bidi, &errorCode);
    456     if (U_FAILURE(errorCode)) {
    457         strcpy(levelChars, "BAD LEVELS");
    458     } else {
    459         log_err("Processed length: %d", length); fputs("\n", stderr);
    460         for (i = 0; i < length; i++) {
    461             lev = levels[i];
    462             if (lev < sizeof(columns)) {
    463                 levelChars[i] = columns[lev];
    464             } else {
    465                 levelChars[i] = '+';
    466             }
    467         }
    468         levelChars[length] = 0;
    469     }
    470     log_err("Levels: %s", levelChars); fputs("\n", stderr);
    471     log_err("Source: %s", src); fputs("\n", stderr);
    472     log_err("Result: %s", dst); fputs("\n", stderr);
    473     log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
    474     log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
    475     i = ubidi_getReorderingMode(bidi);
    476     log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
    477     fputs("\n", stderr);
    478     i = ubidi_getReorderingOptions(bidi);
    479     log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
    480     fputs("\n", stderr);
    481     runCount = ubidi_countRuns(bidi, &errorCode);
    482     if (U_FAILURE(errorCode)) {
    483         log_err( "BAD RUNS");
    484     } else {
    485         log_err("Runs: %d => logicalStart.length/level: ", runCount);
    486         for (i = 0; i < runCount; i++) {
    487             UBiDiDirection dir;
    488             int32_t start, len;
    489             dir = ubidi_getVisualRun(bidi, i, &start, &len);
    490             log_err(" %d.%d/%d", start, len, dir);
    491         }
    492     }
    493     fputs("\n", stderr);
    494 }
    495 
    496 static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
    497 {
    498     /* No test for []{} since they have special meaning for pseudo Bidi */
    499     static char mates1Chars[] = "<>()";
    500     static char mates2Chars[] = "><)(";
    501     UBiDiLevel level;
    502     int k, len;
    503 
    504     if (c1 == c2) {
    505         return TRUE;
    506     }
    507     /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
    508        so we use the appropriate run's level, which is good for all cases.
    509      */
    510     ubidi_getLogicalRun(bidi, i, NULL, &level);
    511     if ((level & 1) == 0) {
    512         return FALSE;
    513     }
    514     len = strlen(mates1Chars);
    515     for (k = 0; k < len; k++) {
    516         if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
    517             return TRUE;
    518         }
    519     }
    520     return FALSE;
    521 }
    522 
    523 static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
    524 /* srcChars and dstChars are char arrays encoded as pseudo Bidi */
    525 {
    526     int32_t i, idx, logLimit, visLimit;
    527     UBool testOK, errMap, errDst;
    528     UErrorCode errorCode=U_ZERO_ERROR;
    529     int32_t visMap[MAXLEN];
    530     int32_t logMap[MAXLEN];
    531     char accumSrc[MAXLEN];
    532     char accumDst[MAXLEN];
    533     ubidi_getVisualMap(bidi, visMap, &errorCode);
    534     ubidi_getLogicalMap(bidi, logMap, &errorCode);
    535     if (U_FAILURE(errorCode)) {
    536         log_err("Error #1 invoking ICU within checkWhatYouCan\n");
    537         return FALSE;
    538     }
    539 
    540     testOK = TRUE;
    541     errMap = errDst = FALSE;
    542     logLimit = ubidi_getProcessedLength(bidi);
    543     visLimit = ubidi_getResultLength(bidi);
    544     memset(accumSrc, '?', logLimit);
    545     memset(accumDst, '?', visLimit);
    546 
    547     for (i = 0; i < logLimit; i++) {
    548         idx = ubidi_getVisualIndex(bidi, i, &errorCode);
    549         if (idx != logMap[i]) {
    550             errMap = TRUE;
    551         }
    552         if (idx == UBIDI_MAP_NOWHERE) {
    553             continue;
    554         }
    555         if (idx >= visLimit) {
    556             continue;
    557         }
    558         accumDst[idx] = srcChars[i];
    559         if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
    560             errDst = TRUE;
    561         }
    562     }
    563     accumDst[visLimit] = 0;
    564     if (U_FAILURE(errorCode)) {
    565         log_err("Error #2 invoking ICU within checkWhatYouCan\n");
    566         return FALSE;
    567     }
    568     if (errMap) {
    569         if (testOK) {
    570             printCaseInfo(bidi, srcChars, dstChars);
    571             testOK = FALSE;
    572         }
    573         log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
    574         log_err("Map    :");
    575         for (i = 0; i < logLimit; i++) {
    576             log_err(" %d", logMap[i]);
    577         }
    578         fputs("\n", stderr);
    579         log_err("Indexes:");
    580         for (i = 0; i < logLimit; i++) {
    581             log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
    582         }
    583         fputs("\n", stderr);
    584     }
    585     if (errDst) {
    586         if (testOK) {
    587             printCaseInfo(bidi, srcChars, dstChars);
    588             testOK = FALSE;
    589         }
    590         log_err("Source does not map to Result\n");
    591         log_err("We got: %s", accumDst); fputs("\n", stderr);
    592     }
    593 
    594     errMap = errDst = FALSE;
    595     for (i = 0; i < visLimit; i++) {
    596         idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
    597         if (idx != visMap[i]) {
    598             errMap = TRUE;
    599         }
    600         if (idx == UBIDI_MAP_NOWHERE) {
    601             continue;
    602         }
    603         if (idx >= logLimit) {
    604             continue;
    605         }
    606         accumSrc[idx] = dstChars[i];
    607         if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
    608             errDst = TRUE;
    609         }
    610     }
    611     accumSrc[logLimit] = 0;
    612     if (U_FAILURE(errorCode)) {
    613         log_err("Error #3 invoking ICU within checkWhatYouCan\n");
    614         return FALSE;
    615     }
    616     if (errMap) {
    617         if (testOK) {
    618             printCaseInfo(bidi, srcChars, dstChars);
    619             testOK = FALSE;
    620         }
    621         log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
    622         log_err("Map    :");
    623         for (i = 0; i < visLimit; i++) {
    624             log_err(" %d", visMap[i]);
    625         }
    626         fputs("\n", stderr);
    627         log_err("Indexes:");
    628         for (i = 0; i < visLimit; i++) {
    629             log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
    630         }
    631         fputs("\n", stderr);
    632     }
    633     if (errDst) {
    634         if (testOK) {
    635             printCaseInfo(bidi, srcChars, dstChars);
    636             testOK = FALSE;
    637         }
    638         log_err("Result does not map to Source\n");
    639         log_err("We got: %s", accumSrc);
    640         fputs("\n", stderr);
    641     }
    642     return testOK;
    643 }
    644 
    645 static void
    646 testReorder(void) {
    647     static const char* const logicalOrder[] ={
    648             "del(KC)add(K.C.&)",
    649             "del(QDVT) add(BVDL)",
    650             "del(PQ)add(R.S.)T)U.&",
    651             "del(LV)add(L.V.) L.V.&",
    652             "day  0  R  DPDHRVR dayabbr",
    653             "day  1  H  DPHPDHDA dayabbr",
    654             "day  2   L  DPBLENDA dayabbr",
    655             "day  3  J  DPJQVM  dayabbr",
    656             "day  4   I  DPIQNF    dayabbr",
    657             "day  5  M  DPMEG  dayabbr",
    658             "helloDPMEG",
    659             "hello WXYZ"
    660     };
    661     static const char* const visualOrder[]={
    662             "del(CK)add(&.C.K)",
    663             "del(TVDQ) add(LDVB)",
    664             "del(QP)add(S.R.)&.U(T",            /* updated for Unicode 6.3 matching brackets */
    665             "del(VL)add(V.L.) &.V.L",           /* updated for Unicode 6.3 matching brackets */
    666             "day  0  RVRHDPD  R dayabbr",
    667             "day  1  ADHDPHPD  H dayabbr",
    668             "day  2   ADNELBPD  L dayabbr",
    669             "day  3  MVQJPD  J  dayabbr",
    670             "day  4   FNQIPD  I    dayabbr",
    671             "day  5  GEMPD  M  dayabbr",
    672             "helloGEMPD",
    673             "hello ZYXW"
    674     };
    675     static const char* const visualOrder1[]={
    676             ")K.C.&(dda)KC(led",
    677             ")BVDL(dda )QDVT(led",
    678             "T(U.&).R.S(dda)PQ(led",            /* updated for Unicode 6.3 matching brackets */
    679             "L.V.& ).L.V(dda)LV(led",           /* updated for Unicode 6.3 matching brackets */
    680             "rbbayad R  DPDHRVR  0  yad",
    681             "rbbayad H  DPHPDHDA  1  yad",
    682             "rbbayad L  DPBLENDA   2  yad",
    683             "rbbayad  J  DPJQVM  3  yad",
    684             "rbbayad    I  DPIQNF   4  yad",
    685             "rbbayad  M  DPMEG  5  yad",
    686             "DPMEGolleh",
    687             "WXYZ olleh"
    688     };
    689 
    690     static const char* const visualOrder2[]={
    691             "@)@K.C.&@(dda)@KC@(led",
    692             "@)@BVDL@(dda )@QDVT@(led",
    693             "R.S.)T)U.&@(dda)@PQ@(led",
    694             "L.V.) L.V.&@(dda)@LV@(led",
    695             "rbbayad @R  DPDHRVR@  0  yad",
    696             "rbbayad @H  DPHPDHDA@  1  yad",
    697             "rbbayad @L  DPBLENDA@   2  yad",
    698             "rbbayad  @J  DPJQVM@  3  yad",
    699             "rbbayad    @I  DPIQNF@   4  yad",
    700             "rbbayad  @M  DPMEG@  5  yad",
    701             "DPMEGolleh",
    702             "WXYZ@ olleh"
    703     };
    704     static const char* const visualOrder3[]={
    705             ")K.C.&(KC)dda(led",
    706             ")BVDL(ddaQDVT) (led",
    707             "R.S.)T)U.&(PQ)dda(led",
    708             "L.V.) L.V.&(LV)dda(led",
    709             "rbbayad DPDHRVR   R  0 yad",
    710             "rbbayad DPHPDHDA   H  1 yad",
    711             "rbbayad DPBLENDA     L 2 yad",
    712             "rbbayad  DPJQVM   J  3 yad",
    713             "rbbayad    DPIQNF     I 4 yad",
    714             "rbbayad  DPMEG   M  5 yad",
    715             "DPMEGolleh",
    716             "WXYZ olleh"
    717     };
    718     static const char* const visualOrder4[]={
    719             "del(add(CK(.C.K)",
    720             "del( (TVDQadd(LDVB)",
    721             "del(add(QP(.U(T(.S.R",
    722             "del(add(VL(.V.L (.V.L",
    723             "day 0  R   RVRHDPD dayabbr",
    724             "day 1  H   ADHDPHPD dayabbr",
    725             "day 2 L     ADNELBPD dayabbr",
    726             "day 3  J   MVQJPD  dayabbr",
    727             "day 4 I     FNQIPD    dayabbr",
    728             "day 5  M   GEMPD  dayabbr",
    729             "helloGEMPD",
    730             "hello ZYXW"
    731     };
    732     char formatChars[MAXLEN];
    733     UErrorCode ec = U_ZERO_ERROR;
    734     UBiDi* bidi = ubidi_open();
    735     int i;
    736 
    737     log_verbose("\nEntering TestReorder\n\n");
    738 
    739     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    740         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    741         int32_t destSize = srcSize*2;
    742         UChar src[MAXLEN];
    743         UChar dest[MAXLEN];
    744         char chars[MAXLEN];
    745         log_verbose("Testing L2V #1 for case %d\n", i);
    746         pseudoToU16(srcSize,logicalOrder[i],src);
    747         ec = U_ZERO_ERROR;
    748         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    749         if(U_FAILURE(ec)){
    750             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    751                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    752         }
    753         /* try pre-flighting */
    754         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
    755         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    756             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    757         }else if(destSize!=srcSize){
    758             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    759         }else{
    760             ec= U_ZERO_ERROR;
    761         }
    762         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
    763         u16ToPseudo(destSize,dest,chars);
    764         if(destSize!=srcSize){
    765             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    766         }else if(strcmp(visualOrder[i],chars)!=0){
    767             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
    768                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    769                     logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
    770         }
    771         checkWhatYouCan(bidi, logicalOrder[i], chars);
    772     }
    773 
    774     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    775         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    776         int32_t destSize = srcSize*2;
    777         UChar src[MAXLEN];
    778         UChar dest[MAXLEN];
    779         char chars[MAXLEN];
    780         log_verbose("Testing L2V #2 for case %d\n", i);
    781         pseudoToU16(srcSize,logicalOrder[i],src);
    782         ec = U_ZERO_ERROR;
    783         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    784         if(U_FAILURE(ec)){
    785             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    786                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    787         }
    788         /* try pre-flighting */
    789         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    790         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    791             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    792         }else if(destSize!=srcSize){
    793             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    794         }else{
    795             ec= U_ZERO_ERROR;
    796         }
    797         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
    798         u16ToPseudo(destSize,dest,chars);
    799         if(destSize!=srcSize){
    800             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
    801         }else if(strcmp(visualOrder1[i],chars)!=0){
    802             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
    803                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    804                     logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
    805         }
    806     }
    807 
    808     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    809         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    810         int32_t destSize = srcSize*2;
    811         UChar src[MAXLEN];
    812         UChar dest[MAXLEN];
    813         char chars[MAXLEN];
    814         log_verbose("Testing V2L #3 for case %d\n", i);
    815         pseudoToU16(srcSize,logicalOrder[i],src);
    816         ec = U_ZERO_ERROR;
    817         ubidi_setInverse(bidi,TRUE);
    818         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
    819         if(U_FAILURE(ec)){
    820             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    821                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
    822         }
    823                 /* try pre-flighting */
    824         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    825         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    826             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    827         }else{
    828             ec= U_ZERO_ERROR;
    829         }
    830         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
    831         u16ToPseudo(destSize,dest,chars);
    832         if(strcmp(visualOrder2[i],chars)!=0){
    833             log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
    834                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    835                     logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
    836         }
    837     }
    838         /* Max Explicit level */
    839     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    840         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    841         int32_t destSize = srcSize*2;
    842         UChar src[MAXLEN];
    843         UChar dest[MAXLEN];
    844         char chars[MAXLEN];
    845         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    846         log_verbose("Testing V2L #4 for case %d\n", i);
    847         pseudoToU16(srcSize,logicalOrder[i],src);
    848         ec = U_ZERO_ERROR;
    849         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    850         if(U_FAILURE(ec)){
    851             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    852                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    853         }
    854                 /* try pre-flighting */
    855         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
    856         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    857             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    858         }else if(destSize!=srcSize){
    859             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
    860         }else{
    861             ec = U_ZERO_ERROR;
    862         }
    863         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
    864         u16ToPseudo(destSize,dest,chars);
    865         if(destSize!=srcSize){
    866             log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
    867         }else if(strcmp(visualOrder3[i],chars)!=0){
    868             log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
    869                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    870                     logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
    871         }
    872     }
    873     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
    874         int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
    875         int32_t destSize = srcSize*2;
    876         UChar src[MAXLEN];
    877         UChar dest[MAXLEN];
    878         char chars[MAXLEN];
    879         UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
    880         log_verbose("Testing V2L #5 for case %d\n", i);
    881         pseudoToU16(srcSize,logicalOrder[i],src);
    882         ec = U_ZERO_ERROR;
    883         ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
    884         if(U_FAILURE(ec)){
    885             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
    886                     i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
    887         }
    888         /* try pre-flighting */
    889         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    890         if(ec!=U_BUFFER_OVERFLOW_ERROR){
    891             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
    892         }else{
    893             ec= U_ZERO_ERROR;
    894         }
    895         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
    896         u16ToPseudo(destSize,dest,chars);
    897         if(strcmp(visualOrder4[i],chars)!=0){
    898             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
    899                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
    900                     logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
    901         }
    902     }
    903     ubidi_close(bidi);
    904 
    905     log_verbose("\nExiting TestReorder\n\n");
    906 }
    907 
    908 static void
    909 testReorderArabicMathSymbols(void) {
    910     static const UChar logicalOrder[][MAXLEN]={
    911         /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
    912         {0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
    913         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
    914         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
    915         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
    916         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
    917         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
    918         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
    919         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B},
    920         /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
    921         {0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
    922         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
    923         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
    924         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
    925         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
    926         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
    927         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
    928         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B},
    929         /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
    930         {0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
    931         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
    932         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
    933         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
    934         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
    935         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
    936         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
    937         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB},
    938         /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
    939         {0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
    940         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
    941         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
    942         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
    943         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
    944         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
    945         0xD83B, 0xDE39, 0xD83B, 0xDE3B},
    946         /* Arabic mathematical Symbols - Tailed Symbols */
    947         {0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
    948         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
    949         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
    950         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F}
    951     };
    952     static const UChar visualOrder[][MAXLEN]={
    953         /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
    954         {0xD83B, 0xDE1B, 0xD83B, 0xDE1A, 0xD83B, 0xDE19, 0x20,
    955         0xD83B, 0xDE18, 0xD83B, 0xDE17, 0xD83B, 0xDE16, 0x20,
    956         0xD83B, 0xDE15, 0xD83B, 0xDE14, 0xD83B, 0xDE13, 0xD83B, 0xDE12, 0x20,
    957         0xD83B, 0xDE11, 0xD83B, 0xDE10, 0xD83B, 0xDE0F, 0xD83B, 0xDE0E, 0x20,
    958         0xD83B, 0xDE0D, 0xD83B, 0xDE0C, 0xD83B, 0xDE0B, 0xD83B, 0xDE0A, 0x20,
    959         0xD83B, 0xDE09, 0xD83B, 0xDE08, 0xD83B, 0xDE07, 0x20,
    960         0xD83B, 0xDE06, 0xD83B, 0xDE05, 0xD83B, 0xDE24, 0x20,
    961         0xD83B, 0xDE03, 0xD83B, 0xDE02, 0xD83B, 0xDE01, 0xD83B, 0xDE00},
    962         /* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
    963         {0xD83B, 0xDE9B, 0xD83B, 0xDE9A, 0xD83B, 0xDE99, 0x20,
    964         0xD83B, 0xDE98, 0xD83B, 0xDE97, 0xD83B, 0xDE96, 0x20,
    965         0xD83B, 0xDE95, 0xD83B, 0xDE94, 0xD83B, 0xDE93, 0xD83B, 0xDE92, 0x20,
    966         0xD83B, 0xDE91, 0xD83B, 0xDE90, 0xD83B, 0xDE8F, 0xD83B, 0xDE8E, 0x20,
    967         0xD83B, 0xDE8D, 0xD83B, 0xDE8C, 0xD83B, 0xDE8B, 0x20,
    968         0xD83B, 0xDE89, 0xD83B, 0xDE88, 0xD83B, 0xDE87, 0x20,
    969         0xD83B, 0xDE86, 0xD83B, 0xDE85, 0xD83B, 0xDE84, 0x20,
    970         0xD83B, 0xDE83, 0xD83B, 0xDE82, 0xD83B, 0xDE81, 0xD83B, 0xDE80},
    971         /* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
    972         {0xD83B, 0xDEBB, 0xD83B, 0xDEBA, 0xD83B, 0xDEB9, 0x20,
    973         0xD83B, 0xDEB8, 0xD83B, 0xDEB7, 0xD83B, 0xDEB6, 0x20,
    974         0xD83B, 0xDEB5, 0xD83B, 0xDEB4, 0xD83B, 0xDEB3, 0xD83B, 0xDEB2, 0x20,
    975         0xD83B, 0xDEB1, 0xD83B, 0xDEB0, 0xD83B, 0xDEAF, 0xD83B, 0xDEAE, 0x20,
    976         0xD83B, 0xDEAD, 0xD83B, 0xDEAC, 0xD83B, 0xDEAB, 0x20,
    977         0xD83B, 0xDEA9, 0xD83B, 0xDEA8, 0xD83B, 0xDEA7, 0x20,
    978         0xD83B, 0xDEA6, 0xD83B, 0xDEA5, 0x20,
    979         0xD83B, 0xDEA3, 0xD83B, 0xDEA2, 0xD83B, 0xDEA1},
    980         /* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
    981         {0xD83B, 0xDE3B, 0xD83B, 0xDE39, 0x20,
    982         0xD83B, 0xDE37, 0xD83B, 0xDE36, 0x20,
    983         0xD83B, 0xDE35, 0xD83B, 0xDE34, 0xD83B, 0xDE32, 0x20,
    984         0xD83B, 0xDE31, 0xD83B, 0xDE30, 0xD83B, 0xDE2F, 0xD83B, 0xDE2E, 0x20,
    985         0xD83B, 0xDE2D, 0xD83B, 0xDE2C, 0xD83B, 0xDE2B, 0xD83B, 0xDE2A, 0x20,
    986         0xD83B, 0xDE29, 0xD83B, 0xDE27, 0x20,
    987         0xD83B, 0xDE22, 0xD83B, 0xDE21},
    988         /* Arabic mathematical Symbols - Tailed Symbols */
    989         {0xD83B, 0xDE5F, 0xD83B, 0xDE5D, 0xD83B, 0xDE5B, 0xD83B, 0xDE59, 0x20,
    990         0xD83B, 0xDE57, 0xD83B, 0xDE54, 0xD83B, 0xDE52, 0xD83B, 0xDE51, 0x20,
    991         0xD83B, 0xDE4F, 0xD83B, 0xDE4E, 0xD83B, 0xDE4D, 0x20,
    992         0xD83B, 0xDE4B, 0xD83B, 0xDE49, 0xD83B, 0xDE47, 0xD83B, 0xDE42}
    993     };
    994     char formatChars[MAXLEN];
    995     UErrorCode ec = U_ZERO_ERROR;
    996     UBiDi* bidi = ubidi_open();
    997     int i;
    998 
    999     log_verbose("\nEntering TestReorderArabicMathSymbols\n\n");
   1000 
   1001     for(i=0;i<UPRV_LENGTHOF(logicalOrder);i++){
   1002         int32_t srcSize = u_strlen(logicalOrder[i]);
   1003         int32_t destSize = srcSize*2;
   1004         UChar dest[MAXLEN];
   1005         log_verbose("Testing L2V #1 for case %d\n", i);
   1006         ec = U_ZERO_ERROR;
   1007         ubidi_setPara(bidi,logicalOrder[i],srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
   1008         if(U_FAILURE(ec)){
   1009             log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
   1010                     i, UBIDI_DEFAULT_LTR, u_errorName(ec));
   1011         }
   1012         /* try pre-flighting */
   1013         destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
   1014         if(ec!=U_BUFFER_OVERFLOW_ERROR){
   1015             log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
   1016         }else if(destSize!=srcSize){
   1017             log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
   1018         }else{
   1019             ec= U_ZERO_ERROR;
   1020         }
   1021         destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
   1022         if(destSize!=srcSize){
   1023             log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
   1024         }else if(memcmp(dest, visualOrder[i], destSize*U_SIZEOF_UCHAR)!=0){
   1025             log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
   1026                     "Input   : %s\nExpected: %s\nGot     : %s\nLevels  : %s\nAt Index: %d\n",
   1027                     logicalOrder[i],visualOrder[i],dest,formatLevels(bidi, formatChars),i);
   1028         }
   1029     }
   1030 
   1031     ubidi_close(bidi);
   1032 
   1033     log_verbose("\nExiting TestReorderArabicMathSymbols\n\n");
   1034 }
   1035 
   1036 static void
   1037 doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
   1038     const uint8_t *dirProps=test->text+lineStart;
   1039     const UBiDiLevel *levels=test->levels;
   1040     const uint8_t *visualMap=test->visualMap;
   1041     int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
   1042     UErrorCode errorCode=U_ZERO_ERROR;
   1043     UBiDiLevel level, level2;
   1044 
   1045     if (countRunsFirst) {
   1046         log_verbose("Calling ubidi_countRuns() first.\n");
   1047 
   1048         runCount = ubidi_countRuns(pBiDi, &errorCode);
   1049 
   1050         if(U_FAILURE(errorCode)) {
   1051             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1052             return;
   1053         }
   1054     } else {
   1055         log_verbose("Calling ubidi_getLogicalMap() first.\n");
   1056     }
   1057 
   1058     _testReordering(pBiDi, testNumber);
   1059 
   1060     for(i=0; i<len; ++i) {
   1061         log_verbose("%3d %3d %.*s%-3s @%d\n",
   1062                 i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
   1063                 dirPropNames[dirProps[i]],
   1064                 ubidi_getVisualIndex(pBiDi, i, &errorCode));
   1065     }
   1066 
   1067     log_verbose("\n-----levels:");
   1068     for(i=0; i<len; ++i) {
   1069         if(i>0) {
   1070             log_verbose(",");
   1071         }
   1072         log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
   1073     }
   1074 
   1075     log_verbose("\n--reordered:");
   1076     for(i=0; i<len; ++i) {
   1077         if(i>0) {
   1078             log_verbose(",");
   1079         }
   1080         log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
   1081     }
   1082     log_verbose("\n");
   1083 
   1084     if(test->direction!=ubidi_getDirection(pBiDi)) {
   1085         log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
   1086     }
   1087 
   1088     if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
   1089         log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
   1090     }
   1091 
   1092     for(i=0; i<len; ++i) {
   1093         if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
   1094             log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
   1095             return;
   1096         }
   1097     }
   1098 
   1099     for(i=0; i<len; ++i) {
   1100         logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
   1101         if(U_FAILURE(errorCode)) {
   1102             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1103             return;
   1104         }
   1105         if(visualMap[i]!=logicalIndex) {
   1106             log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
   1107             return;
   1108         }
   1109     }
   1110 
   1111     if (! countRunsFirst) {
   1112         runCount=ubidi_countRuns(pBiDi, &errorCode);
   1113         if(U_FAILURE(errorCode)) {
   1114             log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1115             return;
   1116         }
   1117     }
   1118 
   1119     for(logicalIndex=0; logicalIndex<len;) {
   1120         level=ubidi_getLevelAt(pBiDi, logicalIndex);
   1121         ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
   1122         if(level!=level2) {
   1123             log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
   1124                     "wrong level %d instead of %d\n",
   1125                     testNumber, logicalIndex, level, level2);
   1126         }
   1127         if(--runCount<0) {
   1128             log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
   1129                     "compared to %d=ubidi_countRuns()\n",
   1130                     testNumber, ubidi_countRuns(pBiDi, &errorCode));
   1131             return;
   1132         }
   1133     }
   1134     if(runCount!=0) {
   1135         log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
   1136                 "compared to %d=ubidi_getRunCount()\n",
   1137                 testNumber, ubidi_countRuns(pBiDi, &errorCode));
   1138         return;
   1139     }
   1140 
   1141     log_verbose("\n\n");
   1142 }
   1143 
   1144 static void
   1145 _testReordering(UBiDi *pBiDi, int testNumber) {
   1146     int32_t
   1147         logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
   1148         visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
   1149     UErrorCode errorCode=U_ZERO_ERROR;
   1150     const UBiDiLevel *levels;
   1151     int32_t i, length=ubidi_getLength(pBiDi),
   1152                destLength=ubidi_getResultLength(pBiDi);
   1153     int32_t runCount, visualIndex, logicalStart, runLength;
   1154     UBool odd;
   1155 
   1156     if(length<=0) {
   1157         return;
   1158     }
   1159 
   1160     /* get the logical and visual maps from the object */
   1161     ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
   1162     if(U_FAILURE(errorCode)) {
   1163         log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1164         return;
   1165     }
   1166 
   1167     ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
   1168     if(U_FAILURE(errorCode)) {
   1169         log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1170         return;
   1171     }
   1172 
   1173     /* invert them both */
   1174     ubidi_invertMap(logicalMap1, visualMap2, length);
   1175     ubidi_invertMap(visualMap1, logicalMap2, destLength);
   1176 
   1177     /* get them from the levels array, too */
   1178     levels=ubidi_getLevels(pBiDi, &errorCode);
   1179 
   1180     if(U_FAILURE(errorCode)) {
   1181         log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1182         return;
   1183     }
   1184 
   1185     ubidi_reorderLogical(levels, length, logicalMap3);
   1186     ubidi_reorderVisual(levels, length, visualMap3);
   1187 
   1188     /* get the visual map from the runs, too */
   1189     runCount=ubidi_countRuns(pBiDi, &errorCode);
   1190     if(U_FAILURE(errorCode)) {
   1191         log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
   1192         return;
   1193     }
   1194     log_verbose("\n----%2d runs:", runCount);
   1195     visualIndex=0;
   1196     for(i=0; i<runCount; ++i) {
   1197         odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
   1198         log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
   1199         if(UBIDI_LTR==odd) {
   1200             do { /* LTR */
   1201                 visualMap4[visualIndex++]=logicalStart++;
   1202             } while(--runLength>0);
   1203         } else {
   1204             logicalStart+=runLength;   /* logicalLimit */
   1205             do { /* RTL */
   1206                 visualMap4[visualIndex++]=--logicalStart;
   1207             } while(--runLength>0);
   1208         }
   1209     }
   1210     log_verbose("\n");
   1211 
   1212     /* print all the maps */
   1213     log_verbose("logical maps:\n");
   1214     for(i=0; i<length; ++i) {
   1215         log_verbose("%4d", logicalMap1[i]);
   1216     }
   1217     log_verbose("\n");
   1218     for(i=0; i<length; ++i) {
   1219         log_verbose("%4d", logicalMap2[i]);
   1220     }
   1221     log_verbose("\n");
   1222     for(i=0; i<length; ++i) {
   1223         log_verbose("%4d", logicalMap3[i]);
   1224     }
   1225 
   1226     log_verbose("\nvisual maps:\n");
   1227     for(i=0; i<destLength; ++i) {
   1228         log_verbose("%4d", visualMap1[i]);
   1229     }
   1230     log_verbose("\n");
   1231     for(i=0; i<destLength; ++i) {
   1232         log_verbose("%4d", visualMap2[i]);
   1233     }
   1234     log_verbose("\n");
   1235     for(i=0; i<length; ++i) {
   1236         log_verbose("%4d", visualMap3[i]);
   1237     }
   1238     log_verbose("\n");
   1239     for(i=0; i<length; ++i) {
   1240         log_verbose("%4d", visualMap4[i]);
   1241     }
   1242     log_verbose("\n");
   1243 
   1244     /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
   1245     for(i=0; i<length; ++i) {
   1246         if(logicalMap1[i]!=logicalMap2[i]) {
   1247             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
   1248             break;
   1249         }
   1250         if(logicalMap1[i]!=logicalMap3[i]) {
   1251             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
   1252             break;
   1253         }
   1254 
   1255         if(visualMap1[i]!=visualMap2[i]) {
   1256             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
   1257             break;
   1258         }
   1259         if(visualMap1[i]!=visualMap3[i]) {
   1260             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
   1261             break;
   1262         }
   1263         if(visualMap1[i]!=visualMap4[i]) {
   1264             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
   1265             break;
   1266         }
   1267 
   1268         if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
   1269             log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
   1270             break;
   1271         }
   1272         if(U_FAILURE(errorCode)) {
   1273             log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1274             break;
   1275         }
   1276         if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
   1277             log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
   1278             break;
   1279         }
   1280         if(U_FAILURE(errorCode)) {
   1281             log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
   1282             break;
   1283         }
   1284     }
   1285 }
   1286 
   1287 #define RETURN_IF_BAD_ERRCODE(x)    \
   1288     if (U_FAILURE(errorCode)) {      \
   1289         log_err("\nbad errorCode %d at %s\n", errorCode, (x));  \
   1290         return;     \
   1291     }               \
   1292 
   1293 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
   1294 
   1295 static void testGetBaseDirection(void) {
   1296     UBiDiDirection dir;
   1297     int i;
   1298 
   1299 /* Test Data */
   1300     static const UChar
   1301 /*Mixed Start with L*/
   1302     stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
   1303 /*Mixed Start with AL*/
   1304     stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1305 /*Mixed Start with R*/
   1306     stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
   1307 /*All AL (Arabic. Persian)*/
   1308     stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1309 /*All R (Hebrew etc.)*/
   1310     stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1311 /*All L (English)*/
   1312     stringEnglish[]={0x71, 0x61, 0x66, 0},
   1313 /*Mixed Start with weak AL an then L*/
   1314     stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
   1315 /*Mixed Start with weak L and then AL*/
   1316     stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
   1317 /*Empty*/
   1318     stringEmpty[]={0},
   1319 /*Surrogate Char.*/
   1320     stringSurrogateChar[]={0xD800, 0xDC00, 0},
   1321 /*Invalid UChar*/
   1322     stringInvalidUchar[]={-1},
   1323 /*All weak L (English Digits)*/
   1324     stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
   1325 /*All weak AL (Arabic Digits)*/
   1326     stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
   1327 /*First L (English) others are R (Hebrew etc.) */
   1328     stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
   1329 /*Last R (Hebrew etc.) others are weak L (English Digits)*/
   1330     stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
   1331 
   1332     static const struct {
   1333         const UChar *s;
   1334         int32_t length;
   1335     } testCases[]={
   1336         STRING_TEST_CASE(stringMixedEnglishFirst),
   1337         STRING_TEST_CASE(stringMixedArabicFirst),
   1338         STRING_TEST_CASE(stringMixedHebrewFirst),
   1339         STRING_TEST_CASE(stringPersian),
   1340         STRING_TEST_CASE(stringHebrew),
   1341         STRING_TEST_CASE(stringEnglish),
   1342         STRING_TEST_CASE(stringStartWeakAL),
   1343         STRING_TEST_CASE(stringStartWeakL),
   1344         STRING_TEST_CASE(stringEmpty),
   1345         STRING_TEST_CASE(stringSurrogateChar),
   1346         STRING_TEST_CASE(stringInvalidUchar),
   1347         STRING_TEST_CASE(stringAllEnglishDigits),
   1348         STRING_TEST_CASE(stringAllArabicDigits),
   1349         STRING_TEST_CASE(stringFirstL),
   1350         STRING_TEST_CASE(stringLastR),
   1351     };
   1352 
   1353 /* Expected results */
   1354     static const UBiDiDirection expectedDir[] ={
   1355         UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
   1356         UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
   1357         UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
   1358         UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
   1359         UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
   1360     };
   1361 
   1362     log_verbose("testGetBaseDirection() with %u test cases ---\n",
   1363     UPRV_LENGTHOF(testCases));
   1364 /* Run Tests */
   1365      for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   1366         dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
   1367         log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
   1368         if (dir != expectedDir[i])
   1369             log_err("\nFailed getBaseDirection case %d Expected  %d \tReceived %d\n",
   1370             i, expectedDir[i], dir);
   1371     }
   1372 
   1373 /* Misc. tests */
   1374 /* NULL string */
   1375     dir = ubidi_getBaseDirection(NULL, 3);
   1376     if (dir != UBIDI_NEUTRAL )
   1377         log_err("\nFailed getBaseDirection for NULL string " ,
   1378         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1379 /*All L- English string and length=-3 */
   1380     dir = ubidi_getBaseDirection( stringEnglish, -3);
   1381     if (dir != UBIDI_NEUTRAL )
   1382         log_err("\nFailed getBaseDirection for string w length= -3 ",
   1383         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1384 /*All L- English string and length=-1 */
   1385     dir = ubidi_getBaseDirection( stringEnglish, -1);
   1386     if (dir != UBIDI_LTR )
   1387         log_err("\nFailed getBaseDirection for English string w length= -1 ",
   1388         "\nExpected  %d \nReceived %d", UBIDI_LTR, dir);
   1389 /*All AL- Persian string and length=-1 */
   1390     dir = ubidi_getBaseDirection( stringPersian, -1);
   1391     if (dir != UBIDI_RTL )
   1392         log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
   1393         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1394 /*All R- Hebrew string and length=-1 */
   1395     dir = ubidi_getBaseDirection( stringHebrew, -1);
   1396     if (dir != UBIDI_RTL )
   1397         log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
   1398         "\nExpected  %d \nReceived %d", UBIDI_RTL, dir);
   1399 /*All weak L- English digits string and length=-1 */
   1400     dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
   1401     if (dir != UBIDI_NEUTRAL )
   1402         log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
   1403         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1404 /*All weak AL- Arabic digits string and length=-1 */
   1405     dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
   1406     if (dir != UBIDI_NEUTRAL )
   1407         log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
   1408         "\nExpected  %d \nReceived %d", UBIDI_NEUTRAL, dir);
   1409 
   1410 }
   1411 
   1412 
   1413 static void doMisc(void) {
   1414 /* Miscellaneous tests to exercize less popular code paths */
   1415     UBiDi *bidi, *bidiLine;
   1416     UChar src[MAXLEN], dest[MAXLEN];
   1417     int32_t srcLen, destLen, runCount, i;
   1418     UBiDiLevel level;
   1419     UBiDiDirection dir;
   1420     int32_t map[MAXLEN];
   1421     UErrorCode errorCode=U_ZERO_ERROR;
   1422     static const int32_t srcMap[6] = {0,1,-1,5,4};
   1423     static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
   1424 
   1425     bidi = ubidi_openSized(120, 66, &errorCode);
   1426     if (bidi == NULL) {
   1427         log_err("Error with openSized(120, 66)\n");
   1428         return;
   1429     }
   1430     bidiLine = ubidi_open();
   1431     if (bidi == NULL) {
   1432         log_err("Error with open()\n");
   1433         return;
   1434     }
   1435 
   1436     destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
   1437     if (destLen != 0) {
   1438         log_err("\nwriteReverse should return zero length, ",
   1439                 "returned %d instead\n", destLen);
   1440     }
   1441     RETURN_IF_BAD_ERRCODE("#1#");
   1442 
   1443     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1444     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1445     if (destLen != 0) {
   1446         log_err("\nwriteReordered should return zero length, ",
   1447                 "returned %d instead\n", destLen);
   1448     }
   1449     RETURN_IF_BAD_ERRCODE("#2#");
   1450 
   1451     srcLen = u_unescape("abc       ", src, MAXLEN);
   1452     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1453     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1454     for (i = 3; i < 6; i++) {
   1455         level = ubidi_getLevelAt(bidiLine, i);
   1456         if (level != UBIDI_RTL) {
   1457             log_err("\nTrailing space at index %d should get paragraph level"
   1458                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1459         }
   1460     }
   1461     RETURN_IF_BAD_ERRCODE("#3#");
   1462 
   1463     srcLen = u_unescape("abc       def", src, MAXLEN);
   1464     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1465     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1466     for (i = 3; i < 6; i++) {
   1467         level = ubidi_getLevelAt(bidiLine, i);
   1468         if (level != UBIDI_RTL) {
   1469             log_err("\nTrailing space at index %d should get paragraph level"
   1470                     "%d, got %d instead\n", i, UBIDI_RTL, level);
   1471         }
   1472     }
   1473     RETURN_IF_BAD_ERRCODE("#4#");
   1474 
   1475     srcLen = u_unescape("abcdefghi    ", src, MAXLEN);
   1476     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1477     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1478     for (i = 3; i < 6; i++) {
   1479         level = ubidi_getLevelAt(bidiLine, i);
   1480         if (level != 2) {
   1481             log_err("\nTrailing char at index %d should get level 2, "
   1482                     "got %d instead\n", i, level);
   1483         }
   1484     }
   1485     RETURN_IF_BAD_ERRCODE("#5#");
   1486 
   1487     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
   1488     srcLen = u_unescape("\\u200eabc       def", src, MAXLEN);
   1489     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1490     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1491     destLen = ubidi_getResultLength(bidiLine);
   1492     if (destLen != 5) {
   1493         log_err("\nWrong result length, should be 5, got %d\n", destLen);
   1494     }
   1495     RETURN_IF_BAD_ERRCODE("#6#");
   1496 
   1497     srcLen = u_unescape("abcdefghi", src, MAXLEN);
   1498     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1499     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1500     dir = ubidi_getDirection(bidiLine);
   1501     if (dir != UBIDI_LTR) {
   1502         log_err("\nWrong direction #1, should be %d, got %d\n",
   1503                 UBIDI_LTR, dir);
   1504     }
   1505     RETURN_IF_BAD_ERRCODE("#7#");
   1506 
   1507     ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
   1508     runCount = ubidi_countRuns(bidi, &errorCode);
   1509     if (runCount != 0) {
   1510         log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
   1511     }
   1512     RETURN_IF_BAD_ERRCODE("#8#");
   1513 
   1514     srcLen = u_unescape("          ", src, MAXLEN);
   1515     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1516     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1517     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1518     if (runCount != 1) {
   1519         log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
   1520     }
   1521     RETURN_IF_BAD_ERRCODE("#9#");
   1522 
   1523     srcLen = u_unescape("a\\u05d0        bc", src, MAXLEN);
   1524     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1525     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1526     dir = ubidi_getDirection(bidi);
   1527     if (dir != UBIDI_MIXED) {
   1528         log_err("\nWrong direction #2, should be %d, got %d\n",
   1529                 UBIDI_MIXED, dir);
   1530     }
   1531     dir = ubidi_getDirection(bidiLine);
   1532     if (dir != UBIDI_MIXED) {
   1533         log_err("\nWrong direction #3, should be %d, got %d\n",
   1534                 UBIDI_MIXED, dir);
   1535     }
   1536     runCount = ubidi_countRuns(bidiLine, &errorCode);
   1537     if (runCount != 2) {
   1538         log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
   1539     }
   1540     RETURN_IF_BAD_ERRCODE("#10#");
   1541 
   1542     ubidi_invertMap(srcMap, map, 5);
   1543     if (memcmp(dstMap, map, sizeof(dstMap))) {
   1544         log_err("\nUnexpected inverted Map, got ");
   1545         for (i = 0; i < 6; i++) {
   1546             log_err("%d ", map[i]);
   1547         }
   1548         log_err("\n");
   1549     }
   1550 
   1551     /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
   1552     srcLen = u_unescape("abc\\u200e", src, MAXLEN);
   1553     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1554     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   1555               UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
   1556     if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
   1557         log_err("\nWrong result #1, should be 'abc', got '%s'\n",
   1558                 aescstrdup(dest, destLen));
   1559     }
   1560     RETURN_IF_BAD_ERRCODE("#11#");
   1561 
   1562     /* test inverse Bidi with marks and contextual orientation */
   1563     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   1564     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   1565     ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1566     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1567     if (destLen != 0) {
   1568         log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
   1569     }
   1570     RETURN_IF_BAD_ERRCODE("#12#");
   1571     srcLen = u_unescape("   ", src, MAXLEN);
   1572     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1573     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1574     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1575         log_err("\nWrong result #3, should be '   ', got '%s'\n",
   1576                 aescstrdup(dest, destLen));
   1577     }
   1578     RETURN_IF_BAD_ERRCODE("#13#");
   1579     srcLen = u_unescape("abc", src, MAXLEN);
   1580     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1581     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1582     if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1583         log_err("\nWrong result #4, should be 'abc', got '%s'\n",
   1584                 aescstrdup(dest, destLen));
   1585     }
   1586     RETURN_IF_BAD_ERRCODE("#14#");
   1587     srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
   1588     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1589     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1590     srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
   1591     if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1592         log_err("\nWrong result #5, should be '%s', got '%s'\n",
   1593                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1594     }
   1595     RETURN_IF_BAD_ERRCODE("#15#");
   1596     srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
   1597     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1598     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1599     srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
   1600     if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1601         log_err("\nWrong result #6, should be '%s', got '%s'\n",
   1602                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1603     }
   1604     RETURN_IF_BAD_ERRCODE("#16#");
   1605     srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
   1606     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1607     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1608     srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
   1609     if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1610         log_err("\nWrong result #7, should be '%s', got '%s'\n",
   1611                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1612     }
   1613     RETURN_IF_BAD_ERRCODE("#17#");
   1614     srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
   1615     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1616     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1617     srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
   1618     if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1619         log_err("\nWrong result #8, should be '%s', got '%s'\n",
   1620                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1621     }
   1622     RETURN_IF_BAD_ERRCODE("#18#");
   1623     ubidi_orderParagraphsLTR(bidi, TRUE);
   1624     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
   1625                         "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
   1626                         "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
   1627     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   1628     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1629     srcLen = u_unescape("\n\r   \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
   1630                         "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
   1631                         "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
   1632     if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1633         log_err("\nWrong result #9, should be '%s', got '%s'\n",
   1634                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1635     }
   1636     RETURN_IF_BAD_ERRCODE("#19#");
   1637     srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
   1638     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1639     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1640     srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
   1641     if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1642         log_err("\nWrong result #10, should be '%s', got '%s'\n",
   1643                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1644     }
   1645     RETURN_IF_BAD_ERRCODE("#20#");
   1646     srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
   1647     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1648     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1649     srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
   1650     if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1651         log_err("\nWrong result #11, should be '%s', got '%s'\n",
   1652                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1653     }
   1654     RETURN_IF_BAD_ERRCODE("#21#");
   1655     srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
   1656     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1657     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1658     srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
   1659     if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1660         log_err("\nWrong result #12, should be '%s', got '%s'\n",
   1661                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1662     }
   1663     RETURN_IF_BAD_ERRCODE("#22#");
   1664     srcLen = u_unescape("ab \t", src, MAXLEN);
   1665     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1666     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   1667     srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
   1668     if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
   1669         log_err("\nWrong result #13, should be '%s', got '%s'\n",
   1670                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   1671     }
   1672     RETURN_IF_BAD_ERRCODE("#23#");
   1673 
   1674     /* check exceeding para level */
   1675     ubidi_close(bidi);
   1676     bidi = ubidi_open();
   1677     srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
   1678     ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
   1679     level = ubidi_getLevelAt(bidi, 2);
   1680     if (level != UBIDI_MAX_EXPLICIT_LEVEL) {
   1681         log_err("\nWrong level at index 2\n, should be %d, got %d\n", UBIDI_MAX_EXPLICIT_LEVEL, level);
   1682     }
   1683     RETURN_IF_BAD_ERRCODE("#24#");
   1684 
   1685     /* check 1-char runs with RUNS_ONLY */
   1686     ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
   1687     srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
   1688     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1689     runCount = ubidi_countRuns(bidi, &errorCode);
   1690     if (runCount != 14) {
   1691         log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
   1692     }
   1693     RETURN_IF_BAD_ERRCODE("#25#");
   1694 
   1695     ubidi_close(bidi);
   1696     ubidi_close(bidiLine);
   1697 }
   1698 
   1699 static void
   1700 testFailureRecovery(void) {
   1701     UErrorCode errorCode;
   1702     UBiDi *bidi, *bidiLine;
   1703     UChar src[MAXLEN];
   1704     int32_t srcLen;
   1705     UBiDiLevel level;
   1706     UBiDiReorderingMode rm;
   1707     static UBiDiLevel myLevels[3] = {6,5,4};
   1708 
   1709     log_verbose("\nEntering TestFailureRecovery\n\n");
   1710     errorCode = U_FILE_ACCESS_ERROR;
   1711     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
   1712         log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
   1713     }
   1714     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
   1715         log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
   1716     }
   1717     errorCode = U_ZERO_ERROR;
   1718     if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1719         log_err("ubidi_writeReordered did not fail as expected\n");
   1720     }
   1721 
   1722     bidi = ubidi_open();
   1723     srcLen = u_unescape("abc", src, MAXLEN);
   1724     errorCode = U_ZERO_ERROR;
   1725     ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
   1726     if (U_SUCCESS(errorCode)) {
   1727         log_err("\nubidi_setPara did not fail when passed too big para level\n");
   1728     }
   1729     errorCode = U_ZERO_ERROR;
   1730     if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
   1731         log_err("ubidi_writeReverse did not fail as expected\n");
   1732     }
   1733     bidiLine = ubidi_open();
   1734     errorCode = U_ZERO_ERROR;
   1735     ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
   1736     if (U_SUCCESS(errorCode)) {
   1737         log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
   1738     }
   1739     errorCode = U_ZERO_ERROR;
   1740     srcLen = u_unescape("abc", src, MAXLEN);
   1741     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
   1742     level = ubidi_getLevelAt(bidi, 3);
   1743     if (level != 0) {
   1744         log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
   1745     }
   1746     errorCode = U_ZERO_ERROR;
   1747     ubidi_close(bidi);
   1748     bidi = ubidi_openSized(-1, 0, &errorCode);
   1749     if (U_SUCCESS(errorCode)) {
   1750         log_err("\nubidi_openSized did not fail when called with bad argument\n");
   1751     }
   1752     ubidi_close(bidi);
   1753     bidi = ubidi_openSized(2, 1, &errorCode);
   1754     errorCode = U_ZERO_ERROR;
   1755     srcLen = u_unescape("abc", src, MAXLEN);
   1756     ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
   1757     if (U_SUCCESS(errorCode)) {
   1758         log_err("\nsetPara did not fail when called with text too long\n");
   1759     }
   1760     errorCode = U_ZERO_ERROR;
   1761     srcLen = u_unescape("=2", src, MAXLEN);
   1762     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1763     ubidi_countRuns(bidi, &errorCode);
   1764     if (U_SUCCESS(errorCode)) {
   1765         log_err("\nsetPara did not fail when called for too many runs\n");
   1766     }
   1767     ubidi_close(bidi);
   1768     bidi = ubidi_open();
   1769     rm = ubidi_getReorderingMode(bidi);
   1770     ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
   1771     if (rm != ubidi_getReorderingMode(bidi)) {
   1772         log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
   1773     }
   1774     ubidi_setReorderingMode(bidi, 9999);
   1775     if (rm != ubidi_getReorderingMode(bidi)) {
   1776         log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
   1777     }
   1778 
   1779     /* Try a surrogate char */
   1780     errorCode = U_ZERO_ERROR;
   1781     srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
   1782     ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
   1783     if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
   1784         log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
   1785     }
   1786     errorCode = U_ZERO_ERROR;
   1787     srcLen = u_unescape("abc", src, MAXLEN);
   1788     ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
   1789     if (U_SUCCESS(errorCode)) {
   1790         log_err("\nsetPara did not fail when called with bad levels\n");
   1791     }
   1792     ubidi_close(bidi);
   1793     ubidi_close(bidiLine);
   1794 
   1795     log_verbose("\nExiting TestFailureRecovery\n\n");
   1796 }
   1797 
   1798 static void
   1799 testMultipleParagraphs(void) {
   1800     static const char* const text = "__ABC\\u001c"          /* Para #0 offset 0 */
   1801                                     "__\\u05d0DE\\u001c"    /*       1        6 */
   1802                                     "__123\\u001c"          /*       2       12 */
   1803                                     "\\u000d\\u000a"        /*       3       18 */
   1804                                     "FG\\u000d"             /*       4       20 */
   1805                                     "\\u000d"               /*       5       23 */
   1806                                     "HI\\u000d\\u000a"      /*       6       24 */
   1807                                     "\\u000d\\u000a"        /*       7       28 */
   1808                                     "\\u000a"               /*       8       30 */
   1809                                     "\\u000a"               /*       9       31 */
   1810                                     "JK\\u001c";            /*      10       32 */
   1811     static const int32_t paraCount=11;
   1812     static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
   1813     static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
   1814     static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1815                                                   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
   1816                                                   {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   1817                                                   {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
   1818                                                   {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
   1819                                                   {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
   1820     static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
   1821     static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
   1822     static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
   1823     static const UChar multiparaTestString[] = {
   1824         0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da,
   1825         0x20,  0xa,   0xa,   0x41,  0x72,  0x74,  0x69,  0x73,
   1826         0x74,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
   1827         0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,   0x41,  0x6c,
   1828         0x62,  0x75,  0x6d,  0x3a,  0x20,  0x5de, 0x5e0, 0x5e1,
   1829         0x5d4, 0x20,  0x5e1, 0x5e4, 0x5da, 0x20,  0xa,   0xa,
   1830         0x54,  0x69,  0x6d,  0x65,  0x3a,  0x20,  0x32,  0x3a,
   1831         0x32,  0x37,  0xa,  0xa
   1832     };
   1833     static const UBiDiLevel multiparaTestLevels[] = {
   1834         1, 1, 1, 1, 1, 1, 1, 1,
   1835         1, 1, 0, 0, 0, 0, 0, 0,
   1836         0, 0, 0, 1, 1, 1, 1, 1,
   1837         1, 1, 1, 0, 0, 0, 0, 0,
   1838         0, 0, 0, 0, 0, 1, 1, 1,
   1839         1, 1, 1, 1, 1, 0, 0, 0,
   1840         0, 0, 0, 0, 0, 0, 0, 0,
   1841         0, 0, 0, 0
   1842     };
   1843     UBiDiLevel gotLevel;
   1844     const UBiDiLevel* gotLevels;
   1845     UBool orderParagraphsLTR;
   1846     UChar src[MAXLEN], dest[MAXLEN];
   1847     UErrorCode errorCode=U_ZERO_ERROR;
   1848     UBiDi* pBidi=ubidi_open();
   1849     UBiDi* pLine;
   1850     int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
   1851     int32_t srcLen, destLen;
   1852     int i, j, k;
   1853 
   1854     log_verbose("\nEntering TestMultipleParagraphs\n\n");
   1855     u_unescape(text, src, MAXLEN);
   1856     srcSize=u_strlen(src);
   1857     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1858     if(U_FAILURE(errorCode)){
   1859         log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1860                 UBIDI_LTR, u_errorName(errorCode));
   1861         ubidi_close(pBidi);
   1862         return;
   1863     }
   1864     /* check paragraph count and boundaries */
   1865     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1866         log_err("ubidi_countParagraphs returned %d, should be %d\n",
   1867                 count, paraCount);
   1868     }
   1869     for (i=0; i<paraCount; i++) {
   1870         ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1871         if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1872             log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1873                     i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1874         }
   1875     }
   1876     errorCode=U_ZERO_ERROR;
   1877     /* check with last paragraph not terminated by B */
   1878     src[srcSize-1]='L';
   1879     ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
   1880     if(U_FAILURE(errorCode)){
   1881         log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
   1882                 UBIDI_LTR, u_errorName(errorCode));
   1883         ubidi_close(pBidi);
   1884         return;
   1885     }
   1886     if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
   1887         log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
   1888                 count, paraCount);
   1889     }
   1890     i=paraCount-1;
   1891     ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
   1892     if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
   1893         log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
   1894                 i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
   1895     }
   1896     errorCode=U_ZERO_ERROR;
   1897     /* check paraLevel for all paragraphs under various paraLevel specs */
   1898     for (k=0; k<6; k++) {
   1899         ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
   1900         for (i=0; i<paraCount; i++) {
   1901             paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
   1902             if (paraIndex!=i) {
   1903                 log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
   1904                         paraLevels[k], i, paraIndex, i);
   1905             }
   1906             if (gotLevel!=multiLevels[k][i]) {
   1907                 log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
   1908                         paraLevels[k], i, gotLevel, multiLevels[k][i]);
   1909             }
   1910         }
   1911         gotLevel=ubidi_getParaLevel(pBidi);
   1912         if (gotLevel!=multiLevels[k][0]) {
   1913             log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
   1914                     paraLevels[k], gotLevel, multiLevels[k][0]);
   1915         }
   1916     }
   1917     errorCode=U_ZERO_ERROR;
   1918     /* check that the result of ubidi_getParaLevel changes if the first
   1919      * paragraph has a different level
   1920      */
   1921     src[0]=0x05d2;                      /* Hebrew letter Gimel */
   1922     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   1923     gotLevel=ubidi_getParaLevel(pBidi);
   1924     if (gotLevel!=UBIDI_RTL) {
   1925         log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
   1926                         gotLevel, UBIDI_RTL);
   1927     }
   1928     errorCode=U_ZERO_ERROR;
   1929     /* check that line cannot overlap paragraph boundaries */
   1930     pLine=ubidi_open();
   1931     i=paraBounds[1];
   1932     k=paraBounds[2]+1;
   1933     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1934     if (U_SUCCESS(errorCode)) {
   1935         log_err("For line limits %d-%d got success %s\n",
   1936                 i, k, u_errorName(errorCode));
   1937     }
   1938     errorCode=U_ZERO_ERROR;
   1939     i=paraBounds[1];
   1940     k=paraBounds[2];
   1941     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1942     if (U_FAILURE(errorCode)) {
   1943         log_err("For line limits %d-%d got error %s\n",
   1944                 i, k, u_errorName(errorCode));
   1945         errorCode=U_ZERO_ERROR;
   1946     }
   1947     /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
   1948     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1949     /* get levels through para Bidi block */
   1950     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   1951     if (U_FAILURE(errorCode)) {
   1952         log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
   1953         ubidi_close(pLine);
   1954         ubidi_close(pBidi);
   1955         return;
   1956     }
   1957     for (i=26; i<32; i++) {
   1958         if (gotLevels[i]!=UBIDI_RTL) {
   1959             log_err("For char %d(%04x), level=%d, expected=%d\n",
   1960                     i, src[i], gotLevels[i], UBIDI_RTL);
   1961         }
   1962     }
   1963     /* get levels through para Line block */
   1964     i=paraBounds[1];
   1965     k=paraBounds[2];
   1966     ubidi_setLine(pBidi, i, k, pLine, &errorCode);
   1967     if (U_FAILURE(errorCode)) {
   1968         log_err("For line limits %d-%d got error %s\n",
   1969                 i, k, u_errorName(errorCode));
   1970         ubidi_close(pLine);
   1971         ubidi_close(pBidi);
   1972         return;
   1973     }
   1974     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   1975     gotLevels=ubidi_getLevels(pLine, &errorCode);
   1976     if (U_FAILURE(errorCode)) {
   1977         log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
   1978         ubidi_close(pLine);
   1979         ubidi_close(pBidi);
   1980         return;
   1981     }
   1982     length=ubidi_getLength(pLine);
   1983     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
   1984         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   1985                 "level of separator=%d expected=%d\n",
   1986                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
   1987     }
   1988     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1989     if (orderParagraphsLTR) {
   1990         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
   1991     }
   1992     ubidi_orderParagraphsLTR(pBidi, TRUE);
   1993     orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
   1994     if (!orderParagraphsLTR) {
   1995         log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
   1996     }
   1997     /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
   1998     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   1999     /* get levels through para Bidi block */
   2000     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2001     for (i=26; i<32; i++) {
   2002         if (gotLevels[i]!=0) {
   2003             log_err("For char %d(%04x), level=%d, expected=%d\n",
   2004                     i, src[i], gotLevels[i], 0);
   2005         }
   2006     }
   2007     errorCode=U_ZERO_ERROR;
   2008     /* get levels through para Line block */
   2009     i=paraBounds[1];
   2010     k=paraBounds[2];
   2011     ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
   2012     paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
   2013     gotLevels=ubidi_getLevels(pLine, &errorCode);
   2014     length=ubidi_getLength(pLine);
   2015     if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
   2016         log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
   2017                 "level of separator=%d expected=%d\n",
   2018                 paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
   2019         log_verbose("levels=");
   2020         for (count=0; count<length; count++) {
   2021             log_verbose(" %d", gotLevels[count]);
   2022         }
   2023         log_verbose("\n");
   2024     }
   2025 
   2026     /* test that the concatenation of separate invocations of the bidi code
   2027      * on each individual paragraph in order matches the levels array that
   2028      * results from invoking bidi once over the entire multiparagraph tests
   2029      * (with orderParagraphsLTR false, of course)
   2030      */
   2031     u_unescape(text, src, MAXLEN);      /* restore original content */
   2032     srcSize=u_strlen(src);
   2033     ubidi_orderParagraphsLTR(pBidi, FALSE);
   2034     ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   2035     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2036     for (i=0; i<paraCount; i++) {
   2037         /* use pLine for individual paragraphs */
   2038         paraStart = paraBounds[i];
   2039         length = paraBounds[i+1] - paraStart;
   2040         ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
   2041         for (j=0; j<length; j++) {
   2042             if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
   2043                 log_err("Checking paragraph concatenation: for paragraph=%d, "
   2044                         "char=%d(%04x), level=%d, expected=%d\n",
   2045                         i, j, src[paraStart+j], k, gotLevel);
   2046             }
   2047         }
   2048     }
   2049 
   2050     /* ensure that leading numerics in a paragraph are not treated as arabic
   2051        numerals because of arabic text in a preceding paragraph
   2052      */
   2053     u_unescape(text2, src, MAXLEN);
   2054     srcSize=u_strlen(src);
   2055     ubidi_orderParagraphsLTR(pBidi, TRUE);
   2056     ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
   2057     gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2058     if (U_FAILURE(errorCode)) {
   2059         log_err("Can't get levels. %s\n", u_errorName(errorCode));
   2060         return;
   2061     }
   2062     for (i=0; i<srcSize; i++) {
   2063         if (gotLevels[i]!=levels2[i]) {
   2064             log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
   2065                     i, src[i], gotLevels[i], levels2[i]);
   2066         }
   2067     }
   2068 
   2069     /* check handling of whitespace before end of paragraph separator when
   2070      * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
   2071      */
   2072     u_memset(src, 0x0020, MAXLEN);
   2073     srcSize = 5;
   2074     ubidi_orderParagraphsLTR(pBidi, TRUE);
   2075     for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
   2076         src[4]=(UChar)i;                /* with and without terminating B */
   2077         for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
   2078             src[0]=(UChar)j;            /* leading 'A' or Alef */
   2079             for (gotLevel=4; gotLevel<=5; gotLevel++) {
   2080                 /* test even and odd paraLevel */
   2081                 ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
   2082                 gotLevels=ubidi_getLevels(pBidi, &errorCode);
   2083                 for (k=1; k<=3; k++) {
   2084                     if (gotLevels[k]!=gotLevel) {
   2085                         log_err("Checking trailing spaces: for leading_char=%04x, "
   2086                                 "last_char=%04x, index=%d, level=%d, expected=%d\n",
   2087                                 src[0], src[4], k, gotLevels[k], gotLevel);
   2088                     }
   2089                 }
   2090             }
   2091         }
   2092     }
   2093 
   2094     /* check default orientation when inverse bidi and paragraph starts
   2095      * with LTR strong char and ends with RTL strong char, with and without
   2096      * a terminating B
   2097      */
   2098     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2099     srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
   2100     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2101     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2102     srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
   2103     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2104         log_err("\nInvalid output #0, should be '%s', got '%s'\n",
   2105                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2106     }
   2107     srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
   2108     ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2109     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2110     srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
   2111     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2112         log_err("\nInvalid output #1, should be '%s', got '%s'\n",
   2113                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2114     }
   2115 
   2116     /* check multiple paragraphs together with explicit levels
   2117      */
   2118     ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
   2119     srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
   2120     ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
   2121     destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
   2122     srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
   2123     if (memcmp(src, dest, destLen * sizeof(UChar))) {
   2124         log_err("\nInvalid output #2, should be '%s', got '%s'\n",
   2125                 aescstrdup(src, srcLen), aescstrdup(dest, destLen));
   2126     }
   2127     count = ubidi_countParagraphs(pBidi);
   2128     if (count != 2) {
   2129         log_err("\nInvalid number of paras, should be 2, got %d\n", count);
   2130     }
   2131 
   2132     ubidi_close(pLine);
   2133     ubidi_close(pBidi);
   2134     log_verbose("\nExiting TestMultipleParagraphs\n\n");
   2135 
   2136     /* check levels in multiple paragraphs with default para level
   2137      */
   2138     pBidi = ubidi_open();
   2139     errorCode = U_ZERO_ERROR;
   2140     ubidi_setPara(pBidi, multiparaTestString, UPRV_LENGTHOF(multiparaTestString),
   2141                   UBIDI_DEFAULT_LTR, NULL, &errorCode);
   2142     if (U_FAILURE(errorCode)) {
   2143         log_err("ubidi_setPara failed for multiparaTestString\n");
   2144         ubidi_close(pBidi);
   2145         return;
   2146     }
   2147     gotLevels = ubidi_getLevels(pBidi, &errorCode);
   2148     if (U_FAILURE(errorCode)) {
   2149         log_err("ubidi_getLevels failed for multiparaTestString\n");
   2150         ubidi_close(pBidi);
   2151         return;
   2152     }
   2153     for (i = 0; i < UPRV_LENGTHOF(multiparaTestString); i++) {
   2154         if (gotLevels[i] != multiparaTestLevels[i]) {
   2155             log_err("Error on level for multiparaTestString at index %d, "
   2156                     "expected=%d, actual=%d\n",
   2157                     i, multiparaTestLevels[i], gotLevels[i]);
   2158         }
   2159     }
   2160     ubidi_close(pBidi);
   2161 
   2162 }
   2163 
   2164 
   2165 /* inverse BiDi ------------------------------------------------------------- */
   2166 
   2167 static int countRoundtrips=0, countNonRoundtrips=0;
   2168 
   2169 #define STRING_TEST_CASE(s) { (s), UPRV_LENGTHOF(s) }
   2170 
   2171 static void
   2172 testInverse(void) {
   2173     static const UChar
   2174         string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
   2175         string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
   2176         string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
   2177         string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
   2178         string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
   2179 
   2180     static const struct {
   2181         const UChar *s;
   2182         int32_t length;
   2183     } testCases[]={
   2184         STRING_TEST_CASE(string0),
   2185         STRING_TEST_CASE(string1),
   2186         STRING_TEST_CASE(string2),
   2187         STRING_TEST_CASE(string3),
   2188         STRING_TEST_CASE(string4)
   2189     };
   2190 
   2191     UBiDi *pBiDi;
   2192     UErrorCode errorCode;
   2193     int i;
   2194 
   2195     log_verbose("\nEntering TestInverse\n\n");
   2196     pBiDi=ubidi_open();
   2197     if(pBiDi==NULL) {
   2198         log_err("unable to open a UBiDi object (out of memory)\n");
   2199         return;
   2200     }
   2201 
   2202     log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
   2203      for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   2204         log_verbose("Testing case %d\n", i);
   2205         errorCode=U_ZERO_ERROR;
   2206         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
   2207     }
   2208 
   2209     log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", UPRV_LENGTHOF(testCases));
   2210     for(i=0; i<UPRV_LENGTHOF(testCases); ++i) {
   2211         log_verbose("Testing case %d\n", i);
   2212         errorCode=U_ZERO_ERROR;
   2213         _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
   2214     }
   2215 
   2216     _testManyInverseBidi(pBiDi, 0);
   2217     _testManyInverseBidi(pBiDi, 1);
   2218 
   2219     ubidi_close(pBiDi);
   2220 
   2221     log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
   2222 
   2223     _testWriteReverse();
   2224 
   2225     _testManyAddedPoints();
   2226 
   2227     _testMisc();
   2228 
   2229     log_verbose("\nExiting TestInverse\n\n");
   2230 }
   2231 
   2232 #define COUNT_REPEAT_SEGMENTS 6
   2233 
   2234 static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
   2235     { 0x61, 0x62 },     /* L */
   2236     { 0x5d0, 0x5d1 },   /* R */
   2237     { 0x627, 0x628 },   /* AL */
   2238     { 0x31, 0x32 },     /* EN */
   2239     { 0x661, 0x662 },   /* AN */
   2240     { 0x20, 0x20 }      /* WS (N) */
   2241 };
   2242 
   2243 static void
   2244 _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
   2245     UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
   2246     int i, j, k;
   2247     UErrorCode errorCode;
   2248 
   2249     log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
   2250                  direction==0 ? 'L' : 'R');
   2251     for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
   2252         text[0]=repeatSegments[i][0];
   2253         text[1]=repeatSegments[i][1];
   2254         for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
   2255             text[3]=repeatSegments[j][0];
   2256             text[4]=repeatSegments[j][1];
   2257             for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
   2258                 text[6]=repeatSegments[k][0];
   2259                 text[7]=repeatSegments[k][1];
   2260 
   2261                 errorCode=U_ZERO_ERROR;
   2262                 log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
   2263                 _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
   2264             }
   2265         }
   2266     }
   2267 }
   2268 
   2269 static void
   2270 _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
   2271                 UBiDiLevel direction, UErrorCode *pErrorCode) {
   2272     UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
   2273     int32_t ltrLength, logicalLength, visualLength;
   2274 
   2275     if(direction==0) {
   2276         log_verbose("inverse Bidi: testInverse(L)\n");
   2277 
   2278         /* convert visual to logical */
   2279         ubidi_setInverse(pBiDi, TRUE);
   2280         if (!ubidi_isInverse(pBiDi)) {
   2281             log_err("Error while doing ubidi_setInverse(TRUE)\n");
   2282         }
   2283         ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
   2284         if (src != ubidi_getText(pBiDi)) {
   2285             log_err("Wrong value returned by ubidi_getText\n");
   2286         }
   2287         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
   2288                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2289         log_verbose("  v ");
   2290         printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
   2291         log_verbose("\n");
   2292 
   2293         /* convert back to visual LTR */
   2294         ubidi_setInverse(pBiDi, FALSE);
   2295         if (ubidi_isInverse(pBiDi)) {
   2296             log_err("Error while doing ubidi_setInverse(FALSE)\n");
   2297         }
   2298         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2299         visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
   2300                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
   2301     } else {
   2302         log_verbose("inverse Bidi: testInverse(R)\n");
   2303 
   2304         /* reverse visual from RTL to LTR */
   2305         ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, UPRV_LENGTHOF(visualLTR), 0, pErrorCode);
   2306         log_verbose("  vr");
   2307         printUnicode(src, srcLength, NULL);
   2308         log_verbose("\n");
   2309 
   2310         /* convert visual RTL to logical */
   2311         ubidi_setInverse(pBiDi, TRUE);
   2312         ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
   2313         logicalLength=ubidi_writeReordered(pBiDi, logicalDest, UPRV_LENGTHOF(logicalDest),
   2314                                            UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
   2315         log_verbose("  vl");
   2316         printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
   2317         log_verbose("\n");
   2318 
   2319         /* convert back to visual RTL */
   2320         ubidi_setInverse(pBiDi, FALSE);
   2321         ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
   2322         visualLength=ubidi_writeReordered(pBiDi, visualDest, UPRV_LENGTHOF(visualDest),
   2323                                           UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
   2324     }
   2325     log_verbose("  l ");
   2326     printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
   2327     log_verbose("\n");
   2328     log_verbose("  v ");
   2329     printUnicode(visualDest, visualLength, NULL);
   2330     log_verbose("\n");
   2331 
   2332     /* check and print results */
   2333     if(U_FAILURE(*pErrorCode)) {
   2334         log_err("inverse BiDi: *** error %s\n"
   2335                 "                 turn on verbose mode to see details\n", u_errorName(*pErrorCode));
   2336     } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
   2337         ++countRoundtrips;
   2338         log_verbose(" + roundtripped\n");
   2339     } else {
   2340         ++countNonRoundtrips;
   2341         log_verbose(" * did not roundtrip\n");
   2342         log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
   2343                 "                 turn on verbose mode to see details\n");
   2344     }
   2345 }
   2346 
   2347 static void
   2348 _testWriteReverse(void) {
   2349     /* U+064e and U+0650 are combining marks (Mn) */
   2350     static const UChar forward[]={
   2351         0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
   2352     }, reverseKeepCombining[]={
   2353         0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
   2354     }, reverseRemoveControlsKeepCombiningDoMirror[]={
   2355         0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
   2356     };
   2357     UChar reverse[10];
   2358     UErrorCode errorCode;
   2359     int32_t length;
   2360 
   2361     /* test ubidi_writeReverse() with "interesting" options */
   2362     errorCode=U_ZERO_ERROR;
   2363     length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
   2364                               reverse, UPRV_LENGTHOF(reverse),
   2365                               UBIDI_KEEP_BASE_COMBINING,
   2366                               &errorCode);
   2367     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
   2368         log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
   2369                 length, UPRV_LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
   2370     }
   2371 
   2372     memset(reverse, 0xa5, UPRV_LENGTHOF(reverse)*U_SIZEOF_UCHAR);
   2373     errorCode=U_ZERO_ERROR;
   2374     length=ubidi_writeReverse(forward, UPRV_LENGTHOF(forward),
   2375                               reverse, UPRV_LENGTHOF(reverse),
   2376                               UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
   2377                               &errorCode);
   2378     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
   2379         log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
   2380                 "    length=%d (should be %d), error code %s\n",
   2381                 length, UPRV_LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
   2382     }
   2383 }
   2384 
   2385 static void _testManyAddedPoints(void) {
   2386     UErrorCode errorCode = U_ZERO_ERROR;
   2387     UBiDi *bidi = ubidi_open();
   2388     UChar text[90], dest[MAXLEN], expected[120];
   2389     int destLen, i;
   2390     for (i = 0; i < UPRV_LENGTHOF(text); i+=3) {
   2391         text[i] = 0x0061; /* 'a' */
   2392         text[i+1] = 0x05d0;
   2393         text[i+2] = 0x0033; /* '3' */
   2394     }
   2395     ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
   2396     ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
   2397     ubidi_setPara(bidi, text, UPRV_LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
   2398     destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
   2399     for (i = 0; i < UPRV_LENGTHOF(expected); i+=4) {
   2400         expected[i] = 0x0061; /* 'a' */
   2401         expected[i+1] = 0x05d0;
   2402         expected[i+2] = 0x200e;
   2403         expected[i+3] = 0x0033; /* '3' */
   2404     }
   2405     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2406         log_err("\nInvalid output with many added points, "
   2407                 "expected '%s', got '%s'\n",
   2408                 aescstrdup(expected, UPRV_LENGTHOF(expected)),
   2409                 aescstrdup(dest, destLen));
   2410     }
   2411     ubidi_close(bidi);
   2412 }
   2413 
   2414 static void _testMisc(void) {
   2415     UErrorCode errorCode = U_ZERO_ERROR;
   2416     UBiDi *bidi = ubidi_open();
   2417     UChar src[3], dest[MAXLEN], expected[5];
   2418     int destLen;
   2419     ubidi_setInverse(bidi, TRUE);
   2420     src[0] = src[1] = src[2] = 0x0020;
   2421     ubidi_setPara(bidi, src, UPRV_LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
   2422     destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
   2423               UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
   2424               &errorCode);
   2425     u_unescape("\\u200f   \\u200f", expected, 5);
   2426     if (memcmp(dest, expected, destLen * sizeof(UChar))) {
   2427         log_err("\nInvalid output with RLM at both sides, "
   2428                 "expected '%s', got '%s'\n",
   2429                 aescstrdup(expected, UPRV_LENGTHOF(expected)),
   2430                 aescstrdup(dest, destLen));
   2431     }
   2432     ubidi_close(bidi);
   2433 }
   2434 
   2435 /* arabic shaping ----------------------------------------------------------- */
   2436 
   2437 static void
   2438 doArabicShapingTest(void) {
   2439     static const UChar
   2440     source[]={
   2441         0x31,   /* en:1 */
   2442         0x627,  /* arabic:alef */
   2443         0x32,   /* en:2 */
   2444         0x6f3,  /* an:3 */
   2445         0x61,   /* latin:a */
   2446         0x34,   /* en:4 */
   2447         0
   2448     }, en2an[]={
   2449         0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
   2450     }, an2en[]={
   2451         0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
   2452     }, logical_alen2an_init_lr[]={
   2453         0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
   2454     }, logical_alen2an_init_al[]={
   2455         0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
   2456     }, reverse_alen2an_init_lr[]={
   2457         0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
   2458     }, reverse_alen2an_init_al[]={
   2459         0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
   2460     }, lamalef[]={
   2461         0xfefb, 0
   2462     };
   2463     UChar dest[8];
   2464     UErrorCode errorCode;
   2465     int32_t length;
   2466 
   2467     /* test number shaping */
   2468 
   2469     /* european->arabic */
   2470     errorCode=U_ZERO_ERROR;
   2471     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2472                          dest, UPRV_LENGTHOF(dest),
   2473                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2474                          &errorCode);
   2475     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
   2476         log_err("failure in u_shapeArabic(en2an)\n");
   2477     }
   2478 
   2479     /* arabic->european */
   2480     errorCode=U_ZERO_ERROR;
   2481     length=u_shapeArabic(source, -1,
   2482                          dest, UPRV_LENGTHOF(dest),
   2483                          U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2484                          &errorCode);
   2485     if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
   2486         log_err("failure in u_shapeArabic(an2en)\n");
   2487     }
   2488 
   2489     /* european->arabic with context, logical order, initial state not AL */
   2490     errorCode=U_ZERO_ERROR;
   2491     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2492                          dest, UPRV_LENGTHOF(dest),
   2493                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
   2494                          &errorCode);
   2495     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2496         log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
   2497     }
   2498 
   2499     /* european->arabic with context, logical order, initial state AL */
   2500     errorCode=U_ZERO_ERROR;
   2501     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2502                          dest, UPRV_LENGTHOF(dest),
   2503                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
   2504                          &errorCode);
   2505     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2506         log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
   2507     }
   2508 
   2509     /* european->arabic with context, reverse order, initial state not AL */
   2510     errorCode=U_ZERO_ERROR;
   2511     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2512                          dest, UPRV_LENGTHOF(dest),
   2513                          U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2514                          &errorCode);
   2515     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
   2516         log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
   2517     }
   2518 
   2519     /* european->arabic with context, reverse order, initial state AL */
   2520     errorCode=U_ZERO_ERROR;
   2521     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2522                          dest, UPRV_LENGTHOF(dest),
   2523                          U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2524                          &errorCode);
   2525     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
   2526         log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
   2527     }
   2528 
   2529     /* test noop */
   2530     errorCode=U_ZERO_ERROR;
   2531     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2532                          dest, UPRV_LENGTHOF(dest),
   2533                          0,
   2534                          &errorCode);
   2535     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
   2536         log_err("failure in u_shapeArabic(noop)\n");
   2537     }
   2538 
   2539     errorCode=U_ZERO_ERROR;
   2540     length=u_shapeArabic(source, 0,
   2541                          dest, UPRV_LENGTHOF(dest),
   2542                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2543                          &errorCode);
   2544     if(U_FAILURE(errorCode) || length!=0) {
   2545         log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), UPRV_LENGTHOF(source));
   2546     }
   2547 
   2548     /* preflight digit shaping */
   2549     errorCode=U_ZERO_ERROR;
   2550     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2551                          NULL, 0,
   2552                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2553                          &errorCode);
   2554     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=UPRV_LENGTHOF(source)) {
   2555         log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
   2556                 length, u_errorName(errorCode), UPRV_LENGTHOF(source));
   2557     }
   2558 
   2559     /* test illegal arguments */
   2560     errorCode=U_ZERO_ERROR;
   2561     length=u_shapeArabic(NULL, UPRV_LENGTHOF(source),
   2562                          dest, UPRV_LENGTHOF(dest),
   2563                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2564                          &errorCode);
   2565     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2566         log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2567     }
   2568 
   2569     errorCode=U_ZERO_ERROR;
   2570     length=u_shapeArabic(source, -2,
   2571                          dest, UPRV_LENGTHOF(dest),
   2572                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2573                          &errorCode);
   2574     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2575         log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2576     }
   2577 
   2578     errorCode=U_ZERO_ERROR;
   2579     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2580                          NULL, UPRV_LENGTHOF(dest),
   2581                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2582                          &errorCode);
   2583     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2584         log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2585     }
   2586 
   2587     errorCode=U_ZERO_ERROR;
   2588     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2589                          dest, -1,
   2590                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2591                          &errorCode);
   2592     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2593         log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2594     }
   2595 
   2596     errorCode=U_ZERO_ERROR;
   2597     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2598                          dest, UPRV_LENGTHOF(dest),
   2599                          U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
   2600                          &errorCode);
   2601     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2602         log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2603     }
   2604 
   2605     errorCode=U_ZERO_ERROR;
   2606     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2607                          dest, UPRV_LENGTHOF(dest),
   2608                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
   2609                          &errorCode);
   2610     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2611         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2612     }
   2613 
   2614     errorCode=U_ZERO_ERROR;
   2615     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2616                          (UChar *)(source+2), UPRV_LENGTHOF(dest), /* overlap source and destination */
   2617                          U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
   2618                          &errorCode);
   2619     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   2620         log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
   2621     }
   2622 
   2623     errorCode=U_ZERO_ERROR;
   2624     length=u_shapeArabic(lamalef, UPRV_LENGTHOF(lamalef),
   2625                          dest, UPRV_LENGTHOF(dest),
   2626                          U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2627                          &errorCode);
   2628     if(U_FAILURE(errorCode) || length == UPRV_LENGTHOF(lamalef)) {
   2629         log_err("failure in u_shapeArabic(U_SHAPE_LETTERS_UNSHAPE | U_SHAPE_LENGTH_GROW_SHRINK | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR)\n");
   2630         log_err("returned %s instead of U_ZERO_ERROR or returned length %d instead of 3\n", u_errorName(errorCode), length);
   2631     }
   2632 }
   2633 
   2634 static void
   2635 doLamAlefSpecialVLTRArabicShapingTest(void) {
   2636     static const UChar
   2637     source[]={
   2638 /*a*/   0x20 ,0x646,0x622,0x644,0x627,0x20,
   2639 /*b*/   0x646,0x623,0x64E,0x644,0x627,0x20,
   2640 /*c*/   0x646,0x627,0x670,0x644,0x627,0x20,
   2641 /*d*/   0x646,0x622,0x653,0x644,0x627,0x20,
   2642 /*e*/   0x646,0x625,0x655,0x644,0x627,0x20,
   2643 /*f*/   0x646,0x622,0x654,0x644,0x627,0x20,
   2644 /*g*/   0xFEFC,0x639
   2645     }, shape_near[]={
   2646         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2647         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2648         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2649         0xfefc,0xfecb
   2650     }, shape_at_end[]={
   2651         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2652         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2653         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
   2654     }, shape_at_begin[]={
   2655         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2656         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2657         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2658     }, shape_grow_shrink[]={
   2659         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2660         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2661         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2662     }, shape_excepttashkeel_near[]={
   2663         0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
   2664         0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
   2665         0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
   2666         0xfefc,0xfecb
   2667     }, shape_excepttashkeel_at_end[]={
   2668         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
   2669         0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
   2670         0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
   2671         0x20,0x20,0x20
   2672     }, shape_excepttashkeel_at_begin[]={
   2673         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
   2674         0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
   2675         0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2676     }, shape_excepttashkeel_grow_shrink[]={
   2677         0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
   2678         0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
   2679         0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
   2680     };
   2681 
   2682     UChar dest[38];
   2683     UErrorCode errorCode;
   2684     int32_t length;
   2685 
   2686     errorCode=U_ZERO_ERROR;
   2687 
   2688     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2689                          dest, UPRV_LENGTHOF(dest),
   2690                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2691                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2692                          &errorCode);
   2693 
   2694     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2695         log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
   2696     }
   2697 
   2698     errorCode=U_ZERO_ERROR;
   2699 
   2700     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2701                          dest, UPRV_LENGTHOF(dest),
   2702                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2703                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2704                          &errorCode);
   2705 
   2706     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2707         log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
   2708     }
   2709 
   2710     errorCode=U_ZERO_ERROR;
   2711 
   2712     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2713                          dest, UPRV_LENGTHOF(dest),
   2714                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2715                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2716                          &errorCode);
   2717 
   2718     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2719         log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
   2720     }
   2721 
   2722     errorCode=U_ZERO_ERROR;
   2723 
   2724     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2725                          dest, UPRV_LENGTHOF(dest),
   2726                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2727                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2728                          &errorCode);
   2729 
   2730     if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2731         log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
   2732     }
   2733 
   2734     /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
   2735 
   2736     errorCode=U_ZERO_ERROR;
   2737 
   2738     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2739                          dest, UPRV_LENGTHOF(dest),
   2740                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2741                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2742                          &errorCode);
   2743 
   2744     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2745         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
   2746     }
   2747 
   2748     errorCode=U_ZERO_ERROR;
   2749 
   2750     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2751                          dest, UPRV_LENGTHOF(dest),
   2752                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2753                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2754                          &errorCode);
   2755 
   2756     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
   2757         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
   2758     }
   2759 
   2760     errorCode=U_ZERO_ERROR;
   2761 
   2762     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2763                          dest, UPRV_LENGTHOF(dest),
   2764                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2765                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2766                          &errorCode);
   2767 
   2768     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2769         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
   2770     }
   2771 
   2772     errorCode=U_ZERO_ERROR;
   2773 
   2774     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2775                          dest, UPRV_LENGTHOF(dest),
   2776                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
   2777                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2778                          &errorCode);
   2779 
   2780     if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2781         log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
   2782     }
   2783 }
   2784 
   2785 static void
   2786 doTashkeelSpecialVLTRArabicShapingTest(void) {
   2787     static const UChar
   2788     source[]={
   2789         0x64A,0x628,0x631,0x639,0x20,
   2790         0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
   2791         0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
   2792         0x628,0x670,0x631,0x670,0x639,0x20,
   2793         0x628,0x653,0x631,0x653,0x639,0x20,
   2794         0x628,0x654,0x631,0x654,0x639,0x20,
   2795         0x628,0x655,0x631,0x655,0x639,0x20,
   2796     }, shape_near[]={
   2797         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
   2798         0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
   2799         0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
   2800         0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2801     }, shape_excepttashkeel_near[]={
   2802         0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
   2803         0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
   2804         0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
   2805         0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
   2806     };
   2807 
   2808     UChar dest[43];
   2809     UErrorCode errorCode;
   2810     int32_t length;
   2811 
   2812     errorCode=U_ZERO_ERROR;
   2813 
   2814     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2815                          dest, UPRV_LENGTHOF(dest),
   2816                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2817                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2818                          &errorCode);
   2819 
   2820     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
   2821         log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
   2822     }
   2823 
   2824     errorCode=U_ZERO_ERROR;
   2825 
   2826     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2827                          dest, UPRV_LENGTHOF(dest),
   2828                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2829                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2830                          &errorCode);
   2831 
   2832     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
   2833         log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
   2834     }
   2835 }
   2836 
   2837 static void
   2838 doLOGICALArabicDeShapingTest(void) {
   2839     static const UChar
   2840     source[]={
   2841         0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
   2842         0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
   2843         0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
   2844     }, unshape_near[]={
   2845         0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
   2846         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2847         0x629,0x20,0x20,0x20,0x20
   2848     }, unshape_at_end[]={
   2849         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2850         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2851         0x644,0x62d,0x631,0x629,0x20
   2852     }, unshape_at_begin[]={
   2853         0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
   2854         0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
   2855         0x629,0x20,0x20,0x20,0x20
   2856     }, unshape_grow_shrink[]={
   2857         0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
   2858         0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
   2859         0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
   2860     };
   2861 
   2862     UChar dest[36];
   2863     UErrorCode errorCode;
   2864     int32_t length;
   2865 
   2866     errorCode=U_ZERO_ERROR;
   2867 
   2868     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2869                          dest, UPRV_LENGTHOF(dest),
   2870                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
   2871                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2872                          &errorCode);
   2873 
   2874     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
   2875         log_err("failure in u_shapeArabic(unshape_near)\n");
   2876     }
   2877 
   2878     errorCode=U_ZERO_ERROR;
   2879 
   2880     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2881                          dest, UPRV_LENGTHOF(dest),
   2882                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
   2883                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2884                          &errorCode);
   2885 
   2886     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
   2887         log_err("failure in u_shapeArabic(unshape_at_end)\n");
   2888     }
   2889 
   2890     errorCode=U_ZERO_ERROR;
   2891 
   2892     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2893                          dest, UPRV_LENGTHOF(dest),
   2894                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
   2895                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2896                          &errorCode);
   2897 
   2898     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
   2899         log_err("failure in u_shapeArabic(unshape_at_begin)\n");
   2900     }
   2901 
   2902     errorCode=U_ZERO_ERROR;
   2903 
   2904     length=u_shapeArabic(source, UPRV_LENGTHOF(source),
   2905                          dest, UPRV_LENGTHOF(dest),
   2906                          U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
   2907                          U_SHAPE_TEXT_DIRECTION_LOGICAL,
   2908                          &errorCode);
   2909 
   2910     if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
   2911         log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
   2912     }
   2913 
   2914 }
   2915 
   2916 static void
   2917 doTailTest(void) {
   2918   static const UChar src[] = { 0x0020, 0x0633, 0 };
   2919   static const UChar dst_old[] = { 0xFEB1, 0x200B,0 };
   2920   static const UChar dst_new[] = { 0xFEB1, 0xFE73,0 };
   2921   UChar dst[3] = { 0x0000, 0x0000,0 };
   2922   int32_t length;
   2923   UErrorCode status;
   2924 
   2925   log_verbose("SRC: U+%04X U+%04X\n", src[0],src[1]);
   2926 
   2927   log_verbose("Trying old tail\n");
   2928   status = U_ZERO_ERROR;
   2929   length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
   2930                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR, &status);
   2931   if(U_FAILURE(status)) {
   2932     log_err("Fail: status %s\n", u_errorName(status));
   2933   } else if(length!=2) {
   2934     log_err("Fail: len %d expected 3\n", length);
   2935   } else if(u_strncmp(dst,dst_old,UPRV_LENGTHOF(dst))) {
   2936     log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
   2937             dst[0],dst[1],dst_old[0],dst_old[1]);
   2938   } else {
   2939     log_verbose("OK:  U+%04X U+%04X len %d err %s\n",
   2940             dst[0],dst[1],length,u_errorName(status));
   2941   }
   2942 
   2943 
   2944   log_verbose("Trying new tail\n");
   2945   status = U_ZERO_ERROR;
   2946   length = u_shapeArabic(src, -1, dst, UPRV_LENGTHOF(dst),
   2947                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_SEEN_TWOCELL_NEAR|U_SHAPE_TAIL_NEW_UNICODE, &status);
   2948   if(U_FAILURE(status)) {
   2949     log_err("Fail: status %s\n", u_errorName(status));
   2950   } else if(length!=2) {
   2951     log_err("Fail: len %d expected 3\n", length);
   2952   } else if(u_strncmp(dst,dst_new,UPRV_LENGTHOF(dst))) {
   2953     log_err("Fail: got U+%04X U+%04X expected U+%04X U+%04X\n",
   2954             dst[0],dst[1],dst_new[0],dst_new[1]);
   2955   } else {
   2956     log_verbose("OK:  U+%04X U+%04X len %d err %s\n",
   2957             dst[0],dst[1],length,u_errorName(status));
   2958   }
   2959 }
   2960 
   2961 static void
   2962 doArabicShapingTestForBug5421(void) {
   2963     static const UChar
   2964     persian_letters_source[]={
   2965         0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
   2966     }, persian_letters[]={
   2967         0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
   2968     }, tashkeel_aggregation_source[]={
   2969         0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
   2970         0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
   2971     }, tashkeel_aggregation[]={
   2972         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
   2973         0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
   2974     }, untouched_presentation_source[]={
   2975         0x0020 ,0x0627, 0xfe90,0x0020
   2976     }, untouched_presentation[]={
   2977         0x0020,0xfe8D, 0xfe90,0x0020
   2978     }, untouched_presentation_r_source[]={
   2979         0x0020 ,0xfe90, 0x0627, 0x0020
   2980     }, untouched_presentation_r[]={
   2981         0x0020, 0xfe90,0xfe8D,0x0020
   2982     };
   2983 
   2984     UChar dest[38];
   2985     UErrorCode errorCode;
   2986     int32_t length;
   2987 
   2988     errorCode=U_ZERO_ERROR;
   2989 
   2990     length=u_shapeArabic(persian_letters_source, UPRV_LENGTHOF(persian_letters_source),
   2991                          dest, UPRV_LENGTHOF(dest),
   2992                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   2993                          &errorCode);
   2994 
   2995     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
   2996         log_err("failure in u_shapeArabic(persian_letters)\n");
   2997     }
   2998 
   2999     errorCode=U_ZERO_ERROR;
   3000 
   3001     length=u_shapeArabic(tashkeel_aggregation_source, UPRV_LENGTHOF(tashkeel_aggregation_source),
   3002                          dest, UPRV_LENGTHOF(dest),
   3003                          U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
   3004                          U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   3005                          &errorCode);
   3006 
   3007     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
   3008         log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
   3009     }
   3010 
   3011     errorCode=U_ZERO_ERROR;
   3012 
   3013     length=u_shapeArabic(untouched_presentation_source, UPRV_LENGTHOF(untouched_presentation_source),
   3014                          dest, UPRV_LENGTHOF(dest),
   3015                          U_SHAPE_PRESERVE_PRESENTATION|
   3016                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
   3017                          &errorCode);
   3018 
   3019     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
   3020         log_err("failure in u_shapeArabic(untouched_presentation)\n");
   3021     }
   3022 
   3023     errorCode=U_ZERO_ERROR;
   3024 
   3025     length=u_shapeArabic(untouched_presentation_r_source, UPRV_LENGTHOF(untouched_presentation_r_source),
   3026                          dest, UPRV_LENGTHOF(dest),
   3027                          U_SHAPE_PRESERVE_PRESENTATION|
   3028                          U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
   3029                          &errorCode);
   3030 
   3031     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
   3032         log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
   3033     }
   3034 }
   3035 
   3036 static void
   3037 doArabicShapingTestForBug8703(void) {
   3038     static const UChar
   3039     letters_source1[]={
   3040         0x0634,0x0651,0x0645,0x0652,0x0633
   3041     }, letters_source2[]={
   3042         0x0634,0x0651,0x0645,0x0652,0x0633
   3043     }, letters_source3[]={
   3044        0x0634,0x0651,0x0645,0x0652,0x0633
   3045     }, letters_source4[]={
   3046         0x0634,0x0651,0x0645,0x0652,0x0633
   3047     }, letters_source5[]={
   3048         0x0633,0x0652,0x0645,0x0651,0x0634
   3049     }, letters_source6[]={
   3050         0x0633,0x0652,0x0645,0x0651,0x0634
   3051     }, letters_source7[]={
   3052         0x0633,0x0652,0x0645,0x0651,0x0634
   3053     }, letters_source8[]={
   3054         0x0633,0x0652,0x0645,0x0651,0x0634
   3055     }, letters_dest1[]={
   3056         0x0020,0xFEB7,0xFE7D,0xFEE4,0xFEB2
   3057     }, letters_dest2[]={
   3058         0xFEB7,0xFE7D,0xFEE4,0xFEB2,0x0020
   3059     }, letters_dest3[]={
   3060         0xFEB7,0xFE7D,0xFEE4,0xFEB2
   3061     }, letters_dest4[]={
   3062         0xFEB7,0xFE7D,0xFEE4,0x0640,0xFEB2
   3063     }, letters_dest5[]={
   3064         0x0020,0xFEB2,0xFEE4,0xFE7D,0xFEB7
   3065     }, letters_dest6[]={
   3066         0xFEB2,0xFEE4,0xFE7D,0xFEB7,0x0020
   3067     }, letters_dest7[]={
   3068         0xFEB2,0xFEE4,0xFE7D,0xFEB7
   3069     }, letters_dest8[]={
   3070         0xFEB2,0x0640,0xFEE4,0xFE7D,0xFEB7
   3071     };
   3072 
   3073     UChar dest[20];
   3074     UErrorCode errorCode;
   3075     int32_t length;
   3076 
   3077     errorCode=U_ZERO_ERROR;
   3078 
   3079     length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
   3080                          dest, UPRV_LENGTHOF(dest),
   3081                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3082                          &errorCode);
   3083 
   3084     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
   3085         log_err("failure in u_shapeArabic(letters_source1)\n");
   3086     }
   3087 
   3088     errorCode=U_ZERO_ERROR;
   3089 
   3090     length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
   3091                          dest, UPRV_LENGTHOF(dest),
   3092                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3093                          &errorCode);
   3094 
   3095     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
   3096         log_err("failure in u_shapeArabic(letters_source2)\n");
   3097     }
   3098 
   3099     errorCode=U_ZERO_ERROR;
   3100 
   3101     length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
   3102                          dest, UPRV_LENGTHOF(dest),
   3103                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3104                          &errorCode);
   3105 
   3106     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
   3107         log_err("failure in u_shapeArabic(letters_source3)\n");
   3108     }
   3109 
   3110     errorCode=U_ZERO_ERROR;
   3111 
   3112     length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
   3113                          dest, UPRV_LENGTHOF(dest),
   3114                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3115                          &errorCode);
   3116 
   3117     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
   3118         log_err("failure in u_shapeArabic(letters_source4)\n");
   3119     }
   3120 
   3121     errorCode=U_ZERO_ERROR;
   3122 
   3123     length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
   3124                          dest, UPRV_LENGTHOF(dest),
   3125                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3126                          &errorCode);
   3127 
   3128     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
   3129         log_err("failure in u_shapeArabic(letters_source5)\n");
   3130     }
   3131 
   3132     errorCode=U_ZERO_ERROR;
   3133 
   3134     length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
   3135                          dest, UPRV_LENGTHOF(dest),
   3136                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3137                          &errorCode);
   3138 
   3139     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
   3140         log_err("failure in u_shapeArabic(letters_source6)\n");
   3141     }
   3142 
   3143     errorCode=U_ZERO_ERROR;
   3144 
   3145     length=u_shapeArabic(letters_source7, UPRV_LENGTHOF(letters_source7),
   3146                          dest, UPRV_LENGTHOF(dest),
   3147                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3148                          &errorCode);
   3149 
   3150     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest7) || memcmp(dest, letters_dest7, length*U_SIZEOF_UCHAR)!=0) {
   3151         log_err("failure in u_shapeArabic(letters_source7)\n");
   3152     }
   3153 
   3154     errorCode=U_ZERO_ERROR;
   3155 
   3156     length=u_shapeArabic(letters_source8, UPRV_LENGTHOF(letters_source8),
   3157                          dest, UPRV_LENGTHOF(dest),
   3158                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3159                          &errorCode);
   3160 
   3161     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest8) || memcmp(dest, letters_dest8, length*U_SIZEOF_UCHAR)!=0) {
   3162         log_err("failure in u_shapeArabic(letters_source8)\n");
   3163     }
   3164 }
   3165 
   3166 static void
   3167 doArabicShapingTestForBug9024(void) {
   3168     static const UChar
   3169     letters_source1[]={  /* Arabic mathematical Symbols 0x1EE00 - 0x1EE1B */
   3170         0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
   3171         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
   3172         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
   3173         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
   3174         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
   3175         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
   3176         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
   3177         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
   3178     }, letters_source2[]={/* Arabic mathematical Symbols - Looped Symbols, 0x1EE80 - 0x1EE9B */
   3179         0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
   3180         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
   3181         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
   3182         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
   3183         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
   3184         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
   3185         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
   3186         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
   3187     }, letters_source3[]={/* Arabic mathematical Symbols - Double-struck Symbols, 0x1EEA1 - 0x1EEBB */
   3188         0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
   3189         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
   3190         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
   3191         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
   3192         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
   3193         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
   3194         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
   3195         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
   3196     }, letters_source4[]={/* Arabic mathematical Symbols - Initial Symbols, 0x1EE21 - 0x1EE3B */
   3197         0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
   3198         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
   3199         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
   3200         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
   3201         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
   3202         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
   3203         0xD83B, 0xDE39, 0xD83B, 0xDE3B
   3204     }, letters_source5[]={/* Arabic mathematical Symbols - Tailed Symbols */
   3205         0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
   3206         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
   3207         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
   3208         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
   3209     }, letters_source6[]={/* Arabic mathematical Symbols - Stretched Symbols with 06 range */
   3210         0xD83B, 0xDE21, 0x0633, 0xD83B, 0xDE62, 0x0647
   3211     }, letters_dest1[]={
   3212         0xD83B, 0xDE00, 0xD83B, 0xDE01, 0xD83B, 0xDE02, 0xD83B, 0xDE03, 0x20,
   3213         0xD83B, 0xDE24, 0xD83B, 0xDE05, 0xD83B, 0xDE06, 0x20,
   3214         0xD83B, 0xDE07, 0xD83B, 0xDE08, 0xD83B, 0xDE09, 0x20,
   3215         0xD83B, 0xDE0A, 0xD83B, 0xDE0B, 0xD83B, 0xDE0C, 0xD83B, 0xDE0D, 0x20,
   3216         0xD83B, 0xDE0E, 0xD83B, 0xDE0F, 0xD83B, 0xDE10, 0xD83B, 0xDE11, 0x20,
   3217         0xD83B, 0xDE12, 0xD83B, 0xDE13, 0xD83B, 0xDE14, 0xD83B, 0xDE15, 0x20,
   3218         0xD83B, 0xDE16, 0xD83B, 0xDE17, 0xD83B, 0xDE18, 0x20,
   3219         0xD83B, 0xDE19, 0xD83B, 0xDE1A, 0xD83B, 0xDE1B
   3220     }, letters_dest2[]={
   3221         0xD83B, 0xDE80, 0xD83B, 0xDE81, 0xD83B, 0xDE82, 0xD83B, 0xDE83, 0x20,
   3222         0xD83B, 0xDE84, 0xD83B, 0xDE85, 0xD83B, 0xDE86, 0x20,
   3223         0xD83B, 0xDE87, 0xD83B, 0xDE88, 0xD83B, 0xDE89, 0x20,
   3224         0xD83B, 0xDE8B, 0xD83B, 0xDE8C, 0xD83B, 0xDE8D, 0x20,
   3225         0xD83B, 0xDE8E, 0xD83B, 0xDE8F, 0xD83B, 0xDE90, 0xD83B, 0xDE91, 0x20,
   3226         0xD83B, 0xDE92, 0xD83B, 0xDE93, 0xD83B, 0xDE94, 0xD83B, 0xDE95, 0x20,
   3227         0xD83B, 0xDE96, 0xD83B, 0xDE97, 0xD83B, 0xDE98, 0x20,
   3228         0xD83B, 0xDE99, 0xD83B, 0xDE9A, 0xD83B, 0xDE9B
   3229     }, letters_dest3[]={
   3230         0xD83B, 0xDEA1, 0xD83B, 0xDEA2, 0xD83B, 0xDEA3, 0x20,
   3231         0xD83B, 0xDEA5, 0xD83B, 0xDEA6, 0x20,
   3232         0xD83B, 0xDEA7, 0xD83B, 0xDEA8, 0xD83B, 0xDEA9, 0x20,
   3233         0xD83B, 0xDEAB, 0xD83B, 0xDEAC, 0xD83B, 0xDEAD, 0x20,
   3234         0xD83B, 0xDEAE, 0xD83B, 0xDEAF, 0xD83B, 0xDEB0, 0xD83B, 0xDEB1, 0x20,
   3235         0xD83B, 0xDEB2, 0xD83B, 0xDEB3, 0xD83B, 0xDEB4, 0xD83B, 0xDEB5, 0x20,
   3236         0xD83B, 0xDEB6, 0xD83B, 0xDEB7, 0xD83B, 0xDEB8, 0x20,
   3237         0xD83B, 0xDEB9, 0xD83B, 0xDEBA, 0xD83B, 0xDEBB
   3238     }, letters_dest4[]={
   3239         0xD83B, 0xDE21, 0xD83B, 0xDE22, 0x20,
   3240         0xD83B, 0xDE27, 0xD83B, 0xDE29, 0x20,
   3241         0xD83B, 0xDE2A, 0xD83B, 0xDE2B, 0xD83B, 0xDE2C, 0xD83B, 0xDE2D, 0x20,
   3242         0xD83B, 0xDE2E, 0xD83B, 0xDE2F, 0xD83B, 0xDE30, 0xD83B, 0xDE31, 0x20,
   3243         0xD83B, 0xDE32, 0xD83B, 0xDE34, 0xD83B, 0xDE35, 0x20,
   3244         0xD83B, 0xDE36, 0xD83B, 0xDE37, 0x20,
   3245         0xD83B, 0xDE39, 0xD83B, 0xDE3B
   3246     }, letters_dest5[]={
   3247         0xD83B, 0xDE42, 0xD83B, 0xDE47, 0xD83B, 0xDE49, 0xD83B, 0xDE4B, 0x20,
   3248         0xD83B, 0xDE4D, 0xD83B, 0xDE4E, 0xD83B, 0xDE4F, 0x20,
   3249         0xD83B, 0xDE51, 0xD83B, 0xDE52, 0xD83B, 0xDE54, 0xD83B, 0xDE57, 0x20,
   3250         0xD83B, 0xDE59, 0xD83B, 0xDE5B, 0xD83B, 0xDE5D, 0xD83B, 0xDE5F
   3251     }, letters_dest6[]={
   3252         0xD83B, 0xDE21, 0xFEB1, 0xD83B, 0xDE62, 0xFEE9
   3253     };
   3254 
   3255     UChar dest[MAXLEN];
   3256     UErrorCode errorCode;
   3257     int32_t length;
   3258 
   3259     errorCode=U_ZERO_ERROR;
   3260 
   3261     length=u_shapeArabic(letters_source1, UPRV_LENGTHOF(letters_source1),
   3262                          dest, UPRV_LENGTHOF(dest),
   3263                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3264                          &errorCode);
   3265 
   3266     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest1) || memcmp(dest, letters_dest1, length*U_SIZEOF_UCHAR)!=0) {
   3267         log_err("failure in u_shapeArabic(letters_source1)\n");
   3268     }
   3269 
   3270     errorCode=U_ZERO_ERROR;
   3271 
   3272     length=u_shapeArabic(letters_source2, UPRV_LENGTHOF(letters_source2),
   3273                          dest, UPRV_LENGTHOF(dest),
   3274                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3275                          &errorCode);
   3276 
   3277     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest2) || memcmp(dest, letters_dest2, length*U_SIZEOF_UCHAR)!=0) {
   3278         log_err("failure in u_shapeArabic(letters_source2)\n");
   3279     }
   3280 
   3281     errorCode=U_ZERO_ERROR;
   3282 
   3283     length=u_shapeArabic(letters_source3, UPRV_LENGTHOF(letters_source3),
   3284                          dest, UPRV_LENGTHOF(dest),
   3285                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_RESIZE | U_SHAPE_LETTERS_SHAPE,
   3286                          &errorCode);
   3287 
   3288     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest3) || memcmp(dest, letters_dest3, length*U_SIZEOF_UCHAR)!=0) {
   3289         log_err("failure in u_shapeArabic(letters_source3)\n");
   3290     }
   3291 
   3292     errorCode=U_ZERO_ERROR;
   3293 
   3294     length=u_shapeArabic(letters_source4, UPRV_LENGTHOF(letters_source4),
   3295                          dest, UPRV_LENGTHOF(dest),
   3296                          U_SHAPE_TEXT_DIRECTION_VISUAL_RTL | U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL | U_SHAPE_LETTERS_SHAPE,
   3297                          &errorCode);
   3298 
   3299     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest4) || memcmp(dest, letters_dest4, length*U_SIZEOF_UCHAR)!=0) {
   3300         log_err("failure in u_shapeArabic(letters_source4)\n");
   3301     }
   3302 
   3303     errorCode=U_ZERO_ERROR;
   3304 
   3305     length=u_shapeArabic(letters_source5, UPRV_LENGTHOF(letters_source5),
   3306                          dest, UPRV_LENGTHOF(dest),
   3307                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_BEGIN | U_SHAPE_LETTERS_SHAPE,
   3308                          &errorCode);
   3309 
   3310     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest5) || memcmp(dest, letters_dest5, length*U_SIZEOF_UCHAR)!=0) {
   3311         log_err("failure in u_shapeArabic(letters_source5)\n");
   3312     }
   3313 
   3314     errorCode=U_ZERO_ERROR;
   3315 
   3316     length=u_shapeArabic(letters_source6, UPRV_LENGTHOF(letters_source6),
   3317                          dest, UPRV_LENGTHOF(dest),
   3318                          U_SHAPE_TEXT_DIRECTION_VISUAL_LTR | U_SHAPE_TASHKEEL_END | U_SHAPE_LETTERS_SHAPE,
   3319                          &errorCode);
   3320 
   3321     if(U_FAILURE(errorCode) || length!=UPRV_LENGTHOF(letters_dest6) || memcmp(dest, letters_dest6, length*U_SIZEOF_UCHAR)!=0) {
   3322         log_err("failure in u_shapeArabic(letters_source6)\n");
   3323     }
   3324 
   3325 }
   3326 
   3327 static void _testPresentationForms(const UChar* in) {
   3328   enum Forms { GENERIC, ISOLATED, FINAL, INITIAL, MEDIAL };
   3329   /* This character is used to check whether the in-character is rewritten correctly
   3330      and whether the surrounding characters are shaped correctly as well. */
   3331   UChar otherChar[] = {0x0628, 0xfe8f, 0xfe90, 0xfe91, 0xfe92};
   3332   UChar src[3];
   3333   UChar dst[3];
   3334   UErrorCode errorCode;
   3335   int32_t length;
   3336 
   3337   /* Testing isolated shaping */
   3338   src[0] = in[GENERIC];
   3339   errorCode=U_ZERO_ERROR;
   3340   length=u_shapeArabic(src, 1,
   3341                        dst, 1,
   3342                        U_SHAPE_LETTERS_SHAPE,
   3343                        &errorCode);
   3344   if(U_FAILURE(errorCode) || length!=1 || dst[0] != in[ISOLATED]) {
   3345       log_err("failure in u_shapeArabic(_testAllForms: shaping isolated): %x\n", in[GENERIC]);
   3346   }
   3347   errorCode=U_ZERO_ERROR;
   3348   length=u_shapeArabic(dst, 1,
   3349                        src, 1,
   3350                        U_SHAPE_LETTERS_UNSHAPE,
   3351                        &errorCode);
   3352   if(U_FAILURE(errorCode) || length!=1 || src[0] != in[GENERIC]) {
   3353       log_err("failure in u_shapeArabic(_testAllForms: unshaping isolated): %x\n", in[GENERIC]);
   3354   }
   3355 
   3356   /* Testing final shaping */
   3357   src[0] = otherChar[GENERIC];
   3358   src[1] = in[GENERIC];
   3359   if (in[FINAL] != 0) {
   3360     errorCode=U_ZERO_ERROR;
   3361     length=u_shapeArabic(src, 2,
   3362                          dst, 2,
   3363                          U_SHAPE_LETTERS_SHAPE,
   3364                          &errorCode);
   3365     if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL]) {
   3366       log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
   3367     }
   3368     errorCode=U_ZERO_ERROR;
   3369     length=u_shapeArabic(dst, 2,
   3370                          src, 2,
   3371                          U_SHAPE_LETTERS_UNSHAPE,
   3372                          &errorCode);
   3373     if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
   3374       log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
   3375     }
   3376   } else {
   3377     errorCode=U_ZERO_ERROR;
   3378     length=u_shapeArabic(src, 2,
   3379                          dst, 2,
   3380                          U_SHAPE_LETTERS_SHAPE,
   3381                          &errorCode);
   3382     if(U_FAILURE(errorCode) || length!=2 || dst[0] != otherChar[ISOLATED] || dst[1] != in[ISOLATED]) {
   3383       log_err("failure in u_shapeArabic(_testAllForms: shaping final): %x\n", in[GENERIC]);
   3384     }
   3385     errorCode=U_ZERO_ERROR;
   3386     length=u_shapeArabic(dst, 2,
   3387                          src, 2,
   3388                          U_SHAPE_LETTERS_UNSHAPE,
   3389                          &errorCode);
   3390     if(U_FAILURE(errorCode) || length!=2 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC]) {
   3391       log_err("failure in u_shapeArabic(_testAllForms: unshaping final): %x\n", in[GENERIC]);
   3392     }
   3393   }
   3394 
   3395   /* Testing initial shaping */
   3396   src[0] = in[GENERIC];
   3397   src[1] = otherChar[GENERIC];
   3398   if (in[INITIAL] != 0) {
   3399     /* Testing characters that have an initial form */
   3400     errorCode=U_ZERO_ERROR;
   3401     length=u_shapeArabic(src, 2,
   3402                          dst, 2,
   3403                          U_SHAPE_LETTERS_SHAPE,
   3404                          &errorCode);
   3405     if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[INITIAL] || dst[1] != otherChar[FINAL]) {
   3406       log_err("failure in u_shapeArabic(_testAllForms: shaping initial): %x\n", in[GENERIC]);
   3407     }
   3408     errorCode=U_ZERO_ERROR;
   3409     length=u_shapeArabic(dst, 2,
   3410                          src, 2,
   3411                          U_SHAPE_LETTERS_UNSHAPE,
   3412                          &errorCode);
   3413     if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
   3414       log_err("failure in u_shapeArabic(_testAllForms: unshaping initial): %x\n", in[GENERIC]);
   3415     }
   3416   } else {
   3417     /* Testing characters that do not have an initial form */
   3418     errorCode=U_ZERO_ERROR;
   3419     length=u_shapeArabic(src, 2,
   3420                          dst, 2,
   3421                          U_SHAPE_LETTERS_SHAPE,
   3422                          &errorCode);
   3423     if(U_FAILURE(errorCode) || length!=2 || dst[0] != in[ISOLATED] || dst[1] != otherChar[ISOLATED]) {
   3424       log_err("failure in u_shapeArabic(_testTwoForms: shaping initial): %x\n", in[GENERIC]);
   3425     }
   3426     errorCode=U_ZERO_ERROR;
   3427     length=u_shapeArabic(dst, 2,
   3428                          src, 2,
   3429                          U_SHAPE_LETTERS_UNSHAPE,
   3430                          &errorCode);
   3431     if(U_FAILURE(errorCode) || length!=2 || src[0] != in[GENERIC] || src[1] != otherChar[GENERIC]) {
   3432       log_err("failure in u_shapeArabic(_testTwoForms: unshaping initial): %x\n", in[GENERIC]);
   3433     }
   3434   }
   3435 
   3436   /* Testing medial shaping */
   3437   src[0] = otherChar[0];
   3438   src[1] = in[GENERIC];
   3439   src[2] = otherChar[0];
   3440   errorCode=U_ZERO_ERROR;
   3441   if (in[MEDIAL] != 0) {
   3442     /* Testing characters that have an medial form */
   3443     length=u_shapeArabic(src, 3,
   3444                          dst, 3,
   3445                          U_SHAPE_LETTERS_SHAPE,
   3446                          &errorCode);
   3447     if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[MEDIAL] || dst[2] != otherChar[FINAL]) {
   3448       log_err("failure in u_shapeArabic(_testAllForms: shaping medial): %x\n", in[GENERIC]);
   3449     }
   3450     errorCode=U_ZERO_ERROR;
   3451     length=u_shapeArabic(dst, 3,
   3452                          src, 3,
   3453                          U_SHAPE_LETTERS_UNSHAPE,
   3454                          &errorCode);
   3455     if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
   3456       log_err("failure in u_shapeArabic(_testAllForms: unshaping medial): %x\n", in[GENERIC]);
   3457     }
   3458   } else {
   3459     /* Testing characters that do not have an medial form */
   3460     errorCode=U_ZERO_ERROR;
   3461     length=u_shapeArabic(src, 3,
   3462                          dst, 3,
   3463                          U_SHAPE_LETTERS_SHAPE,
   3464                          &errorCode);
   3465     if(U_FAILURE(errorCode) || length!=3 || dst[0] != otherChar[INITIAL] || dst[1] != in[FINAL] || dst[2] != otherChar[ISOLATED]) {
   3466       log_err("failure in u_shapeArabic(_testTwoForms: shaping medial): %x\n", in[GENERIC]);
   3467     }
   3468     errorCode=U_ZERO_ERROR;
   3469     length=u_shapeArabic(dst, 3,
   3470                          src, 3,
   3471                          U_SHAPE_LETTERS_UNSHAPE,
   3472                          &errorCode);
   3473     if(U_FAILURE(errorCode) || length!=3 || src[0] != otherChar[GENERIC] || src[1] != in[GENERIC] || src[2] != otherChar[GENERIC]) {
   3474       log_err("failure in u_shapeArabic(_testTwoForms: unshaping medial): %x\n", in[GENERIC]);
   3475     }
   3476   }
   3477 }
   3478 
   3479 static void
   3480 doArabicShapingTestForNewCharacters(void) {
   3481   static const UChar letterForms[][5]={
   3482     { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69 },  /* TTEH */
   3483     { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61 },  /* TTEHEH */
   3484     { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55 },  /* BEEH */
   3485     { 0x0688, 0xFB88, 0xFB89, 0, 0 },            /* DDAL */
   3486     { 0x068C, 0xFB84, 0xFB85, 0, 0 },            /* DAHAL */
   3487     { 0x068D, 0xFB82, 0xFB83, 0, 0 },            /* DDAHAL */
   3488     { 0x068E, 0xFB86, 0xFB87, 0, 0 },            /* DUL */
   3489     { 0x0691, 0xFB8C, 0xFB8D, 0, 0 },            /* RREH */
   3490     { 0x06BA, 0xFB9E, 0xFB9F, 0, 0 },            /* NOON GHUNNA */
   3491     { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3 },  /* RNOON */
   3492     { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD },  /* HEH DOACHASHMEE */
   3493     { 0x06C0, 0xFBA4, 0xFBA5, 0, 0 },            /* HEH WITH YEH ABOVE */
   3494     { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9 },  /* HEH GOAL */
   3495     { 0x06C5, 0xFBE0, 0xFBE1, 0, 0 },            /* KIRGIHIZ OE */
   3496     { 0x06C6, 0xFBD9, 0xFBDA, 0, 0 },            /* OE */
   3497     { 0x06C7, 0xFBD7, 0xFBD8, 0, 0 },            /* U */
   3498     { 0x06C8, 0xFBDB, 0xFBDC, 0, 0 },            /* YU */
   3499     { 0x06C9, 0xFBE2, 0xFBE3, 0, 0 },            /* KIRGIZ YU */
   3500     { 0x06CB, 0xFBDE, 0xFBDF, 0, 0},             /* VE */
   3501     { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7 },  /* E */
   3502     { 0x06D2, 0xFBAE, 0xFBAF, 0, 0 },            /* YEH BARREE */
   3503     { 0x06D3, 0xFBB0, 0xFBB1, 0, 0 },            /* YEH BARREE WITH HAMZA ABOVE */
   3504     { 0x0622, 0xFE81, 0xFE82, 0, 0, },           /* ALEF WITH MADDA ABOVE */
   3505     { 0x0623, 0xFE83, 0xFE84, 0, 0, },           /* ALEF WITH HAMZA ABOVE */
   3506     { 0x0624, 0xFE85, 0xFE86, 0, 0, },           /* WAW WITH HAMZA ABOVE */
   3507     { 0x0625, 0xFE87, 0xFE88, 0, 0, },           /* ALEF WITH HAMZA BELOW */
   3508     { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, /* YEH WITH HAMZA ABOVE */
   3509     { 0x0627, 0xFE8D, 0xFE8E, 0, 0, },           /* ALEF */
   3510     { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, /* BEH */
   3511     { 0x0629, 0xFE93, 0xFE94, 0, 0, },           /* TEH MARBUTA */
   3512     { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, /* TEH */
   3513     { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, /* THEH */
   3514     { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, /* JEEM */
   3515     { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, /* HAH */
   3516     { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, /* KHAH */
   3517     { 0x062F, 0xFEA9, 0xFEAA, 0, 0, },           /* DAL */
   3518     { 0x0630, 0xFEAB, 0xFEAC, 0, 0, },           /* THAL */
   3519     { 0x0631, 0xFEAD, 0xFEAE, 0, 0, },           /* REH */
   3520     { 0x0632, 0xFEAF, 0xFEB0, 0, 0, },           /* ZAIN */
   3521     { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, /* SEEN */
   3522     { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, /* SHEEN */
   3523     { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, /* SAD */
   3524     { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, /* DAD */
   3525     { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, /* TAH */
   3526     { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, /* ZAH */
   3527     { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, /* AIN */
   3528     { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, /* GHAIN */
   3529     { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, /* FEH */
   3530     { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, /* QAF */
   3531     { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, /* KAF */
   3532     { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, /* LAM */
   3533     { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, /* MEEM */
   3534     { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, /* NOON */
   3535     { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, /* HEH */
   3536     { 0x0648, 0xFEED, 0xFEEE, 0, 0, },           /* WAW */
   3537     { 0x0649, 0xFEEF, 0xFEF0, 0, 0, },           /* ALEF MAKSURA */
   3538     { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, /* YEH */
   3539     { 0x064E, 0xFE76, 0, 0, 0xFE77, },           /* FATHA */
   3540     { 0x064F, 0xFE78, 0, 0, 0xFE79, },           /* DAMMA */
   3541     { 0x0650, 0xFE7A, 0, 0, 0xFE7B, },           /* KASRA */
   3542     { 0x0651, 0xFE7C, 0, 0, 0xFE7D, },           /* SHADDA */
   3543     { 0x0652, 0xFE7E, 0, 0, 0xFE7F, },           /* SUKUN */
   3544     { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, /* TTEH */
   3545     { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, /* PEH */
   3546     { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, /* TCHEH */
   3547     { 0x0688, 0xFB88, 0xFB89, 0, 0, },           /* DDAL */
   3548     { 0x0691, 0xFB8C, 0xFB8D, 0, 0, },           /* RREH */
   3549     { 0x0698, 0xFB8A, 0xFB8B, 0, 0, },           /* JEH */
   3550     { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, /* KEHEH */
   3551     { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, /* GAF */
   3552     { 0x06BA, 0xFB9E, 0xFB9F, 0, 0, },           /* NOON GHUNNA */
   3553     { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, /* HEH DOACHASHMEE */
   3554     { 0x06C0, 0xFBA4, 0xFBA5, 0, 0, },           /* HEH WITH YEH ABOVE */
   3555     { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, /* HEH GOAL */
   3556     { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, /* FARSI YEH */
   3557     { 0x06D2, 0xFBAE, 0xFBAF, 0, 0, },           /* YEH BARREE */
   3558     { 0x06D3, 0xFBB0, 0xFBB1, 0, 0, }};          /* YEH BARREE WITH HAMZA ABOVE */
   3559   int32_t i;
   3560   for (i = 0; i < UPRV_LENGTHOF(letterForms); ++i) {
   3561     _testPresentationForms(letterForms[i]);
   3562   }
   3563 }
   3564 
   3565 /* helpers ------------------------------------------------------------------ */
   3566 
   3567 static void initCharFromDirProps(void) {
   3568     static const UVersionInfo ucd401={ 4, 0, 1, 0 };
   3569     static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
   3570 
   3571     /* lazy initialization */
   3572     if(ucdVersion[0]>0) {
   3573         return;
   3574     }
   3575 
   3576     u_getUnicodeVersion(ucdVersion);
   3577     if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
   3578         /* Unicode 4.0.1 changes bidi classes for +-/ */
   3579         charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
   3580     }
   3581 }
   3582 
   3583 /* return a string with characters according to the desired directional properties */
   3584 static UChar *
   3585 getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
   3586     int32_t i;
   3587 
   3588     initCharFromDirProps();
   3589 
   3590     /* this part would have to be modified for UTF-x */
   3591     for(i=0; i<length; ++i) {
   3592         buffer[i]=charFromDirProp[dirProps[i]];
   3593     }
   3594     buffer[length]=0;
   3595     return buffer;
   3596 }
   3597 
   3598 static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
   3599     int32_t i;
   3600 
   3601     log_verbose("{ ");
   3602     for(i=0; i<length; ++i) {
   3603         if(levels!=NULL) {
   3604             log_verbose("%4x.%u  ", s[i], levels[i]);
   3605         } else {
   3606             log_verbose("%4x    ", s[i]);
   3607         }
   3608     }
   3609     log_verbose(" }");
   3610 }
   3611 
   3612 /* new BIDI API */
   3613 
   3614 /* Reordering Mode BiDi --------------------------------------------------------- */
   3615 
   3616 static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
   3617 
   3618 static UBool
   3619 assertSuccessful(const char* message, UErrorCode* rc) {
   3620     if (rc != NULL && U_FAILURE(*rc)) {
   3621         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   3622         return FALSE;
   3623     }
   3624     return TRUE;
   3625 }
   3626 
   3627 static UBool
   3628 assertStringsEqual(const char* expected, const char* actual, const char* src,
   3629                    const char* mode, const char* option, UBiDi* pBiDi) {
   3630     if (uprv_strcmp(expected, actual)) {
   3631         char formatChars[MAXLEN];
   3632         log_err("\nActual and expected output mismatch.\n"
   3633             "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
   3634             "Input:", src,
   3635             "Actual output:", actual,
   3636             "Expected output:", expected,
   3637             "Levels:", formatLevels(pBiDi, formatChars),
   3638             "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
   3639             "Paragraph level:", ubidi_getParaLevel(pBiDi),
   3640             "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
   3641         return FALSE;
   3642     }
   3643     return TRUE;
   3644 }
   3645 
   3646 static UBiDi*
   3647 getBiDiObject(void) {
   3648     UBiDi* pBiDi = ubidi_open();
   3649     if (pBiDi == NULL) {
   3650         log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
   3651     }
   3652     return pBiDi;
   3653 }
   3654 
   3655 #define MAKE_ITEMS(val) val, #val
   3656 
   3657 static const struct {
   3658     UBiDiReorderingMode value;
   3659     const char* description;
   3660 }
   3661 modes[] = {
   3662     { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
   3663     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
   3664     { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
   3665     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
   3666     { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
   3667 };
   3668 static const struct {
   3669     uint32_t value;
   3670     const char* description;
   3671 }
   3672 options[] = {
   3673     { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
   3674     { MAKE_ITEMS(0) }
   3675 };
   3676 
   3677 #define TC_COUNT                UPRV_LENGTHOF(textIn)
   3678 #define MODES_COUNT             UPRV_LENGTHOF(modes)
   3679 #define OPTIONS_COUNT           UPRV_LENGTHOF(options)
   3680 #define LEVELS_COUNT            UPRV_LENGTHOF(paraLevels)
   3681 
   3682 static const char* const textIn[] = {
   3683 /* (0) 123 */
   3684     "123",
   3685 /* (1) .123->4.5 */
   3686     ".123->4.5",
   3687 /* (2) 678 */
   3688     "678",
   3689 /* (3) .678->8.9 */
   3690     ".678->8.9",
   3691 /* (4) JIH1.2,3MLK */
   3692     "JIH1.2,3MLK",
   3693 /* (5) FE.>12-> */
   3694     "FE.>12->",
   3695 /* (6) JIH.>12->a */
   3696     "JIH.>12->a",
   3697 /* (7) CBA.>67->89=a */
   3698     "CBA.>67->89=a",
   3699 /* (8) CBA.123->xyz */
   3700     "CBA.123->xyz",
   3701 /* (9) .>12->xyz */
   3702     ".>12->xyz",
   3703 /* (10) a.>67->xyz */
   3704     "a.>67->xyz",
   3705 /* (11) 123JIH */
   3706     "123JIH",
   3707 /* (12) 123 JIH */
   3708     "123 JIH"
   3709 };
   3710 
   3711 static const char* const textOut[] = {
   3712 /* TC 0: 123 */
   3713     "123",                                                              /* (0) */
   3714 /* TC 1: .123->4.5 */
   3715     ".123->4.5",                                                        /* (1) */
   3716     "4.5<-123.",                                                        /* (2) */
   3717 /* TC 2: 678 */
   3718     "678",                                                              /* (3) */
   3719 /* TC 3: .678->8.9 */
   3720     ".8.9<-678",                                                        /* (4) */
   3721     "8.9<-678.",                                                        /* (5) */
   3722     ".678->8.9",                                                        /* (6) */
   3723 /* TC 4: MLK1.2,3JIH */
   3724     "KLM1.2,3HIJ",                                                      /* (7) */
   3725 /* TC 5: FE.>12-> */
   3726     "12<.EF->",                                                         /* (8) */
   3727     "<-12<.EF",                                                         /* (9) */
   3728     "EF.>@12->",                                                        /* (10) */
   3729 /* TC 6: JIH.>12->a */
   3730     "12<.HIJ->a",                                                       /* (11) */
   3731     "a<-12<.HIJ",                                                       /* (12) */
   3732     "HIJ.>@12->a",                                                      /* (13) */
   3733     "a&<-12<.HIJ",                                                      /* (14) */
   3734 /* TC 7: CBA.>67->89=a */
   3735     "ABC.>@67->89=a",                                                   /* (15) */
   3736     "a=89<-67<.ABC",                                                    /* (16) */
   3737     "a&=89<-67<.ABC",                                                   /* (17) */
   3738     "89<-67<.ABC=a",                                                    /* (18) */
   3739 /* TC 8: CBA.123->xyz */
   3740     "123.ABC->xyz",                                                     /* (19) */
   3741     "xyz<-123.ABC",                                                     /* (20) */
   3742     "ABC.@123->xyz",                                                    /* (21) */
   3743     "xyz&<-123.ABC",                                                    /* (22) */
   3744 /* TC 9: .>12->xyz */
   3745     ".>12->xyz",                                                        /* (23) */
   3746     "xyz<-12<.",                                                        /* (24) */
   3747     "xyz&<-12<.",                                                       /* (25) */
   3748 /* TC 10: a.>67->xyz */
   3749     "a.>67->xyz",                                                       /* (26) */
   3750     "a.>@67@->xyz",                                                     /* (27) */
   3751     "xyz<-67<.a",                                                       /* (28) */
   3752 /* TC 11: 123JIH */
   3753     "123HIJ",                                                           /* (29) */
   3754     "HIJ123",                                                           /* (30) */
   3755 /* TC 12: 123 JIH */
   3756     "123 HIJ",                                                          /* (31) */
   3757     "HIJ 123",                                                          /* (32) */
   3758 };
   3759 
   3760 #define NO                  UBIDI_MAP_NOWHERE
   3761 #define MAX_MAP_LENGTH      20
   3762 
   3763 static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
   3764 /* TC 0: 123 */
   3765     { 0, 1, 2 },                                                        /* (0) */
   3766 /* TC 1: .123->4.5 */
   3767     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3768     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (2) */
   3769 /* TC 2: 678 */
   3770     { 0, 1, 2 },                                                        /* (3) */
   3771 /* TC 3: .678->8.9 */
   3772     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3773     { 8, 5, 6, 7, 4, 3, 0, 1, 2 },                                      /* (5) */
   3774     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3775 /* TC 4: MLK1.2,3JIH */
   3776     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3777 /* TC 5: FE.>12-> */
   3778     { 5, 4, 3, 2, 0, 1, 6, 7 },                                         /* (8) */
   3779     { 7, 6, 5, 4, 2, 3, 1, 0 },                                         /* (9) */
   3780     { 1, 0, 2, 3, 5, 6, 7, 8 },                                         /* (10) */
   3781 /* TC 6: JIH.>12->a */
   3782     { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 },                                   /* (11) */
   3783     { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 },                                   /* (12) */
   3784     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 },                                  /* (13) */
   3785     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 },                                  /* (14) */
   3786 /* TC 7: CBA.>67->89=a */
   3787     { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 },                      /* (15) */
   3788     { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 },                       /* (16) */
   3789     { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 },                      /* (17) */
   3790     { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 },                       /* (18) */
   3791 /* TC 8: CBA.123->xyz */
   3792     { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 },                           /* (19) */
   3793     { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 },                           /* (20) */
   3794     { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 },                          /* (21) */
   3795     { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 },                          /* (22) */
   3796 /* TC 9: .>12->xyz */
   3797     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3798     { 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                      /* (24) */
   3799     { 9, 8, 6, 7, 5, 4, 0, 1, 2 },                                      /* (25) */
   3800 /* TC 10: a.>67->xyz */
   3801     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3802     { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 },                                 /* (27) */
   3803     { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 },                                   /* (28) */
   3804 /* TC 11: 123JIH */
   3805     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3806     { 3, 4, 5, 2, 1, 0 },                                               /* (30) */
   3807 /* TC 12: 123 JIH */
   3808     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3809     { 4, 5, 6, 3, 2, 1, 0 },                                            /* (32) */
   3810 };
   3811 
   3812 static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
   3813 /* TC 0: 123 */
   3814     { 0, 1, 2 },                                                        /* (0) */
   3815 /* TC 1: .123->4.5 */
   3816     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (1) */
   3817     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (2) */
   3818 /* TC 2: 678 */
   3819     { 0, 1, 2 },                                                        /* (3) */
   3820 /* TC 3: .678->8.9 */
   3821     { 0, 6, 7, 8, 5, 4, 1, 2, 3 },                                      /* (4) */
   3822     { 6, 7, 8, 5, 4, 1, 2, 3, 0 },                                      /* (5) */
   3823     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (6) */
   3824 /* TC 4: MLK1.2,3JIH */
   3825     { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 },                               /* (7) */
   3826 /* TC 5: FE.>12-> */
   3827     { 4, 5, 3, 2, 1, 0, 6, 7 },                                         /* (8) */
   3828     { 7, 6, 4, 5, 3, 2, 1, 0 },                                         /* (9) */
   3829     { 1, 0, 2, 3, NO, 4, 5, 6, 7 },                                     /* (10) */
   3830 /* TC 6: JIH.>12->a */
   3831     { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 },                                   /* (11) */
   3832     { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                                   /* (12) */
   3833     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 },                               /* (13) */
   3834     { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                               /* (14) */
   3835 /* TC 7: CBA.>67->89=a */
   3836     { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 },                   /* (15) */
   3837     { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                       /* (16) */
   3838     { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 },                   /* (17) */
   3839     { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 },                       /* (18) */
   3840 /* TC 8: CBA.123->xyz */
   3841     { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 },                           /* (19) */
   3842     { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                           /* (20) */
   3843     { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 },                       /* (21) */
   3844     { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 },                       /* (22) */
   3845 /* TC 9: .>12->xyz */
   3846     { 0, 1, 2, 3, 4, 5, 6, 7, 8 },                                      /* (23) */
   3847     { 6, 7, 8, 5, 4, 2, 3, 1, 0 },                                      /* (24) */
   3848     { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 },                                  /* (25) */
   3849 /* TC 10: a.>67->xyz */
   3850     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },                                   /* (26) */
   3851     { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 },                           /* (27) */
   3852     { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 },                                   /* (28) */
   3853 /* TC 11: 123JIH */
   3854     { 0, 1, 2, 5, 4, 3 },                                               /* (29) */
   3855     { 5, 4, 3, 0, 1, 2 },                                               /* (30) */
   3856 /* TC 12: 123 JIH */
   3857     { 0, 1, 2, 3, 6, 5, 4 },                                            /* (31) */
   3858     { 6, 5, 4, 3, 0, 1, 2 },                                            /* (32) */
   3859 };
   3860 
   3861 static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
   3862             [LEVELS_COUNT] = {
   3863     { /* TC 0: 123 */
   3864         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3865         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3866         {{ 0,  0}, { 0,  0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3867         {{ 0,  0}, { 0,  0}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3868     },
   3869     { /* TC 1: .123->4.5 */
   3870         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3871         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3872         {{ 1,  2}, { 1,  2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3873         {{ 1,  2}, { 1,  2}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3874     },
   3875     { /* TC 2: 678 */
   3876         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3877         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3878         {{ 3,  3}, { 3,  3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3879         {{ 3,  3}, { 3,  3}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3880     },
   3881     { /* TC 3: .678->8.9 */
   3882         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3883         {{ 4,  5}, { 4,  5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3884         {{ 6,  5}, { 6,  5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3885         {{ 6,  5}, { 6,  5}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3886     },
   3887     { /* TC 4: MLK1.2,3JIH */
   3888         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3889         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3890         {{ 7,  7}, { 7,  7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3891         {{ 7,  7}, { 7,  7}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3892     },
   3893     { /* TC 5: FE.>12-> */
   3894         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3895         {{10,  9}, { 8,  9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3896         {{ 8,  9}, { 8,  9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3897         {{10,  9}, { 8,  9}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3898     },
   3899     { /* TC 6: JIH.>12->a */
   3900         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3901         {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3902         {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3903         {{13, 14}, {11, 12}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3904     },
   3905     { /* TC 7: CBA.>67->89=a */
   3906         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3907         {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3908         {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3909         {{15, 17}, {18, 16}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3910     },
   3911     { /* TC 8: CBA.>124->xyz */
   3912         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3913         {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3914         {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3915         {{21, 22}, {19, 20}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3916     },
   3917     { /* TC 9: .>12->xyz */
   3918         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3919         {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3920         {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3921         {{23, 25}, {23, 24}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3922     },
   3923     { /* TC 10: a.>67->xyz */
   3924         {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3925         {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3926         {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3927         {{26, 27}, {26, 28}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3928     },
   3929     { /* TC 11: 124JIH */
   3930         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3931         {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3932         {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3933         {{30, 30}, {30, 30}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3934     },
   3935     { /* TC 12: 124 JIH */
   3936         {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3937         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3938         {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3939         {{31, 32}, {31, 32}}  /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3940     }
   3941 };
   3942 
   3943 static UBool
   3944 assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
   3945                 const char *destChars, const UChar *dest, int32_t destLen,
   3946                 int mode, int option, UBiDiLevel level) {
   3947 
   3948     static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
   3949                 [LEVELS_COUNT] = {
   3950         { /* TC 0: 123 */
   3951             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3952             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3953             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3954             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3955             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3956         },
   3957         { /* TC 1: .123->4.5 */
   3958             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3959             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3960             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3961             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3962             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3963         },
   3964         { /* TC 2: 678 */
   3965             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3966             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3967             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3968             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3969             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3970         },
   3971         { /* TC 3: .678->8.9 */
   3972             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3973             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3974             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3975             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3976             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3977         },
   3978         { /* TC 4: MLK1.2,3JIH */
   3979             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3980             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3981             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3982             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3983             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3984         },
   3985         { /* TC 5: FE.>12-> */
   3986             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3987             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3988             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3989             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3990             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3991         },
   3992         { /* TC 6: JIH.>12->a */
   3993             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   3994             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   3995             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   3996             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   3997             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   3998         },
   3999         { /* TC 7: CBA.>67->89=a */
   4000             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4001             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4002             {{ 0,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4003             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4004             {{ 0,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4005         },
   4006         { /* TC 8: CBA.>123->xyz */
   4007             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4008             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4009             {{ 0,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4010             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4011             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4012         },
   4013         { /* TC 9: .>12->xyz */
   4014             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4015             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4016             {{ 1,  0}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4017             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4018             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4019         },
   4020         { /* TC 10: a.>67->xyz */
   4021             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4022             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4023             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4024             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4025             {{ 1,  0}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4026         },
   4027         { /* TC 11: 123JIH */
   4028             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4029             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4030             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4031             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4032             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4033         },
   4034         { /* TC 12: 123 JIH */
   4035             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
   4036             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
   4037             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
   4038             {{ 1,  1}, { 1,  1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
   4039             {{ 1,  1}, { 1,  1}}  /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
   4040         }
   4041     };
   4042 
   4043     #define SET_ROUND_TRIP_MODE(mode) \
   4044         ubidi_setReorderingMode(pBiDi, mode); \
   4045         desc = #mode; \
   4046         break;
   4047 
   4048     UErrorCode rc = U_ZERO_ERROR;
   4049     UChar dest2[MAXLEN];
   4050     int32_t destLen2;
   4051     const char* desc;
   4052     char destChars2[MAXLEN];
   4053     char destChars3[MAXLEN];
   4054 
   4055     switch (modes[mode].value) {
   4056         case UBIDI_REORDER_NUMBERS_SPECIAL:
   4057             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
   4058         case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
   4059             SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
   4060         case UBIDI_REORDER_RUNS_ONLY:
   4061             SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
   4062         case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
   4063             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   4064         case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
   4065             SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
   4066         case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
   4067             SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
   4068         default:
   4069             SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
   4070     }
   4071     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   4072 
   4073     ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
   4074     assertSuccessful("ubidi_setPara", &rc);
   4075     *dest2 = 0;
   4076     destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
   4077                                     &rc);
   4078     assertSuccessful("ubidi_writeReordered", &rc);
   4079 
   4080     u16ToPseudo(destLen, dest, destChars3);
   4081     u16ToPseudo(destLen2, dest2, destChars2);
   4082     checkWhatYouCan(pBiDi, destChars3, destChars2);
   4083     if (strcmp(srcChars, destChars2)) {
   4084         if (roundtrip[tc][mode][option][level]) {
   4085             log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
   4086                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   4087                     "\n%20s %u\n", tc, mode, option,
   4088                     "Original text:", srcChars,
   4089                     "Round-tripped text:", destChars2,
   4090                     "Intermediate  text:", destChars3,
   4091                     "Reordering mode:", modes[mode].description,
   4092                     "Reordering option:", options[option].description,
   4093                     "Paragraph level:", level);
   4094         }
   4095         else {
   4096             log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
   4097                     "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
   4098                     "\n%20s %u\n", tc, mode, option,
   4099                     "Original text:", srcChars,
   4100                     "Round-tripped text:", destChars2,
   4101                     "Intermediate  text:", destChars3,
   4102                     "Reordering mode:", modes[mode].description,
   4103                     "Reordering option:", options[option].description,
   4104                     "Paragraph level:", level);
   4105         }
   4106         return FALSE;
   4107     }
   4108     if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
   4109                            desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
   4110         return FALSE;
   4111     }
   4112     if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
   4113                                     desc, "UBIDI_OPTION_REMOVE_CONTROLS",
   4114                                     level, FALSE)) {
   4115         return FALSE;
   4116     }
   4117     return TRUE;
   4118 }
   4119 
   4120 static UBool
   4121 checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
   4122                   int32_t destLen, const char* mode,
   4123                   const char* option, UBiDiLevel level) {
   4124     int32_t actualLen;
   4125     if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
   4126         actualLen = strlen(destChars);
   4127     else
   4128         actualLen = ubidi_getResultLength(pBiDi);
   4129     if (actualLen != destLen) {
   4130         log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
   4131                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
   4132                 "Expected:", destLen, "Actual:", actualLen,
   4133                 "Input:", srcChars, "Output:", destChars,
   4134                 "Reordering mode:", mode, "Reordering option:", option,
   4135                 "Paragraph level:", level);
   4136         return FALSE;
   4137     }
   4138     return TRUE;
   4139 }
   4140 
   4141 static void
   4142 testReorderRunsOnly(void) {
   4143     static const struct {
   4144         const char* textIn;
   4145         const char* textOut[2][2];
   4146         const char noroundtrip[2];
   4147     } testCases[] = {
   4148         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*0*/
   4149                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   4150         {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}},        /*1*/
   4151         {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}},   /*2*/
   4152         {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"},                            /*3*/
   4153                         {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
   4154         {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"},                   /*4*/
   4155                            {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
   4156         {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"},                   /*5*/
   4157                            {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
   4158         {"123->abc", {{"abc<-123", "abc<-123"},                                  /*6*/
   4159                       {"abc&<-123", "abc<-123"}}, {1, 0}},
   4160         {"123->JKL", {{"JKL<-123", "123->JKL"},                                  /*7*/
   4161                       {"JKL<-123", "JKL<-@123"}}, {0, 1}},
   4162         {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"},                   /*8*/
   4163                            {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
   4164         {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"},                   /*9*/
   4165                            {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
   4166         {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"},                   /*10*/
   4167                            {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
   4168         {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"},                   /*11*/
   4169                            {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
   4170         {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"},                   /*12*/
   4171                            {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
   4172         {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"},                   /*13*/
   4173                            {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
   4174         {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"},                   /*14*/
   4175                            {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
   4176         {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"},                   /*15*/
   4177                            {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
   4178         {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"},          /*16*/
   4179                               {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
   4180         {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"},                       /*17*/
   4181                            {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
   4182         {"123", {{"123", "123"},                /* just one run */               /*18*/
   4183                  {"123", "123"}}, {0, 0}}
   4184     };
   4185     UBiDi *pBiDi = getBiDiObject();
   4186     UBiDi *pL2VBiDi = getBiDiObject();
   4187     UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
   4188     char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
   4189     int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
   4190     UErrorCode rc = U_ZERO_ERROR;
   4191     UBiDiLevel level;
   4192 
   4193     log_verbose("\nEntering TestReorderRunsOnly\n\n");
   4194 
   4195     if(!pL2VBiDi) {
   4196         ubidi_close(pBiDi);             /* in case this one was allocated */
   4197         return;
   4198     }
   4199     ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
   4200     ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
   4201 
   4202     for (option = 0; option < 2; option++) {
   4203         ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
   4204                                                     : UBIDI_OPTION_INSERT_MARKS);
   4205         for (i = 0, nCases = UPRV_LENGTHOF(testCases); i < nCases; i++) {
   4206             srcLen = strlen(testCases[i].textIn);
   4207             pseudoToU16(srcLen, testCases[i].textIn, src);
   4208             for(j = 0; j < 2; j++) {
   4209                 log_verbose("Now doing test for option %d, case %d, level %d\n",
   4210                             i, option, j);
   4211                 level = paraLevels[j];
   4212                 ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   4213                 assertSuccessful("ubidi_setPara", &rc);
   4214                 *dest = 0;
   4215                 destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4216                 assertSuccessful("ubidi_writeReordered", &rc);
   4217                 u16ToPseudo(destLen, dest, destChars);
   4218                 checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
   4219                 assertStringsEqual(testCases[i].textOut[option][level], destChars,
   4220                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
   4221                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   4222                         pBiDi);
   4223 
   4224                 if((option==0) && testCases[i].noroundtrip[level]) {
   4225                     continue;
   4226                 }
   4227                 ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
   4228                 assertSuccessful("ubidi_setPara1", &rc);
   4229                 *visual1 = 0;
   4230                 vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4231                 assertSuccessful("ubidi_writeReordered1", &rc);
   4232                 u16ToPseudo(vis1Len, visual1, vis1Chars);
   4233                 checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
   4234                 ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
   4235                 assertSuccessful("ubidi_setPara2", &rc);
   4236                 *visual2 = 0;
   4237                 vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4238                 assertSuccessful("ubidi_writeReordered2", &rc);
   4239                 u16ToPseudo(vis2Len, visual2, vis2Chars);
   4240                 checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
   4241                 assertStringsEqual(vis1Chars, vis2Chars,
   4242                         testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
   4243                         option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
   4244                         pBiDi);
   4245             }
   4246         }
   4247     }
   4248 
   4249     /* test with null or empty text */
   4250     ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
   4251     assertSuccessful("ubidi_setPara3", &rc);
   4252     paras = ubidi_countParagraphs(pBiDi);
   4253     if (paras != 0) {
   4254         log_err("\nInvalid number of paras (should be 0): %d\n", paras);
   4255     }
   4256 
   4257     ubidi_close(pBiDi);
   4258     ubidi_close(pL2VBiDi);
   4259 
   4260     log_verbose("\nExiting TestReorderRunsOnly\n\n");
   4261 }
   4262 
   4263 static void
   4264 testReorderingMode(void) {
   4265 
   4266     UChar src[MAXLEN], dest[MAXLEN];
   4267     char destChars[MAXLEN];
   4268     UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
   4269     UErrorCode rc;
   4270     int tc, mode, option, level;
   4271     uint32_t optionValue, optionBack;
   4272     UBiDiReorderingMode modeValue, modeBack;
   4273     int32_t srcLen, destLen, idx;
   4274     const char *expectedChars;
   4275     UBool testOK = TRUE;
   4276 
   4277     log_verbose("\nEntering TestReorderingMode\n\n");
   4278 
   4279     pBiDi = getBiDiObject();
   4280     pBiDi2 = getBiDiObject();
   4281     pBiDi3 = getBiDiObject();
   4282     if(!pBiDi3) {
   4283         ubidi_close(pBiDi);             /* in case this one was allocated */
   4284         ubidi_close(pBiDi2);            /* in case this one was allocated */
   4285         return;
   4286     }
   4287 
   4288     ubidi_setInverse(pBiDi2, TRUE);
   4289 
   4290     for (tc = 0; tc < TC_COUNT; tc++) {
   4291         const char *srcChars = textIn[tc];
   4292         srcLen = strlen(srcChars);
   4293         pseudoToU16(srcLen, srcChars, src);
   4294 
   4295         for (mode = 0; mode < MODES_COUNT; mode++) {
   4296             modeValue = modes[mode].value;
   4297             ubidi_setReorderingMode(pBiDi, modeValue);
   4298             modeBack = ubidi_getReorderingMode(pBiDi);
   4299             if (modeValue != modeBack) {
   4300                 log_err("Error while setting reordering mode to %d, returned %d\n",
   4301                         modeValue, modeBack);
   4302             }
   4303 
   4304             for (option = 0; option < OPTIONS_COUNT; option++) {
   4305                 optionValue = options[option].value;
   4306                 ubidi_setReorderingOptions(pBiDi, optionValue);
   4307                 optionBack = ubidi_getReorderingOptions(pBiDi);
   4308                 if (optionValue != optionBack) {
   4309                     log_err("Error while setting reordering option to %d, returned %d\n",
   4310                             optionValue, optionBack);
   4311                 }
   4312 
   4313                 for (level = 0; level < LEVELS_COUNT; level++) {
   4314                     log_verbose("starting test %d mode=%d option=%d level=%d\n",
   4315                                 tc, modes[mode].value, options[option].value, level);
   4316                     rc = U_ZERO_ERROR;
   4317                     ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
   4318                     assertSuccessful("ubidi_setPara", &rc);
   4319 
   4320                     *dest = 0;
   4321                     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   4322                                                    UBIDI_DO_MIRRORING, &rc);
   4323                     assertSuccessful("ubidi_writeReordered", &rc);
   4324                     u16ToPseudo(destLen, dest, destChars);
   4325                     if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
   4326                           (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
   4327                         checkWhatYouCan(pBiDi, srcChars, destChars);
   4328                     }
   4329 
   4330                     if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
   4331                         idx = -1;
   4332                         expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
   4333                                 options[option].value, paraLevels[level], destChars);
   4334                     }
   4335                     else {
   4336                         idx = outIndices[tc][mode][option][level];
   4337                         expectedChars = textOut[idx];
   4338                     }
   4339                     if (!assertStringsEqual(expectedChars, destChars, srcChars,
   4340                                 modes[mode].description,
   4341                                 options[option].description,
   4342                                 pBiDi)) {
   4343                         testOK = FALSE;
   4344                     }
   4345                     if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
   4346                              !assertRoundTrip(pBiDi3, tc, idx, srcChars,
   4347                                               destChars, dest, destLen,
   4348                                               mode, option, paraLevels[level])) {
   4349                         testOK = FALSE;
   4350                     }
   4351                     else if (!checkResultLength(pBiDi, srcChars, destChars,
   4352                                 destLen, modes[mode].description,
   4353                                 options[option].description,
   4354                                 paraLevels[level])) {
   4355                         testOK = FALSE;
   4356                     }
   4357                     else if (idx > -1 && !checkMaps(pBiDi, idx, srcChars,
   4358                             destChars, modes[mode].description,
   4359                             options[option].description, paraLevels[level],
   4360                             TRUE)) {
   4361                         testOK = FALSE;
   4362                     }
   4363                 }
   4364             }
   4365         }
   4366     }
   4367     if (testOK == TRUE) {
   4368         log_verbose("\nReordering mode test OK\n");
   4369     }
   4370     ubidi_close(pBiDi3);
   4371     ubidi_close(pBiDi2);
   4372     ubidi_close(pBiDi);
   4373 
   4374     log_verbose("\nExiting TestReorderingMode\n\n");
   4375 }
   4376 
   4377 static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
   4378                                 uint32_t option, UBiDiLevel level, char *result) {
   4379     UErrorCode rc = U_ZERO_ERROR;
   4380     int32_t destLen;
   4381     UChar src[MAXLEN], dest2[MAXLEN];
   4382 
   4383     if (pBiDi == NULL || srcChars == NULL) {
   4384         return NULL;
   4385     }
   4386     ubidi_setReorderingOptions(pBiDi, option);
   4387     pseudoToU16(srcLen, srcChars, src);
   4388     ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
   4389     assertSuccessful("ubidi_setPara", &rc);
   4390 
   4391     *dest2 = 0;
   4392     destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
   4393                                    UBIDI_DO_MIRRORING, &rc);
   4394     assertSuccessful("ubidi_writeReordered", &rc);
   4395     u16ToPseudo(destLen, dest2, result);
   4396     if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
   4397         checkWhatYouCan(pBiDi, srcChars, result);
   4398     }
   4399     return result;
   4400 }
   4401 
   4402 #define NULL_CHAR '\0'
   4403 
   4404 static void
   4405 testStreaming(void) {
   4406 #define MAXPORTIONS 10
   4407 
   4408     static const struct {
   4409         const char* textIn;
   4410         short int chunk;
   4411         short int nPortions[2];
   4412         char  portionLens[2][MAXPORTIONS];
   4413         const char* message[2];
   4414     } testData[] = {
   4415         {   "123\\u000A"
   4416             "abc45\\u000D"
   4417             "67890\\u000A"
   4418             "\\u000D"
   4419             "02468\\u000D"
   4420             "ghi",
   4421             6, { 6, 6 }, {{ 4, 6, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
   4422             {"4, 6, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
   4423         },
   4424         {   "abcd\\u000Afgh\\u000D12345\\u000A456",
   4425             6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
   4426             {"5, 4, 6, 3", "5, 4, 6, 3"}
   4427         },
   4428         {   "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
   4429             6, { 4, 4 }, {{ 5, 4, 6, 3 }, { 5, 4, 6, 3 }},
   4430             {"5, 4, 6, 3", "5, 4, 6, 3"}
   4431         },
   4432         {   "abcde\\u000Afghi",
   4433             10, { 2, 2 }, {{ 6, 4 }, { 6, 4 }},
   4434             {"6, 4", "6, 4"}
   4435         }
   4436     };
   4437     UChar src[MAXLEN];
   4438     UBiDi *pBiDi = NULL;
   4439     UChar *pSrc;
   4440     UErrorCode rc = U_ZERO_ERROR;
   4441     int32_t srcLen, processedLen, chunk, len, nPortions;
   4442     int i, j, levelIndex;
   4443     UBiDiLevel level;
   4444     int nTests = UPRV_LENGTHOF(testData), nLevels = UPRV_LENGTHOF(paraLevels);
   4445     UBool mismatch, testOK = TRUE;
   4446    char processedLenStr[MAXPORTIONS * 5];
   4447 
   4448     log_verbose("\nEntering TestStreaming\n\n");
   4449 
   4450     pBiDi = getBiDiObject();
   4451 
   4452     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   4453 
   4454     for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
   4455         for (i = 0; i < nTests; i++) {
   4456             srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
   4457             chunk = testData[i].chunk;
   4458             nPortions = testData[i].nPortions[levelIndex];
   4459             level = paraLevels[levelIndex];
   4460             processedLenStr[0] = NULL_CHAR;
   4461             log_verbose("Testing level %d, case %d\n", level, i);
   4462 
   4463             mismatch = FALSE;
   4464 
   4465             ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   4466             for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
   4467 
   4468                 len = chunk < srcLen ? chunk : srcLen;
   4469                 ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
   4470                 if (!assertSuccessful("ubidi_setPara", &rc)) {
   4471                     break;
   4472                 }
   4473 
   4474                 processedLen = ubidi_getProcessedLength(pBiDi);
   4475                 if (processedLen == 0) {
   4476                     ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
   4477                     j--;
   4478                     continue;
   4479                 }
   4480                 ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
   4481 
   4482                 mismatch |= (UBool)(j >= nPortions ||
   4483                            processedLen != testData[i].portionLens[levelIndex][j]);
   4484 
   4485                 sprintf(processedLenStr + j * 4, "%4d", processedLen);
   4486                 srcLen -= processedLen, pSrc += processedLen;
   4487             }
   4488 
   4489             if (mismatch || j != nPortions) {
   4490                 testOK = FALSE;
   4491                 log_err("\nProcessed lengths mismatch.\n"
   4492                     "\tParagraph level: %u\n"
   4493                     "\tInput string: %s\n"
   4494                     "\tActually processed portion lengths: { %s }\n"
   4495                     "\tExpected portion lengths          : { %s }\n",
   4496                     paraLevels[levelIndex], testData[i].textIn,
   4497                     processedLenStr, testData[i].message[levelIndex]);
   4498             }
   4499         }
   4500     }
   4501     ubidi_close(pBiDi);
   4502     if (testOK == TRUE) {
   4503         log_verbose("\nBiDi streaming test OK\n");
   4504     }
   4505     log_verbose("\nExiting TestStreaming\n\n");
   4506 }
   4507 
   4508 U_CDECL_BEGIN
   4509 
   4510 static UCharDirection U_CALLCONV
   4511 overrideBidiClass(const void *context, UChar32 c) {
   4512 
   4513 #define DEF U_BIDI_CLASS_DEFAULT
   4514 
   4515     static const UCharDirection customClasses[] = {
   4516        /* 0/8    1/9    2/A    3/B    4/C    5/D    6/E    7/F  */
   4517           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 00-07 */
   4518           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 08-0F */
   4519           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 10-17 */
   4520           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 18-1F */
   4521           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,     R,   DEF, /* 20-27 */
   4522           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 28-2F */
   4523            EN,    EN,    EN,    EN,    EN,    EN,    AN,    AN, /* 30-37 */
   4524            AN,    AN,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 38-3F */
   4525             L,    AL,    AL,    AL,    AL,    AL,    AL,     R, /* 40-47 */
   4526             R,     R,     R,     R,     R,     R,     R,     R, /* 48-4F */
   4527             R,     R,     R,     R,     R,     R,     R,     R, /* 50-57 */
   4528             R,     R,     R,   LRE,   DEF,   RLE,   PDF,     S, /* 58-5F */
   4529           NSM,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 60-67 */
   4530           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 68-6F */
   4531           DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF,   DEF, /* 70-77 */
   4532           DEF,   DEF,   DEF,   LRO,     B,   RLO,    BN,   DEF  /* 78-7F */
   4533     };
   4534     static const int nEntries = UPRV_LENGTHOF(customClasses);
   4535     const char *dummy = context;        /* just to avoid a compiler warning */
   4536     dummy++;
   4537 
   4538     return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
   4539 }
   4540 
   4541 U_CDECL_END
   4542 
   4543 static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
   4544                                  UBiDiClassCallback* expectedFn,
   4545                                  const void* expectedContext,
   4546                                  int32_t sizeOfContext) {
   4547     if (fn != expectedFn) {
   4548         log_err("Class callback pointer is not set properly.\n");
   4549     }
   4550     if (context != expectedContext) {
   4551         log_err("Class callback context is not set properly.\n");
   4552     }
   4553     else if (context != NULL &&
   4554             memcmp(context, expectedContext, sizeOfContext)) {
   4555         log_err("Callback context content doesn't match the expected one.\n");
   4556     }
   4557 }
   4558 
   4559 static void
   4560 testClassOverride(void) {
   4561     static const char* const textSrc  = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
   4562     static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
   4563 
   4564     UChar src[MAXLEN], dest[MAXLEN];
   4565     UErrorCode rc = U_ZERO_ERROR;
   4566     UBiDi *pBiDi = NULL;
   4567     UBiDiClassCallback* oldFn = NULL;
   4568     UBiDiClassCallback* newFn = overrideBidiClass;
   4569     const void* oldContext = NULL;
   4570     int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
   4571     char* destChars = NULL;
   4572 
   4573     log_verbose("\nEntering TestClassOverride\n\n");
   4574 
   4575     pBiDi = getBiDiObject();
   4576     if(!pBiDi) {
   4577         return;
   4578     }
   4579 
   4580     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   4581     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   4582 
   4583     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   4584     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   4585         ubidi_close(pBiDi);
   4586         return;
   4587     }
   4588     verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
   4589 
   4590     ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
   4591     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   4592 
   4593     ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
   4594     if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
   4595         ubidi_close(pBiDi);
   4596         return;
   4597     }
   4598     verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
   4599 
   4600     srcLen = u_unescape(textSrc, src, MAXLEN);
   4601     ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
   4602     assertSuccessful("ubidi_setPara", &rc);
   4603 
   4604     destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
   4605                                    UBIDI_DO_MIRRORING, &rc);
   4606     assertSuccessful("ubidi_writeReordered", &rc);
   4607 
   4608     destChars = aescstrdup(dest, destLen);
   4609     if (uprv_strcmp(textResult, destChars)) {
   4610         log_err("\nActual and expected output mismatch.\n"
   4611             "%20s %s\n%20s %s\n%20s %s\n",
   4612             "Input:", textSrc, "Actual output:", destChars,
   4613             "Expected output:", textResult);
   4614     }
   4615     else {
   4616         log_verbose("\nClass override test OK\n");
   4617     }
   4618     ubidi_close(pBiDi);
   4619     log_verbose("\nExiting TestClassOverride\n\n");
   4620 }
   4621 
   4622 static char * formatMap(const int32_t * map, int len, char * buffer)
   4623 {
   4624     int32_t i, k;
   4625     char c;
   4626     for (i = 0; i < len; i++) {
   4627         k = map[i];
   4628         if (k < 0)
   4629             c = '-';
   4630         else if (k >= sizeof(columns))
   4631             c = '+';
   4632         else
   4633             c = columns[k];
   4634         buffer[i] = c;
   4635     }
   4636     buffer[len] = '\0';
   4637     return buffer;
   4638 }
   4639 
   4640 static UBool
   4641 checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
   4642           const char *mode, const char* option, UBiDiLevel level, UBool forward)
   4643 {
   4644     int32_t actualLogicalMap[MAX_MAP_LENGTH];
   4645     int32_t actualVisualMap[MAX_MAP_LENGTH];
   4646     int32_t getIndexMap[MAX_MAP_LENGTH];
   4647     int32_t i, srcLen, resLen, idx;
   4648     const int32_t *expectedLogicalMap, *expectedVisualMap;
   4649     UErrorCode rc = U_ZERO_ERROR;
   4650     UBool testOK = TRUE;
   4651 
   4652     if (forward) {
   4653         expectedLogicalMap = forwardMap[stringIndex];
   4654         expectedVisualMap  = inverseMap[stringIndex];
   4655     }
   4656     else {
   4657         expectedLogicalMap = inverseMap[stringIndex];
   4658         expectedVisualMap  = forwardMap[stringIndex];
   4659     }
   4660     ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
   4661     if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
   4662         testOK = FALSE;
   4663     }
   4664     srcLen = ubidi_getProcessedLength(pBiDi);
   4665     if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
   4666         char expChars[MAX_MAP_LENGTH];
   4667         char actChars[MAX_MAP_LENGTH];
   4668         log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
   4669                 "index %d\n"
   4670                 "source: %s\n"
   4671                 "dest  : %s\n"
   4672                 "Scale : %s\n"
   4673                 "ExpMap: %s\n"
   4674                 "Actual: %s\n"
   4675                 "Paragraph level  : %d == %d\n"
   4676                 "Reordering mode  : %s == %d\n"
   4677                 "Reordering option: %s == %d\n"
   4678                 "Forward flag     : %d\n",
   4679                 stringIndex, src, dest, columns,
   4680                 formatMap(expectedLogicalMap, srcLen, expChars),
   4681                 formatMap(actualLogicalMap, srcLen, actChars),
   4682                 level, ubidi_getParaLevel(pBiDi),
   4683                 mode, ubidi_getReorderingMode(pBiDi),
   4684                 option, ubidi_getReorderingOptions(pBiDi),
   4685                 forward
   4686                 );
   4687         testOK = FALSE;
   4688     }
   4689     resLen = ubidi_getResultLength(pBiDi);
   4690     ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
   4691     assertSuccessful("ubidi_getVisualMap", &rc);
   4692     if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
   4693         char expChars[MAX_MAP_LENGTH];
   4694         char actChars[MAX_MAP_LENGTH];
   4695         log_err("\nubidi_getVisualMap() returns unexpected map for output string "
   4696                 "index %d\n"
   4697                 "source: %s\n"
   4698                 "dest  : %s\n"
   4699                 "Scale : %s\n"
   4700                 "ExpMap: %s\n"
   4701                 "Actual: %s\n"
   4702                 "Paragraph level  : %d == %d\n"
   4703                 "Reordering mode  : %s == %d\n"
   4704                 "Reordering option: %s == %d\n"
   4705                 "Forward flag     : %d\n",
   4706                 stringIndex, src, dest, columns,
   4707                 formatMap(expectedVisualMap, resLen, expChars),
   4708                 formatMap(actualVisualMap, resLen, actChars),
   4709                 level, ubidi_getParaLevel(pBiDi),
   4710                 mode, ubidi_getReorderingMode(pBiDi),
   4711                 option, ubidi_getReorderingOptions(pBiDi),
   4712                 forward
   4713                 );
   4714         testOK = FALSE;
   4715     }
   4716     for (i = 0; i < srcLen; i++) {
   4717         idx = ubidi_getVisualIndex(pBiDi, i, &rc);
   4718         assertSuccessful("ubidi_getVisualIndex", &rc);
   4719         getIndexMap[i] = idx;
   4720     }
   4721     if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
   4722         char actChars[MAX_MAP_LENGTH];
   4723         char gotChars[MAX_MAP_LENGTH];
   4724         log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
   4725                 "index %d\n"
   4726                 "source: %s\n"
   4727                 "dest  : %s\n"
   4728                 "Scale : %s\n"
   4729                 "ActMap: %s\n"
   4730                 "IdxMap: %s\n"
   4731                 "Paragraph level  : %d == %d\n"
   4732                 "Reordering mode  : %s == %d\n"
   4733                 "Reordering option: %s == %d\n"
   4734                 "Forward flag     : %d\n",
   4735                 stringIndex, src, dest, columns,
   4736                 formatMap(actualLogicalMap, srcLen, actChars),
   4737                 formatMap(getIndexMap, srcLen, gotChars),
   4738                 level, ubidi_getParaLevel(pBiDi),
   4739                 mode, ubidi_getReorderingMode(pBiDi),
   4740                 option, ubidi_getReorderingOptions(pBiDi),
   4741                 forward
   4742                 );
   4743         testOK = FALSE;
   4744     }
   4745     for (i = 0; i < resLen; i++) {
   4746         idx = ubidi_getLogicalIndex(pBiDi, i, &rc);
   4747         assertSuccessful("ubidi_getLogicalIndex", &rc);
   4748         getIndexMap[i] = idx;
   4749     }
   4750     if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
   4751         char actChars[MAX_MAP_LENGTH];
   4752         char gotChars[MAX_MAP_LENGTH];
   4753         log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
   4754                 "index %d\n"
   4755                 "source: %s\n"
   4756                 "dest  : %s\n"
   4757                 "Scale : %s\n"
   4758                 "ActMap: %s\n"
   4759                 "IdxMap: %s\n"
   4760                 "Paragraph level  : %d == %d\n"
   4761                 "Reordering mode  : %s == %d\n"
   4762                 "Reordering option: %s == %d\n"
   4763                 "Forward flag     : %d\n",
   4764                 stringIndex, src, dest, columns,
   4765                 formatMap(actualVisualMap, resLen, actChars),
   4766                 formatMap(getIndexMap, resLen, gotChars),
   4767                 level, ubidi_getParaLevel(pBiDi),
   4768                 mode, ubidi_getReorderingMode(pBiDi),
   4769                 option, ubidi_getReorderingOptions(pBiDi),
   4770                 forward
   4771                 );
   4772         testOK = FALSE;
   4773     }
   4774     return testOK;
   4775 }
   4776 
   4777 static UBool
   4778 assertIllegalArgument(const char* message, UErrorCode* rc) {
   4779     if (*rc != U_ILLEGAL_ARGUMENT_ERROR) {
   4780         log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
   4781         return FALSE;
   4782     }
   4783     return TRUE;
   4784 }
   4785 
   4786 typedef struct {
   4787     const char* prologue;
   4788     const char* source;
   4789     const char* epilogue;
   4790     const char* expected;
   4791     UBiDiLevel paraLevel;
   4792 } contextCase;
   4793 
   4794 static const contextCase contextData[] = {
   4795     /*00*/  {"", "", "", "", UBIDI_LTR},
   4796     /*01*/  {"", ".-=JKL-+*", "", ".-=LKJ-+*", UBIDI_LTR},
   4797     /*02*/  {" ", ".-=JKL-+*", " ", ".-=LKJ-+*", UBIDI_LTR},
   4798     /*03*/  {"a", ".-=JKL-+*", "b", ".-=LKJ-+*", UBIDI_LTR},
   4799     /*04*/  {"D", ".-=JKL-+*", "", "LKJ=-.-+*", UBIDI_LTR},
   4800     /*05*/  {"", ".-=JKL-+*", " D", ".-=*+-LKJ", UBIDI_LTR},
   4801     /*06*/  {"", ".-=JKL-+*", " 2", ".-=*+-LKJ", UBIDI_LTR},
   4802     /*07*/  {"", ".-=JKL-+*", " 7", ".-=*+-LKJ", UBIDI_LTR},
   4803     /*08*/  {" G 1", ".-=JKL-+*", " H", "*+-LKJ=-.", UBIDI_LTR},
   4804     /*09*/  {"7", ".-=JKL-+*", " H", ".-=*+-LKJ", UBIDI_LTR},
   4805     /*10*/  {"", ".-=abc-+*", "", "*+-abc=-.", UBIDI_RTL},
   4806     /*11*/  {" ", ".-=abc-+*", " ", "*+-abc=-.", UBIDI_RTL},
   4807     /*12*/  {"D", ".-=abc-+*", "G", "*+-abc=-.", UBIDI_RTL},
   4808     /*13*/  {"x", ".-=abc-+*", "", "*+-.-=abc", UBIDI_RTL},
   4809     /*14*/  {"", ".-=abc-+*", " y", "abc-+*=-.", UBIDI_RTL},
   4810     /*15*/  {"", ".-=abc-+*", " 2", "abc-+*=-.", UBIDI_RTL},
   4811     /*16*/  {" x 1", ".-=abc-+*", " 2", ".-=abc-+*", UBIDI_RTL},
   4812     /*17*/  {" x 7", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
   4813     /*18*/  {"x|", ".-=abc-+*", " 8", "*+-abc=-.", UBIDI_RTL},
   4814     /*19*/  {"G|y", ".-=abc-+*", " 8", "*+-.-=abc", UBIDI_RTL},
   4815     /*20*/  {"", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
   4816     /*21*/  {"D", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4817     /*22*/  {"G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4818     /*23*/  {"xG", ".-=", "", ".-=", UBIDI_DEFAULT_LTR},
   4819     /*24*/  {"x|G", ".-=", "", "=-.", UBIDI_DEFAULT_LTR},
   4820     /*25*/  {"x|G", ".-=|-+*", "", "=-.|-+*", UBIDI_DEFAULT_LTR},
   4821 };
   4822 #define CONTEXT_COUNT       UPRV_LENGTHOF(contextData)
   4823 
   4824 static void
   4825 testContext(void) {
   4826 
   4827     UChar prologue[MAXLEN], epilogue[MAXLEN], src[MAXLEN], dest[MAXLEN];
   4828     char destChars[MAXLEN];
   4829     UBiDi *pBiDi = NULL;
   4830     UErrorCode rc;
   4831     int32_t proLength, epiLength, srcLen, destLen, tc;
   4832     contextCase cc;
   4833     UBool testOK = TRUE;
   4834 
   4835     log_verbose("\nEntering TestContext \n\n");
   4836 
   4837     /* test null BiDi object */
   4838     rc = U_ZERO_ERROR;
   4839     ubidi_setContext(pBiDi, NULL, 0, NULL, 0, &rc);
   4840     testOK &= assertIllegalArgument("Error when BiDi object is null", &rc);
   4841 
   4842     pBiDi = getBiDiObject();
   4843     ubidi_orderParagraphsLTR(pBiDi, TRUE);
   4844 
   4845     /* test proLength < -1 */
   4846     rc = U_ZERO_ERROR;
   4847     ubidi_setContext(pBiDi, NULL, -2, NULL, 0, &rc);
   4848     testOK &= assertIllegalArgument("Error when proLength < -1", &rc);
   4849     /* test epiLength < -1 */
   4850     rc = U_ZERO_ERROR;
   4851     ubidi_setContext(pBiDi, NULL, 0, NULL, -2, &rc);
   4852     testOK &= assertIllegalArgument("Error when epiLength < -1", &rc);
   4853     /* test prologue == NULL */
   4854     rc = U_ZERO_ERROR;
   4855     ubidi_setContext(pBiDi, NULL, 3, NULL, 0, &rc);
   4856     testOK &= assertIllegalArgument("Prologue is NULL", &rc);
   4857     /* test epilogue == NULL */
   4858     rc = U_ZERO_ERROR;
   4859     ubidi_setContext(pBiDi, NULL, 0, NULL, 4, &rc);
   4860     testOK &= assertIllegalArgument("Epilogue is NULL", &rc);
   4861 
   4862     for (tc = 0; tc < CONTEXT_COUNT; tc++) {
   4863         cc = contextData[tc];
   4864         proLength = strlen(cc.prologue);
   4865         pseudoToU16(proLength, cc.prologue, prologue);
   4866         epiLength = strlen(cc.epilogue);
   4867         pseudoToU16(epiLength, cc.epilogue, epilogue);
   4868         /* in the call below, prologue and epilogue are swapped to show
   4869            that the next call will override this call */
   4870         rc = U_ZERO_ERROR;
   4871         ubidi_setContext(pBiDi, epilogue, epiLength, prologue, proLength, &rc);
   4872         testOK &= assertSuccessful("swapped ubidi_setContext", &rc);
   4873         ubidi_setContext(pBiDi, prologue, -1, epilogue, -1, &rc);
   4874         testOK &= assertSuccessful("regular ubidi_setContext", &rc);
   4875         srcLen = strlen(cc.source);
   4876         pseudoToU16(srcLen, cc.source, src);
   4877         ubidi_setPara(pBiDi, src, srcLen, cc.paraLevel, NULL, &rc);
   4878         testOK &= assertSuccessful("ubidi_setPara", &rc);
   4879         destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
   4880         assertSuccessful("ubidi_writeReordered", &rc);
   4881         u16ToPseudo(destLen, dest, destChars);
   4882         if (uprv_strcmp(cc.expected, destChars)) {
   4883             char formatChars[MAXLEN];
   4884             log_err("\nActual and expected output mismatch on case %d.\n"
   4885                 "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d\n%20s %u\n%20s %d\n",
   4886                 tc,
   4887                 "Prologue:", cc.prologue,
   4888                 "Input:", cc.source,
   4889                 "Epilogue:", cc.epilogue,
   4890                 "Expected output:", cc.expected,
   4891                 "Actual output:", destChars,
   4892                 "Levels:", formatLevels(pBiDi, formatChars),
   4893                 "Reordering mode:", ubidi_getReorderingMode(pBiDi),
   4894                 "Paragraph level:", ubidi_getParaLevel(pBiDi),
   4895                 "Reordering option:", ubidi_getReorderingOptions(pBiDi));
   4896             testOK = FALSE;
   4897         }
   4898     }
   4899     if (testOK == TRUE) {
   4900         log_verbose("\nContext test OK\n");
   4901     }
   4902     ubidi_close(pBiDi);
   4903 
   4904     log_verbose("\nExiting TestContext \n\n");
   4905 }
   4906 
   4907 /* Ticket#11054 ubidi_setPara crash with heavily nested brackets */
   4908 static void
   4909 testBracketOverflow(void) {
   4910     static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))";
   4911     UErrorCode status = U_ZERO_ERROR;
   4912     UBiDi* bidi;
   4913     UChar src[100];
   4914     int32_t len;
   4915 
   4916     bidi = ubidi_open();
   4917     len = uprv_strlen(TEXT);
   4918     pseudoToU16(len, TEXT, src);
   4919     ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status);
   4920     if (U_FAILURE(status)) {
   4921         log_err("setPara failed with heavily nested brackets - %s", u_errorName(status));
   4922     }
   4923 
   4924     ubidi_close(bidi);
   4925 }
   4926 
   4927 static void TestExplicitLevel0() {
   4928     // The following used to fail with an error, see ICU ticket #12922.
   4929     static const UChar text[2] = { 0x202d, 0x05d0 };
   4930     static UBiDiLevel embeddings[2] = { 0, 0 };
   4931     UErrorCode errorCode = U_ZERO_ERROR;
   4932     UBiDi *bidi = ubidi_open();
   4933     ubidi_setPara(bidi, text, 2, UBIDI_DEFAULT_LTR , embeddings, &errorCode);
   4934     if (U_FAILURE(errorCode)) {
   4935         log_err("ubidi_setPara() - %s", u_errorName(errorCode));
   4936     } else {
   4937         UBiDiLevel level0 = ubidi_getLevelAt(bidi, 0);
   4938         UBiDiLevel level1 = ubidi_getLevelAt(bidi, 1);
   4939         if (level0 != 1 || level1 != 1) {
   4940             log_err("resolved levels != 1: { %d, %d }\n", level0, level1);
   4941         }
   4942         if (embeddings[0] != 1 || embeddings[1] != 1) {
   4943             log_err("modified embeddings[] levels != 1: { %d, %d }\n", embeddings[0], embeddings[1]);
   4944         }
   4945     }
   4946     ubidi_close(bidi);
   4947 }
   4948