icu4c/icu4c.css -text
icu4c/source/aclocal.m4 -text
icu4c/source/allinone/icucheck.bat -text
+icu4c/source/common/ubiditransform.c -text
+icu4c/source/common/unicode/ubiditransform.h -text
icu4c/source/config/m4/icu-conditional.m4 -text
icu4c/source/data/curr/pool.res -text
icu4c/source/data/in/coll/ucadata-implicithan.icu -text
icu4c/source/samples/uresb/resources.vcxproj -text
icu4c/source/samples/uresb/uresb.vcxproj -text
icu4c/source/samples/ustring/ustring.vcxproj -text
+icu4c/source/test/cintltst/cbiditransformtst.c -text
icu4c/source/test/depstest/icu-dependencies-mode.el -text
icu4c/source/test/iotest/iotest.vcxproj -text
icu4c/source/test/letest/cletest.vcxproj -text
icu4c/source/Doxyfile
icu4c/source/Makefile
icu4c/source/README
+icu4c/source/allinone/*.db
icu4c/source/allinone/*.ncb
+icu4c/source/allinone/*.opendb
icu4c/source/allinone/*.opensdf
icu4c/source/allinone/*.opt
icu4c/source/allinone/*.sdf
icu4c/source/allinone/*.suo
+icu4c/source/allinone/.vs
+icu4c/source/allinone/Debug
icu4c/source/allinone/ipch
icu4c/source/autom4te.cache
icu4c/source/bin
util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o dtintrv.o ucnvsel.o propsvec.o \
ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o ulistformatter.o \
sharedobject.o simpleformatter.o unifiedcache.o uloc_keytype.o \
+ubiditransform.o \
pluralmap.o
## Header files to install
<ItemGroup>
<ClCompile Include="filteredbrk.cpp" />
<ClCompile Include="ubidi.c" />
+ <ClCompile Include="ubiditransform.c" />
<ClCompile Include="ubidi_props.c" />
<ClCompile Include="ubidiln.c" />
<ClCompile Include="ubidiwrt.c" />
<ClInclude Include="uchar_props_data.h" />
<ClInclude Include="ucol_data.h" />
<ClInclude Include="ucol_swp.h" />
+ <ClInclude Include="unicode\ubiditransform.h" />
<ClInclude Include="unistrappender.h" />
<ClInclude Include="hash.h" />
<ClInclude Include="propsvec.h" />
<ClCompile Include="stringtriebuilder.cpp">
<Filter>collections</Filter>
</ClCompile>
- <ClCompile Include="icuplug.cpp" />
<ClCompile Include="uloc_keytype.cpp">
<Filter>locales & resources</Filter>
</ClCompile>
<ClCompile Include="filteredbrk.cpp">
<Filter>break iteration</Filter>
</ClCompile>
+ <ClCompile Include="icuplug.cpp">
+ <Filter>registration</Filter>
+ </ClCompile>
+ <ClCompile Include="ubiditransform.c">
+ <Filter>bidi</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ubidi_props.h">
<ClInclude Include="unicode\filteredbrk.h">
<Filter>break iteration</Filter>
</ClInclude>
+ <ClInclude Include="unicode\ubiditransform.h">
+ <Filter>bidi</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc">
<Filter>collections</Filter>
</CustomBuild>
</ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
--- /dev/null
+/*\r
+******************************************************************************\r
+*\r
+* Copyright (C) 2016 and later: Unicode, Inc. and others.\r
+* License & terms of use: http://www.unicode.org/copyright.html\r
+*\r
+******************************************************************************\r
+* file name: ubiditransform.c\r
+* encoding: US-ASCII\r
+* tab size: 8 (not used)\r
+* indentation:4\r
+*\r
+* created on: 2016jul24\r
+* created by: Lina Kemmel\r
+*\r
+*/\r
+\r
+#include "cmemory.h"\r
+#include "unicode/ubidi.h"\r
+#include "unicode/ustring.h"\r
+#include "unicode/ushape.h"\r
+#include "unicode/utf16.h"\r
+#include "ustr_imp.h"\r
+#include "unicode/ubiditransform.h"\r
+\r
+/* Some convenience defines */\r
+#define LTR UBIDI_LTR\r
+#define RTL UBIDI_RTL\r
+#define LOGICAL UBIDI_LOGICAL\r
+#define VISUAL UBIDI_VISUAL\r
+#define SHAPE_LOGICAL U_SHAPE_TEXT_DIRECTION_LOGICAL\r
+#define SHAPE_VISUAL U_SHAPE_TEXT_DIRECTION_VISUAL_LTR\r
+\r
+#define CHECK_LEN(STR, LEN, ERROR) { \\r
+ if (LEN == 0) return 0; \\r
+ if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \\r
+ if (LEN == -1) LEN = u_strlen(STR); \\r
+ } \r
+\r
+#define MAX_ACTIONS 7\r
+\r
+/**\r
+ * Typedef for a pointer to a function, which performs some operation (such as\r
+ * reordering, setting "inverse" mode, character mirroring, etc.). Return value\r
+ * indicates whether the text was changed in the course of this operation or\r
+ * not.\r
+ */\r
+typedef UBool (*UBiDiAction)(UBiDiTransform *, UErrorCode *);\r
+\r
+/**\r
+ * Structure that holds a predefined reordering scheme, including the following\r
+ * information:\r
+ * <ul>\r
+ * <li>an input base direction,</li>\r
+ * <li>an input order,</li>\r
+ * <li>an output base direction,</li>\r
+ * <li>an output order,</li>\r
+ * <li>a digit shaping direction,</li>\r
+ * <li>a letter shaping direction,</li>\r
+ * <li>a base direction that should be applied when the reordering engine is\r
+ * invoked (which can not always be derived from the caller-defined\r
+ * options),</li>\r
+ * <li>an array of pointers to functions that accomplish the bidi layout\r
+ * transformation.</li>\r
+ * </ul>\r
+ */\r
+typedef struct {\r
+ UBiDiLevel inLevel; /* input level */\r
+ UBiDiOrder inOrder; /* input order */\r
+ UBiDiLevel outLevel; /* output level */\r
+ UBiDiOrder outOrder; /* output order */\r
+ uint32_t digitsDir; /* digit shaping direction */\r
+ uint32_t lettersDir; /* letter shaping direction */\r
+ UBiDiLevel baseLevel; /* paragraph level to be used with setPara */\r
+ const UBiDiAction actions[MAX_ACTIONS]; /* array of pointers to functions carrying out the transformation */\r
+} ReorderingScheme;\r
+\r
+struct UBiDiTransform {\r
+ UBiDi *pBidi; /* pointer to a UBiDi object */\r
+ const ReorderingScheme *pActiveScheme; /* effective reordering scheme */\r
+ UChar *src; /* input text */\r
+ UChar *dest; /* output text */\r
+ uint32_t srcLength; /* input text length - not really needed as we are zero-terminated and can u_strlen */\r
+ uint32_t srcSize; /* input text capacity excluding the trailing zero */\r
+ uint32_t destSize; /* output text capacity */\r
+ uint32_t *pDestLength; /* number of UChars written to dest */\r
+ uint32_t reorderingOptions; /* reordering options - currently only suppot DO_MIRRORING */\r
+ uint32_t digits; /* digit option for ArabicShaping */\r
+ uint32_t letters; /* letter option for ArabicShaping */\r
+};\r
+\r
+U_DRAFT UBiDiTransform* U_EXPORT2\r
+ubiditransform_open(UErrorCode *pErrorCode)\r
+{\r
+ UBiDiTransform *pBiDiTransform = NULL;\r
+ if (U_SUCCESS(*pErrorCode)) {\r
+ pBiDiTransform = (UBiDiTransform*) uprv_calloc(1, sizeof(UBiDiTransform));\r
+ if (pBiDiTransform == NULL) {\r
+ *pErrorCode = U_MEMORY_ALLOCATION_ERROR;\r
+ }\r
+ }\r
+ return pBiDiTransform;\r
+}\r
+\r
+U_DRAFT void U_EXPORT2\r
+ubiditransform_close(UBiDiTransform *pBiDiTransform)\r
+{\r
+ if (pBiDiTransform != NULL) {\r
+ if (pBiDiTransform->pBidi != NULL) {\r
+ ubidi_close(pBiDiTransform->pBidi);\r
+ }\r
+ if (pBiDiTransform->src != NULL) {\r
+ uprv_free(pBiDiTransform->src);\r
+ }\r
+ uprv_free(pBiDiTransform);\r
+ }\r
+}\r
+\r
+/**\r
+ * Performs Bidi resolution of text.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_resolve(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ ubidi_setPara(pTransform->pBidi, pTransform->src, pTransform->srcLength,\r
+ pTransform->pActiveScheme->baseLevel, NULL, pErrorCode);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ * Performs basic reordering of text (Logical -> Visual LTR).\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_reorder(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ ubidi_writeReordered(pTransform->pBidi, pTransform->dest, pTransform->destSize,\r
+ pTransform->reorderingOptions, pErrorCode);\r
+\r
+ *pTransform->pDestLength = pTransform->srcLength;\r
+ pTransform->reorderingOptions = UBIDI_REORDER_DEFAULT;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ * Sets "inverse" mode on the <code>UBiDi</code> object.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_setInverse(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ ubidi_setInverse(pTransform->pBidi, TRUE);\r
+ ubidi_setReorderingMode(pTransform->pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ * Sets "runs only" reordering mode indicating a Logical LTR <-> Logical RTL\r
+ * transformation.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_setRunsOnly(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ ubidi_setReorderingMode(pTransform->pBidi, UBIDI_REORDER_RUNS_ONLY);\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ * Performs string reverse.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_reverse(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ ubidi_writeReverse(pTransform->src, pTransform->srcLength,\r
+ pTransform->dest, pTransform->destSize,\r
+ UBIDI_REORDER_DEFAULT, pErrorCode);\r
+ *pTransform->pDestLength = pTransform->srcLength;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ * Applies a new value to the text that serves as input at the current\r
+ * processing step. This value is identical to the original one when we begin\r
+ * the processing, but usually changes as the transformation progresses.\r
+ * \r
+ * @param pTransform A pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param newSrc A pointer whose value is to be used as input text.\r
+ * @param newLength A length of the new text in <code>UChar</code>s.\r
+ * @param newSize A new source capacity in <code>UChar</code>s.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ */\r
+static void\r
+updateSrc(UBiDiTransform *pTransform, const UChar *newSrc, uint32_t newLength,\r
+ uint32_t newSize, UErrorCode *pErrorCode)\r
+{\r
+ if (newSize < newLength) {\r
+ *pErrorCode = U_BUFFER_OVERFLOW_ERROR;\r
+ return;\r
+ }\r
+ if (newSize > pTransform->srcSize) {\r
+ newSize += 50; // allocate slightly more than needed right now\r
+ if (pTransform->src != NULL) {\r
+ uprv_free(pTransform->src);\r
+ pTransform->src = NULL;\r
+ }\r
+ pTransform->src = (UChar *)uprv_malloc(newSize * sizeof(UChar));\r
+ if (pTransform->src == NULL) {\r
+ *pErrorCode = U_MEMORY_ALLOCATION_ERROR;\r
+ //pTransform->srcLength = pTransform->srcSize = 0;\r
+ return;\r
+ }\r
+ pTransform->srcSize = newSize;\r
+ }\r
+ u_strncpy(pTransform->src, newSrc, newLength);\r
+ pTransform->srcLength = u_terminateUChars(pTransform->src,\r
+ pTransform->srcSize, newLength, pErrorCode);\r
+}\r
+\r
+/**\r
+ * Calls a lower level shaping function.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param options Shaping options.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ */\r
+static void\r
+doShape(UBiDiTransform *pTransform, uint32_t options, UErrorCode *pErrorCode)\r
+{\r
+ *pTransform->pDestLength = u_shapeArabic(pTransform->src,\r
+ pTransform->srcLength, pTransform->dest, pTransform->destSize,\r
+ options, pErrorCode);\r
+}\r
+\r
+/**\r
+ * Performs digit and letter shaping.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_shapeArabic(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ if ((pTransform->letters | pTransform->digits) == 0) {\r
+ return FALSE;\r
+ }\r
+ if (pTransform->pActiveScheme->lettersDir == pTransform->pActiveScheme->digitsDir) {\r
+ doShape(pTransform, pTransform->letters | pTransform->digits | pTransform->pActiveScheme->lettersDir,\r
+ pErrorCode);\r
+ } else {\r
+ doShape(pTransform, pTransform->digits | pTransform->pActiveScheme->digitsDir, pErrorCode);\r
+ if (U_SUCCESS(*pErrorCode)) {\r
+ updateSrc(pTransform, pTransform->dest, *pTransform->pDestLength,\r
+ *pTransform->pDestLength, pErrorCode);\r
+ doShape(pTransform, pTransform->letters | pTransform->pActiveScheme->lettersDir,\r
+ pErrorCode);\r
+ }\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ * Performs character mirroring.\r
+ * \r
+ * @param pTransform Pointer to the <code>UBiDiTransform</code> structure.\r
+ * @param pErrorCode Pointer to the error code value.\r
+ *\r
+ * @return Whether or not this function modifies the text. Besides the return\r
+ * value, the caller should also check <code>U_SUCCESS(*pErrorCode)</code>.\r
+ */\r
+static UBool\r
+action_mirror(UBiDiTransform *pTransform, UErrorCode *pErrorCode)\r
+{\r
+ UChar32 c;\r
+ uint32_t i = 0, j = 0;\r
+ if (0 == (pTransform->reorderingOptions & UBIDI_DO_MIRRORING)) {\r
+ return FALSE;\r
+ }\r
+ if (pTransform->destSize < pTransform->srcLength) {\r
+ *pErrorCode = U_BUFFER_OVERFLOW_ERROR;\r
+ return FALSE;\r
+ }\r
+ do {\r
+ UBool isOdd = ubidi_getLevelAt(pTransform->pBidi, i) & 1;\r
+ U16_NEXT(pTransform->src, i, pTransform->srcLength, c); \r
+ U16_APPEND_UNSAFE(pTransform->dest, j, isOdd ? u_charMirror(c) : c);\r
+ } while (i < pTransform->srcLength);\r
+ \r
+ *pTransform->pDestLength = pTransform->srcLength;\r
+ pTransform->reorderingOptions = UBIDI_REORDER_DEFAULT;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ * All possible reordering schemes.\r
+ *\r
+ */\r
+static const ReorderingScheme Schemes[] =\r
+{\r
+ /* 0: Logical LTR => Visual LTR */\r
+ {LTR, LOGICAL, LTR, VISUAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_shapeArabic, action_resolve, action_reorder, NULL}},\r
+ /* 1: Logical RTL => Visual LTR */\r
+ {RTL, LOGICAL, LTR, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, RTL,\r
+ {action_resolve, action_reorder, action_shapeArabic, NULL}},\r
+ /* 2: Logical LTR => Visual RTL */\r
+ {LTR, LOGICAL, RTL, VISUAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_shapeArabic, action_resolve, action_reorder, action_reverse, NULL}},\r
+ /* 3: Logical RTL => Visual RTL */\r
+ {RTL, LOGICAL, RTL, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, RTL,\r
+ {action_resolve, action_reorder, action_shapeArabic, action_reverse, NULL}},\r
+ /* 4: Visual LTR => Logical RTL */\r
+ {LTR, VISUAL, RTL, LOGICAL, SHAPE_LOGICAL, SHAPE_VISUAL, RTL,\r
+ {action_shapeArabic, action_setInverse, action_resolve, action_reorder, NULL}},\r
+ /* 5: Visual RTL => Logical RTL */\r
+ {RTL, VISUAL, RTL, LOGICAL, SHAPE_LOGICAL, SHAPE_VISUAL, RTL,\r
+ {action_reverse, action_shapeArabic, action_setInverse, action_resolve, action_reorder, NULL}},\r
+ /* 6: Visual LTR => Logical LTR */\r
+ {LTR, VISUAL, LTR, LOGICAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_setInverse, action_resolve, action_reorder, action_shapeArabic, NULL}},\r
+ /* 7: Visual RTL => Logical LTR */\r
+ {RTL, VISUAL, LTR, LOGICAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_reverse, action_setInverse, action_resolve, action_reorder, action_shapeArabic, NULL}},\r
+ /* 8: Logical LTR => Logical RTL */\r
+ {LTR, LOGICAL, RTL, LOGICAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_shapeArabic, action_resolve, action_mirror, action_setRunsOnly, action_resolve, action_reorder, NULL}},\r
+ /* 9: Logical RTL => Logical LTR */\r
+ {RTL, LOGICAL, LTR, LOGICAL, SHAPE_LOGICAL, SHAPE_LOGICAL, RTL,\r
+ {action_resolve, action_mirror, action_setRunsOnly, action_resolve, action_reorder, action_shapeArabic, NULL}},\r
+ /* 10: Visual LTR => Visual RTL */\r
+ {LTR, VISUAL, RTL, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, LTR,\r
+ {action_shapeArabic, action_setInverse, action_resolve, action_mirror, action_reverse, NULL}},\r
+ /* 11: Visual RTL => Visual LTR */\r
+ {RTL, VISUAL, LTR, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, LTR,\r
+ {action_reverse, action_shapeArabic, action_setInverse, action_resolve, action_mirror, NULL}},\r
+ /* 12: Logical LTR => Logical LTR */\r
+ {LTR, LOGICAL, LTR, LOGICAL, SHAPE_LOGICAL, SHAPE_LOGICAL, LTR,\r
+ {action_resolve, action_mirror, action_shapeArabic, NULL}},\r
+ /* 13: Logical RTL => Logical RTL */\r
+ {RTL, LOGICAL, RTL, LOGICAL, SHAPE_VISUAL, SHAPE_LOGICAL, RTL,\r
+ {action_resolve, action_mirror, action_shapeArabic, NULL}},\r
+ /* 14: Visual LTR => Visual LTR */\r
+ {LTR, VISUAL, LTR, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, LTR,\r
+ {action_resolve, action_mirror, action_shapeArabic, NULL}},\r
+ /* 15: Visual RTL => Visual RTL */\r
+ {RTL, VISUAL, RTL, VISUAL, SHAPE_LOGICAL, SHAPE_VISUAL, LTR,\r
+ {action_reverse, action_resolve, action_mirror, action_shapeArabic, action_reverse, NULL}}\r
+};\r
+\r
+static const uint32_t nSchemes = sizeof(Schemes) / sizeof(*Schemes);\r
+\r
+/**\r
+ * When the direction option is <code>UBIDI_DEFAULT_LTR</code> or\r
+ * <code>UBIDI_DEFAULT_RTL</code>, resolve the base direction according to that\r
+ * of the first strong bidi character.\r
+ */\r
+static void\r
+resolveBaseDirection(const UChar *text, uint32_t length,\r
+ UBiDiLevel *pInLevel, UBiDiLevel *pOutLevel)\r
+{\r
+ switch (*pInLevel) {\r
+ case UBIDI_DEFAULT_LTR:\r
+ case UBIDI_DEFAULT_RTL: {\r
+ UBiDiLevel level = ubidi_getBaseDirection(text, length);\r
+ *pInLevel = level != UBIDI_NEUTRAL ? level\r
+ : *pInLevel == UBIDI_DEFAULT_RTL ? RTL : LTR;\r
+ break;\r
+ }\r
+ default:\r
+ *pInLevel &= 1;\r
+ break;\r
+ }\r
+ switch (*pOutLevel) {\r
+ case UBIDI_DEFAULT_LTR:\r
+ case UBIDI_DEFAULT_RTL:\r
+ *pOutLevel = *pInLevel;\r
+ break;\r
+ default:\r
+ *pOutLevel &= 1;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ * Finds a valid <code>ReorderingScheme</code> matching the\r
+ * caller-defined scheme.\r
+ * \r
+ * @return A valid <code>ReorderingScheme</code> object or NULL\r
+ */\r
+static const ReorderingScheme*\r
+findMatchingScheme(UBiDiLevel inLevel, UBiDiLevel outLevel,\r
+ UBiDiOrder inOrder, UBiDiOrder outOrder)\r
+{\r
+ uint32_t i;\r
+ for (i = 0; i < nSchemes; i++) {\r
+ const ReorderingScheme *pScheme = Schemes + i;\r
+ if (inLevel == pScheme->inLevel && outLevel == pScheme->outLevel\r
+ && inOrder == pScheme->inOrder && outOrder == pScheme->outOrder) {\r
+ return pScheme;\r
+ }\r
+ }\r
+ return NULL;\r
+}\r
+\r
+U_DRAFT uint32_t U_EXPORT2\r
+ubiditransform_transform(UBiDiTransform *pBiDiTransform,\r
+ const UChar *src, int32_t srcLength,\r
+ UChar *dest, int32_t destSize,\r
+ UBiDiLevel inParaLevel, UBiDiOrder inOrder,\r
+ UBiDiLevel outParaLevel, UBiDiOrder outOrder,\r
+ UBiDiMirroring doMirroring, uint32_t shapingOptions,\r
+ UErrorCode *pErrorCode)\r
+{\r
+ uint32_t destLength = 0;\r
+ UBool textChanged = FALSE;\r
+ const UBiDiTransform *pOrigTransform = pBiDiTransform;\r
+ const UBiDiAction *action = NULL;\r
+\r
+ if (U_FAILURE(*pErrorCode)) {\r
+ return 0;\r
+ }\r
+ if (src == NULL || dest == NULL) {\r
+ *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;\r
+ return 0;\r
+ }\r
+ CHECK_LEN(src, srcLength, pErrorCode);\r
+ CHECK_LEN(dest, destSize, pErrorCode);\r
+\r
+ if (pBiDiTransform == NULL) {\r
+ pBiDiTransform = ubiditransform_open(pErrorCode);\r
+ if (U_FAILURE(*pErrorCode)) {\r
+ return 0;\r
+ }\r
+ }\r
+ /* Current limitation: in multiple paragraphs will be resolved according\r
+ to the 1st paragraph */\r
+ resolveBaseDirection(src, srcLength, &inParaLevel, &outParaLevel);\r
+\r
+ pBiDiTransform->pActiveScheme = findMatchingScheme(inParaLevel, outParaLevel,\r
+ inOrder, outOrder);\r
+ if (pBiDiTransform->pActiveScheme == NULL || pBiDiTransform->pActiveScheme->actions == NULL) {\r
+ goto cleanup;\r
+ }\r
+ pBiDiTransform->reorderingOptions = doMirroring ? UBIDI_DO_MIRRORING\r
+ : UBIDI_REORDER_DEFAULT;\r
+\r
+ /* Ignore TEXT_DIRECTION_* flags, as we apply our own depending on the text\r
+ scheme at the time shaping is invoked. */\r
+ shapingOptions &= ~U_SHAPE_TEXT_DIRECTION_MASK;\r
+ pBiDiTransform->digits = shapingOptions & ~U_SHAPE_LETTERS_MASK;\r
+ pBiDiTransform->letters = shapingOptions & ~U_SHAPE_DIGITS_MASK;\r
+\r
+ updateSrc(pBiDiTransform, src, srcLength, destSize > srcLength ? destSize : srcLength, pErrorCode);\r
+ if (U_FAILURE(*pErrorCode)) {\r
+ goto cleanup;\r
+ }\r
+ if (pBiDiTransform->pBidi == NULL) {\r
+ pBiDiTransform->pBidi = ubidi_openSized(0, 0, pErrorCode);\r
+ if (U_FAILURE(*pErrorCode)) {\r
+ goto cleanup;\r
+ }\r
+ }\r
+ pBiDiTransform->dest = dest;\r
+ pBiDiTransform->destSize = destSize;\r
+ pBiDiTransform->pDestLength = &destLength;\r
+\r
+ /* Checking for U_SUCCESS() within the loop to bail out on first failure. */\r
+ for (action = pBiDiTransform->pActiveScheme->actions; *action && U_SUCCESS(*pErrorCode); action++) {\r
+ if ((*action)(pBiDiTransform, pErrorCode)) {\r
+ if (action + 1) {\r
+ updateSrc(pBiDiTransform, pBiDiTransform->dest, *pBiDiTransform->pDestLength,\r
+ *pBiDiTransform->pDestLength, pErrorCode);\r
+ }\r
+ textChanged = TRUE;\r
+ }\r
+ }\r
+ ubidi_setInverse(pBiDiTransform->pBidi, FALSE);\r
+\r
+ if (!textChanged && U_SUCCESS(*pErrorCode)) {\r
+ /* Text was not changed - just copy src to dest */\r
+ if (destSize < srcLength) {\r
+ *pErrorCode = U_BUFFER_OVERFLOW_ERROR;\r
+ } else {\r
+ u_strncpy(dest, src, srcLength);\r
+ destLength = srcLength;\r
+ }\r
+ }\r
+cleanup:\r
+ if (pOrigTransform != pBiDiTransform) {\r
+ ubiditransform_close(pBiDiTransform);\r
+ } else {\r
+ pBiDiTransform->dest = NULL;\r
+ pBiDiTransform->pDestLength = NULL;\r
+ pBiDiTransform->srcLength = 0;\r
+ pBiDiTransform->destSize = 0;\r
+ }\r
+ return U_FAILURE(*pErrorCode) ? 0 : destLength;\r
+}\r
--- /dev/null
+/*\r
+******************************************************************************\r
+*\r
+* Copyright (C) 2016 and later: Unicode, Inc. and others.\r
+* License & terms of use: http://www.unicode.org/copyright.html\r
+*\r
+******************************************************************************\r
+* file name: ubiditransform.h\r
+* encoding: US-ASCII\r
+* tab size: 8 (not used)\r
+* indentation:4\r
+*\r
+* created on: 2016jul24\r
+* created by: Lina Kemmel\r
+*\r
+*/\r
+\r
+#ifndef UBIDITRANSFORM_H\r
+#define UBIDITRANSFORM_H\r
+\r
+#include "unicode/uchar.h"\r
+#include "unicode/localpointer.h"\r
+\r
+/**\r
+ * <code>UBiDiOrder</code> indicates the order of text.<p>\r
+ * This bidi transformation engine supports all possible combinations (4 in\r
+ * total) of input and output text order:\r
+ * <ul>\r
+ * <li><logical input, visual output>: unless the output direction is RTL, this\r
+ * corresponds to a normal operation of the Bidi algorithm as described in the\r
+ * Unicode Technical Report and implemented by <code>UBiDi</code> when the\r
+ * reordering mode is set to <code>UBIDI_REORDER_DEFAULT</code>. Visual RTL\r
+ * mode is not supported by <code>UBiDi</code> and is accomplished through\r
+ * reversing a visual LTR string,</li>\r
+ * <li><visual input, logical output>: unless the input direction is RTL, this\r
+ * corresponds to an "inverse bidi algorithm" in <code>UBiDi</code> with the\r
+ * reordering mode set to <code>UBIDI_REORDER_INVERSE_LIKE_DIRECT</code>.\r
+ * Visual RTL mode is not not supported by <code>UBiDi</code> and is\r
+ * accomplished through reversing a visual LTR string,</li>\r
+ * <li><logical input, logical output>: if the input and output base directions\r
+ * mismatch, this corresponds to the <code>UBiDi</code> implementation with the\r
+ * reordering mode set to <code>UBIDI_REORDER_RUNS_ONLY</code>; and if the\r
+ * input and output base directions are identical, the transformation engine\r
+ * will only handle character mirroring and Arabic shaping operations without\r
+ * reordering,</li>\r
+ * <li><visual input, visual output>: this reordering mode is not supported by\r
+ * the <code>UBiDi</code> engine; it implies character mirroring, Arabic\r
+ * shaping, and - if the input/output base directions mismatch - string\r
+ * reverse operations.</li>\r
+ * </ul>\r
+ * @see ubidi_setInverse\r
+ * @see ubidi_setReorderingMode\r
+ * @see UBIDI_REORDER_DEFAULT\r
+ * @see UBIDI_REORDER_INVERSE_LIKE_DIRECT\r
+ * @see UBIDI_REORDER_RUNS_ONLY\r
+ * @draft ICU 58\r
+ */\r
+typedef enum {\r
+ /** 0: Constant indicating a logical order.\r
+ * This is the default for input text.\r
+ * @draft ICU 58\r
+ */\r
+ UBIDI_LOGICAL = 0,\r
+ /** 1: Constant indicating a visual order.\r
+ * This is a default for output text.\r
+ * @draft ICU 58\r
+ */\r
+ UBIDI_VISUAL\r
+} UBiDiOrder;\r
+\r
+/**\r
+ * <code>UBiDiMirroring</code> indicates whether or not characters with the\r
+ * "mirrored" property in RTL runs should be replaced with their mirror-image\r
+ * counterparts.\r
+ * @see UBIDI_DO_MIRRORING\r
+ * @see ubidi_setReorderingOptions\r
+ * @see ubidi_writeReordered\r
+ * @see ubidi_writeReverse\r
+ * @draft ICU 58\r
+ */\r
+typedef enum {\r
+ /** 0: Constant indicating that character mirroring should not be\r
+ * performed.\r
+ * This is the default.\r
+ * @draft ICU 58\r
+ */\r
+ UBIDI_MIRRORING_OFF = 0,\r
+ /** 1: Constant indicating that character mirroring should be performed.\r
+ * This corresponds to calling <code>ubidi_writeReordered</code> or\r
+ * <code>ubidi_writeReverse</code> with the\r
+ * <code>UBIDI_DO_MIRRORING</code> option bit set.\r
+ * @draft ICU 58\r
+ */\r
+ UBIDI_MIRRORING_ON\r
+} UBiDiMirroring;\r
+\r
+/**\r
+ * Forward declaration of the <code>UBiDiTransform</code> structure that stores\r
+ * information used by the layout transformation engine.\r
+ * @draft ICU 58\r
+ */\r
+typedef struct UBiDiTransform UBiDiTransform;\r
+\r
+/**\r
+ * Performs transformation of text from the bidi layout defined by the input\r
+ * ordering scheme to the bidi layout defined by the output ordering scheme,\r
+ * and applies character mirroring and Arabic shaping operations.<p>\r
+ * In terms of <code>UBiDi</code>, such a transformation implies:\r
+ * <li>calling <code>ubidi_setReorderingMode</code> as needed (when the\r
+ * reordering mode is other than normal),</li>\r
+ * <li>calling <code>ubidi_setInverse</code> as needed (when text should be\r
+ * transformed from a visual to a logical form),</li>\r
+ * <li>resolving embedding levels of each character in the input text by\r
+ * calling <code>ubidi_setPara</code>,</li>\r
+ * <li>reordering the characters based on the computed embedding levels, also\r
+ * performing character mirroring as needed, and streaming the result to the\r
+ * output, by calling <code>ubidi_writeReordered</code>,</li>\r
+ * <li>performing Arabic digit and letter shaping on the output text by calling\r
+ * <code>u_shapeArabic</code>.</li>\r
+ * </ul>\r
+ * An "ordering scheme" encompasses the base direction and the order of text,\r
+ * and these characteristics must be defined by the caller for both input and\r
+ * output explicitly .<p>\r
+ * There are 36 possible combinations of <input, output> ordering schemes,\r
+ * which are partially supported by <code>UBiDi</code> already. Examples of the\r
+ * currently supported combinations:\r
+ * <ul>\r
+ * <li><Logical LTR, Visual LTR>: this is equivalent to calling\r
+ * <code>ubidi_setPara</code> with <code>paraLevel == UBIDI_LTR</code>,</li>\r
+ * <li><Logical RTL, Visual LTR>: this is equivalent to calling\r
+ * <code>ubidi_setPara</code> with <code>paraLevel == UBIDI_RTL</code>,</li>\r
+ * <li><Logical Default ("Auto") LTR, Visual LTR>: this is equivalent to\r
+ * calling <code>ubidi_setPara</code> with \r
+ * <code>paraLevel == UBIDI_DEFAULT_LTR</code>,</li>\r
+ * <li><Logical Default ("Auto") RTL, Visual LTR>: this is equivalent to\r
+ * calling <code>ubidi_setPara</code> with\r
+ * <code>paraLevel == UBIDI_DEFAULT_RTL</code>,</li>\r
+ * <li><Visual LTR, Logical LTR>: this is equivalent to\r
+ * calling <code>ubidi_setInverse(UBiDi*, TRUE)</code> and then\r
+ * <code>ubidi_setPara</code> with <code>paraLevel == UBIDI_LTR</code>,</li>\r
+ * <li><Visual LTR, Logical RTL>: this is equivalent to\r
+ * calling <code>ubidi_setInverse(UBiDi*, TRUE)</code> and then\r
+ * <code>ubidi_setPara</code> with <code>paraLevel == UBIDI_RTL</code>.</li>\r
+ * </ul>\r
+ * All combinations that involve the Visual RTL scheme are unsupported by\r
+ * <code>UBiDi</code>, for instance:\r
+ * <ul>\r
+ * <li><Logical LTR, Visual RTL>,</li>\r
+ * <li><Visual RTL, Logical RTL>.</li>\r
+ * </ul>\r
+ * <p>Example of usage of the transformation engine:<br>\r
+ * <pre>\r
+ * \code\r
+ * UChar text1[] = {'a', 'b', 'c', 0x0625, '1', 0};\r
+ * UChar text2[] = {'a', 'b', 'c', 0x0625, '1', 0};\r
+ * UErrorCode errorCode = U_ZERO_ERROR;\r
+ * // Run a transformation.\r
+ * ubiditransform_transform(pBidiTransform,\r
+ * text1, -1, text2, -1,\r
+ * UBIDI_LTR, UBIDI_VISUAL,\r
+ * UBIDI_RTL, UBIDI_LOGICAL,\r
+ * UBIDI_MIRRORING_OFF,\r
+ * U_SHAPE_DIGITS_AN2EN | U_SHAPE_DIGIT_TYPE_AN_EXTENDED,\r
+ * &errorCode);\r
+ * // Do something with text2.\r
+ * text2[4] = '2';\r
+ * // Run a reverse transformation.\r
+ * ubiditransform_transform(pBidiTransform,\r
+ * text2, -1, text1, -1,\r
+ * UBIDI_RTL, UBIDI_LOGICAL,\r
+ * UBIDI_LTR, UBIDI_VISUAL,\r
+ * UBIDI_MIRRORING_OFF,\r
+ * U_SHAPE_DIGITS_EN2AN | U_SHAPE_DIGIT_TYPE_AN_EXTENDED,\r
+ * &errorCode);\r
+ *\endcode\r
+ * </pre>\r
+ * </p>\r
+ *\r
+ * @param pBiDiTransform A pointer to a <code>UBiDiTransform</code> object\r
+ * allocated with <code>ubiditransform_open()</code> or\r
+ * <code>NULL</code>.<p>\r
+ * This object serves for one-time setup to amortize initialization\r
+ * overheads. Use of this object is not thread-safe. All other threads\r
+ * should allocate a new <code>UBiDiTransform</code> object by calling\r
+ * <code>ubiditransform_open()</code> before using it. Alternatively,\r
+ * a caller can set this parameter to <code>NULL</code>, in which case\r
+ * the object will be allocated by the engine on the fly.</p>\r
+ * @param src A pointer to the text that the Bidi layout transformations will\r
+ * be performed on.\r
+ * <p><strong>Note:</strong> the text must be (at least)\r
+ * <code>srcLength</code> long.</p>\r
+ * @param srcLength The length of the text, in number of UChars. If\r
+ * <code>length == -1</code> then the text must be zero-terminated.\r
+ * @param dest A pointer to where the processed text is to be copied.\r
+ * @param destSize The size of the <code>dest</code> buffer, in number of\r
+ * UChars. If the <code>U_SHAPE_LETTERS_UNSHAPE</code> option is set,\r
+ * then the destination length could be as large as\r
+ * <code>srcLength * 2</code>. Otherwise, the destination length will\r
+ * not exceed <code>srcLength</code>. If the caller reserves the last\r
+ * position for zero-termination, it should be excluded from\r
+ * <code>destSize</code>.\r
+ * <p><code>destSize == -1</code> is allowed and makes sense when\r
+ * <code>dest</code> was holds some meaningful value, e.g. that of\r
+ * <code>src</code>. In this case <code>dest</code> must be\r
+ * zero-terminated.</p>\r
+ * @param inParaLevel A base embedding level of the input as defined in\r
+ * <code>ubidi_setPara</code> documentation for the\r
+ * <code>paraLevel</code> parameter.\r
+ * @param inOrder An order of the input, which can be one of the\r
+ * <code>UBiDiOrder</code> values.\r
+ * @param outParaLevel A base embedding level of the output as defined in\r
+ * <code>ubidi_setPara</code> documentation for the\r
+ * <code>paraLevel</code> parameter.\r
+ * @param outOrder An order of the output, which can be one of the\r
+ * <code>UBiDiOrder</code> values.\r
+ * @param doMirroring Indicates whether or not to perform character mirroring,\r
+ * and can accept one of the <code>UBiDiMirroring</code> values.\r
+ * @param shapingOptions Arabic digit and letter shaping options defined in the\r
+ * ushape.h documentation.\r
+ * <p><strong>Note:</strong> Direction indicator options are computed by\r
+ * the transformation engine based on the effective ordering schemes, so\r
+ * user-defined direction indicators will be ignored.</p>\r
+ * @param pErrorCode A pointer to an error code value.\r
+ *\r
+ * @return The destination length, i.e. the number of UChars written to\r
+ * <code>dest</code>. If the transformation fails, the return value\r
+ * will be 0 (and the error code will be written to\r
+ * <code>pErrorCode</code>).\r
+ *\r
+ * @see UBiDiLevel\r
+ * @see UBiDiOrder\r
+ * @see UBiDiMirroring\r
+ * @see ubidi_setPara\r
+ * @see u_shapeArabic\r
+ * @draft ICU 58\r
+ */\r
+U_DRAFT uint32_t U_EXPORT2\r
+ubiditransform_transform(UBiDiTransform *pBiDiTransform,\r
+ const UChar *src, int32_t srcLength,\r
+ UChar *dest, int32_t destSize,\r
+ UBiDiLevel inParaLevel, UBiDiOrder inOrder,\r
+ UBiDiLevel outParaLevel, UBiDiOrder outOrder,\r
+ UBiDiMirroring doMirroring, uint32_t shapingOptions,\r
+ UErrorCode *pErrorCode);\r
+\r
+/**\r
+ * Allocates a <code>UBiDiTransform</code> object. This object can be reused,\r
+ * e.g. with different ordering schemes, mirroring or shaping options.<p>\r
+ * <strong>Note:</strong>The object can only be reused in the same thread.\r
+ * All other threads should allocate a new <code>UBiDiTransform</code> object\r
+ * before using it.<p>\r
+ * Example of usage:<p>\r
+ * <pre>\r
+ * \code\r
+ * UErrorCode errorCode = U_ZERO_ERROR;\r
+ * // Open a new UBiDiTransform.\r
+ * UBiDiTransform* transform = ubiditransform_open(&errorCode);\r
+ * // Run a transformation.\r
+ * ubiditransform_transform(transform,\r
+ * text1, -1, text2, -1,\r
+ * UBIDI_RTL, UBIDI_LOGICAL,\r
+ * UBIDI_LTR, UBIDI_VISUAL,\r
+ * UBIDI_MIRRORING_ON,\r
+ * U_SHAPE_DIGITS_EN2AN,\r
+ * &errorCode);\r
+ * // Do something with the output text and invoke another transformation using\r
+ * // that text as input.\r
+ * ubiditransform_transform(transform,\r
+ * text2, -1, text3, -1,\r
+ * UBIDI_LTR, UBIDI_VISUAL,\r
+ * UBIDI_RTL, UBIDI_VISUAL,\r
+ * UBIDI_MIRRORING_ON,\r
+ * 0, &errorCode);\r
+ *\endcode\r
+ * </pre>\r
+ * <p>\r
+ * The <code>UBiDiTransform</code> object must be deallocated by calling\r
+ * <code>ubiditransform_close()</code>.\r
+ *\r
+ * @return An empty <code>UBiDiTransform</code> object.\r
+ * @draft ICU 58\r
+ */\r
+U_DRAFT UBiDiTransform* U_EXPORT2\r
+ubiditransform_open(UErrorCode *pErrorCode);\r
+\r
+/**\r
+ * Deallocates the given <code>UBiDiTransform</code> object.\r
+ * @draft ICU 58\r
+ */\r
+U_DRAFT void U_EXPORT2\r
+ubiditransform_close(UBiDiTransform *pBidiTransform);\r
+\r
+#if U_SHOW_CPLUSPLUS_API\r
+\r
+U_NAMESPACE_BEGIN\r
+\r
+/**\r
+ * \class LocalUBiDiTransformPointer\r
+ * "Smart pointer" class, closes a UBiDiTransform via ubiditransform_close().\r
+ * For most methods see the LocalPointerBase base class.\r
+ *\r
+ * @see LocalPointerBase\r
+ * @see LocalPointer\r
+ * @draft ICU 58\r
+ */\r
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUBiDiTransformPointer, UBiDiTransform, ubiditransform_close);\r
+\r
+U_NAMESPACE_END\r
+\r
+#endif\r
+\r
+#endif\r
idnatest.o nfsprep.o spreptst.o sprpdata.o \
hpmufn.o tracetst.o reapits.o uregiontest.o ulistfmttest.o\
utexttst.o ucsdetst.o spooftest.o \
+cbiditransformtst.o \
cgendtst.o
DEPS = $(OBJECTS:.o=.d)
void addConvert(TestNode** root);
void addCollTest(TestNode** root);
void addComplexTest(TestNode** root);
+void addBidiTransformTest(TestNode** root);
void addUDataTest(TestNode** root);
void addUTF16Test(TestNode** root);
void addUTF8Test(TestNode** root);
addStandardNamesTest(root);
addUCsdetTest(root);
addComplexTest(root);
+ addBidiTransformTest(root);
addUSetTest(root);
#if !UCONFIG_NO_IDNA
addUStringPrepTest(root);
--- /dev/null
+/********************************************************************\r
+ * Copyright (C) 2016 and later: Unicode, Inc. and others.\r
+ * License & terms of use: http://www.unicode.org/copyright.html\r
+ ********************************************************************/\r
+/* file name: cbiditransformtst.c\r
+ * encoding: US-ASCII\r
+ * tab size: 8 (not used)\r
+ * indentation:4\r
+ *\r
+ * created on: 2016aug21\r
+ * created by: Lina Kemmel\r
+*/\r
+\r
+#include "cintltst.h"\r
+#include "unicode/ubidi.h"\r
+#include "unicode/ubiditransform.h"\r
+#include "unicode/ushape.h"\r
+#include "unicode/ustring.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define LATN_ZERO 0x0030\r
+#define ARAB_ZERO 0x0660\r
+#define MIN_HEB_LETTER 0x05D0\r
+#define MIN_ARAB_LETTER 0x0630\r
+#define MIN_SHAPED_LETTER 0xFEAB\r
+\r
+#define STR_CAPACITY 100\r
+\r
+typedef struct {\r
+ UBiDiLevel inLevel;\r
+ UBiDiOrder inOr;\r
+ UBiDiLevel outLevel;\r
+ UBiDiOrder outOr;\r
+ const char *pReorderNoMirror;\r
+ const char *pReorderAndMirror;\r
+ const char *pContextShapes;\r
+ const char *pMessage;\r
+} UBidiTestCases;\r
+\r
+UChar src[STR_CAPACITY] = { 0 };\r
+UChar dest[STR_CAPACITY] = { 0 };\r
+UChar expected[STR_CAPACITY] = { 0 };\r
+UChar temp[STR_CAPACITY * 2] = { 0 };\r
+char pseudo[STR_CAPACITY] = { 0 };\r
+\r
+void addBidiTransformTest(TestNode** root);\r
+\r
+static void testAutoDirection(void);\r
+\r
+static void testAllTransformOptions(void);\r
+\r
+static char* pseudoScript(const UChar *str);\r
+\r
+static void shapeDigits(UChar *str, uint32_t digits);\r
+\r
+static void logResultsForDir(const UChar *srcText, const UChar *destTxt,\r
+ const UChar *expectedTxt, UBiDiLevel inLevel, UBiDiLevel outLevel);\r
+\r
+static void verifyResultsForAllOpt(const UBidiTestCases *pTest, const UChar *srcTxt,\r
+ const UChar *destTxt, const char *expectedChars, uint32_t digits,\r
+ uint32_t letters);\r
+\r
+#if 0\r
+static void substituteByPseudoChar(const UChar *src, char *dest,\r
+ const UChar baseReal, const char basePseudo, const char max);\r
+\r
+\r
+/* TODO: This code assumes the codepage is ASCII based. */\r
+\r
+/*\r
+ * Using the following conventions:\r
+ * AL unshaped: A-E\r
+ * AL shaped: F-J\r
+ * R: K-Z\r
+ * EN: 0-4\r
+ * AN: 5-9\r
+*/\r
+static void\r
+substituteByPseudoChar(const UChar *src, char *dest, const UChar baseReal,\r
+ const char basePseudo, const char max) {\r
+ *dest = basePseudo + (*src - baseReal); /* (range math won't work on EBCDIC) */\r
+ if (*dest > max) {\r
+ *dest = max;\r
+ }\r
+}\r
+\r
+static char*\r
+pseudoScript(const UChar *str) {\r
+ char *p;\r
+ if (!str) {\r
+ return "\0";\r
+ }\r
+ for (p = pseudo; *str; str++, p++) {\r
+ switch (u_charDirection(*str)) {\r
+ case U_RIGHT_TO_LEFT:\r
+ substituteByPseudoChar(str, p, MIN_HEB_LETTER, 'K', 'Z');\r
+ break;\r
+ case U_RIGHT_TO_LEFT_ARABIC:\r
+ if (*str > 0xFE00) {\r
+ substituteByPseudoChar(str, p, MIN_SHAPED_LETTER, 'F', 'J');\r
+ } else {\r
+ substituteByPseudoChar(str, p, MIN_ARAB_LETTER, 'A', 'E');\r
+ }\r
+ break;\r
+ case U_ARABIC_NUMBER:\r
+ substituteByPseudoChar(str, p, ARAB_ZERO, '5', '9');\r
+ break;\r
+ default:\r
+ *p = (char)*str;\r
+ break;\r
+ }\r
+ }\r
+ *p = '\0';\r
+ return pseudo;\r
+}\r
+#else\r
+static char*\r
+pseudoScript(const UChar *str) {\r
+ return aescstrdup(str, -1);\r
+}\r
+#endif\r
+\r
+static void\r
+logResultsForDir(const UChar *srcTxt, const UChar *destTxt, const UChar *expectedTxt,\r
+ UBiDiLevel inLevel, UBiDiLevel outLevel)\r
+{\r
+ if (u_strcmp(expectedTxt, destTxt)) {\r
+ log_err("Unexpected transform Dest: inLevel: 0x%02x; outLevel: 0x%02x;\ninText: %s; outText: %s; expected: %s\n",\r
+ inLevel, outLevel, pseudoScript(srcTxt), pseudoScript(destTxt), pseudoScript(expectedTxt));\r
+ }\r
+}\r
+\r
+/**\r
+ * Tests various combinations of base directions, with the input either\r
+ * <code>UBIDI_DEFAULT_LTR</code> or <code>UBIDI_DEFAULT_RTL</code>, and the\r
+ * output either <code>UBIDI_LTR</code> or <code>UBIDI_RTL</code>. Order is\r
+ * always <code>UBIDI_LOGICAL</code> for the input and <code>UBIDI_VISUAL</code>\r
+ * for the output.\r
+ */\r
+static void\r
+testAutoDirection(void)\r
+{\r
+ static const UBiDiLevel inLevels[] = {\r
+ UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL\r
+ };\r
+ static const UBiDiLevel outLevels[] = {\r
+ UBIDI_LTR, UBIDI_RTL\r
+ };\r
+ static const char *srcTexts[] = {\r
+ "abc \\u05d0\\u05d1\0",\r
+ "... abc \\u05d0\\u05d1\0",\r
+ "\\u05d0\\u05d1 abc\0",\r
+ "... \\u05d0\\u05d1 abc\0",\r
+ ".*:"\r
+ };\r
+ uint32_t nTexts = sizeof(srcTexts) / sizeof(srcTexts[0]);\r
+ uint32_t i, nInLevels = sizeof(inLevels) / sizeof(inLevels[0]);\r
+ uint32_t j, nOutLevels = sizeof(outLevels) / sizeof(outLevels[0]);\r
+\r
+ UBiDi *pBidi = ubidi_open();\r
+\r
+ UErrorCode errorCode = U_ZERO_ERROR;\r
+ UBiDiTransform *pTransform = ubiditransform_open(&errorCode);\r
+\r
+ while (nTexts-- > 0) {\r
+ uint32_t srcLen;\r
+ u_unescape(srcTexts[nTexts], src, STR_CAPACITY);\r
+ srcLen = u_strlen(src);\r
+ for (i = 0; i < nInLevels; i++) {\r
+ for (j = 0; j < nOutLevels; j++) {\r
+ ubiditransform_transform(pTransform, src, -1, dest, STR_CAPACITY - 1,\r
+ inLevels[i], UBIDI_LOGICAL, outLevels[j], UBIDI_VISUAL,\r
+ UBIDI_MIRRORING_OFF, 0, &errorCode);\r
+ /* Use UBiDi as a model we compare to */\r
+ ubidi_setPara(pBidi, src, srcLen, inLevels[i], NULL, &errorCode);\r
+ ubidi_writeReordered(pBidi, expected, STR_CAPACITY, UBIDI_REORDER_DEFAULT, &errorCode);\r
+ if (outLevels[j] == UBIDI_RTL) {\r
+ ubidi_writeReverse(expected, u_strlen(expected), temp, STR_CAPACITY,\r
+ UBIDI_OUTPUT_REVERSE, &errorCode);\r
+ logResultsForDir(src, dest, temp, inLevels[i], outLevels[j]);\r
+ } else {\r
+ logResultsForDir(src, dest, expected, inLevels[i], outLevels[j]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ ubidi_close(pBidi);\r
+ ubiditransform_close(pTransform);\r
+}\r
+\r
+static void\r
+shapeDigits(UChar *str, uint32_t digits)\r
+{\r
+ const UChar srcZero = (digits & U_SHAPE_DIGITS_EN2AN) ? LATN_ZERO : ARAB_ZERO;\r
+ const UChar extent = srcZero == ARAB_ZERO ? LATN_ZERO - ARAB_ZERO : ARAB_ZERO - LATN_ZERO;\r
+ UChar32 c = 0;\r
+ uint32_t i = 0, j, length = u_strlen(str);\r
+ while (i < length) {\r
+ j = i;\r
+ U16_NEXT(str, i, length, c); \r
+ if (c >= srcZero && c <= srcZero + 9) {\r
+ /* length of c here is always a single UChar16 */\r
+ str[j] = c + extent;\r
+ }\r
+ }\r
+}\r
+\r
+static void\r
+verifyResultsForAllOpt(const UBidiTestCases *pTest, const UChar *srcTxt,\r
+ const UChar *destTxt, const char *expectedChars, uint32_t digits, uint32_t letters)\r
+{\r
+ switch (digits) {\r
+ case U_SHAPE_DIGITS_EN2AN:\r
+ case U_SHAPE_DIGITS_AN2EN:\r
+ u_unescape(expectedChars, expected, STR_CAPACITY);\r
+ shapeDigits(expected, digits);\r
+ break;\r
+ case U_SHAPE_DIGITS_ALEN2AN_INIT_LR:\r
+ u_unescape(pTest->pContextShapes, expected, STR_CAPACITY);\r
+ break;\r
+ case U_SHAPE_DIGITS_NOOP:\r
+ u_unescape(expectedChars, expected, STR_CAPACITY);\r
+ break;\r
+ }\r
+ if (letters & U_SHAPE_LETTERS_SHAPE) {\r
+ uint32_t i = 0, j, length = u_strlen(expected);\r
+ UChar32 c = 0;\r
+ while (i < length) {\r
+ j = i;\r
+ U16_NEXT(expected, i, length, c); \r
+ /* below the length of old and new values is always a single\r
+ UChar16, so can just assign a new value to expected[j] */\r
+ if (c == 0x0630) {\r
+ expected[j] = 0xfeab;\r
+ } else if (c == 0x0631) {\r
+ expected[j] = 0xfead;\r
+ } else if (c == 0x0632) {\r
+ expected[j] = 0xfeaf;\r
+ }\r
+ }\r
+ }\r
+ if (u_strcmp(expected, dest)) {\r
+ log_err("Unexpected transform Dest: Test: %s; Digits: 0x%08x; Letters: 0x%08x\ninText: %s; outText: %s; expected: %s\n",\r
+ pTest->pMessage, digits, letters, pseudoScript(srcTxt), pseudoScript(destTxt), pseudoScript(expected));\r
+ }\r
+}\r
+\r
+/**\r
+ * This function covers:\r
+ * <ul>\r
+ * <li>all possible combinations of ordering schemes and <strong>explicit</strong>\r
+ * base directions, applied to both input and output,</li>\r
+ * <li>selected tests for auto direction (systematically, auto direction is\r
+ * covered in a dedicated test) applied on both input and output,</li>\r
+ * <li>all possible combinations of mirroring, digits and letters applied\r
+ * to output only.</li>\r
+ * </ul>\r
+ */\r
+static void\r
+testAllTransformOptions(void)\r
+{\r
+ static const char *inText =\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662\0";\r
+\r
+ static const UBidiTestCases testCases[] = {\r
+ { UBIDI_LTR, UBIDI_LOGICAL,\r
+ UBIDI_LTR, UBIDI_LOGICAL,\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662\0", // reordering no mirroring\r
+ "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662", // mirroring\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u0662\\u0663\\u0660 e\\u0631\\u0664 f \\u0632 \\u0661\\u0662", // context numeric shaping\r
+ "1: Logical LTR ==> Logical LTR" },\r
+ { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "2: Logical LTR ==> Visual LTR" },\r
+ { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_LOGICAL,\r
+ "\\u0632 \\u0661\\u0662 f \\u0631e4 \\u0630 23\\u0660 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 a[b]c",\r
+ "\\u0632 \\u0661\\u0662 f \\u0631e4 \\u0630 23\\u0660 d \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 a[b]c",\r
+ "\\u0632 \\u0661\\u0662 f \\u0631e\\u0664 \\u0630 \\u0662\\u0663\\u0660 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 a[b]c",\r
+ "3: Logical LTR ==> Logical RTL" },\r
+ { UBIDI_LTR, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_VISUAL,\r
+ "\\u0632 \\u0662\\u0661 f \\u06314e \\u0630 \\u066032 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 c]b[a",\r
+ "\\u0632 \\u0662\\u0661 f \\u06314e \\u0630 \\u066032 d \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 c]b[a",\r
+ "\\u0632 \\u0662\\u0661 f \\u0631\\u0664e \\u0630 \\u0660\\u0663\\u0662 d \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 c]b[a",\r
+ "4: Logical LTR ==> Visual RTL" },\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_LOGICAL,\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662\0",\r
+ "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662", // mirroring\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662",\r
+ "5: Logical RTL ==> Logical RTL" },\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_RTL, UBIDI_VISUAL,\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "6: Logical RTL ==> Visual RTL" },\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_LOGICAL,\r
+ "\\u0632 \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 a[b]c",\r
+ "\\u0632 \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 a[b]c",\r
+ "\\u0632 \\u0661\\u0662 f 4\\u0631e 23\\u0630 \\u0660 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 a[b]c",\r
+ "7: Logical RTL ==> Logical LTR" },\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,\r
+ "\\u0661\\u0662 \\u0632 f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",\r
+ "\\u0661\\u0662 \\u0632 f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 a[b]c",\r
+ "\\u0661\\u0662 \\u0632 f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",\r
+ "8: Logical RTL ==> Visual LTR" },\r
+ { UBIDI_LTR, UBIDI_VISUAL, UBIDI_LTR, UBIDI_VISUAL, \r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662\0",\r
+ "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662", // mirroring\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u0662\\u0663\\u0660 e\\u0631\\u0664 f \\u0632 \\u0661\\u0662",\r
+ "9: Visual LTR ==> Visual LTR" },\r
+ { UBIDI_LTR, UBIDI_VISUAL, UBIDI_LTR, UBIDI_LOGICAL,\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "10: Visual LTR ==> Logical LTR" },\r
+ { UBIDI_LTR, UBIDI_VISUAL, UBIDI_RTL, UBIDI_VISUAL,\r
+ "\\u0662\\u0661 \\u0632 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",\r
+ "\\u0662\\u0661 \\u0632 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 c]b[a",\r
+ "\\u0662\\u0661 \\u0632 f \\u0664\\u0631e \\u0660\\u0663\\u0662 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",\r
+ "11: Visual LTR ==> Visual RTL" },\r
+ { UBIDI_LTR, UBIDI_VISUAL, UBIDI_RTL, UBIDI_LOGICAL,\r
+ "\\u0661\\u0662 \\u0632 f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",\r
+ "\\u0661\\u0662 \\u0632 f 4\\u0631e 23\\u0660 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 a[b]c",\r
+ "\\u0661\\u0662 \\u0632 f \\u0664\\u0631e \\u0662\\u0663\\u0660 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 a[b]c",\r
+ "12: Visual LTR ==> Logical RTL" }, \r
+ { UBIDI_RTL, UBIDI_VISUAL, UBIDI_RTL, UBIDI_VISUAL,\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662\0",\r
+ "a[b]c \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662",\r
+ "a[b]c \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 23\\u0660 e\\u06314 f \\u0632 \\u0661\\u0662",\r
+ "13: Visual RTL ==> Visual RTL" },\r
+ { UBIDI_RTL, UBIDI_VISUAL, UBIDI_RTL, UBIDI_LOGICAL,\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "14: Visual RTL ==> Logical RTL" },\r
+ { UBIDI_RTL, UBIDI_VISUAL, UBIDI_LTR, UBIDI_VISUAL,\r
+ "\\u0662\\u0661 \\u0632 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",\r
+ "\\u0662\\u0661 \\u0632 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 c]b[a",\r
+ "\\u0662\\u0661 \\u0632 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 c]b[a",\r
+ "15: Visual RTL ==> Visual LTR" },\r
+ { UBIDI_RTL, UBIDI_VISUAL, UBIDI_LTR, UBIDI_LOGICAL,\r
+ "\\u0632 \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 c]b[a",\r
+ "\\u0632 \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 c]b[a",\r
+ "\\u0632 \\u0662\\u0661 f 4\\u0631e \\u066032 \\u0630 d 1 \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 c]b[a",\r
+ "16: Visual RTL ==> Logical LTR" },\r
+\r
+ { UBIDI_DEFAULT_RTL, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "17: Logical DEFAULT_RTL ==> Visual LTR" },\r
+#if 0\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_DEFAULT_LTR, UBIDI_VISUAL,\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "18: Logical RTL ==> Visual DEFAULT_LTR" },\r
+#endif\r
+ { UBIDI_DEFAULT_LTR, UBIDI_LOGICAL, UBIDI_LTR, UBIDI_VISUAL,\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4(\\u05d3 \\u05d2\\u05d1)\\u05d0 d 23\\u0660 \\u0630 e4\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "a[b]c 1 \\u05d4)\\u05d3 \\u05d2\\u05d1(\\u05d0 d \\u0662\\u0663\\u0660 \\u0630 e\\u0664\\u0631 f \\u0661\\u0662 \\u0632",\r
+ "19: Logical DEFAULT_LTR ==> Visual LTR" },\r
+#if 0\r
+ { UBIDI_RTL, UBIDI_LOGICAL, UBIDI_DEFAULT_RTL, UBIDI_VISUAL,\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0)\\u05d1\\u05d2 \\u05d3(\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "c]b[a \\u05d0(\\u05d1\\u05d2 \\u05d3)\\u05d4 1 d \\u0630 \\u066032 e\\u06314 f \\u0632 \\u0662\\u0661",\r
+ "20: Logical RTL ==> Visual DEFAULT_RTL" }\r
+#endif\r
+ };\r
+ static const uint32_t digits[] = {\r
+ U_SHAPE_DIGITS_NOOP,\r
+ U_SHAPE_DIGITS_AN2EN,\r
+ U_SHAPE_DIGITS_EN2AN,\r
+ U_SHAPE_DIGITS_ALEN2AN_INIT_LR\r
+ };\r
+ static const uint32_t letters[] = {\r
+ U_SHAPE_LETTERS_UNSHAPE,\r
+ U_SHAPE_LETTERS_SHAPE\r
+ };\r
+ uint32_t i, nTestCases = sizeof(testCases) / sizeof(testCases[0]);\r
+ uint32_t j, nDigits = sizeof(digits) / sizeof(digits[0]);\r
+ uint32_t k, nLetters = sizeof(letters) / sizeof(letters[0]);\r
+ \r
+ UErrorCode errorCode = U_ZERO_ERROR;\r
+ UBiDiTransform *pTransform = ubiditransform_open(&errorCode);\r
+\r
+ u_unescape(inText, src, STR_CAPACITY);\r
+\r
+ // Test various combinations of para level, order, mirroring, digits and letters\r
+ for (i = 0; i < nTestCases; i++) {\r
+ ubiditransform_transform(pTransform, src, -1, dest, STR_CAPACITY,\r
+ testCases[i].inLevel, testCases[i].inOr,\r
+ testCases[i].outLevel, testCases[i].outOr,\r
+ UBIDI_MIRRORING_ON, 0, &errorCode);\r
+ verifyResultsForAllOpt(&testCases[i], src, dest,\r
+ testCases[i].pReorderAndMirror, U_SHAPE_DIGITS_NOOP,\r
+ U_SHAPE_LETTERS_NOOP);\r
+\r
+ for (j = 0; j < nDigits; j++) {\r
+ for (k = 0; k < nLetters; k++) {\r
+ /* Use here NULL for pTransform */\r
+ ubiditransform_transform(NULL, src, -1, dest, STR_CAPACITY,\r
+ testCases[i].inLevel, testCases[i].inOr,\r
+ testCases[i].outLevel, testCases[i].outOr,\r
+ UBIDI_MIRRORING_OFF, digits[j] | letters[k],\r
+ &errorCode);\r
+ verifyResultsForAllOpt(&testCases[i], src, dest,\r
+ testCases[i].pReorderNoMirror, digits[j], letters[k]);\r
+ }\r
+ }\r
+ }\r
+ ubiditransform_close(pTransform);\r
+}\r
+\r
+void\r
+addBidiTransformTest(TestNode** root)\r
+{\r
+ addTest(root, testAutoDirection, "complex/bidi-transform/TestAutoDirection");\r
+ addTest(root, testAllTransformOptions, "complex/bidi-transform/TestAllTransformOptions");\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="cbididat.c" />
+ <ClCompile Include="cbiditransformtst.c" />
<ClCompile Include="cbiditst.c" />
<ClCompile Include="cbiapts.c" />
<ClCompile Include="cbkittst.c" />
<ClCompile Include="spooftest.c">
<Filter>spoof</Filter>
</ClCompile>
+ <ClCompile Include="cbiditransformtst.c">
+ <Filter>bidi</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="cbiditst.h">
<Filter>sprep & idna</Filter>
</ClInclude>
</ItemGroup>
-</Project>
+</Project>
\ No newline at end of file