summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-xetex/test/cintltst
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2009-04-20 18:13:48 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2009-04-20 18:13:48 +0000
commite5786f530f9555469c01435f86039b06aa53feba (patch)
treec868e8d32282422d7d445b729db95c3fcdafb6d0 /Build/source/libs/icu/icu-xetex/test/cintltst
parentebaa1768b43c8606d923d2e861b5286b74207b3e (diff)
new build system: build icu libs and xetex plus misc updates
git-svn-id: svn://tug.org/texlive/trunk@12759 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/test/cintltst')
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in109
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c1031
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c1303
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h54
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h109
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c78
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c2148
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h124
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c708
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h35
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c434
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c3860
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h82
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c31
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c1337
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h80
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c3575
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h25
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c157
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h56
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c39
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c36
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c167
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h35
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c958
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h54
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c139
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h42
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c350
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h57
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c536
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h50
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c123
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h44
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c112
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h43
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c78
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h33
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c335
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h44
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c310
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h71
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c384
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c725
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h108
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj721
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c1923
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h118
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c255
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h63
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c1294
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c2774
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h114
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c5075
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c1093
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h60
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c951
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h60
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c1517
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h43
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c1399
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h61
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c17
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c107
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c1014
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h55
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c2950
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h85
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c944
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c286
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c131
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h41
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c356
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h9
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c3342
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c243
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c1185
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c1817
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c48
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c357
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h44
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c188
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c530
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c885
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c3354
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h69
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c755
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h36
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c2055
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c310
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h113
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c5369
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h23
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c371
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c1038
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c89
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c641
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c312
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c297
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c379
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c877
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c355
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c1761
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c307
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c307
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c646
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c498
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c2249
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c250
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c734
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c956
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c487
-rw-r--r--Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c707
113 files changed, 77709 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in b/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in
new file mode 100644
index 00000000000..262b7abf1bc
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/Makefile.in
@@ -0,0 +1,109 @@
+#******************************************************************************
+#
+# Copyright (C) 1999-2006, International Business Machines
+# Corporation and others. All Rights Reserved.
+#
+#******************************************************************************
+## Makefile.in for ICU - test/cintltst
+
+## Source directory information
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+top_builddir = ../..
+
+## All the flags and other definitions are included here.
+include $(top_builddir)/icudefs.mk
+
+## Build directory information
+subdir = test/cintltst
+
+## Extra files to remove for 'make clean'
+CLEANFILES = *~ $(DEPS)
+
+## Target information
+TARGET = cintltst$(EXEEXT)
+
+BUILDDIR := $(CURR_SRCCODE_FULL_DIR)/../../
+# Simplify the path for Unix
+BUILDDIR := $(BUILDDIR:test/cintltst/../../=)
+# Simplify the path for Windows
+BUILDDIR := $(BUILDDIR:test\\cintltst/../../=)
+# Simplify the path for Windows 98
+BUILDDIR := $(BUILDDIR:TEST\\CINTLTST/../../=)
+
+ifneq ($(top_builddir),$(top_srcdir))
+CPPFLAGS += -I$(top_builddir)/common
+endif
+# we define ICU_UNICODE_VERSION so we can test it
+CPPFLAGS += -I$(top_srcdir)/common -I$(top_srcdir)/i18n -I$(top_srcdir)/tools/ctestfw -I$(top_srcdir)/tools/toolutil
+DEFS += -D'ICU_UNICODE_VERSION="$(UNICODE_VERSION)"' -D'ICU_VERSION="@VERSION@"' -D'ICUDATA_NAME="$(ICUDATA_PLATFORM_NAME)"' -D'U_TOPSRCDIR="$(top_srcdir)/"' -D'U_TOPBUILDDIR="$(BUILDDIR)"'
+LIBS = $(LIBCTESTFW) $(LIBICUI18N) $(LIBICUUC) $(LIBICUTOOLUTIL) $(DEFAULT_LIBS) $(LIB_M)
+
+OBJECTS = callcoll.o calltest.o colutil.o capitst.o cbiapts.o cbkittst.o \
+ccaltst.o cctest.o ccapitst.o ccolltst.o encoll.o cconvtst.o ccurrtst.o \
+cdattst.o cdetst.o cdtdptst.o cdtrgtst.o cestst.o cfintst.o cformtst.o \
+cfrtst.o cg7coll.o chashtst.o cintltst.o citertst.o cjaptst.o cloctst.o \
+cmsccoll.o cmsgtst.o cposxtst.o cldrtest.o \
+cnmdptst.o cnormtst.o cnumtst.o crestst.o creststn.o cturtst.o \
+cucdapi.o cucdtst.o custrtst.o cstrcase.o cutiltst.o nucnvtst.o nccbtst.o bocu1tst.o \
+cbiditst.o cbididat.o eurocreg.o udatatst.o utf16tst.o utransts.o \
+ncnvfbts.o ncnvtst.o putiltst.o cstrtest.o udatpg_test.o utf8tst.o \
+stdnmtst.o usrchtst.o custrtrn.o sorttest.o trietest.o usettest.o \
+uenumtst.o utmstest.o currtest.o \
+idnatest.o nfsprep.o spreptst.o sprpdata.o \
+hpmufn.o tracetst.o reapits.o utexttst.o ucsdetst.o
+
+DEPS = $(OBJECTS:.o=.d)
+
+-include Makefile.local
+
+## List of phony targets
+.PHONY : all all-local install install-local clean clean-local \
+distclean distclean-local dist dist-local check check-local
+
+## Clear suffix list
+.SUFFIXES :
+
+## List of standard targets
+all: all-local
+install: install-local
+clean: clean-local
+distclean : distclean-local
+dist: dist-local
+check: all check-local
+
+all-local: $(TARGET)
+
+install-local:
+
+dist-local:
+
+clean-local:
+ test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
+ $(RMV) $(OBJECTS) $(TARGET)
+
+distclean-local: clean-local
+ $(RMV) Makefile
+
+check-local: all-local
+ $(INVOKE) ./$(TARGET) $(CINTLTST_OPTS)
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(TARGET) : $(OBJECTS)
+ $(LINK.c) $(OUTOPT)$@ $^ $(LIBS)
+ $(POST_BUILD_STEP)
+
+ifeq (,$(MAKECMDGOALS))
+-include $(DEPS)
+else
+ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
+ifneq ($(patsubst %install,,$(MAKECMDGOALS)),)
+-include $(DEPS)
+endif
+endif
+endif
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c
new file mode 100644
index 00000000000..0616b1cff9e
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/bocu1tst.c
@@ -0,0 +1,1031 @@
+/*
+******************************************************************************
+*
+* Copyright (C) 2002-2007, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+******************************************************************************
+* file name: bocu1tst.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2002may27
+* created by: Markus W. Scherer
+*
+* This is the reference implementation of BOCU-1,
+* the MIME-friendly form of the Binary Ordered Compression for Unicode,
+* taken directly from ### http://source.icu-project.org/repos/icu/icuhtml/trunk/design/conversion/bocu1/
+* The files bocu1.h and bocu1.c from the design folder are taken
+* verbatim (minus copyright and #include) and copied together into this file.
+* The reference code and some of the reference bocu1tst.c
+* is modified to run as part of the ICU cintltst
+* test framework (minus main(), log_ln() etc. instead of printf()).
+*
+* This reference implementation is used here to verify
+* the ICU BOCU-1 implementation, which is
+* adapted for ICU conversion APIs and optimized.
+* ### links in design doc to here and to ucnvbocu.c
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "cmemory.h"
+#include "cintltst.h"
+
+#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
+
+/* icuhtml/design/conversion/bocu1/bocu1.h ---------------------------------- */
+
+/* BOCU-1 constants and macros ---------------------------------------------- */
+
+/*
+ * BOCU-1 encodes the code points of a Unicode string as
+ * a sequence of byte-encoded differences (slope detection),
+ * preserving lexical order.
+ *
+ * Optimize the difference-taking for runs of Unicode text within
+ * small scripts:
+ *
+ * Most small scripts are allocated within aligned 128-blocks of Unicode
+ * code points. Lexical order is preserved if the "previous code point" state
+ * is always moved into the middle of such a block.
+ *
+ * Additionally, "prev" is moved from anywhere in the Unihan and Hangul
+ * areas into the middle of those areas.
+ *
+ * C0 control codes and space are encoded with their US-ASCII bytes.
+ * "prev" is reset for C0 controls but not for space.
+ */
+
+/* initial value for "prev": middle of the ASCII range */
+#define BOCU1_ASCII_PREV 0x40
+
+/* bounding byte values for differences */
+#define BOCU1_MIN 0x21
+#define BOCU1_MIDDLE 0x90
+#define BOCU1_MAX_LEAD 0xfe
+
+/* add the L suffix to make computations with BOCU1_MAX_TRAIL work on 16-bit compilers */
+#define BOCU1_MAX_TRAIL 0xffL
+#define BOCU1_RESET 0xff
+
+/* number of lead bytes */
+#define BOCU1_COUNT (BOCU1_MAX_LEAD-BOCU1_MIN+1)
+
+/* adjust trail byte counts for the use of some C0 control byte values */
+#define BOCU1_TRAIL_CONTROLS_COUNT 20
+#define BOCU1_TRAIL_BYTE_OFFSET (BOCU1_MIN-BOCU1_TRAIL_CONTROLS_COUNT)
+
+/* number of trail bytes */
+#define BOCU1_TRAIL_COUNT ((BOCU1_MAX_TRAIL-BOCU1_MIN+1)+BOCU1_TRAIL_CONTROLS_COUNT)
+
+/*
+ * number of positive and negative single-byte codes
+ * (counting 0==BOCU1_MIDDLE among the positive ones)
+ */
+#define BOCU1_SINGLE 64
+
+/* number of lead bytes for positive and negative 2/3/4-byte sequences */
+#define BOCU1_LEAD_2 43
+#define BOCU1_LEAD_3 3
+#define BOCU1_LEAD_4 1
+
+/* The difference value range for single-byters. */
+#define BOCU1_REACH_POS_1 (BOCU1_SINGLE-1)
+#define BOCU1_REACH_NEG_1 (-BOCU1_SINGLE)
+
+/* The difference value range for double-byters. */
+#define BOCU1_REACH_POS_2 (BOCU1_REACH_POS_1+BOCU1_LEAD_2*BOCU1_TRAIL_COUNT)
+#define BOCU1_REACH_NEG_2 (BOCU1_REACH_NEG_1-BOCU1_LEAD_2*BOCU1_TRAIL_COUNT)
+
+/* The difference value range for 3-byters. */
+#define BOCU1_REACH_POS_3 \
+ (BOCU1_REACH_POS_2+BOCU1_LEAD_3*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT)
+
+#define BOCU1_REACH_NEG_3 (BOCU1_REACH_NEG_2-BOCU1_LEAD_3*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT)
+
+/* The lead byte start values. */
+#define BOCU1_START_POS_2 (BOCU1_MIDDLE+BOCU1_REACH_POS_1+1)
+#define BOCU1_START_POS_3 (BOCU1_START_POS_2+BOCU1_LEAD_2)
+#define BOCU1_START_POS_4 (BOCU1_START_POS_3+BOCU1_LEAD_3)
+ /* ==BOCU1_MAX_LEAD */
+
+#define BOCU1_START_NEG_2 (BOCU1_MIDDLE+BOCU1_REACH_NEG_1)
+#define BOCU1_START_NEG_3 (BOCU1_START_NEG_2-BOCU1_LEAD_2)
+#define BOCU1_START_NEG_4 (BOCU1_START_NEG_3-BOCU1_LEAD_3)
+ /* ==BOCU1_MIN+1 */
+
+/* The length of a byte sequence, according to the lead byte (!=BOCU1_RESET). */
+#define BOCU1_LENGTH_FROM_LEAD(lead) \
+ ((BOCU1_START_NEG_2<=(lead) && (lead)<BOCU1_START_POS_2) ? 1 : \
+ (BOCU1_START_NEG_3<=(lead) && (lead)<BOCU1_START_POS_3) ? 2 : \
+ (BOCU1_START_NEG_4<=(lead) && (lead)<BOCU1_START_POS_4) ? 3 : 4)
+
+/* The length of a byte sequence, according to its packed form. */
+#define BOCU1_LENGTH_FROM_PACKED(packed) \
+ ((uint32_t)(packed)<0x04000000 ? (packed)>>24 : 4)
+
+/*
+ * 12 commonly used C0 control codes (and space) are only used to encode
+ * themselves directly,
+ * which makes BOCU-1 MIME-usable and reasonably safe for
+ * ASCII-oriented software.
+ *
+ * These controls are
+ * 0 NUL
+ *
+ * 7 BEL
+ * 8 BS
+ *
+ * 9 TAB
+ * a LF
+ * b VT
+ * c FF
+ * d CR
+ *
+ * e SO
+ * f SI
+ *
+ * 1a SUB
+ * 1b ESC
+ *
+ * The other 20 C0 controls are also encoded directly (to preserve order)
+ * but are also used as trail bytes in difference encoding
+ * (for better compression).
+ */
+#define BOCU1_TRAIL_TO_BYTE(t) ((t)>=BOCU1_TRAIL_CONTROLS_COUNT ? (t)+BOCU1_TRAIL_BYTE_OFFSET : bocu1TrailToByte[t])
+
+/*
+ * Byte value map for control codes,
+ * from external byte values 0x00..0x20
+ * to trail byte values 0..19 (0..0x13) as used in the difference calculation.
+ * External byte values that are illegal as trail bytes are mapped to -1.
+ */
+static const int8_t
+bocu1ByteToTrail[BOCU1_MIN]={
+/* 0 1 2 3 4 5 6 7 */
+ -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, -1,
+
+/* 8 9 a b c d e f */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+
+/* 10 11 12 13 14 15 16 17 */
+ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+
+/* 18 19 1a 1b 1c 1d 1e 1f */
+ 0x0e, 0x0f, -1, -1, 0x10, 0x11, 0x12, 0x13,
+
+/* 20 */
+ -1
+};
+
+/*
+ * Byte value map for control codes,
+ * from trail byte values 0..19 (0..0x13) as used in the difference calculation
+ * to external byte values 0x00..0x20.
+ */
+static const int8_t
+bocu1TrailToByte[BOCU1_TRAIL_CONTROLS_COUNT]={
+/* 0 1 2 3 4 5 6 7 */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x10, 0x11,
+
+/* 8 9 a b c d e f */
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+
+/* 10 11 12 13 */
+ 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+/**
+ * Integer division and modulo with negative numerators
+ * yields negative modulo results and quotients that are one more than
+ * what we need here.
+ * This macro adjust the results so that the modulo-value m is always >=0.
+ *
+ * For positive n, the if() condition is always FALSE.
+ *
+ * @param n Number to be split into quotient and rest.
+ * Will be modified to contain the quotient.
+ * @param d Divisor.
+ * @param m Output variable for the rest (modulo result).
+ */
+#define NEGDIVMOD(n, d, m) { \
+ (m)=(n)%(d); \
+ (n)/=(d); \
+ if((m)<0) { \
+ --(n); \
+ (m)+=(d); \
+ } \
+}
+
+/* State for BOCU-1 decoder function. */
+struct Bocu1Rx {
+ int32_t prev, count, diff;
+};
+
+typedef struct Bocu1Rx Bocu1Rx;
+
+/* Function prototypes ------------------------------------------------------ */
+
+/* see bocu1.c */
+U_CFUNC int32_t
+packDiff(int32_t diff);
+
+U_CFUNC int32_t
+encodeBocu1(int32_t *pPrev, int32_t c);
+
+U_CFUNC int32_t
+decodeBocu1(Bocu1Rx *pRx, uint8_t b);
+
+/* icuhtml/design/conversion/bocu1/bocu1.c ---------------------------------- */
+
+/* BOCU-1 implementation functions ------------------------------------------ */
+
+/**
+ * Compute the next "previous" value for differencing
+ * from the current code point.
+ *
+ * @param c current code point, 0..0x10ffff
+ * @return "previous code point" state value
+ */
+static U_INLINE int32_t
+bocu1Prev(int32_t c) {
+ /* compute new prev */
+ if(0x3040<=c && c<=0x309f) {
+ /* Hiragana is not 128-aligned */
+ return 0x3070;
+ } else if(0x4e00<=c && c<=0x9fa5) {
+ /* CJK Unihan */
+ return 0x4e00-BOCU1_REACH_NEG_2;
+ } else if(0xac00<=c && c<=0xd7a3) {
+ /* Korean Hangul (cast to int32_t to avoid wraparound on 16-bit compilers) */
+ return ((int32_t)0xd7a3+(int32_t)0xac00)/2;
+ } else {
+ /* mostly small scripts */
+ return (c&~0x7f)+BOCU1_ASCII_PREV;
+ }
+}
+
+/**
+ * Encode a difference -0x10ffff..0x10ffff in 1..4 bytes
+ * and return a packed integer with them.
+ *
+ * The encoding favors small absolut differences with short encodings
+ * to compress runs of same-script characters.
+ *
+ * @param diff difference value -0x10ffff..0x10ffff
+ * @return
+ * 0x010000zz for 1-byte sequence zz
+ * 0x0200yyzz for 2-byte sequence yy zz
+ * 0x03xxyyzz for 3-byte sequence xx yy zz
+ * 0xwwxxyyzz for 4-byte sequence ww xx yy zz (ww>0x03)
+ */
+U_CFUNC int32_t
+packDiff(int32_t diff) {
+ int32_t result, m, lead, count, shift;
+
+ if(diff>=BOCU1_REACH_NEG_1) {
+ /* mostly positive differences, and single-byte negative ones */
+ if(diff<=BOCU1_REACH_POS_1) {
+ /* single byte */
+ return 0x01000000|(BOCU1_MIDDLE+diff);
+ } else if(diff<=BOCU1_REACH_POS_2) {
+ /* two bytes */
+ diff-=BOCU1_REACH_POS_1+1;
+ lead=BOCU1_START_POS_2;
+ count=1;
+ } else if(diff<=BOCU1_REACH_POS_3) {
+ /* three bytes */
+ diff-=BOCU1_REACH_POS_2+1;
+ lead=BOCU1_START_POS_3;
+ count=2;
+ } else {
+ /* four bytes */
+ diff-=BOCU1_REACH_POS_3+1;
+ lead=BOCU1_START_POS_4;
+ count=3;
+ }
+ } else {
+ /* two- and four-byte negative differences */
+ if(diff>=BOCU1_REACH_NEG_2) {
+ /* two bytes */
+ diff-=BOCU1_REACH_NEG_1;
+ lead=BOCU1_START_NEG_2;
+ count=1;
+ } else if(diff>=BOCU1_REACH_NEG_3) {
+ /* three bytes */
+ diff-=BOCU1_REACH_NEG_2;
+ lead=BOCU1_START_NEG_3;
+ count=2;
+ } else {
+ /* four bytes */
+ diff-=BOCU1_REACH_NEG_3;
+ lead=BOCU1_START_NEG_4;
+ count=3;
+ }
+ }
+
+ /* encode the length of the packed result */
+ if(count<3) {
+ result=(count+1)<<24;
+ } else /* count==3, MSB used for the lead byte */ {
+ result=0;
+ }
+
+ /* calculate trail bytes like digits in itoa() */
+ shift=0;
+ do {
+ NEGDIVMOD(diff, BOCU1_TRAIL_COUNT, m);
+ result|=BOCU1_TRAIL_TO_BYTE(m)<<shift;
+ shift+=8;
+ } while(--count>0);
+
+ /* add lead byte */
+ result|=(lead+diff)<<shift;
+
+ return result;
+}
+
+/**
+ * BOCU-1 encoder function.
+ *
+ * @param pPrev pointer to the integer that holds
+ * the "previous code point" state;
+ * the initial value should be 0 which
+ * encodeBocu1 will set to the actual BOCU-1 initial state value
+ * @param c the code point to encode
+ * @return the packed 1/2/3/4-byte encoding, see packDiff(),
+ * or 0 if an error occurs
+ *
+ * @see packDiff
+ */
+U_CFUNC int32_t
+encodeBocu1(int32_t *pPrev, int32_t c) {
+ int32_t prev;
+
+ if(pPrev==NULL || c<0 || c>0x10ffff) {
+ /* illegal argument */
+ return 0;
+ }
+
+ prev=*pPrev;
+ if(prev==0) {
+ /* lenient handling of initial value 0 */
+ prev=*pPrev=BOCU1_ASCII_PREV;
+ }
+
+ if(c<=0x20) {
+ /*
+ * ISO C0 control & space:
+ * Encode directly for MIME compatibility,
+ * and reset state except for space, to not disrupt compression.
+ */
+ if(c!=0x20) {
+ *pPrev=BOCU1_ASCII_PREV;
+ }
+ return 0x01000000|c;
+ }
+
+ /*
+ * all other Unicode code points c==U+0021..U+10ffff
+ * are encoded with the difference c-prev
+ *
+ * a new prev is computed from c,
+ * placed in the middle of a 0x80-block (for most small scripts) or
+ * in the middle of the Unihan and Hangul blocks
+ * to statistically minimize the following difference
+ */
+ *pPrev=bocu1Prev(c);
+ return packDiff(c-prev);
+}
+
+/**
+ * Function for BOCU-1 decoder; handles multi-byte lead bytes.
+ *
+ * @param pRx pointer to the decoder state structure
+ * @param b lead byte;
+ * BOCU1_MIN<=b<BOCU1_START_NEG_2 or BOCU1_START_POS_2<=b<=BOCU1_MAX_LEAD
+ * @return -1 (state change only)
+ *
+ * @see decodeBocu1
+ */
+static int32_t
+decodeBocu1LeadByte(Bocu1Rx *pRx, uint8_t b) {
+ int32_t c, count;
+
+ if(b>=BOCU1_START_NEG_2) {
+ /* positive difference */
+ if(b<BOCU1_START_POS_3) {
+ /* two bytes */
+ c=((int32_t)b-BOCU1_START_POS_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_1+1;
+ count=1;
+ } else if(b<BOCU1_START_POS_4) {
+ /* three bytes */
+ c=((int32_t)b-BOCU1_START_POS_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_POS_2+1;
+ count=2;
+ } else {
+ /* four bytes */
+ c=BOCU1_REACH_POS_3+1;
+ count=3;
+ }
+ } else {
+ /* negative difference */
+ if(b>=BOCU1_START_NEG_3) {
+ /* two bytes */
+ c=((int32_t)b-BOCU1_START_NEG_2)*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_1;
+ count=1;
+ } else if(b>BOCU1_MIN) {
+ /* three bytes */
+ c=((int32_t)b-BOCU1_START_NEG_3)*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_2;
+ count=2;
+ } else {
+ /* four bytes */
+ c=-BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT+BOCU1_REACH_NEG_3;
+ count=3;
+ }
+ }
+
+ /* set the state for decoding the trail byte(s) */
+ pRx->diff=c;
+ pRx->count=count;
+ return -1;
+}
+
+/**
+ * Function for BOCU-1 decoder; handles multi-byte trail bytes.
+ *
+ * @param pRx pointer to the decoder state structure
+ * @param b trail byte
+ * @return result value, same as decodeBocu1
+ *
+ * @see decodeBocu1
+ */
+static int32_t
+decodeBocu1TrailByte(Bocu1Rx *pRx, uint8_t b) {
+ int32_t t, c, count;
+
+ if(b<=0x20) {
+ /* skip some C0 controls and make the trail byte range contiguous */
+ t=bocu1ByteToTrail[b];
+ if(t<0) {
+ /* illegal trail byte value */
+ pRx->prev=BOCU1_ASCII_PREV;
+ pRx->count=0;
+ return -99;
+ }
+#if BOCU1_MAX_TRAIL<0xff
+ } else if(b>BOCU1_MAX_TRAIL) {
+ return -99;
+#endif
+ } else {
+ t=(int32_t)b-BOCU1_TRAIL_BYTE_OFFSET;
+ }
+
+ /* add trail byte into difference and decrement count */
+ c=pRx->diff;
+ count=pRx->count;
+
+ if(count==1) {
+ /* final trail byte, deliver a code point */
+ c=pRx->prev+c+t;
+ if(0<=c && c<=0x10ffff) {
+ /* valid code point result */
+ pRx->prev=bocu1Prev(c);
+ pRx->count=0;
+ return c;
+ } else {
+ /* illegal code point result */
+ pRx->prev=BOCU1_ASCII_PREV;
+ pRx->count=0;
+ return -99;
+ }
+ }
+
+ /* intermediate trail byte */
+ if(count==2) {
+ pRx->diff=c+t*BOCU1_TRAIL_COUNT;
+ } else /* count==3 */ {
+ pRx->diff=c+t*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT;
+ }
+ pRx->count=count-1;
+ return -1;
+}
+
+/**
+ * BOCU-1 decoder function.
+ *
+ * @param pRx pointer to the decoder state structure;
+ * the initial values should be 0 which
+ * decodeBocu1 will set to actual initial state values
+ * @param b an input byte
+ * @return
+ * 0..0x10ffff for a result code point
+ * -1 if only the state changed without code point output
+ * <-1 if an error occurs
+ */
+U_CFUNC int32_t
+decodeBocu1(Bocu1Rx *pRx, uint8_t b) {
+ int32_t prev, c, count;
+
+ if(pRx==NULL) {
+ /* illegal argument */
+ return -99;
+ }
+
+ prev=pRx->prev;
+ if(prev==0) {
+ /* lenient handling of initial 0 values */
+ prev=pRx->prev=BOCU1_ASCII_PREV;
+ count=pRx->count=0;
+ } else {
+ count=pRx->count;
+ }
+
+ if(count==0) {
+ /* byte in lead position */
+ if(b<=0x20) {
+ /*
+ * Direct-encoded C0 control code or space.
+ * Reset prev for C0 control codes but not for space.
+ */
+ if(b!=0x20) {
+ pRx->prev=BOCU1_ASCII_PREV;
+ }
+ return b;
+ }
+
+ /*
+ * b is a difference lead byte.
+ *
+ * Return a code point directly from a single-byte difference.
+ *
+ * For multi-byte difference lead bytes, set the decoder state
+ * with the partial difference value from the lead byte and
+ * with the number of trail bytes.
+ *
+ * For four-byte differences, the signedness also affects the
+ * first trail byte, which has special handling farther below.
+ */
+ if(b>=BOCU1_START_NEG_2 && b<BOCU1_START_POS_2) {
+ /* single-byte difference */
+ c=prev+((int32_t)b-BOCU1_MIDDLE);
+ pRx->prev=bocu1Prev(c);
+ return c;
+ } else if(b==BOCU1_RESET) {
+ /* only reset the state, no code point */
+ pRx->prev=BOCU1_ASCII_PREV;
+ return -1;
+ } else {
+ return decodeBocu1LeadByte(pRx, b);
+ }
+ } else {
+ /* trail byte in any position */
+ return decodeBocu1TrailByte(pRx, b);
+ }
+}
+
+/* icuhtml/design/conversion/bocu1/bocu1tst.c ------------------------------- */
+
+/* test code ---------------------------------------------------------------- */
+
+/* test code options */
+
+/* ignore comma when processing name lists in testText() */
+#define TEST_IGNORE_COMMA 1
+
+/**
+ * Write a packed BOCU-1 byte sequence into a byte array,
+ * without overflow check.
+ * Test function.
+ *
+ * @param packed packed BOCU-1 byte sequence, see packDiff()
+ * @param p pointer to byte array
+ * @return number of bytes
+ *
+ * @see packDiff
+ */
+static int32_t
+writePacked(int32_t packed, uint8_t *p) {
+ int32_t count=BOCU1_LENGTH_FROM_PACKED(packed);
+ switch(count) {
+ case 4:
+ *p++=(uint8_t)(packed>>24);
+ case 3:
+ *p++=(uint8_t)(packed>>16);
+ case 2:
+ *p++=(uint8_t)(packed>>8);
+ case 1:
+ *p++=(uint8_t)packed;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/**
+ * Unpack a packed BOCU-1 non-C0/space byte sequence and get
+ * the difference to initialPrev.
+ * Used only for round-trip testing of the difference encoding and decoding.
+ * Test function.
+ *
+ * @param initialPrev bogus "previous code point" value to make sure that
+ * the resulting code point is in the range 0..0x10ffff
+ * @param packed packed BOCU-1 byte sequence
+ * @return the difference to initialPrev
+ *
+ * @see packDiff
+ * @see writeDiff
+ */
+static int32_t
+unpackDiff(int32_t initialPrev, int32_t packed) {
+ Bocu1Rx rx={ 0, 0, 0 };
+ int32_t count;
+
+ rx.prev=initialPrev;
+ count=BOCU1_LENGTH_FROM_PACKED(packed);
+ switch(count) {
+ case 4:
+ decodeBocu1(&rx, (uint8_t)(packed>>24));
+ case 3:
+ decodeBocu1(&rx, (uint8_t)(packed>>16));
+ case 2:
+ decodeBocu1(&rx, (uint8_t)(packed>>8));
+ case 1:
+ /* subtract initial prev */
+ return decodeBocu1(&rx, (uint8_t)packed)-initialPrev;
+ default:
+ return -0x7fffffff;
+ }
+}
+
+/**
+ * Encode one difference value -0x10ffff..+0x10ffff in 1..4 bytes,
+ * preserving lexical order.
+ * Also checks for roundtripping of the difference encoding.
+ * Test function.
+ *
+ * @param diff difference value to test, -0x10ffff..0x10ffff
+ * @param p pointer to output byte array
+ * @return p advanced by number of bytes output
+ *
+ * @see unpackDiff
+ */
+static uint8_t *
+writeDiff(int32_t diff, uint8_t *p) {
+ /* generate the difference as a packed value and serialize it */
+ int32_t packed, initialPrev;
+
+ packed=packDiff(diff);
+
+ /*
+ * bogus initial "prev" to work around
+ * code point range check in decodeBocu1()
+ */
+ if(diff<=0) {
+ initialPrev=0x10ffff;
+ } else {
+ initialPrev=-1;
+ }
+
+ if(diff!=unpackDiff(initialPrev, packed)) {
+ log_err("error: unpackDiff(packDiff(diff=%ld)=0x%08lx)=%ld!=diff\n",
+ diff, packed, unpackDiff(initialPrev, packed));
+ }
+ return p+writePacked(packed, p);
+}
+
+/**
+ * Encode a UTF-16 string in BOCU-1.
+ * Does not check for overflows, but otherwise useful function.
+ *
+ * @param s input UTF-16 string
+ * @param length number of UChar code units in s
+ * @param p pointer to output byte array
+ * @return number of bytes output
+ */
+static int32_t
+writeString(const UChar *s, int32_t length, uint8_t *p) {
+ uint8_t *p0;
+ int32_t c, prev, i;
+
+ prev=0;
+ p0=p;
+ i=0;
+ while(i<length) {
+ UTF_NEXT_CHAR(s, i, length, c);
+ p+=writePacked(encodeBocu1(&prev, c), p);
+ }
+ return (int32_t)(p-p0);
+}
+
+/**
+ * Decode a BOCU-1 byte sequence to a UTF-16 string.
+ * Does not check for overflows, but otherwise useful function.
+ *
+ * @param p pointer to input BOCU-1 bytes
+ * @param length number of input bytes
+ * @param s point to output UTF-16 string array
+ * @return number of UChar code units output
+ */
+static int32_t
+readString(const uint8_t *p, int32_t length, UChar *s) {
+ Bocu1Rx rx={ 0, 0, 0 };
+ int32_t c, i, sLength;
+
+ i=sLength=0;
+ while(i<length) {
+ c=decodeBocu1(&rx, p[i++]);
+ if(c<-1) {
+ log_err("error: readString detects encoding error at string index %ld\n", i);
+ return -1;
+ }
+ if(c>=0) {
+ UTF_APPEND_CHAR_UNSAFE(s, sLength, c);
+ }
+ }
+ return sLength;
+}
+
+static U_INLINE char
+hexDigit(uint8_t digit) {
+ return digit<=9 ? (char)('0'+digit) : (char)('a'-10+digit);
+}
+
+/**
+ * Pretty-print 0-terminated byte values.
+ * Helper function for test output.
+ *
+ * @param bytes 0-terminated byte array to print
+ */
+static void
+printBytes(uint8_t *bytes, char *out) {
+ int i;
+ uint8_t b;
+
+ i=0;
+ while((b=*bytes++)!=0) {
+ *out++=' ';
+ *out++=hexDigit((uint8_t)(b>>4));
+ *out++=hexDigit((uint8_t)(b&0xf));
+ ++i;
+ }
+ i=3*(5-i);
+ while(i>0) {
+ *out++=' ';
+ --i;
+ }
+ *out=0;
+}
+
+/**
+ * Basic BOCU-1 test function, called when there are no command line arguments.
+ * Prints some of the #define values and performs round-trip tests of the
+ * difference encoding and decoding.
+ */
+static void
+TestBOCU1RefDiff(void) {
+ char buf1[80], buf2[80];
+ uint8_t prev[5], level[5];
+ int32_t i, cmp, countErrors;
+
+ log_verbose("reach of single bytes: %ld\n", 1+BOCU1_REACH_POS_1-BOCU1_REACH_NEG_1);
+ log_verbose("reach of 2 bytes : %ld\n", 1+BOCU1_REACH_POS_2-BOCU1_REACH_NEG_2);
+ log_verbose("reach of 3 bytes : %ld\n\n", 1+BOCU1_REACH_POS_3-BOCU1_REACH_NEG_3);
+
+ log_verbose(" BOCU1_REACH_NEG_1 %8ld BOCU1_REACH_POS_1 %8ld\n", BOCU1_REACH_NEG_1, BOCU1_REACH_POS_1);
+ log_verbose(" BOCU1_REACH_NEG_2 %8ld BOCU1_REACH_POS_2 %8ld\n", BOCU1_REACH_NEG_2, BOCU1_REACH_POS_2);
+ log_verbose(" BOCU1_REACH_NEG_3 %8ld BOCU1_REACH_POS_3 %8ld\n\n", BOCU1_REACH_NEG_3, BOCU1_REACH_POS_3);
+
+ log_verbose(" BOCU1_MIDDLE 0x%02x\n", BOCU1_MIDDLE);
+ log_verbose(" BOCU1_START_NEG_2 0x%02x BOCU1_START_POS_2 0x%02x\n", BOCU1_START_NEG_2, BOCU1_START_POS_2);
+ log_verbose(" BOCU1_START_NEG_3 0x%02x BOCU1_START_POS_3 0x%02x\n\n", BOCU1_START_NEG_3, BOCU1_START_POS_3);
+
+ /* test packDiff() & unpackDiff() with some specific values */
+ writeDiff(0, level);
+ writeDiff(1, level);
+ writeDiff(65, level);
+ writeDiff(130, level);
+ writeDiff(30000, level);
+ writeDiff(1000000, level);
+ writeDiff(-65, level);
+ writeDiff(-130, level);
+ writeDiff(-30000, level);
+ writeDiff(-1000000, level);
+
+ /* test that each value is smaller than any following one */
+ countErrors=0;
+ i=-0x10ffff;
+ *writeDiff(i, prev)=0;
+
+ /* show first number and bytes */
+ printBytes(prev, buf1);
+ log_verbose(" wD(%8ld) %s\n", i, buf1);
+
+ for(++i; i<=0x10ffff; ++i) {
+ *writeDiff(i, level)=0;
+ cmp=strcmp((const char *)prev, (const char *)level);
+ if(BOCU1_LENGTH_FROM_LEAD(level[0])!=(int32_t)strlen((const char *)level)) {
+ log_verbose("BOCU1_LENGTH_FROM_LEAD(0x%02x)=%ld!=%ld=strlen(writeDiff(%ld))\n",
+ level[0], BOCU1_LENGTH_FROM_LEAD(level[0]), strlen((const char *)level), i);
+ }
+ if(cmp<0) {
+ if(i==0 || i==1 || strlen((const char *)prev)!=strlen((const char *)level)) {
+ /*
+ * if the result is good, then print only if the length changed
+ * to get little but interesting output
+ */
+ printBytes(prev, buf1);
+ printBytes(level, buf2);
+ log_verbose("ok: strcmp(wD(%8ld), wD(%8ld))=%2d %s%s\n", i-1, i, cmp, buf1, buf2);
+ }
+ } else {
+ ++countErrors;
+ printBytes(prev, buf1);
+ printBytes(level, buf2);
+ log_verbose("wrong: strcmp(wD(%8ld), wD(%8ld))=%2d %s%s\n", i-1, i, cmp, buf1, buf2);
+ }
+ /* remember the previous bytes */
+ memcpy(prev, level, 4);
+ }
+
+ /* show last number and bytes */
+ printBytes((uint8_t *)"", buf1);
+ printBytes(prev, buf2);
+ log_verbose(" wD(%8ld) %s%s\n", i-1, buf1, buf2);
+
+ if(countErrors==0) {
+ log_verbose("writeDiff(-0x10ffff..0x10ffff) works fine\n");
+ } else {
+ log_err("writeDiff(-0x10ffff..0x10ffff) violates lexical ordering in %d cases\n", countErrors);
+ }
+
+ /* output signature byte sequence */
+ i=0;
+ writePacked(encodeBocu1(&i, 0xfeff), level);
+ log_verbose("\nBOCU-1 signature byte sequence: %02x %02x %02x\n",
+ level[0], level[1], level[2]);
+}
+
+/* cintltst code ------------------------------------------------------------ */
+
+static const int32_t DEFAULT_BUFFER_SIZE = 30000;
+
+
+/* test one string with the ICU and the reference BOCU-1 implementations */
+static void
+roundtripBOCU1(UConverter *bocu1, int32_t number, const UChar *text, int32_t length) {
+ UChar *roundtripRef, *roundtripICU;
+ char *bocu1Ref, *bocu1ICU;
+
+ int32_t bocu1RefLength, bocu1ICULength, roundtripRefLength, roundtripICULength;
+ UErrorCode errorCode;
+
+ roundtripRef = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar));
+ roundtripICU = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar));
+ bocu1Ref = malloc(DEFAULT_BUFFER_SIZE);
+ bocu1ICU = malloc(DEFAULT_BUFFER_SIZE);
+
+ /* Unicode -> BOCU-1 */
+ bocu1RefLength=writeString(text, length, (uint8_t *)bocu1Ref);
+
+ errorCode=U_ZERO_ERROR;
+ bocu1ICULength=ucnv_fromUChars(bocu1, bocu1ICU, DEFAULT_BUFFER_SIZE, text, length, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_fromUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode));
+ return;
+ }
+
+ if(bocu1RefLength!=bocu1ICULength || 0!=uprv_memcmp(bocu1Ref, bocu1ICU, bocu1RefLength)) {
+ log_err("Unicode(%d)[%d] -> BOCU-1: reference[%d]!=ICU[%d]\n", number, length, bocu1RefLength, bocu1ICULength);
+ return;
+ }
+
+ /* BOCU-1 -> Unicode */
+ roundtripRefLength=readString((uint8_t *)bocu1Ref, bocu1RefLength, roundtripRef);
+ if(roundtripRefLength<0) {
+ return; /* readString() found an error and reported it */
+ }
+
+ roundtripICULength=ucnv_toUChars(bocu1, roundtripICU, DEFAULT_BUFFER_SIZE, bocu1ICU, bocu1ICULength, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_toUChars(BOCU-1, text(%d)[%d]) failed: %s\n", number, length, u_errorName(errorCode));
+ return;
+ }
+
+ if(length!=roundtripRefLength || 0!=u_memcmp(text, roundtripRef, length)) {
+ log_err("BOCU-1 -> Unicode: original(%d)[%d]!=reference[%d]\n", number, length, roundtripRefLength);
+ return;
+ }
+ if(roundtripRefLength!=roundtripICULength || 0!=u_memcmp(roundtripRef, roundtripICU, roundtripRefLength)) {
+ log_err("BOCU-1 -> Unicode: reference(%d)[%d]!=ICU[%d]\n", number, roundtripRefLength, roundtripICULength);
+ return;
+ }
+ free(roundtripRef);
+ free(roundtripICU);
+ free(bocu1Ref);
+ free(bocu1ICU);
+}
+
+static const UChar feff[]={ 0xfeff };
+static const UChar ascii[]={ 0x61, 0x62, 0x20, 0x63, 0x61 };
+static const UChar crlf[]={ 0xd, 0xa, 0x20 };
+static const UChar nul[]={ 0 };
+static const UChar latin[]={ 0xdf, 0xe6 };
+static const UChar devanagari[]={ 0x930, 0x20, 0x918, 0x909 };
+static const UChar hiragana[]={ 0x3086, 0x304d, 0x20, 0x3053, 0x4000 };
+static const UChar unihan[]={ 0x4e00, 0x7777, 0x20, 0x9fa5, 0x4e00 };
+static const UChar hangul[]={ 0xac00, 0xbcde, 0x20, 0xd7a3 };
+static const UChar surrogates[]={ 0xdc00, 0xd800 }; /* single surrogates, unmatched! */
+static const UChar plane1[]={ 0xd800, 0xdc00 };
+static const UChar plane2[]={ 0xd845, 0xdddd };
+static const UChar plane15[]={ 0xdbbb, 0xddee, 0x20 };
+static const UChar plane16[]={ 0xdbff, 0xdfff };
+static const UChar c0[]={ 1, 0xe40, 0x20, 9 };
+
+static const struct {
+ const UChar *s;
+ int32_t length;
+} strings[]={
+ { feff, LENGTHOF(feff) },
+ { ascii, LENGTHOF(ascii) },
+ { crlf, LENGTHOF(crlf) },
+ { nul, LENGTHOF(nul) },
+ { latin, LENGTHOF(latin) },
+ { devanagari, LENGTHOF(devanagari) },
+ { hiragana, LENGTHOF(hiragana) },
+ { unihan, LENGTHOF(unihan) },
+ { hangul, LENGTHOF(hangul) },
+ { surrogates, LENGTHOF(surrogates) },
+ { plane1, LENGTHOF(plane1) },
+ { plane2, LENGTHOF(plane2) },
+ { plane15, LENGTHOF(plane15) },
+ { plane16, LENGTHOF(plane16) },
+ { c0, LENGTHOF(c0) }
+};
+
+/*
+ * Verify that the ICU BOCU-1 implementation produces the same results as
+ * the reference implementation from the design folder.
+ * Generate some texts and convert them with both converters, verifying
+ * identical results and roundtripping.
+ */
+static void
+TestBOCU1(void) {
+ UChar *text;
+ int32_t i, length;
+
+ UConverter *bocu1;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ bocu1=ucnv_open("BOCU-1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: unable to open BOCU-1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ text = malloc(DEFAULT_BUFFER_SIZE * sizeof(UChar));
+
+ /* text 1: each of strings[] once */
+ length=0;
+ for(i=0; i<LENGTHOF(strings); ++i) {
+ u_memcpy(text+length, strings[i].s, strings[i].length);
+ length+=strings[i].length;
+ }
+ roundtripBOCU1(bocu1, 1, text, length);
+
+ /* text 2: each of strings[] twice */
+ length=0;
+ for(i=0; i<LENGTHOF(strings); ++i) {
+ u_memcpy(text+length, strings[i].s, strings[i].length);
+ length+=strings[i].length;
+ u_memcpy(text+length, strings[i].s, strings[i].length);
+ length+=strings[i].length;
+ }
+ roundtripBOCU1(bocu1, 2, text, length);
+
+ /* text 3: each of strings[] many times (set step vs. |strings| so that all strings are used) */
+ length=0;
+ for(i=1; length<5000; i+=7) {
+ if(i>=LENGTHOF(strings)) {
+ i-=LENGTHOF(strings);
+ }
+ u_memcpy(text+length, strings[i].s, strings[i].length);
+ length+=strings[i].length;
+ }
+ roundtripBOCU1(bocu1, 3, text, length);
+
+ ucnv_close(bocu1);
+ free(text);
+}
+
+U_CFUNC void addBOCU1Tests(TestNode** root);
+
+U_CFUNC void
+addBOCU1Tests(TestNode** root) {
+ addTest(root, TestBOCU1RefDiff, "tsconv/bocu1tst/TestBOCU1RefDiff");
+ addTest(root, TestBOCU1, "tsconv/bocu1tst/TestBOCU1");
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c
new file mode 100644
index 00000000000..d898eea25f2
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.c
@@ -0,0 +1,1303 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CALLCOLL.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+********************************************************************************
+*/
+
+/*
+ * Important: This file is included into intltest/allcoll.cpp so that the
+ * test data is shared. This makes it easier to maintain the test data,
+ * especially since the Unicode data must be portable and quoted character
+ * literals will not work.
+ * If it is included, then there will be a #define INCLUDE_CALLCOLL_C
+ * that must prevent the actual code in here from being part of the
+ * allcoll.cpp compilation.
+ */
+
+/**
+ * CollationDummyTest is a third level test class. This tests creation of
+ * a customized collator object. For example, number 1 to be sorted
+ * equlivalent to word 'one'.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "unicode/ucoleitr.h"
+#include "unicode/ustring.h"
+#include "unicode/uclean.h"
+#include "unicode/putil.h"
+#include "unicode/uenum.h"
+
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "calldata.h"
+#include "cstring.h"
+#include "cmemory.h"
+#include "ucol_imp.h"
+
+/* perform test with strength PRIMARY */
+static void TestPrimary(void);
+
+/* perform test with strength SECONDARY */
+static void TestSecondary(void);
+
+/* perform test with strength tertiary */
+static void TestTertiary(void);
+
+/*perform tests with strength Identical */
+static void TestIdentical(void);
+
+/* perform extra tests */
+static void TestExtra(void);
+
+/* Test jitterbug 581 */
+static void TestJB581(void);
+
+/* Test jitterbug 1401 */
+static void TestJB1401(void);
+
+/* Test [variable top] in the rule syntax */
+static void TestVariableTop(void);
+
+/* Test surrogates */
+static void TestSurrogates(void);
+
+static void TestInvalidRules(void);
+
+static void TestJitterbug1098(void);
+
+static void TestFCDCrash(void);
+
+static void TestJ5298(void);
+
+const UCollationResult results[] = {
+ UCOL_LESS,
+ UCOL_LESS, /*UCOL_GREATER,*/
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_LESS, /* 10 */
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ /* test primary > 17 */
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL, /* 20 */
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ /* test secondary > 26 */
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL, /* 30 */
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_EQUAL, /* 34 */
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_LESS /* 37 */
+};
+
+
+static
+void uprv_appendByteToHexString(char *dst, uint8_t val) {
+ uint32_t len = (uint32_t)uprv_strlen(dst);
+ *(dst+len) = T_CString_itosOffset((val >> 4));
+ *(dst+len+1) = T_CString_itosOffset((val & 0xF));
+ *(dst+len+2) = 0;
+}
+
+/* this function makes a string with representation of a sortkey */
+static char* U_EXPORT2 sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) {
+ int32_t strength = UCOL_PRIMARY;
+ uint32_t res_size = 0;
+ UBool doneCase = FALSE;
+
+ char *current = buffer;
+ const uint8_t *currentSk = sortkey;
+
+ uprv_strcpy(current, "[");
+
+ while(strength <= UCOL_QUATERNARY && strength <= coll->strength) {
+ if(strength > UCOL_PRIMARY) {
+ uprv_strcat(current, " . ");
+ }
+ while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */
+ uprv_appendByteToHexString(current, *currentSk++);
+ uprv_strcat(current, " ");
+ }
+ if(coll->caseLevel == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) {
+ doneCase = TRUE;
+ } else if(coll->caseLevel == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) {
+ strength ++;
+ }
+ uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */
+ if(strength == UCOL_QUATERNARY && coll->alternateHandling == UCOL_NON_IGNORABLE) {
+ break;
+ }
+ }
+
+ if(coll->strength == UCOL_IDENTICAL) {
+ uprv_strcat(current, " . ");
+ while(*currentSk != 0) {
+ uprv_appendByteToHexString(current, *currentSk++);
+ uprv_strcat(current, " ");
+ }
+
+ uprv_appendByteToHexString(current, *currentSk++);
+ }
+ uprv_strcat(current, "]");
+
+ if(res_size > *len) {
+ return NULL;
+ }
+
+ return buffer;
+}
+
+void addAllCollTest(TestNode** root)
+{
+
+
+ addTest(root, &TestPrimary, "tscoll/callcoll/TestPrimary");
+ addTest(root, &TestSecondary, "tscoll/callcoll/TestSecondary");
+ addTest(root, &TestTertiary, "tscoll/callcoll/TestTertiary");
+ addTest(root, &TestIdentical, "tscoll/callcoll/TestIdentical");
+ addTest(root, &TestExtra, "tscoll/callcoll/TestExtra");
+ addTest(root, &TestJB581, "tscoll/callcoll/TestJB581");
+ addTest(root, &TestVariableTop, "tscoll/callcoll/TestVariableTop");
+ addTest(root, &TestSurrogates, "tscoll/callcoll/TestSurrogates");
+ addTest(root, &TestInvalidRules, "tscoll/callcoll/TestInvalidRules");
+ addTest(root, &TestJB1401, "tscoll/callcoll/TestJB1401");
+ addTest(root, &TestJitterbug1098, "tscoll/callcoll/TestJitterbug1098");
+ addTest(root, &TestFCDCrash, "tscoll/callcoll/TestFCDCrash");
+ addTest(root, &TestJ5298, "tscoll/callcoll/TestJ5298");
+}
+
+UBool hasCollationElements(const char *locName) {
+
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *ColEl = NULL;
+
+ UResourceBundle *loc = ures_open(U_ICUDATA_COLL, locName, &status);;
+
+ if(U_SUCCESS(status)) {
+ status = U_ZERO_ERROR;
+ ColEl = ures_getByKey(loc, "collations", ColEl, &status);
+ if(status == U_ZERO_ERROR) { /* do the test - there are real elements */
+ ures_close(ColEl);
+ ures_close(loc);
+ return TRUE;
+ }
+ ures_close(ColEl);
+ ures_close(loc);
+ }
+ return FALSE;
+}
+
+static UCollationResult compareUsingPartials(UCollator *coll, const UChar source[], int32_t sLen, const UChar target[], int32_t tLen, int32_t pieceSize, UErrorCode *status) {
+ int32_t partialSKResult = 0;
+ UCharIterator sIter, tIter;
+ uint32_t sState[2], tState[2];
+ int32_t sSize = pieceSize, tSize = pieceSize;
+ /*int32_t i = 0;*/
+ uint8_t sBuf[16384], tBuf[16384];
+ if(pieceSize > 16384) {
+ log_err("Partial sortkey size buffer too small. Please consider increasing the buffer!\n");
+ *status = U_BUFFER_OVERFLOW_ERROR;
+ return UCOL_EQUAL;
+ }
+ *status = U_ZERO_ERROR;
+ sState[0] = 0; sState[1] = 0;
+ tState[0] = 0; tState[1] = 0;
+ while(sSize == pieceSize && tSize == pieceSize && partialSKResult == 0) {
+ uiter_setString(&sIter, source, sLen);
+ uiter_setString(&tIter, target, tLen);
+ sSize = ucol_nextSortKeyPart(coll, &sIter, sState, sBuf, pieceSize, status);
+ tSize = ucol_nextSortKeyPart(coll, &tIter, tState, tBuf, pieceSize, status);
+
+ if(sState[0] != 0 || tState[0] != 0) {
+ /*log_verbose("State != 0 : %08X %08X\n", sState[0], tState[0]);*/
+ }
+ /*log_verbose("%i ", i++);*/
+
+ partialSKResult = memcmp(sBuf, tBuf, pieceSize);
+ }
+
+ if(partialSKResult < 0) {
+ return UCOL_LESS;
+ } else if(partialSKResult > 0) {
+ return UCOL_GREATER;
+ } else {
+ return UCOL_EQUAL;
+ }
+}
+
+static void doTestVariant(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
+{
+ int32_t sortklen1, sortklen2, sortklenmax, sortklenmin;
+ int temp=0, gSortklen1=0,gSortklen2=0;
+ UCollationResult compareResult, compareResulta, keyResult, compareResultIter = result;
+ uint8_t *sortKey1, *sortKey2, *sortKey1a, *sortKey2a;
+ uint32_t sLen = u_strlen(source);
+ uint32_t tLen = u_strlen(target);
+ char buffer[256];
+ uint32_t len;
+ UErrorCode status = U_ZERO_ERROR;
+ UColAttributeValue norm = ucol_getAttribute(myCollation, UCOL_NORMALIZATION_MODE, &status);
+
+ UCharIterator sIter, tIter;
+ uiter_setString(&sIter, source, sLen);
+ uiter_setString(&tIter, target, tLen);
+ compareResultIter = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
+ if(compareResultIter != result) {
+ log_err("different results in iterative comparison for UTF-16 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
+ }
+
+ /* convert the strings to UTF-8 and do try comparing with char iterator */
+ if(QUICK <= 0) { /*!QUICK*/
+ char utf8Source[256], utf8Target[256];
+ int32_t utf8SourceLen = 0, utf8TargetLen = 0;
+ u_strToUTF8(utf8Source, 256, &utf8SourceLen, source, sLen, &status);
+ if(U_FAILURE(status)) { /* probably buffer is not big enough */
+ log_verbose("Src UTF-8 buffer too small! Will not compare!\n");
+ } else {
+ u_strToUTF8(utf8Target, 256, &utf8TargetLen, target, tLen, &status);
+ if(U_SUCCESS(status)) { /* probably buffer is not big enough */
+ UCollationResult compareResultUTF8 = result, compareResultUTF8Norm = result;
+ /*UCharIterator sIter, tIter;*/
+ /*log_verbose("Strings converted to UTF-8:%s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));*/
+ uiter_setUTF8(&sIter, utf8Source, utf8SourceLen);
+ uiter_setUTF8(&tIter, utf8Target, utf8TargetLen);
+ /*uiter_setString(&sIter, source, sLen);
+ uiter_setString(&tIter, target, tLen);*/
+ compareResultUTF8 = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ sIter.move(&sIter, 0, UITER_START);
+ tIter.move(&tIter, 0, UITER_START);
+ compareResultUTF8Norm = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
+ if(compareResultUTF8 != compareResultIter) {
+ log_err("different results in iterative comparison for UTF-16 and UTF-8 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
+ }
+ if(compareResultUTF8 != compareResultUTF8Norm) {
+ log_err("different results in iterative when normalization is turned on with UTF-8 strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
+ }
+ } else {
+ log_verbose("Target UTF-8 buffer too small! Did not compare!\n");
+ }
+ if(U_FAILURE(status)) {
+ log_verbose("UTF-8 strcoll failed! Ignoring result\n");
+ }
+ }
+ }
+
+ /* testing the partial sortkeys */
+ if(1) { /*!QUICK*/
+ int32_t i = 0;
+ int32_t partialSizes[] = { 3, 1, 2, 4, 8, 20, 80 }; /* just size 3 in the quick mode */
+ int32_t partialSizesSize = 1;
+ if(QUICK <= 0) {
+ partialSizesSize = 7;
+ }
+ /*log_verbose("partial sortkey test piecesize=");*/
+ for(i = 0; i < partialSizesSize; i++) {
+ UCollationResult partialSKResult = result, partialNormalizedSKResult = result;
+ /*log_verbose("%i ", partialSizes[i]);*/
+
+ partialSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
+ if(partialSKResult != result) {
+ log_err("Partial sortkey comparison returned wrong result (%i exp. %i): %s, %s (size %i)\n",
+ partialSKResult, result,
+ aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
+ }
+
+ if(QUICK <= 0 && norm != UCOL_ON) {
+ /*log_verbose("N ");*/
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ partialNormalizedSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
+ if(partialSKResult != partialNormalizedSKResult) {
+ log_err("Partial sortkey comparison gets different result when normalization is on: %s, %s (size %i)\n",
+ aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
+ }
+ }
+ }
+ /*log_verbose("\n");*/
+ }
+
+
+ compareResult = ucol_strcoll(myCollation, source, sLen, target, tLen);
+ compareResulta = ucol_strcoll(myCollation, source, -1, target, -1);
+ if (compareResult != compareResulta) {
+ log_err("ucol_strcoll result from null terminated and explicit length strings differs.\n");
+ }
+
+ sortklen1=ucol_getSortKey(myCollation, source, sLen, NULL, 0);
+ sortklen2=ucol_getSortKey(myCollation, target, tLen, NULL, 0);
+
+ sortklenmax = (sortklen1>sortklen2?sortklen1:sortklen2);
+ sortklenmin = (sortklen1<sortklen2?sortklen1:sortklen2);
+
+ sortKey1 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
+ sortKey1a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
+ ucol_getSortKey(myCollation, source, sLen, sortKey1, sortklen1+1);
+ ucol_getSortKey(myCollation, source, -1, sortKey1a, sortklen1+1);
+
+ sortKey2 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
+ sortKey2a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
+ ucol_getSortKey(myCollation, target, tLen, sortKey2, sortklen2+1);
+ ucol_getSortKey(myCollation, target, -1, sortKey2a, sortklen2+1);
+
+ /* Check that sort key generated with null terminated string is identical */
+ /* to that generted with a length specified. */
+ if (uprv_strcmp((const char *)sortKey1, (const char *)sortKey1a) != 0 ||
+ uprv_strcmp((const char *)sortKey2, (const char *)sortKey2a) != 0 ) {
+ log_err("Sort Keys from null terminated and explicit length strings differ.\n");
+ }
+
+ /*memcmp(sortKey1, sortKey2,sortklenmax);*/
+ temp= uprv_strcmp((const char *)sortKey1, (const char *)sortKey2);
+ gSortklen1 = uprv_strlen((const char *)sortKey1)+1;
+ gSortklen2 = uprv_strlen((const char *)sortKey2)+1;
+ if(sortklen1 != gSortklen1){
+ log_err("SortKey length does not match Expected: %i Got: %i\n",sortklen1, gSortklen1);
+ log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey1, buffer, &len));
+ }
+ if(sortklen2!= gSortklen2){
+ log_err("SortKey length does not match Expected: %i Got: %i\n", sortklen2, gSortklen2);
+ log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey2, buffer, &len));
+ }
+
+ if(temp < 0) {
+ keyResult=UCOL_LESS;
+ }
+ else if(temp > 0) {
+ keyResult= UCOL_GREATER;
+ }
+ else {
+ keyResult = UCOL_EQUAL;
+ }
+ reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResultIter, result );
+ free(sortKey1);
+ free(sortKey2);
+ free(sortKey1a);
+ free(sortKey2a);
+
+}
+
+void doTest(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
+{
+ if(myCollation) {
+ doTestVariant(myCollation, source, target, result);
+ if(result == UCOL_LESS) {
+ doTestVariant(myCollation, target, source, UCOL_GREATER);
+ } else if(result == UCOL_GREATER) {
+ doTestVariant(myCollation, target, source, UCOL_LESS);
+ } else {
+ doTestVariant(myCollation, target, source, UCOL_EQUAL);
+ }
+ } else {
+ log_data_err("No collator! Any data around?\n");
+ }
+}
+
+
+/**
+ * Return an integer array containing all of the collation orders
+ * returned by calls to next on the specified iterator
+ */
+int32_t* getOrders(UCollationElements *iter, int32_t *orderLength)
+{
+ UErrorCode status;
+ int32_t order;
+ int32_t maxSize = 100;
+ int32_t size = 0;
+ int32_t *temp;
+ int32_t *orders =(int32_t*)malloc(sizeof(int32_t) * maxSize);
+ status= U_ZERO_ERROR;
+
+
+ while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER)
+ {
+ if (size == maxSize)
+ {
+ maxSize *= 2;
+ temp = (int32_t*)malloc(sizeof(int32_t) * maxSize);
+
+ memcpy(temp, orders, size * sizeof(int32_t));
+ free(orders);
+ orders = temp;
+
+ }
+
+ orders[size++] = order;
+ }
+
+ if (maxSize > size && size > 0)
+ {
+ temp = (int32_t*)malloc(sizeof(int32_t) * size);
+
+ memcpy(temp, orders, size * sizeof(int32_t));
+ free(orders);
+ orders = temp;
+
+
+ }
+
+ *orderLength = size;
+ return orders;
+}
+
+
+void
+backAndForth(UCollationElements *iter)
+{
+ /* Run through the iterator forwards and stick it into an array */
+ int32_t index, o;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t orderLength = 0;
+ int32_t *orders;
+ orders= getOrders(iter, &orderLength);
+
+
+ /* Now go through it backwards and make sure we get the same values */
+ index = orderLength;
+ ucol_reset(iter);
+
+ /* synwee : changed */
+ while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER)
+ {
+ if (o != orders[-- index])
+ {
+ if (o == 0)
+ index ++;
+ else
+ {
+ while (index > 0 && orders[-- index] == 0)
+ {
+ }
+ if (o != orders[index])
+ {
+ log_err("Mismatch at index : 0x%x\n", index);
+ return;
+ }
+
+ }
+ }
+ }
+
+ while (index != 0 && orders[index - 1] == 0) {
+ index --;
+ }
+
+ if (index != 0)
+ {
+ log_err("Didn't get back to beginning - index is %d\n", index);
+
+ ucol_reset(iter);
+ log_err("\nnext: ");
+ if ((o = ucol_next(iter, &status)) != UCOL_NULLORDER)
+ {
+ log_err("Error at %x\n", o);
+ }
+ log_err("\nprev: ");
+ if ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER)
+ {
+ log_err("Error at %x\n", o);
+ }
+ log_verbose("\n");
+ }
+
+ free(orders);
+}
+
+void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result) {
+ UChar t1[2048] = {0};
+ UChar t2[2048] = {0};
+ UCollationElements *iter;
+ UErrorCode status = U_ZERO_ERROR;
+
+ uint32_t i = 0, j = 0;
+ log_verbose("testing sequence:\n");
+ for(i = 0; i < size; i++) {
+ log_verbose("%s\n", s[i]);
+ }
+
+ iter = ucol_openElements(coll, t1, u_strlen(t1), &status);
+ if (U_FAILURE(status)) {
+ log_err("Creation of iterator failed\n");
+ }
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ u_unescape(s[i], t1, 2048);
+ u_unescape(s[j], t2, 2048);
+ doTest(coll, t1, t2, result);
+ /* synwee : added collation element iterator test */
+ ucol_setText(iter, t1, u_strlen(t1), &status);
+ backAndForth(iter);
+ ucol_setText(iter, t2, u_strlen(t2), &status);
+ backAndForth(iter);
+ }
+ }
+ ucol_closeElements(iter);
+}
+
+void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size) {
+ genericOrderingTestWithResult(coll, s, size, UCOL_LESS);
+}
+
+void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size) {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open(locale, &status);
+
+ log_verbose("Locale starter for %s\n", locale);
+
+ if(U_SUCCESS(status)) {
+ genericOrderingTest(coll, s, size);
+ } else if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else {
+ log_err("Unable to open collator for locale %s\n", locale);
+ }
+ ucol_close(coll);
+}
+
+void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result) {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open(locale, &status);
+
+ log_verbose("Locale starter for %s\n", locale);
+
+ if(U_SUCCESS(status)) {
+ genericOrderingTestWithResult(coll, s, size, result);
+ } else if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else {
+ log_err("Unable to open collator for locale %s\n", locale);
+ }
+ ucol_close(coll);
+}
+
+/* currently not used with options */
+void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[RULE_BUFFER_LEN] = { 0 };
+ uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
+ uint32_t i;
+
+ UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
+
+ log_verbose("Rules starter for %s\n", rules);
+
+ if(U_SUCCESS(status)) {
+ log_verbose("Setting attributes\n");
+ for(i = 0; i < attsize; i++) {
+ ucol_setAttribute(coll, attrs[i], values[i], &status);
+ }
+
+ genericOrderingTestWithResult(coll, s, size, result);
+ } else {
+ log_err("Unable to open collator with rules %s\n", rules);
+ }
+ ucol_close(coll);
+}
+
+void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
+ UErrorCode status = U_ZERO_ERROR;
+ uint32_t i;
+
+ UCollator *coll = ucol_open(locale, &status);
+
+ log_verbose("Locale starter for %s\n", locale);
+
+ if(U_SUCCESS(status)) {
+
+ log_verbose("Setting attributes\n");
+ for(i = 0; i < attsize; i++) {
+ ucol_setAttribute(coll, attrs[i], values[i], &status);
+ }
+
+ genericOrderingTestWithResult(coll, s, size, result);
+ } else {
+ log_err("Unable to open collator for locale %s\n", locale);
+ }
+ ucol_close(coll);
+}
+
+void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize) {
+ genericLocaleStarterWithOptionsAndResult(locale, s, size, attrs, values, attsize, UCOL_LESS);
+}
+
+void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[RULE_BUFFER_LEN] = { 0 };
+ uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
+
+ UCollator *coll = NULL;
+ coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
+ log_verbose("Rules starter for %s\n", rules);
+
+ if(U_SUCCESS(status)) {
+ genericOrderingTestWithResult(coll, s, size, result);
+ ucol_close(coll);
+ } else if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ } else {
+ log_err("Unable to open collator with rules %s\n", rules);
+ }
+}
+
+void genericRulesStarter(const char *rules, const char * const s[], uint32_t size) {
+ genericRulesStarterWithResult(rules, s, size, UCOL_LESS);
+}
+
+static void TestTertiary()
+{
+ int32_t len,i;
+ UChar *rules;
+ UCollator *myCollation;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
+ len = strlen(str);
+ rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
+ u_uastrcpy(rules, str);
+
+ myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
+ }
+
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 17 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ free(rules);
+ ucol_close(myCollation);
+ myCollation = 0;
+}
+
+static void TestPrimary( )
+{
+ int32_t len,i;
+ UChar *rules;
+ UCollator *myCollation;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
+ len = strlen(str);
+ rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
+ u_uastrcpy(rules, str);
+
+ myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
+ }
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+
+ for (i = 17; i < 26 ; i++)
+ {
+
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ free(rules);
+ ucol_close(myCollation);
+ myCollation = 0;
+}
+
+static void TestSecondary()
+{
+ int32_t i;
+ int32_t len;
+ UChar *rules;
+ UCollator *myCollation;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
+ len = strlen(str);
+ rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
+ u_uastrcpy(rules, str);
+
+ myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
+ }
+ ucol_setStrength(myCollation, UCOL_SECONDARY);
+ for (i = 26; i < 34 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ free(rules);
+ ucol_close(myCollation);
+ myCollation = 0;
+}
+
+static void TestIdentical()
+{
+ int32_t i;
+ int32_t len;
+ UChar *rules = 0;
+ UCollator *myCollation;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
+ len = strlen(str);
+ rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
+ u_uastrcpy(rules, str);
+
+ myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_IDENTICAL, NULL,&status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
+ }
+ for(i= 34; i<37; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ free(rules);
+ ucol_close(myCollation);
+ myCollation = 0;
+}
+
+static void TestExtra()
+{
+ int32_t i, j;
+ int32_t len;
+ UChar *rules;
+ UCollator *myCollation;
+ UErrorCode status = U_ZERO_ERROR;
+ const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
+ len = strlen(str);
+ rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
+ u_uastrcpy(rules, str);
+
+ myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
+ }
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < COUNT_TEST_CASES-1 ; i++)
+ {
+ for (j = i + 1; j < COUNT_TEST_CASES; j += 1)
+ {
+
+ doTest(myCollation, testCases[i], testCases[j], UCOL_LESS);
+ }
+ }
+ free(rules);
+ ucol_close(myCollation);
+ myCollation = 0;
+}
+
+static void TestJB581(void)
+{
+ UChar dispName [100];
+ int32_t bufferLen = 0;
+ UChar source [100];
+ UChar target [100];
+ UCollationResult result = UCOL_EQUAL;
+ uint8_t sourceKeyArray [100];
+ uint8_t targetKeyArray [100];
+ int32_t sourceKeyOut = 0,
+ targetKeyOut = 0;
+ UCollator *myCollator = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ /*u_uastrcpy(source, "This is a test.");*/
+ /*u_uastrcpy(target, "THISISATEST.");*/
+ u_uastrcpy(source, "THISISATEST.");
+ u_uastrcpy(target, "Thisisatest.");
+
+ myCollator = ucol_open("en_US", &status);
+ if (U_FAILURE(status)){
+ bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status);
+ /*Report the error with display name... */
+ log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName);
+ return;
+ }
+ result = ucol_strcoll(myCollator, source, -1, target, -1);
+ /* result is 1, secondary differences only for ignorable space characters*/
+ if (result != 1)
+ {
+ log_err("Comparing two strings with only secondary differences in C failed.\n");
+ }
+ /* To compare them with just primary differences */
+ ucol_setStrength(myCollator, UCOL_PRIMARY);
+ result = ucol_strcoll(myCollator, source, -1, target, -1);
+ /* result is 0 */
+ if (result != 0)
+ {
+ log_err("Comparing two strings with no differences in C failed.\n");
+ }
+ /* Now, do the same comparison with keys */
+ sourceKeyOut = ucol_getSortKey(myCollator, source, -1, sourceKeyArray, 100);
+ targetKeyOut = ucol_getSortKey(myCollator, target, -1, targetKeyArray, 100);
+ bufferLen = ((targetKeyOut > 100) ? 100 : targetKeyOut);
+ if (memcmp(sourceKeyArray, targetKeyArray, bufferLen) != 0)
+ {
+ log_err("Comparing two strings with sort keys in C failed.\n");
+ }
+ ucol_close(myCollator);
+}
+
+static void TestJB1401(void)
+{
+ UCollator *myCollator = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ static UChar NFD_UnsafeStartChars[] = {
+ 0x0f73, /* Tibetan Vowel Sign II */
+ 0x0f75, /* Tibetan Vowel Sign UU */
+ 0x0f81, /* Tibetan Vowel Sign Reversed II */
+ 0
+ };
+ int i;
+
+
+ myCollator = ucol_open("en_US", &status);
+ if (U_FAILURE(status)){
+ int32_t bufferLen = 0;
+ UChar dispName [100];
+ bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status);
+ /*Report the error with display name... */
+ log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName);
+ return;
+ }
+ ucol_setAttribute(myCollator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: Failed to set normalization mode ON for collator.\n");
+ return;
+ }
+
+ for (i=0; ; i++) {
+ UChar c;
+ UChar X[4];
+ UChar Y[20];
+ UChar Z[20];
+
+ /* Get the next funny character to be tested, and set up the
+ * three test strings X, Y, Z, consisting of an A-grave + test char,
+ * in original form, NFD, and then NFC form.
+ */
+ c = NFD_UnsafeStartChars[i];
+ if (c==0) {break;}
+
+ X[0]=0xC0; X[1]=c; X[2]=0; /* \u00C0 is A Grave*/
+
+ unorm_normalize(X, -1, UNORM_NFD, 0, Y, 20, &status);
+ unorm_normalize(Y, -1, UNORM_NFC, 0, Z, 20, &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: Failed to normalize test of character %x\n", c);
+ return;
+ }
+
+ /* Collation test. All three strings should be equal.
+ * doTest does both strcoll and sort keys, with params in both orders.
+ */
+ doTest(myCollator, X, Y, UCOL_EQUAL);
+ doTest(myCollator, X, Z, UCOL_EQUAL);
+ doTest(myCollator, Y, Z, UCOL_EQUAL);
+
+ /* Run collation element iterators over the three strings. Results should be same for each.
+ */
+ {
+ UCollationElements *ceiX, *ceiY, *ceiZ;
+ int32_t ceX, ceY, ceZ;
+ int j;
+
+ ceiX = ucol_openElements(myCollator, X, -1, &status);
+ ceiY = ucol_openElements(myCollator, Y, -1, &status);
+ ceiZ = ucol_openElements(myCollator, Z, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: uucol_openElements failed.\n");
+ return;
+ }
+
+ for (j=0;; j++) {
+ ceX = ucol_next(ceiX, &status);
+ ceY = ucol_next(ceiY, &status);
+ ceZ = ucol_next(ceiZ, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
+ break;
+ }
+ if (ceX != ceY || ceY != ceZ) {
+ log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
+ break;
+ }
+ if (ceX == UCOL_NULLORDER) {
+ break;
+ }
+ }
+ ucol_closeElements(ceiX);
+ ucol_closeElements(ceiY);
+ ucol_closeElements(ceiZ);
+ }
+ }
+ ucol_close(myCollator);
+}
+
+
+
+/**
+* Tests the [variable top] tag in rule syntax. Since the default [alternate]
+* tag has the value shifted, any codepoints before [variable top] should give
+* a primary ce of 0.
+*/
+static void TestVariableTop(void)
+{
+ const char *str = "&z = [variable top]";
+ int len = strlen(str);
+ UChar *rules;
+ UCollator *myCollation;
+ UCollator *enCollation;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar source[1];
+ UChar ch;
+ uint8_t result[20];
+ uint8_t expected[20];
+
+ rules = (UChar*)malloc(sizeof(UChar*) * (len + 1));
+ u_uastrcpy(rules, str);
+
+ enCollation = ucol_open("en_US", &status);
+ myCollation = ucol_openRules(rules, len, UCOL_OFF,
+ UCOL_PRIMARY,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: in creation of rule based collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+
+ ucol_setStrength(enCollation, UCOL_PRIMARY);
+ ucol_setAttribute(enCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
+ &status);
+ ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
+ &status);
+
+ if (ucol_getAttribute(myCollation, UCOL_ALTERNATE_HANDLING, &status) !=
+ UCOL_SHIFTED || U_FAILURE(status)) {
+ log_err("ERROR: ALTERNATE_HANDLING value can not be set to SHIFTED\n");
+ }
+
+ uprv_memset(expected, 0, 20);
+
+ /* space is supposed to be a variable */
+ source[0] = ' ';
+ len = ucol_getSortKey(enCollation, source, 1, result,
+ sizeof(result));
+
+ if (uprv_memcmp(expected, result, len) != 0) {
+ log_err("ERROR: SHIFTED alternate does not return 0 for primary of space\n");
+ }
+
+ ch = 'a';
+ while (ch < 'z') {
+ source[0] = ch;
+ len = ucol_getSortKey(myCollation, source, 1, result,
+ sizeof(result));
+ if (uprv_memcmp(expected, result, len) != 0) {
+ log_err("ERROR: SHIFTED alternate does not return 0 for primary of %c\n",
+ ch);
+ }
+ ch ++;
+ }
+
+ free(rules);
+ ucol_close(enCollation);
+ ucol_close(myCollation);
+ enCollation = NULL;
+ myCollation = NULL;
+}
+
+/**
+ * Tests surrogate support.
+ * NOTE: This test used \\uD801\\uDC01 pair, which is now assigned to Desseret
+ * Therefore, another (unassigned) code point was used for this test.
+ */
+static void TestSurrogates(void)
+{
+ const char *str =
+ "&z<'\\uD800\\uDC00'<'\\uD800\\uDC0A\\u0308'<A";
+ int len = strlen(str);
+ int rlen = 0;
+ UChar *rules;
+ UCollator *myCollation;
+ UCollator *enCollation;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar source[][4] =
+ {{'z', 0, 0}, {0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {0xD800, 0xDC02}};
+ UChar target[][4] =
+ {{0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {'A', 0, 0}, {0xD800, 0xDC03}};
+ int count = 0;
+ uint8_t enresult[20], myresult[20];
+ int enlen, mylen;
+
+ /* tests for open rules with surrogate rules */
+ rules = (UChar*)malloc(sizeof(UChar*) * (len + 1));
+ rlen = u_unescape(str, rules, len);
+
+ enCollation = ucol_open("en_US", &status);
+ myCollation = ucol_openRules(rules, rlen, UCOL_OFF,
+ UCOL_TERTIARY,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: in creation of rule based collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+
+ /*
+ this test is to verify the supplementary sort key order in the english
+ collator
+ */
+ log_verbose("start of english collation supplementary characters test\n");
+ while (count < 2) {
+ doTest(enCollation, source[count], target[count], UCOL_LESS);
+ count ++;
+ }
+ doTest(enCollation, source[count], target[count], UCOL_GREATER);
+
+ log_verbose("start of tailored collation supplementary characters test\n");
+ count = 0;
+ /* tests getting collation elements for surrogates for tailored rules */
+ while (count < 4) {
+ doTest(myCollation, source[count], target[count], UCOL_LESS);
+ count ++;
+ }
+
+ /* tests that \uD800\uDC02 still has the same value, not changed */
+ enlen = ucol_getSortKey(enCollation, source[3], 2, enresult, 20);
+ mylen = ucol_getSortKey(myCollation, source[3], 2, myresult, 20);
+ if (enlen != mylen ||
+ uprv_memcmp(enresult, myresult, enlen) != 0) {
+ log_verbose("Failed : non-tailored supplementary characters should have the same value\n");
+ }
+
+ free(rules);
+ ucol_close(enCollation);
+ ucol_close(myCollation);
+ enCollation = NULL;
+ myCollation = NULL;
+}
+
+/*
+ *### TODO: Add more invalid rules to test all different scenarios.
+ *
+ */
+static void
+TestInvalidRules(){
+#define MAX_ERROR_STATES 2
+
+ static const char* rulesArr[MAX_ERROR_STATES] = {
+ "& C < ch, cH, Ch[this should fail]<d",
+ "& C < ch, cH, & Ch[variable top]"
+ };
+ static const char* preContextArr[MAX_ERROR_STATES] = {
+ "his should fail",
+ "& C < ch, cH, ",
+
+ };
+ static const char* postContextArr[MAX_ERROR_STATES] = {
+ "<d",
+ " Ch[variable t"
+ };
+ int i;
+
+ for(i = 0;i<MAX_ERROR_STATES;i++){
+ UChar rules[1000] = { '\0' };
+ UChar preContextExp[1000] = { '\0' };
+ UChar postContextExp[1000] = { '\0' };
+ UParseError parseError;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator* coll=0;
+ u_charsToUChars(rulesArr[i],rules,uprv_strlen(rulesArr[i])+1);
+ u_charsToUChars(preContextArr[i],preContextExp,uprv_strlen(preContextArr[i])+1);
+ u_charsToUChars(postContextArr[i],postContextExp,uprv_strlen(postContextArr[i])+1);
+ /* clean up stuff in parseError */
+ u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
+ u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
+ /* open the rules and test */
+ coll = ucol_openRules(rules,u_strlen(rules),UCOL_OFF,UCOL_DEFAULT_STRENGTH,&parseError,&status);
+ if(u_strcmp(parseError.preContext,preContextExp)!=0){
+ log_err("preContext in UParseError for ucol_openRules does not match\n");
+ }
+ if(u_strcmp(parseError.postContext,postContextExp)!=0){
+ log_err("postContext in UParseError for ucol_openRules does not match\n");
+ }
+ }
+}
+
+static void
+TestJitterbug1098(){
+ UChar rule[1000];
+ UCollator* c1 = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+ char preContext[200]={0};
+ char postContext[200]={0};
+ int i=0;
+ const char* rules[] = {
+ "&''<\\\\",
+ "&\\'<\\\\",
+ "&\\\"<'\\'",
+ "&'\"'<\\'",
+ '\0'
+
+ };
+ const UCollationResult results1098[] = {
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ };
+ const UChar input[][2]= {
+ {0x0027,0x005c},
+ {0x0027,0x005c},
+ {0x0022,0x005c},
+ {0x0022,0x0027},
+ };
+ UChar X[2] ={0};
+ UChar Y[2] ={0};
+ u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
+ u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
+ for(;rules[i]!=0;i++){
+ u_uastrcpy(rule, rules[i]);
+ c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, &parseError, &status);
+ if(U_FAILURE(status)){
+ log_err("Could not parse the rules syntax. Error: %s ", u_errorName(status));
+
+ if (status == U_PARSE_ERROR) {
+ u_UCharsToChars(parseError.preContext,preContext,20);
+ u_UCharsToChars(parseError.postContext,postContext,20);
+ log_verbose("\n\tPre-Context: %s \n\tPost-Context:%s \n",preContext,postContext);
+ }
+
+ return;
+ }
+ X[0] = input[i][0];
+ Y[0] = input[i][1];
+ doTest(c1,X,Y,results1098[i]);
+ ucol_close(c1);
+ }
+}
+
+/* These tests do cleanup and reinitialize ICU in the course of their operation.
+ * The ICU data directory must be preserved across these operations.
+ * Here is a helper function to assist with that.
+ */
+static char *safeGetICUDataDirectory() {
+ const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */
+ char *retStr = NULL;
+ if (dataDir != NULL) {
+ retStr = (char *)malloc(strlen(dataDir)+1);
+ strcpy(retStr, dataDir);
+ }
+ return retStr;
+}
+
+
+static void
+TestFCDCrash(void) {
+ static const char *test[] = {
+ "Gr\\u00F6\\u00DFe",
+ "Grossist"
+ };
+
+ char *icuDataDir = safeGetICUDataDirectory();
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("es", &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't open collator\n");
+ return;
+ }
+ ucol_close(coll);
+ coll = NULL;
+ u_cleanup();
+ u_setDataDirectory(icuDataDir);
+ coll = ucol_open("de_DE", &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't open collator\n");
+ return;
+ }
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ genericOrderingTest(coll, test, 2);
+ ucol_close(coll);
+ free(icuDataDir);
+
+}
+
+/*static UBool
+find(UEnumeration* list, const char* str, UErrorCode* status){
+ const char* value = NULL;
+ int32_t length=0;
+ if(U_FAILURE(*status)){
+ return FALSE;
+ }
+ uenum_reset(list, status);
+ while( (value= uenum_next(list, &length, status))!=NULL){
+ if(strcmp(value, str)==0){
+ return TRUE;
+ }
+ }
+ return FALSE;
+}*/
+
+static void TestJ5298(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ char input[256], output[256];
+ UBool isAvailable;
+ int32_t i = 0;
+ UEnumeration* values = NULL;
+ const char *keywordValue = NULL;
+ log_verbose("Number of collator locales returned : %i \n", ucol_countAvailable());
+ values = ucol_getKeywordValues("collation", &status);
+ for (i = 0; i < ucol_countAvailable(); i++) {
+ uenum_reset(values, &status);
+ while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) {
+ strcpy(input, ucol_getAvailable(i));
+ if (strcmp(keywordValue, "standard") != 0) {
+ strcat(input, "@collation=");
+ strcat(input, keywordValue);
+ }
+
+ ucol_getFunctionalEquivalent(output, 256, "collation", input, &isAvailable, &status);
+ if (strcmp(input, output) == 0) { /* Unique locale, print it out */
+ log_verbose("%s, \n", output);
+ }
+ }
+ }
+ uenum_close(values);
+ log_verbose("\n");
+}
+#endif /* #if !UCONFIG_NO_COLLATION */
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h
new file mode 100644
index 00000000000..ae07b1257ab
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/callcoll.h
@@ -0,0 +1,54 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CALLCOLL.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported to C
+*********************************************************************************
+*/
+/**
+ * CollationDummyTest is a third level test class. This tests creation of
+ * a customized collator object. For example, number 1 to be sorted
+ * equlivalent to word 'one'.
+ */
+#ifndef _CALLCOLLTST
+#define _CALLCOLLTST
+
+#include "unicode/utypes.h"
+#include "unicode/ucoleitr.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define RULE_BUFFER_LEN 8192
+
+
+ /* tests comparison of custom collation with different strengths */
+void doTest(UCollator*, const UChar* source, const UChar* target, UCollationResult result);
+/* verify that iterating forward and backwards over the string yields same CEs */
+void backAndForth(UCollationElements *iter);
+/* gets an array of CEs for a string in UCollationElements iterator. */
+int32_t* getOrders(UCollationElements *iter, int32_t *orderLength);
+
+void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result);
+void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size);
+void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size);
+void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result);
+void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize);
+void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result);
+void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result);
+void genericRulesStarter(const char *rules, const char * const s[], uint32_t size);
+void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result);
+UBool hasCollationElements(const char *locName);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h b/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h
new file mode 100644
index 00000000000..4d3cb3983d2
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/calldata.h
@@ -0,0 +1,109 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+#ifndef COLLATION_TEST_DATA
+#define COLLATION_TEST_DATA
+
+#define COUNT_TEST_CASES 13
+
+const UChar testSourceCases[][16] = {
+ {0x61, 0x62, 0x27, 0x63, 0},
+ {0x63, 0x6f, 0x2d, 0x6f, 0x70, 0},
+ {0x61, 0x62, 0},
+ {0x61, 0x6d, 0x70, 0x65, 0x72, 0x73, 0x61, 0x64, 0},
+ {0x61, 0x6c, 0x6c, 0},
+ {0x66, 0x6f, 0x75, 0x72, 0},
+ {0x66, 0x69, 0x76, 0x65, 0},
+ {0x31, 0},
+ {0x31, 0},
+ {0x31, 0}, /* 10 */
+ {0x32, 0},
+ {0x32, 0},
+ {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0},
+ {0x61, 0x3c, 0x62, 0},
+ {0x61, 0x3c, 0x62, 0},
+ {0x61, 0x63, 0x63, 0},
+ {0x61, 0x63, 0x48, 0x63, 0}, /* simple test */
+ {0x70, 0x00EA, 0x63, 0x68, 0x65, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x62, 0x63, 0}, /* 20 */
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x00E6, 0x63, 0},
+ {0x61, 0x63, 0x48, 0x63, 0}, /* primary test */
+ {0x62, 0x6c, 0x61, 0x63, 0x6b, 0},
+ {0x66, 0x6f, 0x75, 0x72, 0},
+ {0x66, 0x69, 0x76, 0x65, 0},
+ {0x31, 0},
+ {0x61, 0x62, 0x63, 0}, /* 30 */
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x62, 0x63, 0x48, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x63, 0x48, 0x63, 0}, /* 34 */
+ {0x61, 0x63, 0x65, 0x30},
+ {0x31, 0x30},
+ {0x70, 0x00EA,0x30} /* 37 */
+};
+
+const UChar testTargetCases[][16] = {
+ {0x61, 0x62, 0x63, 0x27, 0},
+ {0x43, 0x4f, 0x4f, 0x50, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x26, 0},
+ {0x26, 0},
+ {0x34, 0},
+ {0x35, 0},
+ {0x6f, 0x6e, 0x65, 0},
+ {0x6e, 0x6e, 0x65, 0},
+ {0x70, 0x6e, 0x65, 0}, /* 10 */
+ {0x74, 0x77, 0x6f, 0},
+ {0x75, 0x77, 0x6f, 0},
+ {0x68, 0x65, 0x6c, 0x6c, 0x4f, 0},
+ {0x61, 0x3c, 0x3d, 0x62, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x43, 0x48, 0x63, 0},
+ {0x61, 0x43, 0x48, 0x63, 0}, /* simple test */
+ {0x70, (UChar)0x00E9, 0x63, 0x68, 0x00E9, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x42, 0x43, 0}, /* 20 */
+ {0x61, 0x62, 0x63, 0x68, 0},
+ {0x61, 0x62, 0x64, 0},
+ {(UChar)0x00E4, 0x62, 0x63, 0},
+ {0x61, (UChar)0x00C6, 0x63, 0},
+ {0x61, 0x43, 0x48, 0x63, 0}, /* primary test */
+ {0x62, 0x6c, 0x61, 0x63, 0x6b, 0x2d, 0x62, 0x69, 0x72, 0x64, 0},
+ {0x34, 0},
+ {0x35, 0},
+ {0x6f, 0x6e, 0x65, 0},
+ {0x61, 0x62, 0x63, 0},
+ {0x61, 0x42, 0x63, 0}, /* 30 */
+ {0x61, 0x62, 0x63, 0x68, 0},
+ {0x61, 0x62, 0x64, 0},
+ {0x61, 0x43, 0x48, 0x63, 0}, /* 34 */
+ {0x61, 0x63, 0x65, 0x30},
+ {0x31, 0x30},
+ {0x70, (UChar)0x00EB,0x30} /* 37 */
+};
+
+const UChar testCases[][4] =
+{
+ {0x61, 0},
+ {0x41, 0},
+ {0x00e4, 0},
+ {0x00c4, 0},
+ {0x61, 0x65, 0},
+ {0x61, 0x45, 0},
+ {0x41, 0x65, 0},
+ {0x41, 0x45, 0},
+ {(UChar)0x00e6, 0},
+ {(UChar)0x00c6, 0},
+ {0x62, 0},
+ {0x63, 0},
+ {0x7a, 0}
+};
+
+#endif /* #ifndef COLLATION_TEST_DATA */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c
new file mode 100644
index 00000000000..8e5f192dbe1
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/calltest.c
@@ -0,0 +1,78 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1996-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CALLTEST.C
+*
+* Modification History:
+* Creation: Madhu Katragadda
+*********************************************************************************
+*/
+/* THE FILE WHERE ALL C API TESTS ARE ADDED TO THE ROOT */
+
+
+#include "cintltst.h"
+
+void addUtility(TestNode** root);
+void addBreakIter(TestNode** root);
+void addStandardNamesTest(TestNode **root);
+void addFormatTest(TestNode** root);
+void addConvert(TestNode** root);
+void addCollTest(TestNode** root);
+void addComplexTest(TestNode** root);
+void addUDataTest(TestNode** root);
+void addUTF16Test(TestNode** root);
+void addUTF8Test(TestNode** root);
+void addUTransTest(TestNode** root);
+void addPUtilTest(TestNode** root);
+void addUCharTransformTest(TestNode** root);
+void addUSetTest(TestNode** root);
+void addUStringPrepTest(TestNode** root);
+void addIDNATest(TestNode** root);
+void addHeapMutexTest(TestNode **root);
+void addUTraceTest(TestNode** root);
+void addURegexTest(TestNode** root);
+void addUTextTest(TestNode** root);
+void addUCsdetTest(TestNode** root);
+
+
+void addAllTests(TestNode** root)
+{
+ addUDataTest(root);
+ addHeapMutexTest(root);
+ addPUtilTest(root);
+ addUTF16Test(root);
+ addUTF8Test(root);
+ addUtility(root);
+ addUTraceTest(root);
+ addUTextTest(root);
+ addConvert(root);
+ addUCharTransformTest(root);
+ addStandardNamesTest(root);
+ addUCsdetTest(root);
+ addComplexTest(root);
+ addUSetTest(root);
+#if !UCONFIG_NO_IDNA
+ addUStringPrepTest(root);
+ addIDNATest(root);
+#endif
+#if !UCONFIG_NO_REGULAR_EXPRESSIONS
+ addURegexTest(root);
+#endif
+#if !UCONFIG_NO_BREAK_ITERATION
+ addBreakIter(root);
+#endif
+#if !UCONFIG_NO_FORMATTING
+ addFormatTest(root);
+#endif
+#if !UCONFIG_NO_COLLATION
+ addCollTest(root);
+#endif
+#if !UCONFIG_NO_TRANSLITERATION
+ addUTransTest(root);
+#endif
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c
new file mode 100644
index 00000000000..db1de56f54a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.c
@@ -0,0 +1,2148 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CAPITEST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************
+*//* C API TEST For COLLATOR */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/uloc.h"
+#include "unicode/ustring.h"
+#include "unicode/ures.h"
+#include "unicode/ucoleitr.h"
+#include "cintltst.h"
+#include "capitst.h"
+#include "ccolltst.h"
+#include "putilimp.h"
+
+static void TestAttribute(void);
+static void TestDefault(void);
+ int TestBufferSize(); /* defined in "colutil.c" */
+
+
+
+
+/* next two function is modified from "i18n/ucol.cpp" to avoid include "ucol_imp.h" */
+static void uprv_appendByteToHexString(char *dst, uint8_t val) {
+ uint32_t len = (uint32_t)strlen(dst);
+ sprintf(dst+len, "%02X", val);
+}
+
+static char* U_EXPORT2 ucol_sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) {
+ int32_t strength = UCOL_PRIMARY;
+ uint32_t res_size = 0;
+ UBool doneCase = FALSE;
+
+ char *current = buffer;
+ const uint8_t *currentSk = sortkey;
+
+ UErrorCode error_code = U_ZERO_ERROR;
+
+ strcpy(current, "[");
+
+ while(strength <= UCOL_QUATERNARY && strength <= ucol_getAttribute(coll,UCOL_STRENGTH, &error_code)) {
+ if(U_FAILURE(error_code)) {
+ log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code));
+ }
+ if(strength > UCOL_PRIMARY) {
+ strcat(current, " . ");
+ }
+ while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */
+ uprv_appendByteToHexString(current, *currentSk++);
+ strcat(current, " ");
+ }
+ if(ucol_getAttribute(coll,UCOL_CASE_LEVEL, &error_code) == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) {
+ doneCase = TRUE;
+ } else if(ucol_getAttribute(coll,UCOL_CASE_LEVEL, &error_code) == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) {
+ strength ++;
+ }
+ if(U_FAILURE(error_code)) {
+ log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code));
+ }
+ uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */
+ if(strength == UCOL_QUATERNARY && ucol_getAttribute(coll,UCOL_ALTERNATE_HANDLING, &error_code) == UCOL_NON_IGNORABLE) {
+ break;
+ }
+ }
+
+ if(ucol_getAttribute(coll,UCOL_STRENGTH, &error_code) == UCOL_IDENTICAL) {
+ strcat(current, " . ");
+ while(*currentSk != 0) {
+ uprv_appendByteToHexString(current, *currentSk++);
+ strcat(current, " ");
+ }
+
+ uprv_appendByteToHexString(current, *currentSk++);
+ }
+ if(U_FAILURE(error_code)) {
+ log_err("ucol_getAttribute returned error: %s\n", u_errorName(error_code));
+ }
+ strcat(current, "]");
+
+ if(res_size > *len) {
+ return NULL;
+ }
+
+ return buffer;
+}
+/* end of avoid include "ucol_imp.h" */
+
+
+void addCollAPITest(TestNode** root)
+{
+ /* WEIVTODO: return tests here */
+ addTest(root, &TestProperty, "tscoll/capitst/TestProperty");
+ addTest(root, &TestRuleBasedColl, "tscoll/capitst/TestRuleBasedColl");
+ addTest(root, &TestCompare, "tscoll/capitst/TestCompare");
+ addTest(root, &TestSortKey, "tscoll/capitst/TestSortKey");
+ addTest(root, &TestHashCode, "tscoll/capitst/TestHashCode");
+ addTest(root, &TestElemIter, "tscoll/capitst/TestElemIter");
+ addTest(root, &TestGetAll, "tscoll/capitst/TestGetAll");
+ /*addTest(root, &TestGetDefaultRules, "tscoll/capitst/TestGetDefaultRules");*/
+ addTest(root, &TestDecomposition, "tscoll/capitst/TestDecomposition");
+ addTest(root, &TestSafeClone, "tscoll/capitst/TestSafeClone");
+ addTest(root, &TestCloneBinary, "tscoll/capitst/TestCloneBinary");
+ addTest(root, &TestGetSetAttr, "tscoll/capitst/TestGetSetAttr");
+ addTest(root, &TestBounds, "tscoll/capitst/TestBounds");
+ addTest(root, &TestGetLocale, "tscoll/capitst/TestGetLocale");
+ addTest(root, &TestSortKeyBufferOverrun, "tscoll/capitst/TestSortKeyBufferOverrun");
+ addTest(root, &TestAttribute, "tscoll/capitst/TestAttribute");
+ addTest(root, &TestGetTailoredSet, "tscoll/capitst/TestGetTailoredSet");
+ addTest(root, &TestMergeSortKeys, "tscoll/capitst/TestMergeSortKeys");
+ addTest(root, &TestShortString, "tscoll/capitst/TestShortString");
+ addTest(root, &TestGetContractionsAndUnsafes, "tscoll/capitst/TestGetContractionsAndUnsafes");
+ addTest(root, &TestOpenBinary, "tscoll/capitst/TestOpenBinary");
+ addTest(root, &TestDefault, "tscoll/capitst/TestDefault");
+}
+
+void TestGetSetAttr(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open(NULL, &status);
+ struct attrTest {
+ UColAttribute att;
+ UColAttributeValue val[5];
+ uint32_t valueSize;
+ UColAttributeValue nonValue;
+ } attrs[] = {
+ {UCOL_FRENCH_COLLATION, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},
+ {UCOL_ALTERNATE_HANDLING, {UCOL_NON_IGNORABLE, UCOL_SHIFTED}, 2, UCOL_OFF},/* attribute for handling variable elements*/
+ {UCOL_CASE_FIRST, {UCOL_OFF, UCOL_LOWER_FIRST, UCOL_UPPER_FIRST}, 3, UCOL_SHIFTED},/* who goes first, lower case or uppercase */
+ {UCOL_CASE_LEVEL, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* do we have an extra case level */
+ {UCOL_NORMALIZATION_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* attribute for normalization */
+ {UCOL_DECOMPOSITION_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},
+ {UCOL_STRENGTH, {UCOL_PRIMARY, UCOL_SECONDARY, UCOL_TERTIARY, UCOL_QUATERNARY, UCOL_IDENTICAL}, 5, UCOL_SHIFTED},/* attribute for strength */
+ {UCOL_HIRAGANA_QUATERNARY_MODE, {UCOL_ON, UCOL_OFF}, 2, UCOL_SHIFTED},/* when turned on, this attribute */
+ };
+ UColAttribute currAttr;
+ UColAttributeValue value;
+ uint32_t i = 0, j = 0;
+
+ for(i = 0; i<sizeof(attrs)/sizeof(attrs[0]); i++) {
+ currAttr = attrs[i].att;
+ ucol_setAttribute(coll, currAttr, UCOL_DEFAULT, &status);
+ if(U_FAILURE(status)) {
+ log_err("ucol_setAttribute with the default value returned error: %s\n", u_errorName(status));
+ break;
+ }
+ value = ucol_getAttribute(coll, currAttr, &status);
+ if(U_FAILURE(status)) {
+ log_err("ucol_getAttribute returned error: %s\n", u_errorName(status));
+ break;
+ }
+ for(j = 0; j<attrs[i].valueSize; j++) {
+ ucol_setAttribute(coll, currAttr, attrs[i].val[j], &status);
+ if(U_FAILURE(status)) {
+ log_err("ucol_setAttribute with the value %i returned error: %s\n", attrs[i].val[j], u_errorName(status));
+ break;
+ }
+ }
+ status = U_ZERO_ERROR;
+ ucol_setAttribute(coll, currAttr, attrs[i].nonValue, &status);
+ if(U_SUCCESS(status)) {
+ log_err("ucol_setAttribute with the bad value didn't return an error\n");
+ break;
+ }
+ status = U_ZERO_ERROR;
+
+ ucol_setAttribute(coll, currAttr, value, &status);
+ if(U_FAILURE(status)) {
+ log_err("ucol_setAttribute with the default valuereturned error: %s\n", u_errorName(status));
+ break;
+ }
+
+ }
+ status = U_ZERO_ERROR;
+ value = ucol_getAttribute(coll, UCOL_ATTRIBUTE_COUNT, &status);
+ if(U_SUCCESS(status)) {
+ log_err("ucol_getAttribute for UCOL_ATTRIBUTE_COUNT didn't return an error\n");
+ }
+ status = U_ZERO_ERROR;
+ ucol_setAttribute(coll, UCOL_ATTRIBUTE_COUNT, UCOL_DEFAULT, &status);
+ if(U_SUCCESS(status)) {
+ log_err("ucol_setAttribute for UCOL_ATTRIBUTE_COUNT didn't return an error\n");
+ }
+ status = U_ZERO_ERROR;
+ ucol_close(coll);
+}
+
+
+static void doAssert(int condition, const char *message)
+{
+ if (condition==0) {
+ log_err("ERROR : %s\n", message);
+ }
+}
+
+#if 0
+/* We don't have default rules, at least not in the previous sense */
+void TestGetDefaultRules(){
+ uint32_t size=0;
+ UErrorCode status=U_ZERO_ERROR;
+ UCollator *coll=NULL;
+ int32_t len1 = 0, len2=0;
+ uint8_t *binColData = NULL;
+
+ UResourceBundle *res = NULL;
+ UResourceBundle *binColl = NULL;
+ uint8_t *binResult = NULL;
+
+
+ const UChar * defaultRulesArray=ucol_getDefaultRulesArray(&size);
+ log_verbose("Test the function ucol_getDefaultRulesArray()\n");
+
+ coll = ucol_openRules(defaultRulesArray, size, UCOL_ON, UCOL_PRIMARY, &status);
+ if(U_SUCCESS(status) && coll !=NULL) {
+ binColData = (uint8_t*)ucol_cloneRuleData(coll, &len1, &status);
+
+ }
+
+
+ status=U_ZERO_ERROR;
+ res=ures_open(NULL, "root", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: Failed to get resource for \"root Locale\" with %s", myErrorName(status));
+ return;
+ }
+ binColl=ures_getByKey(res, "%%Collation", binColl, &status);
+ if(U_SUCCESS(status)){
+ binResult=(uint8_t*)ures_getBinary(binColl, &len2, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_getBinary() failed\n");
+ }
+ }else{
+ log_err("ERROR: ures_getByKey(locale(default), %%Collation) failed");
+ }
+
+
+ if(len1 != len2){
+ log_err("Error: ucol_getDefaultRulesArray() failed to return the correct length.\n");
+ }
+ if(memcmp(binColData, binResult, len1) != 0){
+ log_err("Error: ucol_getDefaultRulesArray() failed\n");
+ }
+
+ free(binColData);
+ ures_close(binColl);
+ ures_close(res);
+ ucol_close(coll);
+
+}
+#endif
+
+/* Collator Properties
+ ucol_open, ucol_strcoll, getStrength/setStrength
+ getDecomposition/setDecomposition, getDisplayName*/
+void TestProperty()
+{
+ UCollator *col, *ruled;
+ UChar *disName;
+ int32_t len = 0, i = 0;
+ UChar *source, *target;
+ int32_t tempLength;
+ UErrorCode status = U_ZERO_ERROR;
+ /*
+ All the collations have the same version in an ICU
+ version.
+ ICU 2.0 currVersionArray = {0x18, 0xC0, 0x02, 0x02};
+ ICU 2.1 currVersionArray = {0x19, 0x00, 0x03, 0x03};
+ ICU 2.2 currVersionArray = {0x21, 0x40, 0x04, 0x04};
+ ICU 2.4 currVersionArray = {0x21, 0x40, 0x04, 0x04};
+ ICU 2.6 currVersionArray = {0x21, 0x40, 0x03, 0x03};
+ ICU 2.8 currVersionArray = {0x29, 0x80, 0x00, 0x04};
+ ICU 3.4 currVersionArray = {0x31, 0xC0, 0x00, 0x04};
+ */
+ UVersionInfo currVersionArray = {0x31, 0xC0, 0x00, 0x05};
+ /* ICU 3.4 had UCA 4.1 */
+ /*UVersionInfo currUCAVersionArray = {4, 1, 0, 0};*/
+ UVersionInfo currUCAVersionArray = {5, 0, 0, 0};
+ UVersionInfo versionArray = {0, 0, 0, 0};
+ UVersionInfo versionUCAArray = {0, 0, 0, 0};
+
+ log_verbose("The property tests begin : \n");
+ log_verbose("Test ucol_strcoll : \n");
+ col = ucol_open("en_US", &status);
+ if (U_FAILURE(status)) {
+ log_err("Default Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+
+ ucol_getVersion(col, versionArray);
+ for (i=0; i<4; ++i) {
+ if (versionArray[i] != currVersionArray[i]) {
+ log_err("Testing ucol_getVersion() - unexpected result: %hu.%hu.%hu.%hu\n",
+ versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
+ break;
+ }
+ }
+
+ ucol_getUCAVersion(col, versionUCAArray);
+ for (i=0; i<4; ++i) {
+ if (versionUCAArray[i] != currUCAVersionArray[i]) {
+ log_err("Testing ucol_getUCAVersion() - unexpected result: %hu.%hu.%hu.%hu\n",
+ versionUCAArray[0], versionUCAArray[1], versionUCAArray[2], versionUCAArray[3]);
+ break;
+ }
+ }
+
+ source=(UChar*)malloc(sizeof(UChar) * 12);
+ target=(UChar*)malloc(sizeof(UChar) * 12);
+
+
+ u_uastrcpy(source, "ab");
+ u_uastrcpy(target, "abc");
+
+ doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS), "ab < abc comparison failed");
+
+ u_uastrcpy(source, "ab");
+ u_uastrcpy(target, "AB");
+
+ doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS), "ab < AB comparison failed");
+/* u_uastrcpy(source, "black-bird");
+ u_uastrcpy(target, "blackbird"); */
+ u_uastrcpy(target, "black-bird");
+ u_uastrcpy(source, "blackbird");
+
+ doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_GREATER),
+ "black-bird > blackbird comparison failed");
+ u_uastrcpy(source, "black bird");
+ u_uastrcpy(target, "black-bird");
+ doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_LESS),
+ "black bird < black-bird comparison failed");
+ u_uastrcpy(source, "Hello");
+ u_uastrcpy(target, "hello");
+
+ doAssert((ucol_strcoll(col, source, u_strlen(source), target, u_strlen(target)) == UCOL_GREATER),
+ "Hello > hello comparison failed");
+ free(source);
+ free(target);
+ log_verbose("Test ucol_strcoll ends.\n");
+
+ log_verbose("testing ucol_getStrength() method ...\n");
+ doAssert( (ucol_getStrength(col) == UCOL_TERTIARY), "collation object has the wrong strength");
+ doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference");
+
+ log_verbose("testing ucol_setStrength() method ...\n");
+ ucol_setStrength(col, UCOL_SECONDARY);
+ doAssert( (ucol_getStrength(col) != UCOL_TERTIARY), "collation object's strength is secondary difference");
+ doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference");
+ doAssert( (ucol_getStrength(col) == UCOL_SECONDARY), "collation object has the wrong strength");
+
+
+ log_verbose("Get display name for the default collation in German : \n");
+
+ len=ucol_getDisplayName("en_US", "de_DE", NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ disName=(UChar*)malloc(sizeof(UChar) * (len+1));
+ ucol_getDisplayName("en_US", "de_DE", disName, len+1, &status);
+ log_verbose("the display name for default collation in german: %s\n", austrdup(disName) );
+ free(disName);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in getDisplayName: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Default collation getDisplayName ended.\n");
+
+ ruled = ucol_open("da_DK", &status);
+ log_verbose("ucol_getRules() testing ...\n");
+ ucol_getRules(ruled, &tempLength);
+ doAssert( tempLength != 0, "getRules() result incorrect" );
+ log_verbose("getRules tests end.\n");
+ {
+ UChar *buffer = (UChar *)malloc(200000*sizeof(UChar));
+ int32_t bufLen = 200000;
+ buffer[0] = '\0';
+ log_verbose("ucol_getRulesEx() testing ...\n");
+ tempLength = ucol_getRulesEx(col,UCOL_TAILORING_ONLY,buffer,bufLen );
+ doAssert( tempLength == 0x0a, "getRulesEx() result incorrect" );
+ log_verbose("getRules tests end.\n");
+
+ log_verbose("ucol_getRulesEx() testing ...\n");
+ tempLength=ucol_getRulesEx(col,UCOL_FULL_RULES,buffer,bufLen );
+ doAssert( tempLength != 0, "getRulesEx() result incorrect" );
+ log_verbose("getRules tests end.\n");
+ free(buffer);
+ }
+ ucol_close(ruled);
+ ucol_close(col);
+
+ log_verbose("open an collator for french locale");
+ col = ucol_open("fr_FR", &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: Creating French collation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ ucol_setStrength(col, UCOL_PRIMARY);
+ log_verbose("testing ucol_getStrength() method again ...\n");
+ doAssert( (ucol_getStrength(col) != UCOL_TERTIARY), "collation object has the wrong strength");
+ doAssert( (ucol_getStrength(col) == UCOL_PRIMARY), "collation object's strength is not primary difference");
+
+ log_verbose("testing French ucol_setStrength() method ...\n");
+ ucol_setStrength(col, UCOL_TERTIARY);
+ doAssert( (ucol_getStrength(col) == UCOL_TERTIARY), "collation object's strength is not tertiary difference");
+ doAssert( (ucol_getStrength(col) != UCOL_PRIMARY), "collation object's strength is primary difference");
+ doAssert( (ucol_getStrength(col) != UCOL_SECONDARY), "collation object's strength is secondary difference");
+ ucol_close(col);
+
+ log_verbose("Get display name for the french collation in english : \n");
+ len=ucol_getDisplayName("fr_FR", "en_US", NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ disName=(UChar*)malloc(sizeof(UChar) * (len+1));
+ ucol_getDisplayName("fr_FR", "en_US", disName, len+1, &status);
+ log_verbose("the display name for french collation in english: %s\n", austrdup(disName) );
+ free(disName);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in getDisplayName: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Default collation getDisplayName ended.\n");
+
+}
+
+/* Test RuleBasedCollator and getRules*/
+void TestRuleBasedColl()
+{
+ UCollator *col1, *col2, *col3, *col4;
+ UCollationElements *iter1, *iter2;
+ UChar ruleset1[60];
+ UChar ruleset2[50];
+ UChar teststr[10];
+ UChar teststr2[10];
+ const UChar *rule1, *rule2, *rule3, *rule4;
+ int32_t tempLength;
+ UErrorCode status = U_ZERO_ERROR;
+ u_uastrcpy(ruleset1, "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E");
+ u_uastrcpy(ruleset2, "&9 < a, A < b, B < c, C < d, D, e, E");
+
+
+ col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL,&status);
+ if (U_FAILURE(status)) {
+ log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ else
+ log_verbose("PASS: RuleBased Collator creation passed\n");
+
+ status = U_ZERO_ERROR;
+ col2 = ucol_openRules(ruleset2, u_strlen(ruleset2), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ else
+ log_verbose("PASS: RuleBased Collator creation passed\n");
+
+
+ status = U_ZERO_ERROR;
+ col3= ucol_open(NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Default Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ else
+ log_verbose("PASS: Default Collator creation passed\n");
+
+ rule1 = ucol_getRules(col1, &tempLength);
+ rule2 = ucol_getRules(col2, &tempLength);
+ rule3 = ucol_getRules(col3, &tempLength);
+
+ doAssert((u_strcmp(rule1, rule2) != 0), "Default collator getRules failed");
+ doAssert((u_strcmp(rule2, rule3) != 0), "Default collator getRules failed");
+ doAssert((u_strcmp(rule1, rule3) != 0), "Default collator getRules failed");
+
+ col4=ucol_openRules(rule2, u_strlen(rule2), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ rule4= ucol_getRules(col4, &tempLength);
+ doAssert((u_strcmp(rule2, rule4) == 0), "Default collator getRules failed");
+
+ ucol_close(col1);
+ ucol_close(col2);
+ ucol_close(col3);
+ ucol_close(col4);
+
+ /* tests that modifier ! is always ignored */
+ u_uastrcpy(ruleset1, "!&a<b");
+ teststr[0] = 0x0e40;
+ teststr[1] = 0x0e01;
+ teststr[2] = 0x0e2d;
+ col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ col2 = ucol_open("en_US", &status);
+ if (U_FAILURE(status)) {
+ log_err("en_US Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ iter1 = ucol_openElements(col1, teststr, 3, &status);
+ iter2 = ucol_openElements(col2, teststr, 3, &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: CollationElement iterator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ while (TRUE) {
+ /* testing with en since thai has its own tailoring */
+ uint32_t ce = ucol_next(iter1, &status);
+ uint32_t ce2 = ucol_next(iter2, &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: CollationElement iterator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ if (ce2 != ce) {
+ log_err("! modifier test failed");
+ }
+ if (ce == UCOL_NULLORDER) {
+ break;
+ }
+ }
+ ucol_closeElements(iter1);
+ ucol_closeElements(iter2);
+ ucol_close(col1);
+ ucol_close(col2);
+ /* test that we can start a rule without a & or < */
+ u_uastrcpy(ruleset1, "< z < a");
+ col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("RuleBased Collator creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ u_uastrcpy(teststr, "z");
+ u_uastrcpy(teststr2, "a");
+ if (ucol_greaterOrEqual(col1, teststr, 1, teststr2, 1)) {
+ log_err("Rule \"z < a\" fails");
+ }
+ ucol_close(col1);
+}
+
+void TestCompare()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *col;
+ UChar* test1;
+ UChar* test2;
+
+ log_verbose("The compare tests begin : \n");
+ status=U_ZERO_ERROR;
+ col = ucol_open("en_US", &status);
+ if(U_FAILURE(status)) {
+ log_err("ucal_open() collation creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ test1=(UChar*)malloc(sizeof(UChar) * 6);
+ test2=(UChar*)malloc(sizeof(UChar) * 6);
+ u_uastrcpy(test1, "Abcda");
+ u_uastrcpy(test2, "abcda");
+
+ log_verbose("Use tertiary comparison level testing ....\n");
+
+ doAssert( (!ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" != \"abcda\" ");
+ doAssert( (ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" >>> \"abcda\" ");
+ doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" >>> \"abcda\"");
+
+ ucol_setStrength(col, UCOL_SECONDARY);
+ log_verbose("Use secondary comparison level testing ....\n");
+
+ doAssert( (ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2) )), "Result should be \"Abcda\" == \"abcda\"");
+ doAssert( (!ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\"");
+ doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2) )), "Result should be \"Abcda\" == \"abcda\"");
+
+ ucol_setStrength(col, UCOL_PRIMARY);
+ log_verbose("Use primary comparison level testing ....\n");
+
+ doAssert( (ucol_equal(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\"");
+ doAssert( (!ucol_greater(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\"");
+ doAssert( (ucol_greaterOrEqual(col, test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"Abcda\" == \"abcda\"");
+
+
+ log_verbose("The compare tests end.\n");
+ ucol_close(col);
+ free(test1);
+ free(test2);
+
+}
+/*
+---------------------------------------------
+ tests decomposition setting
+*/
+void TestDecomposition() {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *en_US, *el_GR, *vi_VN;
+ en_US = ucol_open("en_US", &status);
+ el_GR = ucol_open("el_GR", &status);
+ vi_VN = ucol_open("vi_VN", &status);
+
+ if (U_FAILURE(status)) {
+ log_err("ERROR: collation creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+
+ if (ucol_getAttribute(vi_VN, UCOL_NORMALIZATION_MODE, &status) != UCOL_ON ||
+ U_FAILURE(status))
+ {
+ log_err("ERROR: vi_VN collation did not have cannonical decomposition for normalization!\n");
+ }
+
+ status = U_ZERO_ERROR;
+ if (ucol_getAttribute(el_GR, UCOL_NORMALIZATION_MODE, &status) != UCOL_ON ||
+ U_FAILURE(status))
+ {
+ log_err("ERROR: el_GR collation did not have cannonical decomposition for normalization!\n");
+ }
+
+ status = U_ZERO_ERROR;
+ if (ucol_getAttribute(en_US, UCOL_NORMALIZATION_MODE, &status) != UCOL_OFF ||
+ U_FAILURE(status))
+ {
+ log_err("ERROR: en_US collation had cannonical decomposition for normalization!\n");
+ }
+
+ ucol_close(en_US);
+ ucol_close(el_GR);
+ ucol_close(vi_VN);
+}
+
+#define CLONETEST_COLLATOR_COUNT 4
+
+void TestSafeClone() {
+ UChar* test1;
+ UChar* test2;
+ static const UChar umlautUStr[] = {0x00DC, 0};
+ static const UChar oeStr[] = {0x0055, 0x0045, 0};
+ UCollator * someCollators [CLONETEST_COLLATOR_COUNT];
+ UCollator * someClonedCollators [CLONETEST_COLLATOR_COUNT];
+ UCollator * col;
+ UErrorCode err = U_ZERO_ERROR;
+ int8_t testSize = 6; /* Leave this here to test buffer alingment in memory*/
+ uint8_t buffer [CLONETEST_COLLATOR_COUNT] [U_COL_SAFECLONE_BUFFERSIZE];
+ int32_t bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
+ const char sampleRuleChars[] = "&Z < CH";
+ UChar sampleRule[sizeof(sampleRuleChars)];
+ int index;
+
+ if (TestBufferSize()) {
+ log_err("U_COL_SAFECLONE_BUFFERSIZE should be larger than sizeof(UCollator)\n");
+ return;
+ }
+
+ test1=(UChar*)malloc(sizeof(UChar) * testSize);
+ test2=(UChar*)malloc(sizeof(UChar) * testSize);
+ u_uastrcpy(test1, "abCda");
+ u_uastrcpy(test2, "abcda");
+ u_uastrcpy(sampleRule, sampleRuleChars);
+
+ /* one default collator & two complex ones */
+ someCollators[0] = ucol_open("en_US", &err);
+ someCollators[1] = ucol_open("ko", &err);
+ someCollators[2] = ucol_open("ja_JP", &err);
+ someCollators[3] = ucol_openRules(sampleRule, -1, UCOL_ON, UCOL_TERTIARY, NULL, &err);
+ if(U_FAILURE(err)) {
+ log_data_err("Couldn't open one or more collators\n");
+ return;
+ }
+
+ /* Check the various error & informational states: */
+
+ /* Null status - just returns NULL */
+ if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, 0))
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with null status\n");
+ }
+ /* error status - should return 0 & keep error the same */
+ err = U_MEMORY_ALLOCATION_ERROR;
+ if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR)
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with incoming error status\n");
+ }
+ err = U_ZERO_ERROR;
+
+ /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
+ if (0 != ucol_safeClone(someCollators[0], buffer[0], 0, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with null bufferSize pointer\n");
+ }
+ err = U_ZERO_ERROR;
+
+ /* buffer size pointer is 0 - fill in pbufferSize with a size */
+ bufferSize = 0;
+ if (0 != ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0)
+ {
+ log_err("FAIL: Cloned Collator failed a sizing request ('preflighting')\n");
+ }
+ /* Verify our define is large enough */
+ if (U_COL_SAFECLONE_BUFFERSIZE < bufferSize)
+ {
+ log_err("FAIL: Pre-calculated buffer size is too small\n");
+ }
+ /* Verify we can use this run-time calculated size */
+ if (0 == (col = ucol_safeClone(someCollators[0], buffer[0], &bufferSize, &err)) || U_FAILURE(err))
+ {
+ log_err("FAIL: Collator can't be cloned with run-time size\n");
+ }
+ if (col) ucol_close(col);
+ /* size one byte too small - should allocate & let us know */
+ --bufferSize;
+ if (0 == (col = ucol_safeClone(someCollators[0], 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with too-small buffer size\n");
+ }
+ if (col) ucol_close(col);
+ err = U_ZERO_ERROR;
+ bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
+
+
+ /* Null buffer pointer - return Collator & set error to U_SAFECLONE_ALLOCATED_ERROR */
+ if (0 == (col = ucol_safeClone(someCollators[0], 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with null buffer pointer\n");
+ }
+ if (col) ucol_close(col);
+ err = U_ZERO_ERROR;
+
+ /* Null Collator - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
+ if (0 != ucol_safeClone(0, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned Collator failed to deal correctly with null Collator pointer\n");
+ }
+
+ err = U_ZERO_ERROR;
+
+ /* Test that a cloned collator doesn't accidentally use UCA. */
+ col=ucol_open("de@collation=phonebook", &err);
+ bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
+ someClonedCollators[0] = ucol_safeClone(col, buffer[0], &bufferSize, &err);
+ doAssert( (ucol_greater(col, umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Original German phonebook collation sorts differently than expected");
+ doAssert( (ucol_greater(someClonedCollators[0], umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Cloned German phonebook collation sorts differently than expected");
+ if (!ucol_equals(someClonedCollators[0], col)) {
+ log_err("FAIL: Cloned German phonebook collator is not equal to original.\n");
+ }
+ ucol_close(col);
+ ucol_close(someClonedCollators[0]);
+
+ err = U_ZERO_ERROR;
+
+ /* change orig & clone & make sure they are independent */
+
+ for (index = 0; index < CLONETEST_COLLATOR_COUNT; index++)
+ {
+ ucol_setStrength(someCollators[index], UCOL_IDENTICAL);
+ bufferSize = 1;
+ err = U_ZERO_ERROR;
+ ucol_close(ucol_safeClone(someCollators[index], buffer[index], &bufferSize, &err));
+ if (err != U_SAFECLONE_ALLOCATED_WARNING) {
+ log_err("FAIL: collator number %d was not allocated.\n", index);
+ }
+
+ bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
+ err = U_ZERO_ERROR;
+ someClonedCollators[index] = ucol_safeClone(someCollators[index], buffer[index], &bufferSize, &err);
+ if (someClonedCollators[index] == NULL
+ || someClonedCollators[index] < (UCollator *)buffer[index]
+ || someClonedCollators[index] > (UCollator *)(buffer[index]+(U_COL_SAFECLONE_BUFFERSIZE-1)))
+ {
+ log_err("FAIL: Cloned collator didn't use provided buffer.\n");
+ return;
+ }
+ if (!ucol_equals(someClonedCollators[index], someCollators[index])) {
+ log_err("FAIL: Cloned collator is not equal to original at index = %d.\n", index);
+ }
+
+ /* Check the usability */
+ ucol_setStrength(someCollators[index], UCOL_PRIMARY);
+ ucol_setAttribute(someCollators[index], UCOL_CASE_LEVEL, UCOL_OFF, &err);
+
+ doAssert( (ucol_equal(someCollators[index], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abcda\" == \"abCda\"");
+
+ /* Close the original to make sure that the clone is usable. */
+ ucol_close(someCollators[index]);
+
+ ucol_setStrength(someClonedCollators[index], UCOL_TERTIARY);
+ ucol_setAttribute(someClonedCollators[index], UCOL_CASE_LEVEL, UCOL_OFF, &err);
+ doAssert( (ucol_greater(someClonedCollators[index], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abCda\" >>> \"abcda\" ");
+
+ ucol_close(someClonedCollators[index]);
+ }
+ free(test1);
+ free(test2);
+}
+
+void TestCloneBinary(){
+ UErrorCode err = U_ZERO_ERROR;
+ UCollator * col = ucol_open("en_US", &err);
+ UCollator * c;
+ int32_t size;
+ uint8_t * buffer;
+
+ if (U_FAILURE(err)) {
+ log_data_err("Couldn't open collator. Error: %s\n", u_errorName(err));
+ return;
+ }
+
+ size = ucol_cloneBinary(col, NULL, 0, &err);
+ if(size==0 || err!=U_BUFFER_OVERFLOW_ERROR) {
+ log_err("ucol_cloneBinary - couldn't check size. Error: %s\n", u_errorName(err));
+ return;
+ }
+ err = U_ZERO_ERROR;
+
+ buffer = (uint8_t *) malloc(size);
+ ucol_cloneBinary(col, buffer, size, &err);
+ if(U_FAILURE(err)) {
+ log_err("ucol_cloneBinary - couldn't clone.. Error: %s\n", u_errorName(err));
+ free(buffer);
+ return;
+ }
+
+ /* how to check binary result ? */
+
+ c = ucol_openBinary(buffer, size, col, &err);
+ if(U_FAILURE(err)) {
+ log_err("ucol_openBinary failed. Error: %s\n", u_errorName(err));
+ } else {
+ UChar t[] = {0x41, 0x42, 0x43, 0}; /* ABC */
+ uint8_t *k1, *k2;
+ int l1, l2;
+ l1 = ucol_getSortKey(col, t, -1, NULL,0);
+ l2 = ucol_getSortKey(c, t, -1, NULL,0);
+ k1 = (uint8_t *) malloc(sizeof(uint8_t) * l1);
+ k2 = (uint8_t *) malloc(sizeof(uint8_t) * l2);
+ ucol_getSortKey(col, t, -1, k1, l1);
+ ucol_getSortKey(col, t, -1, k2, l2);
+ if (strcmp((char *)k1,(char *)k2) != 0){
+ log_err("ucol_openBinary - new collator should equal to old one\n");
+ };
+ free(k1);
+ free(k2);
+ }
+ free(buffer);
+ ucol_close(c);
+ ucol_close(col);
+}
+/*
+----------------------------------------------------------------------------
+ ctor -- Tests the getSortKey
+*/
+void TestSortKey()
+{
+ uint8_t *sortk1 = NULL, *sortk2 = NULL, *sortk3 = NULL, *sortkEmpty = NULL;
+ uint8_t sortk2_compat[] = {
+ /* 3.6 key, from UCA 5.0 */
+ 0x29, 0x2b, 0x2d, 0x2f, 0x29, 0x01,
+ 0x09, 0x01, 0x09, 0x01, 0x28, 0x01,
+ 0x92, 0x93, 0x94, 0x95, 0x92, 0x00
+ /* 3.4 key, from UCA 4.1 */
+ /* 0x28, 0x2a, 0x2c, 0x2e, 0x28, 0x01, 0x09, 0x01, 0x09, 0x01, 0x27, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00 */
+ /* 2.6.1 key */
+ /* 0x26, 0x28, 0x2A, 0x2C, 0x26, 0x01, 0x09, 0x01, 0x09, 0x01, 0x25, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00 */
+ /* 2.2 key */
+ /*0x1D, 0x1F, 0x21, 0x23, 0x1D, 0x01, 0x09, 0x01, 0x09, 0x01, 0x1C, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/
+ /* 2.0 key */
+ /*0x19, 0x1B, 0x1D, 0x1F, 0x19, 0x01, 0x09, 0x01, 0x09, 0x01, 0x18, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/
+ /* 1.8.1 key.*/
+ /*0x19, 0x1B, 0x1D, 0x1F, 0x19, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x92, 0x93, 0x94, 0x95, 0x92, 0x00*/
+ /*this is a 1.8 sortkey */
+ /*0x17, 0x19, 0x1B, 0x1D, 0x17, 0x01, 0x08, 0x01, 0x08, 0x00*/
+ /*this is a 1.7 sortkey */
+ /*0x02, 0x54, 0x02, 0x55, 0x02, 0x56, 0x02, 0x57, 0x02, 0x54, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00*/
+ /* this is a 1.6 sortkey */
+ /*0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00*/
+ };
+
+ int32_t sortklen, osortklen;
+ uint32_t toStringLen=0;
+ UCollator *col;
+ UChar *test1, *test2, *test3;
+ UErrorCode status = U_ZERO_ERROR;
+ char toStringBuffer[256], *resultP;
+
+
+ uint8_t s1[] = { 0x9f, 0x00 };
+ uint8_t s2[] = { 0x61, 0x00 };
+ int strcmpResult;
+
+ strcmpResult = strcmp((const char *)s1, (const char *)s2);
+ log_verbose("strcmp(0x9f..., 0x61...) = %d\n", strcmpResult);
+
+ if(strcmpResult <= 0) {
+ log_err("ERR: expected strcmp(\"9f 00\", \"61 00\") to be >=0 (GREATER).. got %d. Calling strcmp() for sortkeys may not work! \n",
+ strcmpResult);
+ }
+
+
+ log_verbose("testing SortKey begins...\n");
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* col = ucol_open(NULL, &status); */
+ col = ucol_open("en_US", &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+
+
+ if(ucol_getStrength(col) != UCOL_DEFAULT_STRENGTH)
+ {
+ log_err("ERROR: default collation did not have UCOL_DEFAULT_STRENGTH !\n");
+ }
+ /* Need to use identical strength */
+ ucol_setAttribute(col, UCOL_STRENGTH, UCOL_IDENTICAL, &status);
+
+ test1=(UChar*)malloc(sizeof(UChar) * 6);
+ test2=(UChar*)malloc(sizeof(UChar) * 6);
+ test3=(UChar*)malloc(sizeof(UChar) * 6);
+
+ memset(test1,0xFE, sizeof(UChar)*6);
+ memset(test2,0xFE, sizeof(UChar)*6);
+ memset(test3,0xFE, sizeof(UChar)*6);
+
+
+ u_uastrcpy(test1, "Abcda");
+ u_uastrcpy(test2, "abcda");
+ u_uastrcpy(test3, "abcda");
+
+ log_verbose("Use tertiary comparison level testing ....\n");
+
+ sortklen=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0);
+ sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ memset(sortk1,0xFE, sortklen);
+ ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortklen+1);
+
+ sortklen=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0);
+ sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ memset(sortk2,0xFE, sortklen);
+ ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortklen+1);
+
+ osortklen = sortklen;
+ sortklen=ucol_getSortKey(col, test2, u_strlen(test3), NULL, 0);
+ sortk3=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ memset(sortk3,0xFE, sortklen);
+ ucol_getSortKey(col, test2, u_strlen(test2), sortk3, sortklen+1);
+
+ doAssert( (sortklen == osortklen), "Sortkey length should be the same (abcda, abcda)");
+
+ doAssert( (memcmp(sortk1, sortk2, sortklen) > 0), "Result should be \"Abcda\" > \"abcda\"");
+ doAssert( (memcmp(sortk2, sortk1, sortklen) < 0), "Result should be \"abcda\" < \"Abcda\"");
+ doAssert( (memcmp(sortk2, sortk3, sortklen) == 0), "Result should be \"abcda\" == \"abcda\"");
+
+ doAssert( (memcmp(sortk2, sortk2_compat, sortklen) == 0), "Binary format for 'abcda' sortkey different!");
+
+ resultP = ucol_sortKeyToString(col, sortk2_compat, toStringBuffer, &toStringLen);
+ doAssert( (resultP != 0), "sortKeyToString failed!");
+
+#if 1 /* verobse log of sortkeys */
+ {
+ char junk2[1000];
+ char junk3[1000];
+ int i;
+
+ strcpy(junk2, "abcda[2] ");
+ strcpy(junk3, " abcda[3] ");
+
+ for(i=0;i<sortklen;i++)
+ {
+ sprintf(junk2+strlen(junk2), "%02X ",(int)( 0xFF & sortk2[i]));
+ sprintf(junk3+strlen(junk3), "%02X ",(int)( 0xFF & sortk3[i]));
+ }
+
+ log_verbose("%s\n", junk2);
+ log_verbose("%s\n", junk3);
+ }
+#endif
+
+ free(sortk1);
+ free(sortk2);
+ free(sortk3);
+
+ log_verbose("Use secondary comparision level testing ...\n");
+ ucol_setStrength(col, UCOL_SECONDARY);
+ sortklen=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0);
+ sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortklen+1);
+ sortklen=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0);
+ sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortklen+1);
+
+ doAssert( !(memcmp(sortk1, sortk2, sortklen) > 0), "Result should be \"Abcda\" == \"abcda\"");
+ doAssert( !(memcmp(sortk2, sortk1, sortklen) < 0), "Result should be \"abcda\" == \"Abcda\"");
+ doAssert( (memcmp(sortk1, sortk2, sortklen) == 0), "Result should be \"abcda\" == \"abcda\"");
+
+ log_verbose("getting sortkey for an empty string\n");
+ ucol_setAttribute(col, UCOL_STRENGTH, UCOL_TERTIARY, &status);
+ sortklen = ucol_getSortKey(col, test1, 0, NULL, 0);
+ sortkEmpty = (uint8_t*)malloc(sizeof(uint8_t) * sortklen+1);
+ sortklen = ucol_getSortKey(col, test1, 0, sortkEmpty, sortklen+1);
+ if(sortklen != 3 || sortkEmpty[0] != 1 || sortkEmpty[0] != 1 || sortkEmpty[2] != 0) {
+ log_err("Empty string generated wrong sortkey!\n");
+ }
+ free(sortkEmpty);
+
+ log_verbose("testing passing invalid string\n");
+ sortklen = ucol_getSortKey(col, NULL, 0, NULL, 0);
+ if(sortklen != 0) {
+ log_err("Invalid string didn't return sortkey size of 0\n");
+ }
+
+
+ log_verbose("testing sortkey ends...\n");
+ ucol_close(col);
+ free(test1);
+ free(test2);
+ free(test3);
+ free(sortk1);
+ free(sortk2);
+
+}
+void TestHashCode()
+{
+ uint8_t *sortk1, *sortk2, *sortk3;
+ int32_t sortk1len, sortk2len, sortk3len;
+ UCollator *col;
+ UChar *test1, *test2, *test3;
+ UErrorCode status = U_ZERO_ERROR;
+ log_verbose("testing getHashCode begins...\n");
+ col = ucol_open("en_US", &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ test1=(UChar*)malloc(sizeof(UChar) * 6);
+ test2=(UChar*)malloc(sizeof(UChar) * 6);
+ test3=(UChar*)malloc(sizeof(UChar) * 6);
+ u_uastrcpy(test1, "Abcda");
+ u_uastrcpy(test2, "abcda");
+ u_uastrcpy(test3, "abcda");
+
+ log_verbose("Use tertiary comparison level testing ....\n");
+ sortk1len=ucol_getSortKey(col, test1, u_strlen(test1), NULL, 0);
+ sortk1=(uint8_t*)malloc(sizeof(uint8_t) * (sortk1len+1));
+ ucol_getSortKey(col, test1, u_strlen(test1), sortk1, sortk1len+1);
+ sortk2len=ucol_getSortKey(col, test2, u_strlen(test2), NULL, 0);
+ sortk2=(uint8_t*)malloc(sizeof(uint8_t) * (sortk2len+1));
+ ucol_getSortKey(col, test2, u_strlen(test2), sortk2, sortk2len+1);
+ sortk3len=ucol_getSortKey(col, test2, u_strlen(test3), NULL, 0);
+ sortk3=(uint8_t*)malloc(sizeof(uint8_t) * (sortk3len+1));
+ ucol_getSortKey(col, test2, u_strlen(test2), sortk3, sortk3len+1);
+
+
+ log_verbose("ucol_hashCode() testing ...\n");
+
+ doAssert( ucol_keyHashCode(sortk1, sortk1len) != ucol_keyHashCode(sortk2, sortk2len), "Hash test1 result incorrect" );
+ doAssert( !(ucol_keyHashCode(sortk1, sortk1len) == ucol_keyHashCode(sortk2, sortk2len)), "Hash test2 result incorrect" );
+ doAssert( ucol_keyHashCode(sortk2, sortk2len) == ucol_keyHashCode(sortk3, sortk3len), "Hash result not equal" );
+
+ log_verbose("hashCode tests end.\n");
+ ucol_close(col);
+ free(sortk1);
+ free(sortk2);
+ free(sortk3);
+ free(test1);
+ free(test2);
+ free(test3);
+
+
+}
+/*
+ *----------------------------------------------------------------------------
+ * Tests the UCollatorElements API.
+ *
+ */
+void TestElemIter()
+{
+ int32_t offset;
+ int32_t order1, order2, order3;
+ UChar *testString1, *testString2;
+ UCollator *col;
+ UCollationElements *iterator1, *iterator2, *iterator3;
+ UErrorCode status = U_ZERO_ERROR;
+ log_verbose("testing UCollatorElements begins...\n");
+ col = ucol_open("en_US", &status);
+ ucol_setAttribute(col, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: Default collation creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+
+ testString1=(UChar*)malloc(sizeof(UChar) * 150);
+ testString2=(UChar*)malloc(sizeof(UChar) * 150);
+ u_uastrcpy(testString1, "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?");
+ u_uastrcpy(testString2, "Xf_ile What subset of all possible test cases has the lowest probability of detecting the least errors?");
+
+ log_verbose("Constructors and comparison testing....\n");
+
+ iterator1 = ucol_openElements(col, testString1, u_strlen(testString1), &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status));
+ ucol_close(col);
+ return;
+ }
+ else{ log_verbose("PASS: Default collationElement iterator1 creation passed\n");}
+
+ iterator2 = ucol_openElements(col, testString1, u_strlen(testString1), &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status));
+ ucol_close(col);
+ return;
+ }
+ else{ log_verbose("PASS: Default collationElement iterator2 creation passed\n");}
+
+ iterator3 = ucol_openElements(col, testString2, u_strlen(testString2), &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: Default collationElement iterator creation failed.: %s\n", myErrorName(status));
+ ucol_close(col);
+ return;
+ }
+ else{ log_verbose("PASS: Default collationElement iterator3 creation passed\n");}
+
+ offset=ucol_getOffset(iterator1);
+ ucol_setOffset(iterator1, 6, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error in setOffset for UCollatorElements iterator.: %s\n", myErrorName(status));
+ return;
+ }
+ if(ucol_getOffset(iterator1)==6)
+ log_verbose("setOffset and getOffset working fine\n");
+ else{
+ log_err("error in set and get Offset got %d instead of 6\n", ucol_getOffset(iterator1));
+ }
+
+ ucol_setOffset(iterator1, 0, &status);
+ order1 = ucol_next(iterator1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator1.: %s\n", myErrorName(status));
+ return;
+ }
+ order2=ucol_getOffset(iterator2);
+ doAssert((order1 != order2), "The first iterator advance failed");
+ order2 = ucol_next(iterator2, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status));
+ return;
+ }
+ order3 = ucol_next(iterator3, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator3.: %s\n", myErrorName(status));
+ return;
+ }
+
+ doAssert((order1 == order2), "The second iterator advance failed should be the same as first one");
+
+doAssert( (ucol_primaryOrder(order1) == ucol_primaryOrder(order3)), "The primary orders should be identical");
+doAssert( (ucol_secondaryOrder(order1) == ucol_secondaryOrder(order3)), "The secondary orders should be identical");
+doAssert( (ucol_tertiaryOrder(order1) == ucol_tertiaryOrder(order3)), "The tertiary orders should be identical");
+
+ order1=ucol_next(iterator1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status));
+ return;
+ }
+ order3=ucol_next(iterator3, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status));
+ return;
+ }
+doAssert( (ucol_primaryOrder(order1) == ucol_primaryOrder(order3)), "The primary orders should be identical");
+doAssert( (ucol_tertiaryOrder(order1) != ucol_tertiaryOrder(order3)), "The tertiary orders should be different");
+
+ order1=ucol_next(iterator1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status));
+ return;
+ }
+ order3=ucol_next(iterator3, &status);
+ if (U_FAILURE(status)) {
+ log_err("Somehow ran out of memory stepping through the iterator2.: %s\n", myErrorName(status));
+ return;
+ }
+ /* this here, my friends, is either pure lunacy or something so obsolete that even it's mother
+ * doesn't care about it. Essentialy, this test complains if secondary values for 'I' and '_'
+ * are the same. According to the UCA, this is not true. Therefore, remove the test.
+ * Besides, if primary strengths for two code points are different, it doesn't matter one bit
+ * what is the relation between secondary or any other strengths.
+ * killed by weiv 06/11/2002.
+ */
+ /*
+ doAssert( ((order1 & UCOL_SECONDARYMASK) != (order3 & UCOL_SECONDARYMASK)), "The secondary orders should be different");
+ */
+ doAssert( (order1 != UCOL_NULLORDER), "Unexpected end of iterator reached");
+
+ free(testString1);
+ free(testString2);
+ ucol_closeElements(iterator1);
+ ucol_closeElements(iterator2);
+ ucol_closeElements(iterator3);
+ ucol_close(col);
+
+ log_verbose("testing CollationElementIterator ends...\n");
+}
+
+void TestGetLocale() {
+ UErrorCode status = U_ZERO_ERROR;
+ const char *rules = "&a<x<y<z";
+ UChar rlz[256] = {0};
+ uint32_t rlzLen = u_unescape(rules, rlz, 256);
+
+ UCollator *coll = NULL;
+ const char *locale = NULL;
+
+ int32_t i = 0;
+
+ /* Now that the collation tree is separate, actual==valid at all times. [alan] */
+ static const struct {
+ const char* requestedLocale;
+ const char* validLocale;
+ const char* actualLocale;
+ } testStruct[] = {
+ { "sr_RS", "sr_Cyrl_RS", "ru" },
+ { "sh_YU", "sr_Latn_RS", "hr" }, /* this used to be sh, but now sh collation aliases hr */
+ { "en_BE_FOO", "en_BE", "en_BE" },
+ { "fr_FR_NONEXISTANT", "fr_FR", "fr" }
+ };
+
+ /* test opening collators for different locales */
+ for(i = 0; i<sizeof(testStruct)/sizeof(testStruct[0]); i++) {
+ status = U_ZERO_ERROR;
+ coll = ucol_open(testStruct[i].requestedLocale, &status);
+ if(U_FAILURE(status)) {
+ log_err("Failed to open collator for %s with %s\n", testStruct[i].requestedLocale, u_errorName(status));
+ ucol_close(coll);
+ continue;
+ }
+ locale = ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status);
+ if(strcmp(locale, testStruct[i].requestedLocale) != 0) {
+ log_err("[Coll %s]: Error in requested locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].requestedLocale, locale);
+ }
+ locale = ucol_getLocale(coll, ULOC_VALID_LOCALE, &status);
+ if(strcmp(locale, testStruct[i].validLocale) != 0) {
+ log_err("[Coll %s]: Error in valid locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].validLocale, locale);
+ }
+ locale = ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status);
+ if(strcmp(locale, testStruct[i].actualLocale) != 0) {
+ log_err("[Coll %s]: Error in actual locale, expected %s, got %s\n", testStruct[i].requestedLocale, testStruct[i].actualLocale, locale);
+ }
+ ucol_close(coll);
+ }
+
+ /* completely non-existant locale for collator should get a default collator */
+ {
+ UCollator *defaultColl = ucol_open(NULL, &status);
+ coll = ucol_open("blahaha", &status);
+ if(U_SUCCESS(status)) {
+ if(strcmp(ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status), "blahaha")) {
+ log_err("Nonexisting locale didn't preserve the requested locale\n");
+ }
+ if(strcmp(ucol_getLocale(coll, ULOC_VALID_LOCALE, &status),
+ ucol_getLocale(defaultColl, ULOC_VALID_LOCALE, &status))) {
+ log_err("Valid locale for nonexisting locale locale collator differs "
+ "from valid locale for default collator\n");
+ }
+ if(strcmp(ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status),
+ ucol_getLocale(defaultColl, ULOC_ACTUAL_LOCALE, &status))) {
+ log_err("Actual locale for nonexisting locale locale collator differs "
+ "from actual locale for default collator\n");
+ }
+ ucol_close(coll);
+ ucol_close(defaultColl);
+ } else {
+ log_data_err("Couldn't open collators\n");
+ }
+ }
+
+
+
+ /* collator instantiated from rules should have all three locales NULL */
+ coll = ucol_openRules(rlz, rlzLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ locale = ucol_getLocale(coll, ULOC_REQUESTED_LOCALE, &status);
+ if(locale != NULL) {
+ log_err("For collator instantiated from rules, requested locale returned %s instead of NULL\n", locale);
+ }
+ locale = ucol_getLocale(coll, ULOC_VALID_LOCALE, &status);
+ if(locale != NULL) {
+ log_err("For collator instantiated from rules, valid locale returned %s instead of NULL\n", locale);
+ }
+ locale = ucol_getLocale(coll, ULOC_ACTUAL_LOCALE, &status);
+ if(locale != NULL) {
+ log_err("For collator instantiated from rules, actual locale returned %s instead of NULL\n", locale);
+ }
+ ucol_close(coll);
+
+}
+
+
+void TestGetAll()
+{
+ int32_t i, count;
+ count=ucol_countAvailable();
+ /* use something sensible w/o hardcoding the count */
+ if(count < 0){
+ log_err("Error in countAvailable(), it returned %d\n", count);
+ }
+ else{
+ log_verbose("PASS: countAvailable() successful, it returned %d\n", count);
+ }
+ for(i=0;i<count;i++)
+ log_verbose("%s\n", ucol_getAvailable(i));
+
+
+}
+
+
+struct teststruct {
+ const char *original;
+ uint8_t key[256];
+} ;
+
+static int compare_teststruct(const void *string1, const void *string2) {
+ return(strcmp((const char *)((struct teststruct *)string1)->key, (const char *)((struct teststruct *)string2)->key));
+}
+
+void TestBounds() {
+ UErrorCode status = U_ZERO_ERROR;
+
+ UCollator *coll = ucol_open("sh", &status);
+
+ uint8_t sortkey[512], lower[512], upper[512];
+ UChar buffer[512];
+
+ static const char * const test[] = {
+ "John Smith",
+ "JOHN SMITH",
+ "john SMITH",
+ "j\\u00F6hn sm\\u00EFth",
+ "J\\u00F6hn Sm\\u00EFth",
+ "J\\u00D6HN SM\\u00CFTH",
+ "john smithsonian",
+ "John Smithsonian",
+ };
+
+ struct teststruct tests[] = {
+ {"\\u010CAKI MIHALJ" } ,
+ {"\\u010CAKI MIHALJ" } ,
+ {"\\u010CAKI PIRO\\u0160KA" },
+ {"\\u010CABAI ANDRIJA" } ,
+ {"\\u010CABAI LAJO\\u0160" } ,
+ {"\\u010CABAI MARIJA" } ,
+ {"\\u010CABAI STEVAN" } ,
+ {"\\u010CABAI STEVAN" } ,
+ {"\\u010CABARKAPA BRANKO" } ,
+ {"\\u010CABARKAPA MILENKO" } ,
+ {"\\u010CABARKAPA MIROSLAV" } ,
+ {"\\u010CABARKAPA SIMO" } ,
+ {"\\u010CABARKAPA STANKO" } ,
+ {"\\u010CABARKAPA TAMARA" } ,
+ {"\\u010CABARKAPA TOMA\\u0160" } ,
+ {"\\u010CABDARI\\u0106 NIKOLA" } ,
+ {"\\u010CABDARI\\u0106 ZORICA" } ,
+ {"\\u010CABI NANDOR" } ,
+ {"\\u010CABOVI\\u0106 MILAN" } ,
+ {"\\u010CABRADI AGNEZIJA" } ,
+ {"\\u010CABRADI IVAN" } ,
+ {"\\u010CABRADI JELENA" } ,
+ {"\\u010CABRADI LJUBICA" } ,
+ {"\\u010CABRADI STEVAN" } ,
+ {"\\u010CABRDA MARTIN" } ,
+ {"\\u010CABRILO BOGDAN" } ,
+ {"\\u010CABRILO BRANISLAV" } ,
+ {"\\u010CABRILO LAZAR" } ,
+ {"\\u010CABRILO LJUBICA" } ,
+ {"\\u010CABRILO SPASOJA" } ,
+ {"\\u010CADE\\u0160 ZDENKA" } ,
+ {"\\u010CADESKI BLAGOJE" } ,
+ {"\\u010CADOVSKI VLADIMIR" } ,
+ {"\\u010CAGLJEVI\\u0106 TOMA" } ,
+ {"\\u010CAGOROVI\\u0106 VLADIMIR" } ,
+ {"\\u010CAJA VANKA" } ,
+ {"\\u010CAJI\\u0106 BOGOLJUB" } ,
+ {"\\u010CAJI\\u0106 BORISLAV" } ,
+ {"\\u010CAJI\\u0106 RADOSLAV" } ,
+ {"\\u010CAK\\u0160IRAN MILADIN" } ,
+ {"\\u010CAKAN EUGEN" } ,
+ {"\\u010CAKAN EVGENIJE" } ,
+ {"\\u010CAKAN IVAN" } ,
+ {"\\u010CAKAN JULIJAN" } ,
+ {"\\u010CAKAN MIHAJLO" } ,
+ {"\\u010CAKAN STEVAN" } ,
+ {"\\u010CAKAN VLADIMIR" } ,
+ {"\\u010CAKAN VLADIMIR" } ,
+ {"\\u010CAKAN VLADIMIR" } ,
+ {"\\u010CAKARA ANA" } ,
+ {"\\u010CAKAREVI\\u0106 MOMIR" } ,
+ {"\\u010CAKAREVI\\u0106 NEDELJKO" } ,
+ {"\\u010CAKI \\u0160ANDOR" } ,
+ {"\\u010CAKI AMALIJA" } ,
+ {"\\u010CAKI ANDRA\\u0160" } ,
+ {"\\u010CAKI LADISLAV" } ,
+ {"\\u010CAKI LAJO\\u0160" } ,
+ {"\\u010CAKI LASLO" } ,
+ };
+
+
+
+ int32_t i = 0, j = 0, k = 0, buffSize = 0, skSize = 0, lowerSize = 0, upperSize = 0;
+ int32_t arraySize = sizeof(tests)/sizeof(tests[0]);
+
+ if(U_SUCCESS(status) && coll) {
+ for(i = 0; i<arraySize; i++) {
+ buffSize = u_unescape(tests[i].original, buffer, 512);
+ skSize = ucol_getSortKey(coll, buffer, buffSize, tests[i].key, 512);
+ }
+
+ qsort(tests, arraySize, sizeof(struct teststruct), compare_teststruct);
+
+ for(i = 0; i < arraySize-1; i++) {
+ for(j = i+1; j < arraySize; j++) {
+ lowerSize = ucol_getBound(tests[i].key, -1, UCOL_BOUND_LOWER, 1, lower, 512, &status);
+ upperSize = ucol_getBound(tests[j].key, -1, UCOL_BOUND_UPPER, 1, upper, 512, &status);
+ for(k = i; k <= j; k++) {
+ if(strcmp((const char *)lower, (const char *)tests[k].key) > 0) {
+ log_err("Problem with lower! j = %i (%s vs %s)\n", k, tests[k].original, tests[i].original);
+ }
+ if(strcmp((const char *)upper, (const char *)tests[k].key) <= 0) {
+ log_err("Problem with upper! j = %i (%s vs %s)\n", k, tests[k].original, tests[j].original);
+ }
+ }
+ }
+ }
+
+
+#if 0
+ for(i = 0; i < 1000; i++) {
+ lowerRND = (rand()/(RAND_MAX/arraySize));
+ upperRND = lowerRND + (rand()/(RAND_MAX/(arraySize-lowerRND)));
+
+ lowerSize = ucol_getBound(tests[lowerRND].key, -1, UCOL_BOUND_LOWER, 1, lower, 512, &status);
+ upperSize = ucol_getBound(tests[upperRND].key, -1, UCOL_BOUND_UPPER_LONG, 1, upper, 512, &status);
+
+ for(j = lowerRND; j<=upperRND; j++) {
+ if(strcmp(lower, tests[j].key) > 0) {
+ log_err("Problem with lower! j = %i (%s vs %s)\n", j, tests[j].original, tests[lowerRND].original);
+ }
+ if(strcmp(upper, tests[j].key) <= 0) {
+ log_err("Problem with upper! j = %i (%s vs %s)\n", j, tests[j].original, tests[upperRND].original);
+ }
+ }
+ }
+#endif
+
+
+
+
+
+ for(i = 0; i<sizeof(test)/sizeof(test[0]); i++) {
+ buffSize = u_unescape(test[i], buffer, 512);
+ skSize = ucol_getSortKey(coll, buffer, buffSize, sortkey, 512);
+ lowerSize = ucol_getBound(sortkey, skSize, UCOL_BOUND_LOWER, 1, lower, 512, &status);
+ upperSize = ucol_getBound(sortkey, skSize, UCOL_BOUND_UPPER_LONG, 1, upper, 512, &status);
+ for(j = i+1; j<sizeof(test)/sizeof(test[0]); j++) {
+ buffSize = u_unescape(test[j], buffer, 512);
+ skSize = ucol_getSortKey(coll, buffer, buffSize, sortkey, 512);
+ if(strcmp((const char *)lower, (const char *)sortkey) > 0) {
+ log_err("Problem with lower! i = %i, j = %i (%s vs %s)\n", i, j, test[i], test[j]);
+ }
+ if(strcmp((const char *)upper, (const char *)sortkey) <= 0) {
+ log_err("Problem with upper! i = %i, j = %i (%s vs %s)\n", i, j, test[i], test[j]);
+ }
+ }
+ }
+ ucol_close(coll);
+ } else {
+ log_data_err("Couldn't open collator\n");
+ }
+
+}
+
+static void doOverrunTest(UCollator *coll, const UChar *uString, int32_t strLen) {
+ int32_t skLen = 0, skLen2 = 0;
+ uint8_t sortKey[256];
+ int32_t i, j;
+ uint8_t filler = 0xFF;
+
+ skLen = ucol_getSortKey(coll, uString, strLen, NULL, 0);
+
+ for(i = 0; i < skLen; i++) {
+ memset(sortKey, filler, 256);
+ skLen2 = ucol_getSortKey(coll, uString, strLen, sortKey, i);
+ if(skLen != skLen2) {
+ log_err("For buffer size %i, got different sortkey length. Expected %i got %i\n", i, skLen, skLen2);
+ }
+ for(j = i; j < 256; j++) {
+ if(sortKey[j] != filler) {
+ log_err("Something run over index %i\n", j);
+ break;
+ }
+ }
+ }
+}
+
+/* j1865 reports that if a shorter buffer is passed to
+* to get sort key, a buffer overrun happens in some
+* cases. This test tries to check this.
+*/
+void TestSortKeyBufferOverrun(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char* cString = "A very Merry liTTle-lamB..";
+ UChar uString[256];
+ int32_t strLen = 0;
+ UCollator *coll = ucol_open("root", &status);
+ strLen = u_unescape(cString, uString, 256);
+
+ if(U_SUCCESS(status)) {
+ log_verbose("testing non ignorable\n");
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
+ doOverrunTest(coll, uString, strLen);
+
+ log_verbose("testing shifted\n");
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ doOverrunTest(coll, uString, strLen);
+
+ log_verbose("testing shifted quaternary\n");
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
+ doOverrunTest(coll, uString, strLen);
+
+ log_verbose("testing with french secondaries\n");
+ ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_ON, &status);
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &status);
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
+ doOverrunTest(coll, uString, strLen);
+
+ }
+ ucol_close(coll);
+}
+
+static void TestAttribute()
+{
+ UErrorCode error = U_ZERO_ERROR;
+ UCollator *coll = ucol_open(NULL, &error);
+
+ if (U_FAILURE(error)) {
+ log_err("Creation of default collator failed");
+ return;
+ }
+
+ ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_OFF, &error);
+ if (ucol_getAttribute(coll, UCOL_FRENCH_COLLATION, &error) != UCOL_OFF ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the french collation failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_FRENCH_COLLATION, UCOL_ON, &error);
+ if (ucol_getAttribute(coll, UCOL_FRENCH_COLLATION, &error) != UCOL_ON ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the french collation failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &error);
+ if (ucol_getAttribute(coll, UCOL_ALTERNATE_HANDLING, &error) != UCOL_SHIFTED ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the alternate handling failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &error);
+ if (ucol_getAttribute(coll, UCOL_ALTERNATE_HANDLING, &error) != UCOL_NON_IGNORABLE ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the alternate handling failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_LOWER_FIRST, &error);
+ if (ucol_getAttribute(coll, UCOL_CASE_FIRST, &error) != UCOL_LOWER_FIRST ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the case first attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_UPPER_FIRST, &error);
+ if (ucol_getAttribute(coll, UCOL_CASE_FIRST, &error) != UCOL_UPPER_FIRST ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the case first attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &error);
+ if (ucol_getAttribute(coll, UCOL_CASE_LEVEL, &error) != UCOL_ON ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the case level attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &error);
+ if (ucol_getAttribute(coll, UCOL_CASE_LEVEL, &error) != UCOL_OFF ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the case level attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &error);
+ if (ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, &error) != UCOL_ON ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the normalization on/off attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &error);
+ if (ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, &error) != UCOL_OFF ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the normalization on/off attribute failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &error);
+ if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_PRIMARY ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the collation strength failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_SECONDARY, &error);
+ if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_SECONDARY ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the collation strength failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &error);
+ if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_TERTIARY ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the collation strength failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &error);
+ if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_QUATERNARY ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the collation strength failed");
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_IDENTICAL, &error);
+ if (ucol_getAttribute(coll, UCOL_STRENGTH, &error) != UCOL_IDENTICAL ||
+ U_FAILURE(error)) {
+ log_err("Setting and retrieving of the collation strength failed");
+ }
+
+ ucol_close(coll);
+}
+
+void TestGetTailoredSet() {
+ struct {
+ const char *rules;
+ const char *tests[20];
+ int32_t testsize;
+ } setTest[] = {
+ { "&a < \\u212b", { "\\u212b", "A\\u030a", "\\u00c5" }, 3},
+ { "& S < \\u0161 <<< \\u0160", { "\\u0161", "s\\u030C", "\\u0160", "S\\u030C" }, 4}
+ };
+
+ int32_t i = 0, j = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError pError;
+
+ UCollator *coll = NULL;
+ UChar buff[1024];
+ int32_t buffLen = 0;
+ USet *set = NULL;
+
+ for(i = 0; i < sizeof(setTest)/sizeof(setTest[0]); i++) {
+ buffLen = u_unescape(setTest[i].rules, buff, 1024);
+ coll = ucol_openRules(buff, buffLen, UCOL_DEFAULT, UCOL_DEFAULT, &pError, &status);
+ if(U_SUCCESS(status)) {
+ set = ucol_getTailoredSet(coll, &status);
+ if(uset_size(set) != setTest[i].testsize) {
+ log_err("Tailored set size different (%d) than expected (%d)\n", uset_size(set), setTest[i].testsize);
+ }
+ for(j = 0; j < setTest[i].testsize; j++) {
+ buffLen = u_unescape(setTest[i].tests[j], buff, 1024);
+ if(!uset_containsString(set, buff, buffLen)) {
+ log_err("Tailored set doesn't contain %s... It should\n", setTest[i].tests[j]);
+ }
+ }
+ uset_close(set);
+ } else {
+ log_err("Couldn't open collator with rules %s\n", setTest[i].rules);
+ }
+ ucol_close(coll);
+ }
+}
+
+static int tMemCmp(const uint8_t *first, const uint8_t *second) {
+ int32_t firstLen = (int32_t)strlen((const char *)first);
+ int32_t secondLen = (int32_t)strlen((const char *)second);
+ return memcmp(first, second, uprv_min(firstLen, secondLen));
+}
+static const char * strengthsC[] = {
+ "UCOL_PRIMARY",
+ "UCOL_SECONDARY",
+ "UCOL_TERTIARY",
+ "UCOL_QUATERNARY",
+ "UCOL_IDENTICAL"
+};
+
+void TestMergeSortKeys(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("en", &status);
+ if(U_SUCCESS(status)) {
+
+ const char* cases[] = {
+ "abc",
+ "abcd",
+ "abcde"
+ };
+ uint32_t casesSize = sizeof(cases)/sizeof(cases[0]);
+ const char* prefix = "foo";
+ const char* suffix = "egg";
+ char outBuff1[256], outBuff2[256];
+
+ uint8_t **sortkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *));
+ uint8_t **mergedPrefixkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *));
+ uint8_t **mergedSuffixkeys = (uint8_t **)malloc(casesSize*sizeof(uint8_t *));
+ uint32_t *sortKeysLen = (uint32_t *)malloc(casesSize*sizeof(uint32_t));
+ uint8_t prefixKey[256], suffixKey[256];
+ uint32_t prefixKeyLen = 0, suffixKeyLen = 0, i = 0;
+ UChar buffer[256];
+ uint32_t unescapedLen = 0, l1 = 0, l2 = 0;
+ UColAttributeValue strength;
+
+ log_verbose("ucol_mergeSortkeys test\n");
+ log_verbose("Testing order of the test cases\n");
+ genericLocaleStarter("en", cases, casesSize);
+
+ for(i = 0; i<casesSize; i++) {
+ sortkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t));
+ mergedPrefixkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t));
+ mergedSuffixkeys[i] = (uint8_t *)malloc(256*sizeof(uint8_t));
+ }
+
+ unescapedLen = u_unescape(prefix, buffer, 256);
+ prefixKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, prefixKey, 256);
+
+ unescapedLen = u_unescape(suffix, buffer, 256);
+ suffixKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, suffixKey, 256);
+
+ log_verbose("Massaging data with prefixes and different strengths\n");
+ strength = UCOL_PRIMARY;
+ while(strength <= UCOL_IDENTICAL) {
+ log_verbose("Strength %s\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]);
+ ucol_setAttribute(coll, UCOL_STRENGTH, strength, &status);
+ for(i = 0; i<casesSize; i++) {
+ unescapedLen = u_unescape(cases[i], buffer, 256);
+ sortKeysLen[i] = ucol_getSortKey(coll, buffer, unescapedLen, sortkeys[i], 256);
+ ucol_mergeSortkeys(prefixKey, prefixKeyLen, sortkeys[i], sortKeysLen[i], mergedPrefixkeys[i], 256);
+ ucol_mergeSortkeys(sortkeys[i], sortKeysLen[i], suffixKey, suffixKeyLen, mergedSuffixkeys[i], 256);
+ if(i>0) {
+ if(tMemCmp(mergedPrefixkeys[i-1], mergedPrefixkeys[i]) >= 0) {
+ log_err("Error while comparing prefixed keys @ strength %s:\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]);
+ log_err("%s\n%s\n",
+ ucol_sortKeyToString(coll, mergedPrefixkeys[i-1], outBuff1, &l1),
+ ucol_sortKeyToString(coll, mergedPrefixkeys[i], outBuff2, &l2));
+ }
+ if(tMemCmp(mergedSuffixkeys[i-1], mergedSuffixkeys[i]) >= 0) {
+ log_err("Error while comparing suffixed keys @ strength %s:\n", strengthsC[strength<=UCOL_QUATERNARY?strength:4]);
+ log_err("%s\n%s\n",
+ ucol_sortKeyToString(coll, mergedSuffixkeys[i-1], outBuff1, &l1),
+ ucol_sortKeyToString(coll, mergedSuffixkeys[i], outBuff2, &l2));
+ }
+ }
+ }
+ if(strength == UCOL_QUATERNARY) {
+ strength = UCOL_IDENTICAL;
+ } else {
+ strength++;
+ }
+ }
+
+ {
+ uint8_t smallBuf[3];
+ uint32_t reqLen = 0;
+ log_verbose("testing buffer overflow\n");
+ reqLen = ucol_mergeSortkeys(prefixKey, prefixKeyLen, suffixKey, suffixKeyLen, smallBuf, 3);
+ if(reqLen != (prefixKeyLen+suffixKeyLen-1)) {
+ log_err("Wrong preflight size for merged sortkey\n");
+ }
+ }
+
+ {
+ UChar empty = 0;
+ uint8_t emptyKey[20], abcKey[50], mergedKey[100];
+ int32_t emptyKeyLen = 0, abcKeyLen = 0, mergedKeyLen = 0;
+
+ log_verbose("testing merging with sortkeys generated for empty strings\n");
+ emptyKeyLen = ucol_getSortKey(coll, &empty, 0, emptyKey, 20);
+ unescapedLen = u_unescape(cases[0], buffer, 256);
+ abcKeyLen = ucol_getSortKey(coll, buffer, unescapedLen, abcKey, 50);
+ mergedKeyLen = ucol_mergeSortkeys(emptyKey, emptyKeyLen, abcKey, abcKeyLen, mergedKey, 100);
+ if(mergedKey[0] != 2) {
+ log_err("Empty sortkey didn't produce a level separator\n");
+ }
+ /* try with zeros */
+ mergedKeyLen = ucol_mergeSortkeys(emptyKey, 0, abcKey, abcKeyLen, mergedKey, 100);
+ if(mergedKeyLen != 0 || mergedKey[0] != 0) {
+ log_err("Empty key didn't produce null mergedKey\n");
+ }
+ mergedKeyLen = ucol_mergeSortkeys(abcKey, abcKeyLen, emptyKey, 0, mergedKey, 100);
+ if(mergedKeyLen != 0 || mergedKey[0] != 0) {
+ log_err("Empty key didn't produce null mergedKey\n");
+ }
+
+ }
+
+ for(i = 0; i<casesSize; i++) {
+ free(sortkeys[i]);
+ free(mergedPrefixkeys[i]);
+ free(mergedSuffixkeys[i]);
+ }
+ free(sortkeys);
+ free(mergedPrefixkeys);
+ free(mergedSuffixkeys);
+ free(sortKeysLen);
+ ucol_close(coll);
+ /* need to finish this up */
+ } else {
+ log_data_err("Couldn't open collator");
+ }
+}
+static void TestShortString(void)
+{
+ struct {
+ const char *input;
+ const char *expectedOutput;
+ const char *locale;
+ UErrorCode expectedStatus;
+ int32_t expectedOffset;
+ uint32_t expectedIdentifier;
+ } testCases[] = {
+ {"LDE_RDE_KPHONEBOOK_T0041_ZLATN","B2900_KPHONEBOOK_LDE", "de@collation=phonebook", U_USING_FALLBACK_WARNING, 0, 0 },
+ {"LEN_RUS_NO_AS_S4","AS_LEN_NO_S4", NULL, U_USING_FALLBACK_WARNING, 0, 0 },
+ {"LDE_VPHONEBOOK_EO_SI","EO_KPHONEBOOK_LDE_SI", "de@collation=phonebook", U_ZERO_ERROR, 0, 0 },
+ {"LDE_Kphonebook","KPHONEBOOK_LDE", "de@collation=phonebook", U_ZERO_ERROR, 0, 0 },
+ {"Xqde_DE@collation=phonebookq_S3_EX","KPHONEBOOK_LDE", "de@collation=phonebook", U_USING_FALLBACK_WARNING, 0, 0 },
+ {"LFR_FO", "LFR", NULL, U_ZERO_ERROR, 0, 0 },
+ {"SO_LX_AS", "", NULL, U_ILLEGAL_ARGUMENT_ERROR, 8, 0 },
+ {"S3_ASS_MMM", "", NULL, U_ILLEGAL_ARGUMENT_ERROR, 5, 0 }
+ };
+
+ int32_t i = 0, j = 0;
+ UCollator *coll = NULL, *fromID = NULL, *fromNormalized = NULL;
+ UParseError parseError;
+ UErrorCode status = U_ZERO_ERROR;
+ char fromShortBuffer[256], fromIDBuffer[256], fromIDRoundtrip[256], normalizedBuffer[256], fromNormalizedBuffer[256];
+ uint32_t identifier = 0, idFromSS = 0;
+ const char* locale = NULL;
+
+
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ status = U_ZERO_ERROR;
+ if(testCases[i].locale) {
+ locale = testCases[i].locale;
+ } else {
+ locale = NULL;
+ }
+
+ coll = ucol_openFromShortString(testCases[i].input, FALSE, &parseError, &status);
+ if(status != testCases[i].expectedStatus) {
+ log_err("Got status '%s' that is different from expected '%s' for '%s'\n",
+ u_errorName(status), u_errorName(testCases[i].expectedStatus), testCases[i].input);
+ }
+
+ if(U_SUCCESS(status)) {
+ ucol_getShortDefinitionString(coll, locale, fromShortBuffer, 256, &status);
+
+ if(strcmp(fromShortBuffer, testCases[i].expectedOutput)) {
+ log_err("Got short string '%s' from the collator. Expected '%s' for input '%s'\n",
+ fromShortBuffer, testCases[i].expectedOutput, testCases[i].input);
+ }
+
+ ucol_normalizeShortDefinitionString(testCases[i].input, normalizedBuffer, 256, &parseError, &status);
+ fromNormalized = ucol_openFromShortString(normalizedBuffer, FALSE, &parseError, &status);
+ ucol_getShortDefinitionString(fromNormalized, locale, fromNormalizedBuffer, 256, &status);
+
+ if(strcmp(fromShortBuffer, fromNormalizedBuffer)) {
+ log_err("Strings obtained from collators instantiated by short string ('%s') and from normalized string ('%s') differ\n",
+ fromShortBuffer, fromNormalizedBuffer);
+ }
+
+
+ if(!ucol_equals(coll, fromNormalized)) {
+ log_err("Collator from short string ('%s') differs from one obtained through a normalized version ('%s')\n",
+ testCases[i].input, normalizedBuffer);
+ }
+
+ /* test identifiers */
+ identifier = ucol_collatorToIdentifier(coll, locale, &status);
+ if(identifier < UCOL_SIT_COLLATOR_NOT_ENCODABLE) {
+ ucol_identifierToShortString(identifier, fromIDBuffer, 256, FALSE, &status);
+ fromID = ucol_openFromIdentifier(identifier, FALSE, &status);
+ if(!ucol_equals(coll, fromID)) {
+ log_err("Collator from short string ('%s') differs from one obtained through an identifier ('%s')\n",
+ testCases[i].input, fromIDBuffer);
+ }
+ ucol_close(fromID);
+ }
+
+ /* round-trip short string - identifier */
+ for(j = 1; j < 2; j++) {
+ idFromSS = ucol_shortStringToIdentifier(testCases[i].input, (UBool)j, &status);
+ ucol_identifierToShortString(idFromSS, fromIDBuffer, 256, (UBool)j, &status);
+ identifier = ucol_shortStringToIdentifier(fromIDBuffer, (UBool)j, &status);
+ ucol_identifierToShortString(identifier, fromIDRoundtrip, 256, (UBool)j, &status);
+
+ if(idFromSS != identifier) {
+ log_err("FD = %i, id didn't round trip. %08X vs %08X (%s)\n",
+ j, idFromSS, identifier, testCases[i].input);
+ }
+ if(strcmp(fromIDBuffer, fromIDRoundtrip)) {
+ log_err("FD = %i, SS didn't round trip. %s vs %s (%s)\n",
+ j, fromIDBuffer, fromIDRoundtrip, testCases[i].input);
+ }
+ }
+
+ ucol_close(fromNormalized);
+ ucol_close(coll);
+
+ } else {
+ if(parseError.offset != testCases[i].expectedOffset) {
+ log_err("Got parse error offset %i, but expected %i instead for '%s'\n",
+ parseError.offset, testCases[i].expectedOffset, testCases[i].input);
+ }
+ }
+ }
+
+}
+
+static void
+doSetsTest(const char *locale, const USet *ref, USet *set, const char* inSet, const char* outSet, UErrorCode *status) {
+ UChar buffer[512];
+ int32_t bufLen;
+
+ uset_clear(set);
+ bufLen = u_unescape(inSet, buffer, 512);
+ uset_applyPattern(set, buffer, bufLen, 0, status);
+ if(U_FAILURE(*status)) {
+ log_err("%s: Failure setting pattern %s\n", locale, u_errorName(*status));
+ }
+
+ if(!uset_containsAll(ref, set)) {
+ log_err("%s: Some stuff from %s is not present in the set\n", locale, inSet);
+ }
+
+ uset_clear(set);
+ bufLen = u_unescape(outSet, buffer, 512);
+ uset_applyPattern(set, buffer, bufLen, 0, status);
+ if(U_FAILURE(*status)) {
+ log_err("%s: Failure setting pattern %s\n", locale, u_errorName(*status));
+ }
+
+ if(!uset_containsNone(ref, set)) {
+ log_err("%s: Some stuff from %s is present in the set\n", locale, outSet);
+ }
+}
+
+
+
+
+static void
+TestGetContractionsAndUnsafes(void)
+{
+ static struct {
+ const char* locale;
+ const char* inConts;
+ const char* outConts;
+ const char* inExp;
+ const char* outExp;
+ const char* unsafeCodeUnits;
+ const char* safeCodeUnits;
+ } tests[] = {
+ { "ru",
+ "[{\\u0474\\u030F}{\\u0475\\u030F}{\\u04D8\\u0308}{\\u04D9\\u0308}{\\u04E8\\u0308}{\\u04E9\\u0308}]",
+ "[{\\u0430\\u0306}{\\u0410\\u0306}{\\u0430\\u0308}{\\u0410\\u0306}{\\u0433\\u0301}{\\u0413\\u0301}]",
+ "[\\u00e6]",
+ "[a]",
+ "[\\u0474\\u0475\\u04d8\\u04d9\\u04e8\\u04e9]",
+ "[aAbB\\u0430\\u0410\\u0433\\u0413]"
+ },
+ { "uk",
+ "[{\\u0474\\u030F}{\\u0475\\u030F}{\\u04D8\\u0308}{\\u04D9\\u0308}{\\u04E8\\u0308}{\\u04E9\\u0308}"
+ "{\\u0430\\u0306}{\\u0410\\u0306}{\\u0430\\u0308}{\\u0410\\u0306}{\\u0433\\u0301}{\\u0413\\u0301}]",
+ "[]",
+ "[\\u00e6]",
+ "[a]",
+ "[\\u0474\\u0475\\u04D8\\u04D9\\u04E8\\u04E9\\u0430\\u0410\\u0433\\u0413]",
+ "[aAbBxv]",
+ },
+ { "sh",
+ "[{C\\u0301}{C\\u030C}{C\\u0341}{DZ\\u030C}{Dz\\u030C}{D\\u017D}{D\\u017E}{lj}{nj}]",
+ "[{\\u309d\\u3099}{\\u30fd\\u3099}]",
+ "[\\u00e6]",
+ "[a]",
+ "[nlcdzNLCDZ]",
+ "[jabv]"
+ },
+ { "ja",
+ "[{\\u3053\\u3099\\u309D}{\\u3053\\u3099\\u309D\\u3099}{\\u3053\\u3099\\u309E}{\\u3053\\u3099\\u30FC}{\\u3053\\u309D}{\\u3053\\u309D\\u3099}{\\u3053\\u309E}{\\u3053\\u30FC}{\\u30B3\\u3099\\u30FC}{\\u30B3\\u3099\\u30FD}{\\u30B3\\u3099\\u30FD\\u3099}{\\u30B3\\u3099\\u30FE}{\\u30B3\\u30FC}{\\u30B3\\u30FD}{\\u30B3\\u30FD\\u3099}{\\u30B3\\u30FE}]",
+ "[{\\u30FD\\u3099}{\\u309D\\u3099}{\\u3053\\u3099}{\\u30B3\\u3099}{lj}{nj}]",
+ "[\\u30FE\\u00e6]",
+ "[a]",
+ "[\\u3099]",
+ "[]"
+ }
+ };
+
+
+
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = NULL;
+ int32_t i = 0;
+ int32_t noConts = 0;
+ USet *conts = uset_open(0,0);
+ USet *exp = uset_open(0, 0);
+ USet *set = uset_open(0,0);
+ int32_t setBufferLen = 65536;
+ UChar buffer[65536];
+ int32_t setLen = 0;
+
+ for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ log_verbose("Testing locale: %s\n", tests[i].locale);
+ coll = ucol_open(tests[i].locale, &status);
+ ucol_getContractionsAndExpansions(coll, conts, exp, TRUE, &status);
+ doSetsTest(tests[i].locale, conts, set, tests[i].inConts, tests[i].outConts, &status);
+ setLen = uset_toPattern(conts, buffer, setBufferLen, TRUE, &status);
+ if(U_SUCCESS(status)) {
+ /*log_verbose("Contractions %i: %s\n", uset_getItemCount(conts), aescstrdup(buffer, setLen));*/
+ } else {
+ log_err("error %s. %i\n", u_errorName(status), setLen);
+ status = U_ZERO_ERROR;
+ }
+ doSetsTest(tests[i].locale, exp, set, tests[i].inExp, tests[i].outExp, &status);
+ setLen = uset_toPattern(exp, buffer, setBufferLen, TRUE, &status);
+ if(U_SUCCESS(status)) {
+ /*log_verbose("Expansions %i: %s\n", uset_getItemCount(exp), aescstrdup(buffer, setLen));*/
+ } else {
+ log_err("error %s. %i\n", u_errorName(status), setLen);
+ status = U_ZERO_ERROR;
+ }
+
+ noConts = ucol_getUnsafeSet(coll, conts, &status);
+ doSetsTest(tests[i].locale, conts, set, tests[i].unsafeCodeUnits, tests[i].safeCodeUnits, &status);
+ setLen = uset_toPattern(conts, buffer, setBufferLen, TRUE, &status);
+ if(U_SUCCESS(status)) {
+ log_verbose("Unsafe %i: %s\n", uset_getItemCount(exp), aescstrdup(buffer, setLen));
+ } else {
+ log_err("error %s. %i\n", u_errorName(status), setLen);
+ status = U_ZERO_ERROR;
+ }
+
+ ucol_close(coll);
+ }
+
+
+ uset_close(conts);
+ uset_close(exp);
+ uset_close(set);
+}
+
+static void
+TestOpenBinary(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ /*
+ char rule[] = "&h < d < c < b";
+ char *wUCA[] = { "a", "h", "d", "c", "b", "i" };
+ char *noUCA[] = {"d", "c", "b", "a", "h", "i" };
+ */
+ /* we have to use Cyrillic letters because latin-1 always gets copied */
+ const char rule[] = "&\\u0452 < \\u0434 < \\u0433 < \\u0432"; /* &dje < d < g < v */
+ const char *wUCA[] = { "\\u0430", "\\u0452", "\\u0434", "\\u0433", "\\u0432", "\\u0435" }; /* a, dje, d, g, v, e */
+ const char *noUCA[] = {"\\u0434", "\\u0433", "\\u0432", "\\u0430", "\\u0435", "\\u0452" }; /* d, g, v, a, e, dje */
+
+ UChar uRules[256];
+ int32_t uRulesLen = u_unescape(rule, uRules, 256);
+
+ UCollator *coll = ucol_openRules(uRules, uRulesLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ UCollator *UCA = ucol_open("root", &status);
+ UCollator *cloneNOUCA = NULL, *cloneWUCA = NULL;
+
+ uint8_t imageBuffer[32768];
+ uint8_t *image = imageBuffer;
+ int32_t imageBufferCapacity = 32768;
+
+ int32_t imageSize;
+
+ if((coll==NULL)||(UCA==NULL)||(U_FAILURE(status))) {
+ log_data_err("could not load collators or error occured: %s\n",
+ u_errorName(status));
+ return;
+ }
+ imageSize = ucol_cloneBinary(coll, image, imageBufferCapacity, &status);
+ if(U_FAILURE(status)) {
+ image = (uint8_t *)malloc(imageSize*sizeof(uint8_t));
+ status = U_ZERO_ERROR;
+ imageSize = ucol_cloneBinary(coll, imageBuffer, imageSize, &status);
+ }
+
+
+ cloneWUCA = ucol_openBinary(image, imageSize, UCA, &status);
+ cloneNOUCA = ucol_openBinary(image, imageSize, NULL, &status);
+
+ genericOrderingTest(coll, wUCA, sizeof(wUCA)/sizeof(wUCA[0]));
+
+ genericOrderingTest(cloneWUCA, wUCA, sizeof(wUCA)/sizeof(wUCA[0]));
+ genericOrderingTest(cloneNOUCA, noUCA, sizeof(noUCA)/sizeof(noUCA[0]));
+
+ if(image != imageBuffer) {
+ free(image);
+ }
+ ucol_close(coll);
+ ucol_close(cloneNOUCA);
+ ucol_close(cloneWUCA);
+ ucol_close(UCA);
+}
+
+static void TestDefault(void) {
+ /* Tests for code coverage. */
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("es@collation=pinyin", &status);
+ if (status != U_USING_DEFAULT_WARNING) {
+ /* What do you mean that you know about using pinyin collation in Spanish!? This should be in the zh locale. */
+ log_err("es@collation=pinyin should return U_USING_DEFAULT_WARNING, but returned %s\n", u_errorName(status));
+ }
+ ucol_close(coll);
+ if (ucol_getKeywordValues("funky", &status) != NULL) {
+ log_err("Collators should not know about the funky keyword.\n");
+ }
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("funky keyword didn't fail as expected %s\n", u_errorName(status));
+ }
+ if (ucol_getKeywordValues("collation", &status) != NULL) {
+ log_err("ucol_getKeywordValues should not work when given a bad status.\n");
+ }
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h
new file mode 100644
index 00000000000..49f8b7533c6
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/capitst.h
@@ -0,0 +1,124 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CAPITEST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*//* C API TEST For COLLATOR */
+
+#ifndef _CCOLLAPITST
+#define _CCOLLAPITST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+#include "callcoll.h"
+#define MAX_TOKEN_LEN 16
+
+
+ /**
+ * error reporting utility method
+ **/
+
+ static void doAssert(int condition, const char *message);
+ /**
+ * Collator Class Properties
+ * ctor, dtor, createInstance, compare, getStrength/setStrength
+ * getDecomposition/setDecomposition, getDisplayName
+ */
+ void TestProperty(void);
+ /**
+ * Test RuleBasedCollator and getRules
+ **/
+ void TestRuleBasedColl(void);
+
+ /**
+ * Test compare
+ **/
+ void TestCompare(void);
+ /**
+ * Test hashCode functionality
+ **/
+ void TestHashCode(void);
+ /**
+ * Tests the constructor and numerous other methods for CollationKey
+ **/
+ void TestSortKey(void);
+ /**
+ * test the CollationElementIterator methods
+ **/
+ void TestElemIter(void);
+ /**
+ * Test ucol_getAvailable and ucol_countAvailable()
+ **/
+ void TestGetAll(void);
+ /**
+ * Test ucol_GetDefaultRules ()
+ void TestGetDefaultRules(void);
+ **/
+
+ void TestDecomposition(void);
+ /**
+ * Test ucol_safeClone ()
+ **/
+ void TestSafeClone(void);
+
+ /**
+ * Test ucol_cloneBinary(), ucol_openBinary()
+ **/
+ void TestCloneBinary(void);
+
+ /**
+ * Test getting bounds for a sortkey
+ */
+ void TestBounds(void);
+
+ /**
+ * Test ucol_getLocale function
+ */
+ void TestGetLocale(void);
+
+ /**
+ * Test buffer overrun while having smaller buffer for sortkey (j1865)
+ */
+ void TestSortKeyBufferOverrun(void);
+ /**
+ * Test getting and setting of attributes
+ */
+ void TestGetSetAttr(void);
+ /**
+ * Test getTailoredSet
+ */
+ void TestGetTailoredSet(void);
+
+ /**
+ * Test mergeSortKeys
+ */
+ void TestMergeSortKeys(void);
+
+ /**
+ * test short string and collator identifier functions
+ */
+ static void TestShortString(void);
+
+ /**
+ * test getContractions and getUnsafeSet
+ */
+ static void TestGetContractionsAndUnsafes(void);
+
+ /**
+ * Test funny stuff with open binary
+ */
+ static void TestOpenBinary(void);
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c
new file mode 100644
index 00000000000..fe597ae1857
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.c
@@ -0,0 +1,708 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CBIAPTS.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************/
+/*C API TEST FOR BREAKITERATOR */
+/**
+* This is an API test. It doesn't test very many cases, and doesn't
+* try to test the full functionality. It just calls each function in the class and
+* verifies that it works on a basic level.
+**/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/uloc.h"
+#include "unicode/ubrk.h"
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "unicode/utext.h"
+#include "cintltst.h"
+#include "cbiapts.h"
+
+#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
+log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}}
+
+#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \
+log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}}
+
+static void TestBreakIteratorSafeClone(void);
+static void TestBreakIteratorRules(void);
+static void TestBreakIteratorRuleError(void);
+static void TestBreakIteratorStatusVec(void);
+static void TestBreakIteratorUText(void);
+
+void addBrkIterAPITest(TestNode** root);
+
+void addBrkIterAPITest(TestNode** root)
+{
+ addTest(root, &TestBreakIteratorCAPI, "tstxtbd/cbiapts/TestBreakIteratorCAPI");
+ addTest(root, &TestBreakIteratorSafeClone, "tstxtbd/cbiapts/TestBreakIteratorSafeClone");
+ addTest(root, &TestBreakIteratorRules, "tstxtbd/cbiapts/TestBreakIteratorRules");
+ addTest(root, &TestBreakIteratorRuleError, "tstxtbd/cbiapts/TestBreakIteratorRuleError");
+ addTest(root, &TestBreakIteratorStatusVec, "tstxtbd/cbiapts/TestBreakIteratorStatusVec");
+ addTest(root, &TestBreakIteratorUText, "tstxtbd/cbiapts/TestBreakIteratorUText");
+}
+
+#define CLONETEST_ITERATOR_COUNT 2
+
+/*
+ * Utility function for converting char * to UChar * strings, to
+ * simplify the test code. Converted strings are put in heap allocated
+ * storage. A hook (probably a local in the caller's code) allows all
+ * strings converted with that hook to be freed with a single call.
+ */
+typedef struct StringStruct {
+ struct StringStruct *link;
+ UChar str[1];
+ } StringStruct;
+
+
+static UChar* toUChar(const char *src, void **freeHook) {
+ /* Structure of the memory that we allocate on the heap */
+
+ int32_t numUChars;
+ int32_t destSize;
+ UChar stackBuf[2000 + sizeof(void *)/sizeof(UChar)];
+ StringStruct *dest;
+ UConverter *cnv;
+
+ UErrorCode status = U_ZERO_ERROR;
+ if (src == NULL) {
+ return NULL;
+ };
+
+ cnv = ucnv_open(NULL, &status);
+ if(U_FAILURE(status) || cnv == NULL) {
+ return NULL;
+ }
+ ucnv_reset(cnv);
+ numUChars = ucnv_toUChars(cnv,
+ stackBuf,
+ 2000,
+ src, -1,
+ &status);
+
+ destSize = (numUChars+1) * sizeof(UChar) + sizeof(struct StringStruct);
+ dest = (StringStruct *)malloc(destSize);
+ if (dest != NULL) {
+ if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) {
+ ucnv_toUChars(cnv, dest->str, numUChars+1, src, -1, &status);
+ } else if (status == U_ZERO_ERROR) {
+ u_strcpy(dest->str, stackBuf);
+ } else {
+ free(dest);
+ dest = NULL;
+ }
+ }
+
+ ucnv_reset(cnv); /* be good citizens */
+ ucnv_close(cnv);
+ if (dest == NULL) {
+ return NULL;
+ }
+
+ dest->link = (StringStruct*)(*freeHook);
+ *freeHook = dest;
+ return dest->str;
+}
+
+static void freeToUCharStrings(void **hook) {
+ StringStruct *s = *(StringStruct **)hook;
+ while (s != NULL) {
+ StringStruct *next = s->link;
+ free(s);
+ s = next;
+ }
+}
+
+
+static void TestBreakIteratorCAPI()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UBreakIterator *word, *sentence, *line, *character, *b, *bogus;
+ int32_t start,pos,end,to;
+ int32_t i;
+ int32_t count = 0;
+
+ UChar text[50];
+
+ /* Note: the adjacent "" are concatenating strings, not adding a \" to the
+ string, which is probably what whoever wrote this intended. Don't fix,
+ because it would throw off the hard coded break positions in the following
+ tests. */
+ u_uastrcpy(text, "He's from Africa. ""Mr. Livingston, I presume?"" Yeah");
+
+
+/*test ubrk_open()*/
+ log_verbose("\nTesting BreakIterator open functions\n");
+
+ /* Use french for fun */
+ word = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Check your data - it doesn't seem to be around\n");
+ return;
+ } else if(U_FAILURE(status)){
+ log_err("FAIL: Error in ubrk_open() for word breakiterator: %s\n", myErrorName(status));
+ }
+ else{
+ log_verbose("PASS: Successfully opened word breakiterator\n");
+ }
+
+ sentence = ubrk_open(UBRK_SENTENCE, "en_US", text, u_strlen(text), &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: Error in ubrk_open() for sentence breakiterator: %s\n", myErrorName(status));
+ return;
+ }
+ else{
+ log_verbose("PASS: Successfully opened sentence breakiterator\n");
+ }
+
+ line = ubrk_open(UBRK_LINE, "en_US", text, u_strlen(text), &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: Error in ubrk_open() for line breakiterator: %s\n", myErrorName(status));
+ return;
+ }
+ else{
+ log_verbose("PASS: Successfully opened line breakiterator\n");
+ }
+
+ character = ubrk_open(UBRK_CHARACTER, "en_US", text, u_strlen(text), &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: Error in ubrk_open() for character breakiterator: %s\n", myErrorName(status));
+ return;
+ }
+ else{
+ log_verbose("PASS: Successfully opened character breakiterator\n");
+ }
+ /*trying to open an illegal iterator*/
+ bogus = ubrk_open((UBreakIteratorType)5, "en_US", text, u_strlen(text), &status);
+ if(U_SUCCESS(status)){
+ log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n");
+ }
+ if(U_FAILURE(status)){
+ if(status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n Got %s\n", myErrorName(status));
+ }
+ }
+ status=U_ZERO_ERROR;
+
+
+/* ======= Test ubrk_countAvialable() and ubrk_getAvialable() */
+
+ log_verbose("\nTesting ubrk_countAvailable() and ubrk_getAvailable()\n");
+ count=ubrk_countAvailable();
+ /* use something sensible w/o hardcoding the count */
+ if(count < 0){
+ log_err("FAIL: Error in ubrk_countAvialable() returned %d\n", count);
+ }
+ else{
+ log_verbose("PASS: ubrk_countAvialable() successful returned %d\n", count);
+ }
+ for(i=0;i<count;i++)
+ {
+ log_verbose("%s\n", ubrk_getAvailable(i));
+ if (ubrk_getAvailable(i) == 0)
+ log_err("No locale for which breakiterator is applicable\n");
+ else
+ log_verbose("A locale %s for which breakiterator is applicable\n",ubrk_getAvailable(i));
+ }
+
+/*========Test ubrk_first(), ubrk_last()...... and other functions*/
+
+ log_verbose("\nTesting the functions for word\n");
+ start = ubrk_first(word);
+ if(start!=0)
+ log_err("error ubrk_start(word) did not return 0\n");
+ log_verbose("first (word = %d\n", (int32_t)start);
+ pos=ubrk_next(word);
+ if(pos!=4)
+ log_err("error ubrk_next(word) did not return 4\n");
+ log_verbose("next (word = %d\n", (int32_t)pos);
+ pos=ubrk_following(word, 4);
+ if(pos!=5)
+ log_err("error ubrl_following(word,4) did not return 6\n");
+ log_verbose("next (word = %d\n", (int32_t)pos);
+ end=ubrk_last(word);
+ if(end!=49)
+ log_err("error ubrk_last(word) did not return 49\n");
+ log_verbose("last (word = %d\n", (int32_t)end);
+
+ pos=ubrk_previous(word);
+ log_verbose("%d %d\n", end, pos);
+
+ pos=ubrk_previous(word);
+ log_verbose("%d \n", pos);
+
+ if (ubrk_isBoundary(word, 2) != FALSE) {
+ log_err("error ubrk_isBoundary(word, 2) did not return FALSE\n");
+ }
+ pos=ubrk_current(word);
+ if (pos != 4) {
+ log_err("error ubrk_current() != 4 after ubrk_isBoundary(word, 2)\n");
+ }
+ if (ubrk_isBoundary(word, 4) != TRUE) {
+ log_err("error ubrk_isBoundary(word, 4) did not return TRUE\n");
+ }
+
+
+
+ log_verbose("\nTesting the functions for character\n");
+ ubrk_first(character);
+ pos = ubrk_following(character, 5);
+ if(pos!=6)
+ log_err("error ubrk_following(character,5) did not return 6\n");
+ log_verbose("Following (character,5) = %d\n", (int32_t)pos);
+ pos=ubrk_following(character, 18);
+ if(pos!=19)
+ log_err("error ubrk_following(character,18) did not return 19\n");
+ log_verbose("Followingcharacter,18) = %d\n", (int32_t)pos);
+ pos=ubrk_preceding(character, 22);
+ if(pos!=21)
+ log_err("error ubrk_preceding(character,22) did not return 21\n");
+ log_verbose("preceding(character,22) = %d\n", (int32_t)pos);
+
+
+ log_verbose("\nTesting the functions for line\n");
+ pos=ubrk_first(line);
+ if(pos != 0)
+ log_err("error ubrk_first(line) returned %d, expected 0\n", (int32_t)pos);
+ pos = ubrk_next(line);
+ pos=ubrk_following(line, 18);
+ if(pos!=22)
+ log_err("error ubrk_following(line) did not return 22\n");
+ log_verbose("following (line) = %d\n", (int32_t)pos);
+
+
+ log_verbose("\nTesting the functions for sentence\n");
+ ubrk_first(sentence);
+ pos = ubrk_current(sentence);
+ log_verbose("Current(sentence) = %d\n", (int32_t)pos);
+ pos = ubrk_last(sentence);
+ if(pos!=49)
+ log_err("error ubrk_last for sentence did not return 49\n");
+ log_verbose("Last (sentence) = %d\n", (int32_t)pos);
+ ubrk_first(sentence);
+ to = ubrk_following( sentence, 0 );
+ if (to == 0) log_err("ubrk_following returned 0\n");
+ to = ubrk_preceding( sentence, to );
+ if (to != 0) log_err("ubrk_preceding didn't return 0\n");
+ if (ubrk_first(sentence)!=ubrk_current(sentence)) {
+ log_err("error in ubrk_first() or ubrk_current()\n");
+ }
+
+
+ /*---- */
+ /*Testing ubrk_open and ubrk_close()*/
+ log_verbose("\nTesting open and close for us locale\n");
+ b = ubrk_open(UBRK_WORD, "fr_FR", text, u_strlen(text), &status);
+ if (U_FAILURE(status)) {
+ log_err("ubrk_open for word returned NULL: %s\n", myErrorName(status));
+ }
+ ubrk_close(b);
+
+ /* Test setText and setUText */
+ {
+ UChar s1[] = {0x41, 0x42, 0x20, 0};
+ UChar s2[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0};
+ UText *ut = NULL;
+ UBreakIterator *bb;
+ int j;
+
+ log_verbose("\nTesting ubrk_setText() and ubrk_setUText()\n");
+ status = U_ZERO_ERROR;
+ bb = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ ubrk_setText(bb, s1, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+ ubrk_first(bb);
+ j = ubrk_next(bb);
+ TEST_ASSERT(j == 2);
+ ut = utext_openUChars(ut, s2, -1, &status);
+ ubrk_setUText(bb, ut, &status);
+ TEST_ASSERT_SUCCESS(status);
+ j = ubrk_next(bb);
+ TEST_ASSERT(j == 5);
+
+ ubrk_close(bb);
+ utext_close(ut);
+ }
+
+ ubrk_close(word);
+ ubrk_close(sentence);
+ ubrk_close(line);
+ ubrk_close(character);
+}
+
+static void TestBreakIteratorSafeClone(void)
+{
+ UChar text[51]; /* Keep this odd to test for 64-bit memory alignment */
+ /* NOTE: This doesn't reliably force mis-alignment of following items. */
+ uint8_t buffer [CLONETEST_ITERATOR_COUNT] [U_BRK_SAFECLONE_BUFFERSIZE];
+ int32_t bufferSize = U_BRK_SAFECLONE_BUFFERSIZE;
+
+ UBreakIterator * someIterators [CLONETEST_ITERATOR_COUNT];
+ UBreakIterator * someClonedIterators [CLONETEST_ITERATOR_COUNT];
+
+ UBreakIterator * brk;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t start,pos;
+ int32_t i;
+
+ /*Testing ubrk_safeClone */
+
+ /* Note: the adjacent "" are concatenating strings, not adding a \" to the
+ string, which is probably what whoever wrote this intended. Don't fix,
+ because it would throw off the hard coded break positions in the following
+ tests. */
+ u_uastrcpy(text, "He's from Africa. ""Mr. Livingston, I presume?"" Yeah");
+
+ /* US & Thai - rule-based & dictionary based */
+ someIterators[0] = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status);
+ if(!someIterators[0] || U_FAILURE(status)) {
+ log_data_err("Couldn't open en_US word break iterator - %s\n", u_errorName(status));
+ return;
+ }
+
+ someIterators[1] = ubrk_open(UBRK_WORD, "th_TH", text, u_strlen(text), &status);
+ if(!someIterators[1] || U_FAILURE(status)) {
+ log_data_err("Couldn't open th_TH word break iterator - %s\n", u_errorName(status));
+ return;
+ }
+
+ /* test each type of iterator */
+ for (i = 0; i < CLONETEST_ITERATOR_COUNT; i++)
+ {
+
+ /* Check the various error & informational states */
+
+ /* Null status - just returns NULL */
+ if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, 0))
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with null status\n");
+ }
+ /* error status - should return 0 & keep error the same */
+ status = U_MEMORY_ALLOCATION_ERROR;
+ if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status) || status != U_MEMORY_ALLOCATION_ERROR)
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with incoming error status\n");
+ }
+ status = U_ZERO_ERROR;
+
+ /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
+ if (0 != ubrk_safeClone(someIterators[i], buffer[i], 0, &status) || status != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with null bufferSize pointer\n");
+ }
+ status = U_ZERO_ERROR;
+
+ /* buffer size pointer is 0 - fill in pbufferSize with a size */
+ bufferSize = 0;
+ if (0 != ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status) || U_FAILURE(status) || bufferSize <= 0)
+ {
+ log_err("FAIL: Cloned Iterator failed a sizing request ('preflighting')\n");
+ }
+ /* Verify our define is large enough */
+ if (U_BRK_SAFECLONE_BUFFERSIZE < bufferSize)
+ {
+ log_err("FAIL: Pre-calculated buffer size is too small\n");
+ }
+ /* Verify we can use this run-time calculated size */
+ if (0 == (brk = ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status)) || U_FAILURE(status))
+ {
+ log_err("FAIL: Iterator can't be cloned with run-time size\n");
+ }
+ if (brk)
+ ubrk_close(brk);
+ /* size one byte too small - should allocate & let us know */
+ --bufferSize;
+ if (0 == (brk = ubrk_safeClone(someIterators[i], 0, &bufferSize, &status)) || status != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with too-small buffer size\n");
+ }
+ if (brk)
+ ubrk_close(brk);
+ status = U_ZERO_ERROR;
+ bufferSize = U_BRK_SAFECLONE_BUFFERSIZE;
+
+ /* Null buffer pointer - return Iterator & set error to U_SAFECLONE_ALLOCATED_ERROR */
+ if (0 == (brk = ubrk_safeClone(someIterators[i], 0, &bufferSize, &status)) || status != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with null buffer pointer\n");
+ }
+ if (brk)
+ ubrk_close(brk);
+ status = U_ZERO_ERROR;
+
+ /* Mis-aligned buffer pointer. */
+ {
+ char stackBuf[U_BRK_SAFECLONE_BUFFERSIZE+sizeof(void *)];
+ void *p;
+ int32_t offset;
+
+ brk = ubrk_safeClone(someIterators[i], &stackBuf[1], &bufferSize, &status);
+ if (U_FAILURE(status) || brk == 0) {
+ log_err("FAIL: Cloned Iterator failed with misaligned buffer pointer\n");
+ }
+ if (status == U_SAFECLONE_ALLOCATED_WARNING) {
+ log_err("FAIL: Cloned Iterator allocated when using a mis-aligned buffer.\n");
+ }
+ offset = (int32_t)((char *)&p-(char*)brk);
+ if (offset < 0) {
+ offset = -offset;
+ }
+ if (offset % sizeof(void *) != 0) {
+ log_err("FAIL: Cloned Iterator failed to align correctly with misaligned buffer pointer\n");
+ }
+ if (brk)
+ ubrk_close(brk);
+ }
+
+
+ /* Null Iterator - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
+ if (0 != ubrk_safeClone(0, buffer[i], &bufferSize, &status) || status != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned Iterator failed to deal correctly with null Iterator pointer\n");
+ }
+ status = U_ZERO_ERROR;
+
+ /* Do these cloned Iterators work at all - make a first & next call */
+ bufferSize = U_BRK_SAFECLONE_BUFFERSIZE;
+ someClonedIterators[i] = ubrk_safeClone(someIterators[i], buffer[i], &bufferSize, &status);
+
+ start = ubrk_first(someClonedIterators[i]);
+ if(start!=0)
+ log_err("error ubrk_start(clone) did not return 0\n");
+ pos=ubrk_next(someClonedIterators[i]);
+ if(pos!=4)
+ log_err("error ubrk_next(clone) did not return 4\n");
+
+ ubrk_close(someClonedIterators[i]);
+ ubrk_close(someIterators[i]);
+ }
+}
+
+
+/*
+// Open a break iterator from char * rules. Take care of conversion
+// of the rules and error checking.
+*/
+static UBreakIterator * testOpenRules(char *rules) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *ruleSourceU = NULL;
+ void *strCleanUp = NULL;
+ UParseError parseErr;
+ UBreakIterator *bi;
+
+ ruleSourceU = toUChar(rules, &strCleanUp);
+
+ bi = ubrk_openRules(ruleSourceU, -1, /* The rules */
+ NULL, -1, /* The text to be iterated over. */
+ &parseErr, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ubrk_openRules: ICU Error \"%s\"\n", u_errorName(status));
+ bi = 0;
+ };
+ freeToUCharStrings(&strCleanUp);
+ return bi;
+
+}
+
+/*
+ * TestBreakIteratorRules - Verify that a break iterator can be created from
+ * a set of source rules.
+ */
+static void TestBreakIteratorRules() {
+ /* Rules will keep together any run of letters not including 'a', OR
+ * keep together 'abc', but only when followed by 'def', OTHERWISE
+ * just return one char at a time.
+ */
+ char rules[] = "abc{666}/def;\n [\\p{L} - [a]]* {2}; . {1};";
+ /* 0123456789012345678 */
+ char data[] = "abcdex abcdefgh-def"; /* the test data string */
+ char breaks[] = "** ** * ** *"; /* * the expected break positions */
+ char tags[] = "01 21 6 21 2"; /* expected tag values at break positions */
+ int32_t tagMap[] = {0, 1, 2, 3, 4, 5, 666};
+
+ UChar *uData;
+ void *freeHook = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t pos;
+ int i;
+
+ UBreakIterator *bi = testOpenRules(rules);
+ if (bi == NULL) {return;}
+ uData = toUChar(data, &freeHook);
+ ubrk_setText(bi, uData, -1, &status);
+
+ pos = ubrk_first(bi);
+ for (i=0; i<sizeof(breaks); i++) {
+ if (pos == i && breaks[i] != '*') {
+ log_err("FAIL: unexpected break at position %d found\n", pos);
+ break;
+ }
+ if (pos != i && breaks[i] == '*') {
+ log_err("FAIL: expected break at position %d not found.\n", i);
+ break;
+ }
+ if (pos == i) {
+ int32_t tag, expectedTag;
+ tag = ubrk_getRuleStatus(bi);
+ expectedTag = tagMap[tags[i]&0xf];
+ if (tag != expectedTag) {
+ log_err("FAIL: incorrect tag value. Position = %d; expected tag %d, got %d",
+ pos, expectedTag, tag);
+ break;
+ }
+ pos = ubrk_next(bi);
+ }
+ }
+
+ freeToUCharStrings(&freeHook);
+ ubrk_close(bi);
+}
+
+static void TestBreakIteratorRuleError() {
+/*
+ * TestBreakIteratorRuleError - Try to create a BI from rules with syntax errors,
+ * check that the error is reported correctly.
+ */
+ char rules[] = " # This is a rule comment on line 1\n"
+ "[:L:]; # this rule is OK.\n"
+ "abcdefg); # Error, mismatched parens\n";
+ UChar *uRules;
+ void *freeHook = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseErr;
+ UBreakIterator *bi;
+
+ uRules = toUChar(rules, &freeHook);
+ bi = ubrk_openRules(uRules, -1, /* The rules */
+ NULL, -1, /* The text to be iterated over. */
+ &parseErr, &status);
+ if (U_SUCCESS(status)) {
+ log_err("FAIL: construction of break iterator succeeded when it should have failed.\n");
+ ubrk_close(bi);
+ } else {
+ if (parseErr.line != 3 || parseErr.offset != 8) {
+ log_err("FAIL: incorrect error position reported. Got line %d, char %d, expected line 3, char 7",
+ parseErr.line, parseErr.offset);
+ }
+ }
+ freeToUCharStrings(&freeHook);
+}
+
+
+/*
+* TestsBreakIteratorStatusVals() Test the ubrk_getRuleStatusVec() funciton
+*/
+static void TestBreakIteratorStatusVec() {
+ #define RULE_STRING_LENGTH 200
+ UChar rules[RULE_STRING_LENGTH];
+
+ #define TEST_STRING_LENGTH 25
+ UChar testString[TEST_STRING_LENGTH];
+ UBreakIterator *bi = NULL;
+ int32_t pos = 0;
+ int32_t vals[10];
+ int32_t numVals;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_uastrncpy(rules, "[A-N]{100}; \n"
+ "[a-w]{200}; \n"
+ "[\\p{L}]{300}; \n"
+ "[\\p{N}]{400}; \n"
+ "[0-5]{500}; \n"
+ "!.*;\n", RULE_STRING_LENGTH);
+ u_uastrncpy(testString, "ABC", TEST_STRING_LENGTH);
+
+
+ bi = ubrk_openRules(rules, -1, testString, -1, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(bi != NULL);
+
+ /* The TEST_ASSERT above should change too... */
+ if (bi != NULL) {
+ pos = ubrk_next(bi);
+ TEST_ASSERT(pos == 1);
+
+ memset(vals, -1, sizeof(vals));
+ numVals = ubrk_getRuleStatusVec(bi, vals, 10, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(numVals == 2);
+ TEST_ASSERT(vals[0] == 100);
+ TEST_ASSERT(vals[1] == 300);
+ TEST_ASSERT(vals[2] == -1);
+
+ numVals = ubrk_getRuleStatusVec(bi, vals, 0, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(numVals == 2);
+ }
+
+ ubrk_close(bi);
+}
+
+
+/*
+ * static void TestBreakIteratorUText(void);
+ *
+ * Test that ubrk_setUText() is present and works for a simple case.
+ */
+static void TestBreakIteratorUText(void) {
+ const char *UTF8Str = "\x41\xc3\x85\x5A\x20\x41\x52\x69\x6E\x67"; /* c3 85 is utf-8 for A with a ring on top */
+ /* 0 1 2 34567890 */
+
+ UErrorCode status = U_ZERO_ERROR;
+ UBreakIterator *bi = NULL;
+ int32_t pos = 0;
+
+
+ UText *ut = utext_openUTF8(NULL, UTF8Str, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ bi = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status);
+ if (U_FAILURE(status)) {
+ log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ ubrk_setUText(bi, ut, &status);
+ if (U_FAILURE(status)) {
+ log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ pos = ubrk_first(bi);
+ TEST_ASSERT(pos == 0);
+
+ pos = ubrk_next(bi);
+ TEST_ASSERT(pos == 4);
+
+ pos = ubrk_next(bi);
+ TEST_ASSERT(pos == 5);
+
+ pos = ubrk_next(bi);
+ TEST_ASSERT(pos == 10);
+
+ pos = ubrk_next(bi);
+ TEST_ASSERT(pos == UBRK_DONE);
+ ubrk_close(bi);
+ utext_close(ut);
+}
+
+
+
+#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h
new file mode 100644
index 00000000000..ea6769fcf08
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiapts.h
@@ -0,0 +1,35 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CBIAPTS.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************/
+/* C API TEST FOR BREAKITERATOR */
+
+#ifndef _CBRKITRAPITST
+#define _CBRKITRAPITST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+#include "cintltst.h"
+
+/**
+* This is an API test. It doesn't test very many cases, and doesn't
+* try to test the full functionality. It just calls each function in the class and
+* verifies that it works on a basic level.
+**/
+/* The function used to test the BreakIterator API*/
+static void TestBreakIteratorCAPI(void);
+
+#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c
new file mode 100644
index 00000000000..a73f3a74655
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbididat.c
@@ -0,0 +1,434 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/* file name: cbididat.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 1999sep22
+* created by: Markus W. Scherer
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+#include "unicode/ubidi.h"
+#include "cbiditst.h"
+
+const char * const
+dirPropNames[U_CHAR_DIRECTION_COUNT]={
+ "L", "R", "EN", "ES", "ET", "AN", "CS", "B", "S", "WS", "ON",
+ "LRE", "LRO", "AL", "RLE", "RLO", "PDF", "NSM", "BN"
+};
+
+UChar
+charFromDirProp[U_CHAR_DIRECTION_COUNT]={
+ /* L R EN ES ET AN CS B S WS ON */
+ 0x61, 0x5d0, 0x30, 0x2f, 0x25, 0x660, 0x2c, 0xa, 0x9, 0x20, 0x26,
+ /* LRE LRO AL RLE RLO PDF NSM BN */
+ 0x202a, 0x202d, 0x627, 0x202b, 0x202e, 0x202c, 0x308, 0x200c
+};
+
+static const uint8_t
+testText1[]={
+ L, L, WS, L, WS, EN, L, B
+};
+
+static const UBiDiLevel
+testLevels1[]={
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const uint8_t
+testVisualMap1[]={
+ 0, 1, 2, 3, 4, 5, 6, 7
+};
+
+static const uint8_t
+testText2[]={
+ R, AL, WS, R, AL, WS, R
+};
+
+static const UBiDiLevel
+testLevels2[]={
+ 1, 1, 1, 1, 1, 1, 1
+};
+
+static const uint8_t
+testVisualMap2[]={
+ 6, 5, 4, 3, 2, 1, 0
+};
+
+static const uint8_t
+testText3[]={
+ L, L, WS, EN, CS, WS, EN, CS, EN, WS, L, L
+};
+
+static const UBiDiLevel
+testLevels3[]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const uint8_t
+testVisualMap3[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const uint8_t
+testText4[]={
+ L, AL, AL, AL, L, AL, AL, L, WS, EN, CS, WS, EN, CS, EN, WS, L, L
+};
+
+static const UBiDiLevel
+testLevels4[]={
+ 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const uint8_t
+testVisualMap4[]={
+ 0, 3, 2, 1, 4, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
+};
+
+static const uint8_t
+testText5[]={
+ AL, R, AL, WS, EN, CS, WS, EN, CS, EN, WS, R, R, WS, L, L
+};
+
+static const UBiDiLevel
+testLevels5[]={
+ 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2
+};
+
+static const uint8_t
+testVisualMap5[]={
+ 15, 14, 13, 12, 11, 10, 9, 6, 7, 8, 5, 4, 3, 2, 0, 1
+};
+
+static const uint8_t
+testText6[]={
+ R, EN, NSM, ET
+};
+
+static const UBiDiLevel
+testLevels6[]={
+ 1, 2, 2, 2
+};
+
+static const uint8_t
+testVisualMap6[]={
+ 3, 0, 1, 2
+};
+
+#if 0
+static const uint8_t
+testText7[]={
+ /* empty */
+};
+
+static const UBiDiLevel
+testLevels7[]={
+};
+
+static const uint8_t
+testVisualMap7[]={
+};
+
+#endif
+
+static const uint8_t
+testText8[]={
+ RLE, WS, R, R, R, WS, PDF, WS, B
+};
+
+static const UBiDiLevel
+testLevels8[]={
+ 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static const uint8_t
+testVisualMap8[]={
+ 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static const uint8_t
+testText9[]={
+ LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE,
+ LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE,
+ AN, RLO, NSM, LRE, PDF, RLE, ES, EN, ON
+};
+
+static const UBiDiLevel
+testLevels9[]={
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61
+};
+
+static const uint8_t
+testVisualMap9[]={
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static const uint8_t
+testText10[]={
+ LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE,
+ LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE, LRE,
+ LRE, BN, CS, RLO, S, PDF, EN, LRO, AN, ES
+};
+
+static const UBiDiLevel
+testLevels10[]={
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 62, 62, 62, 62, 60
+};
+
+static const uint8_t
+testVisualMap10[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
+};
+
+static const uint8_t
+testText11[]={
+ S, WS, NSM, RLE, WS, L, L, L, WS, LRO, WS, R, R, R, WS, RLO, WS, L, L,
+ L, WS, LRE, WS, R, R, R, WS, PDF, WS, L, L, L, WS, PDF, WS,
+ AL, AL, AL, WS, PDF, WS, L, L, L, WS, PDF, WS, L, L, L, WS, PDF,
+ ON, PDF, BN, BN, ON, PDF
+};
+
+static const UBiDiLevel
+testLevels11[]={
+ 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const uint8_t
+testVisualMap11[]={
+ 0, 1, 2, 44, 43, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 31, 30, 29, 28, 27, 26, 20, 21, 24, 23, 22, 25, 19, 18, 17, 16, 15, 14, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 3, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
+};
+
+static const uint8_t
+testText12[]={
+ NSM, WS, L, L, L, L, L, L, L, WS, L, L, L, L, WS,
+ R, R, R, R, R, WS, L, L, L, L, L, L, L, WS, WS, AL,
+ AL, AL, AL, WS, EN, EN, ES, EN, EN, CS, S, EN, EN, CS, WS,
+ EN, EN, WS, AL, AL, AL, AL, AL, B, L, L, L, L, L, L,
+ L, L, WS, AN, AN, CS, AN, AN, WS
+};
+
+static const UBiDiLevel
+testLevels12[]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0
+};
+
+static const uint8_t
+testVisualMap12[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
+};
+
+static const UBiDiLevel
+testLevels13[]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0
+};
+
+static const uint8_t
+testVisualMap13[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
+};
+
+static const UBiDiLevel
+testLevels14[]={
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 2, 4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2
+};
+
+static const uint8_t
+testVisualMap14[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
+};
+
+static const UBiDiLevel
+testLevels15[]={
+ 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 6, 6, 5, 5, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 5
+};
+
+static const uint8_t
+testVisualMap15[]={
+ 69, 68, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 55, 54, 53, 52, 51, 50, 49, 42, 43, 44, 45, 46, 47, 48, 41, 40, 39, 38, 37, 36, 35, 33, 34, 32, 30, 31, 29, 28, 26, 27, 25, 24, 22, 23, 21, 20, 19, 18, 17, 16, 15, 7, 8, 9, 10, 11, 12, 13, 14, 6, 1, 2, 3, 4, 5, 0
+};
+
+static const UBiDiLevel
+testLevels16[]={
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0
+};
+
+static const uint8_t
+testVisualMap16[]={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 40, 39, 38, 37, 36, 34, 35, 33, 31, 32, 30, 41, 52, 53, 51, 50, 48, 49, 47, 46, 45, 44, 43, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
+};
+
+static const uint8_t
+testText13[]={
+ ON, L, RLO, CS, R, WS, AN, AN, PDF, LRE, R, L, LRO, WS, BN, ON, S, LRE, LRO, B
+};
+
+static const UBiDiLevel
+testLevels17[]={
+ 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, 4, 4, 4, 4, 0, 0, 0, 0
+};
+
+static const uint8_t
+testVisualMap17[]={
+ 0, 1, 15, 14, 13, 12, 11, 10, 4, 3, 2, 5, 6, 7, 8, 9, 16, 17, 18, 19
+};
+
+static const UBiDiLevel
+testLevels18[]={
+ 0, 0, 1, 1, 1, 0
+};
+
+static const uint8_t
+testVisualMap18[]={
+ 0, 1, 4, 3, 2, 5
+};
+
+static const uint8_t
+testText14[]={
+ RLO, RLO, AL, AL, WS, EN, ES, ON, WS, S, S, PDF, LRO, WS, AL, ET, RLE, ON, EN, B
+};
+
+static const UBiDiLevel
+testLevels19[]={
+ 1
+};
+
+static const uint8_t
+testVisualMap19[]={
+ 0
+};
+
+static const uint8_t
+testText15[]={
+ R, L, CS, L
+};
+
+static const UBiDiLevel
+testLevels20[]={
+ 2
+};
+
+static const uint8_t
+testText16[]={
+ L, L, L, WS, L, L, L, WS, L, L, L
+};
+
+static const UBiDiLevel
+testLevels21[]={
+ 2, 2, 2, 2, 2, 2, 2, 1
+};
+
+static const uint8_t
+testVisualMap20[]={
+ 1, 2, 3, 4, 5, 6, 7, 0
+};
+
+static const uint8_t
+testText17[]={
+ R, R, R, WS, R, R, R, WS, R, R, R
+};
+
+static const UBiDiLevel
+testLevels22[]={
+ 1, 1, 1, 1, 1, 1, 1, 0
+};
+
+static const uint8_t
+testVisualMap21[]={
+ 6, 5, 4, 3, 2, 1, 0, 7
+};
+
+static const uint8_t
+testTextXX[]={
+ L
+};
+
+static const UBiDiLevel
+testLevelsXX[]={
+ 2
+};
+
+static const uint8_t
+testVisualMapXX[]={
+ 0
+};
+
+const BiDiTestData
+tests[]={
+ {testText1, ARRAY_LENGTH(testText1), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_LTR, 0,
+ testLevels1, testVisualMap1},
+ {testText2, ARRAY_LENGTH(testText2), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_RTL, 1,
+ testLevels2, testVisualMap2},
+ {testText3, ARRAY_LENGTH(testText3), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_LTR, 0,
+ testLevels3, testVisualMap3},
+ {testText4, ARRAY_LENGTH(testText4), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels4, testVisualMap4},
+ {testText5, ARRAY_LENGTH(testText5), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 1,
+ testLevels5, testVisualMap5},
+ {testText6, ARRAY_LENGTH(testText6), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 1,
+ testLevels6, testVisualMap6},
+ {NULL, 0, UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_LTR, 0,
+ NULL, NULL},
+ {testText8, ARRAY_LENGTH(testText8), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_RTL, 1,
+ testLevels8, testVisualMap8},
+ {testText9, ARRAY_LENGTH(testText9), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels9, testVisualMap9},
+ {testText10, ARRAY_LENGTH(testText10), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels10, testVisualMap10},
+ {testText11, ARRAY_LENGTH(testText11), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels11, testVisualMap11},
+ {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels12, testVisualMap12},
+ {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_RTL, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels13, testVisualMap13},
+ {testText12, ARRAY_LENGTH(testText12), 2, -1, -1,
+ UBIDI_MIXED, 2,
+ testLevels14, testVisualMap14},
+ {testText12, ARRAY_LENGTH(testText12), 5, -1, -1,
+ UBIDI_MIXED, 5,
+ testLevels15, testVisualMap15},
+ {testText12, ARRAY_LENGTH(testText12), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels16, testVisualMap16},
+ {testText13, ARRAY_LENGTH(testText13), UBIDI_DEFAULT_LTR, -1, -1,
+ UBIDI_MIXED, 0,
+ testLevels17, testVisualMap17},
+ {testText13, ARRAY_LENGTH(testText13), UBIDI_DEFAULT_LTR, 0, 6,
+ UBIDI_MIXED, 0,
+ testLevels18, testVisualMap18},
+ {testText14, ARRAY_LENGTH(testText14), UBIDI_DEFAULT_LTR, 13, 14,
+ UBIDI_RTL, 1,
+ testLevels19, testVisualMap19},
+ {testText15, ARRAY_LENGTH(testText15), UBIDI_DEFAULT_LTR, 2, 3,
+ UBIDI_LTR, 2,
+ testLevels20, testVisualMap19},
+ {testText16, ARRAY_LENGTH(testText16), UBIDI_RTL, 0, 8,
+ UBIDI_MIXED, 1,
+ testLevels21, testVisualMap20},
+ {testText17, ARRAY_LENGTH(testText17), UBIDI_LTR, 0, 8,
+ UBIDI_MIXED, 0,
+ testLevels22, testVisualMap21},
+ {testTextXX, ARRAY_LENGTH(testTextXX), UBIDI_RTL, -1, -1,
+ UBIDI_MIXED, 1, testLevelsXX, testVisualMapXX}
+};
+
+const int
+bidiTestCount=ARRAY_LENGTH(tests);
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c
new file mode 100644
index 00000000000..517d219df33
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.c
@@ -0,0 +1,3860 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/* file name: cbiditst.cpp
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 1999sep27
+* created by: Markus W. Scherer, updated by Matitiahu Allouche
+*/
+
+#include "cintltst.h"
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+#include "unicode/ubidi.h"
+#include "unicode/ushape.h"
+#include "cbiditst.h"
+#include "cstring.h"
+/* the following include is needed for sprintf */
+#include <stdio.h>
+
+#define MAXLEN MAX_STRING_LENGTH
+#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
+
+/* prototypes ---------------------------------------------------------------*/
+
+void addComplexTest(TestNode** root);
+
+static void testCharFromDirProp(void);
+
+static void testBidi(void);
+
+static void doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst);
+
+static void doMisc(void);
+
+static void doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test,
+ int32_t lineStart, UBool countRunsFirst);
+
+static void _testReordering(UBiDi *pBiDi, int testNumber);
+
+static void testInverse(void);
+
+static void _testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction);
+
+static void _testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
+ UBiDiLevel direction, UErrorCode *pErrorCode);
+
+static void _testWriteReverse(void);
+
+static void _testManyAddedPoints(void);
+
+static void _testMisc(void);
+
+static void doArabicShapingTest(void);
+
+static void doLamAlefSpecialVLTRArabicShapingTest(void);
+
+static void doTashkeelSpecialVLTRArabicShapingTest(void);
+
+static void doLOGICALArabicDeShapingTest(void);
+
+static void doArabicShapingTestForBug5421(void);
+
+static void testReorder(void);
+
+static void testFailureRecovery(void);
+
+static void testMultipleParagraphs(void);
+
+/* new BIDI API */
+static void testReorderingMode(void);
+static void testReorderRunsOnly(void);
+static void testStreaming(void);
+static void testClassOverride(void);
+static const char* inverseBasic(UBiDi *pBiDi, const char *src, int32_t srcLen,
+ uint32_t option, UBiDiLevel level, char *result);
+static UBool assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex,
+ const char *srcChars, const char *destChars,
+ const UChar *dest, int32_t destLen, int mode,
+ int option, UBiDiLevel level);
+static UBool checkResultLength(UBiDi *pBiDi, const char *srcChars,
+ const char *destChars,
+ int32_t destLen, const char *mode,
+ const char *option, UBiDiLevel level);
+static UBool checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src,
+ const char *dest, const char *mode, const char* option,
+ UBiDiLevel level, UBool forward);
+
+/* helpers ------------------------------------------------------------------ */
+
+static const char *levelString="...............................................................";
+
+static void initCharFromDirProps(void);
+
+static UChar *
+getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer);
+
+static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels);
+
+/* regression tests ---------------------------------------------------------*/
+
+void
+addComplexTest(TestNode** root) {
+ addTest(root, testCharFromDirProp, "complex/bidi/TestCharFromDirProp");
+ addTest(root, testBidi, "complex/bidi/TestBidi");
+ addTest(root, testInverse, "complex/bidi/TestInverse");
+ addTest(root, testReorder,"complex/bidi/TestReorder");
+ addTest(root, testFailureRecovery,"complex/bidi/TestFailureRecovery");
+ addTest(root, testMultipleParagraphs,"complex/bidi/TestMultipleParagraphs");
+ addTest(root, testReorderingMode, "complex/bidi/TestReorderingMode");
+ addTest(root, testReorderRunsOnly, "complex/bidi/TestReorderRunsOnly");
+ addTest(root, testStreaming, "complex/bidi/TestStreaming");
+ addTest(root, testClassOverride, "complex/bidi/TestClassOverride");
+
+ addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest");
+ addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef");
+ addTest(root, doTashkeelSpecialVLTRArabicShapingTest, "complex/arabic-shaping/tashkeel");
+ addTest(root, doLOGICALArabicDeShapingTest, "complex/arabic-shaping/unshaping");
+ addTest(root, doArabicShapingTestForBug5421, "complex/arabic-shaping/bug-5421");
+}
+
+static void
+testCharFromDirProp(void) {
+ /* verify that the exemplar characters have the expected bidi classes */
+ int32_t i;
+
+ log_verbose("\nEntering TestCharFromDirProp\n\n");
+ initCharFromDirProps();
+
+ for(i=0; i<U_CHAR_DIRECTION_COUNT; ++i) {
+ if(u_charDirection(charFromDirProp[i])!=(UCharDirection)i) {
+ log_err("\nu_charDirection(charFromDirProp[%d]=U+%04x)==%d!=%d\n",
+ i, charFromDirProp[i], u_charDirection(charFromDirProp[i]), i);
+ }
+ }
+ log_verbose("\nExiting TestCharFromDirProp\n\n");
+}
+
+static void
+testBidi(void) {
+ UBiDi *pBiDi, *pLine=NULL;
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ log_verbose("\nEntering TestBidi\n\n");
+
+ pBiDi=ubidi_openSized(MAXLEN, 0, &errorCode);
+ if(pBiDi!=NULL) {
+ pLine=ubidi_open();
+ if(pLine!=NULL) {
+ doTests(pBiDi, pLine, FALSE);
+ doTests(pBiDi, pLine, TRUE);
+ } else {
+ log_err("ubidi_open() returned NULL, out of memory\n");
+ }
+ } else {
+ log_err("ubidi_openSized() returned NULL, errorCode %s\n", myErrorName(errorCode));
+ }
+ doMisc();
+
+ if(pLine!=NULL) {
+ ubidi_close(pLine);
+ }
+ if(pBiDi!=NULL) {
+ ubidi_close(pBiDi);
+ }
+
+ log_verbose("\nExiting TestBidi\n\n");
+}
+
+static void
+doTests(UBiDi *pBiDi, UBiDi *pLine, UBool countRunsFirst) {
+ int testNumber;
+ UChar string[MAXLEN];
+ UErrorCode errorCode;
+ int32_t lineStart;
+ UBiDiLevel paraLevel;
+
+ for(testNumber=0; testNumber<bidiTestCount; ++testNumber) {
+ errorCode=U_ZERO_ERROR;
+ getStringFromDirProps(tests[testNumber].text, tests[testNumber].length, string);
+ paraLevel=tests[testNumber].paraLevel;
+ ubidi_setPara(pBiDi, string, -1, paraLevel, NULL, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ log_verbose("ubidi_setPara(tests[%d], paraLevel %d) ok, direction %d paraLevel=%d\n",
+ testNumber, paraLevel, ubidi_getDirection(pBiDi), paraLevel);
+ lineStart=tests[testNumber].lineStart;
+ if(lineStart==-1) {
+ doTest(pBiDi, testNumber, tests+testNumber, 0, countRunsFirst);
+ } else {
+ ubidi_setLine(pBiDi, lineStart, tests[testNumber].lineLimit, pLine, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ log_verbose("ubidi_setLine(%d, %d) ok, direction %d paraLevel=%d\n",
+ lineStart, tests[testNumber].lineLimit, ubidi_getDirection(pLine), ubidi_getParaLevel(pLine));
+ doTest(pLine, testNumber, tests+testNumber, lineStart, countRunsFirst);
+ } else {
+ log_err("ubidi_setLine(tests[%d], %d, %d) failed with errorCode %s\n",
+ testNumber, lineStart, tests[testNumber].lineLimit, myErrorName(errorCode));
+ }
+ }
+ } else {
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ testNumber, paraLevel, myErrorName(errorCode));
+ }
+ }
+}
+
+static const char columns[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+#define TABLE_SIZE 256
+static UBool tablesInitialized = FALSE;
+static UChar pseudoToUChar[TABLE_SIZE];
+static uint8_t UCharToPseudo[TABLE_SIZE]; /* used for Unicode chars < 0x0100 */
+static uint8_t UCharToPseud2[TABLE_SIZE]; /* used for Unicode chars >=0x0100 */
+
+static void buildPseudoTables(void)
+/*
+ The rules for pseudo-Bidi are as follows:
+ - [ == LRE
+ - ] == RLE
+ - { == LRO
+ - } == RLO
+ - ^ == PDF
+ - @ == LRM
+ - & == RLM
+ - A-F == Arabic Letters 0631-0636
+ - G-V == Hebrew letters 05d7-05e6
+ - W-Z == Unassigned RTL 08d0-08d3
+ - 0-5 == western digits 0030-0035
+ - 6-9 == Arabic-Indic digits 0666-0669
+ - ` == Combining Grave Accent 0300 (NSM)
+ - ~ == Delete 007f (BN)
+ - | == Paragraph Separator 2029 (B)
+ - _ == Info Separator 1 001f (S)
+ All other characters represent themselves as Latin-1, with the corresponding
+ Bidi properties.
+*/
+{
+ int i;
+ UChar uchar;
+ uint8_t c;
+ /* initialize all tables to unknown */
+ for (i=0; i < TABLE_SIZE; i++) {
+ pseudoToUChar[i] = 0xFFFD;
+ UCharToPseudo[i] = '?';
+ UCharToPseud2[i] = '?';
+ }
+ /* initialize non letters or digits */
+ pseudoToUChar[(uint8_t) 0 ] = 0x0000; UCharToPseudo[0x00] = (uint8_t) 0 ;
+ pseudoToUChar[(uint8_t)' '] = 0x0020; UCharToPseudo[0x20] = (uint8_t)' ';
+ pseudoToUChar[(uint8_t)'!'] = 0x0021; UCharToPseudo[0x21] = (uint8_t)'!';
+ pseudoToUChar[(uint8_t)'"'] = 0x0022; UCharToPseudo[0x22] = (uint8_t)'"';
+ pseudoToUChar[(uint8_t)'#'] = 0x0023; UCharToPseudo[0x23] = (uint8_t)'#';
+ pseudoToUChar[(uint8_t)'$'] = 0x0024; UCharToPseudo[0x24] = (uint8_t)'$';
+ pseudoToUChar[(uint8_t)'%'] = 0x0025; UCharToPseudo[0x25] = (uint8_t)'%';
+ pseudoToUChar[(uint8_t)'\'']= 0x0027; UCharToPseudo[0x27] = (uint8_t)'\'';
+ pseudoToUChar[(uint8_t)'('] = 0x0028; UCharToPseudo[0x28] = (uint8_t)'(';
+ pseudoToUChar[(uint8_t)')'] = 0x0029; UCharToPseudo[0x29] = (uint8_t)')';
+ pseudoToUChar[(uint8_t)'*'] = 0x002A; UCharToPseudo[0x2A] = (uint8_t)'*';
+ pseudoToUChar[(uint8_t)'+'] = 0x002B; UCharToPseudo[0x2B] = (uint8_t)'+';
+ pseudoToUChar[(uint8_t)','] = 0x002C; UCharToPseudo[0x2C] = (uint8_t)',';
+ pseudoToUChar[(uint8_t)'-'] = 0x002D; UCharToPseudo[0x2D] = (uint8_t)'-';
+ pseudoToUChar[(uint8_t)'.'] = 0x002E; UCharToPseudo[0x2E] = (uint8_t)'.';
+ pseudoToUChar[(uint8_t)'/'] = 0x002F; UCharToPseudo[0x2F] = (uint8_t)'/';
+ pseudoToUChar[(uint8_t)':'] = 0x003A; UCharToPseudo[0x3A] = (uint8_t)':';
+ pseudoToUChar[(uint8_t)';'] = 0x003B; UCharToPseudo[0x3B] = (uint8_t)';';
+ pseudoToUChar[(uint8_t)'<'] = 0x003C; UCharToPseudo[0x3C] = (uint8_t)'<';
+ pseudoToUChar[(uint8_t)'='] = 0x003D; UCharToPseudo[0x3D] = (uint8_t)'=';
+ pseudoToUChar[(uint8_t)'>'] = 0x003E; UCharToPseudo[0x3E] = (uint8_t)'>';
+ pseudoToUChar[(uint8_t)'?'] = 0x003F; UCharToPseudo[0x3F] = (uint8_t)'?';
+ pseudoToUChar[(uint8_t)'\\']= 0x005C; UCharToPseudo[0x5C] = (uint8_t)'\\';
+ /* initialize specially used characters */
+ pseudoToUChar[(uint8_t)'`'] = 0x0300; UCharToPseud2[0x00] = (uint8_t)'`'; /* NSM */
+ pseudoToUChar[(uint8_t)'@'] = 0x200E; UCharToPseud2[0x0E] = (uint8_t)'@'; /* LRM */
+ pseudoToUChar[(uint8_t)'&'] = 0x200F; UCharToPseud2[0x0F] = (uint8_t)'&'; /* RLM */
+ pseudoToUChar[(uint8_t)'_'] = 0x001F; UCharToPseudo[0x1F] = (uint8_t)'_'; /* S */
+ pseudoToUChar[(uint8_t)'|'] = 0x2029; UCharToPseud2[0x29] = (uint8_t)'|'; /* B */
+ pseudoToUChar[(uint8_t)'['] = 0x202A; UCharToPseud2[0x2A] = (uint8_t)'['; /* LRE */
+ pseudoToUChar[(uint8_t)']'] = 0x202B; UCharToPseud2[0x2B] = (uint8_t)']'; /* RLE */
+ pseudoToUChar[(uint8_t)'^'] = 0x202C; UCharToPseud2[0x2C] = (uint8_t)'^'; /* PDF */
+ pseudoToUChar[(uint8_t)'{'] = 0x202D; UCharToPseud2[0x2D] = (uint8_t)'{'; /* LRO */
+ pseudoToUChar[(uint8_t)'}'] = 0x202E; UCharToPseud2[0x2E] = (uint8_t)'}'; /* RLO */
+ pseudoToUChar[(uint8_t)'~'] = 0x007F; UCharToPseudo[0x7F] = (uint8_t)'~'; /* BN */
+ /* initialize western digits */
+ for (i = 0, uchar = 0x0030; i < 6; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseudo[uchar & 0x00ff] = c;
+ }
+ /* initialize Hindi digits */
+ for (i = 6, uchar = 0x0666; i < 10; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseud2[uchar & 0x00ff] = c;
+ }
+ /* initialize Arabic letters */
+ for (i = 10, uchar = 0x0631; i < 16; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseud2[uchar & 0x00ff] = c;
+ }
+ /* initialize Hebrew letters */
+ for (i = 16, uchar = 0x05D7; i < 32; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseud2[uchar & 0x00ff] = c;
+ }
+ /* initialize Unassigned code points */
+ for (i = 32, uchar=0x08D0; i < 36; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseud2[uchar & 0x00ff] = c;
+ }
+ /* initialize Latin lower case letters */
+ for (i = 36, uchar = 0x0061; i < 62; i++, uchar++) {
+ c = (uint8_t)columns[i];
+ pseudoToUChar[c] = uchar;
+ UCharToPseudo[uchar & 0x00ff] = c;
+ }
+ tablesInitialized = TRUE;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int pseudoToU16(const int length, const char * input, UChar * output)
+/* This function converts a pseudo-Bidi string into a UChar string.
+ It returns the length of the UChar string.
+*/
+{
+ int i;
+ if (!tablesInitialized) {
+ buildPseudoTables();
+ }
+ for (i = 0; i < length; i++)
+ output[i] = pseudoToUChar[(uint8_t)input[i]];
+ return length;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int u16ToPseudo(const int length, const UChar * input, char * output)
+/* This function converts a UChar string into a pseudo-Bidi string.
+ It returns the length of the pseudo-Bidi string.
+*/
+{
+ int i;
+ UChar uchar;
+ if (!tablesInitialized) {
+ buildPseudoTables();
+ }
+ for (i = 0; i < length; i++)
+ {
+ uchar = input[i];
+ output[i] = uchar < 0x0100 ? UCharToPseudo[uchar] :
+ UCharToPseud2[uchar & 0x00ff];
+ }
+ output[length] = '\0';
+ return length;
+}
+
+static char * formatLevels(UBiDi *bidi, char *buffer) {
+ UErrorCode ec = U_ZERO_ERROR;
+ const UBiDiLevel* gotLevels = ubidi_getLevels(bidi, &ec);
+ int len = ubidi_getLength(bidi);
+ char c;
+ int i, k;
+
+ if(U_FAILURE(ec)) {
+ strcpy(buffer, "BAD LEVELS");
+ return buffer;
+ }
+ for (i=0; i<len; i++) {
+ k = gotLevels[i];
+ if (k >= sizeof(columns))
+ c = '+';
+ else
+ c = columns[k];
+ buffer[i] = c;
+ }
+ buffer[len] = '\0';
+ return buffer;
+}
+static const char *reorderingModeNames[] = {
+ "UBIDI_REORDER_DEFAULT",
+ "UBIDI_REORDER_NUMBERS_SPECIAL",
+ "UBIDI_REORDER_GROUP_NUMBERS_WITH_R",
+ "UBIDI_REORDER_RUNS_ONLY",
+ "UBIDI_REORDER_INVERSE_NUMBERS_AS_L",
+ "UBIDI_REORDER_INVERSE_LIKE_DIRECT",
+ "UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL"};
+
+static char *reorderingOptionNames(char *buffer, int options) {
+ buffer[0] = 0;
+ if (options & UBIDI_OPTION_INSERT_MARKS) {
+ strcat(buffer, " UBIDI_OPTION_INSERT_MARKS");
+ }
+ if (options & UBIDI_OPTION_REMOVE_CONTROLS) {
+ strcat(buffer, " UBIDI_OPTION_REMOVE_CONTROLS");
+ }
+ if (options & UBIDI_OPTION_STREAMING) {
+ strcat(buffer, " UBIDI_OPTION_STREAMING");
+ }
+ return buffer;
+}
+
+static void printCaseInfo(UBiDi *bidi, const char *src, const char *dst)
+/* src and dst are char arrays encoded as pseudo Bidi */
+{
+ /* Since calls to log_err with a \n within the pattern increment the
+ * error count, new lines are issued via fputs, except when we want the
+ * increment to happen.
+ */
+ UErrorCode errorCode=U_ZERO_ERROR;
+ int32_t i, length = ubidi_getProcessedLength(bidi);
+ const UBiDiLevel *levels;
+ char levelChars[MAXLEN];
+ UBiDiLevel lev;
+ int32_t runCount;
+ char buffer[100];
+ log_err("========================================"); fputs("\n", stderr);
+ levels = ubidi_getLevels(bidi, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ strcpy(levelChars, "BAD LEVELS");
+ } else {
+ log_err("Processed length: %d", length); fputs("\n", stderr);
+ for (i = 0; i < length; i++) {
+ lev = levels[i];
+ if (lev < sizeof(columns)) {
+ levelChars[i] = columns[lev];
+ } else {
+ levelChars[i] = '+';
+ }
+ }
+ levelChars[length] = 0;
+ }
+ log_err("Levels: %s", levelChars); fputs("\n", stderr);
+ log_err("Source: %s", src); fputs("\n", stderr);
+ log_err("Result: %s", dst); fputs("\n", stderr);
+ log_err("Direction: %d", ubidi_getDirection(bidi)); fputs("\n", stderr);
+ log_err("paraLevel: %d", ubidi_getParaLevel(bidi)); fputs("\n", stderr);
+ i = ubidi_getReorderingMode(bidi);
+ log_err("reorderingMode: %d = %s", i, reorderingModeNames[i]);
+ fputs("\n", stderr);
+ i = ubidi_getReorderingOptions(bidi);
+ log_err("reorderingOptions: %d = %s", i, reorderingOptionNames(buffer, i));
+ fputs("\n", stderr);
+ runCount = ubidi_countRuns(bidi, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err( "BAD RUNS");
+ } else {
+ log_err("Runs: %d => logicalStart.length/level: ", runCount);
+ for (i = 0; i < runCount; i++) {
+ UBiDiDirection dir;
+ int32_t start, len;
+ dir = ubidi_getVisualRun(bidi, i, &start, &len);
+ log_err(" %d.%d/%d", start, len, dir);
+ }
+ }
+ fputs("\n", stderr);
+}
+
+static UBool matchingPair(UBiDi *bidi, int32_t i, char c1, char c2)
+{
+ /* No test for []{} since they have special meaning for pseudo Bidi */
+ static char mates1Chars[] = "<>()";
+ static char mates2Chars[] = "><)(";
+ UBiDiLevel level;
+ int k, len;
+
+ if (c1 == c2) {
+ return TRUE;
+ }
+ /* For UBIDI_REORDER_RUNS_ONLY, it would not be correct to check levels[i],
+ so we use the appropriate run's level, which is good for all cases.
+ */
+ ubidi_getLogicalRun(bidi, i, NULL, &level);
+ if ((level & 1) == 0) {
+ return FALSE;
+ }
+ len = strlen(mates1Chars);
+ for (k = 0; k < len; k++) {
+ if ((c1 == mates1Chars[k]) && (c2 == mates2Chars[k])) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static UBool checkWhatYouCan(UBiDi *bidi, const char *srcChars, const char *dstChars)
+/* srcChars and dstChars are char arrays encoded as pseudo Bidi */
+{
+ int32_t i, idx, logLimit, visLimit;
+ UBool testOK, errMap, errDst;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ int32_t visMap[MAXLEN];
+ int32_t logMap[MAXLEN];
+ char accumSrc[MAXLEN];
+ char accumDst[MAXLEN];
+ ubidi_getVisualMap(bidi, visMap, &errorCode);
+ ubidi_getLogicalMap(bidi, logMap, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("Error #1 invoking ICU within checkWhatYouCan\n");
+ return FALSE;
+ }
+
+ testOK = TRUE;
+ errMap = errDst = FALSE;
+ logLimit = ubidi_getProcessedLength(bidi);
+ visLimit = ubidi_getResultLength(bidi);
+ memset(accumSrc, '?', logLimit);
+ memset(accumDst, '?', visLimit);
+
+ for (i = 0; i < logLimit; i++) {
+ idx = ubidi_getVisualIndex(bidi, i, &errorCode);
+ if (idx != logMap[i]) {
+ errMap = TRUE;
+ }
+ if (idx == UBIDI_MAP_NOWHERE) {
+ continue;
+ }
+ if (idx >= visLimit) {
+ continue;
+ }
+ accumDst[idx] = srcChars[i];
+ if (!matchingPair(bidi, i, srcChars[i], dstChars[idx])) {
+ errDst = TRUE;
+ }
+ }
+ accumDst[visLimit] = 0;
+ if (U_FAILURE(errorCode)) {
+ log_err("Error #2 invoking ICU within checkWhatYouCan\n");
+ return FALSE;
+ }
+ if (errMap) {
+ if (testOK) {
+ printCaseInfo(bidi, srcChars, dstChars);
+ testOK = FALSE;
+ }
+ log_err("Mismatch between getLogicalMap() and getVisualIndex()\n");
+ log_err("Map :");
+ for (i = 0; i < logLimit; i++) {
+ log_err(" %d", logMap[i]);
+ }
+ fputs("\n", stderr);
+ log_err("Indexes:");
+ for (i = 0; i < logLimit; i++) {
+ log_err(" %d", ubidi_getVisualIndex(bidi, i, &errorCode));
+ }
+ fputs("\n", stderr);
+ }
+ if (errDst) {
+ if (testOK) {
+ printCaseInfo(bidi, srcChars, dstChars);
+ testOK = FALSE;
+ }
+ log_err("Source does not map to Result\n");
+ log_err("We got: %s", accumDst); fputs("\n", stderr);
+ }
+
+ errMap = errDst = FALSE;
+ for (i = 0; i < visLimit; i++) {
+ idx = ubidi_getLogicalIndex(bidi, i, &errorCode);
+ if (idx != visMap[i]) {
+ errMap = TRUE;
+ }
+ if (idx == UBIDI_MAP_NOWHERE) {
+ continue;
+ }
+ if (idx >= logLimit) {
+ continue;
+ }
+ accumSrc[idx] = dstChars[i];
+ if (!matchingPair(bidi, idx, srcChars[idx], dstChars[i])) {
+ errDst = TRUE;
+ }
+ }
+ accumSrc[logLimit] = 0;
+ if (U_FAILURE(errorCode)) {
+ log_err("Error #3 invoking ICU within checkWhatYouCan\n");
+ return FALSE;
+ }
+ if (errMap) {
+ if (testOK) {
+ printCaseInfo(bidi, srcChars, dstChars);
+ testOK = FALSE;
+ }
+ log_err("Mismatch between getVisualMap() and getLogicalIndex()\n");
+ log_err("Map :");
+ for (i = 0; i < visLimit; i++) {
+ log_err(" %d", visMap[i]);
+ }
+ fputs("\n", stderr);
+ log_err("Indexes:");
+ for (i = 0; i < visLimit; i++) {
+ log_err(" %d", ubidi_getLogicalIndex(bidi, i, &errorCode));
+ }
+ fputs("\n", stderr);
+ }
+ if (errDst) {
+ if (testOK) {
+ printCaseInfo(bidi, srcChars, dstChars);
+ testOK = FALSE;
+ }
+ log_err("Result does not map to Source\n");
+ log_err("We got: %s", accumSrc);
+ fputs("\n", stderr);
+ }
+ return testOK;
+}
+
+static void
+testReorder(void) {
+ static const char* const logicalOrder[] ={
+ "del(KC)add(K.C.&)",
+ "del(QDVT) add(BVDL)",
+ "del(PQ)add(R.S.)T)U.&",
+ "del(LV)add(L.V.) L.V.&",
+ "day 0 R DPDHRVR dayabbr",
+ "day 1 H DPHPDHDA dayabbr",
+ "day 2 L DPBLENDA dayabbr",
+ "day 3 J DPJQVM dayabbr",
+ "day 4 I DPIQNF dayabbr",
+ "day 5 M DPMEG dayabbr",
+ "helloDPMEG",
+ "hello WXYZ"
+ };
+ static const char* const visualOrder[]={
+ "del(CK)add(&.C.K)",
+ "del(TVDQ) add(LDVB)",
+ "del(QP)add(&.U(T(.S.R",
+ "del(VL)add(&.V.L (.V.L",
+ "day 0 RVRHDPD R dayabbr",
+ "day 1 ADHDPHPD H dayabbr",
+ "day 2 ADNELBPD L dayabbr",
+ "day 3 MVQJPD J dayabbr",
+ "day 4 FNQIPD I dayabbr",
+ "day 5 GEMPD M dayabbr",
+ "helloGEMPD",
+ "hello ZYXW"
+ };
+ static const char* const visualOrder1[]={
+ ")K.C.&(dda)KC(led",
+ ")BVDL(dda )QDVT(led",
+ "R.S.(T(U.&(dda)PQ(led",
+ "L.V.( L.V.&(dda)LV(led",
+ "rbbayad R DPDHRVR 0 yad",
+ "rbbayad H DPHPDHDA 1 yad",
+ "rbbayad L DPBLENDA 2 yad",
+ "rbbayad J DPJQVM 3 yad",
+ "rbbayad I DPIQNF 4 yad",
+ "rbbayad M DPMEG 5 yad",
+ "DPMEGolleh",
+ "WXYZ olleh"
+ };
+
+ static const char* const visualOrder2[]={
+ "@)@K.C.&@(dda)@KC@(led",
+ "@)@BVDL@(dda )@QDVT@(led",
+ "R.S.)T)U.&@(dda)@PQ@(led",
+ "L.V.) L.V.&@(dda)@LV@(led",
+ "rbbayad @R DPDHRVR@ 0 yad",
+ "rbbayad @H DPHPDHDA@ 1 yad",
+ "rbbayad @L DPBLENDA@ 2 yad",
+ "rbbayad @J DPJQVM@ 3 yad",
+ "rbbayad @I DPIQNF@ 4 yad",
+ "rbbayad @M DPMEG@ 5 yad",
+ "DPMEGolleh",
+ "WXYZ@ olleh"
+ };
+ static const char* const visualOrder3[]={
+ ")K.C.&(KC)dda(led",
+ ")BVDL(ddaQDVT) (led",
+ "R.S.)T)U.&(PQ)dda(led",
+ "L.V.) L.V.&(LV)dda(led",
+ "rbbayad DPDHRVR R 0 yad",
+ "rbbayad DPHPDHDA H 1 yad",
+ "rbbayad DPBLENDA L 2 yad",
+ "rbbayad DPJQVM J 3 yad",
+ "rbbayad DPIQNF I 4 yad",
+ "rbbayad DPMEG M 5 yad",
+ "DPMEGolleh",
+ "WXYZ olleh"
+ };
+ static const char* const visualOrder4[]={
+ "del(add(CK(.C.K)",
+ "del( (TVDQadd(LDVB)",
+ "del(add(QP(.U(T(.S.R",
+ "del(add(VL(.V.L (.V.L",
+ "day 0 R RVRHDPD dayabbr",
+ "day 1 H ADHDPHPD dayabbr",
+ "day 2 L ADNELBPD dayabbr",
+ "day 3 J MVQJPD dayabbr",
+ "day 4 I FNQIPD dayabbr",
+ "day 5 M GEMPD dayabbr",
+ "helloGEMPD",
+ "hello ZYXW"
+ };
+ char formatChars[MAXLEN];
+ UErrorCode ec = U_ZERO_ERROR;
+ UBiDi* bidi = ubidi_open();
+ int i;
+
+ log_verbose("\nEntering TestReorder\n\n");
+
+ for(i=0;i<LENGTHOF(logicalOrder);i++){
+ int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
+ int32_t destSize = srcSize*2;
+ UChar src[MAXLEN];
+ UChar dest[MAXLEN];
+ char chars[MAXLEN];
+ log_verbose("Testing L2V #1 for case %d\n", i);
+ pseudoToU16(srcSize,logicalOrder[i],src);
+ ec = U_ZERO_ERROR;
+ ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
+ if(U_FAILURE(ec)){
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ i, UBIDI_DEFAULT_LTR, u_errorName(ec));
+ }
+ /* try pre-flighting */
+ destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING,&ec);
+ if(ec!=U_BUFFER_OVERFLOW_ERROR){
+ log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
+ }else if(destSize!=srcSize){
+ log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
+ }else{
+ ec= U_ZERO_ERROR;
+ }
+ destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING,&ec);
+ u16ToPseudo(destSize,dest,chars);
+ if(destSize!=srcSize){
+ log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
+ }else if(strcmp(visualOrder[i],chars)!=0){
+ log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING.\n"
+ "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
+ logicalOrder[i],visualOrder[i],chars,formatLevels(bidi, formatChars),i);
+ }
+ checkWhatYouCan(bidi, logicalOrder[i], chars);
+ }
+
+ for(i=0;i<LENGTHOF(logicalOrder);i++){
+ int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
+ int32_t destSize = srcSize*2;
+ UChar src[MAXLEN];
+ UChar dest[MAXLEN];
+ char chars[MAXLEN];
+ log_verbose("Testing L2V #2 for case %d\n", i);
+ pseudoToU16(srcSize,logicalOrder[i],src);
+ ec = U_ZERO_ERROR;
+ ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
+ if(U_FAILURE(ec)){
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ i, UBIDI_DEFAULT_LTR, u_errorName(ec));
+ }
+ /* try pre-flighting */
+ destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
+ if(ec!=U_BUFFER_OVERFLOW_ERROR){
+ log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
+ }else if(destSize!=srcSize){
+ log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
+ }else{
+ ec= U_ZERO_ERROR;
+ }
+ destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE,&ec);
+ u16ToPseudo(destSize,dest,chars);
+ if(destSize!=srcSize){
+ log_err("ubidi_writeReordered() destSize and srcSize do not match\n");
+ }else if(strcmp(visualOrder1[i],chars)!=0){
+ log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_OUTPUT_REVERSE.\n"
+ "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
+ logicalOrder[i],visualOrder1[i],chars,formatLevels(bidi, formatChars),i);
+ }
+ }
+
+ for(i=0;i<LENGTHOF(logicalOrder);i++){
+ int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
+ int32_t destSize = srcSize*2;
+ UChar src[MAXLEN];
+ UChar dest[MAXLEN];
+ char chars[MAXLEN];
+ log_verbose("Testing V2L #3 for case %d\n", i);
+ pseudoToU16(srcSize,logicalOrder[i],src);
+ ec = U_ZERO_ERROR;
+ ubidi_setInverse(bidi,TRUE);
+ ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR ,NULL,&ec);
+ if(U_FAILURE(ec)){
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ i, UBIDI_DEFAULT_LTR, u_errorName(ec));
+ }
+ /* try pre-flighting */
+ destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
+ if(ec!=U_BUFFER_OVERFLOW_ERROR){
+ log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
+ }else{
+ ec= U_ZERO_ERROR;
+ }
+ destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE,&ec);
+ u16ToPseudo(destSize,dest,chars);
+ if(strcmp(visualOrder2[i],chars)!=0){
+ log_err("ubidi_writeReordered() did not give expected results for UBIDI_INSERT_LRM_FOR_NUMERIC+UBIDI_OUTPUT_REVERSE.\n"
+ "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
+ logicalOrder[i],visualOrder2[i],chars,formatLevels(bidi, formatChars),i);
+ }
+ }
+ /* Max Explicit level */
+ for(i=0;i<LENGTHOF(logicalOrder);i++){
+ int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
+ int32_t destSize = srcSize*2;
+ UChar src[MAXLEN];
+ UChar dest[MAXLEN];
+ char chars[MAXLEN];
+ UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
+ log_verbose("Testing V2L #4 for case %d\n", i);
+ pseudoToU16(srcSize,logicalOrder[i],src);
+ ec = U_ZERO_ERROR;
+ ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
+ if(U_FAILURE(ec)){
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
+ }
+ /* try pre-flighting */
+ destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_OUTPUT_REVERSE,&ec);
+ if(ec!=U_BUFFER_OVERFLOW_ERROR){
+ log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
+ }else if(destSize!=srcSize){
+ log_err("Pre-flighting did not give expected size: Expected: %d. Got: %d \n",srcSize,destSize);
+ }else{
+ ec = U_ZERO_ERROR;
+ }
+ destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_OUTPUT_REVERSE,&ec);
+ u16ToPseudo(destSize,dest,chars);
+ if(destSize!=srcSize){
+ log_err("ubidi_writeReordered() destSize and srcSize do not match. Dest Size = %d Source Size = %d\n",destSize,srcSize );
+ }else if(strcmp(visualOrder3[i],chars)!=0){
+ log_err("ubidi_writeReordered() did not give expected results for UBIDI_OUTPUT_REVERSE.\n"
+ "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
+ logicalOrder[i],visualOrder3[i],chars,formatLevels(bidi, formatChars),i);
+ }
+ }
+ for(i=0;i<LENGTHOF(logicalOrder);i++){
+ int32_t srcSize = (int32_t)strlen(logicalOrder[i]);
+ int32_t destSize = srcSize*2;
+ UChar src[MAXLEN];
+ UChar dest[MAXLEN];
+ char chars[MAXLEN];
+ UBiDiLevel levels[UBIDI_MAX_EXPLICIT_LEVEL]={1,2,3,4,5,6,7,8,9,10};
+ log_verbose("Testing V2L #5 for case %d\n", i);
+ pseudoToU16(srcSize,logicalOrder[i],src);
+ ec = U_ZERO_ERROR;
+ ubidi_setPara(bidi,src,srcSize,UBIDI_DEFAULT_LTR,levels,&ec);
+ if(U_FAILURE(ec)){
+ log_err("ubidi_setPara(tests[%d], paraLevel %d) failed with errorCode %s\n",
+ i, UBIDI_MAX_EXPLICIT_LEVEL, u_errorName(ec));
+ }
+ /* try pre-flighting */
+ destSize = ubidi_writeReordered(bidi,dest,0,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
+ if(ec!=U_BUFFER_OVERFLOW_ERROR){
+ log_err("Pre-flighting did not give expected error: Expected: U_BUFFER_OVERFLOW_ERROR. Got: %s \n",u_errorName(ec));
+ }else{
+ ec= U_ZERO_ERROR;
+ }
+ destSize=ubidi_writeReordered(bidi,dest,destSize+1,UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS,&ec);
+ u16ToPseudo(destSize,dest,chars);
+ if(strcmp(visualOrder4[i],chars)!=0){
+ log_err("ubidi_writeReordered() did not give expected results for UBIDI_DO_MIRRORING+UBIDI_REMOVE_BIDI_CONTROLS.\n"
+ "Input : %s\nExpected: %s\nGot : %s\nLevels : %s\nAt Index: %d\n",
+ logicalOrder[i],visualOrder4[i],chars,formatLevels(bidi, formatChars),i);
+ }
+ }
+ ubidi_close(bidi);
+
+ log_verbose("\nExiting TestReorder\n\n");
+}
+
+static void
+doTest(UBiDi *pBiDi, int testNumber, const BiDiTestData *test, int32_t lineStart, UBool countRunsFirst) {
+ const uint8_t *dirProps=test->text+lineStart;
+ const UBiDiLevel *levels=test->levels;
+ const uint8_t *visualMap=test->visualMap;
+ int32_t i, len=ubidi_getLength(pBiDi), logicalIndex, runCount = 0;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UBiDiLevel level, level2;
+
+ if (countRunsFirst) {
+ log_verbose("Calling ubidi_countRuns() first.\n");
+
+ runCount = ubidi_countRuns(pBiDi, &errorCode);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+ } else {
+ log_verbose("Calling ubidi_getLogicalMap() first.\n");
+ }
+
+ _testReordering(pBiDi, testNumber);
+
+ for(i=0; i<len; ++i) {
+ log_verbose("%3d %3d %.*s%-3s @%d\n",
+ i, ubidi_getLevelAt(pBiDi, i), ubidi_getLevelAt(pBiDi, i), levelString,
+ dirPropNames[dirProps[i]],
+ ubidi_getVisualIndex(pBiDi, i, &errorCode));
+ }
+
+ log_verbose("\n-----levels:");
+ for(i=0; i<len; ++i) {
+ if(i>0) {
+ log_verbose(",");
+ }
+ log_verbose(" %d", ubidi_getLevelAt(pBiDi, i));
+ }
+
+ log_verbose("\n--reordered:");
+ for(i=0; i<len; ++i) {
+ if(i>0) {
+ log_verbose(",");
+ }
+ log_verbose(" %d", ubidi_getVisualIndex(pBiDi, i, &errorCode));
+ }
+ log_verbose("\n");
+
+ if(test->direction!=ubidi_getDirection(pBiDi)) {
+ log_err("ubidi_getDirection(tests[%d]): wrong direction %d\n", testNumber, ubidi_getDirection(pBiDi));
+ }
+
+ if(test->resultLevel!=ubidi_getParaLevel(pBiDi)) {
+ log_err("ubidi_getParaLevel(tests[%d]): wrong paragraph level %d\n", testNumber, ubidi_getParaLevel(pBiDi));
+ }
+
+ for(i=0; i<len; ++i) {
+ if(levels[i]!=ubidi_getLevelAt(pBiDi, i)) {
+ log_err("ubidi_getLevelAt(tests[%d], %d): wrong level %d, expected %d\n", testNumber, i, ubidi_getLevelAt(pBiDi, i), levels[i]);
+ return;
+ }
+ }
+
+ for(i=0; i<len; ++i) {
+ logicalIndex=ubidi_getVisualIndex(pBiDi, i, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
+ return;
+ }
+ if(visualMap[i]!=logicalIndex) {
+ log_err("ubidi_getVisualIndex(tests[%d], %d): wrong index %d\n", testNumber, i, logicalIndex);
+ return;
+ }
+ }
+
+ if (! countRunsFirst) {
+ runCount=ubidi_countRuns(pBiDi, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+ }
+
+ for(logicalIndex=0; logicalIndex<len;) {
+ level=ubidi_getLevelAt(pBiDi, logicalIndex);
+ ubidi_getLogicalRun(pBiDi, logicalIndex, &logicalIndex, &level2);
+ if(level!=level2) {
+ log_err("ubidi_getLogicalRun(tests[%d], run ending at index %d): "
+ "wrong level %d instead of %d\n",
+ testNumber, logicalIndex, level, level2);
+ }
+ if(--runCount<0) {
+ log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
+ "compared to %d=ubidi_countRuns()\n",
+ testNumber, ubidi_countRuns(pBiDi, &errorCode));
+ return;
+ }
+ }
+ if(runCount!=0) {
+ log_err("\nubidi_getLogicalRun(tests[%d]): wrong number of runs "
+ "compared to %d=ubidi_getRunCount()\n",
+ testNumber, ubidi_countRuns(pBiDi, &errorCode));
+ return;
+ }
+
+ log_verbose("\n\n");
+}
+
+static void
+_testReordering(UBiDi *pBiDi, int testNumber) {
+ int32_t
+ logicalMap1[MAXLEN], logicalMap2[MAXLEN], logicalMap3[MAXLEN],
+ visualMap1[MAXLEN], visualMap2[MAXLEN], visualMap3[MAXLEN], visualMap4[MAXLEN];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ const UBiDiLevel *levels;
+ int32_t i, length=ubidi_getLength(pBiDi),
+ destLength=ubidi_getResultLength(pBiDi);
+ int32_t runCount, visualIndex, logicalStart, runLength;
+ UBool odd;
+
+ if(length<=0) {
+ return;
+ }
+
+ /* get the logical and visual maps from the object */
+ ubidi_getLogicalMap(pBiDi, logicalMap1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getLogicalMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+
+ ubidi_getVisualMap(pBiDi, visualMap1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getVisualMap(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+
+ /* invert them both */
+ ubidi_invertMap(logicalMap1, visualMap2, length);
+ ubidi_invertMap(visualMap1, logicalMap2, destLength);
+
+ /* get them from the levels array, too */
+ levels=ubidi_getLevels(pBiDi, &errorCode);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getLevels(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+
+ ubidi_reorderLogical(levels, length, logicalMap3);
+ ubidi_reorderVisual(levels, length, visualMap3);
+
+ /* get the visual map from the runs, too */
+ runCount=ubidi_countRuns(pBiDi, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_countRuns(tests[%d]): error %s\n", testNumber, myErrorName(errorCode));
+ return;
+ }
+ log_verbose("\n----%2d runs:", runCount);
+ visualIndex=0;
+ for(i=0; i<runCount; ++i) {
+ odd=(UBool)ubidi_getVisualRun(pBiDi, i, &logicalStart, &runLength);
+ log_verbose(" (%c @%d[%d])", odd ? 'R' : 'L', logicalStart, runLength);
+ if(UBIDI_LTR==odd) {
+ do { /* LTR */
+ visualMap4[visualIndex++]=logicalStart++;
+ } while(--runLength>0);
+ } else {
+ logicalStart+=runLength; /* logicalLimit */
+ do { /* RTL */
+ visualMap4[visualIndex++]=--logicalStart;
+ } while(--runLength>0);
+ }
+ }
+ log_verbose("\n");
+
+ /* print all the maps */
+ log_verbose("logical maps:\n");
+ for(i=0; i<length; ++i) {
+ log_verbose("%4d", logicalMap1[i]);
+ }
+ log_verbose("\n");
+ for(i=0; i<length; ++i) {
+ log_verbose("%4d", logicalMap2[i]);
+ }
+ log_verbose("\n");
+ for(i=0; i<length; ++i) {
+ log_verbose("%4d", logicalMap3[i]);
+ }
+
+ log_verbose("\nvisual maps:\n");
+ for(i=0; i<destLength; ++i) {
+ log_verbose("%4d", visualMap1[i]);
+ }
+ log_verbose("\n");
+ for(i=0; i<destLength; ++i) {
+ log_verbose("%4d", visualMap2[i]);
+ }
+ log_verbose("\n");
+ for(i=0; i<length; ++i) {
+ log_verbose("%4d", visualMap3[i]);
+ }
+ log_verbose("\n");
+ for(i=0; i<length; ++i) {
+ log_verbose("%4d", visualMap4[i]);
+ }
+ log_verbose("\n");
+
+ /* check that the indexes are the same between these and ubidi_getLogical/VisualIndex() */
+ for(i=0; i<length; ++i) {
+ if(logicalMap1[i]!=logicalMap2[i]) {
+ log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap2[i] at i=%d\n", testNumber, i);
+ break;
+ }
+ if(logicalMap1[i]!=logicalMap3[i]) {
+ log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=logicalMap3[i] at i=%d\n", testNumber, i);
+ break;
+ }
+
+ if(visualMap1[i]!=visualMap2[i]) {
+ log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap2[i] at i=%d\n", testNumber, i);
+ break;
+ }
+ if(visualMap1[i]!=visualMap3[i]) {
+ log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap3[i] at i=%d\n", testNumber, i);
+ break;
+ }
+ if(visualMap1[i]!=visualMap4[i]) {
+ log_err("bidi reordering error in tests[%d]: visualMap1[i]!=visualMap4[i] at i=%d\n", testNumber, i);
+ break;
+ }
+
+ if(logicalMap1[i]!=ubidi_getVisualIndex(pBiDi, i, &errorCode)) {
+ log_err("bidi reordering error in tests[%d]: logicalMap1[i]!=ubidi_getVisualIndex(i) at i=%d\n", testNumber, i);
+ break;
+ }
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getVisualIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
+ break;
+ }
+ if(visualMap1[i]!=ubidi_getLogicalIndex(pBiDi, i, &errorCode)) {
+ log_err("bidi reordering error in tests[%d]: visualMap1[i]!=ubidi_getLogicalIndex(i) at i=%d\n", testNumber, i);
+ break;
+ }
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_getLogicalIndex(tests[%d], %d): error %s\n", testNumber, i, myErrorName(errorCode));
+ break;
+ }
+ }
+}
+
+#define RETURN_IF_BAD_ERRCODE(x) \
+ if (U_FAILURE(errorCode)) { \
+ log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \
+ return; \
+ } \
+
+
+static void doMisc(void) {
+/* Miscellaneous tests to exercize less popular code paths */
+ UBiDi *bidi, *bidiLine;
+ UChar src[MAXLEN], dest[MAXLEN];
+ int32_t srcLen, destLen, runCount, i;
+ UBiDiLevel level;
+ UBiDiDirection dir;
+ int32_t map[MAXLEN];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ static const int32_t srcMap[6] = {0,1,-1,5,4};
+ static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
+
+ bidi = ubidi_openSized(120, 66, &errorCode);
+ if (bidi == NULL) {
+ log_err("Error with openSized(120, 66)\n");
+ return;
+ }
+ bidiLine = ubidi_open();
+ if (bidi == NULL) {
+ log_err("Error with open()\n");
+ return;
+ }
+
+ destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nwriteReverse should return zero length, ",
+ "returned %d instead\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#1#");
+
+ ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nwriteReordered should return zero length, ",
+ "returned %d instead\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#2#");
+
+ srcLen = u_unescape("abc ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != UBIDI_RTL) {
+ log_err("\nTrailing space at index %d should get paragraph level"
+ "%d, got %d instead\n", i, UBIDI_RTL, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#3#");
+
+ srcLen = u_unescape("abc def", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != UBIDI_RTL) {
+ log_err("\nTrailing space at index %d should get paragraph level"
+ "%d, got %d instead\n", i, UBIDI_RTL, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#4#");
+
+ srcLen = u_unescape("abcdefghi ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != 2) {
+ log_err("\nTrailing char at index %d should get level 2, "
+ "got %d instead\n", i, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#5#");
+
+ ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
+ srcLen = u_unescape("\\u200eabc def", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ destLen = ubidi_getResultLength(bidiLine);
+ if (destLen != 5) {
+ log_err("\nWrong result length, should be 5, got %d\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#6#");
+
+ srcLen = u_unescape("abcdefghi", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ dir = ubidi_getDirection(bidiLine);
+ if (dir != UBIDI_LTR) {
+ log_err("\nWrong direction #1, should be %d, got %d\n",
+ UBIDI_LTR, dir);
+ }
+ RETURN_IF_BAD_ERRCODE("#7#");
+
+ ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
+ runCount = ubidi_countRuns(bidi, &errorCode);
+ if (runCount != 0) {
+ log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#8#");
+
+ srcLen = u_unescape(" ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ runCount = ubidi_countRuns(bidiLine, &errorCode);
+ if (runCount != 1) {
+ log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#9#");
+
+ srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ dir = ubidi_getDirection(bidi);
+ if (dir != UBIDI_MIXED) {
+ log_err("\nWrong direction #2, should be %d, got %d\n",
+ UBIDI_MIXED, dir);
+ }
+ dir = ubidi_getDirection(bidiLine);
+ if (dir != UBIDI_MIXED) {
+ log_err("\nWrong direction #3, should be %d, got %d\n",
+ UBIDI_MIXED, dir);
+ }
+ runCount = ubidi_countRuns(bidiLine, &errorCode);
+ if (runCount != 2) {
+ log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#10#");
+
+ ubidi_invertMap(srcMap, map, 5);
+ if (memcmp(dstMap, map, sizeof(dstMap))) {
+ log_err("\nUnexpected inverted Map, got ");
+ for (i = 0; i < 6; i++) {
+ log_err("%d ", map[i]);
+ }
+ log_err("\n");
+ }
+
+ /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
+ srcLen = u_unescape("abc\\u200e", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
+ UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
+ log_err("\nWrong result #1, should be 'abc', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#11#");
+
+ /* test inverse Bidi with marks and contextual orientation */
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
+ ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
+ ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#12#");
+ srcLen = u_unescape(" ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #3, should be ' ', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#13#");
+ srcLen = u_unescape("abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #4, should be 'abc', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#14#");
+ srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #5, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#15#");
+ srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
+ if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #6, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#16#");
+ srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #7, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#17#");
+ srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #8, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#18#");
+ ubidi_orderParagraphsLTR(bidi, TRUE);
+ srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
+ "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
+ "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
+ "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
+ "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
+ if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #9, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#19#");
+ srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
+ if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #10, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#20#");
+ srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
+ if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #11, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#21#");
+ srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
+ if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #12, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#22#");
+ srcLen = u_unescape("ab \t", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
+ if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #13, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#23#");
+
+ /* check exceeding para level */
+ ubidi_close(bidi);
+ bidi = ubidi_open();
+ srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
+ level = ubidi_getLevelAt(bidi, 2);
+ if (level != 61) {
+ log_err("\nWrong level at index 2\n, should be 61, got %d\n", level);
+ }
+ RETURN_IF_BAD_ERRCODE("#24#");
+
+ /* check 1-char runs with RUNS_ONLY */
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
+ srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ runCount = ubidi_countRuns(bidi, &errorCode);
+ if (runCount != 14) {
+ log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#25#");
+
+ ubidi_close(bidi);
+ ubidi_close(bidiLine);
+}
+
+static void
+testFailureRecovery(void) {
+ UErrorCode errorCode;
+ UBiDi *bidi, *bidiLine;
+ UChar src[MAXLEN];
+ int32_t srcLen;
+ UBiDiLevel level;
+ UBiDiReorderingMode rm;
+ static UBiDiLevel myLevels[3] = {6,5,4};
+
+ log_verbose("\nEntering TestFailureRecovery\n\n");
+ errorCode = U_FILE_ACCESS_ERROR;
+ if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0) {
+ log_err("ubidi_writeReordered did not return 0 when passed a failing UErrorCode\n");
+ }
+ if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0) {
+ log_err("ubidi_writeReverse did not return 0 when passed a failing UErrorCode\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ if (ubidi_writeReordered(NULL, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ubidi_writeReordered did not fail as expected\n");
+ }
+
+ bidi = ubidi_open();
+ srcLen = u_unescape("abc", src, MAXLEN);
+ errorCode = U_ZERO_ERROR;
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_LTR - 1, NULL, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nubidi_setPara did not fail when passed too big para level\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ if (ubidi_writeReverse(NULL, 0, NULL, 0, 0, &errorCode) != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ubidi_writeReverse did not fail as expected\n");
+ }
+ bidiLine = ubidi_open();
+ errorCode = U_ZERO_ERROR;
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nubidi_setLine did not fail when called before valid setPara()\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ srcLen = u_unescape("abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR + 4, NULL, &errorCode);
+ level = ubidi_getLevelAt(bidi, 3);
+ if (level != 0) {
+ log_err("\nubidi_getLevelAt did not fail when called with bad argument\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ ubidi_close(bidi);
+ bidi = ubidi_openSized(-1, 0, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nubidi_openSized did not fail when called with bad argument\n");
+ }
+ ubidi_close(bidi);
+ bidi = ubidi_openSized(2, 1, &errorCode);
+ errorCode = U_ZERO_ERROR;
+ srcLen = u_unescape("abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nsetPara did not fail when called with text too long\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ srcLen = u_unescape("=2", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_countRuns(bidi, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nsetPara did not fail when called for too many runs\n");
+ }
+ ubidi_close(bidi);
+ bidi = ubidi_open();
+ rm = ubidi_getReorderingMode(bidi);
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_DEFAULT - 1);
+ if (rm != ubidi_getReorderingMode(bidi)) {
+ log_err("\nsetReorderingMode with bad argument #1 should have no effect\n");
+ }
+ ubidi_setReorderingMode(bidi, 9999);
+ if (rm != ubidi_getReorderingMode(bidi)) {
+ log_err("\nsetReorderingMode with bad argument #2 should have no effect\n");
+ }
+
+ /* Try a surrogate char */
+ errorCode = U_ZERO_ERROR;
+ srcLen = u_unescape("\\uD800\\uDC00", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ if (ubidi_getDirection(bidi) != UBIDI_MIXED) {
+ log_err("\ngetDirection for 1st surrogate char should be MIXED\n");
+ }
+ errorCode = U_ZERO_ERROR;
+ srcLen = u_unescape("abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, 5, myLevels, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("\nsetPara did not fail when called with bad levels\n");
+ }
+ ubidi_close(bidi);
+ ubidi_close(bidiLine);
+
+ log_verbose("\nExiting TestFailureRecovery\n\n");
+}
+
+static void
+testMultipleParagraphs(void) {
+ static const char* const text = "__ABC\\u001c" /* Para #0 offset 0 */
+ "__\\u05d0DE\\u001c" /* 1 6 */
+ "__123\\u001c" /* 2 12 */
+ "\\u000d\\u000a" /* 3 18 */
+ "FG\\u000d" /* 4 20 */
+ "\\u000d" /* 5 23 */
+ "HI\\u000d\\u000a" /* 6 24 */
+ "\\u000d\\u000a" /* 7 28 */
+ "\\u000a" /* 8 30 */
+ "\\u000a" /* 9 31 */
+ "JK\\u001c"; /* 10 32 */
+ static const int32_t paraCount=11;
+ static const int32_t paraBounds[]={0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35};
+ static const UBiDiLevel paraLevels[]={UBIDI_LTR, UBIDI_RTL, UBIDI_DEFAULT_LTR, UBIDI_DEFAULT_RTL, 22, 23};
+ static const UBiDiLevel multiLevels[6][11] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
+ {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
+ {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}};
+ static const char* const text2 = "\\u05d0 1-2\\u001c\\u0630 1-2\\u001c1-2";
+ static const UBiDiLevel levels2[] = {1,1,2,2,2,0, 1,1,2,1,2,0, 2,2,2};
+ static UBiDiLevel myLevels[10] = {0,0,0,0,0,0,0,0,0,0};
+ UBiDiLevel gotLevel;
+ const UBiDiLevel* gotLevels;
+ UBool orderParagraphsLTR;
+ UChar src[MAXLEN], dest[MAXLEN];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UBiDi* pBidi=ubidi_open();
+ UBiDi* pLine;
+ int32_t srcSize, count, paraStart, paraLimit, paraIndex, length;
+ int32_t srcLen, destLen;
+ int i, j, k;
+
+ log_verbose("\nEntering TestMultipleParagraphs\n\n");
+ u_unescape(text, src, MAXLEN);
+ srcSize=u_strlen(src);
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
+ UBIDI_LTR, u_errorName(errorCode));
+ ubidi_close(pBidi);
+ return;
+ }
+ /* check paragraph count and boundaries */
+ if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
+ log_err("ubidi_countParagraphs returned %d, should be %d\n",
+ count, paraCount);
+ }
+ for (i=0; i<paraCount; i++) {
+ ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
+ if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
+ log_err("Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
+ i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
+ }
+ }
+ errorCode=U_ZERO_ERROR;
+ /* check with last paragraph not terminated by B */
+ src[srcSize-1]='L';
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_LTR, NULL, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("2nd ubidi_setPara failed, paraLevel=%d, errorCode %s\n",
+ UBIDI_LTR, u_errorName(errorCode));
+ ubidi_close(pBidi);
+ return;
+ }
+ if (paraCount!=(count=ubidi_countParagraphs(pBidi))) {
+ log_err("2nd ubidi_countParagraphs returned %d, should be %d\n",
+ count, paraCount);
+ }
+ i=paraCount-1;
+ ubidi_getParagraphByIndex(pBidi, i, &paraStart, &paraLimit, NULL, &errorCode);
+ if ((paraStart!=paraBounds[i]) || (paraLimit!=paraBounds[i+1])) {
+ log_err("2nd Found boundaries of paragraph %d: %d-%d; expected: %d-%d\n",
+ i, paraStart, paraLimit, paraBounds[i], paraBounds[i+1]);
+ }
+ errorCode=U_ZERO_ERROR;
+ /* check paraLevel for all paragraphs under various paraLevel specs */
+ for (k=0; k<6; k++) {
+ ubidi_setPara(pBidi, src, srcSize, paraLevels[k], NULL, &errorCode);
+ for (i=0; i<paraCount; i++) {
+ paraIndex=ubidi_getParagraph(pBidi, paraBounds[i], NULL, NULL, &gotLevel, &errorCode);
+ if (paraIndex!=i) {
+ log_err("For paraLevel=%d paragraph=%d, found paragraph index=%d expected=%d\n",
+ paraLevels[k], i, paraIndex, i);
+ }
+ if (gotLevel!=multiLevels[k][i]) {
+ log_err("For paraLevel=%d paragraph=%d, found level=%d expected %d\n",
+ paraLevels[k], i, gotLevel, multiLevels[k][i]);
+ }
+ }
+ gotLevel=ubidi_getParaLevel(pBidi);
+ if (gotLevel!=multiLevels[k][0]) {
+ log_err("For paraLevel=%d getParaLevel=%d, expected %d\n",
+ paraLevels[k], gotLevel, multiLevels[k][0]);
+ }
+ }
+ errorCode=U_ZERO_ERROR;
+ /* check that the result of ubidi_getParaLevel changes if the first
+ * paragraph has a different level
+ */
+ src[0]=0x05d2; /* Hebrew letter Gimel */
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_LTR, NULL, &errorCode);
+ gotLevel=ubidi_getParaLevel(pBidi);
+ if (gotLevel!=UBIDI_RTL) {
+ log_err("For paraLevel=UBIDI_DEFAULT_LTR getParaLevel=%d, expected=%d\n",
+ gotLevel, UBIDI_RTL);
+ }
+ errorCode=U_ZERO_ERROR;
+ /* check that line cannot overlap paragraph boundaries */
+ pLine=ubidi_open();
+ i=paraBounds[1];
+ k=paraBounds[2]+1;
+ ubidi_setLine(pBidi, i, k, pLine, &errorCode);
+ if (U_SUCCESS(errorCode)) {
+ log_err("For line limits %d-%d got success %s\n",
+ i, k, u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ i=paraBounds[1];
+ k=paraBounds[2];
+ ubidi_setLine(pBidi, i, k, pLine, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("For line limits %d-%d got error %s\n",
+ i, k, u_errorName(errorCode));
+ errorCode=U_ZERO_ERROR;
+ }
+ /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
+ /* get levels through para Bidi block */
+ gotLevels=ubidi_getLevels(pBidi, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("Error on Para getLevels %s\n", u_errorName(errorCode));
+ ubidi_close(pLine);
+ ubidi_close(pBidi);
+ return;
+ }
+ for (i=26; i<32; i++) {
+ if (gotLevels[i]!=UBIDI_RTL) {
+ log_err("For char %d(%04x), level=%d, expected=%d\n",
+ i, src[i], gotLevels[i], UBIDI_RTL);
+ }
+ }
+ /* get levels through para Line block */
+ i=paraBounds[1];
+ k=paraBounds[2];
+ ubidi_setLine(pBidi, i, k, pLine, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("For line limits %d-%d got error %s\n",
+ i, k, u_errorName(errorCode));
+ ubidi_close(pLine);
+ ubidi_close(pBidi);
+ return;
+ }
+ paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
+ gotLevels=ubidi_getLevels(pLine, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("Error on Line getLevels %s\n", u_errorName(errorCode));
+ ubidi_close(pLine);
+ ubidi_close(pBidi);
+ return;
+ }
+ length=ubidi_getLength(pLine);
+ if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=UBIDI_RTL)) {
+ log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
+ "level of separator=%d expected=%d\n",
+ paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], UBIDI_RTL);
+ }
+ orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
+ if (orderParagraphsLTR) {
+ log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, FALSE);
+ }
+ ubidi_orderParagraphsLTR(pBidi, TRUE);
+ orderParagraphsLTR=ubidi_isOrderParagraphsLTR(pBidi);
+ if (!orderParagraphsLTR) {
+ log_err("Found orderParagraphsLTR=%d expected=%d\n", orderParagraphsLTR, TRUE);
+ }
+ /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
+ /* get levels through para Bidi block */
+ gotLevels=ubidi_getLevels(pBidi, &errorCode);
+ for (i=26; i<32; i++) {
+ if (gotLevels[i]!=0) {
+ log_err("For char %d(%04x), level=%d, expected=%d\n",
+ i, src[i], gotLevels[i], 0);
+ }
+ }
+ errorCode=U_ZERO_ERROR;
+ /* get levels through para Line block */
+ i=paraBounds[1];
+ k=paraBounds[2];
+ ubidi_setLine(pBidi, paraStart, paraLimit, pLine, &errorCode);
+ paraIndex=ubidi_getParagraph(pLine, i, &paraStart, &paraLimit, &gotLevel, &errorCode);
+ gotLevels=ubidi_getLevels(pLine, &errorCode);
+ length=ubidi_getLength(pLine);
+ if ((gotLevel!=UBIDI_RTL) || (gotLevels[length-1]!=0)) {
+ log_err("For paragraph %d with limits %d-%d, paraLevel=%d expected=%d, "
+ "level of separator=%d expected=%d\n",
+ paraIndex, paraStart, paraLimit, gotLevel, UBIDI_RTL, gotLevels[length-1], 0);
+ log_verbose("levels=");
+ for (count=0; count<length; count++) {
+ log_verbose(" %d", gotLevels[count]);
+ }
+ log_verbose("\n");
+ }
+
+ /* test that the concatenation of separate invocations of the bidi code
+ * on each individual paragraph in order matches the levels array that
+ * results from invoking bidi once over the entire multiparagraph tests
+ * (with orderParagraphsLTR false, of course)
+ */
+ u_unescape(text, src, MAXLEN); /* restore original content */
+ srcSize=u_strlen(src);
+ ubidi_orderParagraphsLTR(pBidi, FALSE);
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ gotLevels=ubidi_getLevels(pBidi, &errorCode);
+ for (i=0; i<paraCount; i++) {
+ /* use pLine for individual paragraphs */
+ paraStart = paraBounds[i];
+ length = paraBounds[i+1] - paraStart;
+ ubidi_setPara(pLine, src+paraStart, length, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ for (j=0; j<length; j++) {
+ if ((k=ubidi_getLevelAt(pLine, j)) != (gotLevel=gotLevels[paraStart+j])) {
+ log_err("Checking paragraph concatenation: for paragraph=%d, "
+ "char=%d(%04x), level=%d, expected=%d\n",
+ i, j, src[paraStart+j], k, gotLevel);
+ }
+ }
+ }
+
+ /* ensure that leading numerics in a paragraph are not treated as arabic
+ numerals because of arabic text in a preceding paragraph
+ */
+ u_unescape(text2, src, MAXLEN);
+ srcSize=u_strlen(src);
+ ubidi_orderParagraphsLTR(pBidi, TRUE);
+ ubidi_setPara(pBidi, src, srcSize, UBIDI_RTL, NULL, &errorCode);
+ gotLevels=ubidi_getLevels(pBidi, &errorCode);
+ for (i=0; i<srcSize; i++) {
+ if (gotLevels[i]!=levels2[i]) {
+ log_err("Checking leading numerics: for char %d(%04x), level=%d, expected=%d\n",
+ i, src[i], gotLevels[i], levels2[i]);
+ }
+ }
+
+ /* check handling of whitespace before end of paragraph separator when
+ * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
+ */
+ u_memset(src, 0x0020, MAXLEN);
+ srcSize = 5;
+ ubidi_orderParagraphsLTR(pBidi, TRUE);
+ for (i=0x001c; i<=0x0020; i+=(0x0020-0x001c)) {
+ src[4]=(UChar)i; /* with and without terminating B */
+ for (j=0x0041; j<=0x05d0; j+=(0x05d0-0x0041)) {
+ src[0]=(UChar)j; /* leading 'A' or Alef */
+ for (gotLevel=4; gotLevel<=5; gotLevel++) {
+ /* test even and odd paraLevel */
+ ubidi_setPara(pBidi, src, srcSize, gotLevel, NULL, &errorCode);
+ gotLevels=ubidi_getLevels(pBidi, &errorCode);
+ for (k=1; k<=3; k++) {
+ if (gotLevels[k]!=gotLevel) {
+ log_err("Checking trailing spaces: for leading_char=%04x, "
+ "last_char=%04x, index=%d, level=%d, expected=%d\n",
+ src[0], src[4], k, gotLevels[k], gotLevel);
+ }
+ }
+ }
+ }
+ }
+
+ /* check default orientation when inverse bidi and paragraph starts
+ * with LTR strong char and ends with RTL strong char, with and without
+ * a terminating B
+ */
+ ubidi_setReorderingMode(pBidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
+ srcLen = u_unescape("abc \\u05d2\\u05d1\n", src, MAXLEN);
+ ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d2 abc\n", src, MAXLEN);
+ if (memcmp(src, dest, destLen * sizeof(UChar))) {
+ log_err("\nInvalid output #0, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ srcLen = u_unescape("abc \\u05d2\\u05d1", src, MAXLEN);
+ ubidi_setPara(pBidi, src, srcLen, UBIDI_DEFAULT_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d2 abc", src, MAXLEN);
+ if (memcmp(src, dest, destLen * sizeof(UChar))) {
+ log_err("\nInvalid output #1, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+
+ /* check multiple paragraphs together with explicit levels
+ */
+ ubidi_setReorderingMode(pBidi, UBIDI_REORDER_DEFAULT);
+ srcLen = u_unescape("ab\\u05d1\\u05d2\n\\u05d3\\u05d4123", src, MAXLEN);
+ ubidi_setPara(pBidi, src, srcLen, UBIDI_LTR, myLevels, &errorCode);
+ destLen = ubidi_writeReordered(pBidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("ab\\u05d2\\u05d1\\n123\\u05d4\\u05d3", src, MAXLEN);
+ if (memcmp(src, dest, destLen * sizeof(UChar))) {
+ log_err("\nInvalid output #2, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ count = ubidi_countParagraphs(pBidi);
+ if (count != 2) {
+ log_err("\nInvalid number of paras, should be 2, got %d\n", count);
+ }
+
+ ubidi_close(pLine);
+ ubidi_close(pBidi);
+ log_verbose("\nExiting TestMultipleParagraphs\n\n");
+}
+
+
+/* inverse BiDi ------------------------------------------------------------- */
+
+static int countRoundtrips=0, countNonRoundtrips=0;
+
+#define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
+
+static void
+testInverse(void) {
+ static const UChar
+ string0[]={ 0x6c, 0x61, 0x28, 0x74, 0x69, 0x6e, 0x20, 0x5d0, 0x5d1, 0x29, 0x5d2, 0x5d3 },
+ string1[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x31, 0x32, 0x33 },
+ string2[]={ 0x6c, 0x61, 0x74, 0x20, 0x5d0, 0x28, 0x5d1, 0x5d2, 0x20, 0x31, 0x29, 0x32, 0x33 },
+ string3[]={ 0x31, 0x32, 0x33, 0x20, 0x5d0, 0x5d1, 0x5d2, 0x20, 0x34, 0x35, 0x36 },
+ string4[]={ 0x61, 0x62, 0x20, 0x61, 0x62, 0x20, 0x661, 0x662 };
+
+ static const struct {
+ const UChar *s;
+ int32_t length;
+ } testCases[]={
+ STRING_TEST_CASE(string0),
+ STRING_TEST_CASE(string1),
+ STRING_TEST_CASE(string2),
+ STRING_TEST_CASE(string3),
+ STRING_TEST_CASE(string4)
+ };
+
+ UBiDi *pBiDi;
+ UErrorCode errorCode;
+ int i;
+
+ log_verbose("\nEntering TestInverse\n\n");
+ pBiDi=ubidi_open();
+ if(pBiDi==NULL) {
+ log_err("unable to open a UBiDi object (out of memory)\n");
+ return;
+ }
+
+ log_verbose("inverse Bidi: testInverse(L) with %u test cases ---\n", LENGTHOF(testCases));
+ for(i=0; i<LENGTHOF(testCases); ++i) {
+ log_verbose("Testing case %d\n", i);
+ errorCode=U_ZERO_ERROR;
+ _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 0, &errorCode);
+ }
+
+ log_verbose("inverse Bidi: testInverse(R) with %u test cases ---\n", LENGTHOF(testCases));
+ for(i=0; i<LENGTHOF(testCases); ++i) {
+ log_verbose("Testing case %d\n", i);
+ errorCode=U_ZERO_ERROR;
+ _testInverseBidi(pBiDi, testCases[i].s, testCases[i].length, 1, &errorCode);
+ }
+
+ _testManyInverseBidi(pBiDi, 0);
+ _testManyInverseBidi(pBiDi, 1);
+
+ ubidi_close(pBiDi);
+
+ log_verbose("inverse Bidi: rountrips: %5u\nnon-roundtrips: %5u\n", countRoundtrips, countNonRoundtrips);
+
+ _testWriteReverse();
+
+ _testManyAddedPoints();
+
+ _testMisc();
+
+ log_verbose("\nExiting TestInverse\n\n");
+}
+
+#define COUNT_REPEAT_SEGMENTS 6
+
+static const UChar repeatSegments[COUNT_REPEAT_SEGMENTS][2]={
+ { 0x61, 0x62 }, /* L */
+ { 0x5d0, 0x5d1 }, /* R */
+ { 0x627, 0x628 }, /* AL */
+ { 0x31, 0x32 }, /* EN */
+ { 0x661, 0x662 }, /* AN */
+ { 0x20, 0x20 } /* WS (N) */
+};
+
+static void
+_testManyInverseBidi(UBiDi *pBiDi, UBiDiLevel direction) {
+ UChar text[8]={ 0, 0, 0x20, 0, 0, 0x20, 0, 0 };
+ int i, j, k;
+ UErrorCode errorCode;
+
+ log_verbose("inverse Bidi: testManyInverseBidi(%c) - test permutations of text snippets ---\n",
+ direction==0 ? 'L' : 'R');
+ for(i=0; i<COUNT_REPEAT_SEGMENTS; ++i) {
+ text[0]=repeatSegments[i][0];
+ text[1]=repeatSegments[i][1];
+ for(j=0; j<COUNT_REPEAT_SEGMENTS; ++j) {
+ text[3]=repeatSegments[j][0];
+ text[4]=repeatSegments[j][1];
+ for(k=0; k<COUNT_REPEAT_SEGMENTS; ++k) {
+ text[6]=repeatSegments[k][0];
+ text[7]=repeatSegments[k][1];
+
+ errorCode=U_ZERO_ERROR;
+ log_verbose("inverse Bidi: testManyInverseBidi()[%u %u %u]\n", i, j, k);
+ _testInverseBidi(pBiDi, text, 8, direction, &errorCode);
+ }
+ }
+ }
+}
+
+static void
+_testInverseBidi(UBiDi *pBiDi, const UChar *src, int32_t srcLength,
+ UBiDiLevel direction, UErrorCode *pErrorCode) {
+ UChar visualLTR[MAXLEN], logicalDest[MAXLEN], visualDest[MAXLEN];
+ int32_t ltrLength, logicalLength, visualLength;
+
+ if(direction==0) {
+ log_verbose("inverse Bidi: testInverse(L)\n");
+
+ /* convert visual to logical */
+ ubidi_setInverse(pBiDi, TRUE);
+ if (!ubidi_isInverse(pBiDi)) {
+ log_err("Error while doing ubidi_setInverse(TRUE)\n");
+ }
+ ubidi_setPara(pBiDi, src, srcLength, 0, NULL, pErrorCode);
+ if (src != ubidi_getText(pBiDi)) {
+ log_err("Wrong value returned by ubidi_getText\n");
+ }
+ logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
+ UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
+ log_verbose(" v ");
+ printUnicode(src, srcLength, ubidi_getLevels(pBiDi, pErrorCode));
+ log_verbose("\n");
+
+ /* convert back to visual LTR */
+ ubidi_setInverse(pBiDi, FALSE);
+ if (ubidi_isInverse(pBiDi)) {
+ log_err("Error while doing ubidi_setInverse(FALSE)\n");
+ }
+ ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
+ visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
+ UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS, pErrorCode);
+ } else {
+ log_verbose("inverse Bidi: testInverse(R)\n");
+
+ /* reverse visual from RTL to LTR */
+ ltrLength=ubidi_writeReverse(src, srcLength, visualLTR, LENGTHOF(visualLTR), 0, pErrorCode);
+ log_verbose(" vr");
+ printUnicode(src, srcLength, NULL);
+ log_verbose("\n");
+
+ /* convert visual RTL to logical */
+ ubidi_setInverse(pBiDi, TRUE);
+ ubidi_setPara(pBiDi, visualLTR, ltrLength, 0, NULL, pErrorCode);
+ logicalLength=ubidi_writeReordered(pBiDi, logicalDest, LENGTHOF(logicalDest),
+ UBIDI_DO_MIRRORING|UBIDI_INSERT_LRM_FOR_NUMERIC, pErrorCode);
+ log_verbose(" vl");
+ printUnicode(visualLTR, ltrLength, ubidi_getLevels(pBiDi, pErrorCode));
+ log_verbose("\n");
+
+ /* convert back to visual RTL */
+ ubidi_setInverse(pBiDi, FALSE);
+ ubidi_setPara(pBiDi, logicalDest, logicalLength, 0, NULL, pErrorCode);
+ visualLength=ubidi_writeReordered(pBiDi, visualDest, LENGTHOF(visualDest),
+ UBIDI_DO_MIRRORING|UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_OUTPUT_REVERSE, pErrorCode);
+ }
+ log_verbose(" l ");
+ printUnicode(logicalDest, logicalLength, ubidi_getLevels(pBiDi, pErrorCode));
+ log_verbose("\n");
+ log_verbose(" v ");
+ printUnicode(visualDest, visualLength, NULL);
+ log_verbose("\n");
+
+ /* check and print results */
+ if(U_FAILURE(*pErrorCode)) {
+ log_err("inverse BiDi: *** error %s\n"
+ " turn on verbose mode to see details\n", u_errorName(*pErrorCode));
+ } else if(srcLength==visualLength && memcmp(src, visualDest, srcLength*U_SIZEOF_UCHAR)==0) {
+ ++countRoundtrips;
+ log_verbose(" + roundtripped\n");
+ } else {
+ ++countNonRoundtrips;
+ log_verbose(" * did not roundtrip\n");
+ log_err("inverse BiDi: transformation visual->logical->visual did not roundtrip the text;\n"
+ " turn on verbose mode to see details\n");
+ }
+}
+
+static void
+_testWriteReverse(void) {
+ /* U+064e and U+0650 are combining marks (Mn) */
+ static const UChar forward[]={
+ 0x200f, 0x627, 0x64e, 0x650, 0x20, 0x28, 0x31, 0x29
+ }, reverseKeepCombining[]={
+ 0x29, 0x31, 0x28, 0x20, 0x627, 0x64e, 0x650, 0x200f
+ }, reverseRemoveControlsKeepCombiningDoMirror[]={
+ 0x28, 0x31, 0x29, 0x20, 0x627, 0x64e, 0x650
+ };
+ UChar reverse[10];
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* test ubidi_writeReverse() with "interesting" options */
+ errorCode=U_ZERO_ERROR;
+ length=ubidi_writeReverse(forward, LENGTHOF(forward),
+ reverse, LENGTHOF(reverse),
+ UBIDI_KEEP_BASE_COMBINING,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseKeepCombining) || memcmp(reverse, reverseKeepCombining, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in ubidi_writeReverse(UBIDI_KEEP_BASE_COMBINING): length=%d (should be %d), error code %s\n",
+ length, LENGTHOF(reverseKeepCombining), u_errorName(errorCode));
+ }
+
+ memset(reverse, 0xa5, LENGTHOF(reverse)*U_SIZEOF_UCHAR);
+ errorCode=U_ZERO_ERROR;
+ length=ubidi_writeReverse(forward, LENGTHOF(forward),
+ reverse, LENGTHOF(reverse),
+ UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror) || memcmp(reverse, reverseRemoveControlsKeepCombiningDoMirror, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in ubidi_writeReverse(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING):\n"
+ " length=%d (should be %d), error code %s\n",
+ length, LENGTHOF(reverseRemoveControlsKeepCombiningDoMirror), u_errorName(errorCode));
+ }
+}
+
+static void _testManyAddedPoints(void) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UBiDi *bidi = ubidi_open();
+ UChar text[90], dest[MAXLEN], expected[120];
+ int destLen, i;
+ for (i = 0; i < LENGTHOF(text); i+=3) {
+ text[i] = 0x0061; /* 'a' */
+ text[i+1] = 0x05d0;
+ text[i+2] = 0x0033; /* '3' */
+ }
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
+ ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
+ ubidi_setPara(bidi, text, LENGTHOF(text), UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ for (i = 0; i < LENGTHOF(expected); i+=4) {
+ expected[i] = 0x0061; /* 'a' */
+ expected[i+1] = 0x05d0;
+ expected[i+2] = 0x200e;
+ expected[i+3] = 0x0033; /* '3' */
+ }
+ if (memcmp(dest, expected, destLen * sizeof(UChar))) {
+ log_err("\nInvalid output with many added points, "
+ "expected '%s', got '%s'\n",
+ aescstrdup(expected, LENGTHOF(expected)),
+ aescstrdup(dest, destLen));
+ }
+ ubidi_close(bidi);
+}
+
+static void _testMisc(void) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UBiDi *bidi = ubidi_open();
+ UChar src[3], dest[MAXLEN], expected[5];
+ int destLen;
+ ubidi_setInverse(bidi, TRUE);
+ src[0] = src[1] = src[2] = 0x0020;
+ ubidi_setPara(bidi, src, LENGTHOF(src), UBIDI_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
+ UBIDI_OUTPUT_REVERSE | UBIDI_INSERT_LRM_FOR_NUMERIC,
+ &errorCode);
+ u_unescape("\\u200f \\u200f", expected, 5);
+ if (memcmp(dest, expected, destLen * sizeof(UChar))) {
+ log_err("\nInvalid output with RLM at both sides, "
+ "expected '%s', got '%s'\n",
+ aescstrdup(expected, LENGTHOF(expected)),
+ aescstrdup(dest, destLen));
+ }
+ ubidi_close(bidi);
+}
+
+/* arabic shaping ----------------------------------------------------------- */
+
+static void
+doArabicShapingTest(void) {
+ static const UChar
+ source[]={
+ 0x31, /* en:1 */
+ 0x627, /* arabic:alef */
+ 0x32, /* en:2 */
+ 0x6f3, /* an:3 */
+ 0x61, /* latin:a */
+ 0x34, /* en:4 */
+ 0
+ }, en2an[]={
+ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0
+ }, an2en[]={
+ 0x31, 0x627, 0x32, 0x33, 0x61, 0x34, 0
+ }, logical_alen2an_init_lr[]={
+ 0x31, 0x627, 0x662, 0x6f3, 0x61, 0x34, 0
+ }, logical_alen2an_init_al[]={
+ 0x6f1, 0x627, 0x6f2, 0x6f3, 0x61, 0x34, 0
+ }, reverse_alen2an_init_lr[]={
+ 0x661, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0
+ }, reverse_alen2an_init_al[]={
+ 0x6f1, 0x627, 0x32, 0x6f3, 0x61, 0x6f4, 0
+ };
+ UChar dest[8];
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* test number shaping */
+
+ /* european->arabic */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, en2an, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(en2an)\n");
+ }
+
+ /* arabic->european */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, -1,
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_AN2EN|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=u_strlen(source) || memcmp(dest, an2en, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(an2en)\n");
+ }
+
+ /* european->arabic with context, logical order, initial state not AL */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(logical_alen2an_init_lr)\n");
+ }
+
+ /* european->arabic with context, logical order, initial state AL */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, logical_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(logical_alen2an_init_al)\n");
+ }
+
+ /* european->arabic with context, reverse order, initial state not AL */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_ALEN2AN_INIT_LR|U_SHAPE_DIGIT_TYPE_AN|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_lr, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(reverse_alen2an_init_lr)\n");
+ }
+
+ /* european->arabic with context, reverse order, initial state AL */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_ALEN2AN_INIT_AL|U_SHAPE_DIGIT_TYPE_AN_EXTENDED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, reverse_alen2an_init_al, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(reverse_alen2an_init_al)\n");
+ }
+
+ /* test noop */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ 0,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(source) || memcmp(dest, source, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(noop)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, 0,
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=0) {
+ log_err("failure in u_shapeArabic(en2an, sourceLength=0), returned %d/%s\n", u_errorName(errorCode), LENGTHOF(source));
+ }
+
+ /* preflight digit shaping */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ NULL, 0,
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=LENGTHOF(source)) {
+ log_err("failure in u_shapeArabic(en2an preflighting), returned %d/%s instead of %d/U_BUFFER_OVERFLOW_ERROR\n",
+ length, u_errorName(errorCode), LENGTHOF(source));
+ }
+
+ /* test illegal arguments */
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(NULL, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(source=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, -2,
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(sourceLength=-2), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ NULL, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(dest=NULL), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, -1,
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(destSize=-1), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_RESERVED|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(U_SHAPE_DIGITS_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_RESERVED,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_shapeArabic(source, LENGTHOF(source),
+ (UChar *)(source+2), LENGTHOF(dest), /* overlap source and destination */
+ U_SHAPE_DIGITS_EN2AN|U_SHAPE_DIGIT_TYPE_AN,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("failure in u_shapeArabic(U_SHAPE_DIGIT_TYPE_RESERVED), returned %s instead of U_ILLEGAL_ARGUMENT_ERROR\n", u_errorName(errorCode));
+ }
+}
+
+static void
+doLamAlefSpecialVLTRArabicShapingTest(void) {
+ static const UChar
+ source[]={
+/*a*/ 0x20 ,0x646,0x622,0x644,0x627,0x20,
+/*b*/ 0x646,0x623,0x64E,0x644,0x627,0x20,
+/*c*/ 0x646,0x627,0x670,0x644,0x627,0x20,
+/*d*/ 0x646,0x622,0x653,0x644,0x627,0x20,
+/*e*/ 0x646,0x625,0x655,0x644,0x627,0x20,
+/*f*/ 0x646,0x622,0x654,0x644,0x627,0x20,
+/*g*/ 0xFEFC,0x639
+ }, shape_near[]={
+ 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
+ 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
+ 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
+ 0xfefc,0xfecb
+ }, shape_at_end[]={
+ 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
+ 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
+ 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,0x20,0x20,0x20
+ }, shape_at_begin[]={
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
+ 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
+ 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
+ }, shape_grow_shrink[]={
+ 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
+ 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
+ 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
+ }, shape_excepttashkeel_near[]={
+ 0x20,0xfee5,0x20,0xfef5,0xfe8d,0x20,0xfee5,0x20,0xfe76,0xfef7,0xfe8d,0x20,
+ 0xfee5,0x20,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x20,0x653,0xfef5,0xfe8d,0x20,
+ 0xfee5,0x20,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x20,0x654,0xfef5,0xfe8d,0x20,
+ 0xfefc,0xfecb
+ }, shape_excepttashkeel_at_end[]={
+ 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,
+ 0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,
+ 0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb,0x20,0x20,0x20,
+ 0x20,0x20,0x20
+ }, shape_excepttashkeel_at_begin[]={
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,
+ 0xfef7,0xfe8d,0x20,0xfee5,0x670,0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,
+ 0x20,0xfee5,0x655,0xfef9,0xfe8d,0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
+ }, shape_excepttashkeel_grow_shrink[]={
+ 0x20,0xfee5,0xfef5,0xfe8d,0x20,0xfee5,0xfe76,0xfef7,0xfe8d,0x20,0xfee5,0x670,
+ 0xfefb,0xfe8d,0x20,0xfee5,0x653,0xfef5,0xfe8d,0x20,0xfee5,0x655,0xfef9,0xfe8d,
+ 0x20,0xfee5,0x654,0xfef5,0xfe8d,0x20,0xfefc,0xfecb
+ };
+
+ UChar dest[38];
+ UErrorCode errorCode;
+ int32_t length;
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_near)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_end) || memcmp(dest, shape_at_end, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_at_end)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_at_begin) || memcmp(dest, shape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_at_begin)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || memcmp(dest, shape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_grow_shrink)\n");
+ }
+
+ /* ==================== U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED ==================== */
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_near)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_end) || memcmp(dest,shape_excepttashkeel_at_end , length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_end)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_at_begin) || memcmp(dest, shape_excepttashkeel_at_begin, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_at_begin)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_GROW_SHRINK|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || memcmp(dest, shape_excepttashkeel_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(LAMALEF shape_excepttashkeel_grow_shrink)\n");
+ }
+}
+
+static void
+doTashkeelSpecialVLTRArabicShapingTest(void) {
+ static const UChar
+ source[]={
+ 0x64A,0x628,0x631,0x639,0x20,
+ 0x64A,0x628,0x651,0x631,0x64E,0x639,0x20,
+ 0x64C,0x64A,0x628,0x631,0x64F,0x639,0x20,
+ 0x628,0x670,0x631,0x670,0x639,0x20,
+ 0x628,0x653,0x631,0x653,0x639,0x20,
+ 0x628,0x654,0x631,0x654,0x639,0x20,
+ 0x628,0x655,0x631,0x655,0x639,0x20,
+ }, shape_near[]={
+ 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe77,0xfecb,
+ 0x20,0xfe72,0xfef2,0xfe91,0xfeae,0xfe79,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,
+ 0xfecb,0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,
+ 0xfecb,0x20,0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
+ }, shape_excepttashkeel_near[]={
+ 0xfef2,0xfe91,0xfeae,0xfecb,0x20,0xfef2,0xfe91,0xfe7c,0xfeae,0xfe76,0xfecb,0x20,
+ 0xfe72,0xfef2,0xfe91,0xfeae,0xfe78,0xfecb,0x20,0xfe8f,0x670,0xfeae,0x670,0xfecb,
+ 0x20,0xfe8f,0x653,0xfeae,0x653,0xfecb,0x20,0xfe8f,0x654,0xfeae,0x654,0xfecb,0x20,
+ 0xfe8f,0x655,0xfeae,0x655,0xfecb,0x20
+ };
+
+ UChar dest[43];
+ UErrorCode errorCode;
+ int32_t length;
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_near) || memcmp(dest, shape_near, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(TASHKEEL shape_near)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
+ U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(shape_excepttashkeel_near) || memcmp(dest, shape_excepttashkeel_near, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(TASHKEEL shape_excepttashkeel_near)\n");
+ }
+}
+
+static void
+doLOGICALArabicDeShapingTest(void) {
+ static const UChar
+ source[]={
+ 0x0020,0x0020,0x0020,0xFE8D,0xFEF5,0x0020,0xFEE5,0x0020,0xFE8D,0xFEF7,0x0020,
+ 0xFED7,0xFEFC,0x0020,0xFEE1,0x0020,0xFE8D,0xFEDF,0xFECC,0xFEAE,0xFE91,0xFEF4,
+ 0xFE94,0x0020,0xFE8D,0xFEDF,0xFEA4,0xFEAE,0xFE93,0x0020,0x0020,0x0020,0x0020
+ }, unshape_near[]={
+ 0x20,0x20,0x20,0x627,0x644,0x622,0x646,0x20,0x627,0x644,0x623,0x642,0x644,0x627,
+ 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
+ 0x629,0x20,0x20,0x20,0x20
+ }, unshape_at_end[]={
+ 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
+ 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
+ 0x644,0x62d,0x631,0x629,0x20
+ }, unshape_at_begin[]={
+ 0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,0x644,0x627,0x20,
+ 0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,0x644,0x62d,0x631,
+ 0x629,0x20,0x20,0x20,0x20
+ }, unshape_grow_shrink[]={
+ 0x20,0x20,0x20,0x627,0x644,0x622,0x20,0x646,0x20,0x627,0x644,0x623,0x20,0x642,
+ 0x644,0x627,0x20,0x645,0x20,0x627,0x644,0x639,0x631,0x628,0x64a,0x629,0x20,0x627,
+ 0x644,0x62d,0x631,0x629,0x20,0x20,0x20,0x20
+ };
+
+ UChar dest[36];
+ UErrorCode errorCode;
+ int32_t length;
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
+ U_SHAPE_TEXT_DIRECTION_LOGICAL,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_near) || memcmp(dest, unshape_near, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(unshape_near)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_END|
+ U_SHAPE_TEXT_DIRECTION_LOGICAL,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_end) || memcmp(dest, unshape_at_end, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(unshape_at_end)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_FIXED_SPACES_AT_BEGINNING|
+ U_SHAPE_TEXT_DIRECTION_LOGICAL,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(unshape_at_begin) || memcmp(dest, unshape_at_begin, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(unshape_at_begin)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(source, LENGTHOF(source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_UNSHAPE|U_SHAPE_LENGTH_GROW_SHRINK|
+ U_SHAPE_TEXT_DIRECTION_LOGICAL,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || memcmp(dest, unshape_grow_shrink, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(unshape_grow_shrink)\n");
+ }
+
+}
+
+static void
+doArabicShapingTestForBug5421(void) {
+ static const UChar
+ persian_letters_source[]={
+ 0x0020, 0x0698, 0x067E, 0x0686, 0x06AF, 0x0020
+ }, persian_letters[]={
+ 0x0020, 0xFB8B, 0xFB59, 0xFB7D, 0xFB94, 0x0020
+ }, tashkeel_aggregation_source[]={
+ 0x0020, 0x0628, 0x0651, 0x064E, 0x062A, 0x0631, 0x0645, 0x0020,
+ 0x0628, 0x064E, 0x0651, 0x062A, 0x0631, 0x0645, 0x0020
+ }, tashkeel_aggregation[]={
+ 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3,
+ 0x0020, 0xFE90, 0xFC60, 0xFE97, 0xFEAE, 0xFEE3, 0x0020
+ }, untouched_presentation_source[]={
+ 0x0020 ,0x0627, 0xfe90,0x0020
+ }, untouched_presentation[]={
+ 0x0020,0xfe8D, 0xfe90,0x0020
+ }, untouched_presentation_r_source[]={
+ 0x0020 ,0xfe90, 0x0627, 0x0020
+ }, untouched_presentation_r[]={
+ 0x0020, 0xfe90,0xfe8D,0x0020
+ };
+
+ UChar dest[38];
+ UErrorCode errorCode;
+ int32_t length;
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(persian_letters_source, LENGTHOF(persian_letters_source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(persian_letters) || memcmp(dest, persian_letters, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(persian_letters)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(tashkeel_aggregation_source, LENGTHOF(tashkeel_aggregation_source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_AGGREGATE_TASHKEEL|U_SHAPE_PRESERVE_PRESENTATION|
+ U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(tashkeel_aggregation) || memcmp(dest, tashkeel_aggregation, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(tashkeel_aggregation)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(untouched_presentation_source, LENGTHOF(untouched_presentation_source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_PRESERVE_PRESENTATION|
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_VISUAL_LTR,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation) || memcmp(dest, untouched_presentation, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(untouched_presentation)\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ length=u_shapeArabic(untouched_presentation_r_source, LENGTHOF(untouched_presentation_r_source),
+ dest, LENGTHOF(dest),
+ U_SHAPE_PRESERVE_PRESENTATION|
+ U_SHAPE_LETTERS_SHAPE|U_SHAPE_TEXT_DIRECTION_LOGICAL,
+ &errorCode);
+
+ if(U_FAILURE(errorCode) || length!=LENGTHOF(untouched_presentation_r) || memcmp(dest, untouched_presentation_r, length*U_SIZEOF_UCHAR)!=0) {
+ log_err("failure in u_shapeArabic(untouched_presentation_r)\n");
+ }
+}
+
+/* helpers ------------------------------------------------------------------ */
+
+static void initCharFromDirProps(void) {
+ static const UVersionInfo ucd401={ 4, 0, 1, 0 };
+ static UVersionInfo ucdVersion={ 0, 0, 0, 0 };
+
+ /* lazy initialization */
+ if(ucdVersion[0]>0) {
+ return;
+ }
+
+ u_getUnicodeVersion(ucdVersion);
+ if(memcmp(ucdVersion, ucd401, sizeof(UVersionInfo))>=0) {
+ /* Unicode 4.0.1 changes bidi classes for +-/ */
+ charFromDirProp[U_EUROPEAN_NUMBER_SEPARATOR]=0x2b; /* change ES character from / to + */
+ }
+}
+
+/* return a string with characters according to the desired directional properties */
+static UChar *
+getStringFromDirProps(const uint8_t *dirProps, int32_t length, UChar *buffer) {
+ int32_t i;
+
+ initCharFromDirProps();
+
+ /* this part would have to be modified for UTF-x */
+ for(i=0; i<length; ++i) {
+ buffer[i]=charFromDirProp[dirProps[i]];
+ }
+ buffer[length]=0;
+ return buffer;
+}
+
+static void printUnicode(const UChar *s, int32_t length, const UBiDiLevel *levels) {
+ int32_t i;
+
+ log_verbose("{ ");
+ for(i=0; i<length; ++i) {
+ if(levels!=NULL) {
+ log_verbose("%4x.%u ", s[i], levels[i]);
+ } else {
+ log_verbose("%4x ", s[i]);
+ }
+ }
+ log_verbose(" }");
+}
+
+/* new BIDI API */
+
+/* Reordering Mode BiDi --------------------------------------------------------- */
+
+static const UBiDiLevel paraLevels[] = { UBIDI_LTR, UBIDI_RTL };
+
+static UBool
+assertSuccessful(const char* message, UErrorCode* rc) {
+ if (rc != NULL && U_FAILURE(*rc)) {
+ log_err("%s() failed with error %s.\n", message, myErrorName(*rc));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static UBool
+assertStringsEqual(const char* expected, const char* actual, const char* src,
+ const char* mode, const char* option, UBiDi* pBiDi) {
+ if (uprv_strcmp(expected, actual)) {
+ char formatChars[MAXLEN];
+ log_err("\nActual and expected output mismatch.\n"
+ "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %d %s\n%20s %u\n%20s %d %s\n",
+ "Input:", src,
+ "Actual output:", actual,
+ "Expected output:", expected,
+ "Levels:", formatLevels(pBiDi, formatChars),
+ "Reordering mode:", ubidi_getReorderingMode(pBiDi), mode,
+ "Paragraph level:", ubidi_getParaLevel(pBiDi),
+ "Reordering option:", ubidi_getReorderingOptions(pBiDi), option);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static UBiDi*
+getBiDiObject(void) {
+ UBiDi* pBiDi = ubidi_open();
+ if (pBiDi == NULL) {
+ log_err("Unable to allocate a UBiDi object. Tests are skipped.\n");
+ }
+ return pBiDi;
+}
+
+#define MAKE_ITEMS(val) val, #val
+
+static const struct {
+ UBiDiReorderingMode value;
+ const char* description;
+}
+modes[] = {
+ { MAKE_ITEMS(UBIDI_REORDER_GROUP_NUMBERS_WITH_R) },
+ { MAKE_ITEMS(UBIDI_REORDER_INVERSE_LIKE_DIRECT) },
+ { MAKE_ITEMS(UBIDI_REORDER_NUMBERS_SPECIAL) },
+ { MAKE_ITEMS(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) },
+ { MAKE_ITEMS(UBIDI_REORDER_INVERSE_NUMBERS_AS_L) }
+};
+static const struct {
+ uint32_t value;
+ const char* description;
+}
+options[] = {
+ { MAKE_ITEMS(UBIDI_OPTION_INSERT_MARKS) },
+ { MAKE_ITEMS(0) }
+};
+
+#define TC_COUNT LENGTHOF(textIn)
+#define MODES_COUNT LENGTHOF(modes)
+#define OPTIONS_COUNT LENGTHOF(options)
+#define LEVELS_COUNT LENGTHOF(paraLevels)
+
+static const char* const textIn[] = {
+/* (0) 123 */
+ "123",
+/* (1) .123->4.5 */
+ ".123->4.5",
+/* (2) 678 */
+ "678",
+/* (3) .678->8.9 */
+ ".678->8.9",
+/* (4) JIH1.2,3MLK */
+ "JIH1.2,3MLK",
+/* (5) FE.>12-> */
+ "FE.>12->",
+/* (6) JIH.>12->a */
+ "JIH.>12->a",
+/* (7) CBA.>67->89=a */
+ "CBA.>67->89=a",
+/* (8) CBA.123->xyz */
+ "CBA.123->xyz",
+/* (9) .>12->xyz */
+ ".>12->xyz",
+/* (10) a.>67->xyz */
+ "a.>67->xyz",
+/* (11) 123JIH */
+ "123JIH",
+/* (12) 123 JIH */
+ "123 JIH"
+};
+
+static const char* const textOut[] = {
+/* TC 0: 123 */
+ "123", /* (0) */
+/* TC 1: .123->4.5 */
+ ".123->4.5", /* (1) */
+ "4.5<-123.", /* (2) */
+/* TC 2: 678 */
+ "678", /* (3) */
+/* TC 3: .678->8.9 */
+ ".8.9<-678", /* (4) */
+ "8.9<-678.", /* (5) */
+ ".678->8.9", /* (6) */
+/* TC 4: MLK1.2,3JIH */
+ "KLM1.2,3HIJ", /* (7) */
+/* TC 5: FE.>12-> */
+ "12<.EF->", /* (8) */
+ "<-12<.EF", /* (9) */
+ "EF.>@12->", /* (10) */
+/* TC 6: JIH.>12->a */
+ "12<.HIJ->a", /* (11) */
+ "a<-12<.HIJ", /* (12) */
+ "HIJ.>@12->a", /* (13) */
+ "a&<-12<.HIJ", /* (14) */
+/* TC 7: CBA.>67->89=a */
+ "ABC.>@67->89=a", /* (15) */
+ "a=89<-67<.ABC", /* (16) */
+ "a&=89<-67<.ABC", /* (17) */
+ "89<-67<.ABC=a", /* (18) */
+/* TC 8: CBA.123->xyz */
+ "123.ABC->xyz", /* (19) */
+ "xyz<-123.ABC", /* (20) */
+ "ABC.@123->xyz", /* (21) */
+ "xyz&<-123.ABC", /* (22) */
+/* TC 9: .>12->xyz */
+ ".>12->xyz", /* (23) */
+ "xyz<-12<.", /* (24) */
+ "xyz&<-12<.", /* (25) */
+/* TC 10: a.>67->xyz */
+ "a.>67->xyz", /* (26) */
+ "a.>@67@->xyz", /* (27) */
+ "xyz<-67<.a", /* (28) */
+/* TC 11: 123JIH */
+ "123HIJ", /* (29) */
+ "HIJ123", /* (30) */
+/* TC 12: 123 JIH */
+ "123 HIJ", /* (31) */
+ "HIJ 123", /* (32) */
+};
+
+#define NO UBIDI_MAP_NOWHERE
+#define MAX_MAP_LENGTH 20
+
+static const int32_t forwardMap[][MAX_MAP_LENGTH] = {
+/* TC 0: 123 */
+ { 0, 1, 2 }, /* (0) */
+/* TC 1: .123->4.5 */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
+ { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (2) */
+/* TC 2: 678 */
+ { 0, 1, 2 }, /* (3) */
+/* TC 3: .678->8.9 */
+ { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
+ { 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (5) */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
+/* TC 4: MLK1.2,3JIH */
+ { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
+/* TC 5: FE.>12-> */
+ { 5, 4, 3, 2, 0, 1, 6, 7 }, /* (8) */
+ { 7, 6, 5, 4, 2, 3, 1, 0 }, /* (9) */
+ { 1, 0, 2, 3, 5, 6, 7, 8 }, /* (10) */
+/* TC 6: JIH.>12->a */
+ { 6, 5, 4, 3, 2, 0, 1, 7, 8, 9 }, /* (11) */
+ { 9, 8, 7, 6, 5, 3, 4, 2, 1, 0 }, /* (12) */
+ { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10 }, /* (13) */
+ { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0 }, /* (14) */
+/* TC 7: CBA.>67->89=a */
+ { 2, 1, 0, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13 }, /* (15) */
+ { 12, 11, 10, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0 }, /* (16) */
+ { 13, 12, 11, 10, 9, 7, 8, 6, 5, 3, 4, 2, 0 }, /* (17) */
+ { 10, 9, 8, 7, 6, 4, 5, 3, 2, 0, 1, 11, 12 }, /* (18) */
+/* TC 8: CBA.123->xyz */
+ { 6, 5, 4, 3, 0, 1, 2, 7, 8, 9, 10, 11 }, /* (19) */
+ { 11, 10, 9, 8, 5, 6, 7, 4, 3, 0, 1, 2 }, /* (20) */
+ { 2, 1, 0, 3, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (21) */
+ { 12, 11, 10, 9, 6, 7, 8, 5, 4, 0, 1, 2 }, /* (22) */
+/* TC 9: .>12->xyz */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
+ { 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (24) */
+ { 9, 8, 6, 7, 5, 4, 0, 1, 2 }, /* (25) */
+/* TC 10: a.>67->xyz */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
+ { 0, 1, 2, 4, 5, 7, 8, 9, 10, 11 }, /* (27) */
+ { 9, 8, 7, 5, 6, 4, 3, 0, 1, 2 }, /* (28) */
+/* TC 11: 123JIH */
+ { 0, 1, 2, 5, 4, 3 }, /* (29) */
+ { 3, 4, 5, 2, 1, 0 }, /* (30) */
+/* TC 12: 123 JIH */
+ { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
+ { 4, 5, 6, 3, 2, 1, 0 }, /* (32) */
+};
+
+static const int32_t inverseMap[][MAX_MAP_LENGTH] = {
+/* TC 0: 123 */
+ { 0, 1, 2 }, /* (0) */
+/* TC 1: .123->4.5 */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (1) */
+ { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (2) */
+/* TC 2: 678 */
+ { 0, 1, 2 }, /* (3) */
+/* TC 3: .678->8.9 */
+ { 0, 6, 7, 8, 5, 4, 1, 2, 3 }, /* (4) */
+ { 6, 7, 8, 5, 4, 1, 2, 3, 0 }, /* (5) */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (6) */
+/* TC 4: MLK1.2,3JIH */
+ { 10, 9, 8, 3, 4, 5, 6, 7, 2, 1, 0 }, /* (7) */
+/* TC 5: FE.>12-> */
+ { 4, 5, 3, 2, 1, 0, 6, 7 }, /* (8) */
+ { 7, 6, 4, 5, 3, 2, 1, 0 }, /* (9) */
+ { 1, 0, 2, 3, NO, 4, 5, 6, 7 }, /* (10) */
+/* TC 6: JIH.>12->a */
+ { 5, 6, 4, 3, 2, 1, 0, 7, 8, 9 }, /* (11) */
+ { 9, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (12) */
+ { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (13) */
+ { 9, NO, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (14) */
+/* TC 7: CBA.>67->89=a */
+ { 2, 1, 0, 3, 4, NO, 5, 6, 7, 8, 9, 10, 11, 12 }, /* (15) */
+ { 12, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (16) */
+ { 12, NO, 11, 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0 }, /* (17) */
+ { 9, 10, 8, 7, 5, 6, 4, 3, 2, 1, 0, 11, 12 }, /* (18) */
+/* TC 8: CBA.123->xyz */
+ { 4, 5, 6, 3, 2, 1, 0, 7, 8, 9, 10, 11 }, /* (19) */
+ { 9, 10, 11, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (20) */
+ { 2, 1, 0, 3, NO, 4, 5, 6, 7, 8, 9, 10, 11 }, /* (21) */
+ { 9, 10, 11, NO, 8, 7, 4, 5, 6, 3, 2, 1, 0 }, /* (22) */
+/* TC 9: .>12->xyz */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, /* (23) */
+ { 6, 7, 8, 5, 4, 2, 3, 1, 0 }, /* (24) */
+ { 6, 7, 8, NO, 5, 4, 2, 3, 1, 0 }, /* (25) */
+/* TC 10: a.>67->xyz */
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* (26) */
+ { 0, 1, 2, NO, 3, 4, NO, 5, 6, 7, 8, 9 }, /* (27) */
+ { 7, 8, 9, 6, 5, 3, 4, 2, 1, 0 }, /* (28) */
+/* TC 11: 123JIH */
+ { 0, 1, 2, 5, 4, 3 }, /* (29) */
+ { 5, 4, 3, 0, 1, 2 }, /* (30) */
+/* TC 12: 123 JIH */
+ { 0, 1, 2, 3, 6, 5, 4 }, /* (31) */
+ { 6, 5, 4, 3, 0, 1, 2 }, /* (32) */
+};
+
+static const char outIndices[TC_COUNT][MODES_COUNT - 1][OPTIONS_COUNT]
+ [LEVELS_COUNT] = {
+ { /* TC 0: 123 */
+ {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 0, 0}, { 0, 0}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 0, 0}, { 0, 0}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 1: .123->4.5 */
+ {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 2}, { 1, 2}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 2}, { 1, 2}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 2: 678 */
+ {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 3, 3}, { 3, 3}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 3, 3}, { 3, 3}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 3: .678->8.9 */
+ {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 4, 5}, { 4, 5}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 6, 5}, { 6, 5}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 6, 5}, { 6, 5}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 4: MLK1.2,3JIH */
+ {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 7, 7}, { 7, 7}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 7, 7}, { 7, 7}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 5: FE.>12-> */
+ {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{10, 9}, { 8, 9}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 8, 9}, { 8, 9}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{10, 9}, { 8, 9}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 6: JIH.>12->a */
+ {{11, 12}, {11, 12}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{13, 14}, {11, 12}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{11, 12}, {11, 12}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{13, 14}, {11, 12}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 7: CBA.>67->89=a */
+ {{18, 16}, {18, 16}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{18, 17}, {18, 16}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{18, 16}, {18, 16}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{15, 17}, {18, 16}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 8: CBA.>124->xyz */
+ {{19, 20}, {19, 20}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{21, 22}, {19, 20}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{19, 20}, {19, 20}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{21, 22}, {19, 20}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 9: .>12->xyz */
+ {{23, 24}, {23, 24}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{23, 25}, {23, 24}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{23, 24}, {23, 24}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{23, 25}, {23, 24}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 10: a.>67->xyz */
+ {{26, 26}, {26, 26}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{26, 27}, {26, 28}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{26, 28}, {26, 28}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{26, 27}, {26, 28}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 11: 124JIH */
+ {{30, 30}, {30, 30}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{29, 30}, {29, 30}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{30, 30}, {30, 30}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{30, 30}, {30, 30}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ },
+ { /* TC 12: 124 JIH */
+ {{32, 32}, {32, 32}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{31, 32}, {31, 32}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{31, 32}, {31, 32}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{31, 32}, {31, 32}} /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ }
+};
+
+static UBool
+assertRoundTrip(UBiDi *pBiDi, int32_t tc, int32_t outIndex, const char *srcChars,
+ const char *destChars, const UChar *dest, int32_t destLen,
+ int mode, int option, UBiDiLevel level) {
+
+ static const char roundtrip[TC_COUNT][MODES_COUNT][OPTIONS_COUNT]
+ [LEVELS_COUNT] = {
+ { /* TC 0: 123 */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 1: .123->4.5 */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 2: 678 */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 3: .678->8.9 */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 4: MLK1.2,3JIH */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 5: FE.>12-> */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 6: JIH.>12->a */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 7: CBA.>67->89=a */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 0, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 0, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 8: CBA.>123->xyz */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 0, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 9: .>12->xyz */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 0}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 10: a.>67->xyz */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 0}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 11: 123JIH */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ },
+ { /* TC 12: 123 JIH */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_GROUP_NUMBERS_WITH_R */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_LIKE_DIRECT */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}}, /* UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL */
+ {{ 1, 1}, { 1, 1}} /* UBIDI_REORDER_INVERSE_NUMBERS_AS_L */
+ }
+ };
+
+ #define SET_ROUND_TRIP_MODE(mode) \
+ ubidi_setReorderingMode(pBiDi, mode); \
+ desc = #mode; \
+ break;
+
+ UErrorCode rc = U_ZERO_ERROR;
+ UChar dest2[MAXLEN];
+ int32_t destLen2;
+ const char* desc;
+ char destChars2[MAXLEN];
+ char destChars3[MAXLEN];
+
+ switch (modes[mode].value) {
+ case UBIDI_REORDER_NUMBERS_SPECIAL:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL)
+ case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_GROUP_NUMBERS_WITH_R)
+ case UBIDI_REORDER_RUNS_ONLY:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_RUNS_ONLY)
+ case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
+ case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_DEFAULT)
+ case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_NUMBERS_SPECIAL)
+ default:
+ SET_ROUND_TRIP_MODE(UBIDI_REORDER_INVERSE_LIKE_DIRECT)
+ }
+ ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
+
+ ubidi_setPara(pBiDi, dest, destLen, level, NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+ *dest2 = 0;
+ destLen2 = ubidi_writeReordered(pBiDi, dest2, MAXLEN, UBIDI_DO_MIRRORING,
+ &rc);
+ assertSuccessful("ubidi_writeReordered", &rc);
+
+ u16ToPseudo(destLen, dest, destChars3);
+ u16ToPseudo(destLen2, dest2, destChars2);
+ checkWhatYouCan(pBiDi, destChars3, destChars2);
+ if (strcmp(srcChars, destChars2)) {
+ if (roundtrip[tc][mode][option][level]) {
+ log_err("\nRound trip failed for case=%d mode=%d option=%d.\n"
+ "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
+ "\n%20s %u\n", tc, mode, option,
+ "Original text:", srcChars,
+ "Round-tripped text:", destChars2,
+ "Intermediate text:", destChars3,
+ "Reordering mode:", modes[mode].description,
+ "Reordering option:", options[option].description,
+ "Paragraph level:", level);
+ }
+ else {
+ log_verbose("\nExpected round trip failure for case=%d mode=%d option=%d.\n"
+ "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %s"
+ "\n%20s %u\n", tc, mode, option,
+ "Original text:", srcChars,
+ "Round-tripped text:", destChars2,
+ "Intermediate text:", destChars3,
+ "Reordering mode:", modes[mode].description,
+ "Reordering option:", options[option].description,
+ "Paragraph level:", level);
+ }
+ return FALSE;
+ }
+ if (!checkResultLength(pBiDi, destChars, destChars2, destLen2,
+ desc, "UBIDI_OPTION_REMOVE_CONTROLS", level)) {
+ return FALSE;
+ }
+ if (outIndex > -1 && !checkMaps(pBiDi, outIndex, srcChars, destChars,
+ desc, "UBIDI_OPTION_REMOVE_CONTROLS",
+ level, FALSE)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static UBool
+checkResultLength(UBiDi *pBiDi, const char *srcChars, const char *destChars,
+ int32_t destLen, const char* mode,
+ const char* option, UBiDiLevel level) {
+ int32_t actualLen;
+ if (strcmp(mode, "UBIDI_REORDER_INVERSE_NUMBERS_AS_L") == 0)
+ actualLen = strlen(destChars);
+ else
+ actualLen = ubidi_getResultLength(pBiDi);
+ if (actualLen != destLen) {
+ log_err("\nubidi_getResultLength failed.\n%20s %7d\n%20s %7d\n"
+ "%20s %s\n%20s %s\n%20s %s\n%20s %s\n%20s %u\n",
+ "Expected:", destLen, "Actual:", actualLen,
+ "Input:", srcChars, "Output:", destChars,
+ "Reordering mode:", mode, "Reordering option:", option,
+ "Paragraph level:", level);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+testReorderRunsOnly(void) {
+ static const struct {
+ const char* textIn;
+ const char* textOut[2][2];
+ const char noroundtrip[2];
+ } testCases[] = {
+ {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*0*/
+ {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
+ {"abcGHI", {{"GHIabc", "GHIabc"}, {"GHIabc", "GHIabc"}}, {0, 0}}, /*1*/
+ {"a.>67->", {{"<-67<.a", "<-67<.a"}, {"<-67<.a", "<-67<.a"}}, {0, 0}}, /*2*/
+ {"-=%$123/ *", {{"* /%$123=-", "* /%$123=-"}, /*3*/
+ {"* /%$123=-", "* /%$123=-"}}, {0, 0}},
+ {"abc->12..>JKL", {{"JKL<..12<-abc", "JKL<..abc->12"}, /*4*/
+ {"JKL<..12<-abc", "JKL<..abc->12"}}, {0, 0}},
+ {"JKL->12..>abc", {{"abc<..JKL->12", "abc<..12<-JKL"}, /*5*/
+ {"abc<..JKL->12", "abc<..12<-JKL"}}, {0, 0}},
+ {"123->abc", {{"abc<-123", "abc<-123"}, /*6*/
+ {"abc&<-123", "abc<-123"}}, {1, 0}},
+ {"123->JKL", {{"JKL<-123", "123->JKL"}, /*7*/
+ {"JKL<-123", "JKL<-@123"}}, {0, 1}},
+ {"*>12.>34->JKL", {{"JKL<-34<.12<*", "12.>34->JKL<*"}, /*8*/
+ {"JKL<-34<.12<*", "JKL<-@34<.12<*"}}, {0, 1}},
+ {"*>67.>89->JKL", {{"67.>89->JKL<*", "67.>89->JKL<*"}, /*9*/
+ {"67.>89->JKL<*", "67.>89->JKL<*"}}, {0, 0}},
+ {"* /abc-=$%123", {{"$%123=-abc/ *", "abc-=$%123/ *"}, /*10*/
+ {"$%123=-abc/ *", "abc-=$%123/ *"}}, {0, 0}},
+ {"* /$%def-=123", {{"123=-def%$/ *", "def-=123%$/ *"}, /*11*/
+ {"123=-def%$/ *", "def-=123%$/ *"}}, {0, 0}},
+ {"-=GHI* /123%$", {{"GHI* /123%$=-", "123%$/ *GHI=-"}, /*12*/
+ {"GHI* /123%$=-", "123%$/ *GHI=-"}}, {0, 0}},
+ {"-=%$JKL* /123", {{"JKL* /%$123=-", "123/ *JKL$%=-"}, /*13*/
+ {"JKL* /%$123=-", "123/ *JKL$%=-"}}, {0, 0}},
+ {"ab =#CD *?450", {{"CD *?450#= ab", "450?* CD#= ab"}, /*14*/
+ {"CD *?450#= ab", "450?* CD#= ab"}}, {0, 0}},
+ {"ab 234 896 de", {{"de 896 ab 234", "de 896 ab 234"}, /*15*/
+ {"ab 234 @896@ de", "de 896 ab 234"}}, {0, 0}},
+ {"abc-=%$LMN* /123", {{"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}, /*16*/
+ {"LMN* /%$123=-abc", "123/ *LMN$%=-abc"}}, {0, 0}},
+ {"123->JKL&MN&P", {{"JKLMNP<-123", "123->JKLMNP"}, /*17*/
+ {"JKLMNP<-123", "JKLMNP<-@123"}}, {0, 1}},
+ {"123", {{"123", "123"}, /* just one run */ /*18*/
+ {"123", "123"}}, {0, 0}}
+ };
+ UBiDi *pBiDi = getBiDiObject();
+ UBiDi *pL2VBiDi = getBiDiObject();
+ UChar src[MAXLEN], dest[MAXLEN], visual1[MAXLEN], visual2[MAXLEN];
+ char destChars[MAXLEN], vis1Chars[MAXLEN], vis2Chars[MAXLEN];
+ int32_t srcLen, destLen, vis1Len, vis2Len, option, i, j, nCases, paras;
+ UErrorCode rc = U_ZERO_ERROR;
+ UBiDiLevel level;
+
+ log_verbose("\nEntering TestReorderRunsOnly\n\n");
+
+ if(!pL2VBiDi) {
+ ubidi_close(pBiDi); /* in case this one was allocated */
+ return;
+ }
+ ubidi_setReorderingMode(pBiDi, UBIDI_REORDER_RUNS_ONLY);
+ ubidi_setReorderingOptions(pL2VBiDi, UBIDI_OPTION_REMOVE_CONTROLS);
+
+ for (option = 0; option < 2; option++) {
+ ubidi_setReorderingOptions(pBiDi, option==0 ? UBIDI_OPTION_REMOVE_CONTROLS
+ : UBIDI_OPTION_INSERT_MARKS);
+ for (i = 0, nCases = LENGTHOF(testCases); i < nCases; i++) {
+ srcLen = strlen(testCases[i].textIn);
+ pseudoToU16(srcLen, testCases[i].textIn, src);
+ for(j = 0; j < 2; j++) {
+ log_verbose("Now doing test for option %d, case %d, level %d\n",
+ i, option, j);
+ level = paraLevels[j];
+ ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+ *dest = 0;
+ destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN, UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered", &rc);
+ u16ToPseudo(destLen, dest, destChars);
+ checkWhatYouCan(pBiDi, testCases[i].textIn, destChars);
+ assertStringsEqual(testCases[i].textOut[option][level], destChars,
+ testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY",
+ option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
+ pBiDi);
+
+ if((option==0) && testCases[i].noroundtrip[level]) {
+ continue;
+ }
+ ubidi_setPara(pL2VBiDi, src, srcLen, level, NULL, &rc);
+ assertSuccessful("ubidi_setPara1", &rc);
+ *visual1 = 0;
+ vis1Len = ubidi_writeReordered(pL2VBiDi, visual1, MAXLEN, UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered1", &rc);
+ u16ToPseudo(vis1Len, visual1, vis1Chars);
+ checkWhatYouCan(pL2VBiDi, testCases[i].textIn, vis1Chars);
+ ubidi_setPara(pL2VBiDi, dest, destLen, level^1, NULL, &rc);
+ assertSuccessful("ubidi_setPara2", &rc);
+ *visual2 = 0;
+ vis2Len = ubidi_writeReordered(pL2VBiDi, visual2, MAXLEN, UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered2", &rc);
+ u16ToPseudo(vis2Len, visual2, vis2Chars);
+ checkWhatYouCan(pL2VBiDi, destChars, vis2Chars);
+ assertStringsEqual(vis1Chars, vis2Chars,
+ testCases[i].textIn, "UBIDI_REORDER_RUNS_ONLY (2)",
+ option==0 ? "0" : "UBIDI_OPTION_INSERT_MARKS",
+ pBiDi);
+ }
+ }
+ }
+
+ /* test with null or empty text */
+ ubidi_setPara(pBiDi, src, 0, UBIDI_LTR, NULL, &rc);
+ assertSuccessful("ubidi_setPara3", &rc);
+ paras = ubidi_countParagraphs(pBiDi);
+ if (paras != 0) {
+ log_err("\nInvalid number of paras (should be 0): %d\n", paras);
+ }
+
+ ubidi_close(pBiDi);
+ ubidi_close(pL2VBiDi);
+
+ log_verbose("\nExiting TestReorderRunsOnly\n\n");
+}
+
+static void
+testReorderingMode(void) {
+
+ UChar src[MAXLEN], dest[MAXLEN];
+ char destChars[MAXLEN];
+ UBiDi *pBiDi = NULL, *pBiDi2 = NULL, *pBiDi3 = NULL;
+ UErrorCode rc;
+ int tc, mode, option, level;
+ uint32_t optionValue, optionBack;
+ UBiDiReorderingMode modeValue, modeBack;
+ int32_t srcLen, destLen, index;
+ const char *expectedChars;
+ UBool testOK = TRUE;
+
+ log_verbose("\nEntering TestReorderingMode\n\n");
+
+ pBiDi = getBiDiObject();
+ pBiDi2 = getBiDiObject();
+ pBiDi3 = getBiDiObject();
+ if(!pBiDi3) {
+ ubidi_close(pBiDi); /* in case this one was allocated */
+ ubidi_close(pBiDi2); /* in case this one was allocated */
+ return;
+ }
+
+ ubidi_setInverse(pBiDi2, TRUE);
+
+ for (tc = 0; tc < TC_COUNT; tc++) {
+ const char *srcChars = textIn[tc];
+ srcLen = strlen(srcChars);
+ pseudoToU16(srcLen, srcChars, src);
+
+ for (mode = 0; mode < MODES_COUNT; mode++) {
+ modeValue = modes[mode].value;
+ ubidi_setReorderingMode(pBiDi, modeValue);
+ modeBack = ubidi_getReorderingMode(pBiDi);
+ if (modeValue != modeBack) {
+ log_err("Error while setting reordering mode to %d, returned %d\n",
+ modeValue, modeBack);
+ }
+
+ for (option = 0; option < OPTIONS_COUNT; option++) {
+ optionValue = options[option].value;
+ ubidi_setReorderingOptions(pBiDi, optionValue);
+ optionBack = ubidi_getReorderingOptions(pBiDi);
+ if (optionValue != optionBack) {
+ log_err("Error while setting reordering option to %d, returned %d\n",
+ optionValue, optionBack);
+ }
+
+ for (level = 0; level < LEVELS_COUNT; level++) {
+ log_verbose("starting test %d mode=%d option=%d level=%d\n",
+ tc, modes[mode].value, options[option].value, level);
+ rc = U_ZERO_ERROR;
+ ubidi_setPara(pBiDi, src, srcLen, paraLevels[level], NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+
+ *dest = 0;
+ destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
+ UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered", &rc);
+ u16ToPseudo(destLen, dest, destChars);
+ if (!((modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
+ (options[option].value == UBIDI_OPTION_INSERT_MARKS))) {
+ checkWhatYouCan(pBiDi, srcChars, destChars);
+ }
+
+ if (modes[mode].value == UBIDI_REORDER_INVERSE_NUMBERS_AS_L) {
+ index = -1;
+ expectedChars = inverseBasic(pBiDi2, srcChars, srcLen,
+ options[option].value, paraLevels[level], destChars);
+ }
+ else {
+ index = outIndices[tc][mode][option][level];
+ expectedChars = textOut[index];
+ }
+ if (!assertStringsEqual(expectedChars, destChars, srcChars,
+ modes[mode].description,
+ options[option].description,
+ pBiDi)) {
+ testOK = FALSE;
+ }
+ if (options[option].value == UBIDI_OPTION_INSERT_MARKS &&
+ !assertRoundTrip(pBiDi3, tc, index, srcChars,
+ destChars, dest, destLen,
+ mode, option, paraLevels[level])) {
+ testOK = FALSE;
+ }
+ else if (!checkResultLength(pBiDi, srcChars, destChars,
+ destLen, modes[mode].description,
+ options[option].description,
+ paraLevels[level])) {
+ testOK = FALSE;
+ }
+ else if (index > -1 && !checkMaps(pBiDi, index, srcChars,
+ destChars, modes[mode].description,
+ options[option].description, paraLevels[level],
+ TRUE)) {
+ testOK = FALSE;
+ }
+ }
+ }
+ }
+ }
+ if (testOK == TRUE) {
+ log_verbose("\nReordering mode test OK\n");
+ }
+ ubidi_close(pBiDi3);
+ ubidi_close(pBiDi2);
+ ubidi_close(pBiDi);
+
+ log_verbose("\nExiting TestReorderingMode\n\n");
+}
+
+static const char* inverseBasic(UBiDi *pBiDi, const char *srcChars, int32_t srcLen,
+ uint32_t option, UBiDiLevel level, char *result) {
+ UErrorCode rc = U_ZERO_ERROR;
+ int32_t destLen;
+ UChar src[MAXLEN], dest2[MAXLEN];
+
+ if (pBiDi == NULL || src == NULL) {
+ return NULL;
+ }
+ ubidi_setReorderingOptions(pBiDi, option);
+ pseudoToU16(srcLen, srcChars, src);
+ ubidi_setPara(pBiDi, src, srcLen, level, NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+
+ *dest2 = 0;
+ destLen = ubidi_writeReordered(pBiDi, dest2, MAXLEN,
+ UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered", &rc);
+ u16ToPseudo(destLen, dest2, result);
+ if (!(option == UBIDI_OPTION_INSERT_MARKS)) {
+ checkWhatYouCan(pBiDi, srcChars, result);
+ }
+ return result;
+}
+
+#define NULL_CHAR '\0'
+
+static void
+testStreaming(void) {
+#define MAXPORTIONS 10
+
+ static const struct {
+ const char* textIn;
+ short int chunk;
+ short int nPortions[2];
+ char portionLens[2][MAXPORTIONS];
+ const char* message[2];
+ } testData[] = {
+ { "123\\u000A"
+ "abc45\\u000D"
+ "67890\\u000A"
+ "\\u000D"
+ "02468\\u000D"
+ "ghi",
+ 6, { 6, 6 }, {{ 6, 4, 6, 1, 6, 3}, { 4, 6, 6, 1, 6, 3 }},
+ {"6, 4, 6, 1, 6, 3", "4, 6, 6, 1, 6, 3"}
+ },
+ { "abcd\\u000Afgh\\u000D12345\\u000A456",
+ 6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
+ {"6, 3, 6, 3", "5, 4, 6, 3"}
+ },
+ { "abcd\\u000Afgh\\u000D12345\\u000A45\\u000D",
+ 6, { 4, 4 }, {{ 6, 3, 6, 3 }, { 5, 4, 6, 3 }},
+ {"6, 3, 6, 3", "5, 4, 6, 3"}
+ },
+ { "abcde\\u000Afghi",
+ 10, { 1, 2 }, {{ 10 }, { 6, 4 }},
+ {"10", "6, 4"}
+ }
+ };
+ UChar src[MAXLEN];
+ UBiDi *pBiDi = NULL;
+ UChar *pSrc;
+ UErrorCode rc = U_ZERO_ERROR;
+ int32_t srcLen, processedLen, chunk, len, nPortions;
+ int i, j, levelIndex;
+ UBiDiLevel level;
+ int nTests = LENGTHOF(testData), nLevels = LENGTHOF(paraLevels);
+ UBool mismatch, testOK = TRUE;
+ char processedLenStr[MAXPORTIONS * 5];
+
+ log_verbose("\nEntering TestStreaming\n\n");
+
+ pBiDi = getBiDiObject();
+
+ ubidi_orderParagraphsLTR(pBiDi, TRUE);
+
+ for (levelIndex = 0; levelIndex < nLevels; levelIndex++) {
+ for (i = 0; i < nTests; i++) {
+ srcLen = u_unescape(testData[i].textIn, src, MAXLEN);
+ chunk = testData[i].chunk;
+ nPortions = testData[i].nPortions[levelIndex];
+ level = paraLevels[levelIndex];
+ *processedLenStr = NULL_CHAR;
+ log_verbose("Testing level %d, case %d\n", level, i);
+
+ mismatch = FALSE;
+
+ ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
+ for (j = 0, pSrc = src; j < MAXPORTIONS && srcLen > 0; j++) {
+
+ len = chunk < srcLen ? chunk : srcLen;
+ ubidi_setPara(pBiDi, pSrc, len, level, NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+
+ processedLen = ubidi_getProcessedLength(pBiDi);
+ if (processedLen == 0) {
+ ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_DEFAULT);
+ j--;
+ continue;
+ }
+ ubidi_setReorderingOptions(pBiDi, UBIDI_OPTION_STREAMING);
+
+ mismatch = (UBool)(j >= nPortions ||
+ processedLen != testData[i].portionLens[levelIndex][j]);
+
+ sprintf(processedLenStr + j * 4, "%4d", processedLen);
+ srcLen -= processedLen, pSrc += processedLen;
+ }
+
+ if (mismatch || j != nPortions) {
+ testOK = FALSE;
+ log_err("\nProcessed lengths mismatch.\n"
+ "\tParagraph level: %u\n"
+ "\tInput string: %s\n"
+ "\tActually processed portion lengths: { %s }\n"
+ "\tExpected portion lengths : { %s }\n",
+ paraLevels[levelIndex], testData[i].textIn,
+ processedLenStr, testData[i].message[levelIndex]);
+ }
+ }
+ }
+ ubidi_close(pBiDi);
+ if (testOK == TRUE) {
+ log_verbose("\nBiDi streaming test OK\n");
+ }
+ log_verbose("\nExiting TestStreaming\n\n");
+}
+
+U_CDECL_BEGIN
+
+static UCharDirection U_CALLCONV
+overrideBidiClass(const void *context, UChar32 c) {
+
+#define DEF U_BIDI_CLASS_DEFAULT
+
+ static const UCharDirection customClasses[] = {
+ /* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 00-07 */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 08-0F */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 10-17 */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 18-1F */
+ DEF, DEF, DEF, DEF, DEF, DEF, R, DEF, /* 20-27 */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 28-2F */
+ EN, EN, EN, EN, EN, EN, AN, AN, /* 30-37 */
+ AN, AN, DEF, DEF, DEF, DEF, DEF, DEF, /* 38-3F */
+ L, AL, AL, AL, AL, AL, AL, R, /* 40-47 */
+ R, R, R, R, R, R, R, R, /* 48-4F */
+ R, R, R, R, R, R, R, R, /* 50-57 */
+ R, R, R, LRE, DEF, RLE, PDF, S, /* 58-5F */
+ NSM, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 60-67 */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 68-6F */
+ DEF, DEF, DEF, DEF, DEF, DEF, DEF, DEF, /* 70-77 */
+ DEF, DEF, DEF, LRO, B, RLO, BN, DEF /* 78-7F */
+ };
+ static const int nEntries = LENGTHOF(customClasses);
+ const char *dummy = context; /* just to avoid a compiler warning */
+ dummy++;
+
+ return c >= nEntries ? U_BIDI_CLASS_DEFAULT : customClasses[c];
+}
+
+U_CDECL_END
+
+static void verifyCallbackParams(UBiDiClassCallback* fn, const void* context,
+ UBiDiClassCallback* expectedFn,
+ const void* expectedContext,
+ int32_t sizeOfContext) {
+ if (fn != expectedFn) {
+ log_err("Class callback pointer is not set properly.\n");
+ }
+ if (context != expectedContext) {
+ log_err("Class callback context is not set properly.\n");
+ }
+ else if (context != NULL &&
+ memcmp(context, expectedContext, sizeOfContext)) {
+ log_err("Callback context content doesn't match the expected one.\n");
+ }
+}
+
+static void
+testClassOverride(void) {
+ static const char* const textSrc = "JIH.>12->a \\u05D0\\u05D1 6 ABC78";
+ static const char* const textResult = "12<.HIJ->a 78CBA 6 \\u05D1\\u05D0";
+
+ UChar src[MAXLEN], dest[MAXLEN];
+ UErrorCode rc = U_ZERO_ERROR;
+ UBiDi *pBiDi = NULL;
+ UBiDiClassCallback* oldFn = NULL;
+ UBiDiClassCallback* newFn = overrideBidiClass;
+ const void* oldContext = NULL;
+ int32_t srcLen, destLen, textSrcSize = (int32_t)uprv_strlen(textSrc);
+ char* destChars = NULL;
+
+ log_verbose("\nEntering TestClassOverride\n\n");
+
+ pBiDi = getBiDiObject();
+ if(!pBiDi) {
+ return;
+ }
+
+ ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
+ verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
+
+ ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
+ if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
+ ubidi_close(pBiDi);
+ return;
+ }
+ verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0);
+
+ ubidi_getClassCallback(pBiDi, &oldFn, &oldContext);
+ verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
+
+ ubidi_setClassCallback(pBiDi, newFn, textSrc, &oldFn, &oldContext, &rc);
+ if (!assertSuccessful("ubidi_setClassCallback", &rc)) {
+ ubidi_close(pBiDi);
+ return;
+ }
+ verifyCallbackParams(oldFn, oldContext, newFn, textSrc, textSrcSize);
+
+ srcLen = u_unescape(textSrc, src, MAXLEN);
+ ubidi_setPara(pBiDi, src, srcLen, UBIDI_LTR, NULL, &rc);
+ assertSuccessful("ubidi_setPara", &rc);
+
+ destLen = ubidi_writeReordered(pBiDi, dest, MAXLEN,
+ UBIDI_DO_MIRRORING, &rc);
+ assertSuccessful("ubidi_writeReordered", &rc);
+
+ destChars = aescstrdup(dest, destLen);
+ if (uprv_strcmp(textResult, destChars)) {
+ log_err("\nActual and expected output mismatch.\n"
+ "%20s %s\n%20s %s\n%20s %s\n",
+ "Input:", textSrc, "Actual output:", destChars,
+ "Expected output:", textResult);
+ }
+ else {
+ log_verbose("\nClass override test OK\n");
+ }
+ ubidi_close(pBiDi);
+ log_verbose("\nExiting TestClassOverride\n\n");
+}
+
+static char * formatMap(const int32_t * map, int len, char * buffer)
+{
+ int32_t i, k;
+ char c;
+ for (i = 0; i < len; i++) {
+ k = map[i];
+ if (k < 0)
+ c = '-';
+ else if (k >= sizeof(columns))
+ c = '+';
+ else
+ c = columns[k];
+ buffer[i] = c;
+ }
+ buffer[len] = '\0';
+ return buffer;
+}
+
+static UBool
+checkMaps(UBiDi *pBiDi, int32_t stringIndex, const char *src, const char *dest,
+ const char *mode, const char* option, UBiDiLevel level, UBool forward)
+{
+ int32_t actualLogicalMap[MAX_MAP_LENGTH];
+ int32_t actualVisualMap[MAX_MAP_LENGTH];
+ int32_t getIndexMap[MAX_MAP_LENGTH];
+ int32_t i, srcLen, resLen, index;
+ const int32_t *expectedLogicalMap, *expectedVisualMap;
+ UErrorCode rc = U_ZERO_ERROR;
+ UBool testOK = TRUE;
+
+ if (forward) {
+ expectedLogicalMap = forwardMap[stringIndex];
+ expectedVisualMap = inverseMap[stringIndex];
+ }
+ else {
+ expectedLogicalMap = inverseMap[stringIndex];
+ expectedVisualMap = forwardMap[stringIndex];
+ }
+ ubidi_getLogicalMap(pBiDi, actualLogicalMap, &rc);
+ if (!assertSuccessful("ubidi_getLogicalMap", &rc)) {
+ testOK = FALSE;
+ }
+ srcLen = ubidi_getProcessedLength(pBiDi);
+ if (memcmp(expectedLogicalMap, actualLogicalMap, srcLen * sizeof(int32_t))) {
+ char expChars[MAX_MAP_LENGTH];
+ char actChars[MAX_MAP_LENGTH];
+ log_err("\nubidi_getLogicalMap() returns unexpected map for output string "
+ "index %d\n"
+ "source: %s\n"
+ "dest : %s\n"
+ "Scale : %s\n"
+ "ExpMap: %s\n"
+ "Actual: %s\n"
+ "Paragraph level : %d == %d\n"
+ "Reordering mode : %s == %d\n"
+ "Reordering option: %s == %d\n"
+ "Forward flag : %d\n",
+ stringIndex, src, dest, columns,
+ formatMap(expectedLogicalMap, srcLen, expChars),
+ formatMap(actualLogicalMap, srcLen, actChars),
+ level, ubidi_getParaLevel(pBiDi),
+ mode, ubidi_getReorderingMode(pBiDi),
+ option, ubidi_getReorderingOptions(pBiDi),
+ forward
+ );
+ testOK = FALSE;
+ }
+ resLen = ubidi_getResultLength(pBiDi);
+ ubidi_getVisualMap(pBiDi, actualVisualMap, &rc);
+ assertSuccessful("ubidi_getVisualMap", &rc);
+ if (memcmp(expectedVisualMap, actualVisualMap, resLen * sizeof(int32_t))) {
+ char expChars[MAX_MAP_LENGTH];
+ char actChars[MAX_MAP_LENGTH];
+ log_err("\nubidi_getVisualMap() returns unexpected map for output string "
+ "index %d\n"
+ "source: %s\n"
+ "dest : %s\n"
+ "Scale : %s\n"
+ "ExpMap: %s\n"
+ "Actual: %s\n"
+ "Paragraph level : %d == %d\n"
+ "Reordering mode : %s == %d\n"
+ "Reordering option: %s == %d\n"
+ "Forward flag : %d\n",
+ stringIndex, src, dest, columns,
+ formatMap(expectedVisualMap, resLen, expChars),
+ formatMap(actualVisualMap, resLen, actChars),
+ level, ubidi_getParaLevel(pBiDi),
+ mode, ubidi_getReorderingMode(pBiDi),
+ option, ubidi_getReorderingOptions(pBiDi),
+ forward
+ );
+ testOK = FALSE;
+ }
+ for (i = 0; i < srcLen; i++) {
+ index = ubidi_getVisualIndex(pBiDi, i, &rc);
+ assertSuccessful("ubidi_getVisualIndex", &rc);
+ getIndexMap[i] = index;
+ }
+ if (memcmp(actualLogicalMap, getIndexMap, srcLen * sizeof(int32_t))) {
+ char actChars[MAX_MAP_LENGTH];
+ char gotChars[MAX_MAP_LENGTH];
+ log_err("\nMismatch between ubidi_getLogicalMap and ubidi_getVisualIndex for output string "
+ "index %d\n"
+ "source: %s\n"
+ "dest : %s\n"
+ "Scale : %s\n"
+ "ActMap: %s\n"
+ "IdxMap: %s\n"
+ "Paragraph level : %d == %d\n"
+ "Reordering mode : %s == %d\n"
+ "Reordering option: %s == %d\n"
+ "Forward flag : %d\n",
+ stringIndex, src, dest, columns,
+ formatMap(actualLogicalMap, srcLen, actChars),
+ formatMap(getIndexMap, srcLen, gotChars),
+ level, ubidi_getParaLevel(pBiDi),
+ mode, ubidi_getReorderingMode(pBiDi),
+ option, ubidi_getReorderingOptions(pBiDi),
+ forward
+ );
+ testOK = FALSE;
+ }
+ for (i = 0; i < resLen; i++) {
+ index = ubidi_getLogicalIndex(pBiDi, i, &rc);
+ assertSuccessful("ubidi_getLogicalIndex", &rc);
+ getIndexMap[i] = index;
+ }
+ if (memcmp(actualVisualMap, getIndexMap, resLen * sizeof(int32_t))) {
+ char actChars[MAX_MAP_LENGTH];
+ char gotChars[MAX_MAP_LENGTH];
+ log_err("\nMismatch between ubidi_getVisualMap and ubidi_getLogicalIndex for output string "
+ "index %d\n"
+ "source: %s\n"
+ "dest : %s\n"
+ "Scale : %s\n"
+ "ActMap: %s\n"
+ "IdxMap: %s\n"
+ "Paragraph level : %d == %d\n"
+ "Reordering mode : %s == %d\n"
+ "Reordering option: %s == %d\n"
+ "Forward flag : %d\n",
+ stringIndex, src, dest, columns,
+ formatMap(actualVisualMap, resLen, actChars),
+ formatMap(getIndexMap, resLen, gotChars),
+ level, ubidi_getParaLevel(pBiDi),
+ mode, ubidi_getReorderingMode(pBiDi),
+ option, ubidi_getReorderingOptions(pBiDi),
+ forward
+ );
+ testOK = FALSE;
+ }
+ return testOK;
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h
new file mode 100644
index 00000000000..afaffb27d48
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbiditst.h
@@ -0,0 +1,82 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/* file name: cbiditst.h
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 1999sep22
+* created by: Markus W. Scherer
+*/
+
+#ifndef CBIDITST_H
+#define CBIDITST_H
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+#include "unicode/ubidi.h"
+
+#ifdef XP_CPLUSPLUS
+extern "C" {
+#endif
+
+#define MAX_STRING_LENGTH 200
+
+/* length of an array */
+#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
+
+/* Comparing the description of the BiDi algorithm with this implementation
+ is easier with the same names for the BiDi types in the code as there.
+ See UCharDirection in uchar.h .
+*/
+#define L U_LEFT_TO_RIGHT
+#define R U_RIGHT_TO_LEFT
+#define EN U_EUROPEAN_NUMBER
+#define ES U_EUROPEAN_NUMBER_SEPARATOR
+#define ET U_EUROPEAN_NUMBER_TERMINATOR
+#define AN U_ARABIC_NUMBER
+#define CS U_COMMON_NUMBER_SEPARATOR
+#define B U_BLOCK_SEPARATOR
+#define S U_SEGMENT_SEPARATOR
+#define WS U_WHITE_SPACE_NEUTRAL
+#define ON U_OTHER_NEUTRAL
+#define LRE U_LEFT_TO_RIGHT_EMBEDDING
+#define LRO U_LEFT_TO_RIGHT_OVERRIDE
+#define AL U_RIGHT_TO_LEFT_ARABIC
+#define RLE U_RIGHT_TO_LEFT_EMBEDDING
+#define RLO U_RIGHT_TO_LEFT_OVERRIDE
+#define PDF U_POP_DIRECTIONAL_FORMAT
+#define NSM U_DIR_NON_SPACING_MARK
+#define BN U_BOUNDARY_NEUTRAL
+
+extern const char * const
+dirPropNames[U_CHAR_DIRECTION_COUNT];
+
+extern UChar
+charFromDirProp[U_CHAR_DIRECTION_COUNT];
+
+typedef struct {
+ const uint8_t *text;
+ int32_t length;
+ UBiDiLevel paraLevel;
+ int32_t lineStart, lineLimit;
+ UBiDiDirection direction;
+ UBiDiLevel resultLevel;
+ const UBiDiLevel *levels;
+ const uint8_t *visualMap;
+} BiDiTestData;
+
+extern const BiDiTestData
+tests[];
+
+extern const int
+bidiTestCount;
+
+#ifdef XP_CPLUSPLUS
+}
+#endif
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c
new file mode 100644
index 00000000000..4d25865584d
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cbkittst.c
@@ -0,0 +1,31 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CBKITTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+#include "cintltst.h"
+
+void addBrkIterAPITest(TestNode**);
+
+void addBreakIter(TestNode** root);
+
+void addBreakIter(TestNode** root)
+{
+ addBrkIterAPITest(root);
+}
+
+#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c
new file mode 100644
index 00000000000..bc04ceffbf0
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.c
@@ -0,0 +1,1337 @@
+/********************************************************************
+ * Copyright (c) 1997-2007, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ ********************************************************************
+ *
+ * File CCALTST.C
+ *
+ * Modification History:
+ * Name Description
+ * Madhu Katragadda Creation
+ ********************************************************************
+ */
+
+/* C API AND FUNCTIONALITY TEST FOR CALENDAR (ucol.h)*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include <stdlib.h>
+
+#include "unicode/uloc.h"
+#include "unicode/ucal.h"
+#include "unicode/udat.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "ccaltst.h"
+#include "cformtst.h"
+#include "cstring.h"
+
+void TestGregorianChange(void);
+
+void addCalTest(TestNode** root);
+
+void addCalTest(TestNode** root)
+{
+
+ addTest(root, &TestCalendar, "tsformat/ccaltst/TestCalendar");
+ addTest(root, &TestGetSetDateAPI, "tsformat/ccaltst/TestGetSetDateAPI");
+ addTest(root, &TestFieldGetSet, "tsformat/ccaltst/TestFieldGetSet");
+ addTest(root, &TestAddRollExtensive, "tsformat/ccaltst/TestAddRollExtensive");
+ addTest(root, &TestGetLimits, "tsformat/ccaltst/TestGetLimits");
+ addTest(root, &TestDOWProgression, "tsformat/ccaltst/TestDOWProgression");
+ addTest(root, &TestGMTvsLocal, "tsformat/ccaltst/TestGMTvsLocal");
+ addTest(root, &TestGregorianChange, "tsformat/ccaltst/TestGregorianChange");
+}
+
+/* "GMT" */
+static const UChar fgGMTID [] = { 0x0047, 0x004d, 0x0054, 0x0000 };
+
+/* "PST" */
+static const UChar PST[] = {0x50, 0x53, 0x54, 0x00}; /* "PST" */
+
+static const UChar EUROPE_PARIS[] = {0x45, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2F, 0x50, 0x61, 0x72, 0x69, 0x73, 0x00}; /* "Europe/Paris" */
+
+static void TestCalendar()
+{
+ UCalendar *caldef = 0, *caldef2 = 0, *calfr = 0, *calit = 0;
+ UEnumeration* uenum = NULL;
+ int32_t count, count2, i,j;
+ UChar *tzID = 0;
+ UChar *tzdname = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UDate now;
+ UDateFormat *datdef = 0;
+ UChar *result = 0;
+ int32_t resultlength, resultlengthneeded;
+ char tempMsgBuf[256];
+ UChar zone1[32], zone2[32];
+ const char *tzver = 0;
+
+#ifdef U_USE_UCAL_OBSOLETE_2_8
+ /*Testing countAvailableTimeZones*/
+ int32_t offset=0;
+ log_verbose("\nTesting ucal_countAvailableTZIDs\n");
+ count=ucal_countAvailableTZIDs(offset);
+ log_verbose("The number of timezone id's present with offset 0 are %d:\n", count);
+ if(count < 5) /* Don't hard code an exact == test here! */
+ log_err("FAIL: error in the ucal_countAvailableTZIDs - got %d expected at least 5 total\n", count);
+
+ /*Testing getAvailableTZIDs*/
+ log_verbose("\nTesting ucal_getAvailableTZIDs");
+ for(i=0;i<count;i++){
+ ucal_getAvailableTZIDs(offset, i, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: ucal_getAvailableTZIDs returned %s\n", u_errorName(status));
+ }
+ log_verbose("%s\n", u_austrcpy(tempMsgBuf, ucal_getAvailableTZIDs(offset, i, &status)));
+ }
+ /*get Illegal TZID where index >= count*/
+ ucal_getAvailableTZIDs(offset, i, &status);
+ if(status != U_INDEX_OUTOFBOUNDS_ERROR){
+ log_err("FAIL:for TZID index >= count Expected INDEX_OUTOFBOUNDS_ERROR Got %s\n", u_errorName(status));
+ }
+ status=U_ZERO_ERROR;
+#endif
+
+ /*Test ucal_openTimeZones & ucal_openCountryTimeZones*/
+ for (j=0; j<2; ++j) {
+ const char* api = (j==0) ? "ucal_openTimeZones()" :
+ "ucal_openCountryTimeZones(US)";
+ uenum = (j==0) ? ucal_openTimeZones(&status) :
+ ucal_openCountryTimeZones("US", &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: %s failed with %s", api,
+ u_errorName(status));
+ } else {
+ const char* id;
+ int32_t len;
+ count = uenum_count(uenum, &status);
+ log_verbose("%s returned %d timezone id's:\n", api, count);
+ if (count < 5) { /* Don't hard code an exact == test here! */
+ log_err("FAIL: in %s, got %d, expected at least 5\n", api, count);
+ }
+ uenum_reset(uenum, &status);
+ if (U_FAILURE(status)){
+ log_err("FAIL: uenum_reset for %s returned %s\n",
+ api, u_errorName(status));
+ }
+ for (i=0; i<count; i++) {
+ id = uenum_next(uenum, &len, &status);
+ if (U_FAILURE(status)){
+ log_err("FAIL: uenum_next for %s returned %s\n",
+ api, u_errorName(status));
+ } else {
+ log_verbose("%s\n", id);
+ }
+ }
+ /* Next one should be NULL */
+ id = uenum_next(uenum, &len, &status);
+ if (id != NULL) {
+ log_err("FAIL: uenum_next for %s returned %s, expected NULL\n",
+ api, id);
+ }
+ }
+ uenum_close(uenum);
+ }
+
+ /*Test ucal_getDSTSavings*/
+ status = U_ZERO_ERROR;
+ i = ucal_getDSTSavings(fgGMTID, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_getDSTSavings(GMT) => %s\n",
+ u_errorName(status));
+ } else if (i != 0) {
+ log_err("FAIL: ucal_getDSTSavings(GMT) => %d, expect 0\n", i);
+ }
+ i = ucal_getDSTSavings(PST, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_getDSTSavings(PST) => %s\n",
+ u_errorName(status));
+ } else if (i != 1*60*60*1000) {
+ log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000);
+ }
+
+ /*Test ucal_set/getDefaultTimeZone*/
+ status = U_ZERO_ERROR;
+ i = ucal_getDefaultTimeZone(zone1, sizeof(zone1)/sizeof(zone1[0]), &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_getDefaultTimeZone() => %s\n",
+ u_errorName(status));
+ } else {
+ ucal_setDefaultTimeZone(EUROPE_PARIS, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_setDefaultTimeZone(Europe/Paris) => %s\n",
+ u_errorName(status));
+ } else {
+ i = ucal_getDefaultTimeZone(zone2, sizeof(zone2)/sizeof(zone2[0]), &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_getDefaultTimeZone() => %s\n",
+ u_errorName(status));
+ } else {
+ if (u_strcmp(zone2, EUROPE_PARIS) != 0) {
+ log_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris\n");
+ }
+ }
+ }
+ status = U_ZERO_ERROR;
+ ucal_setDefaultTimeZone(zone1, &status);
+ }
+
+ /*Test ucal_getTZDataVersion*/
+ status = U_ZERO_ERROR;
+ tzver = ucal_getTZDataVersion(&status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ucal_getTZDataVersion() => %s\n", u_errorName(status));
+ } else if (uprv_strlen(tzver) != 5 /*4 digits + 1 letter*/) {
+ log_err("FAIL: Bad version string was returned by ucal_getTZDataVersion\n");
+ } else {
+ log_verbose("PASS: ucal_getTZDataVersion returned %s\n", tzver);
+ }
+
+
+ /*Testing the ucal_open() function*/
+ status = U_ZERO_ERROR;
+ log_verbose("\nTesting the ucal_open()\n");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in ucal_open caldef : %s\n", u_errorName(status));
+ }
+
+ caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in ucal_open caldef : %s\n", u_errorName(status));
+ }
+ u_strcpy(tzID, fgGMTID);
+ calfr=ucal_open(tzID, u_strlen(tzID), "fr_FR", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in ucal_open calfr : %s\n", u_errorName(status));
+ }
+ calit=ucal_open(tzID, u_strlen(tzID), "it_IT", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)) {
+ log_err("FAIL: error in ucal_open calit : %s\n", u_errorName(status));
+ }
+
+
+ /*Testing udat_getAvailable() and udat_countAvailable()*/
+ log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
+ count=ucal_countAvailable();
+ /* use something sensible w/o hardcoding the count */
+ if(count > 0) {
+ log_verbose("PASS: ucal_countAvailable() works fine\n");
+ log_verbose("The no: of locales for which calendars are avilable are %d\n", count);
+ } else {
+ log_data_err("FAIL: Error in countAvailable()\n");
+ }
+
+ for(i=0;i<count;i++) {
+ log_verbose("%s\n", ucal_getAvailable(i));
+ }
+
+
+ /*Testing the equality between calendar's*/
+ log_verbose("\nTesting ucal_equivalentTo()\n");
+ if(caldef && caldef2 && calfr && calit) {
+ if(ucal_equivalentTo(caldef, caldef2) == FALSE || ucal_equivalentTo(caldef, calfr)== TRUE ||
+ ucal_equivalentTo(caldef, calit)== TRUE) {
+ log_err("FAIL: Error. equivalentTo test failed\n");
+ } else {
+ log_verbose("PASS: equivalentTo test passed\n");
+ }
+ }
+
+
+ /*Testing the current time and date using ucal_getnow()*/
+ log_verbose("\nTesting the ucal_getNow function to check if it is fetching tbe current time\n");
+ now=ucal_getNow();
+ /* open the date format and format the date to check the output */
+ datdef=udat_open(UDAT_FULL,UDAT_FULL ,NULL, NULL, 0,NULL,0,&status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in creating the dateformat : %s\n", u_errorName(status));
+ return;
+ }
+ log_verbose("PASS: The current date and time fetched is %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datdef, now)) );
+
+
+ /*Testing the TimeZoneDisplayName */
+ log_verbose("\nTesting the fetching of time zone display name\n");
+ /*for the US locale */
+ resultlength=0;
+ resultlengthneeded=ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", NULL, resultlength, &status);
+
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", result, resultlength, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("FAIL: Error in getting the timezone display name : %s\n", u_errorName(status));
+ }
+ else{
+ log_verbose("PASS: getting the time zone display name successful : %s, %d needed \n",
+ u_errorName(status), resultlengthneeded);
+ }
+
+
+#define expectPDT "Pacific Daylight Time"
+
+ tzdname=(UChar*)malloc(sizeof(UChar) * (sizeof(expectPDT)+1));
+ u_uastrcpy(tzdname, expectPDT);
+ if(u_strcmp(tzdname, result)==0){
+ log_verbose("PASS: got the correct time zone display name %s\n", u_austrcpy(tempMsgBuf, result) );
+ }
+ else{
+ log_err("FAIL: got the wrong time zone(DST) display name %s, wanted %s\n", austrdup(result) , expectPDT);
+ }
+
+ ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_DST, "en_US", result, resultlength, &status);
+ u_uastrcpy(tzdname, "PDT");
+ if(u_strcmp(tzdname, result) != 0){
+ log_err("FAIL: got the wrong time zone(SHORT_DST) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
+ }
+
+ ucal_getTimeZoneDisplayName(caldef, UCAL_STANDARD, "en_US", result, resultlength, &status);
+ u_uastrcpy(tzdname, "Pacific Standard Time");
+ if(u_strcmp(tzdname, result) != 0){
+ log_err("FAIL: got the wrong time zone(STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
+ }
+
+ ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_STANDARD, "en_US", result, resultlength, &status);
+ u_uastrcpy(tzdname, "PST");
+ if(u_strcmp(tzdname, result) != 0){
+ log_err("FAIL: got the wrong time zone(SHORT_STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
+ }
+
+
+ /*testing the setAttributes and getAttributes of a UCalendar*/
+ log_verbose("\nTesting the getAttributes and set Attributes\n");
+ count=ucal_getAttribute(calit, UCAL_LENIENT);
+ count2=ucal_getAttribute(calfr, UCAL_LENIENT);
+ ucal_setAttribute(calit, UCAL_LENIENT, 0);
+ ucal_setAttribute(caldef, UCAL_LENIENT, count2);
+ if( ucal_getAttribute(calit, UCAL_LENIENT) !=0 ||
+ ucal_getAttribute(calfr, UCAL_LENIENT)!=ucal_getAttribute(caldef, UCAL_LENIENT) )
+ log_err("FAIL: there is an error in getAttributes or setAttributes\n");
+ else
+ log_verbose("PASS: attribute set and got successfully\n");
+ /*set it back to orginal value */
+ log_verbose("Setting it back to normal\n");
+ ucal_setAttribute(calit, UCAL_LENIENT, count);
+ if(ucal_getAttribute(calit, UCAL_LENIENT)!=count)
+ log_err("FAIL: Error in setting the attribute back to normal\n");
+
+ /*setting the first day of the week to other values */
+ count=ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK);
+ for (i=1; i<=7; ++i) {
+ ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,i);
+ if (ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK) != i)
+ log_err("FAIL: set/getFirstDayOfWeek failed\n");
+ }
+ /*get bogus Attribute*/
+ count=ucal_getAttribute(calit, (UCalendarAttribute)99); /* BOGUS_ATTRIBUTE */
+ if(count != -1){
+ log_err("FAIL: get/bogus attribute should return -1\n");
+ }
+
+ /*set it back to normal */
+ ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,count);
+ /*setting minimal days of the week to other values */
+ count=ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
+ for (i=1; i<=7; ++i) {
+ ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,i);
+ if (ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK) != i)
+ log_err("FAIL: set/getMinimalDaysInFirstWeek failed\n");
+ }
+ /*set it back to normal */
+ ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,count);
+
+
+ /*testing if the UCalendar's timezone is currently in day light saving's time*/
+ log_verbose("\nTesting if the UCalendar is currently in daylight saving's time\n");
+ ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 10, 45, 20, &status);
+ ucal_inDaylightTime(caldef, &status );
+ if(U_FAILURE(status)) {
+ log_err("Error in ucal_inDaylightTime: %s\n", u_errorName(status));
+ }
+ if(!ucal_inDaylightTime(caldef, &status))
+ log_verbose("PASS: It is not in daylight saving's time\n");
+ else
+ log_err("FAIL: It is not in daylight saving's time\n");
+
+
+
+ /*closing the UCalendar*/
+ ucal_close(caldef);
+ ucal_close(caldef2);
+ ucal_close(calfr);
+ ucal_close(calit);
+ /*closing the UDateFormat used */
+ udat_close(datdef);
+ free(tzID);
+ free(result);
+ free(tzdname);
+}
+
+/*------------------------------------------------------*/
+/*Testing the getMillis, setMillis, setDate and setDateTime functions extensively*/
+
+static void TestGetSetDateAPI()
+{
+ UCalendar *caldef = 0, *caldef2 = 0;
+ UChar *tzID =0;
+ UDate d1;
+ int32_t hour;
+ int32_t zoneOffset;
+ UDateFormat *datdef = 0;
+ UErrorCode status=U_ZERO_ERROR;
+ UDate d2= 837039928046.0;
+ UChar temp[30];
+
+ log_verbose("\nOpening the calendars()\n");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_strcpy(tzID, fgGMTID);
+ /*open the calendars used */
+ caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ /*open the dateformat */
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /*datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL,fgGMTID,-1, &status);*/
+ datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US",fgGMTID,-1,NULL,0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat : %s\n", u_errorName(status));
+ return;
+ }
+
+
+ /*Testing getMillis and setMillis */
+ log_verbose("\nTesting the date and time fetched in millis for a calendar using getMillis\n");
+ d1=ucal_getMillis(caldef, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in getMillis : %s\n", u_errorName(status));
+ }
+
+ /*testing setMillis */
+ log_verbose("\nTesting the set date and time function using setMillis\n");
+ ucal_setMillis(caldef, d2, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in setMillis : %s\n", u_errorName(status));
+ }
+
+ /*testing if the calendar date is set properly or not */
+ d1=ucal_getMillis(caldef, &status);
+ if(u_strcmp(myDateFormat(datdef, d1), myDateFormat(datdef, d2))!=0)
+ log_err("error in setMillis or getMillis\n");
+ /*-------------------*/
+
+
+
+ ctest_setTimeZone(NULL, &status);
+
+ /*testing ucal_setTimeZone() function*/
+ log_verbose("\nTesting if the function ucal_setTimeZone() works fine\n");
+ ucal_setMillis(caldef2, d2, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in getMillis : %s\n", u_errorName(status));;
+ }
+ hour=ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status);
+
+ u_uastrcpy(tzID, "PST");
+ ucal_setTimeZone(caldef2,tzID, 3, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
+ }
+ else
+ log_verbose("ucal_setTimeZone worked fine\n");
+ if(hour == ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status))
+ log_err("FAIL: Error setting the time zone doesn't change the represented time\n");
+ else if((hour-8 + 1) != ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status)) /*because it is not in daylight savings time */
+ log_err("FAIL: Error setTimeZone doesn't change the represented time correctly with 8 hour offset\n");
+ else
+ log_verbose("PASS: setTimeZone works fine\n");
+
+ /*testing setTimeZone roundtrip */
+ log_verbose("\nTesting setTimeZone() roundtrip\n");
+ u_strcpy(tzID, fgGMTID);
+ ucal_setTimeZone(caldef2, tzID, 3, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
+ }
+ if(d2==ucal_getMillis(caldef2, &status))
+ log_verbose("PASS: setTimeZone roundtrip test passed\n");
+ else
+ log_err("FAIL: setTimeZone roundtrip test failed\n");
+
+ zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status));
+ }
+ else if (zoneOffset != 0) {
+ log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset);
+ }
+
+ ucal_setTimeZone(caldef2, NULL, -1, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
+ }
+ if(ucal_getMillis(caldef2, &status))
+ log_verbose("PASS: setTimeZone roundtrip test passed\n");
+ else
+ log_err("FAIL: setTimeZone roundtrip test failed\n");
+
+ zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status));
+ }
+ else if (zoneOffset != -28800000) {
+ log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset);
+ }
+
+ ctest_resetTimeZone();
+
+/*----------------------------* */
+
+
+
+ /*Testing if setDate works fine */
+ log_verbose("\nTesting the ucal_setDate() function \n");
+ u_uastrcpy(temp, "Dec 17, 1971 11:05:28 PM");
+ ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status);
+ if(U_FAILURE(status)){
+ log_err("error in setting the calendar date : %s\n", u_errorName(status));
+ }
+ /*checking if the calendar date is set properly or not */
+ d1=ucal_getMillis(caldef, &status);
+ if(u_strcmp(myDateFormat(datdef, d1), temp)==0)
+ log_verbose("PASS:setDate works fine\n");
+ else
+ log_err("FAIL:Error in setDate()\n");
+
+
+ /* Testing setDate Extensively with various input values */
+ log_verbose("\nTesting ucal_setDate() extensively\n");
+ ucal_setDate(caldef, 1999, UCAL_JANUARY, 10, &status);
+ verify1("1999 10th day of January is :", caldef, datdef, 1999, UCAL_JANUARY, 10);
+ ucal_setDate(caldef, 1999, UCAL_DECEMBER, 3, &status);
+ verify1("1999 3rd day of December is :", caldef, datdef, 1999, UCAL_DECEMBER, 3);
+ ucal_setDate(caldef, 2000, UCAL_MAY, 3, &status);
+ verify1("2000 3rd day of May is :", caldef, datdef, 2000, UCAL_MAY, 3);
+ ucal_setDate(caldef, 1999, UCAL_AUGUST, 32, &status);
+ verify1("1999 32th day of August is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1);
+ ucal_setDate(caldef, 1999, UCAL_MARCH, 0, &status);
+ verify1("1999 0th day of March is :", caldef, datdef, 1999, UCAL_FEBRUARY, 28);
+ ucal_setDate(caldef, 0, UCAL_MARCH, 12, &status);
+
+ /*--------------------*/
+
+ /*Testing if setDateTime works fine */
+ log_verbose("\nTesting the ucal_setDateTime() function \n");
+ u_uastrcpy(temp, "May 3, 1972 4:30:42 PM");
+ ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status);
+ if(U_FAILURE(status)){
+ log_err("error in setting the calendar date : %s\n", u_errorName(status));
+ }
+ /*checking if the calendar date is set properly or not */
+ d1=ucal_getMillis(caldef, &status);
+ if(u_strcmp(myDateFormat(datdef, d1), temp)==0)
+ log_verbose("PASS: setDateTime works fine\n");
+ else
+ log_err("FAIL: Error in setDateTime\n");
+
+
+
+ /*Testing setDateTime extensively with various input values*/
+ log_verbose("\nTesting ucal_setDateTime() function extensively\n");
+ ucal_setDateTime(caldef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, &status);
+ verify2("1999 10th day of October at 6:45:30 is :", caldef, datdef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, 0 );
+ ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 15, 10, 55, &status);
+ verify2("1999 3rd day of March at 15:10:55 is :", caldef, datdef, 1999, UCAL_MARCH, 3, 3, 10, 55, 1);
+ ucal_setDateTime(caldef, 1999, UCAL_MAY, 3, 25, 30, 45, &status);
+ verify2("1999 3rd day of May at 25:30:45 is :", caldef, datdef, 1999, UCAL_MAY, 4, 1, 30, 45, 0);
+ ucal_setDateTime(caldef, 1999, UCAL_AUGUST, 32, 22, 65, 40, &status);
+ verify2("1999 32th day of August at 22:65:40 is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1, 11, 5, 40,1);
+ ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, 0, 0, 0,&status);
+ verify2("1999 12th day of March at 0:0:0 is :", caldef, datdef, 1999, UCAL_MARCH, 12, 0, 0, 0, 0);
+ ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, -10, -10,0, &status);
+ verify2("1999 12th day of March is at -10:-10:0 :", caldef, datdef, 1999, UCAL_MARCH, 11, 1, 50, 0, 1);
+
+
+
+ /*close caldef and datdef*/
+ ucal_close(caldef);
+ ucal_close(caldef2);
+ udat_close(datdef);
+ free(tzID);
+
+}
+
+/*----------------------------------------------------------- */
+/**
+ * Confirm the functioning of the calendar field related functions.
+ */
+static void TestFieldGetSet()
+{
+ UCalendar *cal = 0;
+ UChar *tzID = 0;
+ UDateFormat *datdef = 0;
+ UDate d1;
+ UErrorCode status=U_ZERO_ERROR;
+ log_verbose("\nFetching pointer to UCalendar using the ucal_open()\n");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_strcpy(tzID, fgGMTID);
+ /*open the calendar used */
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_open failed: %s\n", u_errorName(status));
+ return;
+ }
+ datdef=udat_open(UDAT_SHORT,UDAT_SHORT ,NULL,fgGMTID,-1,NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat : %s\n", u_errorName(status));
+ }
+
+ /*Testing ucal_get()*/
+ log_verbose("\nTesting the ucal_get() function of Calendar\n");
+ ucal_setDateTime(cal, 1999, UCAL_MARCH, 12, 5, 25, 30, &status);
+ if(U_FAILURE(status)){
+ log_err("error in the setDateTime() : %s\n", u_errorName(status));
+ }
+ if(ucal_get(cal, UCAL_YEAR, &status)!=1999 || ucal_get(cal, UCAL_MONTH, &status)!=2 ||
+ ucal_get(cal, UCAL_DATE, &status)!=12 || ucal_get(cal, UCAL_HOUR, &status)!=5)
+ log_err("error in ucal_get()\n");
+ else if(ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status)!=2 || ucal_get(cal, UCAL_DAY_OF_WEEK, &status)!=6
+ || ucal_get(cal, UCAL_WEEK_OF_MONTH, &status)!=2 || ucal_get(cal, UCAL_WEEK_OF_YEAR, &status)!= 11)
+ log_err("FAIL: error in ucal_get()\n");
+ else
+ log_verbose("PASS: ucal_get() works fine\n");
+
+ /*Testing the ucal_set() , ucal_clear() functions of calendar*/
+ log_verbose("\nTesting the set, and clear field functions of calendar\n");
+ ucal_setAttribute(cal, UCAL_LENIENT, 0);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_DATE, 3);
+ verify1("1997 third day of June = ", cal, datdef, 1997, UCAL_JUNE, 3);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 1);
+ verify1("1997 first Tuesday in June = ", cal, datdef, 1997, UCAL_JUNE, 3);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, - 1);
+ verify1("1997 last Tuesday in June = ", cal, datdef,1997, UCAL_JUNE, 24);
+ /*give undesirable input */
+ status = U_ZERO_ERROR;
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 0);
+ d1=ucal_getMillis(cal,&status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("FAIL: No IllegalArgumentError for :");
+ log_err("1997 zero-th Tuesday in June \n");
+ }
+ else
+ log_verbose("PASS: IllegalArgumentError as expected\n");
+
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_WEEK_OF_MONTH, 1);
+ verify1("1997 Tuesday in week 1 of June = ", cal,datdef, 1997, UCAL_JUNE, 3);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_WEEK_OF_MONTH, 5);
+ verify1("1997 Tuesday in week 5 of June = ", cal,datdef, 1997, UCAL_JULY, 1);
+ status = U_ZERO_ERROR;
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
+ ucal_set(cal, UCAL_WEEK_OF_MONTH, 0);
+ verify1("1997 Tuesday in week 0 of June = ", cal, datdef , 1997, UCAL_MAY, 27);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR_WOY, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_WEEK_OF_YEAR, 1);
+ verify1("1997 Tuesday in week 1 of year = ", cal, datdef,1996, UCAL_DECEMBER, 31);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1997);
+ ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
+ ucal_set(cal, UCAL_WEEK_OF_YEAR, 10);
+ verify1("1997 Tuesday in week 10 of year = ", cal,datdef, 1997, UCAL_MARCH, 4);
+ ucal_clear(cal);
+ ucal_set(cal, UCAL_YEAR, 1999);
+ ucal_set(cal, UCAL_DAY_OF_YEAR, 1);
+ verify1("1999 1st day of the year =", cal, datdef, 1999, UCAL_JANUARY, 1);
+ ucal_set(cal, UCAL_MONTH, -3);
+ d1=ucal_getMillis(cal,&status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("FAIL: No IllegalArgumentError for :\"1999 -3th month \" ");
+ }
+ else
+ log_verbose("PASS: IllegalArgumentError as expected\n");
+
+ ucal_setAttribute(cal, UCAL_LENIENT, 1);
+
+ ucal_set(cal, UCAL_MONTH, -3);
+ verify1("1999 -3th month should be", cal, datdef, 1998, UCAL_OCTOBER, 1);
+
+
+ /*testing isSet and clearField()*/
+ if(!ucal_isSet(cal, UCAL_WEEK_OF_YEAR))
+ log_err("FAIL: error in isSet\n");
+ else
+ log_verbose("PASS: isSet working fine\n");
+ ucal_clearField(cal, UCAL_WEEK_OF_YEAR);
+ if(ucal_isSet(cal, UCAL_WEEK_OF_YEAR))
+ log_err("FAIL: there is an error in clearField or isSet\n");
+ else
+ log_verbose("PASS :clearField working fine\n");
+
+ /*-------------------------------*/
+
+ ucal_close(cal);
+ udat_close(datdef);
+ free(tzID);
+
+}
+
+
+
+/* ------------------------------------- */
+/**
+ * Execute adding and rolling in Calendar extensively,
+ */
+static void TestAddRollExtensive()
+{
+ UCalendar *cal = 0;
+ int32_t i,limit;
+ UChar* tzID = 0;
+ UCalendarDateFields e;
+ int32_t y,m,d,hr,min,sec,ms;
+ int32_t maxlimit = 40;
+ UErrorCode status = U_ZERO_ERROR;
+ y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0;
+
+ log_verbose("Testing add and roll extensively\n");
+
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ /*open the calendar used */
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);;
+ if (U_FAILURE(status)) {
+ log_err("ucal_open() failed : %s\n", u_errorName(status));
+ return;
+ }
+
+ ucal_set(cal, UCAL_YEAR, y);
+ ucal_set(cal, UCAL_MONTH, m);
+ ucal_set(cal, UCAL_DATE, d);
+
+ /* Confirm that adding to various fields works.*/
+ log_verbose("\nTesting to confirm that adding to various fields works with ucal_add()\n");
+ checkDate(cal, y, m, d);
+ ucal_add(cal,UCAL_YEAR, 1, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status)); return; }
+ y++;
+ checkDate(cal, y, m, d);
+ ucal_add(cal,UCAL_MONTH, 12, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
+ y+=1;
+ checkDate(cal, y, m, d);
+ ucal_add(cal,UCAL_DATE, 1, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
+ d++;
+ checkDate(cal, y, m, d);
+ ucal_add(cal,UCAL_DATE, 2, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
+ d += 2;
+ checkDate(cal, y, m, d);
+ ucal_add(cal,UCAL_DATE, 28, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
+ ++m;
+ checkDate(cal, y, m, d);
+ ucal_add(cal, (UCalendarDateFields)-1, 10, &status);
+ if(status==U_ILLEGAL_ARGUMENT_ERROR)
+ log_verbose("Pass: Illegal argument error as expected\n");
+ else{
+ log_err("Fail: No, illegal argument error as expected. Got....: %s\n", u_errorName(status));
+ }
+ status=U_ZERO_ERROR;
+
+
+ /*confirm that applying roll to various fields works fine*/
+ log_verbose("\nTesting to confirm that ucal_roll() works\n");
+ ucal_roll(cal, UCAL_DATE, -1, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ d -=1;
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, UCAL_MONTH, -2, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ m -=2;
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, UCAL_DATE, 1, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ d +=1;
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, UCAL_MONTH, -12, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, UCAL_YEAR, -1, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ y -=1;
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, UCAL_DATE, 29, &status);
+ if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
+ d = 2;
+ checkDate(cal, y, m, d);
+ ucal_roll(cal, (UCalendarDateFields)-1, 10, &status);
+ if(status==U_ILLEGAL_ARGUMENT_ERROR)
+ log_verbose("Pass: illegal arguement error as expected\n");
+ else{
+ log_err("Fail: no illegal argument error got..: %s\n", u_errorName(status));
+ return;
+ }
+ status=U_ZERO_ERROR;
+ ucal_clear(cal);
+ ucal_setDateTime(cal, 1999, UCAL_FEBRUARY, 28, 10, 30, 45, &status);
+ if(U_FAILURE(status)){
+ log_err("error is setting the datetime: %s\n", u_errorName(status));
+ }
+ ucal_add(cal, UCAL_MONTH, 1, &status);
+ checkDate(cal, 1999, UCAL_MARCH, 28);
+ ucal_add(cal, UCAL_MILLISECOND, 1000, &status);
+ checkDateTime(cal, 1999, UCAL_MARCH, 28, 10, 30, 46, 0, UCAL_MILLISECOND);
+
+ ucal_close(cal);
+/*--------------- */
+ status=U_ZERO_ERROR;
+ /* Testing add and roll extensively */
+ log_verbose("\nTesting the ucal_add() and ucal_roll() functions extensively\n");
+ y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0;
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_open failed: %s\n", u_errorName(status));
+ return;
+ }
+ ucal_set(cal, UCAL_YEAR, y);
+ ucal_set(cal, UCAL_MONTH, m);
+ ucal_set(cal, UCAL_DATE, d);
+ ucal_set(cal, UCAL_HOUR, hr);
+ ucal_set(cal, UCAL_MINUTE, min);
+ ucal_set(cal, UCAL_SECOND,sec);
+ ucal_set(cal, UCAL_MILLISECOND, ms);
+ status=U_ZERO_ERROR;
+
+ log_verbose("\nTesting UCalendar add...\n");
+ for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) {
+ limit = maxlimit;
+ status = U_ZERO_ERROR;
+ for (i = 0; i < limit; i++) {
+ ucal_add(cal, e, 1, &status);
+ if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; }
+ }
+ for (i = 0; i < limit; i++) {
+ ucal_add(cal, e, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_add -1 failed: %s\n", u_errorName(status));
+ return;
+ }
+ }
+ checkDateTime(cal, y, m, d, hr, min, sec, ms, e);
+ }
+ log_verbose("\nTesting calendar ucal_roll()...\n");
+ for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) {
+ limit = maxlimit;
+ status = U_ZERO_ERROR;
+ for (i = 0; i < limit; i++) {
+ ucal_roll(cal, e, 1, &status);
+ if (U_FAILURE(status)) {
+ limit = i;
+ status = U_ZERO_ERROR;
+ }
+ }
+ for (i = 0; i < limit; i++) {
+ ucal_roll(cal, e, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_roll -1 failed: %s\n", u_errorName(status));
+ return;
+ }
+ }
+ checkDateTime(cal, y, m, d, hr, min, sec, ms, e);
+ }
+
+ ucal_close(cal);
+ free(tzID);
+}
+
+/*------------------------------------------------------ */
+/*Testing the Limits for various Fields of Calendar*/
+static void TestGetLimits()
+{
+ UCalendar *cal = 0;
+ int32_t min, max, gr_min, le_max, ac_min, ac_max, val;
+ UChar* tzID = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ /*open the calendar used */
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);;
+ if (U_FAILURE(status)) {
+ log_err("ucal_open() for gregorian calendar failed in TestGetLimits: %s\n", u_errorName(status));
+ return;
+ }
+
+ log_verbose("\nTesting the getLimits function for various fields\n");
+
+
+
+ ucal_setDate(cal, 1999, UCAL_MARCH, 5, &status); /* Set the date to be March 5, 1999 */
+ val = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
+ min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MINIMUM, &status);
+ max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MAXIMUM, &status);
+ if ( (min != UCAL_SUNDAY || max != UCAL_SATURDAY ) && (min > val && val > max) && (val != UCAL_FRIDAY)){
+ log_err("FAIL: Min/max bad\n");
+ log_err("FAIL: Day of week %d out of range\n", val);
+ log_err("FAIL: FAIL: Day of week should be SUNDAY Got %d\n", val);
+ }
+ else
+ log_verbose("getLimits successful\n");
+
+ val = ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status);
+ min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MINIMUM, &status);
+ max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MAXIMUM, &status);
+ if ( (min != 0 || max != 5 ) && (min > val && val > max) && (val != 1)){
+ log_err("FAIL: Min/max bad\n");
+ log_err("FAIL: Day of week in month %d out of range\n", val);
+ log_err("FAIL: FAIL: Day of week in month should be SUNDAY Got %d\n", val);
+
+ }
+ else
+ log_verbose("getLimits successful\n");
+
+ min=ucal_getLimit(cal, UCAL_MONTH, UCAL_MINIMUM, &status);
+ max=ucal_getLimit(cal, UCAL_MONTH, UCAL_MAXIMUM, &status);
+ gr_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_GREATEST_MINIMUM, &status);
+ le_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_LEAST_MAXIMUM, &status);
+ ac_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MINIMUM, &status);
+ ac_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MAXIMUM, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in getLimits: %s\n", u_errorName(status));
+ }
+ if(min!=0 || max!=11 || gr_min!=0 || le_max!=11 || ac_min!=0 || ac_max!=11)
+ log_err("There is and error in getLimits in fetching the values\n");
+ else
+ log_verbose("getLimits successful\n");
+
+ ucal_setDateTime(cal, 1999, UCAL_MARCH, 5, 4, 10, 35, &status);
+ val=ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
+ min=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MINIMUM, &status);
+ max=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MAXIMUM, &status);
+ gr_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_GREATEST_MINIMUM, &status);
+ le_max=ucal_getLimit(cal, UCAL_MINUTE, UCAL_LEAST_MAXIMUM, &status);
+ ac_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_ACTUAL_MINIMUM, &status);
+ ac_max=ucal_getLimit(cal, UCAL_SECOND, UCAL_ACTUAL_MAXIMUM, &status);
+ if( (min!=0 || max!= 11 || gr_min!=0 || le_max!=60 || ac_min!=0 || ac_max!=60) &&
+ (min>val && val>max) && val!=4){
+
+ log_err("FAIL: Min/max bad\n");
+ log_err("FAIL: Hour of Day %d out of range\n", val);
+ log_err("FAIL: HOUR_OF_DAY should be 4 Got %d\n", val);
+ }
+ else
+ log_verbose("getLimits successful\n");
+
+
+ /*get BOGUS_LIMIT type*/
+ val=ucal_getLimit(cal, UCAL_SECOND, (UCalendarLimitType)99, &status);
+ if(val != -1){
+ log_err("FAIL: ucal_getLimit() with BOGUS type should return -1\n");
+ }
+ status=U_ZERO_ERROR;
+
+
+ ucal_close(cal);
+ free(tzID);
+}
+
+
+
+/* ------------------------------------- */
+
+/**
+ * Test that the days of the week progress properly when add is called repeatedly
+ * for increments of 24 days.
+ */
+static void TestDOWProgression()
+{
+ int32_t initialDOW, DOW, newDOW, expectedDOW;
+ UCalendar *cal = 0;
+ UDateFormat *datfor = 0;
+ UDate date1;
+ int32_t delta=24;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar* tzID = 0;
+ char tempMsgBuf[256];
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_strcpy(tzID, fgGMTID);
+ /*open the calendar used */
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);;
+ if (U_FAILURE(status)) {
+ log_err("ucal_open failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status);
+ if(U_FAILURE(status)){
+ log_err("error in creating the dateformat : %s\n", u_errorName(status));
+ }
+
+
+ ucal_setDate(cal, 1999, UCAL_JANUARY, 1, &status);
+
+ log_verbose("\nTesting the DOW progression\n");
+
+ initialDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
+ if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status) ); return; }
+ newDOW = initialDOW;
+ do {
+ DOW = newDOW;
+ log_verbose("DOW = %d...\n", DOW);
+ date1=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;}
+ log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)));
+
+ ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status);
+ if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); return; }
+
+ newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
+ if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); return; }
+ expectedDOW = 1 + (DOW + delta - 1) % 7;
+ date1=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); return;}
+ if (newDOW != expectedDOW) {
+ log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW,
+ u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) );
+ return;
+ }
+ }
+ while (newDOW != initialDOW);
+
+ ucal_close(cal);
+ udat_close(datfor);
+ free(tzID);
+
+}
+
+/* ------------------------------------- */
+
+/**
+ * Confirm that the offset between local time and GMT behaves as expected.
+ */
+static void TestGMTvsLocal()
+{
+ log_verbose("\nTesting the offset between the GMT and local time\n");
+ testZones(1999, 1, 1, 12, 0, 0);
+ testZones(1999, 4, 16, 18, 30, 0);
+ testZones(1998, 12, 17, 19, 0, 0);
+}
+
+/* ------------------------------------- */
+
+static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc)
+{
+ int32_t offset,utc, expected;
+ UCalendar *gmtcal = 0, *cal = 0;
+ UDate date1;
+ double temp;
+ UDateFormat *datfor = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar* tzID = 0;
+ char tempMsgBuf[256];
+
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_strcpy(tzID, fgGMTID);
+ gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);;
+ if (U_FAILURE(status)) {
+ log_err("ucal_open failed: %s\n", u_errorName(status));
+ return;
+ }
+ u_uastrcpy(tzID, "PST");
+ cal = ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_open failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status);
+ if(U_FAILURE(status)){
+ log_err("error in creating the dateformat : %s\n", u_errorName(status));
+ }
+
+ ucal_setDateTime(gmtcal, yr, mo - 1, dt, hr, mn, sc, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_setDateTime failed: %s\n", u_errorName(status));
+ return;
+ }
+ ucal_set(gmtcal, UCAL_MILLISECOND, 0);
+ date1 = ucal_getMillis(gmtcal, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_getMillis failed: %s\n", u_errorName(status));
+ return;
+ }
+ log_verbose("date = %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) );
+
+
+ ucal_setMillis(cal, date1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_setMillis() failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ offset = ucal_get(cal, UCAL_ZONE_OFFSET, &status);
+ offset += ucal_get(cal, UCAL_DST_OFFSET, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("ucal_get() failed: %s\n", u_errorName(status));
+ return;
+ }
+ temp=(double)((double)offset / 1000.0 / 60.0 / 60.0);
+ /*printf("offset for %s %f hr\n", austrdup(myDateFormat(datfor, date1)), temp);*/
+
+ utc = ((ucal_get(cal, UCAL_HOUR_OF_DAY, &status) * 60 +
+ ucal_get(cal, UCAL_MINUTE, &status)) * 60 +
+ ucal_get(cal, UCAL_SECOND, &status)) * 1000 +
+ ucal_get(cal, UCAL_MILLISECOND, &status) - offset;
+ if (U_FAILURE(status)) {
+ log_err("ucal_get() failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ expected = ((hr * 60 + mn) * 60 + sc) * 1000;
+ if (utc != expected) {
+ temp=(double)(utc - expected)/ 1000 / 60 / 60.0;
+ log_err("FAIL: Discrepancy of %d millis = %fhr\n", utc-expected, temp );
+ }
+ else
+ log_verbose("PASS: the offset between local and GMT is correct\n");
+ ucal_close(gmtcal);
+ ucal_close(cal);
+ udat_close(datfor);
+ free(tzID);
+}
+
+/* ------------------------------------- */
+
+
+
+
+/* INTERNAL FUNCTIONS USED */
+/*------------------------------------------------------------------------------------------- */
+
+/* ------------------------------------- */
+static void checkDateTime(UCalendar* c,
+ int32_t y, int32_t m, int32_t d,
+ int32_t hr, int32_t min, int32_t sec,
+ int32_t ms, UCalendarDateFields field)
+
+{
+ UErrorCode status = U_ZERO_ERROR;
+ if (ucal_get(c, UCAL_YEAR, &status) != y ||
+ ucal_get(c, UCAL_MONTH, &status) != m ||
+ ucal_get(c, UCAL_DATE, &status) != d ||
+ ucal_get(c, UCAL_HOUR, &status) != hr ||
+ ucal_get(c, UCAL_MINUTE, &status) != min ||
+ ucal_get(c, UCAL_SECOND, &status) != sec ||
+ ucal_get(c, UCAL_MILLISECOND, &status) != ms) {
+ log_err("U_FAILURE for field %d, Expected y/m/d h:m:s:ms of %d/%d/%d %d:%d:%d:%d got %d/%d/%d %d:%d:%d:%d\n",
+ (int32_t)field, y, m + 1, d, hr, min, sec, ms,
+ ucal_get(c, UCAL_YEAR, &status),
+ ucal_get(c, UCAL_MONTH, &status) + 1,
+ ucal_get(c, UCAL_DATE, &status),
+ ucal_get(c, UCAL_HOUR, &status),
+ ucal_get(c, UCAL_MINUTE, &status) + 1,
+ ucal_get(c, UCAL_SECOND, &status),
+ ucal_get(c, UCAL_MILLISECOND, &status) );
+
+ if (U_FAILURE(status)){
+ log_err("ucal_get failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ }
+ else
+ log_verbose("Confirmed: %d/%d/%d %d:%d:%d:%d\n", y, m + 1, d, hr, min, sec, ms);
+
+}
+
+/* ------------------------------------- */
+static void checkDate(UCalendar* c, int32_t y, int32_t m, int32_t d)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ if (ucal_get(c,UCAL_YEAR, &status) != y ||
+ ucal_get(c, UCAL_MONTH, &status) != m ||
+ ucal_get(c, UCAL_DATE, &status) != d) {
+
+ log_err("FAILURE: Expected y/m/d of %d/%d/%d got %d/%d/%d\n", y, m + 1, d,
+ ucal_get(c, UCAL_YEAR, &status),
+ ucal_get(c, UCAL_MONTH, &status) + 1,
+ ucal_get(c, UCAL_DATE, &status) );
+
+ if (U_FAILURE(status)) {
+ log_err("ucal_get failed: %s\n", u_errorName(status));
+ return;
+ }
+ }
+ else
+ log_verbose("Confirmed: %d/%d/%d\n", y, m + 1, d);
+
+
+}
+
+/* ------------------------------------- */
+
+/* ------------------------------------- */
+
+static void verify1(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day)
+{
+ UDate d1;
+ UErrorCode status = U_ZERO_ERROR;
+ if (ucal_get(c, UCAL_YEAR, &status) == year &&
+ ucal_get(c, UCAL_MONTH, &status) == month &&
+ ucal_get(c, UCAL_DATE, &status) == day) {
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status));
+ return;
+ }
+ log_verbose("PASS: %s\n", msg);
+ d1=ucal_getMillis(c, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_getMillis failed: %s\n", u_errorName(status));
+ return;
+ }
+ /*log_verbose(austrdup(myDateFormat(dat, d1)) );*/
+ }
+ else {
+ log_err("FAIL: %s\n", msg);
+ d1=ucal_getMillis(c, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_getMillis failed: %s\n", u_errorName(status) );
+ return;
+ }
+ log_err("Got %s Expected %d/%d/%d \n", austrdup(myDateFormat(dat, d1)), year, month + 1, day );
+ return;
+ }
+
+
+}
+
+/* ------------------------------------ */
+static void verify2(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day,
+ int32_t hour, int32_t min, int32_t sec, int32_t am_pm)
+{
+ UDate d1;
+ UErrorCode status = U_ZERO_ERROR;
+ char tempMsgBuf[256];
+
+ if (ucal_get(c, UCAL_YEAR, &status) == year &&
+ ucal_get(c, UCAL_MONTH, &status) == month &&
+ ucal_get(c, UCAL_DATE, &status) == day &&
+ ucal_get(c, UCAL_HOUR, &status) == hour &&
+ ucal_get(c, UCAL_MINUTE, &status) == min &&
+ ucal_get(c, UCAL_SECOND, &status) == sec &&
+ ucal_get(c, UCAL_AM_PM, &status) == am_pm ){
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status));
+ return;
+ }
+ log_verbose("PASS: %s\n", msg);
+ d1=ucal_getMillis(c, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_getMillis failed: %s\n", u_errorName(status));
+ return;
+ }
+ log_verbose("%s\n" , u_austrcpy(tempMsgBuf, myDateFormat(dat, d1)) );
+ }
+ else {
+ log_err("FAIL: %s\n", msg);
+ d1=ucal_getMillis(c, &status);
+ if (U_FAILURE(status)) {
+ log_err("ucal_getMillis failed: %s\n", u_errorName(status));
+ return;
+ }
+ log_err("Got %s Expected %d/%d/%d/ %d:%d:%d %s\n", austrdup(myDateFormat(dat, d1)),
+ year, month + 1, day, hour, min, sec, (am_pm==0) ? "AM": "PM");
+
+ return;
+ }
+
+
+}
+
+void TestGregorianChange() {
+ static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */
+ const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */
+ UCalendar *cal;
+ UDate date;
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ /* Test ucal_setGregorianChange() on a Gregorian calendar. */
+ errorCode = U_ZERO_ERROR;
+ cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucal_open(UTC) failed: %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucal_setGregorianChange(cal, -365 * (dayMillis * (UDate)1), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucal_setGregorianChange(1969) failed: %s\n", u_errorName(errorCode));
+ } else {
+ date = ucal_getGregorianChange(cal, &errorCode);
+ if(U_FAILURE(errorCode) || date != -365 * (dayMillis * (UDate)1)) {
+ log_err("ucal_getGregorianChange() failed: %s, date = %f\n", u_errorName(errorCode), date);
+ }
+ }
+ ucal_close(cal);
+
+ /* Test ucal_setGregorianChange() on a non-Gregorian calendar where it should fail. */
+ errorCode = U_ZERO_ERROR;
+ cal = ucal_open(utc, -1, "th@calendar=buddhist", UCAL_TRADITIONAL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucal_open(UTC, non-Gregorian) failed: %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucal_setGregorianChange(cal, -730 * (dayMillis * (UDate)1), &errorCode);
+ if(errorCode != U_UNSUPPORTED_ERROR) {
+ log_err("ucal_setGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n",
+ u_errorName(errorCode));
+ }
+ errorCode = U_ZERO_ERROR;
+ date = ucal_getGregorianChange(cal, &errorCode);
+ if(errorCode != U_UNSUPPORTED_ERROR) {
+ log_err("ucal_getGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n",
+ u_errorName(errorCode));
+ }
+ ucal_close(cal);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h
new file mode 100644
index 00000000000..e4ec3fdafe0
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccaltst.h
@@ -0,0 +1,80 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CAPITEST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************/
+/* C API TEST FOR CALENDAR */
+#ifndef _CCALTST
+#define _CCALTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+
+ /**
+ * The function used to test the Calendar API
+ **/
+ static void TestCalendar(void);
+ /**
+ * The function used to test getMillis, setMillis, setDate and setDateTime functions extensively
+ **/
+ static void TestGetSetDateAPI(void);
+ /**
+ * This function is used to test and confirm the functioning of
+ * the calendar get and set functions of calendar fields.
+ **/
+ static void TestFieldGetSet(void);
+ /**
+ * Execute and test adding and rolling extensively.
+ **/
+ static void TestAddRollExtensive(void);
+ /**
+ *Testing the Limits for various Fields of Calendar
+ **/
+ static void TestGetLimits(void);
+ /**
+ * Test that the days of the week progress properly when add is called repeatedly
+ * for increments of 24 days.
+ **/
+ static void TestDOWProgression(void);
+ /**
+ * Confirm that the offset between local time and GMT behaves as expected.
+ **/
+ static void TestGMTvsLocal(void);
+ /**
+ * test subroutine used by TestGMTvsLocal()
+ */
+ static void testZones(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+
+/*Internal functions used*/
+ /**
+ * test subroutines used by TestAddRollExtensive()
+ **/
+ static void checkDate(UCalendar* c, int32_t y, int32_t m, int32_t d);
+
+ static void checkDateTime(UCalendar* c, int32_t y, int32_t m, int32_t d,
+ int32_t hr, int32_t min, int32_t sec, int32_t ms,
+ UCalendarDateFields field);
+
+ /**
+ * test subroutines used by TestGetSetDateAPI and TestFieldGetSet
+ **/
+ static void verify1(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day);
+
+ static void verify2(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day,
+ int32_t hour, int32_t min, int32_t sec, int32_t am_pm);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c
new file mode 100644
index 00000000000..4864ccd6260
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.c
@@ -0,0 +1,3575 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*****************************************************************************
+*
+* File CU_CAPITST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+******************************************************************************
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "unicode/uloc.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_err.h"
+#include "unicode/putil.h"
+#include "unicode/uset.h"
+#include "unicode/ustring.h"
+#include "ucnv_bld.h" /* for sizeof(UConverter) */
+#include "cmemory.h" /* for UAlignedMemory */
+#include "cintltst.h"
+#include "ccapitst.h"
+
+/* for not including "cstring.h" -begin*/
+#ifdef U_WINDOWS
+# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2)
+#elif defined(POSIX)
+# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2)
+#else
+# define ctest_stricmp(str1, str2) T_CString_stricmp(str1, str2)
+#endif
+
+static int U_EXPORT2
+T_CString_stricmp(const char *str1, const char *str2) {
+ if(str1==NULL) {
+ if(str2==NULL) {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else if(str2==NULL) {
+ return 1;
+ } else {
+ /* compare non-NULL strings lexically with lowercase */
+ int rc;
+ unsigned char c1, c2;
+ for(;;) {
+ c1=(unsigned char)*str1;
+ c2=(unsigned char)*str2;
+ if(c1==0) {
+ if(c2==0) {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else if(c2==0) {
+ return 1;
+ } else {
+ /* compare non-zero characters with lowercase */
+ rc=(int)(unsigned char)tolower(c1)-(int)(unsigned char)tolower(c2);
+ if(rc!=0) {
+ return rc;
+ }
+ }
+ ++str1;
+ ++str2;
+ }
+ }
+}
+/* for not including "cstring.h" -end*/
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+#define NUM_CODEPAGE 1
+#define MAX_FILE_LEN 1024*20
+#define UCS_FILE_NAME_SIZE 512
+
+/*returns an action other than the one provided*/
+static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA);
+static UConverterToUCallback otherCharAction(UConverterToUCallback MIA);
+
+static UConverter *
+cnv_open(const char *name, UErrorCode *pErrorCode) {
+ if(name!=NULL && name[0]=='*') {
+ return ucnv_openPackage(loadTestData(pErrorCode), name+1, pErrorCode);
+ } else {
+ return ucnv_open(name, pErrorCode);
+ }
+}
+
+
+static void ListNames(void);
+static void TestFlushCache(void);
+static void TestDuplicateAlias(void);
+static void TestCCSID(void);
+static void TestJ932(void);
+static void TestJ1968(void);
+static void TestLMBCSMaxChar(void);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestConvertSafeCloneCallback(void);
+#endif
+
+static void TestEBCDICSwapLFNL(void);
+static void TestConvertEx(void);
+static void TestConvertExFromUTF8(void);
+static void TestConvertAlgorithmic(void);
+ void TestDefaultConverterError(void); /* defined in cctest.c */
+static void TestToUCountPending(void);
+static void TestFromUCountPending(void);
+static void TestDefaultName(void);
+static void TestCompareNames(void);
+static void TestSubstString(void);
+static void InvalidArguments(void);
+
+void addTestConvert(TestNode** root);
+
+void addTestConvert(TestNode** root)
+{
+ addTest(root, &ListNames, "tsconv/ccapitst/ListNames");
+ addTest(root, &TestConvert, "tsconv/ccapitst/TestConvert");
+ addTest(root, &TestFlushCache, "tsconv/ccapitst/TestFlushCache");
+ addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias");
+ addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias");
+ addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone");
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
+#endif
+ addTest(root, &TestCCSID, "tsconv/ccapitst/TestCCSID");
+ addTest(root, &TestJ932, "tsconv/ccapitst/TestJ932");
+ addTest(root, &TestJ1968, "tsconv/ccapitst/TestJ1968");
+ addTest(root, &TestLMBCSMaxChar, "tsconv/ccapitst/TestLMBCSMaxChar");
+ addTest(root, &TestEBCDICSwapLFNL, "tsconv/ccapitst/TestEBCDICSwapLFNL");
+ addTest(root, &TestConvertEx, "tsconv/ccapitst/TestConvertEx");
+ addTest(root, &TestConvertExFromUTF8, "tsconv/ccapitst/TestConvertExFromUTF8");
+ addTest(root, &TestConvertAlgorithmic, "tsconv/ccapitst/TestConvertAlgorithmic");
+ addTest(root, &TestDefaultConverterError, "tsconv/ccapitst/TestDefaultConverterError");
+ addTest(root, &TestToUCountPending, "tsconv/ccapitst/TestToUCountPending");
+ addTest(root, &TestFromUCountPending, "tsconv/ccapitst/TestFromUCountPending");
+ addTest(root, &TestDefaultName, "tsconv/ccapitst/TestDefaultName");
+ addTest(root, &TestCompareNames, "tsconv/ccapitst/TestCompareNames");
+ addTest(root, &TestSubstString, "tsconv/ccapitst/TestSubstString");
+ addTest(root, &InvalidArguments, "tsconv/ccapitst/InvalidArguments");
+}
+
+static void ListNames(void) {
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t testLong1 = 0;
+ const char* available_conv;
+ UEnumeration *allNamesEnum = NULL;
+ int32_t allNamesCount = 0;
+ uint16_t count;
+
+ log_verbose("Testing ucnv_openAllNames()...");
+ allNamesEnum = ucnv_openAllNames(&err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err));
+ }
+ else {
+ const char *string = NULL;
+ int32_t len = 0;
+ int32_t count1 = 0;
+ int32_t count2 = 0;
+ allNamesCount = uenum_count(allNamesEnum, &err);
+ while ((string = uenum_next(allNamesEnum, &len, &err))) {
+ count1++;
+ log_verbose("read \"%s\", length %i\n", string, len);
+ }
+ if (U_FAILURE(err)) {
+ log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err));
+ err = U_ZERO_ERROR;
+ }
+ uenum_reset(allNamesEnum, &err);
+ while ((string = uenum_next(allNamesEnum, &len, &err))) {
+ count2++;
+ ucnv_close(ucnv_open(string, &err));
+ log_verbose("read \"%s\", length %i (%s)\n", string, len, U_SUCCESS(err) ? "available" : "unavailable");
+ err = U_ZERO_ERROR;
+ }
+ if (count1 != count2) {
+ log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
+ }
+ }
+ uenum_close(allNamesEnum);
+ err = U_ZERO_ERROR;
+
+ /*Tests ucnv_getAvailableName(), getAvialableCount()*/
+
+ log_verbose("Testing ucnv_countAvailable()...");
+
+ testLong1=ucnv_countAvailable();
+ log_info("Number of available codepages: %d/%d\n", testLong1, allNamesCount);
+
+ log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
+
+ available_conv = ucnv_getAvailableName(testLong1);
+ /*test ucnv_getAvailableName with err condition*/
+ log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
+ available_conv = ucnv_getAvailableName(-1);
+ if(available_conv != NULL){
+ log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
+ }
+
+ /* Test ucnv_countAliases() etc. */
+ count = ucnv_countAliases("utf-8", &err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err));
+ } else if(count <= 0) {
+ log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count);
+ } else {
+ /* try to get the aliases individually */
+ const char *alias;
+ alias = ucnv_getAlias("utf-8", 0, &err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err));
+ } else if(strcmp("UTF-8", alias) != 0) {
+ log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias);
+ } else {
+ uint16_t aliasNum;
+ for(aliasNum = 0; aliasNum < count; ++aliasNum) {
+ alias = ucnv_getAlias("utf-8", aliasNum, &err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
+ } else if(strlen(alias) > 20) {
+ /* sanity check */
+ log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum, alias);
+ } else {
+ log_verbose("alias %d for utf-8: %s\n", aliasNum, alias);
+ }
+ }
+ if(U_SUCCESS(err)) {
+ /* try to fill an array with all aliases */
+ const char **aliases;
+ aliases=(const char **)malloc(count * sizeof(const char *));
+ if(aliases != 0) {
+ ucnv_getAliases("utf-8", aliases, &err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err));
+ } else {
+ for(aliasNum = 0; aliasNum < count; ++aliasNum) {
+ /* compare the pointers with the ones returned individually */
+ alias = ucnv_getAlias("utf-8", aliasNum, &err);
+ if(U_FAILURE(err)) {
+ log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
+ } else if(aliases[aliasNum] != alias) {
+ log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum, aliasNum);
+ }
+ }
+ }
+ free((char **)aliases);
+ }
+ }
+ }
+ }
+}
+
+
+static void TestConvert()
+{
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ char myptr[4];
+ char save[4];
+ int32_t testLong1 = 0;
+ uint16_t rest = 0;
+ int32_t len = 0;
+ int32_t x = 0;
+ FILE* ucs_file_in = NULL;
+ UChar BOM = 0x0000;
+ UChar myUChar = 0x0000;
+ char* mytarget; /* [MAX_FILE_LEN] */
+ char* mytarget_1;
+ char* mytarget_use;
+ UChar* consumedUni = NULL;
+ char* consumed = NULL;
+ char* output_cp_buffer; /* [MAX_FILE_LEN] */
+ UChar* ucs_file_buffer; /* [MAX_FILE_LEN] */
+ UChar* ucs_file_buffer_use;
+ UChar* my_ucs_file_buffer; /* [MAX_FILE_LEN] */
+ UChar* my_ucs_file_buffer_1;
+ int8_t ii = 0;
+ int32_t j = 0;
+ uint16_t codepage_index = 0;
+ int32_t cp = 0;
+ UErrorCode err = U_ZERO_ERROR;
+ char ucs_file_name[UCS_FILE_NAME_SIZE];
+ UConverterFromUCallback MIA1, MIA1_2;
+ UConverterToUCallback MIA2, MIA2_2;
+ const void *MIA1Context, *MIA1Context2, *MIA2Context, *MIA2Context2;
+ UConverter* someConverters[5];
+ UConverter* myConverter = 0;
+ UChar* displayname = 0;
+
+ const char* locale;
+
+ UChar* uchar1 = 0;
+ UChar* uchar2 = 0;
+ UChar* uchar3 = 0;
+ int32_t targetcapacity2;
+ int32_t targetcapacity;
+ int32_t targetsize;
+ int32_t disnamelen;
+
+ const UChar* tmp_ucs_buf;
+ const UChar* tmp_consumedUni=NULL;
+ const char* tmp_mytarget_use;
+ const char* tmp_consumed;
+
+ /******************************************************************
+ Checking Unicode -> ksc
+ ******************************************************************/
+
+ const char* CodePagesToTest[NUM_CODEPAGE] =
+ {
+ "ibm-949_P110-1999"
+
+
+ };
+ const uint16_t CodePageNumberToTest[NUM_CODEPAGE] =
+ {
+ 949
+ };
+
+
+ const int8_t CodePagesMinChars[NUM_CODEPAGE] =
+ {
+ 1
+
+ };
+
+ const int8_t CodePagesMaxChars[NUM_CODEPAGE] =
+ {
+ 2
+
+ };
+
+ const uint16_t CodePagesSubstitutionChars[NUM_CODEPAGE] =
+ {
+ 0xAFFE
+ };
+
+ const char* CodePagesTestFiles[NUM_CODEPAGE] =
+ {
+ "uni-text.bin"
+ };
+
+
+ const UConverterPlatform CodePagesPlatform[NUM_CODEPAGE] =
+ {
+ UCNV_IBM
+
+ };
+
+ const char* CodePagesLocale[NUM_CODEPAGE] =
+ {
+ "ko_KR"
+ };
+
+ UConverterFromUCallback oldFromUAction = NULL;
+ UConverterToUCallback oldToUAction = NULL;
+ const void* oldFromUContext = NULL;
+ const void* oldToUContext = NULL;
+
+ /* Allocate memory */
+ mytarget = (char*) malloc(MAX_FILE_LEN * sizeof(mytarget[0]));
+ output_cp_buffer = (char*) malloc(MAX_FILE_LEN * sizeof(output_cp_buffer[0]));
+ ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(ucs_file_buffer[0]));
+ my_ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(my_ucs_file_buffer[0]));
+
+ ucs_file_buffer_use = ucs_file_buffer;
+ mytarget_1=mytarget;
+ mytarget_use = mytarget;
+ my_ucs_file_buffer_1=my_ucs_file_buffer;
+
+ /* flush the converter cache to get a consistent state before the flushing is tested */
+ ucnv_flushCache();
+
+ /*Testing ucnv_openU()*/
+ {
+ UChar converterName[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
+ UChar firstSortedName[]={ 0x0021, 0x0000}; /* ! */
+ UChar lastSortedName[]={ 0x007E, 0x0000}; /* ~ */
+ const char *illegalNameChars={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
+ UChar illegalName[100];
+ UConverter *converter=NULL;
+ err=U_ZERO_ERROR;
+ converter=ucnv_openU(converterName, &err);
+ if(U_FAILURE(err)){
+ log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err));
+ }
+ ucnv_close(converter);
+ err=U_ZERO_ERROR;
+ converter=ucnv_openU(NULL, &err);
+ if(U_FAILURE(err)){
+ log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err));
+ }
+ ucnv_close(converter);
+ /*testing with error value*/
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ converter=ucnv_openU(converterName, &err);
+ if(!(converter == NULL)){
+ log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
+ }
+ ucnv_close(converter);
+ err=U_ZERO_ERROR;
+ u_uastrcpy(illegalName, "");
+ u_uastrcpy(illegalName, illegalNameChars);
+ ucnv_openU(illegalName, &err);
+ if(!(err==U_ILLEGAL_ARGUMENT_ERROR)){
+ log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
+ }
+
+ err=U_ZERO_ERROR;
+ ucnv_openU(firstSortedName, &err);
+ if(err!=U_FILE_ACCESS_ERROR){
+ log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
+ }
+
+ err=U_ZERO_ERROR;
+ ucnv_openU(lastSortedName, &err);
+ if(err!=U_FILE_ACCESS_ERROR){
+ log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
+ }
+
+ err=U_ZERO_ERROR;
+ }
+ log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
+ {
+ UConverter *cnv=NULL;
+ err=U_ZERO_ERROR;
+ cnv=ucnv_open("ibm-949,Madhu", &err);
+ if(U_FAILURE(err)){
+ log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err));
+ }
+ ucnv_close(cnv);
+
+ }
+ /*Testing ucnv_convert()*/
+ {
+ int32_t targetLimit=0, sourceLimit=0, i=0, targetCapacity=0;
+ const uint8_t source[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
+ const uint8_t expectedTarget[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
+ char *target=0;
+ sourceLimit=sizeof(source)/sizeof(source[0]);
+ err=U_ZERO_ERROR;
+ targetLimit=0;
+
+ targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", NULL, targetLimit , (const char*)source, sourceLimit, &err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err=U_ZERO_ERROR;
+ targetLimit=targetCapacity+1;
+ target=(char*)malloc(sizeof(char) * targetLimit);
+ targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
+ }
+ if(U_FAILURE(err)){
+ log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err));
+ }
+ else {
+ for(i=0; i<targetCapacity; i++){
+ if(target[i] != expectedTarget[i]){
+ log_err("FAIL: ucnv_convert(ibm-1363->ibm-1364) failed.at index \n i=%d, Expected: %lx Got: %lx\n", i, (UChar)expectedTarget[i], (uint8_t)target[i]);
+ }
+ }
+
+ i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source+1, -1, &err);
+ if(U_FAILURE(err) || i!=7){
+ log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
+ u_errorName(err), i);
+ }
+
+ /*Test error conditions*/
+ err=U_ZERO_ERROR;
+ i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, 0, &err);
+ if(i !=0){
+ log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
+ }
+
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ sourceLimit=sizeof(source)/sizeof(source[0]);
+ i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
+ if(i !=0 ){
+ log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
+ }
+
+ err=U_ZERO_ERROR;
+ sourceLimit=sizeof(source)/sizeof(source[0]);
+ targetLimit=0;
+ i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
+ if(!(U_FAILURE(err) && err==U_BUFFER_OVERFLOW_ERROR)){
+ log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ err=U_ZERO_ERROR;
+ free(target);
+ }
+ }
+
+ /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
+ log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ if(ucnv_open(NULL, &err) != NULL){
+ log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ if(ucnv_openCCSID(1051, UCNV_IBM, &err) != NULL){
+ log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ err=U_ZERO_ERROR;
+
+ /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
+ log_verbose("\n---Testing ucnv_open default...\n");
+ someConverters[0] = ucnv_open(NULL,&err);
+ someConverters[1] = ucnv_open(NULL,&err);
+ someConverters[2] = ucnv_open("utf8", &err);
+ someConverters[3] = ucnv_openCCSID(949,UCNV_IBM,&err);
+ ucnv_close(ucnv_openCCSID(1051, UCNV_IBM, &err)); /* test for j350; ucnv_close(NULL) is safe */
+ if (U_FAILURE(err)){ log_data_err("FAILURE! %s\n", myErrorName(err));}
+
+ /* Testing ucnv_getName()*/
+ /*default code page */
+ ucnv_getName(someConverters[0], &err);
+ if(U_FAILURE(err)) {
+ log_data_err("getName[0] failed\n");
+ } else {
+ log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters[0], &err));
+ }
+ ucnv_getName(someConverters[1], &err);
+ if(U_FAILURE(err)) {
+ log_data_err("getName[1] failed\n");
+ } else {
+ log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err));
+ }
+
+ ucnv_close(someConverters[0]);
+ ucnv_close(someConverters[1]);
+ ucnv_close(someConverters[2]);
+ ucnv_close(someConverters[3]);
+
+
+ for (codepage_index=0; codepage_index < NUM_CODEPAGE; ++codepage_index)
+ {
+ int32_t i = 0;
+
+ err = U_ZERO_ERROR;
+#ifdef U_TOPSRCDIR
+ strcpy(ucs_file_name, U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING);
+#else
+ strcpy(ucs_file_name, loadTestData(&err));
+
+ if(U_FAILURE(err)){
+ log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err));
+ return;
+ }
+
+ {
+ char* index = strrchr(ucs_file_name,(char)U_FILE_SEP_CHAR);
+
+ if((unsigned int)(index-ucs_file_name) != (strlen(ucs_file_name)-1)){
+ *(index+1)=0;
+ }
+ }
+
+ strcat(ucs_file_name,".."U_FILE_SEP_STRING);
+#endif
+ strcat(ucs_file_name, CodePagesTestFiles[codepage_index]);
+
+ ucs_file_in = fopen(ucs_file_name,"rb");
+ if (!ucs_file_in)
+ {
+ log_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name);
+ return;
+ }
+
+ /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
+
+ /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
+ /* ucnv_flushCache(); */
+ myConverter =ucnv_open( "ibm-949", &err);
+ if (!myConverter || U_FAILURE(err))
+ {
+ log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err));
+
+ return;
+ }
+
+ /*testing for ucnv_getName() */
+ log_verbose("Testing ucnv_getName()...\n");
+ ucnv_getName(myConverter, &err);
+ if(U_FAILURE(err))
+ log_err("Error in getName\n");
+ else
+ {
+ log_verbose("getName o.k. %s\n", ucnv_getName(myConverter, &err));
+ }
+ if (ctest_stricmp(ucnv_getName(myConverter, &err), CodePagesToTest[codepage_index]))
+ log_err("getName failed\n");
+ else
+ log_verbose("getName ok\n");
+ /*Test getName with error condition*/
+ {
+ const char* name=0;
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
+ name=ucnv_getName(myConverter, &err);
+ if(name != NULL){
+ log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
+ }
+ err=U_ZERO_ERROR;
+ }
+
+
+ /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
+
+ log_verbose("Testing ucnv_getMaxCharSize()...\n");
+ if (ucnv_getMaxCharSize(myConverter)==CodePagesMaxChars[codepage_index])
+ log_verbose("Max byte per character OK\n");
+ else
+ log_err("Max byte per character failed\n");
+
+ log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
+ if (ucnv_getMinCharSize(myConverter)==CodePagesMinChars[codepage_index])
+ log_verbose("Min byte per character OK\n");
+ else
+ log_err("Min byte per character failed\n");
+
+
+ /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
+ log_verbose("\n---Testing ucnv_getSubstChars...\n");
+ ii=4;
+ ucnv_getSubstChars(myConverter, myptr, &ii, &err);
+ if (ii <= 0) {
+ log_err("ucnv_getSubstChars returned a negative number %d\n", ii);
+ }
+
+ for(x=0;x<ii;x++)
+ rest = (uint16_t)(((unsigned char)rest << 8) + (unsigned char)myptr[x]);
+ if (rest==CodePagesSubstitutionChars[codepage_index])
+ log_verbose("Substitution character ok\n");
+ else
+ log_err("Substitution character failed.\n");
+
+ log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
+ ucnv_setSubstChars(myConverter, myptr, ii, &err);
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+ ucnv_getSubstChars(myConverter,save, &ii, &err);
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ if (strncmp(save, myptr, ii))
+ log_err("Saved substitution character failed\n");
+ else
+ log_verbose("Saved substitution character ok\n");
+
+ /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
+ log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
+ ii=1;
+ ucnv_getSubstChars(myConverter, myptr, &ii, &err);
+ if(err != U_INDEX_OUTOFBOUNDS_ERROR){
+ log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err));
+ }
+ err=U_ZERO_ERROR;
+ ii=4;
+ ucnv_getSubstChars(myConverter, myptr, &ii, &err);
+ log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
+ ucnv_setSubstChars(myConverter, myptr, 0, &err);
+ if(err != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err));
+ }
+ log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
+ strcpy(myptr, "abc");
+ ucnv_setSubstChars(myConverter, myptr, ii, &err);
+ err=U_ZERO_ERROR;
+ ucnv_getSubstChars(myConverter, save, &ii, &err);
+ if(strncmp(save, myptr, ii) == 0){
+ log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
+ }
+ log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
+ err=U_ZERO_ERROR;
+ strcpy(myptr, "abc");
+ ucnv_setSubstChars(myConverter, myptr, ii, &err);
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ ucnv_getSubstChars(myConverter, save, &ii, &err);
+ if(strncmp(save, myptr, ii) == 0){
+ log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
+ }
+ err=U_ZERO_ERROR;
+ /*------*/
+
+#ifdef U_ENABLE_GENERIC_ISO_2022
+ /*resetState ucnv_reset()*/
+ log_verbose("\n---Testing ucnv_reset()..\n");
+ ucnv_reset(myConverter);
+ {
+ UChar32 c;
+ const uint8_t in[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UConverter *cnv=ucnv_open("ISO_2022", &err);
+ if(U_FAILURE(err)) {
+ log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
+ }
+ c=ucnv_getNextUChar(cnv, &source, limit, &err);
+ if((U_FAILURE(err) || c != (UChar32)0x0031)) {
+ log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err));
+ }
+ ucnv_reset(cnv);
+ ucnv_close(cnv);
+
+ }
+#endif
+
+ /*getDisplayName*/
+ log_verbose("\n---Testing ucnv_getDisplayName()...\n");
+ locale=CodePagesLocale[codepage_index];
+ len=0;
+ displayname=NULL;
+ disnamelen = ucnv_getDisplayName(myConverter, locale, displayname, len, &err);
+ if(err==U_BUFFER_OVERFLOW_ERROR) {
+ err=U_ZERO_ERROR;
+ displayname=(UChar*)malloc((disnamelen+1) * sizeof(UChar));
+ ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
+ if(U_FAILURE(err)) {
+ log_err("getDisplayName failed. The error is %s\n", myErrorName(err));
+ }
+ else {
+ log_verbose(" getDisplayName o.k.\n");
+ }
+ free(displayname);
+ displayname=NULL;
+ }
+ else {
+ log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err));
+ }
+ /*test ucnv_getDiaplayName with error condition*/
+ err= U_ILLEGAL_ARGUMENT_ERROR;
+ len=ucnv_getDisplayName(myConverter,locale,NULL,0, &err);
+ if( len !=0 ){
+ log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
+ }
+ /*test ucnv_getDiaplayName with error condition*/
+ err=U_ZERO_ERROR;
+ len=ucnv_getDisplayName(NULL,locale,NULL,0, &err);
+ if( len !=0 || U_SUCCESS(err)){
+ log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
+ }
+ err=U_ZERO_ERROR;
+
+ /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
+ ucnv_getFromUCallBack(myConverter, &MIA1, &MIA1Context);
+
+ log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
+ ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
+ if (U_FAILURE(err) || oldFromUAction != MIA1 || oldFromUContext != MIA1Context)
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
+ if (MIA1_2 != otherUnicodeAction(MIA1) || MIA1Context2 != &BOM)
+ log_err("get From UCallBack failed\n");
+ else
+ log_verbose("get From UCallBack ok\n");
+
+ log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
+ ucnv_setFromUCallBack(myConverter,MIA1, MIA1Context, &oldFromUAction, &oldFromUContext, &err);
+ if (U_FAILURE(err) || oldFromUAction != otherUnicodeAction(MIA1) || oldFromUContext != &BOM)
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
+ if (MIA1_2 != MIA1 || MIA1Context2 != MIA1Context)
+ log_err("get From UCallBack action failed\n");
+ else
+ log_verbose("get From UCallBack action ok\n");
+
+ /*testing ucnv_setToUCallBack with error conditions*/
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
+ ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
+ ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
+ if(MIA1_2 == otherUnicodeAction(MIA1) || MIA1Context2 == &BOM){
+ log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ err=U_ZERO_ERROR;
+
+
+ /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
+ ucnv_getToUCallBack(myConverter, &MIA2, &MIA2Context);
+
+ log_verbose("\n---Testing setTo UCallBack...\n");
+ ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), &BOM, &oldToUAction, &oldToUContext, &err);
+ if (U_FAILURE(err) || oldToUAction != MIA2 || oldToUContext != MIA2Context)
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
+ if (MIA2_2 != otherCharAction(MIA2) || MIA2Context2 != &BOM)
+ log_err("To UCallBack failed\n");
+ else
+ log_verbose("To UCallBack ok\n");
+
+ log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
+ ucnv_setToUCallBack(myConverter,MIA2, MIA2Context, &oldToUAction, &oldToUContext, &err);
+ if (U_FAILURE(err) || oldToUAction != otherCharAction(MIA2) || oldToUContext != &BOM)
+ { log_err("FAILURE! %s\n", myErrorName(err)); }
+
+ ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
+ if (MIA2_2 != MIA2 || MIA2Context2 != MIA2Context)
+ log_err("To UCallBack failed\n");
+ else
+ log_verbose("To UCallBack ok\n");
+
+ /*testing ucnv_setToUCallBack with error conditions*/
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
+ ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), NULL, &oldToUAction, &oldToUContext, &err);
+ ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
+ if (MIA2_2 == otherCharAction(MIA2) || MIA2Context2 == &BOM){
+ log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ err=U_ZERO_ERROR;
+
+
+ /*getcodepageid testing ucnv_getCCSID() */
+ log_verbose("\n----Testing getCCSID....\n");
+ cp = ucnv_getCCSID(myConverter,&err);
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE!..... %s\n", myErrorName(err));
+ }
+ if (cp != CodePageNumberToTest[codepage_index])
+ log_err("Codepage number test failed\n");
+ else
+ log_verbose("Codepage number test OK\n");
+
+ /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ if( ucnv_getCCSID(myConverter,&err) != -1){
+ log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ err=U_ZERO_ERROR;
+
+ /*getCodepagePlatform testing ucnv_getPlatform()*/
+ log_verbose("\n---Testing getCodepagePlatform ..\n");
+ if (CodePagesPlatform[codepage_index]!=ucnv_getPlatform(myConverter, &err))
+ log_err("Platform codepage test failed\n");
+ else
+ log_verbose("Platform codepage test ok\n");
+
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+ /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
+ err= U_ILLEGAL_ARGUMENT_ERROR;
+ if(ucnv_getPlatform(myConverter, &err) != UCNV_UNKNOWN){
+ log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
+ }
+ err=U_ZERO_ERROR;
+
+
+ /*Reads the BOM*/
+ fread(&BOM, sizeof(UChar), 1, ucs_file_in);
+ if (BOM!=0xFEFF && BOM!=0xFFFE)
+ {
+ log_err("File Missing BOM...Bailing!\n");
+ return;
+ }
+
+
+ /*Reads in the file*/
+ while(!feof(ucs_file_in)&&(i+=fread(ucs_file_buffer+i, sizeof(UChar), 1, ucs_file_in)))
+ {
+ myUChar = ucs_file_buffer[i-1];
+
+ ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN*/
+ }
+
+ myUChar = ucs_file_buffer[i-1];
+ ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN Corner Case*/
+
+
+ /*testing ucnv_fromUChars() and ucnv_toUChars() */
+ /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
+
+ uchar1=(UChar*)malloc(sizeof(UChar) * (i+1));
+ u_uastrcpy(uchar1,"");
+ u_strncpy(uchar1,ucs_file_buffer,i);
+ uchar1[i] = 0;
+
+ uchar3=(UChar*)malloc(sizeof(UChar)*(i+1));
+ u_uastrcpy(uchar3,"");
+ u_strncpy(uchar3,ucs_file_buffer,i);
+ uchar3[i] = 0;
+
+ /*Calls the Conversion Routine */
+ testLong1 = MAX_FILE_LEN;
+ log_verbose("\n---Testing ucnv_fromUChars()\n");
+ targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
+ if (U_FAILURE(err))
+ {
+ log_err("\nFAILURE...%s\n", myErrorName(err));
+ }
+ else
+ log_verbose(" ucnv_fromUChars() o.k.\n");
+
+ /*test the conversion routine */
+ log_verbose("\n---Testing ucnv_toUChars()\n");
+ /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
+ targetcapacity2=0;
+ targetsize = ucnv_toUChars(myConverter,
+ NULL,
+ targetcapacity2,
+ output_cp_buffer,
+ strlen(output_cp_buffer),
+ &err);
+ /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
+
+ if(err==U_BUFFER_OVERFLOW_ERROR)
+ {
+ err=U_ZERO_ERROR;
+ uchar2=(UChar*)malloc((targetsize+1) * sizeof(UChar));
+ targetsize = ucnv_toUChars(myConverter,
+ uchar2,
+ targetsize+1,
+ output_cp_buffer,
+ strlen(output_cp_buffer),
+ &err);
+
+ if(U_FAILURE(err))
+ log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err));
+ else
+ log_verbose(" ucnv_toUChars() o.k.\n");
+
+ if(u_strcmp(uchar1,uchar2)!=0)
+ log_err("equality test failed with conversion routine\n");
+ }
+ else
+ {
+ log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
+ }
+ /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
+ err=U_ILLEGAL_ARGUMENT_ERROR;
+ log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
+ targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
+ if (targetcapacity !=0) {
+ log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
+ }
+ err=U_ZERO_ERROR;
+ log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
+ targetcapacity = ucnv_fromUChars(NULL, output_cp_buffer, testLong1, uchar1, -1, &err);
+ if (targetcapacity !=0 || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
+ }
+ err=U_ZERO_ERROR;
+ log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
+ targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, 0, &err);
+ if (targetcapacity !=0) {
+ log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
+ }
+ log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
+ targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, 0, uchar1, -1, &err);
+ if (err != U_BUFFER_OVERFLOW_ERROR) {
+ log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ /*toUChars with error conditions*/
+ targetsize = ucnv_toUChars(myConverter, uchar2, targetsize, output_cp_buffer, strlen(output_cp_buffer), &err);
+ if(targetsize != 0){
+ log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
+ }
+ err=U_ZERO_ERROR;
+ targetsize = ucnv_toUChars(myConverter, uchar2, -1, output_cp_buffer, strlen(output_cp_buffer), &err);
+ if(targetsize != 0 || err != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
+ }
+ err=U_ZERO_ERROR;
+ targetsize = ucnv_toUChars(myConverter, uchar2, 0, output_cp_buffer, 0, &err);
+ if (targetsize !=0) {
+ log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
+ }
+ targetcapacity2=0;
+ targetsize = ucnv_toUChars(myConverter, NULL, targetcapacity2, output_cp_buffer, strlen(output_cp_buffer), &err);
+ if (err != U_STRING_NOT_TERMINATED_WARNING) {
+ log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
+ u_errorName(err));
+ }
+ err=U_ZERO_ERROR;
+ /*-----*/
+
+
+ /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
+ /*Clean up re-usable vars*/
+ j=0;
+ log_verbose("Testing ucnv_fromUnicode().....\n");
+ tmp_ucs_buf=ucs_file_buffer_use;
+ ucnv_fromUnicode(myConverter, &mytarget_1,
+ mytarget + MAX_FILE_LEN,
+ &tmp_ucs_buf,
+ ucs_file_buffer_use+i,
+ NULL,
+ TRUE,
+ &err);
+ consumedUni = (UChar*)tmp_consumedUni;
+
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+ else
+ log_verbose("ucnv_fromUnicode() o.k.\n");
+
+ /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
+ log_verbose("Testing ucnv_toUnicode().....\n");
+ tmp_mytarget_use=mytarget_use;
+ tmp_consumed = consumed;
+ ucnv_toUnicode(myConverter, &my_ucs_file_buffer_1,
+ my_ucs_file_buffer + MAX_FILE_LEN,
+ &tmp_mytarget_use,
+ mytarget_use + (mytarget_1 - mytarget),
+ NULL,
+ FALSE,
+ &err);
+ consumed = (char*)tmp_consumed;
+ if (U_FAILURE(err))
+ {
+ log_err("FAILURE! %s\n", myErrorName(err));
+ }
+ else
+ log_verbose("ucnv_toUnicode() o.k.\n");
+
+
+ log_verbose("\n---Testing RoundTrip ...\n");
+
+
+ u_strncpy(uchar3, my_ucs_file_buffer,i);
+ uchar3[i] = 0;
+
+ if(u_strcmp(uchar1,uchar3)==0)
+ log_verbose("Equality test o.k.\n");
+ else
+ log_err("Equality test failed\n");
+
+ /*sanity compare */
+ if(uchar2 == NULL)
+ {
+ log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__);
+ }
+ else
+ {
+ if(u_strcmp(uchar2, uchar3)==0)
+ log_verbose("Equality test o.k.\n");
+ else
+ log_err("Equality test failed\n");
+ }
+
+ fclose(ucs_file_in);
+ ucnv_close(myConverter);
+ if (uchar1 != 0) free(uchar1);
+ if (uchar2 != 0) free(uchar2);
+ if (uchar3 != 0) free(uchar3);
+ }
+
+ free((void*)mytarget);
+ free((void*)output_cp_buffer);
+ free((void*)ucs_file_buffer);
+ free((void*)my_ucs_file_buffer);
+#endif
+}
+
+static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA)
+{
+ return (MIA==(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP)?(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_SUBSTITUTE:(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP;
+}
+
+
+static UConverterToUCallback otherCharAction(UConverterToUCallback MIA)
+{
+ return (MIA==(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP)?(UConverterToUCallback)UCNV_TO_U_CALLBACK_SUBSTITUTE:(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP;
+}
+
+static void TestFlushCache(void) {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* someConverters[5];
+ int flushCount = 0;
+
+ /* flush the converter cache to get a consistent state before the flushing is tested */
+ ucnv_flushCache();
+
+ /*Testing ucnv_open()*/
+ /* Note: These converters have been chosen because they do NOT
+ encode the Latin characters (U+0041, ...), and therefore are
+ highly unlikely to be chosen as system default codepages */
+
+ someConverters[0] = ucnv_open("ibm-1047", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ someConverters[1] = ucnv_open("ibm-1047", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ someConverters[2] = ucnv_open("ibm-1047", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ someConverters[3] = ucnv_open("gb18030", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+ someConverters[4] = ucnv_open("ibm-954", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("FAILURE! %s\n", myErrorName(err));
+ }
+
+
+ /* Testing ucnv_flushCache() */
+ log_verbose("\n---Testing ucnv_flushCache...\n");
+ if ((flushCount=ucnv_flushCache())==0)
+ log_verbose("Flush cache ok\n");
+ else
+ log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
+
+ /*testing ucnv_close() and ucnv_flushCache() */
+ ucnv_close(someConverters[0]);
+ ucnv_close(someConverters[1]);
+
+ if ((flushCount=ucnv_flushCache())==0)
+ log_verbose("Flush cache ok\n");
+ else
+ log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
+
+ ucnv_close(someConverters[2]);
+ ucnv_close(someConverters[3]);
+
+ if ((flushCount=ucnv_flushCache())==2)
+ log_verbose("Flush cache ok\n"); /*because first, second and third are same */
+ else
+ log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
+ __LINE__,
+ flushCount);
+
+ ucnv_close(someConverters[4]);
+ if ( (flushCount=ucnv_flushCache())==1)
+ log_verbose("Flush cache ok\n");
+ else
+ log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount);
+#endif
+}
+
+/**
+ * Test the converter alias API, specifically the fuzzy matching of
+ * alias names and the alias table integrity. Make sure each
+ * converter has at least one alias (itself), and that its listed
+ * aliases map back to itself. Check some hard-coded UTF-8 and
+ * ISO_2022 aliases to make sure they work.
+ */
+static void TestAlias() {
+ int32_t i, ncnv;
+ UErrorCode status = U_ZERO_ERROR;
+
+ /* Predetermined aliases that we expect to map back to ISO_2022
+ * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
+ const char* ISO_2022_NAMES[] =
+ {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
+ "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
+ int32_t ISO_2022_NAMES_LENGTH =
+ sizeof(ISO_2022_NAMES) / sizeof(ISO_2022_NAMES[0]);
+ const char *UTF8_NAMES[] =
+ { "UTF-8", "utf-8", "utf8", "ibm-1208",
+ "utf_8", "ibm1208", "cp1208" };
+ int32_t UTF8_NAMES_LENGTH =
+ sizeof(UTF8_NAMES) / sizeof(UTF8_NAMES[0]);
+
+ struct {
+ const char *name;
+ const char *alias;
+ } CONVERTERS_NAMES[] = {
+ { "UTF-32BE", "UTF32_BigEndian" },
+ { "UTF-32LE", "UTF32_LittleEndian" },
+ { "UTF-32", "ISO-10646-UCS-4" },
+ { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
+ { "UTF-32", "ucs-4" }
+ };
+ int32_t CONVERTERS_NAMES_LENGTH = sizeof(CONVERTERS_NAMES) / sizeof(*CONVERTERS_NAMES);
+
+ /* When there are bugs in gencnval or in ucnv_io, converters can
+ appear to have no aliases. */
+ ncnv = ucnv_countAvailable();
+ log_verbose("%d converters\n", ncnv);
+ for (i=0; i<ncnv; ++i) {
+ const char *name = ucnv_getAvailableName(i);
+ const char *alias0;
+ uint16_t na = ucnv_countAliases(name, &status);
+ uint16_t j;
+ UConverter *cnv;
+
+ if (na == 0) {
+ log_err("FAIL: Converter \"%s\" (i=%d)"
+ " has no aliases; expect at least one\n",
+ name, i);
+ continue;
+ }
+ cnv = ucnv_open(name, &status);
+ if (U_FAILURE(status)) {
+ log_data_err("FAIL: Converter \"%s\" (i=%d)"
+ " can't be opened.\n",
+ name, i);
+ }
+ else {
+ if (strcmp(ucnv_getName(cnv, &status), name) != 0
+ && (strstr(name, "PlatformEndian") == 0 && strstr(name, "OppositeEndian") == 0)) {
+ log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
+ "The should be the same\n",
+ name, ucnv_getName(cnv, &status));
+ }
+ }
+ ucnv_close(cnv);
+
+ status = U_ZERO_ERROR;
+ alias0 = ucnv_getAlias(name, 0, &status);
+ for (j=1; j<na; ++j) {
+ const char *alias;
+ /* Make sure each alias maps back to the the same list of
+ aliases. Assume that if alias 0 is the same, the whole
+ list is the same (this should always be true). */
+ const char *mapBack;
+
+ status = U_ZERO_ERROR;
+ alias = ucnv_getAlias(name, j, &status);
+ if (status == U_AMBIGUOUS_ALIAS_WARNING) {
+ log_err("FAIL: Converter \"%s\"is ambiguous\n", name);
+ }
+
+ if (alias == NULL) {
+ log_err("FAIL: Converter \"%s\" -> "
+ "alias[%d]=NULL\n",
+ name, j);
+ continue;
+ }
+
+ mapBack = ucnv_getAlias(alias, 0, &status);
+
+ if (mapBack == NULL) {
+ log_err("FAIL: Converter \"%s\" -> "
+ "alias[%d]=\"%s\" -> "
+ "alias[0]=NULL, exp. \"%s\"\n",
+ name, j, alias, alias0);
+ continue;
+ }
+
+ if (0 != strcmp(alias0, mapBack)) {
+ int32_t idx;
+ UBool foundAlias = FALSE;
+ if (status == U_AMBIGUOUS_ALIAS_WARNING) {
+ /* Make sure that we only get this mismapping when there is
+ an ambiguous alias, and the other converter has this alias too. */
+ for (idx = 0; idx < ucnv_countAliases(mapBack, &status); idx++) {
+ if (strcmp(ucnv_getAlias(mapBack, (uint16_t)idx, &status), alias) == 0) {
+ foundAlias = TRUE;
+ break;
+ }
+ }
+ }
+ /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
+
+ if (!foundAlias) {
+ log_err("FAIL: Converter \"%s\" -> "
+ "alias[%d]=\"%s\" -> "
+ "alias[0]=\"%s\", exp. \"%s\"\n",
+ name, j, alias, mapBack, alias0);
+ }
+ }
+ }
+ }
+
+
+ /* Check a list of predetermined aliases that we expect to map
+ * back to ISO_2022 and UTF-8. */
+ for (i=1; i<ISO_2022_NAMES_LENGTH; ++i) {
+ const char* mapBack = ucnv_getAlias(ISO_2022_NAMES[i], 0, &status);
+ if(!mapBack) {
+ log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES[i]);
+ continue;
+ }
+ if (0 != strcmp(mapBack, ISO_2022_NAMES[0])) {
+ log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
+ ISO_2022_NAMES[i], mapBack);
+ }
+ }
+
+
+ for (i=1; i<UTF8_NAMES_LENGTH; ++i) {
+ const char* mapBack = ucnv_getAlias(UTF8_NAMES[i], 0, &status);
+ if(!mapBack) {
+ log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES[i]);
+ continue;
+ }
+ if (mapBack && 0 != strcmp(mapBack, UTF8_NAMES[0])) {
+ log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
+ UTF8_NAMES[i], mapBack);
+ }
+ }
+
+ /*
+ * Check a list of predetermined aliases that we expect to map
+ * back to predermined converter names.
+ */
+
+ for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) {
+ const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status);
+ if(!mapBack) {
+ log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i].name);
+ continue;
+ }
+ if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) {
+ log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
+ CONVERTERS_NAMES[i].alias, mapBack, CONVERTERS_NAMES[i].name);
+ }
+ }
+
+}
+
+static void TestDuplicateAlias(void) {
+ const char *alias;
+ UErrorCode status = U_ZERO_ERROR;
+
+ status = U_ZERO_ERROR;
+ alias = ucnv_getStandardName("Shift_JIS", "IBM", &status);
+ if (alias == NULL || strcmp(alias, "ibm-943") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
+ log_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias);
+ }
+ status = U_ZERO_ERROR;
+ alias = ucnv_getStandardName("ibm-943", "IANA", &status);
+ if (alias == NULL || strcmp(alias, "Shift_JIS") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
+ log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias);
+ }
+ status = U_ZERO_ERROR;
+ alias = ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status);
+ if (alias != NULL || status == U_AMBIGUOUS_ALIAS_WARNING) {
+ log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias);
+ }
+}
+
+
+/* Test safe clone callback */
+
+static uint32_t TSCC_nextSerial()
+{
+ static uint32_t n = 1;
+
+ return (n++);
+}
+
+typedef struct
+{
+ uint32_t magic; /* 0xC0FFEE to identify that the object is OK */
+ uint32_t serial; /* minted from nextSerial, above */
+ UBool wasClosed; /* close happened on the object */
+} TSCCContext;
+
+static TSCCContext *TSCC_clone(TSCCContext *ctx)
+{
+ TSCCContext *newCtx = (TSCCContext *)malloc(sizeof(TSCCContext));
+
+ newCtx->serial = TSCC_nextSerial();
+ newCtx->wasClosed = 0;
+ newCtx->magic = 0xC0FFEE;
+
+ log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
+
+ return newCtx;
+}
+
+static void TSCC_fromU(const void *context,
+ UConverterFromUnicodeArgs *fromUArgs,
+ const UChar* codeUnits,
+ int32_t length,
+ UChar32 codePoint,
+ UConverterCallbackReason reason,
+ UErrorCode * err)
+{
+ TSCCContext *ctx = (TSCCContext*)context;
+ UConverterFromUCallback junkFrom;
+
+ log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, fromUArgs->converter);
+
+ if(ctx->magic != 0xC0FFEE) {
+ log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
+ return;
+ }
+
+ if(reason == UCNV_CLONE) {
+ UErrorCode subErr = U_ZERO_ERROR;
+ TSCCContext *newCtx;
+ TSCCContext *junkCtx;
+ TSCCContext **pjunkCtx = &junkCtx;
+
+ /* "recreate" it */
+ log_verbose("TSCC_fromU: cloning..\n");
+ newCtx = TSCC_clone(ctx);
+
+ if(newCtx == NULL) {
+ log_err("TSCC_fromU: internal clone failed on %p\n", ctx);
+ }
+
+ /* now, SET it */
+ ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)pjunkCtx);
+ ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
+
+ if(U_FAILURE(subErr)) {
+ *err = subErr;
+ }
+ }
+
+ if(reason == UCNV_CLOSE) {
+ log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx, ctx->serial);
+ ctx->wasClosed = TRUE;
+ }
+}
+
+
+static void TSCC_toU(const void *context,
+ UConverterToUnicodeArgs *toUArgs,
+ const char* codeUnits,
+ int32_t length,
+ UConverterCallbackReason reason,
+ UErrorCode * err)
+{
+ TSCCContext *ctx = (TSCCContext*)context;
+ UConverterToUCallback junkFrom;
+
+ log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, toUArgs->converter);
+
+ if(ctx->magic != 0xC0FFEE) {
+ log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
+ return;
+ }
+
+ if(reason == UCNV_CLONE) {
+ UErrorCode subErr = U_ZERO_ERROR;
+ TSCCContext *newCtx;
+ TSCCContext *junkCtx;
+ TSCCContext **pjunkCtx = &junkCtx;
+
+ /* "recreate" it */
+ log_verbose("TSCC_toU: cloning..\n");
+ newCtx = TSCC_clone(ctx);
+
+ if(newCtx == NULL) {
+ log_err("TSCC_toU: internal clone failed on %p\n", ctx);
+ }
+
+ /* now, SET it */
+ ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)pjunkCtx);
+ ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
+
+ if(U_FAILURE(subErr)) {
+ *err = subErr;
+ }
+ }
+
+ if(reason == UCNV_CLOSE) {
+ log_verbose("TSCC_toU: Context %p:%d closing\n", ctx, ctx->serial);
+ ctx->wasClosed = TRUE;
+ }
+}
+
+static void TSCC_init(TSCCContext *q)
+{
+ q->magic = 0xC0FFEE;
+ q->serial = TSCC_nextSerial();
+ q->wasClosed = 0;
+}
+
+static void TSCC_print_log(TSCCContext *q, const char *name)
+{
+ if(q==NULL) {
+ log_verbose("TSCContext: %s is NULL!!\n", name);
+ } else {
+ if(q->magic != 0xC0FFEE) {
+ log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
+ q,q->serial, q->magic);
+ }
+ log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
+ q, q->serial, name, q->magic, q->wasClosed?"CLOSED":"open");
+ }
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestConvertSafeCloneCallback()
+{
+ UErrorCode err = U_ZERO_ERROR;
+ TSCCContext from1, to1;
+ TSCCContext *from2, *from3, *to2, *to3;
+ TSCCContext **pfrom2 = &from2, **pfrom3 = &from3, **pto2 = &to2, **pto3 = &to3;
+ char hunk[8192];
+ int32_t hunkSize = 8192;
+ UConverterFromUCallback junkFrom;
+ UConverterToUCallback junkTo;
+ UConverter *conv1, *conv2 = NULL;
+
+ conv1 = ucnv_open("iso-8859-3", &err);
+
+ if(U_FAILURE(err)) {
+ log_data_err("Err opening iso-8859-3, %s", u_errorName(err));
+ return;
+ }
+
+ log_verbose("Opened conv1=%p\n", conv1);
+
+ TSCC_init(&from1);
+ TSCC_init(&to1);
+
+ TSCC_print_log(&from1, "from1");
+ TSCC_print_log(&to1, "to1");
+
+ ucnv_setFromUCallBack(conv1, TSCC_fromU, &from1, NULL, NULL, &err);
+ log_verbose("Set from1 on conv1\n");
+ TSCC_print_log(&from1, "from1");
+
+ ucnv_setToUCallBack(conv1, TSCC_toU, &to1, NULL, NULL, &err);
+ log_verbose("Set to1 on conv1\n");
+ TSCC_print_log(&to1, "to1");
+
+ conv2 = ucnv_safeClone(conv1, hunk, &hunkSize, &err);
+ if(U_FAILURE(err)) {
+ log_err("safeClone failed: %s\n", u_errorName(err));
+ return;
+ }
+ log_verbose("Cloned to conv2=%p.\n", conv2);
+
+/********** from *********************/
+ ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)pfrom2);
+ ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)pfrom3);
+
+ TSCC_print_log(from2, "from2");
+ TSCC_print_log(from3, "from3(==from1)");
+
+ if(from2 == NULL) {
+ log_err("FAIL! from2 is null \n");
+ return;
+ }
+
+ if(from3 == NULL) {
+ log_err("FAIL! from3 is null \n");
+ return;
+ }
+
+ if(from3 != (&from1) ) {
+ log_err("FAIL! conv1's FROM context changed!\n");
+ }
+
+ if(from2 == (&from1) ) {
+ log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
+ }
+
+ if(from1.wasClosed) {
+ log_err("FAIL! from1 is closed \n");
+ }
+
+ if(from2->wasClosed) {
+ log_err("FAIL! from2 was closed\n");
+ }
+
+/********** to *********************/
+ ucnv_getToUCallBack(conv2, &junkTo, (const void**)pto2);
+ ucnv_getToUCallBack(conv1, &junkTo, (const void**)pto3);
+
+ TSCC_print_log(to2, "to2");
+ TSCC_print_log(to3, "to3(==to1)");
+
+ if(to2 == NULL) {
+ log_err("FAIL! to2 is null \n");
+ return;
+ }
+
+ if(to3 == NULL) {
+ log_err("FAIL! to3 is null \n");
+ return;
+ }
+
+ if(to3 != (&to1) ) {
+ log_err("FAIL! conv1's TO context changed!\n");
+ }
+
+ if(to2 == (&to1) ) {
+ log_err("FAIL! conv1's TO context is the same as conv2's!\n");
+ }
+
+ if(to1.wasClosed) {
+ log_err("FAIL! to1 is closed \n");
+ }
+
+ if(to2->wasClosed) {
+ log_err("FAIL! to2 was closed\n");
+ }
+
+/*************************************/
+
+ ucnv_close(conv1);
+ log_verbose("ucnv_closed (conv1)\n");
+ TSCC_print_log(&from1, "from1");
+ TSCC_print_log(from2, "from2");
+ TSCC_print_log(&to1, "to1");
+ TSCC_print_log(to2, "to2");
+
+ if(from1.wasClosed == FALSE) {
+ log_err("FAIL! from1 is NOT closed \n");
+ }
+
+ if(from2->wasClosed) {
+ log_err("FAIL! from2 was closed\n");
+ }
+
+ if(to1.wasClosed == FALSE) {
+ log_err("FAIL! to1 is NOT closed \n");
+ }
+
+ if(to2->wasClosed) {
+ log_err("FAIL! to2 was closed\n");
+ }
+
+ ucnv_close(conv2);
+ log_verbose("ucnv_closed (conv2)\n");
+
+ TSCC_print_log(&from1, "from1");
+ TSCC_print_log(from2, "from2");
+
+ if(from1.wasClosed == FALSE) {
+ log_err("FAIL! from1 is NOT closed \n");
+ }
+
+ if(from2->wasClosed == FALSE) {
+ log_err("FAIL! from2 was NOT closed\n");
+ }
+
+ TSCC_print_log(&to1, "to1");
+ TSCC_print_log(to2, "to2");
+
+ if(to1.wasClosed == FALSE) {
+ log_err("FAIL! to1 is NOT closed \n");
+ }
+
+ if(to2->wasClosed == FALSE) {
+ log_err("FAIL! to2 was NOT closed\n");
+ }
+
+ if(to2 != (&to1)) {
+ free(to2); /* to1 is stack based */
+ }
+ if(from2 != (&from1)) {
+ free(from2); /* from1 is stack based */
+ }
+}
+#endif
+
+static UBool
+containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) {
+ while(length>0) {
+ if(*p!=b) {
+ return TRUE;
+ }
+ ++p;
+ --length;
+ }
+ return FALSE;
+}
+
+static void TestConvertSafeClone()
+{
+ /* one 'regular' & all the 'private stateful' converters */
+ static const char *const names[] = {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "ibm-1047",
+ "ISO_2022,locale=zh,version=1",
+#endif
+ "SCSU",
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "HZ",
+ "lmbcs",
+ "ISCII,version=0",
+ "ISO_2022,locale=kr,version=1",
+ "ISO_2022,locale=jp,version=2",
+#endif
+ "BOCU-1",
+ "UTF-7",
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "IMAP-mailbox-name",
+ "ibm-1047-s390"
+#else
+ "IMAP=mailbox-name"
+#endif
+ };
+
+ /* store the actual sizes of each converter */
+ int32_t actualSizes[LENGTHOF(names)];
+
+ static const int32_t bufferSizes[] = {
+ U_CNV_SAFECLONE_BUFFERSIZE,
+ (int32_t)(3*sizeof(UConverter))/2, /* 1.5*sizeof(UConverter) */
+ (int32_t)sizeof(UConverter)/2 /* 0.5*sizeof(UConverter) */
+ };
+
+ char charBuffer[21]; /* Leave at an odd number for alignment testing */
+ uint8_t buffer[3] [U_CNV_SAFECLONE_BUFFERSIZE];
+ int32_t bufferSize, maxBufferSize;
+ const char *maxName;
+ UConverter * cnv, *cnv2;
+ UErrorCode err;
+
+ char *pCharBuffer;
+ const char *pConstCharBuffer;
+ const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
+ UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
+ UChar uniCharBuffer[20];
+ char charSourceBuffer[] = { 0x1b, 0x24, 0x42 };
+ const char *pCharSource = charSourceBuffer;
+ const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
+ UChar *pUCharTarget = uniCharBuffer;
+ UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer)/sizeof(*uniCharBuffer);
+ const UChar * pUniBuffer;
+ const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
+ int32_t index, j;
+
+ err = U_ZERO_ERROR;
+ cnv = ucnv_open(names[0], &err);
+ if(U_SUCCESS(err)) {
+ /* Check the various error & informational states: */
+
+ /* Null status - just returns NULL */
+ bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
+ if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, 0))
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
+ }
+ /* error status - should return 0 & keep error the same */
+ err = U_MEMORY_ALLOCATION_ERROR;
+ if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR)
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
+ }
+ err = U_ZERO_ERROR;
+
+ /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
+ if (0 != ucnv_safeClone(cnv, buffer[0], 0, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
+ }
+ err = U_ZERO_ERROR;
+
+ /* buffer size pointer is 0 - fill in pbufferSize with a size */
+ bufferSize = 0;
+ if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0)
+ {
+ log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
+ }
+ /* Verify our define is large enough */
+ if (U_CNV_SAFECLONE_BUFFERSIZE < bufferSize)
+ {
+ log_err("FAIL: Pre-calculated buffer size is too small\n");
+ }
+ /* Verify we can use this run-time calculated size */
+ if (0 == (cnv2 = ucnv_safeClone(cnv, buffer[0], &bufferSize, &err)) || U_FAILURE(err))
+ {
+ log_err("FAIL: Converter can't be cloned with run-time size\n");
+ }
+ if (cnv2) {
+ ucnv_close(cnv2);
+ }
+
+ /* size one byte too small - should allocate & let us know */
+ --bufferSize;
+ if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
+ }
+ if (cnv2) {
+ ucnv_close(cnv2);
+ }
+
+ err = U_ZERO_ERROR;
+ bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
+
+ /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
+ if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
+ }
+ if (cnv2) {
+ ucnv_close(cnv2);
+ }
+
+ err = U_ZERO_ERROR;
+
+ /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
+ if (0 != ucnv_safeClone(0, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
+ }
+
+ ucnv_close(cnv);
+ }
+
+ maxBufferSize = 0;
+ maxName = "";
+
+ /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
+
+ for(j = 0; j < LENGTHOF(bufferSizes); ++j) {
+ for (index = 0; index < LENGTHOF(names); index++)
+ {
+ err = U_ZERO_ERROR;
+ cnv = ucnv_open(names[index], &err);
+ if(U_FAILURE(err)) {
+ log_data_err("ucnv_open(\"%s\") failed - %s\n", names[index], u_errorName(err));
+ continue;
+ }
+
+ if(j == 0) {
+ /* preflight to get maxBufferSize */
+ actualSizes[index] = 0;
+ ucnv_safeClone(cnv, NULL, &actualSizes[index], &err);
+ if(actualSizes[index] > maxBufferSize) {
+ maxBufferSize = actualSizes[index];
+ maxName = names[index];
+ }
+ }
+
+ memset(buffer, 0xaa, sizeof(buffer));
+
+ bufferSize = bufferSizes[j];
+ cnv2 = ucnv_safeClone(cnv, buffer[1], &bufferSize, &err);
+
+ /* close the original immediately to make sure that the clone works by itself */
+ ucnv_close(cnv);
+
+ if( actualSizes[index] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) &&
+ err == U_SAFECLONE_ALLOCATED_WARNING
+ ) {
+ log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[index]);
+ }
+
+ /* check if the clone function overwrote any bytes that it is not supposed to touch */
+ if(bufferSize <= bufferSizes[j]) {
+ /* used the stack buffer */
+ if( containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer[0]), 0xaa) ||
+ containsAnyOtherByte(buffer[1]+bufferSize, (int32_t)(sizeof(buffer)-(sizeof(buffer[0])+bufferSize)), 0xaa)
+ ) {
+ log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
+ names[index], bufferSize, bufferSizes[j]);
+ }
+ } else {
+ /* heap-allocated the clone */
+ if(containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer), 0xaa)) {
+ log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
+ names[index], bufferSize, bufferSizes[j]);
+ }
+ }
+
+ pCharBuffer = charBuffer;
+ pUniBuffer = uniBuffer;
+
+ ucnv_fromUnicode(cnv2,
+ &pCharBuffer,
+ charBufferLimit,
+ &pUniBuffer,
+ uniBufferLimit,
+ NULL,
+ TRUE,
+ &err);
+ if(U_FAILURE(err)){
+ log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err));
+ }
+ ucnv_toUnicode(cnv2,
+ &pUCharTarget,
+ pUCharTargetLimit,
+ &pCharSource,
+ pCharSourceLimit,
+ NULL,
+ TRUE,
+ &err
+ );
+
+ if(U_FAILURE(err)){
+ log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err));
+ }
+
+ pConstCharBuffer = charBuffer;
+ if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err))
+ {
+ log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err));
+ }
+ ucnv_close(cnv2);
+ }
+ }
+
+ log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
+ sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
+ if(maxBufferSize > U_CNV_SAFECLONE_BUFFERSIZE) {
+ log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
+ maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
+ }
+}
+
+static void TestCCSID() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UConverter *cnv;
+ UErrorCode errorCode;
+ int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
+ int32_t i, ccsid;
+
+ for(i=0; i<(int32_t)(sizeof(ccsids)/sizeof(int32_t)); ++i) {
+ ccsid=ccsids[i];
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_openCCSID(ccsid, UCNV_IBM, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid, u_errorName(errorCode));
+ continue;
+ }
+
+ if(ccsid!=ucnv_getCCSID(cnv, &errorCode)) {
+ log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid, ucnv_getCCSID(cnv, &errorCode));
+ }
+
+ /* skip gb18030(ccsid 1392) */
+ if(ccsid != 1392 && UCNV_IBM!=ucnv_getPlatform(cnv, &errorCode)) {
+ log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid, ucnv_getPlatform(cnv, &errorCode));
+ }
+
+ ucnv_close(cnv);
+ }
+#endif
+}
+
+/* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
+
+/* CHUNK_SIZE defined in common\ucnv.c: */
+#define CHUNK_SIZE 1024
+
+static void bug1(void);
+static void bug2(void);
+static void bug3(void);
+
+static void
+TestJ932(void)
+{
+ bug1(); /* Unicode intermediate buffer straddle bug */
+ bug2(); /* pre-flighting size incorrect caused by simple overflow */
+ bug3(); /* pre-flighting size incorrect caused by expansion overflow */
+}
+
+/*
+ * jitterbug 932: test chunking boundary conditions in
+
+ int32_t ucnv_convert(const char *toConverterName,
+ const char *fromConverterName,
+ char *target,
+ int32_t targetSize,
+ const char *source,
+ int32_t sourceSize,
+ UErrorCode * err)
+
+ * See discussions on the icu mailing list in
+ * 2001-April with the subject "converter 'flush' question".
+ *
+ * Bug report and test code provided by Edward J. Batutis.
+ */
+static void bug1()
+{
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ char char_in[CHUNK_SIZE+32];
+ char char_out[CHUNK_SIZE*2];
+
+ /* GB 18030 equivalent of U+10000 is 90308130 */
+ static const char test_seq[]={ (char)0x90u, 0x30, (char)0x81u, 0x30 };
+
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t i, test_seq_len = sizeof(test_seq);
+
+ /*
+ * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
+ * until the straddle bug appears. I didn't want to hard-code everything so this test could
+ * be expanded - however this is the only type of straddle bug I can think of at the moment -
+ * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
+ * other Unicode sequences cause a bug since combining sequences are not supported by the
+ * converters.
+ */
+
+ for (i = test_seq_len; i >= 0; i--) {
+ /* put character sequence into input buffer */
+ memset(char_in, 0x61, sizeof(char_in)); /* GB 18030 'a' */
+ memcpy(char_in + (CHUNK_SIZE - i), test_seq, test_seq_len);
+
+ /* do the conversion */
+ ucnv_convert("us-ascii", /* out */
+ "gb18030", /* in */
+ char_out,
+ sizeof(char_out),
+ char_in,
+ sizeof(char_in),
+ &err);
+
+ /* bug1: */
+ if (err == U_TRUNCATED_CHAR_FOUND) {
+ /* this happens when surrogate pair straddles the intermediate buffer in
+ * T_UConverter_fromCodepageToCodepage */
+ log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
+ }
+ }
+#endif
+}
+
+/* bug2: pre-flighting loop bug: simple overflow causes bug */
+static void bug2()
+{
+ /* US-ASCII "1234567890" */
+ static const char source[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
+ static const char sourceUTF8[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
+ static const char sourceUTF32[]={ 0x00, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x31,
+ 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x00, 0x34,
+ 0x00, 0x00, 0x00, 0x35,
+ 0x00, 0x00, 0x00, 0x36,
+ 0x00, 0x00, 0x00, 0x37,
+ 0x00, 0x00, 0x00, 0x38,
+ 0x00, 0x00, (char)0xf0, 0x00};
+ static char target[5];
+
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t size;
+
+ /* do the conversion */
+ size = ucnv_convert("iso-8859-1", /* out */
+ "us-ascii", /* in */
+ target,
+ sizeof(target),
+ source,
+ sizeof(source),
+ &err);
+
+ if ( size != 10 ) {
+ /* bug2: size is 5, should be 10 */
+ log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size);
+ }
+
+ err = U_ZERO_ERROR;
+ /* do the conversion */
+ size = ucnv_convert("UTF-32BE", /* out */
+ "UTF-8", /* in */
+ target,
+ sizeof(target),
+ sourceUTF8,
+ sizeof(sourceUTF8),
+ &err);
+
+ if ( size != 32 ) {
+ /* bug2: size is 5, should be 32 */
+ log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size);
+ }
+
+ err = U_ZERO_ERROR;
+ /* do the conversion */
+ size = ucnv_convert("UTF-8", /* out */
+ "UTF-32BE", /* in */
+ target,
+ sizeof(target),
+ sourceUTF32,
+ sizeof(sourceUTF32),
+ &err);
+
+ if ( size != 12 ) {
+ /* bug2: size is 5, should be 12 */
+ log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size);
+ }
+}
+
+/*
+ * bug3: when the characters expand going from source to target codepage
+ * you get bug3 in addition to bug2
+ */
+static void bug3()
+{
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ char char_in[CHUNK_SIZE*4];
+ char target[5];
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t size;
+
+ /*
+ * first get the buggy size from bug2 then
+ * compare it to buggy size with an expansion
+ */
+ memset(char_in, 0x61, sizeof(char_in)); /* US-ASCII 'a' */
+
+ /* do the conversion */
+ size = ucnv_convert("lmbcs", /* out */
+ "us-ascii", /* in */
+ target,
+ sizeof(target),
+ char_in,
+ sizeof(char_in),
+ &err);
+
+ if ( size != sizeof(char_in) ) {
+ /*
+ * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
+ * in the converter?), should be CHUNK_SIZE*4
+ *
+ * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
+ */
+ log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in), size);
+ }
+
+ /*
+ * now do the conversion with expansion
+ * ascii 0x08 expands to 0x0F 0x28 in lmbcs
+ */
+ memset(char_in, 8, sizeof(char_in));
+ err = U_ZERO_ERROR;
+
+ /* do the conversion */
+ size = ucnv_convert("lmbcs", /* out */
+ "us-ascii", /* in */
+ target,
+ sizeof(target),
+ char_in,
+ sizeof(char_in),
+ &err);
+
+ /* expect 2X expansion */
+ if ( size != sizeof(char_in) * 2 ) {
+ /*
+ * bug3:
+ * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
+ */
+ log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size);
+ }
+#endif
+}
+
+static void
+convertExStreaming(UConverter *srcCnv, UConverter *targetCnv,
+ const char *src, int32_t srcLength,
+ const char *expectTarget, int32_t expectTargetLength,
+ int32_t chunkSize,
+ const char *testName,
+ UErrorCode expectCode) {
+ UChar pivotBuffer[CHUNK_SIZE];
+ UChar *pivotSource, *pivotTarget;
+ const UChar *pivotLimit;
+
+ char targetBuffer[CHUNK_SIZE];
+ char *target;
+ const char *srcLimit, *finalSrcLimit, *targetLimit;
+
+ int32_t targetLength;
+
+ UBool flush;
+
+ UErrorCode errorCode;
+
+ /* setup */
+ if(chunkSize>CHUNK_SIZE) {
+ chunkSize=CHUNK_SIZE;
+ }
+
+ pivotSource=pivotTarget=pivotBuffer;
+ pivotLimit=pivotBuffer+chunkSize;
+
+ finalSrcLimit=src+srcLength;
+ target=targetBuffer;
+ targetLimit=targetBuffer+chunkSize;
+
+ ucnv_resetToUnicode(srcCnv);
+ ucnv_resetFromUnicode(targetCnv);
+
+ errorCode=U_ZERO_ERROR;
+ flush=FALSE;
+
+ /* convert, streaming-style (both converters and pivot keep state) */
+ for(;;) {
+ /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
+ if(src+chunkSize<=finalSrcLimit) {
+ srcLimit=src+chunkSize;
+ } else {
+ srcLimit=finalSrcLimit;
+ }
+ ucnv_convertEx(targetCnv, srcCnv,
+ &target, targetLimit,
+ &src, srcLimit,
+ pivotBuffer, &pivotSource, &pivotTarget, pivotLimit,
+ FALSE, flush, &errorCode);
+ targetLength=(int32_t)(target-targetBuffer);
+ if(target>targetLimit) {
+ log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
+ testName, chunkSize, target, targetLimit);
+ break; /* TODO: major problem! */
+ }
+ if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
+ /* continue converting another chunk */
+ errorCode=U_ZERO_ERROR;
+ if(targetLength+chunkSize<=sizeof(targetBuffer)) {
+ targetLimit=target+chunkSize;
+ } else {
+ targetLimit=targetBuffer+sizeof(targetBuffer);
+ }
+ } else if(U_FAILURE(errorCode)) {
+ /* failure */
+ break;
+ } else if(flush) {
+ /* all done */
+ break;
+ } else if(src==finalSrcLimit && pivotSource==pivotTarget) {
+ /* all consumed, now flush without input (separate from conversion for testing) */
+ flush=TRUE;
+ }
+ }
+
+ if(!(errorCode==expectCode || (expectCode==U_ZERO_ERROR && errorCode==U_STRING_NOT_TERMINATED_WARNING))) {
+ log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
+ testName, chunkSize, u_errorName(errorCode), u_errorName(expectCode));
+ } else if(targetLength!=expectTargetLength) {
+ log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
+ testName, chunkSize, targetLength, expectTargetLength);
+ } else if(memcmp(targetBuffer, expectTarget, targetLength)!=0) {
+ log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
+ testName, chunkSize);
+ }
+}
+
+static void
+convertExMultiStreaming(UConverter *srcCnv, UConverter *targetCnv,
+ const char *src, int32_t srcLength,
+ const char *expectTarget, int32_t expectTargetLength,
+ const char *testName,
+ UErrorCode expectCode) {
+ convertExStreaming(srcCnv, targetCnv,
+ src, srcLength,
+ expectTarget, expectTargetLength,
+ 1, testName, expectCode);
+ convertExStreaming(srcCnv, targetCnv,
+ src, srcLength,
+ expectTarget, expectTargetLength,
+ 3, testName, expectCode);
+ convertExStreaming(srcCnv, targetCnv,
+ src, srcLength,
+ expectTarget, expectTargetLength,
+ 7, testName, expectCode);
+}
+
+static void TestConvertEx() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ static const uint8_t
+ utf8[]={
+ /* 4e00 30a1 ff61 0410 */
+ 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
+ },
+ shiftJIS[]={
+ 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
+ },
+ errorTarget[]={
+ /*
+ * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
+ * SUB, SUB, 0x40, SUB, SUB, 0x40
+ */
+ 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
+ };
+
+ char srcBuffer[100], targetBuffer[100];
+
+ const char *src;
+ char *target;
+
+ UChar pivotBuffer[100];
+ UChar *pivotSource, *pivotTarget;
+
+ UConverter *cnv1, *cnv2;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ cnv1=ucnv_open("UTF-8", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ cnv2=ucnv_open("Shift-JIS", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
+ ucnv_close(cnv1);
+ return;
+ }
+
+ /* test ucnv_convertEx() with streaming conversion style */
+ convertExMultiStreaming(cnv1, cnv2,
+ (const char *)utf8, sizeof(utf8), (const char *)shiftJIS, sizeof(shiftJIS),
+ "UTF-8 -> Shift-JIS", U_ZERO_ERROR);
+
+ convertExMultiStreaming(cnv2, cnv1,
+ (const char *)shiftJIS, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8),
+ "Shift-JIS -> UTF-8", U_ZERO_ERROR);
+
+ /* U_ZERO_ERROR because by default the SUB callbacks are set */
+ convertExMultiStreaming(cnv1, cnv2,
+ (const char *)shiftJIS, sizeof(shiftJIS), (const char *)errorTarget, sizeof(errorTarget),
+ "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR);
+
+ /* test some simple conversions */
+
+ /* NUL-terminated source and target */
+ errorCode=U_STRING_NOT_TERMINATED_WARNING;
+ memcpy(srcBuffer, utf8, sizeof(utf8));
+ srcBuffer[sizeof(utf8)]=0;
+ src=srcBuffer;
+ target=targetBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
+ if( errorCode!=U_ZERO_ERROR ||
+ target-targetBuffer!=sizeof(shiftJIS) ||
+ *target!=0 ||
+ memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
+ ) {
+ log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
+ u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
+ }
+
+ /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
+ errorCode=U_AMBIGUOUS_ALIAS_WARNING;
+ memset(targetBuffer, 0xff, sizeof(targetBuffer));
+ src=srcBuffer;
+ target=targetBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(shiftJIS), &src, NULL,
+ NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
+ if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ target-targetBuffer!=sizeof(shiftJIS) ||
+ *target!=(char)0xff ||
+ memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
+ ) {
+ log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
+ u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
+ }
+
+ /* bad arguments */
+ errorCode=U_MESSAGE_PARSE_ERROR;
+ src=srcBuffer;
+ target=targetBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
+ if(errorCode!=U_MESSAGE_PARSE_ERROR) {
+ log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* pivotLimit==pivotStart */
+ errorCode=U_ZERO_ERROR;
+ pivotSource=pivotTarget=pivotBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer, TRUE, TRUE, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* *pivotSource==NULL */
+ errorCode=U_ZERO_ERROR;
+ pivotSource=NULL;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* *source==NULL */
+ errorCode=U_ZERO_ERROR;
+ src=NULL;
+ pivotSource=pivotBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* streaming conversion without a pivot buffer */
+ errorCode=U_ZERO_ERROR;
+ src=srcBuffer;
+ pivotSource=pivotBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ NULL, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, FALSE, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode));
+ }
+
+ ucnv_close(cnv1);
+ ucnv_close(cnv2);
+#endif
+}
+
+/* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
+static const char *const badUTF8[]={
+ /* trail byte */
+ "\x80",
+
+ /* truncated multi-byte sequences */
+ "\xd0",
+ "\xe0",
+ "\xe1",
+ "\xed",
+ "\xee",
+ "\xf0",
+ "\xf1",
+ "\xf4",
+ "\xf8",
+ "\xfc",
+
+ "\xe0\x80",
+ "\xe0\xa0",
+ "\xe1\x80",
+ "\xed\x80",
+ "\xed\xa0",
+ "\xee\x80",
+ "\xf0\x80",
+ "\xf0\x90",
+ "\xf1\x80",
+ "\xf4\x80",
+ "\xf4\x90",
+ "\xf8\x80",
+ "\xfc\x80",
+
+ "\xf0\x80\x80",
+ "\xf0\x90\x80",
+ "\xf1\x80\x80",
+ "\xf4\x80\x80",
+ "\xf4\x90\x80",
+ "\xf8\x80\x80",
+ "\xfc\x80\x80",
+
+ "\xf8\x80\x80\x80",
+ "\xfc\x80\x80\x80",
+
+ "\xfc\x80\x80\x80\x80",
+
+ /* complete sequences but non-shortest forms or out of range etc. */
+ "\xc0\x80",
+ "\xe0\x80\x80",
+ "\xed\xa0\x80",
+ "\xf0\x80\x80\x80",
+ "\xf4\x90\x80\x80",
+ "\xf8\x80\x80\x80\x80",
+ "\xfc\x80\x80\x80\x80\x80",
+ "\xfe",
+ "\xff"
+};
+
+/* get some character that can be converted and convert it */
+static UBool getTestChar(UConverter *cnv, const char *converterName,
+ char charUTF8[4], int32_t *pCharUTF8Length,
+ char char0[8], int32_t *pChar0Length,
+ char char1[8], int32_t *pChar1Length) {
+ UChar utf16[U16_MAX_LENGTH];
+ int32_t utf16Length;
+
+ const UChar *utf16Source;
+ char *target;
+
+ USet *set;
+ UChar32 c;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ set=uset_open(1, 0);
+ ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ c=uset_charAt(set, uset_size(set)/2);
+ uset_close(set);
+
+ utf16Length=0;
+ U16_APPEND_UNSAFE(utf16, utf16Length, c);
+ *pCharUTF8Length=0;
+ U8_APPEND_UNSAFE(charUTF8, *pCharUTF8Length, c);
+
+ utf16Source=utf16;
+ target=char0;
+ ucnv_fromUnicode(cnv,
+ &target, char0+sizeof(char0),
+ &utf16Source, utf16+utf16Length,
+ NULL, FALSE, &errorCode);
+ *pChar0Length=(int32_t)(target-char0);
+
+ utf16Source=utf16;
+ target=char1;
+ ucnv_fromUnicode(cnv,
+ &target, char1+sizeof(char1),
+ &utf16Source, utf16+utf16Length,
+ NULL, FALSE, &errorCode);
+ *pChar1Length=(int32_t)(target-char1);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to get test character for %s - %s\n", converterName, u_errorName(errorCode));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void testFromTruncatedUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
+ char charUTF8[4], int32_t charUTF8Length,
+ char char0[8], int32_t char0Length,
+ char char1[8], int32_t char1Length) {
+ char utf8[16];
+ int32_t utf8Length;
+
+ char output[16];
+ int32_t outputLength;
+
+ char invalidChars[8];
+ int8_t invalidLength;
+
+ const char *source;
+ char *target;
+
+ UChar pivotBuffer[8];
+ UChar *pivotSource, *pivotTarget;
+
+ UErrorCode errorCode;
+ int32_t i;
+
+ /* test truncated sequences */
+ errorCode=U_ZERO_ERROR;
+ ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+
+ memcpy(utf8, charUTF8, charUTF8Length);
+
+ for(i=0; i<LENGTHOF(badUTF8); ++i) {
+ /* truncated sequence? */
+ int32_t length=strlen(badUTF8[i]);
+ if(length>=(1+U8_COUNT_TRAIL_BYTES(badUTF8[i][0]))) {
+ continue;
+ }
+
+ /* assemble a string with the test character and the truncated sequence */
+ memcpy(utf8+charUTF8Length, badUTF8[i], length);
+ utf8Length=charUTF8Length+length;
+
+ /* convert and check the invalidChars */
+ source=utf8;
+ target=output;
+ pivotSource=pivotTarget=pivotBuffer;
+ errorCode=U_ZERO_ERROR;
+ ucnv_convertEx(cnv, utf8Cnv,
+ &target, output+sizeof(output),
+ &source, utf8+utf8Length,
+ pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+LENGTHOF(pivotBuffer),
+ TRUE, TRUE, /* reset & flush */
+ &errorCode);
+ outputLength=(int32_t)(target-output);
+ if(errorCode!=U_TRUNCATED_CHAR_FOUND || pivotSource!=pivotBuffer) {
+ log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode), converterName, (long)i);
+ continue;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ invalidLength=(int8_t)sizeof(invalidChars);
+ ucnv_getInvalidChars(utf8Cnv, invalidChars, &invalidLength, &errorCode);
+ if(invalidLength!=length || 0!=memcmp(invalidChars, badUTF8[i], length)) {
+ log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName, (long)i);
+ }
+ }
+}
+
+static void testFromBadUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
+ char charUTF8[4], int32_t charUTF8Length,
+ char char0[8], int32_t char0Length,
+ char char1[8], int32_t char1Length) {
+ char utf8[600], expect[600];
+ int32_t utf8Length, expectLength;
+
+ char testName[32];
+
+ UErrorCode errorCode;
+ int32_t i;
+
+ errorCode=U_ZERO_ERROR;
+ ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, NULL, &errorCode);
+
+ /*
+ * assemble an input string with the test character between each
+ * bad sequence,
+ * and an expected string with repeated test character output
+ */
+ memcpy(utf8, charUTF8, charUTF8Length);
+ utf8Length=charUTF8Length;
+
+ memcpy(expect, char0, char0Length);
+ expectLength=char0Length;
+
+ for(i=0; i<LENGTHOF(badUTF8); ++i) {
+ int32_t length=strlen(badUTF8[i]);
+ memcpy(utf8+utf8Length, badUTF8[i], length);
+ utf8Length+=length;
+
+ memcpy(utf8+utf8Length, charUTF8, charUTF8Length);
+ utf8Length+=charUTF8Length;
+
+ memcpy(expect+expectLength, char1, char1Length);
+ expectLength+=char1Length;
+ }
+
+ /* expect that each bad UTF-8 sequence is detected and skipped */
+ strcpy(testName, "from bad UTF-8 to ");
+ strcat(testName, converterName);
+
+ convertExMultiStreaming(utf8Cnv, cnv,
+ utf8, utf8Length,
+ expect, expectLength,
+ testName,
+ U_ZERO_ERROR);
+}
+
+/* Test illegal UTF-8 input. */
+static void TestConvertExFromUTF8() {
+ static const char *const converterNames[]={
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "windows-1252",
+ "shift-jis",
+#endif
+ "us-ascii",
+ "iso-8859-1",
+ "utf-8"
+ };
+
+ UConverter *utf8Cnv, *cnv;
+ UErrorCode errorCode;
+ int32_t i;
+
+ /* fromUnicode versions of some character, from initial state and later */
+ char charUTF8[4], char0[8], char1[8];
+ int32_t charUTF8Length, char0Length, char1Length;
+
+ errorCode=U_ZERO_ERROR;
+ utf8Cnv=ucnv_open("UTF-8", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ for(i=0; i<LENGTHOF(converterNames); ++i) {
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open(converterNames[i], &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to open %s converter - %s\n", converterNames[i], u_errorName(errorCode));
+ continue;
+ }
+ if(!getTestChar(cnv, converterNames[i], charUTF8, &charUTF8Length, char0, &char0Length, char1, &char1Length)) {
+ continue;
+ }
+ testFromTruncatedUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
+ testFromBadUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
+ ucnv_close(cnv);
+ }
+ ucnv_close(utf8Cnv);
+}
+
+static void
+TestConvertAlgorithmic() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ static const uint8_t
+ utf8[]={
+ /* 4e00 30a1 ff61 0410 */
+ 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
+ },
+ shiftJIS[]={
+ 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
+ },
+ /*errorTarget[]={*/
+ /*
+ * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
+ * SUB, SUB, 0x40, SUB, SUB, 0x40
+ */
+ /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
+ /*},*/
+ utf16[]={
+ 0xfe, 0xff /* BOM only, no text */
+ },
+ utf32[]={
+ 0xff, 0xfe, 0, 0 /* BOM only, no text */
+ };
+
+ char target[100], utf8NUL[100], shiftJISNUL[100];
+
+ UConverter *cnv;
+ UErrorCode errorCode;
+
+ int32_t length;
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("Shift-JIS", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
+ ucnv_close(cnv);
+ return;
+ }
+
+ memcpy(utf8NUL, utf8, sizeof(utf8));
+ utf8NUL[sizeof(utf8)]=0;
+ memcpy(shiftJISNUL, shiftJIS, sizeof(shiftJIS));
+ shiftJISNUL[sizeof(shiftJIS)]=0;
+
+ /*
+ * The to/from algorithmic convenience functions share a common implementation,
+ * so we need not test all permutations of them.
+ */
+
+ /* length in, not terminated out */
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, UCNV_UTF8, target, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), &errorCode);
+ if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ length!=sizeof(shiftJIS) ||
+ memcmp(target, shiftJIS, length)!=0
+ ) {
+ log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
+ u_errorName(errorCode), length, sizeof(shiftJIS));
+ }
+
+ /* terminated in and out */
+ memset(target, 0x55, sizeof(target));
+ errorCode=U_STRING_NOT_TERMINATED_WARNING;
+ length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, -1, &errorCode);
+ if( errorCode!=U_ZERO_ERROR ||
+ length!=sizeof(utf8) ||
+ memcmp(target, utf8, length)!=0
+ ) {
+ log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
+ u_errorName(errorCode), length, sizeof(shiftJIS));
+ }
+
+ /* empty string, some target buffer */
+ errorCode=U_STRING_NOT_TERMINATED_WARNING;
+ length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, 0, &errorCode);
+ if( errorCode!=U_ZERO_ERROR ||
+ length!=0
+ ) {
+ log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
+ u_errorName(errorCode), length);
+ }
+
+ /* pseudo-empty string, no target buffer */
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
+ if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ length!=0
+ ) {
+ log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
+ u_errorName(errorCode), length);
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, UCNV_UTF32, target, 0, (const char *)utf32, 4, &errorCode);
+ if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ length!=0
+ ) {
+ log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
+ u_errorName(errorCode), length);
+ }
+
+ /* bad arguments */
+ errorCode=U_MESSAGE_PARSE_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
+ if(errorCode!=U_MESSAGE_PARSE_ERROR) {
+ log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* source==NULL */
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, NULL, 2, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode));
+ }
+
+ /* illegal alg. type */
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_fromAlgorithmic(cnv, (UConverterType)99, target, 0, (const char *)utf16, 2, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode));
+ }
+ucnv_close(cnv);
+#endif
+}
+
+static void TestLMBCSMaxChar(void) {
+ static const struct {
+ int8_t maxSize;
+ const char *name;
+ } converter[] = {
+ /* some non-LMBCS converters - perfect test setup here */
+ { 1, "US-ASCII"},
+ { 1, "ISO-8859-1"},
+
+ { 2, "UTF-16"},
+ { 2, "UTF-16BE"},
+ { 3, "UTF-8"},
+ { 3, "CESU-8"},
+ { 3, "SCSU"},
+ { 4, "UTF-32"},
+ { 4, "UTF-7"},
+ { 4, "IMAP-mailbox-name"},
+ { 4, "BOCU-1"},
+
+ { 1, "windows-1256"},
+ { 2, "Shift-JIS"},
+ { 2, "ibm-16684"},
+ { 3, "ibm-930"},
+ { 3, "ibm-1390"},
+ { 4, "*test3"},
+ { 16,"*test4"},
+
+ { 4, "ISCII"},
+ { 4, "HZ"},
+
+ { 3, "ISO-2022"},
+ { 3, "ISO-2022-KR"},
+ { 6, "ISO-2022-JP"},
+ { 8, "ISO-2022-CN"},
+
+ /* LMBCS */
+ { 3, "LMBCS-1"},
+ { 3, "LMBCS-2"},
+ { 3, "LMBCS-3"},
+ { 3, "LMBCS-4"},
+ { 3, "LMBCS-5"},
+ { 3, "LMBCS-6"},
+ { 3, "LMBCS-8"},
+ { 3, "LMBCS-11"},
+ { 3, "LMBCS-16"},
+ { 3, "LMBCS-17"},
+ { 3, "LMBCS-18"},
+ { 3, "LMBCS-19"}
+ };
+ int32_t idx;
+
+ for (idx = 0; idx < LENGTHOF(converter); idx++) {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv = cnv_open(converter[idx].name, &status);
+ if (U_FAILURE(status)) {
+ continue;
+ }
+ if (converter[idx].maxSize != ucnv_getMaxCharSize(cnv)) {
+ log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
+ converter[idx].name, converter[idx].maxSize, ucnv_getMaxCharSize(cnv));
+ }
+ ucnv_close(cnv);
+ }
+
+ /* mostly test that the macro compiles */
+ if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
+ log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
+ }
+}
+
+
+static void TestJ1968(void) {
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter *cnv;
+ char myConvName[] = "My really really really really really really really really really really really"
+ " really really really really really really really really really really really"
+ " really really really really really really really really long converter name";
+ UChar myConvNameU[sizeof(myConvName)];
+
+ u_charsToUChars(myConvName, myConvNameU, sizeof(myConvName));
+
+ err = U_ZERO_ERROR;
+ myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH+1] = 0;
+ cnv = ucnv_openU(myConvNameU, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
+ cnv = ucnv_openU(myConvNameU, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
+ cnv = ucnv_openU(myConvNameU, &err);
+ if (cnv || err != U_FILE_ACCESS_ERROR) {
+ log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
+ }
+
+
+
+
+ err = U_ZERO_ERROR;
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = ',';
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_FILE_ACCESS_ERROR) {
+ log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
+ strncpy(myConvName + UCNV_MAX_CONVERTER_NAME_LENGTH, "locale=", 7);
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ /* The comma isn't really a part of the converter name. */
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_FILE_ACCESS_ERROR) {
+ log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ' ';
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
+ }
+
+ err = U_ZERO_ERROR;
+ myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
+ cnv = ucnv_open(myConvName, &err);
+ if (cnv || err != U_FILE_ACCESS_ERROR) {
+ log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
+ }
+
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void
+testSwap(const char *name, UBool swap) {
+ /*
+ * Test Unicode text.
+ * Contains characters that are the highest for some of the
+ * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
+ * tables copies the entire tables.
+ */
+ static const UChar text[]={
+ 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
+ };
+
+ UChar uNormal[32], uSwapped[32];
+ char normal[32], swapped[32];
+ const UChar *pcu;
+ UChar *pu;
+ char *pc;
+ int32_t i, normalLength, swappedLength;
+ UChar u;
+ char c;
+
+ const char *swappedName;
+ UConverter *cnv, *swapCnv;
+ UErrorCode errorCode;
+
+ /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
+
+ /* open both the normal and the LF/NL-swapping converters */
+ strcpy(swapped, name);
+ strcat(swapped, UCNV_SWAP_LFNL_OPTION_STRING);
+
+ errorCode=U_ZERO_ERROR;
+ swapCnv=ucnv_open(swapped, &errorCode);
+ cnv=ucnv_open(name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name, swapped, u_errorName(errorCode));
+ goto cleanup;
+ }
+
+ /* the name must contain the swap option if and only if we expect the converter to swap */
+ swappedName=ucnv_getName(swapCnv, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name, u_errorName(errorCode));
+ goto cleanup;
+ }
+
+ pc=strstr(swappedName, UCNV_SWAP_LFNL_OPTION_STRING);
+ if(swap != (pc!=NULL)) {
+ log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name, swappedName, swap);
+ goto cleanup;
+ }
+
+ /* convert to EBCDIC */
+ pcu=text;
+ pc=normal;
+ ucnv_fromUnicode(cnv, &pc, normal+LENGTHOF(normal), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode);
+ normalLength=(int32_t)(pc-normal);
+
+ pcu=text;
+ pc=swapped;
+ ucnv_fromUnicode(swapCnv, &pc, swapped+LENGTHOF(swapped), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode);
+ swappedLength=(int32_t)(pc-swapped);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name, u_errorName(errorCode));
+ goto cleanup;
+ }
+
+ /* compare EBCDIC output */
+ if(normalLength!=swappedLength) {
+ log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
+ goto cleanup;
+ }
+ for(i=0; i<normalLength; ++i) {
+ /* swap EBCDIC LF/NL for comparison */
+ c=normal[i];
+ if(swap) {
+ if(c==0x15) {
+ c=0x25;
+ } else if(c==0x25) {
+ c=0x15;
+ }
+ }
+
+ if(c!=swapped[i]) {
+ log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name, i, (uint8_t)swapped[i]);
+ goto cleanup;
+ }
+ }
+
+ /* convert back to Unicode (may not roundtrip) */
+ pc=normal;
+ pu=uNormal;
+ ucnv_toUnicode(cnv, &pu, uNormal+LENGTHOF(uNormal), (const char **)&pc, normal+normalLength, NULL, TRUE, &errorCode);
+ normalLength=(int32_t)(pu-uNormal);
+
+ pc=normal;
+ pu=uSwapped;
+ ucnv_toUnicode(swapCnv, &pu, uSwapped+LENGTHOF(uSwapped), (const char **)&pc, normal+swappedLength, NULL, TRUE, &errorCode);
+ swappedLength=(int32_t)(pu-uSwapped);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name, u_errorName(errorCode));
+ goto cleanup;
+ }
+
+ /* compare EBCDIC output */
+ if(normalLength!=swappedLength) {
+ log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
+ goto cleanup;
+ }
+ for(i=0; i<normalLength; ++i) {
+ /* swap EBCDIC LF/NL for comparison */
+ u=uNormal[i];
+ if(swap) {
+ if(u==0xa) {
+ u=0x85;
+ } else if(u==0x85) {
+ u=0xa;
+ }
+ }
+
+ if(u!=uSwapped[i]) {
+ log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name, i, uSwapped[i]);
+ goto cleanup;
+ }
+ }
+
+ /* clean up */
+cleanup:
+ ucnv_close(cnv);
+ ucnv_close(swapCnv);
+}
+
+static void
+TestEBCDICSwapLFNL() {
+ static const struct {
+ const char *name;
+ UBool swap;
+ } tests[]={
+ { "ibm-37", TRUE },
+ { "ibm-1047", TRUE },
+ { "ibm-1140", TRUE },
+ { "ibm-930", TRUE },
+ { "iso-8859-3", FALSE }
+ };
+
+ int i;
+
+ for(i=0; i<LENGTHOF(tests); ++i) {
+ testSwap(tests[i].name, tests[i].swap);
+ }
+}
+#else
+static void
+TestEBCDICSwapLFNL() {
+ /* test nothing... */
+}
+#endif
+
+static const UVersionInfo ICU_34 = {3,4,0,0};
+
+static void TestFromUCountPending(){
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode status = U_ZERO_ERROR;
+/* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
+ static const struct {
+ UChar input[6];
+ int32_t len;
+ int32_t exp;
+ }fromUnicodeTests[] = {
+ /*m:n conversion*/
+ {{0xdbc4},1,1},
+ {{ 0xdbc4, 0xde34, 0xd84d},3,1},
+ {{ 0xdbc4, 0xde34, 0xd900},3,3},
+ };
+ int i;
+ UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for(i=0; i<LENGTHOF(fromUnicodeTests); ++i) {
+ char tgt[10];
+ char* target = tgt;
+ char* targetLimit = target + 10;
+ const UChar* source = fromUnicodeTests[i].input;
+ const UChar* sourceLimit = source + fromUnicodeTests[i].len;
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+ if(len != fromUnicodeTests[i].exp){
+ log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
+ }
+ }
+ status = U_ZERO_ERROR;
+ {
+ /*
+ * The converter has to read the tail before it knows that
+ * only head alone matches.
+ * At the end, the output for head will overflow the target,
+ * middle will be pending, and tail will not have been consumed.
+ */
+ /*
+ \U00101234 -> x (<U101234> \x07 |0)
+ \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
+ \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
+ \U00060007 -> unassigned
+ */
+ static const UChar head[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
+ static const UChar middle[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
+ static const UChar tail[] = {0xDC07,0x0000};/* second half of \U00060007 */
+ char tgt[10];
+ char* target = tgt;
+ char* targetLimit = target + 2; /* expect overflow from converting \U00101234\U00050005 */
+ const UChar* source = head;
+ const UChar* sourceLimit = source + u_strlen(head);
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ if(len!=4){
+ log_err("ucnv_fromUInputHeld did not return correct length for head\n");
+ }
+ source = middle;
+ sourceLimit = source + u_strlen(middle);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ if(len!=5){
+ log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
+ }
+ source = tail;
+ sourceLimit = source + u_strlen(tail);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ if(status != U_BUFFER_OVERFLOW_ERROR){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ len = ucnv_fromUCountPending(cnv, &status);
+ /* middle[1] is pending, tail has not been consumed */
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len!=1){
+ log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
+ }
+ }
+ ucnv_close(cnv);
+#endif
+}
+
+static void
+TestToUCountPending(){
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode status = U_ZERO_ERROR;
+ static const struct {
+ char input[6];
+ int32_t len;
+ int32_t exp;
+ }toUnicodeTests[] = {
+ /*m:n conversion*/
+ {{0x05, 0x01, 0x02},3,3},
+ {{0x01, 0x02},2,2},
+ {{0x07, 0x00, 0x01, 0x02},4,4},
+ };
+
+ int i;
+ UConverterToUCallback *oldToUAction= NULL;
+ UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
+ for(i=0; i<LENGTHOF(toUnicodeTests); ++i) {
+ UChar tgt[10];
+ UChar* target = tgt;
+ UChar* targetLimit = target + 20;
+ const char* source = toUnicodeTests[i].input;
+ const char* sourceLimit = source + toUnicodeTests[i].len;
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+ if(len != toUnicodeTests[i].exp){
+ log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
+ }
+ }
+ status = U_ZERO_ERROR;
+ ucnv_close(cnv);
+
+ {
+ /*
+ * The converter has to read the tail before it knows that
+ * only head alone matches.
+ * At the end, the output for head will overflow the target,
+ * mid will be pending, and tail will not have been consumed.
+ */
+ char head[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
+ char mid[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
+ char tail[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
+ /*
+ 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
+ 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
+ 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
+ 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
+ */
+ UChar tgt[10];
+ UChar* target = tgt;
+ UChar* targetLimit = target + 1; /* expect overflow from converting */
+ const char* source = head;
+ const char* sourceLimit = source + strlen(head);
+ int32_t len = 0;
+ cnv = ucnv_openPackage(loadTestData(&status), "test4", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 4){
+ log_err("Did not get the expected len for head.\n");
+ }
+ source=mid;
+ sourceLimit = source+strlen(mid);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 8){
+ log_err("Did not get the expected len for mid.\n");
+ }
+
+ source=tail;
+ sourceLimit = source+strlen(tail);
+ targetLimit = target;
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ if(status != U_BUFFER_OVERFLOW_ERROR){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ len = ucnv_toUCountPending(cnv,&status);
+ /* mid[4] is pending, tail has not been consumed */
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 4){
+ log_err("Did not get the expected len for tail.\n");
+ }
+ ucnv_close(cnv);
+ }
+#endif
+}
+
+static void TestOneDefaultNameChange(const char *name) {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv;
+ ucnv_setDefaultName(name);
+ if(strcmp(ucnv_getDefaultName(), name)==0)
+ log_verbose("setDefaultName of %s works.\n", name);
+ else
+ log_err("setDefaultName of %s failed\n", name);
+ cnv=ucnv_open(NULL, &status);
+ if (U_FAILURE(status) || cnv == NULL) {
+ log_err("opening the default converter of %s failed\n", name);
+ return;
+ }
+ if(strcmp(ucnv_getName(cnv, &status), name)==0)
+ log_verbose("ucnv_getName of %s works.\n", name);
+ else
+ log_err("ucnv_getName of %s failed\n", name);
+ ucnv_close(cnv);
+}
+
+static void TestDefaultName(void) {
+ /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
+ static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
+ strcpy(defaultName, ucnv_getDefaultName());
+
+ log_verbose("getDefaultName returned %s\n", defaultName);
+
+ /*change the default name by setting it */
+ TestOneDefaultNameChange("UTF-8");
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ TestOneDefaultNameChange("ISCII,version=1");
+ TestOneDefaultNameChange("ISCII,version=2");
+#endif
+ TestOneDefaultNameChange("ISO-8859-1");
+
+ /*set the default name back*/
+ ucnv_setDefaultName(defaultName);
+}
+
+/* Test that ucnv_compareNames() matches names according to spec. ----------- */
+
+static U_INLINE int
+sign(int n) {
+ if(n==0) {
+ return 0;
+ } else if(n<0) {
+ return -1;
+ } else /* n>0 */ {
+ return 1;
+ }
+}
+
+static void
+compareNames(const char **names) {
+ const char *relation, *name1, *name2;
+ int rel, result;
+
+ relation=*names++;
+ if(*relation=='=') {
+ rel = 0;
+ } else if(*relation=='<') {
+ rel = -1;
+ } else {
+ rel = 1;
+ }
+
+ name1=*names++;
+ if(name1==NULL) {
+ return;
+ }
+ while((name2=*names++)!=NULL) {
+ result=ucnv_compareNames(name1, name2);
+ if(sign(result)!=rel) {
+ log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1, name2, result, rel);
+ }
+ name1=name2;
+ }
+}
+
+static void
+TestCompareNames() {
+ static const char *equalUTF8[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL };
+ static const char *equalIBM[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL };
+ static const char *lessMac[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL };
+ static const char *lessUTF080[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL };
+
+ compareNames(equalUTF8);
+ compareNames(equalIBM);
+ compareNames(lessMac);
+ compareNames(lessUTF080);
+}
+
+static void
+TestSubstString() {
+ static const UChar surrogate[1]={ 0xd900 };
+ char buffer[16];
+
+ static const UChar sub[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
+ static const char subChars[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
+ UConverter *cnv;
+ UErrorCode errorCode;
+ int32_t length;
+ int8_t len8;
+
+ /* UTF-16/32: test that the BOM is output before the sub character */
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-16", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
+ ucnv_close(cnv);
+ if(U_FAILURE(errorCode) ||
+ length!=4 ||
+ NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
+ ) {
+ log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-32", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
+ ucnv_close(cnv);
+ if(U_FAILURE(errorCode) ||
+ length!=8 ||
+ NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
+ ) {
+ log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
+ }
+
+ /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("ISO-8859-1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode));
+ } else {
+ len8 = sizeof(buffer);
+ ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
+ /* Stateless converter, we expect the string converted to charset bytes. */
+ if(U_FAILURE(errorCode) || len8!=sizeof(subChars) || 0!=uprv_memcmp(buffer, subChars, len8)) {
+ log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode));
+ }
+ }
+ ucnv_close(cnv);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("HZ", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode));
+ } else {
+ len8 = sizeof(buffer);
+ ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
+ /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
+ if(U_FAILURE(errorCode) || len8!=0) {
+ log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode));
+ }
+ }
+ ucnv_close(cnv);
+#endif
+ /*
+ * Further testing of ucnv_setSubstString() is done via intltest convert.
+ * We do not test edge cases of illegal arguments and similar because the
+ * function implementation uses all of its parameters in calls to other
+ * functions with UErrorCode parameters.
+ */
+}
+
+static void
+InvalidArguments() {
+ UConverter *cnv;
+ UErrorCode errorCode;
+ char charBuffer[2] = {1, 1};
+ char ucharAsCharBuffer[2] = {2, 2};
+ char *charsPtr = charBuffer;
+ UChar *ucharsPtr = (UChar *)ucharAsCharBuffer;
+ UChar *ucharsBadPtr = (UChar *)(ucharAsCharBuffer + 1);
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-8", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open() failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ /* This one should fail because an incomplete UChar is being passed in */
+ ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsPtr, ucharsBadPtr, NULL, TRUE, &errorCode);
+ if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ /* This one should fail because ucharsBadPtr is > than ucharsPtr */
+ ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsBadPtr, ucharsPtr, NULL, TRUE, &errorCode);
+ if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ /* This one should fail because an incomplete UChar is being passed in */
+ ucnv_toUnicode(cnv, &ucharsPtr, ucharsBadPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
+ if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ /* This one should fail because ucharsBadPtr is > than ucharsPtr */
+ ucnv_toUnicode(cnv, &ucharsBadPtr, ucharsPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
+ if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
+ }
+
+ if (charBuffer[0] != 1 || charBuffer[1] != 1
+ || ucharAsCharBuffer[0] != 2 || ucharAsCharBuffer[1] != 2)
+ {
+ log_err("Data was incorrectly written to buffers\n");
+ }
+
+ ucnv_close(cnv);
+}
+
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h
new file mode 100644
index 00000000000..a15dfc67d88
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccapitst.h
@@ -0,0 +1,25 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CAPITEST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*/
+#ifndef _CU_CAPITSTST
+#define _CU_CAPITSTST
+/* C API TEST FOR CODESET CONVERSION COMPONENT */
+#include "cintltst.h"
+#include "unicode/utypes.h"
+
+static void TestConvert(void);
+static void TestAlias(void);
+static void TestConvertSafeClone(void);
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c
new file mode 100644
index 00000000000..c2e4fd93bc0
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.c
@@ -0,0 +1,157 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CCOLLTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+#include <stdio.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "unicode/ucol.h"
+#include "unicode/ustring.h"
+#include "cmemory.h"
+
+void addCollTest(TestNode** root);
+
+void addCollTest(TestNode** root)
+{
+ addCollAPITest(root);
+ addCurrencyCollTest(root);
+ addNormTest(root);
+ addGermanCollTest(root);
+ addSpanishCollTest(root);
+ addFrenchCollTest(root);
+ addKannaCollTest(root);
+ addTurkishCollTest(root);
+ addEnglishCollTest(root);
+ addFinnishCollTest(root);
+
+ /* WEIVTODO: return tests here */
+ addRuleBasedCollTest(root);
+ addCollIterTest(root);
+ addAllCollTest(root);
+ addMiscCollTest(root);
+
+ addSearchTest(root);
+}
+
+
+
+/*Internal functions used*/
+static char* dumpSk(uint8_t *sourceKey, char *sk) {
+ uint32_t kLen = (uint32_t)strlen((const char *)sourceKey);
+ uint32_t i = 0;
+
+ *sk = 0;
+
+ for(i = 0; i<kLen; i++) {
+ sprintf(sk+2*i, "%02X", sourceKey[i]);
+ }
+ return sk;
+}
+
+void reportCResult( const UChar source[], const UChar target[],
+ uint8_t *sourceKey, uint8_t *targetKey,
+ UCollationResult compareResult,
+ UCollationResult keyResult,
+ UCollationResult incResult,
+ UCollationResult expectedResult )
+{
+ UChar *sResult, *sExpect;
+ sResult=(UChar*)malloc(sizeof(UChar) * 10);
+ sExpect=(UChar*)malloc(sizeof(UChar) * 10);
+ if (expectedResult < -1 || expectedResult > 1)
+ {
+ log_err("***** invalid call to reportCResult ****\n");
+ return;
+ }
+
+ if (compareResult != expectedResult)
+ {
+
+ appendCompareResult(compareResult, sResult);
+ appendCompareResult(expectedResult, sExpect);
+ log_err("Compare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1),
+ austrdup(sResult), austrdup(sExpect) );
+ }
+
+ if (incResult != expectedResult)
+ {
+
+ appendCompareResult(incResult, sResult);
+ appendCompareResult(expectedResult, sExpect);
+ log_err("incCompare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1),
+ austrdup(sResult), austrdup(sExpect) );
+ }
+
+ if (keyResult != expectedResult)
+ {
+
+ appendCompareResult(keyResult, sResult);
+ appendCompareResult(expectedResult, sExpect);
+
+ log_err("KeyCompare(%s , %s) returned: %s expected: %s\n", aescstrdup(source,-1), aescstrdup(target,-1),
+ austrdup(sResult), austrdup(sExpect) );
+
+
+ }
+
+ if (keyResult != compareResult)
+ {
+
+ appendCompareResult(keyResult, sResult);
+ appendCompareResult(compareResult, sExpect);
+
+ log_err("difference between sortkey and compare result for (%s , %s) Keys: %s compare %s\n", aescstrdup(source,-1), aescstrdup(target,-1),
+ austrdup(sResult), austrdup(sExpect) );
+
+
+ }
+
+ if(keyResult != expectedResult || keyResult != compareResult)
+ {
+ char sk[10000];
+ log_verbose("SortKey1: %s\n", dumpSk(sourceKey, sk));
+ log_verbose("SortKey2: %s\n", dumpSk(targetKey, sk));
+ }
+
+ free(sExpect);
+ free(sResult);
+}
+
+UChar* appendCompareResult(UCollationResult result, UChar* target)
+{
+ if (result == UCOL_LESS)
+ {
+ u_uastrcpy(target, "LESS");
+ }
+ else if (result == UCOL_EQUAL)
+ {
+ u_uastrcpy(target, "EQUAL");
+ }
+ else if (result == UCOL_GREATER)
+ {
+ u_uastrcpy(target, "GREATER");
+ }
+ else
+ {
+ u_uastrcpy(target, "huh???");
+ }
+
+ return target;
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h
new file mode 100644
index 00000000000..d3e7f51da3b
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccolltst.h
@@ -0,0 +1,56 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CCOLLTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+#ifndef _CCOLLTST
+#define _CCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+#include "unicode/ucol.h"
+
+/* Internal Functions used*/
+
+void reportCResult( const UChar source[], const UChar target[],
+ uint8_t *sourceKey, uint8_t *targetKey,
+ UCollationResult compareResult,
+ UCollationResult keyResult,
+ UCollationResult incResult,
+ UCollationResult expectedResult );
+
+UChar* appendCompareResult(UCollationResult result, UChar* target);
+
+void addCollAPITest(TestNode**);
+void addCurrencyCollTest(TestNode**);
+void addNormTest(TestNode**);
+void addDanishCollTest(TestNode**);
+void addGermanCollTest(TestNode**);
+void addSpanishCollTest(TestNode**);
+void addFrenchCollTest(TestNode**);
+void addKannaCollTest(TestNode**);
+void addTurkishCollTest(TestNode**);
+void addEnglishCollTest(TestNode**);
+void addFinnishCollTest(TestNode**);
+
+void addRuleBasedCollTest(TestNode**);
+void addCollIterTest(TestNode**);
+void addAllCollTest(TestNode**);
+void addMiscCollTest(TestNode**);
+void addSearchTest(TestNode**);
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c
new file mode 100644
index 00000000000..c4d431b72a9
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cconvtst.c
@@ -0,0 +1,39 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CCONVTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+#include "cintltst.h"
+
+void addTestConvert(TestNode**);
+void addTestNewConvert(TestNode**);
+void addTestConvertErrorCallBack(TestNode** root);
+void addTestEuroRegression(TestNode** root);
+void addTestConverterFallBack(TestNode** root);
+void addExtraTests(TestNode** root);
+
+/* bocu1tst.c */
+U_CFUNC void
+addBOCU1Tests(TestNode** root);
+
+void addConvert(TestNode** root);
+
+void addConvert(TestNode** root)
+{
+ addTestConvert(root);
+ addTestNewConvert(root);
+ addBOCU1Tests(root);
+ addTestConvertErrorCallBack(root);
+ addTestEuroRegression(root);
+ addTestConverterFallBack(root);
+ addExtraTests(root);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c
new file mode 100644
index 00000000000..c7085a12b6a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cctest.c
@@ -0,0 +1,36 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2004, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_err.h"
+
+#include "cintltst.h"
+#include "ustr_cnv.h"
+void TestDefaultConverterError(void); /* keep gcc happy */
+
+
+/* This makes sure that a converter isn't leaked when an error is passed to
+ u_getDefaultConverter */
+void TestDefaultConverterError(void) {
+ UErrorCode err = U_ZERO_ERROR;
+
+ /* Remove the default converter */
+ ucnv_close(u_getDefaultConverter(&err));
+
+ if (U_FAILURE(err)) {
+ log_err("Didn't expect a failure yet %s\n", myErrorName(err));
+ return;
+ }
+
+ /* Set to any radom error state */
+ err = U_FILE_ACCESS_ERROR;
+ if (u_getDefaultConverter(&err) != NULL) {
+ log_err("Didn't expect to get a converter on a failure\n");
+ }
+}
+
+
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c
new file mode 100644
index 00000000000..a768be7c8e3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.c
@@ -0,0 +1,167 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CCURRTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************
+*/
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if (!UCONFIG_NO_COLLATION) /* This is not a formatting test. This is a collation test. */
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccurrtst.h"
+#include "ccolltst.h"
+#include "unicode/ustring.h"
+#include "cmemory.h"
+
+#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
+
+void addCurrencyCollTest(TestNode** root)
+{
+
+ addTest(root, &currTest, "tscoll/ccurrtst/currTest");
+
+}
+
+
+void currTest()
+{
+ /* All the currency symbols, in UCA order*/
+ static const UChar currency[][2] =
+ {
+ { 0x00A4, 0x0000}, /*00A4; L; [14 36, 03, 03] # [082B.0020.0002] # CURRENCY SIGN*/
+ { 0x00A2, 0x0000}, /*00A2; L; [14 38, 03, 03] # [082C.0020.0002] # CENT SIGN*/
+ { 0xFFE0, 0x0000}, /*FFE0; L; [14 38, 03, 05] # [082C.0020.0003] # FULLWIDTH CENT SIGN*/
+ { 0x0024, 0x0000}, /*0024; L; [14 3A, 03, 03] # [082D.0020.0002] # DOLLAR SIGN*/
+ { 0xFF04, 0x0000}, /*FF04; L; [14 3A, 03, 05] # [082D.0020.0003] # FULLWIDTH DOLLAR SIGN*/
+ { 0xFE69, 0x0000}, /*FE69; L; [14 3A, 03, 1D] # [082D.0020.000F] # SMALL DOLLAR SIGN*/
+ { 0x00A3, 0x0000}, /*00A3; L; [14 3C, 03, 03] # [082E.0020.0002] # POUND SIGN*/
+ { 0xFFE1, 0x0000}, /*FFE1; L; [14 3C, 03, 05] # [082E.0020.0003] # FULLWIDTH POUND SIGN*/
+ { 0x00A5, 0x0000}, /*00A5; L; [14 3E, 03, 03] # [082F.0020.0002] # YEN SIGN*/
+ { 0xFFE5, 0x0000}, /*FFE5; L; [14 3E, 03, 05] # [082F.0020.0003] # FULLWIDTH YEN SIGN*/
+ { 0x09F2, 0x0000}, /*09F2; L; [14 40, 03, 03] # [0830.0020.0002] # BENGALI RUPEE MARK*/
+ { 0x09F3, 0x0000}, /*09F3; L; [14 42, 03, 03] # [0831.0020.0002] # BENGALI RUPEE SIGN*/
+ { 0x0E3F, 0x0000}, /*0E3F; L; [14 44, 03, 03] # [0832.0020.0002] # THAI CURRENCY SYMBOL BAHT*/
+ { 0x17DB, 0x0000}, /*17DB; L; [14 46, 03, 03] # [0833.0020.0002] # KHMER CURRENCY SYMBOL RIEL*/
+ { 0x20A0, 0x0000}, /*20A0; L; [14 48, 03, 03] # [0834.0020.0002] # EURO-CURRENCY SIGN*/
+ { 0x20A1, 0x0000}, /*20A1; L; [14 4A, 03, 03] # [0835.0020.0002] # COLON SIGN*/
+ { 0x20A2, 0x0000}, /*20A2; L; [14 4C, 03, 03] # [0836.0020.0002] # CRUZEIRO SIGN*/
+ { 0x20A3, 0x0000}, /*20A3; L; [14 4E, 03, 03] # [0837.0020.0002] # FRENCH FRANC SIGN*/
+ { 0x20A4, 0x0000}, /*20A4; L; [14 50, 03, 03] # [0838.0020.0002] # LIRA SIGN*/
+ { 0x20A5, 0x0000}, /*20A5; L; [14 52, 03, 03] # [0839.0020.0002] # MILL SIGN*/
+ { 0x20A6, 0x0000}, /*20A6; L; [14 54, 03, 03] # [083A.0020.0002] # NAIRA SIGN*/
+ { 0x20A7, 0x0000}, /*20A7; L; [14 56, 03, 03] # [083B.0020.0002] # PESETA SIGN*/
+ { 0x20A9, 0x0000}, /*20A9; L; [14 58, 03, 03] # [083C.0020.0002] # WON SIGN*/
+ { 0xFFE6, 0x0000}, /*FFE6; L; [14 58, 03, 05] # [083C.0020.0003] # FULLWIDTH WON SIGN*/
+ { 0x20AA, 0x0000}, /*20AA; L; [14 5A, 03, 03] # [083D.0020.0002] # NEW SHEQEL SIGN*/
+ { 0x20AB, 0x0000}, /*20AB; L; [14 5C, 03, 03] # [083E.0020.0002] # DONG SIGN*/
+ { 0x20AC, 0x0000}, /*20AC; L; [14 5E, 03, 03] # [083F.0020.0002] # EURO SIGN*/
+ { 0x20AD, 0x0000}, /*20AD; L; [14 60, 03, 03] # [0840.0020.0002] # KIP SIGN*/
+ { 0x20AE, 0x0000}, /*20AE; L; [14 62, 03, 03] # [0841.0020.0002] # TUGRIK SIGN*/
+ { 0x20AF, 0x0000}, /*20AF; L; [14 64, 03, 03] # [0842.0020.0002] # DRACHMA SIGN*/
+ };
+
+#if 0
+ /* All the currency symbols, in collation order*/
+ static const UChar currency[][2] =
+ {
+ { 0x00a4, 0x0000}, /* generic currency*/
+ { 0x0e3f, 0x0000}, /* baht*/
+ { 0x00a2, 0x0000}, /* cent*/
+ { 0x20a1, 0x0000}, /* colon*/
+ { 0x20a2, 0x0000}, /* cruzeiro*/
+ { 0x0024, 0x0000}, /* dollar */
+ { 0x20ab, 0x0000}, /* dong */
+ { 0x20ac, 0x0000}, /* euro */
+ { 0x20a3, 0x0000}, /* franc */
+ { 0x20a4, 0x0000}, /* lira */
+ { 0x20a5, 0x0000}, /* mill */
+ { 0x20a6, 0x0000}, /* naira */
+ { 0x20a7, 0x0000}, /* peseta */
+ { 0x00a3, 0x0000}, /* pound */
+ { 0x20a8, 0x0000}, /* rupee */
+ { 0x20aa, 0x0000}, /* shekel*/
+ { 0x20a9, 0x0000}, /* won*/
+ { 0x00a5, 0x0000} /* yen*/
+ };
+#endif
+
+ UChar source[2], target[2];
+ int32_t i, j, sortklen;
+ int res;
+ UCollator *c;
+ uint8_t *sortKey1, *sortKey2;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationResult compareResult, keyResult;
+ UCollationResult expectedResult = UCOL_EQUAL;
+ log_verbose("Testing currency of all locales\n");
+ c = ucol_open("en_US", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("collator open failed! :%s\n", myErrorName(status));
+ return;
+ }
+
+ /*Compare each currency symbol against all the
+ currency symbols, including itself*/
+ for (i = 0; i < ARRAY_LENGTH(currency); i += 1)
+ {
+ for (j = 0; j < ARRAY_LENGTH(currency); j += 1)
+ {
+ u_strcpy(source, currency[i]);
+ u_strcpy(target, currency[j]);
+
+ if (i < j)
+ {
+ expectedResult = UCOL_LESS;
+ }
+ else if ( i == j)
+ {
+ expectedResult = UCOL_EQUAL;
+ }
+ else
+ {
+ expectedResult = UCOL_GREATER;
+ }
+
+ compareResult = ucol_strcoll(c, source, u_strlen(source), target, u_strlen(target));
+
+ status = U_ZERO_ERROR;
+
+ sortklen=ucol_getSortKey(c, source, u_strlen(source), NULL, 0);
+ sortKey1=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ ucol_getSortKey(c, source, u_strlen(source), sortKey1, sortklen+1);
+
+ sortklen=ucol_getSortKey(c, target, u_strlen(target), NULL, 0);
+ sortKey2=(uint8_t*)malloc(sizeof(uint8_t) * (sortklen+1));
+ ucol_getSortKey(c, target, u_strlen(target), sortKey2, sortklen+1);
+
+ res = uprv_memcmp(sortKey1, sortKey2, sortklen);
+ if (res < 0) keyResult = (UCollationResult)-1;
+ else if (res > 0) keyResult = (UCollationResult)1;
+ else keyResult = (UCollationResult)0;
+
+ reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResult, expectedResult );
+
+ free(sortKey1);
+ free(sortKey2);
+
+ }
+ }
+ ucol_close(c);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h
new file mode 100644
index 00000000000..bec5e99815e
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ccurrtst.h
@@ -0,0 +1,35 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CCURRTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*/
+/**
+ * Collation currency tests.
+ * (It's important to stay current!)
+ */
+
+#ifndef _CCURRCOLLTST
+#define _CCURRCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+ /* Perform Collation Currency Test */
+ void currTest(void);
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c
new file mode 100644
index 00000000000..0bdd4906dd3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.c
@@ -0,0 +1,958 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDATTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+
+/* C API TEST FOR DATE FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/uloc.h"
+#include "unicode/udat.h"
+#include "unicode/ucal.h"
+#include "unicode/unum.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cdattst.h"
+#include "cformtst.h"
+#include "cmemory.h"
+
+#include <math.h>
+
+static void TestExtremeDates(void);
+static void TestAllLocales(void);
+
+#define LEN(a) (sizeof(a)/sizeof(a[0]))
+
+void addDateForTest(TestNode** root);
+
+#define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x)
+
+void addDateForTest(TestNode** root)
+{
+ TESTCASE(TestDateFormat);
+ TESTCASE(TestSymbols);
+ TESTCASE(TestDateFormatCalendar);
+ TESTCASE(TestExtremeDates);
+ TESTCASE(TestAllLocales);
+}
+/* Testing the DateFormat API */
+static void TestDateFormat()
+{
+ UDateFormat *def, *fr, *it, *de, *def1, *fr_pat;
+ UDateFormat *any;
+ UDateFormat *copy;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar* result = NULL;
+ const UCalendar *cal;
+ const UNumberFormat *numformat1, *numformat2;
+ UChar temp[50];
+ int32_t numlocales;
+ UDate d1;
+ int i;
+ int32_t resultlength;
+ int32_t resultlengthneeded;
+ int32_t parsepos;
+ UDate d = 837039928046.0;
+ double num = -10456.37;
+ /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z";
+ const char t[]="2/3/76 2:50 AM";*/
+ /*Testing udat_open() to open a dateformat */
+
+ ctest_setTimeZone(NULL, &status);
+
+ log_verbose("\nTesting udat_open() with various parameters\n");
+ fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using full time style with french locale\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
+ def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+ it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+ de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ /*creating a default dateformat */
+ def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+
+
+ /*Testing udat_getAvailable() and udat_countAvailable()*/
+ log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
+ numlocales=udat_countAvailable();
+ /* use something sensible w/o hardcoding the count */
+ if(numlocales < 0)
+ log_data_err("FAIL: error in countAvailable\n");
+ log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
+
+ for(i=0;i<numlocales;i++) {
+ UErrorCode subStatus = U_ZERO_ERROR;
+ log_verbose("Testing open of %s\n", udat_getAvailable(i));
+ any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus);
+ if(U_FAILURE(subStatus)) {
+ log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus));
+ }
+ udat_close(any);
+ }
+
+ /*Testing udat_clone()*/
+ log_verbose("\nTesting the udat_clone() function of date format\n");
+ copy=udat_clone(def, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) );
+ }
+ /*if(def != copy)
+ log_err("Error in udat_clone");*/ /*how should i check for equality???? */
+
+ /*Testing udat_format()*/
+ log_verbose("\nTesting the udat_format() function of date format\n");
+ u_uastrcpy(temp, "7/10/96 4:05 PM");
+ /*format using def */
+ resultlength=0;
+ resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_format(def, d, result, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status) || !result)
+ {
+ log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) );
+ return;
+ }
+ else
+ log_verbose("PASS: formatting successful\n");
+ if(u_strcmp(result, temp)==0)
+ log_verbose("PASS: Date Format for US locale successful uisng udat_format()\n");
+ else
+ log_err("FAIL: Date Format for US locale failed using udat_format()\n");
+ /*format using fr */
+
+ u_unescape("10 juil. 1996 16:05:28 \\u00C9tats-Unis (Los Angeles)", temp, 50);
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ result=myDateFormat(fr, d);
+ if(u_strcmp(result, temp)==0)
+ log_verbose("PASS: Date Format for french locale successful using udat_format()\n");
+ else
+ log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" );
+
+ /*format using it */
+ u_uastrcpy(temp, "10/lug/1996 16:05:28");
+
+ {
+ UChar *fmtted;
+ char g[100];
+ char x[100];
+
+ fmtted = myDateFormat(it,d);
+ u_austrcpy(g, fmtted);
+ u_austrcpy(x, temp);
+ if(u_strcmp(fmtted, temp)==0) {
+ log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g);
+ } else {
+ log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
+ }
+ }
+
+ /*Testing parsing using udat_parse()*/
+ log_verbose("\nTesting parsing using udat_parse()\n");
+ u_uastrcpy(temp,"2/3/76 2:50 AM");
+ parsepos=0;
+ status=U_ZERO_ERROR;
+
+ d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) );
+ }
+ else
+ log_verbose("PASS: parsing succesful\n");
+ /*format it back and check for equality */
+
+
+ if(u_strcmp(myDateFormat(def, d1),temp)!=0)
+ log_err("FAIL: error in parsing\n");
+
+ /*Testing parsing using udat_parse()*/
+ log_verbose("\nTesting parsing using udat_parse()\n");
+ u_uastrcpy(temp,"2/Don't parse this part");
+ status=U_ZERO_ERROR;
+
+ d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
+ if(status != U_PARSE_ERROR)
+ {
+ log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n");
+ }
+ else
+ log_verbose("PASS: parsing succesful\n");
+
+
+
+ /*Testing udat_openPattern() */
+ status=U_ZERO_ERROR;
+ log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
+ /*for french locale */
+ fr_pat=udat_open(UDAT_IGNORE, UDAT_IGNORE,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
+ myErrorName(status) );
+ }
+ else
+ log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
+
+
+ /*Testing applyPattern and toPattern */
+ log_verbose("\nTesting applyPattern and toPattern()\n");
+ udat_applyPattern(def1, FALSE, temp, u_strlen(temp));
+ log_verbose("Extracting the pattern\n");
+
+ resultlength=0;
+ resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded + 1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_toPattern(def1, FALSE, result, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
+ myErrorName(status) );
+ }
+ if(u_strcmp(result, temp)!=0)
+ log_err("FAIL: Error in extracting the pattern\n");
+ else
+ log_verbose("PASS: applyPattern and toPattern work fine\n");
+
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+
+
+ /*Testing getter and setter functions*/
+ /*isLenient and setLenient()*/
+ log_verbose("\nTesting the isLenient and setLenient properties\n");
+ udat_setLenient(fr, udat_isLenient(it));
+ if(udat_isLenient(fr) != udat_isLenient(it))
+ log_err("ERROR: setLenient() failed\n");
+ else
+ log_verbose("PASS: setLenient() successful\n");
+
+
+ /*Test get2DigitYearStart set2DigitYearStart */
+ log_verbose("\nTesting the get and set 2DigitYearStart properties\n");
+ d1= udat_get2DigitYearStart(fr_pat,&status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) );
+ }
+ status = U_ZERO_ERROR;
+ udat_set2DigitYearStart(def1 ,d1, &status);
+ if(U_FAILURE(status)) {
+ log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
+ }
+ if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status))
+ log_err("FAIL: error in set2DigitYearStart\n");
+ else
+ log_verbose("PASS: set2DigitYearStart successful\n");
+ /*try setting it to another value */
+ udat_set2DigitYearStart(de, 2000.0, &status);
+ if(U_FAILURE(status)){
+ log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
+ }
+ if(udat_get2DigitYearStart(de, &status) != 2000)
+ log_err("FAIL: error in set2DigitYearStart\n");
+ else
+ log_verbose("PASS: set2DigitYearStart successful\n");
+
+
+
+ /*Test getNumberFormat() and setNumberFormat() */
+ log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
+ numformat1=udat_getNumberFormat(fr_pat);
+ udat_setNumberFormat(def1, numformat1);
+ numformat2=udat_getNumberFormat(def1);
+ if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
+ log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
+ else
+ log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n");
+
+ /*try setting the number format to another format */
+ numformat1=udat_getNumberFormat(def);
+ udat_setNumberFormat(def1, numformat1);
+ numformat2=udat_getNumberFormat(def1);
+ if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
+ log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
+ else
+ log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n");
+
+
+
+ /*Test getCalendar and setCalendar*/
+ log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
+ cal=udat_getCalendar(fr_pat);
+
+
+ udat_setCalendar(def1, cal);
+ if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
+ log_err("FAIL: Error in setting and getting the calendar\n");
+ else
+ log_verbose("PASS: getting and setting calendar successful\n");
+
+ if(result!=NULL) {
+ free(result);
+ }
+
+ /*Closing the UDateForamt */
+ udat_close(def);
+ udat_close(fr);
+ udat_close(it);
+ udat_close(de);
+ udat_close(def1);
+ udat_close(fr_pat);
+ udat_close(copy);
+
+ ctest_resetTimeZone();
+}
+
+/*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/
+static void TestSymbols()
+{
+ UDateFormat *def, *fr;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *value=NULL;
+ UChar *result = NULL;
+ int32_t resultlength;
+ int32_t resultlengthout;
+ UChar *pattern;
+
+
+ /*creating a dateformat with french locale */
+ log_verbose("\ncreating a date format with french locale\n");
+ fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat using full time style with french locale\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+ /*creating a default dateformat */
+ log_verbose("\ncreating a date format with default locale\n");
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
+ def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat using short date and time style\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+
+
+ /*Testing countSymbols, getSymbols and setSymbols*/
+ log_verbose("\nTesting countSymbols\n");
+ /*since the month names has the last string empty and week names are 1 based 1.e first string in the weeknames array is empty */
+ if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
+ udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
+ udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
+ udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
+ udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1)
+ {
+ log_err("FAIL: error in udat_countSymbols\n");
+ }
+ else
+ log_verbose("PASS: udat_countSymbols() successful\n");
+
+ /*testing getSymbols*/
+ log_verbose("\nTesting getSymbols\n");
+ pattern=(UChar*)malloc(sizeof(UChar) * 10);
+ u_uastrcpy(pattern, "jeudi");
+ resultlength=0;
+ resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
+
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) );
+ }
+ else
+ log_verbose("PASS: getSymbols succesful\n");
+
+ if(u_strcmp(result, pattern)==0)
+ log_verbose("PASS: getSymbols retrieved the right value\n");
+ else
+ log_data_err("FAIL: getSymbols retrieved the wrong value\n");
+
+ /*run series of tests to test getsymbols regressively*/
+ log_verbose("\nTesting getSymbols() regressively\n");
+ VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche");
+ VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday");
+ VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam.");
+ VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat");
+ VerifygetSymbols(def, UDAT_MONTHS, 11, "December");
+ VerifygetSymbols(def, UDAT_MONTHS, 0, "January");
+ VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C.");
+ VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM");
+ VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM");
+ VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv.");
+ VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec");
+ VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre");
+ VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter");
+ VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2");
+ VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3");
+ VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqV");
+
+
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+free(pattern);
+
+ log_verbose("\nTesting setSymbols\n");
+ /*applying the pattern so that setSymbolss works */
+ resultlength=0;
+ resultlengthout=udat_toPattern(fr, FALSE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout + 1;
+ pattern=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_toPattern(fr, FALSE, pattern, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
+ myErrorName(status) );
+ }
+
+ udat_applyPattern(def, FALSE, pattern, u_strlen(pattern));
+ resultlength=0;
+ resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout + 1;
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_toPattern(fr, FALSE,result, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
+ myErrorName(status) );
+ }
+ if(u_strcmp(result, pattern)==0)
+ log_verbose("Pattern applied properly\n");
+ else
+ log_err("pattern could not be applied properly\n");
+
+free(pattern);
+ /*testing set symbols */
+ resultlength=0;
+ resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
+
+ }
+ if(U_FAILURE(status))
+ log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
+ resultlength=resultlengthout+1;
+
+ udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
+ }
+ else
+ log_verbose("PASS: SetSymbols successful\n");
+
+ resultlength=0;
+ resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ value=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
+
+ if(u_strcmp(result, value)!=0)
+ log_data_err("FAIL: Error in settting and getting symbols\n");
+ else
+ log_verbose("PASS: setSymbols successful\n");
+
+
+ /*run series of tests to test setSymbols regressively*/
+ log_verbose("\nTesting setSymbols regressively\n");
+ VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
+ VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini");
+ VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek");
+ VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek");
+ VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M");
+ VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek");
+ VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams");
+ VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V");
+ VerifysetSymbols(fr, UDAT_MONTHS, 11, "december");
+ VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan");
+ VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R");
+ VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember");
+ VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug");
+ VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M");
+ VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart");
+ VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2");
+ VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar.");
+ VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ");
+
+
+ /*run series of tests to test get and setSymbols regressively*/
+ log_verbose("\nTesting get and set symbols regressively\n");
+ VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1);
+ VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7);
+ VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1);
+ VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7);
+ VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0);
+ VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0);
+ VerifygetsetSymbols(fr, def, UDAT_ERAS,1);
+ VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0);
+ VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1);
+
+
+ /*closing*/
+
+ udat_close(fr);
+ udat_close(def);
+ if(result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ free(value);
+
+}
+
+/**
+ * Test DateFormat(Calendar) API
+ */
+static void TestDateFormatCalendar() {
+ UDateFormat *date=0, *time=0, *full=0;
+ UCalendar *cal=0;
+ UChar buf[256];
+ char cbuf[256];
+ int32_t pos;
+ UDate when;
+ UErrorCode ec = U_ZERO_ERROR;
+
+ ctest_setTimeZone(NULL, &ec);
+
+ /* Create a formatter for date fields. */
+ date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s\n",
+ u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Create a formatter for time fields. */
+ time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
+ u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Create a full format for output */
+ full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
+ u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Create a calendar */
+ cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: ucal_open(en_US) failed with %s\n",
+ u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Parse the date */
+ ucal_clear(cal);
+ u_uastrcpy(buf, "4/5/2001");
+ pos = 0;
+ udat_parseCalendar(date, cal, buf, -1, &pos, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n",
+ pos, u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Parse the time */
+ u_uastrcpy(buf, "5:45 PM");
+ pos = 0;
+ udat_parseCalendar(time, cal, buf, -1, &pos, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n",
+ pos, u_errorName(ec));
+ goto FAIL;
+ }
+
+ /* Check result */
+ when = ucal_getMillis(cal, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec));
+ goto FAIL;
+ }
+ udat_format(full, when, buf, sizeof(buf), NULL, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec));
+ goto FAIL;
+ }
+ u_austrcpy(cbuf, buf);
+ /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */
+ if (when == 986517900000.0) {
+ log_verbose("Ok: Parsed result: %s\n", cbuf);
+ } else {
+ log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
+ }
+
+ FAIL:
+ udat_close(date);
+ udat_close(time);
+ udat_close(full);
+ ucal_close(cal);
+
+ ctest_resetTimeZone();
+}
+
+/*INTERNAL FUNCTIONS USED*/
+static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected)
+{
+ UChar *pattern=NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *result=NULL;
+ int32_t resultlength, resultlengthout;
+
+
+ pattern=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1));
+ u_uastrcpy(pattern, expected);
+ resultlength=0;
+ resultlengthout=udat_getSymbols(datfor, type, index , NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(datfor, type, index, result, resultlength, &status);
+
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) );
+ return;
+ }
+ if(u_strcmp(result, pattern)==0)
+ log_verbose("PASS: getSymbols retrieved the right value\n");
+ else{
+ log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", austrdup(pattern),
+ austrdup(result) );
+ }
+ free(result);
+ free(pattern);
+}
+
+static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected)
+{
+ UChar *result=NULL;
+ UChar *value=NULL;
+ int32_t resultlength, resultlengthout;
+ UErrorCode status = U_ZERO_ERROR;
+
+ value=(UChar*)malloc(sizeof(UChar) * (strlen(expected) + 1));
+ u_uastrcpy(value, expected);
+ udat_setSymbols(datfor, type, index, value, u_strlen(value), &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) );
+ return;
+ }
+
+ resultlength=0;
+ resultlengthout=udat_getSymbols(datfor, type, index, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(datfor, type, index, result, resultlength, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+
+ if(u_strcmp(result, value)!=0){
+ log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(value),
+ austrdup(result) );
+ }
+ else
+ log_verbose("PASS: setSymbols successful\n");
+
+ free(value);
+ free(result);
+}
+
+
+static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t index)
+{
+ UChar *result=NULL;
+ UChar *value=NULL;
+ int32_t resultlength, resultlengthout;
+ UErrorCode status = U_ZERO_ERROR;
+
+ resultlength=0;
+ resultlengthout=udat_getSymbols(from, type, index , NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(from, type, index, result, resultlength, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
+ return;
+ }
+
+ resultlength=resultlengthout+1;
+ udat_setSymbols(to, type, index, result, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
+ return;
+ }
+
+ resultlength=0;
+ resultlengthout=udat_getSymbols(to, type, index, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthout+1;
+ value=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_getSymbols(to, type, index, value, resultlength, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
+ myErrorName(status) );
+ return;
+ }
+
+ if(u_strcmp(result, value)!=0){
+ log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
+ austrdup(value) );
+ }
+ else
+ log_verbose("PASS: setSymbols successful\n");
+
+ free(value);
+ free(result);
+}
+
+
+static UChar* myNumformat(const UNumberFormat* numfor, double d)
+{
+ UChar *result2=NULL;
+ int32_t resultlength, resultlengthneeded;
+ UErrorCode status = U_ZERO_ERROR;
+
+ resultlength=0;
+ resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */
+ result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
+ unum_formatDouble(numfor, d, result2, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
+ return 0;
+ }
+
+ return result2;
+}
+
+/**
+ * The search depth for TestExtremeDates. The total number of
+ * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1.
+ */
+#define EXTREME_DATES_DEPTH 8
+
+/**
+ * Support for TestExtremeDates (below).
+ *
+ * Test a single date to see whether udat_format handles it properly.
+ */
+static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date,
+ UChar* buf, int32_t buflen, char* cbuf,
+ UErrorCode* ec) {
+ int32_t len = udat_format(fmt, date, buf, buflen, 0, ec);
+ if (!assertSuccess("udat_format", ec)) return FALSE;
+ u_austrncpy(cbuf, buf, buflen);
+ if (len < 4) {
+ log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf);
+ } else {
+ log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf);
+ }
+ return TRUE;
+}
+
+/**
+ * Support for TestExtremeDates (below).
+ *
+ * Recursively test between 'small' and 'large', up to the depth
+ * limit specified by EXTREME_DATES_DEPTH.
+ */
+static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large,
+ UChar* buf, int32_t buflen, char* cbuf,
+ int32_t count,
+ UErrorCode* ec) {
+ /* Logarithmic midpoint; see below */
+ UDate mid = (UDate) exp((log(small) + log(large)) / 2);
+ if (count == EXTREME_DATES_DEPTH) {
+ return TRUE;
+ }
+ return
+ _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) &&
+ _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) &&
+ _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec);
+}
+
+/**
+ * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659
+ *
+ * For certain large dates, udat_format crashes on MacOS. This test
+ * attempts to reproduce this problem by doing a recursive logarithmic*
+ * binary search of a predefined interval (from 'small' to 'large').
+ *
+ * The limit of the search is given by EXTREME_DATES_DEPTH, above.
+ *
+ * *The search has to be logarithmic, not linear. A linear search of the
+ * range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and
+ * 0.75*10^30, etc. A logarithmic search will find 10^15, then 10^7.5
+ * and 10^22.5, etc.
+ */
+static void TestExtremeDates() {
+ UDateFormat *fmt;
+ UErrorCode ec;
+ UChar buf[256];
+ char cbuf[256];
+ const double small = 1000; /* 1 sec */
+ const double large = 1e+30; /* well beyond usable UDate range */
+
+ /* There is no need to test larger values from 1e+30 to 1e+300;
+ the failures occur around 1e+27, and never above 1e+30. */
+
+ ec = U_ZERO_ERROR;
+ fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
+ 0, 0, 0, 0, &ec);
+ if (!assertSuccess("udat_open", &ec)) return;
+
+ _aux2ExtremeDates(fmt, small, large, buf, LEN(buf), cbuf, 0, &ec);
+
+ udat_close(fmt);
+}
+
+static void TestAllLocales(void) {
+ int32_t idx, dateIdx, timeIdx, localeCount;
+ static const UDateFormatStyle style[] = {
+ UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT
+ };
+ localeCount = uloc_countAvailable();
+ for (idx = 0; idx < localeCount; idx++) {
+ for (dateIdx = 0; dateIdx < (int32_t)(sizeof(style)/sizeof(style[0])); dateIdx++) {
+ for (timeIdx = 0; timeIdx < (int32_t)(sizeof(style)/sizeof(style[0])); timeIdx++) {
+ UErrorCode status = U_ZERO_ERROR;
+ udat_close(udat_open(style[dateIdx], style[timeIdx],
+ uloc_getAvailable(idx), NULL, 0, NULL, 0, &status));
+ if (U_FAILURE(status)) {
+ log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n",
+ uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx);
+ }
+ }
+ }
+ }
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h
new file mode 100644
index 00000000000..861a1087645
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdattst.h
@@ -0,0 +1,54 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDATTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* C API TEST FOR DATE FORMAT */
+#ifndef _CDATFRMTST
+#define _CDATFRMTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+ /**
+ * The function used to test the Date format API
+ **/
+ static void TestDateFormat(void);
+
+ /**
+ * The function used to test API udat_getSymbols(), udat_setSymbols() and udat_countSymbols()
+ **/
+ static void TestSymbols(void);
+
+ /**
+ * Test DateFormat(Calendar) API
+ */
+ static void TestDateFormatCalendar(void);
+
+ /**
+ * test subroutines used by TestSymbols
+ **/
+ static void VerifygetSymbols(UDateFormat*, UDateFormatSymbolType, int32_t, const char*);
+ static void VerifysetSymbols(UDateFormat*, UDateFormatSymbolType, int32_t, const char*);
+ static void VerifygetsetSymbols(UDateFormat*, UDateFormat*, UDateFormatSymbolType, int32_t);
+
+ /**
+ * test subroutine used by the testing functions
+ **/
+ static UChar* myNumformat(const UNumberFormat* numfor, double d);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c
new file mode 100644
index 00000000000..6d53b74e602
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.c
@@ -0,0 +1,139 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDETST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * CollationGermanTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "cdetst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] =
+{
+ {0x0047/*'G'*/, 0x0072/*'r'*/, 0x00F6, 0x00DF, 0x0065/*'e'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0054/*'T'*/, 0x00F6, 0x006e/*'n'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000},
+ {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here */
+ {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/
+ {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x00DF, 0x0065/*'e'*/, 0x0000},
+ {0x0065/*'e'*/, 0x0066/*'f'*/, 0x0067/*'g'*/, 0x0000},
+ {0x00E4, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/
+ {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x00DF, 0x0065/*'e'*/, 0x0000}
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] =
+{
+ {0x0047/*'G'*/, 0x0072/*'r'*/, 0x006f/*'o'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0069/*'i'*/, 0x0073/*'s'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0054/*'T'*/, 0x006f/*'o'*/, 0x006e/*'n'*/, 0x0000},
+ {0x0054/*'T'*/, 0x006f/*'o'*/, 0x0064/*'d'*/, 0x0000},
+ {0x0054/*'T'*/, 0x006f/*'o'*/, 0x0066/*'f'*/, 0x0075/*'u'*/, 0x0000},
+ {0x0041/*'A'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0308, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/
+ {0x0061/*'a'*/, 0x0065/*'e'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/
+ {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0065/*'e'*/, 0x0066/*'f'*/, 0x0067/*'g'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0065/*'e'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000}, /*doubt in primary here*/
+ {0x0053/*'S'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0073/*'s'*/, 0x0065/*'e'*/, 0x0000}
+};
+
+const static UCollationResult results[][2] =
+{
+ /* Primary*/ /* Tertiary*/
+ { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/
+ { UCOL_EQUAL, UCOL_LESS },
+ { UCOL_GREATER, UCOL_GREATER },
+ { UCOL_GREATER, UCOL_GREATER },
+ { UCOL_GREATER, UCOL_GREATER },
+ { UCOL_EQUAL, UCOL_LESS },
+ { UCOL_EQUAL, UCOL_EQUAL }, /*should be UCOL_GREATER for primary*/
+ { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/
+ { UCOL_EQUAL, UCOL_GREATER },
+ { UCOL_EQUAL, UCOL_EQUAL },
+ { UCOL_LESS, UCOL_LESS }, /*should be UCOL_GREATER for primary*/
+ { UCOL_EQUAL, UCOL_GREATER }
+};
+
+
+
+
+void addGermanCollTest(TestNode** root)
+{
+
+
+ addTest(root, &TestTertiary, "tscoll/cdetst/TestTertiary");
+ addTest(root, &TestPrimary, "tscoll/cdetst/TestPrimary");
+
+
+
+}
+
+static void TestTertiary( )
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("de_DE", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing German Collation with Tertiary strength\n");
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 12 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i][1]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestPrimary()
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("de_DE", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status));
+ return;
+ }
+ log_verbose("Testing German Collation with primary strength\n");
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ for (i = 0; i < 12 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i][0]);
+ }
+ ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h
new file mode 100644
index 00000000000..36696a5c2ec
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdetst.h
@@ -0,0 +1,42 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDETST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationGERMANTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CGERCOLLTST
+#define _CGERCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+
+#define MAX_TOKEN_LEN 16
+
+ /* performs test with strength PRIMARY */
+static void TestPrimary(void);
+
+ /* perform test with strength TERTIARY */
+static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c
new file mode 100644
index 00000000000..d19b7eedac4
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.c
@@ -0,0 +1,350 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDTDPTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* INDEPTH TEST FOR DATE FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/uloc.h"
+#include "unicode/udat.h"
+#include "unicode/ucal.h"
+#include "unicode/unum.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cdtdptst.h"
+#include "cformtst.h"
+
+#include "cmemory.h"
+
+void addDtFrDepTest(TestNode** root);
+
+void addDtFrDepTest(TestNode** root)
+{
+ addTest(root, &TestTwoDigitYearDSTParse, "tsformat/cdtdptst/TestTwoDigitYearDSTParse");
+ addTest(root, &TestPartialParse994, "tsformat/cdtdptst/TestPartialParse994");
+ addTest(root, &TestRunTogetherPattern985, "tsformat/cdtdptst/TestRunTogetherPattern985");
+ addTest(root, &TestCzechMonths459, "tsformat/cdtdptst/TestCzechMonths459");
+ addTest(root, &TestQuotePattern161, "tsformat/cdtdptst/TestQuotePattern161");
+
+}
+
+/**
+ * Test the parsing of 2-digit years.
+ */
+void TestTwoDigitYearDSTParse()
+{
+ UDateFormat *fullFmt, *fmt;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *pattern;
+ UDate d;
+ UChar *s;
+ int32_t pos;
+
+ ctest_setTimeZone(NULL, &status);
+
+ pattern=(UChar*)malloc(sizeof(UChar) * (strlen("EEE MMM dd HH:mm:ss.SSS zzz yyyy G")+1 ));
+ u_uastrcpy(pattern, "EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
+ fullFmt= udat_open(UDAT_IGNORE, UDAT_IGNORE,"en_US",NULL,0,pattern, u_strlen(pattern),&status);
+ if(U_FAILURE(status)) {
+ log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
+ myErrorName(status) );
+ }
+ else {log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");}
+
+ u_uastrcpy(pattern, "dd-MMM-yy h:mm:ss 'o''clock' a z");
+ fmt= udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US", NULL, 0,pattern, u_strlen(pattern), &status);
+
+
+ s=(UChar*)malloc(sizeof(UChar) * (strlen("03-Apr-04 2:20:47 o'clock AM PST")+1) );
+ u_uastrcpy(s, "03-Apr-04 2:20:47 o'clock AM PST");
+ pos=0;
+ d = udat_parse(fmt, s, u_strlen(s), &pos, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Could not parse \"%s\"\n", austrdup(s));
+ } else {
+ UCalendar *cal = ucal_open(NULL, 0, uloc_getDefault(), UCAL_TRADITIONAL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Could not open calendar");
+ } else {
+ int32_t h;
+ ucal_setMillis(cal, d, &status);
+ h = ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Some calendar operations failed");
+ } else if (h != 2) {
+ log_err("FAIL: Parse of \"%s\" returned HOUR_OF_DAY %d\n",
+ austrdup(s), h);
+ }
+ ucal_close(cal);
+ }
+ }
+
+ udat_close(fullFmt);
+ udat_close(fmt);
+ free(pattern);
+ free(s);
+
+ ctest_resetTimeZone();
+}
+
+
+/**
+ * Verify that strings which contain incomplete specifications are parsed
+ * correctly. In some instances, this means not being parsed at all, and
+ * returning an appropriate error.
+ */
+void TestPartialParse994()
+{
+ int32_t pos;
+ UDateFormat *f;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *s;
+ UChar *fmtChars;
+ UDate d, null;
+ null=0;
+
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* f = udat_open(UDAT_DEFAULT, UDAT_SHORT, NULL, NULL, 0, &status); */
+ f = udat_open(UDAT_DEFAULT, UDAT_SHORT, "en_US", NULL, 0, NULL, 0,&status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: ErrorCode received during test: %s\n", myErrorName(status));
+ return;
+ }
+ s=(UChar*)malloc(sizeof(UChar) * (strlen("01/01/1997 10:11:42 AM")+1) );
+ u_uastrcpy(s, "01/01/1997 10:11:42 AM");
+ pos=0;
+ d = udat_parse(f, s, u_strlen(s), &pos, &status);
+ if(U_FAILURE(status)) {
+ log_data_err("FAIL: could not parse - exitting");
+ return;
+ }
+ fmtChars = myDateFormat(f, d);
+ if(fmtChars) {
+ log_verbose("%s\n", fmtChars);
+ } else {
+ log_data_err("FAIL: could not format \n");
+ return;
+ }
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:11:42", d);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 ", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01", null);
+ udat_close(f);
+ free(s);
+}
+
+
+
+void tryPat994(UDateFormat* format, const char* pattern, const char* s, UDate expected)
+{
+ UChar *f;
+ UChar *str, *pat;
+ UDate date;
+ UDate null=0;
+ int32_t pos;
+ UErrorCode status = U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (strlen(s) + 1) );
+ u_uastrcpy(str, s);
+ pat=(UChar*)malloc(sizeof(UChar) * (strlen(pattern) + 1) );
+ u_uastrcpy(pat, pattern);
+ log_verbose("Pattern : %s ; String : %s\n", austrdup(pat), austrdup(str));
+ udat_applyPattern(format, FALSE, pat, u_strlen(pat));
+ pos=0;
+ date = udat_parse(format, str, u_strlen(str), &pos, &status);
+ if(U_FAILURE(status) || date == null) {
+ log_verbose("ParseException: : %s\n", myErrorName(status) );
+ if (expected != null)
+ log_err("FAIL: Expected: %s\n", austrdup(myDateFormat(format, expected)) );
+ }
+ else {
+ f=myDateFormat(format, date);
+ log_verbose(" parse( %s ) -> %s\n", austrdup(str), austrdup(f));
+ if (expected == null || date != expected)
+ log_err("FAIL: Expected null for \"%s\"\n", s);
+ if (u_strcmp(f, str) !=0)
+ log_err("FAIL: Expected : %s\n", austrdup(str) );
+ }
+
+ free(str);
+ free(pat);
+}
+
+
+/**
+ * Verify the behavior of patterns in which digits for different fields run together
+ * without intervening separators.
+ */
+void TestRunTogetherPattern985()
+{
+ int32_t pos;
+ UChar *pattern=NULL, *now=NULL, *then=NULL;
+ UDateFormat *format;
+ UDate date1, date2;
+ UErrorCode status = U_ZERO_ERROR;
+ pattern=(UChar*)malloc(sizeof(UChar) * (strlen("yyyyMMddHHmmssSSS")+1) );
+ u_uastrcpy(pattern, "yyyyMMddHHmmssSSS");
+ format = udat_open(UDAT_IGNORE, UDAT_IGNORE, NULL, NULL, 0,pattern, u_strlen(pattern), &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: Error in date format construction with pattern: %s\n", myErrorName(status));
+ return;
+ }
+ date1 = ucal_getNow();
+ now=myDateFormat(format, date1);
+ log_verbose("%s\n", austrdup(now) );
+ pos = 0;
+ date2 = udat_parse(format, now, u_strlen(now), &pos, &status);
+ if (date2 == 0) log_verbose("Parse stopped at : %d\n", pos);
+ else then=myDateFormat(format, date2);
+ log_verbose("%s\n", austrdup(then) );
+ if (!(date2 == date1)) log_err("FAIL\n");
+
+ udat_close(format);
+ free(pattern);
+
+}
+
+/**
+ * Verify the handling of Czech June and July, which have the unique attribute that
+ * one is a proper prefix substring of the other.
+ */
+void TestCzechMonths459()
+{
+ int32_t lneed, pos;
+ UChar *pattern=NULL, *tzID=NULL;
+ UChar *juneStr, *julyStr;
+ UDateFormat *fmt;
+ UCalendar *cal;
+ UDate june, july, d;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *date;
+
+ ctest_setTimeZone(NULL, &status);
+ fmt = udat_open(UDAT_FULL, UDAT_FULL, "cs", NULL, 0, NULL, 0, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in constructing the date format\n");
+ ctest_resetTimeZone();
+ return;
+ }
+ lneed=0;
+ lneed=udat_toPattern(fmt, TRUE, NULL, lneed, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ pattern=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ udat_toPattern(fmt, TRUE, pattern, lneed+1, &status);
+ }
+ if(U_FAILURE(status)){ log_err("Error in extracting the pattern\n"); }
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "GMT");
+ cal=ucal_open(tzID, u_strlen(tzID), "cs", UCAL_GREGORIAN, &status);
+ if(U_FAILURE(status)){ log_err("error in ucal_open caldef : %s\n", myErrorName(status)); }
+
+ ucal_setDate(cal, 1997, UCAL_JUNE, 15, &status);
+ june=ucal_getMillis(cal, &status);
+ ucal_setDate(cal, 1997, UCAL_JULY, 15, &status);
+ july=ucal_getMillis(cal, &status);
+
+ juneStr = myDateFormat(fmt, june);
+ julyStr = myDateFormat(fmt, july);
+ pos=0;
+ if(juneStr == NULL) {
+ log_data_err("Can't load juneStr. Quitting.\n");
+ return;
+ }
+ d = udat_parse(fmt, juneStr, u_strlen(juneStr), &pos, &status);
+ date = myDateFormat(fmt, d);
+
+ if(U_SUCCESS(status)){
+ UChar* out1 = myDateFormat(fmt, june);
+ UChar* out2 = myDateFormat(fmt, d);
+ if(u_strcmp(out1, out2) !=0)
+ log_err("Error in handling the czech month june\n");
+ else
+ log_verbose("Pass: Date = %s (czech month June)\n", aescstrdup(date, -1));
+ }else{
+ log_err("udat_parse failed. Error. %s\n",u_errorName(status));
+ }
+ pos=0;
+ d = udat_parse(fmt, julyStr, u_strlen(julyStr), &pos, &status);
+ date = myDateFormat(fmt, d);
+ if(u_strcmp(myDateFormat(fmt, july), myDateFormat(fmt, d) ) !=0)
+ log_err("Error in handling the czech month july\n");
+ else
+ log_verbose("Pass: Date = %s (czech month July)\n", aescstrdup(date, -1));
+
+ ctest_resetTimeZone();
+ udat_close(fmt);
+ ucal_close(cal);
+ free(pattern);
+ free(tzID);
+}
+
+/**
+ * Test the handling of single quotes in patterns.
+ */
+void TestQuotePattern161()
+{
+ UDateFormat *format;
+ UCalendar *cal;
+ UDate currentTime_1;
+ UChar *pattern, *tzID, *exp;
+ UChar *dateString;
+ UErrorCode status = U_ZERO_ERROR;
+ const char* expStr = "04/13/1999 at 10:42:28 AM ";
+
+ ctest_setTimeZone(NULL, &status);
+
+ pattern=(UChar*)malloc(sizeof(UChar) * (strlen("MM/dd/yyyy 'at' hh:mm:ss a zzz")+1) );
+ u_uastrcpy(pattern, "MM/dd/yyyy 'at' hh:mm:ss a zzz");
+
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* format= udat_openPattern(pattern, u_strlen(pattern), NULL, &status); */
+ format= udat_open(UDAT_IGNORE, UDAT_IGNORE,"en_US", NULL, 0,pattern, u_strlen(pattern), &status);
+ if(U_FAILURE(status)){
+ log_err("error in udat_open: %s\n", myErrorName(status));
+ return;
+ }
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); }
+
+ ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status);
+ currentTime_1 = ucal_getMillis(cal, &status);
+
+ dateString = myDateFormat(format, currentTime_1);
+ exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) );
+ u_uastrcpy(exp, expStr);
+
+ log_verbose("%s\n", austrdup(dateString) );
+ if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0)
+ log_err("Error in formatting a pattern with single quotes\n");
+
+ udat_close(format);
+ ucal_close(cal);
+ free(exp);
+ free(tzID);
+ free(pattern);
+
+ ctest_resetTimeZone();
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h
new file mode 100644
index 00000000000..11fd9e5faaa
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtdptst.h
@@ -0,0 +1,57 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDTDPTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* INDEPTH TEST FOR DATE FORMAT */
+#ifndef _CDTFRRGSTST
+#define _CDTFRRGSTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+/**
+ * Test the parsing of 2-digit years.
+ */
+void TestTwoDigitYearDSTParse(void);
+/**
+ * Verify that strings which contain incomplete specifications are parsed
+ * correctly. In some instances, this means not being parsed at all, and
+ * returning an appropriate error.
+ */
+void TestPartialParse994(void);
+/**
+ * Verify the behavior of patterns in which digits for different fields run together
+ * without intervening separators.
+ */
+void TestRunTogetherPattern985(void);
+
+/**
+ * Verify the handling of Czech June and July, which have the unique attribute that
+ * one is a proper prefix substring of the other.
+ */
+void TestCzechMonths459(void);
+
+/**
+ * Test the handling of single quotes in patterns.
+ */
+void TestQuotePattern161(void);
+
+/*Internal functions used*/
+void tryPat994(UDateFormat* format, const char* pat, const char* s, UDate expected);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c
new file mode 100644
index 00000000000..3ef0f780af0
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.c
@@ -0,0 +1,536 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDTRGTST.C
+*
+* Madhu Katragadda Ported for C API
+* Modification History:
+* Date Name Description
+* 07/15/99 helena Ported to HPUX 10/11 CC.
+*********************************************************************************
+*/
+/* REGRESSION TEST FOR DATE FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/uloc.h"
+#include "unicode/udat.h"
+#include "unicode/ucal.h"
+#include "unicode/unum.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cdtrgtst.h"
+#include "cmemory.h"
+
+void addDateForRgrTest(TestNode** root);
+
+void addDateForRgrTest(TestNode** root)
+{
+ addTest(root, &Test4029195, "tsformat/cdtrgtst/Test4029195");
+ addTest(root, &Test4056591, "tsformat/cdtrgtst/Test4056591");
+ addTest(root, &Test4059917, "tsformat/cdtrgtst/Test4059917");
+ addTest(root, &Test4060212, "tsformat/cdtrgtst/Test4060212");
+ addTest(root, &Test4061287, "tsformat/cdtrgtst/Test4061287");
+ addTest(root, &Test4073003, "tsformat/cdtrgtst/Test4073003");
+ addTest(root, &Test4162071, "tsformat/cdtrgtst/Test4162071");
+ addTest(root, &Test714, "tsformat/cdtrgtst/Test714");
+}
+
+/**
+ * @bug 4029195
+ */
+void Test4029195()
+{
+ int32_t resultlength, resultlengthneeded;
+ UChar *fmdt, *todayS, *rt;
+ UChar *pat=NULL;
+ UChar *temp;
+ UDate today, d1;
+ UDateFormat *df;
+ int32_t parsepos;
+ UErrorCode status = U_ZERO_ERROR;
+
+ log_verbose("Testing date format and parse function in regression test\n");
+ today = ucal_getNow();
+
+ df = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using default date and time style : %s\n", myErrorName(status));
+ return;
+ }
+ resultlength=0;
+ resultlengthneeded=udat_toPattern(df, TRUE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded + 1;
+ pat=(UChar*)malloc(sizeof(UChar) * resultlength);
+ udat_toPattern(df, TRUE, pat, resultlength, &status);
+ }
+
+ log_verbose("pattern: %s\n", austrdup(pat));
+
+
+ fmdt = myFormatit(df, today);
+ if(fmdt) {
+ log_verbose("today: %s\n", austrdup(fmdt));
+ } else {
+ log_data_err("ERROR: couldn't format, exitting test");
+ return;
+ }
+
+ temp=(UChar*)malloc(sizeof(UChar) * 10);
+ u_uastrcpy(temp, "M yyyy dd");
+ udat_applyPattern(df, TRUE, temp, u_strlen(temp));
+
+ todayS =myFormatit(df, today);
+ log_verbose("After teh pattern is applied\n today: %s\n", austrdup(todayS) );
+ parsepos=0;
+ d1=udat_parse(df, todayS, u_strlen(todayS), &parsepos, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in parsing using udat_parse(.....): %s\n", myErrorName(status));
+ }
+
+ rt =myFormatit(df, d1);
+ log_verbose("today: %s\n", austrdup(rt) );
+
+ log_verbose("round trip: %s\n", austrdup(rt) );
+
+ if(u_strcmp(rt, todayS)!=0) {
+ log_err("Fail: Want %s Got %s\n", austrdup(todayS), austrdup(rt) );
+ }
+ else
+ log_verbose("Pass: parse and format working fine\n");
+ udat_close(df);
+ free(temp);
+ if(pat != NULL) {
+ free(pat);
+ }
+}
+
+
+/**
+ * @bug 4056591
+ * Verify the function of the [s|g]et2DigitYearStart() API.
+ */
+void Test4056591()
+{
+ int i;
+ UCalendar *cal;
+ UDateFormat *def;
+ UDate start,exp,got;
+ UChar s[10];
+ UChar *gotdate, *expdate;
+ UChar pat[10];
+ UDate d[4];
+ UErrorCode status = U_ZERO_ERROR;
+ const char* strings[] = {
+ "091225",
+ "091224",
+ "611226",
+ "991227"
+ };
+
+ log_verbose("Testing s[get] 2 digit year start regressively\n");
+ cal=ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &status);
+ if(U_FAILURE(status)){
+ log_err("error in ucal_open caldef : %s\n", myErrorName(status));
+ }
+ ucal_setDateTime(cal, 1809, UCAL_DECEMBER, 25, 17, 40, 30, &status);
+ d[0]=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){
+ log_err("Error: failure in get millis: %s\n", myErrorName(status));
+ }
+ ucal_setDateTime(cal, 1909, UCAL_DECEMBER, 24, 17, 40, 30, &status);
+ d[1]=ucal_getMillis(cal, &status);
+ ucal_setDateTime(cal, 1861, UCAL_DECEMBER, 26, 17, 40, 30, &status);
+ d[2]=ucal_getMillis(cal, &status);
+ ucal_setDateTime(cal, 1999, UCAL_DECEMBER, 27, 17, 40, 30, &status);
+ d[3]=ucal_getMillis(cal, &status);
+
+
+ u_uastrcpy(pat, "yyMMdd");
+ def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL, NULL, 0, pat, u_strlen(pat), &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using u_openPattern(): %s\n", myErrorName(status));
+ return;
+ }
+ start = 1800;
+ udat_set2DigitYearStart(def, start, &status);
+ if(U_FAILURE(status))
+ log_err("ERROR: in setTwoDigitStartDate: %s\n", myErrorName(status));
+ if( (udat_get2DigitYearStart(def, &status) != start))
+ log_err("ERROR: get2DigitYearStart broken\n");
+
+
+ for(i = 0; i < 4; ++i) {
+ u_uastrcpy(s, strings[i]);
+ exp = d[i];
+ got = udat_parse(def, s, u_strlen(s), 0, &status);
+ gotdate=myFormatit(def, got);
+ expdate=myFormatit(def, exp);
+
+ if (gotdate == NULL || expdate == NULL) {
+ log_err("myFormatit failed!\n");
+ }
+ else if(u_strcmp(gotdate, expdate) !=0){
+ log_err("set2DigitYearStart broken for %s \n got: %s, expected: %s\n", austrdup(s),
+ austrdup(gotdate), austrdup(expdate) );
+ }
+ }
+
+ udat_close(def);
+ ucal_close(cal);
+}
+
+
+/**
+ * SimpleDateFormat does not properly parse date strings without delimiters
+ * @bug 4059917
+ */
+void Test4059917()
+{
+ UDateFormat* def;
+ UChar *myDate;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *pattern;
+ UChar tzID[4];
+
+ log_verbose("Testing apply pattern and to pattern regressively\n");
+ u_uastrcpy(tzID, "PST");
+ pattern=(UChar*)malloc(sizeof(UChar) * 11);
+ u_uastrcpy(pattern, "yyyy/MM/dd");
+ log_verbose("%s\n", austrdup(pattern) );
+ def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,tzID,-1,pattern, u_strlen(pattern),&status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using openPattern: %s\n", myErrorName(status));
+ return;
+ }
+ myDate=(UChar*)malloc(sizeof(UChar) * 11);
+ u_uastrcpy(myDate, "1970/01/12");
+
+ aux917( def, myDate );
+ udat_close(def);
+
+ u_uastrcpy(pattern, "yyyyMMdd");
+ def = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,tzID,-1,pattern, u_strlen(pattern),&status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using openPattern: %s\n", myErrorName(status));
+ return;
+ }
+ u_uastrcpy(myDate, "19700112");
+ aux917( def, myDate );
+ udat_close(def);
+ free(pattern);
+ free(myDate);
+
+}
+
+void aux917( UDateFormat *fmt, UChar* str)
+{
+ int32_t resultlength, resultlengthneeded;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar* formatted=NULL;
+ UChar *pat=NULL;
+ UDate d1=1000000000.0;
+
+ resultlength=0;
+ resultlengthneeded=udat_toPattern(fmt, TRUE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded + 1;
+ pat=(UChar*)malloc(sizeof(UChar) * (resultlength));
+ udat_toPattern(fmt, TRUE, pat, resultlength, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("failure in retrieving the pattern: %s\n", myErrorName(status));
+ }
+ log_verbose("pattern: %s\n", austrdup(pat) );
+
+ status = U_ZERO_ERROR;
+ formatted = myFormatit(fmt, d1);
+ if( u_strcmp(formatted,str)!=0) {
+ log_err("Fail: Want %s Got: %s\n", austrdup(str), austrdup(formatted) );
+ }
+ free(pat);
+}
+
+/**
+ * @bug 4060212
+ */
+void Test4060212()
+{
+ int32_t pos;
+ UCalendar *cal;
+ UDateFormat *formatter, *fmt;
+ UErrorCode status = U_ZERO_ERROR;
+ UDate myDate;
+ UChar *myString;
+ UChar dateString[30], pattern[20], tzID[4];
+ u_uastrcpy(dateString, "1995-040.05:01:29 -8");
+ u_uastrcpy(pattern, "yyyy-DDD.hh:mm:ss z");
+
+ log_verbose( "dateString= %s Using yyyy-DDD.hh:mm:ss\n", austrdup(dateString) );
+ status = U_ZERO_ERROR;
+ u_uastrcpy(tzID, "PST");
+
+ formatter = udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US",tzID,-1,pattern, u_strlen(pattern), &status);
+ pos=0;
+ myDate = udat_parse(formatter, dateString, u_strlen(dateString), &pos, &status);
+
+
+ fmt = udat_open(UDAT_FULL,UDAT_LONG ,NULL, tzID, -1, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using default date and time style: %s\n",
+ myErrorName(status) );
+ return;
+ }
+ myString = myFormatit(fmt, myDate);
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: error in ucal_open caldef : %s\n", myErrorName(status));
+ }
+ ucal_setMillis(cal, myDate, &status);
+ if ((ucal_get(cal, UCAL_DAY_OF_YEAR, &status) != 40)){
+ log_err("Fail: Got %d Expected 40\n", ucal_get(cal, UCAL_DAY_OF_YEAR, &status));
+ }
+
+ udat_close(formatter);
+ ucal_close(cal);
+ udat_close(fmt);
+
+}
+
+/**
+ * @bug 4061287
+ */
+void Test4061287()
+{
+ UBool ok;
+ int32_t pos;
+ UDateFormat *df;
+ UErrorCode status = U_ZERO_ERROR;
+ UDate myDate;
+ UChar pattern[21], dateString[11];
+
+ u_uastrcpy(dateString, "35/13/1971");
+ u_uastrcpy(pattern, "dd/mm/yyyy");
+ status = U_ZERO_ERROR;
+ log_verbose("Testing parsing by changing the attribute lenient\n");
+ df = udat_open(UDAT_IGNORE,UDAT_IGNORE,NULL,NULL,0,pattern, u_strlen(pattern),&status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in open pattern of test4061287: %s\n", myErrorName(status));
+ return;
+ }
+
+ pos=0;
+
+ udat_setLenient(df, FALSE);
+ ok=udat_isLenient(df);
+ if(ok==TRUE)
+ log_err("setLenient nor working\n");
+ ok = FALSE;
+ myDate = udat_parse(df, dateString, u_strlen(dateString), &pos, &status);
+ if(U_FAILURE(status))
+ ok = TRUE;
+ if(ok!=TRUE)
+ log_err("Fail: Lenient not working: does lenient parsing in spite of setting Leninent as FALSE ");
+
+ udat_close(df);
+
+}
+
+
+
+/* The java.text.DateFormat.parse(String) method expects for the
+ US locale a string formatted according to mm/dd/yy and parses it
+ correctly.
+
+ When given a string mm/dd/yyyy it only parses up to the first
+ two y's, typically resulting in a date in the year 1919.
+
+ Please extend the parsing method(s) to handle strings with
+ four-digit year values (probably also applicable to various
+ other locales. */
+/**
+ * @bug 4073003
+ */
+void Test4073003()
+{
+ int32_t pos,i;
+ UDate d,dd;
+ UChar *datestr;
+ UChar temp[15];
+ UErrorCode status = U_ZERO_ERROR;
+ UDateFormat *fmt;
+ UChar *result, *result2;
+ const char* tests [] = {
+ "12/25/61",
+ "12/25/1961",
+ "4/3/1999",
+ "4/3/99"
+ };
+
+ fmt= udat_open(UDAT_SHORT,UDAT_SHORT ,NULL, NULL, 0, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using short date and time style: %s\n",
+ myErrorName(status));
+ return;
+ }
+ u_uastrcpy(temp, "m/D/yy");
+ udat_applyPattern(fmt, FALSE, temp, u_strlen(temp));
+
+ for(i= 0; i < 4; i+=2) {
+ status=U_ZERO_ERROR;
+ datestr=(UChar*)malloc(sizeof(UChar) * (strlen(tests[i])+1));
+ u_uastrcpy(datestr, tests[i]);
+
+ pos=0;
+ d = udat_parse(fmt, datestr, u_strlen(datestr), &pos, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR : in test 4073003: %s\n", myErrorName(status));
+ }
+
+ free(datestr);
+ datestr=(UChar*)malloc(sizeof(UChar) * (strlen(tests[i+1])+1));
+ u_uastrcpy(datestr, tests[i+1]);
+
+ pos=0;
+ status=U_ZERO_ERROR;
+ dd = udat_parse(fmt, datestr, u_strlen(datestr), &pos, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR : in test 4073003: %s\n", myErrorName(status));
+ }
+ free(datestr);
+
+ result =myFormatit(fmt, d);
+ result2 =myFormatit(fmt, dd);
+ if(!result || !result2) {
+ log_data_err("Fail: could not format - exitting test\n");
+ return;
+ }
+ if (u_strcmp(result, result2)!=0){
+ log_err("Fail: %s != %s\n", austrdup(result), austrdup(result2) );
+ }
+ else{
+ log_verbose("Ok: %s == %s\n", austrdup(result), austrdup(result2) );
+ }
+
+ }
+ udat_close(fmt);
+}
+
+/**
+ * @bug 4162071
+ **/
+void Test4162071()
+{
+ int32_t pos;
+ UDate x;
+ UErrorCode status = U_ZERO_ERROR;
+ UDateFormat *df;
+ UChar datestr[30];
+ UChar format[50];
+ u_uastrcpy(datestr, "Thu, 30-Jul-1999 11:51:14 GMT");
+ u_uastrcpy(format, "EEE', 'dd-MMM-yyyy HH:mm:ss z"); /* RFC 822/1123 */
+ status = U_ZERO_ERROR;
+ /* Can't hardcode the result to assume the default locale is "en_US". */
+ df = udat_open(UDAT_IGNORE,UDAT_IGNORE,"en_US",NULL,0,format, u_strlen(format),&status);
+ if(U_FAILURE(status)){
+ log_data_err("ERROR: couldn't create date format: %s\n", myErrorName(status));
+ return;
+ }
+ pos=0;
+ x = udat_parse(df, datestr, u_strlen(datestr), &pos, &status);
+ if(U_FAILURE(status)){
+ log_data_err("ERROR : parse format %s fails : %s\n", austrdup(format), myErrorName(status));
+ }
+ else{
+ log_verbose("Parse format \"%s \" ok.\n", austrdup(format) );
+ }
+ /*log_verbose("date= %s\n", austrdup(myFormatit(df, x)) );*/
+ udat_close(df);
+}
+
+void Test714(void)
+{
+ UDate d=978103543000.0;
+ UChar temp[20];
+ UErrorCode status = U_ZERO_ERROR;
+ UDateFormat *fmt;
+ UChar *result;
+ const char* expect = "7:25:43 AM";
+
+ ctest_setTimeZone(NULL, &status);
+
+ fmt= udat_open(UDAT_MEDIUM,UDAT_NONE ,"en_US_CA", NULL, -1, NULL, 0, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error in creating the dateformat using medium time style and NO date style: %s\n",
+ myErrorName(status));
+ return;
+ }
+ result =myFormatit(fmt, d);
+ if(!result) {
+ log_data_err("Fail: could not format - exitting test\n");
+ return;
+ }
+ u_uastrcpy(temp, expect);
+ if (u_strcmp(result, temp)!=0){
+ log_err("Fail: %s != %s\n", austrdup(result), expect);
+ }
+ else{
+ log_verbose("Ok: %s == %s\n", austrdup(result), expect );
+ }
+
+ udat_close(fmt);
+
+ ctest_resetTimeZone();
+}
+
+/*INTERNAL FUNCTION USED */
+
+UChar* myFormatit(UDateFormat* datdef, UDate d1)
+{
+ UChar *result1=NULL;
+ int32_t resultlength, resultlengthneeded;
+ UErrorCode status = U_ZERO_ERROR;
+
+ resultlength=0;
+ resultlengthneeded=udat_format(datdef, d1, NULL, resultlength, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ /*result1=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /*this leaks*/
+ result1=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
+ udat_format(datdef, d1, result1, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: Error in formatting using udat_format(.....): %s\n", myErrorName(status));
+ return 0;
+ }
+
+
+ return result1;
+
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+/*eof*/
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h
new file mode 100644
index 00000000000..18df92e5ed2
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cdtrgtst.h
@@ -0,0 +1,50 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CDTRGTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*/
+/* REGRESSION TEST FOR DATE FORMAT */
+#ifndef _CDTFRRGSTST
+#define _CDTFRRGSTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+ /**
+ * DateFormat Regresstion tests
+ **/
+
+ void Test4029195(void);
+ void Test4056591(void);
+ void Test4059917(void);
+ void Test4060212(void);
+ void Test4061287(void);
+ void Test4073003(void);
+ void Test4162071(void);
+ void Test714(void);
+
+ /**
+ * test subroutine
+ **/
+ void aux917(UDateFormat *fmt, UChar* str );
+
+ /**
+ * test subroutine used by the testing functions
+ **/
+ UChar* myFormatit(UDateFormat* datdef, UDate d1);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c
new file mode 100644
index 00000000000..650143fb1bc
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.c
@@ -0,0 +1,123 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CESTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * CollationSpanishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "cestst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {0x0062/*'a'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000},
+ {0x0045/*'E'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x006f/*'o'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0063/*'c'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000},
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {0x0062/*'a'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000},
+ {0x0045/*'E'*/, 0x006d/*'m'*/, 0x0069/*'i'*/, 0x006f/*'o'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'O'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0062/*'a'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x0069/*'i'*/, 0x0061/*'a'*/, 0x0073/*'s'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0043/*'C'*/, 0x0048/*'H'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'O'*/, 0x0000},
+};
+
+const static UCollationResult results[] = {
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS,
+ /* test primary > 5*/
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_EQUAL
+};
+
+
+void addSpanishCollTest(TestNode** root)
+{
+
+
+ addTest(root, &TestPrimary, "tscoll/cestst/TestPrimary");
+ addTest(root, &TestTertiary, "tscoll/cestst/TestTertiary");
+
+}
+
+
+static void TestTertiary( )
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("es_ES", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status));
+ return;
+ }
+ log_verbose("Testing Spanish Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 5 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestPrimary()
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("es_ES", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: %s: in creation of rule based collator: %s\n", __FILE__, myErrorName(status));
+ return;
+ }
+ log_verbose("Testing Spanish Collation with Primary strength\n");
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ for (i = 5; i < 9; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h
new file mode 100644
index 00000000000..e15f32d4875
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cestst.h
@@ -0,0 +1,44 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CESTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationSpanishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CESCOLLTST
+#define _CESCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+
+#define MAX_TOKEN_LEN 16
+
+
+ /* perform test with strength SECONDARY */
+ static void TestPrimary(void);
+
+ /* perform test with strength TERTIARY */
+ static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c
new file mode 100644
index 00000000000..3ab68dfde1a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.c
@@ -0,0 +1,112 @@
+/********************************************************************
+ * Copyright (c) 1997-2007, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ ********************************************************************
+ *
+ * File CFINTST.C
+ *
+ * Modification History:
+ * Name Description
+ * Madhu Katragadda Ported for C API
+ ********************************************************************
+ */
+
+/**
+ * CollationFinnishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "cfintst.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0061/*'a'*/, 0x00FC, 0x0062/*'b'*/, 0x0065/*'e'*/, 0x0063/*'c'*/, 0x006b/*'k'*/, 0x0000},
+ {0x004c/*'L'*/, 0x00E5, 0x0076/*'v'*/, 0x0069/*'i'*/, 0x0000},
+ {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000}
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0077/*'w'*/, 0x0061/*'a'*/, 0x0079/*'y'*/, 0x0000},
+ {0x0061/*'a'*/, 0x0078/*'x'*/, 0x0062/*'b'*/, 0x0065/*'e'*/, 0x0063/*'c'*/, 0x006b/*'k'*/, 0x0000},
+ {0x004c/*'L'*/, 0x00E4, 0x0077/*'w'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0076/*'v'*/, 0x0061/*'a'*/, 0x0074/*'t'*/, 0x0000}
+};
+
+const static UCollationResult results[] = {
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_LESS,
+ /* test primary > 4*/
+ UCOL_EQUAL
+};
+
+
+
+void addFinnishCollTest(TestNode** root)
+{
+
+
+ addTest(root, &TestPrimary, "tscoll/cficoll/TestPrimary");
+ addTest(root, &TestTertiary, "tscoll/cficoll/TestTertiary");
+
+
+
+}
+
+
+static void TestTertiary( )
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("fi_FI@collation=standard", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ }
+ log_verbose("Testing Finnish Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 4 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestPrimary()
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("fi_FI@collation=standard", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ }
+ log_verbose("Testing Finnish Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ for (i = 4; i < 5; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h
new file mode 100644
index 00000000000..4edd517611e
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfintst.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CFINTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationFinnishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CFINCOLLTST
+#define _CFINCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+
+#define MAX_TOKEN_LEN 16
+
+
+ /* perform test with strength SECONDARY*/
+static void TestPrimary(void);
+
+ /* perform test with strength TERTIARY */
+ static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c
new file mode 100644
index 00000000000..cbbcf1ff54a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.c
@@ -0,0 +1,78 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CFORMTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+
+/* FormatTest is a medium top level test for everything in the C FORMAT API */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+#include "cformtst.h"
+
+void addCalTest(TestNode**);
+void addDateForTest(TestNode**);
+void addDateTimePatternGeneratorTest(TestNode** root);
+void addNumForTest(TestNode**);
+void addMsgForTest(TestNode**);
+void addDateForRgrTest(TestNode**);
+void addNumFrDepTest(TestNode**);
+void addDtFrDepTest(TestNode**);
+void addUtmsTest(TestNode**);
+void addCurrencyTest(TestNode**);
+
+void addFormatTest(TestNode** root);
+
+void addFormatTest(TestNode** root)
+{
+ addCalTest(root);
+ addDateForTest(root);
+ addDateTimePatternGeneratorTest(root);
+ addNumForTest(root);
+ addNumFrDepTest(root);
+ addMsgForTest(root);
+ addDateForRgrTest(root);
+ addDtFrDepTest(root);
+ addUtmsTest(root);
+ addCurrencyTest(root);
+}
+/*Internal functions used*/
+
+UChar* myDateFormat(UDateFormat* dat, UDate d1)
+{
+ UChar *result1=NULL;
+ int32_t resultlength, resultlengthneeded;
+ UErrorCode status = U_ZERO_ERROR;
+
+
+ resultlength=0;
+ resultlengthneeded=udat_format(dat, d1, NULL, resultlength, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result1=(UChar*)ctst_malloc(sizeof(UChar) * resultlength);
+ udat_format(dat, d1, result1, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using udat_format(.....): %s\n", myErrorName(status));
+ return 0;
+ }
+ return result1;
+
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h
new file mode 100644
index 00000000000..e5c0e44ccea
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cformtst.h
@@ -0,0 +1,33 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CFORMTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* FormatTest is a medium top level test for everything in the C FORMAT API */
+
+#ifndef _CFORMATTST
+#define _CFORMATTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+#include "unicode/udat.h"
+
+
+/* Internal fucntion used by all the test format files */
+UChar* myDateFormat(UDateFormat *dat, UDate d);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c
new file mode 100644
index 00000000000..63a01284f85
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.c
@@ -0,0 +1,335 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CFRTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * CollationFrenchTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "cfrtst.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] =
+{
+ {0x0061/*'a'*/, 0x0062/*'b'*/, 0x0063/*'c'*/, 0x0000},
+ {0x0043/*'C'*/, 0x004f/*'O'*/, 0x0054/*'T'*/, 0x0045/*'E'*/, 0x0000},
+ {0x0063/*'c'*/, 0x006f/*'o'*/, 0x002d/*'-'*/, 0x006f/*'o'*/, 0x0070/*'p'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000},
+ {0x0048/*'H'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x006f/*'o'*/, 0x0000},
+ {0x01f1, 0x0000},
+ {0xfb00, 0x0000},
+ {0x01fa, 0x0000},
+ {0x0101, 0x0000}
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] =
+{
+ {0x0041/*'A'*/, 0x0042/*'B'*/, 0x0043/*'C'*/, 0x0000},
+ {0x0063/*'c'*/, 0x00f4, 0x0074/*'t'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0043/*'C'*/, 0x004f/*'O'*/, 0x004f/*'O'*/, 0x0050/*'P'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x00E9, 0x0000},
+ {0x0070/*'p'*/, 0x00E9, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x00E9, 0x0000},
+ {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0000},
+ {0x0070/*'p'*/, 0x00EA, 0x0063/*'c'*/, 0x0068/*'h'*/, 0x0065/*'e'*/, 0x0072/*'r'*/, 0x0000},
+ {0x0068/*'h'*/, 0x0065/*'e'*/, 0x006c/*'l'*/, 0x006c/*'l'*/, 0x004f/*'O'*/, 0x0000},
+ {0x01ee, 0x0000},
+ {0x25ca, 0x0000},
+ {0x00e0, 0x0000},
+ {0x01df, 0x0000}
+};
+
+const static UCollationResult results[] =
+{
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS, /*UCOL_GREATER,*/
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_LESS, /*UCOL_GREATER,*/
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS
+};
+
+/* 0x0300 is grave, 0x0301 is acute*/
+/* the order of elements in this array must be different than the order in CollationEnglishTest*/
+const static UChar testAcute[][MAX_TOKEN_LEN] =
+{
+/*00*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0000},
+/*01*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0000},
+/*02*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0000},
+/*03*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0000},
+/*04*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0000},
+/*05*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0301, 0x0000},
+/*06*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0000},
+/*07*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0000},
+/*08*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0000},
+/*09*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0000},
+/*0a*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000},
+/*0b*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000},
+/*0c*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000},
+/*0d*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000},
+/*0e*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0301, 0x0000},
+/*0f*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0300, 0x0000},
+/*10*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0000},
+/*11*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0300, 0x0000},
+/*12*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0000},
+/*13*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0300, 0x0000},
+/*14*/ {0x0065/*'e'*/, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000},
+/*15*/ {0x0065/*'e'*/, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000},
+/*16*/ {0x0065/*'e'*/, 0x0300, 0x0301, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000},
+/*17*/ {0x0065/*'e'*/, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000},
+/*18*/ {0x0065/*'e'*/, 0x0301, 0x0300, 0x0065/*'e'*/, 0x0301, 0x0300, 0x0000}
+};
+
+const static UChar testBugs[][MAX_TOKEN_LEN] =
+{
+ {0x0061/*'a'*/, 0x000},
+ {0x0041/*'A'*/, 0x000},
+ {0x0065/*'e'*/, 0x000},
+ {0x0045/*'E'*/, 0x000},
+ {0x00e9, 0x000},
+ {0x00e8, 0x000},
+ {0x00ea, 0x000},
+ {0x00eb, 0x000},
+ {0x0065/*'e'*/, 0x0061/*'a'*/, 0x000},
+ {0x0078/*'x'*/, 0x000}
+};
+
+
+static void TestGetSortKey(void);
+
+
+void addFrenchCollTest(TestNode** root)
+{
+ addTest(root, &TestSecondary, "tscoll/cfrtst/TestSecondary");
+ addTest(root, &TestTertiary, "tscoll/cfrtst/TestTertiary");
+ addTest(root, &TestExtra, "tscoll/cfrtst/TestExtra");
+ addTest(root, &TestGetSortKey, "tscoll/cfrtst/TestGetSortKey");
+}
+
+
+static void TestTertiary( )
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("fr_FR", &status);
+ if(U_FAILURE(status) || !myCollation){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+
+ ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing French Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_QUATERNARY);
+ for (i = 0; i < 12 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestSecondary()
+{
+ int32_t i,j, testAcuteSize;
+ UCollationResult expected=UCOL_EQUAL;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("fr_FR", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_SECONDARY, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing French Collation with Secondary strength\n");
+ /*test acute and grave ordering (compare to french collation)*/
+ testAcuteSize = sizeof(testAcute) / sizeof(testAcute[0]);
+ for (i = 0; i < testAcuteSize; i++)
+ {
+ for (j = 0; j < testAcuteSize; j++)
+ {
+ if (i < j) expected = UCOL_LESS;
+ if (i == j) expected = UCOL_EQUAL;
+ if (i > j) expected = UCOL_GREATER;
+ doTest(myCollation, testAcute[i], testAcute[j], expected );
+ }
+ }
+ ucol_close(myCollation);
+}
+
+static void TestExtra()
+{
+ int32_t i, j;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("fr_FR", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing French Collation extra with secondary strength\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 9 ; i++)
+ {
+ for (j = i + 1; j < 10; j += 1)
+ {
+ doTest(myCollation, testBugs[i], testBugs[j], UCOL_LESS);
+ }
+ }
+ ucol_close(myCollation);
+}
+
+static void TestGetSortKey() {
+ /* This is meant to test a buffer reallocation crash while using
+ French secondary sorting with a large buffer.
+ The fact that Japanese characters are used is irrelevant. */
+ static const UChar pucUTF16[] = {
+ 0x3049,0x30b9,0x3088,0xfffd,0xfffd,0x308f,0xfffd,0x3042,
+ 0xfffd,0xfffd,0x305e,0xfffd,0x30b6,0x30bb,0x305b,0x30b1,
+ 0x3050,0x30af,0x304e,0x30bd,0xfffd,0x30c6,0xfffd,0xfffd,
+ 0x30e1,0xfffd,0xfffd,0x30d9,0xfffd,0x3092,0x3075,0x304a,
+ 0x3074,0x3070,0x30f5,0x30c4,0x306e,0x30df,0x3053,0xfffd,
+ 0x30a6,0x30b6,0x30e0,0xfffd,0x30bc,0x30ef,0x3087,0x30cc,
+ 0x305f,0x30de,0xfffd,0x3090,0x3063,0x30dc,0x30b6,0x30b9,
+ 0x30d2,0x3072,0x3061,0xfffd,0xfffd,0xfffd,0x307b,0x3092,
+ 0x30a5,0x30a9,0x30b1,0x30e7,0xfffd,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0x305e,0xfffd,0x30c7,0x30ae,0x305b,0x308b,0x30c0,
+ 0x30f5,0xfffd,0xfffd,0xfffd,0x307d,0x304e,0xfffd,0xfffd,
+ 0x30c0,0x30c8,0x306f,0x307a,0x30dd,0x30e4,0x3084,0xfffd,
+ 0x308c,0x30f1,0xfffd,0x30c6,0xfffd,0x307a,0xfffd,0x3052,
+ 0x3056,0x305d,0x30b7,0xfffd,0x305b,0x30b0,0x30b9,0xfffd,
+ 0x30b2,0x306d,0x3044,0xfffd,0x3073,0xfffd,0x30be,0x30cf,
+ 0x3080,0xfffd,0x30a8,0x30f5,0x30a5,0x30c7,0x307c,0xfffd,
+ 0x30d1,0x305f,0x30b2,0xfffd,0x3053,0x30ca,0xfffd,0x30dd,
+ 0x3058,0x30c0,0x305d,0x30e1,0xfffd,0x30bb,0x305f,0x30d1,
+ 0x30f2,0x3058,0x3086,0x30ce,0x30db,0x30cb,0x30e9,0xfffd,
+ 0x308c,0xfffd,0xfffd,0x30af,0x30c4,0x3076,0x304c,0x30f5,
+ 0x30e8,0x308c,0xfffd,0x30e2,0x3073,0x30a3,0x304e,0x30ea,
+ 0xfffd,0x304f,0xfffd,0x306c,0x3044,0xfffd,0xfffd,0x30c9,
+ 0xfffd,0x30f5,0xfffd,0xfffd,0xfffd,0x30eb,0x30a8,0xfffd,
+ 0x306d,0x307d,0x30d8,0x3069,0xfffd,0xfffd,0x3086,0x30a9,
+ 0xfffd,0x3076,0x30e9,0x30cc,0x3074,0x30e0,0xfffd,0xfffd,
+ 0xfffd,0x30f0,0x3086,0x30ac,0x3076,0x3068,0x30c7,0xfffd,
+ 0x30b7,0x30d2,0x3048,0x308e,0x30e8,0x30d9,0x30ce,0x30d0,
+ 0x308b,0x30ee,0x30e6,0x3079,0x30f3,0x30af,0xfffd,0x3079,
+ 0xfffd,0xfffd,0x30ca,0x30bf,0xfffd,0x30b5,0xfffd,0xfffd,
+ 0x3093,0xfffd,0x30ba,0xfffd,0x3076,0x3047,0x304a,0xfffd,
+ 0xfffd,0x3086,0xfffd,0x3081,0xfffd,0x30f6,0x3066,0xfffd,
+ 0xfffd,0x30b6,0x30ef,0x30e2,0x30bf,0xfffd,0x3053,0x304a,
+ 0xfffd,0xfffd,0x304a,0x30e8,0xfffd,0x30e2,0xfffd,0xfffd,
+ 0x305c,0x3081,0x30c6,0xfffd,0x3091,0x3046,0x306a,0x3059,
+ 0xfffd,0xfffd,0x30dd,0x30d1,0x308a,0x30ee,0xfffd,0xfffd,
+ 0x308a,0x3042,0x30da,0xfffd,0x3064,0x30ef,0x305c,0x306b,
+ 0xfffd,0x30ca,0x3085,0x3067,0x30ea,0x30c2,0x30c8,0xfffd,
+ 0x30f5,0xfffd,0xfffd,0xfffd,0x30ca,0xfffd,0x3050,0x30f1,
+ 0x3050,0x3053,0x3072,0xfffd,0xfffd,0xfffd,0x3074,0xfffd,
+ 0x304b,0x30dd,0x306d,0xfffd,0x3049,0x30a1,0x30cc,0x30de,
+ 0x30ae,0x307b,0x308a,0xfffd,0x3065,0xfffd,0xfffd,0x30c0,
+ 0xfffd,0x3048,0x30dc,0x304f,0x3085,0x3059,0x304b,0x30d3,
+ 0x30eb,0x30a4,0x3073,0xfffd,0x30ba,0x308f,0x30a7,0x30c3,
+ 0x3074,0x30cf,0x306c,0x3053,0x30c0,0xfffd,0x3066,0xfffd,
+ 0x308f,0xfffd,0x30b5,0xfffd,0x3092,0x30c4,0xfffd,0x30d6,
+ 0x3056,0x30ad,0x30d2,0x30ba,0xfffd,0x30e6,0x304c,0x3088,
+ 0x30b6,0x3048,0x3077,0x30d1,0xfffd,0x3050,0xfffd,0x3042,
+ 0xfffd,0xfffd,0x308f,0xfffd,0x30c1,0xfffd,0x3074,0x3061,
+ 0x3056,0x30e5,0xfffd,0xfffd,0x3057,0xfffd,0xfffd,0xfffd,
+ 0xfffd,0x30bd,0x30b3,0x30ee,0xfffd,0x30f2,0x3084,0x3050,
+ 0xfffd,0x30e7,0xfffd,0xfffd,0x3060,0x3049,0x30f2,0x30ad,
+ 0x30bf,0x30f1,0x30a2,0xfffd,0x30af,0xfffd,0x3060,0x30a1,
+ 0x30e9,0x30c3,0xfffd,0x3072,0x3093,0x3070,0xfffd,0x308f,
+ 0x3060,0xfffd,0x3067,0x306f,0x3082,0x308b,0x3051,0xfffd,
+ 0x3058,0xfffd,0xfffd,0x30a8,0x3051,0x3054,0x30ad,0x30f0,
+ 0x3053,0xfffd,0x30e1,0x30d7,0x308d,0x307f,0x30be,0x30b0,
+ 0xfffd,0x30db,0xfffd,0x30d1,0xfffd,0x3054,0x30a5,0xfffd,
+ 0x306a,0xfffd,0x305c,0xfffd,0x3052,0x3088,0xfffd,0x306e,
+ 0xfffd,0x30a9,0x30a1,0x30b4,0x3083,0x30bd,0xfffd,0xfffd,
+ 0x306a,0x3070,0x30cd,0xfffd,0x3072,0x30ed,0x30c6,0x30be,
+ 0x30c4,0x305e,0x30b3,0x30e1,0x308a,0xfffd,0x305b,0xfffd,
+ 0x3042,0x3088,0xfffd,0x304c,0xfffd,0x3089,0x3071,0xfffd,
+ 0xfffd,0x30c6,0x3062,0x3079,0xfffd,0x304b,0x304a,0xfffd,
+ 0x30ad,0x3045,0x3045,0x3087,0xfffd,0x306a,0x308b,0x0000,
+ 0x30bd,0x3065,0x30b8,0x3086,0x30d3,0x3076,0xfffd,0xfffd,
+ 0x308f,0x3053,0x307c,0x3053,0x3084,0x30ae,0x30c4,0x3045,
+ 0x30a8,0x30d0,0x30e1,0x308c,0x30e6,0x30b7,0xfffd,0xfffd,
+ 0xfffd,0x3046,0x305f,0xfffd,0x3086,0x30ab,0xfffd,0xfffd,
+ 0x30c8,0xfffd,0x30a1,0x3052,0x3059,0xfffd,0x30a4,0xfffd,
+ 0xfffd,0x308c,0x3085,0x30ab,0x30b5,0x3091,0x30bf,0x30e3,
+ 0xfffd,0xfffd,0x3087,0xfffd,0x30f6,0x3051,0x30bd,0x3092,
+ 0x3063,0xfffd,0x30a9,0x3063,0x306e,0xfffd,0xfffd,0xfffd,
+ 0x306c,0xfffd,0x307e,0x30ad,0x3077,0x30c2,0x30e9,0x30d5,
+ 0xfffd,0xfffd,0x30c6,0x305c,0xfffd,0xfffd,0x3089,0xfffd,
+ 0x3048,0x30cb,0x308c,0xfffd,0xfffd,0x3044,0xfffd,0x3080,
+ 0x3063,0x3079,0xfffd,0x308a,0x30cb,0x3042,0x3057,0xfffd,
+ 0x307c,0x30c1,0x30a8,0x30cf,0xfffd,0x3083,0xfffd,0xfffd,
+ 0x306c,0xfffd,0x305e,0x3092,0xfffd,0x30dc,0x30b0,0x3081,
+ 0x30e3,0x30f0,0x304e,0x30cc,0x308e,0x30c4,0x30ad
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *pCollator;
+ int32_t lenActualSortKey;
+ uint8_t pucSortKey[4096];
+ static const int32_t LENSORTKEY = (int32_t)sizeof(pucSortKey);
+
+ ucol_prepareShortStringOpen("LFR_AN_CX_EX_FO_HX_NX_S3", 0, NULL, &status);
+
+ pCollator = ucol_openFromShortString("LFR_AN_CX_EX_FO_HX_NX_S3", 0, NULL, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("error opening collator\n");
+ return;
+ }
+
+ lenActualSortKey = ucol_getSortKey(pCollator,
+ (const UChar *)pucUTF16,
+ sizeof(pucUTF16) / sizeof(pucUTF16[0]),
+ pucSortKey,
+ LENSORTKEY);
+
+ if (lenActualSortKey > LENSORTKEY) {
+ log_err("sort key too big for original buffer. Got: %d Expected: %d\n", lenActualSortKey, LENSORTKEY);
+ return;
+ }
+ /* If the test didn't crash, then the test succeeded. */
+ ucol_close(pCollator);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h
new file mode 100644
index 00000000000..1fe136a3f88
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cfrtst.h
@@ -0,0 +1,44 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CFRTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationFrenchTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CFRCOLLTST
+#define _CFRCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+
+ /* performs Extra tests*/
+ static void TestExtra(void);
+
+ /* perform test with strength SECONDARY*/
+ static void TestSecondary(void);
+
+ /*perform test with strength TERTIARY*/
+static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c
new file mode 100644
index 00000000000..a493450ee6c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.c
@@ -0,0 +1,310 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CG7COLL.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * G7CollationTest is a third level test class. This test performs the examples
+ * mentioned on the IBM Java international demos web site.
+ * Sample Rules: & Z < p , P
+ * Effect : Making P sort after Z.
+ *
+ * Sample Rules: & c < ch , cH, Ch, CH
+ * Effect : As well as adding sequences of characters that act as a single character (this is
+ * known as contraction), you can also add characters that act like a sequence of
+ * characters (this is known as expansion).
+ *
+ * Sample Rules: & Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'
+ * Effect : Expansion and contraction can actually be combined.
+ *
+ * Sample Rules: & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-'
+ * Effect : sorted sequence as the following,
+ * aardvark
+ * a-rdvark
+ * abbot
+ * coop
+ * co-p
+ * cop
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "cg7coll.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "unicode/ustring.h"
+
+
+const char* locales[8] = {
+ "en_US",
+ "en_GB",
+ "en_CA",
+ "fr_FR",
+ "fr_CA",
+ "de_DE",
+ "it_IT",
+ "ja_JP"
+};
+
+
+
+const static UChar testCases[][MAX_TOKEN_LEN] = {
+ { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
+ 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073 /*'s'*/, 0x0000}, /* 9 */
+ { 0x0050 /*'P'*/, 0x0061 /*'a'*/, 0x0074/*'t'*/, 0x0000}, /* 1 */
+ { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x00E9, 0x0000}, /* 2 */
+ { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0000}, /* 3 */
+ { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000}, /* 4 */
+ { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000}, /* 5 */
+ { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0064 /*'d'*/, 0x0000}, /* 6 */
+ { 0x0054 /*'T'*/, 0x00F6, 0x006e /*'n'*/, 0x0065 /*'e'*/, 0x0000}, /* 7 */
+ { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0066 /*'f'*/, 0x0075 /*'u'*/, 0x0000}, /* 8 */
+ { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
+ 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000}, /* 12 */
+ { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x006e /*'n'*/, 0x0000}, /* 10 */
+ { 0x0050 /*'P'*/, 0x0041 /*'A'*/, 0x0054 /*'T'*/, 0x0000}, /* 11 */
+ { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
+ 0x002d /*'-'*/, 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000}, /* 13 */
+ { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
+ 0x002d /*'-'*/, 0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073/*'s'*/, 0x0000}, /* 0 */
+ {0x0070 /*'p'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x0000}, /* 14 */
+ /* Additional tests */
+ { 0x0063 /*'c'*/, 0x007a /*'z'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0000 }, /* 15 */
+ { 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0075 /*'u'*/, 0x0072 /*'r'*/, 0x006f /*'o'*/, 0x0000 }, /* 16 */
+ { 0x0063 /*'c'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x000 }, /* 17 */
+ { 0x0064 /*'d'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x006e /*'n'*/, 0x0000 }, /* 18 */
+ { 0x003f /*'?'*/, 0x0000 }, /* 19 */
+ { 0x0071 /*'q'*/, 0x0075 /*'u'*/, 0x0069 /*'i'*/, 0x0063 /*'c'*/, 0x006b /*'k'*/, 0x0000 }, /* 20 */
+ { 0x0023 /*'#'*/, 0x0000 }, /* 21 */
+ { 0x0026 /*'&'*/, 0x0000 }, /* 22 */
+ { 0x0061 /*'a'*/, 0x002d /*'-'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/,
+ 0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000}, /* 24 */
+ { 0x0061 /*'a'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/,
+ 0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000}, /* 23 */
+ { 0x0061 /*'a'*/, 0x0062 /*'b'*/, 0x0062 /*'b'*/, 0x006f /*'o'*/, 0x0074 /*'t'*/, 0x0000}, /* 25 */
+ { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x002d /*'-'*/, 0x0070 /*'p'*/, 0x0000}, /* 27 */
+ { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x0070 /*'p'*/, 0x0000}, /* 28 */
+ { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x006f /*'o'*/, 0x0070 /*'p'*/, 0x0000}, /* 26 */
+ { 0x007a /*'z'*/, 0x0065 /*'e'*/, 0x0062 /*'b'*/, 0x0072 /*'r'*/, 0x0061 /*'a'*/, 0x0000} /* 29 */
+};
+
+const static int32_t results[TESTLOCALES][TOTALTESTSET] = {
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_US */
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_GB */
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_CA */
+ { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_FR */
+ { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_CA */
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* de_DE */
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* it_IT */
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* ja_JP */
+ /* new table collation with rules "& Z < p, P" loop to FIXEDTESTSET */
+ { 12, 13, 9, 0, 6, 8, 10, 7, 14, 1, 11, 2, 3, 4, 5, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 },
+ /* new table collation with rules "& C < ch , cH, Ch, CH " loop to TOTALTESTSET */
+ { 19, 22, 21, 23, 24, 25, 12, 13, 9, 0, 17, 26, 28, 27, 15, 16, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 },
+ /* new table collation with rules "& Question-mark ; ? & Hash-mark ; # & Ampersand ; '&' " loop to TOTALTESTSET */
+ { 23, 24, 25, 22, 12, 13, 9, 0, 17, 16, 26, 28, 27, 15, 18, 21, 14, 1, 11, 2, 3, 4, 5, 19, 20, 6, 8, 10, 7, 29 },
+ /* analogous to Japanese rules " & aa ; a- & ee ; e- & ii ; i- & oo ; o- & uu ; u- " */ /* loop to TOTALTESTSET */
+ { 19, 22, 21, 24, 23, 25, 12, 13, 9, 0, 17, 16, 28, 26, 27, 15, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 }
+};
+
+void addRuleBasedCollTest(TestNode** root)
+{
+ addTest(root, &TestG7Locales, "tscoll/cg7coll/TestG7Locales");
+ addTest(root, &TestDemo1, "tscoll/cg7coll/TestDemo1");
+ addTest(root, &TestDemo2, "tscoll/cg7coll/TestDemo2");
+ addTest(root, &TestDemo3, "tscoll/cg7coll/TestDemo3");
+ addTest(root, &TestDemo4, "tscoll/cg7coll/TestDemo4");
+
+
+}
+
+static void TestG7Locales()
+{
+ UCollator *myCollation, *tblColl1;
+ UErrorCode status = U_ZERO_ERROR;
+ const UChar *defRules;
+ int32_t i, rlen, j, n;
+ log_verbose("Testing ucol_openRules for all the locales\n");
+ for (i = 0; i < 8; i++)
+ {
+ status = U_ZERO_ERROR;
+ myCollation = ucol_open(locales[i], &status);
+ ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
+ ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+
+ if (U_FAILURE(status))
+ {
+ log_err("Error in creating collator in %s: %s\n", locales[i], myErrorName(status));
+ continue;
+ }
+
+ defRules = ucol_getRules(myCollation, &rlen);
+ status = U_ZERO_ERROR;
+ tblColl1 = ucol_openRules(defRules, rlen, UCOL_OFF,
+ UCOL_DEFAULT_STRENGTH,NULL, &status);
+ if (U_FAILURE(status))
+ {
+
+ log_err("Error in creating collator in %s: %s\n", locales[i], myErrorName(status));
+ continue;
+ }
+
+
+ log_verbose("Locale %s\n", locales[i]);
+ log_verbose(" tests start...\n");
+
+ j = 0;
+ n = 0;
+ for (j = 0; j < FIXEDTESTSET; j++)
+ {
+ for (n = j+1; n < FIXEDTESTSET; n++)
+ {
+ doTest(tblColl1, testCases[results[i][j]], testCases[results[i][n]], UCOL_LESS);
+ }
+ }
+
+ ucol_close(myCollation);
+ ucol_close(tblColl1);
+ }
+}
+
+static void TestDemo1()
+{
+ UCollator *myCollation;
+ int32_t j, n;
+ const char *rules = "& Z < p, P";
+ int32_t len=(int32_t)strlen(rules);
+ UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1));
+ UErrorCode status = U_ZERO_ERROR;
+ u_uastrcpy(temp, rules);
+
+ log_verbose("Demo Test 1 : Create a new table collation with rules \" & Z < p, P \" \n");
+
+ myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+
+ if (U_FAILURE(status))
+ {
+ log_err( "Demo Test 1 Rule collation object creation failed. : %s\n", myErrorName(status));
+ return;
+ }
+
+ for (j = 0; j < FIXEDTESTSET; j++)
+ {
+ for (n = j+1; n < FIXEDTESTSET; n++)
+ {
+ doTest(myCollation, testCases[results[8][j]], testCases[results[8][n]], UCOL_LESS);
+ }
+ }
+
+ ucol_close(myCollation);
+ free(temp);
+}
+
+static void TestDemo2()
+{
+ UCollator *myCollation;
+ int32_t j, n;
+ const char *rules = "& C < ch , cH, Ch, CH";
+ int32_t len=(int32_t)strlen(rules);
+ UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1));
+ UErrorCode status = U_ZERO_ERROR;
+ u_uastrcpy(temp, rules);
+
+ log_verbose("Demo Test 2 : Create a new table collation with rules \"& C < ch , cH, Ch, CH\"");
+
+ myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+
+ if (U_FAILURE(status))
+ {
+ log_err( "Demo Test 2 Rule collation object creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ for (j = 0; j < TOTALTESTSET; j++)
+ {
+ for (n = j+1; n < TOTALTESTSET; n++)
+ {
+ doTest(myCollation, testCases[results[9][j]], testCases[results[9][n]], UCOL_LESS);
+ }
+ }
+ ucol_close(myCollation);
+ free(temp);
+}
+
+static void TestDemo3()
+{
+ UCollator *myCollation;
+ int32_t j, n;
+ const char *rules = "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'";
+ int32_t len=(int32_t)strlen(rules);
+ UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1));
+ UErrorCode status = U_ZERO_ERROR;
+ u_uastrcpy(temp, rules);
+
+ log_verbose("Demo Test 3 : Create a new table collation with rules \"& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'\" \n");
+
+ myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+
+ if (U_FAILURE(status))
+ {
+ log_err( "Demo Test 3 Rule collation object creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+
+ for (j = 0; j < TOTALTESTSET; j++)
+ {
+ for (n = j+1; n < TOTALTESTSET; n++)
+ {
+ doTest(myCollation, testCases[results[10][j]], testCases[results[10][n]], UCOL_LESS);
+ }
+ }
+ ucol_close(myCollation);
+ free(temp);
+}
+
+static void TestDemo4()
+{
+ UCollator *myCollation;
+ int32_t j, n;
+ const char *rules = " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' ";
+ int32_t len=(int32_t)strlen(rules);
+ UChar *temp = (UChar*)malloc(sizeof(UChar) * (len+1));
+ UErrorCode status = U_ZERO_ERROR;
+ u_uastrcpy(temp, rules);
+
+ log_verbose("Demo Test 4 : Create a new table collation with rules \" & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' \"\n");
+
+ myCollation = ucol_openRules(temp, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+
+ if (U_FAILURE(status))
+ {
+ log_err( "Demo Test 4 Rule collation object creation failed.: %s\n", myErrorName(status));
+ return;
+ }
+ for (j = 0; j < TOTALTESTSET; j++)
+ {
+ for (n = j+1; n < TOTALTESTSET; n++)
+ {
+ doTest(myCollation, testCases[results[11][j]], testCases[results[11][n]], UCOL_LESS);
+ }
+ }
+ ucol_close(myCollation);
+ free(temp);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h
new file mode 100644
index 00000000000..d45461cdb12
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cg7coll.h
@@ -0,0 +1,71 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CG7COLL.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * G7CollationTest is a third level test class. This test performs the examples
+ * mentioned on the IBM Java international demos web site.
+ * Sample Rules: & Z < p , P
+ * Effect : Making P sort after Z.
+ *
+ * Sample Rules: & c < ch , cH, Ch, CH
+ * Effect : As well as adding sequences of characters that act as a single character (this is
+ * known as contraction), you can also add characters that act like a sequence of
+ * characters (this is known as expansion).
+ *
+ * Sample Rules: & Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'
+ * Effect : Expansion and contraction can actually be combined.
+ *
+ * Sample Rules: & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-'
+ * Effect : sorted sequence as the following,
+ * aardvark
+ * a-rdvark
+ * abbot
+ * coop
+ * co-p
+ * cop
+ */
+
+#ifndef _CG7COLLTST
+#define _CG7COLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+#define TESTLOCALES 12
+#define FIXEDTESTSET 15
+#define TOTALTESTSET 30
+
+ /* perform test for G7 locales */
+ static void TestG7Locales(void);
+
+ /* perform test with added rules " & Z < p, P" */
+ static void TestDemo1(void);
+
+ /* perorm test with added rules "& C < ch , cH, Ch, CH" */
+ static void TestDemo2(void);
+
+ /* perform test with added rules */
+ /* "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'" */
+ static void TestDemo3(void);
+
+ /* perform test with added rules */
+ /* " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' " */
+ static void TestDemo4(void);
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c
new file mode 100644
index 00000000000..c70ae2bca5d
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/chashtst.c
@@ -0,0 +1,384 @@
+/*
+*******************************************************************************
+* Copyright (C) 2000-2005, International Business Machines
+* Corporation and others. All Rights Reserved.
+*******************************************************************************
+* Date Name Description
+* 03/22/00 aliu Creation.
+* 07/13/00 Madhu Added more tests
+*******************************************************************************
+*/
+
+#include "cintltst.h"
+#include "uhash.h"
+#include "unicode/ctest.h"
+#include "unicode/ustring.h"
+#include "cstring.h"
+
+/**********************************************************************
+ * Prototypes
+ *********************************************************************/
+
+static void TestBasic(void);
+static void TestOtherAPI(void);
+static void hashIChars(void);
+
+static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key);
+
+static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2);
+
+static void _put(UHashtable* hash,
+ const char* key,
+ int32_t value,
+ int32_t expectedOldValue);
+
+static void _get(UHashtable* hash,
+ const char* key,
+ int32_t expectedValue);
+
+static void _remove(UHashtable* hash,
+ const char* key,
+ int32_t expectedValue);
+
+void addHashtableTest(TestNode** root);
+
+/**********************************************************************
+ * UHashTok wrapper functions
+ *********************************************************************/
+
+static UBool
+_compareChars(void* a, void* b) {
+ UHashTok s, t;
+ s.pointer = a;
+ t.pointer = b;
+ return uhash_compareChars(s, t);
+}
+
+static UBool
+_compareIChars(void* a, void* b) {
+ UHashTok s, t;
+ s.pointer = a;
+ t.pointer = b;
+ return uhash_compareIChars(s, t);
+}
+
+static UBool
+_compareUChars(void* a, void* b) {
+ UHashTok s, t;
+ s.pointer = a;
+ t.pointer = b;
+ return uhash_compareUChars(s, t);
+}
+
+static UBool
+_compareLong(int32_t a, int32_t b) {
+ UHashTok s, t;
+ s.integer = a;
+ t.integer = b;
+ return uhash_compareLong(s, t);
+}
+
+/**********************************************************************
+ * FW Registration
+ *********************************************************************/
+
+void addHashtableTest(TestNode** root) {
+
+ addTest(root, &TestBasic, "tsutil/chashtst/TestBasic");
+ addTest(root, &TestOtherAPI, "tsutil/chashtst/TestOtherAPI");
+ addTest(root, &hashIChars, "tsutil/chashtst/hashIChars");
+
+}
+
+/**********************************************************************
+ * Test Functions
+ *********************************************************************/
+
+static void TestBasic(void) {
+ static const char one[4] = {0x6F, 0x6E, 0x65, 0}; /* "one" */
+ static const char one2[4] = {0x6F, 0x6E, 0x65, 0}; /* Get around compiler optimizations */
+ static const char two[4] = {0x74, 0x77, 0x6F, 0}; /* "two" */
+ static const char three[6] = {0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* "three" */
+ static const char omega[6] = {0x6F, 0x6D, 0x65, 0x67, 0x61, 0}; /* "omega" */
+ UErrorCode status = U_ZERO_ERROR;
+ UHashtable *hash;
+
+ hash = uhash_open(hashChars, isEqualChars, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
+ u_errorName(status), hash);
+ return;
+ }
+ if (hash == NULL) {
+ log_err("FAIL: uhash_open returned NULL\n");
+ return;
+ }
+ log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
+
+ _put(hash, one, 1, 0);
+ _put(hash, omega, 24, 0);
+ _put(hash, two, 2, 0);
+ _put(hash, three, 3, 0);
+ _put(hash, one, -1, 1);
+ _put(hash, two, -2, 2);
+ _put(hash, omega, 48, 24);
+ _put(hash, one, 100, -1);
+ _get(hash, three, 3);
+ _remove(hash, two, -2);
+ _get(hash, two, 0);
+ _get(hash, one, 100);
+ _put(hash, two, 200, 0);
+ _get(hash, omega, 48);
+ _get(hash, two, 200);
+
+ if(_compareChars((void*)one, (void*)three) == TRUE ||
+ _compareChars((void*)one, (void*)one2) != TRUE ||
+ _compareChars((void*)one, (void*)one) != TRUE ||
+ _compareChars((void*)one, NULL) == TRUE ) {
+ log_err("FAIL: compareChars failed\n");
+ }
+ if(_compareIChars((void*)one, (void*)three) == TRUE ||
+ _compareIChars((void*)one, (void*)one) != TRUE ||
+ _compareIChars((void*)one, (void*)one2) != TRUE ||
+ _compareIChars((void*)one, NULL) == TRUE ) {
+ log_err("FAIL: compareIChars failed\n");
+ }
+
+ uhash_close(hash);
+
+}
+
+static void TestOtherAPI(void){
+
+ UErrorCode status = U_ZERO_ERROR;
+ UHashtable *hash;
+
+ /* Use the correct type when cast to void * */
+ static const UChar one[4] = {0x006F, 0x006E, 0x0065, 0}; /* L"one" */
+ static const UChar one2[4] = {0x006F, 0x006E, 0x0065, 0}; /* Get around compiler optimizations */
+ static const UChar two[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
+ static const UChar two2[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */
+ static const UChar three[6] = {0x0074, 0x0068, 0x0072, 0x0065, 0x0065, 0}; /* L"three" */
+ static const UChar four[6] = {0x0066, 0x006F, 0x0075, 0x0072, 0}; /* L"four" */
+ static const UChar five[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
+ static const UChar five2[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */
+
+ hash = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
+ u_errorName(status), hash);
+ return;
+ }
+ if (hash == NULL) {
+ log_err("FAIL: uhash_open returned NULL\n");
+ return;
+ }
+ log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
+
+ uhash_puti(hash, (void*)one, 1, &status);
+ if(uhash_count(hash) != 1){
+ log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
+ }
+ if(uhash_find(hash, (void*)two) != NULL){
+ log_err("FAIL: uhash_find failed\n");
+ }
+ uhash_puti(hash, (void*)two, 2, &status);
+ uhash_puti(hash, (void*)three, 3, &status);
+ uhash_puti(hash, (void*)four, 4, &status);
+ uhash_puti(hash, (void*)five, 5, &status);
+
+ if(uhash_count(hash) != 5){
+ log_err("FAIL: uhas_count() failed. Expected: 5, Got: %d\n", uhash_count(hash));
+ }
+
+ if(uhash_geti(hash, (void*)two2) != 2){
+ log_err("FAIL: uhash_geti failed\n");
+ }
+
+ if(uhash_find(hash, (void*)two2) == NULL){
+ log_err("FAIL: uhash_find of \"two\" failed\n");
+ }
+
+ if(uhash_removei(hash, (void*)five2) != 5){
+ log_err("FAIL: uhash_remove() failed\n");
+ }
+ if(uhash_count(hash) != 4){
+ log_err("FAIL: uhas_count() failed. Expected: 4, Got: %d\n", uhash_count(hash));
+ }
+
+ uhash_put(hash, (void*)one, NULL, &status);
+ if(uhash_count(hash) != 3){
+ log_err("FAIL: uhash_put() with value=NULL didn't remove the key value pair\n");
+ }
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ uhash_puti(hash, (void*)one, 1, &status);
+ if(uhash_count(hash) != 3){
+ log_err("FAIL: uhash_put() with value!=NULL should fail when status != U_ZERO_ERROR \n");
+ }
+
+ status=U_ZERO_ERROR;
+ uhash_puti(hash, (void*)one, 1, &status);
+ if(uhash_count(hash) != 4){
+ log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n");
+ }
+
+ if(_compareUChars((void*)one, (void*)two) == TRUE ||
+ _compareUChars((void*)one, (void*)one) != TRUE ||
+ _compareUChars((void*)one, (void*)one2) != TRUE ||
+ _compareUChars((void*)one, NULL) == TRUE ) {
+ log_err("FAIL: compareUChars failed\n");
+ }
+
+ uhash_removeAll(hash);
+ if(uhash_count(hash) != 0){
+ log_err("FAIL: uhas_count() failed. Expected: 0, Got: %d\n", uhash_count(hash));
+ }
+
+ uhash_setKeyComparator(hash, uhash_compareLong);
+ uhash_setKeyHasher(hash, uhash_hashLong);
+ uhash_iputi(hash, 1001, 1, &status);
+ uhash_iputi(hash, 1002, 2, &status);
+ uhash_iputi(hash, 1003, 3, &status);
+ if(_compareLong(1001, 1002) == TRUE ||
+ _compareLong(1001, 1001) != TRUE ||
+ _compareLong(1001, 0) == TRUE ) {
+ log_err("FAIL: compareLong failed\n");
+ }
+ /*set the resize policy to just GROW and SHRINK*/
+ /*how to test this??*/
+ uhash_setResizePolicy(hash, U_GROW_AND_SHRINK);
+ uhash_iputi(hash, 1004, 4, &status);
+ uhash_iputi(hash, 1005, 5, &status);
+ uhash_iputi(hash, 1006, 6, &status);
+ if(uhash_count(hash) != 6){
+ log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash));
+ }
+ if(uhash_iremovei(hash, 1004) != 4){
+ log_err("FAIL: uhash_remove failed\n");
+ }
+ if(uhash_iremovei(hash, 1004) != 0){
+ log_err("FAIL: uhash_remove failed\n");
+ }
+
+ uhash_removeAll(hash);
+ uhash_iput(hash, 2004, (void*)one, &status);
+ uhash_iput(hash, 2005, (void*)two, &status);
+ if(uhash_count(hash) != 2){
+ log_err("FAIL: uhash_count() failed. Expected: 2, Got: %d\n", uhash_count(hash));
+ }
+ if(uhash_iremove(hash, 2004) != (void*)one){
+ log_err("FAIL: uhash_remove failed\n");
+ }
+ if(uhash_iremove(hash, 2004) != NULL){
+ log_err("FAIL: uhash_remove failed\n");
+ }
+ if(uhash_count(hash) != 1){
+ log_err("FAIL: uhash_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
+ }
+
+ uhash_close(hash);
+
+}
+
+static void hashIChars(void) {
+ static const char which[] = "which";
+ static const char WHICH2[] = "WHICH";
+ static const char where[] = "where";
+ UErrorCode status = U_ZERO_ERROR;
+ UHashtable *hash;
+
+ hash = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n",
+ u_errorName(status), hash);
+ return;
+ }
+ if (hash == NULL) {
+ log_err("FAIL: uhash_open returned NULL\n");
+ return;
+ }
+ log_verbose("Ok: uhash_open returned 0x%08X\n", hash);
+
+ _put(hash, which, 1, 0);
+ _put(hash, WHICH2, 2, 1);
+ _put(hash, where, 3, 0);
+ if(uhash_count(hash) != 2){
+ log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash));
+ }
+ _remove(hash, which, 2);
+
+ uhash_close(hash);
+}
+
+
+/**********************************************************************
+ * uhash Callbacks
+ *********************************************************************/
+
+/**
+ * This hash function is designed to collide a lot to test key equality
+ * resolution. It only uses the first char.
+ */
+static int32_t U_EXPORT2 U_CALLCONV hashChars(const UHashTok key) {
+ return *(const char*) key.pointer;
+}
+
+static UBool U_EXPORT2 U_CALLCONV isEqualChars(const UHashTok key1, const UHashTok key2) {
+ return (UBool)((key1.pointer != NULL) &&
+ (key2.pointer != NULL) &&
+ (uprv_strcmp((const char*)key1.pointer, (const char*)key2.pointer) == 0));
+}
+
+/**********************************************************************
+ * Wrapper Functions
+ *********************************************************************/
+
+static void _put(UHashtable* hash,
+ const char* key,
+ int32_t value,
+ int32_t expectedOldValue) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t oldValue =
+ uhash_puti(hash, (void*) key, value, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uhash_put(%s) failed with %s and returned %ld\n",
+ key, u_errorName(status), oldValue);
+ } else if (oldValue != expectedOldValue) {
+ log_err("FAIL: uhash_put(%s) returned old value %ld; expected %ld\n",
+ key, oldValue, expectedOldValue);
+ } else {
+ log_verbose("Ok: uhash_put(%s, %d) returned old value %ld\n",
+ key, value, oldValue);
+ }
+}
+
+static void _get(UHashtable* hash,
+ const char* key,
+ int32_t expectedValue) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value = uhash_geti(hash, key);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uhash_get(%s) failed with %s and returned %ld\n",
+ key, u_errorName(status), value);
+ } else if (value != expectedValue) {
+ log_err("FAIL: uhash_get(%s) returned %ld; expected %ld\n",
+ key, value, expectedValue);
+ } else {
+ log_verbose("Ok: uhash_get(%s) returned value %ld\n",
+ key, value);
+ }
+}
+
+static void _remove(UHashtable* hash,
+ const char* key,
+ int32_t expectedValue) {
+ int32_t value = uhash_removei(hash, key);
+ if (value != expectedValue) {
+ log_err("FAIL: uhash_remove(%s) returned %ld; expected %ld\n",
+ key, value, expectedValue);
+ } else {
+ log_verbose("Ok: uhash_remove(%s) returned old value %ld\n",
+ key, value);
+ }
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c
new file mode 100644
index 00000000000..03efad93248
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.c
@@ -0,0 +1,725 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CINTLTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+
+/*The main root for C API tests*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "cstring.h"
+#include "cintltst.h"
+#include "umutex.h"
+#include "uassert.h"
+#include "cmemory.h"
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "unicode/ures.h"
+#include "unicode/uclean.h"
+#include "unicode/ucal.h"
+#include "uoptions.h"
+#include "putilimp.h" /* for uprv_getUTCtime() */
+
+#ifdef XP_MAC_CONSOLE
+# include <console.h>
+#endif
+
+#define CTST_LEAK_CHECK 1
+#ifdef CTST_LEAK_CHECK
+U_CFUNC void ctst_freeAll(void);
+#endif
+
+static char* _testDataPath=NULL;
+
+/*
+ * Forward Declarations
+ */
+void ctest_setICU_DATA(void);
+
+
+
+#if UCONFIG_NO_LEGACY_CONVERSION
+# define TRY_CNV_1 "iso-8859-1"
+# define TRY_CNV_2 "ibm-1208"
+#else
+# define TRY_CNV_1 "iso-8859-7"
+# define TRY_CNV_2 "sjis"
+#endif
+
+
+/*
+ * Tracing functions.
+ */
+static int traceFnNestingDepth = 0;
+U_CDECL_BEGIN
+static void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) {
+ char buf[500];
+ utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber));
+ buf[sizeof(buf)-1]=0;
+ fputs(buf, stdout);
+ traceFnNestingDepth++;
+}
+
+static void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) {
+ char buf[500];
+
+ if (traceFnNestingDepth>0) {
+ traceFnNestingDepth--;
+ }
+ utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber));
+ buf[sizeof(buf)-1]=0;
+ fputs(buf, stdout);
+ utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
+ buf[sizeof(buf)-1]=0;
+ fputs(buf, stdout);
+ putc('\n', stdout);
+}
+
+static void U_CALLCONV TraceData(const void *context, int32_t fnNumber,
+ int32_t level, const char *fmt, va_list args) {
+ char buf[500];
+ utrace_vformat(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
+ buf[sizeof(buf)-1]=0;
+ fputs(buf, stdout);
+ putc('\n', stdout);
+}
+U_CDECL_END
+
+
+
+int main(int argc, const char* const argv[])
+{
+ int nerrors = 0;
+ int warnOnMissingData = 0;
+ int i, j;
+ UBool defaultDataFound;
+ TestNode *root;
+ const char *warnOrErr = "Failure";
+ const char** argv2;
+ UDate startTime, endTime;
+ int32_t diffTime;
+
+ /* initial check for the default converter */
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UResourceBundle *rb;
+ UConverter *cnv;
+
+ U_MAIN_INIT_ARGS(argc, argv);
+
+ startTime = uprv_getUTCtime();
+
+ argv2 = (const char**) malloc(sizeof(char*) * argc);
+ if (argv2 == NULL) {
+ printf("*** Error: Out of memory (too many cmd line args?)\n");
+ return 1;
+ }
+ argv2[0] = argv[0];
+
+
+ /* Checkargs */
+ /* TODO: Test framework arg handling needs to be decoupled from test execution
+ * so that the args being processed here don't need special handling,
+ * separate from the other test args.
+ */
+ ICU_TRACE = UTRACE_OFF;
+ for(i=1,j=1;i<argc;i++) {
+ argv2[j++] = argv[i];
+ if(!strcmp(argv[i],"-w")) {
+ warnOnMissingData = 1;
+ warnOrErr = "Warning";
+ }
+ else if (strcmp( argv[i], "-t_error") == 0) {
+ ICU_TRACE = UTRACE_ERROR;
+ }
+ else if (strcmp( argv[i], "-t_warn") == 0) {
+ ICU_TRACE = UTRACE_WARNING;
+ }
+ else if (strcmp( argv[i], "-t_oc") == 0) {
+ ICU_TRACE = UTRACE_OPEN_CLOSE;
+ }
+ else if (strcmp( argv[i], "-t_info") == 0) {
+ ICU_TRACE = UTRACE_INFO;
+ }
+ else if (strcmp( argv[i], "-t_verbose") == 0) {
+ ICU_TRACE = UTRACE_VERBOSE;
+ }
+ }
+ argc = j;
+
+
+ utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData);
+ utrace_setLevel(ICU_TRACE);
+
+
+ while (REPEAT_TESTS > 0) { /* Loop runs once per complete execution of the tests
+ * used for -r (repeat) test option. */
+
+ /* Check whether ICU will initialize without forcing the build data directory into
+ * the ICU_DATA path. Success here means either the data dll contains data, or that
+ * this test program was run with ICU_DATA set externally. Failure of this check
+ * is normal when ICU data is not packaged into a shared library.
+ *
+ * Whether or not this test succeeds, we want to cleanup and reinitialize
+ * with a data path so that data loading from individual files can be tested.
+ */
+ defaultDataFound = TRUE;
+ u_init(&errorCode);
+ if (U_FAILURE(errorCode)) {
+ fprintf(stderr,
+ "#### Note: ICU Init without build-specific setDataDirectory() failed. %s\n", u_errorName(errorCode));
+ defaultDataFound = FALSE;
+ }
+ u_cleanup();
+ errorCode = U_ZERO_ERROR;
+ utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData);
+ utrace_setLevel(ICU_TRACE);
+
+ /* Initialize ICU */
+ if (!defaultDataFound) {
+ ctest_setICU_DATA(); /* u_setDataDirectory() must happen Before u_init() */
+ }
+ u_init(&errorCode);
+ if (U_FAILURE(errorCode)) {
+ fprintf(stderr,
+ "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
+ "*** Check the ICU_DATA environment variable and \n"
+ "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
+ if(warnOnMissingData == 0) {
+ fprintf(stderr, "*** Exiting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
+ u_cleanup();
+ return 1;
+ }
+ }
+
+
+
+ /* try more data */
+ cnv = ucnv_open(TRY_CNV_2, &errorCode);
+ if(cnv != 0) {
+ /* ok */
+ ucnv_close(cnv);
+ } else {
+ fprintf(stderr,
+ "*** %s! The converter for " TRY_CNV_2 " cannot be opened.\n"
+ "*** Check the ICU_DATA environment variable and \n"
+ "*** check that the data files are present.\n", warnOrErr);
+ if(warnOnMissingData == 0) {
+ fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
+ u_cleanup();
+ return 1;
+ }
+ }
+
+ rb = ures_open(NULL, "en", &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ /* ok */
+ ures_close(rb);
+ } else {
+ fprintf(stderr,
+ "*** %s! The \"en\" locale resource bundle cannot be opened.\n"
+ "*** Check the ICU_DATA environment variable and \n"
+ "*** check that the data files are present.\n", warnOrErr);
+ if(warnOnMissingData == 0) {
+ fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n*** purposely removed, to continue test anyway.\n");
+ u_cleanup();
+ return 1;
+ }
+ }
+
+ errorCode = U_ZERO_ERROR;
+ rb = ures_open(NULL, NULL, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ /* ok */
+ if (errorCode == U_USING_DEFAULT_WARNING || errorCode == U_USING_FALLBACK_WARNING) {
+ fprintf(stderr,
+ "#### Note: The default locale %s is not available\n", uloc_getDefault());
+ }
+ ures_close(rb);
+ } else {
+ fprintf(stderr,
+ "*** %s! Can not open a resource bundle for the default locale %s\n", warnOrErr, uloc_getDefault());
+ if(warnOnMissingData == 0) {
+ fprintf(stderr, "*** Exitting. Use the '-w' option if data files were\n"
+ "*** purposely removed, to continue test anyway.\n");
+ u_cleanup();
+ return 1;
+ }
+ }
+ fprintf(stdout, "Default locale for this run is %s\n", uloc_getDefault());
+
+ /* Build a tree of all tests.
+ * Subsequently will be used to find / iterate the tests to run */
+ root = NULL;
+ addAllTests(&root);
+
+ /* Tests acutally run HERE. TODO: separate command line option parsing & setting from test execution!! */
+ nerrors = processArgs(root, argc, argv2);
+
+ if (--REPEAT_TESTS > 0) {
+ printf("Repeating tests %d more time(s)\n", REPEAT_TESTS);
+ }
+ cleanUpTestTree(root);
+
+#ifdef CTST_LEAK_CHECK
+ ctst_freeAll();
+ /* To check for leaks */
+ u_cleanup(); /* nuke the hashtable.. so that any still-open cnvs are leaked */
+#endif
+
+ } /* End of loop that repeats the entire test, if requested. (Normally doesn't loop) */
+
+ free((void*)argv2);
+
+ endTime = uprv_getUTCtime();
+ diffTime = (int32_t)(endTime - startTime);
+ printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
+ (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
+ (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
+ (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
+ (int)(diffTime%U_MILLIS_PER_SECOND));
+
+ return nerrors ? 1 : 0;
+}
+
+/*
+static void ctest_appendToDataDirectory(const char *toAppend)
+{
+ const char *oldPath ="";
+ char newBuf [1024];
+ char *newPath = newBuf;
+ int32_t oldLen;
+ int32_t newLen;
+
+ if((toAppend == NULL) || (*toAppend == 0)) {
+ return;
+ }
+
+ oldPath = u_getDataDirectory();
+ if( (oldPath==NULL) || (*oldPath == 0)) {
+ u_setDataDirectory(toAppend);
+ } else {
+ oldLen = strlen(oldPath);
+ newLen = strlen(toAppend)+1+oldLen;
+
+ if(newLen > 1022)
+ {
+ newPath = (char *)ctst_malloc(newLen);
+ }
+
+ strcpy(newPath, oldPath);
+ strcpy(newPath+oldLen, U_PATH_SEP_STRING);
+ strcpy(newPath+oldLen+1, toAppend);
+
+ u_setDataDirectory(newPath);
+
+ if(newPath != newBuf)
+ {
+ free(newPath);
+ }
+ }
+}
+*/
+
+/* returns the path to icu/source/data */
+const char * ctest_dataSrcDir()
+{
+ static const char *dataSrcDir = NULL;
+
+ if(dataSrcDir) {
+ return dataSrcDir;
+ }
+
+ /* U_TOPSRCDIR is set by the makefiles on UNIXes when building cintltst and intltst
+ // to point to the top of the build hierarchy, which may or
+ // may not be the same as the source directory, depending on
+ // the configure options used. At any rate,
+ // set the data path to the built data from this directory.
+ // The value is complete with quotes, so it can be used
+ // as-is as a string constant.
+ */
+#if defined (U_TOPSRCDIR)
+ {
+ dataSrcDir = U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
+ }
+#else
+
+ /* On Windows, the file name obtained from __FILE__ includes a full path.
+ * This file is "wherever\icu\source\test\cintltst\cintltst.c"
+ * Change to "wherever\icu\source\data"
+ */
+ {
+ static char p[sizeof(__FILE__) + 20];
+ char *pBackSlash;
+ int i;
+
+ strcpy(p, __FILE__);
+ /* We want to back over three '\' chars. */
+ /* Only Windows should end up here, so looking for '\' is safe. */
+ for (i=1; i<=3; i++) {
+ pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
+ if (pBackSlash != NULL) {
+ *pBackSlash = 0; /* Truncate the string at the '\' */
+ }
+ }
+
+ if (pBackSlash != NULL) {
+ /* We found and truncated three names from the path.
+ * Now append "source\data" and set the environment
+ */
+ strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING );
+ dataSrcDir = p;
+ }
+ else {
+ /* __FILE__ on MSVC7 does not contain the directory */
+ FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
+ if (file) {
+ fclose(file);
+ dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
+ }
+ else {
+ dataSrcDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING;
+ }
+ }
+ }
+#endif
+
+ return dataSrcDir;
+
+}
+
+/* returns the path to icu/source/data/out */
+const char *ctest_dataOutDir()
+{
+ static const char *dataOutDir = NULL;
+
+ if(dataOutDir) {
+ return dataOutDir;
+ }
+
+ /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
+ // to point to the top of the build hierarchy, which may or
+ // may not be the same as the source directory, depending on
+ // the configure options used. At any rate,
+ // set the data path to the built data from this directory.
+ // The value is complete with quotes, so it can be used
+ // as-is as a string constant.
+ */
+#if defined (U_TOPBUILDDIR)
+ {
+ dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
+ }
+#else
+
+ /* On Windows, the file name obtained from __FILE__ includes a full path.
+ * This file is "wherever\icu\source\test\cintltst\cintltst.c"
+ * Change to "wherever\icu\source\data"
+ */
+ {
+ static char p[sizeof(__FILE__) + 20];
+ char *pBackSlash;
+ int i;
+
+ strcpy(p, __FILE__);
+ /* We want to back over three '\' chars. */
+ /* Only Windows should end up here, so looking for '\' is safe. */
+ for (i=1; i<=3; i++) {
+ pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
+ if (pBackSlash != NULL) {
+ *pBackSlash = 0; /* Truncate the string at the '\' */
+ }
+ }
+
+ if (pBackSlash != NULL) {
+ /* We found and truncated three names from the path.
+ * Now append "source\data" and set the environment
+ */
+ strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
+ dataOutDir = p;
+ }
+ else {
+ /* __FILE__ on MSVC7 does not contain the directory */
+ FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
+ if (file) {
+ fclose(file);
+ dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
+ }
+ else {
+ dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
+ }
+ }
+ }
+#endif
+
+ return dataOutDir;
+}
+
+/* ctest_setICU_DATA - if the ICU_DATA environment variable is not already
+ * set, try to deduce the directory in which ICU was built,
+ * and set ICU_DATA to "icu/source/data" in that location.
+ * The intent is to allow the tests to have a good chance
+ * of running without requiring that the user manually set
+ * ICU_DATA. Common data isn't a problem, since it is
+ * picked up via a static (build time) reference, but the
+ * tests dynamically load some data.
+ */
+void ctest_setICU_DATA() {
+
+ /* No location for the data dir was identifiable.
+ * Add other fallbacks for the test data location here if the need arises
+ */
+ if (getenv("ICU_DATA") == NULL) {
+ /* If ICU_DATA isn't set, set it to the usual location */
+ u_setDataDirectory(ctest_dataOutDir());
+ }
+}
+
+UChar* CharsToUChars(const char* str) {
+ /* Might be faster to just use uprv_strlen() as the preflight len - liu */
+ int32_t len = u_unescape(str, 0, 0); /* preflight */
+ /* Do NOT use malloc() - we are supposed to be acting like user code! */
+ UChar *buf = (UChar*) malloc(sizeof(UChar) * (len + 1));
+ u_unescape(str, buf, len + 1);
+ return buf;
+}
+
+char *austrdup(const UChar* unichars)
+{
+ int length;
+ char *newString;
+
+ length = u_strlen ( unichars );
+ /*newString = (char*)malloc ( sizeof( char ) * 4 * ( length + 1 ) );*/ /* this leaks for now */
+ newString = (char*)ctst_malloc ( sizeof( char ) * 4 * ( length + 1 ) ); /* this shouldn't */
+
+ if ( newString == NULL )
+ return NULL;
+
+ u_austrcpy ( newString, unichars );
+
+ return newString;
+}
+
+char *aescstrdup(const UChar* unichars,int32_t length){
+ char *newString,*targetLimit,*target;
+ UConverterFromUCallback cb;
+ const void *p;
+ UErrorCode errorCode = U_ZERO_ERROR;
+#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+# ifdef OS390
+ static const char convName[] = "ibm-1047";
+# else
+ static const char convName[] = "ibm-37";
+# endif
+#else
+ static const char convName[] = "US-ASCII";
+#endif
+ UConverter* conv = ucnv_open(convName, &errorCode);
+ if(length==-1){
+ length = u_strlen( unichars);
+ }
+ newString = (char*)ctst_malloc ( sizeof(char) * 8 * (length +1));
+ target = newString;
+ targetLimit = newString+sizeof(char) * 8 * (length +1);
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_JAVA, &cb, &p, &errorCode);
+ ucnv_fromUnicode(conv,&target,targetLimit, &unichars, (UChar*)(unichars+length),NULL,TRUE,&errorCode);
+ ucnv_close(conv);
+ *target = '\0';
+ return newString;
+}
+
+const char* loadTestData(UErrorCode* err){
+ if( _testDataPath == NULL){
+ const char* directory=NULL;
+ UResourceBundle* test =NULL;
+ char* tdpath=NULL;
+ const char* tdrelativepath;
+#if defined (U_TOPBUILDDIR)
+ tdrelativepath = "test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
+ directory = U_TOPBUILDDIR;
+#else
+ tdrelativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
+ directory= ctest_dataOutDir();
+#endif
+
+ tdpath = (char*) ctst_malloc(sizeof(char) *(( strlen(directory) * strlen(tdrelativepath)) + 10));
+
+
+ /* u_getDataDirectory shoul return \source\data ... set the
+ * directory to ..\source\data\..\test\testdata\out\testdata
+ *
+ * Fallback: When Memory mapped file is built
+ * ..\source\data\out\..\..\test\testdata\out\testdata
+ */
+ strcpy(tdpath, directory);
+ strcat(tdpath, tdrelativepath);
+ strcat(tdpath,"testdata");
+
+
+ test=ures_open(tdpath, "testtypes", err);
+
+ /* Fall back did not succeed either so return */
+ if(U_FAILURE(*err)){
+ *err = U_FILE_ACCESS_ERROR;
+ log_err("Could not load testtypes.res in testdata bundle with path %s - %s\n", tdpath, u_errorName(*err));
+ return "";
+ }
+ ures_close(test);
+ _testDataPath = tdpath;
+ return _testDataPath;
+ }
+ return _testDataPath;
+}
+
+#define CTEST_MAX_TIMEZONE_SIZE 256
+static UChar gOriginalTimeZone[CTEST_MAX_TIMEZONE_SIZE] = {0};
+
+/**
+ * Call this once to get a consistent timezone. Use ctest_resetTimeZone to set it back to the original value.
+ * @param optionalTimeZone Set this to a requested timezone.
+ * Set to NULL to use the standard test timezone (Pacific Time)
+ */
+U_CFUNC void ctest_setTimeZone(const char *optionalTimeZone, UErrorCode *status) {
+#if !UCONFIG_NO_FORMATTING
+ UChar zoneID[CTEST_MAX_TIMEZONE_SIZE];
+
+ if (optionalTimeZone == NULL) {
+ optionalTimeZone = "America/Los_Angeles";
+ }
+ if (gOriginalTimeZone[0]) {
+ log_err("*** Error: time zone saved twice. New value will be %s\n",
+ optionalTimeZone);
+ }
+ ucal_getDefaultTimeZone(gOriginalTimeZone, CTEST_MAX_TIMEZONE_SIZE, status);
+ if (U_FAILURE(*status)) {
+ log_err("*** Error: Failed to save default time zone: %s\n",
+ u_errorName(*status));
+ *status = U_ZERO_ERROR;
+ }
+
+ u_uastrncpy(zoneID, optionalTimeZone, CTEST_MAX_TIMEZONE_SIZE-1);
+ zoneID[CTEST_MAX_TIMEZONE_SIZE-1] = 0;
+ ucal_setDefaultTimeZone(zoneID, status);
+ if (U_FAILURE(*status)) {
+ log_err("*** Error: Failed to set default time zone to \"%s\": %s\n",
+ optionalTimeZone, u_errorName(*status));
+ }
+#endif
+}
+
+/**
+ * Call this once get back the original timezone
+ */
+U_CFUNC void ctest_resetTimeZone(void) {
+#if !UCONFIG_NO_FORMATTING
+ UErrorCode status = U_ZERO_ERROR;
+
+ ucal_setDefaultTimeZone(gOriginalTimeZone, &status);
+ if (U_FAILURE(status)) {
+ log_err("*** Error: Failed to reset default time zone: %s\n",
+ u_errorName(status));
+ }
+ /* Set to an empty state */
+ gOriginalTimeZone[0] = 0;
+#endif
+}
+
+#define CTST_MAX_ALLOC 8192
+/* Array used as a queue */
+static void * ctst_allocated_stuff[CTST_MAX_ALLOC] = {0};
+static int ctst_allocated = 0;
+static UBool ctst_free = FALSE;
+
+void *ctst_malloc(size_t size) {
+ if(ctst_allocated >= CTST_MAX_ALLOC - 1) {
+ ctst_allocated = 0;
+ ctst_free = TRUE;
+ }
+ if(ctst_allocated_stuff[ctst_allocated]) {
+ free(ctst_allocated_stuff[ctst_allocated]);
+ }
+ return ctst_allocated_stuff[ctst_allocated++] = malloc(size);
+}
+
+#ifdef CTST_LEAK_CHECK
+void ctst_freeAll() {
+ int i;
+ if(ctst_free == 0) {
+ for(i=0; i<ctst_allocated; i++) {
+ free(ctst_allocated_stuff[i]);
+ ctst_allocated_stuff[i] = NULL;
+ }
+ } else {
+ for(i=0; i<CTST_MAX_ALLOC; i++) {
+ free(ctst_allocated_stuff[i]);
+ ctst_allocated_stuff[i] = NULL;
+ }
+ }
+ ctst_allocated = 0;
+ _testDataPath=NULL;
+}
+
+#define VERBOSE_ASSERTIONS
+
+U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec) {
+ U_ASSERT(ec!=NULL);
+ if (U_FAILURE(*ec)) {
+ log_err("FAIL: %s (%s)\n", msg, u_errorName(*ec));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* if 'condition' is a UBool, the compiler complains bitterly about
+ expressions like 'a > 0' which it evaluates as int */
+U_CFUNC UBool assertTrue(const char* msg, int /*not UBool*/ condition) {
+ if (!condition) {
+ log_err("FAIL: assertTrue() failed: %s\n", msg);
+ }
+#ifdef VERBOSE_ASSERTIONS
+ else {
+ log_verbose("Ok: %s\n", msg);
+ }
+#endif
+ return (UBool)condition;
+}
+
+U_CFUNC UBool assertEquals(const char* message, const char* expected,
+ const char* actual) {
+ if (uprv_strcmp(expected, actual) != 0) {
+ log_err("FAIL: %s; got \"%s\"; expected \"%s\"\n",
+ message, actual, expected);
+ return FALSE;
+ }
+#ifdef VERBOSE_ASSERTIONS
+ else {
+ log_verbose("Ok: %s; got \"%s\"\n", message, actual);
+ }
+#endif
+ return TRUE;
+}
+/*--------------------------------------------------------------------
+ * Time bomb - allows temporary behavior that expires at a given
+ * release
+ *--------------------------------------------------------------------
+ */
+
+U_CFUNC UBool isICUVersionAtLeast(const UVersionInfo x) {
+ UVersionInfo v;
+ u_getVersion(v);
+ return (uprv_memcmp(v, x, U_MAX_VERSION_LENGTH) >= 0);
+}
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h
new file mode 100644
index 00000000000..e750424b895
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.h
@@ -0,0 +1,108 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CINTLTST.H
+*
+* Madhu Katragadda Creation
+* Modification History:
+* Date Name Description
+* 07/13/99 helena HPUX 11 CC port.
+*********************************************************************************
+
+The main root for C API tests
+*/
+
+#ifndef _CINTLTST
+#define _CINTLTST
+
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "unicode/ctest.h"
+#include <stdlib.h>
+
+#ifndef U_USE_DEPRECATED_API
+#define U_USE_DEPRECATED_API 1
+#endif
+
+U_CFUNC void addAllTests(TestNode** root);
+
+/**
+ * Return the path to the icu/source/data/out directory
+ */
+U_CFUNC const char* ctest_dataOutDir(void);
+
+/**
+ * Return the path to the icu/source/data/ directory
+ * for out of source builds too returns the source directory
+ */
+U_CFUNC const char* ctest_dataSrcDir(void);
+
+U_CFUNC UChar* CharsToUChars(const char* chars);
+
+/**
+ * Convert a const UChar* into a char*
+ * Caller owns storage, but in practice this function
+ * LEAKS so be aware of that.
+ * @param unichars UChars (null terminated) to be converted
+ * @return new char* to the unichars in host format
+ */
+
+U_CFUNC char *austrdup(const UChar* unichars);
+U_CFUNC char *aescstrdup(const UChar* unichars, int32_t length);
+U_CFUNC void *ctst_malloc(size_t size);
+U_CFUNC void ctst_freeAll(void);
+
+U_CFUNC const char* loadTestData(UErrorCode* err);
+
+/**
+ * function used to specify the error
+ * converts the errorcode to an error descriptive string(const char*)
+ * @param status the error code
+ */
+#define myErrorName(errorCode) u_errorName(errorCode)
+
+
+/**
+ * Call this once to get a consistent timezone. Use ctest_resetTimeZone to set it back to the original value.
+ * @param optionalTimeZone Set this to a requested timezone.
+ * Set to NULL to use the standard test timezone (Pacific Time)
+ */
+U_CFUNC void ctest_setTimeZone(const char *optionalTimeZone, UErrorCode *status);
+/**
+ * Call this once get back the original timezone
+ */
+U_CFUNC void ctest_resetTimeZone(void);
+
+/**
+ * Assert that the given UErrorCode succeeds, and return TRUE if it does.
+ */
+U_CFUNC UBool assertSuccess(const char* msg, UErrorCode* ec);
+
+/**
+ * Assert that the UBool is TRUE, and return TRUE if it does.
+ *
+ * NOTE: Use 'int condition' rather than 'UBool condition' so the
+ * compiler doesn't complain about integral conversion of expressions
+ * like 'p != 0'.
+ */
+U_CFUNC UBool assertTrue(const char* msg, int condition);
+
+/**
+ * Assert that the actualString equals the expectedString, and return
+ * TRUE if it does.
+ */
+U_CFUNC UBool assertEquals(const char* msg, const char* expectedString,
+ const char* actualString);
+
+/**
+ * Time bomb - allows temporary behavior that expires at a given
+ * release
+ *
+ */
+U_CFUNC UBool isICUVersionAtLeast(const UVersionInfo x);
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj
new file mode 100644
index 00000000000..65c4c1b935c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cintltst.vcproj
@@ -0,0 +1,721 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="cintltst"
+ ProjectGUID="{3D1246AE-1B32-479B-BECA-AEFA97BE2321}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/cintltst.tlb"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ BufferSecurityCheck="true"
+ DisableLanguageExtensions="true"
+ TreatWChar_tAsBuiltInType="true"
+ PrecompiledHeaderFile=".\Debug/cintltst.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Debug/cintltst.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/cintltst.pdb"
+ SubSystem="1"
+ FixedBaseAddress="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ UseFAT32Workaround="true"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/cintltst.tlb"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\..\include;..\..\tools\ctestfw;..\..\common;..\..\i18n;..\..\tools\toolutil"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="true"
+ EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="true"
+ TreatWChar_tAsBuiltInType="true"
+ PrecompiledHeaderFile=".\Release/cintltst.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/cintltst.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Release/cintltst.pdb"
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="bidi"
+ >
+ <File
+ RelativePath=".\cbididat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cbiditst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cbiditst.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="break iteration"
+ >
+ <File
+ RelativePath=".\cbiapts.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cbiapts.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cbkittst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="collation"
+ >
+ <File
+ RelativePath=".\callcoll.c"
+ >
+ </File>
+ <File
+ RelativePath=".\callcoll.h"
+ >
+ </File>
+ <File
+ RelativePath=".\capitst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\capitst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ccolltst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccolltst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ccurrtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccurrtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cdetst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cdetst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cestst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cestst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cfintst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cfintst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cfrtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cfrtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cg7coll.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cg7coll.h"
+ >
+ </File>
+ <File
+ RelativePath=".\citertst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\citertst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cjaptst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cjaptst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cmsccoll.c"
+ >
+ </File>
+ <File
+ RelativePath=".\colutil.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cturtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cturtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\encoll.c"
+ >
+ </File>
+ <File
+ RelativePath=".\encoll.h"
+ >
+ </File>
+ <File
+ RelativePath=".\usrchdat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\usrchtst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="collections"
+ >
+ <File
+ RelativePath=".\chashtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\sorttest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\trietest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\uenumtst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="conversion"
+ >
+ <File
+ RelativePath=".\bocu1tst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccapitst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccapitst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cconvtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cctest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\eurocreg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\nccbtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\nccbtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ncnvfbts.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ncnvfbts.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ncnvtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\nucnvtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\nucnvtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdnmtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ucsdetst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="data &amp; memory"
+ >
+ <File
+ RelativePath=".\udatatst.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableLanguageExtensions="false"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableLanguageExtensions="false"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="formatting"
+ >
+ <File
+ RelativePath=".\ccaltst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccaltst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cdattst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cdattst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cdtdptst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cdtdptst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cdtrgtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cdtrgtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cformtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cformtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cmsgtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cmsgtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cnmdptst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cnmdptst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cnumtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cnumtst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\currtest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\udatpg_test.c"
+ >
+ </File>
+ <File
+ RelativePath=".\utmstest.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="locales &amp; resources"
+ >
+ <File
+ RelativePath=".\cldrtest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cloctst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cloctst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cposxtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\crestst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\crestst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\creststn.c"
+ >
+ </File>
+ <File
+ RelativePath=".\creststn.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="misc"
+ >
+ <File
+ RelativePath=".\calltest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cintltst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cintltst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cutiltst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\hpmufn.c"
+ >
+ </File>
+ <File
+ RelativePath=".\putiltst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tracetst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="normalization"
+ >
+ <File
+ RelativePath=".\cnormtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cnormtst.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="properties &amp; sets"
+ >
+ <File
+ RelativePath=".\cucdapi.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cucdapi.h"
+ >
+ </File>
+ <File
+ RelativePath=".\cucdtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\usettest.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="strings"
+ >
+ <File
+ RelativePath=".\cstrcase.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cstrtest.c"
+ >
+ </File>
+ <File
+ RelativePath=".\custrtrn.c"
+ >
+ </File>
+ <File
+ RelativePath=".\custrtst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\utexttst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\utf16tst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\utf8tst.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="transforms"
+ >
+ <File
+ RelativePath=".\utransts.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="regex"
+ >
+ <File
+ RelativePath=".\reapits.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="sprep &amp; idna"
+ >
+ <File
+ RelativePath="idnatest.c"
+ >
+ </File>
+ <File
+ RelativePath="nfsprep.c"
+ >
+ </File>
+ <File
+ RelativePath="nfsprep.h"
+ >
+ </File>
+ <File
+ RelativePath="spreptst.c"
+ >
+ </File>
+ <File
+ RelativePath="sprpdata.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c
new file mode 100644
index 00000000000..dc24f4acea5
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.c
@@ -0,0 +1,1923 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2004, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CITERTST.C
+*
+* Modification History:
+* Date Name Description
+* Madhu Katragadda Ported for C API
+* 02/19/01 synwee Modified test case for new collation iterator
+*********************************************************************************/
+/*
+ * Collation Iterator tests.
+ * (Let me reiterate my position...)
+ */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+#include "unicode/putil.h"
+#include "callcoll.h"
+#include "cmemory.h"
+#include "cintltst.h"
+#include "citertst.h"
+#include "ccolltst.h"
+#include "filestrm.h"
+#include "cstring.h"
+#include "ucol_imp.h"
+#include "ucol_tok.h"
+#include <stdio.h>
+
+extern uint8_t ucol_uprv_getCaseBits(const UChar *, uint32_t, UErrorCode *);
+
+void addCollIterTest(TestNode** root)
+{
+ addTest(root, &TestPrevious, "tscoll/citertst/TestPrevious");
+ addTest(root, &TestOffset, "tscoll/citertst/TestOffset");
+ addTest(root, &TestSetText, "tscoll/citertst/TestSetText");
+ addTest(root, &TestMaxExpansion, "tscoll/citertst/TestMaxExpansion");
+ addTest(root, &TestUnicodeChar, "tscoll/citertst/TestUnicodeChar");
+ addTest(root, &TestNormalizedUnicodeChar,
+ "tscoll/citertst/TestNormalizedUnicodeChar");
+ addTest(root, &TestNormalization, "tscoll/citertst/TestNormalization");
+ addTest(root, &TestBug672, "tscoll/citertst/TestBug672");
+ addTest(root, &TestBug672Normalize, "tscoll/citertst/TestBug672Normalize");
+ addTest(root, &TestSmallBuffer, "tscoll/citertst/TestSmallBuffer");
+ addTest(root, &TestCEs, "tscoll/citertst/TestCEs");
+ addTest(root, &TestDiscontiguos, "tscoll/citertst/TestDiscontiguos");
+ addTest(root, &TestCEBufferOverflow, "tscoll/citertst/TestCEBufferOverflow");
+ addTest(root, &TestCEValidity, "tscoll/citertst/TestCEValidity");
+ addTest(root, &TestSortKeyValidity, "tscoll/citertst/TestSortKeyValidity");
+}
+
+/* The locales we support */
+
+static const char * LOCALES[] = {"en_AU", "en_BE", "en_CA"};
+
+static void TestBug672() {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[20];
+ UChar text[50];
+ int i;
+ int result[3][3];
+
+ u_uastrcpy(pattern, "resume");
+ u_uastrcpy(text, "Time to resume updating my resume.");
+
+ for (i = 0; i < 3; ++ i) {
+ UCollator *coll = ucol_open(LOCALES[i], &status);
+ UCollationElements *pitr = ucol_openElements(coll, pattern, -1,
+ &status);
+ UCollationElements *titer = ucol_openElements(coll, text, -1,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: in creation of either the collator or the collation iterator :%s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("locale tested %s\n", LOCALES[i]);
+
+ while (ucol_next(pitr, &status) != UCOL_NULLORDER &&
+ U_SUCCESS(status)) {
+ }
+ if (U_FAILURE(status)) {
+ log_err("ERROR: reversing collation iterator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ ucol_reset(pitr);
+
+ ucol_setOffset(titer, u_strlen(pattern), &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: setting offset in collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ result[i][0] = ucol_getOffset(titer);
+ log_verbose("Text iterator set to offset %d\n", result[i][0]);
+
+ /* Use previous() */
+ ucol_previous(titer, &status);
+ result[i][1] = ucol_getOffset(titer);
+ log_verbose("Current offset %d after previous\n", result[i][1]);
+
+ /* Add one to index */
+ log_verbose("Adding one to current offset...\n");
+ ucol_setOffset(titer, ucol_getOffset(titer) + 1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: setting offset in collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ result[i][2] = ucol_getOffset(titer);
+ log_verbose("Current offset in text = %d\n", result[i][2]);
+ ucol_closeElements(pitr);
+ ucol_closeElements(titer);
+ ucol_close(coll);
+ }
+
+ if (uprv_memcmp(result[0], result[1], 3) != 0 ||
+ uprv_memcmp(result[1], result[2], 3) != 0) {
+ log_err("ERROR: Different locales have different offsets at the same character\n");
+ }
+}
+
+
+
+/* Running this test with normalization enabled showed up a bug in the incremental
+ normalization code. */
+static void TestBug672Normalize() {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[20];
+ UChar text[50];
+ int i;
+ int result[3][3];
+
+ u_uastrcpy(pattern, "resume");
+ u_uastrcpy(text, "Time to resume updating my resume.");
+
+ for (i = 0; i < 3; ++ i) {
+ UCollator *coll = ucol_open(LOCALES[i], &status);
+ UCollationElements *pitr = NULL;
+ UCollationElements *titer = NULL;
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+
+ pitr = ucol_openElements(coll, pattern, -1, &status);
+ titer = ucol_openElements(coll, text, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: in creation of either the collator or the collation iterator :%s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("locale tested %s\n", LOCALES[i]);
+
+ while (ucol_next(pitr, &status) != UCOL_NULLORDER &&
+ U_SUCCESS(status)) {
+ }
+ if (U_FAILURE(status)) {
+ log_err("ERROR: reversing collation iterator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ ucol_reset(pitr);
+
+ ucol_setOffset(titer, u_strlen(pattern), &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: setting offset in collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ result[i][0] = ucol_getOffset(titer);
+ log_verbose("Text iterator set to offset %d\n", result[i][0]);
+
+ /* Use previous() */
+ ucol_previous(titer, &status);
+ result[i][1] = ucol_getOffset(titer);
+ log_verbose("Current offset %d after previous\n", result[i][1]);
+
+ /* Add one to index */
+ log_verbose("Adding one to current offset...\n");
+ ucol_setOffset(titer, ucol_getOffset(titer) + 1, &status);
+ if (U_FAILURE(status)) {
+ log_err("ERROR: setting offset in collator :%s\n",
+ myErrorName(status));
+ return;
+ }
+ result[i][2] = ucol_getOffset(titer);
+ log_verbose("Current offset in text = %d\n", result[i][2]);
+ ucol_closeElements(pitr);
+ ucol_closeElements(titer);
+ ucol_close(coll);
+ }
+
+ if (uprv_memcmp(result[0], result[1], 3) != 0 ||
+ uprv_memcmp(result[1], result[2], 3) != 0) {
+ log_err("ERROR: Different locales have different offsets at the same character\n");
+ }
+}
+
+
+
+
+/**
+ * Test for CollationElementIterator previous and next for the whole set of
+ * unicode characters.
+ */
+static void TestUnicodeChar()
+{
+ UChar source[0x100];
+ UCollator *en_us;
+ UCollationElements *iter;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar codepoint;
+
+ UChar *test;
+ en_us = ucol_open("en_US", &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: in creation of collation data using ucol_open()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ for (codepoint = 1; codepoint < 0xFFFE;)
+ {
+ test = source;
+
+ while (codepoint % 0xFF != 0)
+ {
+ if (u_isdefined(codepoint))
+ *(test ++) = codepoint;
+ codepoint ++;
+ }
+
+ if (u_isdefined(codepoint))
+ *(test ++) = codepoint;
+
+ if (codepoint != 0xFFFF)
+ codepoint ++;
+
+ *test = 0;
+ iter=ucol_openElements(en_us, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+ /* A basic test to see if it's working at all */
+ log_verbose("codepoint testing %x\n", codepoint);
+ backAndForth(iter);
+ ucol_closeElements(iter);
+
+ /* null termination test */
+ iter=ucol_openElements(en_us, source, -1, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+ /* A basic test to see if it's working at all */
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ }
+
+ ucol_close(en_us);
+}
+
+/**
+ * Test for CollationElementIterator previous and next for the whole set of
+ * unicode characters with normalization on.
+ */
+static void TestNormalizedUnicodeChar()
+{
+ UChar source[0x100];
+ UCollator *th_th;
+ UCollationElements *iter;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar codepoint;
+
+ UChar *test;
+ /* thai should have normalization on */
+ th_th = ucol_open("th_TH", &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: in creation of thai collation using ucol_open()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ for (codepoint = 1; codepoint < 0xFFFE;)
+ {
+ test = source;
+
+ while (codepoint % 0xFF != 0)
+ {
+ if (u_isdefined(codepoint))
+ *(test ++) = codepoint;
+ codepoint ++;
+ }
+
+ if (u_isdefined(codepoint))
+ *(test ++) = codepoint;
+
+ if (codepoint != 0xFFFF)
+ codepoint ++;
+
+ *test = 0;
+ iter=ucol_openElements(th_th, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(th_th);
+ return;
+ }
+
+ backAndForth(iter);
+ ucol_closeElements(iter);
+
+ iter=ucol_openElements(th_th, source, -1, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(th_th);
+ return;
+ }
+
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ }
+
+ ucol_close(th_th);
+}
+
+/**
+* Test the incremental normalization
+*/
+static void TestNormalization()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ const char *str =
+ "&a < \\u0300\\u0315 < A\\u0300\\u0315 < \\u0316\\u0315B < \\u0316\\u0300\\u0315";
+ UCollator *coll;
+ UChar rule[50];
+ int rulelen = u_unescape(str, rule, 50);
+ int count = 0;
+ const char *testdata[] =
+ {"\\u1ED9", "o\\u0323\\u0302",
+ "\\u0300\\u0315", "\\u0315\\u0300",
+ "A\\u0300\\u0315B", "A\\u0315\\u0300B",
+ "A\\u0316\\u0315B", "A\\u0315\\u0316B",
+ "\\u0316\\u0300\\u0315", "\\u0315\\u0300\\u0316",
+ "A\\u0316\\u0300\\u0315B", "A\\u0315\\u0300\\u0316B",
+ "\\u0316\\u0315\\u0300", "A\\u0316\\u0315\\u0300B"};
+ int32_t srclen;
+ UChar source[10];
+ UCollationElements *iter;
+
+ coll = ucol_openRules(rule, rulelen, UCOL_ON, UCOL_TERTIARY, NULL, &status);
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: in creation of collator using ucol_openRules()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ srclen = u_unescape(testdata[0], source, 10);
+ iter = ucol_openElements(coll, source, srclen, &status);
+ backAndForth(iter);
+ ucol_closeElements(iter);
+
+ srclen = u_unescape(testdata[1], source, 10);
+ iter = ucol_openElements(coll, source, srclen, &status);
+ backAndForth(iter);
+ ucol_closeElements(iter);
+
+ while (count < 12) {
+ srclen = u_unescape(testdata[count], source, 10);
+ iter = ucol_openElements(coll, source, srclen, &status);
+
+ if (U_FAILURE(status)){
+ log_err("ERROR: in creation of collator element iterator\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+
+ iter = ucol_openElements(coll, source, -1, &status);
+
+ if (U_FAILURE(status)){
+ log_err("ERROR: in creation of collator element iterator\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ count ++;
+ }
+ ucol_close(coll);
+}
+
+/**
+ * Test for CollationElementIterator.previous()
+ *
+ * @bug 4108758 - Make sure it works with contracting characters
+ *
+ */
+static void TestPrevious()
+{
+ UCollator *coll=NULL;
+ UChar rule[50];
+ UChar *source;
+ UCollator *c1, *c2, *c3;
+ UCollationElements *iter;
+ UErrorCode status = U_ZERO_ERROR;
+
+ test1=(UChar*)malloc(sizeof(UChar) * 50);
+ test2=(UChar*)malloc(sizeof(UChar) * 50);
+ u_uastrcpy(test1, "What subset of all possible test cases?");
+ u_uastrcpy(test2, "has the highest probability of detecting");
+ coll = ucol_open("en_US", &status);
+
+ iter=ucol_openElements(coll, test1, u_strlen(test1), &status);
+ log_verbose("English locale testing back and forth\n");
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(coll);
+ return;
+ }
+ /* A basic test to see if it's working at all */
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(coll);
+
+ /* Test with a contracting character sequence */
+ u_uastrcpy(rule, "&a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH");
+ c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+
+ log_verbose("Contraction rule testing back and forth with no normalization\n");
+
+ if (c1 == NULL || U_FAILURE(status))
+ {
+ log_err("Couldn't create a RuleBasedCollator with a contracting sequence\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ source=(UChar*)malloc(sizeof(UChar) * 20);
+ u_uastrcpy(source, "abchdcba");
+ iter=ucol_openElements(c1, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(c1);
+
+ /* Test with an expanding character sequence */
+ u_uastrcpy(rule, "&a < b < c/abd < d");
+ c2 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
+ log_verbose("Expansion rule testing back and forth with no normalization\n");
+ if (c2 == NULL || U_FAILURE(status))
+ {
+ log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ u_uastrcpy(source, "abcd");
+ iter=ucol_openElements(c2, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(c2);
+ /* Now try both */
+ u_uastrcpy(rule, "&a < b < c/aba < d < z < ch");
+ c3 = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH,NULL, &status);
+ log_verbose("Expansion/contraction rule testing back and forth with no normalization\n");
+
+ if (c3 == NULL || U_FAILURE(status))
+ {
+ log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ u_uastrcpy(source, "abcdbchdc");
+ iter=ucol_openElements(c3, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(c3);
+ source[0] = 0x0e41;
+ source[1] = 0x0e02;
+ source[2] = 0x0e41;
+ source[3] = 0x0e02;
+ source[4] = 0x0e27;
+ source[5] = 0x61;
+ source[6] = 0x62;
+ source[7] = 0x63;
+ source[8] = 0;
+
+ coll = ucol_open("th_TH", &status);
+ log_verbose("Thai locale testing back and forth with normalization\n");
+ iter=ucol_openElements(coll, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(coll);
+
+ /* prev test */
+ source[0] = 0x0061;
+ source[1] = 0x30CF;
+ source[2] = 0x3099;
+ source[3] = 0x30FC;
+ source[4] = 0;
+
+ coll = ucol_open("ja_JP", &status);
+ log_verbose("Japanese locale testing back and forth with normalization\n");
+ iter=ucol_openElements(coll, source, u_strlen(source), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ ucol_close(coll);
+
+ free(source);
+ free(test1);
+ free(test2);
+}
+
+/**
+ * Test for getOffset() and setOffset()
+ */
+static void TestOffset()
+{
+ UErrorCode status= U_ZERO_ERROR;
+ UCollator *en_us=NULL;
+ UCollationElements *iter, *pristine;
+ int32_t offset;
+ int32_t *orders;
+ int32_t orderLength=0;
+ int count = 0;
+ test1=(UChar*)malloc(sizeof(UChar) * 50);
+ test2=(UChar*)malloc(sizeof(UChar) * 50);
+ u_uastrcpy(test1, "What subset of all possible test cases?");
+ u_uastrcpy(test2, "has the highest probability of detecting");
+ en_us = ucol_open("en_US", &status);
+ log_verbose("Testing getOffset and setOffset for collations\n");
+ iter = ucol_openElements(en_us, test1, u_strlen(test1), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+
+ /* testing boundaries */
+ ucol_setOffset(iter, 0, &status);
+ if (U_FAILURE(status) || ucol_previous(iter, &status) != UCOL_NULLORDER) {
+ log_err("Error: After setting offset to 0, we should be at the end "
+ "of the backwards iteration");
+ }
+ ucol_setOffset(iter, u_strlen(test1), &status);
+ if (U_FAILURE(status) || ucol_next(iter, &status) != UCOL_NULLORDER) {
+ log_err("Error: After setting offset to end of the string, we should "
+ "be at the end of the backwards iteration");
+ }
+
+ /* Run all the way through the iterator, then get the offset */
+
+ orders = getOrders(iter, &orderLength);
+
+ offset = ucol_getOffset(iter);
+
+ if (offset != u_strlen(test1))
+ {
+ log_err("offset at end != length %d vs %d\n", offset,
+ u_strlen(test1) );
+ }
+
+ /* Now set the offset back to the beginning and see if it works */
+ pristine=ucol_openElements(en_us, test1, u_strlen(test1), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+ status = U_ZERO_ERROR;
+
+ ucol_setOffset(iter, 0, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("setOffset failed. %s\n", myErrorName(status));
+ }
+ else
+ {
+ assertEqual(iter, pristine);
+ }
+
+ ucol_closeElements(pristine);
+ ucol_closeElements(iter);
+ free(orders);
+
+ /* testing offsets in normalization buffer */
+ test1[0] = 0x61;
+ test1[1] = 0x300;
+ test1[2] = 0x316;
+ test1[3] = 0x62;
+ test1[4] = 0;
+ ucol_setAttribute(en_us, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ iter = ucol_openElements(en_us, test1, 4, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+
+ count = 0;
+ while (ucol_next(iter, &status) != UCOL_NULLORDER &&
+ U_SUCCESS(status)) {
+ switch (count) {
+ case 0:
+ if (ucol_getOffset(iter) != 1) {
+ log_err("ERROR: Offset of iteration should be 0\n");
+ }
+ break;
+ case 3:
+ if (ucol_getOffset(iter) != 4) {
+ log_err("ERROR: Offset of iteration should be 4\n");
+ }
+ break;
+ default:
+ if (ucol_getOffset(iter) != 3) {
+ log_err("ERROR: Offset of iteration should be 3\n");
+ }
+ }
+ count ++;
+ }
+
+ ucol_reset(iter);
+ count = 0;
+ while (ucol_previous(iter, &status) != UCOL_NULLORDER &&
+ U_SUCCESS(status)) {
+ switch (count) {
+ case 0:
+ if (ucol_getOffset(iter) != 3) {
+ log_err("ERROR: Offset of iteration should be 3\n");
+ }
+ break;
+ default:
+ if (ucol_getOffset(iter) != 0) {
+ log_err("ERROR: Offset of iteration should be 0\n");
+ }
+ }
+ count ++;
+ }
+
+ if(U_FAILURE(status)){
+ log_err("ERROR: in iterating collation elements %s\n",
+ myErrorName(status));
+ }
+
+ ucol_closeElements(iter);
+ ucol_close(en_us);
+ free(test1);
+ free(test2);
+}
+
+/**
+ * Test for setText()
+ */
+static void TestSetText()
+{
+ int32_t c,i;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *en_us=NULL;
+ UCollationElements *iter1, *iter2;
+ test1=(UChar*)malloc(sizeof(UChar) * 50);
+ test2=(UChar*)malloc(sizeof(UChar) * 50);
+ u_uastrcpy(test1, "What subset of all possible test cases?");
+ u_uastrcpy(test2, "has the highest probability of detecting");
+ en_us = ucol_open("en_US", &status);
+ log_verbose("testing setText for Collation elements\n");
+ iter1=ucol_openElements(en_us, test1, u_strlen(test1), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator1 using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+ iter2=ucol_openElements(en_us, test2, u_strlen(test2), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of collation element iterator2 using ucol_openElements()\n %s\n",
+ myErrorName(status));
+ ucol_close(en_us);
+ return;
+ }
+
+ /* Run through the second iterator just to exercise it */
+ c = ucol_next(iter2, &status);
+ i = 0;
+
+ while ( ++i < 10 && (c != UCOL_NULLORDER))
+ {
+ if (U_FAILURE(status))
+ {
+ log_err("iter2->next() returned an error. %s\n", myErrorName(status));
+ ucol_closeElements(iter2);
+ ucol_closeElements(iter1);
+ ucol_close(en_us);
+ return;
+ }
+
+ c = ucol_next(iter2, &status);
+ }
+
+ /* Now set it to point to the same string as the first iterator */
+ ucol_setText(iter2, test1, u_strlen(test1), &status);
+ if (U_FAILURE(status))
+ {
+ log_err("call to iter2->setText(test1) failed. %s\n", myErrorName(status));
+ }
+ else
+ {
+ assertEqual(iter1, iter2);
+ }
+
+ /* Now set it to point to a null string with fake length*/
+ ucol_setText(iter2, NULL, 2, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("call to iter2->setText(null) failed. %s\n", myErrorName(status));
+ }
+ else
+ {
+ if (ucol_next(iter2, &status) != UCOL_NULLORDER) {
+ log_err("iter2 with null text expected to return UCOL_NULLORDER\n");
+ }
+ }
+
+ ucol_closeElements(iter2);
+ ucol_closeElements(iter1);
+ ucol_close(en_us);
+ free(test1);
+ free(test2);
+}
+
+/** @bug 4108762
+ * Test for getMaxExpansion()
+ */
+static void TestMaxExpansion()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll ;/*= ucol_open("en_US", &status);*/
+ UChar ch = 0;
+ UChar32 unassigned = 0xEFFFD;
+ UChar supplementary[2];
+ uint32_t index = 0;
+ UBool isError = FALSE;
+ uint32_t sorder = 0;
+ UCollationElements *iter ;/*= ucol_openElements(coll, &ch, 1, &status);*/
+ uint32_t temporder = 0;
+
+ UChar rule[256];
+ u_uastrcpy(rule, "&a < ab < c/aba < d < z < ch");
+ coll = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT,
+ UCOL_DEFAULT_STRENGTH,NULL, &status);
+ if(U_SUCCESS(status) && coll) {
+ iter = ucol_openElements(coll, &ch, 1, &status);
+
+ while (ch < 0xFFFF && U_SUCCESS(status)) {
+ int count = 1;
+ uint32_t order;
+ int32_t size = 0;
+
+ ch ++;
+
+ ucol_setText(iter, &ch, 1, &status);
+ order = ucol_previous(iter, &status);
+
+ /* thai management */
+ if (order == 0)
+ order = ucol_previous(iter, &status);
+
+ while (U_SUCCESS(status) &&
+ ucol_previous(iter, &status) != UCOL_NULLORDER) {
+ count ++;
+ }
+
+ size = ucol_getMaxExpansion(iter, order);
+ if (U_FAILURE(status) || size < count) {
+ log_err("Failure at codepoint %d, maximum expansion count < %d\n",
+ ch, count);
+ }
+ }
+
+ /* testing for exact max expansion */
+ ch = 0;
+ while (ch < 0x61) {
+ uint32_t order;
+ int32_t size;
+ ucol_setText(iter, &ch, 1, &status);
+ order = ucol_previous(iter, &status);
+ size = ucol_getMaxExpansion(iter, order);
+ if (U_FAILURE(status) || size != 1) {
+ log_err("Failure at codepoint %d, maximum expansion count < %d\n",
+ ch, 1);
+ }
+ ch ++;
+ }
+
+ ch = 0x63;
+ ucol_setText(iter, &ch, 1, &status);
+ temporder = ucol_previous(iter, &status);
+
+ if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 3) {
+ log_err("Failure at codepoint %d, maximum expansion count != %d\n",
+ ch, 3);
+ }
+
+ ch = 0x64;
+ ucol_setText(iter, &ch, 1, &status);
+ temporder = ucol_previous(iter, &status);
+
+ if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 1) {
+ log_err("Failure at codepoint %d, maximum expansion count != %d\n",
+ ch, 3);
+ }
+
+ U16_APPEND(supplementary, index, 2, unassigned, isError);
+ ucol_setText(iter, supplementary, 2, &status);
+ sorder = ucol_previous(iter, &status);
+
+ if (U_FAILURE(status) || ucol_getMaxExpansion(iter, sorder) != 2) {
+ log_err("Failure at codepoint %d, maximum expansion count < %d\n",
+ ch, 2);
+ }
+
+ /* testing jamo */
+ ch = 0x1165;
+
+ ucol_setText(iter, &ch, 1, &status);
+ temporder = ucol_previous(iter, &status);
+ if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) > 3) {
+ log_err("Failure at codepoint %d, maximum expansion count > %d\n",
+ ch, 3);
+ }
+
+ ucol_closeElements(iter);
+ ucol_close(coll);
+
+ /* testing special jamo &a<\u1160 */
+ rule[0] = 0x26;
+ rule[1] = 0x71;
+ rule[2] = 0x3c;
+ rule[3] = 0x1165;
+ rule[4] = 0x2f;
+ rule[5] = 0x71;
+ rule[6] = 0x71;
+ rule[7] = 0x71;
+ rule[8] = 0x71;
+ rule[9] = 0;
+
+ coll = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT,
+ UCOL_DEFAULT_STRENGTH,NULL, &status);
+ iter = ucol_openElements(coll, &ch, 1, &status);
+
+ temporder = ucol_previous(iter, &status);
+ if (U_FAILURE(status) || ucol_getMaxExpansion(iter, temporder) != 6) {
+ log_err("Failure at codepoint %d, maximum expansion count > %d\n",
+ ch, 5);
+ }
+
+ ucol_closeElements(iter);
+ ucol_close(coll);
+ } else {
+ log_data_err("Couldn't open collator\n");
+ }
+
+}
+
+
+static void assertEqual(UCollationElements *i1, UCollationElements *i2)
+{
+ int32_t c1, c2;
+ int32_t count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ do
+ {
+ c1 = ucol_next(i1, &status);
+ c2 = ucol_next(i2, &status);
+
+ if (c1 != c2)
+ {
+ log_err("Error in iteration %d assetEqual between\n %d and %d, they are not equal\n", count, c1, c2);
+ break;
+ }
+
+ count += 1;
+ }
+ while (c1 != UCOL_NULLORDER);
+}
+
+/**
+ * Testing iterators with extremely small buffers
+ */
+static void TestSmallBuffer()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll;
+ UCollationElements *testiter,
+ *iter;
+ int32_t count = 0;
+ int32_t *testorders,
+ *orders;
+
+ UChar teststr[500];
+ UChar str[] = {0x300, 0x31A, 0};
+ /*
+ creating a long string of decomposable characters,
+ since by default the writable buffer is of size 256
+ */
+ while (count < 500) {
+ if ((count & 1) == 0) {
+ teststr[count ++] = 0x300;
+ }
+ else {
+ teststr[count ++] = 0x31A;
+ }
+ }
+
+ coll = ucol_open("th_TH", &status);
+ if(U_SUCCESS(status) && coll) {
+ testiter = ucol_openElements(coll, teststr, 500, &status);
+ iter = ucol_openElements(coll, str, 2, &status);
+
+ orders = getOrders(iter, &count);
+ if (count != 2) {
+ log_err("Error collation elements size is not 2 for \\u0300\\u031A\n");
+ }
+
+ /*
+ this will rearrange the string data to 250 characters of 0x300 first then
+ 250 characters of 0x031A
+ */
+ testorders = getOrders(testiter, &count);
+
+ if (count != 500) {
+ log_err("Error decomposition does not give the right sized collation elements\n");
+ }
+
+ while (count != 0) {
+ /* UCA collation element for 0x0F76 */
+ if ((count > 250 && testorders[-- count] != orders[1]) ||
+ (count <= 250 && testorders[-- count] != orders[0])) {
+ log_err("Error decomposition does not give the right collation element at %d count\n", count);
+ break;
+ }
+ }
+
+ free(testorders);
+ free(orders);
+
+ ucol_reset(testiter);
+ /* ensures that the writable buffer was cleared */
+ if (testiter->iteratordata_.writableBuffer !=
+ testiter->iteratordata_.stackWritableBuffer) {
+ log_err("Error Writable buffer in collation element iterator not reset\n");
+ }
+
+ /* ensures closing of elements done properly to clear writable buffer */
+ ucol_next(testiter, &status);
+ ucol_next(testiter, &status);
+ ucol_closeElements(testiter);
+ ucol_closeElements(iter);
+ ucol_close(coll);
+ } else {
+ log_data_err("Couldn't open collator\n");
+ }
+}
+
+/**
+* Sniplets of code from genuca
+*/
+static int32_t hex2num(char hex) {
+ if(hex>='0' && hex <='9') {
+ return hex-'0';
+ } else if(hex>='a' && hex<='f') {
+ return hex-'a'+10;
+ } else if(hex>='A' && hex<='F') {
+ return hex-'A'+10;
+ } else {
+ return 0;
+ }
+}
+
+/**
+* Getting codepoints from a string
+* @param str character string contain codepoints seperated by space and ended
+* by a semicolon
+* @param codepoints array for storage, assuming size > 5
+* @return position at the end of the codepoint section
+*/
+static char * getCodePoints(char *str, UChar *codepoints) {
+ char *pStartCP = str;
+ char *pEndCP = str + 4;
+
+ *codepoints = (UChar)((hex2num(*pStartCP) << 12) |
+ (hex2num(*(pStartCP + 1)) << 8) |
+ (hex2num(*(pStartCP + 2)) << 4) |
+ (hex2num(*(pStartCP + 3))));
+ codepoints ++;
+ while (*pEndCP != ';') {
+ pStartCP = pEndCP + 1;
+ *codepoints = (UChar)((hex2num(*pStartCP) << 12) |
+ (hex2num(*(pStartCP + 1)) << 8) |
+ (hex2num(*(pStartCP + 2)) << 4) |
+ (hex2num(*(pStartCP + 3))));
+ codepoints ++;
+ pEndCP = pStartCP + 4;
+ }
+ *codepoints = 0;
+ return pEndCP + 1;
+}
+
+/**
+* Sniplets of code from genuca
+*/
+static int32_t
+readElement(char **from, char *to, char separator, UErrorCode *status)
+{
+ if (U_SUCCESS(*status)) {
+ char buffer[1024];
+ int32_t i = 0;
+ while (**from != separator) {
+ if (**from != ' ') {
+ *(buffer+i++) = **from;
+ }
+ (*from)++;
+ }
+ (*from)++;
+ *(buffer + i) = 0;
+ strcpy(to, buffer);
+ return i/2;
+ }
+
+ return 0;
+}
+
+/**
+* Sniplets of code from genuca
+*/
+static uint32_t
+getSingleCEValue(char *primary, char *secondary, char *tertiary,
+ UErrorCode *status)
+{
+ if (U_SUCCESS(*status)) {
+ uint32_t value = 0;
+ char primsave = '\0';
+ char secsave = '\0';
+ char tersave = '\0';
+ char *primend = primary+4;
+ char *secend = secondary+2;
+ char *terend = tertiary+2;
+ uint32_t primvalue;
+ uint32_t secvalue;
+ uint32_t tervalue;
+
+ if (uprv_strlen(primary) > 4) {
+ primsave = *primend;
+ *primend = '\0';
+ }
+
+ if (uprv_strlen(secondary) > 2) {
+ secsave = *secend;
+ *secend = '\0';
+ }
+
+ if (uprv_strlen(tertiary) > 2) {
+ tersave = *terend;
+ *terend = '\0';
+ }
+
+ primvalue = (*primary!='\0')?uprv_strtoul(primary, &primend, 16):0;
+ secvalue = (*secondary!='\0')?uprv_strtoul(secondary, &secend, 16):0;
+ tervalue = (*tertiary!='\0')?uprv_strtoul(tertiary, &terend, 16):0;
+ if(primvalue <= 0xFF) {
+ primvalue <<= 8;
+ }
+
+ value = ((primvalue << UCOL_PRIMARYORDERSHIFT) & UCOL_PRIMARYORDERMASK)
+ | ((secvalue << UCOL_SECONDARYORDERSHIFT) & UCOL_SECONDARYORDERMASK)
+ | (tervalue & UCOL_TERTIARYORDERMASK);
+
+ if(primsave!='\0') {
+ *primend = primsave;
+ }
+ if(secsave!='\0') {
+ *secend = secsave;
+ }
+ if(tersave!='\0') {
+ *terend = tersave;
+ }
+ return value;
+ }
+ return 0;
+}
+
+/**
+* Getting collation elements generated from a string
+* @param str character string contain collation elements contained in [] and
+* seperated by space
+* @param ce array for storage, assuming size > 20
+* @param status error status
+* @return position at the end of the codepoint section
+*/
+static char * getCEs(char *str, uint32_t *ces, UErrorCode *status) {
+ char *pStartCP = uprv_strchr(str, '[');
+ int count = 0;
+ char *pEndCP;
+ char primary[100];
+ char secondary[100];
+ char tertiary[100];
+
+ while (*pStartCP == '[') {
+ uint32_t primarycount = 0;
+ uint32_t secondarycount = 0;
+ uint32_t tertiarycount = 0;
+ uint32_t CEi = 1;
+ pEndCP = strchr(pStartCP, ']');
+ if(pEndCP == NULL) {
+ break;
+ }
+ pStartCP ++;
+
+ primarycount = readElement(&pStartCP, primary, ',', status);
+ secondarycount = readElement(&pStartCP, secondary, ',', status);
+ tertiarycount = readElement(&pStartCP, tertiary, ']', status);
+
+ /* I want to get the CEs entered right here, including continuation */
+ ces[count ++] = getSingleCEValue(primary, secondary, tertiary, status);
+ if (U_FAILURE(*status)) {
+ break;
+ }
+
+ while (2 * CEi < primarycount || CEi < secondarycount ||
+ CEi < tertiarycount) {
+ uint32_t value = UCOL_CONTINUATION_MARKER; /* Continuation marker */
+ if (2 * CEi < primarycount) {
+ value |= ((hex2num(*(primary + 4 * CEi)) & 0xF) << 28);
+ value |= ((hex2num(*(primary + 4 * CEi + 1)) & 0xF) << 24);
+ }
+
+ if (2 * CEi + 1 < primarycount) {
+ value |= ((hex2num(*(primary + 4 * CEi + 2)) & 0xF) << 20);
+ value |= ((hex2num(*(primary + 4 * CEi + 3)) &0xF) << 16);
+ }
+
+ if (CEi < secondarycount) {
+ value |= ((hex2num(*(secondary + 2 * CEi)) & 0xF) << 12);
+ value |= ((hex2num(*(secondary + 2 * CEi + 1)) & 0xF) << 8);
+ }
+
+ if (CEi < tertiarycount) {
+ value |= ((hex2num(*(tertiary + 2 * CEi)) & 0x3) << 4);
+ value |= (hex2num(*(tertiary + 2 * CEi + 1)) & 0xF);
+ }
+
+ CEi ++;
+ ces[count ++] = value;
+ }
+
+ pStartCP = pEndCP + 1;
+ }
+ ces[count] = 0;
+ return pStartCP;
+}
+
+/**
+* Getting the FractionalUCA.txt file stream
+*/
+static FileStream * getFractionalUCA(void)
+{
+ char newPath[256];
+ char backupPath[256];
+ FileStream *result = NULL;
+
+ /* Look inside ICU_DATA first */
+ uprv_strcpy(newPath, ctest_dataSrcDir());
+ uprv_strcat(newPath, "unidata" U_FILE_SEP_STRING );
+ uprv_strcat(newPath, "FractionalUCA.txt");
+
+ /* As a fallback, try to guess where the source data was located
+ * at the time ICU was built, and look there.
+ */
+#if defined (U_TOPSRCDIR)
+ strcpy(backupPath, U_TOPSRCDIR U_FILE_SEP_STRING "data");
+#else
+ {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ strcpy(backupPath, loadTestData(&errorCode));
+ strcat(backupPath, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data");
+ }
+#endif
+ strcat(backupPath, U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING "FractionalUCA.txt");
+
+ result = T_FileStream_open(newPath, "rb");
+
+ if (result == NULL) {
+ result = T_FileStream_open(backupPath, "rb");
+ if (result == NULL) {
+ log_err("Failed to open either %s or %s\n", newPath, backupPath);
+ }
+ }
+ return result;
+}
+
+/**
+* Testing the CEs returned by the iterator
+*/
+static void TestCEs() {
+ FileStream *file = NULL;
+ char line[1024];
+ char *str;
+ UChar codepoints[5];
+ uint32_t ces[20];
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("", &status);
+ uint32_t lineNo = 0;
+
+ if (U_FAILURE(status)) {
+ log_err("Error in opening root collator\n");
+ return;
+ }
+
+ file = getFractionalUCA();
+
+ if (file == NULL) {
+ log_err("*** unable to open input FractionalUCA.txt file ***\n");
+ return;
+ }
+
+
+ while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) {
+ int count = 0;
+ UCollationElements *iter;
+ lineNo++;
+ /* skip this line if it is empty or a comment or is a return value
+ or start of some variable section */
+ if(line[0] == 0 || line[0] == '#' || line[0] == '\n' ||
+ line[0] == 0x000D || line[0] == '[') {
+ continue;
+ }
+
+ str = getCodePoints(line, codepoints);
+
+ /* these are 'fake' codepoints in the fractional UCA, and are used just
+ * for positioning of indirect values. They should not go through this
+ * test.
+ */
+ if(*codepoints == 0xFDD0) {
+ continue;
+ }
+
+ getCEs(str, ces, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error in parsing collation elements in FractionalUCA.txt\n");
+ break;
+ }
+ iter = ucol_openElements(coll, codepoints, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error in opening collation elements\n");
+ break;
+ }
+ for (;;) {
+ uint32_t ce = (uint32_t)ucol_next(iter, &status);
+ if (ce == 0xFFFFFFFF) {
+ ce = 0;
+ }
+ /* we now unconditionally reorder Thai/Lao prevowels, so this
+ * test would fail if we don't skip here.
+ */
+ if(UCOL_ISTHAIPREVOWEL(*codepoints) && ce == 0 && count == 0) {
+ continue;
+ }
+ if (ce != ces[count] || U_FAILURE(status)) {
+ log_err("Collation elements in FractionalUCA.txt and iterators do not match!\n");
+ break;
+ }
+ if (ces[count] == 0) {
+ break;
+ }
+ count ++;
+ }
+ ucol_closeElements(iter);
+ }
+
+ T_FileStream_close(file);
+ ucol_close(coll);
+}
+
+/**
+* Testing the discontigous contractions
+*/
+static void TestDiscontiguos() {
+ const char *rulestr =
+ "&z < AB < X\\u0300 < ABC < X\\u0300\\u0315";
+ UChar rule[50];
+ int rulelen = u_unescape(rulestr, rule, 50);
+ const char *src[] = {
+ "ADB", "ADBC", "A\\u0315B", "A\\u0315BC",
+ /* base character blocked */
+ "XD\\u0300", "XD\\u0300\\u0315",
+ /* non blocking combining character */
+ "X\\u0319\\u0300", "X\\u0319\\u0300\\u0315",
+ /* blocking combining character */
+ "X\\u0314\\u0300", "X\\u0314\\u0300\\u0315",
+ /* contraction prefix */
+ "ABDC", "AB\\u0315C","X\\u0300D\\u0315", "X\\u0300\\u0319\\u0315",
+ "X\\u0300\\u031A\\u0315",
+ /* ends not with a contraction character */
+ "X\\u0319\\u0300D", "X\\u0319\\u0300\\u0315D", "X\\u0300D\\u0315D",
+ "X\\u0300\\u0319\\u0315D", "X\\u0300\\u031A\\u0315D"
+ };
+ const char *tgt[] = {
+ /* non blocking combining character */
+ "A D B", "A D BC", "A \\u0315 B", "A \\u0315 BC",
+ /* base character blocked */
+ "X D \\u0300", "X D \\u0300\\u0315",
+ /* non blocking combining character */
+ "X\\u0300 \\u0319", "X\\u0300\\u0315 \\u0319",
+ /* blocking combining character */
+ "X \\u0314 \\u0300", "X \\u0314 \\u0300\\u0315",
+ /* contraction prefix */
+ "AB DC", "AB \\u0315 C","X\\u0300 D \\u0315", "X\\u0300\\u0315 \\u0319",
+ "X\\u0300 \\u031A \\u0315",
+ /* ends not with a contraction character */
+ "X\\u0300 \\u0319D", "X\\u0300\\u0315 \\u0319D", "X\\u0300 D\\u0315D",
+ "X\\u0300\\u0315 \\u0319D", "X\\u0300 \\u031A\\u0315D"
+ };
+ int size = 20;
+ UCollator *coll;
+ UErrorCode status = U_ZERO_ERROR;
+ int count = 0;
+ UCollationElements *iter;
+ UCollationElements *resultiter;
+
+ coll = ucol_openRules(rule, rulelen, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+ iter = ucol_openElements(coll, rule, 1, &status);
+ resultiter = ucol_openElements(coll, rule, 1, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Error opening collation rules\n");
+ return;
+ }
+
+ while (count < size) {
+ UChar str[20];
+ UChar tstr[20];
+ int strLen = u_unescape(src[count], str, 20);
+ UChar *s;
+
+ ucol_setText(iter, str, strLen, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening collation iterator\n");
+ return;
+ }
+
+ u_unescape(tgt[count], tstr, 20);
+ s = tstr;
+
+ log_verbose("count %d\n", count);
+
+ for (;;) {
+ uint32_t ce;
+ UChar *e = u_strchr(s, 0x20);
+ if (e == 0) {
+ e = u_strchr(s, 0);
+ }
+ ucol_setText(resultiter, s, (int32_t)(e - s), &status);
+ ce = ucol_next(resultiter, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error manipulating collation iterator\n");
+ return;
+ }
+ while (ce != UCOL_NULLORDER) {
+ if (ce != (uint32_t)ucol_next(iter, &status) ||
+ U_FAILURE(status)) {
+ log_err("Discontiguos contraction test mismatch\n");
+ return;
+ }
+ ce = ucol_next(resultiter, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error getting next collation element\n");
+ return;
+ }
+ }
+ s = e + 1;
+ if (*e == 0) {
+ break;
+ }
+ }
+ ucol_reset(iter);
+ backAndForth(iter);
+ count ++;
+ }
+ ucol_closeElements(resultiter);
+ ucol_closeElements(iter);
+ ucol_close(coll);
+}
+
+static void TestCEBufferOverflow()
+{
+ UChar str[UCOL_EXPAND_CE_BUFFER_SIZE + 1];
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rule[10];
+ UCollator *coll;
+ UCollationElements *iter;
+
+ u_uastrcpy(rule, "&z < AB");
+ coll = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL,&status);
+ if (U_FAILURE(status)) {
+ log_err("Rule based collator not created for testing ce buffer overflow\n");
+ return;
+ }
+
+ /* 0xDCDC is a trail surrogate hence deemed unsafe by the heuristic
+ test. this will cause an overflow in getPrev */
+ str[0] = 0x0041; /* 'A' */
+ /*uprv_memset(str + 1, 0xE0, sizeof(UChar) * UCOL_EXPAND_CE_BUFFER_SIZE);*/
+ uprv_memset(str + 1, 0xDC, sizeof(UChar) * UCOL_EXPAND_CE_BUFFER_SIZE);
+ str[UCOL_EXPAND_CE_BUFFER_SIZE] = 0x0042; /* 'B' */
+ iter = ucol_openElements(coll, str, UCOL_EXPAND_CE_BUFFER_SIZE + 1,
+ &status);
+ if (ucol_previous(iter, &status) != UCOL_NULLORDER ||
+ status != U_BUFFER_OVERFLOW_ERROR) {
+ log_err("CE buffer expected to overflow with long string of trail surrogates\n");
+ }
+ ucol_closeElements(iter);
+ ucol_close(coll);
+}
+
+/**
+* Byte bounds checks. Checks if each byte in data is between upper and lower
+* inclusive.
+*/
+static UBool checkByteBounds(uint32_t data, char upper, char lower)
+{
+ int count = 4;
+ while (count > 0) {
+ char b = (char)(data & 0xFF);
+ if (b > upper || b < lower) {
+ return FALSE;
+ }
+ data = data >> 8;
+ count --;
+ }
+ return TRUE;
+}
+
+/**
+* Determines case of the string of codepoints.
+* If it is a multiple codepoints it has to treated as a contraction.
+*/
+#if 0
+static uint8_t getCase(const UChar *s, uint32_t len) {
+ UBool lower = FALSE;
+ UBool upper = FALSE;
+ UBool title = FALSE;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar str[256];
+ const UChar *ps = s;
+
+ if (len == 0) {
+ return UCOL_LOWER_CASE;
+ }
+
+ while (len > 0) {
+ UChar c = *ps ++;
+
+ if (u_islower(c)) {
+ lower = TRUE;
+ }
+ if (u_isupper(c)) {
+ upper = TRUE;
+ }
+ if (u_istitle(c)) {
+ title = TRUE;
+ }
+
+ len --;
+ }
+ if ((lower && !upper && !title) || (!lower && !upper && !title)){
+ return UCOL_LOWER_CASE;
+ }
+ if (upper && !lower && !title) {
+ return UCOL_UPPER_CASE;
+ }
+ /* mix of cases here */
+ /* len = unorm_normalize(s, len, UNORM_NFKD, 0, str, 256, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error normalizing data string\n");
+ return UCOL_LOWER_CASE;
+ }*/
+
+ if ((title && len >= 2) || (lower && upper)) {
+ return UCOL_MIXED_CASE;
+ }
+ if (u_isupper(s[0])) {
+ return UCOL_UPPER_CASE;
+ }
+ return UCOL_LOWER_CASE;
+}
+#endif
+
+/**
+* Checking collation element validity given the boundary arguments.
+*/
+static UBool checkCEValidity(const UCollator *coll, const UChar *codepoints,
+ int length, uint32_t primarymax,
+ uint32_t secondarymax)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationElements *iter = ucol_openElements(coll, codepoints, length,
+ &status);
+ uint32_t ce;
+ UBool first = TRUE;
+/*
+ UBool upper = FALSE;
+ UBool lower = FALSE;
+*/
+
+ if (U_FAILURE(status)) {
+ log_err("Error creating iterator for testing validity\n");
+ }
+
+ ce = ucol_next(iter, &status);
+
+ while (ce != UCOL_NULLORDER) {
+ if (ce != 0) {
+ uint32_t primary = UCOL_PRIMARYORDER(ce);
+ uint32_t secondary = UCOL_SECONDARYORDER(ce);
+ uint32_t tertiary = UCOL_TERTIARYORDER(ce);
+/* uint32_t scasebits = tertiary & 0xC0;*/
+
+ if ((tertiary == 0 && secondary != 0) ||
+ (tertiary < 0xC0 && secondary == 0 && primary != 0)) {
+ /* n-1th level is not zero when the nth level is
+ except for continuations, this is wrong */
+ log_err("Lower level weight not 0 when high level weight is 0\n");
+ goto fail;
+ }
+ else {
+ /* checks if any byte is illegal ie = 01 02 03. */
+ if (checkByteBounds(ce, 0x3, 0x1)) {
+ log_err("Byte range in CE lies in illegal bounds 0x1 - 0x3\n");
+ goto fail;
+ }
+ }
+ if ((primary != 0 && primary < primarymax)
+ || ((primary & 0xFF) == 0xFF) || (((primary>>8) & 0xFF) == 0xFF)
+ || ((primary & 0xFF) && ((primary & 0xFF) <= 0x03))
+ || (((primary>>8) & 0xFF) && ((primary>>8) & 0xFF) <= 0x03)
+ || (primary >= 0xFE00 && !isContinuation(ce))) {
+ log_err("UCA primary weight out of bounds: %04X for string starting with %04X\n",
+ primary, codepoints[0]);
+ goto fail;
+ }
+ /* case matching not done since data generated by ken */
+ if (first) {
+ if (secondary >= 6 && secondary <= secondarymax) {
+ log_err("Secondary weight out of range\n");
+ goto fail;
+ }
+ first = FALSE;
+ }
+ }
+ ce = ucol_next(iter, &status);
+ }
+ ucol_closeElements(iter);
+ return TRUE;
+fail :
+ ucol_closeElements(iter);
+ return FALSE;
+}
+
+static void TestCEValidity()
+{
+ /* testing UCA collation elements */
+ UErrorCode status = U_ZERO_ERROR;
+ /* en_US has no tailorings */
+ UCollator *coll = ucol_open("root", &status);
+ /* tailored locales */
+ char locale[][11] = {"fr_FR", "ko_KR", "sh_YU", "th_TH", "zh_CN", "zh__PINYIN"};
+ const char *loc;
+ FileStream *file = getFractionalUCA();
+ char line[1024];
+ UChar codepoints[10];
+ int count = 0;
+ int maxCount = 0;
+ UParseError parseError;
+ if (U_FAILURE(status)) {
+ log_err("en_US collator creation failed\n");
+ return;
+ }
+ log_verbose("Testing UCA elements\n");
+ if (file == NULL) {
+ log_err("Fractional UCA data can not be opened\n");
+ return;
+ }
+
+ while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) {
+ if(line[0] == 0 || line[0] == '#' || line[0] == '\n' ||
+ line[0] == 0x000D || line[0] == '[') {
+ continue;
+ }
+
+ getCodePoints(line, codepoints);
+ checkCEValidity(coll, codepoints, u_strlen(codepoints), 5, 86);
+ }
+
+ log_verbose("Testing UCA elements for the whole range of unicode characters\n");
+ codepoints[0] = 0;
+ while (codepoints[0] < 0xFFFF) {
+ if (u_isdefined((UChar32)codepoints[0])) {
+ checkCEValidity(coll, codepoints, 1, 5, 86);
+ }
+ codepoints[0] ++;
+ }
+
+ ucol_close(coll);
+
+ /* testing tailored collation elements */
+ log_verbose("Testing tailored elements\n");
+ if(QUICK) {
+ maxCount = sizeof(locale)/sizeof(locale[0]);
+ } else {
+ maxCount = uloc_countAvailable();
+ }
+ while (count < maxCount) {
+ const UChar *rules = NULL,
+ *current = NULL;
+ UChar *rulesCopy = NULL;
+ int32_t ruleLen = 0;
+
+ uint32_t chOffset = 0;
+ uint32_t chLen = 0;
+ uint32_t exOffset = 0;
+ uint32_t exLen = 0;
+ uint32_t prefixOffset = 0;
+ uint32_t prefixLen = 0;
+ UBool startOfRules = TRUE;
+ UColOptionSet opts;
+
+ UColTokenParser src;
+ uint32_t strength = 0;
+ uint16_t specs = 0;
+ if(QUICK) {
+ loc = locale[count];
+ } else {
+ loc = uloc_getAvailable(count);
+ if(!hasCollationElements(loc)) {
+ count++;
+ continue;
+ }
+ }
+
+ log_verbose("Testing CEs for %s\n", loc);
+
+ coll = ucol_open(loc, &status);
+ if (U_FAILURE(status)) {
+ log_err("%s collator creation failed\n", loc);
+ return;
+ }
+
+ src.opts = &opts;
+ rules = ucol_getRules(coll, &ruleLen);
+
+ if (ruleLen > 0) {
+ rulesCopy = (UChar *)malloc((ruleLen +
+ UCOL_TOK_EXTRA_RULE_SPACE_SIZE) * sizeof(UChar));
+ uprv_memcpy(rulesCopy, rules, ruleLen * sizeof(UChar));
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy + ruleLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end + UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,&status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ uprv_memcpy(codepoints, src.source + chOffset,
+ chLen * sizeof(UChar));
+ codepoints[chLen] = 0;
+ checkCEValidity(coll, codepoints, chLen, 4, 85);
+ }
+ free(rulesCopy);
+ }
+
+ ucol_close(coll);
+ count ++;
+ }
+ T_FileStream_close(file);
+}
+
+static void printSortKeyError(const UChar *codepoints, int length,
+ uint8_t *sortkey, int sklen)
+{
+ int count = 0;
+ log_err("Sortkey not valid for ");
+ while (length > 0) {
+ log_err("0x%04x ", *codepoints);
+ length --;
+ codepoints ++;
+ }
+ log_err("\nSortkey : ");
+ while (count < sklen) {
+ log_err("0x%02x ", sortkey[count]);
+ count ++;
+ }
+ log_err("\n");
+}
+
+/**
+* Checking sort key validity for all levels
+*/
+static UBool checkSortKeyValidity(UCollator *coll,
+ const UChar *codepoints,
+ int length)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationStrength strength[5] = {UCOL_PRIMARY, UCOL_SECONDARY,
+ UCOL_TERTIARY, UCOL_QUATERNARY,
+ UCOL_IDENTICAL};
+ int strengthlen = 5;
+ int index = 0;
+ int caselevel = 0;
+
+ while (caselevel < 1) {
+ if (caselevel == 0) {
+ ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_OFF, &status);
+ }
+ else {
+ ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &status);
+ }
+
+ while (index < strengthlen) {
+ int count01 = 0;
+ uint32_t count = 0;
+ uint8_t sortkey[128];
+ uint32_t sklen;
+
+ ucol_setStrength(coll, strength[index]);
+ sklen = ucol_getSortKey(coll, codepoints, length, sortkey, 128);
+ while (sortkey[count] != 0) {
+ if (sortkey[count] == 2 || (sortkey[count] == 3 && count01 > 0 && index != 4)) {
+ printSortKeyError(codepoints, length, sortkey, sklen);
+ return FALSE;
+ }
+ if (sortkey[count] == 1) {
+ count01 ++;
+ }
+ count ++;
+ }
+
+ if (count + 1 != sklen || (count01 != index + caselevel)) {
+ printSortKeyError(codepoints, length, sortkey, sklen);
+ return FALSE;
+ }
+ index ++;
+ }
+ caselevel ++;
+ }
+ return TRUE;
+}
+
+static void TestSortKeyValidity(void)
+{
+ /* testing UCA collation elements */
+ UErrorCode status = U_ZERO_ERROR;
+ /* en_US has no tailorings */
+ UCollator *coll = ucol_open("en_US", &status);
+ /* tailored locales */
+ char locale[][6] = {"fr_FR", "ko_KR", "sh_YU", "th_TH", "zh_CN"};
+ FileStream *file = getFractionalUCA();
+ char line[1024];
+ UChar codepoints[10];
+ int count = 0;
+ UParseError parseError;
+ if (U_FAILURE(status)) {
+ log_err("en_US collator creation failed\n");
+ return;
+ }
+ log_verbose("Testing UCA elements\n");
+ if (file == NULL) {
+ log_err("Fractional UCA data can not be opened\n");
+ return;
+ }
+
+ while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) {
+ if(line[0] == 0 || line[0] == '#' || line[0] == '\n' ||
+ line[0] == 0x000D || line[0] == '[') {
+ continue;
+ }
+
+ getCodePoints(line, codepoints);
+ checkSortKeyValidity(coll, codepoints, u_strlen(codepoints));
+ }
+
+ log_verbose("Testing UCA elements for the whole range of unicode characters\n");
+ codepoints[0] = 0;
+
+ while (codepoints[0] < 0xFFFF) {
+ if (u_isdefined((UChar32)codepoints[0])) {
+ checkSortKeyValidity(coll, codepoints, 1);
+ }
+ codepoints[0] ++;
+ }
+
+ ucol_close(coll);
+
+ /* testing tailored collation elements */
+ log_verbose("Testing tailored elements\n");
+ while (count < 5) {
+ const UChar *rules = NULL,
+ *current = NULL;
+ UChar *rulesCopy = NULL;
+ int32_t ruleLen = 0;
+
+ uint32_t chOffset = 0;
+ uint32_t chLen = 0;
+ uint32_t exOffset = 0;
+ uint32_t exLen = 0;
+ uint32_t prefixOffset = 0;
+ uint32_t prefixLen = 0;
+ UBool startOfRules = TRUE;
+ UColOptionSet opts;
+
+ UColTokenParser src;
+ uint32_t strength = 0;
+ uint16_t specs = 0;
+
+ coll = ucol_open(locale[count], &status);
+ if (U_FAILURE(status)) {
+ log_err("%s collator creation failed\n", locale[count]);
+ return;
+ }
+
+ src.opts = &opts;
+ rules = ucol_getRules(coll, &ruleLen);
+
+ if (ruleLen > 0) {
+ rulesCopy = (UChar *)malloc((ruleLen +
+ UCOL_TOK_EXTRA_RULE_SPACE_SIZE) * sizeof(UChar));
+ uprv_memcpy(rulesCopy, rules, ruleLen * sizeof(UChar));
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy + ruleLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end + UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules,&parseError, &status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ uprv_memcpy(codepoints, src.source + chOffset,
+ chLen * sizeof(UChar));
+ codepoints[chLen] = 0;
+ checkSortKeyValidity(coll, codepoints, chLen);
+ }
+ free(rulesCopy);
+ }
+
+ ucol_close(coll);
+ count ++;
+ }
+ T_FileStream_close(file);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h
new file mode 100644
index 00000000000..b810131c898
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/citertst.h
@@ -0,0 +1,118 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CITERTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+
+/**
+ * Collation Iterator tests.
+ * (Let me reiterate my position...)
+ */
+
+#ifndef _CITERCOLLTST
+#define _CITERCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/ucoleitr.h"
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+
+ /**
+ * Test for CollationElementIterator previous and next for the whole set of
+ * unicode characters.
+ */
+ static void TestUnicodeChar(void);
+ /**
+ * Test for CollationElementIterator previous and next for the whole set of
+ * unicode characters with normalization on.
+ */
+ static void TestNormalizedUnicodeChar(void);
+ /**
+ * Test incremental normalization
+ */
+ static void TestNormalization(void);
+ /**
+ * Test for CollationElementIterator.previous()
+ *
+ * @bug 4108758 - Make sure it works with contracting characters
+ *
+ */
+ static void TestPrevious(void);
+
+ /**
+ * Test for getOffset() and setOffset()
+ */
+ static void TestOffset(void);
+ /**
+ * Test for setText()
+ */
+ static void TestSetText(void);
+ /** @bug 4108762
+ * Test for getMaxExpansion()
+ */
+ static void TestMaxExpansion(void);
+ /**
+ * Test Bug 672, where different locales give a different offset after
+ * a previous for the same string at the same position
+ */
+ static void TestBug672(void);
+
+ /**
+ * Repeat TestBug672 with normalizatin enabled - this test revealed a bug
+ * in incremental normalization.
+ */
+ static void TestBug672Normalize(void);
+ /**
+ * Test iterators with an relatively small buffer
+ */
+ static void TestSmallBuffer(void);
+ /**
+ * Tests the CEs generated by the iterators.
+ */
+ static void TestCEs(void);
+ /**
+ * Tests the discontiguos contractions
+ */
+ static void TestDiscontiguos(void);
+ /**
+ * Tests that the iterators bails out when the CEBuffer is exhausted
+ */
+ static void TestCEBufferOverflow(void);
+ /**
+ * Tests the validity of CEs generated by the iterators.
+ * Bound checkings.
+ */
+ static void TestCEValidity(void);
+ /**
+ * Tests the validity of sortkeys generated by the iterators.
+ * Bound checkings.
+ */
+ static void TestSortKeyValidity(void);
+
+ /*------------------------------------------------------------------------
+ Internal utilities
+ */
+
+
+ static void assertEqual(UCollationElements *i1, UCollationElements *i2);
+
+
+ static UChar *test1;
+ static UChar *test2;
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c
new file mode 100644
index 00000000000..7318e07cb93
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.c
@@ -0,0 +1,255 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CJAPTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+* synwee Added TestBase, TestPlainDakutenHandakuten,
+* TestSmallLarge, TestKatakanaHiragana,
+* TestChooonKigoo
+*********************************************************************************/
+/**
+ * CollationKannaTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "cjaptst.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {0xff9E, 0x0000},
+ {0x3042, 0x0000},
+ {0x30A2, 0x0000},
+ {0x3042, 0x3042, 0x0000},
+ {0x30A2, 0x30FC, 0x0000},
+ {0x30A2, 0x30FC, 0x30C8, 0x0000} /* 6 */
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {0xFF9F, 0x0000},
+ {0x30A2, 0x0000},
+ {0x3042, 0x3042, 0x0000},
+ {0x30A2, 0x30FC, 0x0000},
+ {0x30A2, 0x30FC, 0x30C8, 0x0000},
+ {0x3042, 0x3042, 0x3068, 0x0000} /* 6 */
+};
+
+const static UCollationResult results[] = {
+ UCOL_LESS,
+ UCOL_EQUAL, /*UCOL_LESS*/ /* Katakanas and Hiraganas are equal on tertiary level(ICU 2.0)*/
+ UCOL_LESS,
+ UCOL_GREATER, /*UCOL_LESS*/ /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/
+ UCOL_LESS,
+ UCOL_LESS, /*UCOL_GREATER*/ /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*//* 6 */
+};
+
+const static UChar testBaseCases[][MAX_TOKEN_LEN] = {
+ {0x30AB, 0x0000},
+ {0x30AB, 0x30AD, 0x0000},
+ {0x30AD, 0x0000},
+ {0x30AD, 0x30AD, 0x0000}
+};
+
+const static UChar testPlainDakutenHandakutenCases[][MAX_TOKEN_LEN] = {
+ {0x30CF, 0x30AB, 0x0000},
+ {0x30D0, 0x30AB, 0x0000},
+ {0x30CF, 0x30AD, 0x0000},
+ {0x30D0, 0x30AD, 0x0000}
+};
+
+const static UChar testSmallLargeCases[][MAX_TOKEN_LEN] = {
+ {0x30C3, 0x30CF, 0x0000},
+ {0x30C4, 0x30CF, 0x0000},
+ {0x30C3, 0x30D0, 0x0000},
+ {0x30C4, 0x30D0, 0x0000}
+};
+
+const static UChar testKatakanaHiraganaCases[][MAX_TOKEN_LEN] = {
+ {0x3042, 0x30C3, 0x0000},
+ {0x30A2, 0x30C3, 0x0000},
+ {0x3042, 0x30C4, 0x0000},
+ {0x30A2, 0x30C4, 0x0000}
+};
+
+const static UChar testChooonKigooCases[][MAX_TOKEN_LEN] = {
+ /*0*/ {0x30AB, 0x30FC, 0x3042, 0x0000},
+ /*1*/ {0x30AB, 0x30FC, 0x30A2, 0x0000},
+ /*2*/ {0x30AB, 0x30A4, 0x3042, 0x0000},
+ /*3*/ {0x30AB, 0x30A4, 0x30A2, 0x0000},
+ /*6*/ {0x30AD, 0x30FC, 0x3042, 0x0000}, /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/
+ /*7*/ {0x30AD, 0x30FC, 0x30A2, 0x0000}, /* Prolonged sound mark sorts BEFORE equivalent vowel (ICU 2.0)*/
+ /*4*/ {0x30AD, 0x30A4, 0x3042, 0x0000},
+ /*5*/ {0x30AD, 0x30A4, 0x30A2, 0x0000},
+};
+
+void addKannaCollTest(TestNode** root)
+{
+ addTest(root, &TestTertiary, "tscoll/cjacoll/TestTertiary");
+ addTest(root, &TestBase, "tscoll/cjacoll/TestBase");
+ addTest(root, &TestPlainDakutenHandakuten, "tscoll/cjacoll/TestPlainDakutenHandakuten");
+ addTest(root, &TestSmallLarge, "tscoll/cjacoll/TestSmallLarge");
+ addTest(root, &TestKatakanaHiragana, "tscoll/cjacoll/TestKatakanaHiragana");
+ addTest(root, &TestChooonKigoo, "tscoll/cjacoll/TestChooonKigoo");
+}
+
+static void TestTertiary( )
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing Kanna(Japan) Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status);
+ for (i = 0; i < 6 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+/* Testing base letters */
+static void TestBase()
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("ERROR: in creation of rule based collator: %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing Japanese Base Characters Collation\n");
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ for (i = 0; i < 3 ; i++)
+ doTest(myCollation, testBaseCases[i], testBaseCases[i + 1], UCOL_LESS);
+
+ ucol_close(myCollation);
+}
+
+/* Testing plain, Daku-ten, Handaku-ten letters */
+static void TestPlainDakutenHandakuten(void)
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("ERROR: in creation of rule based collator: %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing plain, Daku-ten, Handaku-ten letters Japanese Characters Collation\n");
+ ucol_setStrength(myCollation, UCOL_SECONDARY);
+ for (i = 0; i < 3 ; i++)
+ doTest(myCollation, testPlainDakutenHandakutenCases[i],
+ testPlainDakutenHandakutenCases[i + 1], UCOL_LESS);
+
+ ucol_close(myCollation);
+}
+
+/*
+* Test Small, Large letters
+*/
+static void TestSmallLarge(void)
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("ERROR: in creation of rule based collator: %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing Japanese Small and Large Characters Collation\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status);
+ for (i = 0; i < 3 ; i++)
+ doTest(myCollation, testSmallLargeCases[i], testSmallLargeCases[i + 1],
+ UCOL_LESS);
+
+ ucol_close(myCollation);
+}
+
+/*
+* Test Katakana, Hiragana letters
+*/
+static void TestKatakanaHiragana(void)
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("ERROR: in creation of rule based collator: %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing Japanese Katakana, Hiragana Characters Collation\n");
+ ucol_setStrength(myCollation, UCOL_QUATERNARY);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status);
+ for (i = 0; i < 3 ; i++) {
+ doTest(myCollation, testKatakanaHiraganaCases[i],
+ testKatakanaHiraganaCases[i + 1], UCOL_LESS);
+ }
+
+ ucol_close(myCollation);
+}
+
+/*
+* Test Choo-on kigoo
+*/
+static void TestChooonKigoo(void)
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("ja_JP", &status);
+ if (U_FAILURE(status))
+ {
+ log_err("ERROR: in creation of rule based collator: %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing Japanese Choo-on Kigoo Characters Collation\n");
+ ucol_setAttribute(myCollation, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, UCOL_ON, &status);
+ for (i = 0; i < 7 ; i++) {
+ doTest(myCollation, testChooonKigooCases[i], testChooonKigooCases[i + 1],
+ UCOL_LESS);
+ }
+
+ ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h
new file mode 100644
index 00000000000..311976b706b
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cjaptst.h
@@ -0,0 +1,63 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CJAPTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+* synwee Added TestBase, TestPlainDakutenHandakuten,
+* TestSmallLarge, TestKatakanaHiragana,
+* TestChooonKigoo
+*********************************************************************************/
+/**
+ * CollationKannaTest(JAPAN) is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CJACOLLTST
+#define _CJACOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+
+#define MAX_TOKEN_LEN 16
+
+
+ /*perform test with strength TERTIARY*/
+static void TestTertiary(void);
+
+/* Testing base letters */
+static void TestBase(void);
+
+/* Testing plain, Daku-ten, Handaku-ten letters */
+static void TestPlainDakutenHandakuten(void);
+
+/*
+* Test Small, Large letters
+*/
+static void TestSmallLarge(void);
+
+/*
+* Test Katakana, Hiragana letters
+*/
+static void TestKatakanaHiragana(void);
+
+/*
+* Test Choo-on kigoo
+*/
+static void TestChooonKigoo(void);
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c
new file mode 100644
index 00000000000..b7ba4fe9b98
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cldrtest.c
@@ -0,0 +1,1294 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+#include "cintltst.h"
+#include "unicode/ures.h"
+#include "unicode/ucurr.h"
+#include "unicode/ustring.h"
+#include "unicode/uset.h"
+#include "unicode/udat.h"
+#include "unicode/uscript.h"
+#include "unicode/ulocdata.h"
+#include "cstring.h"
+#include "locmap.h"
+#include "uresimp.h"
+
+/*--------------------------------------------------------------------
+ Time bomb - allows temporary behavior that expires at a given
+ release
+ ---------------------------------------------------------------------*/
+static const UVersionInfo ICU_37 = {3,7,0,0};
+
+/*
+returns a new UnicodeSet that is a flattened form of the original
+UnicodeSet.
+*/
+static USet*
+createFlattenSet(USet *origSet, UErrorCode *status) {
+
+
+ USet *newSet = NULL;
+ int32_t origItemCount = 0;
+ int32_t idx, graphmeSize;
+ UChar32 start, end;
+ UChar graphme[64];
+ if (U_FAILURE(*status)) {
+ log_err("createFlattenSet called with %s\n", u_errorName(*status));
+ return NULL;
+ }
+ newSet = uset_open(1, 0);
+ origItemCount = uset_getItemCount(origSet);
+ for (idx = 0; idx < origItemCount; idx++) {
+ graphmeSize = uset_getItem(origSet, idx,
+ &start, &end,
+ graphme, (int32_t)(sizeof(graphme)/sizeof(graphme[0])),
+ status);
+ if (U_FAILURE(*status)) {
+ log_err("ERROR: uset_getItem returned %s\n", u_errorName(*status));
+ *status = U_ZERO_ERROR;
+ }
+ if (graphmeSize) {
+ uset_addAllCodePoints(newSet, graphme, graphmeSize);
+ }
+ else {
+ uset_addRange(newSet, start, end);
+ }
+ }
+ return newSet;
+}
+static UBool
+isCurrencyPreEuro(const char* currencyKey){
+ if( strcmp(currencyKey, "PTE") == 0 ||
+ strcmp(currencyKey, "ESP") == 0 ||
+ strcmp(currencyKey, "LUF") == 0 ||
+ strcmp(currencyKey, "GRD") == 0 ||
+ strcmp(currencyKey, "BEF") == 0 ||
+ strcmp(currencyKey, "ITL") == 0 ||
+ strcmp(currencyKey, "EEK") == 0){
+ return TRUE;
+ }
+ return FALSE;
+}
+static void
+TestKeyInRootRecursive(UResourceBundle *root, const char *rootName,
+ UResourceBundle *currentBundle, const char *locale) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UResourceBundle *subRootBundle = NULL, *subBundle = NULL;
+
+ ures_resetIterator(root);
+ ures_resetIterator(currentBundle);
+ while (ures_hasNext(currentBundle)) {
+ const char *subBundleKey = NULL;
+ const char *currentBundleKey = NULL;
+
+ errorCode = U_ZERO_ERROR;
+ currentBundleKey = ures_getKey(currentBundle);
+ subBundle = ures_getNextResource(currentBundle, NULL, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("Can't open a resource for locale %s. Error: %s\n", locale, u_errorName(errorCode));
+ continue;
+ }
+ subBundleKey = ures_getKey(subBundle);
+
+
+ subRootBundle = ures_getByKey(root, subBundleKey, NULL, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("Can't open a resource with key \"%s\" in \"%s\" from %s for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ rootName,
+ locale);
+ ures_close(subBundle);
+ continue;
+ }
+ if (ures_getType(subRootBundle) != ures_getType(subBundle)) {
+ log_err("key \"%s\" in \"%s\" has a different type from root for locale \"%s\"\n"
+ "\troot=%d, locale=%d\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale,
+ ures_getType(subRootBundle),
+ ures_getType(subBundle));
+ ures_close(subBundle);
+ continue;
+ }
+ else if (ures_getType(subBundle) == URES_INT_VECTOR) {
+ int32_t minSize;
+ int32_t subBundleSize;
+ int32_t idx;
+ UBool sameArray = TRUE;
+ const int32_t *subRootBundleArr = ures_getIntVector(subRootBundle, &minSize, &errorCode);
+ const int32_t *subBundleArr = ures_getIntVector(subBundle, &subBundleSize, &errorCode);
+
+ if (minSize > subBundleSize) {
+ minSize = subBundleSize;
+ log_err("Arrays are different size with key \"%s\" in \"%s\" from root for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ }
+
+ for (idx = 0; idx < minSize && sameArray; idx++) {
+ if (subRootBundleArr[idx] != subBundleArr[idx]) {
+ sameArray = FALSE;
+ }
+ if (strcmp(subBundleKey, "DateTimeElements") == 0
+ && (subBundleArr[idx] < 1 || 7 < subBundleArr[idx]))
+ {
+ log_err("Value out of range with key \"%s\" at index %d in \"%s\" for locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ }
+ /* Special exception es_US and DateTimeElements */
+ if (sameArray
+ && !(strcmp(locale, "es_US") == 0 && strcmp(subBundleKey, "DateTimeElements") == 0))
+ {
+ log_err("Integer vectors are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ }
+ else if (ures_getType(subBundle) == URES_ARRAY) {
+ UResourceBundle *subSubBundle = ures_getByIndex(subBundle, 0, NULL, &errorCode);
+ UResourceBundle *subSubRootBundle = ures_getByIndex(subRootBundle, 0, NULL, &errorCode);
+
+ if (U_SUCCESS(errorCode)
+ && (ures_getType(subSubBundle) == URES_ARRAY || ures_getType(subSubRootBundle) == URES_ARRAY))
+ {
+ /* Here is one of the recursive parts */
+ TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale);
+ }
+ else {
+ int32_t minSize = ures_getSize(subRootBundle);
+ int32_t idx;
+ UBool sameArray = TRUE;
+
+ if (minSize > ures_getSize(subBundle)) {
+ minSize = ures_getSize(subBundle);
+ }
+
+ if ((subBundleKey == NULL
+ || (subBundleKey != NULL && strcmp(subBundleKey, "LocaleScript") != 0 && !isCurrencyPreEuro(subBundleKey)))
+ && ures_getSize(subRootBundle) != ures_getSize(subBundle))
+ {
+ log_err("Different size array with key \"%s\" in \"%s\" from root for locale \"%s\"\n"
+ "\troot array size=%d, locale array size=%d\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale,
+ ures_getSize(subRootBundle),
+ ures_getSize(subBundle));
+ }
+ /*
+ if(isCurrencyPreEuro(subBundleKey) && ures_getSize(subBundle)!=3){
+ log_err("Different size array with key \"%s\" in \"%s\" for locale \"%s\" the expected size is 3 got size=%d\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale,
+ ures_getSize(subBundle));
+ }
+ */
+ for (idx = 0; idx < minSize; idx++) {
+ int32_t rootStrLen, localeStrLen;
+ const UChar *rootStr = ures_getStringByIndex(subRootBundle,idx,&rootStrLen,&errorCode);
+ const UChar *localeStr = ures_getStringByIndex(subBundle,idx,&localeStrLen,&errorCode);
+ if (rootStr && localeStr && U_SUCCESS(errorCode)) {
+ if (u_strcmp(rootStr, localeStr) != 0) {
+ sameArray = FALSE;
+ }
+ }
+ else {
+ log_err("Got a NULL string with key \"%s\" in \"%s\" at index %d for root or locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ idx,
+ locale);
+ continue;
+ }
+ if (localeStr[0] == (UChar)0x20) {
+ log_err("key \"%s\" at index %d in \"%s\" starts with a space in locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ else if (localeStr[localeStrLen - 1] == (UChar)0x20) {
+ log_err("key \"%s\" at index %d in \"%s\" ends with a space in locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ else if (subBundleKey != NULL
+ && strcmp(subBundleKey, "DateTimePatterns") == 0)
+ {
+ int32_t quoted = 0;
+ const UChar *localeStrItr = localeStr;
+ while (*localeStrItr) {
+ if (*localeStrItr == (UChar)0x27 /* ' */) {
+ quoted++;
+ }
+ else if ((quoted % 2) == 0) {
+ /* Search for unquoted characters */
+ if (4 <= idx && idx <= 7
+ && (*localeStrItr == (UChar)0x6B /* k */
+ || *localeStrItr == (UChar)0x48 /* H */
+ || *localeStrItr == (UChar)0x6D /* m */
+ || *localeStrItr == (UChar)0x73 /* s */
+ || *localeStrItr == (UChar)0x53 /* S */
+ || *localeStrItr == (UChar)0x61 /* a */
+ || *localeStrItr == (UChar)0x68 /* h */
+ || *localeStrItr == (UChar)0x7A /* z */))
+ {
+ log_err("key \"%s\" at index %d has time pattern chars in date for locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ locale);
+ }
+ else if (0 <= idx && idx <= 3
+ && (*localeStrItr == (UChar)0x47 /* G */
+ || *localeStrItr == (UChar)0x79 /* y */
+ || *localeStrItr == (UChar)0x4D /* M */
+ || *localeStrItr == (UChar)0x64 /* d */
+ || *localeStrItr == (UChar)0x45 /* E */
+ || *localeStrItr == (UChar)0x44 /* D */
+ || *localeStrItr == (UChar)0x46 /* F */
+ || *localeStrItr == (UChar)0x77 /* w */
+ || *localeStrItr == (UChar)0x57 /* W */))
+ {
+ log_err("key \"%s\" at index %d has date pattern chars in time for locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ locale);
+ }
+ }
+ localeStrItr++;
+ }
+ }
+ else if (idx == 4 && subBundleKey != NULL
+ && strcmp(subBundleKey, "NumberElements") == 0
+ && u_charDigitValue(localeStr[0]) != 0)
+ {
+ log_err("key \"%s\" at index %d has a non-zero based number for locale \"%s\"\n",
+ subBundleKey,
+ idx,
+ locale);
+ }
+ }
+/* if (sameArray && strcmp(rootName, "root") == 0) {
+ log_err("Arrays are the same with key \"%s\" in \"%s\" from root for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ }*/
+ }
+ ures_close(subSubBundle);
+ ures_close(subSubRootBundle);
+ }
+ else if (ures_getType(subBundle) == URES_STRING) {
+ int32_t len = 0;
+ const UChar *string = ures_getString(subBundle, &len, &errorCode);
+ if (U_FAILURE(errorCode) || string == NULL) {
+ log_err("Can't open a string with key \"%s\" in \"%s\" for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ } else if (string[0] == (UChar)0x20) {
+ log_err("key \"%s\" in \"%s\" starts with a space in locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ } else if (string[len - 1] == (UChar)0x20) {
+ log_err("key \"%s\" in \"%s\" ends with a space in locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ } else if (strcmp(subBundleKey, "localPatternChars") == 0) {
+ /* Note: We no longer import localPatternChars data starting
+ * ICU 3.8. So it never comes into this else if block. (ticket#5597)
+ */
+
+ /* Check well-formedness of localPatternChars. First, the
+ * length must match the number of fields defined by
+ * DateFormat. Second, each character in the string must
+ * be in the set [A-Za-z]. Finally, each character must be
+ * unique.
+ */
+ int32_t i,j;
+#if !UCONFIG_NO_FORMATTING
+ if (len != UDAT_FIELD_COUNT) {
+ log_err("key \"%s\" has the wrong number of characters in locale \"%s\"\n",
+ subBundleKey,
+ locale);
+ }
+#endif
+ /* Check char validity. */
+ for (i=0; i<len; ++i) {
+ if (!((string[i] >= 65/*'A'*/ && string[i] <= 90/*'Z'*/) ||
+ (string[i] >= 97/*'a'*/ && string[i] <= 122/*'z'*/))) {
+ log_err("key \"%s\" has illegal character '%c' in locale \"%s\"\n",
+ subBundleKey,
+ (char) string[i],
+ locale);
+ }
+ /* Do O(n^2) check for duplicate chars. */
+ for (j=0; j<i; ++j) {
+ if (string[j] == string[i]) {
+ log_err("key \"%s\" has duplicate character '%c' in locale \"%s\"\n",
+ subBundleKey,
+ (char) string[i],
+ locale);
+ }
+ }
+ }
+ }
+ /* No fallback was done. Check for duplicate data */
+ /* The ures_* API does not do fallback of sub-resource bundles,
+ So we can't do this now. */
+#if 0
+ else if (strcmp(locale, "root") != 0 && errorCode == U_ZERO_ERROR) {
+
+ const UChar *rootString = ures_getString(subRootBundle, &len, &errorCode);
+ if (U_FAILURE(errorCode) || rootString == NULL) {
+ log_err("Can't open a string with key \"%s\" in \"%s\" in root\n",
+ ures_getKey(subRootBundle),
+ ures_getKey(currentBundle));
+ continue;
+ } else if (u_strcmp(string, rootString) == 0) {
+ if (strcmp(locale, "de_CH") != 0 && strcmp(subBundleKey, "Countries") != 0 &&
+ strcmp(subBundleKey, "Version") != 0) {
+ log_err("Found duplicate data with key \"%s\" in \"%s\" in locale \"%s\"\n",
+ ures_getKey(subRootBundle),
+ ures_getKey(currentBundle),
+ locale);
+ }
+ else {
+ /* Ignore for now. */
+ /* Can be fixed if fallback through de locale was done. */
+ log_verbose("Skipping key %s in %s\n", subBundleKey, locale);
+ }
+ }
+ }
+#endif
+ }
+ else if (ures_getType(subBundle) == URES_TABLE) {
+ if (strcmp(subBundleKey, "availableFormats")!=0) {
+ /* Here is one of the recursive parts */
+ TestKeyInRootRecursive(subRootBundle, rootName, subBundle, locale);
+ }
+ else {
+ log_verbose("Skipping key %s in %s\n", subBundleKey, locale);
+ }
+ }
+ else if (ures_getType(subBundle) == URES_BINARY || ures_getType(subBundle) == URES_INT) {
+ /* Can't do anything to check it */
+ /* We'll assume it's all correct */
+ if (strcmp(subBundleKey, "MeasurementSystem") != 0) {
+ log_verbose("Skipping key \"%s\" in \"%s\" for locale \"%s\"\n",
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ /* Testing for MeasurementSystem is done in VerifyTranslation */
+ }
+ else {
+ log_err("Type %d for key \"%s\" in \"%s\" is unknown for locale \"%s\"\n",
+ ures_getType(subBundle),
+ subBundleKey,
+ ures_getKey(currentBundle),
+ locale);
+ }
+ ures_close(subRootBundle);
+ ures_close(subBundle);
+ }
+}
+
+
+static void
+testLCID(UResourceBundle *currentBundle,
+ const char *localeName)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ uint32_t expectedLCID;
+ char lcidStringC[64] = {0};
+
+ expectedLCID = uloc_getLCID(localeName);
+ if (expectedLCID == 0) {
+ log_verbose("INFO: %-5s does not have any LCID mapping\n",
+ localeName);
+ return;
+ }
+
+ status = U_ZERO_ERROR;
+ uprv_strcpy(lcidStringC, uprv_convertToPosix(expectedLCID, &status));
+ if (U_FAILURE(status)) {
+ log_err("ERROR: %.4x does not have a POSIX mapping due to %s\n",
+ expectedLCID, u_errorName(status));
+ }
+
+ if(strcmp(localeName, lcidStringC) != 0) {
+ char langName[1024];
+ char langLCID[1024];
+ uloc_getLanguage(localeName, langName, sizeof(langName), &status);
+ uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status);
+
+ if (strcmp(langName, langLCID) == 0) {
+ log_verbose("WARNING: %-5s resolves to %s (0x%.4x)\n",
+ localeName, lcidStringC, expectedLCID);
+ }
+ else {
+ log_err("ERROR: %-5s has 0x%.4x and the number resolves wrongfully to %s\n",
+ localeName, expectedLCID, lcidStringC);
+ }
+ }
+}
+
+static void
+TestLocaleStructure(void) {
+ UResourceBundle *root, *currentLocale;
+ int32_t locCount = uloc_countAvailable();
+ int32_t locIndex;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ const char *currLoc, *resolvedLoc;
+
+ /* TODO: Compare against parent's data too. This code can't handle fallbacks that some tools do already. */
+/* char locName[ULOC_FULLNAME_CAPACITY];
+ char *locNamePtr;
+
+ for (locIndex = 0; locIndex < locCount; locIndex++) {
+ errorCode=U_ZERO_ERROR;
+ strcpy(locName, uloc_getAvailable(locIndex));
+ locNamePtr = strrchr(locName, '_');
+ if (locNamePtr) {
+ *locNamePtr = 0;
+ }
+ else {
+ strcpy(locName, "root");
+ }
+
+ root = ures_openDirect(NULL, locName, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Can't open %s\n", locName);
+ continue;
+ }
+*/
+ if (locCount <= 1) {
+ log_data_err("At least root needs to be installed\n");
+ }
+
+ root = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Can't open structLocale\n");
+ return;
+ }
+ for (locIndex = 0; locIndex < locCount; locIndex++) {
+ errorCode=U_ZERO_ERROR;
+ currLoc = uloc_getAvailable(locIndex);
+ currentLocale = ures_open(NULL, currLoc, &errorCode);
+ if(errorCode != U_ZERO_ERROR) {
+ if(U_SUCCESS(errorCode)) {
+ /* It's installed, but there is no data.
+ It's installed for the g18n white paper [grhoten] */
+ log_err("ERROR: Locale %-5s not installed, and it should be!\n",
+ uloc_getAvailable(locIndex));
+ } else {
+ log_err("%%%%%%% Unexpected error %d in %s %%%%%%%",
+ u_errorName(errorCode),
+ uloc_getAvailable(locIndex));
+ }
+ ures_close(currentLocale);
+ continue;
+ }
+ ures_getStringByKey(currentLocale, "Version", NULL, &errorCode);
+ if(errorCode != U_ZERO_ERROR) {
+ log_err("No version information is available for locale %s, and it should be!\n",
+ currLoc);
+ }
+ else if (ures_getStringByKey(currentLocale, "Version", NULL, &errorCode)[0] == (UChar)(0x78)) {
+ log_verbose("WARNING: The locale %s is experimental! It shouldn't be listed as an installed locale.\n",
+ currLoc);
+ }
+ resolvedLoc = ures_getLocaleByType(currentLocale, ULOC_ACTUAL_LOCALE, &errorCode);
+ if (strcmp(resolvedLoc, currLoc) != 0) {
+ /* All locales have at least a Version resource.
+ If it's absolutely empty, then the previous test will fail too.*/
+ log_err("Locale resolves to different locale. Is %s an alias of %s?\n",
+ currLoc, resolvedLoc);
+ }
+ TestKeyInRootRecursive(root, "root", currentLocale, currLoc);
+
+ testLCID(currentLocale, currLoc);
+
+ ures_close(currentLocale);
+ }
+
+ ures_close(root);
+}
+
+static void
+compareArrays(const char *keyName,
+ UResourceBundle *fromArray, const char *fromLocale,
+ UResourceBundle *toArray, const char *toLocale,
+ int32_t start, int32_t end)
+{
+ int32_t fromSize = ures_getSize(fromArray);
+ int32_t toSize = ures_getSize(fromArray);
+ int32_t idx;
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ if (fromSize > toSize) {
+ fromSize = toSize;
+ log_err("Arrays are different size from \"%s\" to \"%s\"\n",
+ fromLocale,
+ toLocale);
+ }
+
+ for (idx = start; idx <= end; idx++) {
+ const UChar *fromBundleStr = ures_getStringByIndex(fromArray, idx, NULL, &errorCode);
+ const UChar *toBundleStr = ures_getStringByIndex(toArray, idx, NULL, &errorCode);
+ if (fromBundleStr && toBundleStr && u_strcmp(fromBundleStr, toBundleStr) != 0)
+ {
+ log_err("Difference for %s at index %d from %s= \"%s\" to %s= \"%s\"\n",
+ keyName,
+ idx,
+ fromLocale,
+ austrdup(fromBundleStr),
+ toLocale,
+ austrdup(toBundleStr));
+ }
+ }
+}
+
+static void
+compareConsistentCountryInfo(const char *fromLocale, const char *toLocale) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UResourceBundle *fromDateTimeElements, *toDateTimeElements, *fromWeekendData = NULL, *toWeekendData = NULL;
+ UResourceBundle *fromArray, *toArray;
+ UResourceBundle *fromLocaleBund = ures_open(NULL, fromLocale, &errorCode);
+ UResourceBundle *toLocaleBund = ures_open(NULL, toLocale, &errorCode);
+ UResourceBundle *toCalendar, *fromCalendar, *toGregorian, *fromGregorian;
+
+ if(U_FAILURE(errorCode)) {
+ log_err("Can't open resource bundle %s or %s - %s\n", fromLocale, toLocale, u_errorName(errorCode));
+ return;
+ }
+ fromCalendar = ures_getByKey(fromLocaleBund, "calendar", NULL, &errorCode);
+ fromGregorian = ures_getByKeyWithFallback(fromCalendar, "gregorian", NULL, &errorCode);
+ fromDateTimeElements = ures_getByKeyWithFallback(fromGregorian, "DateTimeElements", NULL, &errorCode);
+
+ toCalendar = ures_getByKey(toLocaleBund, "calendar", NULL, &errorCode);
+ toGregorian = ures_getByKeyWithFallback(toCalendar, "gregorian", NULL, &errorCode);
+ toDateTimeElements = ures_getByKeyWithFallback(toGregorian, "DateTimeElements", NULL, &errorCode);
+
+ if(U_FAILURE(errorCode)){
+ log_err("Did not get DateTimeElements from the bundle %s or %s\n", fromLocale, toLocale);
+ goto cleanup;
+ }
+
+ fromWeekendData = ures_getByKeyWithFallback(fromGregorian, "weekend", NULL, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("Did not get weekend data from the bundle %s to compare against %s\n", fromLocale, toLocale);
+ goto cleanup;
+ }
+ toWeekendData = ures_getByKeyWithFallback(toGregorian, "weekend", NULL, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("Did not get weekend data from the bundle %s to compare against %s\n", toLocale, fromLocale);
+ goto cleanup;
+ }
+
+ if (strcmp(fromLocale, "ar_IN") != 0)
+ {
+ int32_t fromSize;
+ int32_t toSize;
+ int32_t idx;
+ const int32_t *fromBundleArr = ures_getIntVector(fromDateTimeElements, &fromSize, &errorCode);
+ const int32_t *toBundleArr = ures_getIntVector(toDateTimeElements, &toSize, &errorCode);
+
+ if (fromSize > toSize) {
+ fromSize = toSize;
+ log_err("Arrays are different size with key \"DateTimeElements\" from \"%s\" to \"%s\"\n",
+ fromLocale,
+ toLocale);
+ }
+
+ for (idx = 0; idx < fromSize; idx++) {
+ if (fromBundleArr[idx] != toBundleArr[idx]) {
+ log_err("Difference with key \"DateTimeElements\" at index %d from \"%s\" to \"%s\"\n",
+ idx,
+ fromLocale,
+ toLocale);
+ }
+ }
+ }
+
+ /* test for weekend data */
+ {
+ int32_t fromSize;
+ int32_t toSize;
+ int32_t idx;
+ const int32_t *fromBundleArr = ures_getIntVector(fromWeekendData, &fromSize, &errorCode);
+ const int32_t *toBundleArr = ures_getIntVector(toWeekendData, &toSize, &errorCode);
+
+ if (fromSize > toSize) {
+ fromSize = toSize;
+ log_err("Arrays are different size with key \"weekend\" data from \"%s\" to \"%s\"\n",
+ fromLocale,
+ toLocale);
+ }
+
+ for (idx = 0; idx < fromSize; idx++) {
+ if (fromBundleArr[idx] != toBundleArr[idx]) {
+ log_err("Difference with key \"weekend\" data at index %d from \"%s\" to \"%s\"\n",
+ idx,
+ fromLocale,
+ toLocale);
+ }
+ }
+ }
+
+ fromArray = ures_getByKey(fromLocaleBund, "CurrencyElements", NULL, &errorCode);
+ toArray = ures_getByKey(toLocaleBund, "CurrencyElements", NULL, &errorCode);
+ if (strcmp(fromLocale, "en_CA") != 0)
+ {
+ /* The first one is probably localized. */
+ compareArrays("CurrencyElements", fromArray, fromLocale, toArray, toLocale, 1, 2);
+ }
+ ures_close(fromArray);
+ ures_close(toArray);
+
+ fromArray = ures_getByKey(fromLocaleBund, "NumberPatterns", NULL, &errorCode);
+ toArray = ures_getByKey(toLocaleBund, "NumberPatterns", NULL, &errorCode);
+ if (strcmp(fromLocale, "en_CA") != 0)
+ {
+ compareArrays("NumberPatterns", fromArray, fromLocale, toArray, toLocale, 0, 3);
+ }
+ ures_close(fromArray);
+ ures_close(toArray);
+
+ /* Difficult to test properly */
+/*
+ fromArray = ures_getByKey(fromLocaleBund, "DateTimePatterns", NULL, &errorCode);
+ toArray = ures_getByKey(toLocaleBund, "DateTimePatterns", NULL, &errorCode);
+ {
+ compareArrays("DateTimePatterns", fromArray, fromLocale, toArray, toLocale);
+ }
+ ures_close(fromArray);
+ ures_close(toArray);*/
+
+ fromArray = ures_getByKey(fromLocaleBund, "NumberElements", NULL, &errorCode);
+ toArray = ures_getByKey(toLocaleBund, "NumberElements", NULL, &errorCode);
+ if (strcmp(fromLocale, "en_CA") != 0)
+ {
+ compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 0, 3);
+ /* Index 4 is a script based 0 */
+ compareArrays("NumberElements", fromArray, fromLocale, toArray, toLocale, 5, 10);
+ }
+ ures_close(fromArray);
+ ures_close(toArray);
+
+cleanup:
+ ures_close(fromDateTimeElements);
+ ures_close(toDateTimeElements);
+ ures_close(fromWeekendData);
+ ures_close(toWeekendData);
+
+ ures_close(fromCalendar);
+ ures_close(toCalendar);
+ ures_close(fromGregorian);
+ ures_close(toGregorian);
+
+ ures_close(fromLocaleBund);
+ ures_close(toLocaleBund);
+}
+
+static void
+TestConsistentCountryInfo(void) {
+/* UResourceBundle *fromLocale, *toLocale;*/
+ int32_t locCount = uloc_countAvailable();
+ int32_t fromLocIndex, toLocIndex;
+
+ int32_t fromCountryLen, toCountryLen;
+ char fromCountry[ULOC_FULLNAME_CAPACITY], toCountry[ULOC_FULLNAME_CAPACITY];
+
+ int32_t fromVariantLen, toVariantLen;
+ char fromVariant[ULOC_FULLNAME_CAPACITY], toVariant[ULOC_FULLNAME_CAPACITY];
+
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ for (fromLocIndex = 0; fromLocIndex < locCount; fromLocIndex++) {
+ const char *fromLocale = uloc_getAvailable(fromLocIndex);
+
+ errorCode=U_ZERO_ERROR;
+ fromCountryLen = uloc_getCountry(fromLocale, fromCountry, ULOC_FULLNAME_CAPACITY, &errorCode);
+ if (fromCountryLen <= 0) {
+ /* Ignore countryless locales */
+ continue;
+ }
+ fromVariantLen = uloc_getVariant(fromLocale, fromVariant, ULOC_FULLNAME_CAPACITY, &errorCode);
+ if (fromVariantLen > 0) {
+ /* Most variants are ignorable like PREEURO, or collation variants. */
+ continue;
+ }
+ /* Start comparing only after the current index.
+ Previous loop should have already compared fromLocIndex.
+ */
+ for (toLocIndex = fromLocIndex + 1; toLocIndex < locCount; toLocIndex++) {
+ const char *toLocale = uloc_getAvailable(toLocIndex);
+
+ toCountryLen = uloc_getCountry(toLocale, toCountry, ULOC_FULLNAME_CAPACITY, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unknown failure fromLocale=%s toLocale=%s errorCode=%s\n",
+ fromLocale, toLocale, u_errorName(errorCode));
+ continue;
+ }
+
+ if (toCountryLen <= 0) {
+ /* Ignore countryless locales */
+ continue;
+ }
+ toVariantLen = uloc_getVariant(toLocale, toVariant, ULOC_FULLNAME_CAPACITY, &errorCode);
+ if (toVariantLen > 0) {
+ /* Most variants are ignorable like PREEURO, or collation variants. */
+ /* They're a variant for a reason. */
+ continue;
+ }
+ if (strcmp(fromCountry, toCountry) == 0) {
+ log_verbose("comparing fromLocale=%s toLocale=%s\n",
+ fromLocale, toLocale);
+ compareConsistentCountryInfo(fromLocale, toLocale);
+ }
+ }
+ }
+}
+
+static int32_t
+findStringSetMismatch(const char *currLoc, const UChar *string, int32_t langSize,
+ const UChar *exemplarCharacters, int32_t exemplarLen,
+ UBool ignoreNumbers) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ USet *origSet = uset_openPatternOptions(exemplarCharacters, exemplarLen, USET_CASE_INSENSITIVE, &errorCode);
+ USet *exemplarSet = createFlattenSet(origSet, &errorCode);
+ int32_t strIdx;
+ uset_close(origSet);
+ if (U_FAILURE(errorCode)) {
+ log_err("%s: error uset_openPattern returned %s\n", currLoc, u_errorName(errorCode));
+ return -1;
+ }
+
+ for (strIdx = 0; strIdx < langSize; strIdx++) {
+ if (!uset_contains(exemplarSet, string[strIdx])
+ && string[strIdx] != 0x0020 && string[strIdx] != 0x00A0 && string[strIdx] != 0x002e && string[strIdx] != 0x002c && string[strIdx] != 0x002d && string[strIdx] != 0x0027
+ && string[strIdx] != 0x200C && string[strIdx] != 0x200D) {
+ if (!ignoreNumbers || (ignoreNumbers && (string[strIdx] < 0x30 || string[strIdx] > 0x39))) {
+ uset_close(exemplarSet);
+ return strIdx;
+ }
+ }
+ }
+ uset_close(exemplarSet);
+ return -1;
+}
+/* include non-invariant chars */
+static int32_t
+myUCharsToChars(const UChar* us, char* cs, int32_t len){
+ int32_t i=0;
+ for(; i< len; i++){
+ if(us[i] < 0x7f){
+ cs[i] = (char)us[i];
+ }else{
+ return -1;
+ }
+ }
+ return i;
+}
+static void
+findSetMatch( UScriptCode *scriptCodes, int32_t scriptsLen,
+ USet *exemplarSet,
+ const char *locale){
+ USet *scripts[10]= {0};
+ char pattern[256] = { '[', ':', 0x000 };
+ int32_t patternLen;
+ UChar uPattern[256] = {0};
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i;
+
+ /* create the sets with script codes */
+ for(i = 0; i<scriptsLen; i++){
+ strcat(pattern, uscript_getShortName(scriptCodes[i]));
+ strcat(pattern, ":]");
+ patternLen = (int32_t)strlen(pattern);
+ u_charsToUChars(pattern, uPattern, patternLen);
+ scripts[i] = uset_openPattern(uPattern, patternLen, &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create set for patter %s. Error: %s\n", pattern, u_errorName(status));
+ break;
+ }
+ pattern[2] = 0;
+ }
+ if (strcmp(locale, "uk") == 0 || strcmp(locale, "uk_UA") == 0) {
+ /* Special addition. Add the modifying apostrophe, which isn't in Cyrillic. */
+ uset_add(scripts[0], 0x2bc);
+ }
+ if(U_SUCCESS(status)){
+ UBool existsInScript = FALSE;
+ /* iterate over the exemplarSet and ascertain if all
+ * UChars in exemplarSet belong to the scripts returned
+ * by getScript
+ */
+ int32_t count = uset_getItemCount(exemplarSet);
+
+ for( i=0; i < count; i++){
+ UChar32 start = 0;
+ UChar32 end = 0;
+ UChar *str = NULL;
+ int32_t strCapacity = 0;
+
+ strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status);
+ if(U_SUCCESS(status)){
+ int32_t j;
+ if(strCapacity == 0){
+ /* ok the item is a range */
+ for( j = 0; j < scriptsLen; j++){
+ if(uset_containsRange(scripts[j], start, end) == TRUE){
+ existsInScript = TRUE;
+ }
+ }
+ if(existsInScript == FALSE){
+ for( j = 0; j < scriptsLen; j++){
+ UChar toPattern[500]={'\0'};
+ char pat[500]={'\0'};
+ int32_t len = uset_toPattern(scripts[j], toPattern, 500, TRUE, &status);
+ len = myUCharsToChars(toPattern, pat, len);
+ log_err("uset_indexOf(\\u%04X)=%i uset_indexOf(\\u%04X)=%i\n", start, uset_indexOf(scripts[0], start), end, uset_indexOf(scripts[0], end));
+ if(len!=-1){
+ log_err("Pattern: %s\n",pat);
+ }
+ }
+ log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale);
+ }
+ }else{
+ strCapacity++; /* increment for NUL termination */
+ /* allocate the str and call the api again */
+ str = (UChar*) malloc(U_SIZEOF_UCHAR * strCapacity);
+ strCapacity = uset_getItem(exemplarSet, i, &start, &end, str, strCapacity, &status);
+ /* iterate over the scripts and figure out if the string contained is actually
+ * in the script set
+ */
+ for( j = 0; j < scriptsLen; j++){
+ if(uset_containsString(scripts[j],str, strCapacity) == TRUE){
+ existsInScript = TRUE;
+ }
+ }
+ if(existsInScript == FALSE){
+ log_err("ExemplarCharacters and LocaleScript containment test failed for locale %s. \n", locale);
+ }
+ }
+ }
+ }
+
+ }
+
+ /* close the sets */
+ for(i = 0; i<scriptsLen; i++){
+ uset_close(scripts[i]);
+ }
+}
+
+static void VerifyTranslation(void) {
+ UResourceBundle *root, *currentLocale;
+ int32_t locCount = uloc_countAvailable();
+ int32_t locIndex;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t exemplarLen;
+ const UChar *exemplarCharacters;
+ const char *currLoc;
+ UScriptCode scripts[USCRIPT_CODE_LIMIT];
+ int32_t numScripts;
+ int32_t idx;
+ int32_t end;
+ UResourceBundle *resArray;
+
+ if (locCount <= 1) {
+ log_data_err("At least root needs to be installed\n");
+ }
+
+ root = ures_openDirect(NULL, "root", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Can't open root\n");
+ return;
+ }
+ for (locIndex = 0; locIndex < locCount; locIndex++) {
+ errorCode=U_ZERO_ERROR;
+ currLoc = uloc_getAvailable(locIndex);
+ currentLocale = ures_open(NULL, currLoc, &errorCode);
+ if(errorCode != U_ZERO_ERROR) {
+ if(U_SUCCESS(errorCode)) {
+ /* It's installed, but there is no data.
+ It's installed for the g18n white paper [grhoten] */
+ log_err("ERROR: Locale %-5s not installed, and it should be!\n",
+ uloc_getAvailable(locIndex));
+ } else {
+ log_err("%%%%%%% Unexpected error %d in %s %%%%%%%",
+ u_errorName(errorCode),
+ uloc_getAvailable(locIndex));
+ }
+ ures_close(currentLocale);
+ continue;
+ }
+ exemplarCharacters = ures_getStringByKey(currentLocale, "ExemplarCharacters", &exemplarLen, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error ures_getStringByKey returned %s\n", u_errorName(errorCode));
+ }
+ else if (QUICK && exemplarLen > 2048) {
+ log_verbose("skipping test for %s\n", currLoc);
+ }
+ else {
+ UChar langBuffer[128];
+ int32_t langSize;
+ int32_t strIdx;
+ langSize = uloc_getDisplayLanguage(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error uloc_getDisplayLanguage returned %s\n", u_errorName(errorCode));
+ }
+ else {
+ strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE);
+ if (strIdx >= 0) {
+ log_err("getDisplayLanguage(%s) at index %d returned characters not in the exemplar characters.\n",
+ currLoc, strIdx);
+ }
+ }
+ langSize = uloc_getDisplayCountry(currLoc, currLoc, langBuffer, sizeof(langBuffer)/sizeof(langBuffer[0]), &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error uloc_getDisplayCountry returned %s\n", u_errorName(errorCode));
+ }
+ else {
+ strIdx = findStringSetMismatch(currLoc, langBuffer, langSize, exemplarCharacters, exemplarLen, FALSE);
+ if (strIdx >= 0) {
+ log_err("getDisplayCountry(%s) at index %d returned characters not in the exemplar characters.\n",
+ currLoc, strIdx);
+ }
+ }
+ {
+ UResourceBundle* cal = ures_getByKey(currentLocale, "calendar", NULL, &errorCode);
+ UResourceBundle* greg = ures_getByKeyWithFallback(cal, "gregorian", NULL, &errorCode);
+ UResourceBundle* names = ures_getByKeyWithFallback(greg, "dayNames", NULL, &errorCode);
+ UResourceBundle* format = ures_getByKeyWithFallback(names, "format", NULL, &errorCode);
+ resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ log_err("error ures_getByKey returned %s\n", u_errorName(errorCode));
+ }
+ if (QUICK) {
+ end = 1;
+ }
+ else {
+ end = ures_getSize(resArray);
+ }
+
+
+ for (idx = 0; idx < end; idx++) {
+ const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode));
+ continue;
+ }
+ strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE);
+ if (strIdx >= 0) {
+ log_err("getDayNames(%s, %d) at index %d returned characters not in the exemplar characters.\n",
+ currLoc, idx, strIdx);
+ }
+ }
+ ures_close(resArray);
+ ures_close(format);
+ ures_close(names);
+
+ names = ures_getByKeyWithFallback(greg, "monthNames", NULL, &errorCode);
+ format = ures_getByKeyWithFallback(names,"format", NULL, &errorCode);
+ resArray = ures_getByKeyWithFallback(format, "wide", NULL, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error ures_getByKey returned %s\n", u_errorName(errorCode));
+ }
+ if (QUICK) {
+ end = 1;
+ }
+ else {
+ end = ures_getSize(resArray);
+ }
+
+ for (idx = 0; idx < end; idx++) {
+ const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ log_err("error ures_getStringByIndex(%d) returned %s\n", idx, u_errorName(errorCode));
+ continue;
+ }
+ strIdx = findStringSetMismatch(currLoc, fromBundleStr, langSize, exemplarCharacters, exemplarLen, TRUE);
+ if (strIdx >= 0) {
+ log_err("getMonthNames(%s, %d) at index %d returned characters not in the exemplar characters.\n",
+ currLoc, idx, strIdx);
+ }
+ }
+ ures_close(resArray);
+ ures_close(format);
+ ures_close(names);
+ ures_close(greg);
+ ures_close(cal);
+ }
+ errorCode = U_ZERO_ERROR;
+ numScripts = uscript_getCode(currLoc, scripts, sizeof(scripts)/sizeof(scripts[0]), &errorCode);
+ if (numScripts == 0) {
+ log_err("uscript_getCode(%s) doesn't work.\n", currLoc);
+ }else if(scripts[0] == USCRIPT_COMMON){
+ log_err("uscript_getCode(%s) returned USCRIPT_COMMON.\n", currLoc);
+ }
+
+ /* test that the scripts are a superset of exemplar characters. */
+ {
+ ULocaleData *uld = ulocdata_open(currLoc,&errorCode);
+ USet *exemplarSet = ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &errorCode);
+ /* test if exemplar characters are part of script code */
+ findSetMatch(scripts, numScripts, exemplarSet, currLoc);
+ uset_close(exemplarSet);
+ ulocdata_close(uld);
+ }
+
+ /* test that the paperSize API works */
+ {
+ int32_t height=0, width=0;
+ ulocdata_getPaperSize(currLoc, &height, &width, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ulocdata_getPaperSize failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode));
+ }
+ if(strstr(currLoc, "_US")!=NULL && height != 279 && width != 216 ){
+ log_err("ulocdata_getPaperSize did not return expected data for locale %s \n", currLoc);
+ }
+ }
+ /* test that the MeasurementSystem works API works */
+ {
+ UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(currLoc, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ulocdata_getMeasurementSystem failed for locale %s with error: %s \n", currLoc, u_errorName(errorCode));
+ }
+ if(strstr(currLoc, "_US")!=NULL){
+ if(measurementSystem != UMS_US){
+ log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc);
+ }
+ }else if(measurementSystem != UMS_SI){
+ log_err("ulocdata_getMeasurementSystem did not return expected data for locale %s \n", currLoc);
+ }
+ }
+ }
+ ures_close(currentLocale);
+ }
+
+ ures_close(root);
+}
+
+/* adjust this limit as appropriate */
+#define MAX_SCRIPTS_PER_LOCALE 8
+
+static void TestExemplarSet(void){
+ int32_t i, j, k, m, n;
+ int32_t equalCount = 0;
+ UErrorCode ec = U_ZERO_ERROR;
+ UEnumeration* avail;
+ USet* exemplarSets[2];
+ USet* unassignedSet;
+ UScriptCode code[MAX_SCRIPTS_PER_LOCALE];
+ USet* codeSets[MAX_SCRIPTS_PER_LOCALE];
+ int32_t codeLen;
+ char cbuf[32]; /* 9 should be enough */
+ UChar ubuf[64]; /* adjust as needed */
+ UBool existsInScript;
+ int32_t itemCount;
+ int32_t strLen;
+ UChar32 start, end;
+
+ unassignedSet = NULL;
+ exemplarSets[0] = NULL;
+ exemplarSets[1] = NULL;
+ for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) {
+ codeSets[i] = NULL;
+ }
+
+ avail = ures_openAvailableLocales(NULL, &ec);
+ if (!assertSuccess("ures_openAvailableLocales", &ec)) goto END;
+ n = uenum_count(avail, &ec);
+ if (!assertSuccess("uenum_count", &ec)) goto END;
+
+ u_uastrcpy(ubuf, "[:unassigned:]");
+ unassignedSet = uset_openPattern(ubuf, -1, &ec);
+ if (!assertSuccess("uset_openPattern", &ec)) goto END;
+
+ for(i=0; i<n; i++){
+ const char* locale = uenum_next(avail, NULL, &ec);
+ if (!assertSuccess("uenum_next", &ec)) goto END;
+ log_verbose("%s\n", locale);
+ for (k=0; k<2; ++k) {
+ uint32_t option = (k==0) ? 0 : USET_CASE_INSENSITIVE;
+ ULocaleData *uld = ulocdata_open(locale,&ec);
+ USet* exemplarSet = ulocdata_getExemplarSet(uld,NULL, option, ULOCDATA_ES_STANDARD, &ec);
+ uset_close(exemplarSets[k]);
+ ulocdata_close(uld);
+ exemplarSets[k] = exemplarSet;
+ if (!assertSuccess("ulocaledata_getExemplarSet", &ec)) goto END;
+
+ if (uset_containsSome(exemplarSet, unassignedSet)) {
+ log_err("ExemplarSet contains unassigned characters for locale : %s\n", locale);
+ }
+ codeLen = uscript_getCode(locale, code, 8, &ec);
+ if (!assertSuccess("uscript_getCode", &ec)) goto END;
+
+ for (j=0; j<MAX_SCRIPTS_PER_LOCALE; ++j) {
+ uset_close(codeSets[j]);
+ codeSets[j] = NULL;
+ }
+ for (j=0; j<codeLen; ++j) {
+ uprv_strcpy(cbuf, "[:");
+ if(code[j]==-1){
+ log_err("USCRIPT_INVALID_CODE returned for locale: %s\n", locale);
+ continue;
+ }
+ uprv_strcat(cbuf, uscript_getShortName(code[j]));
+ uprv_strcat(cbuf, ":]");
+ u_uastrcpy(ubuf, cbuf);
+ codeSets[j] = uset_openPattern(ubuf, -1, &ec);
+ }
+ if (!assertSuccess("uset_openPattern", &ec)) goto END;
+
+ existsInScript = FALSE;
+ itemCount = uset_getItemCount(exemplarSet);
+ for (m=0; m<itemCount && !existsInScript; ++m) {
+ strLen = uset_getItem(exemplarSet, m, &start, &end, ubuf,
+ sizeof(ubuf)/sizeof(ubuf[0]), &ec);
+ /* failure here might mean str[] needs to be larger */
+ if (!assertSuccess("uset_getItem", &ec)) goto END;
+ if (strLen == 0) {
+ for (j=0; j<codeLen; ++j) {
+ if (codeSets[j]!=NULL && uset_containsRange(codeSets[j], start, end)) {
+ existsInScript = TRUE;
+ break;
+ }
+ }
+ } else {
+ for (j=0; j<codeLen; ++j) {
+ if (codeSets[j]!=NULL && uset_containsString(codeSets[j], ubuf, strLen)) {
+ existsInScript = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (existsInScript == FALSE){
+ log_err("ExemplarSet containment failed for locale : %s\n", locale);
+ }
+ }
+ assertTrue("case-folded is a superset",
+ uset_containsAll(exemplarSets[1], exemplarSets[0]));
+ if (uset_equals(exemplarSets[1], exemplarSets[0])) {
+ ++equalCount;
+ }
+ }
+ /* Note: The case-folded set should sometimes be a strict superset
+ and sometimes be equal. */
+ assertTrue("case-folded is sometimes a strict superset, and sometimes equal",
+ equalCount > 0 && equalCount < n);
+
+ END:
+ uenum_close(avail);
+ uset_close(exemplarSets[0]);
+ uset_close(exemplarSets[1]);
+ uset_close(unassignedSet);
+ for (i=0; i<MAX_SCRIPTS_PER_LOCALE; ++i) {
+ uset_close(codeSets[i]);
+ }
+}
+
+static void TestCoverage(void){
+ ULocaleDataDelimiterType types[] = {
+ ULOCDATA_QUOTATION_START, /* Quotation start */
+ ULOCDATA_QUOTATION_END, /* Quotation end */
+ ULOCDATA_ALT_QUOTATION_START, /* Alternate quotation start */
+ ULOCDATA_ALT_QUOTATION_END, /* Alternate quotation end */
+ ULOCDATA_DELIMITER_COUNT
+ };
+ int i;
+ UBool sub;
+ UErrorCode status = U_ZERO_ERROR;
+ ULocaleData *uld = ulocdata_open(uloc_getDefault(), &status);
+
+ if(U_FAILURE(status)){
+ log_err("ulocdata_open error");
+ return;
+ }
+
+
+ for(i = 0; i < ULOCDATA_DELIMITER_COUNT; i++){
+ UChar result[32] = {0,};
+ status = U_ZERO_ERROR;
+ ulocdata_getDelimiter(uld, types[i], result, 32, &status);
+ if (U_FAILURE(status)){
+ log_err("ulocdata_getgetDelimiter error with type %d", types[i]);
+ }
+ }
+
+ sub = ulocdata_getNoSubstitute(uld);
+ ulocdata_setNoSubstitute(uld,sub);
+ ulocdata_close(uld);
+}
+
+static void TestCurrencyList(void){
+#if !UCONFIG_NO_FORMATTING
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t structLocaleCount, currencyCount;
+ UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &errorCode);
+ const char *isoCode, *structISOCode;
+ UResourceBundle *subBundle;
+ UResourceBundle *currencies = ures_openDirect(loadTestData(&errorCode), "structLocale", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Can't open structLocale\n");
+ return;
+ }
+ currencies = ures_getByKey(currencies, "Currencies", currencies, &errorCode);
+ currencyCount = uenum_count(en, &errorCode);
+ structLocaleCount = ures_getSize(currencies);
+ if (currencyCount != structLocaleCount) {
+ log_err("structLocale(%d) and ISO4217(%d) currency list are out of sync.\n", structLocaleCount, currencyCount);
+#if U_CHARSET_FAMILY == U_ASCII_FAMILY
+ ures_resetIterator(currencies);
+ while ((isoCode = uenum_next(en, NULL, &errorCode)) != NULL && ures_hasNext(currencies)) {
+ subBundle = ures_getNextResource(currencies, NULL, &errorCode);
+ structISOCode = ures_getKey(subBundle);
+ ures_close(subBundle);
+ if (strcmp(structISOCode, isoCode) != 0) {
+ log_err("First difference found at structLocale(%s) and ISO4217(%s).\n", structISOCode, isoCode);
+ break;
+ }
+ }
+#endif
+ }
+ ures_close(currencies);
+ uenum_close(en);
+#endif
+}
+
+#define TESTCASE(name) addTest(root, &name, "tsutil/cldrtest/" #name)
+
+void addCLDRTest(TestNode** root);
+
+void addCLDRTest(TestNode** root)
+{
+ TESTCASE(TestLocaleStructure);
+ TESTCASE(TestConsistentCountryInfo);
+ TESTCASE(VerifyTranslation);
+ TESTCASE(TestExemplarSet);
+ TESTCASE(TestCurrencyList);
+ TESTCASE(TestCoverage);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c
new file mode 100644
index 00000000000..d75fce50d0f
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.c
@@ -0,0 +1,2774 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*****************************************************************************
+*
+* File CLOCTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+******************************************************************************
+*/
+#include "cloctst.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "cintltst.h"
+#include "cstring.h"
+#include "uparse.h"
+#include "uresimp.h"
+
+#include "unicode/putil.h"
+#include "unicode/ubrk.h"
+#include "unicode/uchar.h"
+#include "unicode/ucol.h"
+#include "unicode/udat.h"
+#include "unicode/uloc.h"
+#include "unicode/umsg.h"
+#include "unicode/ures.h"
+#include "unicode/uset.h"
+#include "unicode/ustring.h"
+#include "unicode/utypes.h"
+#include "unicode/ulocdata.h"
+#include "unicode/parseerr.h" /* may not be included with some uconfig switches */
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void TestNullDefault(void);
+static void TestNonexistentLanguageExemplars(void);
+static void TestLocDataErrorCodeChaining(void);
+static void TestLanguageExemplarsFallbacks(void);
+
+void PrintDataTable();
+
+/*---------------------------------------------------
+ table of valid data
+ --------------------------------------------------- */
+#define LOCALE_SIZE 9
+#define LOCALE_INFO_SIZE 28
+
+static const char* const rawData2[LOCALE_INFO_SIZE][LOCALE_SIZE] = {
+ /* language code */
+ { "en", "fr", "ca", "el", "no", "zh", "de", "es", "ja" },
+ /* script code */
+ { "", "", "", "", "", "Hans", "", "", "" },
+ /* country code */
+ { "US", "FR", "ES", "GR", "NO", "CN", "DE", "", "JP" },
+ /* variant code */
+ { "", "", "", "", "NY", "", "", "", "" },
+ /* full name */
+ { "en_US", "fr_FR", "ca_ES",
+ "el_GR", "no_NO_NY", "zh_Hans_CN",
+ "de_DE@collation=phonebook", "es@collation=traditional", "ja_JP@calendar=japanese" },
+ /* ISO-3 language */
+ { "eng", "fra", "cat", "ell", "nor", "zho", "deu", "spa", "jpn" },
+ /* ISO-3 country */
+ { "USA", "FRA", "ESP", "GRC", "NOR", "CHN", "DEU", "", "JPN" },
+ /* LCID */
+ { "409", "40c", "403", "408", "814", "804", "10407", "40a", "411" },
+
+ /* display language (English) */
+ { "English", "French", "Catalan", "Greek", "Norwegian", "Chinese", "German", "Spanish", "Japanese" },
+ /* display script code (English) */
+ { "", "", "", "", "", "Simplified Han", "", "", "" },
+ /* display country (English) */
+ { "United States", "France", "Spain", "Greece", "Norway", "China", "Germany", "", "Japan" },
+ /* display variant (English) */
+ { "", "", "", "", "NY", "", "", "", "" },
+ /* display name (English) */
+ { "English (United States)", "French (France)", "Catalan (Spain)",
+ "Greek (Greece)", "Norwegian (Norway, NY)", "Chinese (Simplified Han, China)",
+ "German (Germany, collation=Phonebook Sort Order)", "Spanish (collation=Traditional Sort Order)", "Japanese (Japan, calendar=Japanese Calendar)" },
+
+ /* display language (French) */
+ { "anglais", "fran\\u00E7ais", "catalan", "grec", "norv\\u00E9gien", "chinois", "allemand", "espagnol", "japonais" },
+ /* display script code (French) */
+ { "", "", "", "", "", "id\\u00e9ogrammes han (variante simplifi\\u00e9e)", "", "", "" },
+ /* display country (French) */
+ { "\\u00C9tats-Unis", "France", "Espagne", "Gr\\u00E8ce", "Norv\\u00E8ge", "Chine", "Allemagne", "", "Japon" },
+ /* display variant (French) */
+ { "", "", "", "", "NY", "", "", "", "" },
+ /* display name (French) */
+ { "anglais (\\u00C9tats-Unis)", "fran\\u00E7ais (France)", "catalan (Espagne)",
+ "grec (Gr\\u00E8ce)", "norv\\u00E9gien (Norv\\u00E8ge, NY)", "chinois (id\\u00e9ogrammes han (variante simplifi\\u00e9e), Chine)",
+ "allemand (Allemagne, Ordonnancement=Ordre de l\\u2019annuaire)", "espagnol (Ordonnancement=Ordre traditionnel)", "japonais (Japon, Calendrier=Calendrier japonais)" },
+
+ /* display language (Catalan) */
+ { "angl\\u00E8s", "franc\\u00E8s", "catal\\u00E0", "grec", "noruec", "xin\\u00E9s", "alemany", "espanyol", "japon\\u00E8s" },
+ /* display script code (Catalan) */
+ { "", "", "", "", "", "Hans", "", "", "" },
+ /* display country (Catalan) */
+ { "Estats Units", "Fran\\u00E7a", "Espanya", "Gr\\u00E8cia", "Noruega", "Xina", "Alemanya", "", "Jap\\u00F3" },
+ /* display variant (Catalan) */
+ { "", "", "", "", "NY", "", "", "", "" },
+ /* display name (Catalan) */
+ { "angl\\u00E8s (Estats Units)", "franc\\u00E8s (Fran\\u00E7a)", "catal\\u00E0 (Espanya)",
+ "grec (Gr\\u00E8cia)", "noruec (Noruega, NY)", "xin\\u00E9s (Hans, Xina)",
+ "alemany (Alemanya, collation=phonebook)", "espanyol (collation=traditional)", "japon\\u00E8s (Jap\\u00F3, calendar=japanese)" },
+
+ /* display language (Greek) */
+ {
+ "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac",
+ "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac",
+ "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac",
+ "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac",
+ "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac",
+ "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC",
+ "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
+ "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC",
+ "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC"
+ },
+ /* display script code (Greek) */
+
+ { "", "", "", "", "", "\\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc \\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf", "", "", "" },
+ /* display country (Greek) */
+ {
+ "\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2",
+ "\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1",
+ "\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1",
+ "\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1",
+ "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1",
+ "\\u039A\\u03AF\\u03BD\\u03B1",
+ "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1",
+ "",
+ "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1"
+ },
+ /* display variant (Greek) */
+ { "", "", "", "", "NY", "", "", "", "" }, /* TODO: currently there is no translation for NY in Greek fix this test when we have it */
+ /* display name (Greek) */
+ {
+ "\\u0391\\u03b3\\u03b3\\u03bb\\u03b9\\u03ba\\u03ac (\\u0397\\u03bd\\u03c9\\u03bc\\u03ad\\u03bd\\u03b5\\u03c2 \\u03a0\\u03bf\\u03bb\\u03b9\\u03c4\\u03b5\\u03af\\u03b5\\u03c2)",
+ "\\u0393\\u03b1\\u03bb\\u03bb\\u03b9\\u03ba\\u03ac (\\u0393\\u03b1\\u03bb\\u03bb\\u03af\\u03b1)",
+ "\\u039a\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03bd\\u03b9\\u03ba\\u03ac (\\u0399\\u03c3\\u03c0\\u03b1\\u03bd\\u03af\\u03b1)",
+ "\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac (\\u0395\\u03bb\\u03bb\\u03ac\\u03b4\\u03b1)",
+ "\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03b9\\u03ba\\u03ac (\\u039d\\u03bf\\u03c1\\u03b2\\u03b7\\u03b3\\u03af\\u03b1, NY)",
+ "\\u039A\\u03B9\\u03BD\\u03B5\\u03B6\\u03B9\\u03BA\\u03AC (\\u039a\\u03b9\\u03bd\\u03b5\\u03b6\\u03b9\\u03ba\\u03cc \\u0391\\u03c0\\u03bb\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03bc\\u03ad\\u03bd\\u03bf, \\u039A\\u03AF\\u03BD\\u03B1)",
+ "\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0393\\u03B5\\u03C1\\u03BC\\u03B1\\u03BD\\u03AF\\u03B1, \\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A3\\u03B5\\u03B9\\u03C1\\u03AC \\u03A4\\u03B7\\u03BB\\u03B5\\u03C6\\u03C9\\u03BD\\u03B9\\u03BA\\u03BF\\u03CD \\u039A\\u03B1\\u03C4\\u03B1\\u03BB\\u03CC\\u03B3\\u03BF\\u03C5)",
+ "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7\\u003D\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03A3\\u03B5\\u03B9\\u03C1\\u03AC)",
+ "\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03AC (\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03AF\\u03B1, \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF)"
+ }
+};
+
+static UChar*** dataTable=0;
+enum {
+ ENGLISH = 0,
+ FRENCH = 1,
+ CATALAN = 2,
+ GREEK = 3,
+ NORWEGIAN = 4
+};
+
+enum {
+ LANG = 0,
+ SCRIPT = 1,
+ CTRY = 2,
+ VAR = 3,
+ NAME = 4,
+ LANG3 = 5,
+ CTRY3 = 6,
+ LCID = 7,
+ DLANG_EN = 8,
+ DSCRIPT_EN = 9,
+ DCTRY_EN = 10,
+ DVAR_EN = 11,
+ DNAME_EN = 12,
+ DLANG_FR = 13,
+ DSCRIPT_FR = 14,
+ DCTRY_FR = 15,
+ DVAR_FR = 16,
+ DNAME_FR = 17,
+ DLANG_CA = 18,
+ DSCRIPT_CA = 19,
+ DCTRY_CA = 20,
+ DVAR_CA = 21,
+ DNAME_CA = 22,
+ DLANG_EL = 23,
+ DSCRIPT_EL = 24,
+ DCTRY_EL = 25,
+ DVAR_EL = 26,
+ DNAME_EL = 27
+};
+
+#define TESTCASE(name) addTest(root, &name, "tsutil/cloctst/" #name)
+
+void addLocaleTest(TestNode** root);
+
+void addLocaleTest(TestNode** root)
+{
+ TESTCASE(TestObsoleteNames); /* srl- move */
+ TESTCASE(TestBasicGetters);
+ TESTCASE(TestNullDefault);
+ TESTCASE(TestPrefixes);
+ TESTCASE(TestSimpleResourceInfo);
+ TESTCASE(TestDisplayNames);
+ TESTCASE(TestGetAvailableLocales);
+ TESTCASE(TestDataDirectory);
+ TESTCASE(TestISOFunctions);
+ TESTCASE(TestISO3Fallback);
+ TESTCASE(TestUninstalledISO3Names);
+ TESTCASE(TestSimpleDisplayNames);
+ TESTCASE(TestVariantParsing);
+ TESTCASE(TestKeywordVariants);
+ TESTCASE(TestKeywordVariantParsing);
+ TESTCASE(TestCanonicalization);
+ TESTCASE(TestKeywordSet);
+ TESTCASE(TestKeywordSetError);
+ TESTCASE(TestDisplayKeywords);
+ TESTCASE(TestDisplayKeywordValues);
+ TESTCASE(TestGetBaseName);
+ TESTCASE(TestGetLocale);
+ TESTCASE(TestDisplayNameWarning);
+ TESTCASE(TestNonexistentLanguageExemplars);
+ TESTCASE(TestLocDataErrorCodeChaining);
+ TESTCASE(TestLanguageExemplarsFallbacks);
+ TESTCASE(TestCalendar);
+ TESTCASE(TestDateFormat);
+ TESTCASE(TestCollation);
+ TESTCASE(TestULocale);
+ TESTCASE(TestUResourceBundle);
+ TESTCASE(TestDisplayName);
+ TESTCASE(TestAcceptLanguage);
+ TESTCASE(TestGetLocaleForLCID);
+}
+
+
+/* testing uloc(), uloc_getName(), uloc_getLanguage(), uloc_getVariant(), uloc_getCountry() */
+static void TestBasicGetters() {
+ int32_t i;
+ int32_t cap;
+ UErrorCode status = U_ZERO_ERROR;
+ char *testLocale = 0;
+ char *temp = 0, *name = 0;
+ log_verbose("Testing Basic Getters\n");
+ for (i = 0; i < LOCALE_SIZE; i++) {
+ testLocale=(char*)malloc(sizeof(char) * (strlen(rawData2[NAME][i])+1));
+ strcpy(testLocale,rawData2[NAME][i]);
+
+ log_verbose("Testing %s .....\n", testLocale);
+ cap=uloc_getLanguage(testLocale, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ temp=(char*)malloc(sizeof(char) * (cap+1));
+ uloc_getLanguage(testLocale, temp, cap+1, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in uloc_getLanguage %s\n", myErrorName(status));
+ }
+ if (0 !=strcmp(temp,rawData2[LANG][i])) {
+ log_err(" Language code mismatch: %s versus %s\n", temp, rawData2[LANG][i]);
+ }
+
+
+ cap=uloc_getCountry(testLocale, temp, cap, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ temp=(char*)realloc(temp, sizeof(char) * (cap+1));
+ uloc_getCountry(testLocale, temp, cap+1, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in uloc_getCountry %s\n", myErrorName(status));
+ }
+ if (0 != strcmp(temp, rawData2[CTRY][i])) {
+ log_err(" Country code mismatch: %s versus %s\n", temp, rawData2[CTRY][i]);
+
+ }
+
+ cap=uloc_getVariant(testLocale, temp, cap, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ temp=(char*)realloc(temp, sizeof(char) * (cap+1));
+ uloc_getVariant(testLocale, temp, cap+1, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in uloc_getVariant %s\n", myErrorName(status));
+ }
+ if (0 != strcmp(temp, rawData2[VAR][i])) {
+ log_err("Variant code mismatch: %s versus %s\n", temp, rawData2[VAR][i]);
+ }
+
+ cap=uloc_getName(testLocale, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ name=(char*)malloc(sizeof(char) * (cap+1));
+ uloc_getName(testLocale, name, cap+1, &status);
+ } else if(status==U_ZERO_ERROR) {
+ log_err("ERROR: in uloc_getName(%s,NULL,0,..), expected U_BUFFER_OVERFLOW_ERROR!\n", testLocale);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: in uloc_getName %s\n", myErrorName(status));
+ }
+ if (0 != strcmp(name, rawData2[NAME][i])){
+ log_err(" Mismatch in getName: %s versus %s\n", name, rawData2[NAME][i]);
+ }
+
+ free(temp);
+ free(name);
+
+ free(testLocale);
+ }
+}
+
+static void TestNullDefault() {
+ UErrorCode status = U_ZERO_ERROR;
+ char original[ULOC_FULLNAME_CAPACITY];
+
+ uprv_strcpy(original, uloc_getDefault());
+ uloc_setDefault("qq_BLA", &status);
+ if (uprv_strcmp(uloc_getDefault(), "qq_BLA") != 0) {
+ log_err(" Mismatch in uloc_setDefault: qq_BLA versus %s\n", uloc_getDefault());
+ }
+ uloc_setDefault(NULL, &status);
+ if (uprv_strcmp(uloc_getDefault(), original) != 0) {
+ log_err(" uloc_setDefault(NULL, &status) didn't get the default locale back!\n");
+ }
+
+ {
+ /* Test that set & get of default locale work, and that
+ * default locales are cached and reused, and not overwritten.
+ */
+ const char *n_en_US;
+ const char *n_fr_FR;
+ const char *n2_en_US;
+
+ status = U_ZERO_ERROR;
+ uloc_setDefault("en_US", &status);
+ n_en_US = uloc_getDefault();
+ if (strcmp(n_en_US, "en_US") != 0) {
+ log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
+ }
+
+ uloc_setDefault("fr_FR", &status);
+ n_fr_FR = uloc_getDefault();
+ if (strcmp(n_en_US, "en_US") != 0) {
+ log_err("uloc_setDefault altered previously default string."
+ "Expected \"en_US\", got \"%s\"\n", n_en_US);
+ }
+ if (strcmp(n_fr_FR, "fr_FR") != 0) {
+ log_err("Wrong result from uloc_getDefault(). Expected \"fr_FR\", got %s\n", n_fr_FR);
+ }
+
+ uloc_setDefault("en_US", &status);
+ n2_en_US = uloc_getDefault();
+ if (strcmp(n2_en_US, "en_US") != 0) {
+ log_err("Wrong result from uloc_getDefault(). Expected \"en_US\", got \"%s\"\n", n_en_US);
+ }
+ if (n2_en_US != n_en_US) {
+ log_err("Default locale cache failed to reuse en_US locale.\n");
+ }
+
+ if (U_FAILURE(status)) {
+ log_err("Failure returned from uloc_setDefault - \"%s\"\n", u_errorName(status));
+ }
+
+ }
+
+}
+/* Test the i- and x- and @ and . functionality
+*/
+
+#define PREFIXBUFSIZ 128
+
+static void TestPrefixes() {
+ int row = 0;
+ int n;
+ const char *loc, *expected;
+
+ static const char * const testData[][7] =
+ {
+ /* NULL canonicalize() column means "expect same as getName()" */
+ {"sv", "", "FI", "AL", "sv-fi-al", "sv_FI_AL", NULL},
+ {"en", "", "GB", "", "en-gb", "en_GB", NULL},
+ {"i-hakka", "", "MT", "XEMXIJA", "i-hakka_MT_XEMXIJA", "i-hakka_MT_XEMXIJA", NULL},
+ {"i-hakka", "", "CN", "", "i-hakka_CN", "i-hakka_CN", NULL},
+ {"i-hakka", "", "MX", "", "I-hakka_MX", "i-hakka_MX", NULL},
+ {"x-klingon", "", "US", "SANJOSE", "X-KLINGON_us_SANJOSE", "x-klingon_US_SANJOSE", NULL},
+
+ {"mr", "", "", "", "mr.utf8", "mr.utf8", "mr"},
+ {"de", "", "TV", "", "de-tv.koi8r", "de_TV.koi8r", "de_TV"},
+ {"x-piglatin", "", "ML", "", "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML"}, /* Multibyte English */
+ {"i-cherokee", "","US", "", "i-Cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US"},
+ {"x-filfli", "", "MT", "FILFLA", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA"},
+ {"no", "", "NO", "NY", "no-no-ny.utf32@B", "no_NO_NY.utf32@B", "no_NO_NY_B"},
+ {"no", "", "NO", "", "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B"},
+ {"no", "", "", "NY", "no__ny", "no__NY", NULL},
+ {"no", "", "", "", "no@ny", "no@ny", "no__NY"},
+ {"el", "Latn", "", "", "el-latn", "el_Latn", NULL},
+ {"en", "Cyrl", "RU", "", "en-cyrl-ru", "en_Cyrl_RU", NULL},
+ {"zh", "Hant", "TW", "STROKE", "zh-hant_TW_STROKE", "zh_Hant_TW_STROKE", NULL},
+ {"qq", "Qqqq", "QQ", "QQ", "qq_Qqqq_QQ_QQ", "qq_Qqqq_QQ_QQ", NULL},
+ {"qq", "Qqqq", "", "QQ", "qq_Qqqq__QQ", "qq_Qqqq__QQ", NULL},
+ {"12", "3456", "78", "90", "12_3456_78_90", "12_3456_78_90", NULL}, /* total garbage */
+
+ {NULL,NULL,NULL,NULL,NULL,NULL,NULL}
+ };
+
+ static const char * const testTitles[] = {
+ "uloc_getLanguage()",
+ "uloc_getScript()",
+ "uloc_getCountry()",
+ "uloc_getVariant()",
+ "name",
+ "uloc_getName()",
+ "uloc_canonicalize()"
+ };
+
+ char buf[PREFIXBUFSIZ];
+ int32_t len;
+ UErrorCode err;
+
+
+ for(row=0;testData[row][0] != NULL;row++) {
+ loc = testData[row][NAME];
+ log_verbose("Test #%d: %s\n", row, loc);
+
+ err = U_ZERO_ERROR;
+ len=0;
+ buf[0]=0;
+ for(n=0;n<=(NAME+2);n++) {
+ if(n==NAME) continue;
+
+ for(len=0;len<PREFIXBUFSIZ;len++) {
+ buf[len] = '%'; /* Set a tripwire.. */
+ }
+ len = 0;
+
+ switch(n) {
+ case LANG:
+ len = uloc_getLanguage(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ case SCRIPT:
+ len = uloc_getScript(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ case CTRY:
+ len = uloc_getCountry(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ case VAR:
+ len = uloc_getVariant(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ case NAME+1:
+ len = uloc_getName(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ case NAME+2:
+ len = uloc_canonicalize(loc, buf, PREFIXBUFSIZ, &err);
+ break;
+
+ default:
+ strcpy(buf, "**??");
+ len=4;
+ }
+
+ if(U_FAILURE(err)) {
+ log_err("#%d: %s on %s: err %s\n",
+ row, testTitles[n], loc, u_errorName(err));
+ } else {
+ log_verbose("#%d: %s on %s: -> [%s] (length %d)\n",
+ row, testTitles[n], loc, buf, len);
+
+ if(len != (int32_t)strlen(buf)) {
+ log_err("#%d: %s on %s: -> [%s] (length returned %d, actual %d!)\n",
+ row, testTitles[n], loc, buf, len, strlen(buf)+1);
+
+ }
+
+ /* see if they smashed something */
+ if(buf[len+1] != '%') {
+ log_err("#%d: %s on %s: -> [%s] - wrote [%X] out ofbounds!\n",
+ row, testTitles[n], loc, buf, buf[len+1]);
+ }
+
+ expected = testData[row][n];
+ if (expected == NULL && n == (NAME+2)) {
+ /* NULL expected canonicalize() means "expect same as getName()" */
+ expected = testData[row][NAME+1];
+ }
+ if(strcmp(buf, expected)) {
+ log_err("#%d: %s on %s: -> [%s] (expected '%s'!)\n",
+ row, testTitles[n], loc, buf, expected);
+
+ }
+ }
+ }
+ }
+}
+
+
+/* testing uloc_getISO3Language(), uloc_getISO3Country(), */
+static void TestSimpleResourceInfo() {
+ int32_t i;
+ char* testLocale = 0;
+ UChar* expected = 0;
+
+ const char* temp;
+ char temp2[20];
+ testLocale=(char*)malloc(sizeof(char) * 1);
+ expected=(UChar*)malloc(sizeof(UChar) * 1);
+
+ setUpDataTable();
+ log_verbose("Testing getISO3Language and getISO3Country\n");
+ for (i = 0; i < LOCALE_SIZE; i++) {
+
+ testLocale=(char*)realloc(testLocale, sizeof(char) * (u_strlen(dataTable[NAME][i])+1));
+ u_austrcpy(testLocale, dataTable[NAME][i]);
+
+ log_verbose("Testing %s ......\n", testLocale);
+
+ temp=uloc_getISO3Language(testLocale);
+ expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
+ u_uastrcpy(expected,temp);
+ if (0 != u_strcmp(expected, dataTable[LANG3][i])) {
+ log_err(" ISO-3 language code mismatch: %s versus %s\n", austrdup(expected),
+ austrdup(dataTable[LANG3][i]));
+ }
+
+ temp=uloc_getISO3Country(testLocale);
+ expected=(UChar*)realloc(expected, sizeof(UChar) * (strlen(temp) + 1));
+ u_uastrcpy(expected,temp);
+ if (0 != u_strcmp(expected, dataTable[CTRY3][i])) {
+ log_err(" ISO-3 Country code mismatch: %s versus %s\n", austrdup(expected),
+ austrdup(dataTable[CTRY3][i]));
+ }
+ sprintf(temp2, "%x", (int)uloc_getLCID(testLocale));
+ if (strcmp(temp2, rawData2[LCID][i]) != 0) {
+ log_err("LCID mismatch: %s versus %s\n", temp2 , rawData2[LCID][i]);
+ }
+ }
+
+ free(expected);
+ free(testLocale);
+ cleanUpDataTable();
+}
+
+/*
+ * Jitterbug 2439 -- markus 20030425
+ *
+ * The lookup of display names must not fall back through the default
+ * locale because that yields useless results.
+ */
+static void TestDisplayNames()
+{
+ UChar buffer[100];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ int32_t length;
+ log_verbose("Testing getDisplayName for different locales\n");
+
+ log_verbose(" In locale = en_US...\n");
+ doTestDisplayNames("en_US", DLANG_EN);
+ log_verbose(" In locale = fr_FR....\n");
+ doTestDisplayNames("fr_FR", DLANG_FR);
+ log_verbose(" In locale = ca_ES...\n");
+ doTestDisplayNames("ca_ES", DLANG_CA);
+ log_verbose(" In locale = gr_EL..\n");
+ doTestDisplayNames("el_GR", DLANG_EL);
+
+ /* test that the default locale has a display name for its own language */
+ errorCode=U_ZERO_ERROR;
+ length=uloc_getDisplayLanguage(NULL, NULL, buffer, LENGTHOF(buffer), &errorCode);
+ if(U_FAILURE(errorCode) || (length<=3 && buffer[0]<=0x7f)) {
+ /* check <=3 to reject getting the language code as a display name */
+ log_err("unable to get a display string for the language of the default locale - %s\n", u_errorName(errorCode));
+ }
+
+ /* test that we get the language code itself for an unknown language, and a default warning */
+ errorCode=U_ZERO_ERROR;
+ length=uloc_getDisplayLanguage("qq", "rr", buffer, LENGTHOF(buffer), &errorCode);
+ if(errorCode!=U_USING_DEFAULT_WARNING || length!=2 || buffer[0]!=0x71 || buffer[1]!=0x71) {
+ log_err("error getting the display string for an unknown language - %s\n", u_errorName(errorCode));
+ }
+
+ /* test that we get a default warning for a display name where one component is unknown (4255) */
+ errorCode=U_ZERO_ERROR;
+ length=uloc_getDisplayName("qq_US_POSIX", "en_US", buffer, LENGTHOF(buffer), &errorCode);
+ if(errorCode!=U_USING_DEFAULT_WARNING) {
+ log_err("error getting the display name for a locale with an unknown language - %s\n", u_errorName(errorCode));
+ }
+
+ {
+ int32_t i;
+ static const char *aLocale = "es@collation=traditional;calendar=japanese";
+ static const char *testL[] = { "en_US",
+ "fr_FR",
+ "ca_ES",
+ "el_GR" };
+ static const char *expect[] = { "Spanish (calendar=Japanese Calendar, collation=Traditional Sort Order)", /* note sorted order of keywords */
+ "espagnol (Calendrier=Calendrier japonais, Ordonnancement=Ordre traditionnel)",
+ "espanyol (calendar=japanese, collation=traditional)",
+ "\\u0399\\u03C3\\u03C0\\u03B1\\u03BD\\u03B9\\u03BA\\u03AC (\\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF=\\u0399\\u03B1\\u03C0\\u03C9\\u03BD\\u03B9\\u03BA\\u03CC \\u0397\\u03BC\\u03B5\\u03C1\\u03BF\\u03BB\\u03CC\\u03B3\\u03B9\\u03BF, \\u03A4\\u03B1\\u03BA\\u03C4\\u03BF\\u03C0\\u03BF\\u03AF\\u03B7\\u03C3\\u03B7=\\u03A0\\u03B1\\u03C1\\u03B1\\u03B4\\u03BF\\u03C3\\u03B9\\u03B1\\u03BA\\u03AE \\u03A3\\u03B5\\u03B9\\u03C1\\u03AC)" };
+ UChar *expectBuffer;
+
+ for(i=0;i<LENGTHOF(testL);i++) {
+ errorCode = U_ZERO_ERROR;
+ uloc_getDisplayName(aLocale, testL[i], buffer, LENGTHOF(buffer), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("FAIL in uloc_getDisplayName(%s,%s,..) -> %s\n", aLocale, testL[i], u_errorName(errorCode));
+ } else {
+ expectBuffer = CharsToUChars(expect[i]);
+ if(u_strcmp(buffer,expectBuffer)) {
+ log_err("FAIL in uloc_getDisplayName(%s,%s,..) expected '%s' got '%s'\n", aLocale, testL[i], expect[i], austrdup(buffer));
+ } else {
+ log_verbose("pass in uloc_getDisplayName(%s,%s,..) got '%s'\n", aLocale, testL[i], expect[i]);
+ }
+ free(expectBuffer);
+ }
+ }
+ }
+}
+
+
+/* test for uloc_getAvialable() and uloc_countAvilable()*/
+static void TestGetAvailableLocales()
+{
+
+ const char *locList;
+ int32_t locCount,i;
+
+ log_verbose("Testing the no of avialable locales\n");
+ locCount=uloc_countAvailable();
+ if (locCount == 0)
+ log_data_err("countAvailable() returned an empty list!\n");
+
+ /* use something sensible w/o hardcoding the count */
+ else if(locCount < 0){
+ log_data_err("countAvailable() returned a wrong value!= %d\n", locCount);
+ }
+ else{
+ log_info("Number of locales returned = %d\n", locCount);
+ }
+ for(i=0;i<locCount;i++){
+ locList=uloc_getAvailable(i);
+
+ log_verbose(" %s\n", locList);
+ }
+}
+
+/* test for u_getDataDirectory, u_setDataDirectory, uloc_getISO3Language */
+static void TestDataDirectory()
+{
+
+ char oldDirectory[512];
+ const char *temp,*testValue1,*testValue2,*testValue3;
+ const char path[40] ="d:\\icu\\source\\test\\intltest" U_FILE_SEP_STRING; /*give the required path */
+
+ log_verbose("Testing getDataDirectory()\n");
+ temp = u_getDataDirectory();
+ strcpy(oldDirectory, temp);
+
+ testValue1=uloc_getISO3Language("en_US");
+ log_verbose("first fetch of language retrieved %s\n", testValue1);
+
+ if (0 != strcmp(testValue1,"eng")){
+ log_err("Initial check of ISO3 language failed: expected \"eng\", got %s \n", testValue1);
+ }
+
+ /*defining the path for DataDirectory */
+ log_verbose("Testing setDataDirectory\n");
+ u_setDataDirectory( path );
+ if(strcmp(path, u_getDataDirectory())==0)
+ log_verbose("setDataDirectory working fine\n");
+ else
+ log_err("Error in setDataDirectory. Directory not set correctly - came back as [%s], expected [%s]\n", u_getDataDirectory(), path);
+
+ testValue2=uloc_getISO3Language("en_US");
+ log_verbose("second fetch of language retrieved %s \n", testValue2);
+
+ u_setDataDirectory(oldDirectory);
+ testValue3=uloc_getISO3Language("en_US");
+ log_verbose("third fetch of language retrieved %s \n", testValue3);
+
+ if (0 != strcmp(testValue3,"eng")) {
+ log_err("get/setDataDirectory() failed: expected \"eng\", got \" %s \" \n", testValue3);
+ }
+}
+
+
+
+/*=========================================================== */
+
+static UChar _NUL=0;
+
+static void doTestDisplayNames(const char* displayLocale, int32_t compareIndex)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i;
+ int32_t maxresultsize;
+
+ const char *testLocale;
+
+
+ UChar *testLang = 0;
+ UChar *testScript = 0;
+ UChar *testCtry = 0;
+ UChar *testVar = 0;
+ UChar *testName = 0;
+
+
+ UChar* expectedLang = 0;
+ UChar* expectedScript = 0;
+ UChar* expectedCtry = 0;
+ UChar* expectedVar = 0;
+ UChar* expectedName = 0;
+
+setUpDataTable();
+
+ for(i=0;i<LOCALE_SIZE; ++i)
+ {
+ testLocale=rawData2[NAME][i];
+
+ log_verbose("Testing..... %s\n", testLocale);
+
+ maxresultsize=0;
+ maxresultsize=uloc_getDisplayLanguage(testLocale, displayLocale, NULL, maxresultsize, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ testLang=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
+ uloc_getDisplayLanguage(testLocale, displayLocale, testLang, maxresultsize + 1, &status);
+ }
+ else
+ {
+ testLang=&_NUL;
+ }
+ if(U_FAILURE(status)){
+ log_err("Error in getDisplayLanguage() %s\n", myErrorName(status));
+ }
+
+ maxresultsize=0;
+ maxresultsize=uloc_getDisplayScript(testLocale, displayLocale, NULL, maxresultsize, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ testScript=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
+ uloc_getDisplayScript(testLocale, displayLocale, testScript, maxresultsize + 1, &status);
+ }
+ else
+ {
+ testScript=&_NUL;
+ }
+ if(U_FAILURE(status)){
+ log_err("Error in getDisplayScript() %s\n", myErrorName(status));
+ }
+
+ maxresultsize=0;
+ maxresultsize=uloc_getDisplayCountry(testLocale, displayLocale, NULL, maxresultsize, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ testCtry=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
+ uloc_getDisplayCountry(testLocale, displayLocale, testCtry, maxresultsize + 1, &status);
+ }
+ else
+ {
+ testCtry=&_NUL;
+ }
+ if(U_FAILURE(status)){
+ log_err("Error in getDisplayCountry() %s\n", myErrorName(status));
+ }
+
+ maxresultsize=0;
+ maxresultsize=uloc_getDisplayVariant(testLocale, displayLocale, NULL, maxresultsize, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ testVar=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
+ uloc_getDisplayVariant(testLocale, displayLocale, testVar, maxresultsize + 1, &status);
+ }
+ else
+ {
+ testVar=&_NUL;
+ }
+ if(U_FAILURE(status)){
+ log_err("Error in getDisplayVariant() %s\n", myErrorName(status));
+ }
+
+ maxresultsize=0;
+ maxresultsize=uloc_getDisplayName(testLocale, displayLocale, NULL, maxresultsize, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ testName=(UChar*)malloc(sizeof(UChar) * (maxresultsize+1));
+ uloc_getDisplayName(testLocale, displayLocale, testName, maxresultsize + 1, &status);
+ }
+ else
+ {
+ testName=&_NUL;
+ }
+ if(U_FAILURE(status)){
+ log_err("Error in getDisplayName() %s\n", myErrorName(status));
+ }
+
+ expectedLang=dataTable[compareIndex][i];
+ if(u_strlen(expectedLang)== 0)
+ expectedLang=dataTable[DLANG_EN][i];
+
+ expectedScript=dataTable[compareIndex + 1][i];
+ if(u_strlen(expectedScript)== 0)
+ expectedScript=dataTable[DSCRIPT_EN][i];
+
+ expectedCtry=dataTable[compareIndex + 2][i];
+ if(u_strlen(expectedCtry)== 0)
+ expectedCtry=dataTable[DCTRY_EN][i];
+
+ expectedVar=dataTable[compareIndex + 3][i];
+ if(u_strlen(expectedVar)== 0)
+ expectedVar=dataTable[DVAR_EN][i];
+
+ expectedName=dataTable[compareIndex + 4][i];
+ if(u_strlen(expectedName) == 0)
+ expectedName=dataTable[DNAME_EN][i];
+
+ if (0 !=u_strcmp(testLang,expectedLang)) {
+ log_data_err(" Display Language mismatch: got %s expected %s displayLocale=%s\n", austrdup(testLang), austrdup(expectedLang), displayLocale);
+ }
+
+ if (0 != u_strcmp(testScript,expectedScript)) {
+ log_data_err(" Display Script mismatch: got %s expected %s displayLocale=%s\n", austrdup(testScript), austrdup(expectedScript), displayLocale);
+ }
+
+ if (0 != u_strcmp(testCtry,expectedCtry)) {
+ log_data_err(" Display Country mismatch: got %s expected %s displayLocale=%s\n", austrdup(testCtry), austrdup(expectedCtry), displayLocale);
+ }
+
+ if (0 != u_strcmp(testVar,expectedVar)) {
+ log_data_err(" Display Variant mismatch: got %s expected %s displayLocale=%s\n", austrdup(testVar), austrdup(expectedVar), displayLocale);
+ }
+
+ if(0 != u_strcmp(testName, expectedName)) {
+ log_data_err(" Display Name mismatch: got %s expected %s displayLocale=%s\n", austrdup(testName), austrdup(expectedName), displayLocale);
+ }
+
+ if(testName!=&_NUL) {
+ free(testName);
+ }
+ if(testLang!=&_NUL) {
+ free(testLang);
+ }
+ if(testScript!=&_NUL) {
+ free(testScript);
+ }
+ if(testCtry!=&_NUL) {
+ free(testCtry);
+ }
+ if(testVar!=&_NUL) {
+ free(testVar);
+ }
+ }
+cleanUpDataTable();
+}
+
+/* test for uloc_getISOLanguages, uloc_getISOCountries */
+static void TestISOFunctions()
+{
+ const char* const* str=uloc_getISOLanguages();
+ const char* const* str1=uloc_getISOCountries();
+ const char* test;
+ const char *key = NULL;
+ int32_t count = 0, skipped = 0;
+ int32_t expect;
+ UResourceBundle *res;
+ UResourceBundle *subRes;
+ UErrorCode status = U_ZERO_ERROR;
+
+ /* test getISOLanguages*/
+ /*str=uloc_getISOLanguages(); */
+ log_verbose("Testing ISO Languages: \n");
+
+ /* use structLocale - this data is no longer in root */
+ res = ures_openDirect(loadTestData(&status), "structLocale", &status);
+ subRes = ures_getByKey(res, "Languages", NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("There is an error in structLocale's ures_getByKey(\"Languages\"), status=%s\n", u_errorName(status));
+ return;
+ }
+
+ expect = ures_getSize(subRes);
+ for(count = 0; *(str+count) != 0; count++)
+ {
+ key = NULL;
+ test = *(str+count);
+ status = U_ZERO_ERROR;
+
+ do {
+ /* Skip over language tags. This API only returns language codes. */
+ skipped += (key != NULL);
+ ures_getNextString(subRes, NULL, &key, &status);
+ }
+ while (key != NULL && strchr(key, '_'));
+
+ if(key == NULL)
+ break;
+ /* TODO: Consider removing sh, which is deprecated */
+ if(strcmp(key,"root") == 0 || strcmp(key,"Fallback") == 0 || strcmp(key,"sh") == 0) {
+ ures_getNextString(subRes, NULL, &key, &status);
+ skipped++;
+ }
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+ /* This code only works on ASCII machines where the keys are stored in ASCII order */
+ if(strcmp(test,key)) {
+ /* The first difference usually implies the place where things get out of sync */
+ log_err("FAIL Language diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
+ }
+#endif
+
+ if(!strcmp(test,"in"))
+ log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
+ if(!strcmp(test,"iw"))
+ log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
+ if(!strcmp(test,"ji"))
+ log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
+ if(!strcmp(test,"jw"))
+ log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
+ if(!strcmp(test,"sh"))
+ log_err("FAIL getISOLanguages() has obsolete language code %s\n", test);
+ }
+
+ expect -= skipped; /* Ignore the skipped resources from structLocale */
+
+ if(count!=expect) {
+ log_err("There is an error in getISOLanguages, got %d, expected %d (as per structLocale)\n", count, expect);
+ }
+
+ subRes = ures_getByKey(res, "Countries", subRes, &status);
+ log_verbose("Testing ISO Countries");
+ skipped = 0;
+ expect = ures_getSize(subRes) - 1; /* Skip ZZ */
+ for(count = 0; *(str1+count) != 0; count++)
+ {
+ key = NULL;
+ test = *(str1+count);
+ do {
+ /* Skip over numeric UN tags. This API only returns ISO-3166 codes. */
+ skipped += (key != NULL);
+ ures_getNextString(subRes, NULL, &key, &status);
+ }
+ while (key != NULL && strlen(key) != 2);
+
+ if(key == NULL)
+ break;
+ /* TODO: Consider removing CS, which is deprecated */
+ while(strcmp(key,"QO") == 0 || strcmp(key,"QU") == 0 || strcmp(key,"CS") == 0) {
+ ures_getNextString(subRes, NULL, &key, &status);
+ skipped++;
+ }
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+ /* This code only works on ASCII machines where the keys are stored in ASCII order */
+ if(strcmp(test,key)) {
+ /* The first difference usually implies the place where things get out of sync */
+ log_err("FAIL Country diff at offset %d, \"%s\" != \"%s\"\n", count, test, key);
+ }
+#endif
+ if(!strcmp(test,"FX"))
+ log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
+ if(!strcmp(test,"YU"))
+ log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
+ if(!strcmp(test,"ZR"))
+ log_err("FAIL getISOCountries() has obsolete country code %s\n", test);
+ }
+
+ ures_getNextString(subRes, NULL, &key, &status);
+ if (strcmp(key, "ZZ") != 0) {
+ log_err("ZZ was expected to be the last entry in structLocale, but got %s\n", key);
+ }
+#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+ /* On EBCDIC machines, the numbers are sorted last. Account for those in the skipped value too. */
+ key = NULL;
+ do {
+ /* Skip over numeric UN tags. uloc_getISOCountries only returns ISO-3166 codes. */
+ skipped += (key != NULL);
+ ures_getNextString(subRes, NULL, &key, &status);
+ }
+ while (U_SUCCESS(status) && key != NULL && strlen(key) != 2);
+#endif
+ expect -= skipped; /* Ignore the skipped resources from structLocale */
+ if(count!=expect)
+ {
+ log_err("There is an error in getISOCountries, got %d, expected %d \n", count, expect);
+ }
+ ures_close(subRes);
+ ures_close(res);
+}
+
+static void setUpDataTable()
+{
+ int32_t i,j;
+ dataTable = (UChar***)(calloc(sizeof(UChar**),LOCALE_INFO_SIZE));
+
+ for (i = 0; i < LOCALE_INFO_SIZE; i++) {
+ dataTable[i] = (UChar**)(calloc(sizeof(UChar*),LOCALE_SIZE));
+ for (j = 0; j < LOCALE_SIZE; j++){
+ dataTable[i][j] = CharsToUChars(rawData2[i][j]);
+ }
+ }
+}
+
+static void cleanUpDataTable()
+{
+ int32_t i,j;
+ if(dataTable != NULL) {
+ for (i=0; i<LOCALE_INFO_SIZE; i++) {
+ for(j = 0; j < LOCALE_SIZE; j++) {
+ free(dataTable[i][j]);
+ }
+ free(dataTable[i]);
+ }
+ free(dataTable);
+ }
+ dataTable = NULL;
+}
+
+/**
+ * @bug 4011756 4011380
+ */
+static void TestISO3Fallback()
+{
+ const char* test="xx_YY";
+
+ const char * result;
+
+ result = uloc_getISO3Language(test);
+
+ /* Conform to C API usage */
+
+ if (!result || (result[0] != 0))
+ log_err("getISO3Language() on xx_YY returned %s instead of \"\"");
+
+ result = uloc_getISO3Country(test);
+
+ if (!result || (result[0] != 0))
+ log_err("getISO3Country() on xx_YY returned %s instead of \"\"");
+}
+
+/**
+ * @bug 4118587
+ */
+static void TestSimpleDisplayNames()
+{
+ /*
+ This test is different from TestDisplayNames because TestDisplayNames checks
+ fallback behavior, combination of language and country names to form locale
+ names, and other stuff like that. This test just checks specific language
+ and country codes to make sure we have the correct names for them.
+ */
+ char languageCodes[] [4] = { "he", "id", "iu", "ug", "yi", "za" };
+ const char* languageNames [] = { "Hebrew", "Indonesian", "Inuktitut", "Uighur", "Yiddish",
+ "Zhuang" };
+ UErrorCode status=U_ZERO_ERROR;
+
+ int32_t i;
+ for (i = 0; i < 6; i++) {
+ UChar *testLang=0;
+ UChar *expectedLang=0;
+ int size=0;
+ size=uloc_getDisplayLanguage(languageCodes[i], "en_US", NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ testLang=(UChar*)malloc(sizeof(UChar) * (size + 1));
+ uloc_getDisplayLanguage(languageCodes[i], "en_US", testLang, size + 1, &status);
+ }
+ expectedLang=(UChar*)malloc(sizeof(UChar) * (strlen(languageNames[i])+1));
+ u_uastrcpy(expectedLang, languageNames[i]);
+ if (u_strcmp(testLang, expectedLang) != 0)
+ log_data_err("Got wrong display name for %s : Expected \"%s\", got \"%s\".\n",
+ languageCodes[i], languageNames[i], austrdup(testLang));
+ free(testLang);
+ free(expectedLang);
+ }
+
+}
+
+/**
+ * @bug 4118595
+ */
+static void TestUninstalledISO3Names()
+{
+ /* This test checks to make sure getISO3Language and getISO3Country work right
+ even for locales that are not installed. */
+ static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn",
+ "ss", "tw", "zu" };
+ static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run",
+ "ssw", "twi", "zul" };
+ static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN",
+ "ss_SB", "tw_TC", "zu_ZW" };
+ static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG",
+ "SLB", "TCA", "ZWE" };
+ int32_t i;
+
+ for (i = 0; i < 8; i++) {
+ UErrorCode err = U_ZERO_ERROR;
+ const char *test;
+ test = uloc_getISO3Language(iso2Languages[i]);
+ if(strcmp(test, iso3Languages[i]) !=0 || U_FAILURE(err))
+ log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
+ iso2Languages[i], iso3Languages[i], test, myErrorName(err));
+ }
+ for (i = 0; i < 8; i++) {
+ UErrorCode err = U_ZERO_ERROR;
+ const char *test;
+ test = uloc_getISO3Country(iso2Countries[i]);
+ if(strcmp(test, iso3Countries[i]) !=0 || U_FAILURE(err))
+ log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n",
+ iso2Countries[i], iso3Countries[i], test, myErrorName(err));
+ }
+}
+
+
+static void TestVariantParsing()
+{
+ static const char* en_US_custom="en_US_De Anza_Cupertino_California_United States_Earth";
+ static const char* dispName="English (United States, DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH)";
+ static const char* dispVar="DE ANZA_CUPERTINO_CALIFORNIA_UNITED STATES_EARTH";
+ static const char* shortVariant="fr_FR_foo";
+ static const char* bogusVariant="fr_FR__foo";
+ static const char* bogusVariant2="fr_FR_foo_";
+ static const char* bogusVariant3="fr_FR__foo_";
+
+
+ UChar displayVar[100];
+ UChar displayName[100];
+ UErrorCode status=U_ZERO_ERROR;
+ UChar* got=0;
+ int32_t size=0;
+ size=uloc_getDisplayVariant(en_US_custom, "en_US", NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayVariant(en_US_custom, "en_US", got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ u_uastrcpy(displayVar, dispVar);
+ if(u_strcmp(got,displayVar)!=0) {
+ log_err("FAIL: getDisplayVariant() Wanted %s, got %s\n", dispVar, austrdup(got));
+ }
+ size=0;
+ size=uloc_getDisplayName(en_US_custom, "en_US", NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayName(en_US_custom, "en_US", got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ u_uastrcpy(displayName, dispName);
+ if(u_strcmp(got,displayName)!=0) {
+ log_err("FAIL: getDisplayName() Wanted %s, got %s\n", dispName, austrdup(got));
+ }
+
+ size=0;
+ status=U_ZERO_ERROR;
+ size=uloc_getDisplayVariant(shortVariant, NULL, NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayVariant(shortVariant, NULL, got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ if(strcmp(austrdup(got),"FOO")!=0) {
+ log_err("FAIL: getDisplayVariant() Wanted: foo Got: %s\n", austrdup(got));
+ }
+ size=0;
+ status=U_ZERO_ERROR;
+ size=uloc_getDisplayVariant(bogusVariant, NULL, NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayVariant(bogusVariant, NULL, got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ if(strcmp(austrdup(got),"_FOO")!=0) {
+ log_err("FAIL: getDisplayVariant() Wanted: _FOO Got: %s\n", austrdup(got));
+ }
+ size=0;
+ status=U_ZERO_ERROR;
+ size=uloc_getDisplayVariant(bogusVariant2, NULL, NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayVariant(bogusVariant2, NULL, got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ if(strcmp(austrdup(got),"FOO_")!=0) {
+ log_err("FAIL: getDisplayVariant() Wanted: FOO_ Got: %s\n", austrdup(got));
+ }
+ size=0;
+ status=U_ZERO_ERROR;
+ size=uloc_getDisplayVariant(bogusVariant3, NULL, NULL, size, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ got=(UChar*)realloc(got, sizeof(UChar) * (size+1));
+ uloc_getDisplayVariant(bogusVariant3, NULL, got, size + 1, &status);
+ }
+ else {
+ log_err("FAIL: Didn't get U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ if(strcmp(austrdup(got),"_FOO_")!=0) {
+ log_err("FAIL: getDisplayVariant() Wanted: _FOO_ Got: %s\n", austrdup(got));
+ }
+ free(got);
+}
+
+
+static void TestObsoleteNames(void)
+{
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ char buff[256];
+
+ static const struct
+ {
+ char locale[9];
+ char lang3[4];
+ char lang[4];
+ char ctry3[4];
+ char ctry[4];
+ } tests[] =
+ {
+ { "eng_USA", "eng", "en", "USA", "US" },
+ { "kok", "kok", "kok", "", "" },
+ { "in", "ind", "in", "", "" },
+ { "id", "ind", "id", "", "" }, /* NO aliasing */
+ { "sh", "srp", "sh", "", "" },
+ { "zz_CS", "", "zz", "SCG", "CS" },
+ { "zz_FX", "", "zz", "FXX", "FX" },
+ { "zz_RO", "", "zz", "ROU", "RO" },
+ { "zz_TP", "", "zz", "TMP", "TP" },
+ { "zz_TL", "", "zz", "TLS", "TL" },
+ { "zz_ZR", "", "zz", "ZAR", "ZR" },
+ { "zz_FXX", "", "zz", "FXX", "FX" }, /* no aliasing. Doesn't go to PS(PSE). */
+ { "zz_ROM", "", "zz", "ROU", "RO" },
+ { "zz_ROU", "", "zz", "ROU", "RO" },
+ { "zz_ZAR", "", "zz", "ZAR", "ZR" },
+ { "zz_TMP", "", "zz", "TMP", "TP" },
+ { "zz_TLS", "", "zz", "TLS", "TL" },
+ { "zz_YUG", "", "zz", "YUG", "YU" },
+ { "mlt_PSE", "mlt", "mt", "PSE", "PS" },
+ { "iw", "heb", "iw", "", "" },
+ { "ji", "yid", "ji", "", "" },
+ { "jw", "jaw", "jw", "", "" },
+ { "sh", "srp", "sh", "", "" },
+ { "", "", "", "", "" }
+ };
+
+ for(i=0;tests[i].locale[0];i++)
+ {
+ const char *locale;
+
+ locale = tests[i].locale;
+ log_verbose("** %s:\n", locale);
+
+ status = U_ZERO_ERROR;
+ if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
+ {
+ log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
+ locale, uloc_getISO3Language(locale), tests[i].lang3);
+ }
+ else
+ {
+ log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
+ uloc_getISO3Language(locale) );
+ }
+
+ status = U_ZERO_ERROR;
+ uloc_getLanguage(locale, buff, 256, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error getting language from %s\n", locale);
+ }
+ else
+ {
+ if(strcmp(buff,tests[i].lang))
+ {
+ log_err("FAIL: uloc_getLanguage(%s)==\t\"%s\"\t expected \"%s\"\n",
+ locale, buff, tests[i].lang);
+ }
+ else
+ {
+ log_verbose(" uloc_getLanguage(%s)==\t%s\n", locale, buff);
+ }
+ }
+ if(strcmp(tests[i].lang3,uloc_getISO3Language(locale)))
+ {
+ log_err("FAIL: uloc_getISO3Language(%s)==\t\"%s\",\t expected \"%s\"\n",
+ locale, uloc_getISO3Language(locale), tests[i].lang3);
+ }
+ else
+ {
+ log_verbose(" uloc_getISO3Language()==\t\"%s\"\n",
+ uloc_getISO3Language(locale) );
+ }
+
+ if(strcmp(tests[i].ctry3,uloc_getISO3Country(locale)))
+ {
+ log_err("FAIL: uloc_getISO3Country(%s)==\t\"%s\",\t expected \"%s\"\n",
+ locale, uloc_getISO3Country(locale), tests[i].ctry3);
+ }
+ else
+ {
+ log_verbose(" uloc_getISO3Country()==\t\"%s\"\n",
+ uloc_getISO3Country(locale) );
+ }
+
+ status = U_ZERO_ERROR;
+ uloc_getCountry(locale, buff, 256, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("FAIL: error getting country from %s\n", locale);
+ }
+ else
+ {
+ if(strcmp(buff,tests[i].ctry))
+ {
+ log_err("FAIL: uloc_getCountry(%s)==\t\"%s\"\t expected \"%s\"\n",
+ locale, buff, tests[i].ctry);
+ }
+ else
+ {
+ log_verbose(" uloc_getCountry(%s)==\t%s\n", locale, buff);
+ }
+ }
+ }
+
+ if (uloc_getLCID("iw_IL") != uloc_getLCID("he_IL")) {
+ log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw_IL"), uloc_getLCID("he_IL"));
+ }
+
+ if (uloc_getLCID("iw") != uloc_getLCID("he")) {
+ log_err("he,iw LCID mismatch: %X versus %X\n", uloc_getLCID("iw"), uloc_getLCID("he"));
+ }
+
+#if 0
+
+ i = uloc_getLanguage("kok",NULL,0,&icu_err);
+ if(U_FAILURE(icu_err))
+ {
+ log_err("FAIL: Got %s trying to do uloc_getLanguage(kok)\n", u_errorName(icu_err));
+ }
+
+ icu_err = U_ZERO_ERROR;
+ uloc_getLanguage("kok",r1_buff,12,&icu_err);
+ if(U_FAILURE(icu_err))
+ {
+ log_err("FAIL: Got %s trying to do uloc_getLanguage(kok, buff)\n", u_errorName(icu_err));
+ }
+
+ r1_addr = (char *)uloc_getISO3Language("kok");
+
+ icu_err = U_ZERO_ERROR;
+ if (strcmp(r1_buff,"kok") != 0)
+ {
+ log_err("FAIL: uloc_getLanguage(kok)==%s not kok\n",r1_buff);
+ line--;
+ }
+ r1_addr = (char *)uloc_getISO3Language("in");
+ i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
+ if (strcmp(r1_buff,"id") != 0)
+ {
+ printf("uloc_getLanguage error (%s)\n",r1_buff);
+ line--;
+ }
+ r1_addr = (char *)uloc_getISO3Language("sh");
+ i = uloc_getLanguage(r1_addr,r1_buff,12,&icu_err);
+ if (strcmp(r1_buff,"sr") != 0)
+ {
+ printf("uloc_getLanguage error (%s)\n",r1_buff);
+ line--;
+ }
+
+ r1_addr = (char *)uloc_getISO3Country("zz_ZR");
+ strcpy(p1_buff,"zz_");
+ strcat(p1_buff,r1_addr);
+ i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
+ if (strcmp(r1_buff,"ZR") != 0)
+ {
+ printf("uloc_getCountry error (%s)\n",r1_buff);
+ line--;
+ }
+ r1_addr = (char *)uloc_getISO3Country("zz_FX");
+ strcpy(p1_buff,"zz_");
+ strcat(p1_buff,r1_addr);
+ i = uloc_getCountry(p1_buff,r1_buff,12,&icu_err);
+ if (strcmp(r1_buff,"FX") != 0)
+ {
+ printf("uloc_getCountry error (%s)\n",r1_buff);
+ line--;
+ }
+
+#endif
+
+}
+
+static void TestKeywordVariants(void)
+{
+ static const struct {
+ const char *localeID;
+ const char *expectedLocaleID;
+ const char *expectedLocaleIDNoKeywords;
+ const char *expectedCanonicalID;
+ const char *expectedKeywords[10];
+ int32_t numKeywords;
+ UErrorCode expectedStatus; /* from uloc_openKeywords */
+ } testCases[] = {
+ {
+ "de_DE@ currency = euro; C o ll A t i o n = Phonebook ; C alen dar = buddhist ",
+ "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
+ "de_DE",
+ "de_DE@calendar=buddhist;collation=Phonebook;currency=euro",
+ {"calendar", "collation", "currency"},
+ 3,
+ U_ZERO_ERROR
+ },
+ {
+ "de_DE@euro",
+ "de_DE@euro",
+ "de_DE",
+ "de_DE@currency=EUR",
+ {"","","","","","",""},
+ 0,
+ U_INVALID_FORMAT_ERROR /* must have '=' after '@' */
+ },
+ {
+ "de_DE@euro;collation=phonebook",
+ "de_DE", /* error result; bad format */
+ "de_DE", /* error result; bad format */
+ "de_DE", /* error result; bad format */
+ {"","","","","","",""},
+ 0,
+ U_INVALID_FORMAT_ERROR
+ }
+ };
+ UErrorCode status = U_ZERO_ERROR;
+
+ int32_t i = 0, j = 0;
+ int32_t resultLen = 0;
+ char buffer[256];
+ UEnumeration *keywords;
+ int32_t keyCount = 0;
+ const char *keyword = NULL;
+ int32_t keywordLen = 0;
+
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ status = U_ZERO_ERROR;
+ *buffer = 0;
+ keywords = uloc_openKeywords(testCases[i].localeID, &status);
+
+ if(status != testCases[i].expectedStatus) {
+ log_err("Expected to uloc_openKeywords(\"%s\") => status %s. Got %s instead\n",
+ testCases[i].localeID,
+ u_errorName(testCases[i].expectedStatus), u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ if(keywords) {
+ if((keyCount = uenum_count(keywords, &status)) != testCases[i].numKeywords) {
+ log_err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
+ }
+ if(keyCount) {
+ j = 0;
+ while((keyword = uenum_next(keywords, &keywordLen, &status))) {
+ if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
+ log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
+ }
+ j++;
+ }
+ j = 0;
+ uenum_reset(keywords, &status);
+ while((keyword = uenum_next(keywords, &keywordLen, &status))) {
+ if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
+ log_err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
+ }
+ j++;
+ }
+ }
+ uenum_close(keywords);
+ }
+ resultLen = uloc_getName(testCases[i].localeID, buffer, 256, &status);
+ if (uprv_strcmp(testCases[i].expectedLocaleID, buffer) != 0) {
+ log_err("Expected uloc_getName(\"%s\") => \"%s\"; got \"%s\"\n",
+ testCases[i].localeID, testCases[i].expectedLocaleID, buffer);
+ }
+ resultLen = uloc_canonicalize(testCases[i].localeID, buffer, 256, &status);
+ if (uprv_strcmp(testCases[i].expectedCanonicalID, buffer) != 0) {
+ log_err("Expected uloc_canonicalize(\"%s\") => \"%s\"; got \"%s\"\n",
+ testCases[i].localeID, testCases[i].expectedCanonicalID, buffer);
+ }
+ }
+
+}
+
+static void TestKeywordVariantParsing(void)
+{
+ static const struct {
+ const char *localeID;
+ const char *keyword;
+ const char *expectedValue;
+ } testCases[] = {
+ { "de_DE@ C o ll A t i o n = Phonebook ", "c o ll a t i o n", "Phonebook" },
+ { "de_DE", "collation", ""},
+ { "de_DE@collation=PHONEBOOK", "collation", "PHONEBOOK" },
+ { "de_DE@currency = euro; CoLLaTion = PHONEBOOk", "collatiON", "PHONEBOOk" },
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ int32_t i = 0;
+ int32_t resultLen = 0;
+ char buffer[256];
+
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ *buffer = 0;
+ resultLen = uloc_getKeywordValue(testCases[i].localeID, testCases[i].keyword, buffer, 256, &status);
+ if(uprv_strcmp(testCases[i].expectedValue, buffer) != 0) {
+ log_err("Expected to extract \"%s\" from \"%s\" for keyword \"%s\". Got \"%s\" instead\n",
+ testCases[i].expectedValue, testCases[i].localeID, testCases[i].keyword, buffer);
+ }
+ }
+}
+
+static const struct {
+ const char *l; /* locale */
+ const char *k; /* kw */
+ const char *v; /* value */
+ const char *x; /* expected */
+} kwSetTestCases[] = {
+#if 1
+ { "en_US", "calendar", "japanese", "en_US@calendar=japanese" },
+ { "en_US@", "calendar", "japanese", "en_US@calendar=japanese" },
+ { "en_US@calendar=islamic", "calendar", "japanese", "en_US@calendar=japanese" },
+ { "en_US@calendar=slovakian", "calendar", "gregorian", "en_US@calendar=gregorian" }, /* don't know what this means, but it has the same # of chars as gregorian */
+ { "en_US@calendar=gregorian", "calendar", "japanese", "en_US@calendar=japanese" },
+ { "de", "Currency", "CHF", "de@currency=CHF" },
+ { "de", "Currency", "CHF", "de@currency=CHF" },
+
+ { "en_US@collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
+ { "en_US@calendar=japanese", "collation", "phonebook", "en_US@calendar=japanese;collation=phonebook" },
+ { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
+ { "en_US@calendar=gregorian;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
+ { "en_US@calendar=slovakian;collation=phonebook", "calendar", "gregorian", "en_US@calendar=gregorian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */
+ { "en_US@calendar=slovakian;collation=videobook", "collation", "phonebook", "en_US@calendar=slovakian;collation=phonebook" }, /* don't know what this means, but it has the same # of chars as gregorian */
+ { "en_US@calendar=islamic;collation=phonebook", "calendar", "japanese", "en_US@calendar=japanese;collation=phonebook" },
+ { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" },
+#endif
+#if 1
+ { "mt@a=0;b=1;c=2;d=3", "c","j", "mt@a=0;b=1;c=j;d=3" },
+ { "mt@a=0;b=1;c=2;d=3", "x","j", "mt@a=0;b=1;c=2;d=3;x=j" },
+ { "mt@a=0;b=1;c=2;d=3", "a","f", "mt@a=f;b=1;c=2;d=3" },
+ { "mt@a=0;aa=1;aaa=3", "a","x", "mt@a=x;aa=1;aaa=3" },
+ { "mt@a=0;aa=1;aaa=3", "aa","x", "mt@a=0;aa=x;aaa=3" },
+ { "mt@a=0;aa=1;aaa=3", "aaa","x", "mt@a=0;aa=1;aaa=x" },
+ { "mt@a=0;aa=1;aaa=3", "a","yy", "mt@a=yy;aa=1;aaa=3" },
+ { "mt@a=0;aa=1;aaa=3", "aa","yy", "mt@a=0;aa=yy;aaa=3" },
+ { "mt@a=0;aa=1;aaa=3", "aaa","yy", "mt@a=0;aa=1;aaa=yy" },
+#endif
+#if 1
+ /* removal tests */
+ /* 1. removal of item at end */
+ { "de@collation=phonebook;currency=CHF", "currency", "", "de@collation=phonebook" },
+ { "de@collation=phonebook;currency=CHF", "currency", NULL, "de@collation=phonebook" },
+ /* 2. removal of item at beginning */
+ { "de@collation=phonebook;currency=CHF", "collation", "", "de@currency=CHF" },
+ { "de@collation=phonebook;currency=CHF", "collation", NULL, "de@currency=CHF" },
+ /* 3. removal of an item not there */
+ { "de@collation=phonebook;currency=CHF", "calendar", NULL, "de@collation=phonebook;currency=CHF" },
+ /* 4. removal of only item */
+ { "de@collation=phonebook", "collation", NULL, "de" },
+#endif
+ { "de@collation=phonebook", "Currency", "CHF", "de@collation=phonebook;currency=CHF" }
+};
+
+
+static void TestKeywordSet(void)
+{
+ int32_t i = 0;
+ int32_t resultLen = 0;
+ char buffer[1024];
+
+ char cbuffer[1024];
+
+ for(i = 0; i < sizeof(kwSetTestCases)/sizeof(kwSetTestCases[0]); i++) {
+ UErrorCode status = U_ZERO_ERROR;
+ memset(buffer,'%',1023);
+ strcpy(buffer, kwSetTestCases[i].l);
+
+ uloc_canonicalize(kwSetTestCases[i].l, cbuffer, 1023, &status);
+ if(strcmp(buffer,cbuffer)) {
+ log_verbose("note: [%d] wasn't canonical, should be: '%s' not '%s'. Won't check for canonicity in output.\n", i, cbuffer, buffer);
+ }
+ /* sanity check test case results for canonicity */
+ uloc_canonicalize(kwSetTestCases[i].x, cbuffer, 1023, &status);
+ if(strcmp(kwSetTestCases[i].x,cbuffer)) {
+ log_err("%s:%d: ERROR: kwSetTestCases[%d].x = '%s', should be %s (must be canonical)\n", __FILE__, __LINE__, i, kwSetTestCases[i].x, cbuffer);
+ }
+
+ resultLen = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, 1023, &status);
+ if(U_FAILURE(status)) {
+ log_err("Err on test case %d: got error %s\n", i, u_errorName(status));
+ continue;
+ }
+ if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=resultLen)) {
+ log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
+ kwSetTestCases[i].v, buffer, resultLen, kwSetTestCases[i].x, strlen(buffer));
+ } else {
+ log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,buffer);
+ }
+ }
+}
+
+static void TestKeywordSetError(void)
+{
+ char buffer[1024];
+ UErrorCode status;
+ int32_t res;
+ int32_t i;
+ int32_t blen;
+
+ /* 0-test whether an error condition modifies the buffer at all */
+ blen=0;
+ i=0;
+ memset(buffer,'%',1023);
+ status = U_ZERO_ERROR;
+ res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
+ if(status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("expected illegal err got %s\n", u_errorName(status));
+ return;
+ }
+ /* if(res!=strlen(kwSetTestCases[i].x)) {
+ log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
+ return;
+ } */
+ if(buffer[blen]!='%') {
+ log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
+ return;
+ }
+ log_verbose("0-buffer modify OK\n");
+
+ for(i=0;i<=2;i++) {
+ /* 1- test a short buffer with growing text */
+ blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
+ memset(buffer,'%',1023);
+ strcpy(buffer,kwSetTestCases[i].l);
+ status = U_ZERO_ERROR;
+ res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
+ if(status != U_BUFFER_OVERFLOW_ERROR) {
+ log_err("expected buffer overflow on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v);
+ return;
+ }
+ if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
+ log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
+ return;
+ }
+ if(buffer[blen]!='%') {
+ log_err("Buffer byte %d was modified: now %c\n", blen, buffer[blen]);
+ return;
+ }
+ log_verbose("1/%d-buffer modify OK\n",i);
+ }
+
+ for(i=3;i<=4;i++) {
+ /* 2- test a short buffer - text the same size or shrinking */
+ blen=(int32_t)strlen(kwSetTestCases[i].l)+1;
+ memset(buffer,'%',1023);
+ strcpy(buffer,kwSetTestCases[i].l);
+ status = U_ZERO_ERROR;
+ res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
+ if(status != U_ZERO_ERROR) {
+ log_err("expected zero error got %s\n", u_errorName(status));
+ return;
+ }
+ if(buffer[blen+1]!='%') {
+ log_err("Buffer byte %d was modified: now %c\n", blen+1, buffer[blen+1]);
+ return;
+ }
+ if(res!=(int32_t)strlen(kwSetTestCases[i].x)) {
+ log_err("expected result %d got %d\n", strlen(kwSetTestCases[i].x), res);
+ return;
+ }
+ if(strcmp(buffer,kwSetTestCases[i].x) || ((int32_t)strlen(buffer)!=res)) {
+ log_err("FAIL: #%d: %s + [%s=%s] -> %s (%d) expected %s (%d)\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k,
+ kwSetTestCases[i].v, buffer, res, kwSetTestCases[i].x, strlen(buffer));
+ } else {
+ log_verbose("pass: #%d: %s + [%s=%s] -> %s\n", i, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v,
+ buffer);
+ }
+ log_verbose("2/%d-buffer modify OK\n",i);
+ }
+}
+
+static int32_t _canonicalize(int32_t selector, /* 0==getName, 1==canonicalize */
+ const char* localeID,
+ char* result,
+ int32_t resultCapacity,
+ UErrorCode* ec) {
+ /* YOU can change this to use function pointers if you like */
+ switch (selector) {
+ case 0:
+ return uloc_getName(localeID, result, resultCapacity, ec);
+ case 1:
+ return uloc_canonicalize(localeID, result, resultCapacity, ec);
+ default:
+ return -1;
+ }
+}
+
+static void TestCanonicalization(void)
+{
+ static const struct {
+ const char *localeID; /* input */
+ const char *getNameID; /* expected getName() result */
+ const char *canonicalID; /* expected canonicalize() result */
+ } testCases[] = {
+ { "ca_ES_PREEURO-with-extra-stuff-that really doesn't make any sense-unless-you're trying to increase code coverage",
+ "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE",
+ "ca_ES_PREEURO_WITH_EXTRA_STUFF_THAT REALLY DOESN'T MAKE ANY SENSE_UNLESS_YOU'RE TRYING TO INCREASE CODE COVERAGE"},
+ { "ca_ES_PREEURO", "ca_ES_PREEURO", "ca_ES@currency=ESP" },
+ { "de_AT_PREEURO", "de_AT_PREEURO", "de_AT@currency=ATS" },
+ { "de_DE_PREEURO", "de_DE_PREEURO", "de_DE@currency=DEM" },
+ { "de_LU_PREEURO", "de_LU_PREEURO", "de_LU@currency=LUF" },
+ { "el_GR_PREEURO", "el_GR_PREEURO", "el_GR@currency=GRD" },
+ { "en_BE_PREEURO", "en_BE_PREEURO", "en_BE@currency=BEF" },
+ { "en_IE_PREEURO", "en_IE_PREEURO", "en_IE@currency=IEP" },
+ { "es_ES_PREEURO", "es_ES_PREEURO", "es_ES@currency=ESP" },
+ { "eu_ES_PREEURO", "eu_ES_PREEURO", "eu_ES@currency=ESP" },
+ { "fi_FI_PREEURO", "fi_FI_PREEURO", "fi_FI@currency=FIM" },
+ { "fr_BE_PREEURO", "fr_BE_PREEURO", "fr_BE@currency=BEF" },
+ { "fr_FR_PREEURO", "fr_FR_PREEURO", "fr_FR@currency=FRF" },
+ { "fr_LU_PREEURO", "fr_LU_PREEURO", "fr_LU@currency=LUF" },
+ { "ga_IE_PREEURO", "ga_IE_PREEURO", "ga_IE@currency=IEP" },
+ { "gl_ES_PREEURO", "gl_ES_PREEURO", "gl_ES@currency=ESP" },
+ { "it_IT_PREEURO", "it_IT_PREEURO", "it_IT@currency=ITL" },
+ { "nl_BE_PREEURO", "nl_BE_PREEURO", "nl_BE@currency=BEF" },
+ { "nl_NL_PREEURO", "nl_NL_PREEURO", "nl_NL@currency=NLG" },
+ { "pt_PT_PREEURO", "pt_PT_PREEURO", "pt_PT@currency=PTE" },
+ { "de__PHONEBOOK", "de__PHONEBOOK", "de@collation=phonebook" },
+ { "en_GB_EURO", "en_GB_EURO", "en_GB@currency=EUR" },
+ { "en_GB@EURO", "en_GB@EURO", "en_GB@currency=EUR" }, /* POSIX ID */
+ { "es__TRADITIONAL", "es__TRADITIONAL", "es@collation=traditional" },
+ { "hi__DIRECT", "hi__DIRECT", "hi@collation=direct" },
+ { "ja_JP_TRADITIONAL", "ja_JP_TRADITIONAL", "ja_JP@calendar=japanese" },
+ { "th_TH_TRADITIONAL", "th_TH_TRADITIONAL", "th_TH@calendar=buddhist" },
+ { "zh_TW_STROKE", "zh_TW_STROKE", "zh_Hant_TW@collation=stroke" },
+ { "zh__PINYIN", "zh__PINYIN", "zh@collation=pinyin" },
+ { "zh@collation=pinyin", "zh@collation=pinyin", "zh@collation=pinyin" },
+ { "zh_CN@collation=pinyin", "zh_CN@collation=pinyin", "zh_CN@collation=pinyin" },
+ { "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin", "zh_CN_CA@collation=pinyin" },
+ { "en_US_POSIX", "en_US_POSIX", "en_US_POSIX" },
+ { "hy_AM_REVISED", "hy_AM_REVISED", "hy_AM_REVISED" },
+ { "no_NO_NY", "no_NO_NY", "no_NO_NY" /* not: "nn_NO" [alan ICU3.0] */ },
+ { "no@ny", "no@ny", "no__NY" /* not: "nn" [alan ICU3.0] */ }, /* POSIX ID */
+ { "no-no.utf32@B", "no_NO.utf32@B", "no_NO_B" /* not: "nb_NO_B" [alan ICU3.0] */ }, /* POSIX ID */
+ { "qz-qz@Euro", "qz_QZ@Euro", "qz_QZ@currency=EUR" }, /* qz-qz uses private use iso codes */
+ { "en-BOONT", "en_BOONT", "en__BOONT" }, /* registered name */
+ { "de-1901", "de_1901", "de__1901" }, /* registered name */
+ { "de-1906", "de_1906", "de__1906" }, /* registered name */
+ { "sr-SP-Cyrl", "sr_SP_CYRL", "sr_Cyrl_CS" }, /* .NET name */
+ { "sr-SP-Latn", "sr_SP_LATN", "sr_Latn_CS" }, /* .NET name */
+ { "sr_YU_CYRILLIC", "sr_YU_CYRILLIC", "sr_Cyrl_CS" }, /* Linux name */
+ { "uz-UZ-Cyrl", "uz_UZ_CYRL", "uz_Cyrl_UZ" }, /* .NET name */
+ { "uz-UZ-Latn", "uz_UZ_LATN", "uz_Latn_UZ" }, /* .NET name */
+ { "zh-CHS", "zh_CHS", "zh_Hans" }, /* .NET name */
+ { "zh-CHT", "zh_CHT", "zh_Hant" }, /* .NET name This may change back to zh_Hant */
+
+ /* posix behavior that used to be performed by getName */
+ { "mr.utf8", "mr.utf8", "mr" },
+ { "de-tv.koi8r", "de_TV.koi8r", "de_TV" },
+ { "x-piglatin_ML.MBE", "x-piglatin_ML.MBE", "x-piglatin_ML" },
+ { "i-cherokee_US.utf7", "i-cherokee_US.utf7", "i-cherokee_US" },
+ { "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA.gb-18030", "x-filfli_MT_FILFLA" },
+ { "no-no-ny.utf8@B", "no_NO_NY.utf8@B", "no_NO_NY_B" /* not: "nn_NO" [alan ICU3.0] */ }, /* @ ignored unless variant is empty */
+
+ /* fleshing out canonicalization */
+ /* trim space and sort keywords, ';' is separator so not present at end in canonical form */
+ { "en_Hant_IL_VALLEY_GIRL@ currency = EUR; calendar = Japanese ;", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
+ /* already-canonical ids are not changed */
+ { "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR", "en_Hant_IL_VALLEY_GIRL@calendar=Japanese;currency=EUR" },
+ /* PRE_EURO and EURO conversions don't affect other keywords */
+ { "es_ES_PREEURO@CALendar=Japanese", "es_ES_PREEURO@calendar=Japanese", "es_ES@calendar=Japanese;currency=ESP" },
+ { "es_ES_EURO@SHOUT=zipeedeedoodah", "es_ES_EURO@shout=zipeedeedoodah", "es_ES@currency=EUR;shout=zipeedeedoodah" },
+ /* currency keyword overrides PRE_EURO and EURO currency */
+ { "es_ES_PREEURO@currency=EUR", "es_ES_PREEURO@currency=EUR", "es_ES@currency=EUR" },
+ { "es_ES_EURO@currency=ESP", "es_ES_EURO@currency=ESP", "es_ES@currency=ESP" },
+ /* norwegian is just too weird, if we handle things in their full generality */
+ { "no-Hant-GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$", "no_Hant_GB_NY@currency=$$$" /* not: "nn_Hant_GB@currency=$$$" [alan ICU3.0] */ },
+
+ /* test cases reflecting internal resource bundle usage */
+ { "root@kw=foo", "root@kw=foo", "root@kw=foo" },
+ { "@calendar=gregorian", "@calendar=gregorian", "@calendar=gregorian" },
+ { "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese", "ja_JP@calendar=Japanese" },
+ { "ja_JP", "ja_JP", "ja_JP" },
+
+ /* test case for "i-default" */
+ { "i-default", NULL, NULL }
+ };
+
+ static const char* label[] = { "getName", "canonicalize" };
+
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i, j, resultLen = 0, origResultLen;
+ char buffer[256];
+
+ for (i=0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ for (j=0; j<2; ++j) {
+ const char* expected = (j==0) ? testCases[i].getNameID : testCases[i].canonicalID;
+ *buffer = 0;
+ status = U_ZERO_ERROR;
+
+ if (expected == NULL) {
+ expected = uloc_getDefault();
+ }
+
+ /* log_verbose("testing %s -> %s\n", testCases[i], testCases[i].canonicalID); */
+ origResultLen = _canonicalize(j, testCases[i].localeID, NULL, 0, &status);
+ if (status != U_BUFFER_OVERFLOW_ERROR) {
+ log_err("FAIL: uloc_%s(%s) => %s, expected U_BUFFER_OVERFLOW_ERROR\n",
+ label[j], testCases[i].localeID, u_errorName(status));
+ continue;
+ }
+ status = U_ZERO_ERROR;
+ resultLen = _canonicalize(j, testCases[i].localeID, buffer, sizeof(buffer), &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uloc_%s(%s) => %s, expected U_ZERO_ERROR\n",
+ label[j], testCases[i].localeID, u_errorName(status));
+ continue;
+ }
+ if(uprv_strcmp(expected, buffer) != 0) {
+ log_err("FAIL: uloc_%s(%s) => \"%s\", expected \"%s\"\n",
+ label[j], testCases[i].localeID, buffer, expected);
+ } else {
+ log_verbose("Ok: uloc_%s(%s) => \"%s\"\n",
+ label[j], testCases[i].localeID, buffer);
+ }
+ if (resultLen != (int32_t)strlen(buffer)) {
+ log_err("FAIL: uloc_%s(%s) => len %d, expected len %d\n",
+ label[j], testCases[i].localeID, resultLen, strlen(buffer));
+ }
+ if (origResultLen != resultLen) {
+ log_err("FAIL: uloc_%s(%s) => preflight len %d != actual len %d\n",
+ label[j], testCases[i].localeID, origResultLen, resultLen);
+ }
+ }
+ }
+}
+
+static void TestDisplayKeywords(void)
+{
+ int32_t i;
+
+ static const struct {
+ const char *localeID;
+ const char *displayLocale;
+ UChar displayKeyword[200];
+ } testCases[] = {
+ { "ca_ES@currency=ESP", "de_AT",
+ {0x0057, 0x00e4, 0x0068, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000},
+ },
+ { "ja_JP@calendar=japanese", "de",
+ { 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
+ },
+ { "de_DE@collation=traditional", "de_DE",
+ {0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0075, 0x006e, 0x0067, 0x0000}
+ },
+ };
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char* keyword =NULL;
+ int32_t keywordLen = 0;
+ int32_t keywordCount = 0;
+ UChar *displayKeyword=NULL;
+ int32_t displayKeywordLen = 0;
+ UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
+ for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
+ if(U_FAILURE(status)){
+ log_err("uloc_getKeywords failed for locale id: %s with error : %s \n", testCases[i].localeID, u_errorName(status));
+ break;
+ }
+ /* the uenum_next returns NUL terminated string */
+ keyword = uenum_next(keywordEnum, &keywordLen, &status);
+ /* fetch the displayKeyword */
+ displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR;
+ displayKeywordLen++; /* for null termination */
+ displayKeyword = (UChar*) malloc(displayKeywordLen * U_SIZEOF_UCHAR);
+ displayKeywordLen = uloc_getDisplayKeyword(keyword, testCases[i].displayLocale, displayKeyword, displayKeywordLen, &status);
+ if(U_FAILURE(status)){
+ log_err("uloc_getDisplayKeyword filed for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
+ break;
+ }
+ if(u_strncmp(displayKeyword, testCases[i].displayKeyword, displayKeywordLen)!=0){
+ log_err("uloc_getDisplayKeyword did not get the expected value for keyword : %s in locale id: %s for display locale: %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale);
+ break;
+ }
+ }else{
+ log_err("uloc_getDisplayKeyword did not return the expected error. Error: %s\n", u_errorName(status));
+ }
+
+ free(displayKeyword);
+
+ }
+ uenum_close(keywordEnum);
+ }
+}
+
+static void TestDisplayKeywordValues(void){
+ int32_t i;
+
+ static const struct {
+ const char *localeID;
+ const char *displayLocale;
+ UChar displayKeywordValue[500];
+ } testCases[] = {
+ { "ca_ES@currency=ESP", "de_AT",
+ {0x0053, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0065, 0x0000}
+ },
+ { "de_AT@currency=ATS", "fr_FR",
+ {0x0073, 0x0063, 0x0068, 0x0069, 0x006c, 0x006c, 0x0069, 0x006e, 0x0067, 0x0020, 0x0061, 0x0075, 0x0074, 0x0072, 0x0069, 0x0063, 0x0068, 0x0069, 0x0065, 0x006e, 0x0000}
+ },
+ { "de_DE@currency=DEM", "it",
+ {0x004d, 0x0061, 0x0072, 0x0063, 0x006f, 0x0020, 0x0054, 0x0065, 0x0064, 0x0065, 0x0073, 0x0063, 0x006f, 0x0000}
+ },
+ { "el_GR@currency=GRD", "en",
+ {0x0047, 0x0072, 0x0065, 0x0065, 0x006b, 0x0020, 0x0044, 0x0072, 0x0061, 0x0063, 0x0068, 0x006d, 0x0061, 0x0000}
+ },
+ { "eu_ES@currency=ESP", "it_IT",
+ {0x0050, 0x0065, 0x0073, 0x0065, 0x0074, 0x0061, 0x0020, 0x0053, 0x0070, 0x0061, 0x0067, 0x006e, 0x006f, 0x006c, 0x0061, 0x0000}
+ },
+ { "de@collation=phonebook", "es",
+ {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000}
+ },
+
+ { "de_DE@collation=phonebook", "es",
+ {0x006F, 0x0072, 0x0064, 0x0065, 0x006E, 0x0020, 0x0064, 0x0065, 0x0020, 0x006C, 0x0069, 0x0073, 0x0074, 0x00ED, 0x006E, 0x0020, 0x0074, 0x0065, 0x006C, 0x0065, 0x0066, 0x00F3, 0x006E, 0x0069, 0x0063, 0x006F, 0x0000}
+ },
+ { "es_ES@collation=traditional","de",
+ {0x0054, 0x0072, 0x0061, 0x0064, 0x0069, 0x0074, 0x0069, 0x006f, 0x006e, 0x0065, 0x006c, 0x006c, 0x0065, 0x0020, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000}
+ },
+ { "ja_JP@calendar=japanese", "de",
+ {0x004a, 0x0061, 0x0070, 0x0061, 0x006e, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000}
+ },
+ };
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char* keyword =NULL;
+ int32_t keywordLen = 0;
+ int32_t keywordCount = 0;
+ UChar *displayKeywordValue = NULL;
+ int32_t displayKeywordValueLen = 0;
+ UEnumeration* keywordEnum = uloc_openKeywords(testCases[i].localeID, &status);
+ for(keywordCount = uenum_count(keywordEnum, &status); keywordCount > 0 ; keywordCount--){
+ if(U_FAILURE(status)){
+ log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", testCases[i].localeID, testCases[i].displayLocale, u_errorName(status));
+ break;
+ }
+ /* the uenum_next returns NUL terminated string */
+ keyword = uenum_next(keywordEnum, &keywordLen, &status);
+
+ /* fetch the displayKeywordValue */
+ displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR;
+ displayKeywordValueLen++; /* for null termination */
+ displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
+ displayKeywordValueLen = uloc_getDisplayKeywordValue(testCases[i].localeID, keyword, testCases[i].displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
+ if(U_FAILURE(status)){
+ log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
+ break;
+ }
+ if(u_strncmp(displayKeywordValue, testCases[i].displayKeywordValue, displayKeywordValueLen)!=0){
+ log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s with error : %s \n", testCases[i].localeID, keyword, testCases[i].displayLocale, u_errorName(status));
+ break;
+ }
+ }else{
+ log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
+ }
+ free(displayKeywordValue);
+ }
+ uenum_close(keywordEnum);
+ }
+ {
+ /* test a multiple keywords */
+ UErrorCode status = U_ZERO_ERROR;
+ const char* keyword =NULL;
+ int32_t keywordLen = 0;
+ int32_t keywordCount = 0;
+ const char* localeID = "es@collation=phonebook;calendar=buddhist;currency=DEM";
+ const char* displayLocale = "de";
+ static const UChar expected[][50] = {
+ {0x0042, 0x0075, 0x0064, 0x0064, 0x0068, 0x0069, 0x0073, 0x0074, 0x0069, 0x0073, 0x0063, 0x0068, 0x0065, 0x0072, 0x0020, 0x004b, 0x0061, 0x006c, 0x0065, 0x006e, 0x0064, 0x0065, 0x0072, 0x0000},
+
+ {0x0054, 0x0065, 0x006c, 0x0065, 0x0066, 0x006f, 0x006e, 0x0062, 0x0075, 0x0063, 0x0068, 0x002d, 0x0053, 0x006f, 0x0072, 0x0074, 0x0069, 0x0065, 0x0072, 0x0072, 0x0065, 0x0067, 0x0065, 0x006c, 0x006e, 0x0000},
+ {0x0044, 0x0065, 0x0075, 0x0074, 0x0073, 0x0063, 0x0068, 0x0065, 0x0020, 0x004d, 0x0061, 0x0072, 0x006b, 0x0000},
+ };
+
+ UEnumeration* keywordEnum = uloc_openKeywords(localeID, &status);
+
+ for(keywordCount = 0; keywordCount < uenum_count(keywordEnum, &status) ; keywordCount++){
+ UChar *displayKeywordValue = NULL;
+ int32_t displayKeywordValueLen = 0;
+ if(U_FAILURE(status)){
+ log_err("uloc_getKeywords failed for locale id: %s in display locale: % with error : %s \n", localeID, displayLocale, u_errorName(status));
+ break;
+ }
+ /* the uenum_next returns NUL terminated string */
+ keyword = uenum_next(keywordEnum, &keywordLen, &status);
+
+ /* fetch the displayKeywordValue */
+ displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR;
+ displayKeywordValueLen++; /* for null termination */
+ displayKeywordValue = (UChar*)malloc(displayKeywordValueLen * U_SIZEOF_UCHAR);
+ displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, keyword, displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
+ if(U_FAILURE(status)){
+ log_err("uloc_getDisplayKeywordValue failed for keyword : %s in locale id: %s for display locale: %s with error : %s \n", localeID, keyword, displayLocale, u_errorName(status));
+ break;
+ }
+ if(u_strncmp(displayKeywordValue, expected[keywordCount], displayKeywordValueLen)!=0){
+ log_err("uloc_getDisplayKeywordValue did not return the expected value keyword : %s in locale id: %s for display locale: %s \n", localeID, keyword, displayLocale);
+ break;
+ }
+ }else{
+ log_err("uloc_getDisplayKeywordValue did not return the expected error. Error: %s\n", u_errorName(status));
+ }
+ free(displayKeywordValue);
+ }
+ uenum_close(keywordEnum);
+
+ }
+ {
+ /* Test non existent keywords */
+ UErrorCode status = U_ZERO_ERROR;
+ const char* localeID = "es";
+ const char* displayLocale = "de";
+ UChar *displayKeywordValue = NULL;
+ int32_t displayKeywordValueLen = 0;
+
+ /* fetch the displayKeywordValue */
+ displayKeywordValueLen = uloc_getDisplayKeywordValue(localeID, "calendar", displayLocale, displayKeywordValue, displayKeywordValueLen, &status);
+ if(U_FAILURE(status)) {
+ log_err("uloc_getDisplaykeywordValue returned error status %s\n", u_errorName(status));
+ } else if(displayKeywordValueLen != 0) {
+ log_err("uloc_getDisplaykeywordValue returned %d should be 0 \n", displayKeywordValueLen);
+ }
+ }
+}
+
+
+static void TestGetBaseName(void) {
+ static const struct {
+ const char *localeID;
+ const char *baseName;
+ } testCases[] = {
+ { "de_DE@ C o ll A t i o n = Phonebook ", "de_DE" },
+ { "de@currency = euro; CoLLaTion = PHONEBOOk", "de" },
+ { "ja@calendar = buddhist", "ja" }
+ };
+
+ int32_t i = 0, baseNameLen = 0;
+ char baseName[256];
+ UErrorCode status = U_ZERO_ERROR;
+
+ for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
+ baseNameLen = uloc_getBaseName(testCases[i].localeID, baseName, 256, &status);
+ if(strcmp(testCases[i].baseName, baseName)) {
+ log_err("For locale \"%s\" expected baseName \"%s\", but got \"%s\"\n",
+ testCases[i].localeID, testCases[i].baseName, baseName);
+ return;
+ }
+ }
+
+}
+
+
+/* Jitterbug 4115 */
+static void TestDisplayNameWarning(void) {
+ UChar name[256];
+ int32_t size;
+ UErrorCode status = U_ZERO_ERROR;
+
+ size = uloc_getDisplayLanguage("qqq", "kl", name, sizeof(name)/sizeof(name[0]), &status);
+ if (status != U_USING_DEFAULT_WARNING) {
+ log_err("For language \"qqq\" in locale \"kl\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
+ u_errorName(status));
+ }
+}
+
+
+/**
+ * Compare two locale IDs. If they are equal, return 0. If `string'
+ * starts with `prefix' plus an additional element, that is, string ==
+ * prefix + '_' + x, then return 1. Otherwise return a value < 0.
+ */
+static UBool _loccmp(const char* string, const char* prefix) {
+ int32_t slen = (int32_t)uprv_strlen(string),
+ plen = (int32_t)uprv_strlen(prefix);
+ int32_t c = uprv_strncmp(string, prefix, plen);
+ /* 'root' is less than everything */
+ if (uprv_strcmp(prefix, "root") == 0) {
+ return (uprv_strcmp(string, "root") == 0) ? 0 : 1;
+ }
+ if (c) return -1; /* mismatch */
+ if (slen == plen) return 0;
+ if (string[plen] == '_') return 1;
+ return -2; /* false match, e.g. "en_USX" cmp "en_US" */
+}
+
+static void _checklocs(const char* label,
+ const char* req,
+ const char* valid,
+ const char* actual) {
+ /* We want the valid to be strictly > the bogus requested locale,
+ and the valid to be >= the actual. */
+ if (_loccmp(req, valid) > 0 &&
+ _loccmp(valid, actual) >= 0) {
+ log_verbose("%s; req=%s, valid=%s, actual=%s\n",
+ label, req, valid, actual);
+ } else {
+ log_err("FAIL: %s; req=%s, valid=%s, actual=%s\n",
+ label, req, valid, actual);
+ }
+}
+
+static void TestGetLocale(void) {
+ UErrorCode ec = U_ZERO_ERROR;
+ UParseError pe;
+ UChar EMPTY[1] = {0};
+
+ /* === udat === */
+#if !UCONFIG_NO_FORMATTING
+ {
+ UDateFormat *obj;
+ const char *req = "en_US_REDWOODSHORES", *valid, *actual;
+ obj = udat_open(UDAT_DEFAULT, UDAT_DEFAULT,
+ req,
+ NULL, 0,
+ NULL, 0, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("udat_open failed.Error %s\n", u_errorName(ec));
+ return;
+ }
+ valid = udat_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = udat_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("udat_getLocaleByType() failed\n");
+ return;
+ }
+ _checklocs("udat", req, valid, actual);
+ udat_close(obj);
+ }
+#endif
+
+ /* === ucal === */
+#if !UCONFIG_NO_FORMATTING
+ {
+ UCalendar *obj;
+ const char *req = "fr_FR_PROVENCAL", *valid, *actual;
+ obj = ucal_open(NULL, 0,
+ req,
+ UCAL_GREGORIAN,
+ &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ucal_open failed with error: %s\n", u_errorName(ec));
+ return;
+ }
+ valid = ucal_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = ucal_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ucal_getLocaleByType() failed\n");
+ return;
+ }
+ _checklocs("ucal", req, valid, actual);
+ ucal_close(obj);
+ }
+#endif
+
+ /* === unum === */
+#if !UCONFIG_NO_FORMATTING
+ {
+ UNumberFormat *obj;
+ const char *req = "zh_Hant_TW_TAINAN", *valid, *actual;
+ obj = unum_open(UNUM_DECIMAL,
+ NULL, 0,
+ req,
+ &pe, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("unum_open failed\n");
+ return;
+ }
+ valid = unum_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = unum_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("unum_getLocaleByType() failed\n");
+ return;
+ }
+ _checklocs("unum", req, valid, actual);
+ unum_close(obj);
+ }
+#endif
+
+ /* === umsg === */
+#if 0
+ /* commented out by weiv 01/12/2005. umsg_getLocaleByType is to be removed */
+#if !UCONFIG_NO_FORMATTING
+ {
+ UMessageFormat *obj;
+ const char *req = "ja_JP_TAKAYAMA", *valid, *actual;
+ UBool test;
+ obj = umsg_open(EMPTY, 0,
+ req,
+ &pe, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("umsg_open failed\n");
+ return;
+ }
+ valid = umsg_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = umsg_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("umsg_getLocaleByType() failed\n");
+ return;
+ }
+ /* We want the valid to be strictly > the bogus requested locale,
+ and the valid to be >= the actual. */
+ /* TODO MessageFormat is currently just storing the locale it is given.
+ As a result, it will return whatever it was given, even if the
+ locale is invalid. */
+ test = (_cmpversion("3.2") <= 0) ?
+ /* Here is the weakened test for 3.0: */
+ (_loccmp(req, valid) >= 0) :
+ /* Here is what the test line SHOULD be: */
+ (_loccmp(req, valid) > 0);
+
+ if (test &&
+ _loccmp(valid, actual) >= 0) {
+ log_verbose("umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
+ } else {
+ log_err("FAIL: umsg; req=%s, valid=%s, actual=%s\n", req, valid, actual);
+ }
+ umsg_close(obj);
+ }
+#endif
+#endif
+
+ /* === ubrk === */
+#if !UCONFIG_NO_BREAK_ITERATION
+ {
+ UBreakIterator *obj;
+ const char *req = "ar_KW_ABDALI", *valid, *actual;
+ obj = ubrk_open(UBRK_WORD,
+ req,
+ EMPTY,
+ 0,
+ &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ubrk_open failed. Error: %s \n", u_errorName(ec));
+ return;
+ }
+ valid = ubrk_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = ubrk_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ubrk_getLocaleByType() failed\n");
+ return;
+ }
+ _checklocs("ubrk", req, valid, actual);
+ ubrk_close(obj);
+ }
+#endif
+
+ /* === ucol === */
+#if !UCONFIG_NO_COLLATION
+ {
+ UCollator *obj;
+ const char *req = "es_AR_BUENOSAIRES", *valid, *actual;
+ obj = ucol_open(req, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ucol_open failed\n");
+ return;
+ }
+ valid = ucol_getLocaleByType(obj, ULOC_VALID_LOCALE, &ec);
+ actual = ucol_getLocaleByType(obj, ULOC_ACTUAL_LOCALE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("ucol_getLocaleByType() failed\n");
+ return;
+ }
+ _checklocs("ucol", req, valid, actual);
+ ucol_close(obj);
+ }
+#endif
+}
+
+static void TestNonexistentLanguageExemplars(void) {
+ /* JB 4068 - Nonexistent language */
+ UErrorCode ec = U_ZERO_ERROR;
+ ULocaleData *uld = ulocdata_open("qqq",&ec);
+ if (ec != U_USING_DEFAULT_WARNING) {
+ log_err("Exemplar set for \"qqq\", expecting U_USING_DEFAULT_WARNING, but got %s\n",
+ u_errorName(ec));
+ }
+ uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
+ ulocdata_close(uld);
+}
+
+static void TestLocDataErrorCodeChaining(void) {
+ UErrorCode ec = U_USELESS_COLLATOR_ERROR;
+ ulocdata_open(NULL, &ec);
+ ulocdata_getExemplarSet(NULL, NULL, 0, ULOCDATA_ES_STANDARD, &ec);
+ ulocdata_getDelimiter(NULL, ULOCDATA_DELIMITER_COUNT, NULL, -1, &ec);
+ ulocdata_getMeasurementSystem(NULL, &ec);
+ ulocdata_getPaperSize(NULL, NULL, NULL, &ec);
+ if (ec != U_USELESS_COLLATOR_ERROR) {
+ log_err("ulocdata API changed the error code to %s\n", u_errorName(ec));
+ }
+}
+
+static void TestLanguageExemplarsFallbacks(void) {
+ /* Test that en_US fallsback, but en doesn't fallback. */
+ UErrorCode ec = U_ZERO_ERROR;
+ ULocaleData *uld = ulocdata_open("en_US",&ec);
+ uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
+ if (ec != U_USING_FALLBACK_WARNING) {
+ log_err("Exemplar set for \"en_US\", expecting U_USING_FALLBACK_WARNING, but got %s\n",
+ u_errorName(ec));
+ }
+ ulocdata_close(uld);
+ ec = U_ZERO_ERROR;
+ uld = ulocdata_open("en",&ec);
+ uset_close(ulocdata_getExemplarSet(uld, NULL, 0, ULOCDATA_ES_STANDARD, &ec));
+ if (ec != U_ZERO_ERROR) {
+ log_err("Exemplar set for \"en\", expecting U_ZERO_ERROR, but got %s\n",
+ u_errorName(ec));
+ }
+ ulocdata_close(uld);
+}
+
+static void TestAcceptLanguage(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UAcceptResult outResult;
+ UEnumeration *available;
+ char tmp[200];
+ int i;
+ int32_t rc = 0;
+
+ struct {
+ int32_t httpSet;
+ const char *icuSet;
+ const char *expect;
+ UAcceptResult res;
+ } tests[] = {
+ /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID },
+ /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID },
+ /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK },
+ /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED },
+ /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID },
+ };
+ const int32_t numTests = sizeof(tests)/sizeof(tests[0]);
+ static const char *http[] = {
+ /*0*/ "mt-mt, ja;q=0.76, en-us;q=0.95, en;q=0.92, en-gb;q=0.89, fr;q=0.87, iu-ca;q=0.84, iu;q=0.82, ja-jp;q=0.79, mt;q=0.97, de-de;q=0.74, de;q=0.71, es;q=0.68, it-it;q=0.66, it;q=0.63, vi-vn;q=0.61, vi;q=0.58, nl-nl;q=0.55, nl;q=0.53, th-th-traditional;q=.01",
+ /*1*/ "ja;q=0.5, en;q=0.8, tlh",
+ /*2*/ "en-wf, de-lx;q=0.8",
+ /*3*/ "mga-ie;q=0.9, tlh",
+ /*4*/ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, "
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
+ "es"
+ };
+
+ for(i=0;i<numTests;i++) {
+ outResult = -3;
+ status=U_ZERO_ERROR;
+ log_verbose("test #%d: http[%s], ICU[%s], expect %s, %d\n",
+ i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res);
+
+ available = ures_openAvailableLocales(tests[i].icuSet, &status);
+ tmp[0]=0;
+ rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status);
+ uenum_close(available);
+ log_verbose(" got %s, %d [%s]\n", tmp[0]?tmp:"(EMPTY)", outResult, u_errorName(status));
+ if(outResult != tests[i].res) {
+ log_err("FAIL: #%d: expected outResult of %d but got %d\n", i, tests[i].res, outResult);
+ log_info("test #%d: http[%s], ICU[%s], expect %s, %d\n",
+ i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res);
+ }
+ if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
+ log_err("FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
+ log_info("test #%d: http[%s], ICU[%s], expect %s, %d\n",
+ i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, tests[i].res);
+ }
+ }
+}
+
+static const char* LOCALE_ALIAS[][2] = {
+ {"in", "id"},
+ {"in_ID", "id_ID"},
+ {"iw", "he"},
+ {"iw_IL", "he_IL"},
+ {"ji", "yi"},
+ {"en_BU", "en_MM"},
+ {"en_DY", "en_BJ"},
+ {"en_HV", "en_BF"},
+ {"en_NH", "en_VU"},
+ {"en_RH", "en_ZW"},
+ {"en_TP", "en_TL"},
+ {"en_ZR", "en_CD"}
+};
+static UBool isLocaleAvailable(UResourceBundle* resIndex, const char* loc){
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+ ures_getStringByKey(resIndex, loc,&len, &status);
+ if(U_FAILURE(status)){
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void TestCalendar() {
+#if !UCONFIG_NO_FORMATTING
+ int i;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ UCalendar* c1 = NULL;
+ UCalendar* c2 = NULL;
+
+ /*Test function "getLocale(ULocale.VALID_LOCALE)"*/
+ const char* l1 = ucal_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
+ const char* l2 = ucal_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
+
+ if(!isLocaleAvailable(resIndex, newLoc)){
+ continue;
+ }
+ c1 = ucal_open(NULL, -1, oldLoc, UCAL_GREGORIAN, &status);
+ c2 = ucal_open(NULL, -1, newLoc, UCAL_GREGORIAN, &status);
+
+ if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0 || status!=U_ZERO_ERROR) {
+ log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
+ }
+ log_verbose("ucal_getLocaleByType old:%s new:%s\n", l1, l2);
+ ucal_close(c1);
+ ucal_close(c2);
+ }
+ ures_close(resIndex);
+#endif
+}
+
+static void TestDateFormat() {
+#if !UCONFIG_NO_FORMATTING
+ int i;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ UDateFormat* df1 = NULL;
+ UDateFormat* df2 = NULL;
+ const char* l1 = NULL;
+ const char* l2 = NULL;
+
+ if(!isLocaleAvailable(resIndex, newLoc)){
+ continue;
+ }
+ df1 = udat_open(UDAT_FULL, UDAT_FULL,oldLoc, NULL, 0, NULL, -1, &status);
+ df2 = udat_open(UDAT_FULL, UDAT_FULL,newLoc, NULL, 0, NULL, -1, &status);
+ if(U_FAILURE(status)){
+ log_err("Creation of date format failed %s\n", u_errorName(status));
+ return;
+ }
+ /*Test function "getLocale"*/
+ l1 = udat_getLocaleByType(df1, ULOC_VALID_LOCALE, &status);
+ l2 = udat_getLocaleByType(df2, ULOC_VALID_LOCALE, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the locale by type failed. %s\n", u_errorName(status));
+ }
+ if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
+ log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
+ }
+ log_verbose("udat_getLocaleByType old:%s new:%s\n", l1, l2);
+ udat_close(df1);
+ udat_close(df2);
+ }
+ ures_close(resIndex);
+#endif
+}
+
+static void TestCollation() {
+#if !UCONFIG_NO_COLLATION
+ int i;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ UCollator* c1 = NULL;
+ UCollator* c2 = NULL;
+ const char* l1 = NULL;
+ const char* l2 = NULL;
+
+ status = U_ZERO_ERROR;
+ if(!isLocaleAvailable(resIndex, newLoc)){
+ continue;
+ }
+ if(U_FAILURE(status)){
+ log_err("Creation of collators failed %s\n", u_errorName(status));
+ return;
+ }
+ c1 = ucol_open(oldLoc, &status);
+ c2 = ucol_open(newLoc, &status);
+ l1 = ucol_getLocaleByType(c1, ULOC_VALID_LOCALE, &status);
+ l2 = ucol_getLocaleByType(c2, ULOC_VALID_LOCALE, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the locale names failed failed %s\n", u_errorName(status));
+ }
+ if (strcmp(newLoc,l1)!=0 || strcmp(l1,l2)!=0) {
+ log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
+ }
+ log_verbose("ucol_getLocaleByType old:%s new:%s\n", l1, l2);
+ ucol_close(c1);
+ ucol_close(c2);
+ }
+ ures_close(resIndex);
+#endif
+}
+
+static void TestULocale() {
+ int i;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *resIndex = ures_open(NULL,"res_index", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ UChar name1[256], name2[256];
+ char names1[256], names2[256];
+ int32_t capacity = 256;
+
+ status = U_ZERO_ERROR;
+ if(!isLocaleAvailable(resIndex, newLoc)){
+ continue;
+ }
+ uloc_getDisplayName(oldLoc, ULOC_US, name1, capacity, &status);
+ if(U_FAILURE(status)){
+ log_err("uloc_getDisplayName(%s) failed %s\n", oldLoc, u_errorName(status));
+ }
+
+ uloc_getDisplayName(newLoc, ULOC_US, name2, capacity, &status);
+ if(U_FAILURE(status)){
+ log_err("uloc_getDisplayName(%s) failed %s\n", newLoc, u_errorName(status));
+ }
+
+ if (u_strcmp(name1, name2)!=0) {
+ log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
+ }
+ u_austrcpy(names1, name1);
+ u_austrcpy(names2, name2);
+ log_verbose("uloc_getDisplayName old:%s new:%s\n", names1, names2);
+ }
+ ures_close(resIndex);
+
+}
+
+static void TestUResourceBundle() {
+ const char* us1;
+ const char* us2;
+
+ UResourceBundle* rb1 = NULL;
+ UResourceBundle* rb2 = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ int i;
+ UResourceBundle *resIndex = NULL;
+ if(U_FAILURE(status)){
+ log_err("Could not open res_index.res. Exiting. Error: %s\n", u_errorName(status));
+ return;
+ }
+ resIndex = ures_open(NULL,"res_index", &status);
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ if(!isLocaleAvailable(resIndex, newLoc)){
+ continue;
+ }
+ rb1 = ures_open(NULL, oldLoc, &status);
+ if (U_FAILURE(status)) {
+ log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
+ }
+
+ us1 = ures_getLocale(rb1, &status);
+
+ status = U_ZERO_ERROR;
+ rb2 = ures_open(NULL, newLoc, &status);
+ if (U_FAILURE(status)) {
+ log_err("ures_open(%s) failed %s\n", oldLoc, u_errorName(status));
+ }
+ us2 = ures_getLocale(rb2, &status);
+
+ if (strcmp(us1,newLoc)!=0 || strcmp(us1,us2)!=0 ) {
+ log_err("The locales are not equal!.Old: %s, New: %s \n", oldLoc, newLoc);
+ }
+
+ log_verbose("ures_getStringByKey old:%s new:%s\n", us1, us2);
+ ures_close(rb1);
+ rb1 = NULL;
+ ures_close(rb2);
+ rb2 = NULL;
+ }
+ ures_close(resIndex);
+}
+
+static void TestDisplayName() {
+
+ UChar oldCountry[256] = {'\0'};
+ UChar newCountry[256] = {'\0'};
+ UChar oldLang[256] = {'\0'};
+ UChar newLang[256] = {'\0'};
+ char country[256] ={'\0'};
+ char language[256] ={'\0'};
+ int32_t capacity = 256;
+ int i =0;
+ int j=0;
+ for (i=0; i<LENGTHOF(LOCALE_ALIAS); i++) {
+ const char* oldLoc = LOCALE_ALIAS[i][0];
+ const char* newLoc = LOCALE_ALIAS[i][1];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t available = uloc_countAvailable();
+
+ for(j=0; j<available; j++){
+
+ const char* dispLoc = uloc_getAvailable(j);
+ int32_t oldCountryLen = uloc_getDisplayCountry(oldLoc,dispLoc, oldCountry, capacity, &status);
+ int32_t newCountryLen = uloc_getDisplayCountry(newLoc, dispLoc, newCountry, capacity, &status);
+ int32_t oldLangLen = uloc_getDisplayLanguage(oldLoc, dispLoc, oldLang, capacity, &status);
+ int32_t newLangLen = uloc_getDisplayLanguage(newLoc, dispLoc, newLang, capacity, &status );
+
+ int32_t countryLen = uloc_getCountry(newLoc, country, capacity, &status);
+ int32_t langLen = uloc_getLanguage(newLoc, language, capacity, &status);
+ /* there is a display name for the current country ID */
+ if(countryLen != newCountryLen ){
+ if(u_strncmp(oldCountry,newCountry,oldCountryLen)!=0){
+ log_err("uloc_getDisplayCountry() failed for %s in display locale %s \n", oldLoc, dispLoc);
+ }
+ }
+ /* there is a display name for the current lang ID */
+ if(langLen!=newLangLen){
+ if(u_strncmp(oldLang,newLang,oldLangLen)){
+ log_err("uloc_getDisplayLanguage() failed for %s in display locale %s \n", oldLoc, dispLoc); }
+ }
+ }
+ }
+}
+
+static void TestGetLocaleForLCID() {
+ int32_t i, length, lengthPre;
+ const char* testLocale = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ char temp2[40], temp3[40];
+ uint32_t lcid;
+
+ lcid = uloc_getLCID("en_US");
+ if (lcid != 0x0409) {
+ log_err(" uloc_getLCID(\"en_US\") = %d, expected 0x0409\n", lcid);
+ }
+
+ lengthPre = uloc_getLocaleForLCID(lcid, temp2, 4, &status);
+ if (status != U_BUFFER_OVERFLOW_ERROR) {
+ log_err(" unexpected result from uloc_getLocaleForLCID with small buffer: %s\n", u_errorName(status));
+ }
+ else {
+ status = U_ZERO_ERROR;
+ }
+
+ length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
+ if (U_FAILURE(status)) {
+ log_err(" unexpected result from uloc_getLocaleForLCID(0x0409): %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+
+ if (length != lengthPre) {
+ log_err(" uloc_getLocaleForLCID(0x0409): returned length %d does not match preflight length %d\n", length, lengthPre);
+ }
+
+ length = uloc_getLocaleForLCID(0x12345, temp2, sizeof(temp2)/sizeof(char), &status);
+ if (U_SUCCESS(status)) {
+ log_err(" unexpected result from uloc_getLocaleForLCID(0x12345): %s, status %s\n", temp2, u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+
+ log_verbose("Testing getLocaleForLCID vs. locale data\n");
+ for (i = 0; i < LOCALE_SIZE; i++) {
+
+ testLocale=rawData2[NAME][i];
+
+ log_verbose("Testing %s ......\n", testLocale);
+
+ sscanf(rawData2[LCID][i], "%x", &lcid);
+ length = uloc_getLocaleForLCID(lcid, temp2, sizeof(temp2)/sizeof(char), &status);
+ if (U_FAILURE(status)) {
+ log_err(" unexpected failure of uloc_getLocaleForLCID(%#04x), status %s\n", lcid, u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+
+ if (length != uprv_strlen(temp2)) {
+ log_err(" returned length %d not correct for uloc_getLocaleForLCID(%#04x), expected %d\n", length, lcid, uprv_strlen(temp2));
+ }
+
+ /* Compare language, country, script */
+ length = uloc_getLanguage(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
+ if (U_FAILURE(status)) {
+ log_err(" couldn't get language in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ else if (uprv_strcmp(temp3, rawData2[LANG][i]) && !(uprv_strcmp(temp3, "nn") == 0 && uprv_strcmp(rawData2[VAR][i], "NY") == 0)) {
+ log_err(" language doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[LANG][i], lcid, temp2);
+ }
+
+ length = uloc_getScript(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
+ if (U_FAILURE(status)) {
+ log_err(" couldn't get script in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ else if (uprv_strcmp(temp3, rawData2[SCRIPT][i])) {
+ log_err(" script doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[SCRIPT][i], lcid, temp2);
+ }
+
+ length = uloc_getCountry(temp2, temp3, sizeof(temp3)/sizeof(char), &status);
+ if (U_FAILURE(status)) {
+ log_err(" couldn't get country in uloc_getLocaleForLCID(%#04x) = %s, status %s\n", lcid, temp2, u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ else if (uprv_strlen(rawData2[CTRY][i]) && uprv_strcmp(temp3, rawData2[CTRY][i])) {
+ log_err(" country doesn't match expected %s in in uloc_getLocaleForLCID(%#04x) = %s\n", rawData2[CTRY][i], lcid, temp2);
+ }
+ }
+
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h
new file mode 100644
index 00000000000..c82fa356aed
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cloctst.h
@@ -0,0 +1,114 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CLOCTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*/
+#ifndef _CLOCTEST
+#define _CLOCTEST
+
+#include "cintltst.h"
+/*C API TEST FOR LOCALE */
+
+/**
+ * Test functions to set and get data fields
+ **/
+static void TestBasicGetters(void);
+static void TestPrefixes(void);
+/**
+ * Use Locale to access Resource file data and compare against expected values
+ **/
+static void TestSimpleResourceInfo(void);
+/**
+ * Use Locale to access Resource file display names and compare against expected values
+ **/
+static void TestDisplayNames(void);
+/**
+ * Test getAvailableLocales
+ **/
+ static void TestGetAvailableLocales(void);
+/**
+ * Test functions to set and access a custom data directory
+ **/
+ static void TestDataDirectory(void);
+/**
+ * Test functions to test get ISO countries and Languages
+ **/
+ static void TestISOFunctions(void);
+/**
+ * Test functions to test get ISO3 countries and Languages Fallback
+ **/
+ static void TestISO3Fallback(void);
+/**
+ * Test functions to test get ISO3 countries and Languages for Uninstalled locales
+ **/
+ static void TestUninstalledISO3Names(void);
+ static void TestObsoleteNames(void);
+/**
+ * Test functions uloc_getDisplaynames()
+ **/
+ static void TestSimpleDisplayNames(void);
+/**
+ * Test functions uloc_getDisplaynames()
+ **/
+ static void TestVariantParsing(void);
+
+ /* Test getting keyword enumeratin */
+ static void TestKeywordVariants(void);
+
+ static void TestKeywordSet(void);
+ static void TestKeywordSetError(void);
+
+ /* Test getting keyword values */
+ static void TestKeywordVariantParsing(void);
+
+ /* Test warning for no data in getDisplay* */
+ static void TestDisplayNameWarning(void);
+
+ /* Test uloc_getLocaleForLCID */
+ static void TestGetLocaleForLCID(void);
+
+/**
+ * routine to perform subtests, used by TestDisplayNames
+ */
+ static void doTestDisplayNames(const char* inLocale, int32_t compareIndex);
+
+ static void TestCanonicalization(void);
+
+ static void TestDisplayKeywords(void);
+
+ static void TestDisplayKeywordValues(void);
+
+ static void TestGetBaseName(void);
+
+static void TestGetLocale(void);
+
+/**
+ * additional intialization for datatables storing expected values
+ */
+static void setUpDataTable(void);
+static void cleanUpDataTable(void);
+/*static void displayDataTable(void);*/
+static void TestAcceptLanguage(void);
+
+/**
+ * test locale aliases
+*/
+static void TestCalendar(void);
+static void TestDateFormat(void);
+static void TestCollation(void);
+static void TestULocale(void);
+static void TestUResourceBundle(void);
+static void TestDisplayName(void);
+
+static void TestAcceptLanguage(void);
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c
new file mode 100644
index 00000000000..89581eeebdb
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsccoll.c
@@ -0,0 +1,5075 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2001-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File cmsccoll.C
+*
+*******************************************************************************/
+/**
+ * These are the tests specific to ICU 1.8 and above, that I didn't know where
+ * to fit.
+ */
+
+#include <stdio.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/ucoleitr.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "unicode/ustring.h"
+#include "string.h"
+#include "ucol_imp.h"
+#include "ucol_tok.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "uassert.h"
+#include "unicode/parseerr.h"
+#include "unicode/ucnv.h"
+#include "uparse.h"
+
+#define LEN(a) (sizeof(a)/sizeof(a[0]))
+
+#define MAX_TOKEN_LEN 16
+
+typedef UCollationResult tst_strcoll(void *collator, const int object,
+ const UChar *source, const int sLen,
+ const UChar *target, const int tLen);
+
+
+
+const static char cnt1[][10] = {
+
+ "AA",
+ "AC",
+ "AZ",
+ "AQ",
+ "AB",
+ "ABZ",
+ "ABQ",
+ "Z",
+ "ABC",
+ "Q",
+ "B"
+};
+
+const static char cnt2[][10] = {
+ "DA",
+ "DAD",
+ "DAZ",
+ "MAR",
+ "Z",
+ "DAVIS",
+ "MARK",
+ "DAV",
+ "DAVI"
+};
+
+static void IncompleteCntTest(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar temp[90];
+ UChar t1[90];
+ UChar t2[90];
+
+ UCollator *coll = NULL;
+ uint32_t i = 0, j = 0;
+ uint32_t size = 0;
+
+ u_uastrcpy(temp, " & Z < ABC < Q < B");
+
+ coll = ucol_openRules(temp, u_strlen(temp), UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL,&status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(cnt1)/sizeof(cnt1[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ UCollationElements *iter;
+ u_uastrcpy(t1, cnt1[i]);
+ u_uastrcpy(t2, cnt1[j]);
+ doTest(coll, t1, t2, UCOL_LESS);
+ /* synwee : added collation element iterator test */
+ iter = ucol_openElements(coll, t2, u_strlen(t2), &status);
+ if (U_FAILURE(status)) {
+ log_err("Creation of iterator failed\n");
+ break;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ }
+ }
+ }
+
+ ucol_close(coll);
+
+
+ u_uastrcpy(temp, " & Z < DAVIS < MARK <DAV");
+ coll = ucol_openRules(temp, u_strlen(temp), UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(cnt2)/sizeof(cnt2[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ UCollationElements *iter;
+ u_uastrcpy(t1, cnt2[i]);
+ u_uastrcpy(t2, cnt2[j]);
+ doTest(coll, t1, t2, UCOL_LESS);
+
+ /* synwee : added collation element iterator test */
+ iter = ucol_openElements(coll, t2, u_strlen(t2), &status);
+ if (U_FAILURE(status)) {
+ log_err("Creation of iterator failed\n");
+ break;
+ }
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ }
+ }
+ }
+
+ ucol_close(coll);
+
+
+}
+
+const static char shifted[][20] = {
+ "black bird",
+ "black-bird",
+ "blackbird",
+ "black Bird",
+ "black-Bird",
+ "blackBird",
+ "black birds",
+ "black-birds",
+ "blackbirds"
+};
+
+const static UCollationResult shiftedTert[] = {
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_EQUAL
+};
+
+const static char nonignorable[][20] = {
+ "black bird",
+ "black Bird",
+ "black birds",
+ "black-bird",
+ "black-Bird",
+ "black-birds",
+ "blackbird",
+ "blackBird",
+ "blackbirds"
+};
+
+static void BlackBirdTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar t1[90];
+ UChar t2[90];
+
+ uint32_t i = 0, j = 0;
+ uint32_t size = 0;
+ UCollator *coll = ucol_open("en_US", &status);
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(nonignorable)/sizeof(nonignorable[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ u_uastrcpy(t1, nonignorable[i]);
+ u_uastrcpy(t2, nonignorable[j]);
+ doTest(coll, t1, t2, UCOL_LESS);
+ }
+ }
+ }
+
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(shifted)/sizeof(shifted[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ u_uastrcpy(t1, shifted[i]);
+ u_uastrcpy(t2, shifted[j]);
+ doTest(coll, t1, t2, UCOL_LESS);
+ }
+ }
+ }
+
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_TERTIARY, &status);
+ if(U_SUCCESS(status)) {
+ size = sizeof(shifted)/sizeof(shifted[0]);
+ for(i = 1; i < size; i++) {
+ u_uastrcpy(t1, shifted[i-1]);
+ u_uastrcpy(t2, shifted[i]);
+ doTest(coll, t1, t2, shiftedTert[i]);
+ }
+ }
+
+ ucol_close(coll);
+}
+
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {0x0041/*'A'*/, 0x0300, 0x0301, 0x0000},
+ {0x0041/*'A'*/, 0x0300, 0x0316, 0x0000},
+ {0x0041/*'A'*/, 0x0300, 0x0000},
+ {0x00C0, 0x0301, 0x0000},
+ /* this would work with forced normalization */
+ {0x00C0, 0x0316, 0x0000}
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {0x0041/*'A'*/, 0x0301, 0x0300, 0x0000},
+ {0x0041/*'A'*/, 0x0316, 0x0300, 0x0000},
+ {0x00C0, 0},
+ {0x0041/*'A'*/, 0x0301, 0x0300, 0x0000},
+ /* this would work with forced normalization */
+ {0x0041/*'A'*/, 0x0316, 0x0300, 0x0000}
+};
+
+const static UCollationResult results[] = {
+ UCOL_GREATER,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ UCOL_GREATER,
+ UCOL_EQUAL
+};
+
+static void FunkyATest(void)
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *myCollation;
+ myCollation = ucol_open("en_US", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing some A letters, for some reason\n");
+ ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 4 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+UColAttributeValue caseFirst[] = {
+ UCOL_OFF,
+ UCOL_LOWER_FIRST,
+ UCOL_UPPER_FIRST
+};
+
+
+UColAttributeValue alternateHandling[] = {
+ UCOL_NON_IGNORABLE,
+ UCOL_SHIFTED
+};
+
+UColAttributeValue caseLevel[] = {
+ UCOL_OFF,
+ UCOL_ON
+};
+
+UColAttributeValue strengths[] = {
+ UCOL_PRIMARY,
+ UCOL_SECONDARY,
+ UCOL_TERTIARY,
+ UCOL_QUATERNARY,
+ UCOL_IDENTICAL
+};
+
+#if 0
+static const char * strengthsC[] = {
+ "UCOL_PRIMARY",
+ "UCOL_SECONDARY",
+ "UCOL_TERTIARY",
+ "UCOL_QUATERNARY",
+ "UCOL_IDENTICAL"
+};
+
+static const char * caseFirstC[] = {
+ "UCOL_OFF",
+ "UCOL_LOWER_FIRST",
+ "UCOL_UPPER_FIRST"
+};
+
+
+static const char * alternateHandlingC[] = {
+ "UCOL_NON_IGNORABLE",
+ "UCOL_SHIFTED"
+};
+
+static const char * caseLevelC[] = {
+ "UCOL_OFF",
+ "UCOL_ON"
+};
+
+/* not used currently - does not test only prints */
+static void PrintMarkDavis(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar m[256];
+ uint8_t sortkey[256];
+ UCollator *coll = ucol_open("en_US", &status);
+ uint32_t h,i,j,k, sortkeysize;
+ uint32_t sizem = 0;
+ char buffer[512];
+ uint32_t len = 512;
+
+ log_verbose("PrintMarkDavis");
+
+ u_uastrcpy(m, "Mark Davis");
+ sizem = u_strlen(m);
+
+
+ m[1] = 0xe4;
+
+ for(i = 0; i<sizem; i++) {
+ fprintf(stderr, "\\u%04X ", m[i]);
+ }
+ fprintf(stderr, "\n");
+
+ for(h = 0; h<sizeof(caseFirst)/sizeof(caseFirst[0]); h++) {
+ ucol_setAttribute(coll, UCOL_CASE_FIRST, caseFirst[i], &status);
+ fprintf(stderr, "caseFirst: %s\n", caseFirstC[h]);
+
+ for(i = 0; i<sizeof(alternateHandling)/sizeof(alternateHandling[0]); i++) {
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, alternateHandling[i], &status);
+ fprintf(stderr, " AltHandling: %s\n", alternateHandlingC[i]);
+
+ for(j = 0; j<sizeof(caseLevel)/sizeof(caseLevel[0]); j++) {
+ ucol_setAttribute(coll, UCOL_CASE_LEVEL, caseLevel[j], &status);
+ fprintf(stderr, " caseLevel: %s\n", caseLevelC[j]);
+
+ for(k = 0; k<sizeof(strengths)/sizeof(strengths[0]); k++) {
+ ucol_setAttribute(coll, UCOL_STRENGTH, strengths[k], &status);
+ sortkeysize = ucol_getSortKey(coll, m, sizem, sortkey, 256);
+ fprintf(stderr, " strength: %s\n Sortkey: ", strengthsC[k]);
+ fprintf(stderr, "%s\n", ucol_sortKeyToString(coll, sortkey, buffer, &len));
+ }
+
+ }
+
+ }
+
+ }
+}
+#endif
+
+static void BillFairmanTest(void) {
+/*
+** check for actual locale via ICU resource bundles
+**
+** lp points to the original locale ("fr_FR_....")
+*/
+
+ UResourceBundle *lr,*cr;
+ UErrorCode lec = U_ZERO_ERROR;
+ const char *lp = "fr_FR_you_ll_never_find_this_locale";
+
+ log_verbose("BillFairmanTest\n");
+
+ lr = ures_open(NULL,lp,&lec);
+ if (lr) {
+ cr = ures_getByKey(lr,"collations",0,&lec);
+ if (cr) {
+ lp = ures_getLocale(cr,&lec);
+ if (lp) {
+ if (U_SUCCESS(lec)) {
+ if(strcmp(lp, "fr") != 0) {
+ log_err("Wrong locale for French Collation Data, expected \"fr\" got %s", lp);
+ }
+ }
+ }
+ ures_close(cr);
+ }
+ ures_close(lr);
+ }
+}
+
+static void testPrimary(UCollator* col, const UChar* p,const UChar* q){
+ UChar source[256] = { '\0'};
+ UChar target[256] = { '\0'};
+ UChar preP = 0x31a3;
+ UChar preQ = 0x310d;
+/*
+ UChar preP = (*p>0x0400 && *p<0x0500)?0x00e1:0x491;
+ UChar preQ = (*p>0x0400 && *p<0x0500)?0x0041:0x413;
+*/
+ /*log_verbose("Testing primary\n");*/
+
+ doTest(col, p, q, UCOL_LESS);
+/*
+ UCollationResult result = ucol_strcoll(col,p,u_strlen(p),q,u_strlen(q));
+
+ if(result!=UCOL_LESS){
+ aescstrdup(p,utfSource,256);
+ aescstrdup(q,utfTarget,256);
+ fprintf(file,"Primary failed source: %s target: %s \n", utfSource,utfTarget);
+ }
+*/
+ source[0] = preP;
+ u_strcpy(source+1,p);
+ target[0] = preQ;
+ u_strcpy(target+1,q);
+ doTest(col, source, target, UCOL_LESS);
+/*
+ fprintf(file,"Primary swamps 2nd failed source: %s target: %s \n", utfSource,utfTarget);
+*/
+}
+
+static void testSecondary(UCollator* col, const UChar* p,const UChar* q){
+ UChar source[256] = { '\0'};
+ UChar target[256] = { '\0'};
+
+ /*log_verbose("Testing secondary\n");*/
+
+ doTest(col, p, q, UCOL_LESS);
+/*
+ fprintf(file,"secondary failed source: %s target: %s \n", utfSource,utfTarget);
+*/
+ source[0] = 0x0053;
+ u_strcpy(source+1,p);
+ target[0]= 0x0073;
+ u_strcpy(target+1,q);
+
+ doTest(col, source, target, UCOL_LESS);
+/*
+ fprintf(file,"secondary swamps 3rd failed source: %s target: %s \n",utfSource,utfTarget);
+*/
+
+
+ u_strcpy(source,p);
+ source[u_strlen(p)] = 0x62;
+ source[u_strlen(p)+1] = 0;
+
+
+ u_strcpy(target,q);
+ target[u_strlen(q)] = 0x61;
+ target[u_strlen(q)+1] = 0;
+
+ doTest(col, source, target, UCOL_GREATER);
+
+/*
+ fprintf(file,"secondary is swamped by 1 failed source: %s target: %s \n",utfSource,utfTarget);
+*/
+}
+
+static void testTertiary(UCollator* col, const UChar* p,const UChar* q){
+ UChar source[256] = { '\0'};
+ UChar target[256] = { '\0'};
+
+ /*log_verbose("Testing tertiary\n");*/
+
+ doTest(col, p, q, UCOL_LESS);
+/*
+ fprintf(file,"Tertiary failed source: %s target: %s \n",utfSource,utfTarget);
+*/
+ source[0] = 0x0020;
+ u_strcpy(source+1,p);
+ target[0]= 0x002D;
+ u_strcpy(target+1,q);
+
+ doTest(col, source, target, UCOL_LESS);
+/*
+ fprintf(file,"Tertiary swamps 4th failed source: %s target: %s \n", utfSource,utfTarget);
+*/
+
+ u_strcpy(source,p);
+ source[u_strlen(p)] = 0xE0;
+ source[u_strlen(p)+1] = 0;
+
+ u_strcpy(target,q);
+ target[u_strlen(q)] = 0x61;
+ target[u_strlen(q)+1] = 0;
+
+ doTest(col, source, target, UCOL_GREATER);
+
+/*
+ fprintf(file,"Tertiary is swamped by 3rd failed source: %s target: %s \n",utfSource,utfTarget);
+*/
+}
+
+static void testEquality(UCollator* col, const UChar* p,const UChar* q){
+/*
+ UChar source[256] = { '\0'};
+ UChar target[256] = { '\0'};
+*/
+
+ doTest(col, p, q, UCOL_EQUAL);
+/*
+ fprintf(file,"Primary failed source: %s target: %s \n", utfSource,utfTarget);
+*/
+}
+
+static void testCollator(UCollator *coll, UErrorCode *status) {
+ const UChar *rules = NULL, *current = NULL;
+ int32_t ruleLen = 0;
+ uint32_t strength = 0;
+ uint32_t chOffset = 0; uint32_t chLen = 0;
+ uint32_t exOffset = 0; uint32_t exLen = 0;
+ uint32_t prefixOffset = 0; uint32_t prefixLen = 0;
+ uint32_t firstEx = 0;
+/* uint32_t rExpsLen = 0; */
+ uint32_t firstLen = 0;
+ UBool varT = FALSE; UBool top_ = TRUE;
+ uint16_t specs = 0;
+ UBool startOfRules = TRUE;
+ UBool lastReset = FALSE;
+ UBool before = FALSE;
+ uint32_t beforeStrength = 0;
+ UColTokenParser src;
+ UColOptionSet opts;
+
+ UChar first[256];
+ UChar second[256];
+ UChar tempB[256];
+ uint32_t tempLen;
+ UChar *rulesCopy = NULL;
+ UParseError parseError;
+ src.opts = &opts;
+
+ rules = ucol_getRules(coll, &ruleLen);
+ if(U_SUCCESS(*status) && ruleLen > 0) {
+ rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar));
+ uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar));
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy+ruleLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+ *first = *second = 0;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules,&parseError, status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0);
+ top_ = (UBool)((specs & UCOL_TOK_TOP) != 0);
+ if(top_) { /* if reset is on top, the sequence is broken. We should have an empty string */
+ second[0] = 0;
+ } else {
+ u_strncpy(second,rulesCopy+chOffset, chLen);
+ second[chLen] = 0;
+
+ if(exLen > 0 && firstEx == 0) {
+ u_strncat(first, rulesCopy+exOffset, exLen);
+ first[firstLen+exLen] = 0;
+ }
+
+ if(lastReset == TRUE && prefixLen != 0) {
+ u_strncpy(first+prefixLen, first, firstLen);
+ u_strncpy(first, rulesCopy+prefixOffset, prefixLen);
+ first[firstLen+prefixLen] = 0;
+ firstLen = firstLen+prefixLen;
+ }
+
+ if(before == TRUE) { /* swap first and second */
+ u_strcpy(tempB, first);
+ u_strcpy(first, second);
+ u_strcpy(second, tempB);
+
+ tempLen = firstLen;
+ firstLen = chLen;
+ chLen = tempLen;
+
+ tempLen = firstEx;
+ firstEx = exLen;
+ exLen = tempLen;
+ if(beforeStrength < strength) {
+ strength = beforeStrength;
+ }
+ }
+ }
+ lastReset = FALSE;
+
+ switch(strength){
+ case UCOL_IDENTICAL:
+ testEquality(coll,first,second);
+ break;
+ case UCOL_PRIMARY:
+ testPrimary(coll,first,second);
+ break;
+ case UCOL_SECONDARY:
+ testSecondary(coll,first,second);
+ break;
+ case UCOL_TERTIARY:
+ testTertiary(coll,first,second);
+ break;
+ case UCOL_TOK_RESET:
+ lastReset = TRUE;
+ before = (UBool)((specs & UCOL_TOK_BEFORE) != 0);
+ if(before) {
+ beforeStrength = (specs & UCOL_TOK_BEFORE)-1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if(before == TRUE && strength != UCOL_TOK_RESET) { /* first and second were swapped */
+ before = FALSE;
+ } else {
+ firstLen = chLen;
+ firstEx = exLen;
+ u_strcpy(first, second);
+ }
+ }
+ free(rulesCopy);
+ }
+}
+
+static UCollationResult ucaTest(void *collator, const int object, const UChar *source, const int sLen, const UChar *target, const int tLen) {
+ UCollator *UCA = (UCollator *)collator;
+ return ucol_strcoll(UCA, source, sLen, target, tLen);
+}
+
+/*
+static UCollationResult winTest(void *collator, const int object, const UChar *source, const int sLen, const UChar *target, const int tLen) {
+#ifdef U_WINDOWS
+ LCID lcid = (LCID)collator;
+ return (UCollationResult)CompareString(lcid, 0, source, sLen, target, tLen);
+#else
+ return 0;
+#endif
+}
+*/
+
+static UCollationResult swampEarlier(tst_strcoll* func, void *collator, int opts,
+ UChar s1, UChar s2,
+ const UChar *s, const uint32_t sLen,
+ const UChar *t, const uint32_t tLen) {
+ UChar source[256] = {0};
+ UChar target[256] = {0};
+
+ source[0] = s1;
+ u_strcpy(source+1, s);
+ target[0] = s2;
+ u_strcpy(target+1, t);
+
+ return func(collator, opts, source, sLen+1, target, tLen+1);
+}
+
+static UCollationResult swampLater(tst_strcoll* func, void *collator, int opts,
+ UChar s1, UChar s2,
+ const UChar *s, const uint32_t sLen,
+ const UChar *t, const uint32_t tLen) {
+ UChar source[256] = {0};
+ UChar target[256] = {0};
+
+ u_strcpy(source, s);
+ source[sLen] = s1;
+ u_strcpy(target, t);
+ target[tLen] = s2;
+
+ return func(collator, opts, source, sLen+1, target, tLen+1);
+}
+
+static uint32_t probeStrength(tst_strcoll* func, void *collator, int opts,
+ const UChar *s, const uint32_t sLen,
+ const UChar *t, const uint32_t tLen,
+ UCollationResult result) {
+ /*UChar fPrimary = 0x6d;*/
+ /*UChar sPrimary = 0x6e;*/
+ UChar fSecondary = 0x310d;
+ UChar sSecondary = 0x31a3;
+ UChar fTertiary = 0x310f;
+ UChar sTertiary = 0x31b7;
+
+ UCollationResult oposite;
+ if(result == UCOL_EQUAL) {
+ return UCOL_IDENTICAL;
+ } else if(result == UCOL_GREATER) {
+ oposite = UCOL_LESS;
+ } else {
+ oposite = UCOL_GREATER;
+ }
+
+ if(swampEarlier(func, collator, opts, sSecondary, fSecondary, s, sLen, t, tLen) == result) {
+ return UCOL_PRIMARY;
+ } else if((swampEarlier(func, collator, opts, sTertiary, 0x310f, s, sLen, t, tLen) == result) &&
+ (swampEarlier(func, collator, opts, 0x310f, sTertiary, s, sLen, t, tLen) == result)) {
+ return UCOL_SECONDARY;
+ } else if((swampLater(func, collator, opts, sTertiary, fTertiary, s, sLen, t, tLen) == result) &&
+ (swampLater(func, collator, opts, fTertiary, sTertiary, s, sLen, t, tLen) == result)) {
+ return UCOL_TERTIARY;
+ } else if((swampLater(func, collator, opts, sTertiary, 0x310f, s, sLen, t, tLen) == oposite) &&
+ (swampLater(func, collator, opts, fTertiary, sTertiary, s, sLen, t, tLen) == oposite)) {
+ return UCOL_QUATERNARY;
+ } else {
+ return UCOL_IDENTICAL;
+ }
+}
+
+static char *getRelationSymbol(UCollationResult res, uint32_t strength, char *buffer) {
+ uint32_t i = 0;
+
+ if(res == UCOL_EQUAL || strength == 0xdeadbeef) {
+ buffer[0] = '=';
+ buffer[1] = '=';
+ buffer[2] = '\0';
+ } else if(res == UCOL_GREATER) {
+ for(i = 0; i<strength+1; i++) {
+ buffer[i] = '>';
+ }
+ buffer[strength+1] = '\0';
+ } else {
+ for(i = 0; i<strength+1; i++) {
+ buffer[i] = '<';
+ }
+ buffer[strength+1] = '\0';
+ }
+
+ return buffer;
+}
+
+
+
+static void logFailure (const char *platform, const char *test,
+ const UChar *source, const uint32_t sLen,
+ const UChar *target, const uint32_t tLen,
+ UCollationResult realRes, uint32_t realStrength,
+ UCollationResult expRes, uint32_t expStrength, UBool error) {
+
+ uint32_t i = 0;
+
+ char sEsc[256], s[256], tEsc[256], t[256], b[256], output[512], relation[256];
+ static int32_t maxOutputLength = 0;
+ int32_t outputLength;
+
+ *sEsc = *tEsc = *s = *t = 0;
+ if(error == TRUE) {
+ log_err("Difference between expected and generated order. Run test with -v for more info\n");
+ } else if(VERBOSITY == 0) {
+ return;
+ }
+ for(i = 0; i<sLen; i++) {
+ sprintf(b, "%04X", source[i]);
+ strcat(sEsc, "\\u");
+ strcat(sEsc, b);
+ strcat(s, b);
+ strcat(s, " ");
+ if(source[i] < 0x80) {
+ sprintf(b, "(%c)", source[i]);
+ strcat(sEsc, b);
+ }
+ }
+ for(i = 0; i<tLen; i++) {
+ sprintf(b, "%04X", target[i]);
+ strcat(tEsc, "\\u");
+ strcat(tEsc, b);
+ strcat(t, b);
+ strcat(t, " ");
+ if(target[i] < 0x80) {
+ sprintf(b, "(%c)", target[i]);
+ strcat(tEsc, b);
+ }
+ }
+/*
+ strcpy(output, "[[ ");
+ strcat(output, sEsc);
+ strcat(output, getRelationSymbol(expRes, expStrength, relation));
+ strcat(output, tEsc);
+
+ strcat(output, " : ");
+
+ strcat(output, sEsc);
+ strcat(output, getRelationSymbol(realRes, realStrength, relation));
+ strcat(output, tEsc);
+ strcat(output, " ]] ");
+
+ log_verbose("%s", output);
+*/
+
+
+ strcpy(output, "DIFF: ");
+
+ strcat(output, s);
+ strcat(output, " : ");
+ strcat(output, t);
+
+ strcat(output, test);
+ strcat(output, ": ");
+
+ strcat(output, sEsc);
+ strcat(output, getRelationSymbol(expRes, expStrength, relation));
+ strcat(output, tEsc);
+
+ strcat(output, " ");
+
+ strcat(output, platform);
+ strcat(output, ": ");
+
+ strcat(output, sEsc);
+ strcat(output, getRelationSymbol(realRes, realStrength, relation));
+ strcat(output, tEsc);
+
+ outputLength = (int32_t)strlen(output);
+ if(outputLength > maxOutputLength) {
+ maxOutputLength = outputLength;
+ U_ASSERT(outputLength < sizeof(output));
+ }
+
+ log_verbose("%s\n", output);
+
+}
+
+/*
+static void printOutRules(const UChar *rules) {
+ uint32_t len = u_strlen(rules);
+ uint32_t i = 0;
+ char toPrint;
+ uint32_t line = 0;
+
+ fprintf(stdout, "Rules:");
+
+ for(i = 0; i<len; i++) {
+ if(rules[i]<0x7f && rules[i]>=0x20) {
+ toPrint = (char)rules[i];
+ if(toPrint == '&') {
+ line = 1;
+ fprintf(stdout, "\n&");
+ } else if(toPrint == ';') {
+ fprintf(stdout, "<<");
+ line+=2;
+ } else if(toPrint == ',') {
+ fprintf(stdout, "<<<");
+ line+=3;
+ } else {
+ fprintf(stdout, "%c", toPrint);
+ line++;
+ }
+ } else if(rules[i]<0x3400 || rules[i]>=0xa000) {
+ fprintf(stdout, "\\u%04X", rules[i]);
+ line+=6;
+ }
+ if(line>72) {
+ fprintf(stdout, "\n");
+ line = 0;
+ }
+ }
+
+ log_verbose("\n");
+
+}
+*/
+
+static uint32_t testSwitch(tst_strcoll* func, void *collator, int opts, uint32_t strength, const UChar *first, const UChar *second, const char* msg, UBool error) {
+ uint32_t diffs = 0;
+ UCollationResult realResult;
+ uint32_t realStrength;
+
+ uint32_t sLen = u_strlen(first);
+ uint32_t tLen = u_strlen(second);
+
+ realResult = func(collator, opts, first, sLen, second, tLen);
+ realStrength = probeStrength(func, collator, opts, first, sLen, second, tLen, realResult);
+
+ if(strength == UCOL_IDENTICAL && realResult != UCOL_IDENTICAL) {
+ logFailure(msg, "tailoring", first, sLen, second, tLen, realResult, realStrength, UCOL_EQUAL, strength, error);
+ diffs++;
+ } else if(realResult != UCOL_LESS || realStrength != strength) {
+ logFailure(msg, "tailoring", first, sLen, second, tLen, realResult, realStrength, UCOL_LESS, strength, error);
+ diffs++;
+ }
+ return diffs;
+}
+
+
+static void testAgainstUCA(UCollator *coll, UCollator *UCA, const char *refName, UBool error, UErrorCode *status) {
+ const UChar *rules = NULL, *current = NULL;
+ int32_t ruleLen = 0;
+ uint32_t strength = 0;
+ uint32_t chOffset = 0; uint32_t chLen = 0;
+ uint32_t exOffset = 0; uint32_t exLen = 0;
+ uint32_t prefixOffset = 0; uint32_t prefixLen = 0;
+/* uint32_t rExpsLen = 0; */
+ uint32_t firstLen = 0, secondLen = 0;
+ UBool varT = FALSE; UBool top_ = TRUE;
+ uint16_t specs = 0;
+ UBool startOfRules = TRUE;
+ UColTokenParser src;
+ UColOptionSet opts;
+
+ UChar first[256];
+ UChar second[256];
+ UChar *rulesCopy = NULL;
+
+ uint32_t UCAdiff = 0;
+ uint32_t Windiff = 1;
+ UParseError parseError;
+
+ src.opts = &opts;
+
+ rules = ucol_getRules(coll, &ruleLen);
+
+ /*printOutRules(rules);*/
+
+ if(U_SUCCESS(*status) && ruleLen > 0) {
+ rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar));
+ uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar));
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy+ruleLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+ *first = *second = 0;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0);
+ top_ = (UBool)((specs & UCOL_TOK_TOP) != 0);
+
+ u_strncpy(second,rulesCopy+chOffset, chLen);
+ second[chLen] = 0;
+ secondLen = chLen;
+
+ if(exLen > 0) {
+ u_strncat(first, rulesCopy+exOffset, exLen);
+ first[firstLen+exLen] = 0;
+ firstLen += exLen;
+ }
+
+ if(strength != UCOL_TOK_RESET) {
+ if((*first<0x3400 || *first>=0xa000) && (*second<0x3400 || *second>=0xa000)) {
+ UCAdiff += testSwitch(&ucaTest, (void *)UCA, 0, strength, first, second, refName, error);
+ /*Windiff += testSwitch(&winTest, (void *)lcid, 0, strength, first, second, "Win32");*/
+ }
+ }
+
+
+ firstLen = chLen;
+ u_strcpy(first, second);
+
+ }
+ if(UCAdiff != 0 && Windiff != 0) {
+ log_verbose("\n");
+ }
+ if(UCAdiff == 0) {
+ log_verbose("No immediate difference with %s!\n", refName);
+ }
+ if(Windiff == 0) {
+ log_verbose("No immediate difference with Win32!\n");
+ }
+ free(rulesCopy);
+ }
+}
+
+/*
+ * Takes two CEs (lead and continuation) and
+ * compares them as CEs should be compared:
+ * primary vs. primary, secondary vs. secondary
+ * tertiary vs. tertiary
+ */
+static int32_t compareCEs(uint32_t s1, uint32_t s2,
+ uint32_t t1, uint32_t t2) {
+ uint32_t s = 0, t = 0;
+ if(s1 == t1 && s2 == t2) {
+ return 0;
+ }
+ s = (s1 & 0xFFFF0000)|((s2 & 0xFFFF0000)>>16);
+ t = (t1 & 0xFFFF0000)|((t2 & 0xFFFF0000)>>16);
+ if(s < t) {
+ return -1;
+ } else if(s > t) {
+ return 1;
+ } else {
+ s = (s1 & 0x0000FF00) | (s2 & 0x0000FF00)>>8;
+ t = (t1 & 0x0000FF00) | (t2 & 0x0000FF00)>>8;
+ if(s < t) {
+ return -1;
+ } else if(s > t) {
+ return 1;
+ } else {
+ s = (s1 & 0x000000FF)<<8 | (s2 & 0x000000FF);
+ t = (t1 & 0x000000FF)<<8 | (t2 & 0x000000FF);
+ if(s < t) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+}
+
+typedef struct {
+ uint32_t startCE;
+ uint32_t startContCE;
+ uint32_t limitCE;
+ uint32_t limitContCE;
+} indirectBoundaries;
+
+/* these values are used for finding CE values for indirect positioning. */
+/* Indirect positioning is a mechanism for allowing resets on symbolic */
+/* values. It only works for resets and you cannot tailor indirect names */
+/* An indirect name can define either an anchor point or a range. An */
+/* anchor point behaves in exactly the same way as a code point in reset */
+/* would, except that it cannot be tailored. A range (we currently only */
+/* know for the [top] range will explicitly set the upper bound for */
+/* generated CEs, thus allowing for better control over how many CEs can */
+/* be squeezed between in the range without performance penalty. */
+/* In that respect, we use [top] for tailoring of locales that use CJK */
+/* characters. Other indirect values are currently a pure convenience, */
+/* they can be used to assure that the CEs will be always positioned in */
+/* the same place relative to a point with known properties (e.g. first */
+/* primary ignorable). */
+static indirectBoundaries ucolIndirectBoundaries[15];
+static UBool indirectBoundariesSet = FALSE;
+static void setIndirectBoundaries(uint32_t indexR, uint32_t *start, uint32_t *end) {
+
+ /* Set values for the top - TODO: once we have values for all the indirects, we are going */
+ /* to initalize here. */
+ ucolIndirectBoundaries[indexR].startCE = start[0];
+ ucolIndirectBoundaries[indexR].startContCE = start[1];
+ if(end) {
+ ucolIndirectBoundaries[indexR].limitCE = end[0];
+ ucolIndirectBoundaries[indexR].limitContCE = end[1];
+ } else {
+ ucolIndirectBoundaries[indexR].limitCE = 0;
+ ucolIndirectBoundaries[indexR].limitContCE = 0;
+ }
+}
+
+static void testCEs(UCollator *coll, UErrorCode *status) {
+
+ const UChar *rules = NULL, *current = NULL;
+ int32_t ruleLen = 0;
+
+ uint32_t strength = 0;
+ uint32_t maxStrength = UCOL_IDENTICAL;
+ uint32_t baseCE, baseContCE, nextCE, nextContCE, currCE, currContCE;
+ uint32_t lastCE;
+ uint32_t lastContCE;
+
+ int32_t result = 0;
+ uint32_t chOffset = 0; uint32_t chLen = 0;
+ uint32_t exOffset = 0; uint32_t exLen = 0;
+ uint32_t prefixOffset = 0; uint32_t prefixLen = 0;
+ uint32_t oldOffset = 0;
+
+ /* uint32_t rExpsLen = 0; */
+ /* uint32_t firstLen = 0; */
+ uint16_t specs = 0;
+ UBool varT = FALSE; UBool top_ = TRUE;
+ UBool startOfRules = TRUE;
+ UBool before = FALSE;
+ UColTokenParser src;
+ UColOptionSet opts;
+ UParseError parseError;
+ UChar *rulesCopy = NULL;
+ collIterate c;
+ UCollator *UCA = ucol_open("root", status);
+ UCAConstants *consts = (UCAConstants *)((uint8_t *)UCA->image + UCA->image->UCAConsts);
+ uint32_t UCOL_RESET_TOP_VALUE = consts->UCA_LAST_NON_VARIABLE[0], /*UCOL_RESET_TOP_CONT = consts->UCA_LAST_NON_VARIABLE[1], */
+ UCOL_NEXT_TOP_VALUE = consts->UCA_FIRST_IMPLICIT[0], UCOL_NEXT_TOP_CONT = consts->UCA_FIRST_IMPLICIT[1];
+
+ baseCE=baseContCE=nextCE=nextContCE=currCE=currContCE=lastCE=lastContCE = UCOL_NOT_FOUND;
+
+ src.opts = &opts;
+
+ rules = ucol_getRules(coll, &ruleLen);
+
+ src.invUCA = ucol_initInverseUCA(status);
+
+ if(indirectBoundariesSet == FALSE) {
+ /* UCOL_RESET_TOP_VALUE */
+ setIndirectBoundaries(0, consts->UCA_LAST_NON_VARIABLE, consts->UCA_FIRST_IMPLICIT);
+ /* UCOL_FIRST_PRIMARY_IGNORABLE */
+ setIndirectBoundaries(1, consts->UCA_FIRST_PRIMARY_IGNORABLE, 0);
+ /* UCOL_LAST_PRIMARY_IGNORABLE */
+ setIndirectBoundaries(2, consts->UCA_LAST_PRIMARY_IGNORABLE, 0);
+ /* UCOL_FIRST_SECONDARY_IGNORABLE */
+ setIndirectBoundaries(3, consts->UCA_FIRST_SECONDARY_IGNORABLE, 0);
+ /* UCOL_LAST_SECONDARY_IGNORABLE */
+ setIndirectBoundaries(4, consts->UCA_LAST_SECONDARY_IGNORABLE, 0);
+ /* UCOL_FIRST_TERTIARY_IGNORABLE */
+ setIndirectBoundaries(5, consts->UCA_FIRST_TERTIARY_IGNORABLE, 0);
+ /* UCOL_LAST_TERTIARY_IGNORABLE */
+ setIndirectBoundaries(6, consts->UCA_LAST_TERTIARY_IGNORABLE, 0);
+ /* UCOL_FIRST_VARIABLE */
+ setIndirectBoundaries(7, consts->UCA_FIRST_VARIABLE, 0);
+ /* UCOL_LAST_VARIABLE */
+ setIndirectBoundaries(8, consts->UCA_LAST_VARIABLE, 0);
+ /* UCOL_FIRST_NON_VARIABLE */
+ setIndirectBoundaries(9, consts->UCA_FIRST_NON_VARIABLE, 0);
+ /* UCOL_LAST_NON_VARIABLE */
+ setIndirectBoundaries(10, consts->UCA_LAST_NON_VARIABLE, consts->UCA_FIRST_IMPLICIT);
+ /* UCOL_FIRST_IMPLICIT */
+ setIndirectBoundaries(11, consts->UCA_FIRST_IMPLICIT, 0);
+ /* UCOL_LAST_IMPLICIT */
+ setIndirectBoundaries(12, consts->UCA_LAST_IMPLICIT, consts->UCA_FIRST_TRAILING);
+ /* UCOL_FIRST_TRAILING */
+ setIndirectBoundaries(13, consts->UCA_FIRST_TRAILING, 0);
+ /* UCOL_LAST_TRAILING */
+ setIndirectBoundaries(14, consts->UCA_LAST_TRAILING, 0);
+ ucolIndirectBoundaries[14].limitCE = (consts->UCA_PRIMARY_SPECIAL_MIN<<24);
+ indirectBoundariesSet = TRUE;
+ }
+
+
+ if(U_SUCCESS(*status) && ruleLen > 0) {
+ rulesCopy = (UChar *)malloc((ruleLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar));
+ uprv_memcpy(rulesCopy, rules, ruleLen*sizeof(UChar));
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy+ruleLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ varT = (UBool)((specs & UCOL_TOK_VARIABLE_TOP) != 0);
+ top_ = (UBool)((specs & UCOL_TOK_TOP) != 0);
+
+ uprv_init_collIterate(coll, rulesCopy+chOffset, chLen, &c);
+
+ currCE = ucol_getNextCE(coll, &c, status);
+ if(currCE == 0 && UCOL_ISTHAIPREVOWEL(*(rulesCopy+chOffset))) {
+ log_verbose("Thai prevowel detected. Will pick next CE\n");
+ currCE = ucol_getNextCE(coll, &c, status);
+ }
+
+ currContCE = ucol_getNextCE(coll, &c, status);
+ if(!isContinuation(currContCE)) {
+ currContCE = 0;
+ }
+
+ /* we need to repack CEs here */
+
+ if(strength == UCOL_TOK_RESET) {
+ before = (UBool)((specs & UCOL_TOK_BEFORE) != 0);
+ if(top_ == TRUE) {
+ int32_t index = src.parsedToken.indirectIndex;
+
+ nextCE = baseCE = currCE = ucolIndirectBoundaries[index].startCE;
+ nextContCE = baseContCE = currContCE = ucolIndirectBoundaries[index].startContCE;
+ } else {
+ nextCE = baseCE = currCE;
+ nextContCE = baseContCE = currContCE;
+ }
+ maxStrength = UCOL_IDENTICAL;
+ } else {
+ if(strength < maxStrength) {
+ maxStrength = strength;
+ if(baseCE == UCOL_RESET_TOP_VALUE) {
+ log_verbose("Resetting to [top]\n");
+ nextCE = UCOL_NEXT_TOP_VALUE;
+ nextContCE = UCOL_NEXT_TOP_CONT;
+ } else {
+ result = ucol_inv_getNextCE(&src, baseCE & 0xFFFFFF3F, baseContCE, &nextCE, &nextContCE, maxStrength);
+ }
+ if(result < 0) {
+ if(ucol_isTailored(coll, *(rulesCopy+oldOffset), status)) {
+ log_verbose("Reset is tailored codepoint %04X, don't know how to continue, taking next test\n", *(rulesCopy+oldOffset));
+ return;
+ } else {
+ log_err("couldn't find the CE\n");
+ return;
+ }
+ }
+ }
+
+ currCE &= 0xFFFFFF3F;
+ currContCE &= 0xFFFFFFBF;
+
+ if(maxStrength == UCOL_IDENTICAL) {
+ if(baseCE != currCE || baseContCE != currContCE) {
+ log_err("current CE (initial strength UCOL_EQUAL)\n");
+ }
+ } else {
+ if(strength == UCOL_IDENTICAL) {
+ if(lastCE != currCE || lastContCE != currContCE) {
+ log_err("current CE (initial strength UCOL_EQUAL)\n");
+ }
+ } else {
+ if(compareCEs(currCE, currContCE, nextCE, nextContCE) > 0) {
+ /*if(currCE > nextCE || (currCE == nextCE && currContCE >= nextContCE)) {*/
+ log_err("current CE is not less than base CE\n");
+ }
+ if(!before) {
+ if(compareCEs(currCE, currContCE, lastCE, lastContCE) < 0) {
+ /*if(currCE < lastCE || (currCE == lastCE && currContCE <= lastContCE)) {*/
+ log_err("sequence of generated CEs is broken\n");
+ }
+ } else {
+ before = FALSE;
+ if(compareCEs(currCE, currContCE, lastCE, lastContCE) > 0) {
+ /*if(currCE < lastCE || (currCE == lastCE && currContCE <= lastContCE)) {*/
+ log_err("sequence of generated CEs is broken\n");
+ }
+ }
+ }
+ }
+
+ }
+
+ oldOffset = chOffset;
+ lastCE = currCE & 0xFFFFFF3F;
+ lastContCE = currContCE & 0xFFFFFFBF;
+ }
+ free(rulesCopy);
+ }
+ ucol_close(UCA);
+}
+
+#if 0
+/* these locales are now picked from index RB */
+static const char* localesToTest[] = {
+"ar", "bg", "ca", "cs", "da",
+"el", "en_BE", "en_US_POSIX",
+"es", "et", "fi", "fr", "hi",
+"hr", "hu", "is", "iw", "ja",
+"ko", "lt", "lv", "mk", "mt",
+"nb", "nn", "nn_NO", "pl", "ro",
+"ru", "sh", "sk", "sl", "sq",
+"sr", "sv", "th", "tr", "uk",
+"vi", "zh", "zh_TW"
+};
+#endif
+
+static const char* rulesToTest[] = {
+ /* Funky fa rule */
+ "&\\u0622 < \\u0627 << \\u0671 < \\u0621",
+ /*"& Z < p, P",*/
+ /* Cui Mins rules */
+ "&[top]<o,O<p,P<q,Q<'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U & Qu<'?'",*/
+ "&[top]<o,O<p,P<q,Q;'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U & Qu;'?'",*/
+ "&[top]<o,O<p,P<q,Q,'?'/u<r,R<u,U", /*"<o,O<p,P<q,Q<r,R<u,U&'Qu','?'",*/
+ "&[top]<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q;'?'/u<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & Qu;'?'",*/
+ "&[top]<'?';Qu<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & '?';Qu",*/
+ "&[top]<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q;'?'/um<r,R<u,U", /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & Qum;'?'",*/
+ "&[top]<'?';Qum<3<4<5<c,C<f,F<m,M<o,O<p,P<q,Q<r,R<u,U" /*"<'?'<3<4<5<a,A<f,F<m,M<o,O<p,P<q,Q<r,R<u,U & '?';Qum"*/
+};
+
+
+static void TestCollations(void) {
+ int32_t noOfLoc = uloc_countAvailable();
+ int32_t i = 0, j = 0;
+
+ UErrorCode status = U_ZERO_ERROR;
+ char cName[256];
+ UChar name[256];
+ int32_t nameSize;
+
+
+ const char *locName = NULL;
+ UCollator *coll = NULL;
+ UCollator *UCA = ucol_open("", &status);
+ UColAttributeValue oldStrength = ucol_getAttribute(UCA, UCOL_STRENGTH, &status);
+ ucol_setAttribute(UCA, UCOL_STRENGTH, UCOL_QUATERNARY, &status);
+
+ for(i = 0; i<noOfLoc; i++) {
+ status = U_ZERO_ERROR;
+ locName = uloc_getAvailable(i);
+ if(uprv_strcmp("ja", locName) == 0) {
+ log_verbose("Don't know how to test prefixes\n");
+ continue;
+ }
+ if(hasCollationElements(locName)) {
+ nameSize = uloc_getDisplayName(locName, NULL, name, 256, &status);
+ for(j = 0; j<nameSize; j++) {
+ cName[j] = (char)name[j];
+ }
+ cName[nameSize] = 0;
+ log_verbose("\nTesting locale %s (%s)\n", locName, cName);
+ coll = ucol_open(locName, &status);
+ if(U_SUCCESS(status)) {
+ testAgainstUCA(coll, UCA, "UCA", FALSE, &status);
+ ucol_close(coll);
+ } else {
+ log_err("Couldn't instantiate collator for locale %s, error: %s\n", locName, u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ }
+ }
+ ucol_setAttribute(UCA, UCOL_STRENGTH, oldStrength, &status);
+ ucol_close(UCA);
+}
+
+static void RamsRulesTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i = 0;
+ UCollator *coll = NULL;
+ UChar rule[2048];
+ uint32_t ruleLen;
+ int32_t noOfLoc = uloc_countAvailable();
+ const char *locName = NULL;
+
+ log_verbose("RamsRulesTest\n");
+
+ for(i = 0; i<noOfLoc; i++) {
+ status = U_ZERO_ERROR;
+ locName = uloc_getAvailable(i);
+ if(hasCollationElements(locName)) {
+ if (uprv_strcmp("ja", locName)==0) {
+ log_verbose("Don't know how to test Japanese because of prefixes\n");
+ continue;
+ }
+ if (uprv_strcmp("de__PHONEBOOK", locName)==0) {
+ log_verbose("Don't know how to test Phonebook because the reset is on an expanding character\n");
+ continue;
+ }
+ if (uprv_strcmp("km", locName)==0 ||
+ uprv_strcmp("km_KH", locName)==0 ||
+ uprv_strcmp("zh", locName)==0 ||
+ uprv_strcmp("zh_Hant", locName)==0 ) {
+ continue; /* TODO: enable these locale tests after trac#6040 is fixed. */
+ }
+ log_verbose("Testing locale %s\n", locName);
+ coll = ucol_open(locName, &status);
+ if(U_SUCCESS(status)) {
+ if(coll->image->jamoSpecial == TRUE) {
+ log_err("%s has special JAMOs\n", locName);
+ }
+ ucol_setAttribute(coll, UCOL_CASE_FIRST, UCOL_OFF, &status);
+ testCollator(coll, &status);
+ testCEs(coll, &status);
+ ucol_close(coll);
+ }
+ }
+ }
+
+ for(i = 0; i<sizeof(rulesToTest)/sizeof(rulesToTest[0]); i++) {
+ log_verbose("Testing rule: %s\n", rulesToTest[i]);
+ ruleLen = u_unescape(rulesToTest[i], rule, 2048);
+ coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ if(U_SUCCESS(status)) {
+ testCollator(coll, &status);
+ testCEs(coll, &status);
+ ucol_close(coll);
+ }
+ }
+
+}
+
+static void IsTailoredTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ uint32_t i = 0;
+ UCollator *coll = NULL;
+ UChar rule[2048];
+ UChar tailored[2048];
+ UChar notTailored[2048];
+ uint32_t ruleLen, tailoredLen, notTailoredLen;
+
+ log_verbose("IsTailoredTest\n");
+
+ u_uastrcpy(rule, "&Z < A, B, C;c < d");
+ ruleLen = u_strlen(rule);
+
+ u_uastrcpy(tailored, "ABCcd");
+ tailoredLen = u_strlen(tailored);
+
+ u_uastrcpy(notTailored, "ZabD");
+ notTailoredLen = u_strlen(notTailored);
+
+ coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ if(U_SUCCESS(status)) {
+ for(i = 0; i<tailoredLen; i++) {
+ if(!ucol_isTailored(coll, tailored[i], &status)) {
+ log_err("%i: %04X should be tailored - it is reported as not\n", i, tailored[i]);
+ }
+ }
+ for(i = 0; i<notTailoredLen; i++) {
+ if(ucol_isTailored(coll, notTailored[i], &status)) {
+ log_err("%i: %04X should not be tailored - it is reported as it is\n", i, notTailored[i]);
+ }
+ }
+ ucol_close(coll);
+ }
+ else {
+ log_err("Can't tailor rules");
+ }
+ /* Code coverage */
+ status = U_ZERO_ERROR;
+ coll = ucol_open("ja", &status);
+ if(!ucol_isTailored(coll, 0x4E9C, &status)) {
+ log_err("0x4E9C should be tailored - it is reported as not\n");
+ }
+ ucol_close(coll);
+}
+
+
+const static char chTest[][20] = {
+ "c",
+ "C",
+ "ca", "cb", "cx", "cy", "CZ",
+ "c\\u030C", "C\\u030C",
+ "h",
+ "H",
+ "ha", "Ha", "harly", "hb", "HB", "hx", "HX", "hy", "HY",
+ "ch", "cH", "Ch", "CH",
+ "cha", "charly", "che", "chh", "chch", "chr",
+ "i", "I", "iarly",
+ "r", "R",
+ "r\\u030C", "R\\u030C",
+ "s",
+ "S",
+ "s\\u030C", "S\\u030C",
+ "z", "Z",
+ "z\\u030C", "Z\\u030C"
+};
+
+static void TestChMove(void) {
+ UChar t1[256] = {0};
+ UChar t2[256] = {0};
+
+ uint32_t i = 0, j = 0;
+ uint32_t size = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ UCollator *coll = ucol_open("cs", &status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(chTest)/sizeof(chTest[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ u_unescape(chTest[i], t1, 256);
+ u_unescape(chTest[j], t2, 256);
+ doTest(coll, t1, t2, UCOL_LESS);
+ }
+ }
+ }
+ else {
+ log_err("Can't open collator");
+ }
+ ucol_close(coll);
+}
+
+
+
+
+const static char impTest[][20] = {
+ "\\u4e00",
+ "a",
+ "A",
+ "b",
+ "B",
+ "\\u4e01"
+};
+
+
+static void TestImplicitTailoring(void) {
+ static const struct {
+ const char *rules;
+ const char *data[10];
+ const uint32_t len;
+ } tests[] = {
+ { "&[before 1]\\u4e00 < b < c &[before 1]\\u4e00 < d < e", { "d", "e", "b", "c", "\\u4e00"}, 5 },
+ { "&\\u4e00 < a <<< A < b <<< B", { "\\u4e00", "a", "A", "b", "B", "\\u4e01"}, 6 },
+ { "&[before 1]\\u4e00 < \\u4e01 < \\u4e02", { "\\u4e01", "\\u4e02", "\\u4e00"}, 3},
+ { "&[before 1]\\u4e01 < \\u4e02 < \\u4e03", { "\\u4e02", "\\u4e03", "\\u4e01"}, 3}
+ };
+
+ int32_t i = 0;
+
+ for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len);
+ }
+
+/*
+ UChar t1[256] = {0};
+ UChar t2[256] = {0};
+
+ const char *rule = "&\\u4e00 < a <<< A < b <<< B";
+
+ uint32_t i = 0, j = 0;
+ uint32_t size = 0;
+ uint32_t ruleLen = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = NULL;
+ ruleLen = u_unescape(rule, t1, 256);
+
+ coll = ucol_openRules(t1, ruleLen, UCOL_OFF, UCOL_TERTIARY,NULL, &status);
+
+ if(U_SUCCESS(status)) {
+ size = sizeof(impTest)/sizeof(impTest[0]);
+ for(i = 0; i < size-1; i++) {
+ for(j = i+1; j < size; j++) {
+ u_unescape(impTest[i], t1, 256);
+ u_unescape(impTest[j], t2, 256);
+ doTest(coll, t1, t2, UCOL_LESS);
+ }
+ }
+ }
+ else {
+ log_err("Can't open collator");
+ }
+ ucol_close(coll);
+ */
+}
+
+static void TestFCDProblem(void) {
+ UChar t1[256] = {0};
+ UChar t2[256] = {0};
+
+ const char *s1 = "\\u0430\\u0306\\u0325";
+ const char *s2 = "\\u04D1\\u0325";
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("", &status);
+ u_unescape(s1, t1, 256);
+ u_unescape(s2, t2, 256);
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
+ doTest(coll, t1, t2, UCOL_EQUAL);
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ doTest(coll, t1, t2, UCOL_EQUAL);
+
+ ucol_close(coll);
+}
+
+#define NORM_BUFFER_TEST_LEN 32
+typedef struct {
+ UChar32 u;
+ UChar NFC[NORM_BUFFER_TEST_LEN];
+ UChar NFD[NORM_BUFFER_TEST_LEN];
+} tester;
+
+static void TestComposeDecompose(void) {
+ int32_t noOfLoc;
+ int32_t i = 0, j = 0;
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ const char *locName = NULL;
+
+ uint32_t nfcSize;
+ uint32_t nfdSize;
+ tester **t;
+ uint32_t noCases = 0;
+ UCollator *coll = NULL;
+ UChar32 u = 0;
+ UChar comp[NORM_BUFFER_TEST_LEN];
+ uint32_t len = 0;
+ UCollationElements *iter;
+
+ noOfLoc = uloc_countAvailable();
+
+ t = malloc(0x30000 * sizeof(tester *));
+ t[0] = (tester *)malloc(sizeof(tester));
+ log_verbose("Testing UCA extensively\n");
+ coll = ucol_open("", &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+
+
+ for(u = 0; u < 0x30000; u++) {
+ len = 0;
+ UTF_APPEND_CHAR_UNSAFE(comp, len, u);
+ nfcSize = unorm_normalize(comp, len, UNORM_NFC, 0, t[noCases]->NFC, NORM_BUFFER_TEST_LEN, &status);
+ nfdSize = unorm_normalize(comp, len, UNORM_NFD, 0, t[noCases]->NFD, NORM_BUFFER_TEST_LEN, &status);
+
+ if(nfcSize != nfdSize || (uprv_memcmp(t[noCases]->NFC, t[noCases]->NFD, nfcSize * sizeof(UChar)) != 0)
+ || (len != nfdSize || (uprv_memcmp(comp, t[noCases]->NFD, nfdSize * sizeof(UChar)) != 0))) {
+ t[noCases]->u = u;
+ if(len != nfdSize || (uprv_memcmp(comp, t[noCases]->NFD, nfdSize * sizeof(UChar)) != 0)) {
+ u_strncpy(t[noCases]->NFC, comp, len);
+ t[noCases]->NFC[len] = 0;
+ }
+ noCases++;
+ t[noCases] = (tester *)malloc(sizeof(tester));
+ uprv_memset(t[noCases], 0, sizeof(tester));
+ }
+ }
+
+ for(u=0; u<(UChar32)noCases; u++) {
+ if(!ucol_equal(coll, t[u]->NFC, -1, t[u]->NFD, -1)) {
+ log_err("Failure: codePoint %05X fails TestComposeDecompose in the UCA\n", t[u]->u);
+ doTest(coll, t[u]->NFC, t[u]->NFD, UCOL_EQUAL);
+ }
+ }
+ /*
+ for(u = 0; u < 0x30000; u++) {
+ if(!(u&0xFFFF)) {
+ log_verbose("%08X ", u);
+ }
+ uprv_memset(t[noCases], 0, sizeof(tester));
+ t[noCases]->u = u;
+ len = 0;
+ UTF_APPEND_CHAR_UNSAFE(comp, len, u);
+ comp[len] = 0;
+ nfcSize = unorm_normalize(comp, len, UNORM_NFC, 0, t[noCases]->NFC, NORM_BUFFER_TEST_LEN, &status);
+ nfdSize = unorm_normalize(comp, len, UNORM_NFD, 0, t[noCases]->NFD, NORM_BUFFER_TEST_LEN, &status);
+ doTest(coll, comp, t[noCases]->NFD, UCOL_EQUAL);
+ doTest(coll, comp, t[noCases]->NFC, UCOL_EQUAL);
+ }
+ */
+
+ ucol_close(coll);
+
+ log_verbose("Testing locales, number of cases = %i\n", noCases);
+ for(i = 0; i<noOfLoc; i++) {
+ status = U_ZERO_ERROR;
+ locName = uloc_getAvailable(i);
+ if(hasCollationElements(locName)) {
+ char cName[256];
+ UChar name[256];
+ int32_t nameSize = uloc_getDisplayName(locName, NULL, name, sizeof(cName), &status);
+
+ for(j = 0; j<nameSize; j++) {
+ cName[j] = (char)name[j];
+ }
+ cName[nameSize] = 0;
+ log_verbose("\nTesting locale %s (%s)\n", locName, cName);
+
+ coll = ucol_open(locName, &status);
+ ucol_setStrength(coll, UCOL_IDENTICAL);
+ iter = ucol_openElements(coll, t[u]->NFD, u_strlen(t[u]->NFD), &status);
+
+ for(u=0; u<(UChar32)noCases; u++) {
+ if(!ucol_equal(coll, t[u]->NFC, -1, t[u]->NFD, -1)) {
+ log_err("Failure: codePoint %05X fails TestComposeDecompose for locale %s\n", t[u]->u, cName);
+ doTest(coll, t[u]->NFC, t[u]->NFD, UCOL_EQUAL);
+ log_verbose("Testing NFC\n");
+ ucol_setText(iter, t[u]->NFC, u_strlen(t[u]->NFC), &status);
+ backAndForth(iter);
+ log_verbose("Testing NFD\n");
+ ucol_setText(iter, t[u]->NFD, u_strlen(t[u]->NFD), &status);
+ backAndForth(iter);
+ }
+ }
+ ucol_closeElements(iter);
+ ucol_close(coll);
+ }
+ }
+ for(u = 0; u <= (UChar32)noCases; u++) {
+ free(t[u]);
+ }
+ free(t);
+}
+
+static void TestEmptyRule(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rulez[] = { 0 };
+ UCollator *coll = ucol_openRules(rulez, 0, UCOL_OFF, UCOL_TERTIARY,NULL, &status);
+
+ ucol_close(coll);
+}
+
+static void TestUCARules(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar b[256];
+ UChar *rules = b;
+ uint32_t ruleLen = 0;
+ UCollator *UCAfromRules = NULL;
+ UCollator *coll = ucol_open("", &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ ruleLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rules, 256);
+
+ log_verbose("TestUCARules\n");
+ if(ruleLen > 256) {
+ rules = (UChar *)malloc((ruleLen+1)*sizeof(UChar));
+ ruleLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rules, ruleLen);
+ }
+ log_verbose("Rules length is %d\n", ruleLen);
+ UCAfromRules = ucol_openRules(rules, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ if(U_SUCCESS(status)) {
+ ucol_close(UCAfromRules);
+ } else {
+ log_verbose("Unable to create a collator from UCARules!\n");
+ }
+/*
+ u_unescape(blah, b, 256);
+ ucol_getSortKey(coll, b, 1, res, 256);
+*/
+ ucol_close(coll);
+ if(rules != b) {
+ free(rules);
+ }
+}
+
+
+/* Pinyin tonal order */
+/*
+ A < .. (\u0101) < .. (\u00e1) < .. (\u01ce) < .. (\u00e0)
+ (w/macron)< (w/acute)< (w/caron)< (w/grave)
+ E < .. (\u0113) < .. (\u00e9) < .. (\u011b) < .. (\u00e8)
+ I < .. (\u012b) < .. (\u00ed) < .. (\u01d0) < .. (\u00ec)
+ O < .. (\u014d) < .. (\u00f3) < .. (\u01d2) < .. (\u00f2)
+ U < .. (\u016b) < .. (\u00fa) < .. (\u01d4) < .. (\u00f9)
+ < .. (\u01d6) < .. (\u01d8) < .. (\u01da) < .. (\u01dc) <
+.. (\u00fc)
+
+However, in testing we got the following order:
+ A < .. (\u00e1) < .. (\u00e0) < .. (\u01ce) < .. (\u0101)
+ (w/acute)< (w/grave)< (w/caron)< (w/macron)
+ E < .. (\u00e9) < .. (\u00e8) < .. (\u00ea) < .. (\u011b) <
+.. (\u0113)
+ I < .. (\u00ed) < .. (\u00ec) < .. (\u01d0) < .. (\u012b)
+ O < .. (\u00f3) < .. (\u00f2) < .. (\u01d2) < .. (\u014d)
+ U < .. (\u00fa) < .. (\u00f9) < .. (\u01d4) < .. (\u00fc) <
+.. (\u01d8)
+ < .. (\u01dc) < .. (\u01da) < .. (\u01d6) < .. (\u016b)
+*/
+
+static void TestBefore(void) {
+ const static char *data[] = {
+ "\\u0101", "\\u00e1", "\\u01ce", "\\u00e0", "A",
+ "\\u0113", "\\u00e9", "\\u011b", "\\u00e8", "E",
+ "\\u012b", "\\u00ed", "\\u01d0", "\\u00ec", "I",
+ "\\u014d", "\\u00f3", "\\u01d2", "\\u00f2", "O",
+ "\\u016b", "\\u00fa", "\\u01d4", "\\u00f9", "U",
+ "\\u01d6", "\\u01d8", "\\u01da", "\\u01dc", "\\u00fc"
+ };
+ genericRulesStarter(
+ "&[before 1]a<\\u0101<\\u00e1<\\u01ce<\\u00e0"
+ "&[before 1]e<\\u0113<\\u00e9<\\u011b<\\u00e8"
+ "&[before 1]i<\\u012b<\\u00ed<\\u01d0<\\u00ec"
+ "&[before 1]o<\\u014d<\\u00f3<\\u01d2<\\u00f2"
+ "&[before 1]u<\\u016b<\\u00fa<\\u01d4<\\u00f9"
+ "&u<\\u01d6<\\u01d8<\\u01da<\\u01dc<\\u00fc",
+ data, sizeof(data)/sizeof(data[0]));
+}
+
+#if 0
+/* superceded by TestBeforePinyin */
+static void TestJ784(void) {
+ const static char *data[] = {
+ "A", "\\u0101", "\\u00e1", "\\u01ce", "\\u00e0",
+ "E", "\\u0113", "\\u00e9", "\\u011b", "\\u00e8",
+ "I", "\\u012b", "\\u00ed", "\\u01d0", "\\u00ec",
+ "O", "\\u014d", "\\u00f3", "\\u01d2", "\\u00f2",
+ "U", "\\u016b", "\\u00fa", "\\u01d4", "\\u00f9",
+ "\\u00fc",
+ "\\u01d6", "\\u01d8", "\\u01da", "\\u01dc"
+ };
+ genericLocaleStarter("zh", data, sizeof(data)/sizeof(data[0]));
+}
+#endif
+
+#if 0
+/* superceded by the changes to the lv locale */
+static void TestJ831(void) {
+ const static char *data[] = {
+ "I",
+ "i",
+ "Y",
+ "y"
+ };
+ genericLocaleStarter("lv", data, sizeof(data)/sizeof(data[0]));
+}
+#endif
+
+static void TestJ815(void) {
+ const static char *data[] = {
+ "aa",
+ "Aa",
+ "ab",
+ "Ab",
+ "ad",
+ "Ad",
+ "ae",
+ "Ae",
+ "\\u00e6",
+ "\\u00c6",
+ "af",
+ "Af",
+ "b",
+ "B"
+ };
+ genericLocaleStarter("fr", data, sizeof(data)/sizeof(data[0]));
+ genericRulesStarter("[backwards 2]&A<<\\u00e6/e<<<\\u00c6/E", data, sizeof(data)/sizeof(data[0]));
+}
+
+
+/*
+"& a < b < c < d& r < c", "& a < b < d& r < c",
+"& a < b < c < d& c < m", "& a < b < c < m < d",
+"& a < b < c < d& a < m", "& a < m < b < c < d",
+"& a <<< b << c < d& a < m", "& a <<< b << c < m < d",
+"& a < b < c < d& [before 1] c < m", "& a < b < m < c < d",
+"& a < b <<< c << d <<< e& [before 3] e <<< x", "& a < b <<< c << d <<< x <<< e",
+"& a < b <<< c << d <<< e& [before 2] e <<< x", "& a < b <<< c <<< x << d <<< e",
+"& a < b <<< c << d <<< e& [before 1] e <<< x", "& a <<< x < b <<< c << d <<< e",
+"& a < b <<< c << d <<< e <<< f < g& [before 1] g < x", "& a < b <<< c << d <<< e <<< f < x < g",
+*/
+static void TestRedundantRules(void) {
+ int32_t i;
+
+ static const struct {
+ const char *rules;
+ const char *expectedRules;
+ const char *testdata[8];
+ uint32_t testdatalen;
+ } tests[] = {
+ /* this test conflicts with positioning of CODAN placeholder */
+ /*{
+ "& a <<< b <<< c << d <<< e& [before 1] e <<< x",
+ "&\\u2089<<<x",
+ {"\\u2089", "x"}, 2
+ }, */
+ /* this test conflicts with the [before x] syntax tightening */
+ /*{
+ "& b <<< c <<< d << e <<< f& [before 1] f <<< x",
+ "&\\u0252<<<x",
+ {"\\u0252", "x"}, 2
+ }, */
+ /* this test conflicts with the [before x] syntax tightening */
+ /*{
+ "& a < b <<< c << d <<< e& [before 1] e <<< x",
+ "& a <<< x < b <<< c << d <<< e",
+ {"a", "x", "b", "c", "d", "e"}, 6
+ }, */
+ {
+ "& a < b < c < d& [before 1] c < m",
+ "& a < b < m < c < d",
+ {"a", "b", "m", "c", "d"}, 5
+ },
+ {
+ "& a < b <<< c << d <<< e& [before 3] e <<< x",
+ "& a < b <<< c << d <<< x <<< e",
+ {"a", "b", "c", "d", "x", "e"}, 6
+ },
+ /* this test conflicts with the [before x] syntax tightening */
+ /* {
+ "& a < b <<< c << d <<< e& [before 2] e <<< x",
+ "& a < b <<< c <<< x << d <<< e",
+ {"a", "b", "c", "x", "d", "e"},, 6
+ }, */
+ {
+ "& a < b <<< c << d <<< e <<< f < g& [before 1] g < x",
+ "& a < b <<< c << d <<< e <<< f < x < g",
+ {"a", "b", "c", "d", "e", "f", "x", "g"}, 8
+ },
+ {
+ "& a <<< b << c < d& a < m",
+ "& a <<< b << c < m < d",
+ {"a", "b", "c", "m", "d"}, 5
+ },
+ {
+ "&a<b<<b\\u0301 &z<b",
+ "&a<b\\u0301 &z<b",
+ {"a", "b\\u0301", "z", "b"}, 4
+ },
+ {
+ "&z<m<<<q<<<m",
+ "&z<q<<<m",
+ {"z", "q", "m"},3
+ },
+ {
+ "&z<<<m<q<<<m",
+ "&z<q<<<m",
+ {"z", "q", "m"}, 3
+ },
+ {
+ "& a < b < c < d& r < c",
+ "& a < b < d& r < c",
+ {"a", "b", "d"}, 3
+ },
+ {
+ "& a < b < c < d& r < c",
+ "& a < b < d& r < c",
+ {"r", "c"}, 2
+ },
+ {
+ "& a < b < c < d& c < m",
+ "& a < b < c < m < d",
+ {"a", "b", "c", "m", "d"}, 5
+ },
+ {
+ "& a < b < c < d& a < m",
+ "& a < m < b < c < d",
+ {"a", "m", "b", "c", "d"}, 5
+ }
+ };
+
+
+ UCollator *credundant = NULL;
+ UCollator *cresulting = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[2048] = { 0 };
+ uint32_t rlen = 0;
+
+ for(i = 0; i<sizeof(tests)/sizeof(tests[0]); i++) {
+ log_verbose("testing rule %s, expected to be %s\n", tests[i].rules, tests[i].expectedRules);
+ rlen = u_unescape(tests[i].rules, rlz, 2048);
+
+ credundant = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+
+ rlen = u_unescape(tests[i].expectedRules, rlz, 2048);
+ cresulting = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status);
+
+ testAgainstUCA(cresulting, credundant, "expected", TRUE, &status);
+
+ ucol_close(credundant);
+ ucol_close(cresulting);
+
+ log_verbose("testing using data\n");
+
+ genericRulesStarter(tests[i].rules, tests[i].testdata, tests[i].testdatalen);
+ }
+
+}
+
+static void TestExpansionSyntax(void) {
+ int32_t i;
+
+ const static char *rules[] = {
+ "&AE <<< a << b <<< c &d <<< f",
+ "&AE <<< a <<< b << c << d < e < f <<< g",
+ "&AE <<< B <<< C / D <<< F"
+ };
+
+ const static char *expectedRules[] = {
+ "&A <<< a / E << b / E <<< c /E &d <<< f",
+ "&A <<< a / E <<< b / E << c / E << d / E < e < f <<< g",
+ "&A <<< B / E <<< C / ED <<< F / E"
+ };
+
+ const static char *testdata[][8] = {
+ {"AE", "a", "b", "c"},
+ {"AE", "a", "b", "c", "d", "e", "f", "g"},
+ {"AE", "B", "C"} /* / ED <<< F / E"},*/
+ };
+
+ const static uint32_t testdatalen[] = {
+ 4,
+ 8,
+ 3
+ };
+
+
+
+ UCollator *credundant = NULL;
+ UCollator *cresulting = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[2048] = { 0 };
+ uint32_t rlen = 0;
+
+ for(i = 0; i<sizeof(rules)/sizeof(rules[0]); i++) {
+ log_verbose("testing rule %s, expected to be %s\n", rules[i], expectedRules[i]);
+ rlen = u_unescape(rules[i], rlz, 2048);
+
+ credundant = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ rlen = u_unescape(expectedRules[i], rlz, 2048);
+ cresulting = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT, NULL,&status);
+
+ /* testAgainstUCA still doesn't handle expansions correctly, so this is not run */
+ /* as a hard error test, but only in information mode */
+ testAgainstUCA(cresulting, credundant, "expected", FALSE, &status);
+
+ ucol_close(credundant);
+ ucol_close(cresulting);
+
+ log_verbose("testing using data\n");
+
+ genericRulesStarter(rules[i], testdata[i], testdatalen[i]);
+ }
+}
+
+static void TestCase(void)
+{
+ const static UChar gRules[MAX_TOKEN_LEN] =
+ /*" & 0 < 1,\u2461<a,A"*/
+ { 0x0026, 0x0030, 0x003C, 0x0031, 0x002C, 0x2460, 0x003C, 0x0061, 0x002C, 0x0041, 0x0000 };
+
+ const static UChar testCase[][MAX_TOKEN_LEN] =
+ {
+ /*0*/ {0x0031 /*'1'*/, 0x0061/*'a'*/, 0x0000},
+ /*1*/ {0x0031 /*'1'*/, 0x0041/*'A'*/, 0x0000},
+ /*2*/ {0x2460 /*circ'1'*/, 0x0061/*'a'*/, 0x0000},
+ /*3*/ {0x2460 /*circ'1'*/, 0x0041/*'A'*/, 0x0000}
+ };
+
+ const static UCollationResult caseTestResults[][9] =
+ {
+ { UCOL_LESS, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_LESS },
+ { UCOL_GREATER, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_GREATER },
+ { UCOL_LESS, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_GREATER, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_LESS },
+ { UCOL_GREATER, UCOL_LESS, UCOL_GREATER, UCOL_EQUAL, UCOL_LESS, UCOL_LESS, UCOL_EQUAL, UCOL_EQUAL, UCOL_GREATER }
+ };
+
+ const static UColAttributeValue caseTestAttributes[][2] =
+ {
+ { UCOL_LOWER_FIRST, UCOL_OFF},
+ { UCOL_UPPER_FIRST, UCOL_OFF},
+ { UCOL_LOWER_FIRST, UCOL_ON},
+ { UCOL_UPPER_FIRST, UCOL_ON}
+ };
+ int32_t i,j,k;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationElements *iter;
+ UCollator *myCollation;
+ myCollation = ucol_open("en_US", &status);
+
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing different case settings\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+
+ for(k = 0; k<4; k++) {
+ ucol_setAttribute(myCollation, UCOL_CASE_FIRST, caseTestAttributes[k][0], &status);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, caseTestAttributes[k][1], &status);
+ log_verbose("Case first = %d, Case level = %d\n", caseTestAttributes[k][0], caseTestAttributes[k][1]);
+ for (i = 0; i < 3 ; i++) {
+ for(j = i+1; j<4; j++) {
+ doTest(myCollation, testCase[i], testCase[j], caseTestResults[k][3*i+j-1]);
+ }
+ }
+ }
+ ucol_close(myCollation);
+
+ myCollation = ucol_openRules(gRules, u_strlen(gRules), UCOL_OFF, UCOL_TERTIARY,NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing different case settings with custom rules\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+
+ for(k = 0; k<4; k++) {
+ ucol_setAttribute(myCollation, UCOL_CASE_FIRST, caseTestAttributes[k][0], &status);
+ ucol_setAttribute(myCollation, UCOL_CASE_LEVEL, caseTestAttributes[k][1], &status);
+ for (i = 0; i < 3 ; i++) {
+ for(j = i+1; j<4; j++) {
+ log_verbose("k:%d, i:%d, j:%d\n", k, i, j);
+ doTest(myCollation, testCase[i], testCase[j], caseTestResults[k][3*i+j-1]);
+ iter=ucol_openElements(myCollation, testCase[i], u_strlen(testCase[i]), &status);
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ iter=ucol_openElements(myCollation, testCase[j], u_strlen(testCase[j]), &status);
+ backAndForth(iter);
+ ucol_closeElements(iter);
+ }
+ }
+ }
+ ucol_close(myCollation);
+ {
+ const static char *lowerFirst[] = {
+ "h",
+ "H",
+ "ch",
+ "Ch",
+ "CH",
+ "cha",
+ "chA",
+ "Cha",
+ "ChA",
+ "CHa",
+ "CHA",
+ "i",
+ "I"
+ };
+
+ const static char *upperFirst[] = {
+ "H",
+ "h",
+ "CH",
+ "Ch",
+ "ch",
+ "CHA",
+ "CHa",
+ "ChA",
+ "Cha",
+ "chA",
+ "cha",
+ "I",
+ "i"
+ };
+ log_verbose("mixed case test\n");
+ log_verbose("lower first, case level off\n");
+ genericRulesStarter("[casefirst lower]&H<ch<<<Ch<<<CH", lowerFirst, sizeof(lowerFirst)/sizeof(lowerFirst[0]));
+ log_verbose("upper first, case level off\n");
+ genericRulesStarter("[casefirst upper]&H<ch<<<Ch<<<CH", upperFirst, sizeof(upperFirst)/sizeof(upperFirst[0]));
+ log_verbose("lower first, case level on\n");
+ genericRulesStarter("[casefirst lower][caselevel on]&H<ch<<<Ch<<<CH", lowerFirst, sizeof(lowerFirst)/sizeof(lowerFirst[0]));
+ log_verbose("upper first, case level on\n");
+ genericRulesStarter("[casefirst upper][caselevel on]&H<ch<<<Ch<<<CH", upperFirst, sizeof(upperFirst)/sizeof(upperFirst[0]));
+ }
+
+}
+
+static void TestIncrementalNormalize(void) {
+
+ /*UChar baseA =0x61;*/
+ UChar baseA =0x41;
+/* UChar baseB = 0x42;*/
+ static const UChar ccMix[] = {0x316, 0x321, 0x300};
+ /*UChar ccMix[] = {0x61, 0x61, 0x61};*/
+ /*
+ 0x316 is combining grave accent below, cc=220
+ 0x321 is combining palatalized hook below, cc=202
+ 0x300 is combining grave accent, cc=230
+ */
+
+ int maxSLen = 2000;
+ /*int maxSLen = 64000;*/
+ int sLen;
+ int i;
+
+ UCollator *coll;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollationResult result;
+
+ int32_t myQ = QUICK;
+
+ if(QUICK < 0) {
+ QUICK = 1;
+ }
+
+ {
+ /* Test 1. Run very long unnormalized strings, to force overflow of*/
+ /* most buffers along the way.*/
+ UChar *strA;
+ UChar *strB;
+
+ strA = malloc((maxSLen+1) * sizeof(UChar));
+ strB = malloc((maxSLen+1) * sizeof(UChar));
+
+ coll = ucol_open("en_US", &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+
+ /*for (sLen = 257; sLen<maxSLen; sLen++) {*/
+ /*for (sLen = 4; sLen<maxSLen; sLen++) {*/
+ /*for (sLen = 1000; sLen<1001; sLen++) {*/
+ for (sLen = 500; sLen<501; sLen++) {
+ /*for (sLen = 40000; sLen<65000; sLen+=1000) {*/
+ strA[0] = baseA;
+ strB[0] = baseA;
+ for (i=1; i<=sLen-1; i++) {
+ strA[i] = ccMix[i % 3];
+ strB[sLen-i] = ccMix[i % 3];
+ }
+ strA[sLen] = 0;
+ strB[sLen] = 0;
+
+ ucol_setStrength(coll, UCOL_TERTIARY); /* Do test with default strength, which runs*/
+ doTest(coll, strA, strB, UCOL_EQUAL); /* optimized functions in the impl*/
+ ucol_setStrength(coll, UCOL_IDENTICAL); /* Do again with the slow, general impl.*/
+ doTest(coll, strA, strB, UCOL_EQUAL);
+ }
+ free(strA);
+ free(strB);
+ }
+
+ QUICK = myQ;
+
+
+ /* Test 2: Non-normal sequence in a string that extends to the last character*/
+ /* of the string. Checks a couple of edge cases.*/
+
+ {
+ static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0};
+ static const UChar strB[] = {0x41, 0xc0, 0x316, 0};
+ ucol_setStrength(coll, UCOL_TERTIARY);
+ doTest(coll, strA, strB, UCOL_EQUAL);
+ }
+
+ /* Test 3: Non-normal sequence is terminated by a surrogate pair.*/
+
+ {
+ /* New UCA 3.1.1.
+ * test below used a code point from Desseret, which sorts differently
+ * than d800 dc00
+ */
+ /*UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0xD801, 0xDC00, 0};*/
+ static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0xD800, 0xDC01, 0};
+ static const UChar strB[] = {0x41, 0xc0, 0x316, 0xD800, 0xDC00, 0};
+ ucol_setStrength(coll, UCOL_TERTIARY);
+ doTest(coll, strA, strB, UCOL_GREATER);
+ }
+
+ /* Test 4: Imbedded nulls do not terminate a string when length is specified.*/
+
+ {
+ static const UChar strA[] = {0x41, 0x00, 0x42, 0x00};
+ static const UChar strB[] = {0x41, 0x00, 0x00, 0x00};
+ char sortKeyA[50];
+ char sortKeyAz[50];
+ char sortKeyB[50];
+ char sortKeyBz[50];
+ int r;
+
+ /* there used to be -3 here. Hmmmm.... */
+ /*result = ucol_strcoll(coll, strA, -3, strB, -3);*/
+ result = ucol_strcoll(coll, strA, 3, strB, 3);
+ if (result != UCOL_GREATER) {
+ log_err("ERROR 1 in test 4\n");
+ }
+ result = ucol_strcoll(coll, strA, -1, strB, -1);
+ if (result != UCOL_EQUAL) {
+ log_err("ERROR 2 in test 4\n");
+ }
+
+ ucol_getSortKey(coll, strA, 3, (uint8_t *)sortKeyA, sizeof(sortKeyA));
+ ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz));
+ ucol_getSortKey(coll, strB, 3, (uint8_t *)sortKeyB, sizeof(sortKeyB));
+ ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz));
+
+ r = strcmp(sortKeyA, sortKeyAz);
+ if (r <= 0) {
+ log_err("Error 3 in test 4\n");
+ }
+ r = strcmp(sortKeyA, sortKeyB);
+ if (r <= 0) {
+ log_err("Error 4 in test 4\n");
+ }
+ r = strcmp(sortKeyAz, sortKeyBz);
+ if (r != 0) {
+ log_err("Error 5 in test 4\n");
+ }
+
+ ucol_setStrength(coll, UCOL_IDENTICAL);
+ ucol_getSortKey(coll, strA, 3, (uint8_t *)sortKeyA, sizeof(sortKeyA));
+ ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz));
+ ucol_getSortKey(coll, strB, 3, (uint8_t *)sortKeyB, sizeof(sortKeyB));
+ ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz));
+
+ r = strcmp(sortKeyA, sortKeyAz);
+ if (r <= 0) {
+ log_err("Error 6 in test 4\n");
+ }
+ r = strcmp(sortKeyA, sortKeyB);
+ if (r <= 0) {
+ log_err("Error 7 in test 4\n");
+ }
+ r = strcmp(sortKeyAz, sortKeyBz);
+ if (r != 0) {
+ log_err("Error 8 in test 4\n");
+ }
+ ucol_setStrength(coll, UCOL_TERTIARY);
+ }
+
+
+ /* Test 5: Null characters in non-normal source strings.*/
+
+ {
+ static const UChar strA[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x42, 0x00};
+ static const UChar strB[] = {0x41, 0x41, 0x300, 0x316, 0x00, 0x00, 0x00};
+ char sortKeyA[50];
+ char sortKeyAz[50];
+ char sortKeyB[50];
+ char sortKeyBz[50];
+ int r;
+
+ result = ucol_strcoll(coll, strA, 6, strB, 6);
+ if (result != UCOL_GREATER) {
+ log_err("ERROR 1 in test 5\n");
+ }
+ result = ucol_strcoll(coll, strA, -1, strB, -1);
+ if (result != UCOL_EQUAL) {
+ log_err("ERROR 2 in test 5\n");
+ }
+
+ ucol_getSortKey(coll, strA, 6, (uint8_t *)sortKeyA, sizeof(sortKeyA));
+ ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz));
+ ucol_getSortKey(coll, strB, 6, (uint8_t *)sortKeyB, sizeof(sortKeyB));
+ ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz));
+
+ r = strcmp(sortKeyA, sortKeyAz);
+ if (r <= 0) {
+ log_err("Error 3 in test 5\n");
+ }
+ r = strcmp(sortKeyA, sortKeyB);
+ if (r <= 0) {
+ log_err("Error 4 in test 5\n");
+ }
+ r = strcmp(sortKeyAz, sortKeyBz);
+ if (r != 0) {
+ log_err("Error 5 in test 5\n");
+ }
+
+ ucol_setStrength(coll, UCOL_IDENTICAL);
+ ucol_getSortKey(coll, strA, 6, (uint8_t *)sortKeyA, sizeof(sortKeyA));
+ ucol_getSortKey(coll, strA, -1, (uint8_t *)sortKeyAz, sizeof(sortKeyAz));
+ ucol_getSortKey(coll, strB, 6, (uint8_t *)sortKeyB, sizeof(sortKeyB));
+ ucol_getSortKey(coll, strB, -1, (uint8_t *)sortKeyBz, sizeof(sortKeyBz));
+
+ r = strcmp(sortKeyA, sortKeyAz);
+ if (r <= 0) {
+ log_err("Error 6 in test 5\n");
+ }
+ r = strcmp(sortKeyA, sortKeyB);
+ if (r <= 0) {
+ log_err("Error 7 in test 5\n");
+ }
+ r = strcmp(sortKeyAz, sortKeyBz);
+ if (r != 0) {
+ log_err("Error 8 in test 5\n");
+ }
+ ucol_setStrength(coll, UCOL_TERTIARY);
+ }
+
+
+ /* Test 6: Null character as base of a non-normal combining sequence.*/
+
+ {
+ static const UChar strA[] = {0x41, 0x0, 0x300, 0x316, 0x41, 0x302, 0x00};
+ static const UChar strB[] = {0x41, 0x0, 0x302, 0x316, 0x41, 0x300, 0x00};
+
+ result = ucol_strcoll(coll, strA, 5, strB, 5);
+ if (result != UCOL_LESS) {
+ log_err("Error 1 in test 6\n");
+ }
+ result = ucol_strcoll(coll, strA, -1, strB, -1);
+ if (result != UCOL_EQUAL) {
+ log_err("Error 2 in test 6\n");
+ }
+ }
+
+ ucol_close(coll);
+}
+
+
+
+#if 0
+static void TestGetCaseBit(void) {
+ static const char *caseBitData[] = {
+ "a", "A", "ch", "Ch", "CH",
+ "\\uFF9E", "\\u0009"
+ };
+
+ static const uint8_t results[] = {
+ UCOL_LOWER_CASE, UCOL_UPPER_CASE, UCOL_LOWER_CASE, UCOL_MIXED_CASE, UCOL_UPPER_CASE,
+ UCOL_UPPER_CASE, UCOL_LOWER_CASE
+ };
+
+ uint32_t i, blen = 0;
+ UChar b[256] = {0};
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *UCA = ucol_open("", &status);
+ uint8_t res = 0;
+
+ for(i = 0; i<sizeof(results)/sizeof(results[0]); i++) {
+ blen = u_unescape(caseBitData[i], b, 256);
+ res = ucol_uprv_getCaseBits(UCA, b, blen, &status);
+ if(results[i] != res) {
+ log_err("Expected case = %02X, got %02X for %04X\n", results[i], res, b[0]);
+ }
+ }
+}
+#endif
+
+static void TestHangulTailoring(void) {
+ static const char *koreanData[] = {
+ "\\uac00", "\\u4f3d", "\\u4f73", "\\u5047", "\\u50f9", "\\u52a0", "\\u53ef", "\\u5475",
+ "\\u54e5", "\\u5609", "\\u5ac1", "\\u5bb6", "\\u6687", "\\u67b6", "\\u67b7", "\\u67ef",
+ "\\u6b4c", "\\u73c2", "\\u75c2", "\\u7a3c", "\\u82db", "\\u8304", "\\u8857", "\\u8888",
+ "\\u8a36", "\\u8cc8", "\\u8dcf", "\\u8efb", "\\u8fe6", "\\u99d5",
+ "\\u4EEE", "\\u50A2", "\\u5496", "\\u54FF", "\\u5777", "\\u5B8A", "\\u659D", "\\u698E",
+ "\\u6A9F", "\\u73C8", "\\u7B33", "\\u801E", "\\u8238", "\\u846D", "\\u8B0C"
+ };
+
+ const char *rules =
+ "&\\uac00 <<< \\u4f3d <<< \\u4f73 <<< \\u5047 <<< \\u50f9 <<< \\u52a0 <<< \\u53ef <<< \\u5475 "
+ "<<< \\u54e5 <<< \\u5609 <<< \\u5ac1 <<< \\u5bb6 <<< \\u6687 <<< \\u67b6 <<< \\u67b7 <<< \\u67ef "
+ "<<< \\u6b4c <<< \\u73c2 <<< \\u75c2 <<< \\u7a3c <<< \\u82db <<< \\u8304 <<< \\u8857 <<< \\u8888 "
+ "<<< \\u8a36 <<< \\u8cc8 <<< \\u8dcf <<< \\u8efb <<< \\u8fe6 <<< \\u99d5 "
+ "<<< \\u4EEE <<< \\u50A2 <<< \\u5496 <<< \\u54FF <<< \\u5777 <<< \\u5B8A <<< \\u659D <<< \\u698E "
+ "<<< \\u6A9F <<< \\u73C8 <<< \\u7B33 <<< \\u801E <<< \\u8238 <<< \\u846D <<< \\u8B0C";
+
+
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[2048] = { 0 };
+ uint32_t rlen = u_unescape(rules, rlz, 2048);
+
+ UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+
+ log_verbose("Using start of korean rules\n");
+
+ if(U_SUCCESS(status)) {
+ genericOrderingTest(coll, koreanData, sizeof(koreanData)/sizeof(koreanData[0]));
+ } else {
+ log_err("Unable to open collator with rules %s\n", rules);
+ }
+
+ log_verbose("Setting jamoSpecial to TRUE and testing once more\n");
+ ((UCATableHeader *)coll->image)->jamoSpecial = TRUE; /* don't try this at home */
+ genericOrderingTest(coll, koreanData, sizeof(koreanData)/sizeof(koreanData[0]));
+
+ ucol_close(coll);
+
+ log_verbose("Using ko__LOTUS locale\n");
+ genericLocaleStarter("ko__LOTUS", koreanData, sizeof(koreanData)/sizeof(koreanData[0]));
+}
+
+static void TestCompressOverlap(void) {
+ UChar secstr[150];
+ UChar tertstr[150];
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll;
+ char result[200];
+ uint32_t resultlen;
+ int count = 0;
+ char *tempptr;
+
+ coll = ucol_open("", &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Collator can't be created\n");
+ return;
+ }
+ while (count < 149) {
+ secstr[count] = 0x0020; /* [06, 05, 05] */
+ tertstr[count] = 0x0020;
+ count ++;
+ }
+
+ /* top down compression ----------------------------------- */
+ secstr[count] = 0x0332; /* [, 87, 05] */
+ tertstr[count] = 0x3000; /* [06, 05, 07] */
+
+ /* no compression secstr should have 150 secondary bytes, tertstr should
+ have 150 tertiary bytes.
+ with correct overlapping compression, secstr should have 4 secondary
+ bytes, tertstr should have > 2 tertiary bytes */
+ resultlen = ucol_getSortKey(coll, secstr, 150, (uint8_t *)result, 250);
+ tempptr = uprv_strchr(result, 1) + 1;
+ while (*(tempptr + 1) != 1) {
+ /* the last secondary collation element is not checked since it is not
+ part of the compression */
+ if (*tempptr < UCOL_COMMON_TOP2 - UCOL_TOP_COUNT2) {
+ log_err("Secondary compression overlapped\n");
+ }
+ tempptr ++;
+ }
+
+ /* tertiary top/bottom/common for en_US is similar to the secondary
+ top/bottom/common */
+ resultlen = ucol_getSortKey(coll, tertstr, 150, (uint8_t *)result, 250);
+ tempptr = uprv_strrchr(result, 1) + 1;
+ while (*(tempptr + 1) != 0) {
+ /* the last secondary collation element is not checked since it is not
+ part of the compression */
+ if (*tempptr < coll->tertiaryTop - coll->tertiaryTopCount) {
+ log_err("Tertiary compression overlapped\n");
+ }
+ tempptr ++;
+ }
+
+ /* bottom up compression ------------------------------------- */
+ secstr[count] = 0;
+ tertstr[count] = 0;
+ resultlen = ucol_getSortKey(coll, secstr, 150, (uint8_t *)result, 250);
+ tempptr = uprv_strchr(result, 1) + 1;
+ while (*(tempptr + 1) != 1) {
+ /* the last secondary collation element is not checked since it is not
+ part of the compression */
+ if (*tempptr > UCOL_COMMON_BOT2 + UCOL_BOT_COUNT2) {
+ log_err("Secondary compression overlapped\n");
+ }
+ tempptr ++;
+ }
+
+ /* tertiary top/bottom/common for en_US is similar to the secondary
+ top/bottom/common */
+ resultlen = ucol_getSortKey(coll, tertstr, 150, (uint8_t *)result, 250);
+ tempptr = uprv_strrchr(result, 1) + 1;
+ while (*(tempptr + 1) != 0) {
+ /* the last secondary collation element is not checked since it is not
+ part of the compression */
+ if (*tempptr > coll->tertiaryBottom + coll->tertiaryBottomCount) {
+ log_err("Tertiary compression overlapped\n");
+ }
+ tempptr ++;
+ }
+
+ ucol_close(coll);
+}
+
+static void TestCyrillicTailoring(void) {
+ static const char *test[] = {
+ "\\u0410b",
+ "\\u0410\\u0306a",
+ "\\u04d0A"
+ };
+
+ /* Russian overrides contractions, so this test is not valid anymore */
+ /*genericLocaleStarter("ru", test, 3);*/
+
+ genericLocaleStarter("root", test, 3);
+ genericRulesStarter("&\\u0410 = \\u0410", test, 3);
+ genericRulesStarter("&Z < \\u0410", test, 3);
+ genericRulesStarter("&\\u0410 = \\u0410 < \\u04d0", test, 3);
+ genericRulesStarter("&Z < \\u0410 < \\u04d0", test, 3);
+ genericRulesStarter("&\\u0410 = \\u0410 < \\u0410\\u0301", test, 3);
+ genericRulesStarter("&Z < \\u0410 < \\u0410\\u0301", test, 3);
+}
+
+static void TestSuppressContractions(void) {
+
+ static const char *testNoCont2[] = {
+ "\\u0410\\u0302a",
+ "\\u0410\\u0306b",
+ "\\u0410c"
+ };
+ static const char *testNoCont[] = {
+ "a\\u0410",
+ "A\\u0410\\u0306",
+ "\\uFF21\\u0410\\u0302"
+ };
+
+ genericRulesStarter("[suppressContractions [\\u0400-\\u047f]]", testNoCont, 3);
+ genericRulesStarter("[suppressContractions [\\u0400-\\u047f]]", testNoCont2, 3);
+}
+
+static void TestContraction(void) {
+ const static char *testrules[] = {
+ "&A = AB / B",
+ "&A = A\\u0306/\\u0306",
+ "&c = ch / h"
+ };
+ const static UChar testdata[][2] = {
+ {0x0041 /* 'A' */, 0x0042 /* 'B' */},
+ {0x0041 /* 'A' */, 0x0306 /* combining breve */},
+ {0x0063 /* 'c' */, 0x0068 /* 'h' */}
+ };
+ const static UChar testdata2[][2] = {
+ {0x0063 /* 'c' */, 0x0067 /* 'g' */},
+ {0x0063 /* 'c' */, 0x0068 /* 'h' */},
+ {0x0063 /* 'c' */, 0x006C /* 'l' */}
+ };
+ const static char *testrules3[] = {
+ "&z < xyz &xyzw << B",
+ "&z < xyz &xyz << B / w",
+ "&z < ch &achm << B",
+ "&z < ch &a << B / chm",
+ "&\\ud800\\udc00w << B",
+ "&\\ud800\\udc00 << B / w",
+ "&a\\ud800\\udc00m << B",
+ "&a << B / \\ud800\\udc00m",
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll;
+ UChar rule[256] = {0};
+ uint32_t rlen = 0;
+ int i;
+
+ for (i = 0; i < sizeof(testrules) / sizeof(testrules[0]); i ++) {
+ UCollationElements *iter1;
+ int j = 0;
+ log_verbose("Rule %s for testing\n", testrules[i]);
+ rlen = u_unescape(testrules[i], rule, 32);
+ coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Collator creation failed %s\n", testrules[i]);
+ return;
+ }
+ iter1 = ucol_openElements(coll, testdata[i], 2, &status);
+ if (U_FAILURE(status)) {
+ log_err("Collation iterator creation failed\n");
+ return;
+ }
+ while (j < 2) {
+ UCollationElements *iter2 = ucol_openElements(coll,
+ &(testdata[i][j]),
+ 1, &status);
+ uint32_t ce;
+ if (U_FAILURE(status)) {
+ log_err("Collation iterator creation failed\n");
+ return;
+ }
+ ce = ucol_next(iter2, &status);
+ while (ce != UCOL_NULLORDER) {
+ if ((uint32_t)ucol_next(iter1, &status) != ce) {
+ log_err("Collation elements in contraction split does not match\n");
+ return;
+ }
+ ce = ucol_next(iter2, &status);
+ }
+ j ++;
+ ucol_closeElements(iter2);
+ }
+ if (ucol_next(iter1, &status) != UCOL_NULLORDER) {
+ log_err("Collation elements not exhausted\n");
+ return;
+ }
+ ucol_closeElements(iter1);
+ ucol_close(coll);
+ }
+
+ rlen = u_unescape("& a < b < c < ch < d & c = ch / h", rule, 256);
+ coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status);
+ if (ucol_strcoll(coll, testdata2[0], 2, testdata2[1], 2) != UCOL_LESS) {
+ log_err("Expected \\u%04x\\u%04x < \\u%04x\\u%04x\n",
+ testdata2[0][0], testdata2[0][1], testdata2[1][0],
+ testdata2[1][1]);
+ return;
+ }
+ if (ucol_strcoll(coll, testdata2[1], 2, testdata2[2], 2) != UCOL_LESS) {
+ log_err("Expected \\u%04x\\u%04x < \\u%04x\\u%04x\n",
+ testdata2[1][0], testdata2[1][1], testdata2[2][0],
+ testdata2[2][1]);
+ return;
+ }
+ ucol_close(coll);
+
+ for (i = 0; i < sizeof(testrules3) / sizeof(testrules3[0]); i += 2) {
+ UCollator *coll1,
+ *coll2;
+ UCollationElements *iter1,
+ *iter2;
+ UChar ch = 0x0042 /* 'B' */;
+ uint32_t ce;
+ rlen = u_unescape(testrules3[i], rule, 32);
+ coll1 = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status);
+ rlen = u_unescape(testrules3[i + 1], rule, 32);
+ coll2 = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Collator creation failed %s\n", testrules[i]);
+ return;
+ }
+ iter1 = ucol_openElements(coll1, &ch, 1, &status);
+ iter2 = ucol_openElements(coll2, &ch, 1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Collation iterator creation failed\n");
+ return;
+ }
+ ce = ucol_next(iter1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Retrieving ces failed\n");
+ return;
+ }
+ while (ce != UCOL_NULLORDER) {
+ if (ce != (uint32_t)ucol_next(iter2, &status)) {
+ log_err("CEs does not match\n");
+ return;
+ }
+ ce = ucol_next(iter1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Retrieving ces failed\n");
+ return;
+ }
+ }
+ if (ucol_next(iter2, &status) != UCOL_NULLORDER) {
+ log_err("CEs not exhausted\n");
+ return;
+ }
+ ucol_closeElements(iter1);
+ ucol_closeElements(iter2);
+ ucol_close(coll1);
+ ucol_close(coll2);
+ }
+}
+
+static void TestExpansion(void) {
+ const static char *testrules[] = {
+ "&J << K / B & K << M",
+ "&J << K / B << M"
+ };
+ const static UChar testdata[][3] = {
+ {0x004A /*'J'*/, 0x0041 /*'A'*/, 0},
+ {0x004D /*'M'*/, 0x0041 /*'A'*/, 0},
+ {0x004B /*'K'*/, 0x0041 /*'A'*/, 0},
+ {0x004B /*'K'*/, 0x0043 /*'C'*/, 0},
+ {0x004A /*'J'*/, 0x0043 /*'C'*/, 0},
+ {0x004D /*'M'*/, 0x0043 /*'C'*/, 0}
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll;
+ UChar rule[256] = {0};
+ uint32_t rlen = 0;
+ int i;
+
+ for (i = 0; i < sizeof(testrules) / sizeof(testrules[0]); i ++) {
+ int j = 0;
+ log_verbose("Rule %s for testing\n", testrules[i]);
+ rlen = u_unescape(testrules[i], rule, 32);
+ coll = ucol_openRules(rule, rlen, UCOL_ON, UCOL_TERTIARY,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Collator creation failed %s\n", testrules[i]);
+ return;
+ }
+
+ for (j = 0; j < 5; j ++) {
+ doTest(coll, testdata[j], testdata[j + 1], UCOL_LESS);
+ }
+ ucol_close(coll);
+ }
+}
+
+#if 0
+/* this test tests the current limitations of the engine */
+/* it always fail, so it is disabled by default */
+static void TestLimitations(void) {
+ /* recursive expansions */
+ {
+ static const char *rule = "&a=b/c&d=c/e";
+ static const char *tlimit01[] = {"add","b","adf"};
+ static const char *tlimit02[] = {"aa","b","af"};
+ log_verbose("recursive expansions\n");
+ genericRulesStarter(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]));
+ genericRulesStarter(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]));
+ }
+ /* contractions spanning expansions */
+ {
+ static const char *rule = "&a<<<c/e&g<<<eh";
+ static const char *tlimit01[] = {"ad","c","af","f","ch","h"};
+ static const char *tlimit02[] = {"ad","c","ch","af","f","h"};
+ log_verbose("contractions spanning expansions\n");
+ genericRulesStarter(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]));
+ genericRulesStarter(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]));
+ }
+ /* normalization: nulls in contractions */
+ {
+ static const char *rule = "&a<<<\\u0000\\u0302";
+ static const char *tlimit01[] = {"a","\\u0000\\u0302\\u0327"};
+ static const char *tlimit02[] = {"\\u0000\\u0302\\u0327","a"};
+ static const UColAttribute att[] = { UCOL_DECOMPOSITION_MODE };
+ static const UColAttributeValue valOn[] = { UCOL_ON };
+ static const UColAttributeValue valOff[] = { UCOL_OFF };
+
+ log_verbose("NULL in contractions\n");
+ genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOn, 1);
+ genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOn, 1);
+ genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOff, 1);
+ genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOff, 1);
+
+ }
+ /* normalization: contractions spanning normalization */
+ {
+ static const char *rule = "&a<<<\\u0000\\u0302";
+ static const char *tlimit01[] = {"a","\\u0000\\u0302\\u0327"};
+ static const char *tlimit02[] = {"\\u0000\\u0302\\u0327","a"};
+ static const UColAttribute att[] = { UCOL_DECOMPOSITION_MODE };
+ static const UColAttributeValue valOn[] = { UCOL_ON };
+ static const UColAttributeValue valOff[] = { UCOL_OFF };
+
+ log_verbose("contractions spanning normalization\n");
+ genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOn, 1);
+ genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOn, 1);
+ genericRulesStarterWithOptions(rule, tlimit01, 2, att, valOff, 1);
+ genericRulesStarterWithOptions(rule, tlimit02, 2, att, valOff, 1);
+
+ }
+ /* variable top: */
+ {
+ /*static const char *rule2 = "&\\u2010<x=[variable top]<z";*/
+ static const char *rule = "&\\u2010<x<[variable top]=z";
+ /*static const char *rule3 = "&' '<x<[variable top]=z";*/
+ static const char *tlimit01[] = {" ", "z", "zb", "a", " b", "xb", "b", "c" };
+ static const char *tlimit02[] = {"-", "-x", "x","xb", "-z", "z", "zb", "-a", "a", "-b", "b", "c"};
+ static const char *tlimit03[] = {" ", "xb", "z", "zb", "a", " b", "b", "c" };
+ static const UColAttribute att[] = { UCOL_ALTERNATE_HANDLING, UCOL_STRENGTH };
+ static const UColAttributeValue valOn[] = { UCOL_SHIFTED, UCOL_QUATERNARY };
+ static const UColAttributeValue valOff[] = { UCOL_NON_IGNORABLE, UCOL_TERTIARY };
+
+ log_verbose("variable top\n");
+ genericRulesStarterWithOptions(rule, tlimit03, sizeof(tlimit03)/sizeof(tlimit03[0]), att, valOn, sizeof(att)/sizeof(att[0]));
+ genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOn, sizeof(att)/sizeof(att[0]));
+ genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOn, sizeof(att)/sizeof(att[0]));
+ genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOff, sizeof(att)/sizeof(att[0]));
+ genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOff, sizeof(att)/sizeof(att[0]));
+
+ }
+ /* case level */
+ {
+ static const char *rule = "&c<ch<<<cH<<<Ch<<<CH";
+ static const char *tlimit01[] = {"c","CH","Ch","cH","ch"};
+ static const char *tlimit02[] = {"c","CH","cH","Ch","ch"};
+ static const UColAttribute att[] = { UCOL_CASE_FIRST};
+ static const UColAttributeValue valOn[] = { UCOL_UPPER_FIRST};
+ /*static const UColAttributeValue valOff[] = { UCOL_OFF};*/
+ log_verbose("case level\n");
+ genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOn, sizeof(att)/sizeof(att[0]));
+ genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOn, sizeof(att)/sizeof(att[0]));
+ /*genericRulesStarterWithOptions(rule, tlimit01, sizeof(tlimit01)/sizeof(tlimit01[0]), att, valOff, sizeof(att)/sizeof(att[0]));*/
+ /*genericRulesStarterWithOptions(rule, tlimit02, sizeof(tlimit02)/sizeof(tlimit02[0]), att, valOff, sizeof(att)/sizeof(att[0]));*/
+ }
+
+}
+#endif
+
+static void TestBocsuCoverage(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char *testString = "\\u0041\\u0441\\u4441\\U00044441\\u4441\\u0441\\u0041";
+ UChar test[256] = {0};
+ uint32_t tlen = u_unescape(testString, test, 32);
+ uint8_t key[256] = {0};
+ uint32_t klen = 0;
+
+ UCollator *coll = ucol_open("", &status);
+ if(U_SUCCESS(status)) {
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_IDENTICAL, &status);
+
+ klen = ucol_getSortKey(coll, test, tlen, key, 256);
+
+ ucol_close(coll);
+ } else {
+ log_data_err("Couldn't open UCA\n");
+ }
+}
+
+static void TestVariableTopSetting(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ const UChar *current = NULL;
+ uint32_t varTopOriginal = 0, varTop1, varTop2;
+ UCollator *coll = ucol_open("", &status);
+ if(U_SUCCESS(status)) {
+
+ uint32_t strength = 0;
+ uint16_t specs = 0;
+ uint32_t chOffset = 0;
+ uint32_t chLen = 0;
+ uint32_t exOffset = 0;
+ uint32_t exLen = 0;
+ uint32_t oldChOffset = 0;
+ uint32_t oldChLen = 0;
+ uint32_t oldExOffset = 0;
+ uint32_t oldExLen = 0;
+ uint32_t prefixOffset = 0;
+ uint32_t prefixLen = 0;
+
+ UBool startOfRules = TRUE;
+ UColTokenParser src;
+ UColOptionSet opts;
+
+ UChar *rulesCopy = NULL;
+ uint32_t rulesLen;
+
+ UCollationResult result;
+
+ UChar first[256] = { 0 };
+ UChar second[256] = { 0 };
+ UParseError parseError;
+ int32_t myQ = QUICK;
+
+ src.opts = &opts;
+
+ if(QUICK <= 0) {
+ QUICK = 1;
+ }
+
+ /* this test will fail when normalization is turned on */
+ /* therefore we always turn off exhaustive mode for it */
+ { /* QUICK > 0*/
+ log_verbose("Slide variable top over UCARules\n");
+ rulesLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rulesCopy, 0);
+ rulesCopy = (UChar *)malloc((rulesLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE)*sizeof(UChar));
+ rulesLen = ucol_getRulesEx(coll, UCOL_FULL_RULES, rulesCopy, rulesLen+UCOL_TOK_EXTRA_RULE_SPACE_SIZE);
+
+ if(U_SUCCESS(status) && rulesLen > 0) {
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ src.current = src.source = rulesCopy;
+ src.end = rulesCopy+rulesLen;
+ src.extraCurrent = src.end;
+ src.extraEnd = src.end+UCOL_TOK_EXTRA_RULE_SPACE_SIZE;
+
+ while ((current = ucol_tok_parseNextToken(&src, startOfRules, &parseError,&status)) != NULL) {
+ strength = src.parsedToken.strength;
+ chOffset = src.parsedToken.charsOffset;
+ chLen = src.parsedToken.charsLen;
+ exOffset = src.parsedToken.extensionOffset;
+ exLen = src.parsedToken.extensionLen;
+ prefixOffset = src.parsedToken.prefixOffset;
+ prefixLen = src.parsedToken.prefixLen;
+ specs = src.parsedToken.flags;
+
+ startOfRules = FALSE;
+ {
+ log_verbose("%04X %d ", *(rulesCopy+chOffset), chLen);
+ }
+ if(strength == UCOL_PRIMARY) {
+ status = U_ZERO_ERROR;
+ varTopOriginal = ucol_getVariableTop(coll, &status);
+ varTop1 = ucol_setVariableTop(coll, rulesCopy+oldChOffset, oldChLen, &status);
+ if(U_FAILURE(status)) {
+ char buffer[256];
+ char *buf = buffer;
+ uint32_t i = 0, j;
+ uint32_t CE = UCOL_NO_MORE_CES;
+
+ /* before we start screaming, let's see if there is a problem with the rules */
+ collIterate s;
+ uprv_init_collIterate(coll, rulesCopy+oldChOffset, oldChLen, &s);
+
+ CE = ucol_getNextCE(coll, &s, &status);
+
+ for(i = 0; i < oldChLen; i++) {
+ j = sprintf(buf, "%04X ", *(rulesCopy+oldChOffset+i));
+ buf += j;
+ }
+ if(status == U_PRIMARY_TOO_LONG_ERROR) {
+ log_verbose("= Expected failure for %s =", buffer);
+ } else {
+ if(s.pos == s.endp) {
+ log_err("Unexpected failure setting variable top at offset %d. Error %s. Codepoints: %s\n",
+ oldChOffset, u_errorName(status), buffer);
+ } else {
+ log_verbose("There is a goofy contraction in UCA rules that does not appear in the fractional UCA. Codepoints: %s\n",
+ buffer);
+ }
+ }
+ }
+ varTop2 = ucol_getVariableTop(coll, &status);
+ if((varTop1 & 0xFFFF0000) != (varTop2 & 0xFFFF0000)) {
+ log_err("cannot retrieve set varTop value!\n");
+ continue;
+ }
+
+ if((varTop1 & 0xFFFF0000) > 0 && oldExLen == 0) {
+
+ u_strncpy(first, rulesCopy+oldChOffset, oldChLen);
+ u_strncpy(first+oldChLen, rulesCopy+chOffset, chLen);
+ u_strncpy(first+oldChLen+chLen, rulesCopy+oldChOffset, oldChLen);
+ first[2*oldChLen+chLen] = 0;
+
+ if(oldExLen == 0) {
+ u_strncpy(second, rulesCopy+chOffset, chLen);
+ second[chLen] = 0;
+ } else { /* This is skipped momentarily, but should work once UCARules are fully UCA conformant */
+ u_strncpy(second, rulesCopy+oldExOffset, oldExLen);
+ u_strncpy(second+oldChLen, rulesCopy+chOffset, chLen);
+ u_strncpy(second+oldChLen+chLen, rulesCopy+oldExOffset, oldExLen);
+ second[2*oldExLen+chLen] = 0;
+ }
+ result = ucol_strcoll(coll, first, -1, second, -1);
+ if(result == UCOL_EQUAL) {
+ doTest(coll, first, second, UCOL_EQUAL);
+ } else {
+ log_verbose("Suspicious strcoll result for %04X and %04X\n", *(rulesCopy+oldChOffset), *(rulesCopy+chOffset));
+ }
+ }
+ }
+ if(strength != UCOL_TOK_RESET) {
+ oldChOffset = chOffset;
+ oldChLen = chLen;
+ oldExOffset = exOffset;
+ oldExLen = exLen;
+ }
+ }
+ status = U_ZERO_ERROR;
+ }
+ else {
+ log_err("Unexpected failure getting rules %s\n", u_errorName(status));
+ return;
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error parsing rules %s\n", u_errorName(status));
+ return;
+ }
+ status = U_ZERO_ERROR;
+ }
+
+ QUICK = myQ;
+
+ log_verbose("Testing setting variable top to contractions\n");
+ {
+ /* uint32_t tailoredCE = UCOL_NOT_FOUND; */
+ /*UChar *conts = (UChar *)((uint8_t *)coll->image + coll->image->UCAConsts+sizeof(UCAConstants));*/
+ UChar *conts = (UChar *)((uint8_t *)coll->image + coll->image->contractionUCACombos);
+ while(*conts != 0) {
+ if(*(conts+2) == 0) {
+ varTop1 = ucol_setVariableTop(coll, conts, -1, &status);
+ } else {
+ varTop1 = ucol_setVariableTop(coll, conts, 3, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Couldn't set variable top to a contraction %04X %04X %04X\n",
+ *conts, *(conts+1), *(conts+2));
+ status = U_ZERO_ERROR;
+ }
+ conts+=3;
+ }
+
+ status = U_ZERO_ERROR;
+
+ first[0] = 0x0040;
+ first[1] = 0x0050;
+ first[2] = 0x0000;
+
+ ucol_setVariableTop(coll, first, -1, &status);
+
+ if(U_SUCCESS(status)) {
+ log_err("Invalid contraction succeded in setting variable top!\n");
+ }
+
+ }
+
+ log_verbose("Test restoring variable top\n");
+
+ status = U_ZERO_ERROR;
+ ucol_restoreVariableTop(coll, varTopOriginal, &status);
+ if(varTopOriginal != ucol_getVariableTop(coll, &status)) {
+ log_err("Couldn't restore old variable top\n");
+ }
+
+ log_verbose("Testing calling with error set\n");
+
+ status = U_INTERNAL_PROGRAM_ERROR;
+ varTop1 = ucol_setVariableTop(coll, first, 1, &status);
+ varTop2 = ucol_getVariableTop(coll, &status);
+ ucol_restoreVariableTop(coll, varTop2, &status);
+ varTop1 = ucol_setVariableTop(NULL, first, 1, &status);
+ varTop2 = ucol_getVariableTop(NULL, &status);
+ ucol_restoreVariableTop(NULL, varTop2, &status);
+ if(status != U_INTERNAL_PROGRAM_ERROR) {
+ log_err("Bad reaction to passed error!\n");
+ }
+ free(rulesCopy);
+ ucol_close(coll);
+ } else {
+ log_data_err("Couldn't open UCA collator\n");
+ }
+
+}
+
+static void TestNonChars(void) {
+ static const char *test[] = {
+ "\\u0000",
+ "\\uFFFE", "\\uFFFF",
+ "\\U0001FFFE", "\\U0001FFFF",
+ "\\U0002FFFE", "\\U0002FFFF",
+ "\\U0003FFFE", "\\U0003FFFF",
+ "\\U0004FFFE", "\\U0004FFFF",
+ "\\U0005FFFE", "\\U0005FFFF",
+ "\\U0006FFFE", "\\U0006FFFF",
+ "\\U0007FFFE", "\\U0007FFFF",
+ "\\U0008FFFE", "\\U0008FFFF",
+ "\\U0009FFFE", "\\U0009FFFF",
+ "\\U000AFFFE", "\\U000AFFFF",
+ "\\U000BFFFE", "\\U000BFFFF",
+ "\\U000CFFFE", "\\U000CFFFF",
+ "\\U000DFFFE", "\\U000DFFFF",
+ "\\U000EFFFE", "\\U000EFFFF",
+ "\\U000FFFFE", "\\U000FFFFF",
+ "\\U0010FFFE", "\\U0010FFFF"
+ };
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("en_US", &status);
+
+ log_verbose("Test non characters\n");
+
+ if(U_SUCCESS(status)) {
+ genericOrderingTestWithResult(coll, test, 35, UCOL_EQUAL);
+ } else {
+ log_err("Unable to open collator\n");
+ }
+
+ ucol_close(coll);
+}
+
+static void TestExtremeCompression(void) {
+ static char *test[4];
+ int32_t j = 0, i = 0;
+
+ for(i = 0; i<4; i++) {
+ test[i] = (char *)malloc(2048*sizeof(char));
+ }
+
+ for(j = 20; j < 500; j++) {
+ for(i = 0; i<4; i++) {
+ uprv_memset(test[i], 'a', (j-1)*sizeof(char));
+ test[i][j-1] = (char)('a'+i);
+ test[i][j] = 0;
+ }
+ genericLocaleStarter("en_US", (const char **)test, 4);
+ }
+
+
+ for(i = 0; i<4; i++) {
+ free(test[i]);
+ }
+}
+
+#if 0
+static void TestExtremeCompression(void) {
+ static char *test[4];
+ int32_t j = 0, i = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("en_US", status);
+ for(i = 0; i<4; i++) {
+ test[i] = (char *)malloc(2048*sizeof(char));
+ }
+ for(j = 10; j < 2048; j++) {
+ for(i = 0; i<4; i++) {
+ uprv_memset(test[i], 'a', (j-2)*sizeof(char));
+ test[i][j-1] = (char)('a'+i);
+ test[i][j] = 0;
+ }
+ }
+ genericLocaleStarter("en_US", (const char **)test, 4);
+
+ for(j = 10; j < 2048; j++) {
+ for(i = 0; i<1; i++) {
+ uprv_memset(test[i], 'a', (j-1)*sizeof(char));
+ test[i][j] = 0;
+ }
+ }
+ for(i = 0; i<4; i++) {
+ free(test[i]);
+ }
+}
+#endif
+
+static void TestSurrogates(void) {
+ static const char *test[] = {
+ "z","\\ud900\\udc25", "\\ud805\\udc50",
+ "\\ud800\\udc00y", "\\ud800\\udc00r",
+ "\\ud800\\udc00f", "\\ud800\\udc00",
+ "\\ud800\\udc00c", "\\ud800\\udc00b",
+ "\\ud800\\udc00fa", "\\ud800\\udc00fb",
+ "\\ud800\\udc00a",
+ "c", "b"
+ };
+
+ static const char *rule =
+ "&z < \\ud900\\udc25 < \\ud805\\udc50"
+ "< \\ud800\\udc00y < \\ud800\\udc00r"
+ "< \\ud800\\udc00f << \\ud800\\udc00"
+ "< \\ud800\\udc00fa << \\ud800\\udc00fb"
+ "< \\ud800\\udc00a < c < b" ;
+
+ genericRulesStarter(rule, test, 14);
+}
+
+/* This is a test for prefix implementation, used by JIS X 4061 collation rules */
+static void TestPrefix(void) {
+ uint32_t i;
+
+ static const struct {
+ const char *rules;
+ const char *data[50];
+ const uint32_t len;
+ } tests[] = {
+ { "&z <<< z|a",
+ {"zz", "za"}, 2 },
+
+ { "&z <<< z| a",
+ {"zz", "za"}, 2 },
+ { "[strength I]"
+ "&a=\\ud900\\udc25"
+ "&z<<<\\ud900\\udc25|a",
+ {"aa", "az", "\\ud900\\udc25z", "\\ud900\\udc25a", "zz"}, 4 },
+ };
+
+
+ for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len);
+ }
+}
+
+/* This test uses data suplied by Masashiko Maedera to test the implementation */
+/* JIS X 4061 collation order implementation */
+static void TestNewJapanese(void) {
+
+ static const char * const test1[] = {
+ "\\u30b7\\u30e3\\u30fc\\u30ec",
+ "\\u30b7\\u30e3\\u30a4",
+ "\\u30b7\\u30e4\\u30a3",
+ "\\u30b7\\u30e3\\u30ec",
+ "\\u3061\\u3087\\u3053",
+ "\\u3061\\u3088\\u3053",
+ "\\u30c1\\u30e7\\u30b3\\u30ec\\u30fc\\u30c8",
+ "\\u3066\\u30fc\\u305f",
+ "\\u30c6\\u30fc\\u30bf",
+ "\\u30c6\\u30a7\\u30bf",
+ "\\u3066\\u3048\\u305f",
+ "\\u3067\\u30fc\\u305f",
+ "\\u30c7\\u30fc\\u30bf",
+ "\\u30c7\\u30a7\\u30bf",
+ "\\u3067\\u3048\\u305f",
+ "\\u3066\\u30fc\\u305f\\u30fc",
+ "\\u30c6\\u30fc\\u30bf\\u30a1",
+ "\\u30c6\\u30a7\\u30bf\\u30fc",
+ "\\u3066\\u3047\\u305f\\u3041",
+ "\\u3066\\u3048\\u305f\\u30fc",
+ "\\u3067\\u30fc\\u305f\\u30fc",
+ "\\u30c7\\u30fc\\u30bf\\u30a1",
+ "\\u3067\\u30a7\\u305f\\u30a1",
+ "\\u30c7\\u3047\\u30bf\\u3041",
+ "\\u30c7\\u30a8\\u30bf\\u30a2",
+ "\\u3072\\u3086",
+ "\\u3073\\u3085\\u3042",
+ "\\u3074\\u3085\\u3042",
+ "\\u3073\\u3085\\u3042\\u30fc",
+ "\\u30d3\\u30e5\\u30a2\\u30fc",
+ "\\u3074\\u3085\\u3042\\u30fc",
+ "\\u30d4\\u30e5\\u30a2\\u30fc",
+ "\\u30d2\\u30e5\\u30a6",
+ "\\u30d2\\u30e6\\u30a6",
+ "\\u30d4\\u30e5\\u30a6\\u30a2",
+ "\\u3073\\u3085\\u30fc\\u3042\\u30fc",
+ "\\u30d3\\u30e5\\u30fc\\u30a2\\u30fc",
+ "\\u30d3\\u30e5\\u30a6\\u30a2\\u30fc",
+ "\\u3072\\u3085\\u3093",
+ "\\u3074\\u3085\\u3093",
+ "\\u3075\\u30fc\\u308a",
+ "\\u30d5\\u30fc\\u30ea",
+ "\\u3075\\u3045\\u308a",
+ "\\u3075\\u30a5\\u308a",
+ "\\u3075\\u30a5\\u30ea",
+ "\\u30d5\\u30a6\\u30ea",
+ "\\u3076\\u30fc\\u308a",
+ "\\u30d6\\u30fc\\u30ea",
+ "\\u3076\\u3045\\u308a",
+ "\\u30d6\\u30a5\\u308a",
+ "\\u3077\\u3046\\u308a",
+ "\\u30d7\\u30a6\\u30ea",
+ "\\u3075\\u30fc\\u308a\\u30fc",
+ "\\u30d5\\u30a5\\u30ea\\u30fc",
+ "\\u3075\\u30a5\\u308a\\u30a3",
+ "\\u30d5\\u3045\\u308a\\u3043",
+ "\\u30d5\\u30a6\\u30ea\\u30fc",
+ "\\u3075\\u3046\\u308a\\u3043",
+ "\\u30d6\\u30a6\\u30ea\\u30a4",
+ "\\u3077\\u30fc\\u308a\\u30fc",
+ "\\u3077\\u30a5\\u308a\\u30a4",
+ "\\u3077\\u3046\\u308a\\u30fc",
+ "\\u30d7\\u30a6\\u30ea\\u30a4",
+ "\\u30d5\\u30fd",
+ "\\u3075\\u309e",
+ "\\u3076\\u309d",
+ "\\u3076\\u3075",
+ "\\u3076\\u30d5",
+ "\\u30d6\\u3075",
+ "\\u30d6\\u30d5",
+ "\\u3076\\u309e",
+ "\\u3076\\u3077",
+ "\\u30d6\\u3077",
+ "\\u3077\\u309d",
+ "\\u30d7\\u30fd",
+ "\\u3077\\u3075",
+};
+
+ static const char *test2[] = {
+ "\\u306f\\u309d", /* H\\u309d */
+ "\\u30cf\\u30fd", /* K\\u30fd */
+ "\\u306f\\u306f", /* HH */
+ "\\u306f\\u30cf", /* HK */
+ "\\u30cf\\u30cf", /* KK */
+ "\\u306f\\u309e", /* H\\u309e */
+ "\\u30cf\\u30fe", /* K\\u30fe */
+ "\\u306f\\u3070", /* HH\\u309b */
+ "\\u30cf\\u30d0", /* KK\\u309b */
+ "\\u306f\\u3071", /* HH\\u309c */
+ "\\u30cf\\u3071", /* KH\\u309c */
+ "\\u30cf\\u30d1", /* KK\\u309c */
+ "\\u3070\\u309d", /* H\\u309b\\u309d */
+ "\\u30d0\\u30fd", /* K\\u309b\\u30fd */
+ "\\u3070\\u306f", /* H\\u309bH */
+ "\\u30d0\\u30cf", /* K\\u309bK */
+ "\\u3070\\u309e", /* H\\u309b\\u309e */
+ "\\u30d0\\u30fe", /* K\\u309b\\u30fe */
+ "\\u3070\\u3070", /* H\\u309bH\\u309b */
+ "\\u30d0\\u3070", /* K\\u309bH\\u309b */
+ "\\u30d0\\u30d0", /* K\\u309bK\\u309b */
+ "\\u3070\\u3071", /* H\\u309bH\\u309c */
+ "\\u30d0\\u30d1", /* K\\u309bK\\u309c */
+ "\\u3071\\u309d", /* H\\u309c\\u309d */
+ "\\u30d1\\u30fd", /* K\\u309c\\u30fd */
+ "\\u3071\\u306f", /* H\\u309cH */
+ "\\u30d1\\u30cf", /* K\\u309cK */
+ "\\u3071\\u3070", /* H\\u309cH\\u309b */
+ "\\u3071\\u30d0", /* H\\u309cK\\u309b */
+ "\\u30d1\\u30d0", /* K\\u309cK\\u309b */
+ "\\u3071\\u3071", /* H\\u309cH\\u309c */
+ "\\u30d1\\u30d1", /* K\\u309cK\\u309c */
+ };
+ /*
+ static const char *test3[] = {
+ "\\u221er\\u221e",
+ "\\u221eR#",
+ "\\u221et\\u221e",
+ "#r\\u221e",
+ "#R#",
+ "#t%",
+ "#T%",
+ "8t\\u221e",
+ "8T\\u221e",
+ "8t#",
+ "8T#",
+ "8t%",
+ "8T%",
+ "8t8",
+ "8T8",
+ "\\u03c9r\\u221e",
+ "\\u03a9R%",
+ "rr\\u221e",
+ "rR\\u221e",
+ "Rr\\u221e",
+ "RR\\u221e",
+ "RT%",
+ "rt8",
+ "tr\\u221e",
+ "tr8",
+ "TR8",
+ "tt8",
+ "\\u30b7\\u30e3\\u30fc\\u30ec",
+ };
+ */
+ static const UColAttribute att[] = { UCOL_STRENGTH };
+ static const UColAttributeValue val[] = { UCOL_QUATERNARY };
+
+ static const UColAttribute attShifted[] = { UCOL_STRENGTH, UCOL_ALTERNATE_HANDLING};
+ static const UColAttributeValue valShifted[] = { UCOL_QUATERNARY, UCOL_SHIFTED };
+
+ genericLocaleStarterWithOptions("ja", test1, sizeof(test1)/sizeof(test1[0]), att, val, 1);
+ genericLocaleStarterWithOptions("ja", test2, sizeof(test2)/sizeof(test2[0]), att, val, 1);
+ /*genericLocaleStarter("ja", test3, sizeof(test3)/sizeof(test3[0]));*/
+ genericLocaleStarterWithOptions("ja", test1, sizeof(test1)/sizeof(test1[0]), attShifted, valShifted, 2);
+ genericLocaleStarterWithOptions("ja", test2, sizeof(test2)/sizeof(test2[0]), attShifted, valShifted, 2);
+}
+
+static void TestStrCollIdenticalPrefix(void) {
+ const char* rule = "&\\ud9b0\\udc70=\\ud9b0\\udc71";
+ const char* test[] = {
+ "ab\\ud9b0\\udc70",
+ "ab\\ud9b0\\udc71"
+ };
+ genericRulesStarterWithResult(rule, test, sizeof(test)/sizeof(test[0]), UCOL_EQUAL);
+}
+/* Contractions should have all their canonically equivalent */
+/* strings included */
+static void TestContractionClosure(void) {
+ static const struct {
+ const char *rules;
+ const char *data[10];
+ const uint32_t len;
+ } tests[] = {
+ { "&b=\\u00e4\\u00e4",
+ { "b", "\\u00e4\\u00e4", "a\\u0308a\\u0308", "\\u00e4a\\u0308", "a\\u0308\\u00e4" }, 5},
+ { "&b=\\u00C5",
+ { "b", "\\u00C5", "A\\u030A", "\\u212B" }, 4},
+ };
+ uint32_t i;
+
+
+ for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) {
+ genericRulesStarterWithResult(tests[i].rules, tests[i].data, tests[i].len, UCOL_EQUAL);
+ }
+}
+
+/* This tests also fails*/
+static void TestBeforePrefixFailure(void) {
+ static const struct {
+ const char *rules;
+ const char *data[10];
+ const uint32_t len;
+ } tests[] = {
+ { "&g <<< a"
+ "&[before 3]\\uff41 <<< x",
+ {"x", "\\uff41"}, 2 },
+ { "&\\u30A7=\\u30A7=\\u3047=\\uff6a"
+ "&\\u30A8=\\u30A8=\\u3048=\\uff74"
+ "&[before 3]\\u30a7<<<\\u30a9",
+ {"\\u30a9", "\\u30a7"}, 2 },
+ { "&[before 3]\\u30a7<<<\\u30a9"
+ "&\\u30A7=\\u30A7=\\u3047=\\uff6a"
+ "&\\u30A8=\\u30A8=\\u3048=\\uff74",
+ {"\\u30a9", "\\u30a7"}, 2 },
+ };
+ uint32_t i;
+
+
+ for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len);
+ }
+
+#if 0
+ const char* rule1 =
+ "&\\u30A7=\\u30A7=\\u3047=\\uff6a"
+ "&\\u30A8=\\u30A8=\\u3048=\\uff74"
+ "&[before 3]\\u30a7<<<\\u30c6|\\u30fc";
+ const char* rule2 =
+ "&[before 3]\\u30a7<<<\\u30c6|\\u30fc"
+ "&\\u30A7=\\u30A7=\\u3047=\\uff6a"
+ "&\\u30A8=\\u30A8=\\u3048=\\uff74";
+ const char* test[] = {
+ "\\u30c6\\u30fc\\u30bf",
+ "\\u30c6\\u30a7\\u30bf",
+ };
+ genericRulesStarter(rule1, test, sizeof(test)/sizeof(test[0]));
+ genericRulesStarter(rule2, test, sizeof(test)/sizeof(test[0]));
+/* this piece of code should be in some sort of verbose mode */
+/* it gets the collation elements for elements and prints them */
+/* This is useful when trying to see whether the problem is */
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ uint32_t i = 0;
+ UCollationElements *it = NULL;
+ uint32_t CE;
+ UChar string[256];
+ uint32_t uStringLen;
+ UCollator *coll = NULL;
+
+ uStringLen = u_unescape(rule1, string, 256);
+
+ coll = ucol_openRules(string, uStringLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+
+ /*coll = ucol_open("ja_JP_JIS", &status);*/
+ it = ucol_openElements(coll, string, 0, &status);
+
+ for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) {
+ log_verbose("%s\n", test[i]);
+ uStringLen = u_unescape(test[i], string, 256);
+ ucol_setText(it, string, uStringLen, &status);
+
+ while((CE=ucol_next(it, &status)) != UCOL_NULLORDER) {
+ log_verbose("%08X\n", CE);
+ }
+ log_verbose("\n");
+
+ }
+
+ ucol_closeElements(it);
+ ucol_close(coll);
+ }
+#endif
+}
+
+static void TestPrefixCompose(void) {
+ const char* rule1 =
+ "&\\u30a7<<<\\u30ab|\\u30fc=\\u30ac|\\u30fc";
+ /*
+ const char* test[] = {
+ "\\u30c6\\u30fc\\u30bf",
+ "\\u30c6\\u30a7\\u30bf",
+ };
+ */
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ /*uint32_t i = 0;*/
+ /*UCollationElements *it = NULL;*/
+/* uint32_t CE;*/
+ UChar string[256];
+ uint32_t uStringLen;
+ UCollator *coll = NULL;
+
+ uStringLen = u_unescape(rule1, string, 256);
+
+ coll = ucol_openRules(string, uStringLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ ucol_close(coll);
+ }
+
+
+}
+
+/*
+[last variable] last variable value
+[last primary ignorable] largest CE for primary ignorable
+[last secondary ignorable] largest CE for secondary ignorable
+[last tertiary ignorable] largest CE for tertiary ignorable
+[top] guaranteed to be above all implicit CEs, for now and in the future (in 1.8)
+*/
+
+static void TestRuleOptions(void) {
+ /* values here are hardcoded and are correct for the current UCA
+ * when the UCA changes, one might be forced to change these
+ * values. (\\u02d0, \\U00010FFFC etc...)
+ */
+ static const struct {
+ const char *rules;
+ const char *data[10];
+ const uint32_t len;
+ } tests[] = {
+ /* - all befores here amount to zero */
+ { "&[before 3][first tertiary ignorable]<<<a",
+ { "\\u0000", "a"}, 2
+ }, /* you cannot go before first tertiary ignorable */
+
+ { "&[before 3][last tertiary ignorable]<<<a",
+ { "\\u0000", "a"}, 2
+ }, /* you cannot go before last tertiary ignorable */
+
+ { "&[before 3][first secondary ignorable]<<<a",
+ { "\\u0000", "a"}, 2
+ }, /* you cannot go before first secondary ignorable */
+
+ { "&[before 3][last secondary ignorable]<<<a",
+ { "\\u0000", "a"}, 2
+ }, /* you cannot go before first secondary ignorable */
+
+ /* 'normal' befores */
+
+ { "&[before 3][first primary ignorable]<<<c<<<b &[first primary ignorable]<a",
+ { "c", "b", "\\u0332", "a" }, 4
+ },
+
+ /* we don't have a code point that corresponds to
+ * the last primary ignorable
+ */
+ { "&[before 3][last primary ignorable]<<<c<<<b &[last primary ignorable]<a",
+ { "\\u0332", "\\u20e3", "c", "b", "a" }, 5
+ },
+
+ { "&[before 3][first variable]<<<c<<<b &[first variable]<a",
+ { "c", "b", "\\u0009", "a", "\\u000a" }, 5
+ },
+
+ { "&[last variable]<a &[before 3][last variable]<<<c<<<b ",
+ { "c", "b", "\\uD834\\uDF71", "a", "\\u02d0" }, 5
+ },
+
+ { "&[first regular]<a"
+ "&[before 1][first regular]<b",
+ { "b", "\\u02d0", "a", "\\u02d1"}, 4
+ },
+
+ { "&[before 1][last regular]<b"
+ "&[last regular]<a",
+ { "b", "\\uD808\\uDF6E", "a", "\\u4e00" }, 4
+ },
+
+ { "&[before 1][first implicit]<b"
+ "&[first implicit]<a",
+ { "b", "\\u4e00", "a", "\\u4e01"}, 4
+ },
+
+ { "&[before 1][last implicit]<b"
+ "&[last implicit]<a",
+ { "b", "\\U0010FFFD", "a" }, 3
+ },
+
+ { "&[last variable]<z"
+ "&[last primary ignorable]<x"
+ "&[last secondary ignorable]<<y"
+ "&[last tertiary ignorable]<<<w"
+ "&[top]<u",
+ {"\\ufffb", "w", "y", "\\u20e3", "x", "\\u137c", "z", "u"}, 7
+ }
+
+ };
+ uint32_t i;
+
+
+ for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len);
+ }
+}
+
+
+static void TestOptimize(void) {
+ /* this is not really a test - just trying out
+ * whether copying of UCA contents will fail
+ * Cannot really test, since the functionality
+ * remains the same.
+ */
+ static const struct {
+ const char *rules;
+ const char *data[10];
+ const uint32_t len;
+ } tests[] = {
+ /* - all befores here amount to zero */
+ { "[optimize [\\uAC00-\\uD7FF]]",
+ { "a", "b"}, 2}
+ };
+ uint32_t i;
+
+ for(i = 0; i<(sizeof(tests)/sizeof(tests[0])); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].data, tests[i].len);
+ }
+}
+
+/*
+cycheng@ca.ibm.c... we got inconsistent results when using the UTF-16BE iterator and the UTF-8 iterator.
+weiv ucol_strcollIter?
+cycheng@ca.ibm.c... e.g. s1 = 0xfffc0062, and s2 = d8000021
+weiv these are the input strings?
+cycheng@ca.ibm.c... yes, using the utf-16 iterator and UCA with normalization on, we have s1 > s2
+weiv will check - could be a problem with utf-8 iterator
+cycheng@ca.ibm.c... but if we use the utf-8 iterator, i.e. s1 = efbfbc62 and s2 = eda08021, we have s1 < s2
+weiv hmmm
+cycheng@ca.ibm.c... note that we have a standalone high surrogate
+weiv that doesn't sound right
+cycheng@ca.ibm.c... we got the same inconsistent results on AIX and Win2000
+weiv so you have two strings, you convert them to utf-8 and to utf-16BE
+cycheng@ca.ibm.c... yes
+weiv and then do the comparison
+cycheng@ca.ibm.c... in one case, the input strings are in utf8, and in the other case the input strings are in utf-16be
+weiv utf-16 strings look like a little endian ones in the example you sent me
+weiv It could be a bug - let me try to test it out
+cycheng@ca.ibm.c... ok
+cycheng@ca.ibm.c... we can wait till the conf. call
+cycheng@ca.ibm.c... next weke
+weiv that would be great
+weiv hmmm
+weiv I might be wrong
+weiv let me play with it some more
+cycheng@ca.ibm.c... ok
+cycheng@ca.ibm.c... also please check s3 = 0x0e3a0062 and s4 = 0x0e400021. both are in utf-16be
+cycheng@ca.ibm.c... seems with icu 2.2 we have s3 > s4, but not in icu 2.4 that's built for db2
+cycheng@ca.ibm.c... also s1 & s2 that I sent you earlier are also in utf-16be
+weiv ok
+cycheng@ca.ibm.c... i ask sherman to send you more inconsistent data
+weiv thanks
+cycheng@ca.ibm.c... the 4 strings we sent are just samples
+*/
+#if 0
+static void Alexis(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("", &status);
+
+
+ const char utf16be[2][4] = {
+ { (char)0xd8, (char)0x00, (char)0x00, (char)0x21 },
+ { (char)0xff, (char)0xfc, (char)0x00, (char)0x62 }
+ };
+
+ const char utf8[2][4] = {
+ { (char)0xed, (char)0xa0, (char)0x80, (char)0x21 },
+ { (char)0xef, (char)0xbf, (char)0xbc, (char)0x62 },
+ };
+
+ UCharIterator iterU161, iterU162;
+ UCharIterator iterU81, iterU82;
+
+ UCollationResult resU16, resU8;
+
+ uiter_setUTF16BE(&iterU161, utf16be[0], 4);
+ uiter_setUTF16BE(&iterU162, utf16be[1], 4);
+
+ uiter_setUTF8(&iterU81, utf8[0], 4);
+ uiter_setUTF8(&iterU82, utf8[1], 4);
+
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+
+ resU16 = ucol_strcollIter(coll, &iterU161, &iterU162, &status);
+ resU8 = ucol_strcollIter(coll, &iterU81, &iterU82, &status);
+
+
+ if(resU16 != resU8) {
+ log_err("different results\n");
+ }
+
+ ucol_close(coll);
+}
+#endif
+
+#define CMSCOLL_ALEXIS2_BUFFER_SIZE 256
+static void Alexis2(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar U16Source[CMSCOLL_ALEXIS2_BUFFER_SIZE], U16Target[CMSCOLL_ALEXIS2_BUFFER_SIZE];
+ char U16BESource[CMSCOLL_ALEXIS2_BUFFER_SIZE], U16BETarget[CMSCOLL_ALEXIS2_BUFFER_SIZE];
+ char U8Source[CMSCOLL_ALEXIS2_BUFFER_SIZE], U8Target[CMSCOLL_ALEXIS2_BUFFER_SIZE];
+ int32_t U16LenS = 0, U16LenT = 0, U16BELenS = 0, U16BELenT = 0, U8LenS = 0, U8LenT = 0;
+
+ UConverter *conv = NULL;
+
+ UCharIterator U16BEItS, U16BEItT;
+ UCharIterator U8ItS, U8ItT;
+
+ UCollationResult resU16, resU16BE, resU8;
+
+ static const char* const pairs[][2] = {
+ { "\\ud800\\u0021", "\\uFFFC\\u0062"},
+ { "\\u0435\\u0308\\u0334", "\\u0415\\u0334\\u0340" },
+ { "\\u0E40\\u0021", "\\u00A1\\u0021"},
+ { "\\u0E40\\u0021", "\\uFE57\\u0062"},
+ { "\\u5F20", "\\u5F20\\u4E00\\u8E3F"},
+ { "\\u0000\\u0020", "\\u0000\\u0020\\u0000"},
+ { "\\u0020", "\\u0020\\u0000"}
+/*
+5F20 (my result here)
+5F204E008E3F
+5F20 (your result here)
+*/
+ };
+
+ int32_t i = 0;
+
+ UCollator *coll = ucol_open("", &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ conv = ucnv_open("UTF16BE", &status);
+ for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
+ U16LenS = u_unescape(pairs[i][0], U16Source, CMSCOLL_ALEXIS2_BUFFER_SIZE);
+ U16LenT = u_unescape(pairs[i][1], U16Target, CMSCOLL_ALEXIS2_BUFFER_SIZE);
+
+ resU16 = ucol_strcoll(coll, U16Source, U16LenS, U16Target, U16LenT);
+
+ log_verbose("Result of strcoll is %i\n", resU16);
+
+ U16BELenS = ucnv_fromUChars(conv, U16BESource, CMSCOLL_ALEXIS2_BUFFER_SIZE, U16Source, U16LenS, &status);
+ U16BELenT = ucnv_fromUChars(conv, U16BETarget, CMSCOLL_ALEXIS2_BUFFER_SIZE, U16Target, U16LenT, &status);
+
+ /* use the original sizes, as the result from converter is in bytes */
+ uiter_setUTF16BE(&U16BEItS, U16BESource, U16LenS);
+ uiter_setUTF16BE(&U16BEItT, U16BETarget, U16LenT);
+
+ resU16BE = ucol_strcollIter(coll, &U16BEItS, &U16BEItT, &status);
+
+ log_verbose("Result of U16BE is %i\n", resU16BE);
+
+ if(resU16 != resU16BE) {
+ log_verbose("Different results between UTF16 and UTF16BE for %s & %s\n", pairs[i][0], pairs[i][1]);
+ }
+
+ u_strToUTF8(U8Source, CMSCOLL_ALEXIS2_BUFFER_SIZE, &U8LenS, U16Source, U16LenS, &status);
+ u_strToUTF8(U8Target, CMSCOLL_ALEXIS2_BUFFER_SIZE, &U8LenT, U16Target, U16LenT, &status);
+
+ uiter_setUTF8(&U8ItS, U8Source, U8LenS);
+ uiter_setUTF8(&U8ItT, U8Target, U8LenT);
+
+ resU8 = ucol_strcollIter(coll, &U8ItS, &U8ItT, &status);
+
+ if(resU16 != resU8) {
+ log_verbose("Different results between UTF16 and UTF8 for %s & %s\n", pairs[i][0], pairs[i][1]);
+ }
+
+ }
+
+ ucol_close(coll);
+ ucnv_close(conv);
+}
+
+static void TestHebrewUCA(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ static const char *first[] = {
+ "d790d6b8d79cd795d6bcd7a9",
+ "d790d79cd79ed7a7d799d799d7a1",
+ "d790d6b4d79ed795d6bcd7a9",
+ };
+
+ char utf8String[3][256];
+ UChar utf16String[3][256];
+
+ int32_t i = 0, j = 0;
+ int32_t sizeUTF8[3];
+ int32_t sizeUTF16[3];
+
+ UCollator *coll = ucol_open("", &status);
+ /*ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);*/
+
+ for(i = 0; i < sizeof(first)/sizeof(first[0]); i++) {
+ sizeUTF8[i] = u_parseUTF8(first[i], -1, utf8String[i], 256, &status);
+ u_strFromUTF8(utf16String[i], 256, &sizeUTF16[i], utf8String[i], sizeUTF8[i], &status);
+ log_verbose("%i: ");
+ for(j = 0; j < sizeUTF16[i]; j++) {
+ /*log_verbose("\\u%04X", utf16String[i][j]);*/
+ log_verbose("%04X", utf16String[i][j]);
+ }
+ log_verbose("\n");
+ }
+ for(i = 0; i < sizeof(first)/sizeof(first[0])-1; i++) {
+ for(j = i + 1; j < sizeof(first)/sizeof(first[0]); j++) {
+ doTest(coll, utf16String[i], utf16String[j], UCOL_LESS);
+ }
+ }
+
+ ucol_close(coll);
+
+}
+
+static void TestPartialSortKeyTermination(void) {
+ static const char* cases[] = {
+ "\\u1234\\u1234\\udc00",
+ "\\udc00\\ud800\\ud800"
+ };
+
+ int32_t i = sizeof(UCollator);
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ UCollator *coll = ucol_open("", &status);
+
+ UCharIterator iter;
+
+ UChar currCase[256];
+ int32_t length = 0;
+ int32_t pKeyLen = 0;
+
+ uint8_t key[256];
+
+ for(i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) {
+ uint32_t state[2] = {0, 0};
+ length = u_unescape(cases[i], currCase, 256);
+ uiter_setString(&iter, currCase, length);
+ pKeyLen = ucol_nextSortKeyPart(coll, &iter, state, key, 256, &status);
+
+ log_verbose("Done\n");
+
+ }
+ ucol_close(coll);
+}
+
+static void TestSettings(void) {
+ static const char* cases[] = {
+ "apple",
+ "Apple"
+ };
+
+ static const char* locales[] = {
+ "",
+ "en"
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ int32_t i = 0, j = 0;
+
+ UChar source[256], target[256];
+ int32_t sLen = 0, tLen = 0;
+
+ UCollator *collateObject = NULL;
+ for(i = 0; i < sizeof(locales)/sizeof(locales[0]); i++) {
+ collateObject = ucol_open(locales[i], &status);
+ ucol_setStrength(collateObject, UCOL_PRIMARY);
+ ucol_setAttribute(collateObject, UCOL_CASE_LEVEL , UCOL_OFF, &status);
+ for(j = 1; j < sizeof(cases)/sizeof(cases[0]); j++) {
+ sLen = u_unescape(cases[j-1], source, 256);
+ source[sLen] = 0;
+ tLen = u_unescape(cases[j], target, 256);
+ source[tLen] = 0;
+ doTest(collateObject, source, target, UCOL_EQUAL);
+ }
+ ucol_close(collateObject);
+ }
+}
+
+static int32_t TestEqualsForCollator(const char* locName, UCollator *source, UCollator *target) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t errorNo = 0;
+ /*const UChar *sourceRules = NULL;*/
+ /*int32_t sourceRulesLen = 0;*/
+ UColAttributeValue french = UCOL_OFF;
+ int32_t cloneSize = 0;
+
+ if(!ucol_equals(source, target)) {
+ log_err("Same collators, different address not equal\n");
+ errorNo++;
+ }
+ ucol_close(target);
+ if(uprv_strcmp(ucol_getLocale(source, ULOC_REQUESTED_LOCALE, &status), ucol_getLocale(source, ULOC_ACTUAL_LOCALE, &status)) == 0) {
+ /* currently, safeClone is implemented through getRules/openRules
+ * so it is the same as the test below - I will comment that test out.
+ */
+ /* real thing */
+ target = ucol_safeClone(source, NULL, &cloneSize, &status);
+ if(U_FAILURE(status)) {
+ log_err("Error creating clone\n");
+ errorNo++;
+ return errorNo;
+ }
+ if(!ucol_equals(source, target)) {
+ log_err("Collator different from it's clone\n");
+ errorNo++;
+ }
+ french = ucol_getAttribute(source, UCOL_FRENCH_COLLATION, &status);
+ if(french == UCOL_ON) {
+ ucol_setAttribute(target, UCOL_FRENCH_COLLATION, UCOL_OFF, &status);
+ } else {
+ ucol_setAttribute(target, UCOL_FRENCH_COLLATION, UCOL_ON, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error setting attributes\n");
+ errorNo++;
+ return errorNo;
+ }
+ if(ucol_equals(source, target)) {
+ log_err("Collators same even when options changed\n");
+ errorNo++;
+ }
+ ucol_close(target);
+ /* commented out since safeClone uses exactly the same technique */
+ /*
+ sourceRules = ucol_getRules(source, &sourceRulesLen);
+ target = ucol_openRules(sourceRules, sourceRulesLen, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status);
+ if(U_FAILURE(status)) {
+ log_err("Error instantiating target from rules\n");
+ errorNo++;
+ return errorNo;
+ }
+ if(!ucol_equals(source, target)) {
+ log_err("Collator different from collator that was created from the same rules\n");
+ errorNo++;
+ }
+ ucol_close(target);
+ */
+ }
+ return errorNo;
+}
+
+
+static void TestEquals(void) {
+ /* ucol_equals is not currently a public API. There is a chance that it will become
+ * something like this, but currently it is only used by RuleBasedCollator::operator==
+ */
+ /* test whether the two collators instantiated from the same locale are equal */
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+ int32_t noOfLoc = uloc_countAvailable();
+ const char *locName = NULL;
+ UCollator *source = NULL, *target = NULL;
+ int32_t i = 0;
+
+ const char* rules[] = {
+ "&l < lj <<< Lj <<< LJ",
+ "&n < nj <<< Nj <<< NJ",
+ "&ae <<< \\u00e4",
+ "&AE <<< \\u00c4"
+ };
+ /*
+ const char* badRules[] = {
+ "&l <<< Lj",
+ "&n < nj <<< nJ <<< NJ",
+ "&a <<< \\u00e4",
+ "&AE <<< \\u00c4 <<< x"
+ };
+ */
+
+ UChar sourceRules[1024], targetRules[1024];
+ int32_t sourceRulesSize = 0, targetRulesSize = 0;
+ int32_t rulesSize = sizeof(rules)/sizeof(rules[0]);
+
+ for(i = 0; i < rulesSize; i++) {
+ sourceRulesSize += u_unescape(rules[i], sourceRules+sourceRulesSize, 1024 - sourceRulesSize);
+ targetRulesSize += u_unescape(rules[rulesSize-i-1], targetRules+targetRulesSize, 1024 - targetRulesSize);
+ }
+
+ source = ucol_openRules(sourceRules, sourceRulesSize, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ target = ucol_openRules(targetRules, targetRulesSize, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, &status);
+ if(!ucol_equals(source, target)) {
+ log_err("Equivalent collators not equal!\n");
+ }
+ ucol_close(source);
+ ucol_close(target);
+
+ source = ucol_open("root", &status);
+ target = ucol_open("root", &status);
+ log_verbose("Testing root\n");
+ if(!ucol_equals(source, source)) {
+ log_err("Same collator not equal\n");
+ }
+ if(TestEqualsForCollator(locName, source, target)) {
+ log_err("Errors for root\n", locName);
+ }
+ ucol_close(source);
+
+ for(i = 0; i<noOfLoc; i++) {
+ status = U_ZERO_ERROR;
+ locName = uloc_getAvailable(i);
+ /*if(hasCollationElements(locName)) {*/
+ log_verbose("Testing equality for locale %s\n", locName);
+ source = ucol_open(locName, &status);
+ target = ucol_open(locName, &status);
+ if(TestEqualsForCollator(locName, source, target)) {
+ log_err("Errors for locale %s\n", locName);
+ }
+ ucol_close(source);
+ /*}*/
+ }
+}
+
+static void TestJ2726(void) {
+ UChar a[2] = { 0x61, 0x00 }; /*"a"*/
+ UChar aSpace[3] = { 0x61, 0x20, 0x00 }; /*"a "*/
+ UChar spaceA[3] = { 0x20, 0x61, 0x00 }; /*" a"*/
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("en", &status);
+ ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status);
+ doTest(coll, a, aSpace, UCOL_EQUAL);
+ doTest(coll, aSpace, a, UCOL_EQUAL);
+ doTest(coll, a, spaceA, UCOL_EQUAL);
+ doTest(coll, spaceA, a, UCOL_EQUAL);
+ doTest(coll, spaceA, aSpace, UCOL_EQUAL);
+ doTest(coll, aSpace, spaceA, UCOL_EQUAL);
+ ucol_close(coll);
+}
+
+static void NullRule(void) {
+ UChar r[3] = {0};
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_openRules(r, 1, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ if(U_SUCCESS(status)) {
+ log_err("This should have been an error!\n");
+ ucol_close(coll);
+ } else {
+ status = U_ZERO_ERROR;
+ }
+ coll = ucol_openRules(r, 0, UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
+ if(U_FAILURE(status)) {
+ log_err("Empty rules should have produced a valid collator\n");
+ } else {
+ ucol_close(coll);
+ }
+}
+
+/**
+ * Test for CollationElementIterator previous and next for the whole set of
+ * unicode characters with normalization on.
+ */
+static void TestNumericCollation(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+
+ const static char *basicTestStrings[]={
+ "hello1",
+ "hello2",
+ "hello2002",
+ "hello2003",
+ "hello123456",
+ "hello1234567",
+ "hello10000000",
+ "hello100000000",
+ "hello1000000000",
+ "hello10000000000",
+ };
+
+ const static char *preZeroTestStrings[]={
+ "avery10000",
+ "avery010000",
+ "avery0010000",
+ "avery00010000",
+ "avery000010000",
+ "avery0000010000",
+ "avery00000010000",
+ "avery000000010000",
+ };
+
+ const static char *thirtyTwoBitNumericStrings[]={
+ "avery42949672960",
+ "avery42949672961",
+ "avery42949672962",
+ "avery429496729610"
+ };
+
+ const static char *supplementaryDigits[] = {
+ "\\uD835\\uDFCE", /* 0 */
+ "\\uD835\\uDFCF", /* 1 */
+ "\\uD835\\uDFD0", /* 2 */
+ "\\uD835\\uDFD1", /* 3 */
+ "\\uD835\\uDFCF\\uD835\\uDFCE", /* 10 */
+ "\\uD835\\uDFCF\\uD835\\uDFCF", /* 11 */
+ "\\uD835\\uDFCF\\uD835\\uDFD0", /* 12 */
+ "\\uD835\\uDFD0\\uD835\\uDFCE", /* 20 */
+ "\\uD835\\uDFD0\\uD835\\uDFCF", /* 21 */
+ "\\uD835\\uDFD0\\uD835\\uDFD0" /* 22 */
+ };
+
+ const static char *foreignDigits[] = {
+ "\\u0661",
+ "\\u0662",
+ "\\u0663",
+ "\\u0661\\u0660",
+ "\\u0661\\u0662",
+ "\\u0661\\u0663",
+ "\\u0662\\u0660",
+ "\\u0662\\u0662",
+ "\\u0662\\u0663",
+ "\\u0663\\u0660",
+ "\\u0663\\u0662",
+ "\\u0663\\u0663"
+ };
+
+ const static char *evenZeroes[] = {
+ "2000",
+ "2001",
+ "2002",
+ "2003"
+ };
+
+ UColAttribute att = UCOL_NUMERIC_COLLATION;
+ UColAttributeValue val = UCOL_ON;
+
+ /* Open our collator. */
+ UCollator* coll = ucol_open("root", &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: in using ucol_open()\n %s\n",
+ myErrorName(status));
+ return;
+ }
+ genericLocaleStarterWithOptions("root", basicTestStrings, sizeof(basicTestStrings)/sizeof(basicTestStrings[0]), &att, &val, 1);
+ genericLocaleStarterWithOptions("root", thirtyTwoBitNumericStrings, sizeof(thirtyTwoBitNumericStrings)/sizeof(thirtyTwoBitNumericStrings[0]), &att, &val, 1);
+ genericLocaleStarterWithOptions("en_US", foreignDigits, sizeof(foreignDigits)/sizeof(foreignDigits[0]), &att, &val, 1);
+ genericLocaleStarterWithOptions("root", supplementaryDigits, sizeof(supplementaryDigits)/sizeof(supplementaryDigits[0]), &att, &val, 1);
+ genericLocaleStarterWithOptions("root", evenZeroes, sizeof(evenZeroes)/sizeof(evenZeroes[0]), &att, &val, 1);
+
+ /* Setting up our collator to do digits. */
+ ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status);
+ if (U_FAILURE(status)){
+ log_err("ERROR: in setting UCOL_NUMERIC_COLLATION as an attribute\n %s\n",
+ myErrorName(status));
+ return;
+ }
+
+ /*
+ Testing that prepended zeroes still yield the correct collation behavior.
+ We expect that every element in our strings array will be equal.
+ */
+ genericOrderingTestWithResult(coll, preZeroTestStrings, sizeof(preZeroTestStrings)/sizeof(preZeroTestStrings[0]), UCOL_EQUAL);
+
+ ucol_close(coll);
+}
+
+static void TestTibetanConformance(void)
+{
+ const char* test[] = {
+ "\\u0FB2\\u0591\\u0F71\\u0061",
+ "\\u0FB2\\u0F71\\u0061"
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UCollator *coll = ucol_open("", &status);
+ UChar source[100];
+ UChar target[100];
+ int result;
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ if (U_SUCCESS(status)) {
+ u_unescape(test[0], source, 100);
+ u_unescape(test[1], target, 100);
+ doTest(coll, source, target, UCOL_EQUAL);
+ result = ucol_strcoll(coll, source, -1, target, -1);
+ log_verbose("result %d\n", result);
+ if (UCOL_EQUAL != result) {
+ log_err("Tibetan comparison error\n");
+ }
+ }
+ ucol_close(coll);
+
+ genericLocaleStarterWithResult("", test, 2, UCOL_EQUAL);
+}
+
+static void TestPinyinProblem(void) {
+ static const char *test[] = { "\\u4E56\\u4E56\\u7761", "\\u4E56\\u5B69\\u5B50" };
+ genericLocaleStarter("zh__PINYIN", test, sizeof(test)/sizeof(test[0]));
+}
+
+#define TST_UCOL_MAX_INPUT 0x220001
+#define topByte 0xFF000000;
+#define bottomByte 0xFF;
+#define fourBytes 0xFFFFFFFF;
+
+
+static void showImplicit(UChar32 i) {
+ if (i >= 0 && i <= TST_UCOL_MAX_INPUT) {
+ log_verbose("%08X\t%08X\n", i, uprv_uca_getImplicitFromRaw(i));
+ }
+}
+
+static void TestImplicitGeneration(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar32 last = 0;
+ UChar32 current;
+ UChar32 i = 0, j = 0;
+ UChar32 roundtrip = 0;
+ UChar32 lastBottom = 0;
+ UChar32 currentBottom = 0;
+ UChar32 lastTop = 0;
+ UChar32 currentTop = 0;
+
+ UCollator *coll = ucol_open("root", &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't open UCA\n");
+ return;
+ }
+
+ uprv_uca_getRawFromImplicit(0xE20303E7);
+
+ for (i = 0; i <= TST_UCOL_MAX_INPUT; ++i) {
+ current = uprv_uca_getImplicitFromRaw(i) & fourBytes;
+
+ /* check that it round-trips AND that all intervening ones are illegal*/
+ roundtrip = uprv_uca_getRawFromImplicit(current);
+ if (roundtrip != i) {
+ log_err("No roundtrip %08X\n", i);
+ }
+ if (last != 0) {
+ for (j = last + 1; j < current; ++j) {
+ roundtrip = uprv_uca_getRawFromImplicit(j);
+ /* raise an error if it *doesn't* find an error*/
+ if (roundtrip != -1) {
+ log_err("Fails to recognize illegal %08X\n", j);
+ }
+ }
+ }
+ /* now do other consistency checks*/
+ lastBottom = last & bottomByte;
+ currentBottom = current & bottomByte;
+ lastTop = last & topByte;
+ currentTop = current & topByte;
+
+ /* print out some values for spot-checking*/
+ if (lastTop != currentTop || i == 0x10000 || i == 0x110000) {
+ showImplicit(i-3);
+ showImplicit(i-2);
+ showImplicit(i-1);
+ showImplicit(i);
+ showImplicit(i+1);
+ showImplicit(i+2);
+ }
+ last = current;
+
+ if(uprv_uca_getCodePointFromRaw(uprv_uca_getRawFromCodePoint(i)) != i) {
+ log_err("No raw <-> code point roundtrip for 0x%08X\n", i);
+ }
+ }
+ showImplicit(TST_UCOL_MAX_INPUT-2);
+ showImplicit(TST_UCOL_MAX_INPUT-1);
+ showImplicit(TST_UCOL_MAX_INPUT);
+ ucol_close(coll);
+}
+
+/**
+ * Iterate through the given iterator, checking to see that all the strings
+ * in the expected array are present.
+ * @param expected array of strings we expect to see, or NULL
+ * @param expectedCount number of elements of expected, or 0
+ */
+static int32_t checkUEnumeration(const char* msg,
+ UEnumeration* iter,
+ const char** expected,
+ int32_t expectedCount) {
+ UErrorCode ec = U_ZERO_ERROR;
+ int32_t i = 0, n, j, bit;
+ int32_t seenMask = 0;
+
+ U_ASSERT(expectedCount >= 0 && expectedCount < 31); /* [sic] 31 not 32 */
+ n = uenum_count(iter, &ec);
+ if (!assertSuccess("count", &ec)) return -1;
+ log_verbose("%s = [", msg);
+ for (;; ++i) {
+ const char* s = uenum_next(iter, NULL, &ec);
+ if (!assertSuccess("snext", &ec) || s == NULL) break;
+ if (i != 0) log_verbose(",");
+ log_verbose("%s", s);
+ /* check expected list */
+ for (j=0, bit=1; j<expectedCount; ++j, bit<<=1) {
+ if ((seenMask&bit) == 0 &&
+ uprv_strcmp(s, expected[j]) == 0) {
+ seenMask |= bit;
+ break;
+ }
+ }
+ }
+ log_verbose("] (%d)\n", i);
+ assertTrue("count verified", i==n);
+ /* did we see all expected strings? */
+ for (j=0, bit=1; j<expectedCount; ++j, bit<<=1) {
+ if ((seenMask&bit)!=0) {
+ log_verbose("Ok: \"%s\" seen\n", expected[j]);
+ } else {
+ log_err("FAIL: \"%s\" not seen\n", expected[j]);
+ }
+ }
+ return n;
+}
+
+/**
+ * Test new API added for separate collation tree.
+ */
+static void TestSeparateTrees(void) {
+ UErrorCode ec = U_ZERO_ERROR;
+ UEnumeration *e = NULL;
+ int32_t n = -1;
+ UBool isAvailable;
+ char loc[256];
+
+ static const char* AVAIL[] = { "en", "de" };
+
+ static const char* KW[] = { "collation" };
+
+ static const char* KWVAL[] = { "phonebook", "stroke" };
+
+#if !UCONFIG_NO_SERVICE
+ e = ucol_openAvailableLocales(&ec);
+ assertSuccess("ucol_openAvailableLocales", &ec);
+ assertTrue("ucol_openAvailableLocales!=0", e!=0);
+ n = checkUEnumeration("ucol_openAvailableLocales", e, AVAIL, LEN(AVAIL));
+ /* Don't need to check n because we check list */
+ uenum_close(e);
+#endif
+
+ e = ucol_getKeywords(&ec);
+ assertSuccess("ucol_getKeywords", &ec);
+ assertTrue("ucol_getKeywords!=0", e!=0);
+ n = checkUEnumeration("ucol_getKeywords", e, KW, LEN(KW));
+ /* Don't need to check n because we check list */
+ uenum_close(e);
+
+ e = ucol_getKeywordValues(KW[0], &ec);
+ assertSuccess("ucol_getKeywordValues", &ec);
+ assertTrue("ucol_getKeywordValues!=0", e!=0);
+ n = checkUEnumeration("ucol_getKeywordValues", e, KWVAL, LEN(KWVAL));
+ /* Don't need to check n because we check list */
+ uenum_close(e);
+
+ /* Try setting a warning before calling ucol_getKeywordValues */
+ ec = U_USING_FALLBACK_WARNING;
+ e = ucol_getKeywordValues(KW[0], &ec);
+ assertSuccess("ucol_getKeywordValues [with warning code set]", &ec);
+ assertTrue("ucol_getKeywordValues!=0 [with warning code set]", e!=0);
+ n = checkUEnumeration("ucol_getKeywordValues [with warning code set]", e, KWVAL, LEN(KWVAL));
+ /* Don't need to check n because we check list */
+ uenum_close(e);
+
+ /*
+U_DRAFT int32_t U_EXPORT2
+ucol_getFunctionalEquivalent(char* result, int32_t resultCapacity,
+ const char* locale, UBool* isAvailable,
+ UErrorCode* status);
+}
+*/
+ n = ucol_getFunctionalEquivalent(loc, sizeof(loc), "collation", "fr",
+ &isAvailable, &ec);
+ assertSuccess("getFunctionalEquivalent", &ec);
+ assertEquals("getFunctionalEquivalent(fr)", "fr", loc);
+ assertTrue("getFunctionalEquivalent(fr).isAvailable==TRUE",
+ isAvailable == TRUE);
+
+ n = ucol_getFunctionalEquivalent(loc, sizeof(loc), "collation", "fr_FR",
+ &isAvailable, &ec);
+ assertSuccess("getFunctionalEquivalent", &ec);
+ assertEquals("getFunctionalEquivalent(fr_FR)", "fr", loc);
+ assertTrue("getFunctionalEquivalent(fr_FR).isAvailable==TRUE",
+ isAvailable == TRUE);
+}
+
+/* supercedes TestJ784 */
+static void TestBeforePinyin(void) {
+ const static char rules[] = {
+ "&[before 2]A<<\\u0101<<<\\u0100<<\\u00E1<<<\\u00C1<<\\u01CE<<<\\u01CD<<\\u00E0<<<\\u00C0"
+ "&[before 2]e<<\\u0113<<<\\u0112<<\\u00E9<<<\\u00C9<<\\u011B<<<\\u011A<<\\u00E8<<<\\u00C8"
+ "&[before 2]i<<\\u012B<<<\\u012A<<\\u00ED<<<\\u00CD<<\\u01D0<<<\\u01CF<<\\u00EC<<<\\u00CC"
+ "&[before 2]o<<\\u014D<<<\\u014C<<\\u00F3<<<\\u00D3<<\\u01D2<<<\\u01D1<<\\u00F2<<<\\u00D2"
+ "&[before 2]u<<\\u016B<<<\\u016A<<\\u00FA<<<\\u00DA<<\\u01D4<<<\\u01D3<<\\u00F9<<<\\u00D9"
+ "&U<<\\u01D6<<<\\u01D5<<\\u01D8<<<\\u01D7<<\\u01DA<<<\\u01D9<<\\u01DC<<<\\u01DB<<\\u00FC"
+ };
+
+ const static char *test[] = {
+ "l\\u0101",
+ "la",
+ "l\\u0101n",
+ "lan ",
+ "l\\u0113",
+ "le",
+ "l\\u0113n",
+ "len"
+ };
+
+ const static char *test2[] = {
+ "x\\u0101",
+ "x\\u0100",
+ "X\\u0101",
+ "X\\u0100",
+ "x\\u00E1",
+ "x\\u00C1",
+ "X\\u00E1",
+ "X\\u00C1",
+ "x\\u01CE",
+ "x\\u01CD",
+ "X\\u01CE",
+ "X\\u01CD",
+ "x\\u00E0",
+ "x\\u00C0",
+ "X\\u00E0",
+ "X\\u00C0",
+ "xa",
+ "xA",
+ "Xa",
+ "XA",
+ "x\\u0101x",
+ "x\\u0100x",
+ "x\\u00E1x",
+ "x\\u00C1x",
+ "x\\u01CEx",
+ "x\\u01CDx",
+ "x\\u00E0x",
+ "x\\u00C0x",
+ "xax",
+ "xAx"
+ };
+
+ genericRulesStarter(rules, test, sizeof(test)/sizeof(test[0]));
+ genericLocaleStarter("zh", test, sizeof(test)/sizeof(test[0]));
+ genericRulesStarter(rules, test2, sizeof(test2)/sizeof(test2[0]));
+ genericLocaleStarter("zh", test2, sizeof(test2)/sizeof(test2[0]));
+}
+
+static void TestBeforeTightening(void) {
+ static const struct {
+ const char *rules;
+ UErrorCode expectedStatus;
+ } tests[] = {
+ { "&[before 1]a<x", U_ZERO_ERROR },
+ { "&[before 1]a<<x", U_INVALID_FORMAT_ERROR },
+ { "&[before 1]a<<<x", U_INVALID_FORMAT_ERROR },
+ { "&[before 1]a=x", U_INVALID_FORMAT_ERROR },
+ { "&[before 2]a<x",U_INVALID_FORMAT_ERROR },
+ { "&[before 2]a<<x",U_ZERO_ERROR },
+ { "&[before 2]a<<<x",U_INVALID_FORMAT_ERROR },
+ { "&[before 2]a=x",U_INVALID_FORMAT_ERROR },
+ { "&[before 3]a<x",U_INVALID_FORMAT_ERROR },
+ { "&[before 3]a<<x",U_INVALID_FORMAT_ERROR },
+ { "&[before 3]a<<<x",U_ZERO_ERROR },
+ { "&[before 3]a=x",U_INVALID_FORMAT_ERROR },
+ { "&[before I]a = x",U_INVALID_FORMAT_ERROR }
+ };
+
+ int32_t i = 0;
+
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[RULE_BUFFER_LEN] = { 0 };
+ uint32_t rlen = 0;
+
+ UCollator *coll = NULL;
+
+
+ for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ rlen = u_unescape(tests[i].rules, rlz, RULE_BUFFER_LEN);
+ coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
+ if(status != tests[i].expectedStatus) {
+ log_err("Opening a collator with rules %s returned error code %s, expected %s\n",
+ tests[i].rules, u_errorName(status), u_errorName(tests[i].expectedStatus));
+ }
+ ucol_close(coll);
+ status = U_ZERO_ERROR;
+ }
+
+}
+
+#if 0
+&m < a
+&[before 1] a < x <<< X << q <<< Q < z
+assert: m <<< M < x <<< X << q <<< Q < z < a < n
+
+&m < a
+&[before 2] a << x <<< X << q <<< Q < z
+assert: m <<< M < x <<< X << q <<< Q << a < z < n
+
+&m < a
+&[before 3] a <<< x <<< X << q <<< Q < z
+assert: m <<< M < x <<< X <<< a << q <<< Q < z < n
+
+
+&m << a
+&[before 1] a < x <<< X << q <<< Q < z
+assert: x <<< X << q <<< Q < z < m <<< M << a < n
+
+&m << a
+&[before 2] a << x <<< X << q <<< Q < z
+assert: m <<< M << x <<< X << q <<< Q << a < z < n
+
+&m << a
+&[before 3] a <<< x <<< X << q <<< Q < z
+assert: m <<< M << x <<< X <<< a << q <<< Q < z < n
+
+
+&m <<< a
+&[before 1] a < x <<< X << q <<< Q < z
+assert: x <<< X << q <<< Q < z < n < m <<< a <<< M
+
+&m <<< a
+&[before 2] a << x <<< X << q <<< Q < z
+assert: x <<< X << q <<< Q << m <<< a <<< M < z < n
+
+&m <<< a
+&[before 3] a <<< x <<< X << q <<< Q < z
+assert: m <<< x <<< X <<< a <<< M << q <<< Q < z < n
+
+
+&[before 1] s < x <<< X << q <<< Q < z
+assert: r <<< R < x <<< X << q <<< Q < z < s < n
+
+&[before 2] s << x <<< X << q <<< Q < z
+assert: r <<< R < x <<< X << q <<< Q << s < z < n
+
+&[before 3] s <<< x <<< X << q <<< Q < z
+assert: r <<< R < x <<< X <<< s << q <<< Q < z < n
+
+
+&[before 1] \u24DC < x <<< X << q <<< Q < z
+assert: x <<< X << q <<< Q < z < n < m <<< \u24DC <<< M
+
+&[before 2] \u24DC << x <<< X << q <<< Q < z
+assert: x <<< X << q <<< Q << m <<< \u24DC <<< M < z < n
+
+&[before 3] \u24DC <<< x <<< X << q <<< Q < z
+assert: m <<< x <<< X <<< \u24DC <<< M << q <<< Q < z < n
+#endif
+
+
+#if 0
+/* requires features not yet supported */
+static void TestMoreBefore(void) {
+ static const struct {
+ const char* rules;
+ const char* order[16];
+ int32_t size;
+ } tests[] = {
+ { "&m < a &[before 1] a < x <<< X << q <<< Q < z",
+ { "m","M","x","X","q","Q","z","a","n" }, 9},
+ { "&m < a &[before 2] a << x <<< X << q <<< Q < z",
+ { "m","M","x","X","q","Q","a","z","n" }, 9},
+ { "&m < a &[before 3] a <<< x <<< X << q <<< Q < z",
+ { "m","M","x","X","a","q","Q","z","n" }, 9},
+ { "&m << a &[before 1] a < x <<< X << q <<< Q < z",
+ { "x","X","q","Q","z","m","M","a","n" }, 9},
+ { "&m << a &[before 2] a << x <<< X << q <<< Q < z",
+ { "m","M","x","X","q","Q","a","z","n" }, 9},
+ { "&m << a &[before 3] a <<< x <<< X << q <<< Q < z",
+ { "m","M","x","X","a","q","Q","z","n" }, 9},
+ { "&m <<< a &[before 1] a < x <<< X << q <<< Q < z",
+ { "x","X","q","Q","z","n","m","a","M" }, 9},
+ { "&m <<< a &[before 2] a << x <<< X << q <<< Q < z",
+ { "x","X","q","Q","m","a","M","z","n" }, 9},
+ { "&m <<< a &[before 3] a <<< x <<< X << q <<< Q < z",
+ { "m","x","X","a","M","q","Q","z","n" }, 9},
+ { "&[before 1] s < x <<< X << q <<< Q < z",
+ { "r","R","x","X","q","Q","z","s","n" }, 9},
+ { "&[before 2] s << x <<< X << q <<< Q < z",
+ { "r","R","x","X","q","Q","s","z","n" }, 9},
+ { "&[before 3] s <<< x <<< X << q <<< Q < z",
+ { "r","R","x","X","s","q","Q","z","n" }, 9},
+ { "&[before 1] \\u24DC < x <<< X << q <<< Q < z",
+ { "x","X","q","Q","z","n","m","\\u24DC","M" }, 9},
+ { "&[before 2] \\u24DC << x <<< X << q <<< Q < z",
+ { "x","X","q","Q","m","\\u24DC","M","z","n" }, 9},
+ { "&[before 3] \\u24DC <<< x <<< X << q <<< Q < z",
+ { "m","x","X","\\u24DC","M","q","Q","z","n" }, 9}
+ };
+
+ int32_t i = 0;
+
+ for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ genericRulesStarter(tests[i].rules, tests[i].order, tests[i].size);
+ }
+}
+#endif
+
+static void TestTailorNULL( void ) {
+ const static char* rule = "&a <<< '\\u0000'";
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rlz[RULE_BUFFER_LEN] = { 0 };
+ uint32_t rlen = 0;
+ UChar a = 1, null = 0;
+ UCollationResult res = UCOL_EQUAL;
+
+ UCollator *coll = NULL;
+
+
+ rlen = u_unescape(rule, rlz, RULE_BUFFER_LEN);
+ coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
+
+ if(U_FAILURE(status)) {
+ log_err("Could not open default collator!\n");
+ } else {
+ res = ucol_strcoll(coll, &a, 1, &null, 1);
+
+ if(res != UCOL_LESS) {
+ log_err("NULL was not tailored properly!\n");
+ }
+ }
+
+ ucol_close(coll);
+}
+
+static void
+TestThaiSortKey(void)
+{
+ UChar yamakan = 0x0E4E;
+ UErrorCode status = U_ZERO_ERROR;
+ uint8_t key[256];
+ int32_t keyLen = 0;
+ /* NOTE: there is a Thai tailoring that moves Yammakan. It should not move it, */
+ /* since it stays in the same relative position. This should be addressed in CLDR */
+ /* UCA 4.0 uint8_t expectedKey[256] = { 0x01, 0xd9, 0xb2, 0x01, 0x05, 0x00 }; */
+ /* UCA 4.1 uint8_t expectedKey[256] = { 0x01, 0xdb, 0x3a, 0x01, 0x05, 0x00 }; */
+ /* UCA 5.0 moves Yammakan */
+ uint8_t expectedKey[256] = { 0x01, 0xdc, 0xce, 0x01, 0x05, 0x00 };
+ UCollator *coll = ucol_open("th", &status);
+ if(U_FAILURE(status)) {
+ log_err("Could not open a collator, exiting (%s)\n", u_errorName(status));
+ return;
+ }
+
+ keyLen = ucol_getSortKey(coll, &yamakan, 1, key, 256);
+ if(strcmp((char *)key, (char *)expectedKey)) {
+ log_err("Yammakan key is different from ICU 34!\n");
+ }
+
+ ucol_close(coll);
+}
+
+static void
+TestUpperFirstQuaternary(void)
+{
+ const char* tests[] = { "B", "b", "Bb", "bB" };
+ UColAttribute att[] = { UCOL_STRENGTH, UCOL_CASE_FIRST };
+ UColAttributeValue attVals[] = { UCOL_QUATERNARY, UCOL_UPPER_FIRST };
+ genericLocaleStarterWithOptions("root", tests, sizeof(tests)/sizeof(tests[0]), att, attVals, sizeof(att)/sizeof(att[0]));
+}
+
+static void
+TestJ4960(void)
+{
+ const char* tests[] = { "\\u00e2T", "aT" };
+ UColAttribute att[] = { UCOL_STRENGTH, UCOL_CASE_LEVEL };
+ UColAttributeValue attVals[] = { UCOL_PRIMARY, UCOL_ON };
+ const char* tests2[] = { "a", "A" };
+ const char* rule = "&[first tertiary ignorable]=A=a";
+ UColAttribute att2[] = { UCOL_CASE_LEVEL };
+ UColAttributeValue attVals2[] = { UCOL_ON };
+ /* Test whether we correctly ignore primary ignorables on case level when */
+ /* we have only primary & case level */
+ genericLocaleStarterWithOptionsAndResult("root", tests, sizeof(tests)/sizeof(tests[0]), att, attVals, sizeof(att)/sizeof(att[0]), UCOL_EQUAL);
+ /* Test whether ICU4J will make case level for sortkeys that have primary strength */
+ /* and case level */
+ genericLocaleStarterWithOptions("root", tests2, sizeof(tests2)/sizeof(tests2[0]), att, attVals, sizeof(att)/sizeof(att[0]));
+ /* Test whether completely ignorable letters have case level info (they shouldn't) */
+ genericRulesStarterWithOptionsAndResult(rule, tests2, sizeof(tests2)/sizeof(tests2[0]), att2, attVals2, sizeof(att2)/sizeof(att2[0]), UCOL_EQUAL);
+}
+
+static void
+TestJ5223(void)
+{
+ static const char *test = "this is a test string";
+ UChar ustr[256];
+ int32_t ustr_length = u_unescape(test, ustr, 256);
+ unsigned char sortkey[256];
+ int32_t sortkey_length;
+ UErrorCode status = U_ZERO_ERROR;
+ static UCollator *coll = NULL;
+ coll = ucol_open("root", &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't open UCA\n");
+ return;
+ }
+ ucol_setStrength(coll, UCOL_PRIMARY);
+ ucol_setAttribute(coll, UCOL_STRENGTH, UCOL_PRIMARY, &status);
+ ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ if (U_FAILURE(status)) {
+ log_err("Failed setting atributes\n");
+ return;
+ }
+ sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, NULL, 0);
+ if (sortkey_length > 256) return;
+
+ /* we mark the position where the null byte should be written in advance */
+ sortkey[sortkey_length-1] = 0xAA;
+
+ /* we set the buffer size one byte higher than needed */
+ sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, sortkey,
+ sortkey_length+1);
+
+ /* no error occurs (for me) */
+ if (sortkey[sortkey_length-1] == 0xAA) {
+ log_err("Hit bug at first try\n");
+ }
+
+ /* we mark the position where the null byte should be written again */
+ sortkey[sortkey_length-1] = 0xAA;
+
+ /* this time we set the buffer size to the exact amount needed */
+ sortkey_length = ucol_getSortKey(coll, ustr, ustr_length, sortkey,
+ sortkey_length);
+
+ /* now the trailing null byte is not written */
+ if (sortkey[sortkey_length-1] == 0xAA) {
+ log_err("Hit bug at second try\n");
+ }
+
+ ucol_close(coll);
+}
+
+/* Regression test for Thai partial sort key problem */
+static void
+TestJ5232(void)
+{
+ const static char *test[] = {
+ "\\u0e40\\u0e01\\u0e47\\u0e1a\\u0e40\\u0e25\\u0e47\\u0e21",
+ "\\u0e40\\u0e01\\u0e47\\u0e1a\\u0e40\\u0e25\\u0e48\\u0e21"
+ };
+
+ genericLocaleStarter("th", test, sizeof(test)/sizeof(test[0]));
+}
+
+static void
+TestJ5367(void)
+{
+ const static char *test[] = { "a", "y" };
+ const char* rules = "&Ny << Y &[first secondary ignorable] <<< a";
+ genericRulesStarter(rules, test, sizeof(test)/sizeof(test[0]));
+}
+
+static void
+TestVI5913(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i, j;
+ UCollator *coll =NULL;
+ uint8_t resColl[100], expColl[100];
+ int32_t rLen, tLen, ruleLen, sLen, kLen;
+ UChar rule[256]={0x26, 0x62, 0x3c, 0x1FF3, 0}; /* &a<0x1FF3-omega with Ypogegrammeni*/
+ UChar rule2[256]={0x26, 0x7a, 0x3c, 0x0161, 0}; /* &z<s with caron*/
+ UChar rule3[256]={0x26, 0x7a, 0x3c, 0x0061, 0x00ea, 0}; /* &z<a+e with circumflex.*/
+ UChar tData[][20]={
+ {0x1EAC, 0},
+ {0x0041, 0x0323, 0x0302, 0},
+ {0x1EA0, 0x0302, 0},
+ {0x00C2, 0x0323, 0},
+ {0x1ED8, 0}, /* O with dot and circumflex */
+ {0x1ECC, 0x0302, 0},
+ {0x1EB7, 0},
+ {0x1EA1, 0x0306, 0},
+ };
+ UChar tailorData[][20]={
+ {0x1FA2, 0}, /* Omega with 3 combining marks */
+ {0x03C9, 0x0313, 0x0300, 0x0345, 0},
+ {0x1FF3, 0x0313, 0x0300, 0},
+ {0x1F60, 0x0300, 0x0345, 0},
+ {0x1F62, 0x0345, 0},
+ {0x1FA0, 0x0300, 0},
+ };
+ UChar tailorData2[][20]={
+ {0x1E63, 0x030C, 0}, /* s with dot below + caron */
+ {0x0073, 0x0323, 0x030C, 0},
+ {0x0073, 0x030C, 0x0323, 0},
+ };
+ UChar tailorData3[][20]={
+ {0x007a, 0}, /* z */
+ {0x0061, 0x0065, 0}, /* a + e */
+ {0x0061, 0x00ea, 0}, /* a + e with circumflex */
+ {0x0061, 0x1EC7, 0}, /* a+ e with dot below and circumflex */
+ {0x0061, 0x1EB9, 0x0302, 0}, /* a + e with dot below + combining circumflex */
+ {0x0061, 0x00EA, 0x0323, 0}, /* a + e with circumflex + combining dot below */
+ {0x00EA, 0x0323, 0}, /* e with circumflex + combining dot below */
+ {0x00EA, 0}, /* e with circumflex */
+ };
+
+ /* Test Vietnamese sort. */
+ coll = ucol_open("vi", &status);
+ log_verbose("\n\nVI collation:");
+ if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[2], u_strlen(tData[2])) ) {
+ log_err("\\u1EAC not equals to \\u1EA0+\\u0302\n");
+ }
+ if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[3], u_strlen(tData[3])) ) {
+ log_err("\\u1EAC not equals to \\u00c2+\\u0323\n");
+ }
+ if ( !ucol_equal(coll, tData[5], u_strlen(tData[5]), tData[4], u_strlen(tData[4])) ) {
+ log_err("\\u1ED8 not equals to \\u1ECC+\\u0302\n");
+ }
+ if ( !ucol_equal(coll, tData[7], u_strlen(tData[7]), tData[6], u_strlen(tData[6])) ) {
+ log_err("\\u1EB7 not equals to \\u1EA1+\\u0306\n");
+ }
+
+ for (j=0; j<8; j++) {
+ tLen = u_strlen(tData[j]);
+ log_verbose("\n Data :%s \tlen: %d key: ", tData[j], tLen);
+ rLen = ucol_getSortKey(coll, tData[j], tLen, resColl, 100);
+ for(i = 0; i<rLen; i++) {
+ log_verbose(" %02X", resColl[i]);
+ }
+ }
+
+ ucol_close(coll);
+
+ /* Test Russian sort. */
+ coll = ucol_open("ro", &status);
+ log_verbose("\n\nRO collation:");
+ if ( !ucol_equal(coll, tData[0], u_strlen(tData[0]), tData[1], u_strlen(tData[1])) ) {
+ log_err("\\u1EAC not equals to \\u1EA0+\\u0302\n");
+ }
+ if ( !ucol_equal(coll, tData[4], u_strlen(tData[4]), tData[5], u_strlen(tData[5])) ) {
+ log_err("\\u1EAC not equals to \\u00c2+\\u0323\n");
+ }
+ if ( !ucol_equal(coll, tData[6], u_strlen(tData[6]), tData[7], u_strlen(tData[7])) ) {
+ log_err("\\u1EB7 not equals to \\u1EA1+\\u0306\n");
+ }
+
+ for (j=4; j<8; j++) {
+ tLen = u_strlen(tData[j]);
+ log_verbose("\n Data :%s \tlen: %d key: ", tData[j], tLen);
+ rLen = ucol_getSortKey(coll, tData[j], tLen, resColl, 100);
+ for(i = 0; i<rLen; i++) {
+ log_verbose(" %02X", resColl[i]);
+ }
+ }
+ ucol_close(coll);
+
+ /* Test the precomposed Greek character with 3 combining marks. */
+ log_verbose("\n\nTailoring test: Greek character with 3 combining marks");
+ ruleLen = u_strlen(rule);
+ coll = ucol_openRules(rule, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ sLen = u_strlen(tailorData[0]);
+ for (j=1; j<6; j++) {
+ tLen = u_strlen(tailorData[j]);
+ if ( !ucol_equal(coll, tailorData[0], sLen, tailorData[j], tLen)) {
+ log_err("\n \\u1FA2 not equals to data[%d]:%s\n", j, tailorData[j]);
+ }
+ }
+ /* Test getSortKey. */
+ tLen = u_strlen(tailorData[0]);
+ kLen=ucol_getSortKey(coll, tailorData[0], tLen, expColl, 100);
+ for (j=0; j<6; j++) {
+ tLen = u_strlen(tailorData[j]);
+ rLen = ucol_getSortKey(coll, tailorData[j], tLen, resColl, 100);
+ if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) {
+ log_err("\n Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen);
+ for(i = 0; i<rLen; i++) {
+ log_err(" %02X", resColl[i]);
+ }
+ }
+ }
+ ucol_close(coll);
+
+ log_verbose("\n\nTailoring test for s with caron:");
+ ruleLen = u_strlen(rule2);
+ coll = ucol_openRules(rule2, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ tLen = u_strlen(tailorData2[0]);
+ kLen=ucol_getSortKey(coll, tailorData2[0], tLen, expColl, 100);
+ for (j=1; j<3; j++) {
+ tLen = u_strlen(tailorData2[j]);
+ rLen = ucol_getSortKey(coll, tailorData2[j], tLen, resColl, 100);
+ if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) {
+ log_err("\n After tailoring Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen);
+ for(i = 0; i<rLen; i++) {
+ log_err(" %02X", resColl[i]);
+ }
+ }
+ }
+ ucol_close(coll);
+
+ log_verbose("\n\nTailoring test for &z< ae with circumflex:");
+ ruleLen = u_strlen(rule3);
+ coll = ucol_openRules(rule3, ruleLen, UCOL_OFF, UCOL_TERTIARY, NULL,&status);
+ tLen = u_strlen(tailorData3[3]);
+ kLen=ucol_getSortKey(coll, tailorData3[3], tLen, expColl, 100);
+ for (j=4; j<6; j++) {
+ tLen = u_strlen(tailorData3[j]);
+ rLen = ucol_getSortKey(coll, tailorData3[j], tLen, resColl, 100);
+
+ if ( kLen!=rLen || uprv_memcmp(expColl, resColl, rLen*sizeof(uint8_t))!=0 ) {
+ log_err("\n After tailoring Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen);
+ for(i = 0; i<rLen; i++) {
+ log_err(" %02X", resColl[i]);
+ }
+ }
+
+ log_verbose("\n Test Data[%d] :%s \tlen: %d key: ", j, tailorData[j], tLen);
+ for(i = 0; i<rLen; i++) {
+ log_verbose(" %02X", resColl[i]);
+ }
+ }
+ ucol_close(coll);
+}
+
+#define TSKC_DATA_SIZE 5
+#define TSKC_BUF_SIZE 50
+static void
+TestSortKeyConsistency(void)
+{
+ UErrorCode icuRC = U_ZERO_ERROR;
+ UCollator* ucol;
+ UChar data[] = { 0xFFFD, 0x0006, 0x0006, 0x0006, 0xFFFD};
+
+ uint8_t bufFull[TSKC_DATA_SIZE][TSKC_BUF_SIZE];
+ uint8_t bufPart[TSKC_DATA_SIZE][TSKC_BUF_SIZE];
+ int32_t i, j, i2;
+
+ ucol = ucol_openFromShortString("LEN_S4", FALSE, NULL, &icuRC);
+ if (U_FAILURE(icuRC))
+ {
+ log_err("ucol_openFromShortString failed\n");
+ return;
+ }
+
+ for (i = 0; i < TSKC_DATA_SIZE; i++)
+ {
+ UCharIterator uiter;
+ uint32_t state[2] = { 0, 0 };
+ int32_t dataLen = i+1;
+ for (j=0; j<TSKC_BUF_SIZE; j++)
+ bufFull[i][j] = bufPart[i][j] = 0;
+
+ /* Full sort key */
+ ucol_getSortKey(ucol, data, dataLen, bufFull[i], TSKC_BUF_SIZE);
+
+ /* Partial sort key */
+ uiter_setString(&uiter, data, dataLen);
+ ucol_nextSortKeyPart(ucol, &uiter, state, bufPart[i], TSKC_BUF_SIZE, &icuRC);
+ if (U_FAILURE(icuRC))
+ {
+ log_err("ucol_nextSortKeyPart failed\n");
+ ucol_close(ucol);
+ return;
+ }
+
+ for (i2=0; i2<i; i2++)
+ {
+ UBool fullMatch = TRUE;
+ UBool partMatch = TRUE;
+ for (j=0; j<TSKC_BUF_SIZE; j++)
+ {
+ fullMatch = fullMatch && (bufFull[i][j] != bufFull[i2][j]);
+ partMatch = partMatch && (bufPart[i][j] != bufPart[i2][j]);
+ }
+ if (fullMatch != partMatch) {
+ log_err(fullMatch ? "full key was consistent, but partial key changed\n"
+ : "partial key was consistent, but full key changed\n");
+ ucol_close(ucol);
+ return;
+ }
+ }
+
+ }
+
+ /*=============================================*/
+ ucol_close(ucol);
+}
+
+
+#define TEST(x) addTest(root, &x, "tscoll/cmsccoll/" # x)
+
+void addMiscCollTest(TestNode** root)
+{
+ TEST(TestRuleOptions);
+ TEST(TestBeforePrefixFailure);
+ TEST(TestContractionClosure);
+ TEST(TestPrefixCompose);
+ TEST(TestStrCollIdenticalPrefix);
+ TEST(TestPrefix);
+ TEST(TestNewJapanese);
+ /*TEST(TestLimitations);*/
+ TEST(TestNonChars);
+ TEST(TestExtremeCompression);
+ TEST(TestSurrogates);
+ TEST(TestVariableTopSetting);
+ TEST(TestBocsuCoverage);
+ TEST(TestCyrillicTailoring);
+ TEST(TestCase);
+ TEST(IncompleteCntTest);
+ TEST(BlackBirdTest);
+ TEST(FunkyATest);
+ TEST(BillFairmanTest);
+ TEST(RamsRulesTest);
+ TEST(IsTailoredTest);
+ TEST(TestCollations);
+ TEST(TestChMove);
+ TEST(TestImplicitTailoring);
+ TEST(TestFCDProblem);
+ TEST(TestEmptyRule);
+ /*TEST(TestJ784);*/ /* 'zh' locale has changed - now it is getting tested by TestBeforePinyin */
+ TEST(TestJ815);
+ /*TEST(TestJ831);*/ /* we changed lv locale */
+ TEST(TestBefore);
+ TEST(TestRedundantRules);
+ TEST(TestExpansionSyntax);
+ TEST(TestHangulTailoring);
+ TEST(TestUCARules);
+ TEST(TestIncrementalNormalize);
+ TEST(TestComposeDecompose);
+ TEST(TestCompressOverlap);
+ TEST(TestContraction);
+ TEST(TestExpansion);
+ /*TEST(PrintMarkDavis);*/ /* this test doesn't test - just prints sortkeys */
+ /*TEST(TestGetCaseBit);*/ /*this one requires internal things to be exported */
+ TEST(TestOptimize);
+ TEST(TestSuppressContractions);
+ TEST(Alexis2);
+ TEST(TestHebrewUCA);
+ TEST(TestPartialSortKeyTermination);
+ TEST(TestSettings);
+ TEST(TestEquals);
+ TEST(TestJ2726);
+ TEST(NullRule);
+ TEST(TestNumericCollation);
+ TEST(TestTibetanConformance);
+ TEST(TestPinyinProblem);
+ TEST(TestImplicitGeneration);
+ TEST(TestSeparateTrees);
+ TEST(TestBeforePinyin);
+ TEST(TestBeforeTightening);
+ /*TEST(TestMoreBefore);*/
+ TEST(TestTailorNULL);
+ TEST(TestThaiSortKey);
+ TEST(TestUpperFirstQuaternary);
+ TEST(TestJ4960);
+ TEST(TestJ5223);
+ TEST(TestJ5232);
+ TEST(TestJ5367);
+ TEST(TestSortKeyConsistency);
+ TEST(TestVI5913); /* VI, RO tailored rules */
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c
new file mode 100644
index 00000000000..96e01877029
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.c
@@ -0,0 +1,1093 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CMSGTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* C API TEST FOR MESSAGE FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "unicode/uloc.h"
+#include "unicode/umsg.h"
+#include "unicode/udat.h"
+#include "unicode/umsg.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cmsgtst.h"
+#include "cformtst.h"
+
+static const char* const txt_testCasePatterns[] = {
+ "Quotes '', '{', a {0,number,integer} '{'0}",
+ "Quotes '', '{', a {0,number,integer} '{'0}",
+ "You deposited {0,number,integer} times an amount of {1,number,currency} on {2,date,short}",
+ "'{'2,time,full}, for {1, number }, {0,number,integer} is {2,time,full} and full date is {2,date,full}",
+ "'{'1,number,percent} for {0,number,integer} is {1,number,percent}",
+};
+
+static const char* const txt_testResultStrings[] = {
+ "Quotes ', {, a 1 {0}",
+ "Quotes ', {, a 1 {0}",
+ "You deposited 1 times an amount of $3,456.00 on 1/12/70",
+ "{2,time,full}, for 3,456, 1 is 5:46:40 AM PT and full date is Monday, January 12, 1970",
+ "{1,number,percent} for 1 is 345,600%"
+};
+
+const int32_t cnt_testCases = 5;
+static UChar* testCasePatterns[5];
+
+static UChar* testResultStrings[5];
+
+static UBool strings_initialized = FALSE;
+
+/* function used to create the test patterns for testing Message formatting */
+static void InitStrings( void )
+{
+ int32_t i;
+ if (strings_initialized)
+ return;
+
+ for (i=0; i < cnt_testCases; i++ ) {
+ uint32_t strSize = (uint32_t)strlen(txt_testCasePatterns[i]) + 1;
+ testCasePatterns[i]=(UChar*)malloc(sizeof(UChar) * strSize);
+ u_uastrncpy(testCasePatterns[i], txt_testCasePatterns[i], strSize);
+ }
+ for (i=0; i < cnt_testCases; i++ ) {
+ uint32_t strSize = (uint32_t)strlen(txt_testResultStrings[i]) + 1;
+ testResultStrings[i] = (UChar*)malloc(sizeof(UChar) * strSize);
+ u_uastrncpy(testResultStrings[i], txt_testResultStrings[i], strSize);
+ }
+
+ strings_initialized = TRUE;
+}
+
+static void FreeStrings( void )
+{
+ int32_t i;
+ if (!strings_initialized)
+ return;
+
+ for (i=0; i < cnt_testCases; i++ ) {
+ free(testCasePatterns[i]);
+ }
+ for (i=0; i < cnt_testCases; i++ ) {
+ free(testResultStrings[i]);
+ }
+ strings_initialized = FALSE;
+}
+
+/* Platform dependent test to detect if this type will return NULL when interpreted as a pointer. */
+static UBool returnsNullForType(int firstParam, ...) {
+ UBool isNULL;
+ va_list marker;
+ va_start(marker, firstParam);
+ isNULL = (UBool)(va_arg(marker, void*) == NULL);
+ va_end(marker);
+ return isNULL;
+}
+
+/* Test u_formatMessage() with various test patterns() */
+static void MessageFormatTest( void )
+{
+ UChar *str;
+ UChar* result;
+ int32_t resultLengthOut,resultlength,i, patternlength;
+ UErrorCode status = U_ZERO_ERROR;
+ UDate d1=1000000000.0;
+
+ ctest_setTimeZone(NULL, &status);
+
+ str=(UChar*)malloc(sizeof(UChar) * 7);
+ u_uastrncpy(str, "MyDisk", 7);
+ resultlength=1;
+ result=(UChar*)malloc(sizeof(UChar) * 1);
+ log_verbose("Testing u_formatMessage()\n");
+ InitStrings();
+ for (i = 0; i < cnt_testCases; i++) {
+ status=U_ZERO_ERROR;
+ patternlength=u_strlen(testCasePatterns[i]);
+ resultLengthOut=u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &status, 1, 3456.00, d1);
+ if(status== U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result,sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &status, 1, 3456.00, d1);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) );
+ }
+ if(u_strcmp(result, testResultStrings[i])==0){
+ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
+ }
+ else{
+ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
+ austrdup(result), austrdup(testResultStrings[i]) );
+ }
+ }
+ free(result);
+ result = NULL;
+ free(str);
+ {
+
+ for (i = 0; i < cnt_testCases; i++) {
+ UParseError parseError;
+ status=U_ZERO_ERROR;
+ patternlength=u_strlen(testCasePatterns[i]);
+ resultlength=0;
+ resultLengthOut=u_formatMessageWithError( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &parseError,&status, 1, 3456.00, d1);
+ if(status== U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &status, 1, 3456.00, d1);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) );
+ continue;
+ }
+ if(u_strcmp(result, testResultStrings[i])==0){
+ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
+ }
+ else{
+ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
+ austrdup(result), austrdup(testResultStrings[i]) );
+ }
+ free(result);
+ result=NULL;
+ }
+ }
+ {
+ UErrorCode ec = U_ZERO_ERROR;
+ int32_t patternLength = u_strlen(testCasePatterns[0]);
+
+ UMessageFormat formatter = umsg_open(testCasePatterns[0],patternLength,"en_US",NULL,&ec);
+
+ if(U_FAILURE(ec)){
+ log_err("umsg_open() failed for testCasePattens[%d].\n",i);
+ return;
+ }
+ for(i = 0;i<cnt_testCases; i++){
+ UParseError parseError;
+ int32_t resultLength =0,count=0;
+ int32_t one=0;
+ int32_t two=0;
+ UDate d2=0;
+
+ result=NULL;
+ patternLength = u_strlen(testCasePatterns[i]);
+
+ umsg_applyPattern(formatter,testCasePatterns[i],patternLength,&parseError,&ec);
+ if(U_FAILURE(ec)){
+ log_err("umsg_applyPattern() failed for testCasePattens[%d].\n",i);
+ return;
+ }
+ /* pre-flight */
+ resultLength = umsg_format(formatter,result,resultLength,&ec,1,3456.00,d1);
+ if(ec==U_BUFFER_OVERFLOW_ERROR){
+ ec=U_ZERO_ERROR;
+ result = (UChar*) malloc(U_SIZEOF_UCHAR*resultLength+2);
+ resultLength = umsg_format(formatter,result,resultLength+2,&ec,1,3456.00,d1);
+ if(U_FAILURE(ec)){
+ log_err("ERROR: failure in message format on testcase %d: %s\n", i, u_errorName(status) );
+ free(result);
+ return;
+ }
+
+ if(u_strcmp(result, testResultStrings[i])==0){
+ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
+ }
+ else{
+ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
+ austrdup(result), austrdup(testResultStrings[i]) );
+ }
+
+ if (returnsNullForType(1, (double)2.0)) {
+ /* HP/UX and possibly other platforms don't properly check for this case.
+ We pass in a UDate, but the function expects a UDate *. When va_arg is used,
+ most compilers will return NULL, but HP-UX won't do that and will return 2
+ in this case. This is a platform dependent test.
+
+ This relies upon "undefined" behavior, as indicated by C99 7.15.1.1 paragraph 2
+ */
+ umsg_parse(formatter,result,resultLength,&count,&ec,one,two,d2);
+ if(ec!=U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("FAIL: Did not get expected error for umsg_parse(). Expected: U_ILLEGAL_ARGUMENT_ERROR Got: %s \n",u_errorName(ec));
+ }else{
+ ec = U_ZERO_ERROR;
+ }
+ }
+ else {
+ log_verbose("Warning: Returning NULL for a mismatched va_arg type isn't supported on this platform.\n", i);
+ }
+
+ umsg_parse(formatter,result,resultLength,&count,&ec,&one,&two,&d2);
+ if(U_FAILURE(ec)){
+ log_err("umsg_parse could not parse the pattern. Error: %s.\n",u_errorName(ec));
+ }
+ free(result);
+ }else{
+ log_err("FAIL: Expected U_BUFFER_OVERFLOW error while preflighting got: %s for testCasePatterns[%d]",u_errorName(ec),i);
+ }
+ }
+ umsg_close(formatter);
+ }
+ FreeStrings();
+
+ ctest_resetTimeZone();
+}
+
+
+/*test u_formatMessage() with sample patterns */
+static void TestSampleMessageFormat(void)
+{
+ UChar *str;
+ UChar *result;
+ UChar pattern[100], expected[100];
+ int32_t resultLengthOut, resultlength;
+ UDate d = 837039928046.0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ ctest_setTimeZone(NULL, &status);
+
+ str=(UChar*)malloc(sizeof(UChar) * 15);
+ u_uastrcpy(str, "abc");
+
+ u_uastrcpy(pattern, "There are {0} files on {1,date}");
+ u_uastrcpy(expected, "There are abc files on Jul 10, 1996");
+ result=(UChar*)malloc(sizeof(UChar) * 1);
+ log_verbose("\nTesting a sample for Message format test#1\n");
+ resultlength=1;
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, d);
+ }
+ if(U_FAILURE(status)){
+ log_err("Error: failure in message format on test#1: %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#1\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#1 \n GOT: %s EXPECTED: %s\n",
+ austrdup(result), austrdup(expected) );
+ }
+
+
+ log_verbose("\nTesting message format with another pattern test#2\n");
+ u_uastrcpy(pattern, "The disk \"{0}\" contains {1,number,integer} file(s)");
+ u_uastrcpy(expected, "The disk \"MyDisk\" contains 23 file(s)");
+ u_uastrcpy(str, "MyDisk");
+
+ resultLengthOut=u_formatMessage( "en_US",
+ pattern,
+ u_strlen(pattern),
+ result,
+ resultlength,
+ &status,
+ str,
+ 235);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * (resultlength+1));
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 23);
+ }
+ if(U_FAILURE(status)){
+ log_err("Error: failure in message format on test#2 : %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#2\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#2\n GOT: %s EXPECTED: %s\n",
+ austrdup(result), austrdup(expected) );
+ }
+
+
+
+ log_verbose("\nTesting message format with another pattern test#3\n");
+ u_uastrcpy(pattern, "You made a {0} of {1,number,currency}");
+ u_uastrcpy(expected, "You made a deposit of $500.00");
+ u_uastrcpy(str, "deposit");
+ resultlength=0;
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, str, 500.00);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, str, 500.00);
+ }
+ if(U_FAILURE(status)){
+ log_err("Error: failure in message format on test#3 : %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#3\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#3\n GOT: %s EXPECTED %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+
+ free(result);
+ free(str);
+
+ ctest_resetTimeZone();
+}
+
+/* Test umsg_format() and umsg_parse() , format and parse sequence and round trip */
+static void TestNewFormatAndParseAPI(void)
+{
+
+ UChar *result, *tzID, *str;
+ UChar pattern[100];
+ UChar expected[100];
+ int32_t resultLengthOut, resultlength;
+ UCalendar *cal;
+ UDate d1,d;
+ UDateFormat *def1;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value = 0;
+ UChar ret[30];
+ UParseError parseError;
+ UMessageFormat* fmt = NULL;
+ int32_t count=0;
+
+ ctest_setTimeZone(NULL, &status);
+
+ log_verbose("Testing format and parse with parse error\n");
+
+ str=(UChar*)malloc(sizeof(UChar) * 25);
+ u_uastrcpy(str, "disturbance in force");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("error in ucal_open caldef : %s\n", myErrorName(status) );
+ return;
+ }
+ ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
+ d1=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){
+ log_err("Error: failure in get millis: %s\n", myErrorName(status) );
+ return;
+ }
+
+ log_verbose("\nTesting with pattern test#4");
+ u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
+ u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
+ resultlength=1;
+ fmt = umsg_open(pattern,u_strlen(pattern),"en_US",&parseError,&status);
+ if(U_FAILURE(status)){
+ log_err("error in umsg_open : %s\n", u_errorName(status) );
+ return;
+ }
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+
+ resultLengthOut=umsg_format(fmt ,result, resultlength,&status, d1, str, 7);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
+ u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
+
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#4\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+
+
+ /*try to parse this and check*/
+ log_verbose("\nTesting the parse Message test#5\n");
+
+ umsg_parse(fmt, result, u_strlen(result),&count,&status, &d, ret, &value);
+ if(U_FAILURE(status)){
+ log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status));
+ }
+ if(value!=7 && u_strcmp(str,ret)!=0)
+ log_err("FAIL: Error in parseMessage on test#5 \n");
+ else
+ log_verbose("PASS: parseMessage successful on test#5\n");
+
+ def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status));
+ }else{
+
+ if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
+ log_verbose("PASS: parseMessage successful test#5\n");
+ else{
+ log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
+ austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
+ }
+ }
+ umsg_close(fmt);
+ udat_close(def1);
+ ucal_close(cal);
+
+ free(result);
+ free(str);
+ free(tzID);
+
+ ctest_resetTimeZone();
+}
+
+/* Test u_formatMessageWithError() and u_parseMessageWithError() , format and parse sequence and round trip */
+static void TestSampleFormatAndParseWithError(void)
+{
+
+ UChar *result, *tzID, *str;
+ UChar pattern[100];
+
+ UChar expected[100];
+ int32_t resultLengthOut, resultlength;
+ UCalendar *cal;
+ UDate d1,d;
+ UDateFormat *def1;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value = 0;
+ UChar ret[30];
+ UParseError parseError;
+
+ ctest_setTimeZone(NULL, &status);
+
+ log_verbose("Testing format and parse with parse error\n");
+
+ str=(UChar*)malloc(sizeof(UChar) * 25);
+ u_uastrcpy(str, "disturbance in force");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("error in ucal_open caldef : %s\n", myErrorName(status) );
+ }
+ ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
+ d1=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){
+ log_err("Error: failure in get millis: %s\n", myErrorName(status) );
+ }
+
+ log_verbose("\nTesting with pattern test#4");
+ u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
+ u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
+ resultlength=1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ resultLengthOut=u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
+ u_formatMessageWithError( "en_US", pattern, u_strlen(pattern), result, resultlength,&parseError, &status, d1, str, 7);
+
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#4\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+
+
+ /*try to parse this and check*/
+ log_verbose("\nTesting the parse Message test#5\n");
+
+ u_parseMessageWithError("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &parseError,&status, &d, ret, &value);
+ if(U_FAILURE(status)){
+ log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status));
+ }
+ if(value!=7 && u_strcmp(str,ret)!=0)
+ log_err("FAIL: Error in parseMessage on test#5 \n");
+ else
+ log_verbose("PASS: parseMessage successful on test#5\n");
+
+ def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status));
+ }else{
+
+ if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
+ log_verbose("PASS: parseMessage successful test#5\n");
+ else{
+ log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
+ austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
+ }
+ }
+ udat_close(def1);
+ ucal_close(cal);
+
+ free(result);
+ free(str);
+ free(tzID);
+
+ ctest_resetTimeZone();
+}
+
+/* Test u_formatMessage() and u_parseMessage() , format and parse sequence and round trip */
+static void TestSampleFormatAndParse(void)
+{
+
+ UChar *result, *tzID, *str;
+ UChar pattern[100];
+ UChar expected[100];
+ int32_t resultLengthOut, resultlength;
+ UCalendar *cal;
+ UDate d1,d;
+ UDateFormat *def1;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value = 0;
+ UChar ret[30];
+
+ ctest_setTimeZone(NULL, &status);
+
+ log_verbose("Testing format and parse\n");
+
+ str=(UChar*)malloc(sizeof(UChar) * 25);
+ u_uastrcpy(str, "disturbance in force");
+ tzID=(UChar*)malloc(sizeof(UChar) * 4);
+ u_uastrcpy(tzID, "PST");
+ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
+ if(U_FAILURE(status)){
+ log_err("error in ucal_open caldef : %s\n", myErrorName(status) );
+ }
+ ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
+ d1=ucal_getMillis(cal, &status);
+ if(U_FAILURE(status)){
+ log_err("Error: failure in get millis: %s\n", myErrorName(status) );
+ }
+
+ log_verbose("\nTesting with pattern test#4");
+ u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet {2,number,integer}");
+ u_uastrcpy(expected, "On March 18, 1999, there was a disturbance in force on planet 7");
+ resultlength=1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, d1, str, 7);
+
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format test#4: %s\n", myErrorName(status));
+ }
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#4\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#4\n GOT: %s EXPECTED: %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+
+
+ /*try to parse this and check*/
+ log_verbose("\nTesting the parse Message test#5\n");
+
+ u_parseMessage("en_US", pattern, u_strlen(pattern), result, u_strlen(result), &status, &d, ret, &value);
+ if(U_FAILURE(status)){
+ log_err("ERROR: error in parsing: test#5: %s\n", myErrorName(status));
+ }
+ if(value!=7 && u_strcmp(str,ret)!=0)
+ log_err("FAIL: Error in parseMessage on test#5 \n");
+ else
+ log_verbose("PASS: parseMessage successful on test#5\n");
+
+ def1 = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, NULL,0,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in creating the dateformat using short date and time style:\n %s\n", myErrorName(status));
+ }else{
+
+ if(u_strcmp(myDateFormat(def1, d), myDateFormat(def1, d1))==0)
+ log_verbose("PASS: parseMessage successful test#5\n");
+ else{
+ log_err("FAIL: parseMessage didn't parse the date successfully\n GOT: %s EXPECTED %s\n",
+ austrdup(myDateFormat(def1,d)), austrdup(myDateFormat(def1,d1)) );
+ }
+ }
+ udat_close(def1);
+ ucal_close(cal);
+
+ free(result);
+ free(str);
+ free(tzID);
+
+ ctest_resetTimeZone();
+}
+
+/* test message format with a choice option */
+static void TestMsgFormatChoice(void)
+{
+ UChar* str;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *result;
+ UChar pattern[100];
+ UChar expected[100];
+ int32_t resultlength,resultLengthOut;
+
+ str=(UChar*)malloc(sizeof(UChar) * 25);
+ u_uastrcpy(str, "MyDisk");
+ log_verbose("Testing message format with choice test #6\n:");
+ /*There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.*/
+ u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number,integer} files}");
+ u_uastrcpy(expected, "The disk MyDisk contains 100 files");
+ resultlength=0;
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 100., str);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 100., str);
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#6\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#6\n GOT %s EXPECTED %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+ free(result);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on test#6 : %s\n", myErrorName(status));
+ }
+
+ log_verbose("Testing message format with choice test #7\n:");
+ u_uastrcpy(expected, "The disk MyDisk contains no files");
+ resultlength=0;
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 0., str);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 0., str);
+
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#7\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#7\n GOT: %s EXPECTED %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+ free(result);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on test#7 : %s\n", myErrorName(status));
+ }
+
+ log_verbose("Testing message format with choice test #8\n:");
+ u_uastrcpy(expected, "The disk MyDisk contains one file");
+ resultlength=0;
+ resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, 1., str);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, 1., str);
+
+ if(u_strcmp(result, expected)==0)
+ log_verbose("PASS: MessagFormat successful on test#8\n");
+ else{
+ log_err("FAIL: Error in MessageFormat on test#8\n GOT %s EXPECTED: %s\n", austrdup(result),
+ austrdup(expected) );
+ }
+
+ free(result);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on test#8 : %s\n", myErrorName(status));
+ }
+
+ free(str);
+
+}
+
+/*test u_parseMessage() with various test patterns */
+static void TestParseMessage(void)
+{
+ UChar pattern[100];
+ UChar source[100];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value;
+ UChar str[10];
+ UChar res[10];
+
+ log_verbose("\nTesting a sample for parse Message test#9\n");
+
+ u_uastrcpy(source, "You deposited an amount of $500.00");
+ u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
+ u_uastrcpy(res,"deposited");
+
+ u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in parse Message on test#9: %s\n", myErrorName(status));
+ }
+ if(value==500.00 && u_strcmp(str,res)==0)
+ log_verbose("PASS: parseMessage successful on test#9\n");
+ else
+ log_err("FAIL: Error in parseMessage on test#9 \n");
+
+
+
+ log_verbose("\nTesting a sample for parse Message test#10\n");
+
+ u_uastrcpy(source, "There are 123 files on MyDisk created");
+ u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
+ u_uastrcpy(res,"MyDisk");
+
+ u_parseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in parse Message on test#10: %s\n", myErrorName(status));
+ }
+ if(value==123.00 && u_strcmp(str,res)==0)
+ log_verbose("PASS: parseMessage successful on test#10\n");
+ else
+ log_err("FAIL: Error in parseMessage on test#10 \n");
+
+
+
+}
+
+static int32_t CallFormatMessage(const char* locale, UChar* testCasePattern, int32_t patternLength,
+ UChar* result, int32_t resultLength, UErrorCode *status, ...)
+{
+ int32_t len = 0;
+ va_list ap;
+ va_start(ap, status);
+ len = u_vformatMessage(locale, testCasePattern, patternLength, result, resultLength, ap, status);
+ va_end(ap);
+ return len;
+}
+
+/* Test u_vformatMessage() with various test patterns. */
+static void TestMessageFormatWithValist( void )
+{
+
+ UChar *str;
+ UChar* result;
+ int32_t resultLengthOut,resultlength,i, patternlength;
+ UErrorCode status = U_ZERO_ERROR;
+ UDate d1=1000000000.0;
+
+ ctest_setTimeZone(NULL, &status);
+
+ str=(UChar*)malloc(sizeof(UChar) * 7);
+ u_uastrcpy(str, "MyDisk");
+ resultlength=1;
+ result=(UChar*)malloc(sizeof(UChar) * 1);
+ log_verbose("Testing u_formatMessage90\n");
+ InitStrings();
+ for (i = 0; i < cnt_testCases; i++) {
+ status=U_ZERO_ERROR;
+ patternlength=u_strlen(testCasePatterns[i]);
+ resultLengthOut=CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &status, 1, 3456.00, d1);
+ if(status== U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultLengthOut+1;
+ result=(UChar*)realloc(result,sizeof(UChar) * resultlength);
+ CallFormatMessage( "en_US",testCasePatterns[i], patternlength, result, resultlength,
+ &status, 1, 3456.00, d1);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in message format on testcase %d: %s\n", i, myErrorName(status) );
+ }
+ if(u_strcmp(result, testResultStrings[i])==0){
+ log_verbose("PASS: MessagFormat successful on testcase : %d\n", i);
+ }
+ else{
+ log_err("FAIL: Error in MessageFormat on testcase : %d\n GOT %s EXPECTED %s\n", i,
+ austrdup(result), austrdup(testResultStrings[i]) );
+ }
+ }
+ free(result);
+ free(str);
+ FreeStrings();
+
+ ctest_resetTimeZone();
+}
+
+static void CallParseMessage(const char* locale, UChar* pattern, int32_t patternLength,
+ UChar* source, int32_t sourceLength, UErrorCode *status, ...)
+{
+ va_list ap;
+ va_start(ap, status);
+ u_vparseMessage(locale, pattern, patternLength, source, sourceLength, ap, status);
+ va_end(ap);
+}
+
+/*test u_vparseMessage() with various test patterns */
+static void TestParseMessageWithValist(void)
+{
+ UChar pattern[100];
+ UChar source[100];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t value;
+ UChar str[10];
+ UChar res[10];
+
+ log_verbose("\nTesting a sample for parse Message test#9\n");
+
+ u_uastrcpy(source, "You deposited an amount of $500.00");
+ u_uastrcpy(pattern, "You {0} an amount of {1,number,currency}");
+ u_uastrcpy(res,"deposited");
+
+ CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, str, &value);
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in parse Message on test#9: %s\n", myErrorName(status));
+ }
+ if(value==500.00 && u_strcmp(str,res)==0)
+ log_verbose("PASS: parseMessage successful on test#9\n");
+ else
+ log_err("FAIL: Error in parseMessage on test#9 \n");
+
+
+ log_verbose("\nTesting a sample for parse Message test#10\n");
+
+ u_uastrcpy(source, "There are 123 files on MyDisk created");
+ u_uastrcpy(pattern, "There are {0,number,integer} files on {1} created");
+ u_uastrcpy(res,"MyDisk");
+
+ CallParseMessage( "en_US", pattern, u_strlen(pattern), source, u_strlen(source), &status, &value, str);
+ if(U_FAILURE(status)){
+ log_err("ERROR: failure in parse Message on test#10: %s\n", myErrorName(status));
+ }
+ if(value==123.00 && u_strcmp(str,res)==0)
+ log_verbose("PASS: parseMessage successful on test#10\n");
+ else
+ log_err("FAIL: Error in parseMessage on test#10 \n");
+}
+
+/**
+ * Regression test for ICU4C Jitterbug 904
+ */
+static void TestJ904(void) {
+ UChar pattern[256];
+ UChar result[256];
+ UChar string[16];
+ char cresult[256];
+ int32_t length;
+ UErrorCode status = U_ZERO_ERROR;
+ const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
+ const char* EXP = "Number 0,143, String foo, Date 12:34:56.789";
+
+ ctest_setTimeZone(NULL, &status);
+
+ u_uastrcpy(string, "foo");
+ /* Slight hack here -- instead of date pattern HH:mm:ss.SSS, use
+ * 12:mm:ss.SSS. Why? So this test generates the same output --
+ * "12:34:56.789" -- regardless of time zone (as long as we aren't
+ * in one of the 30 minute offset zones!). */
+ u_uastrcpy(pattern, PAT);
+ length = u_formatMessage("nl", pattern, u_strlen(pattern),
+ result, 256, &status,
+ string, 1/7.0,
+ 789.0+1000*(56+60*(34+60*12)));
+
+ u_austrncpy(cresult, result, sizeof(cresult));
+
+ /* This test passes if it DOESN'T CRASH. However, we test the
+ * output anyway. If the string doesn't match in the date part,
+ * check to see that the machine doesn't have an unusual time zone
+ * offset, that is, one with a non-zero minutes/seconds offset
+ * from GMT -- see above. */
+ if (strcmp(cresult, EXP) == 0) {
+ log_verbose("Ok: \"%s\"\n", cresult);
+ } else {
+ log_err("FAIL: got \"%s\", expected \"%s\"\n", cresult, EXP);
+ }
+
+ ctest_resetTimeZone();
+}
+
+static void OpenMessageFormatTest(void)
+{
+ UMessageFormat *f1, *f2, *f3;
+ UChar pattern[256];
+ UChar result[256];
+ char cresult[256];
+ UParseError parseError;
+ const char* locale = "hi_IN";
+ char* retLoc;
+ const char* PAT = "Number {1,number,#0.000}, String {0}, Date {2,date,12:mm:ss.SSS}";
+ int32_t length=0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_uastrncpy(pattern, PAT, sizeof(pattern)/sizeof(pattern[0]));
+
+ /* Test umsg_open */
+ f1 = umsg_open(pattern,length,NULL,NULL,&status);
+
+ if(U_FAILURE(status))
+ {
+ log_err("umsg_open failed with pattern %s. Error: \n", PAT, u_errorName(status));
+ return;
+ }
+
+ /* Test umsg_open with parse error */
+ status = U_ZERO_ERROR;
+ f2 = umsg_open(pattern,length,NULL,&parseError,&status);
+
+ if(U_FAILURE(status))
+ {
+ log_err("umsg_open with parseError failed with pattern %s. Error: %s\n", PAT, u_errorName(status));
+ return;
+ }
+
+ /* Test umsg_clone */
+ status = U_ZERO_ERROR;
+ f3 = umsg_clone(f1,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("umsg_clone failed. Error %s \n", u_errorName(status));
+ }
+
+ /* Test umsg_setLocale */
+ umsg_setLocale(f1,locale);
+ /* Test umsg_getLocale */
+ retLoc = (char*)umsg_getLocale(f1);
+ if(strcmp(retLoc,locale)!=0)
+ {
+ log_err("umsg_setLocale and umsg_getLocale methods failed. Expected:%s Got: %s \n", locale, retLoc);
+ }
+
+ /* Test umsg_applyPattern */
+ status = U_ZERO_ERROR;
+ umsg_applyPattern(f1,pattern,(int32_t)strlen(PAT),NULL,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("umsg_applyPattern failed. Error %s \n",u_errorName(status));
+ }
+
+ /* Test umsg_toPattern */
+ umsg_toPattern(f1,result,256,&status);
+ if(U_FAILURE(status) ){
+ log_err("umsg_toPattern method failed. Error: %s \n",u_errorName(status));
+ } else {
+ if(u_strcmp(result,pattern)!=0){
+ u_UCharsToChars(result,cresult,256);
+ log_err("umsg_toPattern method failed. Expected: %s Got: %s \n",PAT,cresult);
+ }
+ }
+ /* umsg_format umsg_parse */
+
+ umsg_close(f1);
+ umsg_close(f2);
+ umsg_close(f3);
+}
+
+static void MessageLength(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ const char patChars[] = {"123{0}456{0}"};
+ const char expectedChars[] = {"123abc"};
+ UChar pattern[sizeof(patChars)];
+ UChar arg[] = {0x61,0x62,0x63,0};
+ UChar result[128] = {0};
+ UChar expected[sizeof(expectedChars)];
+
+ u_uastrncpy(pattern, patChars, sizeof(pattern)/sizeof(pattern[0]));
+ u_uastrncpy(expected, expectedChars, sizeof(expected)/sizeof(expected[0]));
+
+ u_formatMessage("en_US", pattern, 6, result, sizeof(result)/sizeof(result[0]), &status, arg);
+ if (U_FAILURE(status)) {
+ log_err("u_formatMessage method failed. Error: %s \n",u_errorName(status));
+ }
+ if (u_strcmp(result, expected) != 0) {
+ log_err("u_formatMessage didn't return expected result\n");
+ }
+}
+
+static void TestErrorChaining(void) {
+ UErrorCode status = U_USELESS_COLLATOR_ERROR;
+
+ umsg_open(NULL, 0, NULL, NULL, &status);
+ umsg_applyPattern(NULL, NULL, 0, NULL, &status);
+ umsg_toPattern(NULL, NULL, 0, &status);
+ umsg_clone(NULL, &status);
+ umsg_format(NULL, NULL, 0, &status);
+ umsg_parse(NULL, NULL, 0, NULL, &status);
+ umsg_close(NULL);
+
+ /* All of this code should have done nothing. */
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Status got changed to %s\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ umsg_open(NULL, 0, NULL, NULL, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ umsg_applyPattern(NULL, NULL, 0, NULL, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ umsg_toPattern(NULL, NULL, 0, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ umsg_clone(NULL, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("Status should be U_ILLEGAL_ARGUMENT_ERROR instead of %s\n", u_errorName(status));
+ }
+}
+
+void addMsgForTest(TestNode** root);
+
+void addMsgForTest(TestNode** root)
+{
+ addTest(root, &OpenMessageFormatTest, "tsformat/cmsgtst/OpenMessageFormatTest");
+ addTest(root, &MessageFormatTest, "tsformat/cmsgtst/MessageFormatTest");
+ addTest(root, &TestSampleMessageFormat, "tsformat/cmsgtst/TestSampleMessageFormat");
+ addTest(root, &TestSampleFormatAndParse, "tsformat/cmsgtst/TestSampleFormatAndParse");
+ addTest(root, &TestSampleFormatAndParseWithError, "tsformat/cmsgtst/TestSampleFormatAndParseWithError");
+ addTest(root, &TestNewFormatAndParseAPI, "tsformat/cmsgtst/TestNewFormatAndParseAPI");
+ addTest(root, &TestMsgFormatChoice, "tsformat/cmsgtst/TestMsgFormatChoice");
+ addTest(root, &TestParseMessage, "tsformat/cmsgtst/TestParseMessage");
+ addTest(root, &TestMessageFormatWithValist, "tsformat/cmsgtst/TestMessageFormatWithValist");
+ addTest(root, &TestParseMessageWithValist, "tsformat/cmsgtst/TestParseMessageWithValist");
+ addTest(root, &TestJ904, "tsformat/cmsgtst/TestJ904");
+ addTest(root, &MessageLength, "tsformat/cmsgtst/MessageLength");
+ addTest(root, &TestErrorChaining, "tsformat/cmsgtst/TestErrorChaining");
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h
new file mode 100644
index 00000000000..6936283980e
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cmsgtst.h
@@ -0,0 +1,60 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CMSGTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* C API TEST FOR MESSAGE FORMAT */
+#ifndef _CMSGFRMTST
+#define _CMSGFRMTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+
+/* The function used to test the Message format API*/
+
+ /**
+ * Test u_formatMessage() with various test patterns
+ **/
+ static void MessageFormatTest(void);
+ /**
+ * Test u_formatMessage() with sample test Patterns
+ **/
+ static void TestSampleMessageFormat(void);
+ /**
+ * Test format and parse sequence and roundtrip
+ **/
+ static void TestSampleFormatAndParse(void);
+ /**
+ * Test u_formatMessage() with choice option
+ **/
+ static void TestMsgFormatChoice(void);
+ /**
+ * Test u_parseMessage() with various test patterns()
+ **/
+ static void TestParseMessage(void);
+ /**
+ * function used to set up various patterns used for testing u_formatMessage()
+ **/
+ static void InitStrings( void );
+
+ /**
+ * Regression test for ICU4C Jitterbug 904
+ */
+ static void TestJ904(void);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c
new file mode 100644
index 00000000000..152351487b5
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.c
@@ -0,0 +1,951 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CNMDPTST.C
+*
+* Madhu Katragadda Creation
+* Modification History:
+*
+* Date Name Description
+* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
+*******************************************************************************
+*/
+
+/* C DEPTH TEST FOR NUMBER FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/ucurr.h"
+#include "unicode/uloc.h"
+#include "unicode/unum.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cnmdptst.h"
+#include "cmemory.h"
+#include "cstring.h"
+
+#define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
+
+void addNumFrDepTest(TestNode** root);
+static void TestCurrencyPreEuro(void);
+static void TestCurrencyObject(void);
+
+void addNumFrDepTest(TestNode** root)
+{
+ addTest(root, &TestPatterns, "tsformat/cnmdptst/TestPatterns");
+ addTest(root, &TestQuotes, "tsformat/cnmdptst/TestQuotes");
+ addTest(root, &TestExponential, "tsformat/cnmdptst/TestExponential");
+ addTest(root, &TestCurrencySign, "tsformat/cnmdptst/TestCurrencySign");
+ addTest(root, &TestCurrency, "tsformat/cnmdptst/TestCurrency");
+ addTest(root, &TestCurrencyPreEuro, "tsformat/cnmdptst/TestCurrencyPreEuro");
+ addTest(root, &TestCurrencyObject, "tsformat/cnmdptst/TestCurrencyObject");
+ addTest(root, &TestRounding487, "tsformat/cnmdptst/TestRounding487");
+ addTest(root, &TestDoubleAttribute, "tsformat/cnmdptst/TestDoubleAttribute");
+ addTest(root, &TestSecondaryGrouping, "tsformat/cnmdptst/TestSecondaryGrouping");
+ addTest(root, &TestCurrencyKeywords, "tsformat/cnmdptst/TestCurrencyKeywords");
+ addTest(root, &TestRounding5350, "tsformat/cnmdptst/TestRounding5350");
+}
+
+/*Test Various format patterns*/
+static void TestPatterns(void)
+{
+ int32_t pat_length, i, lneed;
+ UNumberFormat *fmt;
+ UChar upat[5];
+ UChar unewpat[5];
+ UChar unum[5];
+ UChar *unewp=NULL;
+ UChar *str=NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ const char* pat[] = { "#.#", "#.", ".#", "#" };
+ const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
+ const char* num[] = { "0", "0.", ".0", "0" };
+
+ log_verbose("\nTesting different format patterns\n");
+ pat_length = sizeof(pat) / sizeof(pat[0]);
+ for (i=0; i < pat_length; ++i)
+ {
+ status = U_ZERO_ERROR;
+ u_uastrcpy(upat, pat[i]);
+ fmt= unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Number format constructor failed for pattern %s\n", pat[i]);
+ continue;
+ }
+ lneed=0;
+ lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status= U_ZERO_ERROR;
+ unewp=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_toPattern(fmt, FALSE, unewp, lneed+1, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("FAIL: Number format extracting the pattern failed for %s\n", pat[i]);
+ }
+ u_uastrcpy(unewpat, newpat[i]);
+ if(u_strcmp(unewp, unewpat) != 0)
+ log_err("FAIL: Pattern %s should be transmute to %s; %s seen instead\n", pat[i], newpat[i], austrdup(unewp) );
+
+ lneed=0;
+ lneed=unum_format(fmt, 0, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_format(fmt, 0, str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ u_uastrcpy(unum, num[i]);
+ if (u_strcmp(str, unum) != 0)
+ {
+ log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat[i], num[i], austrdup(str) );
+
+ }
+ free(unewp);
+ free(str);
+ unum_close(fmt);
+ }
+}
+
+/* Test the handling of quotes*/
+static void TestQuotes(void)
+{
+ int32_t lneed;
+ UErrorCode status=U_ZERO_ERROR;
+ UChar pat[15];
+ UChar res[15];
+ UChar *str=NULL;
+ UNumberFormat *fmt;
+ char tempBuf[256];
+ log_verbose("\nTestting the handling of quotes in number format\n");
+ u_uastrcpy(pat, "a'fo''o'b#");
+ fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in number format costruction using pattern \"a'fo''o'b#\"\n");
+ }
+ lneed=0;
+ lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_format(fmt, 123, str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status) || !str) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ return;
+ }
+ log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) );
+ log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) );
+ u_uastrcpy(res, "afo'ob123");
+ if(u_strcmp(str, res) != 0)
+ log_err("FAIL: Expected afo'ob123");
+
+ free(str);
+ unum_close(fmt);
+
+
+ u_uastrcpy(pat, "");
+ u_uastrcpy(pat, "a''b#");
+
+
+ fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in number format costruction using pattern \"a''b#\"\n");
+ }
+ lneed=0;
+ lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_format(fmt, 123, str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) );
+ log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) );
+ u_uastrcpy(res, "");
+ u_uastrcpy(res, "a'b123");
+ if(u_strcmp(str, res) != 0)
+ log_err("FAIL: Expected a'b123\n");
+
+ free(str);
+ unum_close(fmt);
+}
+
+/* Test exponential pattern*/
+static void TestExponential(void)
+{
+ int32_t pat_length, val_length, lval_length;
+ int32_t ival, ilval, p, v, lneed;
+ UNumberFormat *fmt;
+ int32_t ppos;
+ UChar *upat;
+ UChar pattern[20];
+ UChar *str=NULL;
+ UChar uvalfor[20], ulvalfor[20];
+ char tempMsgBug[256];
+ double a;
+ UErrorCode status = U_ZERO_ERROR;
+#ifdef OS390
+ static const double val[] = { 0.01234, 123456789, 1.23e75, -3.141592653e-78 };
+#else
+ static const double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
+#endif
+ static const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
+ static const int32_t lval[] = { 0, -1, 1, 123456789 };
+
+ static const char* valFormat[] =
+ {
+ "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
+ "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
+ "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
+ "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
+ };
+ static const char* lvalFormat[] =
+ {
+ "0E0", "-1E0", "1E0", "1.2346E8",
+ "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
+ "0E000", "-1E000", "1E000", "123.4568E006",
+ "0E0", "[1E0]", "1E0", "1.235E8"
+ };
+ static const double valParse[] =
+ {
+#ifdef OS390
+ 0.01234, 123460000, 1.23E75, -3.1416E-78,
+ 0.01234, 123460000, 1.23E75, -3.1416E-78,
+ 0.01234, 123456800, 1.23E75, -3.141593E-78,
+ 0.01234, 123500000, 1.23E75, -3.142E-78
+#else
+ /* We define the whole IEEE 754 number in the 4th column because
+ Visual Age 7 has a bug in rounding numbers. */
+ 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271,
+ 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271,
+ 0.01234, 123456800, 1.23E300, -3.1415929999999999E-271,
+ 0.01234, 123500000, 1.23E300, -3.1420000000000001E-271
+#endif
+ };
+ static const int32_t lvalParse[] =
+ {
+ 0, -1, 1, 123460000,
+ 0, -1, 1, 123460000,
+ 0, -1, 1, 123456800,
+ 0, -1, 1, 123500000
+ };
+
+
+ pat_length = sizeof(pat) / sizeof(pat[0]);
+ val_length = sizeof(val) / sizeof(val[0]);
+ lval_length = sizeof(lval) / sizeof(lval[0]);
+ ival = 0;
+ ilval = 0;
+ for (p=0; p < pat_length; ++p)
+ {
+ upat=(UChar*)malloc(sizeof(UChar) * (strlen(pat[p])+1) );
+ u_uastrcpy(upat, pat[p]);
+ fmt=unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: Bad status returned by Number format construction with pattern %s\n, pat[i]");
+ continue;
+ }
+ lneed= u_strlen(upat) + 1;
+ unum_toPattern(fmt, FALSE, pattern, lneed, &status);
+ log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat, u_austrcpy(tempMsgBug, pattern) );
+ for (v=0; v<val_length; ++v)
+ {
+ /*format*/
+ lneed=0;
+ lneed=unum_formatDouble(fmt, val[v], NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_formatDouble(fmt, val[v], str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+
+
+
+ u_uastrcpy(uvalfor, valFormat[v+ival]);
+ if(u_strcmp(str, uvalfor) != 0)
+ log_verbose("FAIL: Expected %s ( %s )\n", valFormat[v+ival], u_austrcpy(tempMsgBug, uvalfor) );
+
+ /*parsing*/
+ ppos=0;
+ a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status);
+ if (ppos== u_strlen(str)) {
+ if (a != valParse[v+ival])
+ log_err("FAIL: Expected: %e, Got: %g\n", valParse[v+ival], a);
+ }
+ else
+ log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a);
+
+ free(str);
+ }
+ for (v=0; v<lval_length; ++v)
+ {
+ /*format*/
+ lneed=0;
+ lneed=unum_formatDouble(fmt, lval[v], NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_formatDouble(fmt, lval[v], str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/
+ u_uastrcpy(ulvalfor, lvalFormat[v+ilval]);
+ if(u_strcmp(str, ulvalfor) != 0)
+ log_err("FAIL: Expected %s ( %s )\n", valFormat[v+ilval], austrdup(ulvalfor) );
+
+ /*parsing*/
+ ppos=0;
+ a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status);
+ if (ppos== u_strlen(str)) {
+ /*printf(" Parse -> %e\n", a);*/
+ if (a != lvalParse[v+ilval])
+ log_err("FAIL: Expected : %e\n", valParse[v+ival]);
+ }
+ else
+ log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a);
+
+ free(str);
+
+ }
+ ival += val_length;
+ ilval += lval_length;
+ unum_close(fmt);
+ free(upat);
+ }
+}
+
+/**
+ * Test the handling of the currency symbol in patterns.
+ */
+static void TestCurrencySign(void)
+{
+ int32_t lneed;
+ UNumberFormat *fmt;
+ UChar *pattern=NULL;
+ UChar *str=NULL;
+ UChar *pat=NULL;
+ UChar *res=NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ char tempBuf[256];
+
+ pattern=(UChar*)malloc(sizeof(UChar) * (strlen("*#,##0.00;-*#,##0.00") + 1) );
+ u_uastrcpy(pattern, "*#,##0.00;-*#,##0.00");
+ pattern[0]=pattern[11]=0xa4; /* insert latin-1 currency symbol */
+ fmt = unum_open(UNUM_IGNORE,pattern, u_strlen(pattern), "en_US",NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" \n");
+ }
+ lneed=0;
+ lneed=unum_formatDouble(fmt, 1234.56, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_formatDouble(fmt, 1234.56, str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ lneed=0;
+ lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ pat=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_formatDouble(fmt, FALSE, pat, lneed+1, NULL, &status);
+ }
+ log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf, pat));
+ log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf, str) );
+ if(U_SUCCESS(status) && str) {
+ res=(UChar*)malloc(sizeof(UChar) * (strlen("$1,234.56")+1) );
+ u_uastrcpy(res, "$1,234.56");
+ if (u_strcmp(str, res) !=0) log_err("FAIL: Expected $1,234.56\n");
+ } else {
+ log_err("Error formatting\n");
+ }
+ free(str);
+ free(res);
+ free(pat);
+
+ lneed=0;
+ lneed=unum_formatDouble(fmt, -1234.56, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ unum_formatDouble(fmt, -1234.56, str, lneed+1, NULL, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ if(str) {
+ res=(UChar*)malloc(sizeof(UChar) * (strlen("-$1,234.56")+1) );
+ u_uastrcpy(res, "-$1,234.56");
+ if (u_strcmp(str, res) != 0) log_err("FAIL: Expected -$1,234.56\n");
+ free(str);
+ free(res);
+ }
+
+ unum_close(fmt);
+ free(pattern);
+}
+
+/**
+ * Test localized currency patterns.
+ */
+static void TestCurrency(void)
+{
+ UNumberFormat *currencyFmt;
+ UChar *str;
+ int32_t lneed, i;
+ UFieldPosition pos;
+ UChar res[100];
+ UErrorCode status = U_ZERO_ERROR;
+ const char* locale[]={"fr_CA", "de_DE_PREEURO", "fr_FR_PREEURO"};
+ const char* result[]={"1,50 $", "1,50 DM", "1,50 F"};
+ log_verbose("\nTesting the number format with different currency patterns\n");
+ for(i=0; i < 3; i++)
+ {
+ str=NULL;
+ currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status);
+
+ if(U_FAILURE(status)){
+ log_err("Error in the construction of number format with style currency:\n%s\n",
+ myErrorName(status));
+ } else {
+ lneed=0;
+ lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ pos.field = 0;
+ unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status);
+ }
+
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
+ } else {
+ u_charsToUChars(result[i], res, (int32_t)strlen(result[i])+1);
+
+ if (u_strcmp(str, res) != 0){
+ log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i], aescstrdup(str, -1), locale[i]);
+ }
+ }
+ }
+
+ unum_close(currencyFmt);
+ free(str);
+ }
+}
+/**
+ * Test localized currency patterns for PREEURO variants.
+ */
+static void TestCurrencyPreEuro(void)
+{
+ UNumberFormat *currencyFmt;
+ UChar *str=NULL, *res=NULL;
+ int32_t lneed, i;
+ UFieldPosition pos;
+ UErrorCode status = U_ZERO_ERROR;
+
+ const char* locale[]={
+ "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO",
+ "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO",
+ "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO",
+ "nl_NL_PREEURO",
+ };
+
+ const char* result[]={
+ "2 \\u20A7", "2 F", "\\u00A31.50", "1,50\\u00A0mk", "2 F", "\\u20A4 2",
+ "1$50 Esc.", "\\u00F6S 1,50", "1,50\\u0394\\u03C1\\u03C7", "2 \\u20A7", "1,50 FB", "\\u00a31.50",
+ "1,50 BF", "1,50 DM", "1,50 BF", "2 \\u20A7", "1,50 F", "2 \\u20A7",
+ "fl 1,50"
+ };
+
+ log_verbose("\nTesting the number format with different currency patterns\n");
+ for(i=0; i < 19; i++)
+ {
+ char curID[256] = {0};
+ uloc_canonicalize(locale[i], curID, 256, &status);
+ if(U_FAILURE(status)){
+ log_err("Could not canonicalize %s. Error: %s \n", locale[i], u_errorName(status));
+ continue;
+ }
+ currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,curID,NULL, &status);
+
+ if(U_FAILURE(status)){
+ log_err("Error in the construction of number format with style currency:\n%s\n",
+ myErrorName(status));
+ } else {
+ lneed=0;
+ lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status);
+
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ pos.field = 0;
+ unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status);
+ }
+
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
+ } else {
+ res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) );
+ u_unescape(result[i],res,(int32_t)(strlen(result[i])+1));
+
+ if (u_strcmp(str, res) != 0){
+ log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]);
+ }
+ }
+ }
+
+ unum_close(currencyFmt);
+ free(str);
+ free(res);
+ }
+}
+
+/**
+ * Test currency "object" (we use this name to match the other C++
+ * test name and the Jave name). Actually, test ISO currency code
+ * support in the C API.
+ */
+static void TestCurrencyObject(void)
+{
+ UNumberFormat *currencyFmt;
+ UChar *str=NULL, *res=NULL;
+ int32_t lneed, i;
+ UFieldPosition pos;
+ UErrorCode status = U_ZERO_ERROR;
+
+ const char* locale[]={
+ "fr_FR",
+ "fr_FR",
+ };
+
+ const char* currency[]={
+ "",
+ "JPY",
+ };
+
+ const char* result[]={
+ "1\\u00A0234,56 \\u20AC",
+ "1\\u00A0235 \\u00A5JP",
+ };
+
+ log_verbose("\nTesting the number format with different currency codes\n");
+ for(i=0; i < 2; i++)
+ {
+ char cStr[20]={0};
+ UChar isoCode[16]={0};
+ currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("Error in the construction of number format with style currency:\n%s\n",
+ myErrorName(status));
+ } else {
+ if (*currency[i]) {
+ u_uastrcpy(isoCode, currency[i]);
+ unum_setTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
+ isoCode, u_strlen(isoCode), &status);
+
+ if(U_FAILURE(status)) {
+ log_err("FAIL: can't set currency code %s\n", myErrorName(status) );
+ }
+ }
+
+ unum_getTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
+ isoCode, sizeof(isoCode), &status);
+
+ if(U_FAILURE(status)) {
+ log_err("FAIL: can't get currency code %s\n", myErrorName(status) );
+ }
+
+ u_UCharsToChars(isoCode,cStr,u_strlen(isoCode));
+ log_verbose("ISO code %s\n", cStr);
+ if (*currency[i] && uprv_strcmp(cStr, currency[i])) {
+ log_err("FAIL: currency should be %s, but is %s\n", currency[i], cStr);
+ }
+
+ lneed=0;
+ lneed= unum_formatDouble(currencyFmt, 1234.56, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ pos.field = 0;
+ unum_formatDouble(currencyFmt, 1234.56, str, lneed+1, &pos, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
+ } else {
+ res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) );
+ u_unescape(result[i],res, (int32_t)(strlen(result[i])+1));
+ if (u_strcmp(str, res) != 0){
+ log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]);
+ }
+ }
+ }
+
+ unum_close(currencyFmt);
+ free(str);
+ free(res);
+ }
+}
+
+/**
+ * Test proper rounding by the format method.
+ */
+static void TestRounding487(void)
+{
+ UNumberFormat *nnf;
+ UErrorCode status = U_ZERO_ERROR;
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
+ nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status);
+
+ if(U_FAILURE(status)){
+ log_err("FAIL: failure in the construction of number format: %s\n", myErrorName(status));
+ } else {
+ roundingTest(nnf, 0.00159999, 4, "0.0016");
+ roundingTest(nnf, 0.00995, 4, "0.01");
+
+ roundingTest(nnf, 12.3995, 3, "12.4");
+
+ roundingTest(nnf, 12.4999, 0, "12");
+ roundingTest(nnf, - 19.5, 0, "-20");
+ }
+
+ unum_close(nnf);
+}
+
+/*-------------------------------------*/
+
+static void roundingTest(UNumberFormat* nf, double x, int32_t maxFractionDigits, const char* expected)
+{
+ UChar *out = NULL;
+ UChar *res;
+ UFieldPosition pos;
+ UErrorCode status;
+ int32_t lneed;
+ status=U_ZERO_ERROR;
+ unum_setAttribute(nf, UNUM_MAX_FRACTION_DIGITS, maxFractionDigits);
+ lneed=0;
+ lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ out=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ pos.field=0;
+ unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
+ }
+ /*Need to use log_verbose here. Problem with the float*/
+ /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
+ res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) );
+ u_uastrcpy(res, expected);
+ if (u_strcmp(out, res) != 0)
+ log_err("FAIL: Expected: %s or %s\n", expected, austrdup(res) );
+ free(res);
+ if(out != NULL) {
+ free(out);
+ }
+}
+
+/*
+ * Testing unum_getDoubleAttribute and unum_setDoubleAttribute()
+ */
+static void TestDoubleAttribute(void)
+{
+ double mydata[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
+ double dvalue;
+ int i;
+ UErrorCode status=U_ZERO_ERROR;
+ UNumberFormatAttribute attr;
+ UNumberFormatStyle style= UNUM_DEFAULT;
+ UNumberFormat *def;
+
+ log_verbose("\nTesting get and set DoubleAttributes\n");
+ def=unum_open(style, NULL,0,NULL,NULL, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Fail: error creating a default number formatter\n");
+ } else {
+ attr=UNUM_ROUNDING_INCREMENT;
+ dvalue=unum_getDoubleAttribute(def, attr);
+ for (i = 0; i<9 ; i++)
+ {
+ dvalue = mydata[i];
+ unum_setDoubleAttribute(def, attr, dvalue);
+ if(unum_getDoubleAttribute(def,attr)!=mydata[i])
+ log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n");
+ else
+ log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
+ }
+ }
+
+ unum_close(def);
+}
+
+/**
+ * Test the functioning of the secondary grouping value.
+ */
+static void TestSecondaryGrouping(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UNumberFormat *f = NULL, *g= NULL;
+ UNumberFormat *us = unum_open(UNUM_DECIMAL,NULL,0, "en_US", NULL,&status);
+ UFieldPosition pos;
+ UChar resultBuffer[512];
+ int32_t l = 1876543210L;
+ UBool ok = TRUE;
+ UChar buffer[512];
+ int32_t i;
+ UBool expectGroup = FALSE, isGroup = FALSE;
+
+ u_uastrcpy(buffer, "#,##,###");
+ f = unum_open(UNUM_IGNORE,buffer, -1, "en_US",NULL, &status);
+ CHECK(status, "DecimalFormat ct");
+
+ pos.field = 0;
+ unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status);
+ u_uastrcpy(buffer, "12,34,56,789");
+ if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
+ {
+ log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,34,56,789");
+ }
+ if (pos.beginIndex != 0 && pos.endIndex != 12) {
+ log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos.beginIndex, pos.endIndex);
+ }
+ memset(resultBuffer,0, sizeof(UChar)*512);
+ unum_toPattern(f, FALSE, resultBuffer, 512, &status);
+ u_uastrcpy(buffer, "#,##,###");
+ if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
+ {
+ log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,##,###");
+ }
+ memset(resultBuffer,0, sizeof(UChar)*512);
+ u_uastrcpy(buffer, "#,###");
+ unum_applyPattern(f, FALSE, buffer, -1,NULL,NULL);
+ if (U_FAILURE(status))
+ {
+ log_err("Fail: applyPattern call failed\n");
+ }
+ unum_setAttribute(f, UNUM_SECONDARY_GROUPING_SIZE, 4);
+ unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status);
+ u_uastrcpy(buffer, "12,3456,789");
+ if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
+ {
+ log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,3456,789");
+ }
+ memset(resultBuffer,0, sizeof(UChar)*512);
+ unum_toPattern(f, FALSE, resultBuffer, 512, &status);
+ u_uastrcpy(buffer, "#,####,###");
+ if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
+ {
+ log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,####,###");
+ }
+ memset(resultBuffer,0, sizeof(UChar)*512);
+ g = unum_open(UNUM_DECIMAL, NULL,0,"hi_IN",NULL, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
+ }
+
+ unum_format(g, l, resultBuffer, 512, &pos, &status);
+ unum_close(g);
+ /* expect "1,87,65,43,210", but with Hindi digits */
+ /* 01234567890123 */
+ if (u_strlen(resultBuffer) != 14) {
+ ok = FALSE;
+ } else {
+ for (i=0; i<u_strlen(resultBuffer); ++i) {
+ expectGroup = FALSE;
+ switch (i) {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ expectGroup = TRUE;
+ break;
+ }
+ /* Later -- fix this to get the actual grouping */
+ /* character from the resource bundle. */
+ isGroup = (UBool)(resultBuffer[i] == 0x002C);
+ if (isGroup != expectGroup) {
+ ok = FALSE;
+ break;
+ }
+ }
+ }
+ if (!ok) {
+ log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer);
+ }
+ unum_close(f);
+ unum_close(us);
+}
+
+static void TestCurrencyKeywords(void)
+{
+ static const char * const currencies[] = {
+ "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD",
+ "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS",
+ "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF",
+ "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND",
+ "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ",
+ "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD",
+ "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF",
+ "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK",
+ "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK",
+ "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB",
+ "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF",
+ "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP",
+ "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF",
+ "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP",
+ "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD",
+ "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO",
+ "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR",
+ "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF",
+ "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL",
+ "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP",
+ "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP",
+ "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG",
+ "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN",
+ "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP",
+ "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR",
+ "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK",
+ "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC",
+ "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS",
+ "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS",
+ "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD",
+ "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST",
+ "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR",
+ "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS",
+ "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR",
+ "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD"
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t i = 0, j = 0;
+ int32_t noLocales = uloc_countAvailable();
+ char locale[256];
+ char currLoc[256];
+ UChar result[4];
+ UChar currBuffer[256];
+
+
+ for(i = 0; i < noLocales; i++) {
+ strcpy(currLoc, uloc_getAvailable(i));
+ for(j = 0; j < sizeof(currencies)/sizeof(currencies[0]); j++) {
+ strcpy(locale, currLoc);
+ strcat(locale, "@currency=");
+ strcat(locale, currencies[j]);
+ ucurr_forLocale(locale, result, 4, &status);
+ u_charsToUChars(currencies[j], currBuffer, 3);
+ currBuffer[3] = 0;
+ if(u_strcmp(currBuffer, result) != 0) {
+ log_err("Didn't get the right currency for %s\n", locale);
+ }
+ }
+
+ }
+}
+
+/**
+ * Test proper handling of rounding modes.
+ */
+static void TestRounding5350(void)
+{
+ UNumberFormat *nnf;
+ UErrorCode status = U_ZERO_ERROR;
+ /* this is supposed to open default date format, but later on it treats it like it is "en_US"
+ - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
+ /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
+ nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status);
+
+ if(U_FAILURE(status)){
+ log_err("FAIL: failure in the construction of number format: %s\n", myErrorName(status));
+ return;
+ }
+
+ unum_setAttribute(nnf, UNUM_MAX_FRACTION_DIGITS, 2);
+ roundingTest2(nnf, -0.125, UNUM_ROUND_CEILING, "-0.12");
+ roundingTest2(nnf, -0.125, UNUM_ROUND_FLOOR, "-0.13");
+ roundingTest2(nnf, -0.125, UNUM_ROUND_DOWN, "-0.12");
+ roundingTest2(nnf, -0.125, UNUM_ROUND_UP, "-0.13");
+ roundingTest2(nnf, 0.125, UNUM_FOUND_HALFEVEN, "0.12");
+ roundingTest2(nnf, 0.135, UNUM_ROUND_HALFDOWN, "0.13");
+ roundingTest2(nnf, 0.125, UNUM_ROUND_HALFUP, "0.13");
+ roundingTest2(nnf, 0.135, UNUM_FOUND_HALFEVEN, "0.14");
+ /* The following are exactly represented, and shouldn't round */
+ roundingTest2(nnf, 1.00, UNUM_ROUND_UP, "1");
+ roundingTest2(nnf, 24.25, UNUM_ROUND_UP, "24.25");
+ roundingTest2(nnf, 24.25, UNUM_ROUND_CEILING, "24.25");
+ roundingTest2(nnf, -24.25, UNUM_ROUND_UP, "-24.25");
+
+ /* Differences pretty far out there */
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_CEILING, "1.01");
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_FLOOR, "1");
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_DOWN, "1");
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_UP, "1.01");
+ roundingTest2(nnf, 1.0000001, UNUM_FOUND_HALFEVEN, "1");
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFDOWN, "1");
+ roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFUP, "1");
+
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_CEILING, "-1");
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_FLOOR, "-1.01");
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_DOWN, "-1");
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_UP, "-1.01");
+ roundingTest2(nnf, -1.0000001, UNUM_FOUND_HALFEVEN, "-1");
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFDOWN, "-1");
+ roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFUP, "-1");
+
+ unum_close(nnf);
+}
+
+/*-------------------------------------*/
+
+static void roundingTest2(UNumberFormat* nf, double x, int32_t roundingMode, const char* expected)
+{
+ UChar *out = NULL;
+ UChar *res;
+ UFieldPosition pos;
+ UErrorCode status;
+ int32_t lneed;
+ status=U_ZERO_ERROR;
+ unum_setAttribute(nf, UNUM_ROUNDING_MODE, roundingMode);
+ lneed=0;
+ lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ out=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
+ pos.field=0;
+ unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
+ }
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
+ }
+ /*Need to use log_verbose here. Problem with the float*/
+ /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
+ res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) );
+ u_uastrcpy(res, expected);
+ if (u_strcmp(out, res) != 0)
+ log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected, austrdup(out) );
+ free(res);
+ if(out != NULL) {
+ free(out);
+ }
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h
new file mode 100644
index 00000000000..c437490fabf
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnmdptst.h
@@ -0,0 +1,60 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2003, 2007 International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CNMDPTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* C DEPTH TEST FOR NUMBER FORMAT */
+
+#ifndef _CNUMDEPTST
+#define _CNUMDEPTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+/* The function used to test differnet format patterns*/
+static void TestPatterns(void);
+
+/* Test the handling of quotes*/
+static void TestQuotes(void);
+
+/* Test patterns with exponential representation*/
+static void TestExponential(void);
+
+/* Test the handling of the currency symbol in patterns. */
+static void TestCurrencySign(void);
+
+/* Test proper rounding by the format method.*/
+static void TestRounding487(void);
+
+/* Test proper handling of rounding modes. */
+static void TestRounding5350(void);
+
+/* Test localized currency patterns. */
+static void TestCurrency(void);
+
+/* Test getDoubleAttribute and getDoubleAttribute */
+static void TestDoubleAttribute(void);
+
+static void TestSecondaryGrouping(void);
+
+/*Internal functions used*/
+static void roundingTest(UNumberFormat*, double, int32_t, const char*);
+static void roundingTest2(UNumberFormat*, double, int32_t, const char*);
+
+static void TestCurrencyKeywords(void);
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c
new file mode 100644
index 00000000000..99e6540386a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.c
@@ -0,0 +1,1517 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CNORMTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+* synwee added test for quick check
+* synwee added test for checkFCD
+*********************************************************************************/
+/*tests for u_normalization*/
+#include "unicode/utypes.h"
+#include "unicode/unorm.h"
+#include "unormimp.h"
+#include "cintltst.h"
+
+#if UCONFIG_NO_NORMALIZATION
+
+void addNormTest(TestNode** root) {
+ /* no normalization - nothing to do */
+}
+
+#else
+
+#include <stdlib.h>
+#include <time.h>
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+#include "unicode/unorm.h"
+#include "cnormtst.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof ((array)[0]))
+
+static void
+TestAPI(void);
+
+static void
+TestNormCoverage(void);
+
+static void
+TestConcatenate(void);
+
+static void
+TestNextPrevious(void);
+
+static void TestIsNormalized(void);
+
+static void
+TestFCNFKCClosure(void);
+
+static void
+TestQuickCheckPerCP(void);
+
+static void
+TestComposition(void);
+
+const static char* canonTests[][3] = {
+ /* Input*/ /*Decomposed*/ /*Composed*/
+ { "cat", "cat", "cat" },
+ { "\\u00e0ardvark", "a\\u0300ardvark", "\\u00e0ardvark", },
+
+ { "\\u1e0a", "D\\u0307", "\\u1e0a" }, /* D-dot_above*/
+ { "D\\u0307", "D\\u0307", "\\u1e0a" }, /* D dot_above*/
+
+ { "\\u1e0c\\u0307", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_below dot_above*/
+ { "\\u1e0a\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D-dot_above dot_below */
+ { "D\\u0307\\u0323", "D\\u0323\\u0307", "\\u1e0c\\u0307" }, /* D dot_below dot_above */
+
+ { "\\u1e10\\u0307\\u0323", "D\\u0327\\u0323\\u0307", "\\u1e10\\u0323\\u0307" }, /*D dot_below cedilla dot_above*/
+ { "D\\u0307\\u0328\\u0323", "D\\u0328\\u0323\\u0307", "\\u1e0c\\u0328\\u0307" }, /* D dot_above ogonek dot_below*/
+
+ { "\\u1E14", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron-grave*/
+ { "\\u0112\\u0300", "E\\u0304\\u0300", "\\u1E14" }, /* E-macron + grave*/
+ { "\\u00c8\\u0304", "E\\u0300\\u0304", "\\u00c8\\u0304" }, /* E-grave + macron*/
+
+ { "\\u212b", "A\\u030a", "\\u00c5" }, /* angstrom_sign*/
+ { "\\u00c5", "A\\u030a", "\\u00c5" }, /* A-ring*/
+
+ { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" },
+ { "\\u00C4\\uFB03n", "A\\u0308\\uFB03n", "\\u00C4\\uFB03n" },
+
+ { "Henry IV", "Henry IV", "Henry IV" },
+ { "Henry \\u2163", "Henry \\u2163", "Henry \\u2163" },
+
+ { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/
+ { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/
+ { "\\uFF76\\uFF9E", "\\uFF76\\uFF9E", "\\uFF76\\uFF9E" }, /* hw_ka + hw_ten*/
+ { "\\u30AB\\uFF9E", "\\u30AB\\uFF9E", "\\u30AB\\uFF9E" }, /* ka + hw_ten*/
+ { "\\uFF76\\u3099", "\\uFF76\\u3099", "\\uFF76\\u3099" }, /* hw_ka + ten*/
+ { "A\\u0300\\u0316", "A\\u0316\\u0300", "\\u00C0\\u0316" } /* hw_ka + ten*/
+};
+
+const static char* compatTests[][3] = {
+ /* Input*/ /*Decomposed */ /*Composed*/
+ { "cat", "cat", "cat" },
+
+ { "\\uFB4f", "\\u05D0\\u05DC", "\\u05D0\\u05DC" }, /* Alef-Lamed vs. Alef, Lamed*/
+
+ { "\\u00C4ffin", "A\\u0308ffin", "\\u00C4ffin" },
+ { "\\u00C4\\uFB03n", "A\\u0308ffin", "\\u00C4ffin" }, /* ffi ligature -> f + f + i*/
+
+ { "Henry IV", "Henry IV", "Henry IV" },
+ { "Henry \\u2163", "Henry IV", "Henry IV" },
+
+ { "\\u30AC", "\\u30AB\\u3099", "\\u30AC" }, /* ga (Katakana)*/
+ { "\\u30AB\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /*ka + ten*/
+
+ { "\\uFF76\\u3099", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + ten*/
+
+ /*These two are broken in Unicode 2.1.2 but fixed in 2.1.5 and later*/
+ { "\\uFF76\\uFF9E", "\\u30AB\\u3099", "\\u30AC" }, /* hw_ka + hw_ten*/
+ { "\\u30AB\\uFF9E", "\\u30AB\\u3099", "\\u30AC" } /* ka + hw_ten*/
+
+};
+
+void addNormTest(TestNode** root);
+
+void addNormTest(TestNode** root)
+{
+ addTest(root, &TestAPI, "tscoll/cnormtst/TestAPI");
+ addTest(root, &TestDecomp, "tscoll/cnormtst/TestDecomp");
+ addTest(root, &TestCompatDecomp, "tscoll/cnormtst/TestCompatDecomp");
+ addTest(root, &TestCanonDecompCompose, "tscoll/cnormtst/TestCanonDecompCompose");
+ addTest(root, &TestCompatDecompCompose, "tscoll/cnormtst/CompatDecompCompose");
+ addTest(root, &TestNull, "tscoll/cnormtst/TestNull");
+ addTest(root, &TestQuickCheck, "tscoll/cnormtst/TestQuickCheck");
+ addTest(root, &TestQuickCheckPerCP, "tscoll/cnormtst/TestQuickCheckPerCP");
+ addTest(root, &TestIsNormalized, "tscoll/cnormtst/TestIsNormalized");
+ addTest(root, &TestCheckFCD, "tscoll/cnormtst/TestCheckFCD");
+ addTest(root, &TestNormCoverage, "tscoll/cnormtst/TestNormCoverage");
+ addTest(root, &TestConcatenate, "tscoll/cnormtst/TestConcatenate");
+ addTest(root, &TestNextPrevious, "tscoll/cnormtst/TestNextPrevious");
+ addTest(root, &TestFCNFKCClosure, "tscoll/cnormtst/TestFCNFKCClosure");
+ addTest(root, &TestComposition, "tscoll/cnormtst/TestComposition");
+}
+
+void TestDecomp()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t x, neededLen, resLen;
+ UChar *source=NULL, *result=NULL;
+ status = U_ZERO_ERROR;
+ resLen=0;
+ log_verbose("Testing unorm_normalize with Decomp canonical\n");
+ for(x=0; x < LENGTHOF(canonTests); x++)
+ {
+ source=CharsToUChars(canonTests[x][0]);
+ neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resLen=neededLen+1;
+ result=(UChar*)malloc(sizeof(UChar*) * resLen);
+ unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, result, resLen, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) );
+ } else {
+ assertEqual(result, canonTests[x][1], x);
+ }
+ free(result);
+ free(source);
+ }
+}
+
+void TestCompatDecomp()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t x, neededLen, resLen;
+ UChar *source=NULL, *result=NULL;
+ status = U_ZERO_ERROR;
+ resLen=0;
+ log_verbose("Testing unorm_normalize with Decomp compat\n");
+ for(x=0; x < LENGTHOF(compatTests); x++)
+ {
+ source=CharsToUChars(compatTests[x][0]);
+ neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resLen=neededLen+1;
+ result=(UChar*)malloc(sizeof(UChar*) * resLen);
+ unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, result, resLen, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) );
+ } else {
+ assertEqual(result, compatTests[x][1], x);
+ }
+ free(result);
+ free(source);
+ }
+}
+
+void TestCanonDecompCompose()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t x, neededLen, resLen;
+ UChar *source=NULL, *result=NULL;
+ status = U_ZERO_ERROR;
+ resLen=0;
+ log_verbose("Testing unorm_normalize with Decomp can compose compat\n");
+ for(x=0; x < LENGTHOF(canonTests); x++)
+ {
+ source=CharsToUChars(canonTests[x][0]);
+ neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resLen=neededLen+1;
+ result=(UChar*)malloc(sizeof(UChar*) * resLen);
+ unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, result, resLen, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source),myErrorName(status) );
+ } else {
+ assertEqual(result, canonTests[x][2], x);
+ }
+ free(result);
+ free(source);
+ }
+}
+
+void TestCompatDecompCompose()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t x, neededLen, resLen;
+ UChar *source=NULL, *result=NULL;
+ status = U_ZERO_ERROR;
+ resLen=0;
+ log_verbose("Testing unorm_normalize with compat decomp compose can\n");
+ for(x=0; x < LENGTHOF(compatTests); x++)
+ {
+ source=CharsToUChars(compatTests[x][0]);
+ neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, NULL, 0, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resLen=neededLen+1;
+ result=(UChar*)malloc(sizeof(UChar*) * resLen);
+ unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, result, resLen, &status);
+ }
+ if(U_FAILURE(status)){
+ log_err("ERROR in unorm_normalize at %s: %s\n", austrdup(source), myErrorName(status) );
+ } else {
+ assertEqual(result, compatTests[x][2], x);
+ }
+ free(result);
+ free(source);
+ }
+}
+
+
+/*
+static void assertEqual(const UChar* result, const UChar* expected, int32_t index)
+{
+ if(u_strcmp(result, expected)!=0){
+ log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, austrdup(expected),
+ austrdup(result) );
+ }
+}
+*/
+
+static void assertEqual(const UChar* result, const char* expected, int32_t index)
+{
+ UChar *expectedUni = CharsToUChars(expected);
+ if(u_strcmp(result, expectedUni)!=0){
+ log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, expected,
+ austrdup(result) );
+ }
+ free(expectedUni);
+}
+
+static void TestNull_check(UChar *src, int32_t srcLen,
+ UChar *exp, int32_t expLen,
+ UNormalizationMode mode,
+ const char *name)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len, i;
+
+ UChar result[50];
+
+
+ status = U_ZERO_ERROR;
+
+ for(i=0;i<50;i++)
+ {
+ result[i] = 0xFFFD;
+ }
+
+ len = unorm_normalize(src, srcLen, mode, 0, result, 50, &status);
+
+ if(U_FAILURE(status)) {
+ log_err("unorm_normalize(%s) with 0x0000 failed: %s\n", name, u_errorName(status));
+ } else if (len != expLen) {
+ log_err("unorm_normalize(%s) with 0x0000 failed: Expected len %d, got %d\n", name, expLen, len);
+ }
+
+ {
+ for(i=0;i<len;i++){
+ if(exp[i] != result[i]) {
+ log_err("unorm_normalize(%s): @%d, expected \\u%04X got \\u%04X\n",
+ name,
+ i,
+ exp[i],
+ result[i]);
+ return;
+ }
+ log_verbose(" %d: \\u%04X\n", i, result[i]);
+ }
+ }
+
+ log_verbose("unorm_normalize(%s) with 0x0000: OK\n", name);
+}
+
+void TestNull()
+{
+
+ UChar source_comp[] = { 0x0061, 0x0000, 0x0044, 0x0307 };
+ int32_t source_comp_len = 4;
+ UChar expect_comp[] = { 0x0061, 0x0000, 0x1e0a };
+ int32_t expect_comp_len = 3;
+
+ UChar source_dcmp[] = { 0x1e0A, 0x0000, 0x0929 };
+ int32_t source_dcmp_len = 3;
+ UChar expect_dcmp[] = { 0x0044, 0x0307, 0x0000, 0x0928, 0x093C };
+ int32_t expect_dcmp_len = 5;
+
+ TestNull_check(source_comp,
+ source_comp_len,
+ expect_comp,
+ expect_comp_len,
+ UNORM_NFC,
+ "UNORM_NFC");
+
+ TestNull_check(source_dcmp,
+ source_dcmp_len,
+ expect_dcmp,
+ expect_dcmp_len,
+ UNORM_NFD,
+ "UNORM_NFD");
+
+ TestNull_check(source_comp,
+ source_comp_len,
+ expect_comp,
+ expect_comp_len,
+ UNORM_NFKC,
+ "UNORM_NFKC");
+
+
+}
+
+static void TestQuickCheckResultNO()
+{
+ const UChar CPNFD[] = {0x00C5, 0x0407, 0x1E00, 0x1F57, 0x220C,
+ 0x30AE, 0xAC00, 0xD7A3, 0xFB36, 0xFB4E};
+ const UChar CPNFC[] = {0x0340, 0x0F93, 0x1F77, 0x1FBB, 0x1FEB,
+ 0x2000, 0x232A, 0xF900, 0xFA1E, 0xFB4E};
+ const UChar CPNFKD[] = {0x00A0, 0x02E4, 0x1FDB, 0x24EA, 0x32FE,
+ 0xAC00, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D};
+ const UChar CPNFKC[] = {0x00A0, 0x017F, 0x2000, 0x24EA, 0x32FE,
+ 0x33FE, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D};
+
+
+ const int SIZE = 10;
+
+ int count = 0;
+ UErrorCode error = U_ZERO_ERROR;
+
+ for (; count < SIZE; count ++)
+ {
+ if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) !=
+ UNORM_NO)
+ {
+ log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) !=
+ UNORM_NO)
+ {
+ log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) !=
+ UNORM_NO)
+ {
+ log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
+ UNORM_NO)
+ {
+ log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
+ return;
+ }
+ }
+}
+
+
+static void TestQuickCheckResultYES()
+{
+ const UChar CPNFD[] = {0x00C6, 0x017F, 0x0F74, 0x1000, 0x1E9A,
+ 0x2261, 0x3075, 0x4000, 0x5000, 0xF000};
+ const UChar CPNFC[] = {0x0400, 0x0540, 0x0901, 0x1000, 0x1500,
+ 0x1E9A, 0x3000, 0x4000, 0x5000, 0xF000};
+ const UChar CPNFKD[] = {0x00AB, 0x02A0, 0x1000, 0x1027, 0x2FFB,
+ 0x3FFF, 0x4FFF, 0xA000, 0xF000, 0xFA27};
+ const UChar CPNFKC[] = {0x00B0, 0x0100, 0x0200, 0x0A02, 0x1000,
+ 0x2010, 0x3030, 0x4000, 0xA000, 0xFA0E};
+
+ const int SIZE = 10;
+ int count = 0;
+ UErrorCode error = U_ZERO_ERROR;
+
+ UChar cp = 0;
+ while (cp < 0xA0)
+ {
+ if (unorm_quickCheck(&cp, 1, UNORM_NFD, &error) != UNORM_YES)
+ {
+ log_err("ERROR in NFD quick check at U+%04x\n", cp);
+ return;
+ }
+ if (unorm_quickCheck(&cp, 1, UNORM_NFC, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFC quick check at U+%04x\n", cp);
+ return;
+ }
+ if (unorm_quickCheck(&cp, 1, UNORM_NFKD, &error) != UNORM_YES)
+ {
+ log_err("ERROR in NFKD quick check at U+%04x\n", cp);
+ return;
+ }
+ if (unorm_quickCheck(&cp, 1, UNORM_NFKC, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFKC quick check at U+%04x\n", cp);
+ return;
+ }
+ cp ++;
+ }
+
+ for (; count < SIZE; count ++)
+ {
+ if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error)
+ != UNORM_YES)
+ {
+ log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
+ return;
+ }
+ }
+}
+
+static void TestQuickCheckResultMAYBE()
+{
+ const UChar CPNFC[] = {0x0306, 0x0654, 0x0BBE, 0x102E, 0x1161,
+ 0x116A, 0x1173, 0x1175, 0x3099, 0x309A};
+ const UChar CPNFKC[] = {0x0300, 0x0654, 0x0655, 0x09D7, 0x0B3E,
+ 0x0DCF, 0xDDF, 0x102E, 0x11A8, 0x3099};
+
+
+ const int SIZE = 10;
+
+ int count = 0;
+ UErrorCode error = U_ZERO_ERROR;
+
+ /* NFD and NFKD does not have any MAYBE codepoints */
+ for (; count < SIZE; count ++)
+ {
+ if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) !=
+ UNORM_MAYBE)
+ {
+ log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]);
+ return;
+ }
+ if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
+ UNORM_MAYBE)
+ {
+ log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
+ return;
+ }
+ }
+}
+
+static void TestQuickCheckStringResult()
+{
+ int count;
+ UChar *d = NULL;
+ UChar *c = NULL;
+ UErrorCode error = U_ZERO_ERROR;
+
+ for (count = 0; count < LENGTHOF(canonTests); count ++)
+ {
+ d = CharsToUChars(canonTests[count][1]);
+ c = CharsToUChars(canonTests[count][2]);
+ if (unorm_quickCheck(d, u_strlen(d), UNORM_NFD, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFD quick check for string at count %d\n", count);
+ return;
+ }
+
+ if (unorm_quickCheck(c, u_strlen(c), UNORM_NFC, &error) ==
+ UNORM_NO)
+ {
+ log_err("ERROR in NFC quick check for string at count %d\n", count);
+ return;
+ }
+
+ free(d);
+ free(c);
+ }
+
+ for (count = 0; count < LENGTHOF(compatTests); count ++)
+ {
+ d = CharsToUChars(compatTests[count][1]);
+ c = CharsToUChars(compatTests[count][2]);
+ if (unorm_quickCheck(d, u_strlen(d), UNORM_NFKD, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFKD quick check for string at count %d\n", count);
+ return;
+ }
+
+ if (unorm_quickCheck(c, u_strlen(c), UNORM_NFKC, &error) !=
+ UNORM_YES)
+ {
+ log_err("ERROR in NFKC quick check for string at count %d\n", count);
+ return;
+ }
+
+ free(d);
+ free(c);
+ }
+}
+
+void TestQuickCheck()
+{
+ TestQuickCheckResultNO();
+ TestQuickCheckResultYES();
+ TestQuickCheckResultMAYBE();
+ TestQuickCheckStringResult();
+}
+
+/*
+ * The intltest/NormalizerConformanceTest tests a lot of strings that _are_
+ * normalized, and some that are not.
+ * Here we pick some specific cases and test the C API.
+ */
+static void TestIsNormalized(void) {
+ static const UChar notNFC[][8]={ /* strings that are not in NFC */
+ { 0x62, 0x61, 0x300, 0x63, 0 }, /* 0061 0300 compose */
+ { 0xfb1d, 0 }, /* excluded from composition */
+ { 0x0627, 0x0653, 0 }, /* 0627 0653 compose */
+ { 0x3071, 0x306f, 0x309a, 0x3073, 0 } /* 306F 309A compose */
+ };
+ static const UChar notNFKC[][8]={ /* strings that are not in NFKC */
+ { 0x1100, 0x1161, 0 }, /* Jamo compose */
+ { 0x1100, 0x314f, 0 }, /* compatibility Jamo compose */
+ { 0x03b1, 0x1f00, 0x0345, 0x03b3, 0 } /* 1F00 0345 compose */
+ };
+
+ int32_t i;
+ UErrorCode errorCode;
+
+ /* API test */
+
+ /* normal case with length>=0 (length -1 used for special cases below) */
+ errorCode=U_ZERO_ERROR;
+ if(!unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error: !isNormalized(<U+0300>, NFC) (%s)\n", u_errorName(errorCode));
+ }
+
+ /* incoming U_FAILURE */
+ errorCode=U_TRUNCATED_CHAR_FOUND;
+ (void)unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode);
+ if(errorCode!=U_TRUNCATED_CHAR_FOUND) {
+ log_err("error: isNormalized(U_TRUNCATED_CHAR_FOUND) changed the error code to %s\n", u_errorName(errorCode));
+ }
+
+ /* NULL source */
+ errorCode=U_ZERO_ERROR;
+ (void)unorm_isNormalized(NULL, 1, UNORM_NFC, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error: isNormalized(NULL) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode));
+ }
+
+ /* bad length */
+ errorCode=U_ZERO_ERROR;
+ (void)unorm_isNormalized(notNFC[0]+2, -2, UNORM_NFC, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error: isNormalized([-2]) did not set U_ILLEGAL_ARGUMENT_ERROR but %s\n", u_errorName(errorCode));
+ }
+
+ /* specific cases */
+ for(i=0; i<LENGTHOF(notNFC); ++i) {
+ errorCode=U_ZERO_ERROR;
+ if(unorm_isNormalized(notNFC[i], -1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error: isNormalized(notNFC[%d], NFC) is wrong (%s)\n", i, u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ if(unorm_isNormalized(notNFC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error: isNormalized(notNFC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode));
+ }
+ }
+ for(i=0; i<LENGTHOF(notNFKC); ++i) {
+ errorCode=U_ZERO_ERROR;
+ if(unorm_isNormalized(notNFKC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error: isNormalized(notNFKC[%d], NFKC) is wrong (%s)\n", i, u_errorName(errorCode));
+ }
+ }
+}
+
+void TestCheckFCD()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ static const UChar FAST_[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0A};
+ static const UChar FALSE_[] = {0x0001, 0x0002, 0x02EA, 0x03EB, 0x0300, 0x0301,
+ 0x02B9, 0x0314, 0x0315, 0x0316};
+ static const UChar TRUE_[] = {0x0030, 0x0040, 0x0440, 0x056D, 0x064F, 0x06E7,
+ 0x0050, 0x0730, 0x09EE, 0x1E10};
+
+ static const UChar datastr[][5] =
+ { {0x0061, 0x030A, 0x1E05, 0x0302, 0},
+ {0x0061, 0x030A, 0x00E2, 0x0323, 0},
+ {0x0061, 0x0323, 0x00E2, 0x0323, 0},
+ {0x0061, 0x0323, 0x1E05, 0x0302, 0} };
+ static const UBool result[] = {UNORM_YES, UNORM_NO, UNORM_NO, UNORM_YES};
+
+ static const UChar datachar[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea,
+ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306,
+ 0x0307, 0x0308, 0x0309, 0x030a,
+ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326,
+ 0x0327, 0x0328, 0x0329, 0x032a,
+ 0x1e00, 0x1e01, 0x1e02, 0x1e03, 0x1e04, 0x1e05, 0x1e06,
+ 0x1e07, 0x1e08, 0x1e09, 0x1e0a};
+
+ int count = 0;
+
+ if (unorm_quickCheck(FAST_, 10, UNORM_FCD, &status) != UNORM_YES)
+ log_err("unorm_quickCheck(FCD) failed: expected value for fast unorm_quickCheck is UNORM_YES\n");
+ if (unorm_quickCheck(FALSE_, 10, UNORM_FCD, &status) != UNORM_NO)
+ log_err("unorm_quickCheck(FCD) failed: expected value for error unorm_quickCheck is UNORM_NO\n");
+ if (unorm_quickCheck(TRUE_, 10, UNORM_FCD, &status) != UNORM_YES)
+ log_err("unorm_quickCheck(FCD) failed: expected value for correct unorm_quickCheck is UNORM_YES\n");
+
+ if (U_FAILURE(status))
+ log_err("unorm_quickCheck(FCD) failed: %s\n", u_errorName(status));
+
+ while (count < 4)
+ {
+ UBool fcdresult = unorm_quickCheck(datastr[count], 4, UNORM_FCD, &status);
+ if (U_FAILURE(status)) {
+ log_err("unorm_quickCheck(FCD) failed: exception occured at data set %d\n", count);
+ break;
+ }
+ else {
+ if (result[count] != fcdresult) {
+ log_err("unorm_quickCheck(FCD) failed: Data set %d expected value %d\n", count,
+ result[count]);
+ }
+ }
+ count ++;
+ }
+
+ /* random checks of long strings */
+ status = U_ZERO_ERROR;
+ srand((unsigned)time( NULL ));
+
+ for (count = 0; count < 50; count ++)
+ {
+ int size = 0;
+ UBool testresult = UNORM_YES;
+ UChar data[20];
+ UChar norm[100];
+ UChar nfd[100];
+ int normsize = 0;
+ int nfdsize = 0;
+
+ while (size != 19) {
+ data[size] = datachar[(rand() * 50) / RAND_MAX];
+ log_verbose("0x%x", data[size]);
+ normsize += unorm_normalize(data + size, 1, UNORM_NFD, 0,
+ norm + normsize, 100 - normsize, &status);
+ if (U_FAILURE(status)) {
+ log_err("unorm_quickCheck(FCD) failed: exception occured at data generation\n");
+ break;
+ }
+ size ++;
+ }
+ log_verbose("\n");
+
+ nfdsize = unorm_normalize(data, size, UNORM_NFD, 0,
+ nfd, 100, &status);
+ if (U_FAILURE(status)) {
+ log_err("unorm_quickCheck(FCD) failed: exception occured at normalized data generation\n");
+ }
+
+ if (nfdsize != normsize || u_memcmp(nfd, norm, nfdsize) != 0) {
+ testresult = UNORM_NO;
+ }
+ if (testresult == UNORM_YES) {
+ log_verbose("result UNORM_YES\n");
+ }
+ else {
+ log_verbose("result UNORM_NO\n");
+ }
+
+ if (unorm_quickCheck(data, size, UNORM_FCD, &status) != testresult || U_FAILURE(status)) {
+ log_err("unorm_quickCheck(FCD) failed: expected %d for random data\n", testresult);
+ }
+ }
+}
+
+static void
+TestAPI() {
+ static const UChar in[]={ 0x68, 0xe4 };
+ UChar out[20]={ 0xffff, 0xffff, 0xffff, 0xffff };
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* try preflighting */
+ errorCode=U_ZERO_ERROR;
+ length=unorm_normalize(in, 2, UNORM_NFD, 0, NULL, 0, &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3) {
+ log_err("unorm_normalize(pure preflighting NFD)=%ld failed with %s\n", length, u_errorName(errorCode));
+ return;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=unorm_normalize(in, 2, UNORM_NFD, 0, out, 3, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unorm_normalize(NFD)=%ld failed with %s\n", length, u_errorName(errorCode));
+ return;
+ }
+ if(length!=3 || out[2]!=0x308 || out[3]!=0xffff) {
+ log_err("unorm_normalize(NFD ma<umlaut>)=%ld failed with out[]=U+%04x U+%04x U+%04x U+%04x\n", length, out[0], out[1], out[2], out[3]);
+ return;
+ }
+}
+
+/* test cases to improve test code coverage */
+enum {
+ HANGUL_K_KIYEOK=0x3131, /* NFKD->Jamo L U+1100 */
+ HANGUL_K_WEO=0x315d, /* NFKD->Jamo V U+116f */
+ HANGUL_K_KIYEOK_SIOS=0x3133, /* NFKD->Jamo T U+11aa */
+
+ HANGUL_KIYEOK=0x1100, /* Jamo L U+1100 */
+ HANGUL_WEO=0x116f, /* Jamo V U+116f */
+ HANGUL_KIYEOK_SIOS=0x11aa, /* Jamo T U+11aa */
+
+ HANGUL_AC00=0xac00, /* Hangul syllable = Jamo LV U+ac00 */
+ HANGUL_SYLLABLE=0xac00+14*28+3, /* Hangul syllable = U+1100 * U+116f * U+11aa */
+
+ MUSICAL_VOID_NOTEHEAD=0x1d157,
+ MUSICAL_HALF_NOTE=0x1d15e, /* NFC/NFD->Notehead+Stem */
+ MUSICAL_STEM=0x1d165, /* cc=216 */
+ MUSICAL_STACCATO=0x1d17c /* cc=220 */
+};
+
+static void
+TestNormCoverage() {
+ UChar input[1000], expect[1000], output[1000];
+ UErrorCode errorCode;
+ int32_t i, length, inLength, expectLength, hangulPrefixLength, preflightLength;
+
+ /* create a long and nasty string with NFKC-unsafe characters */
+ inLength=0;
+
+ /* 3 Jamos L/V/T, all 8 combinations normal/compatibility */
+ input[inLength++]=HANGUL_KIYEOK;
+ input[inLength++]=HANGUL_WEO;
+ input[inLength++]=HANGUL_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_KIYEOK;
+ input[inLength++]=HANGUL_WEO;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_KIYEOK;
+ input[inLength++]=HANGUL_K_WEO;
+ input[inLength++]=HANGUL_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_KIYEOK;
+ input[inLength++]=HANGUL_K_WEO;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_WEO;
+ input[inLength++]=HANGUL_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_WEO;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_K_WEO;
+ input[inLength++]=HANGUL_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_K_WEO;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ /* Hangul LV with normal/compatibility Jamo T */
+ input[inLength++]=HANGUL_AC00;
+ input[inLength++]=HANGUL_KIYEOK_SIOS;
+
+ input[inLength++]=HANGUL_AC00;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ /* compatibility Jamo L, V */
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_K_WEO;
+
+ hangulPrefixLength=inLength;
+
+ input[inLength++]=UTF16_LEAD(MUSICAL_HALF_NOTE);
+ input[inLength++]=UTF16_TRAIL(MUSICAL_HALF_NOTE);
+ for(i=0; i<200; ++i) {
+ input[inLength++]=UTF16_LEAD(MUSICAL_STACCATO);
+ input[inLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
+ input[inLength++]=UTF16_LEAD(MUSICAL_STEM);
+ input[inLength++]=UTF16_TRAIL(MUSICAL_STEM);
+ }
+
+ /* (compatibility) Jamo L, T do not compose */
+ input[inLength++]=HANGUL_K_KIYEOK;
+ input[inLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ /* quick checks */
+ errorCode=U_ZERO_ERROR;
+ if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFD, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error unorm_quickCheck(long input, UNORM_NFD)!=NO (%s)\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKD, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error unorm_quickCheck(long input, UNORM_NFKD)!=NO (%s)\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error unorm_quickCheck(long input, UNORM_NFC)!=NO (%s)\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error unorm_quickCheck(long input, UNORM_NFKC)!=NO (%s)\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_FCD, &errorCode) || U_FAILURE(errorCode)) {
+ log_err("error unorm_quickCheck(long input, UNORM_FCD)!=NO (%s)\n", u_errorName(errorCode));
+ }
+
+ /* NFKC */
+ expectLength=0;
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_SYLLABLE;
+
+ expect[expectLength++]=HANGUL_AC00+3;
+
+ expect[expectLength++]=HANGUL_AC00+3;
+
+ expect[expectLength++]=HANGUL_AC00+14*28;
+
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD);
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
+ for(i=0; i<200; ++i) {
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
+ }
+ for(i=0; i<200; ++i) {
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
+ }
+
+ expect[expectLength++]=HANGUL_KIYEOK;
+ expect[expectLength++]=HANGUL_KIYEOK_SIOS;
+
+ /* try destination overflow first */
+ errorCode=U_ZERO_ERROR;
+ preflightLength=unorm_normalize(input, inLength,
+ UNORM_NFKC, 0,
+ output, 100, /* too short */
+ &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR) {
+ log_err("error unorm_normalize(long input, output too short, UNORM_NFKC) did not overflow but %s\n", u_errorName(errorCode));
+ }
+
+ /* real NFKC */
+ errorCode=U_ZERO_ERROR;
+ length=unorm_normalize(input, inLength,
+ UNORM_NFKC, 0,
+ output, sizeof(output)/U_SIZEOF_UCHAR,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error unorm_normalize(long input, UNORM_NFKC) failed with %s\n", u_errorName(errorCode));
+ } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) {
+ log_err("error unorm_normalize(long input, UNORM_NFKC) produced wrong result\n");
+ for(i=0; i<length; ++i) {
+ if(output[i]!=expect[i]) {
+ log_err(" NFKC[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]);
+ break;
+ }
+ }
+ }
+ if(length!=preflightLength) {
+ log_err("error unorm_normalize(long input, UNORM_NFKC)==%ld but preflightLength==%ld\n", length, preflightLength);
+ }
+
+ /* FCD */
+ u_memcpy(expect, input, hangulPrefixLength);
+ expectLength=hangulPrefixLength;
+
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD);
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
+ for(i=0; i<200; ++i) {
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
+ }
+ for(i=0; i<200; ++i) {
+ expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO);
+ expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
+ }
+
+ expect[expectLength++]=HANGUL_K_KIYEOK;
+ expect[expectLength++]=HANGUL_K_KIYEOK_SIOS;
+
+ errorCode=U_ZERO_ERROR;
+ length=unorm_normalize(input, inLength,
+ UNORM_FCD, 0,
+ output, sizeof(output)/U_SIZEOF_UCHAR,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error unorm_normalize(long input, UNORM_FCD) failed with %s\n", u_errorName(errorCode));
+ } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) {
+ log_err("error unorm_normalize(long input, UNORM_FCD) produced wrong result\n");
+ for(i=0; i<length; ++i) {
+ if(output[i]!=expect[i]) {
+ log_err(" FCD[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]);
+ break;
+ }
+ }
+ }
+}
+
+/* API test for unorm_concatenate() - for real test strings see intltest/tstnorm.cpp */
+static void
+TestConcatenate(void) {
+ /* "re + 'sume'" */
+ static const UChar
+ left[]={
+ 0x72, 0x65, 0
+ },
+ right[]={
+ 0x301, 0x73, 0x75, 0x6d, 0xe9, 0
+ },
+ expect[]={
+ 0x72, 0xe9, 0x73, 0x75, 0x6d, 0xe9, 0
+ };
+
+ UChar buffer[100];
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* left with length, right NUL-terminated */
+ errorCode=U_ZERO_ERROR;
+ length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
+ if(U_FAILURE(errorCode) || length!=6 || 0!=u_memcmp(buffer, expect, length)) {
+ log_err("error: unorm_concatenate()=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode));
+ }
+
+ /* preflighting */
+ errorCode=U_ZERO_ERROR;
+ length=unorm_concatenate(left, 2, right, -1, NULL, 0, UNORM_NFC, 0, &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6) {
+ log_err("error: unorm_concatenate(preflighting)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode));
+ }
+
+ buffer[2]=0x5555;
+ errorCode=U_ZERO_ERROR;
+ length=unorm_concatenate(left, 2, right, -1, buffer, 1, UNORM_NFC, 0, &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6 || buffer[2]!=0x5555) {
+ log_err("error: unorm_concatenate(preflighting 2)=%ld (expect 6) failed with %s\n", length, u_errorName(errorCode));
+ }
+
+ /* enter with U_FAILURE */
+ buffer[2]=0xaaaa;
+ errorCode=U_UNEXPECTED_TOKEN;
+ length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
+ if(errorCode!=U_UNEXPECTED_TOKEN || buffer[2]!=0xaaaa) {
+ log_err("error: unorm_concatenate(failure)=%ld failed with %s\n", length, u_errorName(errorCode));
+ }
+
+ /* illegal arguments */
+ buffer[2]=0xaaaa;
+ errorCode=U_ZERO_ERROR;
+ length=unorm_concatenate(NULL, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[2]!=0xaaaa) {
+ log_err("error: unorm_concatenate(left=NULL)=%ld failed with %s\n", length, u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=unorm_concatenate(left, 2, right, -1, NULL, 100, UNORM_NFC, 0, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error: unorm_concatenate(buffer=NULL)=%ld failed with %s\n", length, u_errorName(errorCode));
+ }
+}
+
+enum {
+ _PLUS=0x2b
+};
+
+static const char *const _modeString[UNORM_MODE_COUNT]={
+ "0", "NONE", "NFD", "NFKD", "NFC", "NFKC", "FCD"
+};
+
+static void
+_testIter(const UChar *src, int32_t srcLength,
+ UCharIterator *iter, UNormalizationMode mode, UBool forward,
+ const UChar *out, int32_t outLength,
+ const int32_t *srcIndexes, int32_t srcIndexesLength) {
+ UChar buffer[4];
+ const UChar *expect, *outLimit, *in;
+ int32_t length, i, expectLength, expectIndex, prevIndex, index, inLength;
+ UErrorCode errorCode;
+ UBool neededToNormalize, expectNeeded;
+
+ errorCode=U_ZERO_ERROR;
+ outLimit=out+outLength;
+ if(forward) {
+ expect=out;
+ i=index=0;
+ } else {
+ expect=outLimit;
+ i=srcIndexesLength-2;
+ index=srcLength;
+ }
+
+ for(;;) {
+ prevIndex=index;
+ if(forward) {
+ if(!iter->hasNext(iter)) {
+ return;
+ }
+ length=unorm_next(iter,
+ buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mode, 0,
+ (UBool)(out!=NULL), &neededToNormalize,
+ &errorCode);
+ expectIndex=srcIndexes[i+1];
+ in=src+prevIndex;
+ inLength=expectIndex-prevIndex;
+
+ if(out!=NULL) {
+ /* get output piece from between plus signs */
+ expectLength=0;
+ while((expect+expectLength)!=outLimit && expect[expectLength]!=_PLUS) {
+ ++expectLength;
+ }
+ expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength));
+ } else {
+ expect=in;
+ expectLength=inLength;
+ expectNeeded=FALSE;
+ }
+ } else {
+ if(!iter->hasPrevious(iter)) {
+ return;
+ }
+ length=unorm_previous(iter,
+ buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mode, 0,
+ (UBool)(out!=NULL), &neededToNormalize,
+ &errorCode);
+ expectIndex=srcIndexes[i];
+ in=src+expectIndex;
+ inLength=prevIndex-expectIndex;
+
+ if(out!=NULL) {
+ /* get output piece from between plus signs */
+ expectLength=0;
+ while(expect!=out && expect[-1]!=_PLUS) {
+ ++expectLength;
+ --expect;
+ }
+ expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength));
+ } else {
+ expect=in;
+ expectLength=inLength;
+ expectNeeded=FALSE;
+ }
+ }
+ index=iter->getIndex(iter, UITER_CURRENT);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("error unorm iteration (next/previous %d %s)[%d]: %s\n",
+ forward, _modeString[mode], i, u_errorName(errorCode));
+ return;
+ }
+ if(expectIndex!=index) {
+ log_err("error unorm iteration (next/previous %d %s): index[%d] wrong, got %d expected %d\n",
+ forward, _modeString[mode], i, index, expectIndex);
+ return;
+ }
+ if(expectLength!=length) {
+ log_err("error unorm iteration (next/previous %d %s): length[%d] wrong, got %d expected %d\n",
+ forward, _modeString[mode], i, length, expectLength);
+ return;
+ }
+ if(0!=u_memcmp(expect, buffer, length)) {
+ log_err("error unorm iteration (next/previous %d %s): output string[%d] wrong\n",
+ forward, _modeString[mode], i);
+ return;
+ }
+ if(neededToNormalize!=expectNeeded) {
+ }
+
+ if(forward) {
+ expect+=expectLength+1; /* go after the + */
+ ++i;
+ } else {
+ --expect; /* go before the + */
+ --i;
+ }
+ }
+}
+
+static void
+TestNextPrevious() {
+ static const UChar
+ src[]={ /* input string */
+ 0xa0, 0xe4, 0x63, 0x302, 0x327, 0xac00, 0x3133
+ },
+ nfd[]={ /* + separates expected output pieces */
+ 0xa0, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x3133
+ },
+ nfkd[]={
+ 0x20, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x11aa
+ },
+ nfc[]={
+ 0xa0, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac00, _PLUS, 0x3133
+ },
+ nfkc[]={
+ 0x20, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac03
+ },
+ fcd[]={
+ 0xa0, _PLUS, 0xe4, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0xac00, _PLUS, 0x3133
+ };
+
+ /* expected iterator indexes in the source string for each iteration piece */
+ static const int32_t
+ nfdIndexes[]={
+ 0, 1, 2, 5, 6, 7
+ },
+ nfkdIndexes[]={
+ 0, 1, 2, 5, 6, 7
+ },
+ nfcIndexes[]={
+ 0, 1, 2, 5, 6, 7
+ },
+ nfkcIndexes[]={
+ 0, 1, 2, 5, 7
+ },
+ fcdIndexes[]={
+ 0, 1, 2, 5, 6, 7
+ };
+
+ UCharIterator iter;
+
+ UChar buffer[4];
+ int32_t length;
+
+ UBool neededToNormalize;
+ UErrorCode errorCode;
+
+ uiter_setString(&iter, src, sizeof(src)/U_SIZEOF_UCHAR);
+
+ /* test iteration with doNormalize */
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4);
+
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4);
+
+ /* test iteration without doNormalize */
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4);
+ iter.index=0;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4);
+
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4);
+ iter.index=iter.length;
+ _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4);
+
+ /* try without neededToNormalize */
+ errorCode=U_ZERO_ERROR;
+ buffer[0]=5;
+ iter.index=1;
+ length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ UNORM_NFD, 0, TRUE, NULL,
+ &errorCode);
+ if(U_FAILURE(errorCode) || length!=2 || buffer[0]!=nfd[2] || buffer[1]!=nfd[3]) {
+ log_err("error unorm_next(without needed) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* preflight */
+ neededToNormalize=9;
+ iter.index=1;
+ length=unorm_next(&iter, NULL, 0,
+ UNORM_NFD, 0, TRUE, &neededToNormalize,
+ &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2) {
+ log_err("error unorm_next(pure preflighting) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ buffer[0]=buffer[1]=5;
+ neededToNormalize=9;
+ iter.index=1;
+ length=unorm_next(&iter, buffer, 1,
+ UNORM_NFD, 0, TRUE, &neededToNormalize,
+ &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2 || buffer[1]!=5) {
+ log_err("error unorm_next(preflighting) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* no iterator */
+ errorCode=U_ZERO_ERROR;
+ buffer[0]=buffer[1]=5;
+ neededToNormalize=9;
+ iter.index=1;
+ length=unorm_next(NULL, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ UNORM_NFD, 0, TRUE, &neededToNormalize,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error unorm_next(no iterator) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* illegal mode */
+ buffer[0]=buffer[1]=5;
+ neededToNormalize=9;
+ iter.index=1;
+ length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ (UNormalizationMode)0, 0, TRUE, &neededToNormalize,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error unorm_next(illegal mode) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* error coming in */
+ errorCode=U_MISPLACED_QUANTIFIER;
+ buffer[0]=5;
+ iter.index=1;
+ length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ UNORM_NFD, 0, TRUE, NULL,
+ &errorCode);
+ if(errorCode!=U_MISPLACED_QUANTIFIER) {
+ log_err("error unorm_next(U_MISPLACED_QUANTIFIER) %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* missing pErrorCode */
+ buffer[0]=5;
+ iter.index=1;
+ length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ UNORM_NFD, 0, TRUE, NULL,
+ NULL);
+ if(iter.index!=1 || buffer[0]!=5) {
+ log_err("error unorm_next(pErrorCode==NULL) %s\n", u_errorName(errorCode));
+ return;
+ }
+}
+
+static void
+TestFCNFKCClosure(void) {
+ static const struct {
+ UChar32 c;
+ const UChar s[6];
+ } tests[]={
+ { 0x037A, { 0x0020, 0x03B9, 0 } },
+ { 0x03D2, { 0x03C5, 0 } },
+ { 0x20A8, { 0x0072, 0x0073, 0 } },
+ { 0x210B, { 0x0068, 0 } },
+ { 0x210C, { 0x0068, 0 } },
+ { 0x2121, { 0x0074, 0x0065, 0x006C, 0 } },
+ { 0x2122, { 0x0074, 0x006D, 0 } },
+ { 0x2128, { 0x007A, 0 } },
+ { 0x1D5DB, { 0x0068, 0 } },
+ { 0x1D5ED, { 0x007A, 0 } },
+ { 0x0061, { 0 } }
+ };
+
+ UChar buffer[8];
+ UErrorCode errorCode;
+ int32_t i, length;
+
+ for(i=0; i<LENGTHOF(tests); ++i) {
+ errorCode=U_ZERO_ERROR;
+ length=u_getFC_NFKC_Closure(tests[i].c, buffer, LENGTHOF(buffer), &errorCode);
+ if(U_FAILURE(errorCode) || length!=u_strlen(buffer) || 0!=u_strcmp(tests[i].s, buffer)) {
+ log_err("u_getFC_NFKC_Closure(U+%04lx) is wrong (%s)\n", tests[i].c, u_errorName(errorCode));
+ }
+ }
+
+ /* error handling */
+ errorCode=U_ZERO_ERROR;
+ length=u_getFC_NFKC_Closure(0x5c, NULL, LENGTHOF(buffer), &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("u_getFC_NFKC_Closure(dest=NULL) is wrong (%s)\n", u_errorName(errorCode));
+ }
+
+ length=u_getFC_NFKC_Closure(0x5c, buffer, LENGTHOF(buffer), &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("u_getFC_NFKC_Closure(U_FAILURE) is wrong (%s)\n", u_errorName(errorCode));
+ }
+}
+
+static void
+TestQuickCheckPerCP() {
+ UErrorCode errorCode;
+ UChar32 c, lead, trail;
+ UChar s[U16_MAX_LENGTH], nfd[16];
+ int32_t length, lccc1, lccc2, tccc1, tccc2;
+ int32_t qc1, qc2;
+
+ if(
+ u_getIntPropertyMaxValue(UCHAR_NFD_QUICK_CHECK)!=(int32_t)UNORM_YES ||
+ u_getIntPropertyMaxValue(UCHAR_NFKD_QUICK_CHECK)!=(int32_t)UNORM_YES ||
+ u_getIntPropertyMaxValue(UCHAR_NFC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE ||
+ u_getIntPropertyMaxValue(UCHAR_NFKC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE ||
+ u_getIntPropertyMaxValue(UCHAR_LEAD_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) ||
+ u_getIntPropertyMaxValue(UCHAR_TRAIL_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS)
+ ) {
+ log_err("wrong result from one of the u_getIntPropertyMaxValue(UCHAR_NF*_QUICK_CHECK) or UCHAR_*_CANONICAL_COMBINING_CLASS\n");
+ }
+
+ /*
+ * compare the quick check property values for some code points
+ * to the quick check results for checking same-code point strings
+ */
+ errorCode=U_ZERO_ERROR;
+ c=0;
+ while(c<0x110000) {
+ length=0;
+ U16_APPEND_UNSAFE(s, length, c);
+
+ qc1=u_getIntPropertyValue(c, UCHAR_NFC_QUICK_CHECK);
+ qc2=unorm_quickCheck(s, length, UNORM_NFC, &errorCode);
+ if(qc1!=qc2) {
+ log_err("u_getIntPropertyValue(NFC)=%d != %d=unorm_quickCheck(NFC) for U+%04x\n", qc1, qc2, c);
+ }
+
+ qc1=u_getIntPropertyValue(c, UCHAR_NFD_QUICK_CHECK);
+ qc2=unorm_quickCheck(s, length, UNORM_NFD, &errorCode);
+ if(qc1!=qc2) {
+ log_err("u_getIntPropertyValue(NFD)=%d != %d=unorm_quickCheck(NFD) for U+%04x\n", qc1, qc2, c);
+ }
+
+ qc1=u_getIntPropertyValue(c, UCHAR_NFKC_QUICK_CHECK);
+ qc2=unorm_quickCheck(s, length, UNORM_NFKC, &errorCode);
+ if(qc1!=qc2) {
+ log_err("u_getIntPropertyValue(NFKC)=%d != %d=unorm_quickCheck(NFKC) for U+%04x\n", qc1, qc2, c);
+ }
+
+ qc1=u_getIntPropertyValue(c, UCHAR_NFKD_QUICK_CHECK);
+ qc2=unorm_quickCheck(s, length, UNORM_NFKD, &errorCode);
+ if(qc1!=qc2) {
+ log_err("u_getIntPropertyValue(NFKD)=%d != %d=unorm_quickCheck(NFKD) for U+%04x\n", qc1, qc2, c);
+ }
+
+ length=unorm_normalize(s, length, UNORM_NFD, 0, nfd, LENGTHOF(nfd), &errorCode);
+ /* length-length == 0 is used to get around a compiler warning. */
+ U16_GET(nfd, 0, length-length, length, lead);
+ U16_GET(nfd, 0, length-1, length, trail);
+
+ lccc1=u_getIntPropertyValue(c, UCHAR_LEAD_CANONICAL_COMBINING_CLASS);
+ lccc2=u_getCombiningClass(lead);
+ tccc1=u_getIntPropertyValue(c, UCHAR_TRAIL_CANONICAL_COMBINING_CLASS);
+ tccc2=u_getCombiningClass(trail);
+
+ if(lccc1!=lccc2) {
+ log_err("u_getIntPropertyValue(lccc)=%d != %d=u_getCombiningClass(lead) for U+%04x\n",
+ lccc1, lccc2, c);
+ }
+ if(tccc1!=tccc2) {
+ log_err("u_getIntPropertyValue(tccc)=%d != %d=u_getCombiningClass(trail) for U+%04x\n",
+ tccc1, tccc2, c);
+ }
+
+ /* skip some code points */
+ c=(20*c)/19+1;
+ }
+}
+
+static void
+TestComposition(void) {
+ static const struct {
+ UNormalizationMode mode;
+ uint32_t options;
+ UChar input[12];
+ UChar expect[12];
+ } cases[]={
+ /*
+ * special cases for UAX #15 bug
+ * see Unicode Public Review Issue #29
+ * at http://www.unicode.org/review/resolved-pri.html#pri29
+ */
+ { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0x1100, 0x0300, 0x1161, 0x0327 } },
+ { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 } },
+ { UNORM_NFC, 0, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac00, 0x0327, 0x0300, 0x11a8 } },
+ { UNORM_NFC, 0, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b47, 0x0300, 0x0b3e } },
+
+ { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327 }, { 0xac00, 0x0300, 0x0327 } },
+ { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0xac01, 0x0300, 0x0327 } },
+ { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0xac00, 0x0300, 0x0327, 0x11a8 }, { 0xac01, 0x0327, 0x0300 } },
+ { UNORM_NFC, UNORM_BEFORE_PRI_29, { 0x0b47, 0x0300, 0x0b3e }, { 0x0b4b, 0x0300 } }
+
+ /* TODO: add test cases for UNORM_FCC here (j2151) */
+ };
+
+ UChar output[16];
+ UErrorCode errorCode;
+ int32_t i, length;
+
+ for(i=0; i<LENGTHOF(cases); ++i) {
+ errorCode=U_ZERO_ERROR;
+ length=unorm_normalize(
+ cases[i].input, -1,
+ cases[i].mode, cases[i].options,
+ output, LENGTHOF(output),
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=u_strlen(cases[i].expect) ||
+ 0!=u_memcmp(output, cases[i].expect, length)
+ ) {
+ log_err("unexpected result for case %d\n", i);
+ }
+ }
+}
+
+#endif /* #if !UCONFIG_NO_NORMALIZATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h
new file mode 100644
index 00000000000..bc213a486aa
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnormtst.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CNORMTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+* synwee added test for quick check
+* synwee added test for checkFCD
+*********************************************************************************
+*/
+#ifndef _NORMTST
+#define _NORMTST
+/**
+ * tests for u_normalization
+ */
+
+#include "cintltst.h"
+
+ void TestDecomp(void);
+ void TestCompatDecomp(void);
+ void TestCanonDecompCompose(void);
+ void TestCompatDecompCompose(void);
+ void TestNull(void);
+ void TestQuickCheck(void);
+ void TestCheckFCD(void);
+
+ /*internal functions*/
+
+/* static void assertEqual(const UChar* result, const UChar* expected, int32_t index);
+*/
+ static void assertEqual(const UChar* result, const char* expected, int32_t index);
+
+
+
+
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c
new file mode 100644
index 00000000000..7a8df1f70b4
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.c
@@ -0,0 +1,1399 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CNUMTST.C
+*
+* Madhu Katragadda Creation
+*
+* Modification History:
+*
+* Date Name Description
+* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
+* 07/15/99 helena Ported to HPUX 10/11 CC.
+*********************************************************************************
+*/
+
+/* C API TEST FOR NUMBER FORMAT */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/uloc.h"
+#include "unicode/unum.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cnumtst.h"
+#include "cmemory.h"
+#include "putilimp.h"
+
+#define LENGTH(arr) (sizeof(arr)/sizeof(arr[0]))
+
+void addNumForTest(TestNode** root);
+static void TestTextAttributeCrash(void);
+
+#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
+
+void addNumForTest(TestNode** root)
+{
+ TESTCASE(TestNumberFormat);
+ TESTCASE(TestSignificantDigits);
+ TESTCASE(TestNumberFormatPadding);
+ TESTCASE(TestInt64Format);
+ TESTCASE(TestNonExistentCurrency);
+ TESTCASE(TestCurrencyRegression);
+ TESTCASE(TestTextAttributeCrash);
+ TESTCASE(TestRBNFFormat);
+}
+
+/** copy src to dst with unicode-escapes for values < 0x20 and > 0x7e, null terminate if possible */
+static int32_t ustrToAstr(const UChar* src, int32_t srcLength, char* dst, int32_t dstLength) {
+ static const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ char *p = dst;
+ const char *e = p + dstLength;
+ if (srcLength < 0) {
+ const UChar* s = src;
+ while (*s) {
+ ++s;
+ }
+ srcLength = (int32_t)(s - src);
+ }
+ while (p < e && --srcLength >= 0) {
+ UChar c = *src++;
+ if (c == 0xd || c == 0xa || c == 0x9 || (c>= 0x20 && c <= 0x7e)) {
+ *p++ = (char) c & 0x7f;
+ } else if (e - p >= 6) {
+ *p++ = '\\';
+ *p++ = 'u';
+ *p++ = hex[(c >> 12) & 0xf];
+ *p++ = hex[(c >> 8) & 0xf];
+ *p++ = hex[(c >> 4) & 0xf];
+ *p++ = hex[c & 0xf];
+ } else {
+ break;
+ }
+ }
+ if (p < e) {
+ *p = 0;
+ }
+ return (int32_t)(p - dst);
+}
+
+/* test Number Format API */
+static void TestNumberFormat()
+{
+ UChar *result=NULL;
+ UChar temp1[512];
+ UChar temp2[512];
+
+ UChar temp[5];
+
+ UChar prefix[5];
+ UChar suffix[5];
+ UChar symbol[20];
+ int32_t resultlength;
+ int32_t resultlengthneeded;
+ int32_t parsepos;
+ double d1 = -1.0;
+ int32_t l1;
+ double d = -10456.37;
+ double a = 1234.56, a1 = 1235.0;
+ int32_t l = 100000000;
+ UFieldPosition pos1;
+ UFieldPosition pos2;
+ int32_t numlocales;
+ int32_t i;
+
+ UNumberFormatAttribute attr;
+ UNumberFormatSymbol symType = UNUM_DECIMAL_SEPARATOR_SYMBOL;
+ int32_t newvalue;
+ UErrorCode status=U_ZERO_ERROR;
+ UNumberFormatStyle style= UNUM_DEFAULT;
+ UNumberFormat *pattern;
+ UNumberFormat *def, *fr, *cur_def, *cur_fr, *per_def, *per_fr,
+ *cur_frpattern, *myclone, *spellout_def;
+
+ /* Testing unum_open() with various Numberformat styles and locales*/
+ status = U_ZERO_ERROR;
+ log_verbose("Testing unum_open() with default style and locale\n");
+ def=unum_open(style, NULL,0,NULL, NULL,&status);
+
+ /* Might as well pack it in now if we can't even get a default NumberFormat... */
+ if(U_FAILURE(status))
+ {
+ log_err("Error in creating default NumberFormat using unum_open(): %s\n", myErrorName(status));
+ return;
+ }
+
+ log_verbose("\nTesting unum_open() with french locale and default style(decimal)\n");
+ fr=unum_open(style,NULL,0, "fr_FR",NULL, &status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat (french): %s\n", myErrorName(status));
+
+ log_verbose("\nTesting unum_open(currency,NULL,status)\n");
+ style=UNUM_CURRENCY;
+ /* Can't hardcode the result to assume the default locale is "en_US". */
+ cur_def=unum_open(style, NULL,0,"en_US", NULL, &status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat using \n unum_open(currency, NULL, &status) %s\n",
+ myErrorName(status) );
+
+ log_verbose("\nTesting unum_open(currency, frenchlocale, status)\n");
+ cur_fr=unum_open(style,NULL,0, "fr_FR", NULL, &status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat using unum_open(currency, french, &status): %s\n",
+ myErrorName(status));
+
+ log_verbose("\nTesting unum_open(percent, NULL, status)\n");
+ style=UNUM_PERCENT;
+ per_def=unum_open(style,NULL,0, NULL,NULL, &status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat using unum_open(percent, NULL, &status): %s\n", myErrorName(status));
+
+ log_verbose("\nTesting unum_open(percent,frenchlocale, status)\n");
+ per_fr=unum_open(style, NULL,0,"fr_FR", NULL,&status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat using unum_open(percent, french, &status): %s\n", myErrorName(status));
+
+ log_verbose("\nTesting unum_open(spellout, NULL, status)");
+ style=UNUM_SPELLOUT;
+ spellout_def=unum_open(style, NULL, 0, "en_US", NULL, &status);
+ if(U_FAILURE(status))
+ log_err("Error: could not create NumberFormat using unum_open(spellout, NULL, &status): %s\n", myErrorName(status));
+
+ /* Testing unum_clone(..) */
+ log_verbose("\nTesting unum_clone(fmt, status)");
+ status = U_ZERO_ERROR;
+ myclone = unum_clone(def,&status);
+ if(U_FAILURE(status))
+ log_err("Error: could not clone unum_clone(def, &status): %s\n", myErrorName(status));
+ else
+ {
+ log_verbose("unum_clone() successful\n");
+ }
+
+ /*Testing unum_getAvailable() and unum_countAvailable()*/
+ log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
+ numlocales=unum_countAvailable();
+ if(numlocales < 0)
+ log_err("error in countAvailable");
+ else{
+ log_verbose("unum_countAvialable() successful\n");
+ log_verbose("The no: of locales where number formattting is applicable is %d\n", numlocales);
+ }
+ for(i=0;i<numlocales;i++)
+ {
+ log_verbose("%s\n", unum_getAvailable(i));
+ if (unum_getAvailable(i) == 0)
+ log_err("No locale for which number formatting patterns are applicable\n");
+ else
+ log_verbose("A locale %s for which number formatting patterns are applicable\n",unum_getAvailable(i));
+ }
+
+
+ /*Testing unum_format() and unum_formatdouble()*/
+ u_uastrcpy(temp1, "$100,000,000.00");
+
+ log_verbose("\nTesting unum_format() \n");
+ resultlength=0;
+ pos1.field = 0; /* Integer Section */
+ resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+/* for (i = 0; i < 100000; i++) */
+ {
+ unum_format(cur_def, l, result, resultlength, &pos1, &status);
+ }
+ }
+
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
+ }
+ if(u_strcmp(result, temp1)==0)
+ log_verbose("Pass: Number formatting using unum_format() successful\n");
+ else
+ log_err("Fail: Error in number Formatting using unum_format()\n");
+ if(pos1.beginIndex == 1 && pos1.endIndex == 12)
+ log_verbose("Pass: Complete number formatting using unum_format() successful\n");
+ else
+ log_err("Fail: Error in complete number Formatting using unum_format()\nGot: b=%d end=%d\nExpected: b=1 end=12\n",
+ pos1.beginIndex, pos1.endIndex);
+
+free(result);
+ result = 0;
+
+ log_verbose("\nTesting unum_formatDouble()\n");
+ u_uastrcpy(temp1, "($10,456.37)");
+ resultlength=0;
+ pos2.field = 1; /* Fractional Section */
+ resultlengthneeded=unum_formatDouble(cur_def, d, NULL, resultlength, &pos2, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+/* for (i = 0; i < 100000; i++) */
+ {
+ unum_formatDouble(cur_def, d, result, resultlength, &pos2, &status);
+ }
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
+ }
+ if(result && u_strcmp(result, temp1)==0)
+ log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
+ else
+ log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
+ if(pos2.beginIndex == 9 && pos2.endIndex == 11)
+ log_verbose("Pass: Complete number formatting using unum_format() successful\n");
+ else
+ log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=9 end=11",
+ pos1.beginIndex, pos1.endIndex);
+
+
+ /* Testing unum_parse() and unum_parseDouble() */
+ log_verbose("\nTesting unum_parseDouble()\n");
+/* for (i = 0; i < 100000; i++)*/
+ if (result != NULL)
+ {
+ parsepos=0;
+ d1=unum_parseDouble(cur_def, result, u_strlen(result), &parsepos, &status);
+ }
+ else {
+ log_err("result is NULL\n");
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("parse failed. The error is : %s\n", myErrorName(status));
+ }
+
+ if(d1!=d)
+ log_err("Fail: Error in parsing\n");
+ else
+ log_verbose("Pass: parsing successful\n");
+ if (result)
+ free(result);
+ result = 0;
+
+
+ /* Testing unum_formatDoubleCurrency / unum_parseDoubleCurrency */
+ log_verbose("\nTesting unum_formatDoubleCurrency\n");
+ u_uastrcpy(temp1, "Y1,235");
+ temp1[0] = 0xA5; /* Yen sign */
+ u_uastrcpy(temp, "JPY");
+ resultlength=0;
+ pos2.field = 0; /* integer part */
+ resultlengthneeded=unum_formatDoubleCurrency(cur_def, a, temp, NULL, resultlength, &pos2, &status);
+ if (status==U_BUFFER_OVERFLOW_ERROR) {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_formatDoubleCurrency(cur_def, a, temp, result, resultlength, &pos2, &status);
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
+ }
+ if (result && u_strcmp(result, temp1)==0) {
+ log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
+ } else {
+ log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
+ }
+ if (pos2.beginIndex == 1 && pos2.endIndex == 6) {
+ log_verbose("Pass: Complete number formatting using unum_format() successful\n");
+ } else {
+ log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=1 end=6\n",
+ pos1.beginIndex, pos1.endIndex);
+ }
+
+ log_verbose("\nTesting unum_parseDoubleCurrency\n");
+ parsepos=0;
+ if (result == NULL) {
+ log_err("result is NULL\n");
+ }
+ else {
+ d1=unum_parseDoubleCurrency(cur_def, result, u_strlen(result), &parsepos, temp2, &status);
+ if (U_FAILURE(status)) {
+ log_err("parse failed. The error is : %s\n", myErrorName(status));
+ }
+ /* Note: a==1234.56, but on parse expect a1=1235.0 */
+ if (d1!=a1) {
+ log_err("Fail: Error in parsing currency, got %f, expected %f\n", d1, a1);
+ } else {
+ log_verbose("Pass: parsed currency ammount successfully\n");
+ }
+ if (u_strcmp(temp2, temp)==0) {
+ log_verbose("Pass: parsed correct currency\n");
+ } else {
+ log_err("Fail: parsed incorrect currency\n");
+ }
+ }
+
+free(result);
+ result = 0;
+
+
+/* performance testing */
+ u_uastrcpy(temp1, "$462.12345");
+ resultlength=u_strlen(temp1);
+/* for (i = 0; i < 100000; i++) */
+ {
+ parsepos=0;
+ d1=unum_parseDouble(cur_def, temp1, resultlength, &parsepos, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("parse failed. The error is : %s\n", myErrorName(status));
+ }
+
+ if(d1!=462.12345)
+ log_err("Fail: Error in parsing\n");
+ else
+ log_verbose("Pass: parsing successful\n");
+
+free(result);
+
+ u_uastrcpy(temp1, "($10,456.3E1])");
+ parsepos=0;
+ d1=unum_parseDouble(cur_def, temp1, u_strlen(temp1), &parsepos, &status);
+ if(U_SUCCESS(status))
+ {
+ log_err("Error in unum_parseDouble(..., %s, ...): %s\n", temp1, myErrorName(status));
+ }
+
+
+ log_verbose("\nTesting unum_format()\n");
+ status=U_ZERO_ERROR;
+ resultlength=0;
+ parsepos=0;
+ resultlengthneeded=unum_format(per_fr, l, NULL, resultlength, &pos1, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+/* for (i = 0; i < 100000; i++)*/
+ {
+ unum_format(per_fr, l, result, resultlength, &pos1, &status);
+ }
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
+ }
+
+
+ log_verbose("\nTesting unum_parse()\n");
+/* for (i = 0; i < 100000; i++) */
+ {
+ parsepos=0;
+ l1=unum_parse(per_fr, result, u_strlen(result), &parsepos, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("parse failed. The error is : %s\n", myErrorName(status));
+ }
+
+ if(l1!=l)
+ log_err("Fail: Error in parsing\n");
+ else
+ log_verbose("Pass: parsing successful\n");
+
+free(result);
+
+ /* create a number format using unum_openPattern(....)*/
+ log_verbose("\nTesting unum_openPattern()\n");
+ u_uastrcpy(temp1, "#,##0.0#;(#,##0.0#)");
+ pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in unum_openPattern(): %s\n", myErrorName(status) );;
+ }
+ else
+ log_verbose("Pass: unum_openPattern() works fine\n");
+
+ /*test for unum_toPattern()*/
+ log_verbose("\nTesting unum_toPattern()\n");
+ resultlength=0;
+ resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_toPattern(pattern, FALSE, result, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
+ }
+ else
+ {
+ if(u_strcmp(result, temp1)!=0)
+ log_err("FAIL: Error in extracting the pattern using unum_toPattern()\n");
+ else
+ log_verbose("Pass: extracted the pattern correctly using unum_toPattern()\n");
+free(result);
+ }
+
+ /*Testing unum_getSymbols() and unum_setSymbols()*/
+ log_verbose("\nTesting unum_getSymbols and unum_setSymbols()\n");
+ /*when we try to change the symbols of french to default we need to apply the pattern as well to fetch correct results */
+ resultlength=0;
+ resultlengthneeded=unum_toPattern(cur_def, FALSE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_toPattern(cur_def, FALSE, result, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
+ }
+
+ status=U_ZERO_ERROR;
+ cur_frpattern=unum_open(UNUM_IGNORE,result, u_strlen(result), "fr_FR",NULL, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in unum_openPattern(): %s\n", myErrorName(status));
+ }
+
+free(result);
+
+ /*getting the symbols of cur_def */
+ /*set the symbols of cur_frpattern to cur_def */
+ for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
+ status=U_ZERO_ERROR;
+ unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
+ unum_setSymbol(cur_frpattern, symType, temp1, -1, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Error in get/set symbols: %s\n", myErrorName(status));
+ }
+ }
+
+ /*format to check the result */
+ resultlength=0;
+ resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_format(cur_def, l, result, resultlength, &pos1, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
+ }
+
+ if(U_FAILURE(status)){
+ log_err("Fail: error in unum_setSymbols: %s\n", myErrorName(status));
+ }
+ unum_applyPattern(cur_frpattern, FALSE, result, u_strlen(result),NULL,NULL);
+
+ for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
+ status=U_ZERO_ERROR;
+ unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
+ unum_getSymbol(cur_frpattern, symType, temp2, sizeof(temp2), &status);
+ if(U_FAILURE(status) || u_strcmp(temp1, temp2) != 0)
+ {
+ log_err("Fail: error in getting symbols\n");
+ }
+ else
+ log_verbose("Pass: get and set symbols successful\n");
+ }
+
+ /*format and check with the previous result */
+
+ resultlength=0;
+ resultlengthneeded=unum_format(cur_frpattern, l, NULL, resultlength, &pos1, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ unum_format(cur_frpattern, l, temp1, resultlength, &pos1, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
+ }
+ /* TODO:
+ * This test fails because we have not called unum_applyPattern().
+ * Currently, such an applyPattern() does not exist on the C API, and
+ * we have jitterbug 411 for it.
+ * Since it is close to the 1.5 release, I (markus) am disabling this test just
+ * for this release (I added the test itself only last week).
+ * For the next release, we need to fix this.
+ * Then, remove the uprv_strcmp("1.5", ...) and this comment, and the include "cstring.h" at the beginning of this file.
+ */
+ if(u_strcmp(result, temp1) != 0) {
+ log_err("Formatting failed after setting symbols. result=%s temp1=%s\n", result, temp1);
+ }
+
+
+ /*----------- */
+
+free(result);
+
+ /* Testing unum_get/setSymbol() */
+ for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
+ symbol[0] = (UChar)(0x41 + i);
+ symbol[1] = (UChar)(0x61 + i);
+ unum_setSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, 2, &status);
+ if(U_FAILURE(status)) {
+ log_err("Error from unum_setSymbol(%d): %s\n", i, myErrorName(status));
+ return;
+ }
+ }
+ for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
+ resultlength = unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
+ if(U_FAILURE(status)) {
+ log_err("Error from unum_getSymbol(%d): %s\n", i, myErrorName(status));
+ return;
+ }
+ if(resultlength != 2 || symbol[0] != 0x41 + i || symbol[1] != 0x61 + i) {
+ log_err("Failure in unum_getSymbol(%d): got unexpected symbol\n", i);
+ }
+ }
+ /*try getting from a bogus symbol*/
+ unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
+ if(U_SUCCESS(status)){
+ log_err("Error : Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol");
+ }
+ if(U_FAILURE(status)){
+ if(status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("Error: Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol, Got %s\n", myErrorName(status));
+ }
+ }
+ status=U_ZERO_ERROR;
+
+ /* Testing unum_getTextAttribute() and unum_setTextAttribute()*/
+ log_verbose("\nTesting getting and setting text attributes\n");
+ resultlength=5;
+ unum_getTextAttribute(cur_fr, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
+ }
+ unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
+ }
+ unum_getTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, suffix, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
+ }
+ if(u_strcmp(suffix,temp)!=0)
+ log_err("Fail:Error in setTextAttribute or getTextAttribute in setting and getting suffix\n");
+ else
+ log_verbose("Pass: setting and getting suffix works fine\n");
+ /*set it back to normal */
+ u_uastrcpy(temp,"$");
+ unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
+
+ /*checking some more text setter conditions */
+ u_uastrcpy(prefix, "+");
+ unum_setTextAttribute(def, UNUM_POSITIVE_PREFIX, prefix, u_strlen(prefix) , &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in setting the text attributes : %s\n", myErrorName(status));
+ }
+ unum_getTextAttribute(def, UNUM_POSITIVE_PREFIX, temp, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in getting the text attributes : %s\n", myErrorName(status));
+ }
+
+ if(u_strcmp(prefix, temp)!=0)
+ log_err("ERROR: get and setTextAttributes with positive prefix failed\n");
+ else
+ log_verbose("Pass: get and setTextAttributes with positive prefix works fine\n");
+
+ u_uastrcpy(prefix, "+");
+ unum_setTextAttribute(def, UNUM_NEGATIVE_PREFIX, prefix, u_strlen(prefix), &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in setting the text attributes : %s\n", myErrorName(status));
+ }
+ unum_getTextAttribute(def, UNUM_NEGATIVE_PREFIX, temp, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in getting the text attributes : %s\n", myErrorName(status));
+ }
+ if(u_strcmp(prefix, temp)!=0)
+ log_err("ERROR: get and setTextAttributes with negative prefix failed\n");
+ else
+ log_verbose("Pass: get and setTextAttributes with negative prefix works fine\n");
+
+ u_uastrcpy(suffix, "+");
+ unum_setTextAttribute(def, UNUM_NEGATIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in setting the text attributes: %s\n", myErrorName(status));
+ }
+
+ unum_getTextAttribute(def, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in getting the text attributes : %s\n", myErrorName(status));
+ }
+ if(u_strcmp(suffix, temp)!=0)
+ log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
+ else
+ log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
+
+ u_uastrcpy(suffix, "++");
+ unum_setTextAttribute(def, UNUM_POSITIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in setting the text attributes: %s\n", myErrorName(status));
+ }
+
+ unum_getTextAttribute(def, UNUM_POSITIVE_SUFFIX, temp, resultlength, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in getting the text attributes : %s\n", myErrorName(status));
+ }
+ if(u_strcmp(suffix, temp)!=0)
+ log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
+ else
+ log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
+
+ /*Testing unum_getAttribute and unum_setAttribute() */
+ log_verbose("\nTesting get and set Attributes\n");
+ attr=UNUM_GROUPING_SIZE;
+ newvalue=unum_getAttribute(def, attr);
+ newvalue=2;
+ unum_setAttribute(def, attr, newvalue);
+ if(unum_getAttribute(def,attr)!=2)
+ log_err("Fail: error in setting and getting attributes for UNUM_GROUPING_SIZE\n");
+ else
+ log_verbose("Pass: setting and getting attributes for UNUM_GROUPING_SIZE works fine\n");
+
+ attr=UNUM_MULTIPLIER;
+ newvalue=unum_getAttribute(def, attr);
+ newvalue=8;
+ unum_setAttribute(def, attr, newvalue);
+ if(unum_getAttribute(def,attr) != 8)
+ log_err("error in setting and getting attributes for UNUM_MULTIPLIER\n");
+ else
+ log_verbose("Pass:setting and getting attributes for UNUM_MULTIPLIER works fine\n");
+
+ attr=UNUM_SECONDARY_GROUPING_SIZE;
+ newvalue=unum_getAttribute(def, attr);
+ newvalue=2;
+ unum_setAttribute(def, attr, newvalue);
+ if(unum_getAttribute(def,attr) != 2)
+ log_err("error in setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE\n");
+ else
+ log_verbose("Pass:setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE works fine\n");
+
+ /*testing set and get Attributes extensively */
+ log_verbose("\nTesting get and set attributes extensively\n");
+ for(attr=UNUM_PARSE_INT_ONLY; attr<= UNUM_PADDING_POSITION; attr=(UNumberFormatAttribute)((int32_t)attr + 1) )
+ {
+ newvalue=unum_getAttribute(fr, attr);
+ unum_setAttribute(def, attr, newvalue);
+ if(unum_getAttribute(def,attr)!=unum_getAttribute(fr, attr))
+ log_err("error in setting and getting attributes\n");
+ else
+ log_verbose("Pass: attributes set and retrieved successfully\n");
+ }
+
+ /*testing spellout format to make sure we can use it successfully.*/
+ log_verbose("\nTesting spellout format\n");
+ if (spellout_def)
+ {
+ static const int32_t values[] = { 0, -5, 105, 1005, 105050 };
+ for (i = 0; i < LENGTH(values); ++i) {
+ UChar buffer[128];
+ int32_t len;
+ int32_t value = values[i];
+ status = U_ZERO_ERROR;
+ len = unum_format(spellout_def, value, buffer, LENGTH(buffer), NULL, &status);
+ if(U_FAILURE(status)) {
+ log_err("Error in formatting using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
+ } else {
+ int32_t pp = 0;
+ int32_t parseResult;
+ char logbuf[256];
+ ustrToAstr(buffer, len, logbuf, LENGTH(logbuf));
+ log_verbose("formatted %d as '%s', length: %d\n", value, logbuf, len);
+
+ parseResult = unum_parse(spellout_def, buffer, len, &pp, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error in parsing using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
+ } else if (parseResult != value) {
+ log_err("unum_format result %d != value %d\n", parseResult, value);
+ }
+ }
+ }
+ }
+ else {
+ log_err("Spellout format is unavailable\n");
+ }
+
+ /*closing the NumberFormat() using unum_close(UNumberFormat*)")*/
+ unum_close(def);
+ unum_close(fr);
+ unum_close(cur_def);
+ unum_close(cur_fr);
+ unum_close(per_def);
+ unum_close(per_fr);
+ unum_close(spellout_def);
+ unum_close(pattern);
+ unum_close(cur_frpattern);
+ unum_close(myclone);
+
+}
+
+static void TestSignificantDigits()
+{
+ UChar temp[128];
+ int32_t resultlengthneeded;
+ int32_t resultlength;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *result = NULL;
+ UNumberFormat* fmt;
+ double d = 123456.789;
+
+ u_uastrcpy(temp, "###0.0#");
+ fmt=unum_open(UNUM_IGNORE, temp, -1, NULL, NULL,&status);
+ if (U_FAILURE(status)) {
+ log_err("got unexpected error for unum_open: '%s'\n", u_errorName(status));
+ }
+ unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
+ unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 6);
+
+ u_uastrcpy(temp, "123457");
+ resultlength=0;
+ resultlengthneeded=unum_formatDouble(fmt, d, NULL, resultlength, NULL, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_formatDouble(fmt, d, result, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
+ return;
+ }
+ if(u_strcmp(result, temp)==0)
+ log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
+ else
+ log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
+ free(result);
+ unum_close(fmt);
+}
+
+static void TestNumberFormatPadding()
+{
+ UChar *result=NULL;
+ UChar temp1[512];
+
+ UErrorCode status=U_ZERO_ERROR;
+ int32_t resultlength;
+ int32_t resultlengthneeded;
+ UNumberFormat *pattern;
+ double d1;
+ double d = -10456.37;
+ UFieldPosition pos1;
+ int32_t parsepos;
+
+ /* create a number format using unum_openPattern(....)*/
+ log_verbose("\nTesting unum_openPattern() with padding\n");
+ u_uastrcpy(temp1, "*#,##0.0#*;(#,##0.0#)");
+ status=U_ZERO_ERROR;
+ pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
+ if(U_SUCCESS(status))
+ {
+ log_err("error in unum_openPattern(%s): %s\n", temp1, myErrorName(status) );;
+ }
+ else
+ {
+ unum_close(pattern);
+ }
+
+/* u_uastrcpy(temp1, "*x#,###,###,##0.0#;(*x#,###,###,##0.0#)"); */
+ u_uastrcpy(temp1, "*x#,###,###,##0.0#;*x(###,###,##0.0#)");
+ status=U_ZERO_ERROR;
+ pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), "en_US",NULL, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) );;
+ }
+ else {
+ log_verbose("Pass: padding unum_openPattern() works fine\n");
+
+ /*test for unum_toPattern()*/
+ log_verbose("\nTesting padding unum_toPattern()\n");
+ resultlength=0;
+ resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_toPattern(pattern, FALSE, result, resultlength, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("error in extracting the padding pattern from UNumberFormat: %s\n", myErrorName(status));
+ }
+ else
+ {
+ if(u_strcmp(result, temp1)!=0)
+ log_err("FAIL: Error in extracting the padding pattern using unum_toPattern()\n");
+ else
+ log_verbose("Pass: extracted the padding pattern correctly using unum_toPattern()\n");
+free(result);
+ }
+/* u_uastrcpy(temp1, "(xxxxxxx10,456.37)"); */
+ u_uastrcpy(temp1, "xxxxx(10,456.37)");
+ resultlength=0;
+ pos1.field = 1; /* Fraction field */
+ resultlengthneeded=unum_formatDouble(pattern, d, NULL, resultlength, &pos1, &status);
+ if(status==U_BUFFER_OVERFLOW_ERROR)
+ {
+ status=U_ZERO_ERROR;
+ resultlength=resultlengthneeded+1;
+ result=(UChar*)malloc(sizeof(UChar) * resultlength);
+ unum_formatDouble(pattern, d, result, resultlength, NULL, &status);
+ }
+ if(U_FAILURE(status))
+ {
+ log_err("Error in formatting using unum_formatDouble(.....) with padding : %s\n", myErrorName(status));
+ }
+ else
+ {
+ if(u_strcmp(result, temp1)==0)
+ log_verbose("Pass: Number Formatting using unum_formatDouble() padding Successful\n");
+ else
+ log_err("FAIL: Error in number formatting using unum_formatDouble() with padding\n");
+ if(pos1.beginIndex == 13 && pos1.endIndex == 15)
+ log_verbose("Pass: Complete number formatting using unum_formatDouble() successful\n");
+ else
+ log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=13 end=15\n",
+ pos1.beginIndex, pos1.endIndex);
+
+
+ /* Testing unum_parse() and unum_parseDouble() */
+ log_verbose("\nTesting padding unum_parseDouble()\n");
+ parsepos=0;
+ d1=unum_parseDouble(pattern, result, u_strlen(result), &parsepos, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("padding parse failed. The error is : %s\n", myErrorName(status));
+ }
+
+ if(d1!=d)
+ log_err("Fail: Error in padding parsing\n");
+ else
+ log_verbose("Pass: padding parsing successful\n");
+free(result);
+ }
+ }
+
+ unum_close(pattern);
+}
+
+static UBool
+withinErr(double a, double b, double err) {
+ return uprv_fabs(a - b) < uprv_fabs(a * err);
+}
+
+static void TestInt64Format() {
+ UChar temp1[512];
+ UChar result[512];
+ UNumberFormat *fmt;
+ UErrorCode status = U_ZERO_ERROR;
+ const double doubleInt64Max = (double)U_INT64_MAX;
+ const double doubleInt64Min = (double)U_INT64_MIN;
+ const double doubleBig = 10.0 * (double)U_INT64_MAX;
+ int32_t val32;
+ int64_t val64;
+ double valDouble;
+ int32_t parsepos;
+
+ /* create a number format using unum_openPattern(....) */
+ log_verbose("\nTesting Int64Format\n");
+ u_uastrcpy(temp1, "#.#E0");
+ fmt = unum_open(UNUM_IGNORE, temp1, u_strlen(temp1), NULL, NULL, &status);
+ if(U_FAILURE(status)) {
+ log_err("error in unum_openPattern(): %s\n", myErrorName(status));
+ } else {
+ unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 20);
+ unum_formatInt64(fmt, U_INT64_MAX, result, 512, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("error in unum_format(): %s\n", myErrorName(status));
+ } else {
+ log_verbose("format int64max: '%s'\n", result);
+ parsepos = 0;
+ val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
+ if (status != U_INVALID_FORMAT_ERROR) {
+ log_err("parse didn't report error: %s\n", myErrorName(status));
+ } else if (val32 != INT32_MAX) {
+ log_err("parse didn't pin return value, got: %d\n", val32);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
+ if (U_FAILURE(status)) {
+ log_err("parseInt64 returned error: %s\n", myErrorName(status));
+ } else if (val64 != U_INT64_MAX) {
+ log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
+ if (U_FAILURE(status)) {
+ log_err("parseDouble returned error: %s\n", myErrorName(status));
+ } else if (valDouble != doubleInt64Max) {
+ log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
+ }
+ }
+
+ unum_formatInt64(fmt, U_INT64_MIN, result, 512, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("error in unum_format(): %s\n", myErrorName(status));
+ } else {
+ log_verbose("format int64min: '%s'\n", result);
+ parsepos = 0;
+ val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
+ if (status != U_INVALID_FORMAT_ERROR) {
+ log_err("parse didn't report error: %s\n", myErrorName(status));
+ } else if (val32 != INT32_MIN) {
+ log_err("parse didn't pin return value, got: %d\n", val32);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
+ if (U_FAILURE(status)) {
+ log_err("parseInt64 returned error: %s\n", myErrorName(status));
+ } else if (val64 != U_INT64_MIN) {
+ log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
+ if (U_FAILURE(status)) {
+ log_err("parseDouble returned error: %s\n", myErrorName(status));
+ } else if (valDouble != doubleInt64Min) {
+ log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
+ }
+ }
+
+ unum_formatDouble(fmt, doubleBig, result, 512, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("error in unum_format(): %s\n", myErrorName(status));
+ } else {
+ log_verbose("format doubleBig: '%s'\n", result);
+ parsepos = 0;
+ val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
+ if (status != U_INVALID_FORMAT_ERROR) {
+ log_err("parse didn't report error: %s\n", myErrorName(status));
+ } else if (val32 != INT32_MAX) {
+ log_err("parse didn't pin return value, got: %d\n", val32);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
+ if (status != U_INVALID_FORMAT_ERROR) {
+ log_err("parseInt64 didn't report error error: %s\n", myErrorName(status));
+ } else if (val64 != U_INT64_MAX) {
+ log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
+ }
+
+ status = U_ZERO_ERROR;
+ parsepos = 0;
+ valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
+ if (U_FAILURE(status)) {
+ log_err("parseDouble returned error: %s\n", myErrorName(status));
+ } else if (!withinErr(valDouble, doubleBig, 1e-15)) {
+ log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
+ }
+ }
+ }
+ unum_close(fmt);
+}
+
+
+static void test_fmt(UNumberFormat* fmt, UBool isDecimal) {
+ char temp[512];
+ UChar buffer[512];
+ int32_t BUFSIZE = sizeof(buffer)/sizeof(buffer[0]);
+ double vals[] = {
+ -.2, 0, .2, 5.5, 15.2, 250, 123456789
+ };
+ int i;
+
+ for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
+ UErrorCode status = U_ZERO_ERROR;
+ unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
+ } else {
+ u_austrcpy(temp, buffer);
+ log_verbose("formatting %g returned '%s'\n", vals[i], temp);
+ }
+ }
+
+ /* check APIs now */
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError perr;
+ u_uastrcpy(buffer, "#,##0.0#");
+ unum_applyPattern(fmt, FALSE, buffer, -1, &perr, &status);
+ if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
+ log_err("got unexpected error for applyPattern: '%s'\n", u_errorName(status));
+ }
+ }
+
+ {
+ int isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
+ log_verbose("lenient: 0x%x\n", isLenient);
+ if (isDecimal ? (isLenient != -1) : (isLenient == TRUE)) {
+ log_err("didn't expect lenient value: %d\n", isLenient);
+ }
+
+ unum_setAttribute(fmt, UNUM_LENIENT_PARSE, TRUE);
+ isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
+ if (isDecimal ? (isLenient != -1) : (isLenient == FALSE)) {
+ log_err("didn't expect lenient value after set: %d\n", isLenient);
+ }
+ }
+
+ {
+ double val2;
+ double val = unum_getDoubleAttribute(fmt, UNUM_LENIENT_PARSE);
+ if (val != -1) {
+ log_err("didn't expect double attribute\n");
+ }
+ val = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
+ if ((val == -1) == isDecimal) {
+ log_err("didn't expect -1 rounding increment\n");
+ }
+ unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, val+.5);
+ val2 = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
+ if (isDecimal && (val2 - val != .5)) {
+ log_err("set rounding increment had no effect on decimal format");
+ }
+ }
+
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ int len = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
+ if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
+ log_err("got unexpected error for get default ruleset: '%s'\n", u_errorName(status));
+ }
+ if (U_SUCCESS(status)) {
+ u_austrcpy(temp, buffer);
+ log_verbose("default ruleset: '%s'\n", temp);
+ }
+
+ status = U_ZERO_ERROR;
+ len = unum_getTextAttribute(fmt, UNUM_PUBLIC_RULESETS, buffer, BUFSIZE, &status);
+ if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
+ log_err("got unexpected error for get public rulesets: '%s'\n", u_errorName(status));
+ }
+ if (U_SUCCESS(status)) {
+ u_austrcpy(temp, buffer);
+ log_verbose("public rulesets: '%s'\n", temp);
+
+ /* set the default ruleset to the first one found, and retry */
+
+ if (len > 0) {
+ for (i = 0; i < len && temp[i] != ';'; ++i){};
+ if (i < len) {
+ buffer[i] = 0;
+ unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("unexpected error setting default ruleset: '%s'\n", u_errorName(status));
+ } else {
+ int len2 = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
+ if (U_FAILURE(status)) {
+ log_err("could not fetch default ruleset: '%s'\n", u_errorName(status));
+ } else if (len2 != i) {
+ u_austrcpy(temp, buffer);
+ log_err("unexpected ruleset len: %d ex: %d val: %s\n", len2, i, temp);
+ } else {
+ for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
+ status = U_ZERO_ERROR;
+ unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
+ } else {
+ u_austrcpy(temp, buffer);
+ log_verbose("formatting %g returned '%s'\n", vals[i], temp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ unum_toPattern(fmt, FALSE, buffer, BUFSIZE, &status);
+ if (U_SUCCESS(status)) {
+ u_austrcpy(temp, buffer);
+ log_verbose("pattern: '%s'\n", temp);
+ } else if (status != U_BUFFER_OVERFLOW_ERROR) {
+ log_err("toPattern failed unexpectedly: %s\n", u_errorName(status));
+ } else {
+ log_verbose("pattern too long to display\n");
+ }
+ }
+
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ int len = unum_getSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, BUFSIZE, &status);
+ if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
+ log_err("unexpected error getting symbol: '%s'\n", u_errorName(status));
+ }
+
+ unum_setSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, len, &status);
+ if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
+ log_err("unexpected error setting symbol: '%s'\n", u_errorName(status));
+ }
+ }
+}
+
+static void TestNonExistentCurrency() {
+ UNumberFormat *format;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar currencySymbol[8];
+ static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
+
+ /* Get a non-existent currency and make sure it returns the correct currency code. */
+ format = unum_open(UNUM_CURRENCY, NULL, 0, "th_TH@currency=QQQ", NULL, &status);
+ if (format == NULL || U_FAILURE(status)) {
+ log_err("unum_open did not return expected result for non-existent requested currency: '%s'\n", u_errorName(status));
+ }
+ else {
+ unum_getSymbol(format,
+ UNUM_CURRENCY_SYMBOL,
+ currencySymbol,
+ sizeof(currencySymbol)/sizeof(currencySymbol[0]),
+ &status);
+ if (u_strcmp(currencySymbol, QQQ) != 0) {
+ log_err("unum_open set the currency to QQQ\n");
+ }
+ }
+ unum_close(format);
+}
+
+static void TestRBNFFormat() {
+ UErrorCode status;
+ UParseError perr;
+ UChar pat[1024];
+ UChar tempUChars[512];
+ UNumberFormat *formats[5];
+ int COUNT = sizeof(formats)/sizeof(formats[0]);
+ int i;
+
+ for (i = 0; i < COUNT; ++i) {
+ formats[i] = 0;
+ }
+
+ /* instantiation */
+ status = U_ZERO_ERROR;
+ u_uastrcpy(pat, "#,##0.0#;(#,##0.0#)");
+ formats[0] = unum_open(UNUM_PATTERN_DECIMAL, pat, -1, "en_US", &perr, &status);
+ if (U_FAILURE(status)) {
+ log_err("unable to open decimal pattern");
+ }
+
+ status = U_ZERO_ERROR;
+ formats[1] = unum_open(UNUM_SPELLOUT, NULL, 0, "en_US", &perr, &status);
+ if (U_FAILURE(status)) {
+ log_err("unable to open spellout");
+ }
+
+ status = U_ZERO_ERROR;
+ formats[2] = unum_open(UNUM_ORDINAL, NULL, 0, "en_US", &perr, &status);
+ if (U_FAILURE(status)) {
+ log_err("unable to open ordinal");
+ }
+
+ status = U_ZERO_ERROR;
+ formats[3] = unum_open(UNUM_DURATION, NULL, 0, "en_US", &perr, &status);
+ if (U_FAILURE(status)) {
+ log_err("unable to open duration");
+ }
+
+ status = U_ZERO_ERROR;
+ u_uastrcpy(pat,
+ "%standard:\n"
+ "-x: minus >>;\n"
+ "x.x: << point >>;\n"
+ "zero; one; two; three; four; five; six; seven; eight; nine;\n"
+ "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
+ "seventeen; eighteen; nineteen;\n"
+ "20: twenty[->>];\n"
+ "30: thirty[->>];\n"
+ "40: forty[->>];\n"
+ "50: fifty[->>];\n"
+ "60: sixty[->>];\n"
+ "70: seventy[->>];\n"
+ "80: eighty[->>];\n"
+ "90: ninety[->>];\n"
+ "100: =#,##0=;\n");
+ u_uastrcpy(tempUChars,
+ "%simple:\n"
+ "=%standard=;\n"
+ "20: twenty[ and change];\n"
+ "30: thirty[ and change];\n"
+ "40: forty[ and change];\n"
+ "50: fifty[ and change];\n"
+ "60: sixty[ and change];\n"
+ "70: seventy[ and change];\n"
+ "80: eighty[ and change];\n"
+ "90: ninety[ and change];\n"
+ "100: =#,##0=;\n"
+ "%bogus:\n"
+ "0.x: tiny;\n"
+ "x.x: << point something;\n"
+ "=%standard=;\n"
+ "20: some reasonable number;\n"
+ "100: some substantial number;\n"
+ "100,000,000: some huge number;\n");
+ /* This is to get around some compiler warnings about char * string length. */
+ u_strcat(pat, tempUChars);
+ formats[4] = unum_open(UNUM_PATTERN_RULEBASED, pat, -1, "en_US", &perr, &status);
+ if (U_FAILURE(status)) {
+ log_err("unable to open rulebased pattern");
+ }
+
+ for (i = 0; i < COUNT; ++i) {
+ log_verbose("\n\ntesting format %d\n", i);
+ test_fmt(formats[i], (UBool)(i == 0));
+ }
+
+ for (i = 0; i < COUNT; ++i) {
+ unum_close(formats[i]);
+ }
+}
+
+static void TestCurrencyRegression(void) {
+/*
+ I've found a case where unum_parseDoubleCurrency is not doing what I
+expect. The value I pass in is $1234567890q123460000.00 and this
+returns with a status of zero error & a parse pos of 22 (I would
+expect a parse error at position 11).
+
+I stepped into DecimalFormat::subparse() and it looks like it parses
+the first 10 digits and then stops parsing at the q but doesn't set an
+error. Then later in DecimalFormat::parse() the value gets crammed
+into a long (which greatly truncates the value).
+
+This is very problematic for me 'cause I try to remove chars that are
+invalid but this allows my users to enter bad chars and truncates
+their data!
+*/
+
+ UChar buf[1024];
+ UChar currency[8];
+ char acurrency[16];
+ double d;
+ UNumberFormat *cur;
+ int32_t pos;
+ UErrorCode status = U_ZERO_ERROR;
+ const int32_t expected = 11;
+
+ currency[0]=0;
+ u_uastrcpy(buf, "$1234567890q643210000.00");
+ cur = unum_open(UNUM_CURRENCY, NULL,0,"en_US", NULL, &status);
+
+ if(U_FAILURE(status)) {
+ log_err("unum_open failed: %s\n", u_errorName(status));
+ return;
+ }
+
+ status = U_ZERO_ERROR; /* so we can test it later. */
+ pos = 0;
+
+ d = unum_parseDoubleCurrency(cur,
+ buf,
+ -1,
+ &pos, /* 0 = start */
+ currency,
+ &status);
+
+ u_austrcpy(acurrency, currency);
+
+ if(U_FAILURE(status) || (pos != expected)) {
+ log_err("unum_parseDoubleCurrency should have failed with pos %d, but gave: value %.9f, err %s, pos=%d, currency [%s]\n",
+ expected, d, u_errorName(status), pos, acurrency);
+ } else {
+ log_verbose("unum_parseDoubleCurrency failed, value %.9f err %s, pos %d, currency [%s]\n", d, u_errorName(status), pos, acurrency);
+ }
+
+ unum_close(cur);
+}
+
+static void TestTextAttributeCrash(void) {
+ UChar ubuffer[64] = {0x0049,0x004E,0x0052,0};
+ static const UChar expectedNeg[] = {0x0049,0x004E,0x0052,0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
+ static const UChar expectedPos[] = {0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
+ int32_t used;
+ UErrorCode status = U_ZERO_ERROR;
+ UNumberFormat *nf = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILED 1\n");
+ return;
+ }
+ unum_setTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, 3, &status);
+ /*
+ * the usual negative prefix and suffix seem to be '($' and ')' at this point
+ * also crashes if UNUM_NEGATIVE_SUFFIX is substituted for UNUM_NEGATIVE_PREFIX here
+ */
+ used = unum_getTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, 64, &status);
+ unum_setTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, used, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILED 2\n"); exit(1);
+ }
+ log_verbose("attempting to format...\n");
+ used = unum_formatDouble(nf, -1234.5, ubuffer, 64, NULL, &status);
+ if (U_FAILURE(status) || 64 < used) {
+ log_err("Failed formatting %s\n", u_errorName(status));
+ return;
+ }
+ if (u_strcmp(expectedNeg, ubuffer) == 0) {
+ log_err("Didn't get expected negative result\n");
+ }
+ used = unum_formatDouble(nf, 1234.5, ubuffer, 64, NULL, &status);
+ if (U_FAILURE(status) || 64 < used) {
+ log_err("Failed formatting %s\n", u_errorName(status));
+ return;
+ }
+ if (u_strcmp(expectedPos, ubuffer) == 0) {
+ log_err("Didn't get expected positive result\n");
+ }
+ unum_close(nf);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h
new file mode 100644
index 00000000000..93851dc733e
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cnumtst.h
@@ -0,0 +1,61 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2005, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CNUMTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+/* C API TEST FOR NUMBER FORMAT */
+#ifndef _CNUMFRMTST
+#define _CNUMFRMTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cintltst.h"
+
+
+/**
+ * The function used to test the Number format API
+ **/
+static void TestNumberFormat(void);
+
+/**
+ * The function used to test significant digits in the Number format API
+ **/
+static void TestSignificantDigits(void);
+
+/**
+ * The function used to test the Number format API with padding
+ **/
+static void TestNumberFormatPadding(void);
+
+/**
+ * The function used to test the Number format API with padding
+ **/
+static void TestInt64Format(void);
+
+static void TestNonExistentCurrency(void);
+
+/**
+ * Test RBNF access through unumfmt APIs.
+ **/
+static void TestRBNFFormat(void);
+
+/**
+ * Test some Currency stuff
+ **/
+static void TestCurrencyRegression(void);
+
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c b/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c
new file mode 100644
index 00000000000..8e9f3609118
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/colutil.c
@@ -0,0 +1,17 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+#include "ucol_imp.h"
+
+#if !UCONFIG_NO_COLLATION
+
+int TestBufferSize(void); /* keep gcc happy */
+
+int TestBufferSize(void)
+{
+ return (U_COL_SAFECLONE_BUFFERSIZE < sizeof(UCollator));
+}
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c
new file mode 100644
index 00000000000..8d6d7b67278
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cposxtst.c
@@ -0,0 +1,107 @@
+/*
+**********************************************************************
+* Copyright (c) 2003, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+* Author: Alan Liu
+* Created: March 20 2003
+* Since: ICU 2.6
+**********************************************************************
+*/
+#include "cintltst.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "unicode/ucat.h"
+#include "unicode/ustring.h"
+
+/**********************************************************************/
+/* Prototypes */
+
+void TestMessageCatalog(void);
+
+/**********************************************************************/
+/* Add our tests into the hierarchy */
+
+void addPosixTest(TestNode** root);
+
+void addPosixTest(TestNode** root)
+{
+ addTest(root, &TestMessageCatalog, "tsutil/cposxtst/TestMessageCatalog");
+}
+
+/**********************************************************************/
+/* Test basic ucat.h API */
+
+void TestMessageCatalog(void) {
+
+ UErrorCode ec = U_ZERO_ERROR;
+ u_nl_catd catd;
+ const char* DATA[] = {
+ /* set_num, msg_num, expected string result, expected error code */
+ "1", "4", "Good morning.", "U_ZERO_ERROR",
+ "1", "5", "Good afternoon.", "U_ZERO_ERROR",
+ "1", "6", "FAIL", "U_MISSING_RESOURCE_ERROR",
+ "1", "7", "Good evening.", "U_ZERO_ERROR",
+ "1", "8", "Good night.", "U_ZERO_ERROR",
+ "1", "9", "FAIL", "U_MISSING_RESOURCE_ERROR",
+ "3", "1", "FAIL", "U_MISSING_RESOURCE_ERROR",
+ "4", "14", "Please ", "U_ZERO_ERROR",
+ "4", "15", "FAIL", "U_MISSING_RESOURCE_ERROR",
+ "4", "19", "Thank you.", "U_ZERO_ERROR",
+ "4", "20", "Sincerely,", "U_ZERO_ERROR",
+ NULL
+ };
+ const UChar FAIL[] = {0x46, 0x41, 0x49, 0x4C, 0x00}; /* "FAIL" */
+ int32_t i;
+ const char *path = loadTestData(&ec);
+
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: loadTestData => %s\n", u_errorName(ec));
+ return;
+ }
+
+ catd = u_catopen(path, "mc", &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: u_catopen => %s\n", u_errorName(ec));
+ return;
+ }
+
+ for (i=0; DATA[i]!=NULL; i+=4) {
+ int32_t set_num = T_CString_stringToInteger(DATA[i], 10);
+ int32_t msg_num = T_CString_stringToInteger(DATA[i+1], 10);
+ UChar exp[128];
+ int32_t len = -1;
+ const char* err;
+ char str[128];
+ const UChar* ustr;
+
+ u_uastrcpy(exp, DATA[i+2]);
+
+ ec = U_ZERO_ERROR;
+ ustr = u_catgets(catd, set_num, msg_num, FAIL, &len, &ec);
+ u_austrcpy(str, ustr);
+ err = u_errorName(ec);
+
+ log_verbose("u_catgets(%d, %d) => \"%s\", len=%d, %s\n",
+ set_num, msg_num, str, len, err);
+
+ if (u_strcmp(ustr, exp) != 0) {
+ log_err("FAIL: u_catgets => \"%s\", exp. \"%s\"\n",
+ str, DATA[i+2]);
+ }
+
+ if (len != (int32_t) uprv_strlen(DATA[i+2])) {
+ log_err("FAIL: u_catgets => len=%d, exp. %d\n",
+ len, uprv_strlen(DATA[i+2]));
+ }
+
+ if (uprv_strcmp(err, DATA[i+3]) != 0) {
+ log_err("FAIL: u_catgets => %s, exp. %s\n",
+ err, DATA[i+3]);
+ }
+ }
+
+ u_catclose(catd);
+}
+
+/*eof*/
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c
new file mode 100644
index 00000000000..1f5cf321aa3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.c
@@ -0,0 +1,1014 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CRESTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+* 06/14/99 stephen Updated for RB API changes (no suffix).
+********************************************************************************
+*/
+
+
+#include "unicode/utypes.h"
+#include "cintltst.h"
+#include "unicode/ustring.h"
+#include "cstring.h"
+#include "filestrm.h"
+#include <stdlib.h>
+
+#define RESTEST_HEAP_CHECK 0
+
+#include "unicode/ures.h"
+#include "crestst.h"
+#include "unicode/ctest.h"
+
+#include "ucol_imp.h" /* collation */
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void TestOpenDirect(void);
+static void TestFallback(void);
+static void TestTable32(void);
+static void TestFileStream(void);
+/*****************************************************************************/
+
+const UChar kERROR[] = { 0x0045 /*E*/, 0x0052 /*'R'*/, 0x0052 /*'R'*/,
+ 0x004F /*'O'*/, 0x0052/*'R'*/, 0x0000 /*'\0'*/};
+
+/*****************************************************************************/
+
+enum E_Where
+{
+ e_Root,
+ e_te,
+ e_te_IN,
+ e_Where_count
+};
+typedef enum E_Where E_Where;
+/*****************************************************************************/
+
+#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); }
+
+#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); }
+
+
+/* Array of our test objects */
+
+static struct
+{
+ const char* name;
+ UErrorCode expected_constructor_status;
+ E_Where where;
+ UBool like[e_Where_count];
+ UBool inherits[e_Where_count];
+} param[] =
+{
+ /* "te" means test */
+ /* "IN" means inherits */
+ /* "NE" or "ne" means "does not exist" */
+
+ { "root", U_ZERO_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } },
+ { "te", U_ZERO_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
+ { "te_IN", U_ZERO_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
+ { "te_NE", U_USING_FALLBACK_WARNING, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
+ { "te_IN_NE", U_USING_FALLBACK_WARNING, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
+ { "ne", U_USING_DEFAULT_WARNING, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }
+};
+
+static int32_t bundles_count = sizeof(param) / sizeof(param[0]);
+
+
+
+/***************************************************************************************/
+
+/* Array of our test objects */
+
+void addResourceBundleTest(TestNode** root);
+
+void addResourceBundleTest(TestNode** root)
+{
+ addTest(root, &TestConstruction1, "tsutil/crestst/TestConstruction1");
+ addTest(root, &TestOpenDirect, "tsutil/crestst/TestOpenDirect");
+ addTest(root, &TestResourceBundles, "tsutil/crestst/TestResourceBundles");
+ addTest(root, &TestTable32, "tsutil/crestst/TestTable32");
+ addTest(root, &TestFallback, "tsutil/crestst/TestFallback");
+ addTest(root, &TestAliasConflict, "tsutil/crestst/TestAliasConflict");
+ addTest(root, &TestFileStream, "tsutil/crestst/TestFileStream");
+ addTest(root, &TestGetSize, "tsutil/crestst/TestGetSize");
+ addTest(root, &TestGetLocaleByType, "tsutil/crestst/TestGetLocaleByType");
+}
+
+
+/***************************************************************************************/
+void TestAliasConflict(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *he = NULL;
+ UResourceBundle *iw = NULL;
+ const UChar *result = NULL;
+ int32_t resultLen;
+
+ he = ures_open(NULL, "he", &status);
+ iw = ures_open(NULL, "iw", &status);
+ if(U_FAILURE(status)) {
+ log_err("Failed to get resource with %s\n", myErrorName(status));
+ }
+ ures_close(iw);
+ result = ures_getStringByKey(he, "ExemplarCharacters", &resultLen, &status);
+ if(U_FAILURE(status) || result == NULL) {
+ log_err("Failed to get resource with %s\n", myErrorName(status));
+ }
+ ures_close(he);
+}
+
+
+void TestResourceBundles()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ testTag("only_in_Root", TRUE, FALSE, FALSE);
+ testTag("in_Root_te", TRUE, TRUE, FALSE);
+ testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE);
+ testTag("in_Root_te_IN", TRUE, FALSE, TRUE);
+ testTag("only_in_te", FALSE, TRUE, FALSE);
+ testTag("only_in_te_IN", FALSE, FALSE, TRUE);
+ testTag("in_te_te_IN", FALSE, TRUE, TRUE);
+ testTag("nonexistent", FALSE, FALSE, FALSE);
+
+ log_verbose("Passed:= %d Failed= %d \n", pass, fail);
+}
+
+void TestConstruction1()
+{
+ UResourceBundle *test1 = 0, *test2 = 0;
+ const UChar *result1, *result2;
+ int32_t resultLen;
+ UChar temp[7];
+
+ UErrorCode err = U_ZERO_ERROR;
+ const char* testdatapath ;
+ const char* locale="te_IN";
+
+ log_verbose("Testing ures_open()......\n");
+
+
+ testdatapath=loadTestData(&err);
+ if(U_FAILURE(err))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(err));
+ return;
+ }
+
+ test1=ures_open(testdatapath, NULL, &err);
+ if(U_FAILURE(err))
+ {
+ log_err("construction of %s did not succeed : %s \n",NULL, myErrorName(err));
+ return;
+ }
+
+
+ test2=ures_open(testdatapath, locale, &err);
+ if(U_FAILURE(err))
+ {
+ log_err("construction of %s did not succeed : %s \n",locale, myErrorName(err));
+ return;
+ }
+ result1= ures_getStringByKey(test1, "string_in_Root_te_te_IN", &resultLen, &err);
+ result2= ures_getStringByKey(test2, "string_in_Root_te_te_IN", &resultLen, &err);
+
+
+ if (U_FAILURE(err)) {
+ log_err("Something threw an error in TestConstruction(): %s\n", myErrorName(err));
+ return;
+ }
+
+ u_uastrcpy(temp, "TE_IN");
+
+ if(u_strcmp(result2, temp)!=0)
+ {
+ int n;
+
+ log_err("Construction test failed for ures_open();\n");
+ if(!VERBOSITY)
+ log_info("(run verbose for more information)\n");
+
+ log_verbose("\nGot->");
+ for(n=0;result2[n];n++)
+ {
+ log_verbose("%04X ",result2[n]);
+ }
+ log_verbose("<\n");
+
+ log_verbose("\nWant>");
+ for(n=0;temp[n];n++)
+ {
+ log_verbose("%04X ",temp[n]);
+ }
+ log_verbose("<\n");
+
+ }
+
+ log_verbose("for string_in_Root_te_te_IN, default.txt had %s\n", austrdup(result1));
+ log_verbose("for string_in_Root_te_te_IN, te_IN.txt had %s\n", austrdup(result2));
+
+ /* Test getVersionNumber*/
+ log_verbose("Testing version number\n");
+ log_verbose("for getVersionNumber : %s\n", ures_getVersionNumber(test1));
+
+ ures_close(test1);
+ ures_close(test2);
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+
+UBool testTag(const char* frag,
+ UBool in_Root,
+ UBool in_te,
+ UBool in_te_IN)
+{
+ int32_t passNum=pass;
+
+ /* Make array from input params */
+
+ UBool is_in[3];
+ const char *NAME[] = { "ROOT", "TE", "TE_IN" };
+
+ /* Now try to load the desired items */
+ UResourceBundle* theBundle = NULL;
+ char tag[99];
+ char action[256];
+ UErrorCode status = U_ZERO_ERROR,expected_resource_status = U_ZERO_ERROR;
+ UChar* base = NULL;
+ UChar* expected_string = NULL;
+ const UChar* string = NULL;
+ char item_tag[10];
+ int32_t i,j;
+ int32_t actual_bundle;
+ int32_t resultLen;
+ const char *testdatapath = loadTestData(&status);
+
+ is_in[0] = in_Root;
+ is_in[1] = in_te;
+ is_in[2] = in_te_IN;
+
+ strcpy(item_tag, "tag");
+
+ status = U_ZERO_ERROR;
+ theBundle = ures_open(testdatapath, "root", &status);
+ if(U_FAILURE(status))
+ {
+ ures_close(theBundle);
+ log_err("Couldn't open root bundle in %s", testdatapath);
+ return FALSE;
+ }
+ ures_close(theBundle);
+ theBundle = NULL;
+
+
+ for (i=0; i<bundles_count; ++i)
+ {
+ strcpy(action,"construction for");
+ strcat(action, param[i].name);
+
+
+ status = U_ZERO_ERROR;
+
+ theBundle = ures_open(testdatapath, param[i].name, &status);
+ /*theBundle = ures_open("c:\\icu\\icu\\source\\test\\testdata\\testdata", param[i].name, &status);*/
+
+ CONFIRM_ErrorCode(status,param[i].expected_constructor_status);
+
+
+
+ if(i == 5)
+ actual_bundle = 0; /* ne -> default */
+ else if(i == 3)
+ actual_bundle = 1; /* te_NE -> te */
+ else if(i == 4)
+ actual_bundle = 2; /* te_IN_NE -> te_IN */
+ else
+ actual_bundle = i;
+
+ expected_resource_status = U_MISSING_RESOURCE_ERROR;
+ for (j=e_te_IN; j>=e_Root; --j)
+ {
+ if (is_in[j] && param[i].inherits[j])
+ {
+
+ if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
+ expected_resource_status = U_ZERO_ERROR;
+ else if(j == 0)
+ expected_resource_status = U_USING_DEFAULT_WARNING;
+ else
+ expected_resource_status = U_USING_FALLBACK_WARNING;
+
+ log_verbose("%s[%d]::%s: in<%d:%s> inherits<%d:%s>. actual_bundle=%s\n",
+ param[i].name,
+ i,
+ frag,
+ j,
+ is_in[j]?"Yes":"No",
+ j,
+ param[i].inherits[j]?"Yes":"No",
+ param[actual_bundle].name);
+
+ break;
+ }
+ }
+
+ for (j=param[i].where; j>=0; --j)
+ {
+ if (is_in[j])
+ {
+ if(base != NULL) {
+ free(base);
+ base = NULL;
+ }
+
+ base=(UChar*)malloc(sizeof(UChar)*(strlen(NAME[j]) + 1));
+ u_uastrcpy(base,NAME[j]);
+
+ break;
+ }
+ else {
+ if(base != NULL) {
+ free(base);
+ base = NULL;
+ }
+ base = (UChar*) malloc(sizeof(UChar) * 1);
+ *base = 0x0000;
+ }
+ }
+
+ /*-------------------------------------------------------------------- */
+ /* string */
+
+ strcpy(tag,"string_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action, ".ures_get(" );
+ strcat(action,tag);
+ strcat(action, ")");
+
+ string= kERROR;
+
+ status = U_ZERO_ERROR;
+
+ ures_getStringByKey(theBundle, tag, &resultLen, &status);
+ if(U_SUCCESS(status))
+ {
+ status = U_ZERO_ERROR;
+ string=ures_getStringByKey(theBundle, tag, &resultLen, &status);
+ }
+
+ log_verbose("%s got %d, expected %d\n", action, status, expected_resource_status);
+
+ CONFIRM_ErrorCode(status, expected_resource_status);
+
+
+ if(U_SUCCESS(status)){
+ expected_string=(UChar*)malloc(sizeof(UChar)*(u_strlen(base) + 3));
+ u_strcpy(expected_string,base);
+
+ }
+ else
+ {
+ expected_string = (UChar*)malloc(sizeof(UChar)*(u_strlen(kERROR) + 1));
+ u_strcpy(expected_string,kERROR);
+
+ }
+
+ CONFIRM_EQ(string, expected_string);
+
+ free(expected_string);
+ ures_close(theBundle);
+ }
+ free(base);
+ return (UBool)(passNum == pass);
+}
+
+void record_pass()
+{
+ ++pass;
+}
+
+void record_fail()
+{
+ ++fail;
+}
+
+/**
+ * Test to make sure that the U_USING_FALLBACK_ERROR and U_USING_DEFAULT_ERROR
+ * are set correctly
+ */
+
+static void TestFallback()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *fr_FR = NULL;
+ UResourceBundle *subResource = NULL;
+ const UChar *junk; /* ignored */
+ int32_t resultLen;
+
+ log_verbose("Opening fr_FR..");
+ fr_FR = ures_open(NULL, "fr_FR", &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Couldn't open fr_FR - %d\n", status);
+ return;
+ }
+
+ status = U_ZERO_ERROR;
+
+
+ /* clear it out.. just do some calls to get the gears turning */
+ junk = ures_getStringByKey(fr_FR, "LocaleID", &resultLen, &status);
+ status = U_ZERO_ERROR;
+ junk = ures_getStringByKey(fr_FR, "LocaleString", &resultLen, &status);
+ status = U_ZERO_ERROR;
+ junk = ures_getStringByKey(fr_FR, "LocaleID", &resultLen, &status);
+ status = U_ZERO_ERROR;
+
+ /* OK first one. This should be a Default value. */
+ subResource = ures_getByKey(fr_FR, "MeasurementSystem", NULL, &status);
+ if(status != U_USING_DEFAULT_WARNING)
+ {
+ log_data_err("Expected U_USING_DEFAULT_ERROR when trying to get CurrencyMap from fr_FR, got %s\n",
+ u_errorName(status));
+ }
+ ures_close(subResource);
+ status = U_ZERO_ERROR;
+
+ /* and this is a Fallback, to fr */
+ junk = ures_getStringByKey(fr_FR, "Countries", &resultLen, &status);
+ if(status != U_USING_FALLBACK_WARNING)
+ {
+ log_data_err("Expected U_USING_FALLBACK_ERROR when trying to get Countries from fr_FR, got %s\n",
+ u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+
+ ures_close(fr_FR);
+}
+
+static void
+TestOpenDirect(void) {
+ UResourceBundle *idna_rules, *casing, *te_IN, *ne, *item;
+ UErrorCode errorCode;
+
+ /*
+ * test that ures_openDirect() opens a resource bundle
+ * where one can look up its own items but not fallback items
+ * from root or similar
+ */
+ errorCode=U_ZERO_ERROR;
+ idna_rules=ures_openDirect(loadTestData(&errorCode), "idna_rules", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ures_openDirect(\"idna_rules\") failed: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ if(0!=uprv_strcmp("idna_rules", ures_getLocale(idna_rules, &errorCode))) {
+ log_err("ures_openDirect(\"idna_rules\").getLocale()!=idna_rules\n");
+ }
+ errorCode=U_ZERO_ERROR;
+
+ /* try an item in idna_rules, must work */
+ item=ures_getByKey(idna_rules, "UnassignedSet", NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("translit_index.getByKey(local key) failed: %s\n", u_errorName(errorCode));
+ errorCode=U_ZERO_ERROR;
+ } else {
+ ures_close(item);
+ }
+
+ /* try an item in root, must fail */
+ item=ures_getByKey(idna_rules, "ShortLanguage", NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ errorCode=U_ZERO_ERROR;
+ } else {
+ log_err("idna_rules.getByKey(root key) succeeded!\n");
+ ures_close(item);
+ }
+ ures_close(idna_rules);
+
+ /* now make sure that "idna_rules" will not work with ures_open() */
+ errorCode=U_ZERO_ERROR;
+ idna_rules=ures_open("testdata", "idna_rules", &errorCode);
+ if(U_FAILURE(errorCode) || errorCode==U_USING_DEFAULT_WARNING || errorCode==U_USING_FALLBACK_WARNING) {
+ /* falling back to default or root is ok */
+ errorCode=U_ZERO_ERROR;
+ } else if(0!=uprv_strcmp("idna_rules", ures_getLocale(idna_rules, &errorCode))) {
+ /* Opening this file will work in "files mode" on Windows and the Mac,
+ which have case insensitive file systems */
+ log_err("ures_open(\"idna_rules\") succeeded, should fail! Got: %s\n", u_errorName(errorCode));
+ }
+ ures_close(idna_rules);
+
+ /* ures_openDirect("translit_index_WronG") must fail */
+ idna_rules=ures_openDirect(NULL, "idna_rules_WronG", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ errorCode=U_ZERO_ERROR;
+ } else {
+ log_err("ures_openDirect(\"idna_rules_WronG\") succeeded, should fail!\n");
+ }
+ ures_close(idna_rules);
+
+ errorCode = U_USING_FALLBACK_WARNING;;
+ idna_rules=ures_openDirect("testdata", "idna_rules", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ures_openDirect(\"idna_rules\") failed when U_USING_FALLBACK_WARNING was set prior to call: %s\n", u_errorName(errorCode));
+ return;
+ }
+ ures_close(idna_rules);
+
+ /*
+ * ICU 3.6 has new resource bundle syntax and data for bundles that do not
+ * participate in locale fallback. Now,
+ * - ures_open() works like ures_openDirect() on a bundle with a top-level
+ * type of ":table(nofallback)" _if_ the bundle exists
+ * - ures_open() will continue to find a root bundle if the requested one
+ * does not exist, unlike ures_openDirect()
+ *
+ * Test with a different bundle than above to avoid confusion in the cache.
+ */
+
+ /*
+ * verify that ures_open("casing"), which now has a nofallback declaration,
+ * does not enable fallbacks
+ */
+ errorCode=U_ZERO_ERROR;
+ casing=ures_open("testdata", "casing", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ures_open(\"casing\") failed: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ item=ures_getByKey(casing, "Info", NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("casing.getByKey(Info) failed - %s\n", u_errorName(errorCode));
+ } else {
+ ures_close(item);
+ }
+
+ errorCode=U_ZERO_ERROR;
+ item=ures_getByKey(casing, "ShortLanguage", NULL, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ log_err("casing.getByKey(root key) succeeded despite nofallback declaration - %s\n", u_errorName(errorCode));
+ ures_close(item);
+ }
+ ures_close(casing);
+
+ /*
+ * verify that ures_open("ne") finds the root bundle but
+ * ures_openDirect("ne") does not
+ */
+ errorCode=U_ZERO_ERROR;
+ ne=ures_open("testdata", "ne", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ures_open(\"ne\") failed (expected to get root): %s\n", u_errorName(errorCode));
+ }
+ if(errorCode!=U_USING_DEFAULT_WARNING || 0!=uprv_strcmp("root", ures_getLocale(ne, &errorCode))) {
+ log_err("ures_open(\"ne\") found something other than \"root\" - %s\n", u_errorName(errorCode));
+ }
+ ures_close(ne);
+
+ errorCode=U_ZERO_ERROR;
+ ne=ures_openDirect("testdata", "ne", &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ log_err("ures_openDirect(\"ne\") succeeded unexpectedly\n");
+ ures_close(ne);
+ }
+
+ /* verify that ures_openDirect("te_IN") does not enable fallbacks */
+ errorCode=U_ZERO_ERROR;
+ te_IN=ures_openDirect("testdata", "te_IN", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ures_open(\"te_IN\") failed: %s\n", u_errorName(errorCode));
+ return;
+ }
+ errorCode=U_ZERO_ERROR;
+ item=ures_getByKey(te_IN, "ShortLanguage", NULL, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ log_err("te_IN.getByKey(root key) succeeded despite use of ures_openDirect() - %s\n", u_errorName(errorCode));
+ ures_close(item);
+ }
+ ures_close(te_IN);
+}
+
+static int32_t
+parseTable32Key(const char *key) {
+ int32_t number;
+ char c;
+
+ number=0;
+ while((c=*key++)!=0) {
+ number<<=1;
+ if(c=='1') {
+ number|=1;
+ }
+ }
+ return number;
+}
+
+static void
+TestTable32(void) {
+ static const struct {
+ const char *key;
+ int32_t number;
+ } testcases[]={
+ { "ooooooooooooooooo", 0 },
+ { "oooooooooooooooo1", 1 },
+ { "ooooooooooooooo1o", 2 },
+ { "oo11ooo1ooo11111o", 25150 },
+ { "oo11ooo1ooo111111", 25151 },
+ { "o1111111111111111", 65535 },
+ { "1oooooooooooooooo", 65536 },
+ { "1ooooooo11o11ooo1", 65969 },
+ { "1ooooooo11o11oo1o", 65970 },
+ { "1ooooooo111oo1111", 65999 }
+ };
+
+ /* ### TODO UResourceBundle staticItem={ 0 }; - need to know the size */
+ UResourceBundle *res, *item;
+ const UChar *s;
+ const char *key;
+ UErrorCode errorCode;
+ int32_t i, j, number, parsedNumber, length, count;
+
+ errorCode=U_ZERO_ERROR;
+ res=ures_open(loadTestData(&errorCode), "testtable32", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("unable to open testdata/testtable32.res - %s\n", u_errorName(errorCode));
+ return;
+ }
+ if(ures_getType(res)!=URES_TABLE) {
+ log_data_err("testdata/testtable32.res has type %d instead of URES_TABLE\n", ures_getType(res));
+ }
+
+ count=ures_getSize(res);
+ if(count!=66000) {
+ log_err("testdata/testtable32.res should have 66000 entries but has %d\n", count);
+ }
+
+ /* get the items by index */
+ item=NULL;
+ for(i=0; i<count; ++i) {
+ item=ures_getByIndex(res, i, item, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to get item %d of %d in testdata/testtable32.res - %s\n",
+ i, count, u_errorName(errorCode));
+ break;
+ }
+
+ key=ures_getKey(item);
+ parsedNumber=parseTable32Key(key);
+
+ switch(ures_getType(item)) {
+ case URES_STRING:
+ s=ures_getString(item, &length, &errorCode);
+ if(U_FAILURE(errorCode) || s==NULL) {
+ log_err("unable to access the string \"%s\" at %d in testdata/testtable32.res - %s\n",
+ key, i, u_errorName(errorCode));
+ number=-1;
+ } else {
+ j=0;
+ U16_NEXT(s, j, length, number);
+ }
+ break;
+ case URES_INT:
+ number=ures_getInt(item, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to access the integer \"%s\" at %d in testdata/testtable32.res - %s\n",
+ key, i, u_errorName(errorCode));
+ number=-1;
+ }
+ break;
+ default:
+ log_err("unexpected resource type %d for \"%s\" at %d in testdata/testtable32.res - %s\n",
+ ures_getType(item), key, i, u_errorName(errorCode));
+ number=-1;
+ break;
+ }
+
+ if(number>=0 && number!=parsedNumber) {
+ log_err("\"%s\" at %d in testdata/testtable32.res has a string/int value of %d, expected %d\n",
+ key, i, number, parsedNumber);
+ }
+ }
+
+ /* search for some items by key */
+ for(i=0; i<LENGTHOF(testcases); ++i) {
+ item=ures_getByKey(res, testcases[i].key, item, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to find the key \"%s\" in testdata/testtable32.res - %s\n",
+ testcases[i].key, u_errorName(errorCode));
+ continue;
+ }
+
+ switch(ures_getType(item)) {
+ case URES_STRING:
+ s=ures_getString(item, &length, &errorCode);
+ if(U_FAILURE(errorCode) || s==NULL) {
+ log_err("unable to access the string \"%s\" in testdata/testtable32.res - %s\n",
+ testcases[i].key, u_errorName(errorCode));
+ number=-1;
+ } else {
+ j=0;
+ U16_NEXT(s, j, length, number);
+ }
+ break;
+ case URES_INT:
+ number=ures_getInt(item, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to access the integer \"%s\" in testdata/testtable32.res - %s\n",
+ testcases[i].key, u_errorName(errorCode));
+ number=-1;
+ }
+ break;
+ default:
+ log_err("unexpected resource type %d for \"%s\" in testdata/testtable32.res - %s\n",
+ ures_getType(item), testcases[i].key, u_errorName(errorCode));
+ number=-1;
+ break;
+ }
+
+ if(number>=0 && number!=testcases[i].number) {
+ log_err("\"%s\" in testdata/testtable32.res has a string/int value of %d, expected %d\n",
+ testcases[i].key, number, testcases[i].number);
+ }
+
+ key=ures_getKey(item);
+ if(0!=uprv_strcmp(key, testcases[i].key)) {
+ log_err("\"%s\" in testdata/testtable32.res claims to have the key \"%s\"\n",
+ testcases[i].key, key);
+ }
+ }
+
+ ures_close(item);
+ ures_close(res);
+}
+
+static void TestFileStream(void){
+ int32_t c = 0;
+ int32_t c1=0;
+ UErrorCode status = U_ZERO_ERROR;
+ const char* testdatapath = loadTestData(&status);
+ char* fileName = (char*) malloc(uprv_strlen(testdatapath) +10);
+ FileStream* stream = NULL;
+ /* these should not be closed */
+ FileStream* pStdin = T_FileStream_stdin();
+ FileStream* pStdout = T_FileStream_stdout();
+ FileStream* pStderr = T_FileStream_stderr();
+
+ const char* testline = "This is a test line";
+ int32_t bufLen = (int32_t)strlen(testline)+10;
+ char* buf = (char*) malloc(bufLen);
+ int32_t retLen = 0;
+
+ if(pStdin==NULL){
+ log_err("failed to get T_FileStream_stdin()");
+ }
+ if(pStdout==NULL){
+ log_err("failed to get T_FileStream_stdout()");
+ }
+ if(pStderr==NULL){
+ log_err("failed to get T_FileStream_stderr()");
+ }
+
+ uprv_strcpy(fileName,testdatapath);
+ uprv_strcat(fileName,".dat");
+ stream = T_FileStream_open(fileName, "r");
+ if(stream==NULL){
+ log_data_err("T_FileStream_open failed to open %s\n",fileName);
+ } else {
+ if(!T_FileStream_file_exists(fileName)){
+ log_data_err("T_FileStream_file_exists failed to verify existence of %s \n",fileName);
+ }
+
+ retLen=T_FileStream_read(stream,&c,1);
+ if(retLen==0){
+ log_data_err("T_FileStream_read failed to read from %s \n",fileName);
+ }
+ retLen=0;
+ T_FileStream_rewind(stream);
+ T_FileStream_read(stream,&c1,1);
+ if(c!=c1){
+ log_data_err("T_FileStream_rewind failed to rewind %s \n",fileName);
+ }
+ T_FileStream_rewind(stream);
+ c1 = T_FileStream_peek(stream);
+ if(c!=c1){
+ log_data_err("T_FileStream_peek failed to peekd %s \n",fileName);
+ }
+ c = T_FileStream_getc(stream);
+ T_FileStream_ungetc(c,stream);
+ if(c!= T_FileStream_getc(stream)){
+ log_data_err("T_FileStream_ungetc failed to d %s \n",fileName);
+ }
+
+ if(T_FileStream_size(stream)<=0){
+ log_data_err("T_FileStream_size failed to d %s \n",fileName);
+ }
+ if(T_FileStream_error(stream)){
+ log_data_err("T_FileStream_error shouldn't have an error %s\n",fileName);
+ }
+ if(!T_FileStream_error(NULL)){
+ log_err("T_FileStream_error didn't get an error %s\n",fileName);
+ }
+ T_FileStream_putc(stream, 0x20);
+ if(!T_FileStream_error(stream)){
+ /*
+ Warning
+ writing to a read-only file may not consistently fail on all platforms
+ (e.g. HP-UX, FreeBSD, MacOSX)
+ */
+ log_verbose("T_FileStream_error didn't get an error when writing to a readonly file %s\n",fileName);
+ }
+
+ T_FileStream_close(stream);
+ }
+ /* test writing function */
+ stream=NULL;
+ uprv_strcpy(fileName,testdatapath);
+ uprv_strcat(fileName,".tmp");
+ stream = T_FileStream_open(fileName,"w+");
+
+ if(stream == NULL){
+ log_data_err("Could not open %s for writing\n",fileName);
+ } else {
+ c= '$';
+ T_FileStream_putc(stream,c);
+ T_FileStream_rewind(stream);
+ if(c != T_FileStream_getc(stream)){
+ log_data_err("T_FileStream_putc failed %s\n",fileName);
+ }
+
+ T_FileStream_rewind(stream);
+ T_FileStream_writeLine(stream,testline);
+ T_FileStream_rewind(stream);
+ T_FileStream_readLine(stream,buf,bufLen);
+ if(uprv_strncmp(testline, buf,uprv_strlen(buf))!=0){
+ log_data_err("T_FileStream_writeLine failed %s\n",fileName);
+ }
+
+ T_FileStream_rewind(stream);
+ T_FileStream_write(stream,testline,(int32_t)strlen(testline));
+ T_FileStream_rewind(stream);
+ retLen = T_FileStream_read(stream, buf, bufLen);
+ if(uprv_strncmp(testline, buf,retLen)!=0){
+ log_data_err("T_FileStream_write failed %s\n",fileName);
+ }
+
+ T_FileStream_close(stream);
+ }
+ if(!T_FileStream_remove(fileName)){
+ log_data_err("T_FileStream_remove failed to delete %s\n",fileName);
+ }
+
+
+ free(fileName);
+ free(buf);
+
+}
+
+static void TestGetSize(void) {
+ const struct {
+ const char* key;
+ int32_t size;
+ } test[] = {
+ { "zerotest", 1},
+ { "one", 1},
+ { "importtest", 1},
+ { "integerarray", 1},
+ { "emptyarray", 0},
+ { "emptytable", 0},
+ { "emptystring", 1}, /* empty string is still a string */
+ { "emptyint", 1},
+ { "emptybin", 1},
+ { "testinclude", 1},
+ { "collations", 1}, /* not 2 - there is hidden %%CollationBin */
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ UResourceBundle *rb = NULL;
+ UResourceBundle *res = NULL;
+ UResourceBundle *helper = NULL;
+ const char* testdatapath = loadTestData(&status);
+ int32_t i = 0, j = 0;
+ int32_t size = 0;
+
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s\n", u_errorName(status));
+ return;
+ }
+
+ rb = ures_open(testdatapath, "testtypes", &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not testtypes resource bundle %s\n", u_errorName(status));
+ return;
+ }
+
+ for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) {
+ res = ures_getByKey(rb, test[i].key, res, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Couldn't find the key %s. Error: %s\n", test[i].key, u_errorName(status));
+ ures_close(rb);
+ return;
+ }
+ size = ures_getSize(res);
+ if(size != test[i].size) {
+ log_err("Expected size %i, got size %i for key %s\n", test[i].size, size, test[i].key);
+ for(j = 0; j < size; j++) {
+ helper = ures_getByIndex(res, j, helper, &status);
+ log_err("%s\n", ures_getKey(helper));
+ }
+ }
+ }
+ ures_close(helper);
+ ures_close(res);
+ ures_close(rb);
+}
+
+static void TestGetLocaleByType(void) {
+ static const struct {
+ const char *requestedLocale;
+ const char *resourceKey;
+ const char *validLocale;
+ const char *actualLocale;
+ } test[] = {
+ { "te_IN_BLAH", "string_only_in_te_IN", "te_IN", "te_IN" },
+ { "te_IN_BLAH", "string_only_in_te", "te_IN", "te" },
+ { "te_IN_BLAH", "string_only_in_Root", "te_IN", "root" },
+ { "te_IN_BLAH_01234567890_01234567890_01234567890_01234567890_01234567890_01234567890", "array_2d_only_in_Root", "te_IN", "root" },
+ { "te_IN_BLAH@currency=euro", "array_2d_only_in_te_IN", "te_IN", "te_IN" },
+ { "te_IN_BLAH@collation=phonebook;calendar=thai", "array_2d_only_in_te", "te_IN", "te" }
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ UResourceBundle *rb = NULL;
+ UResourceBundle *res = NULL;
+ const char* testdatapath = loadTestData(&status);
+ int32_t i = 0;
+ const char *locale = NULL;
+
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s\n", u_errorName(status));
+ return;
+ }
+
+ for(i = 0; i < sizeof(test)/sizeof(test[0]); i++) {
+ rb = ures_open(testdatapath, test[i].requestedLocale, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not open resource bundle %s (error %s)\n", test[i].requestedLocale, u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+
+ res = ures_getByKey(rb, test[i].resourceKey, res, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Couldn't find the key %s. Error: %s\n", test[i].resourceKey, u_errorName(status));
+ ures_close(rb);
+ status = U_ZERO_ERROR;
+ continue;
+ }
+
+ locale = ures_getLocaleByType(res, ULOC_REQUESTED_LOCALE, &status);
+ if(locale) {
+ log_err("Requested locale should return NULL\n");
+ }
+ locale = ures_getLocaleByType(res, ULOC_VALID_LOCALE, &status);
+ if(!locale || strcmp(locale, test[i].validLocale) != 0) {
+ log_err("Expected valid locale to be %s. Got %s\n", test[i].requestedLocale, locale);
+ }
+ locale = ures_getLocaleByType(res, ULOC_ACTUAL_LOCALE, &status);
+ if(!locale || strcmp(locale, test[i].actualLocale) != 0) {
+ log_err("Expected actual locale to be %s. Got %s\n", test[i].requestedLocale, locale);
+ }
+ ures_close(rb);
+ }
+ ures_close(res);
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h
new file mode 100644
index 00000000000..de11a959ddd
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/crestst.h
@@ -0,0 +1,55 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2004, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CRESTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************
+*/
+#ifndef _CRESTST
+#define _CRESTST
+/* C API TEST FOR RESOURCEBUNDLE */
+#include "cintltst.h"
+
+
+
+
+ void addTestResourceBundleTest(TestNode**);
+
+ /**
+ * Perform several extensive tests using the subtest routine testTag
+ */
+ void TestResourceBundles(void);
+ /**
+ * Test construction of ResourceBundle accessing a custom test resource-file
+ */
+ void TestConstruction1(void);
+
+ void TestConstruction2(void);
+
+ void TestAliasConflict(void);
+
+ static void TestGetSize(void);
+
+ static void TestGetLocaleByType(void);
+
+ /**
+ * extensive subtests called by TestResourceBundles
+ **/
+
+ UBool testTag(const char* frag, UBool in_Root, UBool in_te, UBool in_te_IN);
+
+ void record_pass(void);
+ void record_fail(void);
+
+
+ int32_t pass;
+ int32_t fail;
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c
new file mode 100644
index 00000000000..159235d4755
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.c
@@ -0,0 +1,2950 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CRESTST.C
+*
+* Modification History:
+* Name Date Description
+* Madhu Katragadda 05/09/2000 Ported Tests for New ResourceBundle API
+* Madhu Katragadda 05/24/2000 Added new tests to test RES_BINARY for collationElements
+********************************************************************************
+*/
+
+
+#include <time.h>
+#include "unicode/utypes.h"
+#include "cintltst.h"
+#include "unicode/putil.h"
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "string.h"
+#include "cstring.h"
+#include "unicode/uchar.h"
+#include "ucol_imp.h" /* for U_ICUDATA_COLL */
+#include "ubrkimpl.h" /* for U_ICUDATA_BRKITR */
+#define RESTEST_HEAP_CHECK 0
+
+#include "unicode/uloc.h"
+#include "uresimp.h"
+#include "creststn.h"
+#include "unicode/ctest.h"
+#include "ucbuf.h"
+static int32_t pass;
+static int32_t fail;
+
+/*****************************************************************************/
+/**
+ * Return a random unsigned long l where 0N <= l <= ULONG_MAX.
+ */
+
+static uint32_t
+randul()
+{
+ uint32_t l=0;
+ int32_t i;
+ static UBool initialized = FALSE;
+ if (!initialized)
+ {
+ srand((unsigned)time(NULL));
+ initialized = TRUE;
+ }
+ /* Assume rand has at least 12 bits of precision */
+
+ for (i=0; i<sizeof(l); ++i)
+ ((char*)&l)[i] = (char)((rand() & 0x0FF0) >> 4);
+ return l;
+}
+
+/**
+ * Return a random double x where 0.0 <= x < 1.0.
+ */
+static double
+randd()
+{
+ return ((double)randul()) / UINT32_MAX;
+}
+
+/**
+ * Return a random integer i where 0 <= i < n.
+ */
+static int32_t randi(int32_t n)
+{
+ return (int32_t)(randd() * n);
+}
+/***************************************************************************************/
+/**
+ * Convert an integer, positive or negative, to a character string radix 10.
+ */
+static char*
+itoa1(int32_t i, char* buf)
+{
+ char *p = 0;
+ char* result = buf;
+ /* Handle negative */
+ if(i < 0) {
+ *buf++ = '-';
+ i = -i;
+ }
+
+ /* Output digits in reverse order */
+ p = buf;
+ do {
+ *p++ = (char)('0' + (i % 10));
+ i /= 10;
+ }
+ while(i);
+ *p-- = 0;
+
+ /* Reverse the string */
+ while(buf < p) {
+ char c = *buf;
+ *buf++ = *p;
+ *p-- = c;
+ }
+
+ return result;
+}
+static const int32_t kERROR_COUNT = -1234567;
+static const UChar kERROR[] = { 0x0045 /*E*/, 0x0052 /*'R'*/, 0x0052 /*'R'*/,
+ 0x004F /*'O'*/, 0x0052/*'R'*/, 0x0000 /*'\0'*/};
+
+/*****************************************************************************/
+
+enum E_Where
+{
+ e_Root,
+ e_te,
+ e_te_IN,
+ e_Where_count
+};
+typedef enum E_Where E_Where;
+/*****************************************************************************/
+
+#define CONFIRM_EQ(actual,expected) if (u_strcmp(expected,actual)==0){ record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, austrdup(actual), austrdup(expected)); }
+#define CONFIRM_INT_EQ(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of %d\n", action, actual, expected); }
+#define CONFIRM_INT_GE(actual,expected) if ((actual)>=(expected)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x >= %d\n", action, actual, expected); }
+#define CONFIRM_INT_NE(actual,expected) if ((expected)!=(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %d instead of x != %d\n", action, actual, expected); }
+/*#define CONFIRM_ErrorCode(actual,expected) if ((expected)==(actual)) { record_pass(); } else { record_fail(); log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); } */
+static void
+CONFIRM_ErrorCode(UErrorCode actual,UErrorCode expected)
+{
+ if ((expected)==(actual))
+ {
+ record_pass();
+ } else {
+ record_fail();
+ /*log_err("%s returned %s instead of %s\n", action, myErrorName(actual), myErrorName(expected)); */
+ log_err("returned %s instead of %s\n", myErrorName(actual), myErrorName(expected));
+ }
+}
+
+
+/* Array of our test objects */
+
+static struct
+{
+ const char* name;
+ UErrorCode expected_constructor_status;
+ E_Where where;
+ UBool like[e_Where_count];
+ UBool inherits[e_Where_count];
+}
+param[] =
+{
+ /* "te" means test */
+ /* "IN" means inherits */
+ /* "NE" or "ne" means "does not exist" */
+
+ { "root", U_ZERO_ERROR, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } },
+ { "te", U_ZERO_ERROR, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
+ { "te_IN", U_ZERO_ERROR, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
+ { "te_NE", U_USING_FALLBACK_WARNING, e_te, { FALSE, TRUE, FALSE }, { TRUE, TRUE, FALSE } },
+ { "te_IN_NE", U_USING_FALLBACK_WARNING, e_te_IN, { FALSE, FALSE, TRUE }, { TRUE, TRUE, TRUE } },
+ { "ne", U_USING_DEFAULT_WARNING, e_Root, { TRUE, FALSE, FALSE }, { TRUE, FALSE, FALSE } }
+};
+
+static int32_t bundles_count = sizeof(param) / sizeof(param[0]);
+
+
+/*static void printUChars(UChar*);*/
+static void TestDecodedBundle(void);
+static void TestGetKeywordValues(void);
+static void TestGetFunctionalEquivalent(void);
+static void TestCLDRStyleAliases(void);
+static void TestFallbackCodes(void);
+static void TestGetUTF8String(void);
+
+/***************************************************************************************/
+
+/* Array of our test objects */
+
+void addNEWResourceBundleTest(TestNode** root)
+{
+ addTest(root, &TestErrorCodes, "tsutil/creststn/TestErrorCodes");
+ addTest(root, &TestEmptyBundle, "tsutil/creststn/TestEmptyBundle");
+ addTest(root, &TestConstruction1, "tsutil/creststn/TestConstruction1");
+ addTest(root, &TestResourceBundles, "tsutil/creststn/TestResourceBundles");
+ addTest(root, &TestFallback, "tsutil/creststn/TestFallback");
+ addTest(root, &TestGetVersion, "tsutil/creststn/TestGetVersion");
+ addTest(root, &TestGetVersionColl, "tsutil/creststn/TestGetVersionColl");
+ addTest(root, &TestAliasConflict, "tsutil/creststn/TestAliasConflict");
+ addTest(root, &TestNewTypes, "tsutil/creststn/TestNewTypes");
+ addTest(root, &TestEmptyTypes, "tsutil/creststn/TestEmptyTypes");
+ addTest(root, &TestBinaryCollationData, "tsutil/creststn/TestBinaryCollationData");
+ addTest(root, &TestAPI, "tsutil/creststn/TestAPI");
+ addTest(root, &TestErrorConditions, "tsutil/creststn/TestErrorConditions");
+ addTest(root, &TestDecodedBundle, "tsutil/creststn/TestDecodedBundle");
+ addTest(root, &TestResourceLevelAliasing, "tsutil/creststn/TestResourceLevelAliasing");
+ addTest(root, &TestDirectAccess, "tsutil/creststn/TestDirectAccess");
+ addTest(root, &TestGetKeywordValues, "tsutil/creststn/TestGetKeywordValues");
+ addTest(root, &TestGetFunctionalEquivalent,"tsutil/creststn/TestGetFunctionalEquivalent");
+ addTest(root, &TestJB3763, "tsutil/creststn/TestJB3763");
+ addTest(root, &TestXPath, "tsutil/creststn/TestXPath");
+ addTest(root, &TestCLDRStyleAliases, "tsutil/creststn/TestCLDRStyleAliases");
+ addTest(root, &TestFallbackCodes, "tsutil/creststn/TestFallbackCodes");
+ addTest(root, &TestStackReuse, "tsutil/creststn/TestStackReuse");
+ addTest(root, &TestGetUTF8String, "tsutil/creststn/TestGetUTF8String");
+}
+
+
+/***************************************************************************************/
+static const char* norwayNames[] = {
+ "no_NO_NY",
+ "no_NO",
+ "no",
+ "nn_NO",
+ "nn",
+ "nb_NO",
+ "nb"
+};
+
+static const char* norwayLocales[] = {
+ "nn_NO",
+ "nb_NO",
+ "nb",
+ "nn_NO",
+ "nn",
+ "nb_NO",
+ "nb"
+};
+
+static void checkStatus(int32_t line, UErrorCode expected, UErrorCode status) {
+ if(U_FAILURE(status)) {
+ log_data_err("Resource not present, cannot test (%s:%d)\n", __FILE__, line);
+ }
+ if(status != expected) {
+ log_err("%s:%d: Expected error code %s, got error code %s\n", __FILE__, line, u_errorName(expected), u_errorName(status));
+ }
+}
+
+static void TestErrorCodes(void) {
+ UErrorCode status = U_USING_DEFAULT_WARNING;
+
+ UResourceBundle *r = NULL, *r2 = NULL;
+
+ /* First check with ICUDATA */
+ /* first bundle should return fallback warning */
+ r = ures_open(NULL, "ti_ER_ASSAB", &status);
+ checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status);
+ ures_close(r);
+
+ /* this bundle should return zero error, so it shouldn't change the status*/
+ status = U_USING_DEFAULT_WARNING;
+ r = ures_open(NULL, "ti_ER", &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+
+ /* we look up the resource which is aliased, but it lives in fallback */
+ if(U_SUCCESS(status) && r != NULL) {
+ status = U_USING_DEFAULT_WARNING;
+ r2 = ures_getByKey(r, "Languages", NULL, &status); /* languages of 'ti' aliases to 'am' */
+ checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status);
+ }
+ ures_close(r);
+
+ /* this bundle should return zero error, so it shouldn't change the status*/
+ status = U_USING_DEFAULT_WARNING;
+ r = ures_open(NULL, "ti", &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+
+ /* we look up the resource which is aliased and at our level */
+ if(U_SUCCESS(status) && r != NULL) {
+ status = U_USING_DEFAULT_WARNING;
+ r2 = ures_getByKey(r, "Languages", r2, &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+ }
+ ures_close(r);
+
+ status = U_USING_FALLBACK_WARNING;
+ r = ures_open(NULL, "nolocale", &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+ ures_close(r);
+ ures_close(r2);
+
+ /** Now, with the collation bundle **/
+
+ /* first bundle should return fallback warning */
+ r = ures_open(U_ICUDATA_COLL, "sr_YU_VOJVODINA", &status);
+ checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status);
+ ures_close(r);
+
+ /* this bundle should return zero error, so it shouldn't change the status*/
+ status = U_USING_FALLBACK_WARNING;
+ r = ures_open(U_ICUDATA_COLL, "sr", &status);
+ checkStatus(__LINE__, U_USING_FALLBACK_WARNING, status);
+
+ /* we look up the resource which is aliased */
+ if(U_SUCCESS(status) && r != NULL) {
+ status = U_USING_DEFAULT_WARNING;
+ r2 = ures_getByKey(r, "collations", NULL, &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+ }
+ ures_close(r);
+
+ /* this bundle should return zero error, so it shouldn't change the status*/
+ status = U_USING_DEFAULT_WARNING;
+ r = ures_open(U_ICUDATA_COLL, "sr", &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+
+ /* we look up the resource which is aliased and at our level */
+ if(U_SUCCESS(status) && r != NULL) {
+ status = U_USING_DEFAULT_WARNING;
+ r2 = ures_getByKey(r, "collations", r2, &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+ }
+ ures_close(r);
+
+ status = U_USING_FALLBACK_WARNING;
+ r = ures_open(U_ICUDATA_COLL, "nolocale", &status);
+ checkStatus(__LINE__, U_USING_DEFAULT_WARNING, status);
+ ures_close(r);
+ ures_close(r2);
+}
+
+static void TestAliasConflict(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *he = NULL;
+ UResourceBundle *iw = NULL;
+ UResourceBundle *norway = NULL;
+ const UChar *result = NULL;
+ int32_t resultLen;
+ uint32_t size = 0;
+ uint32_t i = 0;
+ const char *realName = NULL;
+
+ he = ures_open(NULL, "he", &status);
+ iw = ures_open(NULL, "iw", &status);
+ if(U_FAILURE(status)) {
+ log_err("Failed to get resource with %s\n", myErrorName(status));
+ }
+ ures_close(iw);
+ result = ures_getStringByKey(he, "ExemplarCharacters", &resultLen, &status);
+ if(U_FAILURE(status) || result == NULL) {
+ log_err("Failed to get resource ExemplarCharacters with %s\n", myErrorName(status));
+ }
+ ures_close(he);
+
+ size = sizeof(norwayNames)/sizeof(norwayNames[0]);
+ for(i = 0; i < size; i++) {
+ status = U_ZERO_ERROR;
+ norway = ures_open(NULL, norwayNames[i], &status);
+ if(U_FAILURE(status)) {
+ log_err("Failed to get resource with %s for %s\n", myErrorName(status), norwayNames[i]);
+ continue;
+ }
+ realName = ures_getLocale(norway, &status);
+ log_verbose("ures_getLocale(\"%s\")=%s\n", norwayNames[i], realName);
+ if(realName == NULL || strcmp(norwayLocales[i], realName) != 0) {
+ log_data_err("Wrong locale name for %s, expected %s, got %s\n", norwayNames[i], norwayLocales[i], realName);
+ }
+ ures_close(norway);
+ }
+}
+
+static void TestDecodedBundle(){
+
+ UErrorCode error = U_ZERO_ERROR;
+
+ UResourceBundle* resB;
+
+ const UChar* srcFromRes;
+ int32_t len;
+ static const UChar uSrc[] = {
+ 0x0009,0x092F,0x0941,0x0928,0x0947,0x0938,0x094D,0x0915,0x094B,0x0020,0x002E,0x0915,0x0947,0x0020,0x002E,0x090F,
+ 0x0915,0x0020,0x002E,0x0905,0x0927,0x094D,0x092F,0x092F,0x0928,0x0020,0x002E,0x0915,0x0947,0x0020,0x0905,0x0928,
+ 0x0941,0x0938,0x093E,0x0930,0x0020,0x0031,0x0039,0x0039,0x0030,0x0020,0x0924,0x0915,0x0020,0x0915,0x0902,0x092A,
+ 0x094D,0x092F,0x0942,0x091F,0x0930,0x002D,0x092A,0x094D,0x0930,0x092C,0x0902,0x0927,0x093F,0x0924,0x0020,0x0938,
+ 0x0942,0x091A,0x0928,0x093E,0x092A,0x094D,0x0930,0x0923,0x093E,0x0932,0x0940,0x0020,0x002E,0x0915,0x0947,0x0020,
+ 0x002E,0x092F,0x094B,0x0917,0x0926,0x093E,0x0928,0x0020,0x002E,0x0915,0x0947,0x0020,0x002E,0x092B,0x0932,0x0938,
+ 0x094D,0x0935,0x0930,0x0942,0x092A,0x0020,0x002E,0x0935,0x093F,0x0936,0x094D,0x0935,0x0020,0x002E,0x092E,0x0947,
+ 0x0902,0x0020,0x002E,0x0938,0x093E,0x0932,0x093E,0x0928,0x093E,0x0020,0x002E,0x0032,0x0032,0x0030,0x0030,0x0020,
+ 0x0905,0x0930,0x092C,0x0020,0x0930,0x0941,0x092A,0x092F,0x0947,0x0020,0x092E,0x0942,0x0932,0x094D,0x092F,0x0915,
+ 0x0940,0x0020,0x002E,0x0034,0x0935,0x0938,0x094D,0x0924,0x0941,0x0913,0x0902,0x0020,0x002E,0x0034,0x0915,0x093E,
+ 0x0020,0x002E,0x0034,0x0909,0x0924,0x094D,0x092A,0x093E,0x0926,0x0928,0x0020,0x002E,0x0034,0x0939,0x094B,0x0917,
+ 0x093E,0x002C,0x0020,0x002E,0x0033,0x091C,0x092C,0x0915,0x093F,0x0020,0x002E,0x0033,0x0915,0x0902,0x092A,0x094D,
+ 0x092F,0x0942,0x091F,0x0930,0x0020,0x002E,0x0033,0x0915,0x093E,0x0020,0x002E,0x0033,0x0915,0x0941,0x0932,0x0020,
+ 0x002E,0x0033,0x092F,0x094B,0x0917,0x0926,0x093E,0x0928,0x0020,0x002E,0x0033,0x0907,0x0938,0x0938,0x0947,0x0915,
+ 0x0939,0x093F,0x0020,0x002E,0x002F,0x091C,0x094D,0x092F,0x093E,0x0926,0x093E,0x0020,0x002E,0x002F,0x0939,0x094B,
+ 0x0917,0x093E,0x0964,0x0020,0x002E,0x002F,0x0905,0x0928,0x0941,0x0938,0x0902,0x0927,0x093E,0x0928,0x0020,0x002E,
+ 0x002F,0x0915,0x0940,0x0020,0x002E,0x002F,0x091A,0x0930,0x092E,0x0020,0x0938,0x0940,0x092E,0x093E,0x0913,0x0902,
+ 0x0020,0x092A,0x0930,0x0020,0x092A,0x0939,0x0941,0x0902,0x091A,0x0928,0x0947,0x0020,0x0915,0x0947,0x0020,0x0932,
+ 0x093F,0x090F,0x0020,0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x090F,0x0915,0x0020,0x002E,0x002F,
+ 0x0906,0x092E,0x0020,0x002E,0x002F,0x091C,0x0930,0x0942,0x0930,0x0924,0x0020,0x002E,0x002F,0x091C,0x0948,0x0938,
+ 0x093E,0x0020,0x092C,0x0928,0x0020,0x0917,0x092F,0x093E,0x0020,0x0939,0x0948,0x0964,0x0020,0x092D,0x093E,0x0930,
+ 0x0924,0x0020,0x092E,0x0947,0x0902,0x0020,0x092D,0x0940,0x002C,0x0020,0x0916,0x093E,0x0938,0x0915,0x0930,0x0020,
+ 0x092E,0x094C,0x091C,0x0942,0x0926,0x093E,0x0020,0x0938,0x0930,0x0915,0x093E,0x0930,0x0928,0x0947,0x002C,0x0020,
+ 0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x0020,0x0915,0x0947,0x0020,0x092A,0x094D,0x0930,0x092F,
+ 0x094B,0x0917,0x0020,0x092A,0x0930,0x0020,0x091C,0x092C,0x0930,0x0926,0x0938,0x094D,0x0924,0x0020,0x090F,0x095C,
+ 0x0020,0x0932,0x0917,0x093E,0x092F,0x0940,0x0020,0x0939,0x0948,0x002C,0x0020,0x0915,0x093F,0x0902,0x0924,0x0941,
+ 0x0020,0x0907,0x0938,0x0915,0x0947,0x0020,0x0938,0x0930,0x092A,0x091F,0x0020,0x0926,0x094C,0x095C,0x0932,0x0917,
+ 0x093E,0x0928,0x0947,0x0020,0x002E,0x0032,0x0915,0x0947,0x0020,0x002E,0x0032,0x0932,0x093F,0x090F,0x0020,0x002E,
+ 0x0032,0x0915,0x094D,0x092F,0x093E,0x0020,0x002E,0x0032,0x0938,0x092A,0x093E,0x091F,0x0020,0x002E,0x0032,0x0930,
+ 0x093E,0x0938,0x094D,0x0924,0x093E,0x0020,0x002E,0x0032,0x0909,0x092A,0x0932,0x092C,0x094D,0x0927,0x0020,0x002E,
+ 0x0939,0x0948,0x002C,0x0020,0x002E,0x0905,0x0925,0x0935,0x093E,0x0020,0x002E,0x0935,0x093F,0x0936,0x094D,0x0935,
+ 0x0020,0x002E,0x092E,0x0947,0x0902,0x0020,0x002E,0x0915,0x0902,0x092A,0x094D,0x092F,0x0942,0x091F,0x0930,0x0020,
+ 0x002E,0x0915,0x0940,0x0938,0x092B,0x0932,0x0924,0x093E,0x0020,0x002E,0x0033,0x0935,0x0020,0x002E,0x0033,0x0935,
+ 0x093F,0x092B,0x0932,0x0924,0x093E,0x0020,0x002E,0x0033,0x0938,0x0947,0x0020,0x002E,0x0033,0x0938,0x092C,0x0915,
+ 0x0020,0x002E,0x0033,0x0932,0x0947,0x0020,0x002E,0x0033,0x0915,0x0930,0x0020,0x002E,0x0033,0x0915,0x094D,0x092F,
+ 0x093E,0x0020,0x002E,0x0033,0x0939,0x092E,0x0020,0x002E,0x0033,0x0907,0x0938,0x0915,0x093E,0x0020,0x002E,0x0033,
+ 0x092F,0x0941,0x0915,0x094D,0x0924,0x093F,0x092A,0x0942,0x0930,0x094D,0x0923,0x0020,0x002E,0x0032,0x0935,0x093F,
+ 0x0938,0x094D,0x0924,0x093E,0x0930,0x0020,0x0905,0x092A,0x0947,0x0915,0x094D,0x0937,0x093F,0x0924,0x0020,0x0915,
+ 0x0930,0x0020,0x0938,0x0915,0x0947,0x0902,0x0917,0x0947,0x0020,0x003F,0x0020,
+ 0
+ };
+
+ /* pre-flight */
+ int32_t num =0;
+ const char *testdatapath = loadTestData(&error);
+ resB = ures_open(testdatapath, "iscii", &error);
+ srcFromRes=tres_getString(resB,-1,"str",&len,&error);
+ if(U_FAILURE(error)){
+#if UCONFIG_NO_LEGACY_CONVERSION
+ log_info("Couldn't load iscii.bin from test data bundle, (because UCONFIG_NO_LEGACY_CONVERSION is turned on)\n");
+#else
+ log_err("Could not find iscii.bin from test data bundle. Error: %s\n", u_errorName(error));
+#endif
+ ures_close(resB);
+ return;
+ }
+ if(u_strncmp(srcFromRes,uSrc,len)!=0){
+ log_err("Genrb produced res files after decoding failed\n");
+ }
+ while(num<len){
+ if(uSrc[num]!=srcFromRes[num]){
+ log_verbose(" Expected: 0x%04X Got: 0x%04X \n", uSrc[num],srcFromRes[num]);
+ }
+ num++;
+ }
+ if (len != u_strlen(uSrc)) {
+ log_err("Genrb produced a string larger than expected\n");
+ }
+ ures_close(resB);
+}
+
+static void TestNewTypes() {
+ UResourceBundle* theBundle = NULL;
+ char action[256];
+ const char* testdatapath;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle* res = NULL;
+ uint8_t *binResult = NULL;
+ int32_t len = 0;
+ int32_t i = 0;
+ int32_t intResult = 0;
+ uint32_t uintResult = 0;
+ const UChar *empty = NULL;
+ const UChar *zeroString;
+ UChar expected[] = { 'a','b','c','\0','d','e','f' };
+ const char* expect ="tab:\t cr:\r ff:\f newline:\n backslash:\\\\ quote=\\\' doubleQuote=\\\" singlequoutes=''";
+ UChar uExpect[200];
+
+ testdatapath=loadTestData(&status);
+
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+ theBundle = ures_open(testdatapath, "testtypes", &status);
+
+ empty = tres_getString(theBundle, -1, "emptystring", &len, &status);
+ if(empty && (*empty != 0 || len != 0)) {
+ log_err("Empty string returned invalid value\n");
+ }
+
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+
+ CONFIRM_INT_NE(theBundle, NULL);
+
+ /* This test reads the string "abc\u0000def" from the bundle */
+ /* if everything is working correctly, the size of this string */
+ /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/
+
+ strcpy(action, "getting and testing of string with embeded zero");
+ res = ures_getByKey(theBundle, "zerotest", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_STRING);
+ zeroString=tres_getString(res, -1, NULL, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(len, 7);
+ CONFIRM_INT_NE(len, 3);
+ }
+ for(i=0;i<len;i++){
+ if(zeroString[i]!= expected[i]){
+ log_verbose("Output did not match Expected: \\u%4X Got: \\u%4X", expected[i], zeroString[i]);
+ }
+ }
+
+ strcpy(action, "getting and testing of binary type");
+ res = ures_getByKey(theBundle, "binarytest", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_BINARY);
+ binResult=(uint8_t*)ures_getBinary(res, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(len, 15);
+ for(i = 0; i<15; i++) {
+ CONFIRM_INT_EQ(binResult[i], i);
+ }
+ }
+
+ strcpy(action, "getting and testing of imported binary type");
+ res = ures_getByKey(theBundle, "importtest", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_BINARY);
+ binResult=(uint8_t*)ures_getBinary(res, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(len, 15);
+ for(i = 0; i<15; i++) {
+ CONFIRM_INT_EQ(binResult[i], i);
+ }
+ }
+
+ strcpy(action, "getting and testing of integer types");
+ res = ures_getByKey(theBundle, "one", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT);
+ intResult=ures_getInt(res, &status);
+ uintResult = ures_getUInt(res, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(uintResult, (uint32_t)intResult);
+ CONFIRM_INT_EQ(intResult, 1);
+ }
+
+ strcpy(action, "getting minusone");
+ res = ures_getByKey(theBundle, "minusone", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT);
+ intResult=ures_getInt(res, &status);
+ uintResult = ures_getUInt(res, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(uintResult, 0x0FFFFFFF); /* a 28 bit integer */
+ CONFIRM_INT_EQ(intResult, -1);
+ CONFIRM_INT_NE(uintResult, (uint32_t)intResult);
+ }
+
+ strcpy(action, "getting plusone");
+ res = ures_getByKey(theBundle, "plusone", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT);
+ intResult=ures_getInt(res, &status);
+ uintResult = ures_getUInt(res, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(uintResult, (uint32_t)intResult);
+ CONFIRM_INT_EQ(intResult, 1);
+ }
+
+ res = ures_getByKey(theBundle, "onehundredtwentythree", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT);
+ intResult=ures_getInt(res, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(intResult, 123);
+ }
+
+ /* this tests if escapes are preserved or not */
+ {
+ const UChar* str = tres_getString(theBundle,-1,"testescape",&len,&status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ if(U_SUCCESS(status)){
+ u_charsToUChars(expect,uExpect,(int32_t)strlen(expect)+1);
+ if(u_strcmp(uExpect,str)){
+ log_err("Did not get the expected string for testescape\n");
+ }
+ }
+ }
+ /* this tests if unescaping works are expected */
+ len=0;
+ {
+ char pattern[2048] = "";
+ int32_t patternLen;
+ UChar* expectedEscaped;
+ const UChar* got;
+ int32_t expectedLen;
+
+ /* This strcpy fixes compiler warnings about long strings */
+ strcpy(pattern, "[ \\\\u0020 \\\\u00A0 \\\\u1680 \\\\u2000 \\\\u2001 \\\\u2002 \\\\u2003 \\\\u2004 \\\\u2005 \\\\u2006 \\\\u2007 "
+ "\\\\u2008 \\\\u2009 \\\\u200A \\u200B \\\\u202F \\u205F \\\\u3000 \\u0000-\\u001F \\u007F \\u0080-\\u009F "
+ "\\\\u06DD \\\\u070F \\\\u180E \\\\u200C \\\\u200D \\\\u2028 \\\\u2029 \\\\u2060 \\\\u2061 \\\\u2062 \\\\u2063 "
+ "\\\\u206A-\\\\u206F \\\\uFEFF \\\\uFFF9-\\uFFFC \\U0001D173-\\U0001D17A \\U000F0000-\\U000FFFFD "
+ "\\U00100000-\\U0010FFFD \\uFDD0-\\uFDEF \\uFFFE-\\uFFFF \\U0001FFFE-\\U0001FFFF \\U0002FFFE-\\U0002FFFF "
+ );
+ strcat(pattern,
+ "\\U0003FFFE-\\U0003FFFF \\U0004FFFE-\\U0004FFFF \\U0005FFFE-\\U0005FFFF \\U0006FFFE-\\U0006FFFF "
+ "\\U0007FFFE-\\U0007FFFF \\U0008FFFE-\\U0008FFFF \\U0009FFFE-\\U0009FFFF \\U000AFFFE-\\U000AFFFF "
+ "\\U000BFFFE-\\U000BFFFF \\U000CFFFE-\\U000CFFFF \\U000DFFFE-\\U000DFFFF \\U000EFFFE-\\U000EFFFF "
+ "\\U000FFFFE-\\U000FFFFF \\U0010FFFE-\\U0010FFFF \\uD800-\\uDFFF \\\\uFFF9 \\\\uFFFA \\\\uFFFB "
+ "\\uFFFC \\uFFFD \\u2FF0-\\u2FFB \\u0340 \\u0341 \\\\u200E \\\\u200F \\\\u202A \\\\u202B \\\\u202C "
+ );
+ strcat(pattern,
+ "\\\\u202D \\\\u202E \\\\u206A \\\\u206B \\\\u206C \\\\u206D \\\\u206E \\\\u206F \\U000E0001 \\U000E0020-\\U000E007F "
+ "]"
+ );
+
+ patternLen = (int32_t)uprv_strlen(pattern);
+ expectedEscaped = (UChar*)malloc(U_SIZEOF_UCHAR * patternLen);
+ got = tres_getString(theBundle,-1,"test_unescaping",&len,&status);
+ expectedLen = u_unescape(pattern,expectedEscaped,patternLen);
+ if(got==NULL || u_strncmp(expectedEscaped,got,expectedLen)!=0 || expectedLen != len){
+ log_err("genrb failed to unescape string\n");
+ }
+ if(got != NULL){
+ for(i=0;i<expectedLen;i++){
+ if(expectedEscaped[i] != got[i]){
+ log_verbose("Expected: 0x%04X Got: 0x%04X \n",expectedEscaped[i], got[i]);
+ }
+ }
+ }
+ free(expectedEscaped);
+ status = U_ZERO_ERROR;
+ }
+ /* test for jitterbug#1435 */
+ {
+ const UChar* str = tres_getString(theBundle,-1,"test_underscores",&len,&status);
+ expect ="test message ....";
+ u_charsToUChars(expect,uExpect,(int32_t)strlen(expect)+1);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ if(u_strcmp(uExpect,str)){
+ log_err("Did not get the expected string for test_underscores.\n");
+ }
+ }
+ /* test for jitterbug#2626 */
+#if !UCONFIG_NO_COLLATION
+ {
+ UResourceBundle* resB = NULL;
+ const UChar* str = NULL;
+ int32_t strLength = 0;
+ const UChar my[] = {0x0026,0x0027,0x0075,0x0027,0x0020,0x003d,0x0020,0x0027,0xff55,0x0027,0x0000}; /* &'\u0075' = '\uFF55' */
+ status = U_ZERO_ERROR;
+ resB = ures_getByKey(theBundle, "collations", resB, &status);
+ resB = ures_getByKey(resB, "standard", resB, &status);
+ str = tres_getString(resB,-1,"Sequence",&strLength,&status);
+ if(!str || U_FAILURE(status)) {
+ log_data_err("Could not load collations from theBundle: %s\n", u_errorName(status));
+ } else if(u_strcmp(my,str) != 0){
+ log_err("Did not get the expected string for escaped \\u0075\n");
+ }
+ ures_close(resB);
+ }
+#endif
+ {
+ const char *sourcePath = ctest_dataSrcDir();
+ int32_t srcPathLen = (int32_t)strlen(sourcePath);
+ const char *deltaPath = ".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
+ int32_t deltaPathLen = (int32_t)strlen(deltaPath);
+ char *testDataFileName = (char *) malloc( srcPathLen+ deltaPathLen + 50 );
+ char *path = testDataFileName;
+
+ strcpy(path, sourcePath);
+ path += srcPathLen;
+ strcpy(path, deltaPath);
+ path += deltaPathLen;
+ status = U_ZERO_ERROR;
+ {
+ int32_t strLen =0;
+ const UChar* str = tres_getString(theBundle, -1, "testincludeUTF",&strLen,&status);
+ strcpy(path, "riwords.txt");
+ path[strlen("riwords.txt")]=0;
+ if(U_FAILURE(status)){
+ log_err("Could not get testincludeUTF resource from testtypes bundle. Error: %s\n",u_errorName(status));
+ }else{
+ /* open the file */
+ const char* cp = NULL;
+ UCHARBUF* ucbuf = ucbuf_open(testDataFileName,&cp,FALSE,FALSE,&status);
+ len = 0;
+ if(U_SUCCESS(status)){
+ const UChar* buffer = ucbuf_getBuffer(ucbuf,&len,&status);
+ if(U_SUCCESS(status)){
+ /* verify the contents */
+ if(strLen != len ){
+ log_err("Did not get the expected len for riwords. Expected: %i , Got: %i\n", len ,strLen);
+ }
+ /* test string termination */
+ if(u_strlen(str) != strLen || str[strLen]!= 0 ){
+ log_err("testinclude not null terminated!\n");
+ }
+ if(u_strncmp(str, buffer,strLen)!=0){
+ log_err("Did not get the expected string from riwords. Include functionality failed for genrb.\n");
+ }
+ }else{
+ log_err("ucbuf failed to open %s. Error: %s\n", testDataFileName, u_errorName(status));
+ }
+
+ ucbuf_close(ucbuf);
+ }else{
+ log_err("Could not get riwords.txt (path : %s). Error: %s\n",testDataFileName,u_errorName(status));
+ }
+ }
+ }
+ status = U_ZERO_ERROR;
+ {
+ int32_t strLen =0;
+ const UChar* str = tres_getString(theBundle, -1, "testinclude",&strLen,&status);
+ strcpy(path, "translit_rules.txt");
+ path[strlen("translit_rules.txt")]=0;
+
+ if(U_FAILURE(status)){
+ log_err("Could not get testinclude resource from testtypes bundle. Error: %s\n",u_errorName(status));
+ }else{
+ /* open the file */
+ const char* cp=NULL;
+ UCHARBUF* ucbuf = ucbuf_open(testDataFileName,&cp,FALSE,FALSE,&status);
+ len = 0;
+ if(U_SUCCESS(status)){
+ const UChar* buffer = ucbuf_getBuffer(ucbuf,&len,&status);
+ if(U_SUCCESS(status)){
+ /* verify the contents */
+ if(strLen != len ){
+ log_err("Did not get the expected len for translit_rules. Expected: %i , Got: %i\n", len ,strLen);
+ }
+ if(u_strncmp(str, buffer,strLen)!=0){
+ log_err("Did not get the expected string from translit_rules. Include functionality failed for genrb.\n");
+ }
+ }else{
+ log_err("ucbuf failed to open %s. Error: %s\n", testDataFileName, u_errorName(status));
+ }
+ ucbuf_close(ucbuf);
+ }else{
+ log_err("Could not get translit_rules.txt (path : %s). Error: %s\n",testDataFileName,u_errorName(status));
+ }
+ }
+ }
+ free(testDataFileName);
+ }
+ ures_close(res);
+ ures_close(theBundle);
+
+}
+
+static void TestEmptyTypes() {
+ UResourceBundle* theBundle = NULL;
+ char action[256];
+ const char* testdatapath;
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle* res = NULL;
+ UResourceBundle* resArray = NULL;
+ const uint8_t *binResult = NULL;
+ int32_t len = 0;
+ int32_t intResult = 0;
+ const UChar *zeroString;
+ const int32_t *zeroIntVect;
+
+ strcpy(action, "Construction of testtypes bundle");
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+ theBundle = ures_open(testdatapath, "testtypes", &status);
+
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+
+ CONFIRM_INT_NE(theBundle, NULL);
+
+ /* This test reads the string "abc\u0000def" from the bundle */
+ /* if everything is working correctly, the size of this string */
+ /* should be 7. Everything else is a wrong answer, esp. 3 and 6*/
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of explicit string of zero length string");
+ res = ures_getByKey(theBundle, "emptyexplicitstring", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_STRING);
+ zeroString=tres_getString(res, -1, NULL, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(len, 0);
+ CONFIRM_INT_EQ(u_strlen(zeroString), 0);
+ }
+ else {
+ log_err("Couldn't get emptyexplicitstring\n");
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of normal string of zero length string");
+ res = ures_getByKey(theBundle, "emptystring", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_STRING);
+ zeroString=tres_getString(res, -1, NULL, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(len, 0);
+ CONFIRM_INT_EQ(u_strlen(zeroString), 0);
+ }
+ else {
+ log_err("Couldn't get emptystring\n");
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of empty int");
+ res = ures_getByKey(theBundle, "emptyint", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT);
+ intResult=ures_getInt(res, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(intResult, 0);
+ }
+ else {
+ log_err("Couldn't get emptystring\n");
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of zero length intvector");
+ res = ures_getByKey(theBundle, "emptyintv", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_INT_VECTOR);
+
+ if(U_FAILURE(status)){
+ log_err("Couldn't get emptyintv key %s\n", u_errorName(status));
+ }
+ else {
+ zeroIntVect=ures_getIntVector(res, &len, &status);
+ if(!U_SUCCESS(status) || resArray != NULL || len != 0) {
+ log_err("Shouldn't get emptyintv\n");
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of zero length emptybin");
+ res = ures_getByKey(theBundle, "emptybin", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_BINARY);
+
+ if(U_FAILURE(status)){
+ log_err("Couldn't get emptybin key %s\n", u_errorName(status));
+ }
+ else {
+ binResult=ures_getBinary(res, &len, &status);
+ if(!U_SUCCESS(status) || binResult != NULL || len != 0) {
+ log_err("Shouldn't get emptybin\n");
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of zero length emptyarray");
+ res = ures_getByKey(theBundle, "emptyarray", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_ARRAY);
+
+ if(U_FAILURE(status)){
+ log_err("Couldn't get emptyarray key %s\n", u_errorName(status));
+ }
+ else {
+ resArray=ures_getByIndex(res, 0, resArray, &status);
+ if(U_SUCCESS(status) || resArray != NULL){
+ log_err("Shouldn't get emptyarray\n");
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ strcpy(action, "getting and testing of zero length emptytable");
+ res = ures_getByKey(theBundle, "emptytable", res, &status);
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(res), URES_TABLE);
+
+ if(U_FAILURE(status)){
+ log_err("Couldn't get emptytable key %s\n", u_errorName(status));
+ }
+ else {
+ resArray=ures_getByIndex(res, 0, resArray, &status);
+ if(U_SUCCESS(status) || resArray != NULL){
+ log_err("Shouldn't get emptytable\n");
+ }
+ }
+
+ ures_close(res);
+ ures_close(theBundle);
+}
+
+static void TestEmptyBundle(){
+ UErrorCode status = U_ZERO_ERROR;
+ const char* testdatapath=NULL;
+ UResourceBundle *resb=0, *dResB=0;
+
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+ resb = ures_open(testdatapath, "testempty", &status);
+
+ if(U_SUCCESS(status)){
+ dResB = ures_getByKey(resb,"test",dResB,&status);
+ if(status!= U_MISSING_RESOURCE_ERROR){
+ log_err("Did not get the expected error from an empty resource bundle. Expected : %s Got: %s\n",
+ u_errorName(U_MISSING_RESOURCE_ERROR),u_errorName(status));
+ }
+ }
+ ures_close(dResB);
+ ures_close(resb);
+}
+
+static void TestBinaryCollationData(){
+ UErrorCode status=U_ZERO_ERROR;
+ const char* locale="te";
+#if !UCONFIG_NO_COLLATION
+ const char* testdatapath;
+#endif
+ UResourceBundle *teRes = NULL;
+ UResourceBundle *coll=NULL;
+ UResourceBundle *binColl = NULL;
+ uint8_t *binResult = NULL;
+ int32_t len=0;
+ const char* action="testing the binary collaton data";
+
+#if !UCONFIG_NO_COLLATION
+ log_verbose("Testing binary collation data resource......\n");
+
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+
+ teRes=ures_open(testdatapath, locale, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: Failed to get resource for \"te\" with %s", myErrorName(status));
+ return;
+ }
+ status=U_ZERO_ERROR;
+ coll = ures_getByKey(teRes, "collations", coll, &status);
+ coll = ures_getByKey(coll, "standard", coll, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(coll), URES_TABLE);
+ binColl=ures_getByKey(coll, "%%CollationBin", binColl, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_EQ(ures_getType(binColl), URES_BINARY);
+ binResult=(uint8_t*)ures_getBinary(binColl, &len, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_ErrorCode(status, U_ZERO_ERROR);
+ CONFIRM_INT_GE(len, 1);
+ }
+
+ }else{
+ log_err("ERROR: ures_getByKey(locale(te), %%CollationBin) failed\n");
+ }
+ }
+ else{
+ log_err("ERROR: ures_getByKey(locale(te), collations) failed\n");
+ return;
+ }
+ ures_close(binColl);
+ ures_close(coll);
+ ures_close(teRes);
+#endif
+}
+
+static void TestAPI() {
+ UErrorCode status=U_ZERO_ERROR;
+ int32_t len=0;
+ const char* key=NULL;
+ const UChar* value=NULL;
+ const char* testdatapath;
+ UChar* utestdatapath=NULL;
+ char convOutput[256];
+ UChar largeBuffer[1025];
+ UResourceBundle *teRes = NULL;
+ UResourceBundle *teFillin=NULL;
+ UResourceBundle *teFillin2=NULL;
+
+ log_verbose("Testing ures_openU()......\n");
+
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+ len =(int32_t)strlen(testdatapath);
+ utestdatapath = (UChar*) malloc((len+10)*sizeof(UChar));
+
+ u_charsToUChars(testdatapath, utestdatapath, (int32_t)strlen(testdatapath)+1);
+#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) && U_FILE_SEP_CHAR == '\\'
+ {
+ /* Convert all backslashes to forward slashes so that we can make sure that ures_openU
+ can handle invariant characters. */
+ UChar *backslash;
+ while ((backslash = u_strchr(utestdatapath, 0x005C))) {
+ *backslash = 0x002F;
+ }
+ }
+#endif
+
+ u_memset(largeBuffer, 0x0030, sizeof(largeBuffer)/sizeof(largeBuffer[0]));
+ largeBuffer[sizeof(largeBuffer)/sizeof(largeBuffer[0])-1] = 0;
+
+ /*Test ures_openU */
+
+ status = U_ZERO_ERROR;
+ ures_close(ures_openU(largeBuffer, "root", &status));
+ if(status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_openU() worked when the path is very large. It returned %s\n", myErrorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ ures_close(ures_openU(NULL, "root", &status));
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_openU() failed path = NULL with %s\n", myErrorName(status));
+ }
+
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ if(ures_openU(NULL, "root", &status) != NULL){
+ log_err("ERROR: ures_openU() worked with error status with %s\n", myErrorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ teRes=ures_openU(utestdatapath, "te", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_openU() failed path =%s with %s\n", austrdup(utestdatapath), myErrorName(status));
+ return;
+ }
+ /*Test ures_getLocale() */
+ log_verbose("Testing ures_getLocale() .....\n");
+ if(strcmp(ures_getLocale(teRes, &status), "te") != 0){
+ log_err("ERROR: ures_getLocale() failed. Expected = te_TE Got = %s\n", ures_getLocale(teRes, &status));
+ }
+ /*Test ures_getNextString() */
+ teFillin=ures_getByKey(teRes, "tagged_array_in_te_te_IN", teFillin, &status);
+ key=ures_getKey(teFillin);
+ value=(UChar*)ures_getNextString(teFillin, &len, &key, &status);
+ ures_resetIterator(NULL);
+ value=(UChar*)ures_getNextString(teFillin, &len, &key, &status);
+ if(status !=U_INDEX_OUTOFBOUNDS_ERROR){
+ log_err("ERROR: calling getNextString where index out of bounds should return U_INDEX_OUTOFBOUNDS_ERROR, Got : %s\n",
+ myErrorName(status));
+ }
+ ures_resetIterator(teRes);
+ /*Test ures_getNextResource() where resource is table*/
+ status=U_ZERO_ERROR;
+#if (U_CHARSET_FAMILY == U_ASCII_FAMILY)
+ /* The next key varies depending on the charset. */
+ teFillin=ures_getNextResource(teRes, teFillin, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_getNextResource() failed \n");
+ }
+ key=ures_getKey(teFillin);
+ /*if(strcmp(key, "%%CollationBin") != 0){*/
+ /*if(strcmp(key, "array_2d_in_Root_te") != 0){*/ /* added "aliasClient" that goes first */
+ if(strcmp(key, "a") != 0){
+ log_err("ERROR: ures_getNextResource() failed\n");
+ }
+#endif
+
+ /*Test ures_getByIndex on string Resource*/
+ teFillin=ures_getByKey(teRes, "string_only_in_te", teFillin, &status);
+ teFillin2=ures_getByIndex(teFillin, 0, teFillin2, &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_getByIndex on string resource failed\n");
+ }
+ if(strcmp(u_austrcpy(convOutput, tres_getString(teFillin2, -1, NULL, &len, &status)), "TE") != 0){
+ status=U_ZERO_ERROR;
+ log_err("ERROR: ures_getByIndex on string resource fetched the key=%s, expected \"TE\" \n", austrdup(ures_getString(teFillin2, &len, &status)));
+ }
+
+ /*ures_close(teRes);*/
+
+ /*Test ures_openFillIn*/
+ log_verbose("Testing ures_openFillIn......\n");
+ status=U_ZERO_ERROR;
+ ures_openFillIn(teRes, testdatapath, "te", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_openFillIn failed\n");
+ return;
+ }
+ if(strcmp(ures_getLocale(teRes, &status), "te") != 0){
+ log_err("ERROR: ures_openFillIn did not open the ResourceBundle correctly\n");
+ }
+ ures_getByKey(teRes, "string_only_in_te", teFillin, &status);
+ teFillin2=ures_getNextResource(teFillin, teFillin2, &status);
+ if(ures_getType(teFillin2) != URES_STRING){
+ log_err("ERROR: getType for getNextResource after ures_openFillIn failed\n");
+ }
+ teFillin2=ures_getNextResource(teFillin, teFillin2, &status);
+ if(status !=U_INDEX_OUTOFBOUNDS_ERROR){
+ log_err("ERROR: calling getNextResource where index out of bounds should return U_INDEX_OUTOFBOUNDS_ERROR, Got : %s\n",
+ myErrorName(status));
+ }
+
+ ures_close(teFillin);
+ ures_close(teFillin2);
+ ures_close(teRes);
+
+ /* Test that ures_getLocale() returns the "real" locale ID */
+ status=U_ZERO_ERROR;
+ teRes=ures_open(NULL, "dE_At_NOWHERE_TO_BE_FOUND", &status);
+ if(U_FAILURE(status)) {
+ log_data_err("unable to open a locale resource bundle from \"dE_At_NOWHERE_TO_BE_FOUND\"(%s)\n", u_errorName(status));
+ } else {
+ if(0!=strcmp("de_AT", ures_getLocale(teRes, &status))) {
+ log_data_err("ures_getLocale(\"dE_At_NOWHERE_TO_BE_FOUND\")=%s but must be de_AT\n", ures_getLocale(teRes, &status));
+ }
+ ures_close(teRes);
+ }
+
+ /* same test, but with an aliased locale resource bundle */
+ status=U_ZERO_ERROR;
+ teRes=ures_open(NULL, "iW_Il_depRecaTed_HebreW", &status);
+ if(U_FAILURE(status)) {
+ log_data_err("unable to open a locale resource bundle from \"iW_Il_depRecaTed_HebreW\"(%s)\n", u_errorName(status));
+ } else {
+ if(0!=strcmp("he_IL", ures_getLocale(teRes, &status))) {
+ log_data_err("ures_getLocale(\"iW_Il_depRecaTed_HebreW\")=%s but must be he_IL\n", ures_getLocale(teRes, &status));
+ }
+ ures_close(teRes);
+ }
+ free(utestdatapath);
+}
+
+static void TestErrorConditions(){
+ UErrorCode status=U_ZERO_ERROR;
+ const char *key=NULL;
+ const UChar *value=NULL;
+ const char* testdatapath;
+ UChar* utestdatapath;
+ int32_t len=0;
+ UResourceBundle *teRes = NULL;
+ UResourceBundle *coll=NULL;
+ UResourceBundle *binColl = NULL;
+ UResourceBundle *teFillin=NULL;
+ UResourceBundle *teFillin2=NULL;
+ uint8_t *binResult = NULL;
+ int32_t resultLen;
+
+
+ testdatapath = loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+ len = (int32_t)strlen(testdatapath);
+ utestdatapath = (UChar*) malloc(sizeof(UChar) *(len+10));
+ u_uastrcpy(utestdatapath, testdatapath);
+
+ /*Test ures_openU with status != U_ZERO_ERROR*/
+ log_verbose("Testing ures_openU() with status != U_ZERO_ERROR.....\n");
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ teRes=ures_openU(utestdatapath, "te", &status);
+ if(U_FAILURE(status)){
+ log_verbose("ures_openU() failed as expected path =%s with status != U_ZERO_ERROR\n", testdatapath);
+ }else{
+ log_err("ERROR: ures_openU() is supposed to fail path =%s with status != U_ZERO_ERROR\n", austrdup(utestdatapath));
+ ures_close(teRes);
+ }
+ /*Test ures_openFillIn with UResourceBundle = NULL*/
+ log_verbose("Testing ures_openFillIn with UResourceBundle = NULL.....\n");
+ status=U_ZERO_ERROR;
+ ures_openFillIn(NULL, testdatapath, "te", &status);
+ if(status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_openFillIn with UResourceBundle= NULL should fail. Expected U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getLocale() with status != U_ZERO_ERROR*/
+ status=U_ZERO_ERROR;
+ teRes=ures_openU(utestdatapath, "te", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: ures_openU() failed path =%s with %s\n", austrdup(utestdatapath), myErrorName(status));
+ return;
+ }
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ if(ures_getLocale(teRes, &status) != NULL){
+ log_err("ERROR: ures_getLocale is supposed to fail with errorCode != U_ZERO_ERROR\n");
+ }
+ /*Test ures_getLocale() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getLocale(NULL, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getLocale is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getSize() with UResourceBundle = NULL */
+ status=U_ZERO_ERROR;
+ if(ures_getSize(NULL) != 0){
+ log_err("ERROR: ures_getSize() should return 0 when UResourceBundle=NULL. Got =%d\n", ures_getSize(NULL));
+ }
+ /*Test ures_getType() with UResourceBundle = NULL should return URES_NONE==-1*/
+ status=U_ZERO_ERROR;
+ if(ures_getType(NULL) != URES_NONE){
+ log_err("ERROR: ures_getType() should return URES_NONE when UResourceBundle=NULL. Got =%d\n", ures_getType(NULL));
+ }
+ /*Test ures_getKey() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getKey(NULL) != NULL){
+ log_err("ERROR: ures_getKey() should return NULL when UResourceBundle=NULL. Got =%d\n", ures_getKey(NULL));
+ }
+ /*Test ures_hasNext() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_hasNext(NULL) != FALSE){
+ log_err("ERROR: ures_hasNext() should return FALSE when UResourceBundle=NULL. Got =%d\n", ures_hasNext(NULL));
+ }
+ /*Test ures_get() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getStringByKey(NULL, "string_only_in_te", &resultLen, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_get is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getByKey() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ teFillin=ures_getByKey(NULL, "string_only_in_te", teFillin, &status);
+ if( teFillin != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getByKey is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getByKey() with status != U_ZERO_ERROR*/
+ teFillin=ures_getByKey(NULL, "string_only_in_te", teFillin, &status);
+ if(teFillin != NULL ){
+ log_err("ERROR: ures_getByKey is supposed to fail when errorCode != U_ZERO_ERROR\n");
+ }
+ /*Test ures_getStringByKey() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getStringByKey(NULL, "string_only_in_te", &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getStringByKey is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getStringByKey() with status != U_ZERO_ERROR*/
+ if(ures_getStringByKey(teRes, "string_only_in_te", &len, &status) != NULL){
+ log_err("ERROR: ures_getStringByKey is supposed to fail when status != U_ZERO_ERROR. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getString() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getString(NULL, &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getString is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getString() with status != U_ZERO_ERROR*/
+ if(ures_getString(teRes, &len, &status) != NULL){
+ log_err("ERROR: ures_getString is supposed to fail when status != U_ZERO_ERROR. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getBinary() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ if(ures_getBinary(NULL, &len, &status) != NULL && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getBinary is supposed to fail when UResourceBundle = NULL. Expected: errorCode = U_ILLEGAL_ARGUMENT_ERROR, Got: errorCode=%s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getBinary(0 status != U_ILLEGAL_ARGUMENT_ERROR*/
+ status=U_ZERO_ERROR;
+ coll = ures_getByKey(teRes, "collations", coll, &status);
+ coll = ures_getByKey(teRes, "standard", coll, &status);
+ binColl=ures_getByKey(coll, "%%CollationBin", binColl, &status);
+
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ binResult=(uint8_t*)ures_getBinary(binColl, &len, &status);
+ if(binResult != NULL){
+ log_err("ERROR: ures_getBinary() with status != U_ZERO_ERROR is supposed to fail\n");
+ }
+
+ /*Test ures_getNextResource() with status != U_ZERO_ERROR*/
+ teFillin=ures_getNextResource(teRes, teFillin, &status);
+ if(teFillin != NULL){
+ log_err("ERROR: ures_getNextResource() with errorCode != U_ZERO_ERROR is supposed to fail\n");
+ }
+ /*Test ures_getNextResource() with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ teFillin=ures_getNextResource(NULL, teFillin, &status);
+ if(teFillin != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getNextResource() with UResourceBundle = NULL is supposed to fail. Expected : U_IILEGAL_ARGUMENT_ERROR, Got : %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getNextString with errorCode != U_ZERO_ERROR*/
+ teFillin=ures_getByKey(teRes, "tagged_array_in_te_te_IN", teFillin, &status);
+ key=ures_getKey(teFillin);
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ value=(UChar*)ures_getNextString(teFillin, &len, &key, &status);
+ if(value != NULL){
+ log_err("ERROR: ures_getNextString() with errorCode != U_ZERO_ERROR is supposed to fail\n");
+ }
+ /*Test ures_getNextString with UResourceBundle = NULL*/
+ status=U_ZERO_ERROR;
+ value=(UChar*)ures_getNextString(NULL, &len, &key, &status);
+ if(value != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getNextString() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getByIndex with errorCode != U_ZERO_ERROR*/
+ status=U_ZERO_ERROR;
+ teFillin=ures_getByKey(teRes, "array_only_in_te", teFillin, &status);
+ if(ures_countArrayItems(teRes, "array_only_in_te", &status) != 4) {
+ log_err("ERROR: Wrong number of items in an array!\n");
+ }
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ teFillin2=ures_getByIndex(teFillin, 0, teFillin2, &status);
+ if(teFillin2 != NULL){
+ log_err("ERROR: ures_getByIndex() with errorCode != U_ZERO_ERROR is supposed to fail\n");
+ }
+ /*Test ures_getByIndex with UResourceBundle = NULL */
+ status=U_ZERO_ERROR;
+ teFillin2=ures_getByIndex(NULL, 0, teFillin2, &status);
+ if(status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getByIndex() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getStringByIndex with errorCode != U_ZERO_ERROR*/
+ status=U_ZERO_ERROR;
+ teFillin=ures_getByKey(teRes, "array_only_in_te", teFillin, &status);
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ value=(UChar*)ures_getStringByIndex(teFillin, 0, &len, &status);
+ if( value != NULL){
+ log_err("ERROR: ures_getSringByIndex() with errorCode != U_ZERO_ERROR is supposed to fail\n");
+ }
+ /*Test ures_getStringByIndex with UResourceBundle = NULL */
+ status=U_ZERO_ERROR;
+ value=(UChar*)ures_getStringByIndex(NULL, 0, &len, &status);
+ if(value != NULL || status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getStringByIndex() with UResourceBundle=NULL is supposed to fail\n Expected: U_ILLEGAL_ARGUMENT_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getStringByIndex with UResourceBundle = NULL */
+ status=U_ZERO_ERROR;
+ value=(UChar*)ures_getStringByIndex(teFillin, 9999, &len, &status);
+ if(value != NULL || status != U_MISSING_RESOURCE_ERROR){
+ log_err("ERROR: ures_getStringByIndex() with index that is too big is supposed to fail\n Expected: U_MISSING_RESOURCE_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getInt() where UResourceBundle = NULL */
+ status=U_ZERO_ERROR;
+ if(ures_getInt(NULL, &status) != -1 && status != U_ILLEGAL_ARGUMENT_ERROR){
+ log_err("ERROR: ures_getInt() with UResourceBundle = NULL should fail. Expected: U_IILEGAL_ARGUMENT_ERROR, Got: %s\n",
+ myErrorName(status));
+ }
+ /*Test ures_getInt() where status != U_ZERO_ERROR */
+ if(ures_getInt(teRes, &status) != -1){
+ log_err("ERROR: ures_getInt() with errorCode != U_ZERO_ERROR should fail\n");
+ }
+
+ ures_close(teFillin);
+ ures_close(teFillin2);
+ ures_close(coll);
+ ures_close(binColl);
+ ures_close(teRes);
+ free(utestdatapath);
+
+
+}
+
+static void TestGetVersion(){
+ UVersionInfo minVersionArray = {0x01, 0x00, 0x00, 0x00};
+ UVersionInfo maxVersionArray = {0x50, 0xc0, 0xcf, 0xcf};
+ UVersionInfo versionArray;
+ UErrorCode status= U_ZERO_ERROR;
+ UResourceBundle* resB = NULL;
+ int i=0, j = 0;
+ int locCount = uloc_countAvailable();
+ const char *locName = "root";
+
+ log_verbose("The ures_getVersion tests begin : \n");
+
+ for(j = -1; j < locCount; j++) {
+ if(j >= 0) {
+ locName = uloc_getAvailable(j);
+ }
+ log_verbose("Testing version number for locale %s\n", locName);
+ resB = ures_open(NULL,locName, &status);
+ if (U_FAILURE(status)) {
+ log_err("Resource bundle creation for locale %s failed.: %s\n", locName, myErrorName(status));
+ ures_close(resB);
+ return;
+ }
+ ures_getVersion(resB, versionArray);
+ for (i=0; i<4; ++i) {
+ if (versionArray[i] < minVersionArray[i] ||
+ versionArray[i] > maxVersionArray[i])
+ {
+ log_err("Testing ures_getVersion(%-5s) - unexpected result: %d.%d.%d.%d\n",
+ locName, versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
+ break;
+ }
+ }
+ ures_close(resB);
+ }
+}
+
+
+static void TestGetVersionColl(){
+ UVersionInfo minVersionArray = {0x00, 0x00, 0x00, 0x00};
+ UVersionInfo maxVersionArray = {0x50, 0x80, 0xcf, 0xcf};
+ UVersionInfo versionArray;
+ UErrorCode status= U_ZERO_ERROR;
+ UResourceBundle* resB = NULL;
+ UEnumeration *locs= NULL;
+ int i=0;
+ const char *locName = "root";
+ int32_t locLen;
+ const UChar* rules =NULL;
+ int32_t len = 0;
+
+ log_verbose("The ures_getVersion(%s) tests begin : \n", U_ICUDATA_COLL);
+ locs = ures_openAvailableLocales(U_ICUDATA_COLL, &status);
+ if (U_FAILURE(status)) {
+ log_err("enumeration of %s failed.: %s\n", U_ICUDATA_COLL, myErrorName(status));
+ return;
+ }
+
+ do{
+ log_verbose("Testing version number for locale %s\n", locName);
+ resB = ures_open(U_ICUDATA_COLL,locName, &status);
+ if (U_FAILURE(status)) {
+ log_err("Resource bundle creation for locale %s:%s failed.: %s\n", U_ICUDATA_COLL, locName, myErrorName(status));
+ ures_close(resB);
+ return;
+ }
+ /* test NUL termination of UCARules */
+ rules = tres_getString(resB,-1,"UCARules",&len, &status);
+ if(!rules || U_FAILURE(status)) {
+ log_data_err("Could not load UCARules for locale %s\n", locName);
+ continue;
+ }
+ if(u_strlen(rules) != len){
+ log_err("UCARules string not nul terminated! \n");
+ }
+ ures_getVersion(resB, versionArray);
+ for (i=0; i<4; ++i) {
+ if (versionArray[i] < minVersionArray[i] ||
+ versionArray[i] > maxVersionArray[i])
+ {
+ log_err("Testing ures_getVersion(%-5s) - unexpected result: %d.%d.%d.%d\n",
+ locName, versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
+ break;
+ }
+ }
+ ures_close(resB);
+ } while((locName = uenum_next(locs,&locLen,&status))&&U_SUCCESS(status));
+
+ if(U_FAILURE(status)) {
+ log_err("Err %s testing Collation locales.\n", u_errorName(status));
+ }
+ uenum_close(locs);
+}
+
+static void TestResourceBundles()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ testTag("only_in_Root", TRUE, FALSE, FALSE);
+ testTag("in_Root_te", TRUE, TRUE, FALSE);
+ testTag("in_Root_te_te_IN", TRUE, TRUE, TRUE);
+ testTag("in_Root_te_IN", TRUE, FALSE, TRUE);
+ testTag("only_in_te", FALSE, TRUE, FALSE);
+ testTag("only_in_te_IN", FALSE, FALSE, TRUE);
+ testTag("in_te_te_IN", FALSE, TRUE, TRUE);
+ testTag("nonexistent", FALSE, FALSE, FALSE);
+
+ log_verbose("Passed:= %d Failed= %d \n", pass, fail);
+
+}
+
+
+static void TestConstruction1()
+{
+ UResourceBundle *test1 = 0, *test2 = 0,*empty = 0;
+ const UChar *result1, *result2;
+ UErrorCode status= U_ZERO_ERROR;
+ UErrorCode err = U_ZERO_ERROR;
+ const char* locale="te_IN";
+ const char* testdatapath;
+
+ int32_t len1=0;
+ int32_t len2=0;
+ UVersionInfo versionInfo;
+ char versionString[256];
+ char verboseOutput[256];
+
+ U_STRING_DECL(rootVal, "ROOT", 4);
+ U_STRING_DECL(te_inVal, "TE_IN", 5);
+
+ U_STRING_INIT(rootVal, "ROOT", 4);
+ U_STRING_INIT(te_inVal, "TE_IN", 5);
+
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing ures_open()......\n");
+
+ empty = ures_open(testdatapath, "testempty", &status);
+ if(empty == NULL || U_FAILURE(status)) {
+ log_err("opening empty failed!\n");
+ }
+ ures_close(empty);
+
+ test1=ures_open(testdatapath, NULL, &err);
+
+ if(U_FAILURE(err))
+ {
+ log_err("construction of NULL did not succeed : %s \n", myErrorName(status));
+ return;
+ }
+ test2=ures_open(testdatapath, locale, &err);
+ if(U_FAILURE(err))
+ {
+ log_err("construction of %s did not succeed : %s \n", locale, myErrorName(status));
+ return;
+ }
+ result1= tres_getString(test1, -1, "string_in_Root_te_te_IN", &len1, &err);
+ result2= tres_getString(test2, -1, "string_in_Root_te_te_IN", &len2, &err);
+ if (U_FAILURE(err) || len1==0 || len2==0) {
+ log_err("Something threw an error in TestConstruction(): %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("for string_in_Root_te_te_IN, default.txt had %s\n", u_austrcpy(verboseOutput, result1));
+ log_verbose("for string_in_Root_te_te_IN, te_IN.txt had %s\n", u_austrcpy(verboseOutput, result2));
+ if(u_strcmp(result1, rootVal) !=0 || u_strcmp(result2, te_inVal) !=0 ){
+ log_err("construction test failed. Run Verbose for more information");
+ }
+
+
+ /* Test getVersionNumber*/
+ log_verbose("Testing version number\n");
+ log_verbose("for getVersionNumber : %s\n", ures_getVersionNumber(test1));
+
+ log_verbose("Testing version \n");
+ ures_getVersion(test1, versionInfo);
+ u_versionToString(versionInfo, versionString);
+
+ log_verbose("for getVersion : %s\n", versionString);
+
+ if(strcmp(versionString, ures_getVersionNumber(test1)) != 0) {
+ log_err("Versions differ: %s vs %s\n", versionString, ures_getVersionNumber(test1));
+ }
+
+ ures_close(test1);
+ ures_close(test2);
+
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+
+static UBool testTag(const char* frag,
+ UBool in_Root,
+ UBool in_te,
+ UBool in_te_IN)
+{
+ int32_t failNum = fail;
+
+ /* Make array from input params */
+
+ UBool is_in[3];
+ const char *NAME[] = { "ROOT", "TE", "TE_IN" };
+
+ /* Now try to load the desired items */
+ UResourceBundle* theBundle = NULL;
+ char tag[99];
+ char action[256];
+ UErrorCode expected_status,status = U_ZERO_ERROR,expected_resource_status = U_ZERO_ERROR;
+ UChar* base = NULL;
+ UChar* expected_string = NULL;
+ const UChar* string = NULL;
+ char buf[5];
+ char item_tag[10];
+ int32_t i,j,row,col, len;
+ int32_t actual_bundle;
+ int32_t count = 0;
+ int32_t row_count=0;
+ int32_t column_count=0;
+ int32_t index = 0;
+ int32_t tag_count= 0;
+ const char* testdatapath;
+ char verboseOutput[256];
+ UResourceBundle* array=NULL;
+ UResourceBundle* array2d=NULL;
+ UResourceBundle* tags=NULL;
+ UResourceBundle* arrayItem1=NULL;
+
+ testdatapath = loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return FALSE;
+ }
+
+ is_in[0] = in_Root;
+ is_in[1] = in_te;
+ is_in[2] = in_te_IN;
+
+ strcpy(item_tag, "tag");
+
+ for (i=0; i<bundles_count; ++i)
+ {
+ strcpy(action,"construction for ");
+ strcat(action, param[i].name);
+
+
+ status = U_ZERO_ERROR;
+
+ theBundle = ures_open(testdatapath, param[i].name, &status);
+ CONFIRM_ErrorCode(status,param[i].expected_constructor_status);
+
+ if(i == 5)
+ actual_bundle = 0; /* ne -> default */
+ else if(i == 3)
+ actual_bundle = 1; /* te_NE -> te */
+ else if(i == 4)
+ actual_bundle = 2; /* te_IN_NE -> te_IN */
+ else
+ actual_bundle = i;
+
+ expected_resource_status = U_MISSING_RESOURCE_ERROR;
+ for (j=e_te_IN; j>=e_Root; --j)
+ {
+ if (is_in[j] && param[i].inherits[j])
+ {
+
+ if(j == actual_bundle) /* it's in the same bundle OR it's a nonexistent=default bundle (5) */
+ expected_resource_status = U_ZERO_ERROR;
+ else if(j == 0)
+ expected_resource_status = U_USING_DEFAULT_WARNING;
+ else
+ expected_resource_status = U_USING_FALLBACK_WARNING;
+
+ log_verbose("%s[%d]::%s: in<%d:%s> inherits<%d:%s>. actual_bundle=%s\n",
+ param[i].name,
+ i,
+ frag,
+ j,
+ is_in[j]?"Yes":"No",
+ j,
+ param[i].inherits[j]?"Yes":"No",
+ param[actual_bundle].name);
+
+ break;
+ }
+ }
+
+ for (j=param[i].where; j>=0; --j)
+ {
+ if (is_in[j])
+ {
+ if(base != NULL) {
+ free(base);
+ base = NULL;
+ }
+ base=(UChar*)malloc(sizeof(UChar)*(strlen(NAME[j]) + 1));
+ u_uastrcpy(base,NAME[j]);
+
+ break;
+ }
+ else {
+ if(base != NULL) {
+ free(base);
+ base = NULL;
+ }
+ base = (UChar*) malloc(sizeof(UChar) * 1);
+ *base = 0x0000;
+ }
+ }
+
+ /*----string---------------------------------------------------------------- */
+
+ strcpy(tag,"string_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action, ".ures_getStringByKey(" );
+ strcat(action,tag);
+ strcat(action, ")");
+
+
+ status = U_ZERO_ERROR;
+ len=0;
+
+ string=tres_getString(theBundle, -1, tag, &len, &status);
+ if(U_SUCCESS(status)) {
+ expected_string=(UChar*)malloc(sizeof(UChar)*(u_strlen(base) + 4));
+ u_strcpy(expected_string,base);
+ CONFIRM_INT_EQ(len, u_strlen(expected_string));
+ }else{
+ expected_string = (UChar*)malloc(sizeof(UChar)*(u_strlen(kERROR) + 1));
+ u_strcpy(expected_string,kERROR);
+ string=kERROR;
+ }
+ log_verbose("%s got %d, expected %d\n", action, status, expected_resource_status);
+
+ CONFIRM_ErrorCode(status, expected_resource_status);
+ CONFIRM_EQ(string, expected_string);
+
+
+
+ /*--------------array------------------------------------------------- */
+
+ strcpy(tag,"array_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action, ".ures_getByKey(" );
+ strcat(action,tag);
+ strcat(action, ")");
+
+ len=0;
+
+ count = kERROR_COUNT;
+ status = U_ZERO_ERROR;
+ array=ures_getByKey(theBundle, tag, array, &status);
+ CONFIRM_ErrorCode(status,expected_resource_status);
+ if (U_SUCCESS(status)) {
+ /*confirm the resource type is an array*/
+ CONFIRM_INT_EQ(ures_getType(array), URES_ARRAY);
+ /*confirm the size*/
+ count=ures_getSize(array);
+ CONFIRM_INT_GE(count,1);
+ for (j=0; j<count; ++j) {
+ UChar element[3];
+ u_strcpy(expected_string, base);
+ u_uastrcpy(element, itoa1(j,buf));
+ u_strcat(expected_string, element);
+ arrayItem1=ures_getNextResource(array, arrayItem1, &status);
+ if(U_SUCCESS(status)){
+ CONFIRM_EQ(tres_getString(arrayItem1, -1, NULL, &len, &status),expected_string);
+ }
+ }
+
+ }
+ else {
+ CONFIRM_INT_EQ(count,kERROR_COUNT);
+ CONFIRM_ErrorCode(status, U_MISSING_RESOURCE_ERROR);
+ /*CONFIRM_INT_EQ((int32_t)(unsigned long)array,(int32_t)0);*/
+ count = 0;
+ }
+
+ /*--------------arrayItem------------------------------------------------- */
+
+ strcpy(tag,"array_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action, ".ures_getStringByIndex(");
+ strcat(action, tag);
+ strcat(action, ")");
+
+
+ for (j=0; j<10; ++j){
+ index = count ? (randi(count * 3) - count) : (randi(200) - 100);
+ status = U_ZERO_ERROR;
+ string=kERROR;
+ array=ures_getByKey(theBundle, tag, array, &status);
+ if(!U_FAILURE(status)){
+ UChar *t=NULL;
+ t=(UChar*)ures_getStringByIndex(array, index, &len, &status);
+ if(!U_FAILURE(status)){
+ UChar element[3];
+ string=t;
+ u_strcpy(expected_string, base);
+ u_uastrcpy(element, itoa1(index,buf));
+ u_strcat(expected_string, element);
+ } else {
+ u_strcpy(expected_string, kERROR);
+ }
+
+ }
+ expected_status = (index >= 0 && index < count) ? expected_resource_status : U_MISSING_RESOURCE_ERROR;
+ CONFIRM_ErrorCode(status,expected_status);
+ CONFIRM_EQ(string,expected_string);
+
+ }
+
+
+ /*--------------2dArray------------------------------------------------- */
+
+ strcpy(tag,"array_2d_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action, ".ures_getByKey(" );
+ strcat(action,tag);
+ strcat(action, ")");
+
+
+
+ row_count = kERROR_COUNT, column_count = kERROR_COUNT;
+ status = U_ZERO_ERROR;
+ array2d=ures_getByKey(theBundle, tag, array2d, &status);
+
+ CONFIRM_ErrorCode(status,expected_resource_status);
+ if (U_SUCCESS(status))
+ {
+ /*confirm the resource type is an 2darray*/
+ CONFIRM_INT_EQ(ures_getType(array2d), URES_ARRAY);
+ row_count=ures_getSize(array2d);
+ CONFIRM_INT_GE(row_count,1);
+
+ for(row=0; row<row_count; ++row){
+ UResourceBundle *tableRow=NULL;
+ tableRow=ures_getByIndex(array2d, row, tableRow, &status);
+ CONFIRM_ErrorCode(status, expected_resource_status);
+ if(U_SUCCESS(status)){
+ /*confirm the resourcetype of each table row is an array*/
+ CONFIRM_INT_EQ(ures_getType(tableRow), URES_ARRAY);
+ column_count=ures_getSize(tableRow);
+ CONFIRM_INT_GE(column_count,1);
+
+ for (col=0; j<column_count; ++j) {
+ UChar element[3];
+ u_strcpy(expected_string, base);
+ u_uastrcpy(element, itoa1(row, buf));
+ u_strcat(expected_string, element);
+ u_uastrcpy(element, itoa1(col, buf));
+ u_strcat(expected_string, element);
+ arrayItem1=ures_getNextResource(tableRow, arrayItem1, &status);
+ if(U_SUCCESS(status)){
+ const UChar *stringValue=tres_getString(arrayItem1, -1, NULL, &len, &status);
+ CONFIRM_EQ(stringValue, expected_string);
+ }
+ }
+ }
+ ures_close(tableRow);
+ }
+ }else{
+ CONFIRM_INT_EQ(row_count,kERROR_COUNT);
+ CONFIRM_INT_EQ(column_count,kERROR_COUNT);
+ row_count=column_count=0;
+ }
+
+
+ /*------2dArrayItem-------------------------------------------------------------- */
+ /* 2dArrayItem*/
+ for (j=0; j<10; ++j)
+ {
+ row = row_count ? (randi(row_count * 3) - row_count) : (randi(200) - 100);
+ col = column_count ? (randi(column_count * 3) - column_count) : (randi(200) - 100);
+ status = U_ZERO_ERROR;
+ string = kERROR;
+ len=0;
+ array2d=ures_getByKey(theBundle, tag, array2d, &status);
+ if(U_SUCCESS(status)){
+ UResourceBundle *tableRow=NULL;
+ tableRow=ures_getByIndex(array2d, row, tableRow, &status);
+ if(U_SUCCESS(status)) {
+ UChar *t=NULL;
+ t=(UChar*)ures_getStringByIndex(tableRow, col, &len, &status);
+ if(U_SUCCESS(status)){
+ string=t;
+ }
+ }
+ ures_close(tableRow);
+ }
+ expected_status = (row >= 0 && row < row_count && col >= 0 && col < column_count) ?
+ expected_resource_status: U_MISSING_RESOURCE_ERROR;
+ CONFIRM_ErrorCode(status,expected_status);
+
+ if (U_SUCCESS(status)){
+ UChar element[3];
+ u_strcpy(expected_string, base);
+ u_uastrcpy(element, itoa1(row, buf));
+ u_strcat(expected_string, element);
+ u_uastrcpy(element, itoa1(col, buf));
+ u_strcat(expected_string, element);
+ } else {
+ u_strcpy(expected_string,kERROR);
+ }
+ CONFIRM_EQ(string,expected_string);
+
+ }
+
+
+ /*--------------taggedArray----------------------------------------------- */
+ strcpy(tag,"tagged_array_");
+ strcat(tag,frag);
+
+ strcpy(action,param[i].name);
+ strcat(action,".ures_getByKey(");
+ strcat(action, tag);
+ strcat(action,")");
+
+
+ status = U_ZERO_ERROR;
+ tag_count=0;
+ tags=ures_getByKey(theBundle, tag, tags, &status);
+ CONFIRM_ErrorCode(status, expected_resource_status);
+ if (U_SUCCESS(status)) {
+ UResType bundleType=ures_getType(tags);
+ CONFIRM_INT_EQ(bundleType, URES_TABLE);
+
+ tag_count=ures_getSize(tags);
+ CONFIRM_INT_GE((int32_t)tag_count, (int32_t)0);
+
+ for(index=0; index <tag_count; index++){
+ UResourceBundle *tagelement=NULL;
+ const char *key=NULL;
+ UChar* value=NULL;
+ tagelement=ures_getByIndex(tags, index, tagelement, &status);
+ key=ures_getKey(tagelement);
+ value=(UChar*)ures_getNextString(tagelement, &len, &key, &status);
+ log_verbose("tag = %s, value = %s\n", key, u_austrcpy(verboseOutput, value));
+ if(strncmp(key, "tag", 3) == 0 && u_strncmp(value, base, u_strlen(base)) == 0){
+ record_pass();
+ }else{
+ record_fail();
+ }
+ ures_close(tagelement);
+ }
+ }else{
+ tag_count=0;
+ }
+
+ /*---------taggedArrayItem----------------------------------------------*/
+ count = 0;
+ for (index=-20; index<20; ++index)
+ {
+
+ status = U_ZERO_ERROR;
+ string = kERROR;
+ strcpy(item_tag, "tag");
+ strcat(item_tag, itoa1(index,buf));
+ tags=ures_getByKey(theBundle, tag, tags, &status);
+ if(U_SUCCESS(status)){
+ UResourceBundle *tagelement=NULL;
+ UChar *t=NULL;
+ tagelement=ures_getByKey(tags, item_tag, tagelement, &status);
+ if(!U_FAILURE(status)){
+ UResType elementType=ures_getType(tagelement);
+ CONFIRM_INT_EQ(elementType, URES_STRING);
+ if(strcmp(ures_getKey(tagelement), item_tag) == 0){
+ record_pass();
+ }else{
+ record_fail();
+ }
+ t=(UChar*)tres_getString(tagelement, -1, NULL, &len, &status);
+ if(!U_FAILURE(status)){
+ string=t;
+ }
+ }
+ if (index < 0) {
+ CONFIRM_ErrorCode(status,U_MISSING_RESOURCE_ERROR);
+ }
+ else{
+ if (status != U_MISSING_RESOURCE_ERROR) {
+ UChar element[3];
+ u_strcpy(expected_string, base);
+ u_uastrcpy(element, itoa1(index,buf));
+ u_strcat(expected_string, element);
+ CONFIRM_EQ(string,expected_string);
+ count++;
+ }
+ }
+ ures_close(tagelement);
+ }
+ }
+ CONFIRM_INT_EQ(count, tag_count);
+
+ free(expected_string);
+ ures_close(theBundle);
+ }
+ ures_close(array);
+ ures_close(array2d);
+ ures_close(tags);
+ ures_close(arrayItem1);
+ free(base);
+ return (UBool)(failNum == fail);
+}
+
+static void record_pass()
+{
+ ++pass;
+}
+
+static void record_fail()
+{
+ ++fail;
+}
+
+/**
+ * Test to make sure that the U_USING_FALLBACK_ERROR and U_USING_DEFAULT_ERROR
+ * are set correctly
+ */
+
+static void TestFallback()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *fr_FR = NULL;
+ UResourceBundle *subResource = NULL;
+ const UChar *junk; /* ignored */
+ int32_t resultLen;
+
+ log_verbose("Opening fr_FR..");
+ fr_FR = ures_open(NULL, "fr_FR", &status);
+ if(U_FAILURE(status))
+ {
+ log_err("Couldn't open fr_FR - %d\n", status);
+ return;
+ }
+
+ status = U_ZERO_ERROR;
+
+
+ /* clear it out.. just do some calls to get the gears turning */
+ junk = tres_getString(fr_FR, -1, "LocaleID", &resultLen, &status);
+ status = U_ZERO_ERROR;
+ junk = tres_getString(fr_FR, -1, "LocaleString", &resultLen, &status);
+ status = U_ZERO_ERROR;
+ junk = tres_getString(fr_FR, -1, "LocaleID", &resultLen, &status);
+ status = U_ZERO_ERROR;
+
+ /* OK first one. This should be a Default value. */
+ subResource = ures_getByKey(fr_FR, "MeasurementSystem", NULL, &status);
+ if(status != U_USING_DEFAULT_WARNING)
+ {
+ log_data_err("Expected U_USING_DEFAULT_ERROR when trying to get CurrencyMap from fr_FR, got %s\n",
+ u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ ures_close(subResource);
+
+ /* and this is a Fallback, to fr */
+ junk = tres_getString(fr_FR, -1, "Countries", &resultLen, &status);
+ if(status != U_USING_FALLBACK_WARNING)
+ {
+ log_data_err("Expected U_USING_FALLBACK_ERROR when trying to get Countries from fr_FR, got %d\n",
+ status);
+ }
+
+ status = U_ZERO_ERROR;
+
+ ures_close(fr_FR);
+ /* Temporary hack err actually should be U_USING_FALLBACK_ERROR */
+ /* Test Jitterbug 552 fallback mechanism of aliased data */
+ {
+ UErrorCode err =U_ZERO_ERROR;
+ UResourceBundle* myResB = ures_open(NULL,"no_NO_NY",&err);
+ UResourceBundle* resLocID = ures_getByKey(myResB, "Version", NULL, &err);
+ UResourceBundle* tResB;
+ const UChar* version = NULL;
+ static const UChar versionStr[] = { 0x0031, 0x002E, 0x0034, 0x0033, 0x0000};
+
+ if(err != U_ZERO_ERROR){
+ log_data_err("Expected U_ZERO_ERROR when trying to test no_NO_NY aliased to nn_NO for Version err=%s\n",u_errorName(err));
+ return;
+ }
+ version = tres_getString(resLocID, -1, NULL, &resultLen, &err);
+ if(u_strcmp(version, versionStr) != 0){
+ char x[100];
+ char g[100];
+ u_austrcpy(x, versionStr);
+ u_austrcpy(g, version);
+ log_data_err("ures_getString(resLocID, &resultLen, &err) returned an unexpected version value. Expected '%s', but got '%s'\n",
+ x, g);
+ }
+ tResB = ures_getByKey(myResB, "zoneStrings", NULL, &err);
+ if(err != U_USING_FALLBACK_WARNING){
+ log_err("Expected U_USING_FALLBACK_ERROR when trying to test no_NO_NY aliased with nn_NO_NY for zoneStrings err=%s\n",u_errorName(err));
+ }
+ ures_close(resLocID);
+ ures_close(myResB);
+ ures_close(tResB);
+
+ }
+
+}
+
+/* static void printUChars(UChar* uchars){
+/ int16_t i=0;
+/ for(i=0; i<u_strlen(uchars); i++){
+/ log_err("%04X ", *(uchars+i));
+/ }
+/ } */
+
+static void TestResourceLevelAliasing(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *aliasB = NULL, *tb = NULL;
+ UResourceBundle *en = NULL, *uk = NULL, *testtypes = NULL;
+ const char* testdatapath = NULL;
+ const UChar *string = NULL, *sequence = NULL;
+ /*const uint8_t *binary = NULL, *binSequence = NULL;*/
+ int32_t strLen = 0, seqLen = 0;/*, binLen = 0, binSeqLen = 0;*/
+ char buffer[100];
+ char *s;
+
+ testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+ aliasB = ures_open(testdatapath, "testaliases", &status);
+
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testaliases.res %s \n",myErrorName(status));
+ return;
+ }
+ /* this should fail - circular alias */
+ tb = ures_getByKey(aliasB, "aaa", tb, &status);
+ if(status != U_TOO_MANY_ALIASES_ERROR) {
+ log_err("Failed to detect circular alias\n");
+ }
+ else {
+ status = U_ZERO_ERROR;
+ }
+ tb = ures_getByKey(aliasB, "aab", tb, &status);
+ if(status != U_TOO_MANY_ALIASES_ERROR) {
+ log_err("Failed to detect circular alias\n");
+ } else {
+ status = U_ZERO_ERROR;
+ }
+ if(U_FAILURE(status) ) {
+ log_data_err("err loading tb resource\n");
+ } else {
+ /* testing aliasing to a non existing resource */
+ tb = ures_getByKey(aliasB, "nonexisting", tb, &status);
+ if(status != U_MISSING_RESOURCE_ERROR) {
+ log_err("Managed to find an alias to non-existing resource\n");
+ } else {
+ status = U_ZERO_ERROR;
+ }
+ /* testing referencing/composed alias */
+ uk = ures_findResource("ja/LocaleScript/2", uk, &status);
+ if((uk == NULL) || U_FAILURE(status)) {
+ log_err("Couldn't findResource('ja/LocaleScript/2') err %s\n", u_errorName(status));
+ goto cleanup;
+ }
+
+ sequence = tres_getString(uk, -1, NULL, &seqLen, &status);
+
+ tb = ures_getByKey(aliasB, "referencingalias", tb, &status);
+ string = tres_getString(tb, -1, NULL, &strLen, &status);
+
+ if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) {
+ log_err("Referencing alias didn't get the right string\n");
+ }
+
+ string = tres_getString(aliasB, -1, "referencingalias", &strLen, &status);
+ if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) {
+ log_err("Referencing alias didn't get the right string\n");
+ }
+
+ checkStatus(__LINE__, U_ZERO_ERROR, status);
+ tb = ures_getByKey(aliasB, "LocaleScript", tb, &status);
+ checkStatus(__LINE__, U_ZERO_ERROR, status);
+ tb = ures_getByIndex(tb, 2, tb, &status);
+ checkStatus(__LINE__, U_ZERO_ERROR, status);
+ string = tres_getString(tb, -1, NULL, &strLen, &status);
+ checkStatus(__LINE__, U_ZERO_ERROR, status);
+
+ if(U_FAILURE(status)) {
+ log_err("%s trying to get string via separate getters\n", u_errorName(status));
+ } else if(seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) {
+ log_err("Referencing alias didn't get the right string\n");
+ }
+
+
+ {
+ UResourceBundle* ja = ures_open(U_ICUDATA_BRKITR,"ja", &status);
+ const UChar *got = NULL, *exp=NULL;
+ int32_t gotLen = 0, expLen=0;
+ ja = ures_getByKey(ja, "boundaries", ja, &status);
+ exp = tres_getString(ja, -1, "word", &expLen, &status);
+
+ tb = ures_getByKey(aliasB, "boundaries", tb, &status);
+ got = tres_getString(tb, -1, "word", &gotLen, &status);
+
+ if(U_FAILURE(status)) {
+ log_err("%s trying to read str boundaries\n", u_errorName(status));
+ } else if(gotLen != expLen || u_strncmp(exp, got, gotLen) != 0) {
+ log_err("Referencing alias didn't get the right data\n");
+ }
+ ures_close(ja);
+ status = U_ZERO_ERROR;
+ }
+ /* simple alias */
+ testtypes = ures_open(testdatapath, "testtypes", &status);
+ strcpy(buffer, "menu/file/open");
+ s = buffer;
+ uk = ures_findSubResource(testtypes, s, uk, &status);
+ sequence = tres_getString(uk, -1, NULL, &seqLen, &status);
+
+ tb = ures_getByKey(aliasB, "simplealias", tb, &status);
+ string = tres_getString(tb, -1, NULL, &strLen, &status);
+
+ if(U_FAILURE(status) || seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) {
+ log_err("Referencing alias didn't get the right string\n");
+ }
+
+ /* test indexed aliasing */
+
+ tb = ures_getByKey(aliasB, "zoneTests", tb, &status);
+ tb = ures_getByKey(tb, "zoneAlias2", tb, &status);
+ string = tres_getString(tb, -1, NULL, &strLen, &status);
+
+ en = ures_findResource("en/zoneStrings/3/0", en, &status);
+ sequence = tres_getString(en, -1, NULL, &seqLen, &status);
+
+ if(U_FAILURE(status) || seqLen != strLen || u_strncmp(sequence, string, seqLen) != 0) {
+ log_err("Referencing alias didn't get the right string\n");
+ }
+ }
+ /* test getting aliased string by index */
+ {
+ const char* keys[] = {
+ "KeyAlias0PST",
+ "KeyAlias1PacificStandardTime",
+ "KeyAlias2PDT",
+ "KeyAlias3LosAngeles"
+ };
+
+ const char* strings[] = {
+ "America/Los_Angeles",
+ "Pacific Standard Time",
+ "PDT",
+ "Los Angeles",
+ };
+ UChar uBuffer[256];
+ const UChar* result;
+ int32_t uBufferLen = 0, resultLen = 0;
+ int32_t i = 0;
+ const char *key = NULL;
+ tb = ures_getByKey(aliasB, "testGetStringByKeyAliasing", tb, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't get testGetStringByKeyAliasing resource\n");
+ }
+ for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
+ result = tres_getString(tb, -1, keys[i], &resultLen, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status));
+ continue;
+ }
+ uBufferLen = u_unescape(strings[i], uBuffer, 256);
+ if(resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) {
+ log_err("Didn't get correct string while accesing alias table by key (%s)\n", keys[i]);
+ }
+ }
+ for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
+ result = tres_getString(tb, i, NULL, &resultLen, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status));
+ continue;
+ }
+ uBufferLen = u_unescape(strings[i], uBuffer, 256);
+ if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) {
+ log_err("Didn't get correct string while accesing alias table by index (%s)\n", strings[i]);
+ }
+ }
+ for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
+ result = ures_getNextString(tb, &resultLen, &key, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status));
+ continue;
+ }
+ uBufferLen = u_unescape(strings[i], uBuffer, 256);
+ if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) {
+ log_err("Didn't get correct string while iterating over alias table (%s)\n", strings[i]);
+ }
+ }
+ tb = ures_getByKey(aliasB, "testGetStringByIndexAliasing", tb, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't get testGetStringByIndexAliasing resource\n");
+ }
+ for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
+ result = tres_getString(tb, i, NULL, &resultLen, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status));
+ continue;
+ }
+ uBufferLen = u_unescape(strings[i], uBuffer, 256);
+ if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) {
+ log_err("Didn't get correct string while accesing alias by index in an array (%s)\n", strings[i]);
+ }
+ }
+ for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
+ result = ures_getNextString(tb, &resultLen, &key, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key %s failed. Error: %s\n", keys[i], u_errorName(status));
+ continue;
+ }
+ uBufferLen = u_unescape(strings[i], uBuffer, 256);
+ if(result==NULL || resultLen != uBufferLen || u_strncmp(result, uBuffer, resultLen) != 0) {
+ log_err("Didn't get correct string while iterating over aliases in an array (%s)\n", strings[i]);
+ }
+ }
+ }
+ tb = ures_getByKey(aliasB, "testAliasToTree", tb, &status);
+ if(U_FAILURE(status)){
+ log_err("Fetching the resource with key \"testAliasToTree\" failed. Error: %s\n", u_errorName(status));
+ }
+ if (strcmp(ures_getKey(tb), "collations") != 0) {
+ log_err("ures_getKey(aliasB) unexpectedly returned %s instead of \"collations\"\n", ures_getKey(tb));
+ }
+cleanup:
+ ures_close(aliasB);
+ ures_close(tb);
+ ures_close(en);
+ ures_close(uk);
+ ures_close(testtypes);
+}
+
+static void TestDirectAccess(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *t = NULL, *t2 = NULL;
+ const char* key = NULL;
+
+ char buffer[100];
+ char *s;
+ /*const char* testdatapath=loadTestData(&status);
+ if(U_FAILURE(status)){
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }*/
+
+ t = ures_findResource("/testdata/te/zoneStrings/3/2", t, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't access indexed resource, error %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ } else {
+ key = ures_getKey(t);
+ if(key != NULL) {
+ log_err("Got a strange key, expected NULL, got %s\n", key);
+ }
+ }
+ t = ures_findResource("en/calendar/gregorian/DateTimePatterns/3", t, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't access indexed resource, error %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ } else {
+ key = ures_getKey(t);
+ if(key != NULL) {
+ log_err("Got a strange key, expected NULL, got %s\n", key);
+ }
+ }
+
+ t = ures_findResource("ja/LocaleScript", t, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't access keyed resource, error %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ } else {
+ key = ures_getKey(t);
+ if(strcmp(key, "LocaleScript")!=0) {
+ log_err("Got a strange key, expected 'LocaleScript', got %s\n", key);
+ }
+ }
+
+ t2 = ures_open(NULL, "sr", &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't open 'sr' resource bundle, error %s\n", u_errorName(status));
+ log_data_err("No 'sr', no test - you have bigger problems than testing direct access. "
+ "You probably have no data! Aborting this test\n");
+ }
+
+ if(U_SUCCESS(status)) {
+ strcpy(buffer, "Languages/hr");
+ s = buffer;
+ t = ures_findSubResource(t2, s, t, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't access keyed resource, error %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ } else {
+ key = ures_getKey(t);
+ if(strcmp(key, "hr")!=0) {
+ log_err("Got a strange key, expected 'hr', got %s\n", key);
+ }
+ }
+ }
+
+ t = ures_findResource("root/calendar/islamic-civil/DateTime", t, &status);
+ if(U_SUCCESS(status)) {
+ log_err("This resource does not exist. How did it get here?\n");
+ }
+ status = U_ZERO_ERROR;
+
+ /* this one will freeze */
+ t = ures_findResource("root/calendar/islamic-civil/eras/abbreviated/0/mikimaus/pera", t, &status);
+ if(U_SUCCESS(status)) {
+ log_err("Second resource does not exist. How did it get here?\n");
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(t2);
+ t2 = ures_open(NULL, "he", &status);
+ t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "DateTime", t2, &status);
+ if(U_SUCCESS(status)) {
+ log_err("This resource does not exist. How did it get here?\n");
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(t2);
+ t2 = ures_open(NULL, "he", &status);
+ /* George's fix */
+ t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "eras", t2, &status);
+ if(U_FAILURE(status)) {
+ log_err("Didn't get Eras. I know they are there!\n");
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(t2);
+ t2 = ures_open(NULL, "root", &status);
+ t2 = ures_getByKeyWithFallback(t2, "calendar", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "islamic-civil", t2, &status);
+ t2 = ures_getByKeyWithFallback(t2, "DateTime", t2, &status);
+ if(U_SUCCESS(status)) {
+ log_err("This resource does not exist. How did it get here?\n");
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(t2);
+ ures_close(t);
+}
+
+static void TestJB3763(void) {
+ /* Nasty bug prevented using parent as fill-in, since it would
+ * stomp the path information.
+ */
+ UResourceBundle *t = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ t = ures_open(NULL, "sr_Latn", &status);
+ t = ures_getByKeyWithFallback(t, "calendar", t, &status);
+ t = ures_getByKeyWithFallback(t, "gregorian", t, &status);
+ t = ures_getByKeyWithFallback(t, "AmPmMarkers", t, &status);
+ if(U_FAILURE(status)) {
+ log_err("This resource should be available?\n");
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(t);
+
+}
+
+static void TestGetKeywordValues(void) {
+ UEnumeration *kwVals;
+ UBool foundStandard = FALSE;
+ UErrorCode status = U_ZERO_ERROR;
+ const char *kw;
+#if !UCONFIG_NO_COLLATION
+ kwVals = ures_getKeywordValues( U_ICUDATA_COLL, "collations", &status);
+
+ log_verbose("Testing getting collation keyword values:\n");
+
+ while((kw=uenum_next(kwVals, NULL, &status))) {
+ log_verbose(" %s\n", kw);
+ if(!strcmp(kw,"standard")) {
+ if(foundStandard == FALSE) {
+ foundStandard = TRUE;
+ } else {
+ log_err("'standard' was found twice in the keyword list.\n");
+ }
+ }
+ }
+ if(foundStandard == FALSE) {
+ log_err("'standard' was not found in the keyword list.\n");
+ }
+ uenum_close(kwVals);
+ if(U_FAILURE(status)) {
+ log_err("err %s getting collation values\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+#endif
+ foundStandard = FALSE;
+ kwVals = ures_getKeywordValues( "ICUDATA", "calendar", &status);
+
+ log_verbose("Testing getting calendar keyword values:\n");
+
+ while((kw=uenum_next(kwVals, NULL, &status))) {
+ log_verbose(" %s\n", kw);
+ if(!strcmp(kw,"japanese")) {
+ if(foundStandard == FALSE) {
+ foundStandard = TRUE;
+ } else {
+ log_err("'japanese' was found twice in the calendar keyword list.\n");
+ }
+ }
+ }
+ if(foundStandard == FALSE) {
+ log_err("'japanese' was not found in the calendar keyword list.\n");
+ }
+ uenum_close(kwVals);
+ if(U_FAILURE(status)) {
+ log_err("err %s getting calendar values\n", u_errorName(status));
+ }
+}
+
+static void TestGetFunctionalEquivalentOf(const char *path, const char *resName, const char *keyword, UBool truncate, const char * const testCases[]) {
+ int32_t i;
+ for(i=0;testCases[i];i+=3) {
+ UBool expectAvail = (testCases[i][0]=='t')?TRUE:FALSE;
+ UBool gotAvail = FALSE;
+ const char *inLocale = testCases[i+1];
+ const char *expectLocale = testCases[i+2];
+ char equivLocale[256];
+ int32_t len;
+ UErrorCode status = U_ZERO_ERROR;
+ log_verbose("%d: %c %s\texpect %s\n",i/3, expectAvail?'t':'f', inLocale, expectLocale);
+ len = ures_getFunctionalEquivalent(equivLocale, 255, path,
+ resName, keyword, inLocale,
+ &gotAvail, truncate, &status);
+ if(U_FAILURE(status) || (len <= 0)) {
+ log_err("FAIL: got len %d, err %s on #%d: %c\t%s\t%s\n",
+ len, u_errorName(status),
+ i/3,expectAvail?'t':'f', inLocale, expectLocale);
+ } else {
+ log_verbose("got: %c %s\n", expectAvail?'t':'f',equivLocale);
+
+ if((gotAvail != expectAvail) || strcmp(equivLocale, expectLocale)) {
+ log_err("FAIL: got avail=%c, loc=%s but expected #%d: %c\t%s\t-> loc=%s\n",
+ gotAvail?'t':'f', equivLocale,
+ i/3,
+ expectAvail?'t':'f', inLocale, expectLocale);
+
+ }
+ }
+ }
+}
+
+static void TestGetFunctionalEquivalent(void) {
+ static const char * const collCases[] = {
+ /* avail locale equiv */
+ "f", "de_US_CALIFORNIA", "de",
+ "f", "zh_TW@collation=stroke", "zh@collation=stroke", /* alias of zh_Hant_TW */
+ "t", "zh_Hant_TW@collation=stroke", "zh@collation=stroke",
+ "f", "de_CN@collation=pinyin", "de",
+ "t", "zh@collation=pinyin", "zh",
+ "f", "zh_CN@collation=pinyin", "zh", /* alias of zh_Hans_CN */
+ "t", "zh_Hans_CN@collation=pinyin", "zh",
+ "f", "zh_HK@collation=pinyin", "zh", /* alias of zh_Hant_HK */
+ "t", "zh_Hant_HK@collation=pinyin", "zh",
+ "f", "zh_HK@collation=stroke", "zh@collation=stroke", /* alias of zh_Hant_HK */
+ "t", "zh_Hant_HK@collation=stroke", "zh@collation=stroke",
+ "f", "zh_HK", "zh@collation=stroke", /* alias of zh_Hant_HK */
+ "t", "zh_Hant_HK", "zh@collation=stroke",
+ "f", "zh_MO", "zh@collation=stroke", /* alias of zh_Hant_MO */
+ "t", "zh_Hant_MO", "zh@collation=stroke",
+ "f", "zh_TW_STROKE", "zh@collation=stroke",
+ "f", "zh_TW_STROKE@collation=big5han", "zh@collation=big5han",
+ "f", "de_CN@calendar=japanese", "de",
+ "t", "de@calendar=japanese", "de",
+ "f", "zh_TW@collation=big5han", "zh@collation=big5han", /* alias of zh_Hant_TW */
+ "t", "zh_Hant_TW@collation=big5han", "zh@collation=big5han",
+ "f", "zh_TW@collation=gb2312han", "zh@collation=gb2312han", /* alias of zh_Hant_TW */
+ "t", "zh_Hant_TW@collation=gb2312han", "zh@collation=gb2312han",
+ "f", "zh_CN@collation=big5han", "zh@collation=big5han", /* alias of zh_Hans_CN */
+ "t", "zh_Hans_CN@collation=big5han", "zh@collation=big5han",
+ "f", "zh_CN@collation=gb2312han", "zh@collation=gb2312han", /* alias of zh_Hans_CN */
+ "t", "zh_Hans_CN@collation=gb2312han", "zh@collation=gb2312han",
+ "t", "zh@collation=big5han", "zh@collation=big5han",
+ "t", "zh@collation=gb2312han", "zh@collation=gb2312han",
+ "t", "hi_IN@collation=direct", "hi@collation=direct",
+ "t", "hi@collation=standard", "hi",
+ "t", "hi@collation=direct", "hi@collation=direct",
+ "f", "hi_AU@collation=direct;currency=CHF;calendar=buddhist", "hi@collation=direct",
+ "f", "hi_AU@collation=standard;currency=CHF;calendar=buddhist", "hi",
+ "t", "de_DE@collation=pinyin", "de", /* bug 4582 tests */
+ "f", "de_DE_BONN@collation=pinyin", "de",
+ "t", "nl", "root",
+ "t", "nl_NL", "root",
+ "f", "nl_NL_EEXT", "root",
+ "t", "nl@collation=stroke", "root",
+ "t", "nl_NL@collation=stroke", "root",
+ "f", "nl_NL_EEXT@collation=stroke", "root",
+ NULL
+ };
+
+ static const char *calCases[] = {
+ /* avail locale equiv */
+ "t", "en_US_POSIX", "en_US@calendar=gregorian",
+ "f", "ja_JP_TOKYO", "ja_JP@calendar=gregorian",
+ "f", "ja_JP_TOKYO@calendar=japanese", "ja@calendar=japanese",
+ "t", "sr@calendar=gregorian", "sr@calendar=gregorian",
+ "t", "en", "en@calendar=gregorian",
+ NULL
+ };
+
+#if !UCONFIG_NO_COLLATION
+ TestGetFunctionalEquivalentOf(U_ICUDATA_COLL, "collations", "collation", TRUE, collCases);
+#endif
+ TestGetFunctionalEquivalentOf("ICUDATA", "calendar", "calendar", FALSE, calCases);
+
+#if !UCONFIG_NO_COLLATION
+ log_verbose("Testing error conditions:\n");
+ {
+ char equivLocale[256] = "???";
+ int32_t len;
+ UErrorCode status = U_ZERO_ERROR;
+ UBool gotAvail = FALSE;
+
+ len = ures_getFunctionalEquivalent(equivLocale, 255, U_ICUDATA_COLL,
+ "calendar", "calendar", "ar_EG@calendar=islamic",
+ &gotAvail, FALSE, &status);
+
+ if(status == U_MISSING_RESOURCE_ERROR) {
+ log_verbose("PASS: Got expected U_MISSING_RESOURCE_ERROR\n");
+ } else {
+ log_err("ures_getFunctionalEquivalent returned locale %s, avail %c, err %s, but expected U_MISSING_RESOURCE_ERROR \n",
+ equivLocale, gotAvail?'t':'f', u_errorName(status));
+ }
+ }
+#endif
+}
+
+static void TestXPath(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *rb = NULL, *alias = NULL;
+ int32_t len = 0;
+ const UChar* result = NULL;
+ const UChar expResult[] = { 0x0063, 0x006F, 0x0072, 0x0072, 0x0065, 0x0063, 0x0074, 0x0000 }; /* "correct" */
+ /*const UChar expResult[] = { 0x0074, 0x0065, 0x0069, 0x006E, 0x0064, 0x0065, 0x0073, 0x0074, 0x0000 }; *//*teindest*/
+
+ const char *testdatapath=loadTestData(&status);
+ if(U_FAILURE(status))
+ {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+
+ log_verbose("Testing ures_open()......\n");
+
+ rb = ures_open(testdatapath, "te_IN", &status);
+ if(U_FAILURE(status)) {
+ log_err("Could not open te_IN (%s)\n", myErrorName(status));
+ return;
+ }
+ alias = ures_getByKey(rb, "rootAliasClient", alias, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status));
+ ures_close(rb);
+ return;
+ }
+
+ result = tres_getString(alias, -1, NULL, &len, &status);
+ if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) {
+ log_err("Couldn't get correct string value (%s)\n", myErrorName(status));
+ }
+
+ alias = ures_getByKey(rb, "aliasClient", alias, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status));
+ ures_close(rb);
+ return;
+ }
+
+ result = tres_getString(alias, -1, NULL, &len, &status);
+ if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) {
+ log_err("Couldn't get correct string value (%s)\n", myErrorName(status));
+ }
+
+ alias = ures_getByKey(rb, "nestedRootAliasClient", alias, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't find the aliased resource (%s)\n", myErrorName(status));
+ ures_close(rb);
+ return;
+ }
+
+ result = tres_getString(alias, -1, NULL, &len, &status);
+ if(U_FAILURE(status) || result == NULL || u_strcmp(result, expResult)) {
+ log_err("Couldn't get correct string value (%s)\n", myErrorName(status));
+ }
+
+ ures_close(alias);
+ ures_close(rb);
+}
+static void TestCLDRStyleAliases(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *rb = NULL, *alias = NULL, *a=NULL;
+ int32_t i, len;
+ char resource[256];
+ const UChar *result = NULL;
+ UChar expected[256];
+ const char *expects[7] = { "", "a41", "a12", "a03", "ar4" };
+ const char *testdatapath=loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat %s \n",myErrorName(status));
+ return;
+ }
+ log_verbose("Testing CLDR style aliases......\n");
+
+ rb = ures_open(testdatapath, "te_IN_REVISED", &status);
+ if(U_FAILURE(status)) {
+ log_err("Could not open te_IN (%s)\n", myErrorName(status));
+ return;
+ }
+ alias = ures_getByKey(rb, "a", alias, &status);
+ if(U_FAILURE(status)) {
+ log_err("Couldn't find the aliased with name \"a\" resource (%s)\n", myErrorName(status));
+ ures_close(rb);
+ return;
+ }
+ for(i = 1; i < 5 ; i++) {
+ resource[0]='a';
+ resource[1]='0'+i;
+ resource[2]=0;
+ /* instead of sprintf(resource, "a%i", i); */
+ a = ures_getByKeyWithFallback(alias, resource, a, &status);
+ result = tres_getString(a, -1, NULL, &len, &status);
+ u_charsToUChars(expects[i], expected, strlen(expects[i])+1);
+ if(U_FAILURE(status) || !result || u_strcmp(result, expected)) {
+ log_err("CLDR style aliases failed resource with name \"%s\" resource, exp %s, got %S (%s)\n", resource, expects[i], result, myErrorName(status));
+ status = U_ZERO_ERROR;
+ }
+ }
+
+ ures_close(a);
+ ures_close(alias);
+ ures_close(rb);
+}
+
+static void TestFallbackCodes(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char *testdatapath=loadTestData(&status);
+
+ UResourceBundle *res = ures_open(testdatapath, "te_IN", &status);
+
+ UResourceBundle *r = NULL, *fall = NULL;
+
+ r = ures_getByKey(res, "tagged_array_in_Root_te_te_IN", r, &status);
+
+ status = U_ZERO_ERROR;
+ fall = ures_getByKeyWithFallback(r, "tag2", fall, &status);
+
+ if(status != U_ZERO_ERROR) {
+ log_err("Expected error code to be U_ZERO_ERROR, got %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+
+ fall = ures_getByKeyWithFallback(r, "tag7", fall, &status);
+
+ if(status != U_USING_FALLBACK_WARNING) {
+ log_err("Expected error code to be U_USING_FALLBACK_WARNING, got %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+
+ fall = ures_getByKeyWithFallback(r, "tag1", fall, &status);
+
+ if(status != U_USING_DEFAULT_WARNING) {
+ log_err("Expected error code to be U_USING_DEFAULT_WARNING, got %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+
+ ures_close(fall);
+ ures_close(r);
+ ures_close(res);
+}
+
+/* This test will crash if this doesn't work. Results don't need testing. */
+static void TestStackReuse(void) {
+ UResourceBundle table;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UResourceBundle *rb = ures_open(NULL, "en_US", &errorCode);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("Could not load en_US locale. status=%s\n",myErrorName(errorCode));
+ return;
+ }
+ ures_initStackObject(&table);
+ ures_getByKeyWithFallback(rb, "Types", &table, &errorCode);
+ ures_getByKeyWithFallback(&table, "collation", &table, &errorCode);
+ ures_close(rb);
+ ures_close(&table);
+}
+
+/* Test ures_getUTF8StringXYZ() --------------------------------------------- */
+
+/*
+ * Replace most ures_getStringXYZ() with this function which wraps the
+ * desired call and also calls the UTF-8 variant and checks that it works.
+ */
+extern const UChar *
+tres_getString(const UResourceBundle *resB,
+ int32_t index, const char *key,
+ int32_t *length,
+ UErrorCode *status) {
+ char buffer8[16];
+ char *p8;
+ const UChar *s16;
+ const char *s8;
+ UChar32 c16, c8;
+ int32_t length16, length8, i16, i8;
+ UBool forceCopy;
+
+ if(length == NULL) {
+ length = &length16;
+ }
+ if(index >= 0) {
+ s16 = ures_getStringByIndex(resB, index, length, status);
+ } else if(key != NULL) {
+ s16 = ures_getStringByKey(resB, key, length, status);
+ } else {
+ s16 = ures_getString(resB, length, status);
+ }
+ if(U_FAILURE(*status)) {
+ return s16;
+ }
+ length16 = *length;
+
+ /* try the UTF-8 variant of ures_getStringXYZ() */
+ for(forceCopy = FALSE; forceCopy <= TRUE; ++forceCopy) {
+ p8 = buffer8;
+ length8 = (int32_t)sizeof(buffer8);
+ if(index >= 0) {
+ s8 = ures_getUTF8StringByIndex(resB, index, p8, &length8, forceCopy, status);
+ } else if(key != NULL) {
+ s8 = ures_getUTF8StringByKey(resB, key, p8, &length8, forceCopy, status);
+ } else {
+ s8 = ures_getUTF8String(resB, p8, &length8, forceCopy, status);
+ }
+ if(*status == U_INVALID_CHAR_FOUND) {
+ /* the UTF-16 string contains an unpaired surrogate, can't test UTF-8 variant */
+ return s16;
+ }
+ if(*status == U_BUFFER_OVERFLOW_ERROR) {
+ *status = U_ZERO_ERROR;
+ p8 = (char *)malloc(++length8);
+ if(p8 == NULL) {
+ return s16;
+ }
+ if(index >= 0) {
+ s8 = ures_getUTF8StringByIndex(resB, index, p8, &length8, forceCopy, status);
+ } else if(key != NULL) {
+ s8 = ures_getUTF8StringByKey(resB, key, p8, &length8, forceCopy, status);
+ } else {
+ s8 = ures_getUTF8String(resB, p8, &length8, forceCopy, status);
+ }
+ }
+ if(U_FAILURE(*status)) {
+ /* something unexpected happened */
+ if(p8 != buffer8) {
+ free(p8);
+ }
+ return s16;
+ }
+
+ if(forceCopy && s8 != p8) {
+ log_err("ures_getUTF8String(%p, %ld, '%s') did not write the string to dest\n",
+ resB, (long)index, key);
+ }
+
+ /* verify NUL-termination */
+ if((p8 != buffer8 || length8 < sizeof(buffer8)) && s8[length8] != 0) {
+ log_err("ures_getUTF8String(%p, %ld, '%s') did not NUL-terminate\n",
+ resB, (long)index, key);
+ }
+ /* verify correct string */
+ i16 = i8 = 0;
+ while(i16 < length16 && i8 < length8) {
+ U16_NEXT(s16, i16, length16, c16);
+ U8_NEXT(s8, i8, length8, c8);
+ if(c16 != c8) {
+ log_err("ures_getUTF8String(%p, %ld, '%s') got a bad string, c16=U+%04lx!=U+%04lx=c8 before i16=%ld\n",
+ resB, (long)index, key, (long)c16, (long)c8, (long)i16);
+ }
+ }
+ /* verify correct length */
+ if(i16 < length16) {
+ log_err("ures_getUTF8String(%p, %ld, '%s') UTF-8 string too short, length8=%ld, length16=%ld\n",
+ resB, (long)index, key, (long)length8, (long)length16);
+ }
+ if(i8 < length8) {
+ log_err("ures_getUTF8String(%p, %ld, '%s') UTF-8 string too long, length8=%ld, length16=%ld\n",
+ resB, (long)index, key, (long)length8, (long)length16);
+ }
+
+ /* clean up */
+ if(p8 != buffer8) {
+ free(p8);
+ }
+ }
+ return s16;
+}
+
+/*
+ * API tests for ures_getUTF8String().
+ * Most cases are handled by tres_getString(), which leaves argument checking
+ * to be tested here.
+ * Since the variants share most of their implementation, we only need to test
+ * one of them.
+ * We also need not test for checking arguments which will be checked by the
+ * UTF-16 ures_getStringXYZ() that are called internally.
+ */
+static void
+TestGetUTF8String() {
+ UResourceBundle *res;
+ const char *testdatapath;
+ char buffer8[16];
+ const char *s8;
+ int32_t length8;
+ UErrorCode status;
+
+ status = U_ZERO_ERROR;
+ testdatapath = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat - %s\n", u_errorName(status));
+ return;
+ }
+
+ res = ures_open(testdatapath, "", &status);
+ if(U_FAILURE(status)) {
+ log_err("Unable to ures_open(testdata, \"\") - %s\n", u_errorName(status));
+ return;
+ }
+
+ /* one good call */
+ status = U_ZERO_ERROR;
+ length8 = (int32_t)sizeof(buffer8);
+ s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", buffer8, &length8, FALSE, &status);
+ if(status != U_ZERO_ERROR) {
+ log_err("ures_getUTF8StringByKey(testdata/root string) malfunctioned - %s\n", u_errorName(status));
+ }
+
+ /* negative capacity */
+ status = U_ZERO_ERROR;
+ length8 = -1;
+ s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", buffer8, &length8, FALSE, &status);
+ if(status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ures_getUTF8StringByKey(capacity<0) malfunctioned - %s\n", u_errorName(status));
+ }
+
+ /* capacity>0 but dest=NULL */
+ status = U_ZERO_ERROR;
+ length8 = (int32_t)sizeof(buffer8);
+ s8 = ures_getUTF8StringByKey(res, "string_only_in_Root", NULL, &length8, FALSE, &status);
+ if(status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ures_getUTF8StringByKey(dest=NULL capacity>0) malfunctioned - %s\n", u_errorName(status));
+ }
+
+ ures_close(res);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h
new file mode 100644
index 00000000000..f6becdb979c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/creststn.h
@@ -0,0 +1,85 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/***************************************************************************
+*
+* File CRESTST.H
+*
+* Modification History:
+* Name Date Description
+* Madhu Katragadda 05/09/2000 Ported Tests for New ResourceBundle API
+* Madhu Katragadda 05/24/2000 Added new tests to test RES_BINARY for collationElements
+*************************************************************************************************
+*/
+#ifndef _CRESTSTN
+#define _CRESTSTN
+/* C TEST FOR NEW RESOURCEBUNDLE API*/
+#include "cintltst.h"
+
+/*
+ * Test wrapper for ures_getStringXYZ(), for testing other variants of
+ * these functions as well.
+ * If index>=0, calls ures_getStringByIndex().
+ * If key!=NULL, calls ures_getStringByKey().
+ */
+extern const UChar *
+tres_getString(const UResourceBundle *resB,
+ int32_t index, const char *key,
+ int32_t *length,
+ UErrorCode *status);
+
+void addNEWResourceBundleTest(TestNode**);
+
+/**
+*Perform several extensive tests using the subtest routine testTag
+*/
+static void TestResourceBundles(void);
+/**
+* Test construction of ResourceBundle accessing a custom test resource-file
+**/
+static void TestConstruction1(void);
+
+static void TestAliasConflict(void);
+
+static void TestFallback(void);
+
+static void TestBinaryCollationData(void);
+
+static void TestNewTypes(void);
+
+static void TestEmptyTypes(void);
+
+static void TestAPI(void);
+
+static void TestErrorConditions(void);
+
+static void TestGetVersion(void);
+
+static void TestGetVersionColl(void);
+
+static void TestEmptyBundle(void);
+
+static void TestDirectAccess(void);
+
+static void TestResourceLevelAliasing(void);
+
+static void TestErrorCodes(void);
+
+static void TestJB3763(void);
+
+static void TestXPath(void);
+
+static void TestStackReuse(void);
+
+/**
+* extensive subtests called by TestResourceBundles
+**/
+static UBool testTag(const char* frag, UBool in_Root, UBool in_te, UBool in_te_IN);
+
+static void record_pass(void);
+static void record_fail(void);
+
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c
new file mode 100644
index 00000000000..befc6d4dc2d
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrcase.c
@@ -0,0 +1,944 @@
+/*
+*******************************************************************************
+*
+* Copyright (C) 2002-2007, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+*******************************************************************************
+* file name: cstrcase.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2002feb21
+* created by: Markus W. Scherer
+*
+* Test file for string casing C API functions.
+*/
+
+#include <string.h>
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+#include "unicode/ustring.h"
+#include "unicode/uloc.h"
+#include "unicode/ubrk.h"
+#include "unicode/ucasemap.h"
+#include "cmemory.h"
+#include "cintltst.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+/* test string case mapping functions --------------------------------------- */
+
+static void
+TestCaseLower(void) {
+ static const UChar
+
+ beforeLower[]= { 0x61, 0x42, 0x49, 0x3a3, 0xdf, 0x3a3, 0x2f, 0xd93f, 0xdfff },
+ lowerRoot[]= { 0x61, 0x62, 0x69, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff },
+ lowerTurkish[]={ 0x61, 0x62, 0x131, 0x3c3, 0xdf, 0x3c2, 0x2f, 0xd93f, 0xdfff };
+
+ UChar buffer[32];
+ int32_t length;
+ UErrorCode errorCode;
+
+ /* lowercase with root locale and separate buffers */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
+ "",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToLower(root locale)=%ld error=%s string matches: %s\t\nlowerRoot=%s\t\nbuffer=%s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(lowerRoot, buffer, length*U_SIZEOF_UCHAR)==0 &&
+buffer[length]==0 ? "yes" : "no",
+ aescstrdup(lowerRoot,-1),
+ aescstrdup(buffer,-1));
+ }
+
+ /* lowercase with turkish locale and in the same buffer */
+ uprv_memcpy(buffer, beforeLower, sizeof(beforeLower));
+ buffer[sizeof(beforeLower)/U_SIZEOF_UCHAR]=0;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToLower(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ buffer, -1, /* implicit srcLength */
+ "tr",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(lowerTurkish)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToLower(turkish locale)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(lowerTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* test preflighting */
+ buffer[0]=buffer[2]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToLower(buffer, 2, /* set destCapacity=2 */
+ beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
+ "",
+ &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=(sizeof(lowerRoot)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)!=0 ||
+ buffer[2]!=0xabcd
+ ) {
+ log_err("error in u_strToLower(root locale preflighting)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(lowerRoot, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no");
+ }
+
+ /* test error handling */
+ errorCode=U_ZERO_ERROR;
+ length=u_strToLower(NULL, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
+ "",
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error in u_strToLower(root locale dest=NULL)=%ld error=%s\n",
+ length,
+ u_errorName(errorCode));
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToLower(buffer, -1,
+ beforeLower, sizeof(beforeLower)/U_SIZEOF_UCHAR,
+ "",
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strToLower(root locale destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+}
+
+static void
+TestCaseUpper(void) {
+ static const UChar
+
+ beforeUpper[]= { 0x61, 0x42, 0x69, 0x3c2, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xd93f, 0xdfff },
+ upperRoot[]= { 0x41, 0x42, 0x49, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff },
+ upperTurkish[]={ 0x41, 0x42, 0x130, 0x3a3, 0x53, 0x53, 0x3a3, 0x2f, 0x46, 0x46, 0x49, 0xd93f, 0xdfff };
+
+ UChar buffer[32];
+ int32_t length;
+ UErrorCode errorCode;
+
+ /* uppercase with root locale and in the same buffer */
+ uprv_memcpy(buffer, beforeUpper, sizeof(beforeUpper));
+ errorCode=U_ZERO_ERROR;
+ length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ buffer, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
+ "",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(upperRoot)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToUpper(root locale)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(upperRoot, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* uppercase with turkish locale and separate buffers */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
+ "tr",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToUpper(turkish locale)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(upperTurkish, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* test preflighting */
+ errorCode=U_ZERO_ERROR;
+ length=u_strToUpper(NULL, 0,
+ beforeUpper, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
+ "tr",
+ &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=(sizeof(upperTurkish)/U_SIZEOF_UCHAR)
+ ) {
+ log_err("error in u_strToUpper(turkish locale pure preflighting)=%ld error=%s\n",
+ length,
+ u_errorName(errorCode));
+ }
+
+ /* test error handling */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ NULL, sizeof(beforeUpper)/U_SIZEOF_UCHAR,
+ "tr",
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strToUpper(turkish locale src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToUpper(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeUpper, -2,
+ "tr",
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strToUpper(turkish locale srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+}
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+static void
+TestCaseTitle(void) {
+ static const UChar
+
+ beforeTitle[]= { 0x61, 0x42, 0x20, 0x69, 0x3c2, 0x20, 0xdf, 0x3c3, 0x2f, 0xfb03, 0xd93f, 0xdfff },
+ titleWord[]= { 0x41, 0x62, 0x20, 0x49, 0x3c2, 0x20, 0x53, 0x73, 0x3c3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff },
+ titleChar[]= { 0x41, 0x42, 0x20, 0x49, 0x3a3, 0x20, 0x53, 0x73, 0x3a3, 0x2f, 0x46, 0x66, 0x69, 0xd93f, 0xdfff };
+
+ UChar buffer[32];
+ UBreakIterator *titleIterChars;
+ int32_t length;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ titleIterChars=ubrk_open(UBRK_CHARACTER, "", beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ubrk_open(UBRK_CHARACTER)->%s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* titlecase with standard break iterator and in the same buffer */
+ uprv_memcpy(buffer, beforeTitle, sizeof(beforeTitle));
+ errorCode=U_ZERO_ERROR;
+ length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ buffer, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
+ NULL, "",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(titleWord)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToTitle(standard iterator)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(titleWord, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* titlecase with UBRK_CHARACTERS and separate buffers */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
+ titleIterChars, "",
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(titleChar)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strToTitle(UBRK_CHARACTERS)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(titleChar, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* test preflighting */
+ errorCode=U_ZERO_ERROR;
+ length=u_strToTitle(NULL, 0,
+ beforeTitle, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
+ titleIterChars, "",
+ &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=(sizeof(titleChar)/U_SIZEOF_UCHAR)
+ ) {
+ log_err("error in u_strToTitle(UBRK_CHARACTERS pure preflighting)=%ld error=%s\n",
+ length,
+ u_errorName(errorCode));
+ }
+
+ /* test error handling */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ NULL, sizeof(beforeTitle)/U_SIZEOF_UCHAR,
+ titleIterChars, "",
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strToTitle(UBRK_CHARACTERS src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strToTitle(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ beforeTitle, -2,
+ titleIterChars, "",
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strToTitle(UBRK_CHARACTERS srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+
+ ubrk_close(titleIterChars);
+}
+
+#endif
+
+/* test case folding and case-insensitive string compare -------------------- */
+
+static void
+TestCaseFolding(void) {
+ /*
+ * CaseFolding.txt says about i and its cousins:
+ * 0049; C; 0069; # LATIN CAPITAL LETTER I
+ * 0049; T; 0131; # LATIN CAPITAL LETTER I
+ *
+ * 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE
+ * 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE
+ * That's all.
+ * See CaseFolding.txt and the Unicode Standard for how to apply the case foldings.
+ */
+ static const UChar32
+ simple[]={
+ /* input, default, exclude special i */
+ 0x61, 0x61, 0x61,
+ 0x49, 0x69, 0x131,
+ 0x130, 0x130, 0x69,
+ 0x131, 0x131, 0x131,
+ 0xdf, 0xdf, 0xdf,
+ 0xfb03, 0xfb03, 0xfb03,
+ 0x1040e,0x10436,0x10436,
+ 0x5ffff,0x5ffff,0x5ffff
+ };
+
+ static const UChar
+ mixed[]= { 0x61, 0x42, 0x130, 0x49, 0x131, 0x3d0, 0xdf, 0xfb03, 0xd93f, 0xdfff },
+ foldedDefault[]= { 0x61, 0x62, 0x69, 0x307, 0x69, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff },
+ foldedExcludeSpecialI[]={ 0x61, 0x62, 0x69, 0x131, 0x131, 0x3b2, 0x73, 0x73, 0x66, 0x66, 0x69, 0xd93f, 0xdfff };
+
+ UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 };
+
+ const UChar32 *p;
+ int32_t i;
+
+ UChar buffer[32];
+ int32_t length;
+ UErrorCode errorCode;
+ UBool isUnicode_3_1;
+
+ /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */
+ u_getUnicodeVersion(unicodeVersion);
+ isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0;
+
+ /* test simple case folding */
+ p=simple;
+ for(i=0; i<sizeof(simple)/12; p+=3, ++i) {
+ if(u_foldCase(p[0], U_FOLD_CASE_DEFAULT)!=p[1]) {
+ log_err("error: u_foldCase(0x%04lx, default)=0x%04lx instead of 0x%04lx\n",
+ p[0], u_foldCase(p[0], U_FOLD_CASE_DEFAULT), p[1]);
+ return;
+ }
+
+ if(isUnicode_3_1 && u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I)!=p[2]) {
+ log_err("error: u_foldCase(0x%04lx, exclude special i)=0x%04lx instead of 0x%04lx\n",
+ p[0], u_foldCase(p[0], U_FOLD_CASE_EXCLUDE_SPECIAL_I), p[2]);
+ return;
+ }
+ }
+
+ /* test full string case folding with default option and separate buffers */
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strFoldCase(default)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* exclude special i */
+ if(isUnicode_3_1) {
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_EXCLUDE_SPECIAL_I,
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strFoldCase(exclude special i)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+ }
+
+ /* test full string case folding with default option and in the same buffer */
+ uprv_memcpy(buffer, mixed, sizeof(mixed));
+ buffer[sizeof(mixed)/U_SIZEOF_UCHAR]=0;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ buffer, -1, /* implicit srcLength */
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strFoldCase(default same buffer)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(foldedDefault, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+
+ /* test full string case folding, exclude special i, in the same buffer */
+ if(isUnicode_3_1) {
+ uprv_memcpy(buffer, mixed, sizeof(mixed));
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ buffer, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_EXCLUDE_SPECIAL_I,
+ &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=(sizeof(foldedExcludeSpecialI)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)!=0 ||
+ buffer[length]!=0
+ ) {
+ log_err("error in u_strFoldCase(exclude special i same buffer)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(foldedExcludeSpecialI, buffer, length*U_SIZEOF_UCHAR)==0 && buffer[length]==0 ? "yes" : "no");
+ }
+ }
+
+ /* test preflighting */
+ buffer[0]=buffer[2]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, 2, /* set destCapacity=2 */
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR) ||
+ uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)!=0 ||
+ buffer[2]!=0xabcd
+ ) {
+ log_err("error in u_strFoldCase(default preflighting)=%ld error=%s string matches: %s\n",
+ length,
+ u_errorName(errorCode),
+ uprv_memcmp(foldedDefault, buffer, 2*U_SIZEOF_UCHAR)==0 && buffer[2]==0xabcd ? "yes" : "no");
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(NULL, 0,
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=(sizeof(foldedDefault)/U_SIZEOF_UCHAR)
+ ) {
+ log_err("error in u_strFoldCase(default pure preflighting)=%ld error=%s\n",
+ length,
+ u_errorName(errorCode));
+ }
+
+ /* test error handling */
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(NULL, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error in u_strFoldCase(default dest=NULL)=%ld error=%s\n",
+ length,
+ u_errorName(errorCode));
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, -1,
+ mixed, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_DEFAULT,
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strFoldCase(default destCapacity=-1)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ NULL, sizeof(mixed)/U_SIZEOF_UCHAR,
+ U_FOLD_CASE_EXCLUDE_SPECIAL_I,
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strFoldCase(exclude special i src=NULL)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+
+ buffer[0]=0xabcd;
+ errorCode=U_ZERO_ERROR;
+ length=u_strFoldCase(buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
+ mixed, -2,
+ U_FOLD_CASE_EXCLUDE_SPECIAL_I,
+ &errorCode);
+ if( errorCode!=U_ILLEGAL_ARGUMENT_ERROR ||
+ buffer[0]!=0xabcd
+ ) {
+ log_err("error in u_strFoldCase(exclude special i srcLength=-2)=%ld error=%s buffer[0]==0x%lx\n",
+ length,
+ u_errorName(errorCode),
+ buffer[0]);
+ }
+}
+
+static void
+TestCaseCompare(void) {
+ static const UChar
+
+ mixed[]= { 0x61, 0x42, 0x131, 0x3a3, 0xdf, 0xfb03, 0xd93f, 0xdfff, 0 },
+ otherDefault[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdfff, 0 },
+ otherExcludeSpecialI[]={ 0x41, 0x62, 0x131, 0x3c3, 0x53, 0x73, 0x66, 0x46, 0x69, 0xd93f, 0xdfff, 0 },
+ different[]= { 0x41, 0x62, 0x131, 0x3c3, 0x73, 0x53, 0x46, 0x66, 0x49, 0xd93f, 0xdffd, 0 };
+
+ UVersionInfo unicodeVersion={ 0, 0, 17, 89 }, unicode_3_1={ 3, 1, 0, 0 };
+
+ int32_t result, lenMixed, lenOtherDefault, lenOtherExcludeSpecialI, lenDifferent;
+ UErrorCode errorCode;
+ UBool isUnicode_3_1;
+
+ errorCode=U_ZERO_ERROR;
+
+ lenMixed=u_strlen(mixed);
+ lenOtherDefault=u_strlen(otherDefault);
+ lenOtherExcludeSpecialI=u_strlen(otherExcludeSpecialI);
+ lenDifferent=u_strlen(different);
+
+ /* if unicodeVersion()>=3.1 then test exclude-special-i cases as well */
+ u_getUnicodeVersion(unicodeVersion);
+ isUnicode_3_1= uprv_memcmp(unicodeVersion, unicode_3_1, 4)>=0;
+
+ /* test u_strcasecmp() */
+ result=u_strcasecmp(mixed, otherDefault, U_FOLD_CASE_DEFAULT);
+ if(result!=0) {
+ log_err("error: u_strcasecmp(mixed, other, default)=%ld instead of 0\n", result);
+ }
+ result=u_strCaseCompare(mixed, -1, otherDefault, -1, U_FOLD_CASE_DEFAULT, &errorCode);
+ if(result!=0) {
+ log_err("error: u_strCaseCompare(mixed, other, default)=%ld instead of 0\n", result);
+ }
+
+ /* test u_strcasecmp() - exclude special i */
+ result=u_strcasecmp(mixed, otherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I);
+ if(result!=0) {
+ log_err("error: u_strcasecmp(mixed, other, exclude special i)=%ld instead of 0\n", result);
+ }
+ result=u_strCaseCompare(mixed, lenMixed, otherExcludeSpecialI, lenOtherExcludeSpecialI, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
+ if(result!=0) {
+ log_err("error: u_strCaseCompare(mixed, other, exclude special i)=%ld instead of 0\n", result);
+ }
+
+ /* test u_strcasecmp() */
+ result=u_strcasecmp(mixed, different, U_FOLD_CASE_DEFAULT);
+ if(result<=0) {
+ log_err("error: u_strcasecmp(mixed, different, default)=%ld instead of positive\n", result);
+ }
+ result=u_strCaseCompare(mixed, -1, different, lenDifferent, U_FOLD_CASE_DEFAULT, &errorCode);
+ if(result<=0) {
+ log_err("error: u_strCaseCompare(mixed, different, default)=%ld instead of positive\n", result);
+ }
+
+ /* test u_strncasecmp() - stop before the sharp s (U+00df) */
+ result=u_strncasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
+ if(result!=0) {
+ log_err("error: u_strncasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
+ }
+ result=u_strCaseCompare(mixed, 4, different, 4, U_FOLD_CASE_DEFAULT, &errorCode);
+ if(result!=0) {
+ log_err("error: u_strCaseCompare(mixed, 4, different, 4, default)=%ld instead of 0\n", result);
+ }
+
+ /* test u_strncasecmp() - stop in the middle of the sharp s (U+00df) */
+ result=u_strncasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
+ if(result<=0) {
+ log_err("error: u_strncasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
+ }
+ result=u_strCaseCompare(mixed, 5, different, 5, U_FOLD_CASE_DEFAULT, &errorCode);
+ if(result<=0) {
+ log_err("error: u_strCaseCompare(mixed, 5, different, 5, default)=%ld instead of positive\n", result);
+ }
+
+ /* test u_memcasecmp() - stop before the sharp s (U+00df) */
+ result=u_memcasecmp(mixed, different, 4, U_FOLD_CASE_DEFAULT);
+ if(result!=0) {
+ log_err("error: u_memcasecmp(mixed, different, 4, default)=%ld instead of 0\n", result);
+ }
+
+ /* test u_memcasecmp() - stop in the middle of the sharp s (U+00df) */
+ result=u_memcasecmp(mixed, different, 5, U_FOLD_CASE_DEFAULT);
+ if(result<=0) {
+ log_err("error: u_memcasecmp(mixed, different, 5, default)=%ld instead of positive\n", result);
+ }
+}
+
+/* test UCaseMap ------------------------------------------------------------ */
+
+/*
+ * API test for UCaseMap;
+ * test cases for actual case mappings using UCaseMap see
+ * intltest utility/UnicodeStringTest/StringCaseTest/TestCasing
+ */
+static void
+TestUCaseMap(void) {
+ static const char
+ aBc[] ={ 0x61, 0x42, 0x63, 0 },
+ abc[] ={ 0x61, 0x62, 0x63, 0 },
+ ABCg[]={ 0x41, 0x42, 0x43, 0x67, 0 },
+ defg[]={ 0x64, 0x65, 0x66, 0x67, 0 };
+ char utf8Out[8];
+
+ UCaseMap *csm;
+ const char *locale;
+ uint32_t options;
+ int32_t length;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ csm=ucasemap_open("tur", 0xa5, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucasemap_open(\"tur\") failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ locale=ucasemap_getLocale(csm);
+ if(0!=strcmp(locale, "tr")) {
+ log_err("ucasemap_getLocale(ucasemap_open(\"tur\"))==%s!=\"tr\"\n", locale);
+ }
+ /* overly long locale IDs get truncated to their language code to avoid unnecessary allocation */
+ ucasemap_setLocale(csm, "I-kLInGOn-the-quick-brown-fox-jumps-over-the-lazy-dog", &errorCode);
+ locale=ucasemap_getLocale(csm);
+ if(0!=strcmp(locale, "i-klingon")) {
+ log_err("ucasemap_getLocale(ucasemap_setLocale(\"I-kLInGOn-the-quick-br...\"))==%s!=\"i-klingon\"\n", locale);
+ }
+
+ errorCode=U_ZERO_ERROR;
+ options=ucasemap_getOptions(csm);
+ if(options!=0xa5) {
+ log_err("ucasemap_getOptions(ucasemap_open(0xa5))==0x%lx!=0xa5\n", (long)options);
+ }
+ ucasemap_setOptions(csm, 0x333333, &errorCode);
+ options=ucasemap_getOptions(csm);
+ if(options!=0x333333) {
+ log_err("ucasemap_getOptions(ucasemap_setOptions(0x333333))==0x%lx!=0x333333\n", (long)options);
+ }
+
+ /* test case mapping API; not all permutations necessary due to shared implementation code */
+
+ /* NUL terminated source */
+ errorCode=U_ZERO_ERROR;
+ length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
+ if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(aBc\\0) failed\n");
+ }
+
+ /* incoming failure code */
+ errorCode=U_PARSE_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
+ if(errorCode!=U_PARSE_ERROR || 0!=strcmp(defg, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(failure) failed\n");
+ }
+
+ /* overlapping input & output */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, aBc);
+ length=ucasemap_utf8ToUpper(csm, utf8Out, 2, utf8Out+1, 2, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
+ log_err("ucasemap_utf8ToUpper(overlap 1) failed\n");
+ }
+
+ /* overlap in the other direction */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, aBc);
+ length=ucasemap_utf8ToUpper(csm, utf8Out+1, 2, utf8Out, 2, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(aBc, utf8Out)) {
+ log_err("ucasemap_utf8ToUpper(overlap 2) failed\n");
+ }
+
+ /* NULL destination */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToLower(csm, NULL, (int32_t)sizeof(utf8Out), aBc, -1, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(dest=NULL) failed\n");
+ }
+
+ /* destCapacity<0 */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToLower(csm, utf8Out, -2, aBc, -1, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(destCapacity<0) failed\n");
+ }
+
+ /* NULL source */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), NULL, -1, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(src=NULL) failed\n");
+ }
+
+ /* srcLength<-1 */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToLower(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, -2, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || 0!=strcmp(defg, utf8Out)) {
+ log_err("ucasemap_utf8ToLower(srcLength<-1) failed\n");
+ }
+
+ /* buffer overflow */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToUpper(csm, utf8Out, 2, aBc, 3, &errorCode);
+ if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3 || 0!=strcmp(defg+2, utf8Out+2)) {
+ log_err("ucasemap_utf8ToUpper(overflow) failed\n");
+ }
+
+ /* dest not terminated (leaves g from defg alone) */
+ errorCode=U_ZERO_ERROR;
+ strcpy(utf8Out, defg);
+ length=ucasemap_utf8ToUpper(csm, utf8Out, 3, aBc, 3, &errorCode);
+ if(errorCode!=U_STRING_NOT_TERMINATED_WARNING || length!=3 || 0!=strcmp(ABCg, utf8Out)) {
+ log_err("ucasemap_utf8ToUpper(overflow) failed\n");
+ }
+
+ /* C API coverage for case folding. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
+ errorCode=U_ZERO_ERROR;
+ utf8Out[0]=0;
+ length=ucasemap_utf8FoldCase(csm, utf8Out, (int32_t)sizeof(utf8Out), aBc, 3, &errorCode);
+ if(U_FAILURE(errorCode) || length!=3 || 0!=strcmp(abc, utf8Out)) {
+ log_err("ucasemap_utf8FoldCase(aBc) failed\n");
+ }
+
+ ucasemap_close(csm);
+}
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+/* Try titlecasing with options. */
+static void
+TestUCaseMapToTitle(void) {
+ /* "a 'CaT. A 'dOg! 'eTc." where '=U+02BB */
+ /*
+ * Note: The sentence BreakIterator does not recognize a '.'
+ * as a sentence terminator if it is followed by lowercase.
+ * That is why the example has the '!'.
+ */
+ static const UChar
+
+ beforeTitle[]= { 0x61, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x54, 0x63, 0x2e },
+ titleWord[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x44, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x74, 0x63, 0x2e },
+ titleWordNoAdjust[]={ 0x41, 0x20, 0x2bb, 0x63, 0x61, 0x74, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x6f, 0x67, 0x21, 0x20, 0x2bb, 0x65, 0x74, 0x63, 0x2e },
+ titleSentNoLower[]= { 0x41, 0x20, 0x2bb, 0x43, 0x61, 0x54, 0x2e, 0x20, 0x41, 0x20, 0x2bb, 0x64, 0x4f, 0x67, 0x21, 0x20, 0x2bb, 0x45, 0x54, 0x63, 0x2e };
+
+ UChar buffer[32];
+ UCaseMap *csm;
+ UBreakIterator *sentenceIter;
+ const UBreakIterator *iter;
+ int32_t length;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ csm=ucasemap_open("", 0, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucasemap_open(\"\") failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ iter=ucasemap_getBreakIterator(csm);
+ if(iter!=NULL) {
+ log_err("ucasemap_getBreakIterator() returns %p!=NULL before setting any iterator or titlecasing\n", iter);
+ }
+
+ /* Use default UBreakIterator: Word breaks. */
+ length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=LENGTHOF(titleWord) ||
+ 0!=u_memcmp(buffer, titleWord, length) ||
+ buffer[length]!=0
+ ) {
+ log_err("ucasemap_toTitle(default iterator)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
+ }
+
+ iter=ucasemap_getBreakIterator(csm);
+ if(iter==NULL) {
+ log_err("ucasemap_getBreakIterator() returns NULL after titlecasing\n");
+ }
+
+ /* Try U_TITLECASE_NO_BREAK_ADJUSTMENT. */
+ ucasemap_setOptions(csm, U_TITLECASE_NO_BREAK_ADJUSTMENT, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucasemap_setOptions(U_TITLECASE_NO_BREAK_ADJUSTMENT) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=LENGTHOF(titleWordNoAdjust) ||
+ 0!=u_memcmp(buffer, titleWordNoAdjust, length) ||
+ buffer[length]!=0
+ ) {
+ log_err("ucasemap_toTitle(default iterator, no break adjustment)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
+ }
+
+ /* Set a sentence break iterator. */
+ errorCode=U_ZERO_ERROR;
+ sentenceIter=ubrk_open(UBRK_SENTENCE, "", NULL, 0, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ubrk_open(UBRK_SENTENCE) failed - %s\n", u_errorName(errorCode));
+ ucasemap_close(csm);
+ return;
+ }
+ ucasemap_setBreakIterator(csm, sentenceIter, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucasemap_setBreakIterator(sentence iterator) failed - %s\n", u_errorName(errorCode));
+ ubrk_close(sentenceIter);
+ ucasemap_close(csm);
+ return;
+ }
+ iter=ucasemap_getBreakIterator(csm);
+ if(iter!=sentenceIter) {
+ log_err("ucasemap_getBreakIterator() returns %p!=%p after setting the iterator\n", iter, sentenceIter);
+ }
+
+ ucasemap_setOptions(csm, U_TITLECASE_NO_LOWERCASE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucasemap_setOptions(U_TITLECASE_NO_LOWERCASE) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* Use the sentence break iterator with the option. Preflight first. */
+ length=ucasemap_toTitle(csm, NULL, 0, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
+ if( errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ length!=LENGTHOF(titleSentNoLower)
+ ) {
+ log_err("ucasemap_toTitle(preflight sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ buffer[0]=0;
+ length=ucasemap_toTitle(csm, buffer, LENGTHOF(buffer), beforeTitle, LENGTHOF(beforeTitle), &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=LENGTHOF(titleSentNoLower) ||
+ 0!=u_memcmp(buffer, titleSentNoLower, length) ||
+ buffer[length]!=0
+ ) {
+ log_err("ucasemap_toTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
+ }
+
+ /* UTF-8 C API coverage. More thorough test via C++ intltest's StringCaseTest::TestCasing(). */
+ {
+ char utf8BeforeTitle[64], utf8TitleSentNoLower[64], utf8[64];
+ int32_t utf8BeforeTitleLength, utf8TitleSentNoLowerLength;
+
+ errorCode=U_ZERO_ERROR;
+ u_strToUTF8(utf8BeforeTitle, (int32_t)sizeof(utf8BeforeTitle), &utf8BeforeTitleLength, beforeTitle, LENGTHOF(beforeTitle), &errorCode);
+ u_strToUTF8(utf8TitleSentNoLower, (int32_t)sizeof(utf8TitleSentNoLower), &utf8TitleSentNoLowerLength, titleSentNoLower, LENGTHOF(titleSentNoLower), &errorCode);
+
+ length=ucasemap_utf8ToTitle(csm, utf8, (int32_t)sizeof(utf8), utf8BeforeTitle, utf8BeforeTitleLength, &errorCode);
+ if( U_FAILURE(errorCode) ||
+ length!=utf8TitleSentNoLowerLength ||
+ 0!=uprv_memcmp(utf8, utf8TitleSentNoLower, length) ||
+ utf8[length]!=0
+ ) {
+ log_err("ucasemap_utf8ToTitle(sentence break iterator, no lowercasing)=%ld failed - %s\n", (long)length, u_errorName(errorCode));
+ }
+ }
+
+ ucasemap_close(csm);
+}
+
+#endif
+
+void addCaseTest(TestNode** root);
+
+void addCaseTest(TestNode** root) {
+ /* cstrcase.c functions, declared in cucdtst.h */
+ addTest(root, &TestCaseLower, "tsutil/cstrcase/TestCaseLower");
+ addTest(root, &TestCaseUpper, "tsutil/cstrcase/TestCaseUpper");
+#if !UCONFIG_NO_BREAK_ITERATION
+ addTest(root, &TestCaseTitle, "tsutil/cstrcase/TestCaseTitle");
+#endif
+ addTest(root, &TestCaseFolding, "tsutil/cstrcase/TestCaseFolding");
+ addTest(root, &TestCaseCompare, "tsutil/cstrcase/TestCaseCompare");
+ addTest(root, &TestUCaseMap, "tsutil/cstrcase/TestUCaseMap");
+#if !UCONFIG_NO_BREAK_ITERATION
+ addTest(root, &TestUCaseMapToTitle, "tsutil/cstrcase/TestUCaseMapToTitle");
+#endif
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c
new file mode 100644
index 00000000000..ea6fe5cbeaa
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cstrtest.c
@@ -0,0 +1,286 @@
+/*
+**********************************************************************
+* Copyright (C) 1998-2004, International Business Machines Corporation
+* and others. All Rights Reserved.
+**********************************************************************
+*
+* File cstrtest.c
+*
+* Modification History:
+*
+* Date Name Description
+* 07/13/2000 Madhu created
+*******************************************************************************
+*/
+
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "cstring.h"
+#include "uinvchar.h"
+#include "cintltst.h"
+#include "cmemory.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void TestAPI(void);
+void addCStringTest(TestNode** root);
+
+static void TestInvariant(void);
+
+void addCStringTest(TestNode** root) {
+ addTest(root, &TestAPI, "tsutil/cstrtest/TestAPI");
+ addTest(root, &TestInvariant, "tsutil/cstrtest/TestInvariant");
+}
+
+static void TestAPI(void)
+{
+ int32_t intValue=0;
+ char src[30]="HELLO THERE", dest[30];
+ static const char *const abc="abcdefghijklmnopqrstuvwxyz", *const ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *temp;
+ int32_t i;
+
+ log_verbose("Testing uprv_tolower() and uprv_toupper()\n");
+ for(i=0; i<=26; ++i) {
+ dest[i]=uprv_tolower(abc[i]);
+ }
+ if(0!=strcmp(abc, dest)) {
+ log_err("uprv_tolower(abc) failed\n");
+ }
+
+ for(i=0; i<=26; ++i) {
+ dest[i]=uprv_tolower(ABC[i]);
+ }
+ if(0!=strcmp(abc, dest)) {
+ log_err("uprv_tolower(ABC) failed\n");
+ }
+
+ for(i=0; i<=26; ++i) {
+ dest[i]=uprv_toupper(abc[i]);
+ }
+ if(0!=strcmp(ABC, dest)) {
+ log_err("uprv_toupper(abc) failed\n");
+ }
+
+ for(i=0; i<=26; ++i) {
+ dest[i]=uprv_toupper(ABC[i]);
+ }
+ if(0!=strcmp(ABC, dest)) {
+ log_err("uprv_toupper(ABC) failed\n");
+ }
+
+ log_verbose("Testing the API in cstring\n");
+ T_CString_toLowerCase(src);
+ if(uprv_strcmp(src, "hello there") != 0){
+ log_err("FAIL: *** T_CString_toLowerCase() failed. Expected: \"hello there\", Got: \"%s\"\n", src);
+ }
+ T_CString_toUpperCase(src);
+ if(uprv_strcmp(src, "HELLO THERE") != 0){
+ log_err("FAIL: *** T_CString_toUpperCase() failed. Expected: \"HELLO THERE\", Got: \"%s\"\n", src);
+ }
+
+ intValue=T_CString_stringToInteger("34556", 10);
+ if(intValue != 34556){
+ log_err("FAIL: ****T_CString_stringToInteger(\"34556\", 10) failed. Expected: 34556, Got: %d\n", intValue);
+ }
+ intValue=T_CString_stringToInteger("100", 16);
+ if(intValue != 256){
+ log_err("FAIL: ****T_CString_stringToInteger(\"100\", 16) failed. Expected: 256, Got: %d\n", intValue);
+ }
+ i = T_CString_integerToString(src, 34556, 10);
+ if(uprv_strcmp(src, "34556") != 0 || i != 5){
+ log_err("FAIL: ****integerToString(src, 34566, 10); failed. Expected: \"34556\", Got: %s\n", src);
+ }
+ i = T_CString_integerToString(src, 431, 16);
+ if(uprv_stricmp(src, "1AF") != 0 || i != 3){
+ log_err("FAIL: ****integerToString(src, 431, 16); failed. Expected: \"1AF\", Got: %s\n", src);
+ }
+ i = T_CString_int64ToString(src, U_INT64_MAX, 10);
+ if(uprv_strcmp(src, "9223372036854775807") != 0 || i != 19){
+ log_err("FAIL: ****integerToString(src, 9223372036854775807, 10); failed. Got: %s\n", src);
+ }
+ i = T_CString_int64ToString(src, U_INT64_MAX, 16);
+ if(uprv_stricmp(src, "7FFFFFFFFFFFFFFF") != 0 || i != 16){
+ log_err("FAIL: ****integerToString(src, 7FFFFFFFFFFFFFFF, 16); failed. Got: %s\n", src);
+ }
+
+ uprv_strcpy(src, "this is lower case");
+ if(T_CString_stricmp(src, "THIS is lower CASE") != 0){
+ log_err("FAIL: *****T_CString_stricmp() failed.");
+ }
+ if((intValue=T_CString_stricmp(NULL, "first string is null") )!= -1){
+ log_err("FAIL: T_CString_stricmp() where the first string is null failed. Expected: -1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_stricmp("second string is null", NULL)) != 1){
+ log_err("FAIL: T_CString_stricmp() where the second string is null failed. Expected: 1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_stricmp(NULL, NULL)) != 0){
+ log_err("FAIL: T_CString_stricmp(NULL, NULL) failed. Expected: 0, returned %d\n", intValue);;
+ }
+ if((intValue=T_CString_stricmp("", "")) != 0){
+ log_err("FAIL: T_CString_stricmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);;
+ }
+ if((intValue=T_CString_stricmp("", "abc")) != -1){
+ log_err("FAIL: T_CString_stricmp(\"\", \"abc\") failed. Expected: -1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_stricmp("abc", "")) != 1){
+ log_err("FAIL: T_CString_stricmp(\"abc\", \"\") failed. Expected: 1, returned %d\n", intValue);
+ }
+
+ temp=uprv_strdup("strdup");
+ if(uprv_strcmp(temp, "strdup") !=0 ){
+ log_err("FAIL: uprv_strdup() failed. Expected: \"strdup\", Got: %s\n", temp);
+ }
+ uprv_free((char *)temp);
+
+ uprv_strcpy(src, "this is lower case");
+ if(T_CString_strnicmp(src, "THIS", 4 ) != 0){
+ log_err("FAIL: *****T_CString_strnicmp() failed.");
+ }
+ if((intValue=T_CString_strnicmp(NULL, "first string is null", 10) )!= -1){
+ log_err("FAIL: T_CString_strnicmp() where the first string is null failed. Expected: -1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_strnicmp("second string is null", NULL, 10)) != 1){
+ log_err("FAIL: T_CString_strnicmp() where the second string is null failed. Expected: 1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_strnicmp(NULL, NULL, 10)) != 0){
+ log_err("FAIL: T_CString_strnicmp(NULL, NULL, 10) failed. Expected: 0, returned %d\n", intValue);;
+ }
+ if((intValue=T_CString_strnicmp("", "", 10)) != 0){
+ log_err("FAIL: T_CString_strnicmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);;
+ }
+ if((intValue=T_CString_strnicmp("", "abc", 10)) != -1){
+ log_err("FAIL: T_CString_stricmp(\"\", \"abc\", 10) failed. Expected: -1, returned %d\n", intValue);
+ }
+ if((intValue=T_CString_strnicmp("abc", "", 10)) != 1){
+ log_err("FAIL: T_CString_strnicmp(\"abc\", \"\", 10) failed. Expected: 1, returned %d\n", intValue);
+ }
+
+}
+
+/* test invariant-character handling */
+static void
+TestInvariant() {
+ /* all invariant graphic chars and some control codes (not \n!) */
+ const char invariantChars[]=
+ "\t\r \"%&'()*+,-./"
+ "0123456789:;<=>?"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
+ "abcdefghijklmnopqrstuvwxyz";
+
+ const UChar invariantUChars[]={
+ 9, 0xd, 0x20, 0x22, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5f,
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0
+ };
+
+ const char variantChars[]="\n!#$@[\\]^`{|}~";
+
+ const UChar variantUChars[]={
+ 0x0a, 0x21, 0x23, 0x24, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x7b, 0x7c, 0x7d, 0x7e, 0
+ };
+
+ const UChar nonASCIIUChars[]={ 0x80, 0xa0, 0x900, 0xff51 };
+
+ UChar us[120];
+ char cs[120];
+
+ int32_t i, length;
+
+ /* make sure that all invariant characters convert both ways */
+ length=sizeof(invariantChars);
+ u_charsToUChars(invariantChars, us, length);
+ if(u_strcmp(us, invariantUChars)!=0) {
+ log_err("u_charsToUChars(invariantChars) failed\n");
+ }
+
+ u_UCharsToChars(invariantUChars, cs, length);
+ if(strcmp(cs, invariantChars)!=0) {
+ log_err("u_UCharsToChars(invariantUChars) failed\n");
+ }
+
+
+ /*
+ * make sure that variant characters convert from source code literals to Unicode
+ * but not back to char *
+ */
+ length=sizeof(variantChars);
+ u_charsToUChars(variantChars, us, length);
+ if(u_strcmp(us, variantUChars)!=0) {
+ log_err("u_charsToUChars(variantChars) failed\n");
+ }
+
+#ifdef NDEBUG
+ /*
+ * Test u_UCharsToChars(variantUChars) only in release mode because it will
+ * cause an assertion failure in debug builds.
+ */
+ u_UCharsToChars(variantUChars, cs, length);
+ for(i=0; i<length; ++i) {
+ if(cs[i]!=0) {
+ log_err("u_UCharsToChars(variantUChars) converted the %d-th character to %02x instead of 00\n", i, cs[i]);
+ }
+ }
+#endif
+
+ /*
+ * Verify that invariant characters roundtrip from Unicode to the
+ * default converter and back.
+ */
+ {
+ UConverter *cnv;
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open(NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to open the default converter\n");
+ } else {
+ length=ucnv_fromUChars(cnv, cs, sizeof(cs), invariantUChars, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_fromUChars(invariantUChars) failed - %s\n", u_errorName(errorCode));
+ } else if(length!=sizeof(invariantChars)-1 || strcmp(cs, invariantChars)!=0) {
+ log_err("ucnv_fromUChars(invariantUChars) failed\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=ucnv_toUChars(cnv, us, LENGTHOF(us), invariantChars, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_toUChars(invariantChars) failed - %s\n", u_errorName(errorCode));
+ } else if(length!=LENGTHOF(invariantUChars)-1 || u_strcmp(us, invariantUChars)!=0) {
+ log_err("ucnv_toUChars(invariantChars) failed\n");
+ }
+
+ ucnv_close(cnv);
+ }
+ }
+
+ /* API tests */
+ if(!uprv_isInvariantString(invariantChars, -1)) {
+ log_err("uprv_isInvariantString(invariantChars) failed\n");
+ }
+ if(!uprv_isInvariantUString(invariantUChars, -1)) {
+ log_err("uprv_isInvariantUString(invariantUChars) failed\n");
+ }
+ if(!uprv_isInvariantString(invariantChars+strlen(invariantChars), 1)) {
+ log_err("uprv_isInvariantString(\"\\0\") failed\n");
+ }
+
+ for(i=0; i<(sizeof(variantChars)-1); ++i) {
+ if(uprv_isInvariantString(variantChars+i, 1)) {
+ log_err("uprv_isInvariantString(variantChars[%d]) failed\n", i);
+ }
+ if(uprv_isInvariantUString(variantUChars+i, 1)) {
+ log_err("uprv_isInvariantUString(variantUChars[%d]) failed\n", i);
+ }
+ }
+
+ for(i=0; i<LENGTHOF(nonASCIIUChars); ++i) {
+ if(uprv_isInvariantUString(nonASCIIUChars+i, 1)) {
+ log_err("uprv_isInvariantUString(nonASCIIUChars[%d]) failed\n", i);
+ }
+ }
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c
new file mode 100644
index 00000000000..c4a1767d0f9
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.c
@@ -0,0 +1,131 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CTURTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * CollationTurkishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "cturtst.h"
+#include "unicode/ustring.h"
+#include "string.h"
+
+static UCollator *myCollation;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {0x0073/*'s'*/, 0x0327, 0x0000},
+ {0x0076/*'v'*/, 0x00E4, 0x0074/*'t'*/, 0x0000},
+ {0x006f/*'o'*/, 0x006c/*'l'*/, 0x0064/*'d'*/, 0x0000},
+ {0x00FC, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064/*'d'*/, 0x0000},
+ {0x0068/*'h'*/, 0x011E, 0x0061/*'a'*/, 0x006c/*'l'*/, 0x0074/*'t'*/, 0x0000},
+ {0x0073/*'s'*/, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0065/*'e'*/, 0x0073/*'s'*/, 0x015E, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0131, 0x0064/*'d'*/, 0x0000},
+ {0x0069/*'i'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000},
+ {0x00FC, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0131, 0x0064 /*d'*/, 0x0000},
+ {0x0069/*'i'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000},
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {0x0075/*'u'*/, 0x0308, 0x0000},
+ {0x0076/*'v'*/, 0x0062/*'b'*/, 0x0074/*'t'*/, 0x0000},
+ {0x00D6, 0x0061/*'a'*/, 0x0079/*'y'*/, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000},
+ {0x0068/*'h'*/, 0x0061/*'a'*/, 0x006c/*'l'*/, 0x0074/*'t'*/, 0x0000},
+ {0x015E, 0x0074/*'t'*/, 0x0072/*'r'*/, 0x0065/*'e'*/, 0x015E, 0x0073/*'s'*/, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000},
+ {0x0049/*'I'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000},
+ {0x0076/*'v'*/, 0x006f/*'o'*/, 0x0069/*'i'*/, 0x0064 /*d'*/, 0x0000},
+ {0x0049/*'I'*/, 0x0064/*'d'*/, 0x0065/*'e'*/, 0x0061/*'a'*/, 0x0000},
+};
+
+const static UCollationResult results[] = {
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ /* test priamry > 8 */
+ UCOL_LESS,
+ UCOL_LESS, /*Turkish translator made a primary differnce between dotted and dotless I */
+ UCOL_GREATER
+};
+
+
+
+void addTurkishCollTest(TestNode** root)
+{
+
+ addTest(root, &TestPrimary, "tscoll/cturtst/TestPrimary");
+ addTest(root, &TestTertiary, "tscoll/cturtst/TestTertiary");
+
+
+}
+
+static void TestTertiary( )
+{
+
+ int32_t i;
+
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("tr", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing Turkish Collation with Tertiary strength\n");
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 8 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestPrimary()
+{
+
+ int32_t i;
+
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("tr", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing Turkish Collation with Primary strength\n");
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ for (i = 8; i < 11; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h
new file mode 100644
index 00000000000..542a484fc0c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cturtst.h
@@ -0,0 +1,41 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CTURTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationTurkishTest(JAPAN) is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CTRCOLLTST
+#define _CTRCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+
+
+ /*perform test with strength PRIMARY */
+static void TestPrimary(void);
+ /* perform test with strength TERTIARY */
+static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c
new file mode 100644
index 00000000000..f59acfef16c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.c
@@ -0,0 +1,356 @@
+/********************************************************************
+ * Copyright (c) 1997-2007, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ ********************************************************************/
+
+#include <string.h>
+#include "unicode/utypes.h"
+#include "unicode/uscript.h"
+#include "unicode/uchar.h"
+#include "cintltst.h"
+#include "cucdapi.h"
+
+#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0])
+
+void TestUScriptCodeAPI(){
+ int i =0;
+ int numErrors =0;
+ {
+ const char* testNames[]={
+ /* test locale */
+ "en", "en_US", "sr", "ta" , "te_IN",
+ "hi", "he", "ar",
+ /* test abbr */
+ "Hani", "Hang","Hebr","Hira",
+ "Knda","Kana","Khmr","Lao",
+ "Latn",/*"Latf","Latg",*/
+ "Mlym", "Mong",
+
+ /* test names */
+ "CYRILLIC","DESERET","DEVANAGARI","ETHIOPIC","GEORGIAN",
+ "GOTHIC", "GREEK", "GUJARATI", "COMMON", "INHERITED",
+ /* test lower case names */
+ "malayalam", "mongolian", "myanmar", "ogham", "old-italic",
+ "oriya", "runic", "sinhala", "syriac","tamil",
+ "telugu", "thaana", "thai", "tibetan",
+ /* test the bounds*/
+ "tagb", "arabic",
+ /* test bogus */
+ "asfdasd", "5464", "12235",
+ /* test the last index */
+ "zyyy", "YI",
+ '\0'
+ };
+ UScriptCode expected[] ={
+ /* locales should return */
+ USCRIPT_LATIN, USCRIPT_LATIN, USCRIPT_CYRILLIC, USCRIPT_TAMIL, USCRIPT_TELUGU,
+ USCRIPT_DEVANAGARI, USCRIPT_HEBREW, USCRIPT_ARABIC,
+ /* abbr should return */
+ USCRIPT_HAN, USCRIPT_HANGUL, USCRIPT_HEBREW, USCRIPT_HIRAGANA,
+ USCRIPT_KANNADA, USCRIPT_KATAKANA, USCRIPT_KHMER, USCRIPT_LAO,
+ USCRIPT_LATIN,/* USCRIPT_LATIN, USCRIPT_LATIN,*/
+ USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN,
+ /* names should return */
+ USCRIPT_CYRILLIC, USCRIPT_DESERET, USCRIPT_DEVANAGARI, USCRIPT_ETHIOPIC, USCRIPT_GEORGIAN,
+ USCRIPT_GOTHIC, USCRIPT_GREEK, USCRIPT_GUJARATI, USCRIPT_COMMON, USCRIPT_INHERITED,
+ /* lower case names should return */
+ USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN, USCRIPT_MYANMAR, USCRIPT_OGHAM, USCRIPT_OLD_ITALIC,
+ USCRIPT_ORIYA, USCRIPT_RUNIC, USCRIPT_SINHALA, USCRIPT_SYRIAC, USCRIPT_TAMIL,
+ USCRIPT_TELUGU, USCRIPT_THAANA, USCRIPT_THAI, USCRIPT_TIBETAN,
+ /* bounds */
+ USCRIPT_TAGBANWA, USCRIPT_ARABIC,
+ /* bogus names should return invalid code */
+ USCRIPT_INVALID_CODE, USCRIPT_INVALID_CODE, USCRIPT_INVALID_CODE,
+ USCRIPT_COMMON, USCRIPT_YI,
+ };
+
+ UErrorCode err = U_ZERO_ERROR;
+
+ const int32_t capacity = 10;
+
+ for( ; testNames[i]!='\0'; i++){
+ UScriptCode script[10]={USCRIPT_INVALID_CODE};
+ uscript_getCode(testNames[i],script,capacity, &err);
+ if( script[0] != expected[i]){
+ log_err("Error getting script code Got: %i Expected: %i for name %s\n",
+ script[0],expected[i],testNames[i]);
+ numErrors++;
+ }
+ }
+ if(numErrors >0 ){
+ log_data_err("Errors uchar_getScriptCode() : %i \n",numErrors);
+ }
+ }
+
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t capacity=0;
+ int32_t j;
+ UScriptCode jaCode[]={USCRIPT_KATAKANA, USCRIPT_HIRAGANA, USCRIPT_HAN };
+ UScriptCode script[10]={USCRIPT_INVALID_CODE};
+ int32_t num = uscript_getCode("ja",script,capacity, &err);
+ /* preflight */
+ if(err==U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ capacity = 10;
+ num = uscript_getCode("ja",script,capacity, &err);
+ if(num!=(sizeof(jaCode)/sizeof(UScriptCode))){
+ log_err("Errors uscript_getScriptCode() for Japanese locale: num=%d, expected %d \n",
+ num, (sizeof(jaCode)/sizeof(UScriptCode)));
+ }
+ for(j=0;j<sizeof(jaCode)/sizeof(UScriptCode);j++) {
+ if(script[j]!=jaCode[j]) {
+ log_err("Japanese locale: code #%d was %d (%s) but expected %d (%s)\n", j,
+ script[j], uscript_getName(script[j]),
+ jaCode[j], uscript_getName(jaCode[j]));
+
+ }
+ }
+ }else{
+ log_data_err("Errors in uscript_getScriptCode() expected error : %s got: %s \n",
+ "U_BUFFER_OVERFLOW_ERROR",
+ u_errorName(err));
+ }
+
+ }
+
+ {
+ UScriptCode testAbbr[]={
+ /* names should return */
+ USCRIPT_CYRILLIC, USCRIPT_DESERET, USCRIPT_DEVANAGARI, USCRIPT_ETHIOPIC, USCRIPT_GEORGIAN,
+ USCRIPT_GOTHIC, USCRIPT_GREEK, USCRIPT_GUJARATI,
+ };
+
+ const char* expectedNames[]={
+
+ /* test names */
+ "Cyrillic","Deseret","Devanagari","Ethiopic","Georgian",
+ "Gothic", "Greek", "Gujarati",
+ '\0'
+ };
+ i=0;
+ while(i<sizeof(testAbbr)/sizeof(UScriptCode)){
+ const char* name = uscript_getName(testAbbr[i]);
+ if(name == NULL) {
+ log_data_err("Couldn't get script name\n");
+ return;
+ }
+ numErrors=0;
+ if(strcmp(expectedNames[i],name)!=0){
+ log_err("Error getting abbreviations Got: %s Expected: %s\n",name,expectedNames[i]);
+ numErrors++;
+ }
+ if(numErrors > 0){
+ if(numErrors >0 ){
+ log_err("Errors uchar_getScriptAbbr() : %i \n",numErrors);
+ }
+ }
+ i++;
+ }
+
+ }
+
+ {
+ UScriptCode testAbbr[]={
+ /* abbr should return */
+ USCRIPT_HAN, USCRIPT_HANGUL, USCRIPT_HEBREW, USCRIPT_HIRAGANA,
+ USCRIPT_KANNADA, USCRIPT_KATAKANA, USCRIPT_KHMER, USCRIPT_LAO,
+ USCRIPT_LATIN,
+ USCRIPT_MALAYALAM, USCRIPT_MONGOLIAN,
+ };
+
+ const char* expectedAbbr[]={
+ /* test abbr */
+ "Hani", "Hang","Hebr","Hira",
+ "Knda","Kana","Khmr","Laoo",
+ "Latn",
+ "Mlym", "Mong",
+ '\0'
+ };
+ i=0;
+ while(i<sizeof(testAbbr)/sizeof(UScriptCode)){
+ const char* name = uscript_getShortName(testAbbr[i]);
+ numErrors=0;
+ if(strcmp(expectedAbbr[i],name)!=0){
+ log_err("Error getting abbreviations Got: %s Expected: %s\n",name,expectedAbbr[i]);
+ numErrors++;
+ }
+ if(numErrors > 0){
+ if(numErrors >0 ){
+ log_err("Errors uchar_getScriptAbbr() : %i \n",numErrors);
+ }
+ }
+ i++;
+ }
+
+ }
+ /* now test uscript_getScript() API */
+ {
+#define MAX_ARRAY_SIZE 23
+ uint32_t codepoints[] = {
+ 0x0000FF9D, /* USCRIPT_KATAKANA*/
+ 0x0000FFBE, /* USCRIPT_HANGUL*/
+ 0x0000FFC7, /* USCRIPT_HANGUL*/
+ 0x0000FFCF, /* USCRIPT_HANGUL*/
+ 0x0000FFD7, /* USCRIPT_HANGUL*/
+ 0x0000FFDC, /* USCRIPT_HANGUL*/
+ 0x00010300, /* USCRIPT_OLD_ITALIC*/
+ 0x00010330, /* USCRIPT_GOTHIC*/
+ 0x0001034A, /* USCRIPT_GOTHIC*/
+ 0x00010400, /* USCRIPT_DESERET*/
+ 0x00010428, /* USCRIPT_DESERET*/
+ 0x0001D167, /* USCRIPT_INHERITED*/
+ 0x0001D17B, /* USCRIPT_INHERITED*/
+ 0x0001D185, /* USCRIPT_INHERITED*/
+ 0x0001D1AA, /* USCRIPT_INHERITED*/
+ 0x00020000, /* USCRIPT_HAN*/
+ 0x00000D02, /* USCRIPT_MALAYALAM*/
+ 0x00000D00, /* USCRIPT_UNKNOWN (new Zzzz value in Unicode 5.0) */
+ 0x00000000, /* USCRIPT_COMMON*/
+ 0x0001D169, /* USCRIPT_INHERITED*/
+ 0x0001D182, /* USCRIPT_INHERITED*/
+ 0x0001D18B, /* USCRIPT_INHERITED*/
+ 0x0001D1AD, /* USCRIPT_INHERITED*/
+ 0x00110000, /* USCRIPT_INVALID_CODE */
+ };
+
+ UScriptCode expected[] = {
+ USCRIPT_KATAKANA ,
+ USCRIPT_HANGUL ,
+ USCRIPT_HANGUL ,
+ USCRIPT_HANGUL ,
+ USCRIPT_HANGUL ,
+ USCRIPT_HANGUL ,
+ USCRIPT_OLD_ITALIC,
+ USCRIPT_GOTHIC ,
+ USCRIPT_GOTHIC ,
+ USCRIPT_DESERET ,
+ USCRIPT_DESERET ,
+ USCRIPT_INHERITED,
+ USCRIPT_INHERITED,
+ USCRIPT_INHERITED,
+ USCRIPT_INHERITED,
+ USCRIPT_HAN ,
+ USCRIPT_MALAYALAM,
+ USCRIPT_UNKNOWN,
+ USCRIPT_COMMON,
+ USCRIPT_INHERITED ,
+ USCRIPT_INHERITED ,
+ USCRIPT_INHERITED ,
+ USCRIPT_INHERITED ,
+ USCRIPT_INVALID_CODE,
+ };
+ UScriptCode code = USCRIPT_INVALID_CODE;
+ UErrorCode status = U_ZERO_ERROR;
+ UBool passed = TRUE;
+
+ i =0;
+ while(i< MAX_ARRAY_SIZE){
+ code = uscript_getScript(codepoints[i],&status);
+ if(U_SUCCESS(status)){
+ if( code != expected[i] ||
+ code != (UScriptCode)u_getIntPropertyValue(codepoints[i], UCHAR_SCRIPT)
+ ) {
+ log_err("uscript_getScript for codepoint \\U%08X failed\n",codepoints[i]);
+ passed = FALSE;
+ }
+ }else{
+ log_err("uscript_getScript for codepoint \\U%08X failed. Error: %s\n",
+ codepoints[i],u_errorName(status));
+ break;
+ }
+ i++;
+ }
+
+ if(passed==FALSE){
+ log_err("uscript_getScript failed.\n");
+ }
+ }
+ {
+ UScriptCode code= USCRIPT_INVALID_CODE;
+ UErrorCode status = U_ZERO_ERROR;
+ code = uscript_getScript(0x001D169,&status);
+ if(code != USCRIPT_INHERITED){
+ log_err("\\U001D169 is not contained in USCRIPT_INHERITED");
+ }
+ }
+ {
+ UScriptCode code= USCRIPT_INVALID_CODE;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t err = 0;
+
+ for(i = 0; i<=0x10ffff; i++){
+ code = uscript_getScript(i,&status);
+ if(code == USCRIPT_INVALID_CODE){
+ err++;
+ log_err("uscript_getScript for codepoint \\U%08X failed.\n", i);
+ }
+ }
+ if(err>0){
+ log_err("uscript_getScript failed for %d codepoints\n", err);
+ }
+ }
+ {
+ for(i=0; (UScriptCode)i< USCRIPT_CODE_LIMIT; i++){
+ const char* name = uscript_getName((UScriptCode)i);
+ if(name==NULL || strcmp(name,"")==0){
+ log_err("uscript_getName failed for code %i: name is NULL or \"\"\n",i);
+ }
+ }
+ }
+
+ {
+ /*
+ * These script codes were originally added to ICU pre-3.6, so that ICU would
+ * have all ISO 15924 script codes. ICU was then based on Unicode 4.1.
+ * These script codes were added with only short names because we don't
+ * want to invent long names ourselves.
+ * Unicode 5 and later encode some of these scripts and give them long names.
+ * Whenever this happens, the long script names here need to be updated.
+ */
+ static const char* expectedLong[] = {
+ "Balinese", "Batk", "Blis", "Brah", "Cham", "Cirt", "Cyrs", "Egyd", "Egyh", "Egyp",
+ "Geok", "Hans", "Hant", "Hmng", "Hung", "Inds", "Java", "Kali", "Latf", "Latg",
+ "Lepc", "Lina", "Mand", "Maya", "Mero", "Nko", "Orkh", "Perm", "Phags_Pa", "Phoenician",
+ "Plrd", "Roro", "Sara", "Syre", "Syrj", "Syrn", "Teng", "Vaii", "Visp", "Cuneiform",
+ "Zxxx", "Unknown",
+ "Cari", "Jpan", "Lana", "Lyci", "Lydi", "Olck", "Rjng", "Saur", "Sgnw", "Sund",
+ "Moon", "Mtei",
+ };
+ static const char* expectedShort[] = {
+ "Bali", "Batk", "Blis", "Brah", "Cham", "Cirt", "Cyrs", "Egyd", "Egyh", "Egyp",
+ "Geok", "Hans", "Hant", "Hmng", "Hung", "Inds", "Java", "Kali", "Latf", "Latg",
+ "Lepc", "Lina", "Mand", "Maya", "Mero", "Nkoo", "Orkh", "Perm", "Phag", "Phnx",
+ "Plrd", "Roro", "Sara", "Syre", "Syrj", "Syrn", "Teng", "Vaii", "Visp", "Xsux",
+ "Zxxx", "Zzzz",
+ "Cari", "Jpan", "Lana", "Lyci", "Lydi", "Olck", "Rjng", "Saur", "Sgnw", "Sund",
+ "Moon", "Mtei",
+ };
+ int32_t j = 0;
+ for(i=USCRIPT_BALINESE; (UScriptCode)i<USCRIPT_CODE_LIMIT; i++, j++){
+ const char* name = uscript_getName((UScriptCode)i);
+ if(name==NULL || strcmp(name,expectedLong[j])!=0){
+ log_err("uscript_getName failed for code %i: %s!=%s\n", i, name, expectedLong[j]);
+ }
+ name = uscript_getShortName((UScriptCode)i);
+ if(name==NULL || strcmp(name,expectedShort[j])!=0){
+ log_err("uscript_getShortName failed for code %i: %s!=%s\n", i, name, expectedShort[j]);
+ }
+ }
+ for(i=0; i<ARRAY_SIZE(expectedLong); i++){
+ UScriptCode fillIn[5] = {USCRIPT_INVALID_CODE};
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+ len = uscript_getCode(expectedShort[i], fillIn, ARRAY_SIZE(fillIn), &status);
+ if(U_FAILURE(status)){
+ log_err("uscript_getCode failed for script name %s. Error: %s\n",expectedShort[i], u_errorName(status));
+ }
+ if(len>1){
+ log_err("uscript_getCode did not return expected number of codes for script %s. EXPECTED: 1 GOT: %i\n", expectedShort[i], len);
+ }
+ if(fillIn[0]!= (UScriptCode)(USCRIPT_BALINESE+i)){
+ log_err("uscript_getCode did not return expected code for script %s. EXPECTED: %i GOT: %i\n", expectedShort[i], (USCRIPT_BALINESE+i), fillIn[0] );
+ }
+ }
+ }
+ }
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h
new file mode 100644
index 00000000000..a61b52da4f3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdapi.h
@@ -0,0 +1,9 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2003-2003, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+
+void TestUScriptCodeAPI(void);
+
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c
new file mode 100644
index 00000000000..f132d12e6f2
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cucdtst.c
@@ -0,0 +1,3342 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CUCDTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API, added tests for string functions
+********************************************************************************
+*/
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+#include "unicode/putil.h"
+#include "unicode/ustring.h"
+#include "unicode/uloc.h"
+
+#include "cintltst.h"
+#include "putilimp.h"
+#include "uparse.h"
+#include "ucase.h"
+#include "ubidi_props.h"
+#include "uprops.h"
+#include "uset_imp.h"
+#include "usc_impl.h"
+#include "unormimp.h"
+#include "udatamem.h" /* for testing ucase_openBinary() */
+#include "cucdapi.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+/* prototypes --------------------------------------------------------------- */
+
+static void TestUpperLower(void);
+static void TestLetterNumber(void);
+static void TestMisc(void);
+static void TestPOSIX(void);
+static void TestControlPrint(void);
+static void TestIdentifier(void);
+static void TestUnicodeData(void);
+static void TestCodeUnit(void);
+static void TestCodePoint(void);
+static void TestCharLength(void);
+static void TestCharNames(void);
+static void TestMirroring(void);
+/* void TestUScriptCodeAPI(void);*/ /* defined in cucdapi.h */
+static void TestUScriptRunAPI(void);
+static void TestAdditionalProperties(void);
+static void TestNumericProperties(void);
+static void TestPropertyNames(void);
+static void TestPropertyValues(void);
+static void TestConsistency(void);
+static void TestUCase(void);
+static void TestUBiDiProps(void);
+static void TestCaseFolding(void);
+
+/* internal methods used */
+static int32_t MakeProp(char* str);
+static int32_t MakeDir(char* str);
+
+/* helpers ------------------------------------------------------------------ */
+
+static void
+parseUCDFile(const char *filename,
+ char *fields[][2], int32_t fieldCount,
+ UParseLineFn *lineFn, void *context,
+ UErrorCode *pErrorCode) {
+ char path[256];
+ char backupPath[256];
+
+ if(U_FAILURE(*pErrorCode)) {
+ return;
+ }
+
+ /* Look inside ICU_DATA first */
+ strcpy(path, u_getDataDirectory());
+ strcat(path, ".." U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING);
+ strcat(path, filename);
+
+ /* As a fallback, try to guess where the source data was located
+ * at the time ICU was built, and look there.
+ */
+ strcpy(backupPath, ctest_dataSrcDir());
+ strcat(backupPath, U_FILE_SEP_STRING);
+ strcat(backupPath, "unidata" U_FILE_SEP_STRING);
+ strcat(backupPath, filename);
+
+ u_parseDelimitedFile(path, ';', fields, fieldCount, lineFn, context, pErrorCode);
+ if(*pErrorCode==U_FILE_ACCESS_ERROR) {
+ *pErrorCode=U_ZERO_ERROR;
+ u_parseDelimitedFile(backupPath, ';', fields, fieldCount, lineFn, context, pErrorCode);
+ }
+ if(U_FAILURE(*pErrorCode)) {
+ log_err("error parsing %s: %s\n", filename, u_errorName(*pErrorCode));
+ }
+}
+
+/* test data ---------------------------------------------------------------- */
+
+static const UChar LAST_CHAR_CODE_IN_FILE = 0xFFFD;
+static const char tagStrings[] = "MnMcMeNdNlNoZsZlZpCcCfCsCoCnLuLlLtLmLoPcPdPsPePoSmScSkSoPiPf";
+static const int32_t tagValues[] =
+ {
+ /* Mn */ U_NON_SPACING_MARK,
+ /* Mc */ U_COMBINING_SPACING_MARK,
+ /* Me */ U_ENCLOSING_MARK,
+ /* Nd */ U_DECIMAL_DIGIT_NUMBER,
+ /* Nl */ U_LETTER_NUMBER,
+ /* No */ U_OTHER_NUMBER,
+ /* Zs */ U_SPACE_SEPARATOR,
+ /* Zl */ U_LINE_SEPARATOR,
+ /* Zp */ U_PARAGRAPH_SEPARATOR,
+ /* Cc */ U_CONTROL_CHAR,
+ /* Cf */ U_FORMAT_CHAR,
+ /* Cs */ U_SURROGATE,
+ /* Co */ U_PRIVATE_USE_CHAR,
+ /* Cn */ U_UNASSIGNED,
+ /* Lu */ U_UPPERCASE_LETTER,
+ /* Ll */ U_LOWERCASE_LETTER,
+ /* Lt */ U_TITLECASE_LETTER,
+ /* Lm */ U_MODIFIER_LETTER,
+ /* Lo */ U_OTHER_LETTER,
+ /* Pc */ U_CONNECTOR_PUNCTUATION,
+ /* Pd */ U_DASH_PUNCTUATION,
+ /* Ps */ U_START_PUNCTUATION,
+ /* Pe */ U_END_PUNCTUATION,
+ /* Po */ U_OTHER_PUNCTUATION,
+ /* Sm */ U_MATH_SYMBOL,
+ /* Sc */ U_CURRENCY_SYMBOL,
+ /* Sk */ U_MODIFIER_SYMBOL,
+ /* So */ U_OTHER_SYMBOL,
+ /* Pi */ U_INITIAL_PUNCTUATION,
+ /* Pf */ U_FINAL_PUNCTUATION
+ };
+
+static const char dirStrings[][5] = {
+ "L",
+ "R",
+ "EN",
+ "ES",
+ "ET",
+ "AN",
+ "CS",
+ "B",
+ "S",
+ "WS",
+ "ON",
+ "LRE",
+ "LRO",
+ "AL",
+ "RLE",
+ "RLO",
+ "PDF",
+ "NSM",
+ "BN"
+};
+
+void addUnicodeTest(TestNode** root);
+
+void addUnicodeTest(TestNode** root)
+{
+ addTest(root, &TestUnicodeData, "tsutil/cucdtst/TestUnicodeData");
+ addTest(root, &TestCodeUnit, "tsutil/cucdtst/TestCodeUnit");
+ addTest(root, &TestCodePoint, "tsutil/cucdtst/TestCodePoint");
+ addTest(root, &TestCharLength, "tsutil/cucdtst/TestCharLength");
+ addTest(root, &TestAdditionalProperties, "tsutil/cucdtst/TestAdditionalProperties");
+ addTest(root, &TestNumericProperties, "tsutil/cucdtst/TestNumericProperties");
+ addTest(root, &TestUpperLower, "tsutil/cucdtst/TestUpperLower");
+ addTest(root, &TestLetterNumber, "tsutil/cucdtst/TestLetterNumber");
+ addTest(root, &TestMisc, "tsutil/cucdtst/TestMisc");
+ addTest(root, &TestPOSIX, "tsutil/cucdtst/TestPOSIX");
+ addTest(root, &TestControlPrint, "tsutil/cucdtst/TestControlPrint");
+ addTest(root, &TestIdentifier, "tsutil/cucdtst/TestIdentifier");
+ addTest(root, &TestCharNames, "tsutil/cucdtst/TestCharNames");
+ addTest(root, &TestMirroring, "tsutil/cucdtst/TestMirroring");
+ addTest(root, &TestUScriptCodeAPI, "tsutil/cucdtst/TestUScriptCodeAPI");
+ addTest(root, &TestUScriptRunAPI, "tsutil/cucdtst/TestUScriptRunAPI");
+ addTest(root, &TestPropertyNames, "tsutil/cucdtst/TestPropertyNames");
+ addTest(root, &TestPropertyValues, "tsutil/cucdtst/TestPropertyValues");
+ addTest(root, &TestConsistency, "tsutil/cucdtst/TestConsistency");
+ addTest(root, &TestUCase, "tsutil/cucdtst/TestUCase");
+ addTest(root, &TestUBiDiProps, "tsutil/cucdtst/TestUBiDiProps");
+ addTest(root, &TestCaseFolding, "tsutil/cucdtst/TestCaseFolding");
+}
+
+/*==================================================== */
+/* test u_toupper() and u_tolower() */
+/*==================================================== */
+static void TestUpperLower()
+{
+ const UChar upper[] = {0x41, 0x42, 0x00b2, 0x01c4, 0x01c6, 0x01c9, 0x01c8, 0x01c9, 0x000c, 0x0000};
+ const UChar lower[] = {0x61, 0x62, 0x00b2, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01c9, 0x000c, 0x0000};
+ U_STRING_DECL(upperTest, "abcdefg123hij.?:klmno", 21);
+ U_STRING_DECL(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21);
+ int32_t i;
+
+ U_STRING_INIT(upperTest, "abcdefg123hij.?:klmno", 21);
+ U_STRING_INIT(lowerTest, "ABCDEFG123HIJ.?:KLMNO", 21);
+
+/*
+Checks LetterLike Symbols which were previously a source of confusion
+[Bertrand A. D. 02/04/98]
+*/
+ for (i=0x2100;i<0x2138;i++)
+ {
+ /* Unicode 5.0 adds lowercase U+214E (TURNED SMALL F) to U+2132 (TURNED CAPITAL F) */
+ if(i!=0x2126 && i!=0x212a && i!=0x212b && i!=0x2132)
+ {
+ if (i != (int)u_tolower(i)) /* itself */
+ log_err("Failed case conversion with itself: U+%04x\n", i);
+ if (i != (int)u_toupper(i))
+ log_err("Failed case conversion with itself: U+%04x\n", i);
+ }
+ }
+
+ for(i=0; i < u_strlen(upper); i++){
+ if(u_tolower(upper[i]) != lower[i]){
+ log_err("FAILED u_tolower() for %lx Expected %lx Got %lx\n", upper[i], lower[i], u_tolower(upper[i]));
+ }
+ }
+
+ log_verbose("testing upper lower\n");
+ for (i = 0; i < 21; i++) {
+
+ if (u_isalpha(upperTest[i]) && !u_islower(upperTest[i]))
+ {
+ log_err("Failed isLowerCase test at %c\n", upperTest[i]);
+ }
+ else if (u_isalpha(lowerTest[i]) && !u_isupper(lowerTest[i]))
+ {
+ log_err("Failed isUpperCase test at %c\n", lowerTest[i]);
+ }
+ else if (upperTest[i] != u_tolower(lowerTest[i]))
+ {
+ log_err("Failed case conversion from %c To %c :\n", lowerTest[i], upperTest[i]);
+ }
+ else if (lowerTest[i] != u_toupper(upperTest[i]))
+ {
+ log_err("Failed case conversion : %c To %c \n", upperTest[i], lowerTest[i]);
+ }
+ else if (upperTest[i] != u_tolower(upperTest[i]))
+ {
+ log_err("Failed case conversion with itself: %c\n", upperTest[i]);
+ }
+ else if (lowerTest[i] != u_toupper(lowerTest[i]))
+ {
+ log_err("Failed case conversion with itself: %c\n", lowerTest[i]);
+ }
+ }
+ log_verbose("done testing upper lower\n");
+
+ log_verbose("testing u_istitle\n");
+ {
+ static const UChar expected[] = {
+ 0x1F88,
+ 0x1F89,
+ 0x1F8A,
+ 0x1F8B,
+ 0x1F8C,
+ 0x1F8D,
+ 0x1F8E,
+ 0x1F8F,
+ 0x1F88,
+ 0x1F89,
+ 0x1F8A,
+ 0x1F8B,
+ 0x1F8C,
+ 0x1F8D,
+ 0x1F8E,
+ 0x1F8F,
+ 0x1F98,
+ 0x1F99,
+ 0x1F9A,
+ 0x1F9B,
+ 0x1F9C,
+ 0x1F9D,
+ 0x1F9E,
+ 0x1F9F,
+ 0x1F98,
+ 0x1F99,
+ 0x1F9A,
+ 0x1F9B,
+ 0x1F9C,
+ 0x1F9D,
+ 0x1F9E,
+ 0x1F9F,
+ 0x1FA8,
+ 0x1FA9,
+ 0x1FAA,
+ 0x1FAB,
+ 0x1FAC,
+ 0x1FAD,
+ 0x1FAE,
+ 0x1FAF,
+ 0x1FA8,
+ 0x1FA9,
+ 0x1FAA,
+ 0x1FAB,
+ 0x1FAC,
+ 0x1FAD,
+ 0x1FAE,
+ 0x1FAF,
+ 0x1FBC,
+ 0x1FBC,
+ 0x1FCC,
+ 0x1FCC,
+ 0x1FFC,
+ 0x1FFC,
+ };
+ int32_t num = sizeof(expected)/sizeof(expected[0]);
+ for(i=0; i<num; i++){
+ if(!u_istitle(expected[i])){
+ log_err("u_istitle failed for 0x%4X. Expected TRUE, got FALSE\n",expected[i]);
+ }
+ }
+
+ }
+}
+
+/* compare two sets and verify that their difference or intersection is empty */
+static UBool
+showADiffB(const USet *a, const USet *b,
+ const char *a_name, const char *b_name,
+ UBool expect, UBool diffIsError) {
+ USet *aa;
+ int32_t i, start, end, length;
+ UErrorCode errorCode;
+
+ /*
+ * expect:
+ * TRUE -> a-b should be empty, that is, b should contain all of a
+ * FALSE -> a&b should be empty, that is, a should contain none of b (and vice versa)
+ */
+ if(expect ? uset_containsAll(b, a) : uset_containsNone(a, b)) {
+ return TRUE;
+ }
+
+ /* clone a to aa because a is const */
+ aa=uset_open(1, 0);
+ if(aa==NULL) {
+ /* unusual problem - out of memory? */
+ return FALSE;
+ }
+ uset_addAll(aa, a);
+
+ /* compute the set in question */
+ if(expect) {
+ /* a-b */
+ uset_removeAll(aa, b);
+ } else {
+ /* a&b */
+ uset_retainAll(aa, b);
+ }
+
+ /* aa is not empty because of the initial tests above; show its contents */
+ errorCode=U_ZERO_ERROR;
+ i=0;
+ for(;;) {
+ length=uset_getItem(aa, i, &start, &end, NULL, 0, &errorCode);
+ if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
+ break; /* done */
+ }
+ if(U_FAILURE(errorCode)) {
+ log_err("error comparing %s with %s at difference item %d: %s\n",
+ a_name, b_name, i, u_errorName(errorCode));
+ break;
+ }
+ if(length!=0) {
+ break; /* done with code points, got a string or -1 */
+ }
+
+ if(diffIsError) {
+ if(expect) {
+ log_err("error: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name);
+ } else {
+ log_err("error: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end);
+ }
+ } else {
+ if(expect) {
+ log_verbose("info: %s contains U+%04x..U+%04x but %s does not\n", a_name, start, end, b_name);
+ } else {
+ log_verbose("info: %s and %s both contain U+%04x..U+%04x but should not intersect\n", a_name, b_name, start, end);
+ }
+ }
+
+ ++i;
+ }
+
+ uset_close(aa);
+ return FALSE;
+}
+
+static UBool
+showAMinusB(const USet *a, const USet *b,
+ const char *a_name, const char *b_name,
+ UBool diffIsError) {
+ return showADiffB(a, b, a_name, b_name, TRUE, diffIsError);
+}
+
+static UBool
+showAIntersectB(const USet *a, const USet *b,
+ const char *a_name, const char *b_name,
+ UBool diffIsError) {
+ return showADiffB(a, b, a_name, b_name, FALSE, diffIsError);
+}
+
+static UBool
+compareUSets(const USet *a, const USet *b,
+ const char *a_name, const char *b_name,
+ UBool diffIsError) {
+ /*
+ * Use an arithmetic & not a logical && so that both branches
+ * are always taken and all differences are shown.
+ */
+ return
+ showAMinusB(a, b, a_name, b_name, diffIsError) &
+ showAMinusB(b, a, b_name, a_name, diffIsError);
+}
+
+/* test isLetter(u_isapha()) and isDigit(u_isdigit()) */
+static void TestLetterNumber()
+{
+ UChar i = 0x0000;
+
+ log_verbose("Testing for isalpha\n");
+ for (i = 0x0041; i < 0x005B; i++) {
+ if (!u_isalpha(i))
+ {
+ log_err("Failed isLetter test at %.4X\n", i);
+ }
+ }
+ for (i = 0x0660; i < 0x066A; i++) {
+ if (u_isalpha(i))
+ {
+ log_err("Failed isLetter test with numbers at %.4X\n", i);
+ }
+ }
+
+ log_verbose("Testing for isdigit\n");
+ for (i = 0x0660; i < 0x066A; i++) {
+ if (!u_isdigit(i))
+ {
+ log_verbose("Failed isNumber test at %.4X\n", i);
+ }
+ }
+
+ log_verbose("Testing for isalnum\n");
+ for (i = 0x0041; i < 0x005B; i++) {
+ if (!u_isalnum(i))
+ {
+ log_err("Failed isAlNum test at %.4X\n", i);
+ }
+ }
+ for (i = 0x0660; i < 0x066A; i++) {
+ if (!u_isalnum(i))
+ {
+ log_err("Failed isAlNum test at %.4X\n", i);
+ }
+ }
+
+ {
+ /*
+ * The following checks work only starting from Unicode 4.0.
+ * Check the version number here.
+ */
+ static UVersionInfo u401={ 4, 0, 1, 0 };
+ UVersionInfo version;
+ u_getUnicodeVersion(version);
+ if(version[0]<4 || 0==memcmp(version, u401, 4)) {
+ return;
+ }
+ }
+
+ {
+ /*
+ * Sanity check:
+ * Verify that exactly the digit characters have decimal digit values.
+ * This assumption is used in the implementation of u_digit()
+ * (which checks nt=de)
+ * compared with the parallel java.lang.Character.digit()
+ * (which checks Nd).
+ *
+ * This was not true in Unicode 3.2 and earlier.
+ * Unicode 4.0 fixed discrepancies.
+ * Unicode 4.0.1 re-introduced problems in this area due to an
+ * unintentionally incomplete last-minute change.
+ */
+ U_STRING_DECL(digitsPattern, "[:Nd:]", 6);
+ U_STRING_DECL(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24);
+
+ USet *digits, *decimalValues;
+ UErrorCode errorCode;
+
+ U_STRING_INIT(digitsPattern, "[:Nd:]", 6);
+ U_STRING_INIT(decimalValuesPattern, "[:Numeric_Type=Decimal:]", 24);
+ errorCode=U_ZERO_ERROR;
+ digits=uset_openPattern(digitsPattern, 6, &errorCode);
+ decimalValues=uset_openPattern(decimalValuesPattern, 24, &errorCode);
+
+ if(U_SUCCESS(errorCode)) {
+ compareUSets(digits, decimalValues, "[:Nd:]", "[:Numeric_Type=Decimal:]", TRUE);
+ }
+
+ uset_close(digits);
+ uset_close(decimalValues);
+ }
+}
+
+/* Tests for isDefined(u_isdefined)(, isBaseForm(u_isbase()), isSpaceChar(u_isspace()), isWhiteSpace(), u_CharDigitValue() */
+static void TestMisc()
+{
+ static const UChar sampleSpaces[] = {0x0020, 0x00a0, 0x2000, 0x2001, 0x2005};
+ static const UChar sampleNonSpaces[] = {0x61, 0x62, 0x63, 0x64, 0x74};
+ static const UChar sampleUndefined[] = {0xfff1, 0xfff7, 0xfa6b };
+ static const UChar sampleDefined[] = {0x523E, 0x4f88, 0xfffd};
+ static const UChar sampleBase[] = {0x0061, 0x0031, 0x03d2};
+ static const UChar sampleNonBase[] = {0x002B, 0x0020, 0x203B};
+/* static const UChar sampleChars[] = {0x000a, 0x0045, 0x4e00, 0xDC00, 0xFFE8, 0xFFF0};*/
+ static const UChar sampleDigits[]= {0x0030, 0x0662, 0x0F23, 0x0ED5};
+ static const UChar sampleNonDigits[] = {0x0010, 0x0041, 0x0122, 0x68FE};
+ static const UChar sampleWhiteSpaces[] = {0x2008, 0x2009, 0x200a, 0x001c, 0x000c};
+ static const UChar sampleNonWhiteSpaces[] = {0x61, 0x62, 0x3c, 0x28, 0x3f};
+
+
+ static const int32_t sampleDigitValues[] = {0, 2, 3, 5};
+
+ uint32_t mask;
+
+ int32_t i;
+ char icuVersion[U_MAX_VERSION_STRING_LENGTH];
+ UVersionInfo realVersion;
+
+ memset(icuVersion, 0, U_MAX_VERSION_STRING_LENGTH);
+
+ log_verbose("Testing for isspace and nonspaces\n");
+ for (i = 0; i < 5; i++) {
+ if (!(u_isspace(sampleSpaces[i])) ||
+ (u_isspace(sampleNonSpaces[i])))
+ {
+ log_err("Space char test error : %d or %d \n", (int32_t)sampleSpaces[i], (int32_t)sampleNonSpaces[i]);
+ }
+ if (!(u_isJavaSpaceChar(sampleSpaces[i])) ||
+ (u_isJavaSpaceChar(sampleNonSpaces[i])))
+ {
+ log_err("u_isJavaSpaceChar() test error : %d or %d \n", (int32_t)sampleSpaces[i], (int32_t)sampleNonSpaces[i]);
+ }
+ }
+
+ log_verbose("Testing for isspace and nonspaces\n");
+ for (i = 0; i < 5; i++) {
+ if (!(u_isWhitespace(sampleWhiteSpaces[i])) ||
+ (u_isWhitespace(sampleNonWhiteSpaces[i])))
+ {
+ log_err("White Space char test error : %lx or %lx \n", sampleWhiteSpaces[i], sampleNonWhiteSpaces[i]);
+ }
+ }
+
+ log_verbose("Testing for isdefined\n");
+ for (i = 0; i < 3; i++) {
+ if ((u_isdefined(sampleUndefined[i])) ||
+ !(u_isdefined(sampleDefined[i])))
+ {
+ log_err("Undefined char test error : U+%04x or U+%04x\n", (int32_t)sampleUndefined[i], (int32_t)sampleDefined[i]);
+ }
+ }
+
+ log_verbose("Testing for isbase\n");
+ for (i = 0; i < 3; i++) {
+ if ((u_isbase(sampleNonBase[i])) ||
+ !(u_isbase(sampleBase[i])))
+ {
+ log_err("Non-baseform char test error : U+%04x or U+%04x",(int32_t)sampleNonBase[i], (int32_t)sampleBase[i]);
+ }
+ }
+
+ log_verbose("Testing for isdigit \n");
+ for (i = 0; i < 4; i++) {
+ if ((u_isdigit(sampleDigits[i]) &&
+ (u_charDigitValue(sampleDigits[i])!= sampleDigitValues[i])) ||
+ (u_isdigit(sampleNonDigits[i]))) {
+ log_err("Digit char test error : %lx or %lx\n", sampleDigits[i], sampleNonDigits[i]);
+ }
+ }
+
+ /* Tests the ICU version #*/
+ u_getVersion(realVersion);
+ u_versionToString(realVersion, icuVersion);
+ if (strncmp(icuVersion, U_ICU_VERSION, uprv_min((int32_t)strlen(icuVersion), (int32_t)strlen(U_ICU_VERSION))) != 0)
+ {
+ log_err("ICU version test failed. Header says=%s, got=%s \n", U_ICU_VERSION, icuVersion);
+ }
+#if defined(ICU_VERSION)
+ /* test only happens where we have configure.in with VERSION - sanity check. */
+ if(strcmp(U_ICU_VERSION, ICU_VERSION))
+ {
+ log_err("ICU version mismatch: Header says %s, build environment says %s.\n", U_ICU_VERSION, ICU_VERSION);
+ }
+#endif
+
+ /* test U_GC_... */
+ if(
+ U_GET_GC_MASK(0x41)!=U_GC_LU_MASK ||
+ U_GET_GC_MASK(0x662)!=U_GC_ND_MASK ||
+ U_GET_GC_MASK(0xa0)!=U_GC_ZS_MASK ||
+ U_GET_GC_MASK(0x28)!=U_GC_PS_MASK ||
+ U_GET_GC_MASK(0x2044)!=U_GC_SM_MASK ||
+ U_GET_GC_MASK(0xe0063)!=U_GC_CF_MASK
+ ) {
+ log_err("error: U_GET_GC_MASK does not work properly\n");
+ }
+
+ mask=0;
+ mask=(mask&~U_GC_CN_MASK)|U_GC_CN_MASK;
+
+ mask=(mask&~U_GC_LU_MASK)|U_GC_LU_MASK;
+ mask=(mask&~U_GC_LL_MASK)|U_GC_LL_MASK;
+ mask=(mask&~U_GC_LT_MASK)|U_GC_LT_MASK;
+ mask=(mask&~U_GC_LM_MASK)|U_GC_LM_MASK;
+ mask=(mask&~U_GC_LO_MASK)|U_GC_LO_MASK;
+
+ mask=(mask&~U_GC_MN_MASK)|U_GC_MN_MASK;
+ mask=(mask&~U_GC_ME_MASK)|U_GC_ME_MASK;
+ mask=(mask&~U_GC_MC_MASK)|U_GC_MC_MASK;
+
+ mask=(mask&~U_GC_ND_MASK)|U_GC_ND_MASK;
+ mask=(mask&~U_GC_NL_MASK)|U_GC_NL_MASK;
+ mask=(mask&~U_GC_NO_MASK)|U_GC_NO_MASK;
+
+ mask=(mask&~U_GC_ZS_MASK)|U_GC_ZS_MASK;
+ mask=(mask&~U_GC_ZL_MASK)|U_GC_ZL_MASK;
+ mask=(mask&~U_GC_ZP_MASK)|U_GC_ZP_MASK;
+
+ mask=(mask&~U_GC_CC_MASK)|U_GC_CC_MASK;
+ mask=(mask&~U_GC_CF_MASK)|U_GC_CF_MASK;
+ mask=(mask&~U_GC_CO_MASK)|U_GC_CO_MASK;
+ mask=(mask&~U_GC_CS_MASK)|U_GC_CS_MASK;
+
+ mask=(mask&~U_GC_PD_MASK)|U_GC_PD_MASK;
+ mask=(mask&~U_GC_PS_MASK)|U_GC_PS_MASK;
+ mask=(mask&~U_GC_PE_MASK)|U_GC_PE_MASK;
+ mask=(mask&~U_GC_PC_MASK)|U_GC_PC_MASK;
+ mask=(mask&~U_GC_PO_MASK)|U_GC_PO_MASK;
+
+ mask=(mask&~U_GC_SM_MASK)|U_GC_SM_MASK;
+ mask=(mask&~U_GC_SC_MASK)|U_GC_SC_MASK;
+ mask=(mask&~U_GC_SK_MASK)|U_GC_SK_MASK;
+ mask=(mask&~U_GC_SO_MASK)|U_GC_SO_MASK;
+
+ mask=(mask&~U_GC_PI_MASK)|U_GC_PI_MASK;
+ mask=(mask&~U_GC_PF_MASK)|U_GC_PF_MASK;
+
+ if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) {
+ log_err("error: problems with U_GC_XX_MASK constants\n");
+ }
+
+ mask=0;
+ mask=(mask&~U_GC_C_MASK)|U_GC_C_MASK;
+ mask=(mask&~U_GC_L_MASK)|U_GC_L_MASK;
+ mask=(mask&~U_GC_M_MASK)|U_GC_M_MASK;
+ mask=(mask&~U_GC_N_MASK)|U_GC_N_MASK;
+ mask=(mask&~U_GC_Z_MASK)|U_GC_Z_MASK;
+ mask=(mask&~U_GC_P_MASK)|U_GC_P_MASK;
+ mask=(mask&~U_GC_S_MASK)|U_GC_S_MASK;
+
+ if(mask!=(U_CHAR_CATEGORY_COUNT<32 ? U_MASK(U_CHAR_CATEGORY_COUNT)-1: 0xffffffff)) {
+ log_err("error: problems with U_GC_Y_MASK constants\n");
+ }
+ {
+ static const UChar32 digit[10]={ 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039 };
+ for(i=0; i<10; i++){
+ if(digit[i]!=u_forDigit(i,10)){
+ log_err("u_forDigit failed for %i. Expected: 0x%4X Got: 0x%4X\n",i,digit[i],u_forDigit(i,10));
+ }
+ }
+ }
+
+ /* test u_digit() */
+ {
+ static const struct {
+ UChar32 c;
+ int8_t radix, value;
+ } data[]={
+ /* base 16 */
+ { 0x0031, 16, 1 },
+ { 0x0038, 16, 8 },
+ { 0x0043, 16, 12 },
+ { 0x0066, 16, 15 },
+ { 0x00e4, 16, -1 },
+ { 0x0662, 16, 2 },
+ { 0x06f5, 16, 5 },
+ { 0xff13, 16, 3 },
+ { 0xff41, 16, 10 },
+
+ /* base 8 */
+ { 0x0031, 8, 1 },
+ { 0x0038, 8, -1 },
+ { 0x0043, 8, -1 },
+ { 0x0066, 8, -1 },
+ { 0x00e4, 8, -1 },
+ { 0x0662, 8, 2 },
+ { 0x06f5, 8, 5 },
+ { 0xff13, 8, 3 },
+ { 0xff41, 8, -1 },
+
+ /* base 36 */
+ { 0x5a, 36, 35 },
+ { 0x7a, 36, 35 },
+ { 0xff3a, 36, 35 },
+ { 0xff5a, 36, 35 },
+
+ /* wrong radix values */
+ { 0x0031, 1, -1 },
+ { 0xff3a, 37, -1 }
+ };
+
+ for(i=0; i<LENGTHOF(data); ++i) {
+ if(u_digit(data[i].c, data[i].radix)!=data[i].value) {
+ log_err("u_digit(U+%04x, %d)=%d expected %d\n",
+ data[i].c,
+ data[i].radix,
+ u_digit(data[i].c, data[i].radix),
+ data[i].value);
+ }
+ }
+ }
+}
+
+/* test C/POSIX-style functions --------------------------------------------- */
+
+/* bit flags */
+#define ISAL 1
+#define ISLO 2
+#define ISUP 4
+
+#define ISDI 8
+#define ISXD 0x10
+
+#define ISAN 0x20
+
+#define ISPU 0x40
+#define ISGR 0x80
+#define ISPR 0x100
+
+#define ISSP 0x200
+#define ISBL 0x400
+#define ISCN 0x800
+
+/* C/POSIX-style functions, in the same order as the bit flags */
+typedef UBool U_EXPORT2 IsPOSIXClass(UChar32 c);
+
+static const struct {
+ IsPOSIXClass *fn;
+ const char *name;
+} posixClasses[]={
+ { u_isalpha, "isalpha" },
+ { u_islower, "islower" },
+ { u_isupper, "isupper" },
+ { u_isdigit, "isdigit" },
+ { u_isxdigit, "isxdigit" },
+ { u_isalnum, "isalnum" },
+ { u_ispunct, "ispunct" },
+ { u_isgraph, "isgraph" },
+ { u_isprint, "isprint" },
+ { u_isspace, "isspace" },
+ { u_isblank, "isblank" },
+ { u_iscntrl, "iscntrl" }
+};
+
+static const struct {
+ UChar32 c;
+ uint32_t posixResults;
+} posixData[]={
+ { 0x0008, ISCN }, /* backspace */
+ { 0x0009, ISSP|ISBL|ISCN }, /* TAB */
+ { 0x000a, ISSP| ISCN }, /* LF */
+ { 0x000c, ISSP| ISCN }, /* FF */
+ { 0x000d, ISSP| ISCN }, /* CR */
+ { 0x0020, ISPR|ISSP|ISBL }, /* space */
+ { 0x0021, ISPU|ISGR|ISPR }, /* ! */
+ { 0x0033, ISDI|ISXD|ISAN| ISGR|ISPR }, /* 3 */
+ { 0x0040, ISPU|ISGR|ISPR }, /* @ */
+ { 0x0041, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* A */
+ { 0x007a, ISAL|ISLO| ISAN| ISGR|ISPR }, /* z */
+ { 0x007b, ISPU|ISGR|ISPR }, /* { */
+ { 0x0085, ISSP| ISCN }, /* NEL */
+ { 0x00a0, ISPR|ISSP|ISBL }, /* NBSP */
+ { 0x00a4, ISGR|ISPR }, /* currency sign */
+ { 0x00e4, ISAL|ISLO| ISAN| ISGR|ISPR }, /* a-umlaut */
+ { 0x0300, ISGR|ISPR }, /* combining grave */
+ { 0x0600, ISCN }, /* arabic number sign */
+ { 0x0627, ISAL| ISAN| ISGR|ISPR }, /* alef */
+ { 0x0663, ISDI|ISXD|ISAN| ISGR|ISPR }, /* arabic 3 */
+ { 0x2002, ISPR|ISSP|ISBL }, /* en space */
+ { 0x2007, ISPR|ISSP|ISBL }, /* figure space */
+ { 0x2009, ISPR|ISSP|ISBL }, /* thin space */
+ { 0x200b, ISCN }, /* ZWSP */
+ /*{ 0x200b, ISPR|ISSP },*/ /* ZWSP */ /* ZWSP became a control char in 4.0.1*/
+ { 0x200e, ISCN }, /* LRM */
+ { 0x2028, ISPR|ISSP| ISCN }, /* LS */
+ { 0x2029, ISPR|ISSP| ISCN }, /* PS */
+ { 0x20ac, ISGR|ISPR }, /* Euro */
+ { 0xff15, ISDI|ISXD|ISAN| ISGR|ISPR }, /* fullwidth 5 */
+ { 0xff25, ISAL| ISUP| ISXD|ISAN| ISGR|ISPR }, /* fullwidth E */
+ { 0xff35, ISAL| ISUP| ISAN| ISGR|ISPR }, /* fullwidth U */
+ { 0xff45, ISAL|ISLO| ISXD|ISAN| ISGR|ISPR }, /* fullwidth e */
+ { 0xff55, ISAL|ISLO| ISAN| ISGR|ISPR } /* fullwidth u */
+};
+
+static void
+TestPOSIX() {
+ uint32_t mask;
+ int32_t cl, i;
+ UBool expect;
+
+ mask=1;
+ for(cl=0; cl<12; ++cl) {
+ for(i=0; i<LENGTHOF(posixData); ++i) {
+ expect=(UBool)((posixData[i].posixResults&mask)!=0);
+ if(posixClasses[cl].fn(posixData[i].c)!=expect) {
+ log_err("u_%s(U+%04x)=%s is wrong\n",
+ posixClasses[cl].name, posixData[i].c, expect ? "FALSE" : "TRUE");
+ }
+ }
+ mask<<=1;
+ }
+}
+
+/* Tests for isControl(u_iscntrl()) and isPrintable(u_isprint()) */
+static void TestControlPrint()
+{
+ const UChar sampleControl[] = {0x1b, 0x97, 0x82, 0x2028, 0x2029, 0x200c, 0x202b};
+ const UChar sampleNonControl[] = {0x61, 0x0031, 0x00e2};
+ const UChar samplePrintable[] = {0x0042, 0x005f, 0x2014};
+ const UChar sampleNonPrintable[] = {0x200c, 0x009f, 0x001b};
+ UChar32 c;
+ int i;
+
+ log_verbose("Testing for iscontrol\n");
+ for (i = 0; i < LENGTHOF(sampleControl); i++) {
+ if (!u_iscntrl(sampleControl[i]))
+ {
+ log_err("Control char test error : U+%04x should be control but is not\n", (int32_t)sampleControl[i]);
+ }
+ }
+
+ log_verbose("Testing for !iscontrol\n");
+ for (i = 0; i < LENGTHOF(sampleNonControl); i++) {
+ if (u_iscntrl(sampleNonControl[i]))
+ {
+ log_err("Control char test error : U+%04x should not be control but is\n", (int32_t)sampleNonControl[i]);
+ }
+ }
+
+ log_verbose("testing for isprintable\n");
+ for (i = 0; i < 3; i++) {
+ if (!u_isprint(samplePrintable[i]))
+ {
+ log_err("Printable char test error : U+%04x should be printable but is not\n", (int32_t)samplePrintable[i]);
+ }
+ if (u_isprint(sampleNonPrintable[i]))
+ {
+ log_err("Printable char test error : U+%04x should not be printable but is\n", (int32_t)sampleNonPrintable[i]);
+ }
+ }
+
+ /* test all ISO 8 controls */
+ for(c=0; c<=0x9f; ++c) {
+ if(c==0x20) {
+ /* skip ASCII graphic characters and continue with DEL */
+ c=0x7f;
+ }
+ if(!u_iscntrl(c)) {
+ log_err("error: u_iscntrl(ISO 8 control U+%04x)=FALSE\n", c);
+ }
+ if(!u_isISOControl(c)) {
+ log_err("error: u_isISOControl(ISO 8 control U+%04x)=FALSE\n", c);
+ }
+ if(u_isprint(c)) {
+ log_err("error: u_isprint(ISO 8 control U+%04x)=TRUE\n", c);
+ }
+ }
+
+ /* test all Latin-1 graphic characters */
+ for(c=0x20; c<=0xff; ++c) {
+ if(c==0x7f) {
+ c=0xa0;
+ } else if(c==0xad) {
+ /* Unicode 4 changes 00AD Soft Hyphen to Cf (and it is in fact not printable) */
+ ++c;
+ }
+ if(!u_isprint(c)) {
+ log_err("error: u_isprint(Latin-1 graphic character U+%04x)=FALSE\n", c);
+ }
+ }
+}
+
+/* u_isJavaIDStart, u_isJavaIDPart, u_isIDStart(), u_isIDPart(), u_isIDIgnorable()*/
+static void TestIdentifier()
+{
+ const UChar sampleJavaIDStart[] = {0x0071, 0x00e4, 0x005f};
+ const UChar sampleNonJavaIDStart[] = {0x0020, 0x2030, 0x0082};
+ const UChar sampleJavaIDPart[] = {0x005f, 0x0032, 0x0045};
+ const UChar sampleNonJavaIDPart[] = {0x2030, 0x2020, 0x0020};
+ const UChar sampleUnicodeIDStart[] = {0x0250, 0x00e2, 0x0061};
+ const UChar sampleNonUnicodeIDStart[] = {0x2000, 0x000a, 0x2019};
+ const UChar sampleUnicodeIDPart[] = {0x005f, 0x0032, 0x0045};
+ const UChar sampleNonUnicodeIDPart[] = {0x2030, 0x00a3, 0x0020};
+ const UChar sampleIDIgnore[] = {0x0006, 0x0010, 0x206b};
+ const UChar sampleNonIDIgnore[] = {0x0075, 0x00a3, 0x0061};
+
+ int i;
+
+ log_verbose("Testing sampleJavaID start \n");
+ for (i = 0; i < 3; i++) {
+ if (!(u_isJavaIDStart(sampleJavaIDStart[i])) ||
+ (u_isJavaIDStart(sampleNonJavaIDStart[i])))
+ log_err("Java ID Start char test error : %lx or %lx\n",
+ sampleJavaIDStart[i], sampleNonJavaIDStart[i]);
+ }
+
+ log_verbose("Testing sampleJavaID part \n");
+ for (i = 0; i < 3; i++) {
+ if (!(u_isJavaIDPart(sampleJavaIDPart[i])) ||
+ (u_isJavaIDPart(sampleNonJavaIDPart[i])))
+ log_err("Java ID Part char test error : %lx or %lx\n",
+ sampleJavaIDPart[i], sampleNonJavaIDPart[i]);
+ }
+
+ log_verbose("Testing sampleUnicodeID start \n");
+ for (i = 0; i < 3; i++) {
+ /* T_test_logln_ustr((int32_t)i); */
+ if (!(u_isIDStart(sampleUnicodeIDStart[i])) ||
+ (u_isIDStart(sampleNonUnicodeIDStart[i])))
+ {
+ log_err("Unicode ID Start char test error : %lx or %lx\n", sampleUnicodeIDStart[i],
+ sampleNonUnicodeIDStart[i]);
+ }
+ }
+
+ log_verbose("Testing sample unicode ID part \n");
+ for (i = 2; i < 3; i++) { /* nos *** starts with 2 instead of 0, until clarified */
+ /* T_test_logln_ustr((int32_t)i); */
+ if (!(u_isIDPart(sampleUnicodeIDPart[i])) ||
+ (u_isIDPart(sampleNonUnicodeIDPart[i])))
+ {
+ log_err("Unicode ID Part char test error : %lx or %lx", sampleUnicodeIDPart[i], sampleNonUnicodeIDPart[i]);
+ }
+ }
+
+ log_verbose("Testing sampleId ignore\n");
+ for (i = 0; i < 3; i++) {
+ /*T_test_logln_ustr((int32_t)i); */
+ if (!(u_isIDIgnorable(sampleIDIgnore[i])) ||
+ (u_isIDIgnorable(sampleNonIDIgnore[i])))
+ {
+ log_err("ID ignorable char test error : U+%04x or U+%04x\n", sampleIDIgnore[i], sampleNonIDIgnore[i]);
+ }
+ }
+}
+
+/* for each line of UnicodeData.txt, check some of the properties */
+/*
+ * ### TODO
+ * This test fails incorrectly if the First or Last code point of a repetitive area
+ * is overridden, which is allowed and is encouraged for the PUAs.
+ * Currently, this means that both area First/Last and override lines are
+ * tested against the properties from the API,
+ * and the area boundary will not match and cause an error.
+ *
+ * This function should detect area boundaries and skip them for the test of individual
+ * code points' properties.
+ * Then it should check that the areas contain all the same properties except where overridden.
+ * For this, it would have had to set a flag for which code points were listed explicitly.
+ */
+static void U_CALLCONV
+unicodeDataLineFn(void *context,
+ char *fields[][2], int32_t fieldCount,
+ UErrorCode *pErrorCode)
+{
+ char buffer[100];
+ char *end;
+ uint32_t value;
+ UChar32 c;
+ int32_t i;
+ int8_t type;
+
+ /* get the character code, field 0 */
+ c=strtoul(fields[0][0], &end, 16);
+ if(end<=fields[0][0] || end!=fields[0][1]) {
+ log_err("error: syntax error in field 0 at %s\n", fields[0][0]);
+ return;
+ }
+ if((uint32_t)c>=UCHAR_MAX_VALUE + 1) {
+ log_err("error in UnicodeData.txt: code point %lu out of range\n", c);
+ return;
+ }
+
+ /* get general category, field 2 */
+ *fields[2][1]=0;
+ type = (int8_t)tagValues[MakeProp(fields[2][0])];
+ if(u_charType(c)!=type) {
+ log_err("error: u_charType(U+%04lx)==%u instead of %u\n", c, u_charType(c), type);
+ }
+ if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
+ log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
+ }
+
+ /* get canonical combining class, field 3 */
+ value=strtoul(fields[3][0], &end, 10);
+ if(end<=fields[3][0] || end!=fields[3][1]) {
+ log_err("error: syntax error in field 3 at code 0x%lx\n", c);
+ return;
+ }
+ if(value>255) {
+ log_err("error in UnicodeData.txt: combining class %lu out of range\n", value);
+ return;
+ }
+#if !UCONFIG_NO_NORMALIZATION
+ if(value!=u_getCombiningClass(c) || value!=(uint32_t)u_getIntPropertyValue(c, UCHAR_CANONICAL_COMBINING_CLASS)) {
+ log_err("error: u_getCombiningClass(U+%04lx)==%hu instead of %lu\n", c, u_getCombiningClass(c), value);
+ }
+#endif
+
+ /* get BiDi category, field 4 */
+ *fields[4][1]=0;
+ i=MakeDir(fields[4][0]);
+ if(i!=u_charDirection(c) || i!=u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)) {
+ log_err("error: u_charDirection(U+%04lx)==%u instead of %u (%s)\n", c, u_charDirection(c), MakeDir(fields[4][0]), fields[4][0]);
+ }
+
+ /* get ISO Comment, field 11 */
+ *fields[11][1]=0;
+ i=u_getISOComment(c, buffer, sizeof(buffer), pErrorCode);
+ if(U_FAILURE(*pErrorCode) || 0!=strcmp(fields[11][0], buffer)) {
+ log_err("error: u_getISOComment(U+%04lx) wrong (%s): \"%s\" should be \"%s\"\n",
+ c, u_errorName(*pErrorCode),
+ U_FAILURE(*pErrorCode) ? buffer : "[error]",
+ fields[11][0]);
+ }
+
+ /* get uppercase mapping, field 12 */
+ if(fields[12][0]!=fields[12][1]) {
+ value=strtoul(fields[12][0], &end, 16);
+ if(end!=fields[12][1]) {
+ log_err("error: syntax error in field 12 at code 0x%lx\n", c);
+ return;
+ }
+ if((UChar32)value!=u_toupper(c)) {
+ log_err("error: u_toupper(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_toupper(c), value);
+ }
+ } else {
+ /* no case mapping: the API must map the code point to itself */
+ if(c!=u_toupper(c)) {
+ log_err("error: U+%04lx does not have an uppercase mapping but u_toupper()==U+%04lx\n", c, u_toupper(c));
+ }
+ }
+
+ /* get lowercase mapping, field 13 */
+ if(fields[13][0]!=fields[13][1]) {
+ value=strtoul(fields[13][0], &end, 16);
+ if(end!=fields[13][1]) {
+ log_err("error: syntax error in field 13 at code 0x%lx\n", c);
+ return;
+ }
+ if((UChar32)value!=u_tolower(c)) {
+ log_err("error: u_tolower(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_tolower(c), value);
+ }
+ } else {
+ /* no case mapping: the API must map the code point to itself */
+ if(c!=u_tolower(c)) {
+ log_err("error: U+%04lx does not have a lowercase mapping but u_tolower()==U+%04lx\n", c, u_tolower(c));
+ }
+ }
+
+ /* get titlecase mapping, field 14 */
+ if(fields[14][0]!=fields[14][1]) {
+ value=strtoul(fields[14][0], &end, 16);
+ if(end!=fields[14][1]) {
+ log_err("error: syntax error in field 14 at code 0x%lx\n", c);
+ return;
+ }
+ if((UChar32)value!=u_totitle(c)) {
+ log_err("error: u_totitle(U+%04lx)==U+%04lx instead of U+%04lx\n", c, u_totitle(c), value);
+ }
+ } else {
+ /* no case mapping: the API must map the code point to itself */
+ if(c!=u_totitle(c)) {
+ log_err("error: U+%04lx does not have a titlecase mapping but u_totitle()==U+%04lx\n", c, u_totitle(c));
+ }
+ }
+}
+
+static UBool U_CALLCONV
+enumTypeRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) {
+ static const UChar32 test[][2]={
+ {0x41, U_UPPERCASE_LETTER},
+ {0x308, U_NON_SPACING_MARK},
+ {0xfffe, U_GENERAL_OTHER_TYPES},
+ {0xe0041, U_FORMAT_CHAR},
+ {0xeffff, U_UNASSIGNED}
+ };
+
+ int32_t i, count;
+
+ if(0!=strcmp((const char *)context, "a1")) {
+ log_err("error: u_enumCharTypes() passes on an incorrect context pointer\n");
+ return FALSE;
+ }
+
+ count=LENGTHOF(test);
+ for(i=0; i<count; ++i) {
+ if(start<=test[i][0] && test[i][0]<limit) {
+ if(type!=(UCharCategory)test[i][1]) {
+ log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld instead of U+%04lx with %ld\n",
+ start, limit, (long)type, test[i][0], test[i][1]);
+ }
+ /* stop at the range that includes the last test code point (increases code coverage for enumeration) */
+ return i==(count-1) ? FALSE : TRUE;
+ }
+ }
+
+ if(start>test[count-1][0]) {
+ log_err("error: u_enumCharTypes() has range [U+%04lx, U+%04lx[ with %ld after it should have stopped\n",
+ start, limit, (long)type);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static UBool U_CALLCONV
+enumDefaultsRange(const void *context, UChar32 start, UChar32 limit, UCharCategory type) {
+ /* default Bidi classes for unassigned code points */
+ static const int32_t defaultBidi[][2]={ /* { limit, class } */
+ { 0x0590, U_LEFT_TO_RIGHT },
+ { 0x0600, U_RIGHT_TO_LEFT },
+ { 0x07C0, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x0900, U_RIGHT_TO_LEFT },
+ { 0xFB1D, U_LEFT_TO_RIGHT },
+ { 0xFB50, U_RIGHT_TO_LEFT },
+ { 0xFE00, U_RIGHT_TO_LEFT_ARABIC },
+ { 0xFE70, U_LEFT_TO_RIGHT },
+ { 0xFF00, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x10800, U_LEFT_TO_RIGHT },
+ { 0x11000, U_RIGHT_TO_LEFT },
+ { 0x110000, U_LEFT_TO_RIGHT }
+ };
+
+ UChar32 c;
+ int32_t i;
+ UCharDirection shouldBeDir;
+
+ /*
+ * LineBreak.txt specifies:
+ * # - Assigned characters that are not listed explicitly are given the value
+ * # "AL".
+ * # - Unassigned characters are given the value "XX".
+ *
+ * PUA characters are listed explicitly with "XX".
+ * Verify that no assigned character has "XX".
+ */
+ if(type!=U_UNASSIGNED && type!=U_PRIVATE_USE_CHAR) {
+ c=start;
+ while(c<limit) {
+ if(0==u_getIntPropertyValue(c, UCHAR_LINE_BREAK)) {
+ log_err("error UCHAR_LINE_BREAK(assigned U+%04lx)=XX\n", c);
+ }
+ ++c;
+ }
+ }
+
+ /*
+ * Verify default Bidi classes.
+ * For recent Unicode versions, see UCD.html.
+ *
+ * For older Unicode versions:
+ * See table 3-7 "Bidirectional Character Types" in UAX #9.
+ * http://www.unicode.org/reports/tr9/
+ *
+ * See also DerivedBidiClass.txt for Cn code points!
+ *
+ * Unicode 4.0.1/Public Review Issue #28 (http://www.unicode.org/review/resolved-pri.html)
+ * changed some default values.
+ * In particular, non-characters and unassigned Default Ignorable Code Points
+ * change from L to BN.
+ *
+ * UCD.html version 4.0.1 does not yet reflect these changes.
+ */
+ if(type==U_UNASSIGNED || type==U_PRIVATE_USE_CHAR) {
+ /* enumerate the intersections of defaultBidi ranges with [start..limit[ */
+ c=start;
+ for(i=0; i<LENGTHOF(defaultBidi) && c<limit; ++i) {
+ if((int32_t)c<defaultBidi[i][0]) {
+ while(c<limit && (int32_t)c<defaultBidi[i][0]) {
+ if(U_IS_UNICODE_NONCHAR(c) || u_hasBinaryProperty(c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT)) {
+ shouldBeDir=U_BOUNDARY_NEUTRAL;
+ } else {
+ shouldBeDir=(UCharDirection)defaultBidi[i][1];
+ }
+
+ if( u_charDirection(c)!=shouldBeDir ||
+ u_getIntPropertyValue(c, UCHAR_BIDI_CLASS)!=shouldBeDir
+ ) {
+ log_err("error: u_charDirection(unassigned/PUA U+%04lx)=%s should be %s\n",
+ c, dirStrings[u_charDirection(c)], dirStrings[shouldBeDir]);
+ }
+ ++c;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* tests for several properties */
+static void TestUnicodeData()
+{
+ UVersionInfo expectVersionArray;
+ UVersionInfo versionArray;
+ char *fields[15][2];
+ UErrorCode errorCode;
+ UChar32 c;
+ int8_t type;
+
+ u_versionFromString(expectVersionArray, U_UNICODE_VERSION);
+ u_getUnicodeVersion(versionArray);
+ if(memcmp(versionArray, expectVersionArray, U_MAX_VERSION_LENGTH) != 0)
+ {
+ log_err("Testing u_getUnicodeVersion() - expected " U_UNICODE_VERSION " got %d.%d.%d.%d\n",
+ versionArray[0], versionArray[1], versionArray[2], versionArray[3]);
+ }
+
+#if defined(ICU_UNICODE_VERSION)
+ /* test only happens where we have configure.in with UNICODE_VERSION - sanity check. */
+ if(strcmp(U_UNICODE_VERSION, ICU_UNICODE_VERSION))
+ {
+ log_err("Testing configure.in's ICU_UNICODE_VERSION - expected " U_UNICODE_VERSION " got " ICU_UNICODE_VERSION "\n");
+ }
+#endif
+
+ if (ublock_getCode((UChar)0x0041) != UBLOCK_BASIC_LATIN || u_getIntPropertyValue(0x41, UCHAR_BLOCK)!=(int32_t)UBLOCK_BASIC_LATIN) {
+ log_err("ublock_getCode(U+0041) property failed! Expected : %i Got: %i \n", UBLOCK_BASIC_LATIN,ublock_getCode((UChar)0x0041));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ parseUCDFile("UnicodeData.txt", fields, 15, unicodeDataLineFn, NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ return; /* if we couldn't parse UnicodeData.txt, we should return */
+ }
+
+ /* sanity check on repeated properties */
+ for(c=0xfffe; c<=0x10ffff;) {
+ type=u_charType(c);
+ if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
+ log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
+ }
+ if(type!=U_UNASSIGNED) {
+ log_err("error: u_charType(U+%04lx)!=U_UNASSIGNED (returns %d)\n", c, u_charType(c));
+ }
+ if((c&0xffff)==0xfffe) {
+ ++c;
+ } else {
+ c+=0xffff;
+ }
+ }
+
+ /* test that PUA is not "unassigned" */
+ for(c=0xe000; c<=0x10fffd;) {
+ type=u_charType(c);
+ if((uint32_t)u_getIntPropertyValue(c, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(type)) {
+ log_err("error: (uint32_t)u_getIntPropertyValue(U+%04lx, UCHAR_GENERAL_CATEGORY_MASK)!=U_MASK(u_charType())\n", c);
+ }
+ if(type==U_UNASSIGNED) {
+ log_err("error: u_charType(U+%04lx)==U_UNASSIGNED\n", c);
+ } else if(type!=U_PRIVATE_USE_CHAR) {
+ log_verbose("PUA override: u_charType(U+%04lx)=%d\n", c, type);
+ }
+ if(c==0xf8ff) {
+ c=0xf0000;
+ } else if(c==0xffffd) {
+ c=0x100000;
+ } else {
+ ++c;
+ }
+ }
+
+ /* test u_enumCharTypes() */
+ u_enumCharTypes(enumTypeRange, "a1");
+
+ /* check default properties */
+ u_enumCharTypes(enumDefaultsRange, NULL);
+}
+
+static void TestCodeUnit(){
+ const UChar codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0};
+
+ int32_t i;
+
+ for(i=0; i<(int32_t)(sizeof(codeunit)/sizeof(codeunit[0])); i++){
+ UChar c=codeunit[i];
+ if(i<4){
+ if(!(UTF_IS_SINGLE(c)) || (UTF_IS_LEAD(c)) || (UTF_IS_TRAIL(c)) ||(UTF_IS_SURROGATE(c))){
+ log_err("ERROR: U+%04x is a single", c);
+ }
+
+ }
+ if(i >= 4 && i< 8){
+ if(!(UTF_IS_LEAD(c)) || UTF_IS_SINGLE(c) || UTF_IS_TRAIL(c) || !(UTF_IS_SURROGATE(c))){
+ log_err("ERROR: U+%04x is a first surrogate", c);
+ }
+ }
+ if(i >= 8 && i< 12){
+ if(!(UTF_IS_TRAIL(c)) || UTF_IS_SINGLE(c) || UTF_IS_LEAD(c) || !(UTF_IS_SURROGATE(c))){
+ log_err("ERROR: U+%04x is a second surrogate", c);
+ }
+ }
+ }
+
+}
+
+static void TestCodePoint(){
+ const UChar32 codePoint[]={
+ /*surrogate, notvalid(codepoint), not a UnicodeChar, not Error */
+ 0xd800,
+ 0xdbff,
+ 0xdc00,
+ 0xdfff,
+ 0xdc04,
+ 0xd821,
+ /*not a surrogate, valid, isUnicodeChar , not Error*/
+ 0x20ac,
+ 0xd7ff,
+ 0xe000,
+ 0xe123,
+ 0x0061,
+ 0xe065,
+ 0x20402,
+ 0x24506,
+ 0x23456,
+ 0x20402,
+ 0x10402,
+ 0x23456,
+ /*not a surrogate, not valid, isUnicodeChar, isError */
+ 0x0015,
+ 0x009f,
+ /*not a surrogate, not valid, not isUnicodeChar, isError */
+ 0xffff,
+ 0xfffe,
+ };
+ int32_t i;
+ for(i=0; i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0])); i++){
+ UChar32 c=codePoint[i];
+ if(i<6){
+ if(!UTF_IS_SURROGATE(c) || !U_IS_SURROGATE(c) || !U16_IS_SURROGATE(c)){
+ log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_VALID(c)){
+ log_err("ERROR: isValid() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){
+ log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_ERROR(c)){
+ log_err("ERROR: isError() failed for U+%04x\n", c);
+ }
+ }else if(i >=6 && i<18){
+ if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
+ log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
+ }
+ if(!UTF_IS_VALID(c)){
+ log_err("ERROR: isValid() failed for U+%04x\n", c);
+ }
+ if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){
+ log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_ERROR(c)){
+ log_err("ERROR: isError() failed for U+%04x\n", c);
+ }
+ }else if(i >=18 && i<20){
+ if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
+ log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_VALID(c)){
+ log_err("ERROR: isValid() failed for U+%04x\n", c);
+ }
+ if(!UTF_IS_UNICODE_CHAR(c) || !U_IS_UNICODE_CHAR(c)){
+ log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
+ }
+ if(!UTF_IS_ERROR(c)){
+ log_err("ERROR: isError() failed for U+%04x\n", c);
+ }
+ }
+ else if(i >=18 && i<(int32_t)(sizeof(codePoint)/sizeof(codePoint[0]))){
+ if(UTF_IS_SURROGATE(c) || U_IS_SURROGATE(c) || U16_IS_SURROGATE(c)){
+ log_err("ERROR: isSurrogate() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_VALID(c)){
+ log_err("ERROR: isValid() failed for U+%04x\n", c);
+ }
+ if(UTF_IS_UNICODE_CHAR(c) || U_IS_UNICODE_CHAR(c)){
+ log_err("ERROR: isUnicodeChar() failed for U+%04x\n", c);
+ }
+ if(!UTF_IS_ERROR(c)){
+ log_err("ERROR: isError() failed for U+%04x\n", c);
+ }
+ }
+ }
+
+ if(
+ !U_IS_BMP(0) || !U_IS_BMP(0x61) || !U_IS_BMP(0x20ac) ||
+ !U_IS_BMP(0xd9da) || !U_IS_BMP(0xdfed) || !U_IS_BMP(0xffff) ||
+ U_IS_BMP(U_SENTINEL) || U_IS_BMP(0x10000) || U_IS_BMP(0x50005) ||
+ U_IS_BMP(0x10ffff) || U_IS_BMP(0x110000) || U_IS_BMP(0x7fffffff)
+ ) {
+ log_err("error with U_IS_BMP()\n");
+ }
+
+ if(
+ U_IS_SUPPLEMENTARY(0) || U_IS_SUPPLEMENTARY(0x61) || U_IS_SUPPLEMENTARY(0x20ac) ||
+ U_IS_SUPPLEMENTARY(0xd9da) || U_IS_SUPPLEMENTARY(0xdfed) || U_IS_SUPPLEMENTARY(0xffff) ||
+ U_IS_SUPPLEMENTARY(U_SENTINEL) || !U_IS_SUPPLEMENTARY(0x10000) || !U_IS_SUPPLEMENTARY(0x50005) ||
+ !U_IS_SUPPLEMENTARY(0x10ffff) || U_IS_SUPPLEMENTARY(0x110000) || U_IS_SUPPLEMENTARY(0x7fffffff)
+ ) {
+ log_err("error with U_IS_SUPPLEMENTARY()\n");
+ }
+}
+
+static void TestCharLength()
+{
+ const int32_t codepoint[]={
+ 1, 0x0061,
+ 1, 0xe065,
+ 1, 0x20ac,
+ 2, 0x20402,
+ 2, 0x23456,
+ 2, 0x24506,
+ 2, 0x20402,
+ 2, 0x10402,
+ 1, 0xd7ff,
+ 1, 0xe000
+ };
+
+ int32_t i;
+ UBool multiple;
+ for(i=0; i<(int32_t)(sizeof(codepoint)/sizeof(codepoint[0])); i=(int16_t)(i+2)){
+ UChar32 c=codepoint[i+1];
+ if(UTF_CHAR_LENGTH(c) != codepoint[i] || U16_LENGTH(c) != codepoint[i]){
+ log_err("The no: of code units for U+%04x:- Expected: %d Got: %d\n", c, codepoint[i], UTF_CHAR_LENGTH(c));
+ }
+ multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
+ if(UTF_NEED_MULTIPLE_UCHAR(c) != multiple){
+ log_err("ERROR: Unicode::needMultipleUChar() failed for U+%04x\n", c);
+ }
+ }
+}
+
+/*internal functions ----*/
+static int32_t MakeProp(char* str)
+{
+ int32_t result = 0;
+ char* matchPosition =0;
+
+ matchPosition = strstr(tagStrings, str);
+ if (matchPosition == 0)
+ {
+ log_err("unrecognized type letter ");
+ log_err(str);
+ }
+ else
+ result = (int32_t)((matchPosition - tagStrings) / 2);
+ return result;
+}
+
+static int32_t MakeDir(char* str)
+{
+ int32_t pos = 0;
+ for (pos = 0; pos < 19; pos++) {
+ if (strcmp(str, dirStrings[pos]) == 0) {
+ return pos;
+ }
+ }
+ return -1;
+}
+
+/* test u_charName() -------------------------------------------------------- */
+
+static const struct {
+ uint32_t code;
+ const char *name, *oldName, *extName;
+} names[]={
+ {0x0061, "LATIN SMALL LETTER A", "", "LATIN SMALL LETTER A"},
+ {0x0284, "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK", "LATIN SMALL LETTER DOTLESS J BAR HOOK", "LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK" },
+ {0x3401, "CJK UNIFIED IDEOGRAPH-3401", "", "CJK UNIFIED IDEOGRAPH-3401" },
+ {0x7fed, "CJK UNIFIED IDEOGRAPH-7FED", "", "CJK UNIFIED IDEOGRAPH-7FED" },
+ {0xac00, "HANGUL SYLLABLE GA", "", "HANGUL SYLLABLE GA" },
+ {0xd7a3, "HANGUL SYLLABLE HIH", "", "HANGUL SYLLABLE HIH" },
+ {0xd800, "", "", "<lead surrogate-D800>" },
+ {0xdc00, "", "", "<trail surrogate-DC00>" },
+ {0xff08, "FULLWIDTH LEFT PARENTHESIS", "FULLWIDTH OPENING PARENTHESIS", "FULLWIDTH LEFT PARENTHESIS" },
+ {0xffe5, "FULLWIDTH YEN SIGN", "", "FULLWIDTH YEN SIGN" },
+ {0xffff, "", "", "<noncharacter-FFFF>" },
+ {0x23456, "CJK UNIFIED IDEOGRAPH-23456", "", "CJK UNIFIED IDEOGRAPH-23456" }
+};
+
+static UBool
+enumCharNamesFn(void *context,
+ UChar32 code, UCharNameChoice nameChoice,
+ const char *name, int32_t length) {
+ int32_t *pCount=(int32_t *)context;
+ int i;
+
+ if(length<=0 || length!=(int32_t)strlen(name)) {
+ /* should not be called with an empty string or invalid length */
+ log_err("u_enumCharName(0x%lx)=%s but length=%ld\n", name, length);
+ return TRUE;
+ }
+
+ ++*pCount;
+ for(i=0; i<sizeof(names)/sizeof(names[0]); ++i) {
+ if(code==(UChar32)names[i].code) {
+ switch (nameChoice) {
+ case U_EXTENDED_CHAR_NAME:
+ if(0!=strcmp(name, names[i].extName)) {
+ log_err("u_enumCharName(0x%lx - Extended)=%s instead of %s\n", code, name, names[i].extName);
+ }
+ break;
+ case U_UNICODE_CHAR_NAME:
+ if(0!=strcmp(name, names[i].name)) {
+ log_err("u_enumCharName(0x%lx)=%s instead of %s\n", code, name, names[i].name);
+ }
+ break;
+ case U_UNICODE_10_CHAR_NAME:
+ if(names[i].oldName[0]==0 || 0!=strcmp(name, names[i].oldName)) {
+ log_err("u_enumCharName(0x%lx - 1.0)=%s instead of %s\n", code, name, names[i].oldName);
+ }
+ break;
+ case U_CHAR_NAME_CHOICE_COUNT:
+ break;
+ }
+ break;
+ }
+ }
+ return TRUE;
+}
+
+struct enumExtCharNamesContext {
+ uint32_t length;
+ int32_t last;
+};
+
+static UBool
+enumExtCharNamesFn(void *context,
+ UChar32 code, UCharNameChoice nameChoice,
+ const char *name, int32_t length) {
+ struct enumExtCharNamesContext *ecncp = (struct enumExtCharNamesContext *) context;
+
+ if (ecncp->last != (int32_t) code - 1) {
+ if (ecncp->last < 0) {
+ log_err("u_enumCharName(0x%lx - Ext) after u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x%lx - Ext)\n", code, ecncp->last, ecncp->last + 1);
+ } else {
+ log_err("u_enumCharName(0x%lx - Ext) instead of u_enumCharName(0x0 - Ext)\n", code);
+ }
+ }
+ ecncp->last = (int32_t) code;
+
+ if (!*name) {
+ log_err("u_enumCharName(0x%lx - Ext) should not be an empty string\n", code);
+ }
+
+ return enumCharNamesFn(&ecncp->length, code, nameChoice, name, length);
+}
+
+/**
+ * This can be made more efficient by moving it into putil.c and having
+ * it directly access the ebcdic translation tables.
+ * TODO: If we get this method in putil.c, then delete it from here.
+ */
+static UChar
+u_charToUChar(char c) {
+ UChar uc;
+ u_charsToUChars(&c, &uc, 1);
+ return uc;
+}
+
+static void
+TestCharNames() {
+ static char name[80];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ struct enumExtCharNamesContext extContext;
+ int32_t length;
+ UChar32 c;
+ int32_t i;
+
+ log_verbose("Testing uprv_getMaxCharNameLength()\n");
+ length=uprv_getMaxCharNameLength();
+ if(length==0) {
+ /* no names data available */
+ return;
+ }
+ if(length<83) { /* Unicode 3.2 max char name length */
+ log_err("uprv_getMaxCharNameLength()=%d is too short");
+ }
+ /* ### TODO same tests for max ISO comment length as for max name length */
+
+ log_verbose("Testing u_charName()\n");
+ for(i=0; i<(int32_t)(sizeof(names)/sizeof(names[0])); ++i) {
+ /* modern Unicode character name */
+ length=u_charName(names[i].code, U_UNICODE_CHAR_NAME, name, sizeof(name), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("u_charName(0x%lx) error %s\n", names[i].code, u_errorName(errorCode));
+ return;
+ }
+ if(length<0 || 0!=strcmp(name, names[i].name) || length!=(uint16_t)strlen(name)) {
+ log_err("u_charName(0x%lx) gets: %s (length %ld) instead of: %s\n", names[i].code, name, length, names[i].name);
+ }
+
+ /* find the modern name */
+ if (*names[i].name) {
+ c=u_charFromName(U_UNICODE_CHAR_NAME, names[i].name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("u_charFromName(%s) error %s\n", names[i].name, u_errorName(errorCode));
+ return;
+ }
+ if(c!=(UChar32)names[i].code) {
+ log_err("u_charFromName(%s) gets 0x%lx instead of 0x%lx\n", names[i].name, c, names[i].code);
+ }
+ }
+
+ /* Unicode 1.0 character name */
+ length=u_charName(names[i].code, U_UNICODE_10_CHAR_NAME, name, sizeof(name), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("u_charName(0x%lx - 1.0) error %s\n", names[i].code, u_errorName(errorCode));
+ return;
+ }
+ if(length<0 || (length>0 && 0!=strcmp(name, names[i].oldName)) || length!=(uint16_t)strlen(name)) {
+ log_err("u_charName(0x%lx - 1.0) gets %s length %ld instead of nothing or %s\n", names[i].code, name, length, names[i].oldName);
+ }
+
+ /* find the Unicode 1.0 name if it is stored (length>0 means that we could read it) */
+ if(names[i].oldName[0]!=0 /* && length>0 */) {
+ c=u_charFromName(U_UNICODE_10_CHAR_NAME, names[i].oldName, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("u_charFromName(%s - 1.0) error %s\n", names[i].oldName, u_errorName(errorCode));
+ return;
+ }
+ if(c!=(UChar32)names[i].code) {
+ log_err("u_charFromName(%s - 1.0) gets 0x%lx instead of 0x%lx\n", names[i].oldName, c, names[i].code);
+ }
+ }
+ }
+
+ /* test u_enumCharNames() */
+ length=0;
+ errorCode=U_ZERO_ERROR;
+ u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumCharNamesFn, &length, U_UNICODE_CHAR_NAME, &errorCode);
+ if(U_FAILURE(errorCode) || length<94140) {
+ log_err("u_enumCharNames(%ld..%lx) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE, u_errorName(errorCode), length);
+ }
+
+ extContext.length = 0;
+ extContext.last = -1;
+ errorCode=U_ZERO_ERROR;
+ u_enumCharNames(UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, enumExtCharNamesFn, &extContext, U_EXTENDED_CHAR_NAME, &errorCode);
+ if(U_FAILURE(errorCode) || extContext.length<UCHAR_MAX_VALUE + 1) {
+ log_err("u_enumCharNames(%ld..0x%lx - Extended) error %s names count=%ld\n", UCHAR_MIN_VALUE, UCHAR_MAX_VALUE + 1, u_errorName(errorCode), extContext.length);
+ }
+
+ /* test that u_charFromName() uppercases the input name, i.e., works with mixed-case names (new in 2.0) */
+ if(0x61!=u_charFromName(U_UNICODE_CHAR_NAME, "LATin smALl letTER A", &errorCode)) {
+ log_err("u_charFromName(U_UNICODE_CHAR_NAME, \"LATin smALl letTER A\") did not find U+0061 (%s)\n", u_errorName(errorCode));
+ }
+
+ /* Test getCharNameCharacters */
+ if(!QUICK) {
+ enum { BUFSIZE = 256 };
+ UErrorCode ec = U_ZERO_ERROR;
+ char buf[BUFSIZE];
+ int32_t maxLength;
+ UChar32 cp;
+ UChar pat[BUFSIZE], dumbPat[BUFSIZE];
+ int32_t l1, l2;
+ UBool map[256];
+ UBool ok;
+
+ USet* set = uset_open(1, 0); /* empty set */
+ USet* dumb = uset_open(1, 0); /* empty set */
+
+ /*
+ * uprv_getCharNameCharacters() will likely return more lowercase
+ * letters than actual character names contain because
+ * it includes all the characters in lowercased names of
+ * general categories, for the full possible set of extended names.
+ */
+ {
+ USetAdder sa={
+ NULL,
+ uset_add,
+ uset_addRange,
+ uset_addString,
+ NULL /* don't need remove() */
+ };
+ sa.set=set;
+ uprv_getCharNameCharacters(&sa);
+ }
+
+ /* build set the dumb (but sure-fire) way */
+ for (i=0; i<256; ++i) {
+ map[i] = FALSE;
+ }
+
+ maxLength=0;
+ for (cp=0; cp<0x110000; ++cp) {
+ int32_t len = u_charName(cp, U_EXTENDED_CHAR_NAME,
+ buf, BUFSIZE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: u_charName failed when it shouldn't\n");
+ uset_close(set);
+ uset_close(dumb);
+ return;
+ }
+ if(len>maxLength) {
+ maxLength=len;
+ }
+
+ for (i=0; i<len; ++i) {
+ if (!map[(uint8_t) buf[i]]) {
+ uset_add(dumb, (UChar32)u_charToUChar(buf[i]));
+ map[(uint8_t) buf[i]] = TRUE;
+ }
+ }
+
+ /* test for leading/trailing whitespace */
+ if(buf[0]==' ' || buf[0]=='\t' || buf[len-1]==' ' || buf[len-1]=='\t') {
+ log_err("u_charName(U+%04x) returns a name with leading or trailing whitespace\n", cp);
+ }
+ }
+
+ if(map[(uint8_t)'\t']) {
+ log_err("u_charName() returned a name with a TAB for some code point\n", cp);
+ }
+
+ length=uprv_getMaxCharNameLength();
+ if(length!=maxLength) {
+ log_err("uprv_getMaxCharNameLength()=%d differs from the maximum length %d of all extended names\n",
+ length, maxLength);
+ }
+
+ /* compare the sets. Where is my uset_equals?!! */
+ ok=TRUE;
+ for(i=0; i<256; ++i) {
+ if(uset_contains(set, i)!=uset_contains(dumb, i)) {
+ if(0x61<=i && i<=0x7a /* a-z */ && uset_contains(set, i) && !uset_contains(dumb, i)) {
+ /* ignore lowercase a-z that are in set but not in dumb */
+ ok=TRUE;
+ } else {
+ ok=FALSE;
+ break;
+ }
+ }
+ }
+
+ l1 = uset_toPattern(set, pat, BUFSIZE, TRUE, &ec);
+ l2 = uset_toPattern(dumb, dumbPat, BUFSIZE, TRUE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: uset_toPattern failed when it shouldn't\n");
+ uset_close(set);
+ uset_close(dumb);
+ return;
+ }
+
+ if (l1 >= BUFSIZE) {
+ l1 = BUFSIZE-1;
+ pat[l1] = 0;
+ }
+ if (l2 >= BUFSIZE) {
+ l2 = BUFSIZE-1;
+ dumbPat[l2] = 0;
+ }
+
+ if (!ok) {
+ log_err("FAIL: uprv_getCharNameCharacters() returned %s, expected %s (too many lowercase a-z are ok)\n",
+ aescstrdup(pat, l1), aescstrdup(dumbPat, l2));
+ } else if(VERBOSITY) {
+ log_verbose("Ok: uprv_getCharNameCharacters() returned %s\n", aescstrdup(pat, l1));
+ }
+
+ uset_close(set);
+ uset_close(dumb);
+ }
+
+ /* ### TODO: test error cases and other interesting things */
+}
+
+/* test u_isMirrored() and u_charMirror() ----------------------------------- */
+
+static void
+TestMirroring() {
+ USet *set;
+ UErrorCode errorCode;
+
+ UChar32 start, end, c2, c3;
+ int32_t i;
+
+ U_STRING_DECL(mirroredPattern, "[:Bidi_Mirrored:]", 17);
+
+ U_STRING_INIT(mirroredPattern, "[:Bidi_Mirrored:]", 17);
+
+ log_verbose("Testing u_isMirrored()\n");
+ if(!(u_isMirrored(0x28) && u_isMirrored(0xbb) && u_isMirrored(0x2045) && u_isMirrored(0x232a) &&
+ !u_isMirrored(0x27) && !u_isMirrored(0x61) && !u_isMirrored(0x284) && !u_isMirrored(0x3400)
+ )
+ ) {
+ log_err("u_isMirrored() does not work correctly\n");
+ }
+
+ log_verbose("Testing u_charMirror()\n");
+ if(!(u_charMirror(0x3c)==0x3e && u_charMirror(0x5d)==0x5b && u_charMirror(0x208d)==0x208e && u_charMirror(0x3017)==0x3016 &&
+ u_charMirror(0xbb)==0xab && u_charMirror(0x2215)==0x29F5 && u_charMirror(0x29F5)==0x2215 && /* large delta between the code points */
+ u_charMirror(0x2e)==0x2e && u_charMirror(0x6f3)==0x6f3 && u_charMirror(0x301c)==0x301c && u_charMirror(0xa4ab)==0xa4ab &&
+ /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */
+ u_charMirror(0x2018)==0x2018 && u_charMirror(0x201b)==0x201b && u_charMirror(0x301d)==0x301d
+ )
+ ) {
+ log_err("u_charMirror() does not work correctly\n");
+ }
+
+ /* verify that Bidi_Mirroring_Glyph roundtrips */
+ errorCode=U_ZERO_ERROR;
+ set=uset_openPattern(mirroredPattern, 17, &errorCode);
+
+ if (U_FAILURE(errorCode)) {
+ log_data_err("uset_openPattern(mirroredPattern, 17, &errorCode) failed!");
+ } else {
+ for(i=0; 0==uset_getItem(set, i, &start, &end, NULL, 0, &errorCode); ++i) {
+ do {
+ c2=u_charMirror(start);
+ c3=u_charMirror(c2);
+ if(c3!=start) {
+ log_err("u_charMirror() does not roundtrip: U+%04lx->U+%04lx->U+%04lx\n", (long)start, (long)c2, (long)c3);
+ }
+ } while(++start<=end);
+ }
+ }
+
+ uset_close(set);
+}
+
+
+struct RunTestData
+{
+ const char *runText;
+ UScriptCode runCode;
+};
+
+typedef struct RunTestData RunTestData;
+
+static void
+CheckScriptRuns(UScriptRun *scriptRun, int32_t *runStarts, const RunTestData *testData, int32_t nRuns,
+ const char *prefix)
+{
+ int32_t run, runStart, runLimit;
+ UScriptCode runCode;
+
+ /* iterate over all the runs */
+ run = 0;
+ while (uscript_nextRun(scriptRun, &runStart, &runLimit, &runCode)) {
+ if (runStart != runStarts[run]) {
+ log_err("%s: incorrect start offset for run %d: expected %d, got %d\n",
+ prefix, run, runStarts[run], runStart);
+ }
+
+ if (runLimit != runStarts[run + 1]) {
+ log_err("%s: incorrect limit offset for run %d: expected %d, got %d\n",
+ prefix, run, runStarts[run + 1], runLimit);
+ }
+
+ if (runCode != testData[run].runCode) {
+ log_err("%s: incorrect script for run %d: expected \"%s\", got \"%s\"\n",
+ prefix, run, uscript_getName(testData[run].runCode), uscript_getName(runCode));
+ }
+
+ run += 1;
+
+ /* stop when we've seen all the runs we expect to see */
+ if (run >= nRuns) {
+ break;
+ }
+ }
+
+ /* Complain if we didn't see then number of runs we expected */
+ if (run != nRuns) {
+ log_err("%s: incorrect number of runs: expected %d, got %d\n", prefix, run, nRuns);
+ }
+}
+
+static void
+TestUScriptRunAPI()
+{
+ static const RunTestData testData1[] = {
+ {"\\u0020\\u0946\\u0939\\u093F\\u0928\\u094D\\u0926\\u0940\\u0020", USCRIPT_DEVANAGARI},
+ {"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064A\\u0629\\u0020", USCRIPT_ARABIC},
+ {"\\u0420\\u0443\\u0441\\u0441\\u043A\\u0438\\u0439\\u0020", USCRIPT_CYRILLIC},
+ {"English (", USCRIPT_LATIN},
+ {"\\u0E44\\u0E17\\u0E22", USCRIPT_THAI},
+ {") ", USCRIPT_LATIN},
+ {"\\u6F22\\u5B75", USCRIPT_HAN},
+ {"\\u3068\\u3072\\u3089\\u304C\\u306A\\u3068", USCRIPT_HIRAGANA},
+ {"\\u30AB\\u30BF\\u30AB\\u30CA", USCRIPT_KATAKANA},
+ {"\\U00010400\\U00010401\\U00010402\\U00010403", USCRIPT_DESERET}
+ };
+
+ static const RunTestData testData2[] = {
+ {"((((((((((abc))))))))))", USCRIPT_LATIN}
+ };
+
+ static const struct {
+ const RunTestData *testData;
+ int32_t nRuns;
+ } testDataEntries[] = {
+ {testData1, LENGTHOF(testData1)},
+ {testData2, LENGTHOF(testData2)}
+ };
+
+ static const int32_t nTestEntries = LENGTHOF(testDataEntries);
+ int32_t testEntry;
+
+ for (testEntry = 0; testEntry < nTestEntries; testEntry += 1) {
+ UChar testString[1024];
+ int32_t runStarts[256];
+ int32_t nTestRuns = testDataEntries[testEntry].nRuns;
+ const RunTestData *testData = testDataEntries[testEntry].testData;
+
+ int32_t run, stringLimit;
+ UScriptRun *scriptRun = NULL;
+ UErrorCode err;
+
+ /*
+ * Fill in the test string and the runStarts array.
+ */
+ stringLimit = 0;
+ for (run = 0; run < nTestRuns; run += 1) {
+ runStarts[run] = stringLimit;
+ stringLimit += u_unescape(testData[run].runText, &testString[stringLimit], 1024 - stringLimit);
+ /*stringLimit -= 1;*/
+ }
+
+ /* The limit of the last run */
+ runStarts[nTestRuns] = stringLimit;
+
+ /*
+ * Make sure that calling uscript_OpenRun with a NULL text pointer
+ * and a non-zero text length returns the correct error.
+ */
+ err = U_ZERO_ERROR;
+ scriptRun = uscript_openRun(NULL, stringLimit, &err);
+
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("uscript_openRun(NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
+ }
+
+ if (scriptRun != NULL) {
+ log_err("uscript_openRun(NULL, stringLimit, &err) returned a non-NULL result.\n");
+ uscript_closeRun(scriptRun);
+ }
+
+ /*
+ * Make sure that calling uscript_OpenRun with a non-NULL text pointer
+ * and a zero text length returns the correct error.
+ */
+ err = U_ZERO_ERROR;
+ scriptRun = uscript_openRun(testString, 0, &err);
+
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("uscript_openRun(testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
+ }
+
+ if (scriptRun != NULL) {
+ log_err("uscript_openRun(testString, 0, &err) returned a non-NULL result.\n");
+ uscript_closeRun(scriptRun);
+ }
+
+ /*
+ * Make sure that calling uscript_openRun with a NULL text pointer
+ * and a zero text length doesn't return an error.
+ */
+ err = U_ZERO_ERROR;
+ scriptRun = uscript_openRun(NULL, 0, &err);
+
+ if (U_FAILURE(err)) {
+ log_err("Got error %s from uscript_openRun(NULL, 0, &err)\n", u_errorName(err));
+ }
+
+ /* Make sure that the empty iterator doesn't find any runs */
+ if (uscript_nextRun(scriptRun, NULL, NULL, NULL)) {
+ log_err("uscript_nextRun(...) returned TRUE for an empty iterator.\n");
+ }
+
+ /*
+ * Make sure that calling uscript_setRunText with a NULL text pointer
+ * and a non-zero text length returns the correct error.
+ */
+ err = U_ZERO_ERROR;
+ uscript_setRunText(scriptRun, NULL, stringLimit, &err);
+
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("uscript_setRunText(scriptRun, NULL, stringLimit, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
+ }
+
+ /*
+ * Make sure that calling uscript_OpenRun with a non-NULL text pointer
+ * and a zero text length returns the correct error.
+ */
+ err = U_ZERO_ERROR;
+ uscript_setRunText(scriptRun, testString, 0, &err);
+
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("uscript_setRunText(scriptRun, testString, 0, &err) returned %s instead of U_ILLEGAL_ARGUMENT_ERROR.\n", u_errorName(err));
+ }
+
+ /*
+ * Now call uscript_setRunText on the empty iterator
+ * and make sure that it works.
+ */
+ err = U_ZERO_ERROR;
+ uscript_setRunText(scriptRun, testString, stringLimit, &err);
+
+ if (U_FAILURE(err)) {
+ log_err("Got error %s from uscript_setRunText(...)\n", u_errorName(err));
+ } else {
+ CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_setRunText");
+ }
+
+ uscript_closeRun(scriptRun);
+
+ /*
+ * Now open an interator over the testString
+ * using uscript_openRun and make sure that it works
+ */
+ scriptRun = uscript_openRun(testString, stringLimit, &err);
+
+ if (U_FAILURE(err)) {
+ log_err("Got error %s from uscript_openRun(...)\n", u_errorName(err));
+ } else {
+ CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_openRun");
+ }
+
+ /* Now reset the iterator, and make sure
+ * that it still works.
+ */
+ uscript_resetRun(scriptRun);
+
+ CheckScriptRuns(scriptRun, runStarts, testData, nTestRuns, "uscript_resetRun");
+
+ /* Close the iterator */
+ uscript_closeRun(scriptRun);
+ }
+}
+
+/* test additional, non-core properties */
+static void
+TestAdditionalProperties() {
+ /* test data for u_charAge() */
+ static const struct {
+ UChar32 c;
+ UVersionInfo version;
+ } charAges[]={
+ {0x41, { 1, 1, 0, 0 }},
+ {0xffff, { 1, 1, 0, 0 }},
+ {0x20ab, { 2, 0, 0, 0 }},
+ {0x2fffe, { 2, 0, 0, 0 }},
+ {0x20ac, { 2, 1, 0, 0 }},
+ {0xfb1d, { 3, 0, 0, 0 }},
+ {0x3f4, { 3, 1, 0, 0 }},
+ {0x10300, { 3, 1, 0, 0 }},
+ {0x220, { 3, 2, 0, 0 }},
+ {0xff60, { 3, 2, 0, 0 }}
+ };
+
+ /* test data for u_hasBinaryProperty() */
+ static const int32_t
+ props[][3]={ /* code point, property, value */
+ { 0x0627, UCHAR_ALPHABETIC, TRUE },
+ { 0x1034a, UCHAR_ALPHABETIC, TRUE },
+ { 0x2028, UCHAR_ALPHABETIC, FALSE },
+
+ { 0x0066, UCHAR_ASCII_HEX_DIGIT, TRUE },
+ { 0x0067, UCHAR_ASCII_HEX_DIGIT, FALSE },
+
+ { 0x202c, UCHAR_BIDI_CONTROL, TRUE },
+ { 0x202f, UCHAR_BIDI_CONTROL, FALSE },
+
+ { 0x003c, UCHAR_BIDI_MIRRORED, TRUE },
+ { 0x003d, UCHAR_BIDI_MIRRORED, FALSE },
+
+ /* see Unicode Corrigendum #6 at http://www.unicode.org/versions/corrigendum6.html */
+ { 0x2018, UCHAR_BIDI_MIRRORED, FALSE },
+ { 0x201d, UCHAR_BIDI_MIRRORED, FALSE },
+ { 0x201f, UCHAR_BIDI_MIRRORED, FALSE },
+ { 0x301e, UCHAR_BIDI_MIRRORED, FALSE },
+
+ { 0x058a, UCHAR_DASH, TRUE },
+ { 0x007e, UCHAR_DASH, FALSE },
+
+ { 0x0c4d, UCHAR_DIACRITIC, TRUE },
+ { 0x3000, UCHAR_DIACRITIC, FALSE },
+
+ { 0x0e46, UCHAR_EXTENDER, TRUE },
+ { 0x0020, UCHAR_EXTENDER, FALSE },
+
+#if !UCONFIG_NO_NORMALIZATION
+ { 0xfb1d, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE },
+ { 0x1d15f, UCHAR_FULL_COMPOSITION_EXCLUSION, TRUE },
+ { 0xfb1e, UCHAR_FULL_COMPOSITION_EXCLUSION, FALSE },
+
+ { 0x110a, UCHAR_NFD_INERT, TRUE }, /* Jamo L */
+ { 0x0308, UCHAR_NFD_INERT, FALSE },
+
+ { 0x1164, UCHAR_NFKD_INERT, TRUE }, /* Jamo V */
+ { 0x1d79d, UCHAR_NFKD_INERT, FALSE }, /* math compat version of xi */
+
+ { 0x0021, UCHAR_NFC_INERT, TRUE }, /* ! */
+ { 0x0061, UCHAR_NFC_INERT, FALSE }, /* a */
+ { 0x00e4, UCHAR_NFC_INERT, FALSE }, /* a-umlaut */
+ { 0x0102, UCHAR_NFC_INERT, FALSE }, /* a-breve */
+ { 0xac1c, UCHAR_NFC_INERT, FALSE }, /* Hangul LV */
+ { 0xac1d, UCHAR_NFC_INERT, TRUE }, /* Hangul LVT */
+
+ { 0x1d79d, UCHAR_NFKC_INERT, FALSE }, /* math compat version of xi */
+ { 0x2a6d6, UCHAR_NFKC_INERT, TRUE }, /* Han, last of CJK ext. B */
+
+ { 0x00e4, UCHAR_SEGMENT_STARTER, TRUE },
+ { 0x0308, UCHAR_SEGMENT_STARTER, FALSE },
+ { 0x110a, UCHAR_SEGMENT_STARTER, TRUE }, /* Jamo L */
+ { 0x1164, UCHAR_SEGMENT_STARTER, FALSE },/* Jamo V */
+ { 0xac1c, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LV */
+ { 0xac1d, UCHAR_SEGMENT_STARTER, TRUE }, /* Hangul LVT */
+#endif
+
+ { 0x0044, UCHAR_HEX_DIGIT, TRUE },
+ { 0xff46, UCHAR_HEX_DIGIT, TRUE },
+ { 0x0047, UCHAR_HEX_DIGIT, FALSE },
+
+ { 0x30fb, UCHAR_HYPHEN, TRUE },
+ { 0xfe58, UCHAR_HYPHEN, FALSE },
+
+ { 0x2172, UCHAR_ID_CONTINUE, TRUE },
+ { 0x0307, UCHAR_ID_CONTINUE, TRUE },
+ { 0x005c, UCHAR_ID_CONTINUE, FALSE },
+
+ { 0x2172, UCHAR_ID_START, TRUE },
+ { 0x007a, UCHAR_ID_START, TRUE },
+ { 0x0039, UCHAR_ID_START, FALSE },
+
+ { 0x4db5, UCHAR_IDEOGRAPHIC, TRUE },
+ { 0x2f999, UCHAR_IDEOGRAPHIC, TRUE },
+ { 0x2f99, UCHAR_IDEOGRAPHIC, FALSE },
+
+ { 0x200c, UCHAR_JOIN_CONTROL, TRUE },
+ { 0x2029, UCHAR_JOIN_CONTROL, FALSE },
+
+ { 0x1d7bc, UCHAR_LOWERCASE, TRUE },
+ { 0x0345, UCHAR_LOWERCASE, TRUE },
+ { 0x0030, UCHAR_LOWERCASE, FALSE },
+
+ { 0x1d7a9, UCHAR_MATH, TRUE },
+ { 0x2135, UCHAR_MATH, TRUE },
+ { 0x0062, UCHAR_MATH, FALSE },
+
+ { 0xfde1, UCHAR_NONCHARACTER_CODE_POINT, TRUE },
+ { 0x10ffff, UCHAR_NONCHARACTER_CODE_POINT, TRUE },
+ { 0x10fffd, UCHAR_NONCHARACTER_CODE_POINT, FALSE },
+
+ { 0x0022, UCHAR_QUOTATION_MARK, TRUE },
+ { 0xff62, UCHAR_QUOTATION_MARK, TRUE },
+ { 0xd840, UCHAR_QUOTATION_MARK, FALSE },
+
+ { 0x061f, UCHAR_TERMINAL_PUNCTUATION, TRUE },
+ { 0xe003f, UCHAR_TERMINAL_PUNCTUATION, FALSE },
+
+ { 0x1d44a, UCHAR_UPPERCASE, TRUE },
+ { 0x2162, UCHAR_UPPERCASE, TRUE },
+ { 0x0345, UCHAR_UPPERCASE, FALSE },
+
+ { 0x0020, UCHAR_WHITE_SPACE, TRUE },
+ { 0x202f, UCHAR_WHITE_SPACE, TRUE },
+ { 0x3001, UCHAR_WHITE_SPACE, FALSE },
+
+ { 0x0711, UCHAR_XID_CONTINUE, TRUE },
+ { 0x1d1aa, UCHAR_XID_CONTINUE, TRUE },
+ { 0x007c, UCHAR_XID_CONTINUE, FALSE },
+
+ { 0x16ee, UCHAR_XID_START, TRUE },
+ { 0x23456, UCHAR_XID_START, TRUE },
+ { 0x1d1aa, UCHAR_XID_START, FALSE },
+
+ /*
+ * Version break:
+ * The following properties are only supported starting with the
+ * Unicode version indicated in the second field.
+ */
+ { -1, 0x320, 0 },
+
+ { 0x180c, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE },
+ { 0xfe02, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, TRUE },
+ { 0x1801, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, FALSE },
+
+ { 0x0341, UCHAR_DEPRECATED, TRUE },
+ { 0xe0041, UCHAR_DEPRECATED, FALSE },
+
+ { 0x00a0, UCHAR_GRAPHEME_BASE, TRUE },
+ { 0x0a4d, UCHAR_GRAPHEME_BASE, FALSE },
+ { 0xff9f, UCHAR_GRAPHEME_BASE, TRUE }, /* changed from Unicode 3.2 to 4 */
+
+ { 0x0300, UCHAR_GRAPHEME_EXTEND, TRUE },
+ { 0xff9f, UCHAR_GRAPHEME_EXTEND, FALSE }, /* changed from Unicode 3.2 to 4 */
+ { 0x0603, UCHAR_GRAPHEME_EXTEND, FALSE },
+
+ { 0x0a4d, UCHAR_GRAPHEME_LINK, TRUE },
+ { 0xff9f, UCHAR_GRAPHEME_LINK, FALSE },
+
+ { 0x2ff7, UCHAR_IDS_BINARY_OPERATOR, TRUE },
+ { 0x2ff3, UCHAR_IDS_BINARY_OPERATOR, FALSE },
+
+ { 0x2ff3, UCHAR_IDS_TRINARY_OPERATOR, TRUE },
+ { 0x2f03, UCHAR_IDS_TRINARY_OPERATOR, FALSE },
+
+ { 0x0ec1, UCHAR_LOGICAL_ORDER_EXCEPTION, TRUE },
+ { 0xdcba, UCHAR_LOGICAL_ORDER_EXCEPTION, FALSE },
+
+ { 0x2e9b, UCHAR_RADICAL, TRUE },
+ { 0x4e00, UCHAR_RADICAL, FALSE },
+
+ { 0x012f, UCHAR_SOFT_DOTTED, TRUE },
+ { 0x0049, UCHAR_SOFT_DOTTED, FALSE },
+
+ { 0xfa11, UCHAR_UNIFIED_IDEOGRAPH, TRUE },
+ { 0xfa12, UCHAR_UNIFIED_IDEOGRAPH, FALSE },
+
+ { -1, 0x401, 0 }, /* version break for Unicode 4.0.1 */
+
+ { 0x002e, UCHAR_S_TERM, TRUE },
+ { 0x0061, UCHAR_S_TERM, FALSE },
+
+ { 0x180c, UCHAR_VARIATION_SELECTOR, TRUE },
+ { 0xfe03, UCHAR_VARIATION_SELECTOR, TRUE },
+ { 0xe01ef, UCHAR_VARIATION_SELECTOR, TRUE },
+ { 0xe0200, UCHAR_VARIATION_SELECTOR, FALSE },
+
+ /* enum/integer type properties */
+
+ /* UCHAR_BIDI_CLASS tested for assigned characters in TestUnicodeData() */
+ /* test default Bidi classes for unassigned code points */
+ { 0x0590, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x05cf, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x05ed, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x07f2, UCHAR_BIDI_CLASS, U_DIR_NON_SPACING_MARK }, /* Nko, new in Unicode 5.0 */
+ { 0x07fe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT }, /* unassigned R */
+ { 0x08ba, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0xfb37, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0xfb42, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x10806, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x10909, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+ { 0x10fe4, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT },
+
+ { 0x0606, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x061c, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x063f, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x070e, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0x0775, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0xfbc2, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0xfd90, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+ { 0xfefe, UCHAR_BIDI_CLASS, U_RIGHT_TO_LEFT_ARABIC },
+
+ { 0x02AF, UCHAR_BLOCK, UBLOCK_IPA_EXTENSIONS },
+ { 0x0C4E, UCHAR_BLOCK, UBLOCK_TELUGU },
+ { 0x155A, UCHAR_BLOCK, UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS },
+ { 0x1717, UCHAR_BLOCK, UBLOCK_TAGALOG },
+ { 0x1900, UCHAR_BLOCK, UBLOCK_LIMBU },
+ { 0x1AFF, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
+ { 0x3040, UCHAR_BLOCK, UBLOCK_HIRAGANA },
+ { 0x1D0FF, UCHAR_BLOCK, UBLOCK_BYZANTINE_MUSICAL_SYMBOLS },
+ { 0x50000, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
+ { 0xEFFFF, UCHAR_BLOCK, UBLOCK_NO_BLOCK },
+ { 0x10D0FF, UCHAR_BLOCK, UBLOCK_SUPPLEMENTARY_PRIVATE_USE_AREA_B },
+
+ /* UCHAR_CANONICAL_COMBINING_CLASS tested for assigned characters in TestUnicodeData() */
+ { 0xd7d7, UCHAR_CANONICAL_COMBINING_CLASS, 0 },
+
+ { 0x00A0, UCHAR_DECOMPOSITION_TYPE, U_DT_NOBREAK },
+ { 0x00A8, UCHAR_DECOMPOSITION_TYPE, U_DT_COMPAT },
+ { 0x00bf, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE },
+ { 0x00c0, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
+ { 0x1E9B, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
+ { 0xBCDE, UCHAR_DECOMPOSITION_TYPE, U_DT_CANONICAL },
+ { 0xFB5D, UCHAR_DECOMPOSITION_TYPE, U_DT_MEDIAL },
+ { 0x1D736, UCHAR_DECOMPOSITION_TYPE, U_DT_FONT },
+ { 0xe0033, UCHAR_DECOMPOSITION_TYPE, U_DT_NONE },
+
+ { 0x0009, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
+ { 0x0020, UCHAR_EAST_ASIAN_WIDTH, U_EA_NARROW },
+ { 0x00B1, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
+ { 0x20A9, UCHAR_EAST_ASIAN_WIDTH, U_EA_HALFWIDTH },
+ { 0x2FFB, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0x3000, UCHAR_EAST_ASIAN_WIDTH, U_EA_FULLWIDTH },
+ { 0x35bb, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0x58bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0xD7A3, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0xEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
+ { 0x1D198, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
+ { 0x20000, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0x2F8C7, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE },
+ { 0x3a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_WIDE }, /* plane 3 got default W values in Unicode 4 */
+ { 0x5a5bd, UCHAR_EAST_ASIAN_WIDTH, U_EA_NEUTRAL },
+ { 0xFEEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
+ { 0x10EEEE, UCHAR_EAST_ASIAN_WIDTH, U_EA_AMBIGUOUS },
+
+ /* UCHAR_GENERAL_CATEGORY tested for assigned characters in TestUnicodeData() */
+ { 0xd7d7, UCHAR_GENERAL_CATEGORY, 0 },
+
+ { 0x0444, UCHAR_JOINING_GROUP, U_JG_NO_JOINING_GROUP },
+ { 0x0639, UCHAR_JOINING_GROUP, U_JG_AIN },
+ { 0x072A, UCHAR_JOINING_GROUP, U_JG_DALATH_RISH },
+ { 0x0647, UCHAR_JOINING_GROUP, U_JG_HEH },
+ { 0x06C1, UCHAR_JOINING_GROUP, U_JG_HEH_GOAL },
+ { 0x06C3, UCHAR_JOINING_GROUP, U_JG_HAMZA_ON_HEH_GOAL },
+
+ { 0x200C, UCHAR_JOINING_TYPE, U_JT_NON_JOINING },
+ { 0x200D, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING },
+ { 0x0639, UCHAR_JOINING_TYPE, U_JT_DUAL_JOINING },
+ { 0x0640, UCHAR_JOINING_TYPE, U_JT_JOIN_CAUSING },
+ { 0x06C3, UCHAR_JOINING_TYPE, U_JT_RIGHT_JOINING },
+ { 0x0300, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
+ { 0x070F, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
+ { 0xe0033, UCHAR_JOINING_TYPE, U_JT_TRANSPARENT },
+
+ /* TestUnicodeData() verifies that no assigned character has "XX" (unknown) */
+ { 0xe7e7, UCHAR_LINE_BREAK, U_LB_UNKNOWN },
+ { 0x10fffd, UCHAR_LINE_BREAK, U_LB_UNKNOWN },
+ { 0x0028, UCHAR_LINE_BREAK, U_LB_OPEN_PUNCTUATION },
+ { 0x232A, UCHAR_LINE_BREAK, U_LB_CLOSE_PUNCTUATION },
+ { 0x3401, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
+ { 0x4e02, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
+ { 0x20004, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
+ { 0xf905, UCHAR_LINE_BREAK, U_LB_IDEOGRAPHIC },
+ { 0xdb7e, UCHAR_LINE_BREAK, U_LB_SURROGATE },
+ { 0xdbfd, UCHAR_LINE_BREAK, U_LB_SURROGATE },
+ { 0xdffc, UCHAR_LINE_BREAK, U_LB_SURROGATE },
+ { 0x2762, UCHAR_LINE_BREAK, U_LB_EXCLAMATION },
+ { 0x002F, UCHAR_LINE_BREAK, U_LB_BREAK_SYMBOLS },
+ { 0x1D49C, UCHAR_LINE_BREAK, U_LB_ALPHABETIC },
+ { 0x1731, UCHAR_LINE_BREAK, U_LB_ALPHABETIC },
+
+ /* UCHAR_NUMERIC_TYPE tested in TestNumericProperties() */
+
+ /* UCHAR_SCRIPT tested in TestUScriptCodeAPI() */
+
+ { 0x1100, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
+ { 0x1111, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
+ { 0x1159, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
+ { 0x115f, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LEADING_JAMO },
+
+ { 0x1160, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
+ { 0x1161, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
+ { 0x1172, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
+ { 0x11a2, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_VOWEL_JAMO },
+
+ { 0x11a8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
+ { 0x11b8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
+ { 0x11c8, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
+ { 0x11f9, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_TRAILING_JAMO },
+
+ { 0x115a, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+ { 0x115e, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+ { 0x11a3, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+ { 0x11a7, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+ { 0x11fa, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+ { 0x11ff, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+
+ { 0xac00, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
+ { 0xac1c, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
+ { 0xc5ec, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
+ { 0xd788, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LV_SYLLABLE },
+
+ { 0xac01, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
+ { 0xac1b, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
+ { 0xac1d, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
+ { 0xc5ee, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
+ { 0xd7a3, UCHAR_HANGUL_SYLLABLE_TYPE, U_HST_LVT_SYLLABLE },
+
+ { 0xd7a4, UCHAR_HANGUL_SYLLABLE_TYPE, 0 },
+
+ { -1, 0x410, 0 }, /* version break for Unicode 4.1 */
+
+ { 0x00d7, UCHAR_PATTERN_SYNTAX, TRUE },
+ { 0xfe45, UCHAR_PATTERN_SYNTAX, TRUE },
+ { 0x0061, UCHAR_PATTERN_SYNTAX, FALSE },
+
+ { 0x0020, UCHAR_PATTERN_WHITE_SPACE, TRUE },
+ { 0x0085, UCHAR_PATTERN_WHITE_SPACE, TRUE },
+ { 0x200f, UCHAR_PATTERN_WHITE_SPACE, TRUE },
+ { 0x00a0, UCHAR_PATTERN_WHITE_SPACE, FALSE },
+ { 0x3000, UCHAR_PATTERN_WHITE_SPACE, FALSE },
+
+ { 0x1d200, UCHAR_BLOCK, UBLOCK_ANCIENT_GREEK_MUSICAL_NOTATION },
+ { 0x2c8e, UCHAR_BLOCK, UBLOCK_COPTIC },
+ { 0xfe17, UCHAR_BLOCK, UBLOCK_VERTICAL_FORMS },
+
+ { 0x1a00, UCHAR_SCRIPT, USCRIPT_BUGINESE },
+ { 0x2cea, UCHAR_SCRIPT, USCRIPT_COPTIC },
+ { 0xa82b, UCHAR_SCRIPT, USCRIPT_SYLOTI_NAGRI },
+ { 0x103d0, UCHAR_SCRIPT, USCRIPT_OLD_PERSIAN },
+
+ { 0xcc28, UCHAR_LINE_BREAK, U_LB_H2 },
+ { 0xcc29, UCHAR_LINE_BREAK, U_LB_H3 },
+ { 0xac03, UCHAR_LINE_BREAK, U_LB_H3 },
+ { 0x115f, UCHAR_LINE_BREAK, U_LB_JL },
+ { 0x11aa, UCHAR_LINE_BREAK, U_LB_JT },
+ { 0x11a1, UCHAR_LINE_BREAK, U_LB_JV },
+
+ { 0xb2c9, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_LVT },
+ { 0x036f, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_EXTEND },
+ { 0x0000, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_CONTROL },
+ { 0x1160, UCHAR_GRAPHEME_CLUSTER_BREAK, U_GCB_V },
+
+ { 0x05f4, UCHAR_WORD_BREAK, U_WB_MIDLETTER },
+ { 0x4ef0, UCHAR_WORD_BREAK, U_WB_OTHER },
+ { 0x19d9, UCHAR_WORD_BREAK, U_WB_NUMERIC },
+ { 0x2044, UCHAR_WORD_BREAK, U_WB_MIDNUM },
+
+ { 0xfffd, UCHAR_SENTENCE_BREAK, U_SB_OTHER },
+ { 0x1ffc, UCHAR_SENTENCE_BREAK, U_SB_UPPER },
+ { 0xff63, UCHAR_SENTENCE_BREAK, U_SB_CLOSE },
+ { 0x2028, UCHAR_SENTENCE_BREAK, U_SB_SEP },
+
+ /* undefined UProperty values */
+ { 0x61, 0x4a7, 0 },
+ { 0x234bc, 0x15ed, 0 }
+ };
+
+ UVersionInfo version;
+ UChar32 c;
+ int32_t i, result, uVersion;
+ UProperty which;
+
+ /* what is our Unicode version? */
+ u_getUnicodeVersion(version);
+ uVersion=((int32_t)version[0]<<8)|(version[1]<<4)|version[2]; /* major/minor/update version numbers */
+
+ u_charAge(0x20, version);
+ if(version[0]==0) {
+ /* no additional properties available */
+ log_err("TestAdditionalProperties: no additional properties available, not tested\n");
+ return;
+ }
+
+ /* test u_charAge() */
+ for(i=0; i<sizeof(charAges)/sizeof(charAges[0]); ++i) {
+ u_charAge(charAges[i].c, version);
+ if(0!=memcmp(version, charAges[i].version, sizeof(UVersionInfo))) {
+ log_err("error: u_charAge(U+%04lx)={ %u, %u, %u, %u } instead of { %u, %u, %u, %u }\n",
+ charAges[i].c,
+ version[0], version[1], version[2], version[3],
+ charAges[i].version[0], charAges[i].version[1], charAges[i].version[2], charAges[i].version[3]);
+ }
+ }
+
+ if( u_getIntPropertyMinValue(UCHAR_DASH)!=0 ||
+ u_getIntPropertyMinValue(UCHAR_BIDI_CLASS)!=0 ||
+ u_getIntPropertyMinValue(UCHAR_BLOCK)!=0 || /* j2478 */
+ u_getIntPropertyMinValue(UCHAR_SCRIPT)!=0 || /*JB#2410*/
+ u_getIntPropertyMinValue(0x2345)!=0
+ ) {
+ log_err("error: u_getIntPropertyMinValue() wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_DASH)!=1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_DASH) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE)!=1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_ID_CONTINUE) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue((UProperty)(UCHAR_BINARY_LIMIT-1))!=1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_BINARY_LIMIT-1) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)!=(int32_t)U_CHAR_DIRECTION_COUNT-1 ) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_BLOCK)!=(int32_t)UBLOCK_COUNT-1 ) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_BLOCK) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_LINE_BREAK)!=(int32_t)U_LB_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_LINE_BREAK) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_SCRIPT)!=(int32_t)USCRIPT_CODE_LIMIT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_SCRIPT) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE)!=(int32_t)U_NT_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_NUMERIC_TYPE) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY)!=(int32_t)U_CHAR_CATEGORY_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE)!=(int32_t)U_HST_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_HANGUL_SYLLABLE_TYPE) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK)!=(int32_t)U_GCB_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_GRAPHEME_CLUSTER_BREAK) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK)!=(int32_t)U_SB_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_SENTENCE_BREAK) wrong\n");
+ }
+ if(u_getIntPropertyMaxValue(UCHAR_WORD_BREAK)!=(int32_t)U_WB_COUNT-1) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_WORD_BREAK) wrong\n");
+ }
+ /*JB#2410*/
+ if( u_getIntPropertyMaxValue(0x2345)!=-1) {
+ log_err("error: u_getIntPropertyMaxValue(0x2345) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) != (int32_t) (U_DT_COUNT - 1)) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_DECOMPOSITION_TYPE) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) != (int32_t) (U_JG_COUNT -1)) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_GROUP) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) != (int32_t) (U_JT_COUNT -1)) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_JOINING_TYPE) wrong\n");
+ }
+ if( u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) != (int32_t) (U_EA_COUNT -1)) {
+ log_err("error: u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH) wrong\n");
+ }
+
+ /* test u_hasBinaryProperty() and u_getIntPropertyValue() */
+ for(i=0; i<sizeof(props)/sizeof(props[0]); ++i) {
+ if(props[i][0]<0) {
+ /* Unicode version break */
+ if(uVersion<props[i][1]) {
+ break; /* do not test properties that are not yet supported */
+ } else {
+ continue; /* skip this row */
+ }
+ }
+
+ c=(UChar32)props[i][0];
+ which=(UProperty)props[i][1];
+
+ if(which<UCHAR_INT_START) {
+ result=u_hasBinaryProperty(c, which);
+ if(result!=props[i][2]) {
+ log_err("error: u_hasBinaryProperty(U+%04lx, %d)=%d is wrong (props[%d])\n",
+ c, which, result, i);
+ }
+ }
+
+ result=u_getIntPropertyValue(c, which);
+ if(result!=props[i][2]) {
+ log_err("error: u_getIntPropertyValue(U+%04lx, 0x1000+%d)=%d is wrong, should be %d (props[%d])\n",
+ c, (int32_t)which-0x1000, result, props[i][2], i);
+ }
+
+ /* test separate functions, too */
+ switch((UProperty)props[i][1]) {
+ case UCHAR_ALPHABETIC:
+ if(u_isUAlphabetic((UChar32)props[i][0])!=(UBool)props[i][2]) {
+ log_err("error: u_isUAlphabetic(U+%04lx)=%d is wrong (props[%d])\n",
+ props[i][0], result, i);
+ }
+ break;
+ case UCHAR_LOWERCASE:
+ if(u_isULowercase((UChar32)props[i][0])!=(UBool)props[i][2]) {
+ log_err("error: u_isULowercase(U+%04lx)=%d is wrong (props[%d])\n",
+ props[i][0], result, i);
+ }
+ break;
+ case UCHAR_UPPERCASE:
+ if(u_isUUppercase((UChar32)props[i][0])!=(UBool)props[i][2]) {
+ log_err("error: u_isUUppercase(U+%04lx)=%d is wrong (props[%d])\n",
+ props[i][0], result, i);
+ }
+ break;
+ case UCHAR_WHITE_SPACE:
+ if(u_isUWhiteSpace((UChar32)props[i][0])!=(UBool)props[i][2]) {
+ log_err("error: u_isUWhiteSpace(U+%04lx)=%d is wrong (props[%d])\n",
+ props[i][0], result, i);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+TestNumericProperties(void) {
+ /* see UnicodeData.txt, DerivedNumericValues.txt */
+ static const struct {
+ UChar32 c;
+ int32_t type;
+ double numValue;
+ } values[]={
+ { 0x0F33, U_NT_NUMERIC, -1./2. },
+ { 0x0C66, U_NT_DECIMAL, 0 },
+ { 0x96f6, U_NT_NUMERIC, 0 },
+ { 0x2159, U_NT_NUMERIC, 1./6. },
+ { 0x00BD, U_NT_NUMERIC, 1./2. },
+ { 0x0031, U_NT_DECIMAL, 1. },
+ { 0x4e00, U_NT_NUMERIC, 1. },
+ { 0x58f1, U_NT_NUMERIC, 1. },
+ { 0x10320, U_NT_NUMERIC, 1. },
+ { 0x0F2B, U_NT_NUMERIC, 3./2. },
+ { 0x00B2, U_NT_DIGIT, 2. },
+ { 0x5f10, U_NT_NUMERIC, 2. },
+ { 0x1813, U_NT_DECIMAL, 3. },
+ { 0x5f0e, U_NT_NUMERIC, 3. },
+ { 0x2173, U_NT_NUMERIC, 4. },
+ { 0x8086, U_NT_NUMERIC, 4. },
+ { 0x278E, U_NT_DIGIT, 5. },
+ { 0x1D7F2, U_NT_DECIMAL, 6. },
+ { 0x247A, U_NT_DIGIT, 7. },
+ { 0x7396, U_NT_NUMERIC, 9. },
+ { 0x1372, U_NT_NUMERIC, 10. },
+ { 0x216B, U_NT_NUMERIC, 12. },
+ { 0x16EE, U_NT_NUMERIC, 17. },
+ { 0x249A, U_NT_NUMERIC, 19. },
+ { 0x303A, U_NT_NUMERIC, 30. },
+ { 0x5345, U_NT_NUMERIC, 30. },
+ { 0x32B2, U_NT_NUMERIC, 37. },
+ { 0x1375, U_NT_NUMERIC, 40. },
+ { 0x10323, U_NT_NUMERIC, 50. },
+ { 0x0BF1, U_NT_NUMERIC, 100. },
+ { 0x964c, U_NT_NUMERIC, 100. },
+ { 0x217E, U_NT_NUMERIC, 500. },
+ { 0x2180, U_NT_NUMERIC, 1000. },
+ { 0x4edf, U_NT_NUMERIC, 1000. },
+ { 0x2181, U_NT_NUMERIC, 5000. },
+ { 0x137C, U_NT_NUMERIC, 10000. },
+ { 0x4e07, U_NT_NUMERIC, 10000. },
+ { 0x4ebf, U_NT_NUMERIC, 100000000. },
+ { 0x5146, U_NT_NUMERIC, 1000000000000. },
+ { 0x61, U_NT_NONE, U_NO_NUMERIC_VALUE },
+ { 0x3000, U_NT_NONE, U_NO_NUMERIC_VALUE },
+ { 0xfffe, U_NT_NONE, U_NO_NUMERIC_VALUE },
+ { 0x10301, U_NT_NONE, U_NO_NUMERIC_VALUE },
+ { 0xe0033, U_NT_NONE, U_NO_NUMERIC_VALUE },
+ { 0x10ffff, U_NT_NONE, U_NO_NUMERIC_VALUE }
+ };
+
+ double nv;
+ UChar32 c;
+ int32_t i, type;
+
+ for(i=0; i<LENGTHOF(values); ++i) {
+ c=values[i].c;
+ type=u_getIntPropertyValue(c, UCHAR_NUMERIC_TYPE);
+ nv=u_getNumericValue(c);
+
+ if(type!=values[i].type) {
+ log_err("UCHAR_NUMERIC_TYPE(U+%04lx)=%d should be %d\n", c, type, values[i].type);
+ }
+ if(0.000001 <= fabs(nv - values[i].numValue)) {
+ log_err("u_getNumericValue(U+%04lx)=%g should be %g\n", c, nv, values[i].numValue);
+ }
+ }
+}
+
+/**
+ * Test the property names and property value names API.
+ */
+static void
+TestPropertyNames(void) {
+ int32_t p, v, choice=0, rev;
+ UBool atLeastSomething = FALSE;
+
+ for (p=0; ; ++p) {
+ UProperty propEnum = (UProperty)p;
+ UBool sawProp = FALSE;
+ if(p > 10 && !atLeastSomething) {
+ log_data_err("Never got anything after 10 tries.\nYour data is probably fried. Quitting this test\n", p, choice);
+ return;
+ }
+
+ for (choice=0; ; ++choice) {
+ const char* name = u_getPropertyName(propEnum, (UPropertyNameChoice)choice);
+ if (name) {
+ if (!sawProp)
+ log_verbose("prop 0x%04x+%2d:", p&~0xfff, p&0xfff);
+ log_verbose("%d=\"%s\"", choice, name);
+ sawProp = TRUE;
+ atLeastSomething = TRUE;
+
+ /* test reverse mapping */
+ rev = u_getPropertyEnum(name);
+ if (rev != p) {
+ log_err("Property round-trip failure: %d -> %s -> %d\n",
+ p, name, rev);
+ }
+ }
+ if (!name && choice>0) break;
+ }
+ if (sawProp) {
+ /* looks like a valid property; check the values */
+ const char* pname = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME);
+ int32_t max = 0;
+ if (p == UCHAR_CANONICAL_COMBINING_CLASS) {
+ max = 255;
+ } else if (p == UCHAR_GENERAL_CATEGORY_MASK) {
+ /* it's far too slow to iterate all the way up to
+ the real max, U_GC_P_MASK */
+ max = U_GC_NL_MASK;
+ } else if (p == UCHAR_BLOCK) {
+ /* UBlockCodes, unlike other values, start at 1 */
+ max = 1;
+ }
+ log_verbose("\n");
+ for (v=-1; ; ++v) {
+ UBool sawValue = FALSE;
+ for (choice=0; ; ++choice) {
+ const char* vname = u_getPropertyValueName(propEnum, v, (UPropertyNameChoice)choice);
+ if (vname) {
+ if (!sawValue) log_verbose(" %s, value %d:", pname, v);
+ log_verbose("%d=\"%s\"", choice, vname);
+ sawValue = TRUE;
+
+ /* test reverse mapping */
+ rev = u_getPropertyValueEnum(p, vname);
+ if (rev != v) {
+ log_err("Value round-trip failure (%s): %d -> %s -> %d\n",
+ pname, v, vname, rev);
+ }
+ }
+ if (!vname && choice>0) break;
+ }
+ if (sawValue) {
+ log_verbose("\n");
+ }
+ if (!sawValue && v>=max) break;
+ }
+ }
+ if (!sawProp) {
+ if (p>=UCHAR_STRING_LIMIT) {
+ break;
+ } else if (p>=UCHAR_DOUBLE_LIMIT) {
+ p = UCHAR_STRING_START - 1;
+ } else if (p>=UCHAR_MASK_LIMIT) {
+ p = UCHAR_DOUBLE_START - 1;
+ } else if (p>=UCHAR_INT_LIMIT) {
+ p = UCHAR_MASK_START - 1;
+ } else if (p>=UCHAR_BINARY_LIMIT) {
+ p = UCHAR_INT_START - 1;
+ }
+ }
+ }
+}
+
+/**
+ * Test the property values API. See JB#2410.
+ */
+static void
+TestPropertyValues(void) {
+ int32_t i, p, min, max;
+ UErrorCode ec;
+
+ /* Min should be 0 for everything. */
+ /* Until JB#2478 is fixed, the one exception is UCHAR_BLOCK. */
+ for (p=UCHAR_INT_START; p<UCHAR_INT_LIMIT; ++p) {
+ UProperty propEnum = (UProperty)p;
+ min = u_getIntPropertyMinValue(propEnum);
+ if (min != 0) {
+ if (p == UCHAR_BLOCK) {
+ /* This is okay...for now. See JB#2487.
+ TODO Update this for JB#2487. */
+ } else {
+ const char* name;
+ name = u_getPropertyName(propEnum, U_LONG_PROPERTY_NAME);
+ if (name == NULL)
+ name = "<ERROR>";
+ log_err("FAIL: u_getIntPropertyMinValue(%s) = %d, exp. 0\n",
+ name, min);
+ }
+ }
+ }
+
+ if( u_getIntPropertyMinValue(UCHAR_GENERAL_CATEGORY_MASK)!=0 ||
+ u_getIntPropertyMaxValue(UCHAR_GENERAL_CATEGORY_MASK)!=-1) {
+ log_err("error: u_getIntPropertyMin/MaxValue(UCHAR_GENERAL_CATEGORY_MASK) is wrong\n");
+ }
+
+ /* Max should be -1 for invalid properties. */
+ max = u_getIntPropertyMaxValue(UCHAR_INVALID_CODE);
+ if (max != -1) {
+ log_err("FAIL: u_getIntPropertyMaxValue(-1) = %d, exp. -1\n",
+ max);
+ }
+
+ /* Script should return USCRIPT_INVALID_CODE for an invalid code point. */
+ for (i=0; i<2; ++i) {
+ int32_t script;
+ const char* desc;
+ ec = U_ZERO_ERROR;
+ switch (i) {
+ case 0:
+ script = uscript_getScript(-1, &ec);
+ desc = "uscript_getScript(-1)";
+ break;
+ case 1:
+ script = u_getIntPropertyValue(-1, UCHAR_SCRIPT);
+ desc = "u_getIntPropertyValue(-1, UCHAR_SCRIPT)";
+ break;
+ default:
+ log_err("Internal test error. Too many scripts\n");
+ return;
+ }
+ /* We don't explicitly test ec. It should be U_FAILURE but it
+ isn't documented as such. */
+ if (script != (int32_t)USCRIPT_INVALID_CODE) {
+ log_err("FAIL: %s = %d, exp. 0\n",
+ desc, script);
+ }
+ }
+}
+
+/* add characters from a serialized set to a normal one */
+static void
+_setAddSerialized(USet *set, const USerializedSet *sset) {
+ UChar32 start, end;
+ int32_t i, count;
+
+ count=uset_getSerializedRangeCount(sset);
+ for(i=0; i<count; ++i) {
+ uset_getSerializedRange(sset, i, &start, &end);
+ uset_addRange(set, start, end);
+ }
+}
+
+/* various tests for consistency of UCD data and API behavior */
+static void
+TestConsistency() {
+#if !UCONFIG_NO_NORMALIZATION
+ UChar buffer16[300];
+#endif
+ char buffer[300];
+ USet *set1, *set2, *set3, *set4;
+ UErrorCode errorCode;
+
+#if !UCONFIG_NO_NORMALIZATION
+ USerializedSet sset;
+#endif
+ UChar32 start, end;
+ int32_t i, length;
+
+ U_STRING_DECL(hyphenPattern, "[:Hyphen:]", 10);
+ U_STRING_DECL(dashPattern, "[:Dash:]", 8);
+ U_STRING_DECL(lowerPattern, "[:Lowercase:]", 13);
+ U_STRING_DECL(formatPattern, "[:Cf:]", 6);
+ U_STRING_DECL(alphaPattern, "[:Alphabetic:]", 14);
+
+ U_STRING_DECL(mathBlocksPattern,
+ "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]",
+ 1+32+46+46+45+43+1+1); /* +1 for NUL */
+ U_STRING_DECL(mathPattern, "[:Math:]", 8);
+ U_STRING_DECL(unassignedPattern, "[:Cn:]", 6);
+ U_STRING_DECL(unknownPattern, "[:sc=Unknown:]", 14);
+ U_STRING_DECL(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20);
+
+ U_STRING_INIT(hyphenPattern, "[:Hyphen:]", 10);
+ U_STRING_INIT(dashPattern, "[:Dash:]", 8);
+ U_STRING_INIT(lowerPattern, "[:Lowercase:]", 13);
+ U_STRING_INIT(formatPattern, "[:Cf:]", 6);
+ U_STRING_INIT(alphaPattern, "[:Alphabetic:]", 14);
+
+ U_STRING_INIT(mathBlocksPattern,
+ "[[:block=Mathematical Operators:][:block=Miscellaneous Mathematical Symbols-A:][:block=Miscellaneous Mathematical Symbols-B:][:block=Supplemental Mathematical Operators:][:block=Mathematical Alphanumeric Symbols:]]",
+ 1+32+46+46+45+43+1+1); /* +1 for NUL */
+ U_STRING_INIT(mathPattern, "[:Math:]", 8);
+ U_STRING_INIT(unassignedPattern, "[:Cn:]", 6);
+ U_STRING_INIT(unknownPattern, "[:sc=Unknown:]", 14);
+ U_STRING_INIT(reservedPattern, "[[:Cn:][:Co:][:Cs:]]", 20);
+
+ /*
+ * It used to be that UCD.html and its precursors said
+ * "Those dashes used to mark connections between pieces of words,
+ * plus the Katakana middle dot."
+ *
+ * Unicode 4 changed 00AD Soft Hyphen to Cf and removed it from Dash
+ * but not from Hyphen.
+ * UTC 94 (2003mar) decided to leave it that way and to changed UCD.html.
+ * Therefore, do not show errors when testing the Hyphen property.
+ */
+ log_verbose("Starting with Unicode 4, inconsistencies with [:Hyphen:] are\n"
+ "known to the UTC and not considered errors.\n");
+
+ errorCode=U_ZERO_ERROR;
+ set1=uset_openPattern(hyphenPattern, 10, &errorCode);
+ set2=uset_openPattern(dashPattern, 8, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ /* remove the Katakana middle dot(s) from set1 */
+ uset_remove(set1, 0x30fb);
+ uset_remove(set1, 0xff65); /* halfwidth variant */
+ showAMinusB(set1, set2, "[:Hyphen:]", "[:Dash:]", FALSE);
+ } else {
+ log_err("error opening [:Hyphen:] or [:Dash:] - %s\n", u_errorName(errorCode));
+ }
+
+ /* check that Cf is neither Hyphen nor Dash nor Alphabetic */
+ set3=uset_openPattern(formatPattern, 6, &errorCode);
+ set4=uset_openPattern(alphaPattern, 14, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ showAIntersectB(set3, set1, "[:Cf:]", "[:Hyphen:]", FALSE);
+ showAIntersectB(set3, set2, "[:Cf:]", "[:Dash:]", TRUE);
+ showAIntersectB(set3, set4, "[:Cf:]", "[:Alphabetic:]", TRUE);
+ } else {
+ log_err("error opening [:Cf:] or [:Alpbabetic:] - %s\n", u_errorName(errorCode));
+ }
+
+ uset_close(set1);
+ uset_close(set2);
+ uset_close(set3);
+ uset_close(set4);
+
+ /*
+ * Check that each lowercase character has "small" in its name
+ * and not "capital".
+ * There are some such characters, some of which seem odd.
+ * Use the verbose flag to see these notices.
+ */
+ errorCode=U_ZERO_ERROR;
+ set1=uset_openPattern(lowerPattern, 13, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ for(i=0;; ++i) {
+ length=uset_getItem(set1, i, &start, &end, NULL, 0, &errorCode);
+ if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
+ break; /* done */
+ }
+ if(U_FAILURE(errorCode)) {
+ log_err("error iterating over [:Lowercase:] at item %d: %s\n",
+ i, u_errorName(errorCode));
+ break;
+ }
+ if(length!=0) {
+ break; /* done with code points, got a string or -1 */
+ }
+
+ while(start<=end) {
+ length=u_charName(start, U_UNICODE_CHAR_NAME, buffer, sizeof(buffer), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error getting the name of U+%04x - %s\n", start, u_errorName(errorCode));
+ errorCode=U_ZERO_ERROR;
+ continue;
+ }
+ if( (strstr(buffer, "SMALL")==NULL || strstr(buffer, "CAPITAL")!=NULL) &&
+ strstr(buffer, "SMALL CAPITAL")==NULL
+ ) {
+ log_verbose("info: [:Lowercase:] contains U+%04x whose name does not suggest lowercase: %s\n", start, buffer);
+ }
+ ++start;
+ }
+ }
+ } else {
+ log_err("error opening [:Lowercase:] - %s\n", u_errorName(errorCode));
+ }
+ uset_close(set1);
+
+#if !UCONFIG_NO_NORMALIZATION
+
+ /*
+ * Test for an example that unorm_getCanonStartSet() delivers
+ * all characters that compose from the input one,
+ * even in multiple steps.
+ * For example, the set for "I" (0049) should contain both
+ * I-diaeresis (00CF) and I-diaeresis-acute (1E2E).
+ * In general, the set for the middle such character should be a subset
+ * of the set for the first.
+ */
+ set1=uset_open(1, 0);
+ set2=uset_open(1, 0);
+
+ if (unorm_getCanonStartSet(0x49, &sset)) {
+ _setAddSerialized(set1, &sset);
+
+ /* enumerate all characters that are plausible to be latin letters */
+ for(start=0xa0; start<0x2000; ++start) {
+ if(unorm_getDecomposition(start, FALSE, buffer16, LENGTHOF(buffer16))>1 && buffer16[0]==0x49) {
+ uset_add(set2, start);
+ }
+ }
+
+ compareUSets(set1, set2,
+ "[canon start set of 0049]", "[all c with canon decomp with 0049]",
+ TRUE);
+ } else {
+ log_err("error calling unorm_getCanonStartSet()\n");
+ }
+
+ uset_close(set1);
+ uset_close(set2);
+
+#endif
+
+ /* verify that all assigned characters in Math blocks are exactly Math characters */
+ errorCode=U_ZERO_ERROR;
+ set1=uset_openPattern(mathBlocksPattern, -1, &errorCode);
+ set2=uset_openPattern(mathPattern, 8, &errorCode);
+ set3=uset_openPattern(unassignedPattern, 6, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ uset_retainAll(set2, set1); /* [math blocks]&[:Math:] */
+ uset_complement(set3); /* assigned characters */
+ uset_retainAll(set1, set3); /* [math blocks]&[assigned] */
+ compareUSets(set1, set2,
+ "[assigned Math block chars]", "[math blocks]&[:Math:]",
+ TRUE);
+ } else {
+ log_err("error opening [math blocks] or [:Math:] or [:Cn:] - %s\n", u_errorName(errorCode));
+ }
+ uset_close(set1);
+ uset_close(set2);
+ uset_close(set3);
+
+ /* new in Unicode 5.0: exactly all unassigned+PUA+surrogate code points have script=Unknown */
+ errorCode=U_ZERO_ERROR;
+ set1=uset_openPattern(unknownPattern, 14, &errorCode);
+ set2=uset_openPattern(reservedPattern, 20, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ compareUSets(set1, set2,
+ "[:sc=Unknown:]", "[[:Cn:][:Co:][:Cs:]]",
+ TRUE);
+ } else {
+ log_err("error opening [:sc=Unknown:] or [[:Cn:][:Co:][:Cs:]] - %s\n", u_errorName(errorCode));
+ }
+ uset_close(set1);
+ uset_close(set2);
+}
+
+/*
+ * Starting with ICU4C 3.4, the core Unicode properties files
+ * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu)
+ * are hardcoded in the common DLL and therefore not included
+ * in the data package any more.
+ * Test requiring these files are disabled so that
+ * we need not jump through hoops (like adding snapshots of these files
+ * to testdata).
+ * See Jitterbug 4497.
+ */
+#define HARDCODED_DATA_4497 1
+
+/* API coverage for ucase.c */
+static void TestUCase() {
+#if !HARDCODED_DATA_4497
+ UDataMemory *pData;
+ UCaseProps *csp;
+#endif
+ const UCaseProps *ccsp;
+ UErrorCode errorCode;
+
+#if !HARDCODED_DATA_4497
+ /* coverage for ucase_openBinary() */
+ errorCode=U_ZERO_ERROR;
+ pData=udata_open(NULL, UCASE_DATA_TYPE, UCASE_DATA_NAME, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("unable to open " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n",
+ u_errorName(errorCode));
+ return;
+ }
+
+ csp=ucase_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucase_openBinary() fails for the contents of " UCASE_DATA_NAME "." UCASE_DATA_TYPE ": %s\n",
+ u_errorName(errorCode));
+ udata_close(pData);
+ return;
+ }
+
+ if(UCASE_LOWER!=ucase_getType(csp, 0xdf)) { /* verify islower(sharp s) */
+ log_err("ucase_openBinary() does not seem to return working UCaseProps\n");
+ }
+
+ ucase_close(csp);
+ udata_close(pData);
+#endif
+
+ /* coverage for ucase_getDummy() */
+ errorCode=U_ZERO_ERROR;
+ ccsp=ucase_getDummy(&errorCode);
+ if(ucase_tolower(ccsp, 0x41)!=0x41) {
+ log_err("ucase_tolower(dummy, A)!=A\n");
+ }
+}
+
+/* API coverage for ubidi_props.c */
+static void TestUBiDiProps() {
+#if !HARDCODED_DATA_4497
+ UDataMemory *pData;
+ UBiDiProps *bdp;
+#endif
+ const UBiDiProps *cbdp;
+ UErrorCode errorCode;
+
+#if !HARDCODED_DATA_4497
+ /* coverage for ubidi_openBinary() */
+ errorCode=U_ZERO_ERROR;
+ pData=udata_open(NULL, UBIDI_DATA_TYPE, UBIDI_DATA_NAME, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("unable to open " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n",
+ u_errorName(errorCode));
+ return;
+ }
+
+ bdp=ubidi_openBinary((const uint8_t *)pData->pHeader, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ubidi_openBinary() fails for the contents of " UBIDI_DATA_NAME "." UBIDI_DATA_TYPE ": %s\n",
+ u_errorName(errorCode));
+ udata_close(pData);
+ return;
+ }
+
+ if(0x2215!=ubidi_getMirror(bdp, 0x29F5)) { /* verify some data */
+ log_err("ubidi_openBinary() does not seem to return working UBiDiProps\n");
+ }
+
+ ubidi_closeProps(bdp);
+ udata_close(pData);
+#endif
+
+ /* coverage for ubidi_getDummy() */
+ errorCode=U_ZERO_ERROR;
+ cbdp=ubidi_getDummy(&errorCode);
+ if(ubidi_getClass(cbdp, 0x20)!=0) {
+ log_err("ubidi_getClass(dummy, space)!=0\n");
+ }
+}
+
+/* test case folding, compare return values with CaseFolding.txt ------------ */
+
+/* bit set for which case foldings for a character have been tested already */
+enum {
+ CF_SIMPLE=1,
+ CF_FULL=2,
+ CF_TURKIC=4,
+ CF_ALL=7
+};
+
+static void
+testFold(UChar32 c, int which,
+ UChar32 simple, UChar32 turkic,
+ const UChar *full, int32_t fullLength,
+ const UChar *turkicFull, int32_t turkicFullLength) {
+ UChar s[2], t[32];
+ UChar32 c2;
+ int32_t length, length2;
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ length=0;
+ U16_APPEND_UNSAFE(s, length, c);
+
+ if((which&CF_SIMPLE)!=0 && (c2=u_foldCase(c, 0))!=simple) {
+ log_err("u_foldCase(U+%04lx, default)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple);
+ }
+ if((which&CF_FULL)!=0) {
+ length2=u_strFoldCase(t, LENGTHOF(t), s, length, 0, &errorCode);
+ if(length2!=fullLength || 0!=u_memcmp(t, full, fullLength)) {
+ log_err("u_strFoldCase(U+%04lx, default) does not fold properly\n", (long)c);
+ }
+ }
+ if((which&CF_TURKIC)!=0) {
+ if((c2=u_foldCase(c, U_FOLD_CASE_EXCLUDE_SPECIAL_I))!=turkic) {
+ log_err("u_foldCase(U+%04lx, turkic)=U+%04lx != U+%04lx\n", (long)c, (long)c2, (long)simple);
+ }
+
+ length2=u_strFoldCase(t, LENGTHOF(t), s, length, U_FOLD_CASE_EXCLUDE_SPECIAL_I, &errorCode);
+ if(length2!=turkicFullLength || 0!=u_memcmp(t, turkicFull, length2)) {
+ log_err("u_strFoldCase(U+%04lx, turkic) does not fold properly\n", (long)c);
+ }
+ }
+}
+
+/* test that c case-folds to itself */
+static void
+testFoldToSelf(UChar32 c, int which) {
+ UChar s[2];
+ int32_t length;
+
+ length=0;
+ U16_APPEND_UNSAFE(s, length, c);
+ testFold(c, which, c, c, s, length, s, length);
+}
+
+struct CaseFoldingData {
+ USet *notSeen;
+ UChar32 prev, prevSimple;
+ UChar prevFull[32];
+ int32_t prevFullLength;
+ int which;
+};
+typedef struct CaseFoldingData CaseFoldingData;
+
+static void U_CALLCONV
+caseFoldingLineFn(void *context,
+ char *fields[][2], int32_t fieldCount,
+ UErrorCode *pErrorCode) {
+ CaseFoldingData *pData=(CaseFoldingData *)context;
+ char *end;
+ UChar full[32];
+ UChar32 c, prev, simple;
+ int32_t count;
+ int which;
+ char status;
+
+ /* get code point */
+ c=(UChar32)strtoul(u_skipWhitespace(fields[0][0]), &end, 16);
+ end=(char *)u_skipWhitespace(end);
+ if(end<=fields[0][0] || end!=fields[0][1]) {
+ log_err("syntax error in CaseFolding.txt field 0 at %s\n", fields[0][0]);
+ *pErrorCode=U_PARSE_ERROR;
+ return;
+ }
+
+ /* get the status of this mapping */
+ status=*u_skipWhitespace(fields[1][0]);
+ if(status!='C' && status!='S' && status!='F' && status!='T') {
+ log_err("unrecognized status field in CaseFolding.txt at %s\n", fields[0][0]);
+ *pErrorCode=U_PARSE_ERROR;
+ return;
+ }
+
+ /* get the mapping */
+ count=u_parseString(fields[2][0], full, 32, (uint32_t *)&simple, pErrorCode);
+ if(U_FAILURE(*pErrorCode)) {
+ log_err("error parsing CaseFolding.txt mapping at %s\n", fields[0][0]);
+ return;
+ }
+
+ /* there is a simple mapping only if there is exactly one code point (count is in UChars) */
+ if(count==0 || count>2 || (count==2 && U16_IS_SINGLE(full[1]))) {
+ simple=c;
+ }
+
+ if(c!=(prev=pData->prev)) {
+ /*
+ * Test remaining mappings for the previous code point.
+ * If a turkic folding was not mentioned, then it should fold the same
+ * as the regular simple case folding.
+ */
+ UChar s[2];
+ int32_t length;
+
+ length=0;
+ U16_APPEND_UNSAFE(s, length, prev);
+ testFold(prev, (~pData->which)&CF_ALL,
+ prev, pData->prevSimple,
+ s, length,
+ pData->prevFull, pData->prevFullLength);
+ pData->prev=pData->prevSimple=c;
+ length=0;
+ U16_APPEND_UNSAFE(pData->prevFull, length, c);
+ pData->prevFullLength=length;
+ pData->which=0;
+ }
+
+ /*
+ * Turn the status into a bit set of case foldings to test.
+ * Remember non-Turkic case foldings as defaults for Turkic mode.
+ */
+ switch(status) {
+ case 'C':
+ which=CF_SIMPLE|CF_FULL;
+ pData->prevSimple=simple;
+ u_memcpy(pData->prevFull, full, count);
+ pData->prevFullLength=count;
+ break;
+ case 'S':
+ which=CF_SIMPLE;
+ pData->prevSimple=simple;
+ break;
+ case 'F':
+ which=CF_FULL;
+ u_memcpy(pData->prevFull, full, count);
+ pData->prevFullLength=count;
+ break;
+ case 'T':
+ which=CF_TURKIC;
+ break;
+ default:
+ which=0;
+ break; /* won't happen because of test above */
+ }
+
+ testFold(c, which, simple, simple, full, count, full, count);
+
+ /* remember which case foldings of c have been tested */
+ pData->which|=which;
+
+ /* remove c from the set of ones not mentioned in CaseFolding.txt */
+ uset_remove(pData->notSeen, c);
+}
+
+static void
+TestCaseFolding() {
+ CaseFoldingData data={ NULL };
+ char *fields[3][2];
+ UErrorCode errorCode;
+
+ static char *lastLine= (char *)"10FFFF; C; 10FFFF;";
+
+ errorCode=U_ZERO_ERROR;
+ /* test BMP & plane 1 - nothing interesting above */
+ data.notSeen=uset_open(0, 0x1ffff);
+ data.prevFullLength=1; /* length of full case folding of U+0000 */
+
+ parseUCDFile("CaseFolding.txt", fields, 3, caseFoldingLineFn, &data, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ int32_t i, start, end;
+
+ /* add a pseudo-last line to finish testing of the actual last one */
+ fields[0][0]=lastLine;
+ fields[0][1]=lastLine+6;
+ fields[1][0]=lastLine+7;
+ fields[1][1]=lastLine+9;
+ fields[2][0]=lastLine+10;
+ fields[2][1]=lastLine+17;
+ caseFoldingLineFn(&data, fields, 3, &errorCode);
+
+ /* verify that all code points that are not mentioned in CaseFolding.txt fold to themselves */
+ for(i=0;
+ 0==uset_getItem(data.notSeen, i, &start, &end, NULL, 0, &errorCode) &&
+ U_SUCCESS(errorCode);
+ ++i
+ ) {
+ do {
+ testFoldToSelf(start, CF_ALL);
+ } while(++start<=end);
+ }
+ }
+
+ uset_close(data.notSeen);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c
new file mode 100644
index 00000000000..adce0854037
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/currtest.c
@@ -0,0 +1,243 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2005-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+#include "unicode/unum.h"
+#include "unicode/ucurr.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "cstring.h"
+
+static void expectInList(const char *isoCurrency, uint32_t currencyType, UBool isExpected) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char *foundCurrency = NULL;
+ const char *currentCurrency;
+ UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
+ return;
+ }
+
+ while ((currentCurrency = uenum_next(en, NULL, &status)) != NULL) {
+ if (strcmp(isoCurrency, currentCurrency) == 0) {
+ foundCurrency = currentCurrency;
+ break;
+ }
+ }
+
+ if ((foundCurrency != NULL) != isExpected) {
+ log_err("Error: could not find %s as expected. isExpected = %s type=0x%X\n",
+ isoCurrency, isExpected ? "TRUE" : "FALSE", currencyType);
+ }
+ uenum_close(en);
+}
+
+static void TestEnumList(void) {
+ expectInList("ADP", UCURR_ALL, TRUE); /* First in list */
+ expectInList("ZWD", UCURR_ALL, TRUE); /* Last in list */
+
+ expectInList("USD", UCURR_ALL, TRUE);
+ expectInList("USD", UCURR_COMMON, TRUE);
+ expectInList("USD", UCURR_UNCOMMON, FALSE);
+ expectInList("USD", UCURR_DEPRECATED, FALSE);
+ expectInList("USD", UCURR_NON_DEPRECATED, TRUE);
+ expectInList("USD", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("USD", UCURR_COMMON|UCURR_NON_DEPRECATED, TRUE);
+ expectInList("USD", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("USD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
+
+ expectInList("USN", UCURR_ALL, TRUE);
+ expectInList("USN", UCURR_COMMON, FALSE);
+ expectInList("USN", UCURR_UNCOMMON, TRUE);
+ expectInList("USN", UCURR_DEPRECATED, FALSE);
+ expectInList("USN", UCURR_NON_DEPRECATED, TRUE);
+ expectInList("USN", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("USN", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
+ expectInList("USN", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, TRUE);
+
+ expectInList("DEM", UCURR_ALL, TRUE);
+ expectInList("DEM", UCURR_COMMON, TRUE);
+ expectInList("DEM", UCURR_UNCOMMON, FALSE);
+ expectInList("DEM", UCURR_DEPRECATED, TRUE);
+ expectInList("DEM", UCURR_NON_DEPRECATED, FALSE);
+ expectInList("DEM", UCURR_COMMON|UCURR_DEPRECATED, TRUE);
+ expectInList("DEM", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
+ expectInList("DEM", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("DEM", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
+
+ expectInList("XEU", UCURR_ALL, TRUE);
+ expectInList("XEU", UCURR_COMMON, FALSE);
+ expectInList("XEU", UCURR_UNCOMMON, TRUE);
+ expectInList("XEU", UCURR_DEPRECATED, TRUE);
+ expectInList("XEU", UCURR_NON_DEPRECATED, FALSE);
+ expectInList("XEU", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
+ expectInList("XEU", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
+ expectInList("XEU", UCURR_UNCOMMON|UCURR_DEPRECATED, TRUE);
+ expectInList("XEU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
+
+}
+
+static void TestEnumListReset(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ const char *currency1;
+ const char *currency2;
+ UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
+ return;
+ }
+
+ currency1 = uenum_next(en, NULL, &status);
+ uenum_reset(en, &status);
+ currency2 = uenum_next(en, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error: uenum_next or uenum_reset returned %s\n", myErrorName(status));
+ return;
+ }
+ /* The first item's pointer in the list should be the same between resets. */
+ if (currency1 != currency2) {
+ log_err("Error: reset doesn't work %s != %s\n", currency1, currency2);
+ }
+ uenum_close(en);
+}
+
+static int32_t checkItemCount(uint32_t currencyType) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t originalCount, count;
+ UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status);
+ int32_t expectedLen = 3, len;
+ if (U_FAILURE(status)) {
+ log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
+ return -1;
+ }
+
+ originalCount = uenum_count(en, &status);
+ for (count=0;;count++) {
+ const char *str = uenum_next(en, &len, &status);
+ if (str == NULL || len != expectedLen || strlen(str) != expectedLen) {
+ break;
+ }
+ }
+
+ if (originalCount != count) {
+ log_err("Error: uenum_count returned the wrong value (type = 0x%X). Got: %d Expected %d\n",
+ currencyType, count, originalCount);
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error: uenum_next got an error: %s\n", u_errorName(status));
+ }
+ uenum_close(en);
+ return count;
+}
+
+static void TestEnumListCount(void) {
+ checkItemCount(UCURR_ALL);
+ checkItemCount(UCURR_COMMON);
+ checkItemCount(UCURR_UNCOMMON);
+ checkItemCount(UCURR_DEPRECATED);
+ checkItemCount(UCURR_NON_DEPRECATED);
+ checkItemCount(UCURR_COMMON|UCURR_DEPRECATED);
+ checkItemCount(UCURR_COMMON|UCURR_NON_DEPRECATED);
+ checkItemCount(UCURR_UNCOMMON|UCURR_DEPRECATED);
+ checkItemCount(UCURR_UNCOMMON|UCURR_NON_DEPRECATED);
+
+ if (checkItemCount(UCURR_DEPRECATED|UCURR_NON_DEPRECATED) != 0) {
+ log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n");
+ }
+ if (checkItemCount(UCURR_COMMON|UCURR_UNCOMMON) != 0) {
+ log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n");
+ }
+}
+
+static void TestFractionDigitOverride(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UNumberFormat *fmt = unum_open(UNUM_CURRENCY, NULL, 0, "hu_HU", NULL, &status);
+ UChar buffer[256];
+ UChar expectedBuf[256];
+ const char expectedFirst[] = "123,46 Ft";
+ const char expectedSecond[] = "123 Ft";
+ const char expectedThird[] = "123,456 Ft";
+ if (U_FAILURE(status)) {
+ log_err("Error: unum_open returned %s\n", myErrorName(status));
+ return;
+ }
+ /* Make sure that you can format normal fraction digits. */
+ unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
+ u_charsToUChars(expectedFirst, expectedBuf, strlen(expectedFirst)+1);
+ if (u_strcmp(buffer, expectedBuf) != 0) {
+ log_err("Error: unum_formatDouble didn't return %s\n", expectedFirst);
+ }
+ /* Make sure that you can format no fraction digits. */
+ unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 0);
+ unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
+ u_charsToUChars(expectedSecond, expectedBuf, strlen(expectedSecond)+1);
+ if (u_strcmp(buffer, expectedBuf) != 0) {
+ log_err("Error: unum_formatDouble didn't return %s\n", expectedSecond);
+ }
+ /* Make sure that you can format more fraction digits. */
+ unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 3);
+ unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
+ u_charsToUChars(expectedThird, expectedBuf, strlen(expectedThird)+1);
+ if (u_strcmp(buffer, expectedBuf) != 0) {
+ log_err("Error: unum_formatDouble didn't return %s\n", expectedThird);
+ }
+ unum_close(fmt);
+}
+
+static void TestPrefixSuffix(void) {
+ int32_t pos;
+ UErrorCode status;
+ double result1 = 0.0, result2 = 0.0;
+ UNumberFormat* parser;
+ UChar buffer[4];
+ static const UChar TEST_NUMBER[] = {0x0024,0x0031,0x0032,0x002E,0x0030,0x0030,0}; /* $12.00 */
+ static const UChar NEG_PREFIX[] = {0x005B,0}; /* "[" */
+ static const UChar NEG_SUFFIX[] = {0x005D,0}; /* "]" */
+
+
+ status = U_ZERO_ERROR;
+ parser = unum_open(UNUM_CURRENCY, NULL, -1, "en_US", NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error: unum_open returned %s\n", u_errorName(status));
+ return;
+ }
+
+ pos = 0;
+ status = U_ZERO_ERROR;
+ result1 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status);
+
+ unum_setTextAttribute(parser, UNUM_NEGATIVE_SUFFIX, NEG_SUFFIX, -1, &status);
+ unum_setTextAttribute(parser, UNUM_NEGATIVE_PREFIX, NEG_PREFIX, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error: unum_setTextAttribute returned %s\n", u_errorName(status));
+ return;
+ }
+
+ pos = 0;
+ result2 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status);
+ if (result1 != result2 || U_FAILURE(status)) {
+ log_err("Error: unum_parseDoubleCurrency didn't return the same value for same string %f %f %s\n",
+ result1, result2, u_errorName(status));
+ }
+ unum_close(parser);
+}
+
+void addCurrencyTest(TestNode** root);
+
+#define TESTCASE(x) addTest(root, &x, "tsformat/currtest/" #x)
+
+void addCurrencyTest(TestNode** root)
+{
+ TESTCASE(TestEnumList);
+ TESTCASE(TestEnumListReset);
+ TESTCASE(TestEnumListCount);
+ TESTCASE(TestFractionDigitOverride);
+ TESTCASE(TestPrefixSuffix);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c
new file mode 100644
index 00000000000..90cc00ae5c4
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtrn.c
@@ -0,0 +1,1185 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2001-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File custrtrn.C
+*
+* Modification History:
+* Name Description
+* Ram String transformations test
+*********************************************************************************
+*/
+/****************************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "unicode/ures.h"
+#include "ustr_imp.h"
+#include "cintltst.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "cwchar.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+void addUCharTransformTest(TestNode** root);
+
+static void Test_UChar_UTF32_API(void);
+static void Test_UChar_UTF8_API(void);
+static void Test_FromUTF8Lenient(void);
+static void Test_UChar_WCHART_API(void);
+static void Test_widestrs(void);
+static void Test_WCHART_LongString(void);
+
+void
+addUCharTransformTest(TestNode** root)
+{
+ addTest(root, &Test_UChar_UTF32_API, "custrtrn/Test_UChar_UTF32_API");
+ addTest(root, &Test_UChar_UTF8_API, "custrtrn/Test_UChar_UTF8_API");
+ addTest(root, &Test_FromUTF8Lenient, "custrtrn/Test_FromUTF8Lenient");
+ addTest(root, &Test_UChar_WCHART_API, "custrtrn/Test_UChar_WCHART_API");
+ addTest(root, &Test_widestrs, "custrtrn/Test_widestrs");
+ addTest(root, &Test_WCHART_LongString, "custrtrn/Test_WCHART_LongString");
+}
+
+static const UChar32 src32[]={
+ 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A,
+ 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A,
+ 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A,
+ 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A,
+ 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A,
+ 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A,
+ 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A,
+ 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A,
+ 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A,
+ 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A,
+ 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A,
+ 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A,
+ 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A,
+ /* test non-BMP code points */
+ 0x0002A699,
+ 0x0002A69C, 0x0002A69D, 0x0002A69E, 0x0002A69F, 0x0002A6A0, 0x0002A6A5, 0x0002A6A6, 0x0002A6A7, 0x0002A6A8, 0x0002A6AB,
+ 0x0002A6AC, 0x0002A6AD, 0x0002A6AE, 0x0002A6AF, 0x0002A6B0, 0x0002A6B1, 0x0002A6B3, 0x0002A6B5, 0x0002A6B6, 0x0002A6B7,
+ 0x0002A6B8, 0x0002A6B9, 0x0002A6BA, 0x0002A6BB, 0x0002A6BC, 0x0002A6BD, 0x0002A6BE, 0x0002A6BF, 0x0002A6C0, 0x0002A6C1,
+ 0x0002A6C2, 0x0002A6C3, 0x0002A6C4, 0x0002A6C8, 0x0002A6CA, 0x0002A6CB, 0x0002A6CD, 0x0002A6CE, 0x0002A6CF, 0x0002A6D0,
+ 0x0002A6D1, 0x0002A6D2, 0x0002A6D3, 0x0002A6D4, 0x0002A6D5,
+
+ 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A,
+ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A,
+ 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A,
+ 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A,
+ 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,0x0000
+};
+
+static const UChar src16[] = {
+ 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A,
+ 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A,
+ 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A,
+ 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A,
+ 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A,
+ 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A,
+ 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A,
+ 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A,
+ 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A,
+ 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A,
+ 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A,
+ 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A,
+ 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A,
+
+ /* test non-BMP code points */
+ 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F,
+ 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8,
+ 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF,
+ 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6,
+ 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB,
+ 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0,
+ 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8,
+ 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF,
+ 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4,
+ 0xD869, 0xDED5,
+
+ 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A,
+ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A,
+ 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A,
+ 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A,
+ 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,0x0000
+};
+
+
+static void Test_UChar_UTF32_API(void){
+
+ UErrorCode err = U_ZERO_ERROR;
+ UChar uTemp[1];
+ UChar32 u32Temp[1];
+ UChar* uTarget=uTemp;
+ const UChar32* u32Src = src32;
+ int32_t u32SrcLen = sizeof(src32)/4;
+ int32_t uTargetLength = 0;
+ int32_t uDestLen=0;
+ const UChar* uSrc = src16;
+ int32_t uSrcLen = sizeof(src16)/2;
+ UChar32* u32Target = u32Temp;
+ uint32_t u32TargetLength =0;
+ int32_t u32DestLen =0;
+ UBool failed = FALSE;
+ int i= 0;
+ {
+ /* preflight */
+ u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ u32Target = (UChar32*) malloc (sizeof(uint32_t) * (u32DestLen+1));
+ u32TargetLength = u32DestLen+1;
+
+ u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err);
+ }
+ else {
+ log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR");
+ }
+ failed = FALSE;
+ /*for(i=0; i< u32DestLen; i++){
+ printf("0x%08X, ",uTarget[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+ for(i=0; i< u32SrcLen; i++){
+ if(u32Target[i] != src32[i]){
+ log_verbose("u_strToUTF32() failed expected: \\U%08X got: \\U%08X at index: %i \n", src32[i], u32Target[i],i);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF32() failed \n");
+ }
+
+ /* preflight */
+ u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1));
+ uTargetLength = uDestLen+1;
+ u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err);
+
+ }
+ /*for(i=0; i< uDestLen; i++){
+ printf("0x%04X, ",uTarget[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+
+ for(i=0; i< uDestLen; i++){
+ if(uTarget[i] != src16[i]){
+ log_verbose("u_strFromUTF32() failed expected: \\U%08X got: \\U%08X at index: %i \n", src16[i] ,uTarget[i],i);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF32() failed \n");
+ }
+
+ free(u32Target);
+ free(uTarget);
+ }
+ {
+ u32SrcLen = -1;
+ uTargetLength = 0;
+ uSrcLen =-1;
+ u32TargetLength=0;
+ failed = FALSE;
+
+ /* preflight */
+ u_strToUTF32(NULL,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ u32Target = (UChar32*) malloc (sizeof(uint32_t) * (u32DestLen+1));
+ u32TargetLength = u32DestLen+1;
+
+ u_strToUTF32(u32Target,u32TargetLength, &u32DestLen, uSrc, uSrcLen,&err);
+ }
+ else {
+ log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR");
+ }
+ failed = FALSE;
+
+ for(i=0; i< u32SrcLen; i++){
+ if(u32Target[i] != src32[i]){
+ log_verbose("u_strToUTF32() failed expected: \\U%08X got: \\U%08X \n", src32[i], u32Target[i]);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF32() failed \n");
+ }
+
+ /* preflight */
+ u_strFromUTF32(NULL,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1));
+ uTargetLength = uDestLen+1;
+ u_strFromUTF32(uTarget,uTargetLength,&uDestLen,u32Src,u32SrcLen,&err);
+
+ }
+
+ for(i=0; i< uDestLen; i++){
+ if(uTarget[i] != src16[i]){
+ log_verbose("u_strFromUTF32() failed expected: \\U%08X got: \\U%08X \n", src16[i] ,uTarget[i]);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF32() failed \n");
+ }
+
+ free(u32Target);
+ free(uTarget);
+ }
+}
+
+
+static void Test_UChar_UTF8_API(void){
+
+ UErrorCode err = U_ZERO_ERROR;
+ UChar uTemp[1];
+ char u8Temp[1];
+ UChar* uTarget=uTemp;
+ const char* u8Src;
+ int32_t u8SrcLen = 0;
+ int32_t uTargetLength = 0;
+ int32_t uDestLen=0;
+ const UChar* uSrc = src16;
+ int32_t uSrcLen = sizeof(src16)/2;
+ char* u8Target = u8Temp;
+ int32_t u8TargetLength =0;
+ int32_t u8DestLen =0;
+ UBool failed = FALSE;
+ int i= 0;
+ int32_t numSubstitutions;
+
+ {
+ /* preflight */
+ u8Temp[0] = 0x12;
+ u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR && u8Temp[0] == 0x12){
+ err = U_ZERO_ERROR;
+ u8Target = (char*) malloc (sizeof(uint8_t) * (u8DestLen+1));
+ u8TargetLength = u8DestLen;
+
+ u8Target[u8TargetLength] = (char)0xfe;
+ u8DestLen = -1;
+ u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err);
+ if(U_FAILURE(err) || u8DestLen != u8TargetLength || u8Target[u8TargetLength] != (char)0xfe){
+ log_err("u_strToUTF8 failed after preflight. Error: %s\n", u_errorName(err));
+ return;
+ }
+
+ }
+ else {
+ log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR");
+ }
+ failed = FALSE;
+ /*for(i=0; i< u8DestLen; i++){
+ printf("0x%04X, ",u8Target[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+ /*for(i=0; i< u8DestLen; i++){
+ if(u8Target[i] != src8[i]){
+ log_verbose("u_strToUTF8() failed expected: \\U%08X got: \\U%08X \n", src8[i], u8Target[i]);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF8() failed \n");
+ }*/
+ u8Src = u8Target;
+ u8SrcLen = u8DestLen;
+
+ /* preflight */
+ uTemp[0] = 0x1234;
+ u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR && uTemp[0] == 0x1234){
+ err = U_ZERO_ERROR;
+ uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1));
+ uTargetLength = uDestLen;
+
+ uTarget[uTargetLength] = 0xfff0;
+ uDestLen = -1;
+ u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err);
+ }
+ else {
+ log_err("error: u_strFromUTF8(preflight) should have gotten U_BUFFER_OVERFLOW_ERROR\n");
+ }
+ /*for(i=0; i< uDestLen; i++){
+ printf("0x%04X, ",uTarget[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+
+ if(U_FAILURE(err) || uDestLen != uTargetLength || uTarget[uTargetLength] != 0xfff0) {
+ failed = TRUE;
+ }
+ for(i=0; i< uSrcLen; i++){
+ if(uTarget[i] != src16[i]){
+ log_verbose("u_strFromUTF8() failed expected: \\u%04X got: \\u%04X at index: %i \n", src16[i] ,uTarget[i],i);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("error: u_strFromUTF8(after preflighting) failed\n");
+ }
+
+ free(u8Target);
+ free(uTarget);
+ }
+ {
+ u8SrcLen = -1;
+ uTargetLength = 0;
+ uSrcLen =-1;
+ u8TargetLength=0;
+ failed = FALSE;
+ /* preflight */
+ u_strToUTF8(NULL,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ u8Target = (char*) malloc (sizeof(uint8_t) * (u8DestLen+1));
+ u8TargetLength = u8DestLen;
+
+ u_strToUTF8(u8Target,u8TargetLength, &u8DestLen, uSrc, uSrcLen,&err);
+
+ }
+ else {
+ log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR");
+ }
+ failed = FALSE;
+ /*for(i=0; i< u8DestLen; i++){
+ printf("0x%04X, ",u8Target[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+ /*for(i=0; i< u8DestLen; i++){
+ if(u8Target[i] != src8[i]){
+ log_verbose("u_strToUTF8() failed expected: \\U%08X got: \\U%08X \n", src8[i], u8Target[i]);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF8() failed \n");
+ }*/
+ u8Src = u8Target;
+ u8SrcLen = u8DestLen;
+
+ /* preflight */
+ u_strFromUTF8(NULL,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err);
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err = U_ZERO_ERROR;
+ uTarget = (UChar*) malloc( sizeof(UChar) * (uDestLen+1));
+ uTargetLength = uDestLen;
+
+ u_strFromUTF8(uTarget,uTargetLength,&uDestLen,u8Src,u8SrcLen,&err);
+ }
+ else {
+ log_err("Should have gotten U_BUFFER_OVERFLOW_ERROR");
+ }
+ /*for(i=0; i< uDestLen; i++){
+ printf("0x%04X, ",uTarget[i]);
+ if(i%10==0){
+ printf("\n");
+ }
+ }*/
+
+ for(i=0; i< uSrcLen; i++){
+ if(uTarget[i] != src16[i]){
+ log_verbose("u_strFromUTF8() failed expected: \\u%04X got: \\u%04X at index: %i \n", src16[i] ,uTarget[i],i);
+ failed =TRUE;
+ }
+ }
+ if(failed){
+ log_err("u_strToUTF8() failed \n");
+ }
+
+ free(u8Target);
+ free(uTarget);
+ }
+
+ /* test UTF-8 with single surrogates - illegal in Unicode 3.2 */
+ {
+ static const UChar
+ withLead16[]={ 0x1800, 0xd89a, 0x0061 },
+ withTrail16[]={ 0x1800, 0xdcba, 0x0061, 0 },
+ withTrail16SubFFFD[]={ 0x1800, 0xfffd, 0x0061, 0 }, /* sub==U+FFFD */
+ withTrail16Sub50005[]={ 0x1800, 0xd900, 0xdc05, 0x0061, 0 }; /* sub==U+50005 */
+ static const uint8_t
+ withLead8[]={ 0xe1, 0xa0, 0x80, 0xed, 0xa2, 0x9a, 0x61 },
+ withTrail8[]={ 0xe1, 0xa0, 0x80, 0xed, 0xb2, 0xba, 0x61, 0 },
+ withTrail8Sub1A[]={ 0xe1, 0xa0, 0x80, 0x1a, 0x61, 0 }, /* sub==U+001A */
+ withTrail8SubFFFD[]={ 0xe1, 0xa0, 0x80, 0xef, 0xbf, 0xbd, 0x61, 0 }; /* sub==U+FFFD */
+ UChar out16[10];
+ char out8[10];
+
+ if(
+ (err=U_ZERO_ERROR, u_strToUTF8(out8, LENGTHOF(out8), NULL, withLead16, LENGTHOF(withLead16), &err), err!=U_INVALID_CHAR_FOUND) ||
+ (err=U_ZERO_ERROR, u_strToUTF8(out8, LENGTHOF(out8), NULL, withTrail16, -1, &err), err!=U_INVALID_CHAR_FOUND) ||
+ (err=U_ZERO_ERROR, u_strFromUTF8(out16, LENGTHOF(out16), NULL, (const char *)withLead8, LENGTHOF(withLead8), &err), err!=U_INVALID_CHAR_FOUND) ||
+ (err=U_ZERO_ERROR, u_strFromUTF8(out16, LENGTHOF(out16), NULL, (const char *)withTrail8, -1, &err), err!=U_INVALID_CHAR_FOUND)
+ ) {
+ log_err("error: u_strTo/FromUTF8(string with single surrogate) fails to report error\n");
+ }
+
+ /* test error handling with substitution characters */
+
+ /* from UTF-8 with length */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out16[0]=0x55aa;
+ uDestLen=0;
+ u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen,
+ (const char *)withTrail8, uprv_strlen((const char *)withTrail8),
+ 0x50005, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || uDestLen!=u_strlen(withTrail16Sub50005) ||
+ 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen+1) ||
+ numSubstitutions!=1) {
+ log_err("error: u_strFromUTF8WithSub(length) failed\n");
+ }
+
+ /* from UTF-8 with NUL termination */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out16[0]=0x55aa;
+ uDestLen=0;
+ u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen,
+ (const char *)withTrail8, -1,
+ 0xfffd, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || uDestLen!=u_strlen(withTrail16SubFFFD) ||
+ 0!=u_memcmp(withTrail16SubFFFD, out16, uDestLen+1) ||
+ numSubstitutions!=1) {
+ log_err("error: u_strFromUTF8WithSub(NUL termination) failed\n");
+ }
+
+ /* preflight from UTF-8 with NUL termination */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out16[0]=0x55aa;
+ uDestLen=0;
+ u_strFromUTF8WithSub(out16, 1, &uDestLen,
+ (const char *)withTrail8, -1,
+ 0x50005, &numSubstitutions,
+ &err);
+ if(err!=U_BUFFER_OVERFLOW_ERROR || uDestLen!=u_strlen(withTrail16Sub50005) || numSubstitutions!=1) {
+ log_err("error: u_strFromUTF8WithSub(preflight/NUL termination) failed\n");
+ }
+
+ /* to UTF-8 with length */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out8[0]=(char)0xf5;
+ u8DestLen=0;
+ u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen,
+ withTrail16, u_strlen(withTrail16),
+ 0xfffd, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) ||
+ 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen+1) ||
+ numSubstitutions!=1) {
+ log_err("error: u_strToUTF8WithSub(length) failed\n");
+ }
+
+ /* to UTF-8 with NUL termination */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out8[0]=(char)0xf5;
+ u8DestLen=0;
+ u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen,
+ withTrail16, -1,
+ 0x1a, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || u8DestLen!=uprv_strlen((const char *)withTrail8Sub1A) ||
+ 0!=uprv_memcmp((const char *)withTrail8Sub1A, out8, u8DestLen+1) ||
+ numSubstitutions!=1) {
+ log_err("error: u_strToUTF8WithSub(NUL termination) failed\n");
+ }
+
+ /* preflight to UTF-8 with NUL termination */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out8[0]=(char)0xf5;
+ u8DestLen=0;
+ u_strToUTF8WithSub(out8, 1, &u8DestLen,
+ withTrail16, -1,
+ 0xfffd, &numSubstitutions,
+ &err);
+ if(err!=U_BUFFER_OVERFLOW_ERROR || u8DestLen!=uprv_strlen((const char *)withTrail8SubFFFD) ||
+ numSubstitutions!=1) {
+ log_err("error: u_strToUTF8WithSub(preflight/NUL termination) failed\n");
+ }
+
+ /* test that numSubstitutions==0 if there are no substitutions */
+
+ /* from UTF-8 with length (just first 3 bytes which are valid) */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out16[0]=0x55aa;
+ uDestLen=0;
+ u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen,
+ (const char *)withTrail8, 3,
+ 0x50005, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || uDestLen!=1 ||
+ 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen) ||
+ numSubstitutions!=0) {
+ log_err("error: u_strFromUTF8WithSub(no subs) failed\n");
+ }
+
+ /* to UTF-8 with length (just first UChar which is valid) */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out8[0]=(char)0xf5;
+ u8DestLen=0;
+ u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen,
+ withTrail16, 1,
+ 0xfffd, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || u8DestLen!=3 ||
+ 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen) ||
+ numSubstitutions!=0) {
+ log_err("error: u_strToUTF8WithSub(no subs) failed\n");
+ }
+
+ /* test that numSubstitutions==0 if subchar==U_SENTINEL (no subchar) */
+
+ /* from UTF-8 with length (just first 3 bytes which are valid) */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out16[0]=0x55aa;
+ uDestLen=0;
+ u_strFromUTF8WithSub(out16, LENGTHOF(out16), &uDestLen,
+ (const char *)withTrail8, 3,
+ U_SENTINEL, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || uDestLen!=1 ||
+ 0!=u_memcmp(withTrail16Sub50005, out16, uDestLen) ||
+ numSubstitutions!=0) {
+ log_err("error: u_strFromUTF8WithSub(no subchar) failed\n");
+ }
+
+ /* to UTF-8 with length (just first UChar which is valid) */
+ err=U_ZERO_ERROR;
+ numSubstitutions=-1;
+ out8[0]=(char)0xf5;
+ u8DestLen=0;
+ u_strToUTF8WithSub(out8, LENGTHOF(out8), &u8DestLen,
+ withTrail16, 1,
+ U_SENTINEL, &numSubstitutions,
+ &err);
+ if(U_FAILURE(err) || u8DestLen!=3 ||
+ 0!=uprv_memcmp((const char *)withTrail8SubFFFD, out8, u8DestLen) ||
+ numSubstitutions!=0) {
+ log_err("error: u_strToUTF8WithSub(no subchar) failed\n");
+ }
+ }
+}
+
+/* compare if two strings are equal, but match 0xfffd in the second string with anything in the first */
+static UBool
+equalAnyFFFD(const UChar *s, const UChar *t, int32_t length) {
+ UChar c1, c2;
+
+ while(length>0) {
+ c1=*s++;
+ c2=*t++;
+ if(c1!=c2 && c2!=0xfffd) {
+ return FALSE;
+ }
+ --length;
+ }
+ return TRUE;
+}
+
+/* test u_strFromUTF8Lenient() */
+static void
+Test_FromUTF8Lenient(void) {
+ /*
+ * Multiple input strings, each NUL-terminated.
+ * Terminate with a string starting with 0xff.
+ */
+ static const uint8_t bytes[]={
+ /* well-formed UTF-8 */
+ 0x61, 0xc3, 0x9f, 0xe0, 0xa0, 0x80, 0xf0, 0xa0, 0x80, 0x80,
+ 0x62, 0xc3, 0xa0, 0xe0, 0xa0, 0x81, 0xf0, 0xa0, 0x80, 0x81, 0,
+
+ /* various malformed sequences */
+ 0xc3, 0xc3, 0x9f, 0xc3, 0xa0, 0xe0, 0x80, 0x8a, 0xf0, 0x41, 0x42, 0x43, 0,
+
+ /* truncated input */
+ 0xc3, 0,
+ 0xe0, 0,
+ 0xe0, 0xa0, 0,
+ 0xf0, 0,
+ 0xf0, 0x90, 0,
+ 0xf0, 0x90, 0x80, 0,
+
+ /* non-ASCII characters in the last few bytes */
+ 0x61, 0xc3, 0x9f, 0xe0, 0xa0, 0x80, 0,
+ 0x61, 0xe0, 0xa0, 0x80, 0xc3, 0x9f, 0,
+
+ /* empty string */
+ 0,
+
+ /* finish */
+ 0xff, 0
+ };
+
+ /* Multiple output strings, each NUL-terminated. 0xfffd matches anything. */
+ static const UChar uchars[]={
+ 0x61, 0xdf, 0x800, 0xd840, 0xdc00,
+ 0x62, 0xe0, 0x801, 0xd840, 0xdc01, 0,
+
+ 0xfffd, 0x9f, 0xe0, 0xa, 0xfffd, 0xfffd, 0,
+
+ 0xfffd, 0,
+ 0xfffd, 0,
+ 0xfffd, 0,
+ 0xfffd, 0,
+ 0xfffd, 0,
+ 0xfffd, 0,
+
+ 0x61, 0xdf, 0x800, 0,
+ 0x61, 0x800, 0xdf, 0,
+
+ 0,
+
+ 0
+ };
+
+ UChar dest[64];
+ const char *pb;
+ const UChar *pu, *pDest;
+ int32_t srcLength, destLength0, destLength;
+ int number;
+ UErrorCode errorCode;
+
+ /* verify checking for some illegal arguments */
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, 1, &destLength, NULL, -1, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || dest[0]!=0x1234) {
+ log_err("u_strFromUTF8Lenient(src=NULL) failed\n");
+ }
+
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(NULL, 1, &destLength, (const char *)bytes, -1, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("u_strFromUTF8Lenient(dest=NULL[1]) failed\n");
+ }
+
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_MEMORY_ALLOCATION_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, 1, &destLength, (const char *)bytes, -1, &errorCode);
+ if(errorCode!=U_MEMORY_ALLOCATION_ERROR || dest[0]!=0x1234) {
+ log_err("u_strFromUTF8Lenient(U_MEMORY_ALLOCATION_ERROR) failed\n");
+ }
+
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_MEMORY_ALLOCATION_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, 1, &destLength, (const char *)bytes, -1, NULL);
+ if(dest[0]!=0x1234) {
+ log_err("u_strFromUTF8Lenient(pErrorCode=NULL) failed\n");
+ }
+
+ /* test normal behavior */
+ number=0; /* string number for log_err() */
+
+ for(pb=(const char *)bytes, pu=uchars;
+ *pb!=(char)0xff;
+ pb+=srcLength+1, pu+=destLength0+1, ++number
+ ) {
+ srcLength=uprv_strlen(pb);
+ destLength0=u_strlen(pu);
+
+ /* preflighting with NUL-termination */
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(NULL, 0, &destLength, pb, -1, &errorCode);
+ if (errorCode!= (destLength0==0 ? U_STRING_NOT_TERMINATED_WARNING : U_BUFFER_OVERFLOW_ERROR) ||
+ pDest!=NULL || dest[0]!=0x1234 || destLength!=destLength0
+ ) {
+ log_err("u_strFromUTF8Lenient(%d preflighting with NUL-termination) failed\n", number);
+ }
+
+ /* preflighting/some capacity with NUL-termination */
+ if(srcLength>0) {
+ dest[destLength0-1]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, destLength0-1, &destLength, pb, -1, &errorCode);
+ if (errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ dest[destLength0-1]!=0x1234 || destLength!=destLength0
+ ) {
+ log_err("u_strFromUTF8Lenient(%d preflighting/some capacity with NUL-termination) failed\n", number);
+ }
+ }
+
+ /* conversion with NUL-termination, much capacity */
+ dest[0]=dest[destLength0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, LENGTHOF(dest), &destLength, pb, -1, &errorCode);
+ if (errorCode!=U_ZERO_ERROR ||
+ pDest!=dest || dest[destLength0]!=0 ||
+ destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength)
+ ) {
+ log_err("u_strFromUTF8Lenient(%d conversion with NUL-termination, much capacity) failed\n", number);
+ }
+
+ /* conversion with NUL-termination, exact capacity */
+ dest[0]=dest[destLength0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, destLength0, &destLength, pb, -1, &errorCode);
+ if (errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ pDest!=dest || dest[destLength0]!=0x1234 ||
+ destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength)
+ ) {
+ log_err("u_strFromUTF8Lenient(%d conversion with NUL-termination, exact capacity) failed\n", number);
+ }
+
+ /* preflighting with length */
+ dest[0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(NULL, 0, &destLength, pb, srcLength, &errorCode);
+ if (errorCode!= (destLength0==0 ? U_STRING_NOT_TERMINATED_WARNING : U_BUFFER_OVERFLOW_ERROR) ||
+ pDest!=NULL || dest[0]!=0x1234 || destLength!=srcLength
+ ) {
+ log_err("u_strFromUTF8Lenient(%d preflighting with length) failed\n", number);
+ }
+
+ /* preflighting/some capacity with length */
+ if(srcLength>0) {
+ dest[srcLength-1]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, srcLength-1, &destLength, pb, srcLength, &errorCode);
+ if (errorCode!=U_BUFFER_OVERFLOW_ERROR ||
+ dest[srcLength-1]!=0x1234 || destLength!=srcLength
+ ) {
+ log_err("u_strFromUTF8Lenient(%d preflighting/some capacity with length) failed\n", number);
+ }
+ }
+
+ /* conversion with length, much capacity */
+ dest[0]=dest[destLength0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, LENGTHOF(dest), &destLength, pb, srcLength, &errorCode);
+ if (errorCode!=U_ZERO_ERROR ||
+ pDest!=dest || dest[destLength0]!=0 ||
+ destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength)
+ ) {
+ log_err("u_strFromUTF8Lenient(%d conversion with length, much capacity) failed\n", number);
+ }
+
+ /* conversion with length, srcLength capacity */
+ dest[0]=dest[srcLength]=dest[destLength0]=0x1234;
+ destLength=-1;
+ errorCode=U_ZERO_ERROR;
+ pDest=u_strFromUTF8Lenient(dest, srcLength, &destLength, pb, srcLength, &errorCode);
+ if(srcLength==destLength0) {
+ if (errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
+ pDest!=dest || dest[destLength0]!=0x1234 ||
+ destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength)
+ ) {
+ log_err("u_strFromUTF8Lenient(%d conversion with length, srcLength capacity/not terminated) failed\n", number);
+ }
+ } else {
+ if (errorCode!=U_ZERO_ERROR ||
+ pDest!=dest || dest[destLength0]!=0 ||
+ destLength!=destLength0 || !equalAnyFFFD(dest, pu, destLength)
+ ) {
+ log_err("u_strFromUTF8Lenient(%d conversion with length, srcLength capacity/terminated) failed\n", number);
+ }
+ }
+ }
+}
+
+static const uint16_t src16j[] = {
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x0000,
+ /* Test only ASCII */
+
+};
+static const uint16_t src16WithNulls[] = {
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0000,
+ 0x0048, 0x0049, 0x004A, 0x000D, 0x000A, 0x0000,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0000,
+ 0x0050, 0x0051, 0x0052, 0x000D, 0x000A, 0x0000,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0000,
+ 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, 0x0000,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0000,
+ 0x0058, 0x0059, 0x005A, 0x000D, 0x000A, 0x0000,
+ /* test only ASCII */
+ /*
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD,
+ 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1,
+ 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
+ 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5,
+ 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
+ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
+ 0x0054, 0x0000 */
+
+};
+static void Test_UChar_WCHART_API(void){
+#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION)
+ UErrorCode err = U_ZERO_ERROR;
+ const UChar* uSrc = src16j;
+ int32_t uSrcLen = sizeof(src16j)/2;
+ wchar_t* wDest = NULL;
+ int32_t wDestLen = 0;
+ int32_t reqLen= 0 ;
+ UBool failed = FALSE;
+ UChar* uDest = NULL;
+ int32_t uDestLen = 0;
+ int i =0;
+ {
+ /* Bad UErrorCode arguments. Make sure that the API doesn't crash, and that Purify doesn't complain. */
+ if (u_strFromWCS(NULL,0,NULL,NULL,0,NULL) != NULL) {
+ log_err("u_strFromWCS() should return NULL with a bad argument\n");
+ }
+ if (u_strToWCS(NULL,0,NULL,NULL,0,NULL) != NULL) {
+ log_err("u_strToWCS() should return NULL with a bad argument\n");
+ }
+
+ /* Bad UErrorCode arguments. */
+ err = U_ZERO_ERROR;
+ u_strFromWCS(NULL,0,NULL,NULL,0,&err);
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("u_strFromWCS() didn't fail as expected with bad arguments. Error: %s \n", u_errorName(err));
+ }
+ err = U_ZERO_ERROR;
+ u_strToWCS(NULL,0,NULL,NULL,0,&err);
+ if (err != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("u_strToWCS() didn't fail as expected with bad arguments. Error: %s \n", u_errorName(err));
+ }
+ err = U_ZERO_ERROR;
+
+ /* pre-flight*/
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err=U_ZERO_ERROR;
+ wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1));
+ wDestLen = reqLen+1;
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
+ }
+
+ /* pre-flight */
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err);
+
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err =U_ZERO_ERROR;
+ uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1));
+ uDestLen = reqLen + 1;
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err);
+ }else if(U_FAILURE(err)){
+
+ log_err("u_strFromWCS() failed. Error: %s \n", u_errorName(err));
+ return;
+ }
+
+ for(i=0; i< uSrcLen; i++){
+ if(uDest[i] != src16j[i]){
+ log_verbose("u_str*WCS() failed for unterminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i);
+ failed =TRUE;
+ }
+ }
+
+ if(U_FAILURE(err)){
+ failed = TRUE;
+ }
+ if(failed){
+ log_err("u_strToWCS() failed \n");
+ }
+ free(wDest);
+ free(uDest);
+
+
+ /* test with embeded nulls */
+ uSrc = src16WithNulls;
+ uSrcLen = sizeof(src16WithNulls)/2;
+ wDestLen =0;
+ uDestLen =0;
+ wDest = NULL;
+ uDest = NULL;
+ /* pre-flight*/
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err=U_ZERO_ERROR;
+ wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1));
+ wDestLen = reqLen+1;
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
+ }
+
+ /* pre-flight */
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err);
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err =U_ZERO_ERROR;
+ uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1));
+ uDestLen = reqLen + 1;
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,reqLen,&err);
+ }
+
+
+ for(i=0; i< uSrcLen; i++){
+ if(uDest[i] != src16WithNulls[i]){
+ log_verbose("u_str*WCS() failed for string with nulls expected: \\u%04X got: \\u%04X at index: %i \n", src16WithNulls[i] ,uDest[i],i);
+ failed =TRUE;
+ }
+ }
+
+ if(U_FAILURE(err)){
+ failed = TRUE;
+ }
+ if(failed){
+ log_err("u_strToWCS() failed \n");
+ }
+ free(wDest);
+ free(uDest);
+
+ }
+
+ {
+
+ uSrc = src16j;
+ uSrcLen = sizeof(src16j)/2;
+ wDestLen =0;
+ uDestLen =0;
+ wDest = NULL;
+ uDest = NULL;
+ wDestLen = 0;
+ /* pre-flight*/
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&err);
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err=U_ZERO_ERROR;
+ wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1));
+ wDestLen = reqLen+1;
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&err);
+ }
+ uDestLen = 0;
+ /* pre-flight */
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&err);
+
+ if(err == U_BUFFER_OVERFLOW_ERROR){
+ err =U_ZERO_ERROR;
+ uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1));
+ uDestLen = reqLen + 1;
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&err);
+ }
+
+
+ for(i=0; i< uSrcLen; i++){
+ if(uDest[i] != src16j[i]){
+ log_verbose("u_str*WCS() failed for null terminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i);
+ failed =TRUE;
+ }
+ }
+
+ if(U_FAILURE(err)){
+ failed = TRUE;
+ }
+ if(failed){
+ log_err("u_strToWCS() failed \n");
+ }
+ free(wDest);
+ free(uDest);
+ }
+
+ /*
+ * Test u_terminateWChars().
+ * All u_terminateXYZ() use the same implementation macro;
+ * we test this function to improve API coverage.
+ */
+ {
+ wchar_t buffer[10];
+
+ err=U_ZERO_ERROR;
+ buffer[3]=0x20ac;
+ wDestLen=u_terminateWChars(buffer, LENGTHOF(buffer), 3, &err);
+ if(err!=U_ZERO_ERROR || wDestLen!=3 || buffer[3]!=0) {
+ log_err("u_terminateWChars(buffer, all, 3, zero) failed: %s length %d [3]==U+%04x\n",
+ u_errorName(err), wDestLen, buffer[3]);
+ }
+
+ err=U_ZERO_ERROR;
+ buffer[3]=0x20ac;
+ wDestLen=u_terminateWChars(buffer, 3, 3, &err);
+ if(err!=U_STRING_NOT_TERMINATED_WARNING || wDestLen!=3 || buffer[3]!=0x20ac) {
+ log_err("u_terminateWChars(buffer, 3, 3, zero) failed: %s length %d [3]==U+%04x\n",
+ u_errorName(err), wDestLen, buffer[3]);
+ }
+
+ err=U_STRING_NOT_TERMINATED_WARNING;
+ buffer[3]=0x20ac;
+ wDestLen=u_terminateWChars(buffer, LENGTHOF(buffer), 3, &err);
+ if(err!=U_ZERO_ERROR || wDestLen!=3 || buffer[3]!=0) {
+ log_err("u_terminateWChars(buffer, all, 3, not-terminated) failed: %s length %d [3]==U+%04x\n",
+ u_errorName(err), wDestLen, buffer[3]);
+ }
+
+ err=U_ZERO_ERROR;
+ buffer[3]=0x20ac;
+ wDestLen=u_terminateWChars(buffer, 2, 3, &err);
+ if(err!=U_BUFFER_OVERFLOW_ERROR || wDestLen!=3 || buffer[3]!=0x20ac) {
+ log_err("u_terminateWChars(buffer, 2, 3, zero) failed: %s length %d [3]==U+%04x\n",
+ u_errorName(err), wDestLen, buffer[3]);
+ }
+ }
+#else
+ log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32");
+#endif
+}
+
+static void Test_widestrs()
+{
+#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION)
+ wchar_t ws[100];
+ UChar rts[100];
+ int32_t wcap = sizeof(ws) / sizeof(*ws);
+ int32_t wl;
+ int32_t rtcap = sizeof(rts) / sizeof(*rts);
+ int32_t rtl;
+ wchar_t *wcs;
+ UChar *cp;
+ const char *errname;
+ UChar ustr[] = {'h', 'e', 'l', 'l', 'o', 0};
+ int32_t ul = sizeof(ustr)/sizeof(*ustr) -1;
+ char astr[100];
+
+ UErrorCode err;
+
+ err = U_ZERO_ERROR;
+ wcs = u_strToWCS(ws, wcap, &wl, ustr, ul, &err);
+ if (U_FAILURE(err)) {
+ errname = u_errorName(err);
+ log_err("test_widestrs: u_strToWCS error: %s!\n",errname);
+ }
+ if(ul!=wl){
+ log_err("u_strToWCS: ustr = %s, ul = %d, ws = %S, wl = %d!\n", u_austrcpy(astr, ustr), ul, ws, wl);
+ }
+ err = U_ZERO_ERROR;
+ wl = (int32_t)uprv_wcslen(wcs);
+ cp = u_strFromWCS(rts, rtcap, &rtl, wcs, wl, &err);
+ if (U_FAILURE(err)) {
+ errname = u_errorName(err);
+ fprintf(stderr, "test_widestrs: ucnv_wcstombs error: %s!\n",errname);
+ }
+ if(wl != rtl){
+ log_err("u_strFromWCS: wcs = %S, wl = %d,rts = %s, rtl = %d!\n", wcs, wl, u_austrcpy(astr, rts), rtl);
+ }
+#else
+ log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32");
+#endif
+}
+
+static void
+Test_WCHART_LongString(){
+#if (defined(U_WCHAR_IS_UTF16) || defined(U_WCHAR_IS_UTF32)) || (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION)
+ UErrorCode status = U_ZERO_ERROR;
+ const char* testdatapath=loadTestData(&status);
+ UResourceBundle *theBundle = ures_open(testdatapath, "testtypes", &status);
+ int32_t strLen =0;
+ const UChar* str = ures_getStringByKey(theBundle, "testinclude",&strLen,&status);
+ const UChar* uSrc = str;
+ int32_t uSrcLen = strLen;
+ int32_t wDestLen =0, reqLen=0, i=0;
+ int32_t uDestLen =0;
+ wchar_t* wDest = NULL;
+ UChar* uDest = NULL;
+ UBool failed = FALSE;
+
+ if(U_FAILURE(status)){
+ log_err("Could not get testinclude resource from testtypes bundle. Error: %s\n",u_errorName(status));
+ return;
+ }
+
+ /* pre-flight*/
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&status);
+
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status=U_ZERO_ERROR;
+ wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1));
+ wDestLen = reqLen+1;
+ u_strToWCS(wDest,wDestLen,&reqLen,uSrc,-1,&status);
+ }
+ uDestLen = 0;
+ /* pre-flight */
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&status);
+
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status =U_ZERO_ERROR;
+ uDest = (UChar*) malloc(sizeof(UChar) * (reqLen+1));
+ uDestLen = reqLen + 1;
+ u_strFromWCS(uDest, uDestLen,&reqLen,wDest,-1,&status);
+ }
+
+
+ for(i=0; i< uSrcLen; i++){
+ if(uDest[i] != str[i]){
+ log_verbose("u_str*WCS() failed for null terminated string expected: \\u%04X got: \\u%04X at index: %i \n", src16j[i] ,uDest[i],i);
+ failed =TRUE;
+ }
+ }
+
+ if(U_FAILURE(status)){
+ failed = TRUE;
+ }
+ if(failed){
+ log_err("u_strToWCS() failed \n");
+ }
+ free(wDest);
+ free(uDest);
+ /* close the bundle */
+ ures_close(theBundle);
+#else
+ log_info("Not testing u_str*WCS because (!UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION) and wchar is neither utf16 nor utf32");
+#endif
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c
new file mode 100644
index 00000000000..76cae0be6d7
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/custrtst.c
@@ -0,0 +1,1817 @@
+/*
+******************************************************************************
+*
+* Copyright (C) 2002-2006, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+******************************************************************************
+* file name: custrtst.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2002oct09
+* created by: Markus W. Scherer
+*
+* Tests of ustring.h Unicode string API functions.
+*/
+
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "unicode/uiter.h"
+#include "cintltst.h"
+#include <string.h>
+
+#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
+
+/* get the sign of an integer */
+#define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1)
+
+/* test setup --------------------------------------------------------------- */
+
+static void setUpDataTable(void);
+static void TestStringCopy(void);
+static void TestStringFunctions(void);
+static void TestStringSearching(void);
+static void TestSurrogateSearching(void);
+static void TestUnescape(void);
+static void TestCountChar32(void);
+static void TestUCharIterator(void);
+static void TestUNormIterator(void);
+static void TestBadUNormIterator(void);
+
+void addUStringTest(TestNode** root);
+
+void addUStringTest(TestNode** root)
+{
+ addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy");
+ addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions");
+ addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching");
+ addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearching");
+ addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape");
+ addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32");
+ addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator");
+ addTest(root, &TestUNormIterator, "tsutil/custrtst/TestUNormIterator");
+ addTest(root, &TestBadUNormIterator, "tsutil/custrtst/TestBadUNormIterator");
+}
+
+/* test data for TestStringFunctions ---------------------------------------- */
+
+UChar*** dataTable = NULL;
+
+static const char* raw[3][4] = {
+
+ /* First String */
+ { "English_", "French_", "Croatian_", "English_"},
+ /* Second String */
+ { "United States", "France", "Croatia", "Unites States"},
+
+ /* Concatenated string */
+ { "English_United States", "French_France", "Croatian_Croatia", "English_United States"}
+};
+
+static void setUpDataTable()
+{
+ int32_t i,j;
+ if(dataTable == NULL) {
+ dataTable = (UChar***)calloc(sizeof(UChar**),3);
+
+ for (i = 0; i < 3; i++) {
+ dataTable[i] = (UChar**)calloc(sizeof(UChar*),4);
+ for (j = 0; j < 4; j++){
+ dataTable[i][j] = (UChar*) malloc(sizeof(UChar)*(strlen(raw[i][j])+1));
+ u_uastrcpy(dataTable[i][j],raw[i][j]);
+ }
+ }
+ }
+}
+
+static void cleanUpDataTable()
+{
+ int32_t i,j;
+ if(dataTable != NULL) {
+ for (i=0; i<3; i++) {
+ for(j = 0; j<4; j++) {
+ free(dataTable[i][j]);
+ }
+ free(dataTable[i]);
+ }
+ free(dataTable);
+ }
+ dataTable = NULL;
+}
+
+/*Tests for u_strcat(),u_strcmp(), u_strlen(), u_strcpy(),u_strncat(),u_strncmp(),u_strncpy, u_uastrcpy(),u_austrcpy(), u_uastrncpy(); */
+static void TestStringFunctions()
+{
+ int32_t i,j,k;
+ UChar temp[512];
+ UChar nullTemp[512];
+ char test[512];
+ char tempOut[512];
+
+ setUpDataTable();
+
+ log_verbose("Testing u_strlen()\n");
+ if( u_strlen(dataTable[0][0])!= u_strlen(dataTable[0][3]) || u_strlen(dataTable[0][0]) == u_strlen(dataTable[0][2]))
+ log_err("There is an error in u_strlen()");
+
+ log_verbose("Testing u_memcpy() and u_memcmp()\n");
+
+ for(i=0;i<3;++i)
+ {
+ for(j=0;j<4;++j)
+ {
+ log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j]));
+ temp[0] = 0;
+ temp[7] = 0xA4; /* Mark the end */
+ u_memcpy(temp,dataTable[i][j], 7);
+
+ if(temp[7] != 0xA4)
+ log_err("an error occured in u_memcpy()\n");
+ if(u_memcmp(temp, dataTable[i][j], 7)!=0)
+ log_err("an error occured in u_memcpy() or u_memcmp()\n");
+ }
+ }
+ if(u_memcmp(dataTable[0][0], dataTable[1][1], 7)==0)
+ log_err("an error occured in u_memcmp()\n");
+
+ log_verbose("Testing u_memset()\n");
+ nullTemp[0] = 0;
+ nullTemp[7] = 0;
+ u_memset(nullTemp, 0xa4, 7);
+ for (i = 0; i < 7; i++) {
+ if(nullTemp[i] != 0xa4) {
+ log_err("an error occured in u_memset()\n");
+ }
+ }
+ if(nullTemp[7] != 0) {
+ log_err("u_memset() went too far\n");
+ }
+
+ u_memset(nullTemp, 0, 7);
+ nullTemp[7] = 0xa4;
+ temp[7] = 0;
+ u_memcpy(temp,nullTemp, 7);
+ if(u_memcmp(temp, nullTemp, 7)!=0 || temp[7]!=0)
+ log_err("an error occured in u_memcpy() or u_memcmp()\n");
+
+
+ log_verbose("Testing u_memmove()\n");
+ for (i = 0; i < 7; i++) {
+ temp[i] = (UChar)i;
+ }
+ u_memmove(temp + 1, temp, 7);
+ if(temp[0] != 0) {
+ log_err("an error occured in u_memmove()\n");
+ }
+ for (i = 1; i <= 7; i++) {
+ if(temp[i] != (i - 1)) {
+ log_err("an error occured in u_memmove()\n");
+ }
+ }
+
+ log_verbose("Testing u_strcpy() and u_strcmp()\n");
+
+ for(i=0;i<3;++i)
+ {
+ for(j=0;j<4;++j)
+ {
+ log_verbose("Testing %s\n", u_austrcpy(tempOut, dataTable[i][j]));
+ temp[0] = 0;
+ u_strcpy(temp,dataTable[i][j]);
+
+ if(u_strcmp(temp,dataTable[i][j])!=0)
+ log_err("something threw an error in u_strcpy() or u_strcmp()\n");
+ }
+ }
+ if(u_strcmp(dataTable[0][0], dataTable[1][1])==0)
+ log_err("an error occured in u_memcmp()\n");
+
+ log_verbose("testing u_strcat()\n");
+ i=0;
+ for(j=0; j<2;++j)
+ {
+ u_uastrcpy(temp, "");
+ u_strcpy(temp,dataTable[i][j]);
+ u_strcat(temp,dataTable[i+1][j]);
+ if(u_strcmp(temp,dataTable[i+2][j])!=0)
+ log_err("something threw an error in u_strcat()\n");
+
+ }
+ log_verbose("Testing u_strncmp()\n");
+ for(i=0,j=0;j<4; ++j)
+ {
+ k=u_strlen(dataTable[i][j]);
+ if(u_strncmp(dataTable[i][j],dataTable[i+2][j],k)!=0)
+ log_err("Something threw an error in u_strncmp\n");
+ }
+ if(u_strncmp(dataTable[0][0], dataTable[1][1], 7)==0)
+ log_err("an error occured in u_memcmp()\n");
+
+
+ log_verbose("Testing u_strncat\n");
+ for(i=0,j=0;j<4; ++j)
+ {
+ k=u_strlen(dataTable[i][j]);
+
+ u_uastrcpy(temp,"");
+
+ if(u_strcmp(u_strncat(temp,dataTable[i+2][j],k),dataTable[i][j])!=0)
+ log_err("something threw an error in u_strncat or u_uastrcpy()\n");
+
+ }
+
+ log_verbose("Testing u_strncpy() and u_uastrcpy()\n");
+ for(i=2,j=0;j<4; ++j)
+ {
+ k=u_strlen(dataTable[i][j]);
+ u_strncpy(temp, dataTable[i][j],k);
+ temp[k] = 0xa4;
+
+ if(u_strncmp(temp, dataTable[i][j],k)!=0)
+ log_err("something threw an error in u_strncpy()\n");
+
+ if(temp[k] != 0xa4)
+ log_err("something threw an error in u_strncpy()\n");
+
+ u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
+ u_uastrncpy(temp, raw[i][j], k-1);
+ if(u_strncmp(temp, dataTable[i][j],k-1)!=0)
+ log_err("something threw an error in u_uastrncpy(k-1)\n");
+
+ if(temp[k-1] != 0x3F)
+ log_err("something threw an error in u_uastrncpy(k-1)\n");
+
+ u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
+ u_uastrncpy(temp, raw[i][j], k+1);
+ if(u_strcmp(temp, dataTable[i][j])!=0)
+ log_err("something threw an error in u_uastrncpy(k+1)\n");
+
+ if(temp[k] != 0)
+ log_err("something threw an error in u_uastrncpy(k+1)\n");
+
+ u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
+ u_uastrncpy(temp, raw[i][j], k);
+ if(u_strncmp(temp, dataTable[i][j], k)!=0)
+ log_err("something threw an error in u_uastrncpy(k)\n");
+
+ if(temp[k] != 0x3F)
+ log_err("something threw an error in u_uastrncpy(k)\n");
+ }
+
+ log_verbose("Testing u_strchr() and u_memchr()\n");
+
+ for(i=2,j=0;j<4;j++)
+ {
+ UChar saveVal = dataTable[i][j][0];
+ UChar *findPtr = u_strchr(dataTable[i][j], 0x005F);
+ int32_t dataSize = (int32_t)(u_strlen(dataTable[i][j]) + 1);
+
+ log_verbose("%s ", u_austrcpy(tempOut, findPtr));
+
+ if (findPtr == NULL || *findPtr != 0x005F) {
+ log_err("u_strchr can't find '_' in the string\n");
+ }
+
+ findPtr = u_strchr32(dataTable[i][j], 0x005F);
+ if (findPtr == NULL || *findPtr != 0x005F) {
+ log_err("u_strchr32 can't find '_' in the string\n");
+ }
+
+ findPtr = u_strchr(dataTable[i][j], 0);
+ if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
+ log_err("u_strchr can't find NULL in the string\n");
+ }
+
+ findPtr = u_strchr32(dataTable[i][j], 0);
+ if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
+ log_err("u_strchr32 can't find NULL in the string\n");
+ }
+
+ findPtr = u_memchr(dataTable[i][j], 0, dataSize);
+ if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
+ log_err("u_memchr can't find NULL in the string\n");
+ }
+
+ findPtr = u_memchr32(dataTable[i][j], 0, dataSize);
+ if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
+ log_err("u_memchr32 can't find NULL in the string\n");
+ }
+
+ dataTable[i][j][0] = 0;
+ /* Make sure we skip over the NULL termination */
+ findPtr = u_memchr(dataTable[i][j], 0x005F, dataSize);
+ if (findPtr == NULL || *findPtr != 0x005F) {
+ log_err("u_memchr can't find '_' in the string\n");
+ }
+
+ findPtr = u_memchr32(dataTable[i][j], 0x005F, dataSize);
+ if (findPtr == NULL || *findPtr != 0x005F) {
+ log_err("u_memchr32 can't find '_' in the string\n");
+ }
+ findPtr = u_memchr32(dataTable[i][j], 0xFFFD, dataSize);
+ if (findPtr != NULL) {
+ log_err("Should have found NULL when the character is not there.\n");
+ }
+ dataTable[i][j][0] = saveVal; /* Put it back for the other tests */
+ }
+
+ /*
+ * test that u_strchr32()
+ * does not find surrogate code points when they are part of matched pairs
+ * (= part of supplementary code points)
+ * Jitterbug 1542
+ */
+ {
+ static const UChar s[]={
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ 0x0061, 0xd841, 0xdc02, 0xd841, 0x0062, 0xdc02, 0xd841, 0xdc02, 0x0063, 0
+ };
+
+ if(u_strchr32(s, 0xd841)!=(s+3) || u_strchr32(s, 0xdc02)!=(s+5)) {
+ log_err("error: u_strchr32(surrogate) finds a partial supplementary code point\n");
+ }
+ if(u_memchr32(s, 0xd841, 9)!=(s+3) || u_memchr32(s, 0xdc02, 9)!=(s+5)) {
+ log_err("error: u_memchr32(surrogate) finds a partial supplementary code point\n");
+ }
+ }
+
+ log_verbose("Testing u_austrcpy()");
+ u_austrcpy(test,dataTable[0][0]);
+ if(strcmp(test,raw[0][0])!=0)
+ log_err("There is an error in u_austrcpy()");
+
+
+ log_verbose("Testing u_strtok_r()");
+ {
+ const char tokString[] = " , 1 2 3 AHHHHH! 5.5 6 7 , 8\n";
+ const char *tokens[] = {",", "1", "2", "3", "AHHHHH!", "5.5", "6", "7", "8\n"};
+ UChar delimBuf[sizeof(test)];
+ UChar currTokenBuf[sizeof(tokString)];
+ UChar *state;
+ uint32_t currToken = 0;
+ UChar *ptr;
+
+ u_uastrcpy(temp, tokString);
+ u_uastrcpy(delimBuf, " ");
+
+ ptr = u_strtok_r(temp, delimBuf, &state);
+ u_uastrcpy(delimBuf, " ,");
+ while (ptr != NULL) {
+ u_uastrcpy(currTokenBuf, tokens[currToken]);
+ if (u_strcmp(ptr, currTokenBuf) != 0) {
+ log_err("u_strtok_r mismatch at %d. Got: %s, Expected: %s\n", currToken, ptr, tokens[currToken]);
+ }
+ ptr = u_strtok_r(NULL, delimBuf, &state);
+ currToken++;
+ }
+
+ if (currToken != sizeof(tokens)/sizeof(tokens[0])) {
+ log_err("Didn't get correct number of tokens\n");
+ }
+ state = delimBuf; /* Give it an "invalid" saveState */
+ u_uastrcpy(currTokenBuf, "");
+ if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
+ log_err("Didn't get NULL for empty string\n");
+ }
+ if (state != NULL) {
+ log_err("State should be NULL for empty string\n");
+ }
+ state = delimBuf; /* Give it an "invalid" saveState */
+ u_uastrcpy(currTokenBuf, ", ,");
+ if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
+ log_err("Didn't get NULL for a string of delimiters\n");
+ }
+ if (state != NULL) {
+ log_err("State should be NULL for a string of delimiters\n");
+ }
+
+ state = delimBuf; /* Give it an "invalid" saveState */
+ u_uastrcpy(currTokenBuf, "q, ,");
+ if (u_strtok_r(currTokenBuf, delimBuf, &state) == NULL) {
+ log_err("Got NULL for a string that does not begin with delimiters\n");
+ }
+ if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
+ log_err("Didn't get NULL for a string that ends in delimiters\n");
+ }
+ if (state != NULL) {
+ log_err("State should be NULL for empty string\n");
+ }
+
+ state = delimBuf; /* Give it an "invalid" saveState */
+ u_uastrcpy(currTokenBuf, tokString);
+ u_uastrcpy(temp, tokString);
+ u_uastrcpy(delimBuf, "q"); /* Give it a delimiter that it can't find. */
+ ptr = u_strtok_r(currTokenBuf, delimBuf, &state);
+ if (ptr == NULL || u_strcmp(ptr, temp) != 0) {
+ log_err("Should have recieved the same string when there are no delimiters\n");
+ }
+ if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
+ log_err("Should not have found another token in a one token string\n");
+ }
+ }
+
+ /* test u_strcmpCodePointOrder() */
+ {
+ /* these strings are in ascending order */
+ static const UChar strings[][4]={
+ { 0x61, 0 }, /* U+0061 */
+ { 0x20ac, 0xd801, 0 }, /* U+20ac U+d801 */
+ { 0x20ac, 0xd800, 0xdc00, 0 }, /* U+20ac U+10000 */
+ { 0xd800, 0 }, /* U+d800 */
+ { 0xd800, 0xff61, 0 }, /* U+d800 U+ff61 */
+ { 0xdfff, 0 }, /* U+dfff */
+ { 0xff61, 0xdfff, 0 }, /* U+ff61 U+dfff */
+ { 0xff61, 0xd800, 0xdc02, 0 }, /* U+ff61 U+10002 */
+ { 0xd800, 0xdc02, 0 }, /* U+10002 */
+ { 0xd84d, 0xdc56, 0 } /* U+23456 */
+ };
+
+ UCharIterator iter1, iter2;
+ int32_t len1, len2, r1, r2;
+
+ for(i=0; i<(sizeof(strings)/sizeof(strings[0])-1); ++i) {
+ if(u_strcmpCodePointOrder(strings[i], strings[i+1])>=0) {
+ log_err("error: u_strcmpCodePointOrder() fails for string %d and the following one\n", i);
+ }
+ if(u_strncmpCodePointOrder(strings[i], strings[i+1], 10)>=0) {
+ log_err("error: u_strncmpCodePointOrder() fails for string %d and the following one\n", i);
+ }
+
+ /* There are at least 2 UChars in each string - verify that strncmp()==memcmp(). */
+ if(u_strncmpCodePointOrder(strings[i], strings[i+1], 2)!=u_memcmpCodePointOrder(strings[i], strings[i+1], 2)) {
+ log_err("error: u_strncmpCodePointOrder(2)!=u_memcmpCodePointOrder(2) for string %d and the following one\n", i);
+ }
+
+ /* test u_strCompare(TRUE) */
+ len1=u_strlen(strings[i]);
+ len2=u_strlen(strings[i+1]);
+ if( u_strCompare(strings[i], -1, strings[i+1], -1, TRUE)>=0 ||
+ u_strCompare(strings[i], -1, strings[i+1], len2, TRUE)>=0 ||
+ u_strCompare(strings[i], len1, strings[i+1], -1, TRUE)>=0 ||
+ u_strCompare(strings[i], len1, strings[i+1], len2, TRUE)>=0
+ ) {
+ log_err("error: u_strCompare(code point order) fails for string %d and the following one\n", i);
+ }
+
+ /* test u_strCompare(FALSE) */
+ r1=u_strCompare(strings[i], -1, strings[i+1], -1, FALSE);
+ r2=u_strcmp(strings[i], strings[i+1]);
+ if(_SIGN(r1)!=_SIGN(r2)) {
+ log_err("error: u_strCompare(code unit order)!=u_strcmp() for string %d and the following one\n", i);
+ }
+
+ /* test u_strCompareIter() */
+ uiter_setString(&iter1, strings[i], len1);
+ uiter_setString(&iter2, strings[i+1], len2);
+ if(u_strCompareIter(&iter1, &iter2, TRUE)>=0) {
+ log_err("error: u_strCompareIter(code point order) fails for string %d and the following one\n", i);
+ }
+ r1=u_strCompareIter(&iter1, &iter2, FALSE);
+ if(_SIGN(r1)!=_SIGN(u_strcmp(strings[i], strings[i+1]))) {
+ log_err("error: u_strCompareIter(code unit order)!=u_strcmp() for string %d and the following one\n", i);
+ }
+ }
+ }
+
+ cleanUpDataTable();
+}
+
+static void TestStringSearching()
+{
+ const UChar testString[] = {0x0061, 0x0062, 0x0063, 0x0064, 0x0064, 0x0061, 0};
+ const UChar testSurrogateString[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0x0063, 0x0064, 0x0064, 0xdbff, 0xdfff, 0xdb00, 0xdf00, 0x0061, 0};
+ const UChar surrMatchSet1[] = {0xdbff, 0xdfff, 0};
+ const UChar surrMatchSet2[] = {0x0061, 0x0062, 0xdbff, 0xdfff, 0};
+ const UChar surrMatchSet3[] = {0xdb00, 0xdf00, 0xdbff, 0xdfff, 0};
+ const UChar surrMatchSet4[] = {0x0000};
+ const UChar surrMatchSetBad[] = {0xdbff, 0x0061, 0};
+ const UChar surrMatchSetBad2[] = {0x0061, 0xdbff, 0};
+ const UChar surrMatchSetBad3[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0}; /* has partial surrogate */
+ const UChar
+ empty[] = { 0 },
+ a[] = { 0x61, 0 },
+ ab[] = { 0x61, 0x62, 0 },
+ ba[] = { 0x62, 0x61, 0 },
+ abcd[] = { 0x61, 0x62, 0x63, 0x64, 0 },
+ cd[] = { 0x63, 0x64, 0 },
+ dc[] = { 0x64, 0x63, 0 },
+ cdh[] = { 0x63, 0x64, 0x68, 0 },
+ f[] = { 0x66, 0 },
+ fg[] = { 0x66, 0x67, 0 },
+ gf[] = { 0x67, 0x66, 0 };
+
+ log_verbose("Testing u_strpbrk()");
+
+ if (u_strpbrk(testString, a) != &testString[0]) {
+ log_err("u_strpbrk couldn't find first letter a.\n");
+ }
+ if (u_strpbrk(testString, dc) != &testString[2]) {
+ log_err("u_strpbrk couldn't find d or c.\n");
+ }
+ if (u_strpbrk(testString, cd) != &testString[2]) {
+ log_err("u_strpbrk couldn't find c or d.\n");
+ }
+ if (u_strpbrk(testString, cdh) != &testString[2]) {
+ log_err("u_strpbrk couldn't find c, d or h.\n");
+ }
+ if (u_strpbrk(testString, f) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"f\".\n");
+ }
+ if (u_strpbrk(testString, fg) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"fg\".\n");
+ }
+ if (u_strpbrk(testString, gf) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"gf\".\n");
+ }
+ if (u_strpbrk(testString, empty) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"\".\n");
+ }
+
+ log_verbose("Testing u_strpbrk() with surrogates");
+
+ if (u_strpbrk(testSurrogateString, a) != &testSurrogateString[1]) {
+ log_err("u_strpbrk couldn't find first letter a.\n");
+ }
+ if (u_strpbrk(testSurrogateString, dc) != &testSurrogateString[5]) {
+ log_err("u_strpbrk couldn't find d or c.\n");
+ }
+ if (u_strpbrk(testSurrogateString, cd) != &testSurrogateString[5]) {
+ log_err("u_strpbrk couldn't find c or d.\n");
+ }
+ if (u_strpbrk(testSurrogateString, cdh) != &testSurrogateString[5]) {
+ log_err("u_strpbrk couldn't find c, d or h.\n");
+ }
+ if (u_strpbrk(testSurrogateString, f) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"f\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, fg) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"fg\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, gf) != NULL) {
+ log_err("u_strpbrk didn't return NULL for \"gf\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, surrMatchSet1) != &testSurrogateString[3]) {
+ log_err("u_strpbrk couldn't find \"0xdbff, 0xdfff\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, surrMatchSet2) != &testSurrogateString[1]) {
+ log_err("u_strpbrk couldn't find \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, surrMatchSet3) != &testSurrogateString[3]) {
+ log_err("u_strpbrk couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
+ }
+ if (u_strpbrk(testSurrogateString, surrMatchSet4) != NULL) {
+ log_err("u_strpbrk should have returned NULL for empty string.\n");
+ }
+ if (u_strpbrk(testSurrogateString, surrMatchSetBad) != &testSurrogateString[0]) {
+ log_err("u_strpbrk should have found bad surrogate.\n");
+ }
+
+ log_verbose("Testing u_strcspn()");
+
+ if (u_strcspn(testString, a) != 0) {
+ log_err("u_strcspn couldn't find first letter a.\n");
+ }
+ if (u_strcspn(testString, dc) != 2) {
+ log_err("u_strcspn couldn't find d or c.\n");
+ }
+ if (u_strcspn(testString, cd) != 2) {
+ log_err("u_strcspn couldn't find c or d.\n");
+ }
+ if (u_strcspn(testString, cdh) != 2) {
+ log_err("u_strcspn couldn't find c, d or h.\n");
+ }
+ if (u_strcspn(testString, f) != u_strlen(testString)) {
+ log_err("u_strcspn didn't return NULL for \"f\".\n");
+ }
+ if (u_strcspn(testString, fg) != u_strlen(testString)) {
+ log_err("u_strcspn didn't return NULL for \"fg\".\n");
+ }
+ if (u_strcspn(testString, gf) != u_strlen(testString)) {
+ log_err("u_strcspn didn't return NULL for \"gf\".\n");
+ }
+
+ log_verbose("Testing u_strcspn() with surrogates");
+
+ if (u_strcspn(testSurrogateString, a) != 1) {
+ log_err("u_strcspn couldn't find first letter a.\n");
+ }
+ if (u_strcspn(testSurrogateString, dc) != 5) {
+ log_err("u_strcspn couldn't find d or c.\n");
+ }
+ if (u_strcspn(testSurrogateString, cd) != 5) {
+ log_err("u_strcspn couldn't find c or d.\n");
+ }
+ if (u_strcspn(testSurrogateString, cdh) != 5) {
+ log_err("u_strcspn couldn't find c, d or h.\n");
+ }
+ if (u_strcspn(testSurrogateString, f) != u_strlen(testSurrogateString)) {
+ log_err("u_strcspn didn't return NULL for \"f\".\n");
+ }
+ if (u_strcspn(testSurrogateString, fg) != u_strlen(testSurrogateString)) {
+ log_err("u_strcspn didn't return NULL for \"fg\".\n");
+ }
+ if (u_strcspn(testSurrogateString, gf) != u_strlen(testSurrogateString)) {
+ log_err("u_strcspn didn't return NULL for \"gf\".\n");
+ }
+ if (u_strcspn(testSurrogateString, surrMatchSet1) != 3) {
+ log_err("u_strcspn couldn't find \"0xdbff, 0xdfff\".\n");
+ }
+ if (u_strcspn(testSurrogateString, surrMatchSet2) != 1) {
+ log_err("u_strcspn couldn't find \"a, b, 0xdbff, 0xdfff\".\n");
+ }
+ if (u_strcspn(testSurrogateString, surrMatchSet3) != 3) {
+ log_err("u_strcspn couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
+ }
+ if (u_strcspn(testSurrogateString, surrMatchSet4) != u_strlen(testSurrogateString)) {
+ log_err("u_strcspn should have returned strlen for empty string.\n");
+ }
+
+
+ log_verbose("Testing u_strspn()");
+
+ if (u_strspn(testString, a) != 1) {
+ log_err("u_strspn couldn't skip first letter a.\n");
+ }
+ if (u_strspn(testString, ab) != 2) {
+ log_err("u_strspn couldn't skip a or b.\n");
+ }
+ if (u_strspn(testString, ba) != 2) {
+ log_err("u_strspn couldn't skip a or b.\n");
+ }
+ if (u_strspn(testString, f) != 0) {
+ log_err("u_strspn didn't return 0 for \"f\".\n");
+ }
+ if (u_strspn(testString, dc) != 0) {
+ log_err("u_strspn couldn't find first letter a (skip d or c).\n");
+ }
+ if (u_strspn(testString, abcd) != u_strlen(testString)) {
+ log_err("u_strspn couldn't skip over the whole string.\n");
+ }
+ if (u_strspn(testString, empty) != 0) {
+ log_err("u_strspn should have returned 0 for empty string.\n");
+ }
+
+ log_verbose("Testing u_strspn() with surrogates");
+ if (u_strspn(testSurrogateString, surrMatchSetBad) != 2) {
+ log_err("u_strspn couldn't skip 0xdbff or a.\n");
+ }
+ if (u_strspn(testSurrogateString, surrMatchSetBad2) != 2) {
+ log_err("u_strspn couldn't skip 0xdbff or a.\n");
+ }
+ if (u_strspn(testSurrogateString, f) != 0) {
+ log_err("u_strspn couldn't skip d or c (skip first letter).\n");
+ }
+ if (u_strspn(testSurrogateString, dc) != 0) {
+ log_err("u_strspn couldn't skip d or c (skip first letter).\n");
+ }
+ if (u_strspn(testSurrogateString, cd) != 0) {
+ log_err("u_strspn couldn't skip d or c (skip first letter).\n");
+ }
+ if (u_strspn(testSurrogateString, testSurrogateString) != u_strlen(testSurrogateString)) {
+ log_err("u_strspn couldn't skip whole string.\n");
+ }
+ if (u_strspn(testSurrogateString, surrMatchSet1) != 0) {
+ log_err("u_strspn couldn't skip \"0xdbff, 0xdfff\" (get first letter).\n");
+ }
+ if (u_strspn(testSurrogateString, surrMatchSetBad3) != 5) {
+ log_err("u_strspn couldn't skip \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
+ }
+ if (u_strspn(testSurrogateString, surrMatchSet4) != 0) {
+ log_err("u_strspn should have returned 0 for empty string.\n");
+ }
+}
+
+/*
+ * All binary Unicode string searches should behave the same for equivalent input.
+ * See Jitterbug 2145.
+ * There are some new functions, too - just test them all.
+ */
+static void
+TestSurrogateSearching() {
+ static const UChar s[]={
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 */
+ 0x61, 0xd801, 0xdc02, 0x61, 0xdc02, 0x61, 0xd801, 0x61, 0xd801, 0xdc02, 0x61, 0
+ }, sub_a[]={
+ 0x61, 0
+ }, sub_b[]={
+ 0x62, 0
+ }, sub_lead[]={
+ 0xd801, 0
+ }, sub_trail[]={
+ 0xdc02, 0
+ }, sub_supp[]={
+ 0xd801, 0xdc02, 0
+ }, sub_supp2[]={
+ 0xd801, 0xdc03, 0
+ }, sub_a_lead[]={
+ 0x61, 0xd801, 0
+ }, sub_trail_a[]={
+ 0xdc02, 0x61, 0
+ }, sub_aba[]={
+ 0x61, 0x62, 0x61, 0
+ };
+ static const UChar a=0x61, b=0x62, lead=0xd801, trail=0xdc02, nul=0;
+ static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456;
+
+ const UChar *first, *last;
+
+ /* search for NUL code point: find end of string */
+ first=s+u_strlen(s);
+
+ if(
+ first!=u_strchr(s, nul) ||
+ first!=u_strchr32(s, nul) ||
+ first!=u_memchr(s, nul, LENGTHOF(s)) ||
+ first!=u_memchr32(s, nul, LENGTHOF(s)) ||
+ first!=u_strrchr(s, nul) ||
+ first!=u_strrchr32(s, nul) ||
+ first!=u_memrchr(s, nul, LENGTHOF(s)) ||
+ first!=u_memrchr32(s, nul, LENGTHOF(s))
+ ) {
+ log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find the terminator of s\n");
+ }
+
+ /* search for empty substring: find beginning of string */
+ if(
+ s!=u_strstr(s, &nul) ||
+ s!=u_strFindFirst(s, -1, &nul, -1) ||
+ s!=u_strFindFirst(s, -1, &nul, 0) ||
+ s!=u_strFindFirst(s, LENGTHOF(s), &nul, -1) ||
+ s!=u_strFindFirst(s, LENGTHOF(s), &nul, 0) ||
+ s!=u_strrstr(s, &nul) ||
+ s!=u_strFindLast(s, -1, &nul, -1) ||
+ s!=u_strFindLast(s, -1, &nul, 0) ||
+ s!=u_strFindLast(s, LENGTHOF(s), &nul, -1) ||
+ s!=u_strFindLast(s, LENGTHOF(s), &nul, 0)
+ ) {
+ log_err("error: one of the u_str[str etc](s, \"\") does not find s itself\n");
+ }
+
+ /* find 'a' in s[1..10[ */
+ first=s+3;
+ last=s+7;
+ if(
+ first!=u_strchr(s+1, a) ||
+ first!=u_strchr32(s+1, a) ||
+ first!=u_memchr(s+1, a, 9) ||
+ first!=u_memchr32(s+1, a, 9) ||
+ first!=u_strstr(s+1, sub_a) ||
+ first!=u_strFindFirst(s+1, -1, sub_a, -1) ||
+ first!=u_strFindFirst(s+1, -1, &a, 1) ||
+ first!=u_strFindFirst(s+1, 9, sub_a, -1) ||
+ first!=u_strFindFirst(s+1, 9, &a, 1) ||
+ (s+10)!=u_strrchr(s+1, a) ||
+ (s+10)!=u_strrchr32(s+1, a) ||
+ last!=u_memrchr(s+1, a, 9) ||
+ last!=u_memrchr32(s+1, a, 9) ||
+ (s+10)!=u_strrstr(s+1, sub_a) ||
+ (s+10)!=u_strFindLast(s+1, -1, sub_a, -1) ||
+ (s+10)!=u_strFindLast(s+1, -1, &a, 1) ||
+ last!=u_strFindLast(s+1, 9, sub_a, -1) ||
+ last!=u_strFindLast(s+1, 9, &a, 1)
+ ) {
+ log_err("error: one of the u_str[chr etc]('a') does not find the correct place\n");
+ }
+
+ /* do not find 'b' in s[1..10[ */
+ if(
+ NULL!=u_strchr(s+1, b) ||
+ NULL!=u_strchr32(s+1, b) ||
+ NULL!=u_memchr(s+1, b, 9) ||
+ NULL!=u_memchr32(s+1, b, 9) ||
+ NULL!=u_strstr(s+1, sub_b) ||
+ NULL!=u_strFindFirst(s+1, -1, sub_b, -1) ||
+ NULL!=u_strFindFirst(s+1, -1, &b, 1) ||
+ NULL!=u_strFindFirst(s+1, 9, sub_b, -1) ||
+ NULL!=u_strFindFirst(s+1, 9, &b, 1) ||
+ NULL!=u_strrchr(s+1, b) ||
+ NULL!=u_strrchr32(s+1, b) ||
+ NULL!=u_memrchr(s+1, b, 9) ||
+ NULL!=u_memrchr32(s+1, b, 9) ||
+ NULL!=u_strrstr(s+1, sub_b) ||
+ NULL!=u_strFindLast(s+1, -1, sub_b, -1) ||
+ NULL!=u_strFindLast(s+1, -1, &b, 1) ||
+ NULL!=u_strFindLast(s+1, 9, sub_b, -1) ||
+ NULL!=u_strFindLast(s+1, 9, &b, 1)
+ ) {
+ log_err("error: one of the u_str[chr etc]('b') incorrectly finds something\n");
+ }
+
+ /* do not find a non-code point in s[1..10[ */
+ if(
+ NULL!=u_strchr32(s+1, ill) ||
+ NULL!=u_memchr32(s+1, ill, 9) ||
+ NULL!=u_strrchr32(s+1, ill) ||
+ NULL!=u_memrchr32(s+1, ill, 9)
+ ) {
+ log_err("error: one of the u_str[chr etc](illegal code point) incorrectly finds something\n");
+ }
+
+ /* find U+d801 in s[1..10[ */
+ first=s+6;
+ if(
+ first!=u_strchr(s+1, lead) ||
+ first!=u_strchr32(s+1, lead) ||
+ first!=u_memchr(s+1, lead, 9) ||
+ first!=u_memchr32(s+1, lead, 9) ||
+ first!=u_strstr(s+1, sub_lead) ||
+ first!=u_strFindFirst(s+1, -1, sub_lead, -1) ||
+ first!=u_strFindFirst(s+1, -1, &lead, 1) ||
+ first!=u_strFindFirst(s+1, 9, sub_lead, -1) ||
+ first!=u_strFindFirst(s+1, 9, &lead, 1) ||
+ first!=u_strrchr(s+1, lead) ||
+ first!=u_strrchr32(s+1, lead) ||
+ first!=u_memrchr(s+1, lead, 9) ||
+ first!=u_memrchr32(s+1, lead, 9) ||
+ first!=u_strrstr(s+1, sub_lead) ||
+ first!=u_strFindLast(s+1, -1, sub_lead, -1) ||
+ first!=u_strFindLast(s+1, -1, &lead, 1) ||
+ first!=u_strFindLast(s+1, 9, sub_lead, -1) ||
+ first!=u_strFindLast(s+1, 9, &lead, 1)
+ ) {
+ log_err("error: one of the u_str[chr etc](U+d801) does not find the correct place\n");
+ }
+
+ /* find U+dc02 in s[1..10[ */
+ first=s+4;
+ if(
+ first!=u_strchr(s+1, trail) ||
+ first!=u_strchr32(s+1, trail) ||
+ first!=u_memchr(s+1, trail, 9) ||
+ first!=u_memchr32(s+1, trail, 9) ||
+ first!=u_strstr(s+1, sub_trail) ||
+ first!=u_strFindFirst(s+1, -1, sub_trail, -1) ||
+ first!=u_strFindFirst(s+1, -1, &trail, 1) ||
+ first!=u_strFindFirst(s+1, 9, sub_trail, -1) ||
+ first!=u_strFindFirst(s+1, 9, &trail, 1) ||
+ first!=u_strrchr(s+1, trail) ||
+ first!=u_strrchr32(s+1, trail) ||
+ first!=u_memrchr(s+1, trail, 9) ||
+ first!=u_memrchr32(s+1, trail, 9) ||
+ first!=u_strrstr(s+1, sub_trail) ||
+ first!=u_strFindLast(s+1, -1, sub_trail, -1) ||
+ first!=u_strFindLast(s+1, -1, &trail, 1) ||
+ first!=u_strFindLast(s+1, 9, sub_trail, -1) ||
+ first!=u_strFindLast(s+1, 9, &trail, 1)
+ ) {
+ log_err("error: one of the u_str[chr etc](U+dc02) does not find the correct place\n");
+ }
+
+ /* find U+10402 in s[1..10[ */
+ first=s+1;
+ last=s+8;
+ if(
+ first!=u_strchr32(s+1, supp) ||
+ first!=u_memchr32(s+1, supp, 9) ||
+ first!=u_strstr(s+1, sub_supp) ||
+ first!=u_strFindFirst(s+1, -1, sub_supp, -1) ||
+ first!=u_strFindFirst(s+1, -1, sub_supp, 2) ||
+ first!=u_strFindFirst(s+1, 9, sub_supp, -1) ||
+ first!=u_strFindFirst(s+1, 9, sub_supp, 2) ||
+ last!=u_strrchr32(s+1, supp) ||
+ last!=u_memrchr32(s+1, supp, 9) ||
+ last!=u_strrstr(s+1, sub_supp) ||
+ last!=u_strFindLast(s+1, -1, sub_supp, -1) ||
+ last!=u_strFindLast(s+1, -1, sub_supp, 2) ||
+ last!=u_strFindLast(s+1, 9, sub_supp, -1) ||
+ last!=u_strFindLast(s+1, 9, sub_supp, 2)
+ ) {
+ log_err("error: one of the u_str[chr etc](U+10402) does not find the correct place\n");
+ }
+
+ /* do not find U+10402 in a single UChar */
+ if(
+ NULL!=u_memchr32(s+1, supp, 1) ||
+ NULL!=u_strFindFirst(s+1, 1, sub_supp, -1) ||
+ NULL!=u_strFindFirst(s+1, 1, sub_supp, 2) ||
+ NULL!=u_memrchr32(s+1, supp, 1) ||
+ NULL!=u_strFindLast(s+1, 1, sub_supp, -1) ||
+ NULL!=u_strFindLast(s+1, 1, sub_supp, 2) ||
+ NULL!=u_memrchr32(s+2, supp, 1) ||
+ NULL!=u_strFindLast(s+2, 1, sub_supp, -1) ||
+ NULL!=u_strFindLast(s+2, 1, sub_supp, 2)
+ ) {
+ log_err("error: one of the u_str[chr etc](U+10402) incorrectly finds a supplementary c.p. in a single UChar\n");
+ }
+
+ /* do not find U+10403 in s[1..10[ */
+ if(
+ NULL!=u_strchr32(s+1, supp2) ||
+ NULL!=u_memchr32(s+1, supp2, 9) ||
+ NULL!=u_strstr(s+1, sub_supp2) ||
+ NULL!=u_strFindFirst(s+1, -1, sub_supp2, -1) ||
+ NULL!=u_strFindFirst(s+1, -1, sub_supp2, 2) ||
+ NULL!=u_strFindFirst(s+1, 9, sub_supp2, -1) ||
+ NULL!=u_strFindFirst(s+1, 9, sub_supp2, 2) ||
+ NULL!=u_strrchr32(s+1, supp2) ||
+ NULL!=u_memrchr32(s+1, supp2, 9) ||
+ NULL!=u_strrstr(s+1, sub_supp2) ||
+ NULL!=u_strFindLast(s+1, -1, sub_supp2, -1) ||
+ NULL!=u_strFindLast(s+1, -1, sub_supp2, 2) ||
+ NULL!=u_strFindLast(s+1, 9, sub_supp2, -1) ||
+ NULL!=u_strFindLast(s+1, 9, sub_supp2, 2)
+ ) {
+ log_err("error: one of the u_str[chr etc](U+10403) incorrectly finds something\n");
+ }
+
+ /* find <0061 d801> in s[1..10[ */
+ first=s+5;
+ if(
+ first!=u_strstr(s+1, sub_a_lead) ||
+ first!=u_strFindFirst(s+1, -1, sub_a_lead, -1) ||
+ first!=u_strFindFirst(s+1, -1, sub_a_lead, 2) ||
+ first!=u_strFindFirst(s+1, 9, sub_a_lead, -1) ||
+ first!=u_strFindFirst(s+1, 9, sub_a_lead, 2) ||
+ first!=u_strrstr(s+1, sub_a_lead) ||
+ first!=u_strFindLast(s+1, -1, sub_a_lead, -1) ||
+ first!=u_strFindLast(s+1, -1, sub_a_lead, 2) ||
+ first!=u_strFindLast(s+1, 9, sub_a_lead, -1) ||
+ first!=u_strFindLast(s+1, 9, sub_a_lead, 2)
+ ) {
+ log_err("error: one of the u_str[str etc](<0061 d801>) does not find the correct place\n");
+ }
+
+ /* find <dc02 0061> in s[1..10[ */
+ first=s+4;
+ if(
+ first!=u_strstr(s+1, sub_trail_a) ||
+ first!=u_strFindFirst(s+1, -1, sub_trail_a, -1) ||
+ first!=u_strFindFirst(s+1, -1, sub_trail_a, 2) ||
+ first!=u_strFindFirst(s+1, 9, sub_trail_a, -1) ||
+ first!=u_strFindFirst(s+1, 9, sub_trail_a, 2) ||
+ first!=u_strrstr(s+1, sub_trail_a) ||
+ first!=u_strFindLast(s+1, -1, sub_trail_a, -1) ||
+ first!=u_strFindLast(s+1, -1, sub_trail_a, 2) ||
+ first!=u_strFindLast(s+1, 9, sub_trail_a, -1) ||
+ first!=u_strFindLast(s+1, 9, sub_trail_a, 2)
+ ) {
+ log_err("error: one of the u_str[str etc](<dc02 0061>) does not find the correct place\n");
+ }
+
+ /* do not find "aba" in s[1..10[ */
+ if(
+ NULL!=u_strstr(s+1, sub_aba) ||
+ NULL!=u_strFindFirst(s+1, -1, sub_aba, -1) ||
+ NULL!=u_strFindFirst(s+1, -1, sub_aba, 3) ||
+ NULL!=u_strFindFirst(s+1, 9, sub_aba, -1) ||
+ NULL!=u_strFindFirst(s+1, 9, sub_aba, 3) ||
+ NULL!=u_strrstr(s+1, sub_aba) ||
+ NULL!=u_strFindLast(s+1, -1, sub_aba, -1) ||
+ NULL!=u_strFindLast(s+1, -1, sub_aba, 3) ||
+ NULL!=u_strFindLast(s+1, 9, sub_aba, -1) ||
+ NULL!=u_strFindLast(s+1, 9, sub_aba, 3)
+ ) {
+ log_err("error: one of the u_str[str etc](\"aba\") incorrectly finds something\n");
+ }
+}
+
+static void TestStringCopy()
+{
+ UChar temp[40];
+ UChar *result=0;
+ UChar subString[5];
+ UChar uchars[]={0x61, 0x62, 0x63, 0x00};
+ char charOut[40];
+ char chars[]="abc"; /* needs default codepage */
+
+ log_verbose("Testing u_uastrncpy() and u_uastrcpy()");
+
+ u_uastrcpy(temp, "abc");
+ if(u_strcmp(temp, uchars) != 0) {
+ log_err("There is an error in u_uastrcpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
+ }
+
+ temp[0] = 0xFB; /* load garbage into it */
+ temp[1] = 0xFB;
+ temp[2] = 0xFB;
+ temp[3] = 0xFB;
+
+ u_uastrncpy(temp, "abcabcabc", 3);
+ if(u_strncmp(uchars, temp, 3) != 0){
+ log_err("There is an error in u_uastrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
+ }
+ if(temp[3] != 0xFB) {
+ log_err("u_uastrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
+ }
+
+ charOut[0] = (char)0x7B; /* load garbage into it */
+ charOut[1] = (char)0x7B;
+ charOut[2] = (char)0x7B;
+ charOut[3] = (char)0x7B;
+
+ temp[0] = 0x0061;
+ temp[1] = 0x0062;
+ temp[2] = 0x0063;
+ temp[3] = 0x0061;
+ temp[4] = 0x0062;
+ temp[5] = 0x0063;
+ temp[6] = 0x0000;
+
+ u_austrncpy(charOut, temp, 3);
+ if(strncmp(chars, charOut, 3) != 0){
+ log_err("There is an error in u_austrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
+ }
+ if(charOut[3] != (char)0x7B) {
+ log_err("u_austrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
+ }
+
+ /*Testing u_strchr()*/
+ log_verbose("Testing u_strchr\n");
+ temp[0]=0x42;
+ temp[1]=0x62;
+ temp[2]=0x62;
+ temp[3]=0x63;
+ temp[4]=0xd841;
+ temp[5]=0xd841;
+ temp[6]=0xdc02;
+ temp[7]=0;
+ result=u_strchr(temp, (UChar)0x62);
+ if(result != temp+1){
+ log_err("There is an error in u_strchr() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ /*Testing u_strstr()*/
+ log_verbose("Testing u_strstr\n");
+ subString[0]=0x62;
+ subString[1]=0x63;
+ subString[2]=0;
+ result=u_strstr(temp, subString);
+ if(result != temp+2){
+ log_err("There is an error in u_strstr() Expected match at position 2 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_strstr(temp, subString+2); /* subString+2 is an empty string */
+ if(result != temp){
+ log_err("There is an error in u_strstr() Expected match at position 0 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_strstr(subString, temp);
+ if(result != NULL){
+ log_err("There is an error in u_strstr() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
+ }
+
+ /*Testing u_strchr32*/
+ log_verbose("Testing u_strchr32\n");
+ result=u_strchr32(temp, (UChar32)0x62);
+ if(result != temp+1){
+ log_err("There is an error in u_strchr32() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_strchr32(temp, (UChar32)0xfb);
+ if(result != NULL){
+ log_err("There is an error in u_strchr32() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
+ }
+ result=u_strchr32(temp, (UChar32)0x20402);
+ if(result != temp+5){
+ log_err("There is an error in u_strchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+
+ temp[7]=0xfc00;
+ result=u_memchr32(temp, (UChar32)0x20402, 7);
+ if(result != temp+5){
+ log_err("There is an error in u_memchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_memchr32(temp, (UChar32)0x20402, 6);
+ if(result != NULL){
+ log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_memchr32(temp, (UChar32)0x20402, 1);
+ if(result != NULL){
+ log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+ result=u_memchr32(temp, (UChar32)0xfc00, 8);
+ if(result != temp+7){
+ log_err("There is an error in u_memchr32() Expected match at position 7 Got %ld (pointer 0x%lx)\n", result-temp, result);
+ }
+}
+
+/* test u_unescape() and u_unescapeAt() ------------------------------------- */
+
+static void
+TestUnescape() {
+ static UChar buffer[200];
+
+ static const char* input =
+ "Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\e\\cC\\n \\x1b\\x{263a}";
+
+ static const UChar expect[]={
+ 0x53, 0x63, 0x68, 0xf6, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x3a, 0x20,
+ 0x20ac, 0x20, 0x31, 0x31, 0x32, 0x34, 0x30, 0x2e, 0x0c,
+ 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x73, 0x20,
+ 0x5a, 0x65, 0x69, 0x63, 0x68, 0x65, 0x6e, 0x3a, 0x20, 0xdbc8, 0xdf45, 0x1b, 0x03, 0x0a, 0x20, 0x1b, 0x263A, 0
+ };
+ static const int32_t explength = sizeof(expect)/sizeof(expect[0])-1;
+ int32_t length;
+
+ /* test u_unescape() */
+ length=u_unescape(input, buffer, sizeof(buffer)/sizeof(buffer[0]));
+ if(length!=explength || u_strcmp(buffer, expect)!=0) {
+ log_err("failure in u_unescape(): length %d!=%d and/or incorrect result string\n", length,
+ explength);
+ }
+
+ /* try preflighting */
+ length=u_unescape(input, NULL, sizeof(buffer)/sizeof(buffer[0]));
+ if(length!=explength || u_strcmp(buffer, expect)!=0) {
+ log_err("failure in u_unescape(preflighting): length %d!=%d\n", length, explength);
+ }
+
+ /* ### TODO: test u_unescapeAt() */
+}
+
+/* test code point counting functions --------------------------------------- */
+
+/* reference implementation of u_strHasMoreChar32Than() */
+static int32_t
+_refStrHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) {
+ int32_t count=u_countChar32(s, length);
+ return count>number;
+}
+
+/* compare the real function against the reference */
+static void
+_testStrHasMoreChar32Than(const UChar *s, int32_t i, int32_t length, int32_t number) {
+ if(u_strHasMoreChar32Than(s, length, number)!=_refStrHasMoreChar32Than(s, length, number)) {
+ log_err("u_strHasMoreChar32Than(s+%d, %d, %d)=%hd is wrong\n",
+ i, length, number, u_strHasMoreChar32Than(s, length, number));
+ }
+}
+
+static void
+TestCountChar32() {
+ static const UChar string[]={
+ 0x61, 0x62, 0xd800, 0xdc00,
+ 0xd801, 0xdc01, 0x63, 0xd802,
+ 0x64, 0xdc03, 0x65, 0x66,
+ 0xd804, 0xdc04, 0xd805, 0xdc05,
+ 0x67
+ };
+ UChar buffer[100];
+ int32_t i, length, number;
+
+ /* test u_strHasMoreChar32Than() with length>=0 */
+ length=LENGTHOF(string);
+ while(length>=0) {
+ for(i=0; i<=length; ++i) {
+ for(number=-1; number<=((length-i)+2); ++number) {
+ _testStrHasMoreChar32Than(string+i, i, length-i, number);
+ }
+ }
+ --length;
+ }
+
+ /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */
+ length=LENGTHOF(string);
+ u_memcpy(buffer, string, length);
+ while(length>=0) {
+ buffer[length]=0;
+ for(i=0; i<=length; ++i) {
+ for(number=-1; number<=((length-i)+2); ++number) {
+ _testStrHasMoreChar32Than(string+i, i, -1, number);
+ }
+ }
+ --length;
+ }
+
+ /* test u_strHasMoreChar32Than() with NULL string (bad input) */
+ for(length=-1; length<=1; ++length) {
+ for(i=0; i<=length; ++i) {
+ for(number=-2; number<=2; ++number) {
+ _testStrHasMoreChar32Than(NULL, 0, length, number);
+ }
+ }
+ }
+}
+
+/* UCharIterator ------------------------------------------------------------ */
+
+/*
+ * Compare results from two iterators, should be same.
+ * Assume that the text is not empty and that
+ * iteration start==0 and iteration limit==length.
+ */
+static void
+compareIterators(UCharIterator *iter1, const char *n1,
+ UCharIterator *iter2, const char *n2) {
+ int32_t i, pos1, pos2, middle, length;
+ UChar32 c1, c2;
+
+ /* compare lengths */
+ length=iter1->getIndex(iter1, UITER_LENGTH);
+ pos2=iter2->getIndex(iter2, UITER_LENGTH);
+ if(length!=pos2) {
+ log_err("%s->getIndex(length)=%d != %d=%s->getIndex(length)\n", n1, length, pos2, n2);
+ return;
+ }
+
+ /* set into the middle */
+ middle=length/2;
+
+ pos1=iter1->move(iter1, middle, UITER_ZERO);
+ if(pos1!=middle) {
+ log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
+ return;
+ }
+
+ pos2=iter2->move(iter2, middle, UITER_ZERO);
+ if(pos2!=middle) {
+ log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
+ return;
+ }
+
+ /* test current() */
+ c1=iter1->current(iter1);
+ c2=iter2->current(iter2);
+ if(c1!=c2) {
+ log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle);
+ return;
+ }
+
+ /* move forward 3 UChars */
+ for(i=0; i<3; ++i) {
+ c1=iter1->next(iter1);
+ c2=iter2->next(iter2);
+ if(c1!=c2) {
+ log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ }
+
+ /* move backward 5 UChars */
+ for(i=0; i<5; ++i) {
+ c1=iter1->previous(iter1);
+ c2=iter2->previous(iter2);
+ if(c1!=c2) {
+ log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ }
+
+ /* iterate forward from the beginning */
+ pos1=iter1->move(iter1, 0, UITER_START);
+ if(pos1<0) {
+ log_err("%s->move(start) failed\n", n1);
+ return;
+ }
+ if(!iter1->hasNext(iter1)) {
+ log_err("%s->hasNext() at the start returns FALSE\n", n1);
+ return;
+ }
+
+ pos2=iter2->move(iter2, 0, UITER_START);
+ if(pos2<0) {
+ log_err("%s->move(start) failed\n", n2);
+ return;
+ }
+ if(!iter2->hasNext(iter2)) {
+ log_err("%s->hasNext() at the start returns FALSE\n", n2);
+ return;
+ }
+
+ do {
+ c1=iter1->next(iter1);
+ c2=iter2->next(iter2);
+ if(c1!=c2) {
+ log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ } while(c1>=0);
+
+ if(iter1->hasNext(iter1)) {
+ log_err("%s->hasNext() at the end returns TRUE\n", n1);
+ return;
+ }
+ if(iter2->hasNext(iter2)) {
+ log_err("%s->hasNext() at the end returns TRUE\n", n2);
+ return;
+ }
+
+ /* back to the middle */
+ pos1=iter1->move(iter1, middle, UITER_ZERO);
+ if(pos1!=middle) {
+ log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
+ return;
+ }
+
+ pos2=iter2->move(iter2, middle, UITER_ZERO);
+ if(pos2!=middle) {
+ log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
+ return;
+ }
+
+ /* move to index 1 */
+ pos1=iter1->move(iter1, 1, UITER_ZERO);
+ if(pos1!=1) {
+ log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n1, middle, pos1);
+ return;
+ }
+
+ pos2=iter2->move(iter2, 1, UITER_ZERO);
+ if(pos2!=1) {
+ log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n2, middle, pos2);
+ return;
+ }
+
+ /* iterate backward from the end */
+ pos1=iter1->move(iter1, 0, UITER_LIMIT);
+ if(pos1<0) {
+ log_err("%s->move(limit) failed\n", n1);
+ return;
+ }
+ if(!iter1->hasPrevious(iter1)) {
+ log_err("%s->hasPrevious() at the end returns FALSE\n", n1);
+ return;
+ }
+
+ pos2=iter2->move(iter2, 0, UITER_LIMIT);
+ if(pos2<0) {
+ log_err("%s->move(limit) failed\n", n2);
+ return;
+ }
+ if(!iter2->hasPrevious(iter2)) {
+ log_err("%s->hasPrevious() at the end returns FALSE\n", n2);
+ return;
+ }
+
+ do {
+ c1=iter1->previous(iter1);
+ c2=iter2->previous(iter2);
+ if(c1!=c2) {
+ log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ } while(c1>=0);
+
+ if(iter1->hasPrevious(iter1)) {
+ log_err("%s->hasPrevious() at the start returns TRUE\n", n1);
+ return;
+ }
+ if(iter2->hasPrevious(iter2)) {
+ log_err("%s->hasPrevious() at the start returns TRUE\n", n2);
+ return;
+ }
+}
+
+/*
+ * Test the iterator's getState() and setState() functions.
+ * iter1 and iter2 must be set up for the same iterator type and the same string
+ * but may be physically different structs (different addresses).
+ *
+ * Assume that the text is not empty and that
+ * iteration start==0 and iteration limit==length.
+ * It must be 2<=middle<=length-2.
+ */
+static void
+testIteratorState(UCharIterator *iter1, UCharIterator *iter2, const char *n, int32_t middle) {
+ UChar32 u[4];
+
+ UErrorCode errorCode;
+ UChar32 c;
+ uint32_t state;
+ int32_t i, j;
+
+ /* get four UChars from the middle of the string */
+ iter1->move(iter1, middle-2, UITER_ZERO);
+ for(i=0; i<4; ++i) {
+ c=iter1->next(iter1);
+ if(c<0) {
+ /* the test violates the assumptions, see comment above */
+ log_err("test error: %s[%d]=%d\n", n, middle-2+i, c);
+ return;
+ }
+ u[i]=c;
+ }
+
+ /* move to the middle and get the state */
+ iter1->move(iter1, -2, UITER_CURRENT);
+ state=uiter_getState(iter1);
+
+ /* set the state into the second iterator and compare the results */
+ errorCode=U_ZERO_ERROR;
+ uiter_setState(iter2, state, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("%s->setState(0x%x) failed: %s\n", n, state, u_errorName(errorCode));
+ return;
+ }
+
+ c=iter2->current(iter2);
+ if(c!=u[2]) {
+ log_err("%s->current(at %d)=U+%04x!=U+%04x\n", n, middle, c, u[2]);
+ }
+
+ c=iter2->previous(iter2);
+ if(c!=u[1]) {
+ log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-1, c, u[1]);
+ }
+
+ iter2->move(iter2, 2, UITER_CURRENT);
+ c=iter2->next(iter2);
+ if(c!=u[3]) {
+ log_err("%s->next(at %d)=U+%04x!=U+%04x\n", n, middle+1, c, u[3]);
+ }
+
+ iter2->move(iter2, -3, UITER_CURRENT);
+ c=iter2->previous(iter2);
+ if(c!=u[0]) {
+ log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-2, c, u[0]);
+ }
+
+ /* move the second iterator back to the middle */
+ iter2->move(iter2, 1, UITER_CURRENT);
+ iter2->next(iter2);
+
+ /* check that both are in the middle */
+ i=iter1->getIndex(iter1, UITER_CURRENT);
+ j=iter2->getIndex(iter2, UITER_CURRENT);
+ if(i!=middle) {
+ log_err("%s->getIndex(current)=%d!=%d as expected\n", n, i, middle);
+ }
+ if(i!=j) {
+ log_err("%s->getIndex(current)=%d!=%d after setState()\n", n, j, i);
+ }
+
+ /* compare lengths */
+ i=iter1->getIndex(iter1, UITER_LENGTH);
+ j=iter2->getIndex(iter2, UITER_LENGTH);
+ if(i!=j) {
+ log_err("%s->getIndex(length)=%d!=%d before/after setState()\n", n, i, j);
+ }
+}
+
+static void
+TestUCharIterator() {
+ static const UChar text[]={
+ 0x61, 0x62, 0x63, 0xd801, 0xdffd, 0x78, 0x79, 0x7a, 0
+ };
+ char bytes[40];
+
+ UCharIterator iter, iter1, iter2;
+ UConverter *cnv;
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* simple API/code coverage - test NOOP UCharIterator */
+ uiter_setString(&iter, NULL, 0);
+ if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!=-1 ||
+ iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT)!=0 ||
+ iter.hasNext(&iter) || iter.hasPrevious(&iter)
+ ) {
+ log_err("NOOP UCharIterator behaves unexpectedly\n");
+ }
+
+ /* test get/set state */
+ length=LENGTHOF(text)-1;
+ uiter_setString(&iter1, text, -1);
+ uiter_setString(&iter2, text, length);
+ testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2);
+ testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1);
+
+ /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */
+ errorCode=U_ZERO_ERROR;
+ u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uiter_setString(&iter1, text, -1);
+ uiter_setUTF8(&iter2, bytes, length);
+ compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator");
+
+ /* try again with length=-1 */
+ uiter_setUTF8(&iter2, bytes, -1);
+ compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1");
+
+ /* test get/set state */
+ length=LENGTHOF(text)-1;
+ uiter_setUTF8(&iter1, bytes, -1);
+ testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2);
+ testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1);
+
+ /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-16BE", &errorCode);
+ length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode);
+ ucnv_close(cnv);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_fromUChars(UTF-16BE) failed, %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* terminate with a _pair_ of 0 bytes - a UChar NUL in UTF-16BE (length is known to be ok) */
+ bytes[length]=bytes[length+1]=0;
+
+ uiter_setString(&iter1, text, -1);
+ uiter_setUTF16BE(&iter2, bytes, length);
+ compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator");
+
+ /* try again with length=-1 */
+ uiter_setUTF16BE(&iter2, bytes, -1);
+ compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1");
+
+ /* try again after moving the bytes up one, and with length=-1 */
+ memmove(bytes+1, bytes, length+2);
+ uiter_setUTF16BE(&iter2, bytes+1, -1);
+ compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1");
+
+ /* ### TODO test other iterators: CharacterIterator, Replaceable */
+}
+
+#if UCONFIG_NO_COLLATION
+
+static void
+TestUNormIterator() {
+ /* test nothing */
+}
+
+static void
+TestBadUNormIterator(void) {
+ /* test nothing, as well */
+}
+
+#else
+
+#include "unicode/unorm.h"
+#include "unorm_it.h"
+
+/*
+ * Compare results from two iterators, should be same.
+ * Assume that the text is not empty and that
+ * iteration start==0 and iteration limit==length.
+ *
+ * Modified version of compareIterators() but does not assume that indexes
+ * are available.
+ */
+static void
+compareIterNoIndexes(UCharIterator *iter1, const char *n1,
+ UCharIterator *iter2, const char *n2,
+ int32_t middle) {
+ uint32_t state;
+ int32_t i;
+ UChar32 c1, c2;
+ UErrorCode errorCode;
+
+ /* code coverage for unorm_it.c/unormIteratorGetIndex() */
+ if(
+ iter2->getIndex(iter2, UITER_START)!=0 ||
+ iter2->getIndex(iter2, UITER_LENGTH)!=UITER_UNKNOWN_INDEX
+ ) {
+ log_err("UNormIterator.getIndex() failed\n");
+ }
+
+ /* set into the middle */
+ iter1->move(iter1, middle, UITER_ZERO);
+ iter2->move(iter2, middle, UITER_ZERO);
+
+ /* test current() */
+ c1=iter1->current(iter1);
+ c2=iter2->current(iter2);
+ if(c1!=c2) {
+ log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle);
+ return;
+ }
+
+ /* move forward 3 UChars */
+ for(i=0; i<3; ++i) {
+ c1=iter1->next(iter1);
+ c2=iter2->next(iter2);
+ if(c1!=c2) {
+ log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ }
+
+ /* move backward 5 UChars */
+ for(i=0; i<5; ++i) {
+ c1=iter1->previous(iter1);
+ c2=iter2->previous(iter2);
+ if(c1!=c2) {
+ log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ }
+
+ /* iterate forward from the beginning */
+ iter1->move(iter1, 0, UITER_START);
+ if(!iter1->hasNext(iter1)) {
+ log_err("%s->hasNext() at the start returns FALSE\n", n1);
+ return;
+ }
+
+ iter2->move(iter2, 0, UITER_START);
+ if(!iter2->hasNext(iter2)) {
+ log_err("%s->hasNext() at the start returns FALSE\n", n2);
+ return;
+ }
+
+ do {
+ c1=iter1->next(iter1);
+ c2=iter2->next(iter2);
+ if(c1!=c2) {
+ log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ } while(c1>=0);
+
+ if(iter1->hasNext(iter1)) {
+ log_err("%s->hasNext() at the end returns TRUE\n", n1);
+ return;
+ }
+ if(iter2->hasNext(iter2)) {
+ log_err("%s->hasNext() at the end returns TRUE\n", n2);
+ return;
+ }
+
+ /* iterate backward */
+ do {
+ c1=iter1->previous(iter1);
+ c2=iter2->previous(iter2);
+ if(c1!=c2) {
+ log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ } while(c1>=0);
+
+ /* back to the middle */
+ iter1->move(iter1, middle, UITER_ZERO);
+ iter2->move(iter2, middle, UITER_ZERO);
+
+ /* try get/set state */
+ while((state=uiter_getState(iter2))==UITER_NO_STATE) {
+ if(!iter2->hasNext(iter2)) {
+ log_err("%s has no known state from middle=%d to the end\n", n2, middle);
+ return;
+ }
+ iter2->next(iter2);
+ }
+
+ errorCode=U_ZERO_ERROR;
+
+ c2=iter2->current(iter2);
+ iter2->move(iter2, 0, UITER_ZERO);
+ uiter_setState(iter2, state, &errorCode);
+ c1=iter2->current(iter2);
+ if(U_FAILURE(errorCode) || c1!=c2) {
+ log_err("%s->current() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1);
+ return;
+ }
+
+ c2=iter2->previous(iter2);
+ iter2->move(iter2, 0, UITER_ZERO);
+ uiter_setState(iter2, state, &errorCode);
+ c1=iter2->previous(iter2);
+ if(U_FAILURE(errorCode) || c1!=c2) {
+ log_err("%s->previous() differs across get/set state, U+%04x vs. U+%04x\n", n2, c2, c1);
+ return;
+ }
+
+ /* iterate backward from the end */
+ iter1->move(iter1, 0, UITER_LIMIT);
+ if(!iter1->hasPrevious(iter1)) {
+ log_err("%s->hasPrevious() at the end returns FALSE\n", n1);
+ return;
+ }
+
+ iter2->move(iter2, 0, UITER_LIMIT);
+ if(!iter2->hasPrevious(iter2)) {
+ log_err("%s->hasPrevious() at the end returns FALSE\n", n2);
+ return;
+ }
+
+ do {
+ c1=iter1->previous(iter1);
+ c2=iter2->previous(iter2);
+ if(c1!=c2) {
+ log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
+ return;
+ }
+ } while(c1>=0);
+
+ if(iter1->hasPrevious(iter1)) {
+ log_err("%s->hasPrevious() at the start returns TRUE\n", n1);
+ return;
+ }
+ if(iter2->hasPrevious(iter2)) {
+ log_err("%s->hasPrevious() at the start returns TRUE\n", n2);
+ return;
+ }
+}
+
+/* n2 must have a digit 1 at the end, will be incremented with the normalization mode */
+static void
+testUNormIteratorWithText(const UChar *text, int32_t textLength, int32_t middle,
+ const char *name1, const char *n2) {
+ UChar buffer[600];
+ char name2[40];
+
+ UCharIterator iter1, iter2, *iter;
+ UNormIterator *uni;
+
+ UNormalizationMode mode;
+ UErrorCode errorCode;
+ int32_t length;
+
+ /* open a normalizing iterator */
+ errorCode=U_ZERO_ERROR;
+ uni=unorm_openIter(NULL, 0, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unorm_openIter() fails: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* set iterator 2 to the original text */
+ uiter_setString(&iter2, text, textLength);
+
+ strcpy(name2, n2);
+
+ /* test the normalizing iterator for each mode */
+ for(mode=UNORM_NONE; mode<UNORM_MODE_COUNT; ++mode) {
+ length=unorm_normalize(text, textLength, mode, 0, buffer, LENGTHOF(buffer), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unorm_normalize(mode %d) failed: %s\n", mode, u_errorName(errorCode));
+ break;
+ }
+
+ /* set iterator 1 to the normalized text */
+ uiter_setString(&iter1, buffer, length);
+
+ /* set the normalizing iterator to use iter2 */
+ iter=unorm_setIter(uni, &iter2, mode, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unorm_setIter(mode %d) failed: %s\n", mode, u_errorName(errorCode));
+ break;
+ }
+
+ compareIterNoIndexes(&iter1, name1, iter, name2, middle);
+ ++name2[strlen(name2)-1];
+ }
+
+ unorm_closeIter(uni);
+}
+
+static void
+TestUNormIterator() {
+ static const UChar text[]={ /* must contain <00C5 0327> see u_strchr() below */
+ 0x61, /* 'a' */
+ 0xe4, 0x61, 0x308, /* variations of 'a'+umlaut */
+ 0xc5, 0x327, 0x41, 0x30a, 0x327, 0x41, 0x327, 0x30a, /* variations of 'A'+ring+cedilla */
+ 0xfb03, 0xfb00, 0x69, 0x66, 0x66, 0x69, 0x66, 0xfb01 /* variations of 'ffi' */
+ };
+ static const UChar surrogateText[]={
+ 0x6e, 0xd900, 0x6a, 0xdc00, 0xd900, 0xdc00, 0x61
+ };
+
+ UChar longText[600];
+ int32_t i, middle, length;
+
+ length=LENGTHOF(text);
+ testUNormIteratorWithText(text, length, length/2, "UCharIter", "UNormIter1");
+ testUNormIteratorWithText(text, length, length, "UCharIterEnd", "UNormIterEnd1");
+
+ /* test again, this time with an insane string to cause internal buffer overflows */
+ middle=(int32_t)(u_strchr(text, 0x327)-text); /* see comment at text[] */
+ memcpy(longText, text, middle*U_SIZEOF_UCHAR);
+ for(i=0; i<150; ++i) {
+ longText[middle+i]=0x30a; /* insert many rings between 'A-ring' and cedilla */
+ }
+ memcpy(longText+middle+i, text+middle, (LENGTHOF(text)-middle)*U_SIZEOF_UCHAR);
+ length=LENGTHOF(text)+i;
+
+ /* append another copy of this string for more overflows */
+ memcpy(longText+length, longText, length*U_SIZEOF_UCHAR);
+ length*=2;
+
+ /* the first test of the following two starts at length/4, inside the sea of combining rings */
+ testUNormIteratorWithText(longText, length, length/4, "UCharIterLong", "UNormIterLong1");
+ testUNormIteratorWithText(longText, length, length, "UCharIterLongEnd", "UNormIterLongEnd1");
+
+ length=LENGTHOF(surrogateText);
+ testUNormIteratorWithText(surrogateText, length, length/4, "UCharIterSurr", "UNormIterSurr1");
+ testUNormIteratorWithText(surrogateText, length, length, "UCharIterSurrEnd", "UNormIterSurrEnd1");
+}
+
+static void
+TestBadUNormIterator(void) {
+#if !UCONFIG_NO_NORMALIZATION
+ UErrorCode status = U_ILLEGAL_ESCAPE_SEQUENCE;
+ UNormIterator *uni;
+
+ unorm_setIter(NULL, NULL, UNORM_NONE, &status);
+ if (status != U_ILLEGAL_ESCAPE_SEQUENCE) {
+ log_err("unorm_setIter changed the error code to: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ unorm_setIter(NULL, NULL, UNORM_NONE, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("unorm_setIter didn't react correctly to bad arguments: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ uni=unorm_openIter(NULL, 0, &status);
+ if(U_FAILURE(status)) {
+ log_err("unorm_openIter() fails: %s\n", u_errorName(status));
+ return;
+ }
+ unorm_setIter(uni, NULL, UNORM_NONE, &status);
+ unorm_closeIter(uni);
+#endif
+}
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c
new file mode 100644
index 00000000000..2bb339c6d96
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/cutiltst.c
@@ -0,0 +1,48 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File CUTILTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Creation
+*********************************************************************************
+*/
+#include "cintltst.h"
+
+void addLocaleTest(TestNode**);
+void addCLDRTest(TestNode**);
+void addUnicodeTest(TestNode**);
+void addUStringTest(TestNode**);
+void addCaseTest(TestNode**);
+void addResourceBundleTest(TestNode**);
+void addNEWResourceBundleTest(TestNode**);
+void addHashtableTest(TestNode** root);
+void addCStringTest(TestNode** root);
+void addTrieTest(TestNode** root);
+void addEnumerationTest(TestNode** root);
+void addPosixTest(TestNode** root);
+void addSortTest(TestNode** root);
+
+void addUtility(TestNode** root);
+
+void addUtility(TestNode** root)
+{
+ addCStringTest(root);
+ addTrieTest(root);
+ addLocaleTest(root);
+ addCLDRTest(root);
+ addUnicodeTest(root);
+ addUStringTest(root);
+ addCaseTest(root);
+ addResourceBundleTest(root);
+ addNEWResourceBundleTest(root);
+ addHashtableTest(root);
+ addEnumerationTest(root);
+ addPosixTest(root);
+ addSortTest(root);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c
new file mode 100644
index 00000000000..1c48eca45aa
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.c
@@ -0,0 +1,357 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2003, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File encoll.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Ported for C API
+*********************************************************************************/
+/**
+ * CollationEnglishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/ucol.h"
+#include "unicode/uloc.h"
+#include "cintltst.h"
+#include "encoll.h"
+#include "ccolltst.h"
+#include "callcoll.h"
+#include "unicode/ustring.h"
+
+static UCollator *myCollation = NULL;
+const static UChar testSourceCases[][MAX_TOKEN_LEN] = {
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0020 /* ' ' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0048 /* 'H' */, (UChar)0x0065 /* 'e' */, (UChar)0x006C /* 'l' */, (UChar)0x006C /* 'l' */, (UChar)0x006F /* 'o' */, 0},
+ {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0},
+ {0x00C4, (UChar)0x0042 /* 'B' */, 0x0308, (UChar)0x0043 /* 'C' */, 0x0308, 0},
+ {(UChar)0x0061 /* 'a' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x0072 /* 'r' */, 0},
+ {(UChar)0x0072 /* 'r' */, (UChar)0x006F /* 'o' */, (UChar)0x006C /* 'l' */, (UChar)0x0065 /* 'e' */, (UChar)0x0073 /* 's' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0041 /* 'A' */, 0},
+ {(UChar)0x0041 /* 'A' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0074 /* 't' */, (UChar)0x0063 /* 'c' */, (UChar)0x006F /* 'o' */, (UChar)0x006D /* 'm' */, (UChar)0x0070 /* 'p' */, (UChar)0x0061 /* 'a' */, (UChar)0x0072 /* 'r' */, (UChar)0x0065 /* 'e' */, (UChar)0x0070 /* 'p' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0069 /* 'i' */, (UChar)0x006E /* 'n' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0041 /* 'A' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00E6, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x0048 /* 'H' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0074 /* 't' */, (UChar)0x0068 /* 'h' */, (UChar)0x0069 /* 'i' */, 0x0302, (UChar)0x0073 /* 's' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, 0x00E6, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, 0x00E6, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0}
+};
+
+const static UChar testTargetCases[][MAX_TOKEN_LEN] = {
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x002D /* '-' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, 0},
+ {(UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x006C /* 'l' */, (UChar)0x006C /* 'l' */, (UChar)0x006F /* 'o' */, 0},
+ {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0},
+ {(UChar)0x0041 /* 'A' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, (UChar)0x0073 /* 's' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, (UChar)0x0073 /* 's' */, 0},
+ {(UChar)0x0062 /* 'b' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0063 /* 'c' */, (UChar)0x006B /* 'k' */, (UChar)0x0062 /* 'b' */, (UChar)0x0069 /* 'i' */, (UChar)0x0072 /* 'r' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, (UChar)0x0072 /* 'r' */, 0},
+ {0x00C4, (UChar)0x0042 /* 'B' */, 0x0308, (UChar)0x0043 /* 'C' */, 0x0308, 0},
+ {(UChar)0x0041 /* 'A' */, 0x0308, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0072 /* 'r' */, (UChar)0x006F /* 'o' */, 0x0302, (UChar)0x006C /* 'l' */, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0041 /* 'A' */, 0x00E1, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0041 /* 'A' */, 0x00E1, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0054 /* 'T' */, (UChar)0x0043 /* 'C' */, (UChar)0x006F /* 'o' */, (UChar)0x006D /* 'm' */, (UChar)0x0070 /* 'p' */, (UChar)0x0061 /* 'a' */, (UChar)0x0072 /* 'r' */, (UChar)0x0065 /* 'e' */, (UChar)0x0050 /* 'P' */, (UChar)0x006C /* 'l' */, (UChar)0x0061 /* 'a' */, (UChar)0x0069 /* 'i' */, (UChar)0x006E /* 'n' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0042 /* 'B' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0026 /* '&' */, (UChar)0x0062 /* 'b' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0023 /* '#' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {0x00C4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, (UChar)0x0064 /* 'd' */, (UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0023 /* '#' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x003D /* '=' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0064 /* 'd' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0043 /* 'C' */, (UChar)0x0048 /* 'H' */, (UChar)0x0063 /* 'c' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0074 /* 't' */, (UChar)0x0068 /* 'h' */, 0x00EE, (UChar)0x0073 /* 's' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00E9, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, 0x00E9, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0043 /* 'C' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0062 /* 'b' */, (UChar)0x0064 /* 'd' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, 0x00C6, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0064 /* 'd' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, 0x00C6, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0042 /* 'B' */, (UChar)0x0064 /* 'd' */, 0},
+ {0x00E4, (UChar)0x0062 /* 'b' */, (UChar)0x0063 /* 'c' */, 0},
+ {(UChar)0x0070 /* 'p' */, 0x00EA, (UChar)0x0063 /* 'c' */, (UChar)0x0068 /* 'h' */, (UChar)0x0065 /* 'e' */, 0}
+};
+
+const static UCollationResult results[] = {
+ UCOL_LESS,
+ UCOL_LESS, /*UCOL_GREATER,*/
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS, /*UCOL_GREATER,*/ /* 10 */
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS, /* 20 */
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ UCOL_GREATER,
+ /* Test Tertiary > 26 */
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_GREATER,
+ UCOL_LESS, /* 30 */
+ UCOL_GREATER,
+ UCOL_EQUAL,
+ UCOL_GREATER,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS,
+ /* test identical > 36 */
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ /* test primary > 38 */
+ UCOL_EQUAL,
+ UCOL_EQUAL, /* 40 */
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_EQUAL,
+ /* test secondary > 43 */
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_EQUAL,
+ UCOL_LESS,
+ UCOL_LESS,
+ UCOL_LESS /* 49 */
+};
+
+const static UChar testBugs[][MAX_TOKEN_LEN] = {
+ {(UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0041 /* 'A' */, 0},
+ {(UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0045 /* 'E' */, 0},
+ {0x00e9, 0},
+ {0x00e8, 0},
+ {0x00ea, 0},
+ {0x00eb, 0},
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0061 /* 'a' */, 0},
+ {(UChar)0x0078 /* 'x' */, 0}
+
+};
+
+/* 0x0300 is grave, 0x0301 is acute
+ the order of elements in this array must be different than the order in CollationFrenchTest */
+const static UChar testAcute[][MAX_TOKEN_LEN] = {
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0301, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0301, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0},
+ {(UChar)0x0065 /* 'e' */, 0x0300, 0x0301, (UChar)0x0065 /* 'e' */, 0x0300, 0x0301, 0}
+};
+
+static const UChar testMore[][MAX_TOKEN_LEN] = {
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0065 /* 'e' */, 0},
+ { 0x00E6, 0},
+ { 0x00C6, 0},
+ {(UChar)0x0061 /* 'a' */, (UChar)0x0066 /* 'f' */, 0},
+ {(UChar)0x006F /* 'o' */, (UChar)0x0065 /* 'e' */, 0},
+ { 0x0153, 0},
+ { 0x0152, 0},
+ {(UChar)0x006F /* 'o' */, (UChar)0x0066 /* 'f' */, 0},
+};
+
+
+void addEnglishCollTest(TestNode** root)
+{
+
+ addTest(root, &TestPrimary, "tscoll/encoll/TestPrimary");
+ addTest(root, &TestSecondary, "tscoll/encoll/TestSecondary");
+ addTest(root, &TestTertiary, "tscoll/encoll/TestTertiary");
+
+}
+
+static void TestTertiary( )
+{
+ int32_t testMoreSize;
+ UCollationResult expected=UCOL_EQUAL;
+ int32_t i,j;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("en_US", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ log_verbose("Testing English Collation with Tertiary strength\n");
+
+ ucol_setStrength(myCollation, UCOL_TERTIARY);
+ for (i = 0; i < 38 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+
+
+ j = 0;
+ for (i = 0; i < 10; i++)
+ {
+ for (j = i+1; j < 10; j++)
+ {
+ doTest(myCollation, testBugs[i], testBugs[j], UCOL_LESS);
+ }
+ }
+ /*test more interesting cases */
+ testMoreSize = sizeof(testMore) / sizeof(testMore[0]);
+ for (i = 0; i < testMoreSize; i++)
+ {
+ for (j = 0; j < testMoreSize; j++)
+ {
+ if (i < j) expected = UCOL_LESS;
+ if (i == j) expected = UCOL_EQUAL;
+ if (i > j) expected = UCOL_GREATER;
+ doTest(myCollation, testMore[i], testMore[j], expected );
+ }
+ }
+ ucol_close(myCollation);
+}
+
+static void TestPrimary()
+{
+
+ int32_t i;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("en_US", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ ucol_setStrength(myCollation, UCOL_PRIMARY);
+ log_verbose("Testing English Collation with Primary strength\n");
+ for (i = 38; i < 43 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+ ucol_close(myCollation);
+}
+
+static void TestSecondary()
+{
+ UCollationResult expected=UCOL_EQUAL;
+ int32_t i,j, testAcuteSize;
+ UErrorCode status = U_ZERO_ERROR;
+ myCollation = ucol_open("en_US", &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: in creation of rule based collator: %s\n", myErrorName(status));
+ return;
+ }
+ ucol_setStrength(myCollation, UCOL_SECONDARY);
+ log_verbose("Testing English Collation with Secondary strength\n");
+ for (i = 43; i < 49 ; i++)
+ {
+ doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
+ }
+
+
+ /*test acute and grave ordering (compare to french collation) */
+ testAcuteSize = sizeof(testAcute) / sizeof(testAcute[0]);
+ for (i = 0; i < testAcuteSize; i++)
+ {
+ for (j = 0; j < testAcuteSize; j++)
+ {
+ if (i < j) expected = UCOL_LESS;
+ if (i == j) expected = UCOL_EQUAL;
+ if (i > j) expected = UCOL_GREATER;
+ doTest(myCollation, testAcute[i], testAcute[j], expected );
+ }
+ }
+ucol_close(myCollation);
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h
new file mode 100644
index 00000000000..1102885a213
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/encoll.h
@@ -0,0 +1,44 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File encoll.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda Converted to C
+*********************************************************************************/
+/**
+ * CollationEnglishTest is a third level test class. This tests the locale
+ * specific primary, secondary and tertiary rules. For example, the ignorable
+ * character '-' in string "black-bird". The en_US locale uses the default
+ * collation rules as its sorting sequence.
+ */
+
+#ifndef _CENCOLLTST
+#define _CENCOLLTST
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "cintltst.h"
+
+#define MAX_TOKEN_LEN 16
+
+ /* performs test with strength PRIMARY */
+static void TestPrimary(void);
+
+ /* perform test with strength SECONDARY */
+static void TestSecondary(void);
+
+ /* perform test with strength TERTIARY */
+static void TestTertiary(void);
+
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c b/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c
new file mode 100644
index 00000000000..8e29d4c6815
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/eurocreg.c
@@ -0,0 +1,188 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1999-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "unicode/ctest.h"
+#include "unicode/ucnv.h"
+
+void TestEuroRegression(void);
+void addTestEuroRegression(TestNode** root);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+void addTestEuroRegression(TestNode** root)
+{
+ addTest(root, &TestEuroRegression, "tsconv/eurocreg/TestEuroRegression");
+}
+
+/*
+ * The table below lists codepages that are supposed to have roundtrip mappings for
+ * the U+20AC Euro sign.
+ *
+ * Changes made 2000nov28 and marked as such are due to the following:
+ *
+ * After updating all ibm-*.ucm files with precise fallback indicators (|0, |1, |3),
+ * some of these codepages failed the Euro regression test.
+ * This means that the actuall mappings changed when only the preciseness of fallback
+ * mappings should have changed.
+ * My (Markus) suspicion is that some files got Euro sign mappings added manually,
+ * changing their contents compared to the NLTC (IBM Toronto codepage database) definition.
+ * Such changes are highly undesirable because they effectively define new codepages.
+ * Codepage mapping files with "ibm-*.ucm" should always exactly match the files
+ * from the IBM codepage database.
+ * (If there are several mappings with the same number, then we choose the
+ * default mappings with Private-Use Area assignments.)
+ *
+ * Also, in the past, some aliases were set such that e.g. cp850 became an alias for ibm-858.
+ * This followed the practice of OS/2 that uses the old codepage number 850 for the new
+ * codepage 858, with the main difference being the additional Euro sign.
+ * However, we have documented that the "cp" prefix should be used for Microsoft-compatible
+ * codepages, and Microsoft Windows 2000's codepage 850 does not contain a Euro sign mapping.
+ * Therefore, cp850 must not support the Euro sign.
+ * In these cases, I have changed the codepage name here to point to a newer codepage with the
+ * Euro sign, using its new name.
+ * I could not find such "updates" for codepages 1362 and 1363 - we might want to supply them later.
+ */
+
+static const char convertersToCheck[][15] = {
+ "cp1250",
+ "cp1251",
+ "cp1252",
+ "cp1254",
+ "cp1255",
+ "cp1256",
+ "cp1257",
+ "cp1258",
+ "ibm1140",
+ "ibm1142",
+ "ibm1143",
+ "ibm1144",
+ "ibm1145",
+ "ibm1146",
+ "ibm1147",
+ "ibm1148",
+ "ibm1149",
+ "ibm1153",
+ "ibm1154",
+ "ibm1155",
+ "ibm1156",
+ "ibm1157",
+ "ibm1158",
+ /*"ibm-1159",*/ /* removed 2003Apr17 */
+ "ibm12712",
+ "ibm16804",
+ "ibm-1160",
+ "ibm-1162",
+ "ibm-1164",
+
+ "ibm-858", /* was "cp850" changed 2000nov28 */
+ /* duplicate "cp850" removed 2000nov28 */
+ /*"ibm-9049",*/ /* was "cp857" changed 2002nov25 */
+ "ibm-12712", /* was "cp424" changed 2000nov28 */
+ "ibm-4899", /* was "cp803" changed 2000nov28 */
+ "ibm-867", /* was "cp862" changed 2002nov25 */
+ "cp1258",
+ "windows-950",
+ "cp1253",
+ /* "cp819",
+ "cp13488",*/
+ "ibm-4971",
+ /*"ibm-9061",*/ /* was "cp869" changed 2002nov25 */
+ /* "cp813",*/
+ /*"ibm-9044",*/ /* was "cp852" changed 2002nov25 */
+ /*"ibm-872",*/ /* was "cp855" changed 2002nov25 */
+ /*"ibm-808",*/ /* was "cp866" changed 2002nov25 */
+/* "cp1131",
+ "cp1125",*/
+ "ibm-902", /* was "cp922" changed 2003jan08 */
+ "ibm-901", /* was "cp921" changed 2003jan09 */
+ /*"ibm-17248",*/ /* was "cp864" changed 2002nov25 */
+ /*"cp1008",
+ "cp1046",*/
+ /* "cp9066",
+ "cp1129",*/
+ "ibm-5123", /* was "cp1027" changed 2003jan08 */
+ /* "cp300",*/
+ /* "cp4930",*/
+ "ibm-1364",
+ /* "cp1362" removed 2000nov28 */
+ "cp1363",
+ /* "cp1114", removed 2002jul3
+ "cp947", removed 2002jul3 */
+ "gb18030",
+ ""};
+
+UBool isEuroAware(UConverter*);
+
+void TestEuroRegression()
+{
+ int32_t i=0;
+
+ do
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* myConv = ucnv_open(convertersToCheck[i], &err);
+ if (U_FAILURE(err)&&convertersToCheck[i][0])
+ log_data_err("%s \tMISSING [%s]\n", convertersToCheck[i], u_errorName(err));
+ else
+ {
+ if (isEuroAware(myConv))
+ log_verbose("%s \tsupports euro\n", convertersToCheck[i]);
+ else
+ log_err("%s \tDOES NOT support euro\n", convertersToCheck[i]);
+ ucnv_close(myConv);
+ }
+ } while (convertersToCheck[++i][0]);
+}
+
+UBool isEuroAware(UConverter* myConv)
+{
+ static const UChar euroString[2] = { 0x20AC, 0x0000 };
+ char target[20];
+ UChar euroBack[2];
+ int32_t targetSize, euroBackSize;
+ UErrorCode err = U_ZERO_ERROR;
+ /*const char* myName = ucnv_getName(myConv, &err);*/
+
+ targetSize = ucnv_fromUChars(myConv,
+ target,
+ sizeof(target),
+ euroString,
+ -1,
+ &err);
+ if (U_FAILURE(err))
+ {
+ log_err("Failure Occured in ucnv_fromUChars euro roundtrip test\n");
+ return FALSE;
+ }
+ euroBackSize = ucnv_toUChars(myConv,
+ euroBack,
+ 2,
+ target,
+ targetSize,
+ &err);
+ if (U_FAILURE(err))
+ {
+ log_err("Failure Occured in ucnv_toUChars euro roundtrip test\n");
+ return FALSE;
+ }
+ if (u_strcmp(euroString, euroBack))
+ {
+ /* log_err("%s FAILED Euro rountrip\n", myName);*/
+ return FALSE;
+ }
+ else
+ {
+ /* log_verbose("%s PASSED Euro rountrip\n", myName);*/
+ return TRUE;
+ }
+
+}
+#else
+void addTestEuroRegression(TestNode** root)
+{
+ /* test nothing... */
+}
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c b/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c
new file mode 100644
index 00000000000..02cf1576cd3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/hpmufn.c
@@ -0,0 +1,530 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2003-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File hpmufn.c
+*
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "unicode/uclean.h"
+#include "unicode/uchar.h"
+#include "unicode/ures.h"
+#include "cintltst.h"
+#include "umutex.h"
+#include "unicode/utrace.h"
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * This should align the memory properly on any machine.
+ */
+typedef union {
+ long t1;
+ double t2;
+ void *t3;
+} ctest_AlignedMemory;
+
+static void TestHeapFunctions(void);
+static void TestMutexFunctions(void);
+static void TestIncDecFunctions(void);
+
+void addHeapMutexTest(TestNode **root);
+
+
+void
+addHeapMutexTest(TestNode** root)
+{
+ addTest(root, &TestHeapFunctions, "hpmufn/TestHeapFunctions" );
+ addTest(root, &TestMutexFunctions, "hpmufn/TestMutexFunctions" );
+ addTest(root, &TestIncDecFunctions, "hpmufn/TestIncDecFunctions");
+}
+
+static int32_t gMutexFailures = 0;
+
+#define TEST_STATUS(status, expected) \
+if (status != expected) { \
+log_err("FAIL at %s:%d. Actual status = \"%s\"; Expected status = \"%s\"\n", \
+ __FILE__, __LINE__, u_errorName(status), u_errorName(expected)); gMutexFailures++; }
+
+
+#define TEST_ASSERT(expr) \
+if (!(expr)) { \
+ log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \
+ gMutexFailures++; \
+}
+
+
+/* These tests do cleanup and reinitialize ICU in the course of their operation.
+ * The ICU data directory must be preserved across these operations.
+ * Here is a helper function to assist with that.
+ */
+static char *safeGetICUDataDirectory() {
+ const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */
+ char *retStr = NULL;
+ if (dataDir != NULL) {
+ retStr = (char *)malloc(strlen(dataDir)+1);
+ strcpy(retStr, dataDir);
+ }
+ return retStr;
+}
+
+
+
+/*
+ * Test Heap Functions.
+ * Implemented on top of the standard malloc heap.
+ * All blocks increased in size by 8 to 16 bytes, and the poiner returned to ICU is
+ * offset up by 8 to 16, which should cause a good heap corruption if one of our "blocks"
+ * ends up being freed directly, without coming through us.
+ * Allocations are counted, to check that ICU actually does call back to us.
+ */
+int gBlockCount = 0;
+const void *gContext;
+
+static void * U_CALLCONV myMemAlloc(const void *context, size_t size) {
+ char *retPtr = (char *)malloc(size+sizeof(ctest_AlignedMemory));
+ if (retPtr != NULL) {
+ retPtr += sizeof(ctest_AlignedMemory);
+ }
+ gBlockCount ++;
+ return retPtr;
+}
+
+static void U_CALLCONV myMemFree(const void *context, void *mem) {
+ char *freePtr = (char *)mem;
+ if (freePtr != NULL) {
+ freePtr -= sizeof(ctest_AlignedMemory);
+ }
+ free(freePtr);
+}
+
+
+
+static void * U_CALLCONV myMemRealloc(const void *context, void *mem, size_t size) {
+ char *p = (char *)mem;
+ char *retPtr;
+
+ if (p!=NULL) {
+ p -= sizeof(ctest_AlignedMemory);
+ }
+ retPtr = realloc(p, size+sizeof(ctest_AlignedMemory));
+ if (retPtr != NULL) {
+ p += sizeof(ctest_AlignedMemory);
+ }
+ return retPtr;
+}
+
+
+static void TestHeapFunctions() {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *rb = NULL;
+ char *icuDataDir;
+ UVersionInfo unicodeVersion = {0,0,0,0};
+
+ UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */
+ UTraceExit *traceExitFunc; /* and restore them across calls to */
+ UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */
+ const void *traceContext;
+ int32_t traceLevel;
+
+ icuDataDir = safeGetICUDataDirectory(); /* save icu data dir, so we can put it back
+ * after doing u_cleanup(). */
+
+ utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc);
+ traceLevel = utrace_getLevel();
+
+ /* Verify that ICU can be cleaned up and reinitialized successfully.
+ * Failure here usually means that some ICU service didn't clean up successfully,
+ * probably because some earlier test accidently left something open. */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(icuDataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ /* Can not set memory functions if ICU is already initialized */
+ u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Un-initialize ICU */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+
+ /* Can not set memory functions with NULL values */
+ status = U_ZERO_ERROR;
+ u_setMemoryFunctions(&gContext, NULL, myMemRealloc, myMemFree, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setMemoryFunctions(&gContext, myMemAlloc, NULL, myMemFree, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, NULL, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+
+ /* u_setMemoryFunctions() should work with null or non-null context pointer */
+ status = U_ZERO_ERROR;
+ u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ u_setMemoryFunctions(&gContext, myMemAlloc, myMemRealloc, myMemFree, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+
+
+ /* After reinitializing ICU, we should not be able to set the memory funcs again. */
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(icuDataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ u_setMemoryFunctions(NULL, myMemAlloc, myMemRealloc, myMemFree, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Doing ICU operations should cause allocations to come through our test heap */
+ gBlockCount = 0;
+ status = U_ZERO_ERROR;
+ rb = ures_open(NULL, "es", &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ if (gBlockCount == 0) {
+ log_err("Heap functions are not being called from ICU.\n");
+ }
+ ures_close(rb);
+
+ /* Cleanup should put the heap back to its default implementation. */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ u_setDataDirectory(icuDataDir);
+ u_getUnicodeVersion(unicodeVersion);
+ if (unicodeVersion[0] <= 0) {
+ log_err("Properties doesn't reinitialize without u_init.\n");
+ }
+ status = U_ZERO_ERROR;
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+
+ /* ICU operations should no longer cause allocations to come through our test heap */
+ gBlockCount = 0;
+ status = U_ZERO_ERROR;
+ rb = ures_open(NULL, "fr", &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ if (gBlockCount != 0) {
+ log_err("Heap functions did not reset after u_cleanup.\n");
+ }
+ ures_close(rb);
+ free(icuDataDir);
+}
+
+
+/*
+ * Test u_setMutexFunctions()
+ */
+
+int gTotalMutexesInitialized = 0; /* Total number of mutexes created */
+int gTotalMutexesActive = 0; /* Total mutexes created, but not destroyed */
+int gAccumulatedLocks = 0;
+const void *gMutexContext;
+
+typedef struct DummyMutex {
+ int fLockCount;
+ int fMagic;
+} DummyMutex;
+
+
+static void U_CALLCONV myMutexInit(const void *context, UMTX *mutex, UErrorCode *status) {
+ DummyMutex *theMutex;
+
+ TEST_STATUS(*status, U_ZERO_ERROR);
+ theMutex = (DummyMutex *)malloc(sizeof(DummyMutex));
+ theMutex->fLockCount = 0;
+ theMutex->fMagic = 123456;
+ gTotalMutexesInitialized++;
+ gTotalMutexesActive++;
+ gMutexContext = context;
+ *mutex = theMutex;
+}
+
+
+static void U_CALLCONV myMutexDestroy(const void *context, UMTX *mutex) {
+ DummyMutex *This = *(DummyMutex **)mutex;
+
+ gTotalMutexesActive--;
+ TEST_ASSERT(This->fLockCount == 0);
+ TEST_ASSERT(This->fMagic == 123456);
+ This->fMagic = 0;
+ This->fLockCount = 0;
+ free(This);
+}
+
+static void U_CALLCONV myMutexLock(const void *context, UMTX *mutex) {
+ DummyMutex *This = *(DummyMutex **)mutex;
+
+ TEST_ASSERT(This->fMagic == 123456);
+ This->fLockCount++;
+ gAccumulatedLocks++;
+}
+
+static void U_CALLCONV myMutexUnlock(const void *context, UMTX *mutex) {
+ DummyMutex *This = *(DummyMutex **)mutex;
+
+ TEST_ASSERT(This->fMagic == 123456);
+ This->fLockCount--;
+ TEST_ASSERT(This->fLockCount >= 0);
+}
+
+
+
+static void TestMutexFunctions() {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle *rb = NULL;
+ char *icuDataDir;
+
+ UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */
+ UTraceExit *traceExitFunc; /* and restore them across calls to */
+ UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */
+ const void *traceContext;
+ int32_t traceLevel;
+
+ gMutexFailures = 0;
+
+ /* Save initial ICU state so that it can be restored later.
+ * u_cleanup(), which is called in this test, resets ICU's state.
+ */
+ icuDataDir = safeGetICUDataDirectory();
+ utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc);
+ traceLevel = utrace_getLevel();
+
+ /* Verify that ICU can be cleaned up and reinitialized successfully.
+ * Failure here usually means that some ICU service didn't clean up successfully,
+ * probably because some earlier test accidently left something open. */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(icuDataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ /* Can not set mutex functions if ICU is already initialized */
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Un-initialize ICU */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+
+ /* Can not set Mutex functions with NULL values */
+ status = U_ZERO_ERROR;
+ u_setMutexFunctions(&gContext, NULL, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setMutexFunctions(&gContext, myMutexInit, NULL, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, NULL, myMutexUnlock, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, NULL, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+
+ /* u_setMutexFunctions() should work with null or non-null context pointer */
+ status = U_ZERO_ERROR;
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+
+
+ /* After reinitializing ICU, we should not be able to set the mutex funcs again. */
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(icuDataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ u_setMutexFunctions(&gContext, myMutexInit, myMutexDestroy, myMutexLock, myMutexUnlock, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Doing ICU operations should cause allocations to come through our test mutexes */
+ gBlockCount = 0;
+ status = U_ZERO_ERROR;
+ rb = ures_open(NULL, "es", &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ TEST_ASSERT(gTotalMutexesInitialized > 0);
+ TEST_ASSERT(gTotalMutexesActive > 0);
+
+ ures_close(rb);
+
+ /* Cleanup should destroy all of the mutexes. */
+ u_cleanup();
+ u_setDataDirectory(icuDataDir);
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ status = U_ZERO_ERROR;
+ TEST_ASSERT(gTotalMutexesInitialized > 0);
+ TEST_ASSERT(gTotalMutexesActive == 0);
+
+
+ /* Additional ICU operations should no longer use our dummy test mutexes */
+ gTotalMutexesInitialized = 0;
+ gTotalMutexesActive = 0;
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+
+ status = U_ZERO_ERROR;
+ rb = ures_open(NULL, "fr", &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ TEST_ASSERT(gTotalMutexesInitialized == 0);
+ TEST_ASSERT(gTotalMutexesActive == 0);
+
+ ures_close(rb);
+ free(icuDataDir);
+
+ if(gMutexFailures) {
+ log_info("Note: these failures may be caused by ICU failing to initialize/uninitialize properly.\n");
+ log_verbose("Check for prior tests which may not have closed all open resources. See the internal function ures_flushCache()\n");
+ }
+}
+
+
+
+
+/*
+ * Test Atomic Increment & Decrement Functions
+ */
+
+int gIncCount = 0;
+int gDecCount = 0;
+const void *gIncDecContext;
+const void *gExpectedContext = &gIncDecContext;
+
+
+static int32_t U_CALLCONV myIncFunc(const void *context, int32_t *p) {
+ int32_t retVal;
+ TEST_ASSERT(context == gExpectedContext);
+ gIncCount++;
+ retVal = ++(*p);
+ return retVal;
+}
+
+static int32_t U_CALLCONV myDecFunc(const void *context, int32_t *p) {
+ int32_t retVal;
+ TEST_ASSERT(context == gExpectedContext);
+ gDecCount++;
+ retVal = --(*p);
+ return retVal;
+}
+
+
+
+
+static void TestIncDecFunctions() {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t t = 1; /* random value to make sure that Inc/dec works */
+ char *dataDir;
+
+ UTraceEntry *traceEntryFunc; /* Tracing function ptrs. We need to save */
+ UTraceExit *traceExitFunc; /* and restore them across calls to */
+ UTraceData *traceDataFunc; /* u_cleanup() that we make in this test. */
+ const void *traceContext;
+ int32_t traceLevel;
+
+ /* Save ICU's data dir and tracing functions so that they can be resored
+ after cleanup and reinit. */
+ dataDir = safeGetICUDataDirectory();
+ utrace_getFunctions(&traceContext, &traceEntryFunc, &traceExitFunc, &traceDataFunc);
+ traceLevel = utrace_getLevel();
+
+ /* Verify that ICU can be cleaned up and reinitialized successfully.
+ * Failure here usually means that some ICU service didn't clean up successfully,
+ * probably because some earlier test accidently left something open. */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(dataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ /* Can not set mutex functions if ICU is already initialized */
+ u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Clean up ICU */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+
+ /* Can not set functions with NULL values */
+ status = U_ZERO_ERROR;
+ u_setAtomicIncDecFunctions(&gIncDecContext, NULL, myDecFunc, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+ status = U_ZERO_ERROR;
+ u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, NULL, &status);
+ TEST_STATUS(status, U_ILLEGAL_ARGUMENT_ERROR);
+
+ /* u_setIncDecFunctions() should work with null or non-null context pointer */
+ status = U_ZERO_ERROR;
+ gExpectedContext = NULL;
+ u_setAtomicIncDecFunctions(NULL, myIncFunc, myDecFunc, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ gExpectedContext = &gIncDecContext;
+ u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+
+
+ /* After reinitializing ICU, we should not be able to set the inc/dec funcs again. */
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(dataDir);
+ u_init(&status);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ gExpectedContext = &gIncDecContext;
+ u_setAtomicIncDecFunctions(&gIncDecContext, myIncFunc, myDecFunc, &status);
+ TEST_STATUS(status, U_INVALID_STATE_ERROR);
+
+ /* Doing ICU operations should cause our functions to be called */
+ gIncCount = 0;
+ gDecCount = 0;
+ umtx_atomic_inc(&t);
+ TEST_ASSERT(t == 2);
+ umtx_atomic_dec(&t);
+ TEST_ASSERT(t == 1);
+ TEST_ASSERT(gIncCount > 0);
+ TEST_ASSERT(gDecCount > 0);
+
+
+ /* Cleanup should cancel use of our inc/dec functions. */
+ /* Additional ICU operations should not use them */
+ u_cleanup();
+ utrace_setFunctions(traceContext, traceEntryFunc, traceExitFunc, traceDataFunc);
+ utrace_setLevel(traceLevel);
+ gIncCount = 0;
+ gDecCount = 0;
+ status = U_ZERO_ERROR;
+ u_setDataDirectory(dataDir);
+ u_init(&status);
+ TEST_ASSERT(gIncCount == 0);
+ TEST_ASSERT(gDecCount == 0);
+
+ status = U_ZERO_ERROR;
+ umtx_atomic_inc(&t);
+ umtx_atomic_dec(&t);
+ TEST_STATUS(status, U_ZERO_ERROR);
+ TEST_ASSERT(gIncCount == 0);
+ TEST_ASSERT(gDecCount == 0);
+
+ free(dataDir);
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c
new file mode 100644
index 00000000000..6196523087a
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/idnatest.c
@@ -0,0 +1,885 @@
+/*
+ *******************************************************************************
+ *
+ * Copyright (C) 2003-2007, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *
+ *******************************************************************************
+ * file name: idnatest.c
+ * encoding: US-ASCII
+ * tab size: 8 (not used)
+ * indentation:4
+ *
+ * created on: 2003jul11
+ * created by: Ram Viswanadha
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_IDNA
+
+#include "unicode/ustring.h"
+#include "unicode/uidna.h"
+#include "cintltst.h"
+
+
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+#define MAX_DEST_SIZE 1000
+
+static void TestToUnicode(void);
+static void TestToASCII(void);
+static void TestIDNToUnicode(void);
+static void TestIDNToASCII(void);
+static void TestCompare(void);
+static void TestUnicode32Norm(void);
+static void TestJB4490(void);
+static void TestJB4475(void);
+static void TestLength(void);
+static void TestJB5273(void);
+void addIDNATest(TestNode** root);
+
+
+typedef int32_t
+(U_EXPORT2 *TestFunc) ( const UChar *src, int32_t srcLength,
+ UChar *dest, int32_t destCapacity,
+ int32_t options, UParseError *parseError,
+ UErrorCode *status);
+typedef int32_t
+(U_EXPORT2 *CompareFunc) (const UChar *s1, int32_t s1Len,
+ const UChar *s2, int32_t s2Len,
+ int32_t options,
+ UErrorCode *status);
+
+
+void
+addIDNATest(TestNode** root)
+{
+ addTest(root, &TestToUnicode, "idna/TestToUnicode");
+ addTest(root, &TestToASCII, "idna/TestToASCII");
+ addTest(root, &TestIDNToUnicode, "idna/TestIDNToUnicode");
+ addTest(root, &TestIDNToASCII, "idna/TestIDNToASCII");
+ addTest(root, &TestCompare, "idna/TestCompare");
+ addTest(root, &TestUnicode32Norm,"idna/TestUnicode32Norm");
+ addTest(root, &TestJB4490, "idna/TestJB4490");
+ addTest(root, &TestJB4475, "idna/TestJB4475");
+ addTest(root, &TestLength, "idna/TestLength");
+ addTest(root, &TestJB5273, "idna/TestJB5273");
+}
+
+static void
+testAPI(const UChar* src, const UChar* expected, const char* testName,
+ UBool useSTD3ASCIIRules,UErrorCode expectedStatus,
+ UBool doCompare, UBool testUnassigned, TestFunc func){
+
+ UErrorCode status = U_ZERO_ERROR;
+ UChar destStack[MAX_DEST_SIZE];
+ int32_t destLen = 0;
+ UChar* dest = NULL;
+ int32_t expectedLen = (expected != NULL) ? u_strlen(expected) : 0;
+ int32_t options = (useSTD3ASCIIRules == TRUE) ? UIDNA_USE_STD3_RULES : UIDNA_DEFAULT;
+ UParseError parseError;
+ int32_t tSrcLen = 0;
+ UChar* tSrc = NULL;
+
+ if(src != NULL){
+ tSrcLen = u_strlen(src);
+ tSrc =(UChar*) malloc( U_SIZEOF_UCHAR * tSrcLen );
+ memcpy(tSrc,src,tSrcLen * U_SIZEOF_UCHAR);
+ }
+
+ /* test null-terminated source and return value of number of UChars required */
+
+ destLen = func(src,-1,NULL,0,options, &parseError , &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code */
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,-1,dest,destLen+1,options, &parseError, &status);
+ /* TODO : compare output with expected */
+ if(U_SUCCESS(status) && expectedStatus != U_IDNA_STD3_ASCII_RULES_ERROR&& (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for null terminated source.\n" );
+ }
+ }else{
+ log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+
+ if(status != expectedStatus){
+ log_err( "Did not get the expected error for %s null terminated source failed. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ free(tSrc);
+ return;
+ }
+ if(testUnassigned ){
+ status = U_ZERO_ERROR;
+ destLen = func(src,-1,NULL,0,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code */
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,-1,dest,destLen+1,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status);
+ /* TODO : compare output with expected */
+ if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for %s null terminated source with both options set.\n",testName);
+
+ }
+ }else{
+ log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+ /*testing query string*/
+ if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){
+ log_err( "Did not get the expected error for %s null terminated source with options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ }
+ }
+
+ status = U_ZERO_ERROR;
+
+ /* test source with lengthand return value of number of UChars required*/
+ destLen = func(tSrc, tSrcLen, NULL,0,options, &parseError, &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code */
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,u_strlen(src),dest,destLen+1,options, &parseError, &status);
+ /* TODO : compare output with expected */
+ if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for %s with source length.\n",testName);
+ }
+ }else{
+ log_err( "%s with source length failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+
+ if(status != expectedStatus){
+ log_err( "Did not get the expected error for %s with source length. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ }
+ if(testUnassigned){
+ status = U_ZERO_ERROR;
+
+ destLen = func(tSrc,tSrcLen,NULL,0,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status);
+
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code */
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,u_strlen(src),dest,destLen+1,options | UIDNA_ALLOW_UNASSIGNED, &parseError, &status);
+ /* TODO : compare output with expected */
+ if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for %s with source length and both options set.\n",testName);
+ }
+ }else{
+ log_err( "%s with source length failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+ /*testing query string*/
+ if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){
+ log_err( "Did not get the expected error for %s with source length and options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = func(src,-1,NULL,0,options | UIDNA_USE_STD3_RULES, &parseError, &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code*/
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,-1,dest,destLen+1,options | UIDNA_USE_STD3_RULES, &parseError, &status);
+ /* TODO : compare output with expected*/
+ if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for %s null terminated source with both options set.\n",testName);
+
+ }
+ }else{
+ log_err( "%s null terminated source failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+ /*testing query string*/
+ if(status != expectedStatus){
+ log_err( "Did not get the expected error for %s null terminated source with options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+
+ destLen = func(tSrc,tSrcLen,NULL,0,options | UIDNA_USE_STD3_RULES, &parseError, &status);
+
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR; /* reset error code*/
+ if(destLen+1 < MAX_DEST_SIZE){
+ dest = destStack;
+ destLen = func(src,u_strlen(src),dest,destLen+1,options | UIDNA_USE_STD3_RULES, &parseError, &status);
+ /* TODO : compare output with expected*/
+ if(U_SUCCESS(status) && (doCompare==TRUE) && u_strCaseCompare(dest,destLen, expected,expectedLen,0,&status)!=0){
+ log_err("Did not get the expected result for %s with source length and both options set.\n",testName);
+ }
+ }else{
+ log_err( "%s with source length failed. Requires destCapacity > 300\n",testName);
+ }
+ }
+ /*testing query string*/
+ if(status != expectedStatus && expectedStatus != U_IDNA_UNASSIGNED_ERROR){
+ log_err( "Did not get the expected error for %s with source length and options set. Expected: %s Got: %s\n",testName, u_errorName(expectedStatus), u_errorName(status));
+ }
+ free(tSrc);
+}
+
+static const UChar unicodeIn[][41] ={
+ {
+ 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644,
+ 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 0x061F, 0x0000
+ },
+ {
+ 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 0x6587,
+ 0x0000
+ },
+ {
+ 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 0x0074,
+ 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 0x00ED, 0x010D,
+ 0x0065, 0x0073, 0x006B, 0x0079, 0x0000
+ },
+ {
+ 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 0x05D8,
+ 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 0x05DD, 0x05E2,
+ 0x05D1, 0x05E8, 0x05D9, 0x05EA, 0x0000
+ },
+ {
+ 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 0x094D,
+ 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 0x0928, 0x0939,
+ 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 0x0915, 0x0924, 0x0947,
+ 0x0939, 0x0948, 0x0902, 0x0000
+ },
+ {
+ 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 0x3092,
+ 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 0x306E, 0x304B,
+ 0x0000
+ },
+/*
+ {
+ 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774,
+ 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C, 0xB2E4, 0xBA74,
+ 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 0xAE4C, 0x0000
+ },
+*/
+ {
+ 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 0x043E,
+ 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 0x043E, 0x0440,
+ 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 0x0441, 0x0441, 0x043A,
+ 0x0438, 0x0000
+ },
+ {
+ 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 0x0070,
+ 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 0x006D, 0x0070,
+ 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 0x0065, 0x0068, 0x0061,
+ 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 0x006E, 0x0045, 0x0073, 0x0070,
+ 0x0061, 0x00F1, 0x006F, 0x006C, 0x0000
+ },
+ {
+ 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 0x6587,
+ 0x0000
+ },
+ {
+ 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 0x006B,
+ 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 0x0063, 0x0068,
+ 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 0x1EBF, 0x006E, 0x0067,
+ 0x0056, 0x0069, 0x1EC7, 0x0074, 0x0000
+ },
+ {
+ 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F, 0x0000
+ },
+ {
+ 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 0x0074,
+ 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 0x002D, 0x004D,
+ 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053, 0x0000
+ },
+ {
+ 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 0x006F,
+ 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 0x0079, 0x002D,
+ 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 0x6240, 0x0000
+ },
+ {
+ 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032, 0x0000
+ },
+ {
+ 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 0x3059,
+ 0x308B, 0x0035, 0x79D2, 0x524D, 0x0000
+ },
+ {
+ 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0,
+ 0x0000
+ },
+ {
+ 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067, 0x0000
+ },
+ /* test non-BMP code points */
+ {
+ 0xD800, 0xDF00, 0xD800, 0xDF01, 0xD800, 0xDF02, 0xD800, 0xDF03, 0xD800, 0xDF05,
+ 0xD800, 0xDF06, 0xD800, 0xDF07, 0xD800, 0xDF09, 0xD800, 0xDF0A, 0xD800, 0xDF0B,
+ 0x0000
+ },
+ {
+ 0xD800, 0xDF0D, 0xD800, 0xDF0C, 0xD800, 0xDF1E, 0xD800, 0xDF0F, 0xD800, 0xDF16,
+ 0xD800, 0xDF15, 0xD800, 0xDF14, 0xD800, 0xDF12, 0xD800, 0xDF10, 0xD800, 0xDF20,
+ 0xD800, 0xDF21,
+ 0x0000
+ },
+ /* Greek */
+ {
+ 0x03b5, 0x03bb, 0x03bb, 0x03b7, 0x03bd, 0x03b9, 0x03ba, 0x03ac
+ },
+ /* Maltese */
+ {
+ 0x0062, 0x006f, 0x006e, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127,
+ 0x0127, 0x0061
+ },
+ /* Russian */
+ {
+ 0x043f, 0x043e, 0x0447, 0x0435, 0x043c, 0x0443, 0x0436, 0x0435,
+ 0x043e, 0x043d, 0x0438, 0x043d, 0x0435, 0x0433, 0x043e, 0x0432,
+ 0x043e, 0x0440, 0x044f, 0x0442, 0x043f, 0x043e, 0x0440, 0x0443,
+ 0x0441, 0x0441, 0x043a, 0x0438
+ },
+ {
+ 0x0054,0x0045,0x0053,0x0054
+ }
+};
+
+static const char * const asciiIn[] = {
+ "xn--egbpdaj6bu4bxfgehfvwxn",
+ "xn--ihqwcrb4cv8a8dqg056pqjye",
+ "xn--Proprostnemluvesky-uyb24dma41a",
+ "xn--4dbcagdahymbxekheh6e0a7fei0b",
+ "xn--i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
+ "xn--n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
+/* "xn--989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c",*/
+ "xn--b1abfaaepdrnnbgefbaDotcwatmq2g4l",
+ "xn--PorqunopuedensimplementehablarenEspaol-fmd56a",
+ "xn--ihqwctvzc91f659drss3x8bo0yb",
+ "xn--TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
+ "xn--3B-ww4c5e180e575a65lsy2b",
+ "xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
+ "xn--Hello-Another-Way--fc4qua05auwb3674vfr0b",
+ "xn--2-u9tlzr9756bt3uc0v",
+ "xn--MajiKoi5-783gue6qz075azm5e",
+ "xn--de-jg4avhby1noc0d",
+ "xn--d9juau41awczczp",
+ "XN--097CCDEKGHQJK",
+ "XN--db8CBHEJLGH4E0AL",
+ "xn--hxargifdar", /* Greek */
+ "xn--bonusaa-5bb1da", /* Maltese */
+ "xn--b1abfaaepdrnnbgefbadotcwatmq2g4l", /* Russian (Cyrillic)*/
+ "TEST"
+
+};
+
+static const char * const domainNames[] = {
+ "slip129-37-118-146.nc.us.ibm.net",
+ "saratoga.pe.utexas.edu",
+ "dial-120-45.ots.utexas.edu",
+ "woo-085.dorms.waller.net",
+ "hd30-049.hil.compuserve.com",
+ "pem203-31.pe.ttu.edu",
+ "56K-227.MaxTNT3.pdq.net",
+ "dial-36-2.ots.utexas.edu",
+ "slip129-37-23-152.ga.us.ibm.net",
+ "ts45ip119.cadvision.com",
+ "sdn-ts-004txaustP05.dialsprint.net",
+ "bar-tnt1s66.erols.com",
+ "101.st-louis-15.mo.dial-access.att.net",
+ "h92-245.Arco.COM",
+ "dial-13-2.ots.utexas.edu",
+ "net-redynet29.datamarkets.com.ar",
+ "ccs-shiva28.reacciun.net.ve",
+ "7.houston-11.tx.dial-access.att.net",
+ "ingw129-37-120-26.mo.us.ibm.net",
+ "dialup6.austintx.com",
+ "dns2.tpao.gov.tr",
+ "slip129-37-119-194.nc.us.ibm.net",
+ "cs7.dillons.co.uk.203.119.193.in-addr.arpa",
+ "swprd1.innovplace.saskatoon.sk.ca",
+ "bikini.bologna.maraut.it",
+ "node91.subnet159-198-79.baxter.com",
+ "cust19.max5.new-york.ny.ms.uu.net",
+ "balexander.slip.andrew.cmu.edu",
+ "pool029.max2.denver.co.dynip.alter.net",
+ "cust49.max9.new-york.ny.ms.uu.net",
+ "s61.abq-dialin2.hollyberry.com",
+ "\\u0917\\u0928\\u0947\\u0936.sanjose.ibm.com", /*':'(0x003a) produces U_IDNA_STD3_ASCII_RULES_ERROR*/
+ "www.xn--vea.com",
+ /* "www.\\u00E0\\u00B3\\u00AF.com",//' ' (0x0020) produces U_IDNA_STD3_ASCII_RULES_ERROR*/
+ "www.\\u00C2\\u00A4.com",
+ "www.\\u00C2\\u00A3.com",
+ /* "\\u0025", //'%' (0x0025) produces U_IDNA_STD3_ASCII_RULES_ERROR*/
+ /* "\\u005C\\u005C", //'\' (0x005C) produces U_IDNA_STD3_ASCII_RULES_ERROR*/
+ /*"@",*/
+ /*"\\u002F",*/
+ /*"www.\\u0021.com",*/
+ /*"www.\\u0024.com",*/
+ /*"\\u003f",*/
+ /* These yeild U_IDNA_PROHIBITED_ERROR*/
+ /*"\\u00CF\\u0082.com",*/
+ /*"\\u00CE\\u00B2\\u00C3\\u009Fss.com",*/
+ /*"\\u00E2\\u0098\\u00BA.com",*/
+ "\\u00C3\\u00BC.com"
+
+};
+
+static void
+TestToASCII(){
+
+ int32_t i;
+ UChar buf[MAX_DEST_SIZE];
+ const char* testName = "uidna_toASCII";
+ TestFunc func = uidna_toASCII;
+ for(i=0;i< (int32_t)(sizeof(unicodeIn)/sizeof(unicodeIn[0])); i++){
+ u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1);
+ testAPI(unicodeIn[i], buf,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
+
+ }
+}
+
+static void
+TestToUnicode(){
+
+ int32_t i;
+ UChar buf[MAX_DEST_SIZE];
+ const char* testName = "uidna_toUnicode";
+ TestFunc func = uidna_toUnicode;
+ for(i=0;i< (int32_t)(sizeof(asciiIn)/sizeof(asciiIn[0])); i++){
+ u_charsToUChars(asciiIn[i],buf, (int32_t)strlen(asciiIn[i])+1);
+ testAPI(buf,unicodeIn[i],testName,FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
+ }
+}
+
+
+static void
+TestIDNToUnicode(){
+ int32_t i;
+ UChar buf[MAX_DEST_SIZE];
+ UChar expected[MAX_DEST_SIZE];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t bufLen = 0;
+ UParseError parseError;
+ const char* testName="uidna_IDNToUnicode";
+ TestFunc func = uidna_IDNToUnicode;
+ for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){
+ bufLen = (int32_t)strlen(domainNames[i]);
+ bufLen = u_unescape(domainNames[i],buf, bufLen+1);
+ func(buf,bufLen,expected,MAX_DEST_SIZE, UIDNA_ALLOW_UNASSIGNED, &parseError,&status);
+ if(U_FAILURE(status)){
+ log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName, i, u_errorName(status));
+ break;
+ }
+ testAPI(buf,expected,testName,FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
+ /*test toUnicode with all labels in the string*/
+ testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
+ if(U_FAILURE(status)){
+ log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status));
+ break;
+ }
+ }
+
+}
+
+static void
+TestIDNToASCII(){
+ int32_t i;
+ UChar buf[MAX_DEST_SIZE];
+ UChar expected[MAX_DEST_SIZE];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t bufLen = 0;
+ UParseError parseError;
+ const char* testName="udina_IDNToASCII";
+ TestFunc func=uidna_IDNToASCII;
+
+ for(i=0;i< (int32_t)(sizeof(domainNames)/sizeof(domainNames[0])); i++){
+ bufLen = (int32_t)strlen(domainNames[i]);
+ bufLen = u_unescape(domainNames[i],buf, bufLen+1);
+ func(buf,bufLen,expected,MAX_DEST_SIZE, UIDNA_ALLOW_UNASSIGNED, &parseError,&status);
+ if(U_FAILURE(status)){
+ log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status));
+ break;
+ }
+ testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, TRUE, TRUE, func);
+ /*test toASCII with all labels in the string*/
+ testAPI(buf,expected,testName, FALSE,U_ZERO_ERROR, FALSE, TRUE, func);
+ if(U_FAILURE(status)){
+ log_err( "%s failed to convert domainNames[%i].Error: %s \n",testName,i, u_errorName(status));
+ break;
+ }
+ }
+
+
+}
+
+
+static void
+testCompareWithSrc(const UChar* s1, int32_t s1Len,
+ const UChar* s2, int32_t s2Len,
+ const char* testName, CompareFunc func,
+ UBool isEqual){
+
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t retVal = func(s1,-1,s2,-1,UIDNA_DEFAULT,&status);
+
+ if(isEqual==TRUE && retVal !=0){
+ log_err("Did not get the expected result for %s with null termniated strings.\n",testName);
+ }
+ if(U_FAILURE(status)){
+ log_err( "%s null terminated source failed. Error: %s\n", testName,u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ retVal = func(s1,-1,s2,-1,UIDNA_ALLOW_UNASSIGNED,&status);
+
+ if(isEqual==TRUE && retVal !=0){
+ log_err("Did not get the expected result for %s with null termniated strings with options set.\n", testName);
+ }
+ if(U_FAILURE(status)){
+ log_err( "%s null terminated source and options set failed. Error: %s\n",testName, u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ retVal = func(s1,s1Len,s2,s2Len,UIDNA_DEFAULT,&status);
+
+ if(isEqual==TRUE && retVal !=0){
+ log_err("Did not get the expected result for %s with string length.\n",testName);
+ }
+ if(U_FAILURE(status)){
+ log_err( "%s with string length. Error: %s\n",testName, u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ retVal = func(s1,s1Len,s2,s2Len,UIDNA_ALLOW_UNASSIGNED,&status);
+
+ if(isEqual==TRUE && retVal !=0){
+ log_err("Did not get the expected result for %s with string length and options set.\n",testName);
+ }
+ if(U_FAILURE(status)){
+ log_err( "%s with string length and options set. Error: %s\n", u_errorName(status), testName);
+ }
+}
+
+
+static void
+TestCompare(){
+ int32_t i;
+
+ const char* testName ="uidna_compare";
+ CompareFunc func = uidna_compare;
+
+ UChar www[] = {0x0057, 0x0057, 0x0057, 0x002E, 0x0000};
+ UChar com[] = {0x002E, 0x0043, 0x004F, 0x004D, 0x0000};
+ UChar buf[MAX_DEST_SIZE]={0x0057, 0x0057, 0x0057, 0x002E, 0x0000};
+ UChar source[MAX_DEST_SIZE]={0},
+ uni0[MAX_DEST_SIZE]={0},
+ uni1[MAX_DEST_SIZE]={0},
+ ascii0[MAX_DEST_SIZE]={0},
+ ascii1[MAX_DEST_SIZE]={0},
+ temp[MAX_DEST_SIZE] ={0};
+
+
+ u_strcat(uni0,unicodeIn[0]);
+ u_strcat(uni0,com);
+
+ u_strcat(uni1,unicodeIn[1]);
+ u_strcat(uni1,com);
+
+ u_charsToUChars(asciiIn[0], temp, (int32_t)strlen(asciiIn[0]));
+ u_strcat(ascii0,temp);
+ u_strcat(ascii0,com);
+
+ memset(temp, 0, U_SIZEOF_UCHAR * MAX_DEST_SIZE);
+
+ u_charsToUChars(asciiIn[1], temp, (int32_t)strlen(asciiIn[1]));
+ u_strcat(ascii1,temp);
+ u_strcat(ascii1,com);
+
+ /* prepend www. */
+ u_strcat(source, www);
+
+ for(i=0;i< (int32_t)(sizeof(unicodeIn)/sizeof(unicodeIn[0])); i++){
+ UChar* src;
+ int32_t srcLen;
+
+ memset(buf+4, 0, (MAX_DEST_SIZE-4) * U_SIZEOF_UCHAR);
+
+ u_charsToUChars(asciiIn[i],buf+4, (int32_t)strlen(asciiIn[i]));
+ u_strcat(buf,com);
+
+
+ /* for every entry in unicodeIn array
+ prepend www. and append .com*/
+ source[4]=0;
+ u_strncat(source,unicodeIn[i], u_strlen(unicodeIn[i]));
+ u_strcat(source,com);
+
+ /* a) compare it with itself*/
+ src = source;
+ srcLen = u_strlen(src);
+
+ testCompareWithSrc(src,srcLen,src,srcLen,testName, func, TRUE);
+
+ /* b) compare it with asciiIn equivalent */
+ testCompareWithSrc(src,srcLen,buf,u_strlen(buf),testName, func,TRUE);
+
+ /* c) compare it with unicodeIn not equivalent*/
+ if(i==0){
+ testCompareWithSrc(src,srcLen,uni1,u_strlen(uni1),testName, func,FALSE);
+ }else{
+ testCompareWithSrc(src,srcLen,uni0,u_strlen(uni0),testName, func,FALSE);
+ }
+ /* d) compare it with asciiIn not equivalent */
+ if(i==0){
+ testCompareWithSrc(src,srcLen,ascii1,u_strlen(ascii1),testName, func,FALSE);
+ }else{
+ testCompareWithSrc(src,srcLen,ascii0,u_strlen(ascii0),testName, func,FALSE);
+ }
+
+ }
+}
+
+static void TestUnicode32Norm() {
+ /*
+ * test Unicode 3.2 normalization, before Public Review Issue #29
+ * see cnormtst.c TestComposition()
+ */
+ static const UChar strings[][8]={
+ { 0x1100, 0x0300, 0x1161, 0x0327 },
+ { 0x0b47, 0x0300, 0x0b3e, 0x0327 }
+ };
+
+ UChar ascii[20], unicode[20];
+ int32_t i, length;
+ UErrorCode errorCode;
+
+ for(i=0; i<LENGTHOF(strings); ++i) {
+ errorCode=U_ZERO_ERROR;
+ length=uidna_toASCII(strings[i], -1, ascii, LENGTHOF(ascii), 0, NULL, &errorCode);
+ length=uidna_toUnicode(ascii, length, unicode, LENGTHOF(unicode), 0, NULL, &errorCode);
+ if(u_strncmp(ascii, unicode, length)!=0) {
+ log_err("Did not get the correct output\n");
+ }
+ }
+}
+
+static void TestJB4490(){
+ static const UChar data[][50]= {
+ {0x00F5,0x00dE,0x00dF,0x00dD, 0x0000},
+ {0xFB00,0xFB01}
+ };
+ UChar output1[40] = {0};
+ UChar output2[40] = {0};
+ int32_t i;
+ for(i=0; i< sizeof(data)/sizeof(data[0]); i++){
+ const UChar* src1 = data[i];
+ int32_t src1Len = u_strlen(src1);
+ UChar* dest1 = output1;
+ int32_t dest1Len = 40;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError ps;
+ UChar* src2 = NULL;
+ int32_t src2Len = 0;
+ UChar* dest2 = output2;
+ int32_t dest2Len = 40;
+ dest1Len = uidna_toASCII(src1, src1Len, dest1, dest1Len,UIDNA_DEFAULT, &ps, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status));
+ }
+ src2 = dest1;
+ src2Len = dest1Len;
+ dest2Len = uidna_toUnicode(src2, src2Len, dest2, dest2Len, UIDNA_DEFAULT, &ps, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status));
+ }
+ }
+}
+
+static void TestJB4475(){
+
+ static const UChar input[][10] = {
+ {0x0054,0x0045,0x0053,0x0054,0x0000},/* TEST */
+ {0x0074,0x0065,0x0073,0x0074,0x0000} /* test */
+ };
+ int i;
+ UChar output[40] = {0};
+ for(i=0; i< sizeof(input)/sizeof(input[0]); i++){
+ const UChar* src = input[i];
+ int32_t srcLen = u_strlen(src);
+ UChar* dest = output;
+ int32_t destLen = 40;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError ps;
+
+ destLen = uidna_toASCII(src, srcLen, dest, destLen,UIDNA_DEFAULT, &ps, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toASCII failed with error %s.\n", u_errorName(status));
+ }
+ if(u_strncmp(input[i], dest, srcLen)!=0){
+ log_err("uidna_toASCII did not return the expected output.\n");
+ }
+ }
+}
+
+static void TestLength(){
+ {
+ static const char* cl = "my_very_very_very_very_very_very_very_very_very_very_very_very_very_long_and_incredibly_uncreative_domain_label";
+ UChar ul[128] = {'\0'};
+ UChar dest[256] = {'\0'};
+ /* this unicode string is longer than MAX_LABEL_BUFFER_SIZE and produces an
+ IDNA prepared string (including xn--)that is exactly 63 bytes long */
+ UChar ul1[] = { 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 0xC774,
+ 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0x00AD, 0x034F, 0x1806, 0x180B,
+ 0x180C, 0x180D, 0x200B, 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02,
+ 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B,
+ 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF, 0xD574, 0xD55C, 0xB2E4, 0xBA74,
+ 0xC138, 0x0041, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B,
+ 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05,
+ 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E,
+ 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B,
+ 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05,
+ 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E,
+ 0xFE0F, 0xFEFF, 0x00AD, 0x034F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B,
+ 0x200C, 0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05,
+ 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E,
+ 0xFE0F, 0xFEFF, 0x0000
+ };
+
+ int32_t len1 = LENGTHOF(ul1)-1/*remove the null termination*/;
+ int32_t destLen = LENGTHOF(dest);
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError ps;
+ int32_t len = (int32_t)strlen(cl);
+ u_charsToUChars(cl, ul, len+1);
+ destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_ZERO_ERROR){
+ log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = -1;
+ destLen = uidna_toUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_ZERO_ERROR){
+ log_err("uidna_toUnicode failed with error %s.\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = (int32_t)strlen(cl);
+ destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_LABEL_TOO_LONG_ERROR){
+ log_err("uidna_toASCII failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = -1;
+ destLen = uidna_toASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_LABEL_TOO_LONG_ERROR){
+ log_err("uidna_toASCII failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_ZERO_ERROR){
+ log_err("uidna_toASCII failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len1 = -1;
+ destLen = uidna_toASCII(ul1, len1, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_ZERO_ERROR){
+ log_err("uidna_toASCII failed with error %s.\n", u_errorName(status));
+ }
+ }
+ {
+ static const char* cl = "my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.my_very_very_long_and_incredibly_uncreative_domain_label.ibm.com";
+ UChar ul[400] = {'\0'};
+ UChar dest[400] = {'\0'};
+ int32_t destLen = LENGTHOF(dest);
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError ps;
+ int32_t len = (int32_t)strlen(cl);
+ u_charsToUChars(cl, ul, len+1);
+
+ destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_IDNToUnicode failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = -1;
+ destLen = uidna_IDNToUnicode(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_IDNToUnicode failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = (int32_t)strlen(cl);
+ destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_IDNToASCII failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ destLen = LENGTHOF(dest);
+ len = -1;
+ destLen = uidna_IDNToASCII(ul, len, dest, destLen, UIDNA_DEFAULT, &ps, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_IDNToASCII failed with error %s.\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ uidna_compare(ul, len, ul, len, UIDNA_DEFAULT, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_compare failed with error %s.\n", u_errorName(status));
+ }
+ uidna_compare(ul, -1, ul, -1, UIDNA_DEFAULT, &status);
+ if(status != U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR){
+ log_err("uidna_compare failed with error %s.\n", u_errorName(status));
+ }
+ }
+}
+static void TestJB5273(){
+ static const char INVALID_DOMAIN_NAME[] = "xn--m\\u00FCller.de";
+ UChar invalid_idn[25] = {'\0'};
+ int32_t len = u_unescape(INVALID_DOMAIN_NAME, invalid_idn, strlen(INVALID_DOMAIN_NAME));
+ UChar output[50] = {'\0'};
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError prsError;
+ int32_t outLen = uidna_toUnicode(invalid_idn, len, output, 50, UIDNA_DEFAULT, &prsError, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ outLen = uidna_toUnicode(invalid_idn, len, output, 50, UIDNA_USE_STD3_RULES, &prsError, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status));
+ }
+
+ status = U_ZERO_ERROR;
+ outLen = uidna_IDNToUnicode(invalid_idn, len, output, 50, UIDNA_DEFAULT, &prsError, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ outLen = uidna_IDNToUnicode(invalid_idn, len, output, 50, UIDNA_USE_STD3_RULES, &prsError, &status);
+ if(U_FAILURE(status)){
+ log_err("uidna_toUnicode failed with error: %s\n", u_errorName(status));
+ }
+}
+#endif
+
+/*
+ * Hey, Emacs, please set the following:
+ *
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c
new file mode 100644
index 00000000000..d82d37b9e6d
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.c
@@ -0,0 +1,3354 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+********************************************************************************
+* File NCCBTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda 7/21/1999 Testing error callback routines
+********************************************************************************
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "cstring.h"
+#include "unicode/uloc.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_err.h"
+#include "cintltst.h"
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "nccbtst.h"
+#include "unicode/ucnv_cb.h"
+#define NEW_MAX_BUFFER 999
+
+#define nct_min(x,y) ((x<y) ? x : y)
+#define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
+
+static int32_t gInBufferSize = 0;
+static int32_t gOutBufferSize = 0;
+static char gNuConvTestName[1024];
+
+static void printSeq(const uint8_t* a, int len)
+{
+ int i=0;
+ log_verbose("\n{");
+ while (i<len)
+ log_verbose("0x%02X, ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printUSeq(const UChar* a, int len)
+{
+ int i=0;
+ log_verbose("{");
+ while (i<len)
+ log_verbose(" 0x%04x, ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printSeqErr(const uint8_t* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{");
+ while (i<len)
+ fprintf(stderr, " 0x%02x, ", a[i++]);
+ fprintf(stderr, "}\n");
+}
+
+static void printUSeqErr(const UChar* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{");
+ while (i<len)
+ fprintf(stderr, "0x%04x, ", a[i++]);
+ fprintf(stderr,"}\n");
+}
+
+static void setNuConvTestName(const char *codepage, const char *direction)
+{
+ sprintf(gNuConvTestName, "[testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]",
+ codepage,
+ direction,
+ (int)gInBufferSize,
+ (int)gOutBufferSize);
+}
+
+
+static void TestCallBackFailure(void);
+
+void addTestConvertErrorCallBack(TestNode** root);
+
+void addTestConvertErrorCallBack(TestNode** root)
+{
+ addTest(root, &TestSkipCallBack, "tsconv/nccbtst/TestSkipCallBack");
+ addTest(root, &TestStopCallBack, "tsconv/nccbtst/TestStopCallBack");
+ addTest(root, &TestSubCallBack, "tsconv/nccbtst/TestSubCallBack");
+ addTest(root, &TestSubWithValueCallBack, "tsconv/nccbtst/TestSubWithValueCallBack");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestLegalAndOtherCallBack, "tsconv/nccbtst/TestLegalAndOtherCallBack");
+ addTest(root, &TestSingleByteCallBack, "tsconv/nccbtst/TestSingleByteCallBack");
+#endif
+
+ addTest(root, &TestCallBackFailure, "tsconv/nccbtst/TestCallBackFailure");
+}
+
+static void TestSkipCallBack()
+{
+ TestSkip(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestSkip(1,NEW_MAX_BUFFER);
+ TestSkip(1,1);
+ TestSkip(NEW_MAX_BUFFER, 1);
+}
+
+static void TestStopCallBack()
+{
+ TestStop(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestStop(1,NEW_MAX_BUFFER);
+ TestStop(1,1);
+ TestStop(NEW_MAX_BUFFER, 1);
+}
+
+static void TestSubCallBack()
+{
+ TestSub(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestSub(1,NEW_MAX_BUFFER);
+ TestSub(1,1);
+ TestSub(NEW_MAX_BUFFER, 1);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ TestEBCDIC_STATEFUL_Sub(1, 1);
+ TestEBCDIC_STATEFUL_Sub(1, NEW_MAX_BUFFER);
+ TestEBCDIC_STATEFUL_Sub(NEW_MAX_BUFFER, 1);
+ TestEBCDIC_STATEFUL_Sub(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+#endif
+}
+
+static void TestSubWithValueCallBack()
+{
+ TestSubWithValue(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestSubWithValue(1,NEW_MAX_BUFFER);
+ TestSubWithValue(1,1);
+ TestSubWithValue(NEW_MAX_BUFFER, 1);
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestLegalAndOtherCallBack()
+{
+ TestLegalAndOthers(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestLegalAndOthers(1,NEW_MAX_BUFFER);
+ TestLegalAndOthers(1,1);
+ TestLegalAndOthers(NEW_MAX_BUFFER, 1);
+}
+
+static void TestSingleByteCallBack()
+{
+ TestSingleByte(NEW_MAX_BUFFER, NEW_MAX_BUFFER);
+ TestSingleByte(1,NEW_MAX_BUFFER);
+ TestSingleByte(1,1);
+ TestSingleByte(NEW_MAX_BUFFER, 1);
+}
+#endif
+
+static void TestSkip(int32_t inputsize, int32_t outputsize)
+{
+ static const uint8_t expskipIBM_949[]= {
+ 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xc8, 0xd3 };
+
+ static const uint8_t expskipIBM_943[] = {
+ 0x9f, 0xaf, 0x9f, 0xb1, 0x89, 0x59 };
+
+ static const uint8_t expskipIBM_930[] = {
+ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x46, 0x6b, 0x0f };
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ /*From Unicode*/
+ log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_SKIP \n");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ {
+ static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 };
+ static const UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 };
+
+ static const int32_t toIBM949Offsskip [] = { 0, 1, 1, 2, 2, 4, 4 };
+ static const int32_t toIBM943Offsskip [] = { 0, 0, 1, 1, 3, 3 };
+
+ if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expskipIBM_949, sizeof(expskipIBM_949), "ibm-949",
+ UCNV_FROM_U_CALLBACK_SKIP, toIBM949Offsskip, NULL, 0 ))
+ log_err("u-> ibm-949 with skip did not match.\n");
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expskipIBM_943, sizeof(expskipIBM_943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_SKIP, toIBM943Offsskip, NULL, 0 ))
+ log_err("u-> ibm-943 with skip did not match.\n");
+ }
+
+ {
+ static const UChar fromU[] = { 0x61, 0xff5e, 0x62, 0x6d63, 0xff5e, 0x6d64, 0x63, 0xff5e, 0x6d66 };
+ static const uint8_t fromUBytes[] = { 0x62, 0x63, 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x0f, 0x64, 0x0e, 0x46, 0x6b, 0x0f };
+ static const int32_t fromUOffsets[] = { 0, 2, 3, 3, 3, 5, 5, 6, 6, 8, 8, 8, 8 };
+
+ /* test ibm-930 (EBCDIC_STATEFUL) with fallbacks that are not taken to check correct state transitions */
+ if(!testConvertFromUnicode(fromU, sizeof(fromU)/U_SIZEOF_UCHAR,
+ fromUBytes, sizeof(fromUBytes),
+ "ibm-930",
+ UCNV_FROM_U_CALLBACK_SKIP, fromUOffsets,
+ NULL, 0)
+ ) {
+ log_err("u->ibm-930 with skip with untaken fallbacks did not match.\n");
+ }
+ }
+#endif
+
+ {
+ static const UChar usasciiFromU[] = { 0x61, 0x80, 0x4e00, 0x31, 0xd800, 0xdfff, 0x39 };
+ static const uint8_t usasciiFromUBytes[] = { 0x61, 0x31, 0x39 };
+ static const int32_t usasciiFromUOffsets[] = { 0, 3, 6 };
+
+ static const UChar latin1FromU[] = { 0x61, 0xa0, 0x4e00, 0x31, 0xd800, 0xdfff, 0x39 };
+ static const uint8_t latin1FromUBytes[] = { 0x61, 0xa0, 0x31, 0x39 };
+ static const int32_t latin1FromUOffsets[] = { 0, 1, 3, 6 };
+
+ /* US-ASCII */
+ if(!testConvertFromUnicode(usasciiFromU, sizeof(usasciiFromU)/U_SIZEOF_UCHAR,
+ usasciiFromUBytes, sizeof(usasciiFromUBytes),
+ "US-ASCII",
+ UCNV_FROM_U_CALLBACK_SKIP, usasciiFromUOffsets,
+ NULL, 0)
+ ) {
+ log_err("u->US-ASCII with skip did not match.\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* SBCS NLTC codepage 367 for US-ASCII */
+ if(!testConvertFromUnicode(usasciiFromU, sizeof(usasciiFromU)/U_SIZEOF_UCHAR,
+ usasciiFromUBytes, sizeof(usasciiFromUBytes),
+ "ibm-367",
+ UCNV_FROM_U_CALLBACK_SKIP, usasciiFromUOffsets,
+ NULL, 0)
+ ) {
+ log_err("u->ibm-367 with skip did not match.\n");
+ }
+#endif
+
+ /* ISO-Latin-1 */
+ if(!testConvertFromUnicode(latin1FromU, sizeof(latin1FromU)/U_SIZEOF_UCHAR,
+ latin1FromUBytes, sizeof(latin1FromUBytes),
+ "LATIN_1",
+ UCNV_FROM_U_CALLBACK_SKIP, latin1FromUOffsets,
+ NULL, 0)
+ ) {
+ log_err("u->LATIN_1 with skip did not match.\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* windows-1252 */
+ if(!testConvertFromUnicode(latin1FromU, sizeof(latin1FromU)/U_SIZEOF_UCHAR,
+ latin1FromUBytes, sizeof(latin1FromUBytes),
+ "windows-1252",
+ UCNV_FROM_U_CALLBACK_SKIP, latin1FromUOffsets,
+ NULL, 0)
+ ) {
+ log_err("u->windows-1252 with skip did not match.\n");
+ }
+ }
+
+ {
+ static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 };
+ static const uint8_t toIBM943[]= { 0x61, 0x61 };
+ static const int32_t offset[]= {0, 4};
+
+ /* EUC_JP*/
+ static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 };
+ static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x61, 0x8e, 0xe0,
+ };
+ static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2, 6, 7, 7};
+
+ /*EUC_TW*/
+ static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, };
+ static const uint8_t to_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x61, 0xe6, 0xca, 0x8a,
+ };
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2, 6, 7, 7, 8,};
+
+ /*ISO-2022-JP*/
+ static const UChar iso_2022_jp_inputText[]={0x0041, 0x00E9/*unassigned*/,0x0042, };
+ static const uint8_t to_iso_2022_jp[]={
+ 0x41,
+ 0x42,
+
+ };
+ static const int32_t from_iso_2022_jpOffs [] ={0,2};
+
+ /*ISO-2022-JP*/
+ UChar const iso_2022_jp_inputText2[]={0x0041, 0x00E9/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, };
+ static const uint8_t to_iso_2022_jp2[]={
+ 0x41,
+ 0x43,
+
+ };
+ static const int32_t from_iso_2022_jpOffs2 [] ={0,2};
+
+ /*ISO-2022-cn*/
+ static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712/*unassigned*/, 0x0042, };
+ static const uint8_t to_iso_2022_cn[]={
+ 0x41, 0x42
+ };
+ static const int32_t from_iso_2022_cnOffs [] ={
+ 0, 2
+ };
+
+ /*ISO-2022-CN*/
+ static const UChar iso_2022_cn_inputText1[]={0x0041, 0x3712/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, };
+ static const uint8_t to_iso_2022_cn1[]={
+ 0x41, 0x43
+
+ };
+ static const int32_t from_iso_2022_cnOffs1 [] ={ 0, 2 };
+
+ /*ISO-2022-kr*/
+ static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042, };
+ static const uint8_t to_iso_2022_kr[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0e, 0x25, 0x50,
+ 0x25, 0x50,
+ 0x0f, 0x42,
+ };
+ static const int32_t from_iso_2022_krOffs [] ={
+ -1,-1,-1,-1,
+ 0,
+ 1,1,1,
+ 3,3,
+ 4,4
+ };
+
+ /*ISO-2022-kr*/
+ static const UChar iso_2022_kr_inputText1[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0,0xd801/*illegal*/, 0x0042, };
+ static const uint8_t to_iso_2022_kr1[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0e, 0x25, 0x50,
+ 0x25, 0x50,
+
+ };
+ static const int32_t from_iso_2022_krOffs1 [] ={
+ -1,-1,-1,-1,
+ 0,
+ 1,1,1,
+ 3,3,
+
+ };
+ /* HZ encoding */
+ static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, };
+
+ static const uint8_t to_hz[]={
+ 0x7e, 0x7d, 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x26, 0x30,
+ 0x7e, 0x7d, 0x42,
+
+ };
+ static const int32_t from_hzOffs [] ={
+ 0,0,0,
+ 1,1,1,1,
+ 3,3,
+ 4,4,4,4
+ };
+
+ static const UChar hz_inputText1[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0,0xd801/*illegal*/, 0x0042, };
+
+ static const uint8_t to_hz1[]={
+ 0x7e, 0x7d, 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x26, 0x30,
+
+
+ };
+ static const int32_t from_hzOffs1 [] ={
+ 0,0,0,
+ 1,1,1,1,
+ 3,3,
+
+ };
+
+#endif
+
+ static const UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, };
+
+ static const uint8_t to_SCSU[]={
+ 0x41,
+ 0x42
+
+
+ };
+ static const int32_t from_SCSUOffs [] ={
+ 0,
+ 2,
+
+ };
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* ISCII */
+ static const UChar iscii_inputText[]={ 0x0041, 0x3712/*unassigned*/, 0x0042, };
+ static const uint8_t to_iscii[]={
+ 0x41,
+ 0x42,
+ };
+ static const int32_t from_isciiOffs [] ={
+ 0,2,
+
+ };
+ /*ISCII*/
+ static const UChar iscii_inputText1[]={0x0044, 0x3712/*unassigned*/,0x43,0xd800/*illegal*/,0x0042, };
+ static const uint8_t to_iscii1[]={
+ 0x44,
+ 0x43,
+
+ };
+ static const int32_t from_isciiOffs1 [] ={0,2};
+
+ if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]),
+ toIBM943, sizeof(toIBM943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_SKIP, offset, NULL, 0 ))
+ log_err("u-> ibm-943 with skip did not match.\n");
+
+ if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]),
+ to_euc_jp, sizeof(to_euc_jp), "euc-jp",
+ UCNV_FROM_U_CALLBACK_SKIP, fromEUC_JPOffs, NULL, 0 ))
+ log_err("u-> euc-jp with skip did not match.\n");
+
+ if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]),
+ to_euc_tw, sizeof(to_euc_tw), "euc-tw",
+ UCNV_FROM_U_CALLBACK_SKIP, from_euc_twOffs, NULL, 0 ))
+ log_err("u-> euc-tw with skip did not match.\n");
+
+ /*iso_2022_jp*/
+ if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]),
+ to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_jpOffs, NULL, 0 ))
+ log_err("u-> iso-2022-jp with skip did not match.\n");
+
+ /* with context */
+ if(!testConvertFromUnicodeWithContext(iso_2022_jp_inputText2, sizeof(iso_2022_jp_inputText2)/sizeof(iso_2022_jp_inputText2[0]),
+ to_iso_2022_jp2, sizeof(to_iso_2022_jp2), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_jpOffs2, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> iso-2022-jp with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n");
+
+ /*iso_2022_cn*/
+ if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]),
+ to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_cnOffs, NULL, 0 ))
+ log_err("u-> iso-2022-cn with skip did not match.\n");
+ /*with context*/
+ if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText1, sizeof(iso_2022_cn_inputText1)/sizeof(iso_2022_cn_inputText1[0]),
+ to_iso_2022_cn1, sizeof(to_iso_2022_cn1), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_cnOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> iso-2022-cn with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n");
+
+ /*iso_2022_kr*/
+ if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]),
+ to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_krOffs, NULL, 0 ))
+ log_err("u-> iso-2022-kr with skip did not match.\n");
+ /*with context*/
+ if(!testConvertFromUnicodeWithContext(iso_2022_kr_inputText1, sizeof(iso_2022_kr_inputText1)/sizeof(iso_2022_kr_inputText1[0]),
+ to_iso_2022_kr1, sizeof(to_iso_2022_kr1), "iso-2022-kr",
+ UCNV_FROM_U_CALLBACK_SKIP, from_iso_2022_krOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> iso-2022-kr with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n");
+
+ /*hz*/
+ if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]),
+ to_hz, sizeof(to_hz), "HZ",
+ UCNV_FROM_U_CALLBACK_SKIP, from_hzOffs, NULL, 0 ))
+ log_err("u-> HZ with skip did not match.\n");
+ /*with context*/
+ if(!testConvertFromUnicodeWithContext(hz_inputText1, sizeof(hz_inputText1)/sizeof(hz_inputText1[0]),
+ to_hz1, sizeof(to_hz1), "hz",
+ UCNV_FROM_U_CALLBACK_SKIP, from_hzOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> hz with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n");
+#endif
+
+ /*SCSU*/
+ if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]),
+ to_SCSU, sizeof(to_SCSU), "SCSU",
+ UCNV_FROM_U_CALLBACK_SKIP, from_SCSUOffs, NULL, 0 ))
+ log_err("u-> SCSU with skip did not match.\n");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /*ISCII*/
+ if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]),
+ to_iscii, sizeof(to_iscii), "ISCII,version=0",
+ UCNV_FROM_U_CALLBACK_SKIP, from_isciiOffs, NULL, 0 ))
+ log_err("u-> iscii with skip did not match.\n");
+ /*with context*/
+ if(!testConvertFromUnicodeWithContext(iscii_inputText1, sizeof(iscii_inputText1)/sizeof(iscii_inputText1[0]),
+ to_iscii1, sizeof(to_iscii1), "ISCII,version=0",
+ UCNV_FROM_U_CALLBACK_SKIP, from_isciiOffs1, NULL, 0,UCNV_SKIP_STOP_ON_ILLEGAL,U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> iscii with skip & UCNV_SKIP_STOP_ON_ILLEGAL did not match.\n");
+#endif
+ }
+
+ log_verbose("Testing fromUnicode for BOCU-1 with UCNV_TO_U_CALLBACK_SKIP\n");
+ {
+ static const uint8_t sampleText[]={ /* from cintltst/bocu1tst.c/TestBOCU1 text 1 */
+ 0xFB, 0xEE, 0x28, /* from source offset 0 */
+ 0x24, 0x1E, 0x52,
+ 0xB2,
+ 0x20,
+ 0xB3,
+ 0xB1,
+ 0x0D,
+ 0x0A,
+
+ 0x20, /* from 8 */
+ 0x00,
+ 0xD0, 0x6C,
+ 0xB6,
+ 0xD8, 0xA5,
+ 0x20,
+ 0x68,
+ 0x59,
+
+ 0xF9, 0x28, /* from 16 */
+ 0x6D,
+ 0x20,
+ 0x73,
+ 0xE0, 0x2D,
+ 0xDE, 0x43,
+ 0xD0, 0x33,
+ 0x20,
+
+ 0xFA, 0x83, /* from 24 */
+ 0x25, 0x01,
+ 0xFB, 0x16, 0x87,
+ 0x4B, 0x16,
+ 0x20,
+ 0xE6, 0xBD,
+ 0xEB, 0x5B,
+ 0x4B, 0xCC,
+
+ 0xF9, 0xA2, /* from 32 */
+ 0xFC, 0x10, 0x3E,
+ 0xFE, 0x16, 0x3A, 0x8C,
+ 0x20,
+ 0xFC, 0x03, 0xAC,
+
+ 0x01, /* from 41 */
+ 0xDE, 0x83,
+ 0x20,
+ 0x09
+ };
+ static const UChar expected[]={
+ 0xFEFF, 0x0061, 0x0062, 0x0020, /* 0 */
+ 0x0063, 0x0061, 0x000D, 0x000A,
+
+ 0x0020, 0x0000, 0x00DF, 0x00E6, /* 8 */
+ 0x0930, 0x0020, 0x0918, 0x0909,
+
+ 0x3086, 0x304D, 0x0020, 0x3053, /* 16 */
+ 0x4000, 0x4E00, 0x7777, 0x0020,
+
+ 0x9FA5, 0x4E00, 0xAC00, 0xBCDE, /* 24 */
+ 0x0020, 0xD7A3, 0xDC00, 0xD800,
+
+ 0xD800, 0xDC00, 0xD845, 0xDDDD, /* 32 */
+ 0xDBBB, 0xDDEE, 0x0020, 0xDBFF,
+
+ 0xDFFF, 0x0001, 0x0E40, 0x0020, /* 40 */
+ 0x0009
+ };
+ static const int32_t offsets[]={
+ 0, 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 10, 11, 12, 12, 13, 14, 15,
+ 16, 16, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23,
+ 24, 24, 25, 25, 26, 26, 26, 27, 27, 28, 29, 29, 30, 30, 31, 31,
+ 32, 32, 34, 34, 34, 36, 36, 36, 36, 38, 39, 39, 39,
+ 41, 42, 42, 43, 44
+ };
+
+ /* BOCU-1 fromUnicode never calls callbacks, so this only tests single-byte and offsets behavior */
+ if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected),
+ sampleText, sizeof(sampleText),
+ "BOCU-1",
+ UCNV_FROM_U_CALLBACK_SKIP, offsets, NULL, 0)
+ ) {
+ log_err("u->BOCU-1 with skip did not match.\n");
+ }
+ }
+
+ log_verbose("Testing fromUnicode for CESU-8 with UCNV_TO_U_CALLBACK_SKIP\n");
+ {
+ const uint8_t sampleText[]={
+ 0x61, /* 'a' */
+ 0xc4, 0xb5, /* U+0135 */
+ 0xed, 0x80, 0xa0, /* Hangul U+d020 */
+ 0xed, 0xa0, 0x81, 0xed, 0xb0, 0x81, /* surrogate pair for U+10401 */
+ 0xee, 0x80, 0x80, /* PUA U+e000 */
+ 0xed, 0xb0, 0x81, /* unpaired trail surrogate U+dc01 */
+ 0x62, /* 'b' */
+ 0xed, 0xa0, 0x81, /* unpaired lead surrogate U+d801 */
+ 0xd0, 0x80 /* U+0400 */
+ };
+ UChar expected[]={
+ 0x0061,
+ 0x0135,
+ 0xd020,
+ 0xd801, 0xdc01,
+ 0xe000,
+ 0xdc01,
+ 0x0062,
+ 0xd801,
+ 0x0400
+ };
+ int32_t offsets[]={
+ 0,
+ 1, 1,
+ 2, 2, 2,
+ 3, 3, 3, 4, 4, 4,
+ 5, 5, 5,
+ 6, 6, 6,
+ 7,
+ 8, 8, 8,
+ 9, 9
+ };
+
+ /* CESU-8 fromUnicode never calls callbacks, so this only tests conversion and offsets behavior */
+
+ /* without offsets */
+ if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected),
+ sampleText, sizeof(sampleText),
+ "CESU-8",
+ UCNV_FROM_U_CALLBACK_SKIP, NULL, NULL, 0)
+ ) {
+ log_err("u->CESU-8 with skip did not match.\n");
+ }
+
+ /* with offsets */
+ if(!testConvertFromUnicode(expected, ARRAY_LENGTH(expected),
+ sampleText, sizeof(sampleText),
+ "CESU-8",
+ UCNV_FROM_U_CALLBACK_SKIP, offsets, NULL, 0)
+ ) {
+ log_err("u->CESU-8 with skip did not match.\n");
+ }
+ }
+
+ /*to Unicode*/
+ log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_SKIP \n");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ {
+
+ static const UChar IBM_949skiptoUnicode[]= {0x0000, 0xAC00, 0xAC01, 0xD700 };
+ static const UChar IBM_943skiptoUnicode[]= { 0x6D63, 0x6D64, 0x6D66 };
+ static const UChar IBM_930skiptoUnicode[]= { 0x6D63, 0x6D64, 0x6D66 };
+
+ static const int32_t fromIBM949Offs [] = { 0, 1, 3, 5};
+ static const int32_t fromIBM943Offs [] = { 0, 2, 4};
+ static const int32_t fromIBM930Offs [] = { 1, 3, 5};
+
+ if(!testConvertToUnicode(expskipIBM_949, sizeof(expskipIBM_949),
+ IBM_949skiptoUnicode, sizeof(IBM_949skiptoUnicode)/sizeof(IBM_949skiptoUnicode),"ibm-949",
+ UCNV_TO_U_CALLBACK_SKIP, fromIBM949Offs, NULL, 0 ))
+ log_err("ibm-949->u with skip did not match.\n");
+ if(!testConvertToUnicode(expskipIBM_943, sizeof(expskipIBM_943),
+ IBM_943skiptoUnicode, sizeof(IBM_943skiptoUnicode)/sizeof(IBM_943skiptoUnicode[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_SKIP, fromIBM943Offs, NULL, 0 ))
+ log_err("ibm-943->u with skip did not match.\n");
+
+
+ if(!testConvertToUnicode(expskipIBM_930, sizeof(expskipIBM_930),
+ IBM_930skiptoUnicode, sizeof(IBM_930skiptoUnicode)/sizeof(IBM_930skiptoUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SKIP, fromIBM930Offs, NULL, 0 ))
+ log_err("ibm-930->u with skip did not match.\n");
+
+
+ if(!testConvertToUnicodeWithContext(expskipIBM_930, sizeof(expskipIBM_930),
+ IBM_930skiptoUnicode, sizeof(IBM_930skiptoUnicode)/sizeof(IBM_930skiptoUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SKIP, fromIBM930Offs, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND ))
+ log_err("ibm-930->u with skip did not match.\n");
+ }
+#endif
+
+ {
+ static const uint8_t usasciiToUBytes[] = { 0x61, 0x80, 0x31 };
+ static const UChar usasciiToU[] = { 0x61, 0x31 };
+ static const int32_t usasciiToUOffsets[] = { 0, 2 };
+
+ static const uint8_t latin1ToUBytes[] = { 0x61, 0xa0, 0x31 };
+ static const UChar latin1ToU[] = { 0x61, 0xa0, 0x31 };
+ static const int32_t latin1ToUOffsets[] = { 0, 1, 2 };
+
+ /* US-ASCII */
+ if(!testConvertToUnicode(usasciiToUBytes, sizeof(usasciiToUBytes),
+ usasciiToU, sizeof(usasciiToU)/U_SIZEOF_UCHAR,
+ "US-ASCII",
+ UCNV_TO_U_CALLBACK_SKIP, usasciiToUOffsets,
+ NULL, 0)
+ ) {
+ log_err("US-ASCII->u with skip did not match.\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* SBCS NLTC codepage 367 for US-ASCII */
+ if(!testConvertToUnicode(usasciiToUBytes, sizeof(usasciiToUBytes),
+ usasciiToU, sizeof(usasciiToU)/U_SIZEOF_UCHAR,
+ "ibm-367",
+ UCNV_TO_U_CALLBACK_SKIP, usasciiToUOffsets,
+ NULL, 0)
+ ) {
+ log_err("ibm-367->u with skip did not match.\n");
+ }
+#endif
+
+ /* ISO-Latin-1 */
+ if(!testConvertToUnicode(latin1ToUBytes, sizeof(latin1ToUBytes),
+ latin1ToU, sizeof(latin1ToU)/U_SIZEOF_UCHAR,
+ "LATIN_1",
+ UCNV_TO_U_CALLBACK_SKIP, latin1ToUOffsets,
+ NULL, 0)
+ ) {
+ log_err("LATIN_1->u with skip did not match.\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* windows-1252 */
+ if(!testConvertToUnicode(latin1ToUBytes, sizeof(latin1ToUBytes),
+ latin1ToU, sizeof(latin1ToU)/U_SIZEOF_UCHAR,
+ "windows-1252",
+ UCNV_TO_U_CALLBACK_SKIP, latin1ToUOffsets,
+ NULL, 0)
+ ) {
+ log_err("windows-1252->u with skip did not match.\n");
+ }
+#endif
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ {
+ static const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={
+ 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44
+ };
+ static const UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63, 0x03b4
+ };
+ static const int32_t from_EBCIDIC_STATEFULOffsets []={ 1, 5};
+
+
+ /* euc-jp*/
+ static const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x8f, 0xda, 0xa1, /*unassigned*/
+ 0x8e, 0xe0,
+ };
+ static const UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec, 0x00a2};
+ static const int32_t from_euc_jpOffs [] ={ 0, 1, 3, 9};
+
+ /*EUC_TW*/
+ static const uint8_t sampleTxt_euc_tw[]={ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/
+ 0xe6, 0xca, 0x8a,
+ };
+ static const UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2, 0x8706, 0x8a, };
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 3, 11, 13};
+ /*iso-2022-jp*/
+ static const uint8_t sampleTxt_iso_2022_jp[]={
+ 0x41,
+ 0x1b, 0x24, 0x42, 0x2A, 0x44, /*unassigned*/
+ 0x1b, 0x28, 0x42, 0x42,
+
+ };
+ static const UChar iso_2022_jptoUnicode[]={ 0x41,0x42 };
+ static const int32_t from_iso_2022_jpOffs [] ={ 0,9 };
+
+ /*iso-2022-cn*/
+ static const uint8_t sampleTxt_iso_2022_cn[]={
+ 0x0f, 0x41, 0x44,
+ 0x1B, 0x24, 0x29, 0x47,
+ 0x0E, 0x40, 0x6f, /*unassigned*/
+ 0x0f, 0x42,
+
+ };
+
+ static const UChar iso_2022_cntoUnicode[]={ 0x41, 0x44,0x42 };
+ static const int32_t from_iso_2022_cnOffs [] ={ 1, 2, 11 };
+
+ /*iso-2022-kr*/
+ static const uint8_t sampleTxt_iso_2022_kr[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0E, 0x7f, 0x1E,
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x51,
+ 0x42, 0x43,
+
+ };
+ static const UChar iso_2022_krtoUnicode[]={ 0x41,0x03A0,0x51, 0x42,0x43};
+ static const int32_t from_iso_2022_krOffs [] ={ 4, 9, 12, 13 , 14 };
+
+ /*hz*/
+ static const uint8_t sampleTxt_hz[]={
+ 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7f, 0x1E, /*unassigned*/
+ 0x26, 0x30,
+ 0x7e, 0x7d, 0x42,
+ 0x7e, 0x7b, 0x7f, 0x1E,/*unassigned*/
+ 0x7e, 0x7d, 0x42,
+ };
+ static const UChar hztoUnicode[]={
+ 0x41,
+ 0x03a0,
+ 0x03A0,
+ 0x42,
+ 0x42,};
+
+ static const int32_t from_hzOffs [] ={0,3,7,11,18, };
+
+ /*ISCII*/
+ static const uint8_t sampleTxt_iscii[]={
+ 0x41,
+ 0xa1,
+ 0xEB, /*unassigned*/
+ 0x26,
+ 0x30,
+ 0xa2,
+ 0xEC, /*unassigned*/
+ 0x42,
+ };
+ static const UChar isciitoUnicode[]={
+ 0x41,
+ 0x0901,
+ 0x26,
+ 0x30,
+ 0x0902,
+ 0x42,
+ };
+
+ static const int32_t from_isciiOffs [] ={0,1,3,4,5,7 };
+
+ /*LMBCS*/
+ static const uint8_t sampleTxtLMBCS[]={ 0x12, 0xc9, 0x50,
+ 0x12, 0x92, 0xa0, /*unassigned*/
+ 0x12, 0x92, 0xA1,
+ };
+ static const UChar LMBCSToUnicode[]={ 0x4e2e, 0xe5c4};
+ static const int32_t fromLMBCS[] = {0, 6};
+
+ if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL),
+ EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SKIP, from_EBCIDIC_STATEFULOffsets, NULL, 0 ))
+ log_err("EBCIDIC_STATEFUL->u with skip did not match.\n");
+
+ if(!testConvertToUnicodeWithContext(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL),
+ EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SKIP, from_EBCIDIC_STATEFULOffsets, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND ))
+ log_err("EBCIDIC_STATEFUL->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp),
+ euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp",
+ UCNV_TO_U_CALLBACK_SKIP, from_euc_jpOffs , NULL, 0))
+ log_err("euc-jp->u with skip did not match.\n");
+
+
+
+ if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw),
+ euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw",
+ UCNV_TO_U_CALLBACK_SKIP, from_euc_twOffs , NULL, 0))
+ log_err("euc-tw->u with skip did not match.\n");
+
+
+ if(!testConvertToUnicode(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_jpOffs , NULL, 0))
+ log_err("iso-2022-jp->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iso_2022_cn, sizeof(sampleTxt_iso_2022_cn),
+ iso_2022_cntoUnicode, sizeof(iso_2022_cntoUnicode)/sizeof(iso_2022_cntoUnicode[0]),"iso-2022-cn",
+ UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_cnOffs , NULL, 0))
+ log_err("iso-2022-cn->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iso_2022_kr, sizeof(sampleTxt_iso_2022_kr),
+ iso_2022_krtoUnicode, sizeof(iso_2022_krtoUnicode)/sizeof(iso_2022_krtoUnicode[0]),"iso-2022-kr",
+ UCNV_TO_U_CALLBACK_SKIP, from_iso_2022_krOffs , NULL, 0))
+ log_err("iso-2022-kr->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_hz, sizeof(sampleTxt_hz),
+ hztoUnicode, sizeof(hztoUnicode)/sizeof(hztoUnicode[0]),"HZ",
+ UCNV_TO_U_CALLBACK_SKIP, from_hzOffs , NULL, 0))
+ log_err("HZ->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iscii, sizeof(sampleTxt_iscii),
+ isciitoUnicode, sizeof(isciitoUnicode)/sizeof(isciitoUnicode[0]),"ISCII,version=0",
+ UCNV_TO_U_CALLBACK_SKIP, from_isciiOffs , NULL, 0))
+ log_err("iscii->u with skip did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxtLMBCS, sizeof(sampleTxtLMBCS),
+ LMBCSToUnicode, sizeof(LMBCSToUnicode)/sizeof(LMBCSToUnicode[0]),"LMBCS-1",
+ UCNV_TO_U_CALLBACK_SKIP, fromLMBCS , NULL, 0))
+ log_err("LMBCS->u with skip did not match.\n");
+
+ }
+#endif
+
+ log_verbose("Testing to Unicode for UTF-8 with UCNV_TO_U_CALLBACK_SKIP \n");
+ {
+ const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c,
+ 0xe0, 0x80, 0x61,};
+ UChar expected1[] = { 0x0031, 0x4e8c, 0x0061};
+ int32_t offsets1[] = { 0x0000, 0x0001, 0x0006};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8",
+ UCNV_TO_U_CALLBACK_SKIP, offsets1, NULL, 0 ))
+ log_err("utf8->u with skip did not match.\n");;
+ }
+
+ log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SKIP \n");
+ {
+ const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,};
+ UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061,0xfffe,0xfffe};
+ int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003,4,5};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU",
+ UCNV_TO_U_CALLBACK_SKIP, offsets1, NULL, 0 ))
+ log_err("scsu->u with skip did not match.\n");
+ }
+
+ log_verbose("Testing toUnicode for BOCU-1 with UCNV_TO_U_CALLBACK_SKIP\n");
+ {
+ const uint8_t sampleText[]={ /* modified from cintltst/bocu1tst.c/TestBOCU1 text 1 */
+ 0xFB, 0xEE, 0x28, /* single-code point sequence at offset 0 */
+ 0x24, 0x1E, 0x52, /* 3 */
+ 0xB2, /* 6 */
+ 0x20, /* 7 */
+ 0x40, 0x07, /* 8 - wrong trail byte */
+ 0xB3, /* 10 */
+ 0xB1, /* 11 */
+ 0xD0, 0x20, /* 12 - wrong trail byte */
+ 0x0D, /* 14 */
+ 0x0A, /* 15 */
+ 0x20, /* 16 */
+ 0x00, /* 17 */
+ 0xD0, 0x6C, /* 18 */
+ 0xB6, /* 20 */
+ 0xD8, 0xA5, /* 21 */
+ 0x20, /* 23 */
+ 0x68, /* 24 */
+ 0x59, /* 25 */
+ 0xF9, 0x28, /* 26 */
+ 0x6D, /* 28 */
+ 0x20, /* 29 */
+ 0x73, /* 30 */
+ 0xE0, 0x2D, /* 31 */
+ 0xDE, 0x43, /* 33 */
+ 0xD0, 0x33, /* 35 */
+ 0x20, /* 37 */
+ 0xFA, 0x83, /* 38 */
+ 0x25, 0x01, /* 40 */
+ 0xFB, 0x16, 0x87, /* 42 */
+ 0x4B, 0x16, /* 45 */
+ 0x20, /* 47 */
+ 0xE6, 0xBD, /* 48 */
+ 0xEB, 0x5B, /* 50 */
+ 0x4B, 0xCC, /* 52 */
+ 0xF9, 0xA2, /* 54 */
+ 0xFC, 0x10, 0x3E, /* 56 */
+ 0xFE, 0x16, 0x3A, 0x8C, /* 59 */
+ 0x20, /* 63 */
+ 0xFC, 0x03, 0xAC, /* 64 */
+ 0xFF, /* 67 - FF just resets the state without encoding anything */
+ 0x01, /* 68 */
+ 0xDE, 0x83, /* 69 */
+ 0x20, /* 71 */
+ 0x09 /* 72 */
+ };
+ UChar expected[]={
+ 0xFEFF, 0x0061, 0x0062, 0x0020,
+ 0x0063, 0x0061, 0x000D, 0x000A,
+ 0x0020, 0x0000, 0x00DF, 0x00E6,
+ 0x0930, 0x0020, 0x0918, 0x0909,
+ 0x3086, 0x304D, 0x0020, 0x3053,
+ 0x4000, 0x4E00, 0x7777, 0x0020,
+ 0x9FA5, 0x4E00, 0xAC00, 0xBCDE,
+ 0x0020, 0xD7A3, 0xDC00, 0xD800,
+ 0xD800, 0xDC00, 0xD845, 0xDDDD,
+ 0xDBBB, 0xDDEE, 0x0020, 0xDBFF,
+ 0xDFFF, 0x0001, 0x0E40, 0x0020,
+ 0x0009
+ };
+ int32_t offsets[]={
+ 0, 3, 6, 7, /* skip 8, */
+ 10, 11, /* skip 12, */
+ 14, 15, 16, 17, 18,
+ 20, 21, 23, 24, 25, 26, 28, 29,
+ 30, 31, 33, 35, 37, 38,
+ 40, 42, 45, 47, 48,
+ 50, 52, 54, /* trail */ 54, 56, /* trail */ 56, 59, /* trail */ 59,
+ 63, 64, /* trail */ 64, /* reset only 67, */
+ 68, 69,
+ 71, 72
+ };
+
+ if(!testConvertToUnicode(sampleText, sizeof(sampleText),
+ expected, ARRAY_LENGTH(expected), "BOCU-1",
+ UCNV_TO_U_CALLBACK_SKIP, offsets, NULL, 0)
+ ) {
+ log_err("BOCU-1->u with skip did not match.\n");
+ }
+ }
+
+ log_verbose("Testing toUnicode for CESU-8 with UCNV_TO_U_CALLBACK_SKIP\n");
+ {
+ const uint8_t sampleText[]={
+ 0x61, /* 0 'a' */
+ 0xc0, 0x80, /* 1 non-shortest form */
+ 0xc4, 0xb5, /* 3 U+0135 */
+ 0xed, 0x80, 0xa0, /* 5 Hangul U+d020 */
+ 0xed, 0xa0, 0x81, 0xed, 0xb0, 0x81, /* 8 surrogate pair for U+10401 */
+ 0xee, 0x80, 0x80, /* 14 PUA U+e000 */
+ 0xed, 0xb0, 0x81, /* 17 unpaired trail surrogate U+dc01 */
+ 0xf0, 0x90, 0x80, 0x80, /* 20 illegal 4-byte form for U+10000 */
+ 0x62, /* 24 'b' */
+ 0xed, 0xa0, 0x81, /* 25 unpaired lead surrogate U+d801 */
+ 0xed, 0xa0, /* 28 incomplete sequence */
+ 0xd0, 0x80 /* 30 U+0400 */
+ };
+ UChar expected[]={
+ 0x0061,
+ /* skip */
+ 0x0135,
+ 0xd020,
+ 0xd801, 0xdc01,
+ 0xe000,
+ 0xdc01,
+ /* skip */
+ 0x0062,
+ 0xd801,
+ 0x0400
+ };
+ int32_t offsets[]={
+ 0,
+ /* skip 1, */
+ 3,
+ 5,
+ 8, 11,
+ 14,
+ 17,
+ /* skip 20, 20, */
+ 24,
+ 25,
+ /* skip 28 */
+ 30
+ };
+
+ /* without offsets */
+ if(!testConvertToUnicode(sampleText, sizeof(sampleText),
+ expected, ARRAY_LENGTH(expected), "CESU-8",
+ UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, 0)
+ ) {
+ log_err("CESU-8->u with skip did not match.\n");
+ }
+
+ /* with offsets */
+ if(!testConvertToUnicode(sampleText, sizeof(sampleText),
+ expected, ARRAY_LENGTH(expected), "CESU-8",
+ UCNV_TO_U_CALLBACK_SKIP, offsets, NULL, 0)
+ ) {
+ log_err("CESU-8->u with skip did not match.\n");
+ }
+ }
+}
+
+static void TestStop(int32_t inputsize, int32_t outputsize)
+{
+ static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 };
+ static const UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 };
+
+ static const uint8_t expstopIBM_949[]= {
+ 0x00, 0xb0, 0xa1, 0xb0, 0xa2};
+
+ static const uint8_t expstopIBM_943[] = {
+ 0x9f, 0xaf, 0x9f, 0xb1};
+
+ static const uint8_t expstopIBM_930[] = {
+ 0x0e, 0x5d, 0x5f, 0x5d, 0x63};
+
+ static const UChar IBM_949stoptoUnicode[]= {0x0000, 0xAC00, 0xAC01};
+ static const UChar IBM_943stoptoUnicode[]= { 0x6D63, 0x6D64};
+ static const UChar IBM_930stoptoUnicode[]= { 0x6D63, 0x6D64};
+
+
+ static const int32_t toIBM949Offsstop [] = { 0, 1, 1, 2, 2};
+ static const int32_t toIBM943Offsstop [] = { 0, 0, 1, 1};
+ static const int32_t toIBM930Offsstop [] = { 0, 0, 0, 1, 1};
+
+ static const int32_t fromIBM949Offs [] = { 0, 1, 3};
+ static const int32_t fromIBM943Offs [] = { 0, 2};
+ static const int32_t fromIBM930Offs [] = { 1, 3};
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ /*From Unicode*/
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expstopIBM_949, sizeof(expstopIBM_949), "ibm-949",
+ UCNV_FROM_U_CALLBACK_STOP, toIBM949Offsstop, NULL, 0 ))
+ log_err("u-> ibm-949 with stop did not match.\n");
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expstopIBM_943, sizeof(expstopIBM_943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_STOP, toIBM943Offsstop , NULL, 0))
+ log_err("u-> ibm-943 with stop did not match.\n");
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expstopIBM_930, sizeof(expstopIBM_930), "ibm-930",
+ UCNV_FROM_U_CALLBACK_STOP, toIBM930Offsstop, NULL, 0 ))
+ log_err("u-> ibm-930 with stop did not match.\n");
+
+ log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_STOP \n");
+ {
+ static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 };
+ static const uint8_t toIBM943[]= { 0x61,};
+ static const int32_t offset[]= {0,} ;
+
+ /*EUC_JP*/
+ static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 };
+ static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,};
+ static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2,};
+
+ /*EUC_TW*/
+ static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, };
+ static const uint8_t to_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,};
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2,};
+
+ /*ISO-2022-JP*/
+ static const UChar iso_2022_jp_inputText[]={0x0041, 0x00E9, 0x0042, };
+ static const uint8_t to_iso_2022_jp[]={
+ 0x41,
+
+ };
+ static const int32_t from_iso_2022_jpOffs [] ={0,};
+
+ /*ISO-2022-cn*/
+ static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712, 0x0042, };
+ static const uint8_t to_iso_2022_cn[]={
+ 0x41,
+
+ };
+ static const int32_t from_iso_2022_cnOffs [] ={
+ 0,0,
+ 2,2,
+ };
+
+ /*ISO-2022-kr*/
+ static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042, };
+ static const uint8_t to_iso_2022_kr[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0e, 0x25, 0x50,
+ };
+ static const int32_t from_iso_2022_krOffs [] ={
+ -1,-1,-1,-1,
+ 0,
+ 1,1,1,
+ };
+
+ /* HZ encoding */
+ static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, };
+
+ static const uint8_t to_hz[]={
+ 0x7e, 0x7d, 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+
+ };
+ static const int32_t from_hzOffs [] ={
+ 0, 0,0,
+ 1,1,1,1,
+ };
+
+ /*ISCII*/
+ static const UChar iscii_inputText[]={ 0x0041, 0x3712, 0x0042, };
+ static const uint8_t to_iscii[]={
+ 0x41,
+ };
+ static const int32_t from_isciiOffs [] ={
+ 0,
+ };
+
+ if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]),
+ toIBM943, sizeof(toIBM943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_STOP, offset, NULL, 0 ))
+ log_err("u-> ibm-943 with stop did not match.\n");
+
+ if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]),
+ to_euc_jp, sizeof(to_euc_jp), "euc-jp",
+ UCNV_FROM_U_CALLBACK_STOP, fromEUC_JPOffs, NULL, 0 ))
+ log_err("u-> euc-jp with stop did not match.\n");
+
+ if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]),
+ to_euc_tw, sizeof(to_euc_tw), "euc-tw",
+ UCNV_FROM_U_CALLBACK_STOP, from_euc_twOffs, NULL, 0 ))
+ log_err("u-> euc-tw with stop did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]),
+ to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_jpOffs, NULL, 0 ))
+ log_err("u-> iso-2022-jp with stop did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_jp_inputText, sizeof(iso_2022_jp_inputText)/sizeof(iso_2022_jp_inputText[0]),
+ to_iso_2022_jp, sizeof(to_iso_2022_jp), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_jpOffs, NULL, 0 ))
+ log_err("u-> iso-2022-jp with stop did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]),
+ to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_cnOffs, NULL, 0 ))
+ log_err("u-> iso-2022-cn with stop did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]),
+ to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr",
+ UCNV_FROM_U_CALLBACK_STOP, from_iso_2022_krOffs, NULL, 0 ))
+ log_err("u-> iso-2022-kr with stop did not match.\n");
+
+ if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]),
+ to_hz, sizeof(to_hz), "HZ",
+ UCNV_FROM_U_CALLBACK_STOP, from_hzOffs, NULL, 0 ))
+ log_err("u-> HZ with stop did not match.\n");\
+
+ if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]),
+ to_iscii, sizeof(to_iscii), "ISCII,version=0",
+ UCNV_FROM_U_CALLBACK_STOP, from_isciiOffs, NULL, 0 ))
+ log_err("u-> iscii with stop did not match.\n");
+
+
+ }
+#endif
+
+ log_verbose("Testing fromUnicode for SCSU with UCNV_FROM_U_CALLBACK_STOP \n");
+ {
+ static const UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, };
+
+ static const uint8_t to_SCSU[]={
+ 0x41,
+
+ };
+ int32_t from_SCSUOffs [] ={
+ 0,
+
+ };
+ if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]),
+ to_SCSU, sizeof(to_SCSU), "SCSU",
+ UCNV_FROM_U_CALLBACK_STOP, from_SCSUOffs, NULL, 0 ))
+ log_err("u-> SCSU with skip did not match.\n");
+
+ }
+
+ /*to Unicode*/
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertToUnicode(expstopIBM_949, sizeof(expstopIBM_949),
+ IBM_949stoptoUnicode, sizeof(IBM_949stoptoUnicode)/sizeof(IBM_949stoptoUnicode[0]),"ibm-949",
+ UCNV_TO_U_CALLBACK_STOP, fromIBM949Offs, NULL, 0 ))
+ log_err("ibm-949->u with stop did not match.\n");
+ if(!testConvertToUnicode(expstopIBM_943, sizeof(expstopIBM_943),
+ IBM_943stoptoUnicode, sizeof(IBM_943stoptoUnicode)/sizeof(IBM_943stoptoUnicode[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_STOP, fromIBM943Offs, NULL, 0 ))
+ log_err("ibm-943->u with stop did not match.\n");
+ if(!testConvertToUnicode(expstopIBM_930, sizeof(expstopIBM_930),
+ IBM_930stoptoUnicode, sizeof(IBM_930stoptoUnicode)/sizeof(IBM_930stoptoUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_STOP, fromIBM930Offs, NULL, 0 ))
+ log_err("ibm-930->u with stop did not match.\n");
+
+ log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_STOP \n");
+ {
+
+ static const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={
+ 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44
+ };
+ static const UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63 };
+ static const int32_t from_EBCIDIC_STATEFULOffsets []={ 1};
+
+
+ /*EUC-JP*/
+ static const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x8f, 0xda, 0xa1, /*unassigned*/
+ 0x8e, 0xe0,
+ };
+ static const UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec};
+ static const int32_t from_euc_jpOffs [] ={ 0, 1, 3};
+
+ /*EUC_TW*/
+ static const uint8_t sampleTxt_euc_tw[]={ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/
+ 0xe6, 0xca, 0x8a,
+ };
+ UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2};
+ int32_t from_euc_twOffs [] ={ 0, 1, 3};
+
+
+
+ if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL),
+ EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_STOP, from_EBCIDIC_STATEFULOffsets, NULL, 0 ))
+ log_err("EBCIDIC_STATEFUL->u with stop did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp),
+ euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp",
+ UCNV_TO_U_CALLBACK_STOP, from_euc_jpOffs , NULL, 0))
+ log_err("euc-jp->u with stop did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw),
+ euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw",
+ UCNV_TO_U_CALLBACK_STOP, from_euc_twOffs, NULL, 0 ))
+ log_err("euc-tw->u with stop did not match.\n");
+ }
+#endif
+
+ log_verbose("Testing toUnicode for UTF-8 with UCNV_TO_U_CALLBACK_STOP \n");
+ {
+ static const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c,
+ 0xe0, 0x80, 0x61,};
+ static const UChar expected1[] = { 0x0031, 0x4e8c,};
+ static const int32_t offsets1[] = { 0x0000, 0x0001};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8",
+ UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 ))
+ log_err("utf8->u with stop did not match.\n");;
+ }
+ log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_STOP \n");
+ {
+ static const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,0x04};
+ static const UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061};
+ static const int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU",
+ UCNV_TO_U_CALLBACK_STOP, offsets1, NULL, 0 ))
+ log_err("scsu->u with stop did not match.\n");;
+ }
+
+}
+
+static void TestSub(int32_t inputsize, int32_t outputsize)
+{
+ static const UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 };
+ static const UChar sampleText2[]= { 0x6D63, 0x6D64, 0x6D65, 0x6D66 };
+
+ static const uint8_t expsubIBM_949[] =
+ { 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xaf, 0xfe, 0xc8, 0xd3 };
+
+ static const uint8_t expsubIBM_943[] = {
+ 0x9f, 0xaf, 0x9f, 0xb1, 0xfc, 0xfc, 0x89, 0x59 };
+
+ static const uint8_t expsubIBM_930[] = {
+ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfe, 0xfe, 0x46, 0x6b, 0x0f };
+
+ static const UChar IBM_949subtoUnicode[]= {0x0000, 0xAC00, 0xAC01, 0xfffd, 0xD700 };
+ static const UChar IBM_943subtoUnicode[]= {0x6D63, 0x6D64, 0xfffd, 0x6D66 };
+ static const UChar IBM_930subtoUnicode[]= {0x6D63, 0x6D64, 0xfffd, 0x6D66 };
+
+ static const int32_t toIBM949Offssub [] ={ 0, 1, 1, 2, 2, 3, 3, 4, 4 };
+ static const int32_t toIBM943Offssub [] ={ 0, 0, 1, 1, 2, 2, 3, 3 };
+ static const int32_t toIBM930Offssub [] ={ 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 };
+
+ static const int32_t fromIBM949Offs [] = { 0, 1, 3, 5, 7 };
+ static const int32_t fromIBM943Offs [] = { 0, 2, 4, 6 };
+ static const int32_t fromIBM930Offs [] = { 1, 3, 5, 7 };
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ /*from unicode*/
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expsubIBM_949, sizeof(expsubIBM_949), "ibm-949",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM949Offssub, NULL, 0 ))
+ log_err("u-> ibm-949 with subst did not match.\n");
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expsubIBM_943, sizeof(expsubIBM_943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM943Offssub , NULL, 0))
+ log_err("u-> ibm-943 with subst did not match.\n");
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expsubIBM_930, sizeof(expsubIBM_930), "ibm-930",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, toIBM930Offssub, NULL, 0 ))
+ log_err("u-> ibm-930 with subst did not match.\n");
+
+ log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_SUBSTITUTE \n");
+ {
+ static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 };
+ static const uint8_t toIBM943[]= { 0x61, 0xfc, 0xfc, 0xfc, 0xfc, 0x61 };
+ static const int32_t offset[]= {0, 1, 1, 3, 3, 4};
+
+
+ /* EUC_JP*/
+ static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2 };
+ static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0xf4, 0xfe, 0xf4, 0xfe,
+ 0x61, 0x8e, 0xe0,
+ };
+ static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2, 3, 3, 5, 5, 6, 7, 7};
+
+ /*EUC_TW*/
+ static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, };
+ static const uint8_t to_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0xfd, 0xfe, 0xfd, 0xfe,
+ 0x61, 0xe6, 0xca, 0x8a,
+ };
+
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2, 3, 3, 5, 5, 6, 7, 7, 8,};
+
+ if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]),
+ toIBM943, sizeof(toIBM943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset, NULL, 0 ))
+ log_err("u-> ibm-943 with substitute did not match.\n");
+
+ if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]),
+ to_euc_jp, sizeof(to_euc_jp), "euc-jp",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, fromEUC_JPOffs, NULL, 0 ))
+ log_err("u-> euc-jp with substitute did not match.\n");
+
+ if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]),
+ to_euc_tw, sizeof(to_euc_tw), "euc-tw",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_euc_twOffs, NULL, 0 ))
+ log_err("u-> euc-tw with substitute did not match.\n");
+ }
+#endif
+
+ log_verbose("Testing fromUnicode for SCSU with UCNV_FROM_U_CALLBACK_SUBSTITUTE \n");
+ {
+ UChar SCSU_inputText[]={ 0x0041, 0xd801/*illegal*/, 0x0042, };
+
+ const uint8_t to_SCSU[]={
+ 0x41,
+ 0x0e, 0xff,0xfd,
+ 0x42
+
+
+ };
+ int32_t from_SCSUOffs [] ={
+ 0,
+ 1,1,1,
+ 2,
+
+ };
+ const uint8_t to_SCSU_1[]={
+ 0x41,
+
+ };
+ int32_t from_SCSUOffs_1 [] ={
+ 0,
+
+ };
+ if(!testConvertFromUnicode(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]),
+ to_SCSU, sizeof(to_SCSU), "SCSU",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_SCSUOffs, NULL, 0 ))
+ log_err("u-> SCSU with substitute did not match.\n");
+
+ if(!testConvertFromUnicodeWithContext(SCSU_inputText, sizeof(SCSU_inputText)/sizeof(SCSU_inputText[0]),
+ to_SCSU_1, sizeof(to_SCSU_1), "SCSU",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, from_SCSUOffs_1, NULL, 0,"i",U_ILLEGAL_CHAR_FOUND ))
+ log_err("u-> SCSU with substitute did not match.\n");
+ }
+
+ log_verbose("Testing fromUnicode for UTF-8 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n");
+ {
+ static const UChar testinput[]={ 0x20ac, 0xd801, 0xdc01, 0xdc01, 0xd801, 0xffff, 0x0061,};
+ static const uint8_t expectedUTF8[]= { 0xe2, 0x82, 0xac,
+ 0xf0, 0x90, 0x90, 0x81,
+ 0xef, 0xbf, 0xbd, 0xef, 0xbf, 0xbd,
+ 0xef, 0xbf, 0xbf, 0x61,
+
+ };
+ static const int32_t offsets[]={ 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6 };
+ if(!testConvertFromUnicode(testinput, sizeof(testinput)/sizeof(testinput[0]),
+ expectedUTF8, sizeof(expectedUTF8), "utf8",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0 )) {
+ log_err("u-> utf8 with stop did not match.\n");
+ }
+ }
+
+ log_verbose("Testing fromUnicode for UTF-16 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n");
+ {
+ static const UChar in[]={ 0x0041, 0xfeff };
+
+ static const uint8_t out[]={
+#if U_IS_BIG_ENDIAN
+ 0xfe, 0xff,
+ 0x00, 0x41,
+ 0xfe, 0xff
+#else
+ 0xff, 0xfe,
+ 0x41, 0x00,
+ 0xff, 0xfe
+#endif
+ };
+ static const int32_t offsets[]={
+ -1, -1, 0, 0, 1, 1
+ };
+
+ if(!testConvertFromUnicode(in, ARRAY_LENGTH(in),
+ out, sizeof(out), "UTF-16",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0)
+ ) {
+ log_err("u->UTF-16 with substitute did not match.\n");
+ }
+ }
+
+ log_verbose("Testing fromUnicode for UTF-32 with UCNV_FROM_U_CALLBACK_SUBSTITUTE\n");
+ {
+ static const UChar in[]={ 0x0041, 0xfeff };
+
+ static const uint8_t out[]={
+#if U_IS_BIG_ENDIAN
+ 0x00, 0x00, 0xfe, 0xff,
+ 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x00, 0xfe, 0xff
+#else
+ 0xff, 0xfe, 0x00, 0x00,
+ 0x41, 0x00, 0x00, 0x00,
+ 0xff, 0xfe, 0x00, 0x00
+#endif
+ };
+ static const int32_t offsets[]={
+ -1, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1
+ };
+
+ if(!testConvertFromUnicode(in, ARRAY_LENGTH(in),
+ out, sizeof(out), "UTF-32",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0)
+ ) {
+ log_err("u->UTF-32 with substitute did not match.\n");
+ }
+ }
+
+ /*to unicode*/
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertToUnicode(expsubIBM_949, sizeof(expsubIBM_949),
+ IBM_949subtoUnicode, sizeof(IBM_949subtoUnicode)/sizeof(IBM_949subtoUnicode[0]),"ibm-949",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM949Offs, NULL, 0 ))
+ log_err("ibm-949->u with substitute did not match.\n");
+ if(!testConvertToUnicode(expsubIBM_943, sizeof(expsubIBM_943),
+ IBM_943subtoUnicode, sizeof(IBM_943subtoUnicode)/sizeof(IBM_943subtoUnicode[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offs, NULL, 0 ))
+ log_err("ibm-943->u with substitute did not match.\n");
+ if(!testConvertToUnicode(expsubIBM_930, sizeof(expsubIBM_930),
+ IBM_930subtoUnicode, sizeof(IBM_930subtoUnicode)/sizeof(IBM_930subtoUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM930Offs, NULL, 0 ))
+ log_err("ibm-930->u with substitute did not match.\n");
+
+ log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_SUBSTITUTE \n");
+ {
+
+ const uint8_t sampleTxtEBCIDIC_STATEFUL [] ={
+ 0x0e, 0x5d, 0x5f , 0x41, 0x79, 0x41, 0x44
+ };
+ UChar EBCIDIC_STATEFUL_toUnicode[] ={ 0x6d63, 0xfffd, 0x03b4
+ };
+ int32_t from_EBCIDIC_STATEFULOffsets []={ 1, 3, 5};
+
+
+ /* EUC_JP*/
+ const uint8_t sampleTxt_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x8f, 0xda, 0xa1, /*unassigned*/
+ 0x8e, 0xe0, 0x8a
+ };
+ UChar euc_jptoUnicode[]={ 0x0061, 0x4edd, 0x5bec, 0xfffd, 0x00a2, 0x008a };
+ int32_t from_euc_jpOffs [] ={ 0, 1, 3, 6, 9, 11 };
+
+ /*EUC_TW*/
+ const uint8_t sampleTxt_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/
+ 0xe6, 0xca, 0x8a,
+ };
+ UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2, 0xfffd, 0x8706, 0x8a, };
+ int32_t from_euc_twOffs [] ={ 0, 1, 3, 7, 11, 13};
+
+
+ if(!testConvertToUnicode(sampleTxtEBCIDIC_STATEFUL, sizeof(sampleTxtEBCIDIC_STATEFUL),
+ EBCIDIC_STATEFUL_toUnicode, sizeof(EBCIDIC_STATEFUL_toUnicode)/sizeof(EBCIDIC_STATEFUL_toUnicode[0]),"ibm-930",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, from_EBCIDIC_STATEFULOffsets, NULL, 0 ))
+ log_err("EBCIDIC_STATEFUL->u with substitute did not match.\n");
+
+
+ if(!testConvertToUnicode(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp),
+ euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_jpOffs, NULL, 0 ))
+ log_err("euc-jp->u with substitute did not match.\n");
+
+
+ if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw),
+ euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_twOffs, NULL, 0 ))
+ log_err("euc-tw->u with substitute did not match.\n");
+
+
+ if(!testConvertToUnicodeWithContext(sampleTxt_euc_jp, sizeof(sampleTxt_euc_jp),
+ euc_jptoUnicode, sizeof(euc_jptoUnicode)/sizeof(euc_jptoUnicode[0]),"euc-jp",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, from_euc_jpOffs, NULL, 0 ,"i", U_ILLEGAL_CHAR_FOUND))
+ log_err("euc-jp->u with substitute did not match.\n");
+ }
+#endif
+
+ log_verbose("Testing toUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n");
+ {
+ const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c,
+ 0xe0, 0x80, 0x61,};
+ UChar expected1[] = { 0x0031, 0x4e8c, 0xfffd, 0x0061};
+ int32_t offsets1[] = { 0x0000, 0x0001, 0x0004, 0x0006};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 ))
+ log_err("utf8->u with substitute did not match.\n");;
+ }
+ log_verbose("Testing toUnicode for SCSU with UCNV_TO_U_CALLBACK_SUBSTITUTE \n");
+ {
+ const uint8_t sampleText1[] = { 0xba, 0x8c,0xF8, 0x61,0x0c, 0x0c,};
+ UChar expected1[] = { 0x00ba, 0x008c, 0x00f8, 0x0061,0xfffd,0xfffd};
+ int32_t offsets1[] = { 0x0000, 0x0001,0x0002,0x0003,4,5};
+
+ if(!testConvertToUnicode(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"SCSU",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0 ))
+ log_err("scsu->u with stop did not match.\n");;
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing ibm-930 subchar/subchar1\n");
+ {
+ static const UChar u1[]={ 0x6d63, 0x6d64, 0x6d65, 0x6d66, 0xdf };
+ static const uint8_t s1[]={ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfe, 0xfe, 0x46, 0x6b, 0x0f, 0x3f };
+ static const int32_t offsets1[]={ 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4 };
+
+ static const UChar u2[]={ 0x6d63, 0x6d64, 0xfffd, 0x6d66, 0x1a };
+ static const uint8_t s2[]={ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0xfc, 0xfc, 0x46, 0x6b, 0x0f, 0x57 };
+ static const int32_t offsets2[]={ 1, 3, 5, 7, 10 };
+
+ if(!testConvertFromUnicode(u1, ARRAY_LENGTH(u1), s1, ARRAY_LENGTH(s1), "ibm-930",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0)
+ ) {
+ log_err("u->ibm-930 subchar/subchar1 did not match.\n");
+ }
+
+ if(!testConvertToUnicode(s2, ARRAY_LENGTH(s2), u2, ARRAY_LENGTH(u2), "ibm-930",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0)
+ ) {
+ log_err("ibm-930->u subchar/subchar1 did not match.\n");
+ }
+ }
+
+ log_verbose("Testing GB 18030 with substitute callbacks\n");
+ {
+ static const UChar u2[]={
+ 0x24, 0x7f, 0x80, 0x1f9, 0x20ac, 0x4e00, 0x9fa6, 0xffff, 0xd800, 0xdc00, 0xfffd, 0xdbff, 0xdfff };
+ static const uint8_t gb2[]={
+ 0x24, 0x7f, 0x81, 0x30, 0x81, 0x30, 0xa8, 0xbf, 0xa2, 0xe3, 0xd2, 0xbb, 0x82, 0x35, 0x8f, 0x33, 0x84, 0x31, 0xa4, 0x39, 0x90, 0x30, 0x81, 0x30, 0xe3, 0x32, 0x9a, 0x36, 0xe3, 0x32, 0x9a, 0x35 };
+ static const int32_t offsets2[]={
+ 0, 1, 2, 6, 8, 10, 12, 16, 20, 20, 24, 28, 28 };
+
+ if(!testConvertToUnicode(gb2, ARRAY_LENGTH(gb2), u2, ARRAY_LENGTH(u2), "gb18030",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0)
+ ) {
+ log_err("gb18030->u with substitute did not match.\n");
+ }
+ }
+#endif
+
+ log_verbose("Testing UTF-7 toUnicode with substitute callbacks\n");
+ {
+ static const uint8_t utf7[]={
+ /* a~ a+AB~ a+AB\x0c a+AB- a+AB. a+. */
+ 0x61, 0x7e, 0x61, 0x2b, 0x41, 0x42, 0x7e, 0x61, 0x2b, 0x41, 0x42, 0x0c, 0x61, 0x2b, 0x41, 0x42, 0x2d, 0x61, 0x2b, 0x41, 0x42, 0x2e, 0x61, 0x2b, 0x2e
+ };
+ static const UChar unicode[]={
+ 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd, 0x61, 0xfffd
+ };
+ static const int32_t offsets[]={
+ 0, 1, 2, 4, 7, 9, 12, 14, 17, 19, 22, 23
+ };
+
+ if(!testConvertToUnicode(utf7, ARRAY_LENGTH(utf7), unicode, ARRAY_LENGTH(unicode), "UTF-7",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets, NULL, 0)
+ ) {
+ log_err("UTF-7->u with substitute did not match.\n");
+ }
+ }
+
+ log_verbose("Testing UTF-16 toUnicode with substitute callbacks\n");
+ {
+ static const uint8_t
+ in1[]={ 0xfe, 0xff, 0x4e, 0x00, 0xfe, 0xff },
+ in2[]={ 0xff, 0xfe, 0x4e, 0x00, 0xfe, 0xff },
+ in3[]={ 0xfe, 0xfd, 0x4e, 0x00, 0xfe, 0xff };
+
+ static const UChar
+ out1[]={ 0x4e00, 0xfeff },
+ out2[]={ 0x004e, 0xfffe },
+ out3[]={ 0xfefd, 0x4e00, 0xfeff };
+
+ static const int32_t
+ offsets1[]={ 2, 4 },
+ offsets2[]={ 2, 4 },
+ offsets3[]={ 0, 2, 4 };
+
+ if(!testConvertToUnicode(in1, ARRAY_LENGTH(in1), out1, ARRAY_LENGTH(out1), "UTF-16",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0)
+ ) {
+ log_err("UTF-16 (BE BOM)->u with substitute did not match.\n");
+ }
+
+ if(!testConvertToUnicode(in2, ARRAY_LENGTH(in2), out2, ARRAY_LENGTH(out2), "UTF-16",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0)
+ ) {
+ log_err("UTF-16 (LE BOM)->u with substitute did not match.\n");
+ }
+
+ if(!testConvertToUnicode(in3, ARRAY_LENGTH(in3), out3, ARRAY_LENGTH(out3), "UTF-16",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets3, NULL, 0)
+ ) {
+ log_err("UTF-16 (no BOM)->u with substitute did not match.\n");
+ }
+ }
+
+ log_verbose("Testing UTF-32 toUnicode with substitute callbacks\n");
+ {
+ static const uint8_t
+ in1[]={ 0x00, 0x00, 0xfe, 0xff, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff },
+ in2[]={ 0xff, 0xfe, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0xfe, 0xff, 0x00, 0x00 },
+ in3[]={ 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x40, 0x00, 0x00, 0xdc, 0x01 },
+ in4[]={ 0x00, 0x01, 0x02, 0x03, 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x4e, 0x00 };
+
+ static const UChar
+ out1[]={ UTF16_LEAD(0x100f00), UTF16_TRAIL(0x100f00), 0xfeff },
+ out2[]={ UTF16_LEAD(0x0f1000), UTF16_TRAIL(0x0f1000), 0xfffe },
+ out3[]={ 0xfefe, UTF16_LEAD(0x100f00), UTF16_TRAIL(0x100f00), 0xfffd, 0xfffd },
+ out4[]={ UTF16_LEAD(0x10203), UTF16_TRAIL(0x10203), 0xfffd, 0x4e00 };
+
+ static const int32_t
+ offsets1[]={ 4, 4, 8 },
+ offsets2[]={ 4, 4, 8 },
+ offsets3[]={ 0, 4, 4, 8, 12 },
+ offsets4[]={ 0, 0, 4, 8 };
+
+ if(!testConvertToUnicode(in1, ARRAY_LENGTH(in1), out1, ARRAY_LENGTH(out1), "UTF-32",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1, NULL, 0)
+ ) {
+ log_err("UTF-32 (BE BOM)->u with substitute did not match.\n");
+ }
+
+ if(!testConvertToUnicode(in2, ARRAY_LENGTH(in2), out2, ARRAY_LENGTH(out2), "UTF-32",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets2, NULL, 0)
+ ) {
+ log_err("UTF-32 (LE BOM)->u with substitute did not match.\n");
+ }
+
+ if(!testConvertToUnicode(in3, ARRAY_LENGTH(in3), out3, ARRAY_LENGTH(out3), "UTF-32",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets3, NULL, 0)
+ ) {
+ log_err("UTF-32 (no BOM)->u with substitute did not match.\n");
+ }
+
+ if(!testConvertToUnicode(in4, ARRAY_LENGTH(in4), out4, ARRAY_LENGTH(out4), "UTF-32",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets4, NULL, 0)
+ ) {
+ log_err("UTF-32 (no BOM, with error)->u with substitute did not match.\n");
+ }
+ }
+}
+
+static void TestSubWithValue(int32_t inputsize, int32_t outputsize)
+{
+ UChar sampleText[] = { 0x0000, 0xAC00, 0xAC01, 0xEF67, 0xD700 };
+ UChar sampleText2[] = { 0x6D63, 0x6D64, 0x6D65, 0x6D66 };
+
+ const uint8_t expsubwvalIBM_949[]= {
+ 0x00, 0xb0, 0xa1, 0xb0, 0xa2,
+ 0x25, 0x55, 0x45, 0x46, 0x36, 0x37, 0xc8, 0xd3 };
+
+ const uint8_t expsubwvalIBM_943[]= {
+ 0x9f, 0xaf, 0x9f, 0xb1,
+ 0x25, 0x55, 0x36, 0x44, 0x36, 0x35, 0x89, 0x59 };
+
+ const uint8_t expsubwvalIBM_930[] = {
+ 0x0e, 0x5d, 0x5f, 0x5d, 0x63, 0x0f, 0x6c, 0xe4, 0xf6, 0xc4, 0xf6, 0xf5, 0x0e, 0x46, 0x6b, 0x0f };
+
+ int32_t toIBM949Offs [] ={ 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4 };
+ int32_t toIBM943Offs [] = { 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3 };
+ int32_t toIBM930Offs [] = { 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3 }; /* last item: 3,3,3,3 because there's SO+DBCS+SI */
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ /*from Unicode*/
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertFromUnicode(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expsubwvalIBM_949, sizeof(expsubwvalIBM_949), "ibm-949",
+ UCNV_FROM_U_CALLBACK_ESCAPE, toIBM949Offs, NULL, 0 ))
+ log_err("u-> ibm-949 with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expsubwvalIBM_943, sizeof(expsubwvalIBM_943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_ESCAPE, toIBM943Offs, NULL, 0 ))
+ log_err("u-> ibm-943 with sub with value did not match.\n");
+
+ if(!testConvertFromUnicode(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expsubwvalIBM_930, sizeof(expsubwvalIBM_930), "ibm-930",
+ UCNV_FROM_U_CALLBACK_ESCAPE, toIBM930Offs, NULL, 0 ))
+ log_err("u-> ibm-930 with subst with value did not match.\n");
+
+
+ log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_ESCAPE \n");
+ {
+ static const UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 };
+ static const uint8_t toIBM943[]= { 0x61,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x43, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x61 };
+ static const int32_t offset[]= {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 4};
+
+
+ /* EUC_JP*/
+ static const UChar euc_jp_inputText[]={ 0x0061, 0x4edd, 0x5bec, 0xd801, 0xdc01, 0xd801, 0x0061, 0x00a2, };
+ static const uint8_t to_euc_jp[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x43, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x61, 0x8e, 0xe0,
+ };
+ static const int32_t fromEUC_JPOffs [] ={ 0, 1, 1, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3,
+ 5, 5, 5, 5, 5, 5,
+ 6, 7, 7,
+ };
+
+ /*EUC_TW*/
+ static const UChar euc_tw_inputText[]={ 0x0061, 0x2295, 0x5BF2, 0xd801, 0xdc01, 0xd801, 0x0061, 0x8706, 0x8a, };
+ static const uint8_t to_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x43, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x61, 0xe6, 0xca, 0x8a,
+ };
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5,
+ 6, 7, 7, 8,
+ };
+ /*ISO-2022-JP*/
+ static const UChar iso_2022_jp_inputText1[]={ 0x3000, 0x00E9, 0x3001,0x00E9, 0x0042} ;
+ static const uint8_t to_iso_2022_jp1[]={
+ 0x1b, 0x24, 0x42, 0x21, 0x21,
+ 0x1b, 0x28, 0x42, 0x25, 0x55, 0x30, 0x30, 0x45, 0x39,
+ 0x1b, 0x24, 0x42, 0x21, 0x22,
+ 0x1b, 0x28, 0x42, 0x25, 0x55, 0x30, 0x30, 0x45, 0x39,
+ 0x42,
+ };
+
+ static const int32_t from_iso_2022_jpOffs1 [] ={
+ 0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,
+ 4,
+ };
+ /* surrogate pair*/
+ static const UChar iso_2022_jp_inputText2[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042} ;
+ static const uint8_t to_iso_2022_jp2[]={
+ 0x1b, 0x24, 0x42, 0x21, 0x21,
+ 0x1b, 0x28, 0x42, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x1b, 0x24, 0x42, 0x21, 0x22,
+ 0x1b, 0x28, 0x42, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x42,
+ };
+ static const int32_t from_iso_2022_jpOffs2 [] ={
+ 0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,
+ 3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,
+ 6,
+ };
+
+ /*ISO-2022-cn*/
+ static const UChar iso_2022_cn_inputText[]={ 0x0041, 0x3712, 0x0042, };
+ static const uint8_t to_iso_2022_cn[]={
+ 0x41,
+ 0x25, 0x55, 0x33, 0x37, 0x31, 0x32,
+ 0x42,
+ };
+ static const int32_t from_iso_2022_cnOffs [] ={
+ 0,
+ 1,1,1,1,1,1,
+ 2,
+ };
+
+ static const UChar iso_2022_cn_inputText4[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042};
+
+ static const uint8_t to_iso_2022_cn4[]={
+ 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21,
+ 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x0e, 0x21, 0x22,
+ 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x42,
+ };
+ static const int32_t from_iso_2022_cnOffs4 [] ={
+ 0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,
+ 3,3,3,
+ 4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,
+ 6
+
+ };
+
+ /*ISO-2022-kr*/
+ static const UChar iso_2022_kr_inputText2[]={ 0x0041, 0x03A0,0xD84D, 0xDC56/*unassigned*/,0x03A0, 0x0042,0xD84D, 0xDC56/*unassigned*/,0x43 };
+ static const uint8_t to_iso_2022_kr2[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x42,
+ 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x43
+ };
+ static const int32_t from_iso_2022_krOffs2 [] ={
+ -1,-1,-1,-1,
+ 0,
+ 1,1,1,
+ 2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,
+ 4,4,4,
+ 5,5,
+ 6,6,6,6,6,6,
+ 6,6,6,6,6,6,
+ 8,
+ };
+
+ static const UChar iso_2022_kr_inputText[]={ 0x0041, 0x03A0,0x3712/*unassigned*/,0x03A0, 0x0042,0x3712/*unassigned*/,0x43 };
+ static const uint8_t to_iso_2022_kr[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x42,
+ 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/
+ 0x43
+ };
+
+
+ static const int32_t from_iso_2022_krOffs [] ={
+ -1,-1,-1,-1,
+ 0,
+ 1,1,1,
+ 2,2,2,2,2,2,2,
+ 3,3,3,
+ 4,4,
+ 5,5,5,5,5,5,
+ 6,
+ };
+ /* HZ encoding */
+ static const UChar hz_inputText[]={ 0x0041, 0x03A0,0x0662/*unassigned*/,0x03A0, 0x0042, };
+
+ static const uint8_t to_hz[]={
+ 0x7e, 0x7d, 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7e, 0x7d, 0x25, 0x55, 0x30, 0x36, 0x36, 0x32, /*unassigned*/
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7e, 0x7d, 0x42,
+
+ };
+ static const int32_t from_hzOffs [] ={
+ 0,0,0,
+ 1,1,1,1,
+ 2,2,2,2,2,2,2,2,
+ 3,3,3,3,
+ 4,4,4
+ };
+
+ static const UChar hz_inputText2[]={ 0x0041, 0x03A0,0xD84D, 0xDC56/*unassigned*/,0x03A0, 0x0042,0xD84D, 0xDC56/*unassigned*/,0x43 };
+ static const uint8_t to_hz2[]={
+ 0x7e, 0x7d, 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7e, 0x7d, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7e, 0x7d, 0x42,
+ 0x25, 0x55, 0x44, 0x38, 0x34, 0x44,
+ 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x43
+ };
+ static const int32_t from_hzOffs2 [] ={
+ 0,0,0,
+ 1,1,1,1,
+ 2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,
+ 4,4,4,4,
+ 5,5,5,
+ 6,6,6,6,6,6,
+ 6,6,6,6,6,6,
+ 8,
+ };
+
+ /*ISCII*/
+ static const UChar iscii_inputText[]={ 0x0041, 0x0901,0x3712/*unassigned*/,0x0902, 0x0042,0x3712/*unassigned*/,0x43 };
+ static const uint8_t to_iscii[]={
+ 0x41,
+ 0xef, 0x42, 0xa1,
+ 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/
+ 0xa2,
+ 0x42,
+ 0x25, 0x55, 0x33, 0x37, 0x31, 0x32, /*unassigned*/
+ 0x43
+ };
+
+
+ static const int32_t from_isciiOffs [] ={
+ 0,
+ 1,1,1,
+ 2,2,2,2,2,2,
+ 3,
+ 4,
+ 5,5,5,5,5,5,
+ 6,
+ };
+
+ if(!testConvertFromUnicode(inputTest, sizeof(inputTest)/sizeof(inputTest[0]),
+ toIBM943, sizeof(toIBM943), "ibm-943",
+ UCNV_FROM_U_CALLBACK_ESCAPE, offset, NULL, 0 ))
+ log_err("u-> ibm-943 with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(euc_jp_inputText, sizeof(euc_jp_inputText)/sizeof(euc_jp_inputText[0]),
+ to_euc_jp, sizeof(to_euc_jp), "euc-jp",
+ UCNV_FROM_U_CALLBACK_ESCAPE, fromEUC_JPOffs, NULL, 0 ))
+ log_err("u-> euc-jp with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(euc_tw_inputText, sizeof(euc_tw_inputText)/sizeof(euc_tw_inputText[0]),
+ to_euc_tw, sizeof(to_euc_tw), "euc-tw",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_euc_twOffs, NULL, 0 ))
+ log_err("u-> euc-tw with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_jp_inputText1, sizeof(iso_2022_jp_inputText1)/sizeof(iso_2022_jp_inputText1[0]),
+ to_iso_2022_jp1, sizeof(to_iso_2022_jp1), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs1, NULL, 0 ))
+ log_err("u-> iso_2022_jp with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_jp_inputText1, sizeof(iso_2022_jp_inputText1)/sizeof(iso_2022_jp_inputText1[0]),
+ to_iso_2022_jp1, sizeof(to_iso_2022_jp1), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs1, NULL, 0 ))
+ log_err("u-> iso_2022_jp with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_jp_inputText2, sizeof(iso_2022_jp_inputText2)/sizeof(iso_2022_jp_inputText2[0]),
+ to_iso_2022_jp2, sizeof(to_iso_2022_jp2), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs2, NULL, 0 ))
+ log_err("u-> iso_2022_jp with subst with value did not match.\n");
+ /*ESCAPE OPTIONS*/
+ {
+ /* surrogate pair*/
+ static const UChar iso_2022_jp_inputText3[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0901c } ;
+ static const uint8_t to_iso_2022_jp3_v2[]={
+ 0x1b, 0x24, 0x42, 0x21, 0x21,
+ 0x1b, 0x28, 0x42, 0x26, 0x23, 0x31, 0x34, 0x34, 0x34, 0x37, 0x30, 0x3b,
+
+ 0x1b, 0x24, 0x42, 0x21, 0x22,
+ 0x1b, 0x28, 0x42, 0x26, 0x23, 0x31, 0x34, 0x34, 0x34, 0x37, 0x30, 0x3b,
+
+ 0x42,
+ 0x26, 0x23, 0x33, 0x36, 0x38, 0x39, 0x32, 0x3b,
+ };
+
+ static const int32_t from_iso_2022_jpOffs3_v2 [] ={
+ 0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,
+
+ 3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,4,4,4,4,
+
+ 6,
+ 7,7,7,7,7,7,7,7,7
+ };
+
+ if(!testConvertFromUnicodeWithContext(iso_2022_jp_inputText3, sizeof(iso_2022_jp_inputText3)/sizeof(iso_2022_jp_inputText3[0]),
+ to_iso_2022_jp3_v2, sizeof(to_iso_2022_jp3_v2), "iso-2022-jp",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs3_v2, NULL, 0,UCNV_ESCAPE_XML_DEC,U_ZERO_ERROR ))
+ log_err("u-> iso-2022-jp with sub & UCNV_ESCAPE_XML_DEC did not match.\n");
+ }
+ {
+ static const UChar iso_2022_cn_inputText5[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902};
+ static const uint8_t to_iso_2022_cn5_v2[]={
+ 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21,
+ 0x0f, 0x5c, 0x75, 0x44, 0x38, 0x34, 0x44,
+ 0x5c, 0x75, 0x44, 0x43, 0x35, 0x36,
+ 0x0e, 0x21, 0x22,
+ 0x0f, 0x5c, 0x75, 0x44, 0x38, 0x34, 0x44,
+ 0x5c, 0x75, 0x44, 0x43, 0x35, 0x36,
+ 0x42,
+ 0x5c, 0x75, 0x30, 0x39, 0x30, 0x32,
+ };
+ static const int32_t from_iso_2022_cnOffs5_v2 [] ={
+ 0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,
+ 3,3,3,
+ 4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,
+ 6,
+ 7,7,7,7,7,7
+ };
+ if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText5, sizeof(iso_2022_cn_inputText5)/sizeof(iso_2022_cn_inputText5[0]),
+ to_iso_2022_cn5_v2, sizeof(to_iso_2022_cn5_v2), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs5_v2, NULL, 0,UCNV_ESCAPE_JAVA,U_ZERO_ERROR ))
+ log_err("u-> iso-2022-cn with sub & UCNV_ESCAPE_JAVA did not match.\n");
+
+ }
+ {
+ static const UChar iso_2022_cn_inputText6[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902};
+ static const uint8_t to_iso_2022_cn6_v2[]={
+ 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21,
+ 0x0f, 0x7b, 0x55, 0x2b, 0x32, 0x33, 0x34, 0x35, 0x36, 0x7d,
+ 0x0e, 0x21, 0x22,
+ 0x0f, 0x7b, 0x55, 0x2b, 0x32, 0x33, 0x34, 0x35, 0x36, 0x7d,
+ 0x42,
+ 0x7b, 0x55, 0x2b, 0x30, 0x39, 0x30, 0x32, 0x7d
+ };
+ static const int32_t from_iso_2022_cnOffs6_v2 [] ={
+ 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 6,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ };
+ if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText6, sizeof(iso_2022_cn_inputText6)/sizeof(iso_2022_cn_inputText6[0]),
+ to_iso_2022_cn6_v2, sizeof(to_iso_2022_cn6_v2), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs6_v2, NULL, 0,UCNV_ESCAPE_UNICODE,U_ZERO_ERROR ))
+ log_err("u-> iso-2022-cn with sub & UCNV_ESCAPE_UNICODE did not match.\n");
+
+ }
+ {
+ static const UChar iso_2022_cn_inputText7[]={ 0x3000, 0xD84D, 0xDC56, 0x3001,0xD84D,0xDC56, 0x0042,0x0902};
+ static const uint8_t to_iso_2022_cn7_v2[]={
+ 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21,
+ 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x0e, 0x21, 0x22,
+ 0x0f, 0x25, 0x55, 0x44, 0x38, 0x34, 0x44, 0x25, 0x55, 0x44, 0x43, 0x35, 0x36,
+ 0x42, 0x25, 0x55, 0x30, 0x39, 0x30, 0x32,
+ };
+ static const int32_t from_iso_2022_cnOffs7_v2 [] ={
+ 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 6,
+ 7, 7, 7, 7, 7, 7,
+ };
+ if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText7, sizeof(iso_2022_cn_inputText7)/sizeof(iso_2022_cn_inputText7[0]),
+ to_iso_2022_cn7_v2, sizeof(to_iso_2022_cn7_v2), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs7_v2, NULL, 0,"K" ,U_ZERO_ERROR ))
+ log_err("u-> iso-2022-cn with sub & K did not match.\n");
+
+ }
+ {
+ static const uint8_t to_iso_2022_cn4_v3[]={
+ 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x21, 0x21,
+ 0x0f, 0x5c, 0x55, 0x30, 0x30, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x0e, 0x21, 0x22,
+ 0x0f, 0x5c, 0x55, 0x30, 0x30, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x42
+ };
+
+
+ static const int32_t from_iso_2022_cnOffs4_v3 [] ={
+ 0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,
+
+ 3,3,3,
+ 4,4,4,4,4,4,4,4,4,4,4,
+
+ 6
+
+ };
+ if(!testConvertFromUnicodeWithContext(iso_2022_cn_inputText4, sizeof(iso_2022_cn_inputText4)/sizeof(iso_2022_cn_inputText4[0]),
+ to_iso_2022_cn4_v3, sizeof(to_iso_2022_cn4_v3), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs4_v3, NULL, 0,UCNV_ESCAPE_C,U_ZERO_ERROR ))
+ {
+ log_err("u-> iso-2022-cn with skip & UCNV_ESCAPE_C did not match.\n");
+ }
+ }
+ if(!testConvertFromUnicode(iso_2022_cn_inputText, sizeof(iso_2022_cn_inputText)/sizeof(iso_2022_cn_inputText[0]),
+ to_iso_2022_cn, sizeof(to_iso_2022_cn), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs, NULL, 0 ))
+ log_err("u-> iso_2022_cn with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(iso_2022_cn_inputText4, sizeof(iso_2022_cn_inputText4)/sizeof(iso_2022_cn_inputText4[0]),
+ to_iso_2022_cn4, sizeof(to_iso_2022_cn4), "iso-2022-cn",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs4, NULL, 0 ))
+ log_err("u-> iso_2022_cn with subst with value did not match.\n");
+ if(!testConvertFromUnicode(iso_2022_kr_inputText, sizeof(iso_2022_kr_inputText)/sizeof(iso_2022_kr_inputText[0]),
+ to_iso_2022_kr, sizeof(to_iso_2022_kr), "iso-2022-kr",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_krOffs, NULL, 0 ))
+ log_err("u-> iso_2022_kr with subst with value did not match.\n");
+ if(!testConvertFromUnicode(iso_2022_kr_inputText2, sizeof(iso_2022_kr_inputText2)/sizeof(iso_2022_kr_inputText2[0]),
+ to_iso_2022_kr2, sizeof(to_iso_2022_kr2), "iso-2022-kr",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_iso_2022_krOffs2, NULL, 0 ))
+ log_err("u-> iso_2022_kr2 with subst with value did not match.\n");
+ if(!testConvertFromUnicode(hz_inputText, sizeof(hz_inputText)/sizeof(hz_inputText[0]),
+ to_hz, sizeof(to_hz), "HZ",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_hzOffs, NULL, 0 ))
+ log_err("u-> hz with subst with value did not match.\n");
+ if(!testConvertFromUnicode(hz_inputText2, sizeof(hz_inputText2)/sizeof(hz_inputText2[0]),
+ to_hz2, sizeof(to_hz2), "HZ",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_hzOffs2, NULL, 0 ))
+ log_err("u-> hz with subst with value did not match.\n");
+
+ if(!testConvertFromUnicode(iscii_inputText, sizeof(iscii_inputText)/sizeof(iscii_inputText[0]),
+ to_iscii, sizeof(to_iscii), "ISCII,version=0",
+ UCNV_FROM_U_CALLBACK_ESCAPE, from_isciiOffs, NULL, 0 ))
+ log_err("u-> iscii with subst with value did not match.\n");
+ }
+#endif
+
+ log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_ESCAPE \n");
+ /*to Unicode*/
+ {
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ static const uint8_t sampleTxtToU[]= { 0x00, 0x9f, 0xaf,
+ 0x81, 0xad, /*unassigned*/
+ 0x89, 0xd3 };
+ static const UChar IBM_943toUnicode[] = { 0x0000, 0x6D63,
+ 0x25, 0x58, 0x38, 0x31, 0x25, 0x58, 0x41, 0x44,
+ 0x7B87};
+ static const int32_t fromIBM943Offs [] = { 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 5};
+
+ /* EUC_JP*/
+ static const uint8_t sampleTxt_EUC_JP[]={ 0x61, 0xa1, 0xb8, 0x8f, 0xf4, 0xae,
+ 0x8f, 0xda, 0xa1, /*unassigned*/
+ 0x8e, 0xe0,
+ };
+ static const UChar EUC_JPtoUnicode[]={ 0x0061, 0x4edd, 0x5bec,
+ 0x25, 0x58, 0x38, 0x46, 0x25, 0x58, 0x44, 0x41, 0x25, 0x58, 0x41, 0x31,
+ 0x00a2 };
+ static const int32_t fromEUC_JPOffs [] ={ 0, 1, 3,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 9,
+ };
+
+ /*EUC_TW*/
+ static const uint8_t sampleTxt_euc_tw[]={
+ 0x61, 0xa2, 0xd3, 0x8e, 0xa2, 0xdc, 0xe5,
+ 0x8e, 0xaa, 0xbb, 0xcc,/*unassigned*/
+ 0xe6, 0xca, 0x8a,
+ };
+ static const UChar euc_twtoUnicode[]={ 0x0061, 0x2295, 0x5BF2,
+ 0x25, 0x58, 0x38, 0x45, 0x25, 0x58, 0x41, 0x41, 0x25, 0x58, 0x42, 0x42, 0x25, 0x58, 0x43, 0x43,
+ 0x8706, 0x8a, };
+ static const int32_t from_euc_twOffs [] ={ 0, 1, 3,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 11, 13};
+
+ /*iso-2022-jp*/
+ static const uint8_t sampleTxt_iso_2022_jp[]={
+ 0x1b, 0x28, 0x42, 0x41,
+ 0x1b, 0x24, 0x42, 0x2A, 0x44, /*unassigned*/
+ 0x1b, 0x28, 0x42, 0x42,
+
+ };
+ static const UChar iso_2022_jptoUnicode[]={ 0x41,0x25,0x58,0x32,0x41,0x25,0x58,0x34,0x34, 0x42 };
+ static const int32_t from_iso_2022_jpOffs [] ={ 3, 7, 7, 7, 7, 7, 7, 7, 7, 12 };
+
+ /*iso-2022-cn*/
+ static const uint8_t sampleTxt_iso_2022_cn[]={
+ 0x0f, 0x41, 0x44,
+ 0x1B, 0x24, 0x29, 0x47,
+ 0x0E, 0x40, 0x6c, /*unassigned*/
+ 0x0f, 0x42,
+
+ };
+ static const UChar iso_2022_cntoUnicode[]={ 0x41, 0x44,0x25,0x58,0x34,0x30,0x25,0x58,0x36,0x43,0x42 };
+ static const int32_t from_iso_2022_cnOffs [] ={ 1, 2, 8, 8, 8, 8, 8, 8, 8, 8, 11 };
+
+ /*iso-2022-kr*/
+ static const uint8_t sampleTxt_iso_2022_kr[]={
+ 0x1b, 0x24, 0x29, 0x43,
+ 0x41,
+ 0x0E, 0x7f, 0x1E,
+ 0x0e, 0x25, 0x50,
+ 0x0f, 0x51,
+ 0x42, 0x43,
+
+ };
+ static const UChar iso_2022_krtoUnicode[]={ 0x41,0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45,0x03A0,0x51, 0x42,0x43};
+ static const int32_t from_iso_2022_krOffs [] ={ 4, 6, 6, 6, 6, 6, 6, 6, 6, 9, 12, 13 , 14 };
+
+ /*hz*/
+ static const uint8_t sampleTxt_hz[]={
+ 0x41,
+ 0x7e, 0x7b, 0x26, 0x30,
+ 0x7f, 0x1E, /*unassigned*/
+ 0x26, 0x30,
+ 0x7e, 0x7d, 0x42,
+ 0x7e, 0x7b, 0x7f, 0x1E,/*unassigned*/
+ 0x7e, 0x7d, 0x42,
+ };
+ static const UChar hztoUnicode[]={
+ 0x41,
+ 0x03a0,
+ 0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45,
+ 0x03A0,
+ 0x42,
+ 0x25,0x58,0x37,0x46,0x25,0x58,0x31,0x45,
+ 0x42,};
+
+ static const int32_t from_hzOffs [] ={0,3,5,5,5,5,5,5,5,5,7,11,14,14,14,14,14,14,14,14,18, };
+
+
+ /*iscii*/
+ static const uint8_t sampleTxt_iscii[]={
+ 0x41,
+ 0x30,
+ 0xEB, /*unassigned*/
+ 0xa3,
+ 0x42,
+ 0xEC, /*unassigned*/
+ 0x42,
+ };
+ static const UChar isciitoUnicode[]={
+ 0x41,
+ 0x30,
+ 0x25, 0x58, 0x45, 0x42,
+ 0x0903,
+ 0x42,
+ 0x25, 0x58, 0x45, 0x43,
+ 0x42,};
+
+ static const int32_t from_isciiOffs [] ={0,1,2,2,2,2,3,4,5,5,5,5,6 };
+#endif
+
+ /*UTF8*/
+ static const uint8_t sampleTxtUTF8[]={
+ 0x20, 0x64, 0x50,
+ 0xC2, 0x7E, /* truncated char */
+ 0x20,
+ 0xE0, 0xB5, 0x7E, /* truncated char */
+ 0x40,
+ };
+ static const UChar UTF8ToUnicode[]={
+ 0x0020, 0x0064, 0x0050,
+ 0x0025, 0x0058, 0x0043, 0x0032, 0x007E, /* \xC2~ */
+ 0x0020,
+ 0x0025, 0x0058, 0x0045, 0x0030, 0x0025, 0x0058, 0x0042, 0x0035, 0x007E,
+ 0x0040
+ };
+ static const int32_t fromUTF8[] = {
+ 0, 1, 2,
+ 3, 3, 3, 3, 4,
+ 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 8,
+ 9
+ };
+ static const UChar UTF8ToUnicodeXML_DEC[]={
+ 0x0020, 0x0064, 0x0050,
+ 0x0026, 0x0023, 0x0031, 0x0039, 0x0034, 0x003B, 0x007E, /* &#194;~ */
+ 0x0020,
+ 0x0026, 0x0023, 0x0032, 0x0032, 0x0034, 0x003B, 0x0026, 0x0023, 0x0031, 0x0038, 0x0031, 0x003B, 0x007E,
+ 0x0040
+ };
+ static const int32_t fromUTF8XML_DEC[] = {
+ 0, 1, 2,
+ 3, 3, 3, 3, 3, 3, 4,
+ 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8,
+ 9
+ };
+
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ if(!testConvertToUnicode(sampleTxtToU, sizeof(sampleTxtToU),
+ IBM_943toUnicode, sizeof(IBM_943toUnicode)/sizeof(IBM_943toUnicode[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_ESCAPE, fromIBM943Offs, NULL, 0 ))
+ log_err("ibm-943->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_EUC_JP, sizeof(sampleTxt_EUC_JP),
+ EUC_JPtoUnicode, sizeof(EUC_JPtoUnicode)/sizeof(EUC_JPtoUnicode[0]),"euc-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, fromEUC_JPOffs, NULL, 0))
+ log_err("euc-jp->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_euc_tw, sizeof(sampleTxt_euc_tw),
+ euc_twtoUnicode, sizeof(euc_twtoUnicode)/sizeof(euc_twtoUnicode[0]),"euc-tw",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_euc_twOffs, NULL, 0))
+ log_err("euc-tw->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs, NULL, 0))
+ log_err("iso-2022-jp->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicode, sizeof(iso_2022_jptoUnicode)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffs, NULL, 0,"K",U_ZERO_ERROR))
+ log_err("iso-2022-jp->u with substitute with value did not match.\n");
+
+ {/* test UCNV_TO_U_CALLBACK_ESCAPE with options */
+ {
+ static const UChar iso_2022_jptoUnicodeDec[]={
+ 0x0041,
+ 0x0026, 0x0023, 0x0034, 0x0032, 0x003b,
+ 0x0026, 0x0023, 0x0036, 0x0038, 0x003b,
+ 0x0042 };
+ static const int32_t from_iso_2022_jpOffsDec [] ={ 3,7,7,7,7,7,7,7,7,7,7,12, };
+ if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicodeDec, sizeof(iso_2022_jptoUnicodeDec)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsDec, NULL, 0,UCNV_ESCAPE_XML_DEC,U_ZERO_ERROR ))
+ log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_XML_DEC did not match.\n");
+ }
+ {
+ static const UChar iso_2022_jptoUnicodeHex[]={
+ 0x0041,
+ 0x0026, 0x0023, 0x0078, 0x0032, 0x0041, 0x003b,
+ 0x0026, 0x0023, 0x0078, 0x0034, 0x0034, 0x003b,
+ 0x0042 };
+ static const int32_t from_iso_2022_jpOffsHex [] ={ 3,7,7,7,7,7,7,7,7,7,7,7,7,12 };
+ if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicodeHex, sizeof(iso_2022_jptoUnicodeHex)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsHex, NULL, 0,UCNV_ESCAPE_XML_HEX,U_ZERO_ERROR ))
+ log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_XML_HEX did not match.\n");
+ }
+ {
+ static const UChar iso_2022_jptoUnicodeC[]={
+ 0x0041,
+ 0x005C, 0x0078, 0x0032, 0x0041,
+ 0x005C, 0x0078, 0x0034, 0x0034,
+ 0x0042 };
+ int32_t from_iso_2022_jpOffsC [] ={ 3,7,7,7,7,7,7,7,7,12 };
+ if(!testConvertToUnicodeWithContext(sampleTxt_iso_2022_jp, sizeof(sampleTxt_iso_2022_jp),
+ iso_2022_jptoUnicodeC, sizeof(iso_2022_jptoUnicodeC)/sizeof(iso_2022_jptoUnicode[0]),"iso-2022-jp",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_jpOffsC, NULL, 0,UCNV_ESCAPE_C,U_ZERO_ERROR ))
+ log_err("iso-2022-jp->u with substitute with value and UCNV_ESCAPE_C did not match.\n");
+ }
+ }
+ if(!testConvertToUnicode(sampleTxt_iso_2022_cn, sizeof(sampleTxt_iso_2022_cn),
+ iso_2022_cntoUnicode, sizeof(iso_2022_cntoUnicode)/sizeof(iso_2022_cntoUnicode[0]),"iso-2022-cn",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_cnOffs, NULL, 0))
+ log_err("iso-2022-cn->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iso_2022_kr, sizeof(sampleTxt_iso_2022_kr),
+ iso_2022_krtoUnicode, sizeof(iso_2022_krtoUnicode)/sizeof(iso_2022_krtoUnicode[0]),"iso-2022-kr",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_iso_2022_krOffs, NULL, 0))
+ log_err("iso-2022-kr->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_hz, sizeof(sampleTxt_hz),
+ hztoUnicode, sizeof(hztoUnicode)/sizeof(hztoUnicode[0]),"HZ",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_hzOffs, NULL, 0))
+ log_err("hz->u with substitute with value did not match.\n");
+
+ if(!testConvertToUnicode(sampleTxt_iscii, sizeof(sampleTxt_iscii),
+ isciitoUnicode, sizeof(isciitoUnicode)/sizeof(isciitoUnicode[0]),"ISCII,version=0",
+ UCNV_TO_U_CALLBACK_ESCAPE, from_isciiOffs, NULL, 0))
+ log_err("ISCII ->u with substitute with value did not match.\n");
+#endif
+
+ if(!testConvertToUnicode(sampleTxtUTF8, sizeof(sampleTxtUTF8),
+ UTF8ToUnicode, sizeof(UTF8ToUnicode)/sizeof(UTF8ToUnicode[0]),"UTF-8",
+ UCNV_TO_U_CALLBACK_ESCAPE, fromUTF8, NULL, 0))
+ log_err("UTF8->u with UCNV_TO_U_CALLBACK_ESCAPE with value did not match.\n");
+ if(!testConvertToUnicodeWithContext(sampleTxtUTF8, sizeof(sampleTxtUTF8),
+ UTF8ToUnicodeXML_DEC, sizeof(UTF8ToUnicodeXML_DEC)/sizeof(UTF8ToUnicodeXML_DEC[0]),"UTF-8",
+ UCNV_TO_U_CALLBACK_ESCAPE, fromUTF8XML_DEC, NULL, 0, UCNV_ESCAPE_XML_DEC, U_ZERO_ERROR))
+ log_err("UTF8->u with UCNV_TO_U_CALLBACK_ESCAPE with value did not match.\n");
+ }
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestLegalAndOthers(int32_t inputsize, int32_t outputsize)
+{
+ static const UChar legalText[] = { 0x0000, 0xAC00, 0xAC01, 0xD700 };
+ static const uint8_t templegal949[] ={ 0x00, 0xb0, 0xa1, 0xb0, 0xa2, 0xc8, 0xd3 };
+ static const int32_t to949legal[] = {0, 1, 1, 2, 2, 3, 3};
+
+
+ static const uint8_t text943[] = {
+ 0x82, 0xa9, 0x82, 0x20, /*0xc8,*/ 0x61, 0x8a, 0xbf, 0x8e, 0x9a };
+ static const UChar toUnicode943sub[] = { 0x304b, 0xfffd, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57};
+ static const UChar toUnicode943skip[]= { 0x304b, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57};
+ static const UChar toUnicode943stop[]= { 0x304b};
+
+ static const int32_t fromIBM943Offssub[] = {0, 2, 4, 5, 7};
+ static const int32_t fromIBM943Offsskip[] = { 0, 4, 5, 7};
+ static const int32_t fromIBM943Offsstop[] = { 0};
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+ /*checking with a legal value*/
+ if(!testConvertFromUnicode(legalText, sizeof(legalText)/sizeof(legalText[0]),
+ templegal949, sizeof(templegal949), "ibm-949",
+ UCNV_FROM_U_CALLBACK_SKIP, to949legal, NULL, 0 ))
+ log_err("u-> ibm-949 with skip did not match.\n");
+
+ /*checking illegal value for ibm-943 with substitute*/
+ if(!testConvertToUnicode(text943, sizeof(text943),
+ toUnicode943sub, sizeof(toUnicode943sub)/sizeof(toUnicode943sub[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offssub, NULL, 0 ))
+ log_err("ibm-943->u with subst did not match.\n");
+ /*checking illegal value for ibm-943 with skip */
+ if(!testConvertToUnicode(text943, sizeof(text943),
+ toUnicode943skip, sizeof(toUnicode943skip)/sizeof(toUnicode943skip[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_SKIP, fromIBM943Offsskip, NULL, 0 ))
+ log_err("ibm-943->u with skip did not match.\n");
+
+ /*checking illegal value for ibm-943 with stop */
+ if(!testConvertToUnicode(text943, sizeof(text943),
+ toUnicode943stop, sizeof(toUnicode943stop)/sizeof(toUnicode943stop[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_STOP, fromIBM943Offsstop, NULL, 0 ))
+ log_err("ibm-943->u with stop did not match.\n");
+
+}
+
+static void TestSingleByte(int32_t inputsize, int32_t outputsize)
+{
+ static const uint8_t sampleText[] = {
+ 0x82, 0xa9, 0x61, 0x62, 0x63 , 0x82,
+ 0xff, /*0x82, 0xa9,*/ 0x32, 0x33};
+ static const UChar toUnicode943sub[] = {0x304b, 0x0061, 0x0062, 0x0063, 0xfffd,/*0x304b,*/ 0x0032, 0x0033};
+ static const int32_t fromIBM943Offssub[] = {0, 2, 3, 4, 5, 7, 8};
+ /*checking illegal value for ibm-943 with substitute*/
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ if(!testConvertToUnicode(sampleText, sizeof(sampleText),
+ toUnicode943sub, sizeof(toUnicode943sub)/sizeof(toUnicode943sub[0]),"ibm-943",
+ UCNV_TO_U_CALLBACK_SUBSTITUTE, fromIBM943Offssub, NULL, 0 ))
+ log_err("ibm-943->u with subst did not match.\n");
+}
+
+static void TestEBCDIC_STATEFUL_Sub(int32_t inputsize, int32_t outputsize)
+{
+ /*EBCDIC_STATEFUL*/
+ static const UChar ebcdic_inputTest[] = { 0x0061, 0x6d64, 0x0061, 0x00A2, 0x6d65, 0x0061 };
+ static const uint8_t toIBM930[]= { 0x62, 0x0e, 0x5d, 0x63, 0x0f, 0x62, 0xb1, 0x0e, 0xfe, 0xfe, 0x0f, 0x62 };
+ static const int32_t offset_930[]= { 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5 };
+/* s SO doubl SI sng s SO fe fe SI s */
+
+ /*EBCDIC_STATEFUL with subChar=3f*/
+ static const uint8_t toIBM930_subvaried[]= { 0x62, 0x0e, 0x5d, 0x63, 0x0f, 0x62, 0xb1, 0x3f, 0x62 };
+ static const int32_t offset_930_subvaried[]= { 0, 1, 1, 1, 2, 2, 3, 4, 5 };
+ static const char mySubChar[]={ 0x3f};
+
+ gInBufferSize = inputsize;
+ gOutBufferSize = outputsize;
+
+ if(!testConvertFromUnicode(ebcdic_inputTest, sizeof(ebcdic_inputTest)/sizeof(ebcdic_inputTest[0]),
+ toIBM930, sizeof(toIBM930), "ibm-930",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset_930, NULL, 0 ))
+ log_err("u-> ibm-930(EBCDIC_STATEFUL) with subst did not match.\n");
+
+ if(!testConvertFromUnicode(ebcdic_inputTest, sizeof(ebcdic_inputTest)/sizeof(ebcdic_inputTest[0]),
+ toIBM930_subvaried, sizeof(toIBM930_subvaried), "ibm-930",
+ UCNV_FROM_U_CALLBACK_SUBSTITUTE, offset_930_subvaried, mySubChar, 1 ))
+ log_err("u-> ibm-930(EBCDIC_STATEFUL) with subst(setSubChar=0x3f) did not match.\n");
+}
+#endif
+
+UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len)
+{
+
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ char junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const UChar *src;
+ char *end;
+ char *targ;
+ int32_t *offs;
+ int i;
+ int32_t realBufferSize;
+ char *realBufferEnd;
+ const UChar *realSourceEnd;
+ const UChar *sourceLimit;
+ UBool checkOffsets = TRUE;
+ UBool doFlush;
+ char junk[9999];
+ char offset_str[9999];
+ char *p;
+ UConverterFromUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = (char)0xF0;
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = 0xFF;
+ setNuConvTestName(codepage, "FROM");
+
+ log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize,
+ gOutBufferSize);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+
+ /*----setting the callback routine----*/
+ ucnv_setFromUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*------------------------*/
+ /*setting the subChar*/
+ if(mySubChar != NULL){
+ ucnv_setSubstChars(conv, mySubChar, len, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ }
+ /*------------*/
+
+ src = source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = source + sourceLen;
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min(targ + gOutBufferSize, realBufferEnd);
+ sourceLimit = nct_min(src + gInBufferSize, realSourceEnd);
+
+ doFlush = (UBool)(sourceLimit == realSourceEnd);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE");
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_fromUnicode (conv,
+ (char **)&targ,
+ (const char *)end,
+ &src,
+ sourceLimit,
+ checkOffsets ? offs : NULL,
+ doFlush, /* flush if we're at the end of the input data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (sourceLimit < realSourceEnd)) );
+
+
+ if(status==U_INVALID_CHAR_FOUND || status == U_ILLEGAL_CHAR_FOUND){
+ UChar errChars[50]; /* should be sufficient */
+ int8_t errLen = 50;
+ UErrorCode err = U_ZERO_ERROR;
+ const UChar* limit= NULL;
+ const UChar* start= NULL;
+ ucnv_getInvalidUChars(conv,errChars, &errLen, &err);
+ if(U_FAILURE(err)){
+ log_err("ucnv_getInvalidUChars failed with error : %s\n",u_errorName(err));
+ }
+ /* src points to limit of invalid chars */
+ limit = src;
+ /* length of in invalid chars should be equal to returned length*/
+ start = src - errLen;
+ if(u_strncmp(errChars,start,errLen)!=0){
+ log_err("ucnv_getInvalidUChars did not return the correct invalid chars for encoding %s \n", ucnv_getName(conv,&err));
+ }
+ }
+ /* allow failure codes for the stop callback */
+ if(U_FAILURE(status) &&
+ (callback != UCNV_FROM_U_CALLBACK_STOP || (status != U_INVALID_CHAR_FOUND && status != U_ILLEGAL_CHAR_FOUND)))
+ {
+ log_err("Problem in fromUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-junkout);
+ if(VERBOSITY)
+ {
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printSeq(expect, expectLen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+
+ if(expectLen != targ-junkout)
+ {
+ log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout));
+ printSeqErr(expect, expectLen);
+ return FALSE;
+ }
+
+ if (checkOffsets && (expectOffsets != 0) )
+ {
+ log_verbose("comparing %d offsets..\n", targ-junkout);
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){
+ log_err("did not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("Got Output : ");
+ printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout));
+ log_err("Got Offsets: ");
+ for(p=junkout;p<targ;p++)
+ log_err("%d,", junokout[p-junkout]);
+ log_err("\n");
+ log_err("Expected Offsets: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ log_err("\n");
+ return FALSE;
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectLen))
+ {
+ log_verbose("String matches! %s\n", gNuConvTestName);
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_err("source: ");
+ printUSeqErr(source, sourceLen);
+ log_err("Got: ");
+ printSeqErr((const uint8_t *)junkout, expectLen);
+ log_err("Expected: ");
+ printSeqErr(expect, expectLen);
+ return FALSE;
+ }
+}
+
+UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ UChar junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const char *src;
+ const char *realSourceEnd;
+ const char *srcLimit;
+ UChar *targ;
+ UChar *end;
+ int32_t *offs;
+ int i;
+ UBool checkOffsets = TRUE;
+ char junk[9999];
+ char offset_str[9999];
+ UChar *p;
+ UConverterToUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+ int32_t realBufferSize;
+ UChar *realBufferEnd;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = 0xFFFE;
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = -1;
+
+ setNuConvTestName(codepage, "TO");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",gNuConvTestName);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+
+ src = (const char *)source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = src + sourcelen;
+ /*----setting the callback routine----*/
+ ucnv_setToUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*-------------------------------------*/
+ /*setting the subChar*/
+ if(mySubChar != NULL){
+ ucnv_setSubstChars(conv, mySubChar, len, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ }
+ /*------------*/
+
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min( targ + gOutBufferSize, realBufferEnd);
+ srcLimit = nct_min(realSourceEnd, src + gInBufferSize);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end);
+
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_toUnicode (conv,
+ &targ,
+ end,
+ (const char **)&src,
+ (const char *)srcLimit,
+ checkOffsets ? offs : NULL,
+ (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of the source data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */
+
+ if(status==U_INVALID_CHAR_FOUND || status == U_ILLEGAL_CHAR_FOUND){
+ char errChars[50]; /* should be sufficient */
+ int8_t errLen = 50;
+ UErrorCode err = U_ZERO_ERROR;
+ const char* limit= NULL;
+ const char* start= NULL;
+ ucnv_getInvalidChars(conv,errChars, &errLen, &err);
+ if(U_FAILURE(err)){
+ log_err("ucnv_getInvalidChars failed with error : %s\n",u_errorName(err));
+ }
+ /* src points to limit of invalid chars */
+ limit = src;
+ /* length of in invalid chars should be equal to returned length*/
+ start = src - errLen;
+ if(uprv_strncmp(errChars,start,errLen)!=0){
+ log_err("ucnv_getInvalidChars did not return the correct invalid chars for encoding %s \n", ucnv_getName(conv,&err));
+ }
+ }
+ /* allow failure codes for the stop callback */
+ if(U_FAILURE(status) &&
+ (callback != UCNV_TO_U_CALLBACK_STOP || (status != U_INVALID_CHAR_FOUND && status != U_ILLEGAL_CHAR_FOUND && status != U_TRUNCATED_CHAR_FOUND)))
+ {
+ log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :",
+ sourcelen, targ-junkout);
+ if(VERBOSITY)
+ {
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printUSeq(expect, expectlen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2);
+
+ if (checkOffsets && (expectOffsets != 0))
+ {
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t)))
+ {
+ log_err("did not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("Got offsets: ");
+ for(p=junkout;p<targ;p++)
+ log_err(" %2d,", junokout[p-junkout]);
+ log_err("\n");
+ log_err("Expected offsets: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err(" %2d,", expectOffsets[i]);
+ log_err("\n");
+ log_err("Got output: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("0x%04x,", junkout[i]);
+ log_err("\n");
+ log_err("From source: ");
+ for(i=0; i<(src-(const char *)source); i++)
+ log_err(" 0x%02x,", (unsigned char)source[i]);
+ log_err("\n");
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectlen*2))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ log_err("Got: ");
+ printUSeqErr(junkout, expectlen);
+ log_err("Expected: ");
+ printUSeqErr(expect, expectlen);
+ log_err("\n");
+ return FALSE;
+ }
+}
+
+UBool testConvertFromUnicodeWithContext(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError)
+{
+
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ char junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const UChar *src;
+ char *end;
+ char *targ;
+ int32_t *offs;
+ int i;
+ int32_t realBufferSize;
+ char *realBufferEnd;
+ const UChar *realSourceEnd;
+ const UChar *sourceLimit;
+ UBool checkOffsets = TRUE;
+ UBool doFlush;
+ char junk[9999];
+ char offset_str[9999];
+ char *p;
+ UConverterFromUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = (char)0xF0;
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = 0xFF;
+ setNuConvTestName(codepage, "FROM");
+
+ log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize,
+ gOutBufferSize);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE; /* Because the err has already been logged. */
+ }
+
+ log_verbose("Converter opened..\n");
+
+ /*----setting the callback routine----*/
+ ucnv_setFromUCallBack (conv, callback, context, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*------------------------*/
+ /*setting the subChar*/
+ if(mySubChar != NULL){
+ ucnv_setSubstChars(conv, mySubChar, len, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting substitution chars! %s\n", myErrorName(status));
+ }
+ }
+ /*------------*/
+
+ src = source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = source + sourceLen;
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min(targ + gOutBufferSize, realBufferEnd);
+ sourceLimit = nct_min(src + gInBufferSize, realSourceEnd);
+
+ doFlush = (UBool)(sourceLimit == realSourceEnd);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE");
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_fromUnicode (conv,
+ (char **)&targ,
+ (const char *)end,
+ &src,
+ sourceLimit,
+ checkOffsets ? offs : NULL,
+ doFlush, /* flush if we're at the end of the input data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (sourceLimit < realSourceEnd)) );
+
+ /* allow failure codes for the stop callback */
+ if(U_FAILURE(status) && status != expectedError)
+ {
+ log_err("Problem in fromUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-junkout);
+ if(VERBOSITY)
+ {
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printSeq(expect, expectLen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+
+ if(expectLen != targ-junkout)
+ {
+ log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout));
+ printSeqErr(expect, expectLen);
+ return FALSE;
+ }
+
+ if (checkOffsets && (expectOffsets != 0) )
+ {
+ log_verbose("comparing %d offsets..\n", targ-junkout);
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){
+ log_err("did not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("Got Output : ");
+ printSeqErr((const uint8_t *)junkout, (int32_t)(targ-junkout));
+ log_err("Got Offsets: ");
+ for(p=junkout;p<targ;p++)
+ log_err("%d,", junokout[p-junkout]);
+ log_err("\n");
+ log_err("Expected Offsets: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ log_err("\n");
+ return FALSE;
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectLen))
+ {
+ log_verbose("String matches! %s\n", gNuConvTestName);
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_err("source: ");
+ printUSeqErr(source, sourceLen);
+ log_err("Got: ");
+ printSeqErr((const uint8_t *)junkout, expectLen);
+ log_err("Expected: ");
+ printSeqErr(expect, expectLen);
+ return FALSE;
+ }
+}
+UBool testConvertToUnicodeWithContext( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ UChar junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const char *src;
+ const char *realSourceEnd;
+ const char *srcLimit;
+ UChar *targ;
+ UChar *end;
+ int32_t *offs;
+ int i;
+ UBool checkOffsets = TRUE;
+ char junk[9999];
+ char offset_str[9999];
+ UChar *p;
+ UConverterToUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+ int32_t realBufferSize;
+ UChar *realBufferEnd;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = 0xFFFE;
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = -1;
+
+ setNuConvTestName(codepage, "TO");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",gNuConvTestName);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+
+ src = (const char *)source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = src + sourcelen;
+ /*----setting the callback routine----*/
+ ucnv_setToUCallBack (conv, callback, context, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status))
+ {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*-------------------------------------*/
+ /*setting the subChar*/
+ if(mySubChar != NULL){
+ ucnv_setSubstChars(conv, mySubChar, len, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ }
+ /*------------*/
+
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min( targ + gOutBufferSize, realBufferEnd);
+ srcLimit = nct_min(realSourceEnd, src + gInBufferSize);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end);
+
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_toUnicode (conv,
+ &targ,
+ end,
+ (const char **)&src,
+ (const char *)srcLimit,
+ checkOffsets ? offs : NULL,
+ (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of the source data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */
+
+ /* allow failure codes for the stop callback */
+ if(U_FAILURE(status) && status!=expectedError)
+ {
+ log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :",
+ sourcelen, targ-junkout);
+ if(VERBOSITY)
+ {
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printUSeq(expect, expectlen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2);
+
+ if (checkOffsets && (expectOffsets != 0))
+ {
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t)))
+ {
+ log_err("did not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("Got offsets: ");
+ for(p=junkout;p<targ;p++)
+ log_err(" %2d,", junokout[p-junkout]);
+ log_err("\n");
+ log_err("Expected offsets: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err(" %2d,", expectOffsets[i]);
+ log_err("\n");
+ log_err("Got output: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("0x%04x,", junkout[i]);
+ log_err("\n");
+ log_err("From source: ");
+ for(i=0; i<(src-(const char *)source); i++)
+ log_err(" 0x%02x,", (unsigned char)source[i]);
+ log_err("\n");
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectlen*2))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ log_err("Got: ");
+ printUSeqErr(junkout, expectlen);
+ log_err("Expected: ");
+ printUSeqErr(expect, expectlen);
+ log_err("\n");
+ return FALSE;
+ }
+}
+
+static void TestCallBackFailure(void) {
+ UErrorCode status = U_USELESS_COLLATOR_ERROR;
+ ucnv_cbFromUWriteBytes(NULL, NULL, -1, -1, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Error: ucnv_cbFromUWriteBytes did not react correctly to a bad UErrorCode\n");
+ }
+ ucnv_cbFromUWriteUChars(NULL, NULL, NULL, -1, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Error: ucnv_cbFromUWriteUChars did not react correctly to a bad UErrorCode\n");
+ }
+ ucnv_cbFromUWriteSub(NULL, -1, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Error: ucnv_cbFromUWriteSub did not react correctly to a bad UErrorCode\n");
+ }
+ ucnv_cbToUWriteUChars(NULL, NULL, -1, -1, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Error: ucnv_cbToUWriteUChars did not react correctly to a bad UErrorCode\n");
+ }
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h
new file mode 100644
index 00000000000..ebce4ae8d2b
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nccbtst.h
@@ -0,0 +1,69 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File NCCBTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda creation
+*********************************************************************************
+*/
+#ifndef _NCCBTST
+#define _NCCBTST
+/* C API TEST FOR CALL BACK ROUTINES OF CODESET CONVERSION COMPONENT */
+#include "cintltst.h"
+#include "unicode/utypes.h"
+
+
+static void TestSkipCallBack(void);
+static void TestStopCallBack(void);
+static void TestSubCallBack(void);
+static void TestSubWithValueCallBack(void);
+static void TestLegalAndOtherCallBack(void);
+static void TestSingleByteCallBack(void);
+
+
+static void TestSkip(int32_t inputsize, int32_t outputsize);
+
+static void TestStop(int32_t inputsize, int32_t outputsize);
+
+static void TestSub(int32_t inputsize, int32_t outputsize);
+
+static void TestSubWithValue(int32_t inputsize, int32_t outputsize);
+
+static void TestLegalAndOthers(int32_t inputsize, int32_t outputsize);
+static void TestSingleByte(int32_t inputsize, int32_t outputsize);
+static void TestEBCDIC_STATEFUL_Sub(int32_t inputsize, int32_t outputsize);
+
+/* Following will return FALSE *only* on a mismach. They will return TRUE on any other error OR success, because
+ * the error would have been emitted to log_err separately. */
+
+UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback, const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len);
+
+
+UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len);
+
+UBool testConvertFromUnicodeWithContext(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError);
+
+UBool testConvertToUnicodeWithContext( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets,
+ const char *mySubChar, int8_t len, const void* context, UErrorCode expectedError);
+
+static void printSeq(const uint8_t* a, int len);
+static void printUSeq(const UChar* a, int len);
+static void printSeqErr(const uint8_t* a, int len);
+static void printUSeqErr(const UChar* a, int len);
+static void setNuConvTestName(const char *codepage, const char *direction);
+
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c
new file mode 100644
index 00000000000..2158bfd41c3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.c
@@ -0,0 +1,755 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ***************************************************************************/
+/*****************************************************************************
+*
+* File NCNVCBTS
+*
+* Modification History:
+* Name Date Description
+* Madhu Katragadda 06/23/2000 Tests for Conveter FallBack API and Functionality
+******************************************************************************
+*/
+#include <stdio.h>
+#include "unicode/uloc.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_err.h"
+#include "cintltst.h"
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "ncnvfbts.h"
+#include "cmemory.h"
+#include "cstring.h"
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+#define NEW_MAX_BUFFER 999
+
+
+#define nct_min(x,y) ((x<y) ? x : y)
+
+static int32_t gInBufferSize = 0;
+static int32_t gOutBufferSize = 0;
+static char gNuConvTestName[1024];
+
+static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err)
+{
+ if(cnv && cnv[0] == '@') {
+ return ucnv_openPackage("testdata", cnv+1, err);
+ } else {
+ return ucnv_open(cnv, err);
+ }
+}
+
+
+static void printSeq(const unsigned char* a, int len)
+{
+ int i=0;
+ log_verbose("{");
+ while (i<len)
+ log_verbose("0x%02x ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printUSeq(const UChar* a, int len)
+{
+ int i=0;
+ log_verbose("{U+");
+ while (i<len)
+ log_verbose("0x%04x ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printSeqErr(const unsigned char* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{");
+ while (i<len)
+ fprintf(stderr, "0x%02x ", a[i++]);
+ fprintf(stderr, "}\n");
+}
+
+static void printUSeqErr(const UChar* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{U+");
+ while (i<len)
+ fprintf(stderr, "0x%04x ", a[i++]);
+ fprintf(stderr,"}\n");
+}
+
+static void TestConverterFallBack(void)
+{
+ TestConvertFallBackWithBufferSizes(10,10);
+ TestConvertFallBackWithBufferSizes(2,3);
+ TestConvertFallBackWithBufferSizes(3,2);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,1);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,2);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,3);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,4);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,5);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,6);
+ TestConvertFallBackWithBufferSizes(1,NEW_MAX_BUFFER);
+ TestConvertFallBackWithBufferSizes(2,NEW_MAX_BUFFER);
+ TestConvertFallBackWithBufferSizes(3,NEW_MAX_BUFFER);
+ TestConvertFallBackWithBufferSizes(4,NEW_MAX_BUFFER);
+ TestConvertFallBackWithBufferSizes(5,NEW_MAX_BUFFER);
+ TestConvertFallBackWithBufferSizes(NEW_MAX_BUFFER,NEW_MAX_BUFFER);
+
+}
+
+
+void addTestConverterFallBack(TestNode** root);
+
+void addTestConverterFallBack(TestNode** root)
+{
+ addTest(root, &TestConverterFallBack, "tsconv/ncnvfbts/TestConverterFallBack");
+
+}
+
+
+/* Note that this test already makes use of statics, so it's not really
+ multithread safe.
+ This convenience function lets us make the error messages actually useful.
+*/
+
+static void setNuConvTestName(const char *codepage, const char *direction)
+{
+ sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]",
+ codepage,
+ direction,
+ (int)gInBufferSize,
+ (int)gOutBufferSize);
+}
+
+
+static UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UBool fallback, const int32_t *expectOffsets)
+{
+
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ char junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const UChar *src;
+ char *end;
+ char *targ;
+ int32_t *offs;
+ int i;
+ int32_t realBufferSize;
+ char *realBufferEnd;
+ const UChar *realSourceEnd;
+ const UChar *sourceLimit;
+ UBool checkOffsets = TRUE;
+ UBool doFlush;
+ UBool action=FALSE;
+ char *p;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = (char)0xF0;
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = 0xFF;
+ setNuConvTestName(codepage, "FROM");
+
+ log_verbose("\nTesting========= %s FROM \n inputbuffer= %d outputbuffer= %d\n", codepage, gInBufferSize,
+ gOutBufferSize);
+
+ conv = my_ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+ /*----setting the callback routine----*/
+ ucnv_setFallback (conv, fallback);
+ action = ucnv_usesFallback(conv);
+ if(action != fallback){
+ log_err("FAIL: Error is setting fallback. Errocode=%s\n", myErrorName(status));
+ }
+ /*------------------------*/
+ src = source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = source + sourceLen;
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min(targ + gOutBufferSize, realBufferEnd);
+ sourceLimit = nct_min(src + gInBufferSize, realSourceEnd);
+
+ doFlush = (UBool)(sourceLimit == realSourceEnd);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE");
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_fromUnicode (conv,
+ (char **)&targ,
+ (const char *)end,
+ &src,
+ sourceLimit,
+ checkOffsets ? offs : NULL,
+ doFlush, /* flush if we're at the end of the input data */
+ &status);
+
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (sourceLimit < realSourceEnd) );
+
+ if(U_FAILURE(status))
+ {
+ log_err("Problem doing toUnicode, errcode %d %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-junkout);
+ if(VERBOSITY)
+ {
+ char junk[9999];
+ char offset_str[9999];
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + uprv_strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printSeq((const unsigned char*)expect, expectLen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+
+ if(expectLen != targ-junkout)
+ {
+ log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ printSeqErr((const unsigned char*)expect, expectLen);
+ return FALSE;
+ }
+
+ if (checkOffsets && (expectOffsets != 0) )
+ {
+ log_verbose("\ncomparing %d offsets..\n", targ-junkout);
+ if(uprv_memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){
+ log_err("\ndid not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("Got : ");
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ for(p=junkout;p<targ;p++)
+ log_err("%d, ", junokout[p-junkout]);
+ log_err("\nExpected: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ }
+ }
+
+ log_verbose("\n\ncomparing..\n");
+ if(!memcmp(junkout, expect, expectLen))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ printSeqErr((const unsigned char*)junkout, expectLen);
+ printSeqErr((const unsigned char*)expect, expectLen);
+ return FALSE;
+ }
+}
+
+static UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UBool fallback, const int32_t *expectOffsets)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ UChar junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const char *src;
+ const char *realSourceEnd;
+ const char *srcLimit;
+ UChar *targ;
+ UChar *end;
+ int32_t *offs;
+ int i;
+ UBool checkOffsets = TRUE;
+ char junk[9999];
+ char offset_str[9999];
+ UChar *p;
+ UBool action;
+
+ int32_t realBufferSize;
+ UChar *realBufferEnd;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = 0xFFFE;
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = -1;
+
+ setNuConvTestName(codepage, "TO");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = my_ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",gNuConvTestName);
+ return TRUE; /* because it has been logged */
+ }
+
+ log_verbose("Converter opened..\n");
+
+ src = (const char *)source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = src + sourcelen;
+ /*----setting the fallback routine----*/
+ ucnv_setFallback (conv, fallback);
+ action = ucnv_usesFallback(conv);
+ if(action != fallback){
+ log_err("FAIL: Error is setting fallback. Errocode=%s\n", myErrorName(status));
+ }
+ /*-------------------------------------*/
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min( targ + gOutBufferSize, realBufferEnd);
+ srcLimit = nct_min(realSourceEnd, src + gInBufferSize);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end);
+
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_toUnicode (conv,
+ &targ,
+ end,
+ (const char **)&src,
+ (const char *)srcLimit,
+ checkOffsets ? offs : NULL,
+ (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of hte source data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (srcLimit < realSourceEnd) ); /* while we just need another buffer */
+
+
+ if(U_FAILURE(status))
+ {
+ log_err("Problem doing toUnicode, errcode %s %s\n", myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :",
+ sourcelen, targ-junkout);
+ if(VERBOSITY)
+ {
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+
+ for(p = junkout;p<targ;p++)
+ {
+ sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*p);
+ sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[p-junkout]);
+ }
+
+ log_verbose(junk);
+ printUSeq(expect, expectlen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2);
+
+ if (checkOffsets && (expectOffsets != 0))
+ {
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t)))
+ {
+ log_err("\n\ndid not get the expected offsets while %s \n", gNuConvTestName);
+ log_err("\nGot : ");
+ for(p=junkout;p<targ;p++)
+ log_err("%d, ", junokout[p-junkout]);
+ log_err("\nExpected: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ log_err("");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("0x%04X,", junkout[i]);
+ log_err("");
+ for(i=0; i<(src-(const char *)source); i++)
+ log_err("0x%04X,", (unsigned char)source[i]);
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectlen*2))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ printUSeqErr(junkout, expectlen);
+ printf("\n");
+ printUSeqErr(expect, expectlen);
+ return FALSE;
+ }
+}
+
+
+
+static void TestConvertFallBackWithBufferSizes(int32_t outsize, int32_t insize )
+{
+
+ static const UChar SBCSText[] =
+ { 0x0021, 0xFF01, 0x0022, 0xFF02, 0x0023, 0xFF03, 0x003A, 0xFF1A, 0x003B, 0xFF1B, 0x003C, 0xFF1C };
+ /* 21, ?, 22, ?, 23, ?, 3a, ?, 3b, ?, 3c, ? SBCS*/
+ static const uint8_t expectedNative[] =
+ { 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c};
+ static const UChar retrievedSBCSText[]=
+ { 0x0021, 0x0021, 0x0022, 0x0022, 0x0023, 0x0023, 0x003A, 0x003A, 0x003B, 0x003B, 0x003C, 0x003C };
+ static const int32_t toNativeOffs [] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b};
+ static const int32_t fromNativeoffs [] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+
+
+ /* 1363 isn't DBCS, but it has the DBCS section */
+ static const UChar DBCSText[] =
+ { 0x00a1, 0x00ad, 0x2010, 0x00b7, 0x30fb};
+ static const uint8_t expectedIBM1363_DBCS[] =
+ { 0xa2, 0xae, 0xa1 ,0xa9, 0xa1, 0xa9,0xa1 ,0xa4, 0xa1, 0xa4};
+ static const UChar retrievedDBCSText[]=
+ { 0x00a1, 0x2010, 0x2010, 0x30fb, 0x30fb };
+ static const int32_t toIBM1363Offs_DBCS[] =
+ { 0x00, 0x00, 0x01,0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04};
+ static const int32_t fromIBM1363offs_DBCS[] =
+ { 0, 2, 4, 6, 8};
+
+
+ static const UChar MBCSText[] =
+ { 0x0001, 0x263a, 0x2013, 0x2014, 0x263b, 0x0002};
+ static const uint8_t expectedIBM950[] =
+ { 0x01, 0x01, 0xa1, 0x56, 0xa1, 0x56, 0x02, 0x02};
+ static const UChar retrievedMBCSText[]=
+ { 0x0001, 0x0001, 0x2014, 0x2014, 0x0002, 0x0002};
+ static const int32_t toIBM950Offs [] =
+ { 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05};
+ static const int32_t fromIBM950offs [] =
+ { 0, 1, 2, 4, 6, 7};
+
+ static const UChar MBCSText1363[] =
+ { 0x0005,
+ 0xffe8,
+ 0x0007,
+ 0x2022,
+ 0x005c,
+ 0x00b7,
+ 0x3016,
+ 0x30fb,
+ 0x9a36};
+ static const uint8_t expectedIBM1363[] =
+ { 0x05,
+ 0x05,
+ 0x07,
+ 0x07,
+ 0x7f,
+ 0xa1, 0xa4,
+ 0xa1, 0xe0,
+ 0xa1, 0xa4,
+ 0xf5, 0xe2};
+ static const UChar retrievedMBCSText1363[]=
+ { 0x0005, 0x0005, 0x0007, 0x0007, 0x001a, 0x30fb, 0x25a1, 0x30fb, 0x9a36};
+ static const int32_t toIBM1363Offs [] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08};
+ static const int32_t fromIBM1363offs [] =
+ { 0, 1, 2, 3, 4, 5, 7, 9, 11};
+
+
+
+ static const char* nativeCodePage[]={
+ /*NLCS Mapping*/
+ "ibm-437",
+ "ibm-850",
+ "ibm-878",
+ "ibm-923",
+ "ibm-1051",
+ "ibm-1089",
+ "ibm-1250",
+ "ibm-1251",
+ "ibm-1253",
+ "ibm-1254",
+ "ibm-1255",
+ "ibm-1256",
+ "ibm-1257",
+ "ibm-1258",
+ "ibm-1276"
+ };
+
+ int32_t i=0;
+ gInBufferSize = insize;
+ gOutBufferSize = outsize;
+
+ for(i=0; i<sizeof(nativeCodePage)/sizeof(nativeCodePage[0]); i++){
+ log_verbose("Testing %s\n", nativeCodePage[i]);
+ if(!testConvertFromUnicode(SBCSText, sizeof(SBCSText)/sizeof(SBCSText[0]),
+ expectedNative, sizeof(expectedNative), nativeCodePage[i], TRUE, toNativeOffs ))
+ log_err("u-> %s(SBCS) with FallBack did not match.\n", nativeCodePage[i]);
+
+ if(!testConvertToUnicode(expectedNative, sizeof(expectedNative),
+ retrievedSBCSText, sizeof(retrievedSBCSText)/sizeof(retrievedSBCSText[0]), nativeCodePage[i], TRUE, fromNativeoffs ))
+ log_err("%s->u(SBCS) with Fallback did not match.\n", nativeCodePage[i]);
+ }
+
+ /*DBCS*/
+ if(!testConvertFromUnicode(DBCSText, sizeof(DBCSText)/sizeof(DBCSText[0]),
+ expectedIBM1363_DBCS, sizeof(expectedIBM1363_DBCS), "ibm-1363", TRUE, toIBM1363Offs_DBCS ))
+ log_err("u-> ibm-1363(DBCS portion) with FallBack did not match.\n");
+
+ if(!testConvertToUnicode(expectedIBM1363_DBCS, sizeof(expectedIBM1363_DBCS),
+ retrievedDBCSText, sizeof(retrievedDBCSText)/sizeof(retrievedDBCSText[0]),"ibm-1363", TRUE, fromIBM1363offs_DBCS ))
+ log_err("ibm-1363->u(DBCS portion) with Fallback did not match.\n");
+
+
+ /*MBCS*/
+ if(!testConvertFromUnicode(MBCSText, sizeof(MBCSText)/sizeof(MBCSText[0]),
+ expectedIBM950, sizeof(expectedIBM950), "ibm-950", TRUE, toIBM950Offs ))
+ log_err("u-> ibm-950(MBCS) with FallBack did not match.\n");
+
+ if(!testConvertToUnicode(expectedIBM950, sizeof(expectedIBM950),
+ retrievedMBCSText, sizeof(retrievedMBCSText)/sizeof(retrievedMBCSText[0]),"ibm-950", TRUE, fromIBM950offs ))
+ log_err("ibm-950->u(MBCS) with Fallback did not match.\n");
+
+ /*commented untill data table is available*/
+ log_verbose("toUnicode fallback with fallback data for MBCS\n");
+ {
+ const uint8_t IBM950input[] = {
+ 0xf4, 0x87, 0xa4, 0x4a, 0xf4, 0x88, 0xa4, 0x4b,
+ 0xf9, 0x92, 0xdc, 0xb0, };
+ UChar expectedUnicodeText[]= { 0x5165, 0x5165, 0x516b, 0x516b, 0x9ef9, 0x9ef9};
+ int32_t fromIBM950inputOffs [] = { 0, 2, 4, 6, 8, 10};
+ /* for testing reverse fallback behavior */
+ UChar expectedFallbackFalse[]= { 0x5165, 0x5165, 0x516b, 0x516b, 0x9ef9, 0x9ef9};
+
+ if(!testConvertToUnicode(IBM950input, sizeof(IBM950input),
+ expectedUnicodeText, sizeof(expectedUnicodeText)/sizeof(expectedUnicodeText[0]),"ibm-950", TRUE, fromIBM950inputOffs ))
+ log_err("ibm-950->u(MBCS) with Fallback did not match.\n");
+ if(!testConvertToUnicode(IBM950input, sizeof(IBM950input),
+ expectedFallbackFalse, sizeof(expectedFallbackFalse)/sizeof(expectedFallbackFalse[0]),"ibm-950", FALSE, fromIBM950inputOffs ))
+ log_err("ibm-950->u(MBCS) with Fallback did not match.\n");
+
+ }
+ log_verbose("toUnicode fallback with fallback data for euc-tw\n");
+ {
+ const uint8_t euc_tw_input[] = {
+ 0xA7, 0xCC, 0x8E, 0xA2, 0xA1, 0xAB,
+ 0xA8, 0xC7, 0xC8, 0xDE,
+ 0xA8, 0xCD, 0x8E, 0xA2, 0xA2, 0xEA,};
+ UChar expectedUnicodeText[]= { 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278};
+ int32_t from_euc_tw_offs [] = { 0, 2, 6, 8, 10, 12};
+ /* for testing reverse fallback behavior */
+ UChar expectedFallbackFalse[]= { 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278};
+
+ if(!testConvertToUnicode(euc_tw_input, sizeof(euc_tw_input),
+ expectedUnicodeText, sizeof(expectedUnicodeText)/sizeof(expectedUnicodeText[0]),"euc-tw", TRUE, from_euc_tw_offs ))
+ log_err("from euc-tw->u with Fallback did not match.\n");
+
+ if(!testConvertToUnicode(euc_tw_input, sizeof(euc_tw_input),
+ expectedFallbackFalse, sizeof(expectedFallbackFalse)/sizeof(expectedFallbackFalse[0]),"euc-tw", FALSE, from_euc_tw_offs ))
+ log_err("from euc-tw->u with Fallback false did not match.\n");
+
+
+ }
+ log_verbose("fromUnicode to euc-tw with fallback data euc-tw\n");
+ {
+ UChar inputText[]= { 0x0001, 0x008e, 0x203e, 0x2223, 0xff5c, 0x5296,
+ 0x5C6E, 0x5C6E, 0x81FC, 0x81FC, 0x8278, 0x8278, 0xEDEC};
+ const uint8_t expected_euc_tw[] = {
+ 0x01, 0x1a, 0xa2, 0xa3,
+ 0xa2, 0xde, 0xa2, 0xde,
+ 0x8e, 0xa2, 0xe5, 0xb9,
+ 0x8e, 0xa2, 0xa1, 0xab, 0x8e, 0xa2, 0xa1, 0xab,
+ 0xc8, 0xde, 0xc8, 0xde,
+ 0x8e, 0xa2, 0xa2, 0xea, 0x8e, 0xa2, 0xa2, 0xea,
+ 0x8e, 0xac, 0xc6, 0xf7};
+ int32_t to_euc_tw_offs [] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6,
+ 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12};
+
+ if(!testConvertFromUnicode(inputText, sizeof(inputText)/sizeof(inputText[0]),
+ expected_euc_tw, sizeof(expected_euc_tw), "euc-tw", TRUE, to_euc_tw_offs ))
+ log_err("u-> euc-tw with FallBack did not match.\n");
+
+ }
+
+ /*MBCS 1363*/
+ if(!testConvertFromUnicode(MBCSText1363, sizeof(MBCSText1363)/sizeof(MBCSText1363[0]),
+ expectedIBM1363, sizeof(expectedIBM1363), "ibm-1363", TRUE, toIBM1363Offs ))
+ log_err("u-> ibm-1363(MBCS) with FallBack did not match.\n");
+
+ if(!testConvertToUnicode(expectedIBM1363, sizeof(expectedIBM1363),
+ retrievedMBCSText1363, sizeof(retrievedMBCSText1363)/sizeof(retrievedMBCSText1363[0]),"ibm-1363", TRUE, fromIBM1363offs ))
+ log_err("ibm-1363->u(MBCS) with Fallback did not match.\n");
+
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test1.ucm
+ which is test file for MBCS conversion with single-byte codepage data.*/
+ {
+
+ /* MBCS with single byte codepage data test1.ucm*/
+ const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, 0x0003};
+ const uint8_t expectedtest1[] = { 0x00, 0x05, 0xff, 0x07, 0x08, 0xff,};
+ int32_t totest1Offs[] = { 0, 1, 2, 3, 5, 7};
+
+ const uint8_t test1input[] = { 0x00, 0x05, 0x06, 0x07, 0x08, 0x09};
+ const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xfffd, 0xfffd, 0xfffe};
+ int32_t fromtest1Offs[] = { 0, 1, 2, 3, 3, 4,5};
+
+ /*from Unicode*/
+ if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest1, sizeof(expectedtest1), "@test1", TRUE, totest1Offs ))
+ log_err("u-> test1(MBCS conversion with single-byte) did not match.\n");
+
+ /*to Unicode*/
+ if(!testConvertToUnicode(test1input, sizeof(test1input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test1", TRUE, fromtest1Offs ))
+ log_err("test1(MBCS conversion with single-byte) -> u did not match.\n");
+
+ }
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test3.ucm
+ which is test file for MBCS conversion with three-byte codepage data.*/
+ {
+
+ /* MBCS with three byte codepage data test3.ucm*/
+ const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0xdbba, 0xdfcd, 0x000b, 0xd84d, 0xdc56, 0x000e, 0x0003, };
+ const uint8_t expectedtest3[] = { 0x00, 0x05, 0xff, 0x07, 0xff, 0x01, 0x02, 0x0b, 0x01, 0x02, 0x0a, 0xff, 0xff,};
+ int32_t totest3Offs[] = { 0, 1, 2, 3, 5, 7, 7, 7, 8, 8, 8, 10, 11};
+
+ const uint8_t test3input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a,
+ 0x01, 0x02, 0x0e, 0x01, 0x02, 0x0d, 0x03, 0x01, 0x02, 0x0f,};
+ const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56,
+ 0x000e, 0xd891, 0xdd67, 0xfffd, 0xfffd };
+ int32_t fromtest3Offs[] = { 0, 1, 2, 3, 6, 6, 7, 7, 10, 13, 13, 16, 17};
+
+ /*from Unicode*/
+ if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest3, sizeof(expectedtest3), "@test3", TRUE, totest3Offs ))
+ log_err("u-> test3(MBCS conversion with three-byte) did not match.\n");
+
+ /*to Unicode*/
+ if(!testConvertToUnicode(test3input, sizeof(test3input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test3", TRUE, fromtest3Offs ))
+ log_err("test3(MBCS conversion with three-byte) -> u did not match.\n");
+
+ }
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test4.ucm
+ which is test file for MBCS conversion with four-byte codepage data.*/
+ {
+
+ /* MBCS with three byte codepage data test4.ucm*/
+ const UChar unicodeInput[] =
+ { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xdbba, 0xdfcd,
+ 0xd84d, 0xdc56, 0x000e, 0xd891, 0xdd67, 0x000f};
+ const uint8_t expectedtest4[] =
+ { 0x00, 0x05, 0xff, 0x01, 0x02, 0x03, 0x0b, 0x07, 0xff,
+ 0x01, 0x02, 0x03, 0x0a, 0xff, 0xff, 0xff};
+ int32_t totest4Offs[] =
+ { 0, 1, 2, 3, 3, 3, 3, 4, 6, 8, 8, 8, 8, 10, 11, 13};
+
+ const uint8_t test4input[] =
+ { 0x00, 0x05, 0x06, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x08,
+ 0x01, 0x02, 0x03, 0x0a, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x02, 0x03, 0x0d, 0x03, 0x01, 0x02, 0x03, 0x0c,};
+ const UChar expectedUnicode[] =
+ { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xdbba, 0xdfcd,
+ 0xd84d, 0xdc56, 0x000e, 0xd891, 0xdd67, 0x1a, 0xfffd};
+ int32_t fromtest4Offs[] =
+ { 0, 1, 2, 3, 7, 7, 8, 8, 9, 9, 13, 17, 17, 21, 22,};
+
+ /*from Unicode*/
+ if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest4, sizeof(expectedtest4), "@test4", TRUE, totest4Offs ))
+ log_err("u-> test4(MBCS conversion with four-byte) did not match.\n");
+
+ /*to Unicode*/
+ if(!testConvertToUnicode(test4input, sizeof(test4input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test4", TRUE, fromtest4Offs ))
+ log_err("test4(MBCS conversion with four-byte) -> u did not match.\n");
+
+ }
+ /* Test for jitterbug 509 EBCDIC_STATEFUL Converters*/
+ {
+ const UChar unicodeInput[] = {0x00AF, 0x2013, 0x2223, 0x004C, 0x5F5D, 0xFF5E };
+ const uint8_t expectedtest1[] = {0x0E,0x42,0xA1, 0x44,0x4A, 0x42,0x4F, 0x0F,0xD3, 0x0E,0x65,0x60, 0x43,0xA1,0x0f };
+ int32_t totest1Offs[] = {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5 };
+ const uint8_t test1input[] = {0x0E,0x42,0xA1, 0x44,0x4A, 0x42,0x4F, 0x0F,0xD3, 0x0E,0x65,0x60, 0x43,0xA1 };
+ const UChar expectedUnicode[] = {0x203e, 0x2014, 0xff5c, 0x004c, 0x5f5e, 0x223c };
+ int32_t fromtest1Offs[] = {1, 3, 5, 8, 10, 12 };
+ /*from Unicode*/
+ if(!testConvertFromUnicode(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest1, sizeof(expectedtest1), "ibm-1371", TRUE, totest1Offs ))
+ log_err("u-> ibm-1371(MBCS conversion with single-byte) did not match.,\n");
+ /*to Unicode*/
+ if(!testConvertToUnicode(test1input, sizeof(test1input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "ibm-1371", TRUE, fromtest1Offs ))
+ log_err("ibm-1371(MBCS conversion with single-byte) -> u did not match.,\n");
+ }
+
+}
+#else
+void addTestConverterFallBack(TestNode** root)
+{
+ /* test nothing... */
+
+}
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h
new file mode 100644
index 00000000000..a47e141ccfc
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvfbts.h
@@ -0,0 +1,36 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File NCCBTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda creation
+*********************************************************************************
+*/
+#ifndef _NCNVFBTS
+#define _NCNVFBTS
+/* C API TEST FOR FALL BACK ROUTINES OF CODESET CONVERSION COMPONENT */
+#include "cintltst.h"
+#include "unicode/utypes.h"
+
+static void TestConverterFallBack(void);
+static void TestConvertFallBackWithBufferSizes(int32_t outsize, int32_t insize );
+static UBool testConvertFromUnicode(const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UBool fallback, const int32_t *expectOffsets);
+static UBool testConvertToUnicode( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UBool fallback, const int32_t *expectOffsets);
+
+
+static void printSeq(const unsigned char* a, int len);
+static void printUSeq(const UChar* a, int len);
+static void printSeqErr(const unsigned char* a, int len);
+static void printUSeqErr(const UChar* a, int len);
+static void setNuConvTestName(const char *codepage, const char *direction);
+
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c
new file mode 100644
index 00000000000..2f56c15f88d
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ncnvtst.c
@@ -0,0 +1,2055 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*****************************************************************************
+*
+* File CCONVTST.C
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda 7/7/2000 Converter Tests for extended code coverage
+******************************************************************************
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/uloc.h"
+#include "unicode/ucnv.h"
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "unicode/uset.h"
+#include "cintltst.h"
+
+#define MAX_LENGTH 999
+
+#define UNICODE_LIMIT 0x10FFFF
+#define SURROGATE_HIGH_START 0xD800
+#define SURROGATE_LOW_END 0xDFFF
+
+static int32_t gInBufferSize = 0;
+static int32_t gOutBufferSize = 0;
+static char gNuConvTestName[1024];
+
+#define nct_min(x,y) ((x<y) ? x : y)
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void printSeq(const unsigned char* a, int len);
+static void printSeqErr(const unsigned char* a, int len);
+static void printUSeq(const UChar* a, int len);
+static void printUSeqErr(const UChar* a, int len);
+static UBool convertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus);
+static UBool convertToU( const uint8_t *source, int sourceLen, const UChar *expect, int expectLen,
+ const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus);
+
+static UBool testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback, const int32_t *expectOffsets, UBool testReset);
+static UBool testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, UBool testReset);
+
+static void setNuConvTestName(const char *codepage, const char *direction)
+{
+ sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]",
+ codepage,
+ direction,
+ (int)gInBufferSize,
+ (int)gOutBufferSize);
+}
+
+
+static void TestSurrogateBehaviour(void);
+static void TestErrorBehaviour(void);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestToUnicodeErrorBehaviour(void);
+static void TestGetNextErrorBehaviour(void);
+#endif
+
+static void TestRegressionUTF8(void);
+static void TestRegressionUTF32(void);
+static void TestAvailableConverters(void);
+static void TestFlushInternalBuffer(void); /*for improved code coverage in ucnv_cnv.c*/
+static void TestResetBehaviour(void);
+static void TestTruncated(void);
+static void TestUnicodeSet(void);
+
+static void TestWithBufferSize(int32_t osize, int32_t isize);
+
+
+static void printSeq(const unsigned char* a, int len)
+{
+ int i=0;
+ log_verbose("\n{");
+ while (i<len)
+ log_verbose("0x%02X ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printUSeq(const UChar* a, int len)
+{
+ int i=0;
+ log_verbose("\n{");
+ while (i<len)
+ log_verbose("%0x04X ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printSeqErr(const unsigned char* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "\n{");
+ while (i<len) fprintf(stderr, "0x%02X ", a[i++]);
+ fprintf(stderr, "}\n");
+}
+
+static void printUSeqErr(const UChar* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "\n{");
+ while (i<len)
+ fprintf(stderr, "0x%04X ", a[i++]);
+ fprintf(stderr,"}\n");
+}
+
+void addExtraTests(TestNode** root);
+
+void addExtraTests(TestNode** root)
+{
+ addTest(root, &TestSurrogateBehaviour, "tsconv/ncnvtst/TestSurrogateBehaviour");
+ addTest(root, &TestErrorBehaviour, "tsconv/ncnvtst/TestErrorBehaviour");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestToUnicodeErrorBehaviour, "tsconv/ncnvtst/ToUnicodeErrorBehaviour");
+ addTest(root, &TestGetNextErrorBehaviour, "tsconv/ncnvtst/TestGetNextErrorBehaviour");
+#endif
+
+ addTest(root, &TestAvailableConverters, "tsconv/ncnvtst/TestAvailableConverters");
+ addTest(root, &TestFlushInternalBuffer, "tsconv/ncnvtst/TestFlushInternalBuffer");
+ addTest(root, &TestResetBehaviour, "tsconv/ncnvtst/TestResetBehaviour");
+ addTest(root, &TestRegressionUTF8, "tsconv/ncnvtst/TestRegressionUTF8");
+ addTest(root, &TestRegressionUTF32, "tsconv/ncnvtst/TestRegressionUTF32");
+ addTest(root, &TestTruncated, "tsconv/ncnvtst/TestTruncated");
+ addTest(root, &TestUnicodeSet, "tsconv/ncnvtst/TestUnicodeSet");
+}
+
+/*test surrogate behaviour*/
+static void TestSurrogateBehaviour(){
+ log_verbose("Testing for SBCS and LATIN_1\n");
+ {
+ UChar sampleText[] = {0x0031, 0xd801, 0xdc01, 0x0032};
+ const uint8_t expected[] = {0x31, 0x1a, 0x32};
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /*SBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-920", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-920 [UCNV_SBCS] not match.\n");
+#endif
+
+ /*LATIN_1*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "LATIN_1", 0, TRUE, U_ZERO_ERROR ))
+ log_err("u-> LATIN_1 not match.\n");
+
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing for DBCS and MBCS\n");
+ {
+ UChar sampleText[] = {0x00a1, 0xd801, 0xdc01, 0x00a4};
+ const uint8_t expected[] = {0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4};
+ int32_t offsets[] = {0x00, 0x00, 0x01, 0x01, 0x03, 0x03 };
+
+ /*DBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", offsets , TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n");
+ /*MBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", offsets, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n");
+ }
+
+ log_verbose("Testing for ISO-2022-jp\n");
+ {
+ UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ const uint8_t expected[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42,
+ 0x31,0x1A, 0x32};
+
+
+ int32_t offsets[] = {0,0,0,0,0,1,1,2,2,2,2,3,5 };
+
+ /*iso-2022-jp*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-jp", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-jp", offsets , TRUE, U_ZERO_ERROR))
+ log_err("u-> not match.\n");
+ }
+
+ log_verbose("Testing for ISO-2022-cn\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {
+ 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B,
+ 0x36, 0x21,
+ 0x0F, 0x31,
+ 0x1A,
+ 0x32
+ };
+
+
+
+ static const int32_t offsets[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 1, 1,
+ 2, 2,
+ 3,
+ 5, };
+
+ /*iso-2022-CN*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-cn", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-cn", offsets , TRUE, U_ZERO_ERROR))
+ log_err("u-> not match.\n");
+ }
+
+ log_verbose("Testing for ISO-2022-kr\n");
+ {
+ static const UChar sampleText[] = { 0x4e00,0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {0x1B, 0x24, 0x29, 0x43,
+ 0x0E, 0x6C, 0x69,
+ 0x0f, 0x1A,
+ 0x0e, 0x6F, 0x4B,
+ 0x0F, 0x31,
+ 0x1A,
+ 0x32 };
+
+ static const int32_t offsets[] = {-1, -1, -1, -1,
+ 0, 0, 0,
+ 1, 1,
+ 3, 3, 3,
+ 4, 4,
+ 5,
+ 7,
+ };
+
+ /*iso-2022-kr*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-kr", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-kr", offsets , TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n");
+ }
+
+ log_verbose("Testing for HZ\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {0x7E, 0x7B, 0x52, 0x3B,
+ 0x7E, 0x7D, 0x1A,
+ 0x7E, 0x7B, 0x36, 0x21,
+ 0x7E, 0x7D, 0x31,
+ 0x1A,
+ 0x32 };
+
+
+ static const int32_t offsets[] = {0,0,0,0,
+ 1,1,1,
+ 3,3,3,3,
+ 4,4,4,
+ 5,
+ 7,};
+
+ /*hz*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "HZ", 0 , TRUE, U_ZERO_ERROR))
+ log_err("u-> HZ not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "HZ", offsets , TRUE, U_ZERO_ERROR))
+ log_err("u-> HZ not match.\n");
+ }
+#endif
+
+ /*UTF-8*/
+ log_verbose("Testing for UTF8\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0x0701, 0x0031, 0xbfc1, 0xd801, 0xdc01, 0x0032};
+ static const int32_t offsets[]={0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
+ 0x04, 0x06 };
+ static const uint8_t expected[] = {0xe4, 0xb8, 0x80, 0xdc, 0x81, 0x31,
+ 0xeb, 0xbf, 0x81, 0xF0, 0x90, 0x90, 0x81, 0x32};
+
+
+ static const int32_t fromOffsets[] = { 0x0000, 0x0003, 0x0005, 0x0006, 0x0009, 0x0009, 0x000D };
+ /*UTF-8*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", offsets, TRUE, U_ZERO_ERROR ))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", 0, TRUE, U_ZERO_ERROR ))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", offsets, FALSE, U_ZERO_ERROR ))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", 0, FALSE, U_ZERO_ERROR ))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+
+ if(!convertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", 0, TRUE, U_ZERO_ERROR ))
+ log_err("UTF8 -> u did not match.\n");
+ if(!convertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", 0, FALSE, U_ZERO_ERROR ))
+ log_err("UTF8 -> u did not match.\n");
+ if(!convertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", fromOffsets, TRUE, U_ZERO_ERROR ))
+ log_err("UTF8 ->u did not match.\n");
+ if(!convertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", fromOffsets, FALSE, U_ZERO_ERROR ))
+ log_err("UTF8 -> u did not match.\n");
+
+ }
+}
+
+/*test various error behaviours*/
+static void TestErrorBehaviour(){
+ log_verbose("Testing for SBCS and LATIN_1\n");
+ {
+ static const UChar sampleText[] = { 0x0031, 0xd801};
+ static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032};
+ static const uint8_t expected0[] = { 0x31};
+ static const uint8_t expected[] = { 0x31, 0x1a};
+ static const uint8_t expected2[] = { 0x31, 0x1a, 0x32};
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /*SBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-920", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-920 [UCNV_SBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected0, sizeof(expected0), "ibm-920", 0, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-920 [UCNV_SBCS] \n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-920", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-920 [UCNV_SBCS] did not match\n");
+#endif
+
+ /*LATIN_1*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "LATIN_1", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> LATIN_1 is supposed to fail\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected0, sizeof(expected0), "LATIN_1", 0, FALSE, U_ZERO_ERROR))
+ log_err("u-> LATIN_1 is supposed to fail\n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "LATIN_1", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> LATIN_1 did not match\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing for DBCS and MBCS\n");
+ {
+ static const UChar sampleText[] = { 0x00a1, 0xd801};
+ static const uint8_t expected[] = { 0xa2, 0xae};
+ static const int32_t offsets[] = { 0x00, 0x00};
+ static const uint8_t expectedSUB[] = { 0xa2, 0xae, 0xa1, 0xe0};
+ static const int32_t offsetsSUB[] = { 0x00, 0x00, 0x01, 0x01};
+
+ static const UChar sampleText2[] = { 0x00a1, 0xd801, 0x00a4};
+ static const uint8_t expected2[] = { 0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4};
+ static const int32_t offsets2[] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02};
+
+ static const UChar sampleText3MBCS[] = { 0x0001, 0x00a4, 0xdc01};
+ static const uint8_t expected3MBCS[] = { 0x01, 0xa2, 0xb4, 0xa1, 0xe0};
+ static const int32_t offsets3MBCS[] = { 0x00, 0x01, 0x01, 0x02, 0x02};
+
+ static const UChar sampleText4MBCS[] = { 0x0061, 0xFFE4, 0xdc01};
+ static const uint8_t expected4MBCS[] = { 0x61, 0x8f, 0xa2, 0xc3, 0xf4, 0xfe};
+ static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01, 0x01, 0x02, 0x02 };
+
+ /*DBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "ibm-1363", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", 0, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n");
+
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "ibm-1363", offsetsSUB, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", offsets, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] is supposed to fail\n");
+
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-1363", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] did not match \n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-1363", offsets2, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] did not match \n");
+
+ /*MBCS*/
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "ibm-1363", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", 0, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-1363", 0, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-1363", 0, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "ibm-1363", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_DBCS] did not match\n");
+
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "ibm-1363", offsets3MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "ibm-1363", offsets3MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "euc-jp", offsets4MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u-> euc-jp [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "euc-jp", offsets4MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> euc-jp [UCNV_MBCS] \n");
+ }
+
+ /*iso-2022-jp*/
+ log_verbose("Testing for iso-2022-jp\n");
+ {
+ static const UChar sampleText[] = { 0x0031, 0xd801};
+ static const uint8_t expected[] = { 0x31};
+ static const uint8_t expectedSUB[] = { 0x31, 0x1a};
+ static const int32_t offsets[] = { 0x00, 1};
+
+ static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032};
+ static const uint8_t expected2[] = { 0x31,0x1A,0x32};
+ static const int32_t offsets2[] = { 0x00,0x01,0x02};
+
+ static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01};
+ static const uint8_t expected4MBCS[] = { 0x61, 0x1b, 0x24, 0x42, 0x30, 0x6c,0x1b,0x28,0x42,0x1a};
+ static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01 ,0x01, 0x01, 0x01,0x02,0x02,0x02,0x02 };
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "iso-2022-jp", offsets, TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-jp [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-jp", offsets, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-jp", offsets2, TRUE, U_ZERO_ERROR))
+ log_err("u->iso-2022-jp[UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-jp", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-jp [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-jp", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-jp [UCNV_DBCS] did not match\n");
+
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "iso-2022-jp", offsets4MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-jp [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "iso-2022-jp", offsets4MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-jp [UCNV_MBCS] \n");
+ }
+
+ /*iso-2022-cn*/
+ log_verbose("Testing for iso-2022-cn\n");
+ {
+ static const UChar sampleText[] = { 0x0031, 0xd801};
+ static const uint8_t expected[] = { 0x31};
+ static const uint8_t expectedSUB[] = { 0x31, 0x1A};
+ static const int32_t offsets[] = { 0x00, 1};
+
+ static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032};
+ static const uint8_t expected2[] = { 0x31, 0x1A,0x32};
+ static const int32_t offsets2[] = { 0x00, 0x01,0x02};
+
+ static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01};
+ static const uint8_t expected3MBCS[] = {0x51, 0x50, 0x1A};
+ static const int32_t offsets3MBCS[] = { 0x00, 0x01, 0x02 };
+
+ static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01};
+ static const uint8_t expected4MBCS[] = { 0x61, 0x1b, 0x24, 0x29, 0x41, 0x0e, 0x52, 0x3b, 0x0f, 0x1a };
+ static const int32_t offsets4MBCS[] = { 0x00, 0x01, 0x01 ,0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02 };
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "iso-2022-cn", offsets, TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-cn", offsets, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-cn", offsets2, TRUE, U_ZERO_ERROR))
+ log_err("u->iso-2022-cn[UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-cn", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-cn", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn [UCNV_DBCS] did not match\n");
+
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "iso-2022-cn", offsets3MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u->iso-2022-cn [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "iso-2022-cn", offsets3MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn[UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "iso-2022-cn", offsets4MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "iso-2022-cn", offsets4MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-cn [UCNV_MBCS] \n");
+ }
+
+ /*iso-2022-kr*/
+ log_verbose("Testing for iso-2022-kr\n");
+ {
+ static const UChar sampleText[] = { 0x0031, 0xd801};
+ static const uint8_t expected[] = { 0x1b, 0x24, 0x29, 0x43, 0x31};
+ static const uint8_t expectedSUB[] = { 0x1b, 0x24, 0x29, 0x43, 0x31, 0x1A};
+ static const int32_t offsets[] = { -1, -1, -1, -1, 0x00, 1};
+
+ static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032};
+ static const uint8_t expected2[] = { 0x1b, 0x24, 0x29, 0x43, 0x31, 0x1A, 0x32};
+ static const int32_t offsets2[] = { -1, -1, -1, -1, 0x00, 0x01, 0x02};
+
+ static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01};
+ static const uint8_t expected3MBCS[] = { 0x1b, 0x24, 0x29, 0x43, 0x51, 0x50, 0x1A };
+ static const int32_t offsets3MBCS[] = { -1, -1, -1, -1, 0x00, 0x01, 0x02, 0x02 };
+
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "iso-2022-kr", offsets, TRUE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-kr", offsets, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-kr", offsets2, TRUE, U_ZERO_ERROR))
+ log_err("u->iso-2022-kr[UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-kr", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "iso-2022-kr", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] did not match\n");
+
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "iso-2022-kr", offsets3MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u->iso-2022-kr [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "iso-2022-kr", offsets3MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> iso-2022-kr[UCNV_MBCS] \n");
+ }
+
+ /*HZ*/
+ log_verbose("Testing for HZ\n");
+ {
+ static const UChar sampleText[] = { 0x0031, 0xd801};
+ static const uint8_t expected[] = { 0x7e, 0x7d, 0x31};
+ static const uint8_t expectedSUB[] = { 0x7e, 0x7d, 0x31, 0x1A};
+ static const int32_t offsets[] = { 0x00, 0x00, 0x00, 1};
+
+ static const UChar sampleText2[] = { 0x0031, 0xd801, 0x0032};
+ static const uint8_t expected2[] = { 0x7e, 0x7d, 0x31, 0x1A, 0x32 };
+ static const int32_t offsets2[] = { 0x00, 0x00, 0x00, 0x01, 0x02 };
+
+ static const UChar sampleText3MBCS[] = { 0x0051, 0x0050, 0xdc01};
+ static const uint8_t expected3MBCS[] = { 0x7e, 0x7d, 0x51, 0x50, 0x1A };
+ static const int32_t offsets3MBCS[] = { 0x00, 0x00, 0x00, 0x01, 0x02};
+
+ static const UChar sampleText4MBCS[] = { 0x0061, 0x4e00, 0xdc01};
+ static const uint8_t expected4MBCS[] = { 0x7e, 0x7d, 0x61, 0x7e, 0x7b, 0x52, 0x3b, 0x7e, 0x7d, 0x1a };
+ static const int32_t offsets4MBCS[] = { 0x00, 0x00, 0x00, 0x01, 0x01, 0x01 ,0x01, 0x02, 0x02, 0x02 };
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedSUB, sizeof(expectedSUB), "HZ", offsets, TRUE, U_ZERO_ERROR))
+ log_err("u-> HZ [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "HZ", offsets, FALSE, U_ZERO_ERROR))
+ log_err("u-> ibm-1363 [UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "HZ", offsets2, TRUE, U_ZERO_ERROR))
+ log_err("u->HZ[UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "HZ", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> HZ [UCNV_DBCS] did not match\n");
+ if(!convertFromU(sampleText2, sizeof(sampleText2)/sizeof(sampleText2[0]),
+ expected2, sizeof(expected2), "HZ", offsets2, FALSE, U_ZERO_ERROR))
+ log_err("u-> HZ [UCNV_DBCS] did not match\n");
+
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "HZ", offsets3MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u->HZ [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText3MBCS, sizeof(sampleText3MBCS)/sizeof(sampleText3MBCS[0]),
+ expected3MBCS, sizeof(expected3MBCS), "HZ", offsets3MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> HZ[UCNV_MBCS] \n");
+
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "HZ", offsets4MBCS, TRUE, U_ZERO_ERROR))
+ log_err("u-> HZ [UCNV_MBCS] \n");
+ if(!convertFromU(sampleText4MBCS, sizeof(sampleText4MBCS)/sizeof(sampleText4MBCS[0]),
+ expected4MBCS, sizeof(expected4MBCS), "HZ", offsets4MBCS, FALSE, U_ZERO_ERROR))
+ log_err("u-> HZ [UCNV_MBCS] \n");
+ }
+#endif
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+/*test different convertToUnicode error behaviours*/
+static void TestToUnicodeErrorBehaviour()
+{
+ log_verbose("Testing error conditions for DBCS\n");
+ {
+ uint8_t sampleText[] = { 0xa2, 0xae, 0x03, 0x04};
+ const UChar expected[] = { 0x00a1 };
+
+ if(!convertToU(sampleText, sizeof(sampleText),
+ expected, sizeof(expected)/sizeof(expected[0]), "ibm-1363", 0, TRUE, U_ZERO_ERROR ))
+ log_err("DBCS (ibm-1363)->Unicode did not match.\n");
+ if(!convertToU(sampleText, sizeof(sampleText),
+ expected, sizeof(expected)/sizeof(expected[0]), "ibm-1363", 0, FALSE, U_ZERO_ERROR ))
+ log_err("DBCS (ibm-1363)->Unicode with flush = false did not match.\n");
+ }
+ log_verbose("Testing error conditions for SBCS\n");
+ {
+ uint8_t sampleText[] = { 0xa2, 0xFF};
+ const UChar expected[] = { 0x00c2 };
+
+ /* uint8_t sampleText2[] = { 0xa2, 0x70 };
+ const UChar expected2[] = { 0x0073 };*/
+
+ if(!convertToU(sampleText, sizeof(sampleText),
+ expected, sizeof(expected)/sizeof(expected[0]), "ibm-1051", 0, TRUE, U_ZERO_ERROR ))
+ log_err("SBCS (ibm-1051)->Unicode did not match.\n");
+ if(!convertToU(sampleText, sizeof(sampleText),
+ expected, sizeof(expected)/sizeof(expected[0]), "ibm-1051", 0, FALSE, U_ZERO_ERROR ))
+ log_err("SBCS (ibm-1051)->Unicode with flush = false did not match.\n");
+
+ }
+}
+
+static void TestGetNextErrorBehaviour(){
+ /*Test for unassigned character*/
+#define INPUT_SIZE 1
+ static const char input1[INPUT_SIZE]={ 0x70 };
+ const char* source=(const char*)input1;
+ UErrorCode err=U_ZERO_ERROR;
+ UChar32 c=0;
+ UConverter *cnv=ucnv_open("ibm-424", &err);
+ if(U_FAILURE(err)) {
+ log_data_err("Unable to open a SBCS(ibm-424) converter: %s\n", u_errorName(err));
+ return;
+ }
+ c=ucnv_getNextUChar(cnv, &source, source + INPUT_SIZE, &err);
+ if(err != U_INVALID_CHAR_FOUND && c!=0xfffd){
+ log_err("FAIL in TestGetNextErrorBehaviour(unassigned): Expected: U_INVALID_CHAR_ERROR or 0xfffd ----Got:%s and 0x%lx\n", myErrorName(err), c);
+ }
+ ucnv_close(cnv);
+}
+#endif
+
+#define MAX_UTF16_LEN 2
+#define MAX_UTF8_LEN 4
+
+/*Regression test for utf8 converter*/
+static void TestRegressionUTF8(){
+ UChar32 currCh = 0;
+ int32_t offset8;
+ int32_t offset16;
+ UChar *standardForm = (UChar*)malloc(MAX_LENGTH*sizeof(UChar));
+ uint8_t *utf8 = (uint8_t*)malloc(MAX_LENGTH);
+
+ while (currCh <= UNICODE_LIMIT) {
+ offset16 = 0;
+ offset8 = 0;
+ while(currCh <= UNICODE_LIMIT
+ && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN)
+ && offset8 < (MAX_LENGTH - MAX_UTF8_LEN))
+ {
+ if (currCh == SURROGATE_HIGH_START) {
+ currCh = SURROGATE_LOW_END + 1; /* Skip surrogate range */
+ }
+ UTF16_APPEND_CHAR_SAFE(standardForm, offset16, MAX_LENGTH, currCh);
+ UTF8_APPEND_CHAR_SAFE(utf8, offset8, MAX_LENGTH, currCh);
+ currCh++;
+ }
+ if(!convertFromU(standardForm, offset16,
+ utf8, offset8, "UTF8", 0, TRUE, U_ZERO_ERROR )) {
+ log_err("Unicode->UTF8 did not match.\n");
+ }
+ if(!convertToU(utf8, offset8,
+ standardForm, offset16, "UTF8", 0, TRUE, U_ZERO_ERROR )) {
+ log_err("UTF8->Unicode did not match.\n");
+ }
+ }
+
+ free(standardForm);
+ free(utf8);
+
+ {
+ static const char src8[] = { (char)0xCC, (char)0x81, (char)0xCC, (char)0x80 };
+ static const UChar expected[] = { 0x0301, 0x0300 };
+ UConverter *conv8;
+ UErrorCode err = U_ZERO_ERROR;
+ UChar pivotBuffer[100];
+ const UChar* const pivEnd = pivotBuffer + 100;
+ const char* srcBeg;
+ const char* srcEnd;
+ UChar* pivBeg;
+
+ conv8 = ucnv_open("UTF-8", &err);
+
+ srcBeg = src8;
+ pivBeg = pivotBuffer;
+ srcEnd = src8 + 3;
+ ucnv_toUnicode(conv8, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on first call.\n");
+ }
+
+ srcEnd = src8 + 4;
+ ucnv_toUnicode(conv8, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on second call.\n");
+ }
+
+ if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) {
+ log_err("Did not get expected results for UTF-8.\n");
+ }
+ ucnv_close(conv8);
+ }
+}
+
+#define MAX_UTF32_LEN 1
+
+static void TestRegressionUTF32(){
+ UChar32 currCh = 0;
+ int32_t offset32;
+ int32_t offset16;
+ UChar *standardForm = (UChar*)malloc(MAX_LENGTH*sizeof(UChar));
+ UChar32 *utf32 = (UChar32*)malloc(MAX_LENGTH*sizeof(UChar32));
+
+ while (currCh <= UNICODE_LIMIT) {
+ offset16 = 0;
+ offset32 = 0;
+ while(currCh <= UNICODE_LIMIT
+ && offset16 < (MAX_LENGTH/sizeof(UChar) - MAX_UTF16_LEN)
+ && offset32 < (MAX_LENGTH/sizeof(UChar32) - MAX_UTF32_LEN))
+ {
+ if (currCh == SURROGATE_HIGH_START) {
+ currCh = SURROGATE_LOW_END + 1; /* Skip surrogate range */
+ }
+ UTF16_APPEND_CHAR_SAFE(standardForm, offset16, MAX_LENGTH, currCh);
+ UTF32_APPEND_CHAR_SAFE(utf32, offset32, MAX_LENGTH, currCh);
+ currCh++;
+ }
+ if(!convertFromU(standardForm, offset16,
+ (const uint8_t *)utf32, offset32*sizeof(UChar32), "UTF32_PlatformEndian", 0, TRUE, U_ZERO_ERROR )) {
+ log_err("Unicode->UTF32 did not match.\n");
+ }
+ if(!convertToU((const uint8_t *)utf32, offset32*sizeof(UChar32),
+ standardForm, offset16, "UTF32_PlatformEndian", 0, TRUE, U_ZERO_ERROR )) {
+ log_err("UTF32->Unicode did not match.\n");
+ }
+ }
+ free(standardForm);
+ free(utf32);
+
+ {
+ /* Check for lone surrogate error handling. */
+ static const UChar sampleBadStartSurrogate[] = { 0x0031, 0xD800, 0x0032 };
+ static const UChar sampleBadEndSurrogate[] = { 0x0031, 0xDC00, 0x0032 };
+ static const uint8_t expectedUTF32BE[] = {
+ 0x00, 0x00, 0x00, 0x31,
+ 0x00, 0x00, 0xff, 0xfd,
+ 0x00, 0x00, 0x00, 0x32
+ };
+ static const uint8_t expectedUTF32LE[] = {
+ 0x31, 0x00, 0x00, 0x00,
+ 0xfd, 0xff, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00
+ };
+ static const int32_t offsetsUTF32[] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02
+ };
+
+ if(!convertFromU(sampleBadStartSurrogate, sizeof(sampleBadStartSurrogate)/sizeof(sampleBadStartSurrogate[0]),
+ expectedUTF32BE, sizeof(expectedUTF32BE), "UTF-32BE", offsetsUTF32, TRUE, U_ZERO_ERROR))
+ log_err("u->UTF-32BE\n");
+ if(!convertFromU(sampleBadEndSurrogate, sizeof(sampleBadEndSurrogate)/sizeof(sampleBadEndSurrogate[0]),
+ expectedUTF32BE, sizeof(expectedUTF32BE), "UTF-32BE", offsetsUTF32, TRUE, U_ZERO_ERROR))
+ log_err("u->UTF-32BE\n");
+
+ if(!convertFromU(sampleBadStartSurrogate, sizeof(sampleBadStartSurrogate)/sizeof(sampleBadStartSurrogate[0]),
+ expectedUTF32LE, sizeof(expectedUTF32LE), "UTF-32LE", offsetsUTF32, TRUE, U_ZERO_ERROR))
+ log_err("u->UTF-32LE\n");
+ if(!convertFromU(sampleBadEndSurrogate, sizeof(sampleBadEndSurrogate)/sizeof(sampleBadEndSurrogate[0]),
+ expectedUTF32LE, sizeof(expectedUTF32LE), "UTF-32LE", offsetsUTF32, TRUE, U_ZERO_ERROR))
+ log_err("u->UTF-32LE\n");
+ }
+
+ {
+ static const char srcBE[] = { 0, 0, 0, 0x31, 0, 0, 0, 0x30 };
+ static const UChar expected[] = { 0x0031, 0x0030 };
+ UConverter *convBE;
+ UErrorCode err = U_ZERO_ERROR;
+ UChar pivotBuffer[100];
+ const UChar* const pivEnd = pivotBuffer + 100;
+ const char* srcBeg;
+ const char* srcEnd;
+ UChar* pivBeg;
+
+ convBE = ucnv_open("UTF-32BE", &err);
+
+ srcBeg = srcBE;
+ pivBeg = pivotBuffer;
+ srcEnd = srcBE + 5;
+ ucnv_toUnicode(convBE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on first call.\n");
+ }
+
+ srcEnd = srcBE + 8;
+ ucnv_toUnicode(convBE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on second call.\n");
+ }
+
+ if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) {
+ log_err("Did not get expected results for UTF-32BE.\n");
+ }
+ ucnv_close(convBE);
+ }
+ {
+ static const char srcLE[] = { 0x31, 0, 0, 0, 0x30, 0, 0, 0 };
+ static const UChar expected[] = { 0x0031, 0x0030 };
+ UConverter *convLE;
+ UErrorCode err = U_ZERO_ERROR;
+ UChar pivotBuffer[100];
+ const UChar* const pivEnd = pivotBuffer + 100;
+ const char* srcBeg;
+ const char* srcEnd;
+ UChar* pivBeg;
+
+ convLE = ucnv_open("UTF-32LE", &err);
+
+ srcBeg = srcLE;
+ pivBeg = pivotBuffer;
+ srcEnd = srcLE + 5;
+ ucnv_toUnicode(convLE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, FALSE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on first call.\n");
+ }
+
+ srcEnd = srcLE + 8;
+ ucnv_toUnicode(convLE, &pivBeg, pivEnd, &srcBeg, srcEnd, 0, TRUE, &err);
+ if (srcBeg != srcEnd) {
+ log_err("Did not consume whole buffer on second call.\n");
+ }
+
+ if (U_FAILURE(err) || (int32_t)(pivBeg - pivotBuffer) != 2 || u_strncmp(pivotBuffer, expected, 2) != 0) {
+ log_err("Did not get expected results for UTF-32LE.\n");
+ }
+ ucnv_close(convLE);
+ }
+}
+
+/*Walk through the available converters*/
+static void TestAvailableConverters(){
+ UErrorCode status=U_ZERO_ERROR;
+ UConverter *conv=NULL;
+ int32_t i=0;
+ for(i=0; i < ucnv_countAvailable(); i++){
+ status=U_ZERO_ERROR;
+ conv=ucnv_open(ucnv_getAvailableName(i), &status);
+ if(U_FAILURE(status)){
+ log_err("ERROR: converter creation failed. Failure in alias table or the data table for \n converter=%s. Error=%s\n",
+ ucnv_getAvailableName(i), myErrorName(status));
+ continue;
+ }
+ ucnv_close(conv);
+ }
+
+}
+
+static void TestFlushInternalBuffer(){
+ TestWithBufferSize(MAX_LENGTH, 1);
+ TestWithBufferSize(1, 1);
+ TestWithBufferSize(1, MAX_LENGTH);
+ TestWithBufferSize(MAX_LENGTH, MAX_LENGTH);
+}
+
+static void TestWithBufferSize(int32_t insize, int32_t outsize){
+
+ gInBufferSize =insize;
+ gOutBufferSize = outsize;
+
+ log_verbose("Testing fromUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n");
+ {
+ UChar sampleText[] =
+ { 0x0031, 0x0032, 0x0033, 0x0000, 0x4e00, 0x4e8c, 0x4e09, 0x002E };
+ const uint8_t expectedUTF8[] =
+ { 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E };
+ int32_t toUTF8Offs[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07};
+ /* int32_t fmUTF8Offs[] =
+ { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, 0x000d };*/
+
+ /*UTF-8*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF8, sizeof(expectedUTF8), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE, toUTF8Offs ,FALSE))
+ log_err("u-> UTF8 did not match.\n");
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing fromUnicode with UCNV_FROM_U_CALLBACK_ESCAPE \n");
+ {
+ UChar inputTest[] = { 0x0061, 0xd801, 0xdc01, 0xd801, 0x0061 };
+ const uint8_t toIBM943[]= { 0x61,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x43, 0x30, 0x31,
+ 0x25, 0x55, 0x44, 0x38, 0x30, 0x31,
+ 0x61 };
+ int32_t offset[]= {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 4};
+
+ if(!testConvertFromU(inputTest, sizeof(inputTest)/sizeof(inputTest[0]),
+ toIBM943, sizeof(toIBM943), "ibm-943",
+ (UConverterFromUCallback)UCNV_FROM_U_CALLBACK_ESCAPE, offset,FALSE))
+ log_err("u-> ibm-943 with subst with value did not match.\n");
+ }
+#endif
+
+ log_verbose("Testing fromUnicode for UTF-8 with UCNV_TO_U_CALLBACK_SUBSTITUTE \n");
+ {
+ const uint8_t sampleText1[] = { 0x31, 0xe4, 0xba, 0x8c,
+ 0xe0, 0x80, 0x61};
+ UChar expected1[] = { 0x0031, 0x4e8c, 0xfffd, 0x0061};
+ int32_t offsets1[] = { 0x0000, 0x0001, 0x0004, 0x0006};
+
+ if(!testConvertToU(sampleText1, sizeof(sampleText1),
+ expected1, sizeof(expected1)/sizeof(expected1[0]),"utf8", UCNV_TO_U_CALLBACK_SUBSTITUTE, offsets1,FALSE))
+ log_err("utf8->u with substitute did not match.\n");;
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing toUnicode with UCNV_TO_U_CALLBACK_ESCAPE \n");
+ /*to Unicode*/
+ {
+ const uint8_t sampleTxtToU[]= { 0x00, 0x9f, 0xaf,
+ 0x81, 0xad, /*unassigned*/
+ 0x89, 0xd3 };
+ UChar IBM_943toUnicode[] = { 0x0000, 0x6D63,
+ 0x25, 0x58, 0x38, 0x31, 0x25, 0x58, 0x41, 0x44,
+ 0x7B87};
+ int32_t fromIBM943Offs [] = { 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 5};
+
+ if(!testConvertToU(sampleTxtToU, sizeof(sampleTxtToU),
+ IBM_943toUnicode, sizeof(IBM_943toUnicode)/sizeof(IBM_943toUnicode[0]),"ibm-943",
+ (UConverterToUCallback)UCNV_TO_U_CALLBACK_ESCAPE, fromIBM943Offs,FALSE))
+ log_err("ibm-943->u with substitute with value did not match.\n");
+
+ }
+#endif
+}
+
+static UBool convertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus)
+{
+
+ int32_t i=0;
+ char *p=0;
+ const UChar *src;
+ char buffer[MAX_LENGTH];
+ int32_t offsetBuffer[MAX_LENGTH];
+ int32_t *offs=0;
+ char *targ;
+ char *targetLimit;
+ UChar *sourceLimit=0;
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE;
+ }
+ log_verbose("Converter %s opened..\n", ucnv_getName(conv, &status));
+
+ for(i=0; i<MAX_LENGTH; i++){
+ buffer[i]=(char)0xF0;
+ offsetBuffer[i]=0xFF;
+ }
+
+ src=source;
+ sourceLimit=(UChar*)src+(sourceLen);
+ targ=buffer;
+ targetLimit=targ+MAX_LENGTH;
+ offs=offsetBuffer;
+ ucnv_fromUnicode (conv,
+ (char **)&targ,
+ (const char *)targetLimit,
+ &src,
+ sourceLimit,
+ expectOffsets ? offs : NULL,
+ doFlush,
+ &status);
+ ucnv_close(conv);
+ if(status != expectedStatus){
+ log_err("ucnv_fromUnicode() failed for codepage=%s. Error =%s Expected=%s\n", codepage, myErrorName(status), myErrorName(expectedStatus));
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-buffer);
+
+ if(expectLen != targ-buffer)
+ {
+ log_err("Expected %d chars out, got %d FROM Unicode to %s\n", expectLen, targ-buffer, codepage);
+ log_verbose("Expected %d chars out, got %d FROM Unicode to %s\n", expectLen, targ-buffer, codepage);
+ printSeqErr((const unsigned char *)buffer, (int32_t)(targ-buffer));
+ printSeqErr((const unsigned char*)expect, expectLen);
+ return FALSE;
+ }
+
+ if(memcmp(buffer, expect, expectLen)){
+ log_err("String does not match. FROM Unicode to codePage%s\n", codepage);
+ log_info("\nGot:");
+ printSeqErr((const unsigned char *)buffer, expectLen);
+ log_info("\nExpected:");
+ printSeqErr((const unsigned char *)expect, expectLen);
+ return FALSE;
+ }
+ else {
+ log_verbose("Matches!\n");
+ }
+
+ if (expectOffsets != 0){
+ log_verbose("comparing %d offsets..\n", targ-buffer);
+ if(memcmp(offsetBuffer,expectOffsets,(targ-buffer) * sizeof(int32_t) )){
+ log_err("did not get the expected offsets. for FROM Unicode to %s\n", codepage);
+ log_info("\nGot : ");
+ printSeqErr((const unsigned char*)buffer, (int32_t)(targ-buffer));
+ for(p=buffer;p<targ;p++)
+ log_info("%d, ", offsetBuffer[p-buffer]);
+ log_info("\nExpected: ");
+ for(i=0; i< (targ-buffer); i++)
+ log_info("%d,", expectOffsets[i]);
+ }
+ }
+
+ return TRUE;
+}
+
+
+static UBool convertToU( const uint8_t *source, int sourceLen, const UChar *expect, int expectLen,
+ const char *codepage, const int32_t *expectOffsets, UBool doFlush, UErrorCode expectedStatus)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ int32_t i=0;
+ UChar *p=0;
+ const char* src;
+ UChar buffer[MAX_LENGTH];
+ int32_t offsetBuffer[MAX_LENGTH];
+ int32_t *offs=0;
+ UChar *targ;
+ UChar *targetLimit;
+ uint8_t *sourceLimit=0;
+
+
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE;
+ }
+ log_verbose("Converter %s opened..\n", ucnv_getName(conv, &status));
+
+
+
+ for(i=0; i<MAX_LENGTH; i++){
+ buffer[i]=0xFFFE;
+ offsetBuffer[i]=-1;
+ }
+
+ src=(const char *)source;
+ sourceLimit=(uint8_t*)(src+(sourceLen));
+ targ=buffer;
+ targetLimit=targ+MAX_LENGTH;
+ offs=offsetBuffer;
+
+
+
+ ucnv_toUnicode (conv,
+ &targ,
+ targetLimit,
+ (const char **)&src,
+ (const char *)sourceLimit,
+ expectOffsets ? offs : NULL,
+ doFlush,
+ &status);
+
+ ucnv_close(conv);
+ if(status != expectedStatus){
+ log_err("ucnv_fromUnicode() failed for codepage=%s. Error =%s Expected=%s\n", codepage, myErrorName(status), myErrorName(expectedStatus));
+ return FALSE;
+ }
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-buffer);
+
+
+
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectLen,expectLen*2);
+
+ if (expectOffsets != 0) {
+ if(memcmp(offsetBuffer, expectOffsets, (targ-buffer) * sizeof(int32_t))){
+
+ log_err("did not get the expected offsets from %s To UNICODE\n", codepage);
+ log_info("\nGot : ");
+ for(p=buffer;p<targ;p++)
+ log_info("%d, ", offsetBuffer[p-buffer]);
+ log_info("\nExpected: ");
+ for(i=0; i<(targ-buffer); i++)
+ log_info("%d, ", expectOffsets[i]);
+ log_info("\nGot result:");
+ for(i=0; i<(targ-buffer); i++)
+ log_info("0x%04X,", buffer[i]);
+ log_info("\nFrom Input:");
+ for(i=0; i<(src-(const char *)source); i++)
+ log_info("0x%02X,", (unsigned char)source[i]);
+ log_info("\n");
+ }
+ }
+ if(memcmp(buffer, expect, expectLen*2)){
+ log_err("String does not match. from codePage %s TO Unicode\n", codepage);
+ log_info("\nGot:");
+ printUSeqErr(buffer, expectLen);
+ log_info("\nExpected:");
+ printUSeqErr(expect, expectLen);
+ return FALSE;
+ }
+ else {
+ log_verbose("Matches!\n");
+ }
+
+ return TRUE;
+}
+
+
+static UBool testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, UConverterFromUCallback callback , const int32_t *expectOffsets, UBool testReset)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ char junkout[MAX_LENGTH]; /* FIX */
+ int32_t junokout[MAX_LENGTH]; /* FIX */
+ char *p;
+ const UChar *src;
+ char *end;
+ char *targ;
+ int32_t *offs;
+ int i;
+ int32_t realBufferSize;
+ char *realBufferEnd;
+ const UChar *realSourceEnd;
+ const UChar *sourceLimit;
+ UBool checkOffsets = TRUE;
+ UBool doFlush;
+
+ UConverterFromUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+ for(i=0;i<MAX_LENGTH;i++)
+ junkout[i] = (char)0xF0;
+ for(i=0;i<MAX_LENGTH;i++)
+ junokout[i] = 0xFF;
+
+ setNuConvTestName(codepage, "FROM");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+ /*----setting the callback routine----*/
+ ucnv_setFromUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*------------------------*/
+
+ src = source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = source + sourceLen;
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != MAX_LENGTH )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min(targ + gOutBufferSize, realBufferEnd);
+ sourceLimit = nct_min(src + gInBufferSize, realSourceEnd);
+
+ doFlush = (UBool)(sourceLimit == realSourceEnd);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE");
+
+
+ status = U_ZERO_ERROR;
+ if(gInBufferSize ==999 && gOutBufferSize==999)
+ doFlush = FALSE;
+ ucnv_fromUnicode (conv,
+ (char **)&targ,
+ (const char *)end,
+ &src,
+ sourceLimit,
+ offs,
+ doFlush, /* flush if we're at the end of the input data */
+ &status);
+ if(testReset)
+ ucnv_resetToUnicode(conv);
+ if(gInBufferSize ==999 && gOutBufferSize==999)
+ ucnv_resetToUnicode(conv);
+
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && sourceLimit < realSourceEnd) );
+
+ if(U_FAILURE(status)) {
+ log_err("Problem doing fromUnicode to %s, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-junkout);
+ if(VERBOSITY)
+ {
+ char junk[999];
+ char offset_str[999];
+ char *ptr;
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+ for(ptr = junkout;ptr<targ;ptr++)
+ {
+ sprintf(junk + strlen(junk), "0x%02x, ", (0xFF) & (unsigned int)*ptr);
+ sprintf(offset_str + strlen(offset_str), "0x%02x, ", (0xFF) & (unsigned int)junokout[ptr-junkout]);
+ }
+
+ log_verbose(junk);
+ printSeq((const unsigned char *)expect, expectLen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+
+ if(expectLen != targ-junkout)
+ {
+ log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_info("\nGot:");
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ log_info("\nExpected:");
+ printSeqErr((const unsigned char*)expect, expectLen);
+ return FALSE;
+ }
+
+ if (checkOffsets && (expectOffsets != 0) )
+ {
+ log_verbose("comparing %d offsets..\n", targ-junkout);
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){
+ log_err("did not get the expected offsets. %s", gNuConvTestName);
+ log_err("Got : ");
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ for(p=junkout;p<targ;p++)
+ log_err("%d, ", junokout[p-junkout]);
+ log_err("\nExpected: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ }
+ }
+
+ log_verbose("comparing..\n");
+ if(!memcmp(junkout, expect, expectLen))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ printUSeqErr(source, sourceLen);
+ log_info("\nGot:");
+ printSeqErr((const unsigned char *)junkout, expectLen);
+ log_info("\nExpected:");
+ printSeqErr((const unsigned char *)expect, expectLen);
+
+ return FALSE;
+ }
+}
+
+static UBool testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, UConverterToUCallback callback, const int32_t *expectOffsets, UBool testReset)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ UChar junkout[MAX_LENGTH]; /* FIX */
+ int32_t junokout[MAX_LENGTH]; /* FIX */
+ const char *src;
+ const char *realSourceEnd;
+ const char *srcLimit;
+ UChar *p;
+ UChar *targ;
+ UChar *end;
+ int32_t *offs;
+ int i;
+ UBool checkOffsets = TRUE;
+ int32_t realBufferSize;
+ UChar *realBufferEnd;
+ UBool doFlush;
+
+ UConverterToUCallback oldAction = NULL;
+ const void* oldContext = NULL;
+
+
+ for(i=0;i<MAX_LENGTH;i++)
+ junkout[i] = 0xFFFE;
+
+ for(i=0;i<MAX_LENGTH;i++)
+ junokout[i] = -1;
+
+ setNuConvTestName(codepage, "TO");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = ucnv_open(codepage, &status);
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",gNuConvTestName);
+ return TRUE;
+ }
+
+ log_verbose("Converter opened..\n");
+ /*----setting the callback routine----*/
+ ucnv_setToUCallBack (conv, callback, NULL, &oldAction, &oldContext, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAILURE in setting the callback Function! %s\n", myErrorName(status));
+ }
+ /*-------------------------------------*/
+
+ src = (const char *)source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = src + sourcelen;
+
+ if ( gOutBufferSize != realBufferSize )
+ checkOffsets = FALSE;
+
+ if( gInBufferSize != MAX_LENGTH )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min( targ + gOutBufferSize, realBufferEnd);
+ srcLimit = nct_min(realSourceEnd, src + gInBufferSize);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjey=%08lx %s",targ,gNuConvTestName);
+ return FALSE;
+ }
+ log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end);
+
+ /* oldTarg = targ; */
+
+ status = U_ZERO_ERROR;
+ doFlush=(UBool)((gInBufferSize ==999 && gOutBufferSize==999)?(srcLimit == realSourceEnd) : FALSE);
+
+ ucnv_toUnicode (conv,
+ &targ,
+ end,
+ (const char **)&src,
+ (const char *)srcLimit,
+ offs,
+ doFlush, /* flush if we're at the end of hte source data */
+ &status);
+ if(testReset)
+ ucnv_resetFromUnicode(conv);
+ if(gInBufferSize ==999 && gOutBufferSize==999)
+ ucnv_resetToUnicode(conv);
+ /* offs += (targ-oldTarg); */
+
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */
+
+ if(U_FAILURE(status))
+ {
+ log_err("Problem doing %s toUnicode, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName);
+ return FALSE;
+ }
+
+ log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :",
+ sourcelen, targ-junkout);
+ if(VERBOSITY)
+ {
+ char junk[999];
+ char offset_str[999];
+
+ UChar *ptr;
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+
+ for(ptr = junkout;ptr<targ;ptr++)
+ {
+ sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*ptr);
+ sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[ptr-junkout]);
+ }
+
+ log_verbose(junk);
+
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2);
+
+ if (checkOffsets && (expectOffsets != 0))
+ {
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))){
+
+ log_err("did not get the expected offsets. %s",gNuConvTestName);
+ for(p=junkout;p<targ;p++)
+ log_err("%d, ", junokout[p-junkout]);
+ log_err("\nExpected: ");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%d,", expectOffsets[i]);
+ log_err("");
+ for(i=0; i<(targ-junkout); i++)
+ log_err("%X,", junkout[i]);
+ log_err("");
+ for(i=0; i<(src-(const char *)source); i++)
+ log_err("%X,", (unsigned char)source[i]);
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectlen*2))
+ {
+ log_verbose("Matches!\n");
+ return TRUE;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ log_info("\nGot:");
+ printUSeq(junkout, expectlen);
+ log_info("\nExpected:");
+ printUSeq(expect, expectlen);
+ return FALSE;
+ }
+}
+
+
+static void TestResetBehaviour(void){
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ log_verbose("Testing Reset for DBCS and MBCS\n");
+ {
+ static const UChar sampleText[] = {0x00a1, 0xd801, 0xdc01, 0x00a4};
+ static const uint8_t expected[] = {0xa2, 0xae, 0xa1, 0xe0, 0xa2, 0xb4};
+ static const int32_t offsets[] = {0x00, 0x00, 0x01, 0x01, 0x03, 0x03 };
+
+
+ static const UChar sampleText1[] = {0x00a1, 0x00a4, 0x00a7, 0x00a8};
+ static const uint8_t expected1[] = {0xa2, 0xae,0xA2,0xB4,0xA1,0xD7,0xA1,0xA7};
+ static const int32_t offsets1[] = { 0,2,4,6};
+
+ /*DBCS*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> ibm-1363 [UCNV_DBCS portion] not match.\n");
+
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "ibm-1363",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("ibm-1363 -> did not match.\n");
+ /*MBCS*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "ibm-1363", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> ibm-1363 [UCNV_MBCS] not match.\n");
+
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "ibm-1363",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("ibm-1363 -> did not match.\n");
+
+ }
+
+ log_verbose("Testing Reset for ISO-2022-jp\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42,
+ 0x31,0x1A, 0x32};
+
+
+ static const int32_t offsets[] = {0,0,0,0,0,1,1,2,2,2,2,3,5 };
+
+
+ static const UChar sampleText1[] = {0x4e00, 0x04e01, 0x0031,0x001A, 0x0032};
+ static const uint8_t expected1[] = {0x1b, 0x24, 0x42,0x30,0x6c,0x43,0x7a,0x1b,0x28,0x42,
+ 0x31,0x1A, 0x32};
+ static const int32_t offsets1[] = { 3,5,10,11,12};
+
+ /*iso-2022-jp*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-jp", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("u-> not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-jp", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> not match.\n");
+
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-jp",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("iso-2022-jp -> did not match.\n");
+
+ }
+
+ log_verbose("Testing Reset for ISO-2022-cn\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {
+ 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B,
+ 0x36, 0x21,
+ 0x0f, 0x31,
+ 0x1A,
+ 0x32
+ };
+
+
+ static const int32_t offsets[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ 1, 1,
+ 2, 2,
+ 3,
+ 5, };
+
+ UChar sampleText1[] = {0x4e00, 0x04e01, 0x0031,0x001A, 0x0032};
+ static const uint8_t expected1[] = {
+ 0x1B, 0x24, 0x29, 0x41, 0x0E, 0x52, 0x3B,
+ 0x36, 0x21,
+ 0x1B, 0x24, 0x29, 0x47, 0x24, 0x22,
+ 0x0f, 0x1A,
+ 0x32
+ };
+ static const int32_t offsets1[] = { 5,7,13,16,17};
+
+ /*iso-2022-CN*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-cn", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("u-> not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-cn", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> not match.\n");
+
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-cn",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("iso-2022-cn -> did not match.\n");
+ }
+
+ log_verbose("Testing Reset for ISO-2022-kr\n");
+ {
+ UChar sampleText[] = { 0x4e00,0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {0x1B, 0x24, 0x29, 0x43,
+ 0x0E, 0x6C, 0x69,
+ 0x0f, 0x1A,
+ 0x0e, 0x6F, 0x4B,
+ 0x0F, 0x31,
+ 0x1A,
+ 0x32 };
+
+ static const int32_t offsets[] = {-1, -1, -1, -1,
+ 0, 0, 0,
+ 1, 1,
+ 3, 3, 3,
+ 4, 4,
+ 5,
+ 7,
+ };
+ static const UChar sampleText1[] = { 0x4e00,0x0041, 0x04e01, 0x0031, 0x0042, 0x0032};
+
+ static const uint8_t expected1[] = {0x1B, 0x24, 0x29, 0x43,
+ 0x0E, 0x6C, 0x69,
+ 0x0f, 0x41,
+ 0x0e, 0x6F, 0x4B,
+ 0x0F, 0x31,
+ 0x42,
+ 0x32 };
+
+ static const int32_t offsets1[] = {
+ 5, 8, 10,
+ 13, 14, 15
+
+ };
+ /*iso-2022-kr*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-kr", UCNV_FROM_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "iso-2022-kr", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> iso-2022-kr [UCNV_DBCS] not match.\n");
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "iso-2022-kr",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("iso-2022-kr -> did not match.\n");
+ }
+
+ log_verbose("Testing Reset for HZ\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0xd801, 0xdc01, 0x04e01, 0x0031, 0xd801, 0xdc01, 0x0032};
+
+ static const uint8_t expected[] = {0x7E, 0x7B, 0x52, 0x3B,
+ 0x7E, 0x7D, 0x1A,
+ 0x7E, 0x7B, 0x36, 0x21,
+ 0x7E, 0x7D, 0x31,
+ 0x1A,
+ 0x32 };
+
+
+ static const int32_t offsets[] = {0,0,0,0,
+ 1,1,1,
+ 3,3,3,3,
+ 4,4,4,
+ 5,
+ 7,};
+ static const UChar sampleText1[] = { 0x4e00, 0x0035, 0x04e01, 0x0031, 0x0041, 0x0032};
+
+ static const uint8_t expected1[] = {0x7E, 0x7B, 0x52, 0x3B,
+ 0x7E, 0x7D, 0x35,
+ 0x7E, 0x7B, 0x36, 0x21,
+ 0x7E, 0x7D, 0x31,
+ 0x41,
+ 0x32 };
+
+
+ static const int32_t offsets1[] = {2,6,9,13,14,15
+ };
+
+ /*hz*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "HZ", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE))
+ log_err("u-> not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "HZ", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> not match.\n");
+ if(!testConvertToU(expected1, sizeof(expected1),
+ sampleText1, sizeof(sampleText1)/sizeof(sampleText1[0]), "hz",UCNV_TO_U_CALLBACK_SUBSTITUTE ,
+ offsets1, TRUE))
+ log_err("hz -> did not match.\n");
+ }
+#endif
+
+ /*UTF-8*/
+ log_verbose("Testing for UTF8\n");
+ {
+ static const UChar sampleText[] = { 0x4e00, 0x0701, 0x0031, 0xbfc1, 0xd801, 0xdc01, 0x0032};
+ int32_t offsets[]={0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
+ 0x04, 0x06 };
+ static const uint8_t expected[] = {0xe4, 0xb8, 0x80, 0xdc, 0x81, 0x31,
+ 0xeb, 0xbf, 0x81, 0xF0, 0x90, 0x90, 0x81, 0x32};
+
+
+ static const int32_t fromOffsets[] = { 0x0000, 0x0003, 0x0005, 0x0006, 0x0009, 0x0009, 0x000D };
+ /*UTF-8*/
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,offsets , TRUE))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expected, sizeof(expected), "UTF8", UCNV_FROM_U_CALLBACK_SUBSTITUTE,NULL , TRUE))
+ log_err("u-> UTF8 with offsets and flush true did not match.\n");
+ if(!testConvertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8",UCNV_TO_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("UTF8 -> did not match.\n");
+ if(!testConvertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", UCNV_TO_U_CALLBACK_SUBSTITUTE , NULL, TRUE))
+ log_err("UTF8 -> did not match.\n");
+ if(!testConvertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8",UCNV_TO_U_CALLBACK_SUBSTITUTE , fromOffsets, TRUE))
+ log_err("UTF8 -> did not match.\n");
+ if(!testConvertToU(expected, sizeof(expected),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "UTF8", UCNV_TO_U_CALLBACK_SUBSTITUTE , fromOffsets, TRUE))
+ log_err("UTF8 -> did not match.\n");
+
+ }
+
+}
+
+/* Test that U_TRUNCATED_CHAR_FOUND is set. */
+static void
+doTestTruncated(const char *cnvName, const uint8_t *bytes, int32_t length) {
+ UConverter *cnv;
+
+ UChar buffer[2];
+ UChar *target, *targetLimit;
+ const char *source, *sourceLimit;
+
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open(cnvName, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("error TestTruncated: unable to open \"%s\" - %s\n", cnvName, u_errorName(errorCode));
+ return;
+ }
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("error TestTruncated: unable to set the stop callback on \"%s\" - %s\n",
+ cnvName, u_errorName(errorCode));
+ ucnv_close(cnv);
+ return;
+ }
+
+ source=(const char *)bytes;
+ sourceLimit=source+length;
+ target=buffer;
+ targetLimit=buffer+LENGTHOF(buffer);
+
+ /* 1. input bytes with flush=FALSE, then input nothing with flush=TRUE */
+ ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, FALSE, &errorCode);
+ if(U_FAILURE(errorCode) || source!=sourceLimit || target!=buffer) {
+ log_err("error TestTruncated(%s, 1a): input bytes[%d], flush=FALSE: %s, input left %d, output %d\n",
+ cnvName, length, u_errorName(errorCode), (int)(sourceLimit-source), (int)(target-buffer));
+ }
+
+ errorCode=U_ZERO_ERROR;
+ source=sourceLimit;
+ target=buffer;
+ ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &errorCode);
+ if(errorCode!=U_TRUNCATED_CHAR_FOUND || target!=buffer) {
+ log_err("error TestTruncated(%s, 1b): no input (previously %d), flush=TRUE: %s (should be U_TRUNCATED_CHAR_FOUND), output %d\n",
+ cnvName, (int)length, u_errorName(errorCode), (int)(target-buffer));
+ }
+
+ /* 2. input bytes with flush=TRUE */
+ ucnv_resetToUnicode(cnv);
+
+ errorCode=U_ZERO_ERROR;
+ source=(const char *)bytes;
+ target=buffer;
+ ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &errorCode);
+ if(errorCode!=U_TRUNCATED_CHAR_FOUND || source!=sourceLimit || target!=buffer) {
+ log_err("error TestTruncated(%s, 2): input bytes[%d], flush=TRUE: %s (should be U_TRUNCATED_CHAR_FOUND), input left %d, output %d\n",
+ cnvName, length, u_errorName(errorCode), (int)(sourceLimit-source), (int)(target-buffer));
+ }
+
+
+ ucnv_close(cnv);
+}
+
+static void
+TestTruncated() {
+ static const struct {
+ const char *cnvName;
+ uint8_t bytes[8]; /* partial input bytes resulting in no output */
+ int32_t length;
+ } testCases[]={
+ { "IMAP-mailbox-name", { 0x26 }, 1 }, /* & */
+ { "IMAP-mailbox-name", { 0x26, 0x42 }, 2 }, /* &B */
+ { "IMAP-mailbox-name", { 0x26, 0x42, 0x42 }, 3 }, /* &BB */
+ { "IMAP-mailbox-name", { 0x26, 0x41, 0x41 }, 3 }, /* &AA */
+
+ { "UTF-7", { 0x2b, 0x42 }, 2 }, /* +B */
+ { "UTF-8", { 0xd1 }, 1 },
+
+ { "UTF-16BE", { 0x4e }, 1 },
+ { "UTF-16LE", { 0x4e }, 1 },
+ { "UTF-16", { 0x4e }, 1 },
+ { "UTF-16", { 0xff }, 1 },
+ { "UTF-16", { 0xfe, 0xff, 0x4e }, 3 },
+
+ { "UTF-32BE", { 0, 0, 0x4e }, 3 },
+ { "UTF-32LE", { 0x4e }, 1 },
+ { "UTF-32", { 0, 0, 0x4e }, 3 },
+ { "UTF-32", { 0xff }, 1 },
+ { "UTF-32", { 0, 0, 0xfe, 0xff, 0 }, 5 },
+ { "SCSU", { 0x0e, 0x4e }, 2 }, /* SQU 0x4e */
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ { "BOCU-1", { 0xd5 }, 1 },
+
+ { "Shift-JIS", { 0xe0 }, 1 },
+
+ { "ibm-939", { 0x0e, 0x41 }, 2 } /* SO 0x41 */
+#else
+ { "BOCU-1", { 0xd5 }, 1 ,}
+#endif
+ };
+ int32_t i;
+
+ for(i=0; i<LENGTHOF(testCases); ++i) {
+ doTestTruncated(testCases[i].cnvName, testCases[i].bytes, testCases[i].length);
+ }
+}
+
+typedef struct NameRange {
+ const char *name;
+ UChar32 start, end, start2, end2, notStart, notEnd;
+} NameRange;
+
+static void
+TestUnicodeSet() {
+ UErrorCode errorCode;
+ UConverter *cnv;
+ USet *set;
+ const char *name;
+ int32_t i, count;
+
+ static const char *const completeSetNames[]={
+ "UTF-7",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-32",
+ "UTF-32BE",
+ "UTF-32LE",
+ "SCSU",
+ "BOCU-1",
+ "CESU-8",
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "gb18030",
+#endif
+ "IMAP-mailbox-name"
+ };
+
+ static const char *const lmbcsNames[]={
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ "LMBCS-1",
+ "LMBCS-2",
+ "LMBCS-3",
+ "LMBCS-4",
+ "LMBCS-5",
+ "LMBCS-6",
+ "LMBCS-8",
+ "LMBCS-11",
+ "LMBCS-16",
+ "LMBCS-17",
+ "LMBCS-18",
+ "LMBCS-19"
+#endif
+ };
+
+ static const NameRange nameRanges[]={
+ { "US-ASCII", 0, 0x7f, -1, -1, 0x80, 0x10ffff },
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ { "ibm-367", 0, 0x7f, -1, -1, 0x80, 0x10ffff },
+#endif
+ { "ISO-8859-1", 0, 0x7f, -1, -1, 0x100, 0x10ffff },
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ { "UTF-8", 0, 0xd7ff, 0xe000, 0x10ffff, 0xd800, 0xdfff },
+ { "windows-1251", 0, 0x7f, 0x410, 0x44f, 0x3000, 0xd7ff },
+ { "HZ", 0x410, 0x44f, 0x4e00, 0x4eff, 0xac00, 0xd7ff },
+ { "shift-jis", 0x3041, 0x3093, 0x30a1, 0x30f3, 0x900, 0x1cff }
+#else
+ { "UTF-8", 0, 0xd7ff, 0xe000, 0x10ffff, 0xd800, 0xdfff }
+#endif
+ };
+
+ /* open an empty set */
+ set=uset_open(1, 0);
+
+ count=ucnv_countAvailable();
+ for(i=0; i<count; ++i) {
+ errorCode=U_ZERO_ERROR;
+ name=ucnv_getAvailableName(i);
+ cnv=ucnv_open(name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: unable to open converter %s - %s\n",
+ name, u_errorName(errorCode));
+ continue;
+ }
+
+ uset_clear(set);
+ ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ } else if(uset_size(set)==0) {
+ log_err("error: ucnv_getUnicodeSet(%s) returns an empty set\n", name);
+ }
+
+ ucnv_close(cnv);
+ }
+
+ /* test converters that are known to convert all of Unicode (except maybe for surrogates) */
+ for(i=0; i<LENGTHOF(completeSetNames); ++i) {
+ errorCode=U_ZERO_ERROR;
+ name=completeSetNames[i];
+ cnv=ucnv_open(name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: unable to open converter %s - %s\n",
+ name, u_errorName(errorCode));
+ continue;
+ }
+
+ uset_clear(set);
+ ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ } else if(!uset_containsRange(set, 0, 0xd7ff) || !uset_containsRange(set, 0xe000, 0x10ffff)) {
+ log_err("error: ucnv_getUnicodeSet(%s) does not return an all-Unicode set\n", name);
+ }
+
+ ucnv_close(cnv);
+ }
+
+ /* test LMBCS variants which convert all of Unicode except for U+F6xx */
+ for(i=0; i<LENGTHOF(lmbcsNames); ++i) {
+ errorCode=U_ZERO_ERROR;
+ name=lmbcsNames[i];
+ cnv=ucnv_open(name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: unable to open converter %s - %s\n",
+ name, u_errorName(errorCode));
+ continue;
+ }
+
+ uset_clear(set);
+ ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ } else if(!uset_containsRange(set, 0, 0xf5ff) || !uset_containsRange(set, 0xf700, 0x10ffff)) {
+ log_err("error: ucnv_getUnicodeSet(%s) does not return an all-Unicode set (minus U+F6xx)\n", name);
+ }
+
+ ucnv_close(cnv);
+ }
+
+ /* test specific sets */
+ for(i=0; i<LENGTHOF(nameRanges); ++i) {
+ errorCode=U_ZERO_ERROR;
+ name=nameRanges[i].name;
+ cnv=ucnv_open(name, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("error: unable to open converter %s - %s\n",
+ name, u_errorName(errorCode));
+ continue;
+ }
+
+ uset_clear(set);
+ ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: ucnv_getUnicodeSet(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ } else if(
+ !uset_containsRange(set, nameRanges[i].start, nameRanges[i].end) ||
+ (nameRanges[i].start2>=0 && !uset_containsRange(set, nameRanges[i].start2, nameRanges[i].end2))
+ ) {
+ log_err("error: ucnv_getUnicodeSet(%s) does not contain the expected ranges\n", name);
+ } else if(nameRanges[i].notStart>=0) {
+ /* simulate containsAny() with the C API */
+ uset_complement(set);
+ if(!uset_containsRange(set, nameRanges[i].notStart, nameRanges[i].notEnd)) {
+ log_err("error: ucnv_getUnicodeSet(%s) contains part of the unexpected range\n", name);
+ }
+ }
+
+ ucnv_close(cnv);
+ }
+
+ errorCode = U_ZERO_ERROR;
+ ucnv_getUnicodeSet(NULL, set, UCNV_ROUNDTRIP_SET, &errorCode);
+ if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("error: ucnv_getUnicodeSet(NULL) returned wrong status code %s\n", u_errorName(errorCode));
+ }
+ errorCode = U_PARSE_ERROR;
+ /* Make sure that it does nothing if an error is passed in. Difficult to proper test for. */
+ ucnv_getUnicodeSet(NULL, NULL, UCNV_ROUNDTRIP_SET, &errorCode);
+ if (errorCode != U_PARSE_ERROR) {
+ log_err("error: ucnv_getUnicodeSet(NULL) returned wrong status code %s\n", u_errorName(errorCode));
+ }
+
+ uset_close(set);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c
new file mode 100644
index 00000000000..61b11214beb
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.c
@@ -0,0 +1,310 @@
+/*
+ *******************************************************************************
+ *
+ * Copyright (C) 2003-2007, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *
+ *******************************************************************************
+ * file name: nfsprep.c
+ * encoding: US-ASCII
+ * tab size: 8 (not used)
+ * indentation:4
+ *
+ * created on: 2003jul11
+ * created by: Ram Viswanadha
+ */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_IDNA
+
+#include "nfsprep.h"
+#include "ustr_imp.h"
+#include "cintltst.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+#define NFS4_MAX_BUFFER_SIZE 1000
+#define PREFIX_SUFFIX_SEPARATOR 0x0040 /* '@' */
+
+
+const char* NFS4DataFileNames[5] ={
+ "nfscss",
+ "nfscsi",
+ "nfscis",
+ "nfsmxp",
+ "nfsmxs"
+};
+
+
+int32_t
+nfs4_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ NFS4ProfileState state,
+ UParseError* parseError,
+ UErrorCode* status){
+
+ UChar b1Stack[NFS4_MAX_BUFFER_SIZE],
+ b2Stack[NFS4_MAX_BUFFER_SIZE];
+ char b3Stack[NFS4_MAX_BUFFER_SIZE];
+
+ /* initialize pointers to stack buffers */
+ UChar *b1 = b1Stack, *b2 = b2Stack;
+ char *b3=b3Stack;
+ int32_t b1Len=0, b2Len=0, b3Len=0,
+ b1Capacity = NFS4_MAX_BUFFER_SIZE,
+ b2Capacity = NFS4_MAX_BUFFER_SIZE,
+ b3Capacity = NFS4_MAX_BUFFER_SIZE,
+ reqLength=0;
+
+ UStringPrepProfile* profile = NULL;
+ /* get the test data path */
+ const char *testdatapath = NULL;
+
+ if(status==NULL || U_FAILURE(*status)){
+ return 0;
+ }
+ if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ testdatapath = loadTestData(status);
+
+ /* convert the string from UTF-8 to UTF-16 */
+ u_strFromUTF8(b1,b1Capacity,&b1Len,src,srcLength,status);
+ if(*status == U_BUFFER_OVERFLOW_ERROR){
+
+ /* reset the status */
+ *status = U_ZERO_ERROR;
+
+ b1 = (UChar*) malloc(b1Len * U_SIZEOF_UCHAR);
+ if(b1==NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ goto CLEANUP;
+ }
+
+ b1Capacity = b1Len;
+ u_strFromUTF8(b1, b1Capacity, &b1Len, src, srcLength, status);
+ }
+
+ /* open the profile */
+ profile = usprep_open(testdatapath, NFS4DataFileNames[state], status);
+ /* prepare the string */
+ b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Capacity, USPREP_DEFAULT, parseError, status);
+ if(*status == U_BUFFER_OVERFLOW_ERROR){
+ *status = U_ZERO_ERROR;
+ b2 = (UChar*) malloc(b2Len * U_SIZEOF_UCHAR);
+ if(b2== NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ goto CLEANUP;
+ }
+ b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Len, USPREP_DEFAULT, parseError, status);
+ }
+
+ /* convert the string back to UTF-8 */
+ u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status);
+ if(*status == U_BUFFER_OVERFLOW_ERROR){
+ *status = U_ZERO_ERROR;
+ b3 = (char*) malloc(b3Len);
+ if(b3== NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ goto CLEANUP;
+ }
+ b3Capacity = b3Len;
+ u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status);
+ }
+
+ reqLength = b3Len;
+ if(dest!=NULL && reqLength <= destCapacity){
+ memmove(dest, b3, reqLength);
+ }
+
+CLEANUP:
+ if(b1!=b1Stack){
+ free(b1);
+ }
+ if(b2!=b2Stack){
+ free(b2);
+ }
+ if(b3!=b3Stack){
+ free(b3);
+ }
+
+ return u_terminateChars(dest, destCapacity, reqLength, status);
+}
+
+/* sorted array for binary search*/
+static const char* special_prefixes[]={
+ "\x0041\x004e\x004f\x004e\x0059\x004d\x004f\x0055\x0053",
+ "\x0041\x0055\x0054\x0048\x0045\x004e\x0054\x0049\x0043\x0041\x0054\x0045\x0044",
+ "\x0042\x0041\x0054\x0043\x0048",
+ "\x0044\x0049\x0041\x004c\x0055\x0050",
+ "\x0045\x0056\x0045\x0052\x0059\x004f\x004e\x0045",
+ "\x0047\x0052\x004f\x0055\x0050",
+ "\x0049\x004e\x0054\x0045\x0052\x0041\x0043\x0054\x0049\x0056\x0045",
+ "\x004e\x0045\x0054\x0057\x004f\x0052\x004b",
+ "\x004f\x0057\x004e\x0045\x0052",
+};
+
+
+/* binary search the sorted array */
+static int
+findStringIndex(const char* const *sortedArr, int32_t sortedArrLen, const char* target, int32_t targetLen){
+
+ int left, middle, right,rc;
+
+ left =0;
+ right= sortedArrLen-1;
+
+ while(left <= right){
+ middle = (left+right)/2;
+ rc=strncmp(sortedArr[middle],target, targetLen);
+
+ if(rc<0){
+ left = middle+1;
+ }else if(rc >0){
+ right = middle -1;
+ }else{
+ return middle;
+ }
+ }
+ return -1;
+}
+
+static void
+getPrefixSuffix(const char *src, int32_t srcLength,
+ const char **prefix, int32_t *prefixLen,
+ const char **suffix, int32_t *suffixLen,
+ UErrorCode *status){
+
+ int32_t i=0;
+ *prefix = src;
+ while(i<srcLength){
+ if(src[i] == PREFIX_SUFFIX_SEPARATOR){
+ if((i+1) == srcLength){
+ /* we reached the end of the string */
+ *suffix = NULL;
+ i++;
+ break;
+ }
+ i++;/* the prefix contains the separator */
+ *suffix = src + i;
+ break;
+ }
+ i++;
+ }
+ *prefixLen = i;
+ *suffixLen = srcLength - i;
+ /* special prefixes must not be followed by suffixes! */
+ if((findStringIndex(special_prefixes,LENGTHOF(special_prefixes), *prefix, *prefixLen-1) != -1) && (*suffix != NULL)){
+ *status = U_PARSE_ERROR;
+ return;
+ }
+
+}
+
+int32_t
+nfs4_mixed_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UParseError* parseError,
+ UErrorCode* status){
+
+ const char *prefix = NULL, *suffix = NULL;
+ int32_t prefixLen=0, suffixLen=0;
+ char pStack[NFS4_MAX_BUFFER_SIZE],
+ sStack[NFS4_MAX_BUFFER_SIZE];
+ char *p=pStack, *s=sStack;
+ int32_t pLen=0, sLen=0, reqLen=0,
+ pCapacity = NFS4_MAX_BUFFER_SIZE,
+ sCapacity = NFS4_MAX_BUFFER_SIZE;
+
+
+ if(status==NULL || U_FAILURE(*status)){
+ return 0;
+ }
+ if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ if(srcLength == -1){
+ srcLength = (int32_t)strlen(src);
+ }
+ getPrefixSuffix(src, srcLength, &prefix, &prefixLen, &suffix, &suffixLen, status);
+
+ /* prepare the prefix */
+ pLen = nfs4_prepare(prefix, prefixLen, p, pCapacity, NFS4_MIXED_PREP_PREFIX, parseError, status);
+ if(*status == U_BUFFER_OVERFLOW_ERROR){
+ *status = U_ZERO_ERROR;
+ p = (char*) malloc(pLen);
+ if(p == NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ goto CLEANUP;
+ }
+ pLen = nfs4_prepare(prefix, prefixLen, p, pLen, NFS4_MIXED_PREP_PREFIX, parseError, status);
+ }
+
+ /* prepare the suffix */
+ if(suffix != NULL){
+ sLen = nfs4_prepare(suffix, suffixLen, s, sCapacity, NFS4_MIXED_PREP_SUFFIX, parseError, status);
+ if(*status == U_BUFFER_OVERFLOW_ERROR){
+ *status = U_ZERO_ERROR;
+ s = (char*) malloc(pLen);
+ if(s == NULL){
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ goto CLEANUP;
+ }
+ sLen = nfs4_prepare(suffix, suffixLen, s, sLen, NFS4_MIXED_PREP_SUFFIX, parseError, status);
+ }
+ }
+ reqLen = pLen+sLen+1 /* for the delimiter */;
+ if(dest != NULL && reqLen <= destCapacity){
+ memmove(dest, p, pLen);
+ /* add the suffix */
+ if(suffix!=NULL){
+ dest[pLen++] = PREFIX_SUFFIX_SEPARATOR;
+ memmove(dest+pLen, s, sLen);
+ }
+ }
+
+CLEANUP:
+ if(p != pStack){
+ free(p);
+ }
+ if(s != sStack){
+ free(s);
+ }
+
+ return u_terminateChars(dest, destCapacity, reqLen, status);
+}
+
+int32_t
+nfs4_cis_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UParseError* parseError,
+ UErrorCode* status){
+ return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CIS_PREP, parseError, status);
+}
+
+
+int32_t
+nfs4_cs_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UBool isCaseSensitive,
+ UParseError* parseError,
+ UErrorCode* status){
+ if(isCaseSensitive){
+ return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CS, parseError, status);
+ }else{
+ return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CI, parseError, status);
+ }
+}
+
+#endif
+/*
+ * Hey, Emacs, please set the following:
+ *
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h
new file mode 100644
index 00000000000..fe3e63d5429
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nfsprep.h
@@ -0,0 +1,113 @@
+/*
+ *******************************************************************************
+ *
+ * Copyright (C) 2003, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *
+ *******************************************************************************
+ * file name: nfsprep.h
+ * encoding: US-ASCII
+ * tab size: 8 (not used)
+ * indentation:4
+ *
+ * created on: 2003jul11
+ * created by: Ram Viswanadha
+ */
+#ifndef _NFSPREP_H
+#define _NFSPREP_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_IDNA
+
+#include "unicode/ustring.h"
+#include "unicode/usprep.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+/* this enum must be kept in syn with NFS4DataFileNames array in nfsprep.c */
+enum NFS4ProfileState{
+ NFS4_CS_PREP_CS,
+ NFS4_CS_PREP_CI,
+ NFS4_CIS_PREP,
+ NFS4_MIXED_PREP_PREFIX,
+ NFS4_MIXED_PREP_SUFFIX
+};
+
+typedef enum NFS4ProfileState NFS4ProfileState;
+
+/**
+ * Prepares the source UTF-8 string for use in file names and
+ * returns UTF-8 string on output.
+ * @param src
+ * @param srcLen
+ * @param dest
+ * @param destCapacity
+ * @param state
+ * @param parseError
+ * @param status
+ */
+int32_t
+nfs4_prepare(const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ NFS4ProfileState state,
+ UParseError* parseError,
+ UErrorCode* status);
+
+/**
+ * @param dest
+ * @param destCapacity
+ * @param src
+ * @param srcLen
+ * @param state
+ * @param parseError
+ * @param status
+ */
+int32_t
+nfs4_mixed_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UParseError* parseError,
+ UErrorCode* status);
+
+/**
+ * @param dest
+ * @param destCapacity
+ * @param src
+ * @param srcLen
+ * @param state
+ * @param parseError
+ * @param status
+ */
+int32_t
+nfs4_cis_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UParseError* parseError,
+ UErrorCode* status);
+
+/**
+ * @param dest
+ * @param destCapacity
+ * @param src
+ * @param srcLen
+ * @param state
+ * @param parseError
+ * @param status
+ */
+int32_t
+nfs4_cs_prepare( const char* src, int32_t srcLength,
+ char* dest, int32_t destCapacity,
+ UBool isCaseSensitive,
+ UParseError* parseError,
+ UErrorCode* status);
+#endif
+
+#endif
+/*
+ * Hey, Emacs, please set the following:
+ *
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c
new file mode 100644
index 00000000000..bdd84eb0023
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.c
@@ -0,0 +1,5369 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*******************************************************************************
+*
+* File CCONVTST.C
+*
+* Modification History:
+* Name Description
+* Steven R. Loomis 7/8/1999 Adding input buffer test
+********************************************************************************
+*/
+#include <stdio.h>
+#include "cstring.h"
+#include "unicode/uloc.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_err.h"
+#include "cintltst.h"
+#include "unicode/utypes.h"
+#include "unicode/ustring.h"
+#include "unicode/ucol.h"
+#include "cmemory.h"
+
+static void TestNextUChar(UConverter* cnv, const char* source, const char* limit, const int32_t results[], const char* message);
+static void TestNextUCharError(UConverter* cnv, const char* source, const char* limit, UErrorCode expected, const char* message);
+#if !UCONFIG_NO_COLLATION
+static void TestJitterbug981(void);
+#endif
+static void TestJitterbug1293(void);
+static void TestNewConvertWithBufferSizes(int32_t osize, int32_t isize) ;
+static void TestConverterTypesAndStarters(void);
+static void TestAmbiguous(void);
+static void TestSignatureDetection(void);
+static void TestUTF7(void);
+static void TestIMAP(void);
+static void TestUTF8(void);
+static void TestCESU8(void);
+static void TestUTF16(void);
+static void TestUTF16BE(void);
+static void TestUTF16LE(void);
+static void TestUTF32(void);
+static void TestUTF32BE(void);
+static void TestUTF32LE(void);
+static void TestLATIN1(void);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestSBCS(void);
+static void TestDBCS(void);
+static void TestMBCS(void);
+
+#ifdef U_ENABLE_GENERIC_ISO_2022
+static void TestISO_2022(void);
+#endif
+
+static void TestISO_2022_JP(void);
+static void TestISO_2022_JP_1(void);
+static void TestISO_2022_JP_2(void);
+static void TestISO_2022_KR(void);
+static void TestISO_2022_KR_1(void);
+static void TestISO_2022_CN(void);
+static void TestISO_2022_CN_EXT(void);
+static void TestJIS(void);
+static void TestHZ(void);
+#endif
+
+static void TestSCSU(void);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestEBCDIC_STATEFUL(void);
+static void TestGB18030(void);
+static void TestLMBCS(void);
+static void TestJitterbug255(void);
+static void TestEBCDICUS4XML(void);
+static void TestJitterbug915(void);
+static void TestISCII(void);
+
+static void TestCoverageMBCS(void);
+static void TestJitterbug2346(void);
+static void TestJitterbug2411(void);
+static void TestJB5275(void);
+static void TestJB5275_1(void);
+#endif
+
+static void TestRoundTrippingAllUTF(void);
+static void TestConv(const uint16_t in[],
+ int len,
+ const char* conv,
+ const char* lang,
+ char byteArr[],
+ int byteArrLen);
+void addTestNewConvert(TestNode** root);
+
+/* open a converter, using test data if it begins with '@' */
+static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err);
+
+
+#define NEW_MAX_BUFFER 999
+
+static int32_t gInBufferSize = NEW_MAX_BUFFER;
+static int32_t gOutBufferSize = NEW_MAX_BUFFER;
+static char gNuConvTestName[1024];
+
+#define nct_min(x,y) ((x<y) ? x : y)
+
+static UConverter *my_ucnv_open(const char *cnv, UErrorCode *err)
+{
+ if(cnv && cnv[0] == '@') {
+ return ucnv_openPackage(loadTestData(err), cnv+1, err);
+ } else {
+ return ucnv_open(cnv, err);
+ }
+}
+
+static void printSeq(const unsigned char* a, int len)
+{
+ int i=0;
+ log_verbose("{");
+ while (i<len)
+ log_verbose("0x%02x ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printUSeq(const UChar* a, int len)
+{
+ int i=0;
+ log_verbose("{U+");
+ while (i<len) log_verbose("0x%04x ", a[i++]);
+ log_verbose("}\n");
+}
+
+static void printSeqErr(const unsigned char* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{");
+ while (i<len)
+ fprintf(stderr, "0x%02x ", a[i++]);
+ fprintf(stderr, "}\n");
+}
+
+static void printUSeqErr(const UChar* a, int len)
+{
+ int i=0;
+ fprintf(stderr, "{U+");
+ while (i<len)
+ fprintf(stderr, "0x%04x ", a[i++]);
+ fprintf(stderr,"}\n");
+}
+
+static void
+TestNextUChar(UConverter* cnv, const char* source, const char* limit, const int32_t results[], const char* message)
+{
+ const char* s0;
+ const char* s=(char*)source;
+ const int32_t *r=results;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UChar32 c;
+
+ while(s<limit) {
+ s0=s;
+ c=ucnv_getNextUChar(cnv, &s, limit, &errorCode);
+ if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
+ break; /* no more significant input */
+ } else if(U_FAILURE(errorCode)) {
+ log_err("%s ucnv_getNextUChar() failed: %s\n", message, u_errorName(errorCode));
+ break;
+ } else if(
+ /* test the expected number of input bytes only if >=0 */
+ (*r>=0 && (int32_t)(s-s0)!=*r) ||
+ c!=*(r+1)
+ ) {
+ log_err("%s ucnv_getNextUChar() result %lx from %d bytes, should have been %lx from %d bytes.\n",
+ message, c, (s-s0), *(r+1), *r);
+ break;
+ }
+ r+=2;
+ }
+}
+
+static void
+TestNextUCharError(UConverter* cnv, const char* source, const char* limit, UErrorCode expected, const char* message)
+{
+ const char* s=(char*)source;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ uint32_t c;
+ c=ucnv_getNextUChar(cnv, &s, limit, &errorCode);
+ if(errorCode != expected){
+ log_err("FAIL: Expected:%s when %s-----Got:%s\n", myErrorName(expected), message, myErrorName(errorCode));
+ }
+ if(c != 0xFFFD && c != 0xffff){
+ log_err("FAIL: Expected return value of 0xfffd or 0xffff when %s-----Got 0x%lx\n", message, c);
+ }
+
+}
+
+static void TestInBufSizes(void)
+{
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,1);
+#if 1
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,2);
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,3);
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,4);
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,5);
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,6);
+ TestNewConvertWithBufferSizes(1,1);
+ TestNewConvertWithBufferSizes(2,3);
+ TestNewConvertWithBufferSizes(3,2);
+#endif
+}
+
+static void TestOutBufSizes(void)
+{
+#if 1
+ TestNewConvertWithBufferSizes(NEW_MAX_BUFFER,NEW_MAX_BUFFER);
+ TestNewConvertWithBufferSizes(1,NEW_MAX_BUFFER);
+ TestNewConvertWithBufferSizes(2,NEW_MAX_BUFFER);
+ TestNewConvertWithBufferSizes(3,NEW_MAX_BUFFER);
+ TestNewConvertWithBufferSizes(4,NEW_MAX_BUFFER);
+ TestNewConvertWithBufferSizes(5,NEW_MAX_BUFFER);
+
+#endif
+}
+
+
+void addTestNewConvert(TestNode** root)
+{
+ addTest(root, &TestInBufSizes, "tsconv/nucnvtst/TestInBufSizes");
+ addTest(root, &TestOutBufSizes, "tsconv/nucnvtst/TestOutBufSizes");
+ addTest(root, &TestConverterTypesAndStarters, "tsconv/nucnvtst/TestConverterTypesAndStarters");
+ addTest(root, &TestAmbiguous, "tsconv/nucnvtst/TestAmbiguous");
+ addTest(root, &TestSignatureDetection, "tsconv/nucnvtst/TestSignatureDetection");
+ addTest(root, &TestUTF7, "tsconv/nucnvtst/TestUTF7");
+ addTest(root, &TestIMAP, "tsconv/nucnvtst/TestIMAP");
+ addTest(root, &TestUTF8, "tsconv/nucnvtst/TestUTF8");
+
+ /* test ucnv_getNextUChar() for charsets that encode single surrogates with complete byte sequences */
+ addTest(root, &TestCESU8, "tsconv/nucnvtst/TestCESU8");
+ addTest(root, &TestUTF16, "tsconv/nucnvtst/TestUTF16");
+ addTest(root, &TestUTF16BE, "tsconv/nucnvtst/TestUTF16BE");
+ addTest(root, &TestUTF16LE, "tsconv/nucnvtst/TestUTF16LE");
+ addTest(root, &TestUTF32, "tsconv/nucnvtst/TestUTF32");
+ addTest(root, &TestUTF32BE, "tsconv/nucnvtst/TestUTF32BE");
+ addTest(root, &TestUTF32LE, "tsconv/nucnvtst/TestUTF32LE");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestLMBCS, "tsconv/nucnvtst/TestLMBCS");
+#endif
+
+ addTest(root, &TestLATIN1, "tsconv/nucnvtst/TestLATIN1");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestSBCS, "tsconv/nucnvtst/TestSBCS");
+ addTest(root, &TestDBCS, "tsconv/nucnvtst/TestDBCS");
+ addTest(root, &TestMBCS, "tsconv/nucnvtst/TestMBCS");
+
+#ifdef U_ENABLE_GENERIC_ISO_2022
+ addTest(root, &TestISO_2022, "tsconv/nucnvtst/TestISO_2022");
+#endif
+
+ addTest(root, &TestISO_2022_JP, "tsconv/nucnvtst/TestISO_2022_JP");
+ addTest(root, &TestJIS, "tsconv/nucnvtst/TestJIS");
+ addTest(root, &TestISO_2022_JP_1, "tsconv/nucnvtst/TestISO_2022_JP_1");
+ addTest(root, &TestISO_2022_JP_2, "tsconv/nucnvtst/TestISO_2022_JP_2");
+ addTest(root, &TestISO_2022_KR, "tsconv/nucnvtst/TestISO_2022_KR");
+ addTest(root, &TestISO_2022_KR_1, "tsconv/nucnvtst/TestISO_2022_KR_1");
+ addTest(root, &TestISO_2022_CN, "tsconv/nucnvtst/TestISO_2022_CN");
+ addTest(root, &TestISO_2022_CN_EXT, "tsconv/nucnvtst/TestISO_2022_CN_EXT");
+ addTest(root, &TestJitterbug915, "tsconv/nucnvtst/TestJitterbug915");
+ addTest(root, &TestHZ, "tsconv/nucnvtst/TestHZ");
+#endif
+
+ addTest(root, &TestSCSU, "tsconv/nucnvtst/TestSCSU");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestEBCDIC_STATEFUL, "tsconv/nucnvtst/TestEBCDIC_STATEFUL");
+ addTest(root, &TestGB18030, "tsconv/nucnvtst/TestGB18030");
+ addTest(root, &TestJitterbug255, "tsconv/nucnvtst/TestJitterbug255");
+ addTest(root, &TestEBCDICUS4XML, "tsconv/nucnvtst/TestEBCDICUS4XML");
+ addTest(root, &TestISCII, "tsconv/nucnvtst/TestISCII");
+ addTest(root, &TestJB5275, "tsconv/nucnvtst/TestJB5275");
+ addTest(root, &TestJB5275_1, "tsconv/nucnvtst/TestJB5275_1");
+#if !UCONFIG_NO_COLLATION
+ addTest(root, &TestJitterbug981, "tsconv/nucnvtst/TestJitterbug981");
+#endif
+
+ addTest(root, &TestJitterbug1293, "tsconv/nucnvtst/TestJitterbug1293");
+#endif
+
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestCoverageMBCS, "tsconv/nucnvtst/TestCoverageMBCS");
+#endif
+
+ addTest(root, &TestRoundTrippingAllUTF, "tsconv/nucnvtst/TestRoundTrippingAllUTF");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestJitterbug2346, "tsconv/nucnvtst/TestJitterbug2346");
+ addTest(root, &TestJitterbug2411, "tsconv/nucnvtst/TestJitterbug2411");
+#endif
+
+}
+
+
+/* Note that this test already makes use of statics, so it's not really
+ multithread safe.
+ This convenience function lets us make the error messages actually useful.
+*/
+
+static void setNuConvTestName(const char *codepage, const char *direction)
+{
+ sprintf(gNuConvTestName, "[Testing %s %s Unicode, InputBufSiz=%d, OutputBufSiz=%d]",
+ codepage,
+ direction,
+ (int)gInBufferSize,
+ (int)gOutBufferSize);
+}
+
+typedef enum
+{
+ TC_OK = 0, /* test was OK */
+ TC_MISMATCH = 1, /* Match failed - err was printed */
+ TC_FAIL = 2 /* Test failed, don't print an err because it was already printed. */
+} ETestConvertResult;
+
+/* Note: This function uses global variables and it will not do offset
+checking without gOutBufferSize and gInBufferSize set to NEW_MAX_BUFFER */
+static ETestConvertResult testConvertFromU( const UChar *source, int sourceLen, const uint8_t *expect, int expectLen,
+ const char *codepage, const int32_t *expectOffsets , UBool useFallback)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ char junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ char *p;
+ const UChar *src;
+ char *end;
+ char *targ;
+ int32_t *offs;
+ int i;
+ int32_t realBufferSize;
+ char *realBufferEnd;
+ const UChar *realSourceEnd;
+ const UChar *sourceLimit;
+ UBool checkOffsets = TRUE;
+ UBool doFlush;
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = (char)0xF0;
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = 0xFF;
+
+ setNuConvTestName(codepage, "FROM");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = my_ucnv_open(codepage, &status);
+
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",codepage);
+ return TC_FAIL;
+ }
+ if(useFallback){
+ ucnv_setFallback(conv,useFallback);
+ }
+
+ log_verbose("Converter opened..\n");
+
+ src = source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = source + sourceLen;
+
+ if ( gOutBufferSize != realBufferSize || gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min(targ + gOutBufferSize, realBufferEnd);
+ sourceLimit = nct_min(src + gInBufferSize, realSourceEnd);
+
+ doFlush = (UBool)(sourceLimit == realSourceEnd);
+
+ if(targ == realBufferEnd) {
+ log_err("Error, overflowed the real buffer while about to call fromUnicode! targ=%08lx %s", targ, gNuConvTestName);
+ return TC_FAIL;
+ }
+ log_verbose("calling fromUnicode @ SOURCE:%08lx to %08lx TARGET: %08lx to %08lx, flush=%s\n", src,sourceLimit, targ,end, doFlush?"TRUE":"FALSE");
+
+
+ status = U_ZERO_ERROR;
+
+ ucnv_fromUnicode (conv,
+ &targ,
+ end,
+ &src,
+ sourceLimit,
+ checkOffsets ? offs : NULL,
+ doFlush, /* flush if we're at the end of the input data */
+ &status);
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && sourceLimit < realSourceEnd) );
+
+ if(U_FAILURE(status)) {
+ log_err("Problem doing fromUnicode to %s, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName);
+ return TC_FAIL;
+ }
+
+ log_verbose("\nConversion done [%d uchars in -> %d chars out]. \nResult :",
+ sourceLen, targ-junkout);
+
+ if(VERBOSITY)
+ {
+ char junk[9999];
+ char offset_str[9999];
+ char *ptr;
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+ for(ptr = junkout;ptr<targ;ptr++) {
+ sprintf(junk + strlen(junk), "0x%02x, ", (int)(0xFF & *ptr));
+ sprintf(offset_str + strlen(offset_str), "0x%02x, ", (int)(0xFF & junokout[ptr-junkout]));
+ }
+
+ log_verbose(junk);
+ printSeq((const uint8_t *)expect, expectLen);
+ if ( checkOffsets ) {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ if(expectLen != targ-junkout) {
+ log_err("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ log_verbose("Expected %d chars out, got %d %s\n", expectLen, targ-junkout, gNuConvTestName);
+ printf("\nGot:");
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ printf("\nExpected:");
+ printSeqErr((const unsigned char*)expect, expectLen);
+ return TC_MISMATCH;
+ }
+
+ if (checkOffsets && (expectOffsets != 0) ) {
+ log_verbose("comparing %d offsets..\n", targ-junkout);
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t) )){
+ log_err("did not get the expected offsets. %s\n", gNuConvTestName);
+ printSeqErr((const unsigned char*)junkout, (int32_t)(targ-junkout));
+ log_err("\n");
+ log_err("Got : ");
+ for(p=junkout;p<targ;p++) {
+ log_err("%d,", junokout[p-junkout]);
+ }
+ log_err("\n");
+ log_err("Expected: ");
+ for(i=0; i<(targ-junkout); i++) {
+ log_err("%d,", expectOffsets[i]);
+ }
+ log_err("\n");
+ }
+ }
+
+ log_verbose("comparing..\n");
+ if(!memcmp(junkout, expect, expectLen)) {
+ log_verbose("Matches!\n");
+ return TC_OK;
+ } else {
+ log_err("String does not match u->%s\n", gNuConvTestName);
+ printUSeqErr(source, sourceLen);
+ printf("\nGot:");
+ printSeqErr((const unsigned char *)junkout, expectLen);
+ printf("\nExpected:");
+ printSeqErr((const unsigned char *)expect, expectLen);
+
+ return TC_MISMATCH;
+ }
+}
+
+/* Note: This function uses global variables and it will not do offset
+checking without gOutBufferSize and gInBufferSize set to NEW_MAX_BUFFER */
+static ETestConvertResult testConvertToU( const uint8_t *source, int sourcelen, const UChar *expect, int expectlen,
+ const char *codepage, const int32_t *expectOffsets, UBool useFallback)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = 0;
+ UChar junkout[NEW_MAX_BUFFER]; /* FIX */
+ int32_t junokout[NEW_MAX_BUFFER]; /* FIX */
+ const char *src;
+ const char *realSourceEnd;
+ const char *srcLimit;
+ UChar *p;
+ UChar *targ;
+ UChar *end;
+ int32_t *offs;
+ int i;
+ UBool checkOffsets = TRUE;
+
+ int32_t realBufferSize;
+ UChar *realBufferEnd;
+
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junkout[i] = 0xFFFE;
+
+ for(i=0;i<NEW_MAX_BUFFER;i++)
+ junokout[i] = -1;
+
+ setNuConvTestName(codepage, "TO");
+
+ log_verbose("\n========= %s\n", gNuConvTestName);
+
+ conv = my_ucnv_open(codepage, &status);
+
+ if(U_FAILURE(status))
+ {
+ log_data_err("Couldn't open converter %s\n",gNuConvTestName);
+ return TC_FAIL;
+ }
+ if(useFallback){
+ ucnv_setFallback(conv,useFallback);
+ }
+ log_verbose("Converter opened..\n");
+
+ src = (const char *)source;
+ targ = junkout;
+ offs = junokout;
+
+ realBufferSize = (sizeof(junkout)/sizeof(junkout[0]));
+ realBufferEnd = junkout + realBufferSize;
+ realSourceEnd = src + sourcelen;
+
+ if ( gOutBufferSize != realBufferSize || gInBufferSize != NEW_MAX_BUFFER )
+ checkOffsets = FALSE;
+
+ do
+ {
+ end = nct_min( targ + gOutBufferSize, realBufferEnd);
+ srcLimit = nct_min(realSourceEnd, src + gInBufferSize);
+
+ if(targ == realBufferEnd)
+ {
+ log_err("Error, the end would overflow the real output buffer while about to call toUnicode! tarjet=%08lx %s",targ,gNuConvTestName);
+ return TC_FAIL;
+ }
+ log_verbose("calling toUnicode @ %08lx to %08lx\n", targ,end);
+
+ /* oldTarg = targ; */
+
+ status = U_ZERO_ERROR;
+
+ ucnv_toUnicode (conv,
+ &targ,
+ end,
+ &src,
+ srcLimit,
+ checkOffsets ? offs : NULL,
+ (UBool)(srcLimit == realSourceEnd), /* flush if we're at the end of hte source data */
+ &status);
+
+ /* offs += (targ-oldTarg); */
+
+ } while ( (status == U_BUFFER_OVERFLOW_ERROR) || (U_SUCCESS(status) && (srcLimit < realSourceEnd)) ); /* while we just need another buffer */
+
+ if(U_FAILURE(status))
+ {
+ log_err("Problem doing %s toUnicode, errcode %s %s\n", codepage, myErrorName(status), gNuConvTestName);
+ return TC_FAIL;
+ }
+
+ log_verbose("\nConversion done. %d bytes -> %d chars.\nResult :",
+ sourcelen, targ-junkout);
+ if(VERBOSITY)
+ {
+ char junk[9999];
+ char offset_str[9999];
+ UChar *ptr;
+
+ junk[0] = 0;
+ offset_str[0] = 0;
+
+ for(ptr = junkout;ptr<targ;ptr++)
+ {
+ sprintf(junk + strlen(junk), "0x%04x, ", (0xFFFF) & (unsigned int)*ptr);
+ sprintf(offset_str + strlen(offset_str), "0x%04x, ", (0xFFFF) & (unsigned int)junokout[ptr-junkout]);
+ }
+
+ log_verbose(junk);
+ printUSeq(expect, expectlen);
+ if ( checkOffsets )
+ {
+ log_verbose("\nOffsets:");
+ log_verbose(offset_str);
+ }
+ log_verbose("\n");
+ }
+ ucnv_close(conv);
+
+ log_verbose("comparing %d uchars (%d bytes)..\n",expectlen,expectlen*2);
+
+ if (checkOffsets && (expectOffsets != 0))
+ {
+ if(memcmp(junokout,expectOffsets,(targ-junkout) * sizeof(int32_t))){
+ log_err("did not get the expected offsets. %s\n",gNuConvTestName);
+ log_err("Got: ");
+ for(p=junkout;p<targ;p++) {
+ log_err("%d,", junokout[p-junkout]);
+ }
+ log_err("\n");
+ log_err("Expected: ");
+ for(i=0; i<(targ-junkout); i++) {
+ log_err("%d,", expectOffsets[i]);
+ }
+ log_err("\n");
+ log_err("output: ");
+ for(i=0; i<(targ-junkout); i++) {
+ log_err("%X,", junkout[i]);
+ }
+ log_err("\n");
+ log_err("input: ");
+ for(i=0; i<(src-(const char *)source); i++) {
+ log_err("%X,", (unsigned char)source[i]);
+ }
+ log_err("\n");
+ }
+ }
+
+ if(!memcmp(junkout, expect, expectlen*2))
+ {
+ log_verbose("Matches!\n");
+ return TC_OK;
+ }
+ else
+ {
+ log_err("String does not match. %s\n", gNuConvTestName);
+ log_verbose("String does not match. %s\n", gNuConvTestName);
+ printf("\nGot:");
+ printUSeqErr(junkout, expectlen);
+ printf("\nExpected:");
+ printUSeqErr(expect, expectlen);
+ return TC_MISMATCH;
+ }
+}
+
+
+static void TestNewConvertWithBufferSizes(int32_t outsize, int32_t insize )
+{
+/** test chars #1 */
+ /* 1 2 3 1Han 2Han 3Han . */
+ static const UChar sampleText[] =
+ { 0x0031, 0x0032, 0x0033, 0x0000, 0x4e00, 0x4e8c, 0x4e09, 0x002E };
+
+
+ static const uint8_t expectedUTF8[] =
+ { 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E };
+ static const int32_t toUTF8Offs[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07};
+ static const int32_t fmUTF8Offs[] =
+ { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, 0x000d };
+
+#ifdef U_ENABLE_GENERIC_ISO_2022
+ /* Same as UTF8, but with ^[%B preceeding */
+ static const const uint8_t expectedISO2022[] =
+ { 0x1b, 0x25, 0x42, 0x31, 0x32, 0x33, 0x00, 0xe4, 0xb8, 0x80, 0xe4, 0xba, 0x8c, 0xe4, 0xb8, 0x89, 0x2E };
+ static const int32_t toISO2022Offs[] =
+ { -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x04,
+ 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07 }; /* right? */
+ static const int32_t fmISO2022Offs[] =
+ { 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x000a, 0x000d, 0x0010 }; /* is this right? */
+#endif
+
+ /* 1 2 3 0, <SO> h1 h2 h3 <SI> . EBCDIC_STATEFUL */
+ static const uint8_t expectedIBM930[] =
+ { 0xF1, 0xF2, 0xF3, 0x00, 0x0E, 0x45, 0x41, 0x45, 0x42, 0x45, 0x43, 0x0F, 0x4B };
+ static const int32_t toIBM930Offs[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, };
+ static const int32_t fmIBM930Offs[] =
+ { 0x0000, 0x0001, 0x0002, 0x0003, 0x0005, 0x0007, 0x0009, 0x000c};
+
+ /* 1 2 3 0 h1 h2 h3 . MBCS*/
+ static const uint8_t expectedIBM943[] =
+ { 0x31, 0x32, 0x33, 0x00, 0x88, 0xea, 0x93, 0xf1, 0x8e, 0x4f, 0x2e };
+ static const int32_t toIBM943Offs [] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07 };
+ static const int32_t fmIBM943Offs[] =
+ { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0006, 0x0008, 0x000a};
+
+ /* 1 2 3 0 h1 h2 h3 . DBCS*/
+ static const uint8_t expectedIBM9027[] =
+ { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x4c, 0x41, 0x4c, 0x48, 0x4c, 0x55, 0xfe, 0xfe};
+ static const int32_t toIBM9027Offs [] =
+ { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07};
+
+ /* 1 2 3 0 <?> <?> <?> . SBCS*/
+ static const uint8_t expectedIBM920[] =
+ { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2e };
+ static const int32_t toIBM920Offs [] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
+
+ /* 1 2 3 0 <?> <?> <?> . SBCS*/
+ static const uint8_t expectedISO88593[] =
+ { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2E };
+ static const int32_t toISO88593Offs[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+ /* 1 2 3 0 <?> <?> <?> . <?> LATIN_1*/
+ static const uint8_t expectedLATIN1[] =
+ { 0x31, 0x32, 0x33, 0x00, 0x1a, 0x1a, 0x1a, 0x2E };
+ static const int32_t toLATIN1Offs[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+
+
+ /* etc */
+ static const uint8_t expectedUTF16BE[] =
+ { 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x4e, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x00, 0x2e };
+ static const int32_t toUTF16BEOffs[]=
+ { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07};
+ static const int32_t fmUTF16BEOffs[] =
+ { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e };
+
+ static const uint8_t expectedUTF16LE[] =
+ { 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x8c, 0x4e, 0x09, 0x4e, 0x2e, 0x00 };
+ static const int32_t toUTF16LEOffs[]=
+ { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07};
+ static const int32_t fmUTF16LEOffs[] =
+ { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e };
+
+ static const uint8_t expectedUTF32BE[] =
+ { 0x00, 0x00, 0x00, 0x31,
+ 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4e, 0x00,
+ 0x00, 0x00, 0x4e, 0x8c,
+ 0x00, 0x00, 0x4e, 0x09,
+ 0x00, 0x00, 0x00, 0x2e };
+ static const int32_t toUTF32BEOffs[]=
+ { 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08 };
+ static const int32_t fmUTF32BEOffs[] =
+ { 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c };
+
+ static const uint8_t expectedUTF32LE[] =
+ { 0x31, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0x00, 0x00,
+ 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4e, 0x00, 0x00,
+ 0x8c, 0x4e, 0x00, 0x00,
+ 0x09, 0x4e, 0x00, 0x00,
+ 0x2e, 0x00, 0x00, 0x00 };
+ static const int32_t toUTF32LEOffs[]=
+ { 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06,
+ 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08 };
+ static const int32_t fmUTF32LEOffs[] =
+ { 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c };
+
+
+
+
+/** Test chars #2 **/
+
+ /* Sahha [health], slashed h's */
+ static const UChar malteseUChars[] = { 0x0053, 0x0061, 0x0127, 0x0127, 0x0061 };
+ static const uint8_t expectedMaltese913[] = { 0x53, 0x61, 0xB1, 0xB1, 0x61 };
+
+ /* LMBCS */
+ static const UChar LMBCSUChars[] = { 0x0027, 0x010A, 0x0000, 0x0127, 0x2666, 0x0220 };
+ static const uint8_t expectedLMBCS[] = { 0x27, 0x06, 0x04, 0x00, 0x01, 0x73, 0x01, 0x04, 0x14, 0x02, 0x20 };
+ static const int32_t toLMBCSOffs[] = { 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x04 , 0x05, 0x05, 0x05 };
+ static const int32_t fmLMBCSOffs[] = { 0x0000, 0x0001, 0x0003, 0x0004, 0x0006, 0x0008};
+ /*********************************** START OF CODE finally *************/
+
+ gInBufferSize = insize;
+ gOutBufferSize = outsize;
+
+ log_verbose("\n\n\nTesting conversions with InputBufferSize = %d, OutputBufferSize = %d\n", gInBufferSize, gOutBufferSize);
+
+
+ /*UTF-8*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF8, sizeof(expectedUTF8), "UTF8", toUTF8Offs,FALSE );
+
+ log_verbose("Test surrogate behaviour for UTF8\n");
+ {
+ static const UChar testinput[]={ 0x20ac, 0xd801, 0xdc01, 0xdc01 };
+ static const uint8_t expectedUTF8test2[]= { 0xe2, 0x82, 0xac,
+ 0xf0, 0x90, 0x90, 0x81,
+ 0xef, 0xbf, 0xbd
+ };
+ static const int32_t offsets[]={ 0, 0, 0, 1, 1, 1, 1, 3, 3, 3 };
+ testConvertFromU(testinput, sizeof(testinput)/sizeof(testinput[0]),
+ expectedUTF8test2, sizeof(expectedUTF8test2), "UTF8", offsets,FALSE );
+
+
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION && defined(U_ENABLE_GENERIC_ISO_2022)
+ /*ISO-2022*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedISO2022, sizeof(expectedISO2022), "ISO_2022", toISO2022Offs,FALSE );
+#endif
+
+ /*UTF16 LE*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF16LE, sizeof(expectedUTF16LE), "utf-16le", toUTF16LEOffs,FALSE );
+ /*UTF16 BE*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF16BE, sizeof(expectedUTF16BE), "utf-16be", toUTF16BEOffs,FALSE );
+ /*UTF32 LE*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF32LE, sizeof(expectedUTF32LE), "utf-32le", toUTF32LEOffs,FALSE );
+ /*UTF32 BE*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedUTF32BE, sizeof(expectedUTF32BE), "utf-32be", toUTF32BEOffs,FALSE );
+
+ /*LATIN_1*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedLATIN1, sizeof(expectedLATIN1), "LATIN_1", toLATIN1Offs,FALSE );
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /*EBCDIC_STATEFUL*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedIBM930, sizeof(expectedIBM930), "ibm-930", toIBM930Offs,FALSE );
+
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedISO88593, sizeof(expectedISO88593), "iso-8859-3", toISO88593Offs,FALSE );
+
+ /*MBCS*/
+
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedIBM943, sizeof(expectedIBM943), "ibm-943", toIBM943Offs,FALSE );
+ /*DBCS*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedIBM9027, sizeof(expectedIBM9027), "@ibm9027", toIBM9027Offs,FALSE );
+ /*SBCS*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedIBM920, sizeof(expectedIBM920), "ibm-920", toIBM920Offs,FALSE );
+ /*SBCS*/
+ testConvertFromU(sampleText, sizeof(sampleText)/sizeof(sampleText[0]),
+ expectedISO88593, sizeof(expectedISO88593), "iso-8859-3", toISO88593Offs,FALSE );
+#endif
+
+
+/****/
+
+ /*UTF-8*/
+ testConvertToU(expectedUTF8, sizeof(expectedUTF8),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf8", fmUTF8Offs,FALSE);
+#if !UCONFIG_NO_LEGACY_CONVERSION && defined(U_ENABLE_GENERIC_ISO_2022)
+ /*ISO-2022*/
+ testConvertToU(expectedISO2022, sizeof(expectedISO2022),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ISO_2022", fmISO2022Offs,FALSE);
+#endif
+
+ /*UTF16 LE*/
+ testConvertToU(expectedUTF16LE, sizeof(expectedUTF16LE),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16le", fmUTF16LEOffs,FALSE);
+ /*UTF16 BE*/
+ testConvertToU(expectedUTF16BE, sizeof(expectedUTF16BE),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16be", fmUTF16BEOffs,FALSE);
+ /*UTF32 LE*/
+ testConvertToU(expectedUTF32LE, sizeof(expectedUTF32LE),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-32le", fmUTF32LEOffs,FALSE);
+ /*UTF32 BE*/
+ testConvertToU(expectedUTF32BE, sizeof(expectedUTF32BE),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-32be", fmUTF32BEOffs,FALSE);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /*EBCDIC_STATEFUL*/
+ testConvertToU(expectedIBM930, sizeof(expectedIBM930),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ibm-930", fmIBM930Offs,FALSE);
+ /*MBCS*/
+ testConvertToU(expectedIBM943, sizeof(expectedIBM943),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "ibm-943", fmIBM943Offs,FALSE);
+#endif
+
+ /* Try it again to make sure it still works */
+ testConvertToU(expectedUTF16LE, sizeof(expectedUTF16LE),
+ sampleText, sizeof(sampleText)/sizeof(sampleText[0]), "utf-16le", fmUTF16LEOffs,FALSE);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ testConvertToU(expectedMaltese913, sizeof(expectedMaltese913),
+ malteseUChars, sizeof(malteseUChars)/sizeof(malteseUChars[0]), "latin3", NULL,FALSE);
+
+ testConvertFromU(malteseUChars, sizeof(malteseUChars)/sizeof(malteseUChars[0]),
+ expectedMaltese913, sizeof(expectedMaltese913), "iso-8859-3", NULL,FALSE );
+
+ /*LMBCS*/
+ testConvertFromU(LMBCSUChars, sizeof(LMBCSUChars)/sizeof(LMBCSUChars[0]),
+ expectedLMBCS, sizeof(expectedLMBCS), "LMBCS-1", toLMBCSOffs,FALSE );
+ testConvertToU(expectedLMBCS, sizeof(expectedLMBCS),
+ LMBCSUChars, sizeof(LMBCSUChars)/sizeof(LMBCSUChars[0]), "LMBCS-1", fmLMBCSOffs,FALSE);
+#endif
+
+ /* UTF-7 examples are mostly from http://www.imc.org/rfc2152 */
+ {
+ /* encode directly set D and set O */
+ static const uint8_t utf7[] = {
+ /*
+ Hi Mom -+Jjo--!
+ A+ImIDkQ.
+ +-
+ +ZeVnLIqe
+ */
+ 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x2b, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x21,
+ 0x41, 0x2b, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2e,
+ 0x2b, 0x2d,
+ 0x2b, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65
+ };
+ static const UChar unicode[] = {
+ /*
+ Hi Mom -<WHITE SMILING FACE>-!
+ A<NOT IDENTICAL TO><ALPHA>.
+ +
+ [Japanese word "nihongo"]
+ */
+ 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x263a, 0x2d, 0x21,
+ 0x41, 0x2262, 0x0391, 0x2e,
+ 0x2b,
+ 0x65e5, 0x672c, 0x8a9e
+ };
+ static const int32_t toUnicodeOffsets[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 14,
+ 15, 17, 19, 23,
+ 24,
+ 27, 29, 32
+ };
+ static const int32_t fromUnicodeOffsets[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10,
+ 11, 12, 12, 12, 13, 13, 13, 13, 14,
+ 15, 15,
+ 16, 16, 16, 17, 17, 17, 18, 18, 18
+ };
+
+ /* same but escaping set O (the exclamation mark) */
+ static const uint8_t utf7Restricted[] = {
+ /*
+ Hi Mom -+Jjo--+ACE-
+ A+ImIDkQ.
+ +-
+ +ZeVnLIqe
+ */
+ 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x2b, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x2b, 0x41, 0x43, 0x45, 0x2d,
+ 0x41, 0x2b, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2e,
+ 0x2b, 0x2d,
+ 0x2b, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65
+ };
+ static const int32_t toUnicodeOffsetsR[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 15,
+ 19, 21, 23, 27,
+ 28,
+ 31, 33, 36
+ };
+ static const int32_t fromUnicodeOffsetsR[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10, 10, 10, 10, 10,
+ 11, 12, 12, 12, 13, 13, 13, 13, 14,
+ 15, 15,
+ 16, 16, 16, 17, 17, 17, 18, 18, 18
+ };
+
+ testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, utf7, sizeof(utf7), "UTF-7", fromUnicodeOffsets,FALSE);
+
+ testConvertToU(utf7, sizeof(utf7), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "UTF-7", toUnicodeOffsets,FALSE);
+
+ testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, utf7Restricted, sizeof(utf7Restricted), "UTF-7,version=1", fromUnicodeOffsetsR,FALSE);
+
+ testConvertToU(utf7Restricted, sizeof(utf7Restricted), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "UTF-7,version=1", toUnicodeOffsetsR,FALSE);
+ }
+
+ /*
+ * IMAP-mailbox-name examples are mostly from http://www.imc.org/rfc2152,
+ * modified according to RFC 2060,
+ * and supplemented with the one example in RFC 2060 itself.
+ */
+ {
+ static const uint8_t imap[] = {
+ /* Hi Mom -&Jjo--!
+ A&ImIDkQ-.
+ &-
+ &ZeVnLIqe-
+ \
+ ~peter
+ /mail
+ /&ZeVnLIqe-
+ /&U,BTFw-
+ */
+ 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x26, 0x4a, 0x6a, 0x6f, 0x2d, 0x2d, 0x21,
+ 0x41, 0x26, 0x49, 0x6d, 0x49, 0x44, 0x6b, 0x51, 0x2d, 0x2e,
+ 0x26, 0x2d,
+ 0x26, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65, 0x2d,
+ 0x5c,
+ 0x7e, 0x70, 0x65, 0x74, 0x65, 0x72,
+ 0x2f, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2f, 0x26, 0x5a, 0x65, 0x56, 0x6e, 0x4c, 0x49, 0x71, 0x65, 0x2d,
+ 0x2f, 0x26, 0x55, 0x2c, 0x42, 0x54, 0x46, 0x77, 0x2d
+ };
+ static const UChar unicode[] = {
+ /* Hi Mom -<WHITE SMILING FACE>-!
+ A<NOT IDENTICAL TO><ALPHA>.
+ &
+ [Japanese word "nihongo"]
+ \
+ ~peter
+ /mail
+ /<65e5, 672c, 8a9e>
+ /<53f0, 5317>
+ */
+ 0x48, 0x69, 0x20, 0x4d, 0x6f, 0x6d, 0x20, 0x2d, 0x263a, 0x2d, 0x21,
+ 0x41, 0x2262, 0x0391, 0x2e,
+ 0x26,
+ 0x65e5, 0x672c, 0x8a9e,
+ 0x5c,
+ 0x7e, 0x70, 0x65, 0x74, 0x65, 0x72,
+ 0x2f, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2f, 0x65e5, 0x672c, 0x8a9e,
+ 0x2f, 0x53f0, 0x5317
+ };
+ static const int32_t toUnicodeOffsets[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 14,
+ 15, 17, 19, 24,
+ 25,
+ 28, 30, 33,
+ 37,
+ 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48,
+ 49, 51, 53, 56,
+ 60, 62, 64
+ };
+ static const int32_t fromUnicodeOffsets[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10,
+ 11, 12, 12, 12, 13, 13, 13, 13, 13, 14,
+ 15, 15,
+ 16, 16, 16, 17, 17, 17, 18, 18, 18, 18,
+ 19,
+ 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30,
+ 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 34,
+ 35, 36, 36, 36, 37, 37, 37, 37, 37
+ };
+
+ testConvertFromU(unicode, sizeof(unicode)/U_SIZEOF_UCHAR, imap, sizeof(imap), "IMAP-mailbox-name", fromUnicodeOffsets,FALSE);
+
+ testConvertToU(imap, sizeof(imap), unicode, sizeof(unicode)/U_SIZEOF_UCHAR, "IMAP-mailbox-name", toUnicodeOffsets,FALSE);
+ }
+
+ /* Test UTF-8 bad data handling*/
+ {
+ static const uint8_t utf8[]={
+ 0x61,
+ 0xf7, 0xbf, 0xbf, 0xbf, /* > 10FFFF */
+ 0x00,
+ 0x62,
+ 0xfb, 0xbf, 0xbf, 0xbf, 0xbf, /* > 10FFFF */
+ 0xfb, 0xbf, 0xbf, 0xbf, 0xbf, /* > 10FFFF */
+ 0xf4, 0x8f, 0xbf, 0xbf, /* 10FFFF */
+ 0xdf, 0xbf, /* 7ff */
+ 0xbf, /* truncated tail */
+ 0xf4, 0x90, 0x80, 0x80, /* 11FFFF */
+ 0x02
+ };
+
+ static const uint16_t utf8Expected[]={
+ 0x0061,
+ 0xfffd,
+ 0x0000,
+ 0x0062,
+ 0xfffd,
+ 0xfffd,
+ 0xdbff, 0xdfff,
+ 0x07ff,
+ 0xfffd,
+ 0xfffd,
+ 0x0002
+ };
+
+ static const int32_t utf8Offsets[]={
+ 0, 1, 5, 6, 7, 12, 17, 17, 21, 23, 24, 28
+ };
+ testConvertToU(utf8, sizeof(utf8),
+ utf8Expected, sizeof(utf8Expected)/sizeof(utf8Expected[0]), "utf-8", utf8Offsets ,FALSE);
+
+ }
+
+ /* Test UTF-32BE bad data handling*/
+ {
+ static const uint8_t utf32[]={
+ 0x00, 0x00, 0x00, 0x61,
+ 0x00, 0x11, 0x00, 0x00, /* 0x110000 out of range */
+ 0x00, 0x10, 0xff, 0xff, /* 0x10FFFF in range */
+ 0x00, 0x00, 0x00, 0x62,
+ 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */
+ 0x7f, 0xff, 0xff, 0xff, /* 0x7fffffff out of range */
+ 0x00, 0x00, 0x01, 0x62,
+ 0x00, 0x00, 0x02, 0x62
+ };
+ static const uint16_t utf32Expected[]={
+ 0x0061,
+ 0xfffd, /* 0x110000 out of range */
+ 0xDBFF, /* 0x10FFFF in range */
+ 0xDFFF,
+ 0x0062,
+ 0xfffd, /* 0xffffffff out of range */
+ 0xfffd, /* 0x7fffffff out of range */
+ 0x0162,
+ 0x0262
+ };
+ static const int32_t utf32Offsets[]={
+ 0, 4, 8, 8, 12, 16, 20, 24, 28
+ };
+ static const uint8_t utf32ExpectedBack[]={
+ 0x00, 0x00, 0x00, 0x61,
+ 0x00, 0x00, 0xff, 0xfd, /* 0x110000 out of range */
+ 0x00, 0x10, 0xff, 0xff, /* 0x10FFFF in range */
+ 0x00, 0x00, 0x00, 0x62,
+ 0x00, 0x00, 0xff, 0xfd, /* 0xffffffff out of range */
+ 0x00, 0x00, 0xff, 0xfd, /* 0x7fffffff out of range */
+ 0x00, 0x00, 0x01, 0x62,
+ 0x00, 0x00, 0x02, 0x62
+ };
+ static const int32_t utf32OffsetsBack[]={
+ 0,0,0,0,
+ 1,1,1,1,
+ 2,2,2,2,
+ 4,4,4,4,
+ 5,5,5,5,
+ 6,6,6,6,
+ 7,7,7,7,
+ 8,8,8,8
+ };
+
+ testConvertToU(utf32, sizeof(utf32),
+ utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), "utf-32be", utf32Offsets ,FALSE);
+ testConvertFromU(utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]),
+ utf32ExpectedBack, sizeof(utf32ExpectedBack), "utf-32be", utf32OffsetsBack, FALSE);
+ }
+
+ /* Test UTF-32LE bad data handling*/
+ {
+ static const uint8_t utf32[]={
+ 0x61, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x00, /* 0x110000 out of range */
+ 0xff, 0xff, 0x10, 0x00, /* 0x10FFFF in range */
+ 0x62, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */
+ 0xff, 0xff, 0xff, 0x7f, /* 0x7fffffff out of range */
+ 0x62, 0x01, 0x00, 0x00,
+ 0x62, 0x02, 0x00, 0x00,
+ };
+
+ static const uint16_t utf32Expected[]={
+ 0x0061,
+ 0xfffd, /* 0x110000 out of range */
+ 0xDBFF, /* 0x10FFFF in range */
+ 0xDFFF,
+ 0x0062,
+ 0xfffd, /* 0xffffffff out of range */
+ 0xfffd, /* 0x7fffffff out of range */
+ 0x0162,
+ 0x0262
+ };
+ static const int32_t utf32Offsets[]={
+ 0, 4, 8, 8, 12, 16, 20, 24, 28
+ };
+ static const uint8_t utf32ExpectedBack[]={
+ 0x61, 0x00, 0x00, 0x00,
+ 0xfd, 0xff, 0x00, 0x00, /* 0x110000 out of range */
+ 0xff, 0xff, 0x10, 0x00, /* 0x10FFFF in range */
+ 0x62, 0x00, 0x00, 0x00,
+ 0xfd, 0xff, 0x00, 0x00, /* 0xffffffff out of range */
+ 0xfd, 0xff, 0x00, 0x00, /* 0x7fffffff out of range */
+ 0x62, 0x01, 0x00, 0x00,
+ 0x62, 0x02, 0x00, 0x00
+ };
+ static const int32_t utf32OffsetsBack[]={
+ 0,0,0,0,
+ 1,1,1,1,
+ 2,2,2,2,
+ 4,4,4,4,
+ 5,5,5,5,
+ 6,6,6,6,
+ 7,7,7,7,
+ 8,8,8,8
+ };
+ testConvertToU(utf32, sizeof(utf32),
+ utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]), "utf-32le", utf32Offsets,FALSE );
+ testConvertFromU(utf32Expected, sizeof(utf32Expected)/sizeof(utf32Expected[0]),
+ utf32ExpectedBack, sizeof(utf32ExpectedBack), "utf-32le", utf32OffsetsBack, FALSE);
+ }
+}
+
+static void TestCoverageMBCS(){
+#if 0
+ UErrorCode status = U_ZERO_ERROR;
+ const char *directory = loadTestData(&status);
+ char* tdpath = NULL;
+ char* saveDirectory = (char*)malloc(sizeof(char) *(strlen(u_getDataDirectory())+1));
+ int len = strlen(directory);
+ char* index=NULL;
+
+ tdpath = (char*) malloc(sizeof(char) * (len * 2));
+ uprv_strcpy(saveDirectory,u_getDataDirectory());
+ log_verbose("Retrieved data directory %s \n",saveDirectory);
+ uprv_strcpy(tdpath,directory);
+ index=strrchr(tdpath,(char)U_FILE_SEP_CHAR);
+
+ if((unsigned int)(index-tdpath) != (strlen(tdpath)-1)){
+ *(index+1)=0;
+ }
+ u_setDataDirectory(tdpath);
+ log_verbose("ICU data directory is set to: %s \n" ,tdpath);
+#endif
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test1.ucm
+ which is test file for MBCS conversion with single-byte codepage data.*/
+ {
+
+ /* MBCS with single byte codepage data test1.ucm*/
+ const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0xdbc4, 0xde34, 0x0003};
+ const uint8_t expectedtest1[] = { 0x00, 0x05, 0xff, 0x07, 0xff,};
+ int32_t totest1Offs[] = { 0, 1, 2, 3, 5, };
+
+ /*from Unicode*/
+ testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest1, sizeof(expectedtest1), "@test1", totest1Offs,FALSE );
+ }
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test3.ucm
+ which is test file for MBCS conversion with three-byte codepage data.*/
+ {
+
+ /* MBCS with three byte codepage data test3.ucm*/
+ const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0x000e};
+ const uint8_t expectedtest3[] = { 0x00, 0x05, 0xff, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a, 0xff,};
+ int32_t totest3Offs[] = { 0, 1, 2, 3, 3, 3, 4, 6, 6, 6, 8};
+
+ const uint8_t test3input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x0b, 0x07, 0x01, 0x02, 0x0a, 0x01, 0x02, 0x0c,};
+ const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd};
+ int32_t fromtest3Offs[] = { 0, 1, 2, 3, 6, 6, 7, 7, 10 };
+
+ /*from Unicode*/
+ testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest3, sizeof(expectedtest3), "@test3", totest3Offs,FALSE );
+
+ /*to Unicode*/
+ testConvertToU(test3input, sizeof(test3input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test3", fromtest3Offs ,FALSE);
+
+ }
+
+ /*some more test to increase the code coverage in MBCS. Create an test converter from test4.ucm
+ which is test file for MBCS conversion with four-byte codepage data.*/
+ {
+
+ /* MBCS with three byte codepage data test4.ucm*/
+ static const UChar unicodeInput[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0x000e};
+ static const uint8_t expectedtest4[] = { 0x00, 0x05, 0xff, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x01, 0x02, 0x03, 0x0a, 0xff,};
+ static const int32_t totest4Offs[] = { 0, 1, 2, 3, 3, 3, 3, 4, 6, 6, 6, 6, 8,};
+
+ static const uint8_t test4input[] = { 0x00, 0x05, 0x06, 0x01, 0x02, 0x03, 0x0b, 0x07, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x02, 0x03, 0x0c,};
+ static const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd};
+ static const int32_t fromtest4Offs[] = { 0, 1, 2, 3, 7, 7, 8, 8, 12,};
+
+ /*from Unicode*/
+ testConvertFromU(unicodeInput, sizeof(unicodeInput)/sizeof(unicodeInput[0]),
+ expectedtest4, sizeof(expectedtest4), "@test4", totest4Offs,FALSE );
+
+ /*to Unicode*/
+ testConvertToU(test4input, sizeof(test4input),
+ expectedUnicode, sizeof(expectedUnicode)/sizeof(expectedUnicode[0]), "@test4", fromtest4Offs,FALSE );
+
+ }
+#if 0
+ free(tdpath);
+ /* restore the original data directory */
+ log_verbose("Setting the data directory to %s \n", saveDirectory);
+ u_setDataDirectory(saveDirectory);
+ free(saveDirectory);
+#endif
+
+}
+
+static void TestConverterType(const char *convName, UConverterType convType) {
+ UConverter* myConverter;
+ UErrorCode err = U_ZERO_ERROR;
+
+ myConverter = my_ucnv_open(convName, &err);
+
+ if (U_FAILURE(err)) {
+ log_data_err("Failed to create an %s converter\n", convName);
+ return;
+ }
+ else
+ {
+ if (ucnv_getType(myConverter)!=convType) {
+ log_err("ucnv_getType Failed for %s. Got enum value 0x%X\n",
+ convName, convType);
+ }
+ else {
+ log_verbose("ucnv_getType %s ok\n", convName);
+ }
+ }
+ ucnv_close(myConverter);
+}
+
+static void TestConverterTypesAndStarters()
+{
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UConverter* myConverter;
+ UErrorCode err = U_ZERO_ERROR;
+ UBool mystarters[256];
+
+/* const UBool expectedKSCstarters[256] = {
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};*/
+
+
+ log_verbose("Testing KSC, ibm-930, ibm-878 for starters and their conversion types.");
+
+ myConverter = ucnv_open("ksc", &err);
+ if (U_FAILURE(err)) {
+ log_data_err("Failed to create an ibm-ksc converter\n");
+ return;
+ }
+ else
+ {
+ if (ucnv_getType(myConverter)!=UCNV_MBCS)
+ log_err("ucnv_getType Failed for ibm-949\n");
+ else
+ log_verbose("ucnv_getType ibm-949 ok\n");
+
+ if(myConverter!=NULL)
+ ucnv_getStarters(myConverter, mystarters, &err);
+
+ /*if (memcmp(expectedKSCstarters, mystarters, sizeof(expectedKSCstarters)))
+ log_err("Failed ucnv_getStarters for ksc\n");
+ else
+ log_verbose("ucnv_getStarters ok\n");*/
+
+ }
+ ucnv_close(myConverter);
+
+ TestConverterType("ibm-930", UCNV_EBCDIC_STATEFUL);
+ TestConverterType("ibm-878", UCNV_SBCS);
+#endif
+
+ TestConverterType("iso-8859-1", UCNV_LATIN_1);
+
+ TestConverterType("ibm-1208", UCNV_UTF8);
+
+ TestConverterType("utf-8", UCNV_UTF8);
+ TestConverterType("UTF-16BE", UCNV_UTF16_BigEndian);
+ TestConverterType("UTF-16LE", UCNV_UTF16_LittleEndian);
+ TestConverterType("UTF-32BE", UCNV_UTF32_BigEndian);
+ TestConverterType("UTF-32LE", UCNV_UTF32_LittleEndian);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+
+#if defined(U_ENABLE_GENERIC_ISO_2022)
+ TestConverterType("iso-2022", UCNV_ISO_2022);
+#endif
+
+ TestConverterType("hz", UCNV_HZ);
+#endif
+
+ TestConverterType("scsu", UCNV_SCSU);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ TestConverterType("x-iscii-de", UCNV_ISCII);
+#endif
+
+ TestConverterType("ascii", UCNV_US_ASCII);
+ TestConverterType("utf-7", UCNV_UTF7);
+ TestConverterType("IMAP-mailbox-name", UCNV_IMAP_MAILBOX);
+ TestConverterType("bocu-1", UCNV_BOCU1);
+}
+
+static void
+TestAmbiguousConverter(UConverter *cnv) {
+ static const char inBytes[3]={ 0x61, 0x5B, 0x5c };
+ UChar outUnicode[20]={ 0, 0, 0, 0 };
+
+ const char *s;
+ UChar *u;
+ UErrorCode errorCode;
+ UBool isAmbiguous;
+
+ /* try to convert an 'a', a square bracket and a US-ASCII backslash */
+ errorCode=U_ZERO_ERROR;
+ s=inBytes;
+ u=outUnicode;
+ ucnv_toUnicode(cnv, &u, u+20, &s, s+3, NULL, TRUE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ /* we do not care about general failures in this test; the input may just not be mappable */
+ return;
+ }
+
+ if(outUnicode[0]!=0x61 || outUnicode[1]!=0x5B || outUnicode[2]==0xfffd) {
+ /* not a close ASCII-family encoding, or 0x5c is unassigned/illegal: this test is not applicable */
+ /* There are some encodings that are partially ASCII based,
+ like the ISO-7 and GSM series of codepages, which we ignore. */
+ return;
+ }
+
+ isAmbiguous=ucnv_isAmbiguous(cnv);
+
+ /* check that outUnicode[1]!=0x5c is exactly the same as ucnv_isAmbiguous() */
+ if((outUnicode[2]!=0x5c)!=isAmbiguous) {
+ log_err("error: converter \"%s\" needs a backslash fix: %d but ucnv_isAmbiguous()==%d\n",
+ ucnv_getName(cnv, &errorCode), outUnicode[2]!=0x5c, isAmbiguous);
+ return;
+ }
+
+ if(outUnicode[2]!=0x5c) {
+ /* needs fixup, fix it */
+ ucnv_fixFileSeparator(cnv, outUnicode, (int32_t)(u-outUnicode));
+ if(outUnicode[2]!=0x5c) {
+ /* the fix failed */
+ log_err("error: ucnv_fixFileSeparator(%s) failed\n", ucnv_getName(cnv, &errorCode));
+ return;
+ }
+ }
+}
+
+static void TestAmbiguous()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *ascii_cnv = 0, *sjis_cnv = 0, *cnv;
+ static const char target[] = {
+ /* "\\usr\\local\\share\\data\\icutest.txt" */
+ 0x5c, 0x75, 0x73, 0x72,
+ 0x5c, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x5c, 0x73, 0x68, 0x61, 0x72, 0x65,
+ 0x5c, 0x64, 0x61, 0x74, 0x61,
+ 0x5c, 0x69, 0x63, 0x75, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78, 0x74,
+ 0
+ };
+ UChar asciiResult[200], sjisResult[200];
+ int32_t asciiLength = 0, sjisLength = 0, i;
+ const char *name;
+
+ /* enumerate all converters */
+ status=U_ZERO_ERROR;
+ for(i=0; (name=ucnv_getAvailableName(i))!=NULL; ++i) {
+ cnv=ucnv_open(name, &status);
+ if(U_SUCCESS(status)) {
+ TestAmbiguousConverter(cnv);
+ ucnv_close(cnv);
+ } else {
+ log_err("error: unable to open available converter \"%s\"\n", name);
+ status=U_ZERO_ERROR;
+ }
+ }
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ sjis_cnv = ucnv_open("ibm-943", &status);
+ if (U_FAILURE(status))
+ {
+ log_data_err("Failed to create a SJIS converter\n");
+ return;
+ }
+ ascii_cnv = ucnv_open("LATIN-1", &status);
+ if (U_FAILURE(status))
+ {
+ log_data_err("Failed to create a LATIN-1 converter\n");
+ ucnv_close(sjis_cnv);
+ return;
+ }
+ /* convert target from SJIS to Unicode */
+ sjisLength = ucnv_toUChars(sjis_cnv, sjisResult, sizeof(sjisResult)/U_SIZEOF_UCHAR, target, (int32_t)strlen(target), &status);
+ if (U_FAILURE(status))
+ {
+ log_err("Failed to convert the SJIS string.\n");
+ ucnv_close(sjis_cnv);
+ ucnv_close(ascii_cnv);
+ return;
+ }
+ /* convert target from Latin-1 to Unicode */
+ asciiLength = ucnv_toUChars(ascii_cnv, asciiResult, sizeof(asciiResult)/U_SIZEOF_UCHAR, target, (int32_t)strlen(target), &status);
+ if (U_FAILURE(status))
+ {
+ log_err("Failed to convert the Latin-1 string.\n");
+ ucnv_close(sjis_cnv);
+ ucnv_close(ascii_cnv);
+ return;
+ }
+ if (!ucnv_isAmbiguous(sjis_cnv))
+ {
+ log_err("SJIS converter should contain ambiguous character mappings.\n");
+ ucnv_close(sjis_cnv);
+ ucnv_close(ascii_cnv);
+ return;
+ }
+ if (u_strcmp(sjisResult, asciiResult) == 0)
+ {
+ log_err("File separators for SJIS don't need to be fixed.\n");
+ }
+ ucnv_fixFileSeparator(sjis_cnv, sjisResult, sjisLength);
+ if (u_strcmp(sjisResult, asciiResult) != 0)
+ {
+ log_err("Fixing file separator for SJIS failed.\n");
+ }
+ ucnv_close(sjis_cnv);
+ ucnv_close(ascii_cnv);
+#endif
+}
+
+static void
+TestSignatureDetection(){
+ /* with null terminated strings */
+ {
+ static const char* data[] = {
+ "\xFE\xFF\x00\x00", /* UTF-16BE */
+ "\xFF\xFE\x00\x00", /* UTF-16LE */
+ "\xEF\xBB\xBF\x00", /* UTF-8 */
+ "\x0E\xFE\xFF\x00", /* SCSU */
+
+ "\xFE\xFF", /* UTF-16BE */
+ "\xFF\xFE", /* UTF-16LE */
+ "\xEF\xBB\xBF", /* UTF-8 */
+ "\x0E\xFE\xFF", /* SCSU */
+
+ "\xFE\xFF\x41\x42", /* UTF-16BE */
+ "\xFF\xFE\x41\x41", /* UTF-16LE */
+ "\xEF\xBB\xBF\x41", /* UTF-8 */
+ "\x0E\xFE\xFF\x41", /* SCSU */
+
+ "\x2B\x2F\x76\x38\x2D", /* UTF-7 */
+ "\x2B\x2F\x76\x38\x41", /* UTF-7 */
+ "\x2B\x2F\x76\x39\x41", /* UTF-7 */
+ "\x2B\x2F\x76\x2B\x41", /* UTF-7 */
+ "\x2B\x2F\x76\x2F\x41", /* UTF-7 */
+
+ "\xDD\x73\x66\x73" /* UTF-EBCDIC */
+ };
+ static const char* expected[] = {
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+
+ "UTF-7",
+ "UTF-7",
+ "UTF-7",
+ "UTF-7",
+ "UTF-7",
+ "UTF-EBCDIC"
+ };
+ static const int32_t expectedLength[] ={
+ 2,
+ 2,
+ 3,
+ 3,
+
+ 2,
+ 2,
+ 3,
+ 3,
+
+ 2,
+ 2,
+ 3,
+ 3,
+
+ 5,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4
+ };
+ int i=0;
+ UErrorCode err;
+ int32_t signatureLength = -1;
+ const char* source = NULL;
+ const char* enc = NULL;
+ for( ; i<sizeof(data)/sizeof(char*); i++){
+ err = U_ZERO_ERROR;
+ source = data[i];
+ enc = ucnv_detectUnicodeSignature(source, -1 , &signatureLength, &err);
+ if(U_FAILURE(err)){
+ log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i. Error: %s\n", source,i,u_errorName(err));
+ continue;
+ }
+ if(enc == NULL || strcmp(enc,expected[i]) !=0){
+ log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i. Expected: %s. Got: %s\n",source,i,expected[i],enc);
+ continue;
+ }
+ if(signatureLength != expectedLength[i]){
+ log_err("ucnv_detectUnicodeSignature failed for source : %s at index :%i.Expected Length: %i. Got length: %i\n",source,i,signatureLength,expectedLength[i]);
+ }
+ }
+ }
+ {
+ static const char* data[] = {
+ "\xFE\xFF\x00", /* UTF-16BE */
+ "\xFF\xFE\x00", /* UTF-16LE */
+ "\xEF\xBB\xBF\x00", /* UTF-8 */
+ "\x0E\xFE\xFF\x00", /* SCSU */
+ "\x00\x00\xFE\xFF", /* UTF-32BE */
+ "\xFF\xFE\x00\x00", /* UTF-32LE */
+ "\xFE\xFF", /* UTF-16BE */
+ "\xFF\xFE", /* UTF-16LE */
+ "\xEF\xBB\xBF", /* UTF-8 */
+ "\x0E\xFE\xFF", /* SCSU */
+ "\x00\x00\xFE\xFF", /* UTF-32BE */
+ "\xFF\xFE\x00\x00", /* UTF-32LE */
+ "\xFE\xFF\x41\x42", /* UTF-16BE */
+ "\xFF\xFE\x41\x41", /* UTF-16LE */
+ "\xEF\xBB\xBF\x41", /* UTF-8 */
+ "\x0E\xFE\xFF\x41", /* SCSU */
+ "\x00\x00\xFE\xFF\x41", /* UTF-32BE */
+ "\xFF\xFE\x00\x00\x42", /* UTF-32LE */
+ "\xFB\xEE\x28", /* BOCU-1 */
+ "\xFF\x41\x42" /* NULL */
+ };
+ static const int len[] = {
+ 3,
+ 3,
+ 4,
+ 4,
+ 4,
+ 4,
+ 2,
+ 2,
+ 3,
+ 3,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 5,
+ 5,
+ 3,
+ 3
+ };
+
+ static const char* expected[] = {
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+ "UTF-32BE",
+ "UTF-32LE",
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+ "UTF-32BE",
+ "UTF-32LE",
+ "UTF-16BE",
+ "UTF-16LE",
+ "UTF-8",
+ "SCSU",
+ "UTF-32BE",
+ "UTF-32LE",
+ "BOCU-1",
+ NULL
+ };
+ static const int32_t expectedLength[] ={
+ 2,
+ 2,
+ 3,
+ 3,
+ 4,
+ 4,
+ 2,
+ 2,
+ 3,
+ 3,
+ 4,
+ 4,
+ 2,
+ 2,
+ 3,
+ 3,
+ 4,
+ 4,
+ 3,
+ 0
+ };
+ int i=0;
+ UErrorCode err;
+ int32_t signatureLength = -1;
+ int32_t sourceLength=-1;
+ const char* source = NULL;
+ const char* enc = NULL;
+ for( ; i<sizeof(data)/sizeof(char*); i++){
+ err = U_ZERO_ERROR;
+ source = data[i];
+ sourceLength = len[i];
+ enc = ucnv_detectUnicodeSignature(source, sourceLength , &signatureLength, &err);
+ if(U_FAILURE(err)){
+ log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i. Error: %s\n", source,i,u_errorName(err));
+ continue;
+ }
+ if(enc == NULL || strcmp(enc,expected[i]) !=0){
+ if(expected[i] !=NULL){
+ log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i. Expected: %s. Got: %s\n",source,i,expected[i],enc);
+ continue;
+ }
+ }
+ if(signatureLength != expectedLength[i]){
+ log_err("ucnv_detectUnicodeSignature test2 failed for source : %s at index :%i.Expected Length: %i. Got length: %i\n",source,i,signatureLength,expectedLength[i]);
+ }
+ }
+ }
+}
+
+void
+static TestUTF7() {
+ /* test input */
+ static const uint8_t in[]={
+ /* H - +Jjo- - ! +- +2AHcAQ */
+ 0x48,
+ 0x2d,
+ 0x2b, 0x4a, 0x6a, 0x6f,
+ 0x2d, 0x2d,
+ 0x21,
+ 0x2b, 0x2d,
+ 0x2b, 0x32, 0x41, 0x48, 0x63, 0x41, 0x51
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x48,
+ 1, 0x2d,
+ 4, 0x263a, /* <WHITE SMILING FACE> */
+ 2, 0x2d,
+ 1, 0x21,
+ 2, 0x2b,
+ 7, 0x10401
+ };
+
+ const char *cnvName;
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-7", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-7 converter: %s\n", u_errorName(errorCode)); /* sholdn't be a data err */
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-7");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ cnvName = ucnv_getName(cnv, &errorCode);
+ if (U_FAILURE(errorCode) || uprv_strcmp(cnvName, "UTF-7") != 0) {
+ log_err("UTF-7 converter is called %s: %s\n", cnvName, u_errorName(errorCode));
+ }
+ ucnv_close(cnv);
+}
+
+void
+static TestIMAP() {
+ /* test input */
+ static const uint8_t in[]={
+ /* H - &Jjo- - ! &- &2AHcAQ- \ */
+ 0x48,
+ 0x2d,
+ 0x26, 0x4a, 0x6a, 0x6f,
+ 0x2d, 0x2d,
+ 0x21,
+ 0x26, 0x2d,
+ 0x26, 0x32, 0x41, 0x48, 0x63, 0x41, 0x51, 0x2d
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x48,
+ 1, 0x2d,
+ 4, 0x263a, /* <WHITE SMILING FACE> */
+ 2, 0x2d,
+ 1, 0x21,
+ 2, 0x26,
+ 7, 0x10401
+ };
+
+ const char *cnvName;
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("IMAP-mailbox-name", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a IMAP-mailbox-name converter: %s\n", u_errorName(errorCode)); /* sholdn't be a data err */
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "IMAP-mailbox-name");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ cnvName = ucnv_getName(cnv, &errorCode);
+ if (U_FAILURE(errorCode) || uprv_strcmp(cnvName, "IMAP-mailbox-name") != 0) {
+ log_err("IMAP-mailbox-name converter is called %s: %s\n", cnvName, u_errorName(errorCode));
+ }
+ ucnv_close(cnv);
+}
+
+void
+static TestUTF8() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61,
+ 0xc2, 0x80,
+ 0xe0, 0xa0, 0x80,
+ 0xf0, 0x90, 0x80, 0x80,
+ 0xf4, 0x84, 0x8c, 0xa1,
+ 0xf0, 0x90, 0x90, 0x81
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 2, 0x80,
+ 3, 0x800,
+ 4, 0x10000,
+ 4, 0x104321,
+ 4, 0x10401
+ };
+
+ /* error test input */
+ static const uint8_t in2[]={
+ 0x61,
+ 0xc0, 0x80, /* illegal non-shortest form */
+ 0xe0, 0x80, 0x80, /* illegal non-shortest form */
+ 0xf0, 0x80, 0x80, 0x80, /* illegal non-shortest form */
+ 0xc0, 0xc0, /* illegal trail byte */
+ 0xf4, 0x90, 0x80, 0x80, /* 0x110000 out of range */
+ 0xf8, 0x80, 0x80, 0x80, 0x80, /* too long */
+ 0xfe, /* illegal byte altogether */
+ 0x62
+ };
+
+ /* expected error test results */
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 22, 0x62
+ };
+
+ UConverterToUCallback cb;
+ const void *p;
+
+ const char *source=(const char *)in,*limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-8", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-8 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-8");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ /* test error behavior with a skip callback */
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode);
+ source=(const char *)in2;
+ limit=(const char *)(in2+sizeof(in2));
+ TestNextUChar(cnv, source, limit, results2, "UTF-8");
+
+ ucnv_close(cnv);
+}
+
+void
+static TestCESU8() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61,
+ 0xc2, 0x80,
+ 0xe0, 0xa0, 0x80,
+ 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80,
+ 0xed, 0xb0, 0x81, 0xed, 0xa0, 0x82,
+ 0xed, 0xaf, 0xbf, 0xed, 0xbf, 0xbf,
+ 0xef, 0xbf, 0xbc
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 2, 0x80,
+ 3, 0x800,
+ 6, 0x10000,
+ 3, 0xdc01,
+ -1,0xd802, /* may read 3 or 6 bytes */
+ -1,0x10ffff,/* may read 0 or 3 bytes */
+ 3, 0xfffc
+ };
+
+ /* error test input */
+ static const uint8_t in2[]={
+ 0x61,
+ 0xc0, 0x80, /* illegal non-shortest form */
+ 0xe0, 0x80, 0x80, /* illegal non-shortest form */
+ 0xf0, 0x80, 0x80, 0x80, /* illegal non-shortest form */
+ 0xc0, 0xc0, /* illegal trail byte */
+ 0xf0, 0x90, 0x80, 0x80, /* illegal 4-byte supplementary code point */
+ 0xf4, 0x84, 0x8c, 0xa1, /* illegal 4-byte supplementary code point */
+ 0xf0, 0x90, 0x90, 0x81, /* illegal 4-byte supplementary code point */
+ 0xf4, 0x90, 0x80, 0x80, /* 0x110000 out of range */
+ 0xf8, 0x80, 0x80, 0x80, 0x80, /* too long */
+ 0xfe, /* illegal byte altogether */
+ 0x62
+ };
+
+ /* expected error test results */
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 34, 0x62
+ };
+
+ UConverterToUCallback cb;
+ const void *p;
+
+ const char *source=(const char *)in,*limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("CESU-8", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a CESU-8 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "CESU-8");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ /* test error behavior with a skip callback */
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode);
+ source=(const char *)in2;
+ limit=(const char *)(in2+sizeof(in2));
+ TestNextUChar(cnv, source, limit, results2, "CESU-8");
+
+ ucnv_close(cnv);
+}
+
+void
+static TestUTF16() {
+ /* test input */
+ static const uint8_t in1[]={
+ 0xfe, 0xff, 0x4e, 0x00, 0xfe, 0xff
+ };
+ static const uint8_t in2[]={
+ 0xff, 0xfe, 0x4e, 0x00, 0xfe, 0xff
+ };
+ static const uint8_t in3[]={
+ 0xfe, 0xfe, 0x4e, 0x00, 0xfe, 0xff, 0xd8, 0x40, 0xdc, 0x01
+ };
+
+ /* expected test results */
+ static const int32_t results1[]={
+ /* number of bytes read, code point */
+ 4, 0x4e00,
+ 2, 0xfeff
+ };
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 4, 0x004e,
+ 2, 0xfffe
+ };
+ static const int32_t results3[]={
+ /* number of bytes read, code point */
+ 2, 0xfefe,
+ 2, 0x4e00,
+ 2, 0xfeff,
+ 4, 0x20001
+ };
+
+ const char *source, *limit;
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-16", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-16 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ source=(const char *)in1, limit=(const char *)in1+sizeof(in1);
+ TestNextUChar(cnv, source, limit, results1, "UTF-16");
+
+ source=(const char *)in2, limit=(const char *)in2+sizeof(in2);
+ ucnv_resetToUnicode(cnv);
+ TestNextUChar(cnv, source, limit, results2, "UTF-16");
+
+ source=(const char *)in3, limit=(const char *)in3+sizeof(in3);
+ ucnv_resetToUnicode(cnv);
+ TestNextUChar(cnv, source, limit, results3, "UTF-16");
+
+ /* Test the condition when source >= sourceLimit */
+ ucnv_resetToUnicode(cnv);
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ ucnv_close(cnv);
+}
+
+void
+static TestUTF16BE() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x00, 0x61,
+ 0x00, 0xc0,
+ 0x00, 0x31,
+ 0x00, 0xf4,
+ 0xce, 0xfe,
+ 0xd8, 0x01, 0xdc, 0x01
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 2, 0x61,
+ 2, 0xc0,
+ 2, 0x31,
+ 2, 0xf4,
+ 2, 0xcefe,
+ 4, 0x10401
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("utf-16be", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF16-BE converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-16BE");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for the condition where there is an invalid character*/
+ {
+ static const uint8_t source2[]={0x61};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an invalid character");
+ }
+#if 0
+ /*
+ * Test disabled because currently the UTF-16BE/LE converters are supposed
+ * to not set errors for unpaired surrogates.
+ * This may change with
+ * Jitterbug 1838 - forbid converting surrogate code points in UTF-16/32
+ */
+
+ /*Test for the condition where there is a surrogate pair*/
+ {
+ const uint8_t source2[]={0xd8, 0x01};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an truncated surrogate character");
+ }
+#endif
+ ucnv_close(cnv);
+}
+
+static void
+TestUTF16LE() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61, 0x00,
+ 0x31, 0x00,
+ 0x4e, 0x2e,
+ 0x4e, 0x00,
+ 0x01, 0xd8, 0x01, 0xdc
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 2, 0x61,
+ 2, 0x31,
+ 2, 0x2e4e,
+ 2, 0x4e,
+ 4, 0x10401
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("utf-16le", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF16-LE converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-16LE");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for the condition where there is an invalid character*/
+ {
+ static const uint8_t source2[]={0x61};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an invalid character");
+ }
+#if 0
+ /*
+ * Test disabled because currently the UTF-16BE/LE converters are supposed
+ * to not set errors for unpaired surrogates.
+ * This may change with
+ * Jitterbug 1838 - forbid converting surrogate code points in UTF-16/32
+ */
+
+ /*Test for the condition where there is a surrogate character*/
+ {
+ static const uint8_t source2[]={0x01, 0xd8};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_TRUNCATED_CHAR_FOUND, "an truncated surrogate character");
+ }
+#endif
+
+ ucnv_close(cnv);
+}
+
+void
+static TestUTF32() {
+ /* test input */
+ static const uint8_t in1[]={
+ 0x00, 0x00, 0xfe, 0xff, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff
+ };
+ static const uint8_t in2[]={
+ 0xff, 0xfe, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0xfe, 0xff, 0x00, 0x00
+ };
+ static const uint8_t in3[]={
+ 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x40, 0x00, 0x00, 0xdc, 0x01
+ };
+
+ /* expected test results */
+ static const int32_t results1[]={
+ /* number of bytes read, code point */
+ 8, 0x100f00,
+ 4, 0xfeff
+ };
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 8, 0x0f1000,
+ 4, 0xfffe
+ };
+ static const int32_t results3[]={
+ /* number of bytes read, code point */
+ 4, 0xfefe,
+ 4, 0x100f00,
+ 4, 0xfffd, /* unmatched surrogate */
+ 4, 0xfffd /* unmatched surrogate */
+ };
+
+ const char *source, *limit;
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-32", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-32 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ source=(const char *)in1, limit=(const char *)in1+sizeof(in1);
+ TestNextUChar(cnv, source, limit, results1, "UTF-32");
+
+ source=(const char *)in2, limit=(const char *)in2+sizeof(in2);
+ ucnv_resetToUnicode(cnv);
+ TestNextUChar(cnv, source, limit, results2, "UTF-32");
+
+ source=(const char *)in3, limit=(const char *)in3+sizeof(in3);
+ ucnv_resetToUnicode(cnv);
+ TestNextUChar(cnv, source, limit, results3, "UTF-32");
+
+ /* Test the condition when source >= sourceLimit */
+ ucnv_resetToUnicode(cnv);
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ ucnv_close(cnv);
+}
+
+static void
+TestUTF32BE() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x00, 0x00, 0x00, 0x61,
+ 0x00, 0x00, 0x30, 0x61,
+ 0x00, 0x00, 0xdc, 0x00,
+ 0x00, 0x00, 0xd8, 0x00,
+ 0x00, 0x00, 0xdf, 0xff,
+ 0x00, 0x00, 0xff, 0xfe,
+ 0x00, 0x10, 0xab, 0xcd,
+ 0x00, 0x10, 0xff, 0xff
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 4, 0x61,
+ 4, 0x3061,
+ 4, 0xfffd,
+ 4, 0xfffd,
+ 4, 0xfffd,
+ 4, 0xfffe,
+ 4, 0x10abcd,
+ 4, 0x10ffff
+ };
+
+ /* error test input */
+ static const uint8_t in2[]={
+ 0x00, 0x00, 0x00, 0x61,
+ 0x00, 0x11, 0x00, 0x00, /* 0x110000 out of range */
+ 0x00, 0x00, 0x00, 0x62,
+ 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */
+ 0x7f, 0xff, 0xff, 0xff, /* 0x7fffffff out of range */
+ 0x00, 0x00, 0x01, 0x62,
+ 0x00, 0x00, 0x02, 0x62
+ };
+
+ /* expected error test results */
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 4, 0x61,
+ 8, 0x62,
+ 12, 0x162,
+ 4, 0x262
+ };
+
+ UConverterToUCallback cb;
+ const void *p;
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-32BE", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-32BE converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-32BE");
+
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ /* test error behavior with a skip callback */
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode);
+ source=(const char *)in2;
+ limit=(const char *)(in2+sizeof(in2));
+ TestNextUChar(cnv, source, limit, results2, "UTF-32BE");
+
+ ucnv_close(cnv);
+}
+
+static void
+TestUTF32LE() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61, 0x00, 0x00, 0x00,
+ 0x61, 0x30, 0x00, 0x00,
+ 0x00, 0xdc, 0x00, 0x00,
+ 0x00, 0xd8, 0x00, 0x00,
+ 0xff, 0xdf, 0x00, 0x00,
+ 0xfe, 0xff, 0x00, 0x00,
+ 0xcd, 0xab, 0x10, 0x00,
+ 0xff, 0xff, 0x10, 0x00
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 4, 0x61,
+ 4, 0x3061,
+ 4, 0xfffd,
+ 4, 0xfffd,
+ 4, 0xfffd,
+ 4, 0xfffe,
+ 4, 0x10abcd,
+ 4, 0x10ffff
+ };
+
+ /* error test input */
+ static const uint8_t in2[]={
+ 0x61, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x00, /* 0x110000 out of range */
+ 0x62, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, /* 0xffffffff out of range */
+ 0xff, 0xff, 0xff, 0x7f, /* 0x7fffffff out of range */
+ 0x62, 0x01, 0x00, 0x00,
+ 0x62, 0x02, 0x00, 0x00,
+ };
+
+ /* expected error test results */
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 4, 0x61,
+ 8, 0x62,
+ 12, 0x162,
+ 4, 0x262,
+ };
+
+ UConverterToUCallback cb;
+ const void *p;
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("UTF-32LE", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a UTF-32LE converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "UTF-32LE");
+
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+
+ /* test error behavior with a skip callback */
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, &cb, &p, &errorCode);
+ source=(const char *)in2;
+ limit=(const char *)(in2+sizeof(in2));
+ TestNextUChar(cnv, source, limit, results2, "UTF-32LE");
+
+ ucnv_close(cnv);
+}
+
+static void
+TestLATIN1() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61,
+ 0x31,
+ 0x32,
+ 0xc0,
+ 0xf0,
+ 0xf4,
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 1, 0x31,
+ 1, 0x32,
+ 1, 0xc0,
+ 1, 0xf0,
+ 1, 0xf4,
+ };
+ static const uint16_t in1[] = {
+ 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84,
+ 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f,
+ 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c,
+ 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d,
+ 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e,
+ 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e,
+ 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d,
+ 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa,
+ 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08,
+ 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d,
+ 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06,
+ 0xcb, 0x82
+ };
+ static const uint8_t out1[] = {
+ 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84,
+ 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f,
+ 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c,
+ 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d,
+ 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e,
+ 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e,
+ 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d,
+ 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa,
+ 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08,
+ 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d,
+ 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06,
+ 0xcb, 0x82
+ };
+ static const uint16_t in2[]={
+ 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23,
+ 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A,
+ 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F,
+ 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21,
+ 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E,
+ 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x0F, 0x2F, 0x2A, 0x70,
+ 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A,
+ 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F,
+ 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47,
+ 0x1B, 0x4F, 0x22, 0x48, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61,
+ 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B,
+ 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21,
+ 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B,
+ 0x4F, 0x22, 0x6C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50,
+ 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F,
+ 0x22, 0x5C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C,
+ 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F,
+ 0x23, 0x71, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65,
+ 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B,
+ 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B,
+ 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23,
+ 0x6F, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20,
+ 0x37, 0x20, 0x2A, 0x2F,
+ };
+ static const unsigned char out2[]={
+ 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23,
+ 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A,
+ 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F,
+ 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21,
+ 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E,
+ 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x0F, 0x2F, 0x2A, 0x70,
+ 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A,
+ 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F,
+ 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47,
+ 0x1B, 0x4F, 0x22, 0x48, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61,
+ 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B,
+ 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21,
+ 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B,
+ 0x4F, 0x22, 0x6C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50,
+ 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F,
+ 0x22, 0x5C, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C,
+ 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F,
+ 0x23, 0x71, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65,
+ 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B,
+ 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B,
+ 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23,
+ 0x6F, 0x0F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20,
+ 0x37, 0x20, 0x2A, 0x2F,
+ };
+ const char *source=(const char *)in;
+ const char *limit=(const char *)in+sizeof(in);
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("LATIN_1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a LATIN_1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "LATIN_1");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ TestConv((uint16_t*)in1,sizeof(in1)/2,"LATIN_1","LATIN-1",(char*)out1,sizeof(out1));
+ TestConv((uint16_t*)in2,sizeof(in2)/2,"ASCII","ASCII",(char*)out2,sizeof(out2));
+
+ ucnv_close(cnv);
+}
+
+static void
+TestSBCS() {
+ /* test input */
+ static const uint8_t in[]={ 0x61, 0xc0, 0x80, 0xe0, 0xf0, 0xf4};
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x61,
+ 1, 0xbf,
+ 1, 0xc4,
+ 1, 0x2021,
+ 1, 0xf8ff,
+ 1, 0x00d9
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("x-mac-turkish", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a SBCS(x-mac-turkish) converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "SBCS(x-mac-turkish)");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for Illegal character */ /*
+ {
+ static const uint8_t input1[]={ 0xA1 };
+ const char* illegalsource=(const char*)input1;
+ TestNextUCharError(cnv, illegalsource, illegalsource+sizeof(illegalsource), U_INVALID_CHAR_FOUND, "source has a illegal characte");
+ }
+ */
+ ucnv_close(cnv);
+}
+
+static void
+TestDBCS() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x44, 0x6a,
+ 0xc4, 0x9c,
+ 0x7a, 0x74,
+ 0x46, 0xab,
+ 0x42, 0x5b,
+
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 2, 0x00a7,
+ 2, 0xe1d2,
+ 2, 0x6962,
+ 2, 0xf842,
+ 2, 0xffe5,
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ UConverter *cnv=my_ucnv_open("@ibm9027", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a DBCS(@ibm9027) converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "DBCS(@ibm9027)");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for the condition where there is an invalid character*/
+ {
+ static const uint8_t source2[]={0x1a, 0x1b};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character");
+ }
+ /*Test for the condition where we have a truncated char*/
+ {
+ static const uint8_t source1[]={0xc4};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated");
+ }
+ ucnv_close(cnv);
+}
+
+static void
+TestMBCS() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x01,
+ 0xa6, 0xa3,
+ 0x00,
+ 0xa6, 0xa1,
+ 0x08,
+ 0xc2, 0x76,
+ 0xc2, 0x78,
+
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x0001,
+ 2, 0x250c,
+ 1, 0x0000,
+ 2, 0x2500,
+ 1, 0x0008,
+ 2, 0xd60c,
+ 2, 0xd60e,
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ UConverter *cnv=ucnv_open("ibm-1363", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a MBCS(ibm-1363) converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "MBCS(ibm-1363)");
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for the condition where there is an invalid character*/
+ {
+ static const uint8_t source2[]={0xa1, 0x01};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character");
+ }
+ /*Test for the condition where we have a truncated char*/
+ {
+ static const uint8_t source1[]={0xc4};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated");
+ }
+ ucnv_close(cnv);
+
+}
+
+#ifdef U_ENABLE_GENERIC_ISO_2022
+
+static void
+TestISO_2022() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x1b, 0x25, 0x42,
+ 0x31,
+ 0x32,
+ 0x61,
+ 0xc2, 0x80,
+ 0xe0, 0xa0, 0x80,
+ 0xf0, 0x90, 0x80, 0x80
+ };
+
+
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 4, 0x0031, /* 4 bytes including the escape sequence */
+ 1, 0x0032,
+ 1, 0x61,
+ 2, 0x80,
+ 3, 0x800,
+ 4, 0x10000
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+
+ cnv=ucnv_open("ISO_2022", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "ISO_2022");
+
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source-1, U_ILLEGAL_ARGUMENT_ERROR, "sourceLimit < source");
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ /*Test for the condition where we have a truncated char*/
+ {
+ static const uint8_t source1[]={0xc4};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_TRUNCATED_CHAR_FOUND, "a character is truncated");
+ }
+ /*Test for the condition where there is an invalid character*/
+ {
+ static const uint8_t source2[]={0xa1, 0x01};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_CHAR_FOUND, "an invalid character");
+ }
+ ucnv_close(cnv);
+}
+
+#endif
+
+static void
+TestSmallTargetBuffer(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ int len=0;
+ int i=2;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 10);
+ ucnv_reset(cnv);
+ for(;--i>0; ){
+ uSource = (UChar*) source;
+ uSourceLimit=(const UChar*)sourceLimit;
+ cTarget = cBuf;
+ uTarget = uBuf;
+ cSource = cBuf;
+ cTargetLimit = cBuf;
+ uTargetLimit = uBuf;
+
+ do{
+
+ cTargetLimit = cTargetLimit+ i;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,FALSE, &errorCode);
+ if(errorCode==U_BUFFER_OVERFLOW_ERROR){
+ errorCode=U_ZERO_ERROR;
+ continue;
+ }
+
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ }while (uSource<uSourceLimit);
+
+ cSourceLimit =cTarget;
+ do{
+ uTargetLimit=uTargetLimit+i;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,FALSE,&errorCode);
+ if(errorCode==U_BUFFER_OVERFLOW_ERROR){
+ errorCode=U_ZERO_ERROR;
+ continue;
+ }
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ }while(cSource<cSourceLimit);
+
+ uSource = source;
+ test =uBuf;
+ for(len=0;len<(int)(source - sourceLimit);len++){
+ if(uBuf[len]!=uSource[len]){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",uSource[len],(int)uBuf[len]) ;
+ }
+ }
+ }
+ free(uBuf);
+ free(cBuf);
+}
+/* Test for Jitterbug 778 */
+static void TestToAndFromUChars(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ int numCharsInTarget=0;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = source;
+ uSourceLimit=sourceLimit;
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_reset(cnv);
+ numCharsInTarget=ucnv_fromUChars(cnv, cTarget, (int32_t)(cTargetLimit-cTarget), uSource, (int32_t)(uSourceLimit-uSource), &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ test =uBuf;
+ ucnv_toUChars(cnv,uTarget,(int32_t)(uTargetLimit-uTarget),cSource,numCharsInTarget,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUChars conversion failed, reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = source;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ free(uBuf);
+ free(cBuf);
+}
+
+static void TestSmallSourceBuffer(const uint16_t* source, const UChar* sourceLimit,UConverter* cnv){
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ int len=0;
+ int i=2;
+ const UChar *temp = sourceLimit;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 10);
+
+ ucnv_reset(cnv);
+ for(;--i>0;){
+ uSource = (UChar*) source;
+ cTarget = cBuf;
+ uTarget = uBuf;
+ cSource = cBuf;
+ cTargetLimit = cBuf;
+ uTargetLimit = uBuf+uBufSize*5;
+ cTargetLimit = cTargetLimit+uBufSize*10;
+ uSourceLimit=uSource;
+ do{
+
+ if (uSourceLimit < sourceLimit) {
+ uSourceLimit = uSourceLimit+1;
+ }
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,FALSE, &errorCode);
+ if(errorCode==U_BUFFER_OVERFLOW_ERROR){
+ errorCode=U_ZERO_ERROR;
+ continue;
+ }
+
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ }while (uSource<temp);
+
+ cSourceLimit =cBuf;
+ do{
+ if (cSourceLimit < cBuf + (cTarget - cBuf)) {
+ cSourceLimit = cSourceLimit+1;
+ }
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,FALSE,&errorCode);
+ if(errorCode==U_BUFFER_OVERFLOW_ERROR){
+ errorCode=U_ZERO_ERROR;
+ continue;
+ }
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ }while(cSource<cTarget);
+
+ uSource = source;
+ test =uBuf;
+ for(;len<(int)(source - sourceLimit);len++){
+ if(uBuf[len]!=uSource[len]){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",uSource[len],(int)uBuf[len]) ;
+ }
+ }
+ }
+ free(uBuf);
+ free(cBuf);
+}
+static void
+TestGetNextUChar2022(UConverter* cnv, const char* source, const char* limit,
+ const uint16_t results[], const char* message){
+ const char* s0;
+ const char* s=(char*)source;
+ const uint16_t *r=results;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ uint32_t c,exC;
+ ucnv_reset(cnv);
+ while(s<limit) {
+ s0=s;
+ c=ucnv_getNextUChar(cnv, &s, limit, &errorCode);
+ if(errorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
+ break; /* no more significant input */
+ } else if(U_FAILURE(errorCode)) {
+ log_err("%s ucnv_getNextUChar() failed: %s\n", message, u_errorName(errorCode));
+ break;
+ } else {
+ if(UTF_IS_FIRST_SURROGATE(*r)){
+ int i =0, len = 2;
+ UTF_NEXT_CHAR_SAFE(r, i, len, exC, FALSE);
+ r++;
+ }else{
+ exC = *r;
+ }
+ if(c!=(uint32_t)(exC))
+ log_err("%s ucnv_getNextUChar() Expected: \\u%04X Got: \\u%04X \n",message,(uint32_t) (*r),c);
+ }
+ r++;
+ }
+}
+
+static int TestJitterbug930(const char* enc){
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter*converter;
+ char out[80];
+ char*target = out;
+ UChar in[4];
+ const UChar*source = in;
+ int32_t off[80];
+ int32_t* offsets = off;
+ int numOffWritten=0;
+ UBool flush = 0;
+ converter = my_ucnv_open(enc, &err);
+
+ in[0] = 0x41; /* 0x4E00;*/
+ in[1] = 0x4E01;
+ in[2] = 0x4E02;
+ in[3] = 0x4E03;
+
+ memset(off, '*', sizeof(off));
+
+ ucnv_fromUnicode (converter,
+ &target,
+ target+2,
+ &source,
+ source+3,
+ offsets,
+ flush,
+ &err);
+
+ /* writes three bytes into the output buffer: 41 1B 24
+ * but offsets contains 0 1 1
+ */
+ while(*offsets< off[10]){
+ numOffWritten++;
+ offsets++;
+ }
+ log_verbose("Testing Jitterbug 930 for encoding %s",enc);
+ if(numOffWritten!= (int)(target-out)){
+ log_err("Jitterbug 930 test for enc: %s failed. Expected: %i Got: %i",enc, (int)(target-out),numOffWritten);
+ }
+
+ err = U_ZERO_ERROR;
+
+ memset(off,'*' , sizeof(off));
+
+ flush = 1;
+ offsets=off;
+ ucnv_fromUnicode (converter,
+ &target,
+ target+4,
+ &source,
+ source,
+ offsets,
+ flush,
+ &err);
+ numOffWritten=0;
+ while(*offsets< off[10]){
+ numOffWritten++;
+ if(*offsets!= -1){
+ log_err("Jitterbug 930 test for enc: %s failed. Expected: %i Got: %i",enc,-1,*offsets) ;
+ }
+ offsets++;
+ }
+
+ /* writes 42 43 7A into output buffer,
+ * offsets contains -1 -1 -1
+ */
+ ucnv_close(converter);
+ return 0;
+}
+
+static void
+TestHZ() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x3000, 0x3001, 0x3002, 0x00B7, 0x02C9, 0x02C7, 0x00A8, 0x3003, 0x3005, 0x2014,
+ 0xFF5E, 0x2016, 0x2026, 0x007E, 0x997C, 0x70B3, 0x75C5, 0x5E76, 0x73BB, 0x83E0,
+ 0x64AD, 0x62E8, 0x94B5, 0x000A, 0x6CE2, 0x535A, 0x52C3, 0x640F, 0x94C2, 0x7B94,
+ 0x4F2F, 0x5E1B, 0x8236, 0x000A, 0x8116, 0x818A, 0x6E24, 0x6CCA, 0x9A73, 0x6355,
+ 0x535C, 0x54FA, 0x8865, 0x000A, 0x57E0, 0x4E0D, 0x5E03, 0x6B65, 0x7C3F, 0x90E8,
+ 0x6016, 0x248F, 0x2490, 0x000A, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496,
+ 0x2497, 0x2498, 0x2499, 0x000A, 0x249A, 0x249B, 0x2474, 0x2475, 0x2476, 0x2477,
+ 0x2478, 0x2479, 0x247A, 0x000A, 0x247B, 0x247C, 0x247D, 0x247E, 0x247F, 0x2480,
+ 0x2481, 0x2482, 0x2483, 0x000A, 0x0041, 0x0043, 0x0044, 0x0045, 0x0046, 0x007E,
+ 0x0048, 0x0049, 0x004A, 0x000A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x000A, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
+ 0x005A, 0x005B, 0x005C, 0x000A
+ };
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("HZ", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open HZ converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, "HZ encoding");
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestJitterbug930("csISO2022JP");
+ ucnv_close(cnv);
+ free(offsets);
+ free(uBuf);
+ free(cBuf);
+}
+
+static void
+TestISCII(){
+ /* test input */
+ static const uint16_t in[]={
+ /* test full range of Devanagari */
+ 0x0901,0x0902,0x0903,0x0905,0x0906,0x0907,0x0908,0x0909,0x090A,
+ 0x090B,0x090E,0x090F,0x0910,0x090D,0x0912,0x0913,0x0914,0x0911,
+ 0x0915,0x0916,0x0917,0x0918,0x0919,0x091A,0x091B,0x091C,0x091D,
+ 0x091E,0x091F,0x0920,0x0921,0x0922,0x0923,0x0924,0x0925,0x0926,
+ 0x0927,0x0928,0x0929,0x092A,0x092B,0x092C,0x092D,0x092E,0x092F,
+ 0x095F,0x0930,0x0931,0x0932,0x0933,0x0934,0x0935,0x0936,0x0937,
+ 0x0938,0x0939,0x200D,0x093E,0x093F,0x0940,0x0941,0x0942,0x0943,
+ 0x0946,0x0947,0x0948,0x0945,0x094A,0x094B,0x094C,0x0949,0x094D,
+ 0x093d,0x0966,0x0967,0x0968,0x0969,0x096A,0x096B,0x096C,
+ 0x096D,0x096E,0x096F,
+ /* test Soft halant*/
+ 0x0915,0x094d, 0x200D,
+ /* test explicit halant */
+ 0x0915,0x094d, 0x200c,
+ /* test double danda */
+ 0x965,
+ /* test ASCII */
+ 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23,
+ 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A,
+ /* tests from Lotus */
+ 0x0061,0x0915,0x000D,0x000A,0x0996,0x0043,
+ 0x0930,0x094D,0x200D,
+ 0x0901,0x000D,0x000A,0x0905,0x0985,0x0043,
+ 0x0915,0x0921,0x002B,0x095F,
+ /* tamil range */
+ 0x0B86, 0xB87, 0xB88,
+ /* telugu range */
+ 0x0C05, 0x0C02, 0x0C03,0x0c31,
+ /* kannada range */
+ 0x0C85, 0xC82, 0x0C83,
+ /* test Abbr sign and Anudatta */
+ 0x0970, 0x952,
+ /* 0x0958,
+ 0x0959,
+ 0x095A,
+ 0x095B,
+ 0x095C,
+ 0x095D,
+ 0x095E,
+ 0x095F,*/
+ 0x0960 /* Vocallic RRI 0xAB, 0xE9*/,
+ 0x0944 /* Vowel Sign Vocallic RRI 0xDF, 0xE9 */,
+ 0x090C ,
+ 0x0962,
+ 0x0961 /* Vocallic LL 0xa6, 0xE9 */,
+ 0x0963 /* Vowel Sign Vocallic LL 0xdb, 0xE9, */,
+ 0x0950 /* OM Symbol 0xa1, 0xE9,*/,
+ 0x093D /* Avagraha 0xEA, 0xE9*/,
+ 0x0958,
+ 0x0959,
+ 0x095A,
+ 0x095B,
+ 0x095C,
+ 0x095D,
+ 0x095E,
+ 0x0020, 0x094D, 0x0930, 0x0000, 0x00A0
+ };
+ static const unsigned char byteArr[]={
+
+ 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,
+ 0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,
+ 0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,
+ 0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,
+ 0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,
+ 0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
+ 0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
+ 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,
+ 0xea,0xe9,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
+ 0xf8,0xf9,0xfa,
+ /* test soft halant */
+ 0xb3, 0xE8, 0xE9,
+ /* test explicit halant */
+ 0xb3, 0xE8, 0xE8,
+ /* test double danda */
+ 0xea, 0xea,
+ /* test ASCII */
+ 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23,
+ 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A,
+ /* test ATR code */
+
+ /* tests from Lotus */
+ 0x61,0xEF,0x42,0xEF,0x30,0xB3,0x0D,0x0A,0xEF,0x43,0xB4,0x43,
+ 0xEF,0x42,0xCF,0xE8,0xD9,
+ 0xEF,0x42,0xA1,0x0D,0x0A,0xEF,0x42,0xA4,0xEF,0x43,0xA4,0x43,
+ 0xEF,0x42,0xB3,0xBF,0x2B,0xEF,0x42,0xCE,
+ /* tamil range */
+ 0xEF, 0x44, 0xa5, 0xa6, 0xa7,
+ /* telugu range */
+ 0xEF, 0x45,0xa4, 0xa2, 0xa3,0xd0,
+ /* kannada range */
+ 0xEF, 0x48,0xa4, 0xa2, 0xa3,
+ /* anudatta and abbreviation sign */
+ 0xEF, 0x42, 0xF0, 0xBF, 0xF0, 0xB8,
+
+
+ 0xAA, 0xE9,/* RI + NUKTA 0x0960*/
+
+ 0xDF, 0xE9,/* Vowel sign RI + NUKTA 0x0944*/
+
+ 0xa6, 0xE9,/* Vowel I + NUKTA 0x090C*/
+
+ 0xdb, 0xE9,/* Vowel sign I + Nukta 0x0962*/
+
+ 0xa7, 0xE9,/* Vowel II + NUKTA 0x0961*/
+
+ 0xdc, 0xE9,/* Vowel sign II + Nukta 0x0963*/
+
+ 0xa1, 0xE9,/* chandrabindu + Nukta 0x0950*/
+
+ 0xEA, 0xE9, /* Danda + Nukta 0x093D*/
+
+ 0xB3, 0xE9, /* Ka + NUKTA */
+
+ 0xB4, 0xE9, /* Kha + NUKTA */
+
+ 0xB5, 0xE9, /* Ga + NUKTA */
+
+ 0xBA, 0xE9,
+
+ 0xBF, 0xE9,
+
+ 0xC0, 0xE9,
+
+ 0xC9, 0xE9,
+ /* INV halant RA */
+ 0xD9, 0xE8, 0xCF,
+ 0x00, 0x00A0,
+ /* just consume unhandled codepoints */
+ 0xEF, 0x30,
+
+ };
+ testConvertToU(byteArr,(sizeof(byteArr)),in,(sizeof(in)/U_SIZEOF_UCHAR),"x-iscii-de",NULL,TRUE);
+ TestConv(in,(sizeof(in)/2),"ISCII,version=0","hindi", (char *)byteArr,sizeof(byteArr));
+
+}
+
+static void
+TestISO_2022_JP() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x0041,/*0x00E9,*/0x3000, 0x3001, 0x3002, 0x0020, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, 0x005C, 0x000D, 0x000A,
+ 0x301C, 0x2016, 0x2026, 0x2025, 0x2018, 0x2019, 0x201C, 0x000D, 0x000A,
+ 0x201D, 0x3014, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ };
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ISO_2022_JP_1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open an ISO_2022_JP_1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-JP encoding");
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestJitterbug930("csISO2022JP");
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void TestConv(const uint16_t in[],int len, const char* conv, const char* lang, char byteArr[],int byteArrLen){
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120*10;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) );
+ int32_t* myOff= offsets;
+ cnv=my_ucnv_open(conv, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a %s converter: %s\n", conv, u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar));
+ cBuf =(char*)malloc(uBufSize * sizeof(char));
+ uSource = (const UChar*)in;
+ uSourceLimit=uSource+len;
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ /*log_verbose("length of compressed string for language %s using %s:%i \n",conv,lang,(cTarget-cBuf));*/
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed, reason: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("for codepage %s : Expected : \\u%04X \t Got: \\u%04X\n",conv,*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestSmallTargetBuffer(in,(const UChar*)&in[len],cnv);
+ TestSmallSourceBuffer(in,(const UChar*)&in[len],cnv);
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, conv);
+ if(byteArr && byteArrLen!=0){
+ TestGetNextUChar2022(cnv, byteArr, (byteArr+byteArrLen), in, lang);
+ TestToAndFromUChars(in,(const UChar*)&in[len],cnv);
+ {
+ cSource = byteArr;
+ cSourceLimit = cSource+byteArrLen;
+ test=uBuf;
+ myOff = offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ }
+ }
+
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+static UChar U_CALLCONV
+_charAt(int32_t offset, void *context) {
+ return ((char*)context)[offset];
+}
+
+static int32_t
+unescape(UChar* dst, int32_t dstLen,const char* src,int32_t srcLen,UErrorCode *status){
+ int32_t srcIndex=0;
+ int32_t dstIndex=0;
+ if(U_FAILURE(*status)){
+ return 0;
+ }
+ if((dst==NULL && dstLen>0) || (src==NULL ) || dstLen < -1 || srcLen <-1 ){
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ if(srcLen==-1){
+ srcLen = (int32_t)uprv_strlen(src);
+ }
+
+ for (; srcIndex<srcLen; ) {
+ UChar32 c = src[srcIndex++];
+ if (c == 0x005C /*'\\'*/) {
+ c = u_unescapeAt(_charAt,&srcIndex,srcLen,(void*)src); /* advances i*/
+ if (c == (UChar32)0xFFFFFFFF) {
+ *status=U_INVALID_CHAR_FOUND; /* return empty string */
+ break; /* invalid escape sequence */
+ }
+ }
+ if(dstIndex < dstLen){
+ if(c>0xFFFF){
+ dst[dstIndex++] = UTF16_LEAD(c);
+ if(dstIndex<dstLen){
+ dst[dstIndex]=UTF16_TRAIL(c);
+ }else{
+ *status=U_BUFFER_OVERFLOW_ERROR;
+ }
+ }else{
+ dst[dstIndex]=(UChar)c;
+ }
+
+ }else{
+ *status = U_BUFFER_OVERFLOW_ERROR;
+ }
+ dstIndex++; /* for preflighting */
+ }
+ return dstIndex;
+}
+
+static void
+TestFullRoundtrip(const char* cp){
+ UChar usource[10] ={0};
+ UChar nsrc[10] = {0};
+ uint32_t i=1;
+ int len=0, ulen;
+ nsrc[0]=0x0061;
+ /* Test codepoint 0 */
+ TestConv(usource,1,cp,"",NULL,0);
+ TestConv(usource,2,cp,"",NULL,0);
+ nsrc[2]=0x5555;
+ TestConv(nsrc,3,cp,"",NULL,0);
+
+ for(;i<=0x10FFFF;i++){
+ if(i==0xD800){
+ i=0xDFFF;
+ continue;
+ }
+ if(i<=0xFFFF){
+ usource[0] =(UChar) i;
+ len=1;
+ }else{
+ usource[0]=UTF16_LEAD(i);
+ usource[1]=UTF16_TRAIL(i);
+ len=2;
+ }
+ ulen=len;
+ if(i==0x80) {
+ usource[2]=0;
+ }
+ /* Test only single code points */
+ TestConv(usource,ulen,cp,"",NULL,0);
+ /* Test codepoint repeated twice */
+ usource[ulen]=usource[0];
+ usource[ulen+1]=usource[1];
+ ulen+=len;
+ TestConv(usource,ulen,cp,"",NULL,0);
+ /* Test codepoint repeated 3 times */
+ usource[ulen]=usource[0];
+ usource[ulen+1]=usource[1];
+ ulen+=len;
+ TestConv(usource,ulen,cp,"",NULL,0);
+ /* Test codepoint in between 2 codepoints */
+ nsrc[1]=usource[0];
+ nsrc[2]=usource[1];
+ nsrc[len+1]=0x5555;
+ TestConv(nsrc,len+2,cp,"",NULL,0);
+ uprv_memset(usource,0,sizeof(UChar)*10);
+ }
+}
+
+static void
+TestRoundTrippingAllUTF(void){
+ if(!QUICK){
+ log_verbose("Running exhaustive round trip test for BOCU-1\n");
+ TestFullRoundtrip("BOCU-1");
+ log_verbose("Running exhaustive round trip test for SCSU\n");
+ TestFullRoundtrip("SCSU");
+ log_verbose("Running exhaustive round trip test for UTF-8\n");
+ TestFullRoundtrip("UTF-8");
+ log_verbose("Running exhaustive round trip test for CESU-8\n");
+ TestFullRoundtrip("CESU-8");
+ log_verbose("Running exhaustive round trip test for UTF-16BE\n");
+ TestFullRoundtrip("UTF-16BE");
+ log_verbose("Running exhaustive round trip test for UTF-16LE\n");
+ TestFullRoundtrip("UTF-16LE");
+ log_verbose("Running exhaustive round trip test for UTF-16\n");
+ TestFullRoundtrip("UTF-16");
+ log_verbose("Running exhaustive round trip test for UTF-32BE\n");
+ TestFullRoundtrip("UTF-32BE");
+ log_verbose("Running exhaustive round trip test for UTF-32LE\n");
+ TestFullRoundtrip("UTF-32LE");
+ log_verbose("Running exhaustive round trip test for UTF-32\n");
+ TestFullRoundtrip("UTF-32");
+ log_verbose("Running exhaustive round trip test for UTF-7\n");
+ TestFullRoundtrip("UTF-7");
+ log_verbose("Running exhaustive round trip test for UTF-7\n");
+ TestFullRoundtrip("UTF-7,version=1");
+ log_verbose("Running exhaustive round trip test for IMAP-mailbox-name\n");
+ TestFullRoundtrip("IMAP-mailbox-name");
+ log_verbose("Running exhaustive round trip test for GB18030\n");
+ TestFullRoundtrip("GB18030");
+ }
+}
+
+static void
+TestSCSU() {
+
+ static const uint16_t germanUTF16[]={
+ 0x00d6, 0x006c, 0x0020, 0x0066, 0x006c, 0x0069, 0x0065, 0x00df, 0x0074
+ };
+
+ static const uint8_t germanSCSU[]={
+ 0xd6, 0x6c, 0x20, 0x66, 0x6c, 0x69, 0x65, 0xdf, 0x74
+ };
+
+ static const uint16_t russianUTF16[]={
+ 0x041c, 0x043e, 0x0441, 0x043a, 0x0432, 0x0430
+ };
+
+ static const uint8_t russianSCSU[]={
+ 0x12, 0x9c, 0xbe, 0xc1, 0xba, 0xb2, 0xb0
+ };
+
+ static const uint16_t japaneseUTF16[]={
+ 0x3000, 0x266a, 0x30ea, 0x30f3, 0x30b4, 0x53ef, 0x611b,
+ 0x3044, 0x3084, 0x53ef, 0x611b, 0x3044, 0x3084, 0x30ea, 0x30f3,
+ 0x30b4, 0x3002, 0x534a, 0x4e16, 0x7d00, 0x3082, 0x524d, 0x306b,
+ 0x6d41, 0x884c, 0x3057, 0x305f, 0x300c, 0x30ea, 0x30f3, 0x30b4,
+ 0x306e, 0x6b4c, 0x300d, 0x304c, 0x3074, 0x3063, 0x305f, 0x308a,
+ 0x3059, 0x308b, 0x304b, 0x3082, 0x3057, 0x308c, 0x306a, 0x3044,
+ 0x3002, 0x7c73, 0x30a2, 0x30c3, 0x30d7, 0x30eb, 0x30b3, 0x30f3,
+ 0x30d4, 0x30e5, 0x30fc, 0x30bf, 0x793e, 0x306e, 0x30d1, 0x30bd,
+ 0x30b3, 0x30f3, 0x300c, 0x30de, 0x30c3, 0x30af, 0xff08, 0x30de,
+ 0x30c3, 0x30ad, 0x30f3, 0x30c8, 0x30c3, 0x30b7, 0x30e5, 0xff09,
+ 0x300d, 0x3092, 0x3001, 0x3053, 0x3088, 0x306a, 0x304f, 0x611b,
+ 0x3059, 0x308b, 0x4eba, 0x305f, 0x3061, 0x306e, 0x3053, 0x3068,
+ 0x3060, 0x3002, 0x300c, 0x30a2, 0x30c3, 0x30d7, 0x30eb, 0x4fe1,
+ 0x8005, 0x300d, 0x306a, 0x3093, 0x3066, 0x8a00, 0x3044, 0x65b9,
+ 0x307e, 0x3067, 0x3042, 0x308b, 0x3002
+ };
+
+ /* SCSUEncoder produces a slightly longer result (179B vs. 178B) because of one different choice:
+ it uses an SQn once where a longer look-ahead could have shown that SCn is more efficient */
+ static const uint8_t japaneseSCSU[]={
+ 0x08, 0x00, 0x1b, 0x4c, 0xea, 0x16, 0xca, 0xd3, 0x94, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84,
+ 0xc4, 0x0f, 0x53, 0xef, 0x61, 0x1b, 0xe5, 0x84, 0xc4, 0x16, 0xca, 0xd3, 0x94, 0x08, 0x02, 0x0f,
+ 0x53, 0x4a, 0x4e, 0x16, 0x7d, 0x00, 0x30, 0x82, 0x52, 0x4d, 0x30, 0x6b, 0x6d, 0x41, 0x88, 0x4c,
+ 0xe5, 0x97, 0x9f, 0x08, 0x0c, 0x16, 0xca, 0xd3, 0x94, 0x15, 0xae, 0x0e, 0x6b, 0x4c, 0x08, 0x0d,
+ 0x8c, 0xb4, 0xa3, 0x9f, 0xca, 0x99, 0xcb, 0x8b, 0xc2, 0x97, 0xcc, 0xaa, 0x84, 0x08, 0x02, 0x0e,
+ 0x7c, 0x73, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x93, 0xd3, 0xb4, 0xc5, 0xdc, 0x9f, 0x0e, 0x79, 0x3e,
+ 0x06, 0xae, 0xb1, 0x9d, 0x93, 0xd3, 0x08, 0x0c, 0xbe, 0xa3, 0x8f, 0x08, 0x88, 0xbe, 0xa3, 0x8d,
+ 0xd3, 0xa8, 0xa3, 0x97, 0xc5, 0x17, 0x89, 0x08, 0x0d, 0x15, 0xd2, 0x08, 0x01, 0x93, 0xc8, 0xaa,
+ 0x8f, 0x0e, 0x61, 0x1b, 0x99, 0xcb, 0x0e, 0x4e, 0xba, 0x9f, 0xa1, 0xae, 0x93, 0xa8, 0xa0, 0x08,
+ 0x02, 0x08, 0x0c, 0xe2, 0x16, 0xa3, 0xb7, 0xcb, 0x0f, 0x4f, 0xe1, 0x80, 0x05, 0xec, 0x60, 0x8d,
+ 0xea, 0x06, 0xd3, 0xe6, 0x0f, 0x8a, 0x00, 0x30, 0x44, 0x65, 0xb9, 0xe4, 0xfe, 0xe7, 0xc2, 0x06,
+ 0xcb, 0x82
+ };
+
+ static const uint16_t allFeaturesUTF16[]={
+ 0x0041, 0x00df, 0x0401, 0x015f, 0x00df, 0x01df, 0xf000, 0xdbff,
+ 0xdfff, 0x000d, 0x000a, 0x0041, 0x00df, 0x0401, 0x015f, 0x00df,
+ 0x01df, 0xf000, 0xdbff, 0xdfff
+ };
+
+ /* see comment at japaneseSCSU: the same kind of different choice yields a slightly shorter
+ * result here (34B vs. 35B)
+ */
+ static const uint8_t allFeaturesSCSU[]={
+ 0x41, 0xdf, 0x12, 0x81, 0x03, 0x5f, 0x10, 0xdf, 0x1b, 0x03,
+ 0xdf, 0x1c, 0x88, 0x80, 0x0b, 0xbf, 0xff, 0xff, 0x0d, 0x0a,
+ 0x41, 0x10, 0xdf, 0x12, 0x81, 0x03, 0x5f, 0x10, 0xdf, 0x13,
+ 0xdf, 0x14, 0x80, 0x15, 0xff
+ };
+ static const uint16_t monkeyIn[]={
+ 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A,
+ 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A,
+ 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A,
+ 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A,
+ 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A,
+ 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A,
+ 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A,
+ 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A,
+ 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A,
+ 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A,
+ 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A,
+ 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A,
+ 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A,
+ /* test non-BMP code points */
+ 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F,
+ 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8,
+ 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF,
+ 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6,
+ 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB,
+ 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0,
+ 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8,
+ 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF,
+ 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4,
+ 0xD869, 0xDED5, 0xD800, 0xDC00, 0xD800, 0xDC00, 0xD800, 0xDC00, 0xDBFF, 0xDFFF,
+ 0xDBFF, 0xDFFF, 0xDBFF, 0xDFFF,
+
+
+ 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A,
+ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A,
+ 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A,
+ 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A,
+ 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,
+ };
+ static const char *fTestCases [] = {
+ "\\ud800\\udc00", /* smallest surrogate*/
+ "\\ud8ff\\udcff",
+ "\\udBff\\udFff", /* largest surrogate pair*/
+ "\\ud834\\udc00",
+ "\\U0010FFFF",
+ "Hello \\u9292 \\u9192 World!",
+ "Hell\\u0429o \\u9292 \\u9192 W\\u00e4rld!",
+ "Hell\\u0429o \\u9292 \\u9292W\\u00e4rld!",
+
+ "\\u0648\\u06c8", /* catch missing reset*/
+ "\\u0648\\u06c8",
+
+ "\\u4444\\uE001", /* lowest quotable*/
+ "\\u4444\\uf2FF", /* highest quotable*/
+ "\\u4444\\uf188\\u4444",
+ "\\u4444\\uf188\\uf288",
+ "\\u4444\\uf188abc\\u0429\\uf288",
+ "\\u9292\\u2222",
+ "Hell\\u0429\\u04230o \\u9292 \\u9292W\\u00e4\\u0192rld!",
+ "Hell\\u0429o \\u9292 \\u9292W\\u00e4rld!",
+ "Hello World!123456",
+ "Hello W\\u0081\\u011f\\u0082!", /* Latin 1 run*/
+
+ "abc\\u0301\\u0302", /* uses SQn for u301 u302*/
+ "abc\\u4411d", /* uses SQU*/
+ "abc\\u4411\\u4412d",/* uses SCU*/
+ "abc\\u0401\\u0402\\u047f\\u00a5\\u0405", /* uses SQn for ua5*/
+ "\\u9191\\u9191\\u3041\\u9191\\u3041\\u3041\\u3000", /* SJIS like data*/
+ "\\u9292\\u2222",
+ "\\u9191\\u9191\\u3041\\u9191\\u3041\\u3041\\u3000",
+ "\\u9999\\u3051\\u300c\\u9999\\u9999\\u3060\\u9999\\u3065\\u3065\\u3065\\u300c",
+ "\\u3000\\u266a\\u30ea\\u30f3\\u30b4\\u53ef\\u611b\\u3044\\u3084\\u53ef\\u611b\\u3044\\u3084\\u30ea\\u30f3\\u30b4\\u3002",
+
+ "", /* empty input*/
+ "\\u0000", /* smallest BMP character*/
+ "\\uFFFF", /* largest BMP character*/
+
+ /* regression tests*/
+ "\\u6441\\ub413\\ua733\\uf8fe\\ueedb\\u587f\\u195f\\u4899\\uf23d\\u49fd\\u0aac\\u5792\\ufc22\\ufc3c\\ufc46\\u00aa",
+ "\\u00df\\u01df\\uf000\\udbff\\udfff\\u000d\n\\u0041\\u00df\\u0401\\u015f\\u00df\\u01df\\uf000\\udbff\\udfff",
+ "\\u30f9\\u8321\\u05e5\\u181c\\ud72b\\u2019\\u99c9\\u2f2f\\uc10c\\u82e1\\u2c4d\\u1ebc\\u6013\\u66dc\\ubbde\\u94a5\\u4726\\u74af\\u3083\\u55b9\\u000c",
+ "\\u0041\\u00df\\u0401\\u015f",
+ "\\u9066\\u2123abc",
+ "\\ud266\\u43d7\\u\\ue386\\uc9c0\\u4a6b\\u9222\\u901f\\u7410\\ua63f\\u539b\\u9596\\u482e\\u9d47\\ucfe4\\u7b71\\uc280\\uf26a\\u982f\\u862a\\u4edd\\uf513\\ufda6\\u869d\\u2ee0\\ua216\\u3ff6\\u3c70\\u89c0\\u9576\\ud5ec\\ubfda\\u6cca\\u5bb3\\ubcea\\u554c\\u914e\\ufa4a\\uede3\\u2990\\ud2f5\\u2729\\u5141\\u0f26\\uccd8\\u5413\\ud196\\ubbe2\\u51b9\\u9b48\\u0dc8\\u2195\\u21a2\\u21e9\\u00e4\\u9d92\\u0bc0\\u06c5",
+ "\\uf95b\\u2458\\u2468\\u0e20\\uf51b\\ue36e\\ubfc1\\u0080\\u02dd\\uf1b5\\u0cf3\\u6059\\u7489",
+ };
+ int i=0;
+ for(;i<sizeof(fTestCases)/sizeof(*fTestCases);i++){
+ const char* cSrc = fTestCases[i];
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t cSrcLen,srcLen;
+ UChar* src;
+ /* UConverter* cnv = ucnv_open("SCSU",&status); */
+ cSrcLen = srcLen = (int32_t)uprv_strlen(fTestCases[i]);
+ src = (UChar*) malloc((sizeof(UChar) * srcLen) + sizeof(UChar));
+ srcLen=unescape(src,srcLen,cSrc,cSrcLen,&status);
+ log_verbose("Testing roundtrip for src: %s at index :%d\n",cSrc,i);
+ TestConv(src,srcLen,"SCSU","Coverage",NULL,0);
+ free(src);
+ }
+ TestConv(allFeaturesUTF16,(sizeof(allFeaturesUTF16)/2),"SCSU","all features", (char *)allFeaturesSCSU,sizeof(allFeaturesSCSU));
+ TestConv(allFeaturesUTF16,(sizeof(allFeaturesUTF16)/2),"SCSU","all features",(char *)allFeaturesSCSU,sizeof(allFeaturesSCSU));
+ TestConv(japaneseUTF16,(sizeof(japaneseUTF16)/2),"SCSU","japaneese",(char *)japaneseSCSU,sizeof(japaneseSCSU));
+ TestConv(japaneseUTF16,(sizeof(japaneseUTF16)/2),"SCSU,locale=ja","japaneese",(char *)japaneseSCSU,sizeof(japaneseSCSU));
+ TestConv(germanUTF16,(sizeof(germanUTF16)/2),"SCSU","german",(char *)germanSCSU,sizeof(germanSCSU));
+ TestConv(russianUTF16,(sizeof(russianUTF16)/2), "SCSU","russian",(char *)russianSCSU,sizeof(russianSCSU));
+ TestConv(monkeyIn,(sizeof(monkeyIn)/2),"SCSU","monkey",NULL,0);
+}
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+static void TestJitterbug2346(){
+ char source[] = { 0x1b,0x24,0x42,0x3d,0x45,0x1b,0x28,0x4a,0x0d,0x0a,
+ 0x1b,0x24,0x42,0x3d,0x45,0x1b,0x28,0x4a,0x0d,0x0a};
+ uint16_t expected[] = {0x91CD,0x000D,0x000A,0x91CD,0x000D,0x000A};
+
+ UChar uTarget[500]={'\0'};
+ UChar* utarget=uTarget;
+ UChar* utargetLimit=uTarget+sizeof(uTarget)/2;
+
+ char cTarget[500]={'\0'};
+ char* ctarget=cTarget;
+ char* ctargetLimit=cTarget+sizeof(cTarget);
+ const char* csource=source;
+ UChar* temp = expected;
+ UErrorCode err=U_ZERO_ERROR;
+
+ UConverter* conv =ucnv_open("ISO_2022_JP",&err);
+ if(U_FAILURE(err)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
+ return;
+ }
+ ucnv_toUnicode(conv,&utarget,utargetLimit,&csource,csource+sizeof(source),NULL,TRUE,&err);
+ if(U_FAILURE(err)) {
+ log_err("ISO_2022_JP to Unicode conversion failed: %s\n", u_errorName(err));
+ return;
+ }
+ utargetLimit=utarget;
+ utarget = uTarget;
+ while(utarget<utargetLimit){
+ if(*temp!=*utarget){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*utarget,(int)*temp) ;
+ }
+ utarget++;
+ temp++;
+ }
+ ucnv_fromUnicode(conv,&ctarget,ctargetLimit,(const UChar**)&utarget,utargetLimit,NULL,TRUE,&err);
+ if(U_FAILURE(err)) {
+ log_err("ISO_2022_JP from Unicode conversion failed: %s\n", u_errorName(err));
+ return;
+ }
+ ctargetLimit=ctarget;
+ ctarget =cTarget;
+ ucnv_close(conv);
+
+
+}
+
+static void
+TestISO_2022_JP_1() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x3000, 0x3001, 0x3002, 0x0020, 0xFF0E, 0x30FB, 0xFF1A, 0xFF1B, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, 0x005C, 0x000D, 0x000A,
+ 0x301C, 0x2016, 0x2026, 0x2025, 0x2018, 0x2019, 0x201C, 0x000D, 0x000A,
+ 0x201D, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x4F94, 0x4F97, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x4F78, 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84, 0x000D, 0x000A,
+ 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92, 0x4F93, 0x000D, 0x000A,
+ 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x000D, 0x000A
+ };
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+
+ cnv=ucnv_open("ISO_2022_JP_1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,NULL,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,NULL,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ /*ucnv_close(cnv);
+ cnv=ucnv_open("ISO_2022,locale=jp,version=1", &errorCode);*/
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x0e,0x24,0x053};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-JP-1]");
+ }
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+}
+
+static void
+TestISO_2022_JP_2() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x00A8, 0x3003, 0x3005, 0x2015, 0xFF5E, 0x2016, 0x2026, 0x2018, 0x000D, 0x000A,
+ 0x2019, 0x201C, 0x201D, 0x3014, 0x3015, 0x3008, 0x3009, 0x300A, 0x000D, 0x000A,
+ 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3016, 0x3017, 0x3010, 0x000D, 0x000A,
+ 0x3011, 0x00B1, 0x00D7, 0x00F7, 0x2236, 0x2227, 0x7FC1, 0x8956, 0x000D, 0x000A,
+ 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, 0x5C4B, 0x000D, 0x000A,
+ 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, 0x57F7, 0x000D, 0x000A,
+ 0x57F4, 0x57F9, 0x57FA, 0x57FC, 0x5800, 0x5802, 0x5805, 0x5806, 0x000D, 0x000A,
+ 0x580A, 0x581E, 0x6BB5, 0x6BB7, 0x6BBA, 0x6BBC, 0x9CE2, 0x977C, 0x000D, 0x000A,
+ 0x6BBF, 0x6BC1, 0x6BC5, 0x6BC6, 0x6BCB, 0x6BCD, 0x6BCF, 0x6BD2, 0x000D, 0x000A,
+ 0x6BD3, 0x6BD4, 0x6BD6, 0x6BD7, 0x6BD8, 0x6BDB, 0x6BEB, 0x6BEC, 0x000D, 0x000A,
+ 0x6C05, 0x6C08, 0x6C0F, 0x6C11, 0x6C13, 0x6C23, 0x6C34, 0x0041, 0x000D, 0x000A,
+ 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x000D, 0x000A,
+ 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x000D, 0x000A,
+ 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x000D, 0x000A,
+ 0x005B, 0x9792, 0x9CCC, 0x9CCD, 0x9CCE, 0x9CCF, 0x9CD0, 0x9CD3, 0x000D, 0x000A,
+ 0x9CD4, 0x9CD5, 0x9CD7, 0x9CD8, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9785, 0x9791, 0x00BD, 0x0390, 0x0385, 0x0386, 0x0388, 0x0389, 0x000D, 0x000A,
+ 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x000D, 0x000A,
+ 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x038A, 0x038C, 0x039C, 0x000D, 0x000A
+ };
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ISO_2022_JP_2", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x0e,0x24,0x053};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-JP-2]");
+ }
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void
+TestISO_2022_KR() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F66,0x9F67,0x9F6A,0x000A,0x000D
+ ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC02,0xAC04
+ ,0xAC07,0xAC08,0xAC09,0x0025,0x0026,0x0027,0x000A,0x000D,0x0028,0x0029
+ ,0x002A,0x002B,0x002C,0x002D,0x002E,0x53C3,0x53C8,0x53C9,0x53CA,0x53CB
+ ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53DF,0x53E1,0x53E2
+ ,0x53E3,0x53E4,0x000A,0x000D};
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ISO_2022,locale=kr", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-KR encoding");
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestJitterbug930("csISO2022KR");
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x1b,0x24,0x053};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_ESCAPE_SEQUENCE, "an invalid character [ISO-2022-KR]");
+ }
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void
+TestISO_2022_KR_1() {
+ /* test input */
+ static const uint16_t in[]={
+ 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F67,0x9F6A,0x000A,0x000D
+ ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC04
+ ,0xAC07,0xAC08,0xAC09,0x0025,0x0026,0x0027,0x000A,0x000D,0x0028,0x0029
+ ,0x002A,0x002B,0x002C,0x002D,0x002E,0x53C3,0x53C8,0x53C9,0x53CA,0x53CB
+ ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53E1,0x53E2
+ ,0x53E3,0x53E4,0x000A,0x000D};
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 120;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ibm-25546", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 5);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ ucnv_reset(cnv);
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-KR encoding");
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ ucnv_reset(cnv);
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x1b,0x24,0x053};
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ILLEGAL_ESCAPE_SEQUENCE, "an invalid character [ISO-2022-KR]");
+ }
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void TestJitterbug2411(){
+ static const char* source = "\x1b\x24\x29\x43\x6b\x6b\x6e\x6e\x6a\x68\x70\x6f\x69\x75\x79\x71\x77\x65\x68\x67\x0A"
+ "\x1b\x24\x29\x43\x6a\x61\x73\x64\x66\x6a\x61\x73\x64\x66\x68\x6f\x69\x75\x79\x1b\x24\x29\x43";
+ UConverter* kr=NULL, *kr1=NULL;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ UChar tgt[100]={'\0'};
+ UChar* target = tgt;
+ UChar* targetLimit = target+100;
+ kr=ucnv_open("iso-2022-kr", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022-kr converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucnv_toUnicode(kr,&target,targetLimit,&source,source+uprv_strlen(source),NULL,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("iso-2022-kr cannot handle multiple escape sequences : %s\n", u_errorName(errorCode));
+ return;
+ }
+ kr1 = ucnv_open("ibm-25546", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022-kr_1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ target = tgt;
+ targetLimit = target+100;
+ ucnv_toUnicode(kr,&target,targetLimit,&source,source+uprv_strlen(source),NULL,TRUE,&errorCode);
+
+ if(U_FAILURE(errorCode)) {
+ log_err("iso-2022-kr_1 cannot handle multiple escape sequences : %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ ucnv_close(kr);
+ ucnv_close(kr1);
+
+}
+
+static void
+TestJIS(){
+ /* From Unicode moved to testdata/conversion.txt */
+ /*To Unicode*/
+ {
+ static const uint8_t sampleTextJIS[] = {
+ 0x1b,0x28,0x48,0x41,0x42, /*jis-Roman*/
+ 0x1b,0x28,0x49,0x41,0x42, /*Katakana Set*/
+ 0x1b,0x26,0x40,0x1b,0x24,0x42,0x21,0x21 /*recognize and ignore <esc>&@*/
+ };
+ static const uint16_t expectedISO2022JIS[] = {
+ 0x0041, 0x0042,
+ 0xFF81, 0xFF82,
+ 0x3000
+ };
+ static const int32_t toISO2022JISOffs[]={
+ 3,4,
+ 8,9,
+ 16
+ };
+
+ static const uint8_t sampleTextJIS7[] = {
+ 0x1b,0x28,0x48,0x41,0x42, /*JIS7-Roman*/
+ 0x1b,0x28,0x49,0x41,0x42, /*Katakana Set*/
+ 0x1b,0x24,0x42,0x21,0x21,
+ 0x0e,0x41,0x42,0x0f, /*Test Katakana set with SI and SO */
+ 0x21,0x22,
+ 0x1b,0x26,0x40,0x1b,0x24,0x42,0x21,0x21 /*recognize and ignore <esc>&@*/
+ };
+ static const uint16_t expectedISO2022JIS7[] = {
+ 0x0041, 0x0042,
+ 0xFF81, 0xFF82,
+ 0x3000,
+ 0xFF81, 0xFF82,
+ 0x3001,
+ 0x3000
+ };
+ static const int32_t toISO2022JIS7Offs[]={
+ 3,4,
+ 8,9,
+ 13,16,
+ 17,
+ 19,27
+ };
+ static const uint8_t sampleTextJIS8[] = {
+ 0x1b,0x28,0x48,0x41,0x42, /*JIS8-Roman*/
+ 0xa1,0xc8,0xd9,/*Katakana Set*/
+ 0x1b,0x28,0x42,
+ 0x41,0x42,
+ 0xb1,0xc3, /*Katakana Set*/
+ 0x1b,0x24,0x42,0x21,0x21
+ };
+ static const uint16_t expectedISO2022JIS8[] = {
+ 0x0041, 0x0042,
+ 0xff61, 0xff88, 0xff99,
+ 0x0041, 0x0042,
+ 0xff71, 0xff83,
+ 0x3000
+ };
+ static const int32_t toISO2022JIS8Offs[]={
+ 3, 4, 5, 6,
+ 7, 11, 12, 13,
+ 14, 18,
+ };
+
+ testConvertToU(sampleTextJIS,sizeof(sampleTextJIS),expectedISO2022JIS,
+ sizeof(expectedISO2022JIS)/sizeof(expectedISO2022JIS[0]),"JIS", toISO2022JISOffs,TRUE);
+ testConvertToU(sampleTextJIS7,sizeof(sampleTextJIS7),expectedISO2022JIS7,
+ sizeof(expectedISO2022JIS7)/sizeof(expectedISO2022JIS7[0]),"JIS7", toISO2022JIS7Offs,TRUE);
+ testConvertToU(sampleTextJIS8,sizeof(sampleTextJIS8),expectedISO2022JIS8,
+ sizeof(expectedISO2022JIS8)/sizeof(expectedISO2022JIS8[0]),"JIS8", toISO2022JIS8Offs,TRUE);
+ }
+
+}
+
+static void TestJitterbug915(){
+/* tests for roundtripping of the below sequence
+\x1b$)G\x0E#!#"###$#%#&#'#(#)#*#+ / *plane 1 * /
+\x1b$*H\x1bN"!\x1bN""\x1bN"#\x1bN"$\x1bN"% / *plane 2 * /
+\x1b$+I\x1bO"D\x1bO"E\x1bO"F\x1bO"G\x1bO"H / *plane 3 * /
+\x1b$+J\x1bO!D\x1bO!E\x1bO"j\x1bO"k\x1bO"l / *plane 4 * /
+\x1b$+K\x1bO!t\x1bO"P\x1bO"Q\x1bO#7\x1bO"\ / *plane 5 * /
+\x1b$+L\x1bO!#\x1bO",\x1bO#N\x1bO!n\x1bO#q / *plane 6 * /
+\x1b$+M\x1bO"q\x1bO!N\x1bO!j\x1bO#:\x1bO#o / *plane 7 * /
+*/
+ static const char cSource[]={
+ 0x1B, 0x24, 0x29, 0x47, 0x0E, 0x23, 0x21, 0x23, 0x22, 0x23,
+ 0x23, 0x23, 0x24, 0x23, 0x25, 0x23, 0x26, 0x23, 0x27, 0x23,
+ 0x28, 0x23, 0x29, 0x23, 0x2A, 0x23, 0x2B, 0x0F, 0x2F, 0x2A,
+ 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20, 0x31, 0x20, 0x2A, 0x2F,
+ 0x0D, 0x0A, 0x1B, 0x24, 0x2A, 0x48, 0x1B, 0x4E, 0x22, 0x21,
+ 0x1B, 0x4E, 0x22, 0x22, 0x1B, 0x4E, 0x22, 0x23, 0x1B, 0x4E,
+ 0x22, 0x24, 0x1B, 0x4E, 0x22, 0x25, 0x2F, 0x2A, 0x70,
+ 0x6C, 0x61, 0x6E, 0x65, 0x32, 0x2A, 0x2F, 0x20, 0x0D, 0x0A,
+ 0x1B, 0x24, 0x2B, 0x49, 0x1B, 0x4F, 0x22, 0x44, 0x1B, 0x4F,
+ 0x22, 0x45, 0x1B, 0x4F, 0x22, 0x46, 0x1B, 0x4F, 0x22, 0x47,
+ 0x1B, 0x4F, 0x22, 0x48, 0x2F, 0x2A, 0x70, 0x6C, 0x61,
+ 0x6E, 0x65, 0x20, 0x33, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B,
+ 0x24, 0x2B, 0x4A, 0x1B, 0x4F, 0x21, 0x44, 0x1B, 0x4F, 0x21,
+ 0x45, 0x1B, 0x4F, 0x22, 0x6A, 0x1B, 0x4F, 0x22, 0x6B, 0x1B,
+ 0x4F, 0x22, 0x6C, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x34, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4B, 0x1B, 0x4F, 0x21, 0x74, 0x1B, 0x4F, 0x22, 0x50,
+ 0x1B, 0x4F, 0x22, 0x51, 0x1B, 0x4F, 0x23, 0x37, 0x1B, 0x4F,
+ 0x22, 0x5C, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E,
+ 0x65, 0x20, 0x35, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24,
+ 0x2B, 0x4C, 0x1B, 0x4F, 0x21, 0x23, 0x1B, 0x4F, 0x22, 0x2C,
+ 0x1B, 0x4F, 0x23, 0x4E, 0x1B, 0x4F, 0x21, 0x6E, 0x1B, 0x4F,
+ 0x23, 0x71, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65,
+ 0x20, 0x36, 0x20, 0x2A, 0x2F, 0x0D, 0x0A, 0x1B, 0x24, 0x2B,
+ 0x4D, 0x1B, 0x4F, 0x22, 0x71, 0x1B, 0x4F, 0x21, 0x4E, 0x1B,
+ 0x4F, 0x21, 0x6A, 0x1B, 0x4F, 0x23, 0x3A, 0x1B, 0x4F, 0x23,
+ 0x6F, 0x2F, 0x2A, 0x70, 0x6C, 0x61, 0x6E, 0x65, 0x20,
+ 0x37, 0x20, 0x2A, 0x2F
+ };
+ UChar uTarget[500]={'\0'};
+ UChar* utarget=uTarget;
+ UChar* utargetLimit=uTarget+sizeof(uTarget)/2;
+
+ char cTarget[500]={'\0'};
+ char* ctarget=cTarget;
+ char* ctargetLimit=cTarget+sizeof(cTarget);
+ const char* csource=cSource;
+ const char* tempSrc = cSource;
+ UErrorCode err=U_ZERO_ERROR;
+
+ UConverter* conv =ucnv_open("ISO_2022_CN_EXT",&err);
+ if(U_FAILURE(err)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
+ return;
+ }
+ ucnv_toUnicode(conv,&utarget,utargetLimit,&csource,csource+sizeof(cSource),NULL,TRUE,&err);
+ if(U_FAILURE(err)) {
+ log_err("iso-2022-CN to Unicode conversion failed: %s\n", u_errorName(err));
+ return;
+ }
+ utargetLimit=utarget;
+ utarget = uTarget;
+ ucnv_fromUnicode(conv,&ctarget,ctargetLimit,(const UChar**)&utarget,utargetLimit,NULL,TRUE,&err);
+ if(U_FAILURE(err)) {
+ log_err("iso-2022-CN from Unicode conversion failed: %s\n", u_errorName(err));
+ return;
+ }
+ ctargetLimit=ctarget;
+ ctarget =cTarget;
+ while(ctarget<ctargetLimit){
+ if(*ctarget != *tempSrc){
+ log_err("j915[%d] Expected : \\x%02X \t Got: \\x%02X\n", (int)(ctarget-cTarget), *ctarget,(int)*tempSrc) ;
+ }
+ ++ctarget;
+ ++tempSrc;
+ }
+
+ ucnv_close(conv);
+}
+
+static void
+TestISO_2022_CN_EXT() {
+ /* test input */
+ static const uint16_t in[]={
+ /* test Non-BMP code points */
+ 0xD869, 0xDE99, 0xD869, 0xDE9C, 0xD869, 0xDE9D, 0xD869, 0xDE9E, 0xD869, 0xDE9F,
+ 0xD869, 0xDEA0, 0xD869, 0xDEA5, 0xD869, 0xDEA6, 0xD869, 0xDEA7, 0xD869, 0xDEA8,
+ 0xD869, 0xDEAB, 0xD869, 0xDEAC, 0xD869, 0xDEAD, 0xD869, 0xDEAE, 0xD869, 0xDEAF,
+ 0xD869, 0xDEB0, 0xD869, 0xDEB1, 0xD869, 0xDEB3, 0xD869, 0xDEB5, 0xD869, 0xDEB6,
+ 0xD869, 0xDEB7, 0xD869, 0xDEB8, 0xD869, 0xDEB9, 0xD869, 0xDEBA, 0xD869, 0xDEBB,
+ 0xD869, 0xDEBC, 0xD869, 0xDEBD, 0xD869, 0xDEBE, 0xD869, 0xDEBF, 0xD869, 0xDEC0,
+ 0xD869, 0xDEC1, 0xD869, 0xDEC2, 0xD869, 0xDEC3, 0xD869, 0xDEC4, 0xD869, 0xDEC8,
+ 0xD869, 0xDECA, 0xD869, 0xDECB, 0xD869, 0xDECD, 0xD869, 0xDECE, 0xD869, 0xDECF,
+ 0xD869, 0xDED0, 0xD869, 0xDED1, 0xD869, 0xDED2, 0xD869, 0xDED3, 0xD869, 0xDED4,
+ 0xD869, 0xDED5,
+
+ 0x4DB3, 0x4DB4, 0x4DB5, 0x4E00, 0x4E00, 0x4E01, 0x4E02, 0x4E03, 0x000D, 0x000A,
+ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x33E0, 0x33E6, 0x000D, 0x000A,
+ 0x4E05, 0x4E07, 0x4E04, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x000D, 0x000A,
+ 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A,
+ 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,
+ 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0x6332, 0x63B0, 0x643F, 0x000D, 0x000A,
+ 0x64D8, 0x8004, 0x6BEA, 0x6BF3, 0x6BFD, 0x6BF5, 0x6BF9, 0x6C05, 0x000D, 0x000A,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x000D, 0x000A,
+ 0x6C07, 0x6C06, 0x6C0D, 0x6C15, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9CE2, 0x977C, 0x9785, 0x9791, 0x9792, 0x9794, 0x97AF, 0x97AB, 0x000D, 0x000A,
+ 0x97A3, 0x97B2, 0x97B4, 0x9AB1, 0x9AB0, 0x9AB7, 0x9E58, 0x9AB6, 0x000D, 0x000A,
+ 0x9ABA, 0x9ABC, 0x9AC1, 0x9AC0, 0x9AC5, 0x9AC2, 0x9ACB, 0x9ACC, 0x000D, 0x000A,
+ 0x9AD1, 0x9B45, 0x9B43, 0x9B47, 0x9B49, 0x9B48, 0x9B4D, 0x9B51, 0x000D, 0x000A,
+ 0x98E8, 0x990D, 0x992E, 0x9955, 0x9954, 0x9ADF, 0x3443, 0x3444, 0x000D, 0x000A,
+ 0x3445, 0x3449, 0x344A, 0x344B, 0x60F2, 0x60F3, 0x60F4, 0x60F5, 0x000D, 0x000A,
+ 0x60F6, 0x60F7, 0x60F8, 0x60F9, 0x60FA, 0x60FB, 0x60FC, 0x60FD, 0x000D, 0x000A,
+ 0x60FE, 0x60FF, 0x6100, 0x6101, 0x6102, 0x0041, 0x0042, 0x0043, 0x000D, 0x000A,
+ 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x000D, 0x000A,
+
+ 0x33E7, 0x33E8, 0x33E9, 0x33EA, 0x000D, 0x000A
+
+ };
+
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 180;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ISO_2022,locale=cn,version=1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 10);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ else{
+ log_verbose(" Got: \\u%04X\n",(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x0e,0x24,0x053};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-CN-EXT]");
+ }
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void
+TestISO_2022_CN() {
+ /* test input */
+ static const uint16_t in[]={
+ /* jitterbug 951 */
+ 0xFF2D, 0xFF49, 0xFF58, 0xFF45, 0xFF44, 0x0020, 0xFF43, 0xFF48, 0xFF41, 0xFF52,
+ 0x0020, 0xFF06, 0x0020, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+ 0xFF18, 0xFF19, 0xFF10, 0x0020, 0xFF4E, 0xFF55, 0xFF4D, 0xFF42, 0xFF45, 0xFF52,
+ 0x0020, 0xFF54, 0xFF45, 0xFF53, 0xFF54, 0x0020, 0xFF4C, 0xFF49, 0xFF4E, 0xFF45,
+ 0x0020, 0x0045, 0x004e, 0x0044,
+ /**/
+ 0x4E00, 0x4E00, 0x4E01, 0x4E03, 0x60F6, 0x60F7, 0x60F8, 0x60FB, 0x000D, 0x000A,
+ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x60FB, 0x60FC, 0x000D, 0x000A,
+ 0x4E07, 0x4E08, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x0042, 0x0043, 0x000D, 0x000A,
+ 0x4E0C, 0x0021, 0x0022, 0x0023, 0x0024, 0xFF40, 0xFF41, 0xFF42, 0x000D, 0x000A,
+ 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0x000D, 0x000A,
+ 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0x6332, 0x63B0, 0x643F, 0x000D, 0x000A,
+ 0x64D8, 0x8004, 0x6BEA, 0x6BF3, 0x6BFD, 0x6BF5, 0x6BF9, 0x6C05, 0x000D, 0x000A,
+ 0x6C07, 0x6C06, 0x6C0D, 0x6C15, 0x9CD9, 0x9CDC, 0x9CDD, 0x9CDF, 0x000D, 0x000A,
+ 0x9CE2, 0x977C, 0x9785, 0x9791, 0x9792, 0x9794, 0x97AF, 0x97AB, 0x000D, 0x000A,
+ 0x97A3, 0x97B2, 0x97B4, 0x9AB1, 0x9AB0, 0x9AB7, 0x9E58, 0x9AB6, 0x000D, 0x000A,
+ 0x9ABA, 0x9ABC, 0x9AC1, 0x9AC0, 0x9AC5, 0x9AC2, 0x9ACB, 0x9ACC, 0x000D, 0x000A,
+ 0x9AD1, 0x9B45, 0x9B43, 0x9B47, 0x9B49, 0x9B48, 0x9B4D, 0x9B51, 0x000D, 0x000A,
+ 0x98E8, 0x990D, 0x992E, 0x9955, 0x9954, 0x9ADF, 0x60FE, 0x60FF, 0x000D, 0x000A,
+ 0x60F2, 0x60F3, 0x60F4, 0x60F5, 0x000D, 0x000A, 0x60F9, 0x60FA, 0x000D, 0x000A,
+ 0x6100, 0x6101, 0x0041, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x000D, 0x000A,
+ 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486,
+ 0x2487, 0x2460, 0x2461, 0xFF20, 0xFF21, 0xFF22, 0x0049, 0x004A, 0x000D, 0x000A,
+
+ };
+ const UChar* uSource;
+ const UChar* uSourceLimit;
+ const char* cSource;
+ const char* cSourceLimit;
+ UChar *uTargetLimit =NULL;
+ UChar *uTarget;
+ char *cTarget;
+ const char *cTargetLimit;
+ char *cBuf;
+ UChar *uBuf,*test;
+ int32_t uBufSize = 180;
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv;
+ int32_t* offsets = (int32_t*) malloc(uBufSize * sizeof(int32_t) * 5);
+ int32_t* myOff= offsets;
+ cnv=ucnv_open("ISO_2022,locale=cn,version=0", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a iso-2022 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ uBuf = (UChar*)malloc(uBufSize * sizeof(UChar)*5);
+ cBuf =(char*)malloc(uBufSize * sizeof(char) * 10);
+ uSource = (const UChar*)in;
+ uSourceLimit=(const UChar*)in + (sizeof(in)/sizeof(in[0]));
+ cTarget = cBuf;
+ cTargetLimit = cBuf +uBufSize*5;
+ uTarget = uBuf;
+ uTargetLimit = uBuf+ uBufSize*5;
+ ucnv_fromUnicode( cnv , &cTarget, cTargetLimit,&uSource,uSourceLimit,myOff,TRUE, &errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_fromUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ cSource = cBuf;
+ cSourceLimit =cTarget;
+ test =uBuf;
+ myOff=offsets;
+ ucnv_toUnicode(cnv,&uTarget,uTargetLimit,&cSource,cSourceLimit,myOff,TRUE,&errorCode);
+ if(U_FAILURE(errorCode)){
+ log_err("ucnv_toUnicode conversion failed reason %s\n", u_errorName(errorCode));
+ return;
+ }
+ uSource = (const UChar*)in;
+ while(uSource<uSourceLimit){
+ if(*test!=*uSource){
+ log_err("Expected : \\u%04X \t Got: \\u%04X\n",*uSource,(int)*test) ;
+ }
+ else{
+ log_verbose(" Got: \\u%04X\n",(int)*test) ;
+ }
+ uSource++;
+ test++;
+ }
+ TestGetNextUChar2022(cnv, cBuf, cTarget, in, "ISO-2022-CN encoding");
+ TestSmallTargetBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestSmallSourceBuffer(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestToAndFromUChars(in,(const UChar*)in + (sizeof(in)/sizeof(in[0])),cnv);
+ TestJitterbug930("csISO2022CN");
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x0e,0x24,0x053};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [ISO-2022-CN]");
+ }
+
+ ucnv_close(cnv);
+ free(uBuf);
+ free(cBuf);
+ free(offsets);
+}
+
+static void
+TestEBCDIC_STATEFUL() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x61,
+ 0x1a,
+ 0x0f, 0x4b,
+ 0x42,
+ 0x40,
+ 0x36,
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x002f,
+ 1, 0x0092,
+ 2, 0x002e,
+ 1, 0xff62,
+ 1, 0x0020,
+ 1, 0x0096,
+
+ };
+ static const uint8_t in2[]={
+ 0x0f,
+ 0xa1,
+ 0x01
+ };
+
+ /* expected test results */
+ static const int32_t results2[]={
+ /* number of bytes read, code point */
+ 2, 0x203E,
+ 1, 0x0001,
+ };
+
+ const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("ibm-930", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a EBCDIC_STATEFUL(ibm-930) converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, source, limit, results, "EBCDIC_STATEFUL(ibm-930)");
+ ucnv_reset(cnv);
+ /* Test the condition when source >= sourceLimit */
+ TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
+ ucnv_reset(cnv);
+ /*Test for the condition where source > sourcelimit after consuming the shift chracter */
+ {
+ static const uint8_t source1[]={0x0f};
+ TestNextUCharError(cnv, (const char*)source1, (const char*)source1+sizeof(source1), U_INDEX_OUTOFBOUNDS_ERROR, "a character is truncated");
+ }
+ /*Test for the condition where there is an invalid character*/
+ ucnv_reset(cnv);
+ {
+ static const uint8_t source2[]={0x0e, 0x7F, 0xFF};
+ TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character [EBCDIC STATEFUL]");
+ }
+ ucnv_reset(cnv);
+ source=(const char*)in2;
+ limit=(const char*)in2+sizeof(in2);
+ TestNextUChar(cnv,source,limit,results2,"EBCDIC_STATEFUL(ibm-930),seq#2");
+ ucnv_close(cnv);
+
+}
+
+static void
+TestGB18030() {
+ /* test input */
+ static const uint8_t in[]={
+ 0x24,
+ 0x7f,
+ 0x81, 0x30, 0x81, 0x30,
+ 0xa8, 0xbf,
+ 0xa2, 0xe3,
+ 0xd2, 0xbb,
+ 0x82, 0x35, 0x8f, 0x33,
+ 0x84, 0x31, 0xa4, 0x39,
+ 0x90, 0x30, 0x81, 0x30,
+ 0xe3, 0x32, 0x9a, 0x35
+#if 0
+ /*
+ * Feature removed markus 2000-oct-26
+ * Only some codepages must match surrogate pairs into supplementary code points -
+ * see javadoc for ucnv_getNextUChar() and implementation notes in ucnvmbcs.c .
+ * GB 18030 provides direct encodings for supplementary code points, therefore
+ * it must not combine two single-encoded surrogates into one code point.
+ */
+ 0x83, 0x36, 0xc8, 0x30, 0x83, 0x37, 0xb0, 0x34 /* separately encoded surrogates */
+#endif
+ };
+
+ /* expected test results */
+ static const int32_t results[]={
+ /* number of bytes read, code point */
+ 1, 0x24,
+ 1, 0x7f,
+ 4, 0x80,
+ 2, 0x1f9,
+ 2, 0x20ac,
+ 2, 0x4e00,
+ 4, 0x9fa6,
+ 4, 0xffff,
+ 4, 0x10000,
+ 4, 0x10ffff
+#if 0
+ /* Feature removed. See comment above. */
+ 8, 0x10000
+#endif
+ };
+
+/* const char *source=(const char *)in,*limit=(const char *)in+sizeof(in); */
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv=ucnv_open("gb18030", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a gb18030 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ TestNextUChar(cnv, (const char *)in, (const char *)in+sizeof(in), results, "gb18030");
+ ucnv_close(cnv);
+}
+
+static void
+TestLMBCS() {
+ /* LMBCS-1 string */
+ static const uint8_t pszLMBCS[]={
+ 0x61,
+ 0x01, 0x29,
+ 0x81,
+ 0xA0,
+ 0x0F, 0x27,
+ 0x0F, 0x91,
+ 0x14, 0x0a, 0x74,
+ 0x14, 0xF6, 0x02,
+ 0x14, 0xd8, 0x4d, 0x14, 0xdc, 0x56, /* UTF-16 surrogate pair */
+ 0x10, 0x88, 0xA0,
+ };
+
+ /* Unicode UChar32 equivalents */
+ static const UChar32 pszUnicode32[]={
+ /* code point */
+ 0x00000061,
+ 0x00002013,
+ 0x000000FC,
+ 0x000000E1,
+ 0x00000007,
+ 0x00000091,
+ 0x00000a74,
+ 0x00000200,
+ 0x00023456, /* code point for surrogate pair */
+ 0x00005516
+ };
+
+/* Unicode UChar equivalents */
+ static const UChar pszUnicode[]={
+ /* code point */
+ 0x0061,
+ 0x2013,
+ 0x00FC,
+ 0x00E1,
+ 0x0007,
+ 0x0091,
+ 0x0a74,
+ 0x0200,
+ 0xD84D, /* low surrogate */
+ 0xDC56, /* high surrogate */
+ 0x5516
+ };
+
+/* expected test results */
+ static const int offsets32[]={
+ /* number of bytes read, code point */
+ 0,
+ 1,
+ 3,
+ 4,
+ 5,
+ 7,
+ 9,
+ 12,
+ 15,
+ 21,
+ 24
+ };
+
+/* expected test results */
+ static const int offsets[]={
+ /* number of bytes read, code point */
+ 0,
+ 1,
+ 3,
+ 4,
+ 5,
+ 7,
+ 9,
+ 12,
+ 15,
+ 18,
+ 21,
+ 24
+ };
+
+
+ UConverter *cnv;
+
+#define NAME_LMBCS_1 "LMBCS-1"
+#define NAME_LMBCS_2 "LMBCS-2"
+
+
+ /* Some basic open/close/property tests on some LMBCS converters */
+ {
+
+ char expected_subchars[] = {0x3F}; /* ANSI Question Mark */
+ char new_subchars [] = {0x7F}; /* subst char used by SmartSuite..*/
+ char get_subchars [1];
+ const char * get_name;
+ UConverter *cnv1;
+ UConverter *cnv2;
+
+ int8_t len = sizeof(get_subchars);
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ /* Open */
+ cnv1=ucnv_open(NAME_LMBCS_1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ cnv2=ucnv_open(NAME_LMBCS_2, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a LMBCS-2 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* Name */
+ get_name = ucnv_getName (cnv1, &errorCode);
+ if (strcmp(NAME_LMBCS_1,get_name)){
+ log_err("Unexpected converter name: %s\n", get_name);
+ }
+ get_name = ucnv_getName (cnv2, &errorCode);
+ if (strcmp(NAME_LMBCS_2,get_name)){
+ log_err("Unexpected converter name: %s\n", get_name);
+ }
+
+ /* substitution chars */
+ ucnv_getSubstChars (cnv1, get_subchars, &len, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Failure on get subst chars: %s\n", u_errorName(errorCode));
+ }
+ if (len!=1){
+ log_err("Unexpected length of sub chars\n");
+ }
+ if (get_subchars[0] != expected_subchars[0]){
+ log_err("Unexpected value of sub chars\n");
+ }
+ ucnv_setSubstChars (cnv2,new_subchars, len, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Failure on set subst chars: %s\n", u_errorName(errorCode));
+ }
+ ucnv_getSubstChars (cnv2, get_subchars, &len, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Failure on get subst chars: %s\n", u_errorName(errorCode));
+ }
+ if (len!=1){
+ log_err("Unexpected length of sub chars\n");
+ }
+ if (get_subchars[0] != new_subchars[0]){
+ log_err("Unexpected value of sub chars\n");
+ }
+ ucnv_close(cnv1);
+ ucnv_close(cnv2);
+
+ }
+
+ /* LMBCS to Unicode - offsets */
+ {
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ const char * pSource = (const char *)pszLMBCS;
+ const char * sourceLimit = (const char *)pszLMBCS + sizeof(pszLMBCS);
+
+ UChar Out [sizeof(pszUnicode) + 1];
+ UChar * pOut = Out;
+ UChar * OutLimit = Out + sizeof(pszUnicode)/sizeof(UChar);
+
+ int32_t off [sizeof(offsets)];
+
+ /* last 'offset' in expected results is just the final size.
+ (Makes other tests easier). Compensate here: */
+
+ off[(sizeof(offsets)/sizeof(offsets[0]))-1] = sizeof(pszLMBCS);
+
+
+
+ cnv=ucnv_open("lmbcs", &errorCode); /* use generic name for LMBCS-1 */
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a LMBCS converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+
+
+ ucnv_toUnicode (cnv,
+ &pOut,
+ OutLimit,
+ &pSource,
+ sourceLimit,
+ off,
+ TRUE,
+ &errorCode);
+
+
+ if (memcmp(off,offsets,sizeof(offsets)))
+ {
+ log_err("LMBCS->Uni: Calculated offsets do not match expected results\n");
+ }
+ if (memcmp(Out,pszUnicode,sizeof(pszUnicode)))
+ {
+ log_err("LMBCS->Uni: Calculated codepoints do not match expected results\n");
+ }
+ ucnv_close(cnv);
+ }
+ {
+ /* LMBCS to Unicode - getNextUChar */
+ const char * sourceStart;
+ const char *source=(const char *)pszLMBCS;
+ const char *limit=(const char *)pszLMBCS+sizeof(pszLMBCS);
+ const UChar32 *results= pszUnicode32;
+ const int *off = offsets32;
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UChar32 uniChar;
+
+ cnv=ucnv_open("LMBCS-1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_data_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+ else
+ {
+
+ while(source<limit) {
+ sourceStart=source;
+ uniChar=ucnv_getNextUChar(cnv, &source, source + (off[1] - off[0]), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("LMBCS-1 ucnv_getNextUChar() failed: %s\n", u_errorName(errorCode));
+ break;
+ } else if(source-sourceStart != off[1] - off[0] || uniChar != *results) {
+ log_err("LMBCS-1 ucnv_getNextUChar() result %lx from %d bytes, should have been %lx from %d bytes.\n",
+ uniChar, (source-sourceStart), *results, *off);
+ break;
+ }
+ results++;
+ off++;
+ }
+ }
+ ucnv_close(cnv);
+ }
+ { /* test locale & optimization group operations: Unicode to LMBCS */
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UConverter *cnv16he = ucnv_open("LMBCS-16,locale=he", &errorCode);
+ UConverter *cnv16jp = ucnv_open("LMBCS-16,locale=ja_JP", &errorCode);
+ UConverter *cnv01us = ucnv_open("LMBCS-1,locale=us_EN", &errorCode);
+ UChar uniString [] = {0x0192}; /* Latin Small letter f with hook */
+ const UChar * pUniOut = uniString;
+ UChar * pUniIn = uniString;
+ uint8_t lmbcsString [4];
+ const char * pLMBCSOut = (const char *)lmbcsString;
+ char * pLMBCSIn = (char *)lmbcsString;
+
+ /* 0192 (hook) converts to both group 3 & group 1. input locale should differentiate */
+ ucnv_fromUnicode (cnv16he,
+ &pLMBCSIn, (pLMBCSIn + sizeof(lmbcsString)/sizeof(lmbcsString[0])),
+ &pUniOut, pUniOut + sizeof(uniString)/sizeof(uniString[0]),
+ NULL, 1, &errorCode);
+
+ if (lmbcsString[0] != 0x3 || lmbcsString[1] != 0x83)
+ {
+ log_err("LMBCS-16,locale=he gives unexpected translation\n");
+ }
+
+ pLMBCSIn= (char *)lmbcsString;
+ pUniOut = uniString;
+ ucnv_fromUnicode (cnv01us,
+ &pLMBCSIn, (const char *)(lmbcsString + sizeof(lmbcsString)/sizeof(lmbcsString[0])),
+ &pUniOut, pUniOut + sizeof(uniString)/sizeof(uniString[0]),
+ NULL, 1, &errorCode);
+
+ if (lmbcsString[0] != 0x9F)
+ {
+ log_err("LMBCS-1,locale=US gives unexpected translation\n");
+ }
+
+ /* single byte char from mbcs char set */
+ lmbcsString[0] = 0xAE; /* 1/2 width katakana letter small Yo */
+ pLMBCSOut = (const char *)lmbcsString;
+ pUniIn = uniString;
+ ucnv_toUnicode (cnv16jp,
+ &pUniIn, pUniIn + 1,
+ &pLMBCSOut, (pLMBCSOut + 1),
+ NULL, 1, &errorCode);
+ if (U_FAILURE(errorCode) || pLMBCSOut != (const char *)lmbcsString+1 || pUniIn != uniString+1 || uniString[0] != 0xFF6E)
+ {
+ log_err("Unexpected results from LMBCS-16 single byte char\n");
+ }
+ /* convert to group 1: should be 3 bytes */
+ pLMBCSIn = (char *)lmbcsString;
+ pUniOut = uniString;
+ ucnv_fromUnicode (cnv01us,
+ &pLMBCSIn, (const char *)(pLMBCSIn + 3),
+ &pUniOut, pUniOut + 1,
+ NULL, 1, &errorCode);
+ if (U_FAILURE(errorCode) || pLMBCSIn != (const char *)lmbcsString+3 || pUniOut != uniString+1
+ || lmbcsString[0] != 0x10 || lmbcsString[1] != 0x10 || lmbcsString[2] != 0xAE)
+ {
+ log_err("Unexpected results to LMBCS-1 single byte mbcs char\n");
+ }
+ pLMBCSOut = (const char *)lmbcsString;
+ pUniIn = uniString;
+ ucnv_toUnicode (cnv01us,
+ &pUniIn, pUniIn + 1,
+ &pLMBCSOut, (const char *)(pLMBCSOut + 3),
+ NULL, 1, &errorCode);
+ if (U_FAILURE(errorCode) || pLMBCSOut != (const char *)lmbcsString+3 || pUniIn != uniString+1 || uniString[0] != 0xFF6E)
+ {
+ log_err("Unexpected results from LMBCS-1 single byte mbcs char\n");
+ }
+ pLMBCSIn = (char *)lmbcsString;
+ pUniOut = uniString;
+ ucnv_fromUnicode (cnv16jp,
+ &pLMBCSIn, (const char *)(pLMBCSIn + 1),
+ &pUniOut, pUniOut + 1,
+ NULL, 1, &errorCode);
+ if (U_FAILURE(errorCode) || pLMBCSIn != (const char *)lmbcsString+1 || pUniOut != uniString+1 || lmbcsString[0] != 0xAE)
+ {
+ log_err("Unexpected results to LMBCS-16 single byte mbcs char\n");
+ }
+ ucnv_close(cnv16he);
+ ucnv_close(cnv16jp);
+ ucnv_close(cnv01us);
+ }
+ {
+ /* Small source buffer testing, LMBCS -> Unicode */
+
+ UErrorCode errorCode=U_ZERO_ERROR;
+
+ const char * pSource = (const char *)pszLMBCS;
+ const char * sourceLimit = (const char *)pszLMBCS + sizeof(pszLMBCS);
+ int codepointCount = 0;
+
+ UChar Out [sizeof(pszUnicode) + 1];
+ UChar * pOut = Out;
+ UChar * OutLimit = Out + sizeof(pszUnicode)/sizeof(UChar);
+
+
+ cnv = ucnv_open(NAME_LMBCS_1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Unable to open a LMBCS-1 converter: %s\n", u_errorName(errorCode));
+ return;
+ }
+
+
+ while ((pSource < sourceLimit) && U_SUCCESS (errorCode))
+ {
+ ucnv_toUnicode (cnv,
+ &pOut,
+ OutLimit,
+ &pSource,
+ (pSource+1), /* claim that this is a 1- byte buffer */
+ NULL,
+ FALSE, /* FALSE means there might be more chars in the next buffer */
+ &errorCode);
+
+ if (U_SUCCESS (errorCode))
+ {
+ if ((pSource - (const char *)pszLMBCS) == offsets [codepointCount+1])
+ {
+ /* we are on to the next code point: check value */
+
+ if (Out[0] != pszUnicode[codepointCount]){
+ log_err("LMBCS->Uni result %lx should have been %lx \n",
+ Out[0], pszUnicode[codepointCount]);
+ }
+
+ pOut = Out; /* reset for accumulating next code point */
+ codepointCount++;
+ }
+ }
+ else
+ {
+ log_err("Unexpected Error on toUnicode: %s\n", u_errorName(errorCode));
+ }
+ }
+ {
+ /* limits & surrogate error testing */
+ char LIn [sizeof(pszLMBCS)];
+ const char * pLIn = LIn;
+
+ char LOut [sizeof(pszLMBCS)];
+ char * pLOut = LOut;
+
+ UChar UOut [sizeof(pszUnicode)];
+ UChar * pUOut = UOut;
+
+ UChar UIn [sizeof(pszUnicode)];
+ const UChar * pUIn = UIn;
+
+ int32_t off [sizeof(offsets)];
+ UChar32 uniChar;
+
+ errorCode=U_ZERO_ERROR;
+
+ /* negative source request should always return U_ILLEGAL_ARGUMENT_ERROR */
+ ucnv_fromUnicode(cnv, &pLOut,pLOut+1,&pUIn,pUIn-1,off,FALSE, &errorCode);
+ if (errorCode != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("Unexpected Error on negative source request to ucnv_fromUnicode: %s\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+ ucnv_toUnicode(cnv, &pUOut,pUOut+1,(const char **)&pLIn,(const char *)(pLIn-1),off,FALSE, &errorCode);
+ if (errorCode != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("Unexpected Error on negative source request to ucnv_toUnicode: %s\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+
+ uniChar = ucnv_getNextUChar(cnv, (const char **)&pLIn, (const char *)(pLIn-1), &errorCode);
+ if (errorCode != U_ILLEGAL_ARGUMENT_ERROR)
+ {
+ log_err("Unexpected Error on negative source request to ucnv_getNextUChar: %s\n", u_errorName(errorCode));
+ }
+ errorCode=U_ZERO_ERROR;
+
+ /* 0 byte source request - no error, no pointer movement */
+ ucnv_toUnicode(cnv, &pUOut,pUOut+1,(const char **)&pLIn,(const char *)pLIn,off,FALSE, &errorCode);
+ ucnv_fromUnicode(cnv, &pLOut,pLOut+1,&pUIn,pUIn,off,FALSE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("0 byte source request: unexpected error: %s\n", u_errorName(errorCode));
+ }
+ if ((pUOut != UOut) || (pUIn != UIn) || (pLOut != LOut) || (pLIn != LIn))
+ {
+ log_err("Unexpected pointer move in 0 byte source request \n");
+ }
+ /*0 byte source request - GetNextUChar : error & value == fffe or ffff */
+ uniChar = ucnv_getNextUChar(cnv, (const char **)&pLIn, (const char *)pLIn, &errorCode);
+ if (errorCode != U_INDEX_OUTOFBOUNDS_ERROR)
+ {
+ log_err("Unexpected Error on 0-byte source request to ucnv_getnextUChar: %s\n", u_errorName(errorCode));
+ }
+ if (((uint32_t)uniChar - 0xfffe) > 1) /* not 0xfffe<=uniChar<=0xffff */
+ {
+ log_err("Unexpected value on 0-byte source request to ucnv_getnextUChar \n");
+ }
+ errorCode = U_ZERO_ERROR;
+
+ /* running out of target room : U_BUFFER_OVERFLOW_ERROR */
+
+ pUIn = pszUnicode;
+ ucnv_fromUnicode(cnv, &pLOut,pLOut+offsets[4],&pUIn,pUIn+sizeof(pszUnicode)/sizeof(UChar),off,FALSE, &errorCode);
+ if (errorCode != U_BUFFER_OVERFLOW_ERROR || pLOut != LOut + offsets[4] || pUIn != pszUnicode+4 )
+ {
+ log_err("Unexpected results on out of target room to ucnv_fromUnicode\n");
+ }
+
+ errorCode = U_ZERO_ERROR;
+
+ pLIn = (const char *)pszLMBCS;
+ ucnv_toUnicode(cnv, &pUOut,pUOut+4,&pLIn,(pLIn+sizeof(pszLMBCS)),off,FALSE, &errorCode);
+ if (errorCode != U_BUFFER_OVERFLOW_ERROR || pUOut != UOut + 4 || pLIn != (const char *)pszLMBCS+offsets[4])
+ {
+ log_err("Unexpected results on out of target room to ucnv_toUnicode\n");
+ }
+
+ /* unpaired or chopped LMBCS surrogates */
+
+ /* OK high surrogate, Low surrogate is chopped */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ LIn [3] = (char)0x14;
+ LIn [4] = (char)0xDC;
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode);
+ if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 5)
+ {
+ log_err("Unexpected results on chopped low surrogate\n");
+ }
+
+ /* chopped at surrogate boundary */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+3),off,TRUE, &errorCode);
+ if (UOut[0] != 0xD801 || U_FAILURE(errorCode) || pUOut != UOut + 1 || pLIn != LIn + 3)
+ {
+ log_err("Unexpected results on chopped at surrogate boundary \n");
+ }
+
+ /* unpaired surrogate plus valid Unichar */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ LIn [3] = (char)0x14;
+ LIn [4] = (char)0xC9;
+ LIn [5] = (char)0xD0;
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+6),off,TRUE, &errorCode);
+ if (UOut[0] != 0xD801 || UOut[1] != 0xC9D0 || U_FAILURE(errorCode) || pUOut != UOut + 2 || pLIn != LIn + 6)
+ {
+ log_err("Unexpected results after unpaired surrogate plus valid Unichar \n");
+ }
+
+ /* unpaired surrogate plus chopped Unichar */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ LIn [3] = (char)0x14;
+ LIn [4] = (char)0xC9;
+
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode);
+ if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 5)
+ {
+ log_err("Unexpected results after unpaired surrogate plus chopped Unichar \n");
+ }
+
+ /* unpaired surrogate plus valid non-Unichar */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ LIn [3] = (char)0x0F;
+ LIn [4] = (char)0x3B;
+
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+5),off,TRUE, &errorCode);
+ if (UOut[0] != 0xD801 || UOut[1] != 0x1B || U_FAILURE(errorCode) || pUOut != UOut + 2 || pLIn != LIn + 5)
+ {
+ log_err("Unexpected results after unpaired surrogate plus valid non-Unichar\n");
+ }
+
+ /* unpaired surrogate plus chopped non-Unichar */
+ LIn [0] = (char)0x14;
+ LIn [1] = (char)0xD8;
+ LIn [2] = (char)0x01;
+ LIn [3] = (char)0x0F;
+
+ pLIn = LIn;
+ errorCode = U_ZERO_ERROR;
+ pUOut = UOut;
+
+ ucnv_toUnicode(cnv, &pUOut,pUOut+sizeof(UOut)/sizeof(UChar),(const char **)&pLIn,(const char *)(pLIn+4),off,TRUE, &errorCode);
+
+ if (UOut[0] != 0xD801 || errorCode != U_TRUNCATED_CHAR_FOUND || pUOut != UOut + 1 || pLIn != LIn + 4)
+ {
+ log_err("Unexpected results after unpaired surrogate plus chopped non-Unichar\n");
+ }
+ }
+ }
+ ucnv_close(cnv); /* final cleanup */
+}
+
+
+static void TestJitterbug255()
+{
+ static const uint8_t testBytes[] = { 0x95, 0xcf, 0x8a, 0xb7, 0x0d, 0x0a, 0x00 };
+ const char *testBuffer = (const char *)testBytes;
+ const char *testEnd = (const char *)testBytes + sizeof(testBytes);
+ UErrorCode status = U_ZERO_ERROR;
+ UChar32 result;
+ UConverter *cnv = 0;
+
+ cnv = ucnv_open("shift-jis", &status);
+ if (U_FAILURE(status) || cnv == 0) {
+ log_data_err("Failed to open the converter for SJIS.\n");
+ return;
+ }
+ while (testBuffer != testEnd)
+ {
+ result = ucnv_getNextUChar (cnv, &testBuffer, testEnd , &status);
+ if (U_FAILURE(status))
+ {
+ log_err("Failed to convert the next UChar for SJIS.\n");
+ break;
+ }
+ }
+ ucnv_close(cnv);
+}
+
+static void TestEBCDICUS4XML()
+{
+ UChar unicodes_x[] = {0x0000, 0x0000, 0x0000, 0x0000};
+ static const UChar toUnicodeMaps_x[] = {0x000A, 0x000A, 0x000D, 0x0000};
+ static const char fromUnicodeMaps_x[] = {0x25, 0x25, 0x0D, 0x00};
+ static const char newLines_x[] = {0x25, 0x15, 0x0D, 0x00};
+ char target_x[] = {0x00, 0x00, 0x00, 0x00};
+ UChar *unicodes = unicodes_x;
+ const UChar *toUnicodeMaps = toUnicodeMaps_x;
+ char *target = target_x;
+ const char* fromUnicodeMaps = fromUnicodeMaps_x, *newLines = newLines_x;
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv = 0;
+
+ cnv = ucnv_open("ebcdic-xml-us", &status);
+ if (U_FAILURE(status) || cnv == 0) {
+ log_data_err("Failed to open the converter for EBCDIC-XML-US.\n");
+ return;
+ }
+ ucnv_toUnicode(cnv, &unicodes, unicodes+3, (const char**)&newLines, newLines+3, NULL, TRUE, &status);
+ if (U_FAILURE(status) || memcmp(unicodes_x, toUnicodeMaps, sizeof(UChar)*3) != 0) {
+ log_err("To Unicode conversion failed in EBCDICUS4XML test. %s\n",
+ u_errorName(status));
+ printUSeqErr(unicodes_x, 3);
+ printUSeqErr(toUnicodeMaps, 3);
+ }
+ status = U_ZERO_ERROR;
+ ucnv_fromUnicode(cnv, &target, target+3, (const UChar**)&toUnicodeMaps, toUnicodeMaps+3, NULL, TRUE, &status);
+ if (U_FAILURE(status) || memcmp(target_x, fromUnicodeMaps, sizeof(char)*3) != 0) {
+ log_err("From Unicode conversion failed in EBCDICUS4XML test. %s\n",
+ u_errorName(status));
+ printSeqErr((const unsigned char*)target_x, 3);
+ printSeqErr((const unsigned char*)fromUnicodeMaps, 3);
+ }
+ ucnv_close(cnv);
+}
+#endif /* #if !UCONFIG_NO_LEGACY_COLLATION */
+
+#if !UCONFIG_NO_COLLATION
+
+static void TestJitterbug981(){
+ const UChar* rules;
+ int32_t rules_length, target_cap, bytes_needed, buff_size;
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *utf8cnv;
+ UCollator* myCollator;
+ char *buff;
+ int numNeeded=0;
+ utf8cnv = ucnv_open ("utf8", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open UTF-8 converter. Error: %s", u_errorName(status));
+ return;
+ }
+ myCollator = ucol_open("zh", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not open collator for zh locale. Error: %s", u_errorName(status));
+ return;
+ }
+
+ rules = ucol_getRules(myCollator, &rules_length);
+ buff_size = rules_length * ucnv_getMaxCharSize(utf8cnv);
+ buff = malloc(buff_size);
+
+ target_cap = 0;
+ do {
+ ucnv_reset(utf8cnv);
+ status = U_ZERO_ERROR;
+ if(target_cap >= buff_size) {
+ log_err("wanted %d bytes, only %d available\n", target_cap, buff_size);
+ break;
+ }
+ bytes_needed = ucnv_fromUChars(utf8cnv, buff, target_cap,
+ rules, rules_length, &status);
+ target_cap = (bytes_needed > target_cap) ? bytes_needed : target_cap +1;
+ if(numNeeded!=0 && numNeeded!= bytes_needed){
+ log_err("ucnv_fromUChars returns different values for required capacity in pre-flight and conversion modes");
+ break;
+ }
+ numNeeded = bytes_needed;
+ } while (status == U_BUFFER_OVERFLOW_ERROR);
+ ucol_close(myCollator);
+ ucnv_close(utf8cnv);
+ free(buff);
+}
+
+#endif
+
+static void TestJitterbug1293(){
+ static const UChar src[] = {0x30DE, 0x30A4, 0x5E83, 0x544A, 0x30BF, 0x30A4, 0x30D7,0x000};
+ char target[256];
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter* conv=NULL;
+ int32_t target_cap, bytes_needed, numNeeded = 0;
+ conv = ucnv_open("shift-jis",&status);
+ if(U_FAILURE(status)){
+ log_data_err("Could not open Shift-Jis converter. Error: %s", u_errorName(status));
+ return;
+ }
+
+ do{
+ target_cap =0;
+ bytes_needed = ucnv_fromUChars(conv,target,256,src,u_strlen(src),&status);
+ target_cap = (bytes_needed > target_cap) ? bytes_needed : target_cap +1;
+ if(numNeeded!=0 && numNeeded!= bytes_needed){
+ log_err("ucnv_fromUChars returns different values for required capacity in pre-flight and conversion modes");
+ }
+ numNeeded = bytes_needed;
+ } while (status == U_BUFFER_OVERFLOW_ERROR);
+ if(U_FAILURE(status)){
+ log_err("An error occured in ucnv_fromUChars. Error: %s", u_errorName(status));
+ return;
+ }
+ ucnv_close(conv);
+}
+static void TestJB5275_1(){
+
+ static const char* data = "\x3B\xB3\x0A" /* Easy characters */
+ "\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Gurmukhi test */
+ /* Switch script: */
+ "\xEF\x43\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Bengali test */
+ "\x3B\xB3\x0A" /* Easy characters - new line, so should default!*/
+ "\xEF\x40\x3B\xB3\x0A";
+ static const UChar expected[] ={
+ 0x003b, 0x0a15, 0x000a, /* Easy characters */
+ 0x0a22, 0x0a3c, 0x0a5c, 0x0a4d, 0x0a39, 0x000a, /* Gurmukhi test */
+ 0x09dd, 0x09dc, 0x09cd, 0x09b9, 0x000a, /* Switch script: to Bengali*/
+ 0x003b, 0x0a15, 0x000a, /* Easy characters - new line, so should default!*/
+ 0x003b, 0x0a15, 0x000a /* Back to Gurmukhi*/
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter* conv = ucnv_open("iscii-gur", &status);
+ UChar dest[100] = {'\0'};
+ UChar* target = dest;
+ UChar* targetLimit = dest+100;
+ const char* source = data;
+ const char* sourceLimit = data+strlen(data);
+ const UChar* exp = expected;
+ log_verbose("Testing switching back to default script when new line is encountered.\n");
+ ucnv_toUnicode(conv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &status);
+ if(U_FAILURE(status)){
+ log_err("conversion failed: %s \n", u_errorName(status));
+ }
+ targetLimit = target;
+ target = dest;
+ printUSeq(target, targetLimit-target);
+ while(target<targetLimit){
+ if(*exp!=*target){
+ log_err("did not get the expected output. \\u%04X != \\u%04X (got)\n", *exp, *target);
+ }
+ target++;
+ exp++;
+ }
+ ucnv_close(conv);
+}
+
+static void TestJB5275(){
+ static const char* data =
+ /* "\xEF\x42\xEF\x41\xA4\xD5\xE5\xB3\xEA\x0A" unsupported sequence \xEF\x41 */
+ /* "\xEF\x42\xEF\x41\xD4\xDA\xB3\xE8\xEA\x0A" unsupported sequence \xEF\x41 */
+ /* "\xEF\x44\xEF\x41\xC8\xE1\x8B\xDB\xB3\xE8 \xB3\xE4\xC1\xE8\x0A" unsupported sequence \xEF\x41 */
+ "\xEF\x4B\xC0\xE9\xBF\xE9\xE8\xD8\x0A" /* Gurmukhi test */
+ "\xEF\x4A\xC0\xD4\xBF\xD4\xE8\xD8\x0A" /* Gujarati test */
+ "\xEF\x48\x38\xB3\x0A" /* Kannada test */
+ "\xEF\x49\x39\xB3\x0A" /* Malayalam test */
+ "\xEF\x4A\x3A\xB3\x0A" /* Gujarati test */
+ "\xEF\x4B\x3B\xB3\x0A" /* Punjabi test */
+ /* "\xEF\x4C\x3C\xB3\x0A" unsupported sequence \xEF\x41 */;
+ static const UChar expected[] ={
+ 0x0A22, 0x0A3C, 0x0A5C, 0x0A4D, 0x0A39, 0x000A, /* Gurmukhi test */
+ 0x0AA2, 0x0AB5, 0x0AA1, 0x0AB5, 0x0ACD, 0x0AB9, 0x000A, /* Gujarati test */
+ 0x0038, 0x0C95, 0x000A, /* Kannada test */
+ 0x0039, 0x0D15, 0x000A, /* Malayalam test */
+ 0x003A, 0x0A95, 0x000A, /* Gujarati test */
+ 0x003B, 0x0A15, 0x000A, /* Punjabi test */
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter* conv = ucnv_open("iscii", &status);
+ UChar dest[100] = {'\0'};
+ UChar* target = dest;
+ UChar* targetLimit = dest+100;
+ const char* source = data;
+ const char* sourceLimit = data+strlen(data);
+ const UChar* exp = expected;
+ ucnv_toUnicode(conv, &target, targetLimit, &source, sourceLimit, NULL, TRUE, &status);
+ if(U_FAILURE(status)){
+ log_err("conversion failed: %s \n", u_errorName(status));
+ }
+ targetLimit = target;
+ target = dest;
+
+ printUSeq(target, targetLimit-target);
+
+ while(target<targetLimit){
+ if(*exp!=*target){
+ log_err("did not get the expected output. \\u%04X != \\u%04X (got)\n", *exp, *target);
+ }
+ target++;
+ exp++;
+ }
+ ucnv_close(conv);
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h
new file mode 100644
index 00000000000..e70bc08163f
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/nucnvtst.h
@@ -0,0 +1,23 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1997-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File NUCNVTST.H
+*
+* Modification History:
+* Name Description
+* Madhu Katragadda creation
+*********************************************************************************
+*/
+#ifndef _NUCNVTST
+#define _NUCNVTST
+/* C API TEST FOR CODESET CONVERSION COMPONENT */
+#include "cintltst.h"
+#include "unicode/utypes.h"
+
+static void TestInBufSizes(void);
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c
new file mode 100644
index 00000000000..e6cff642b23
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/putiltst.c
@@ -0,0 +1,371 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1998-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File putiltst.c (Tests the API in putil)
+*
+* Modification History:
+*
+* Date Name Description
+* 07/12/2000 Madhu Creation
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "cintltst.h"
+#include "cmemory.h"
+#include "unicode/putil.h"
+#include "unicode/ustring.h"
+#include "cstring.h"
+#include "putilimp.h"
+
+static UBool compareWithNAN(double x, double y);
+static void doAssert(double expect, double got, const char *message);
+
+static void TestPUtilAPI(void){
+
+ double n1=0.0, y1=0.0, expn1, expy1;
+ double value1 = 0.021;
+ UVersionInfo versionArray = {0x01, 0x00, 0x02, 0x02};
+ char versionString[17]; /* xxx.xxx.xxx.xxx\0 */
+ char *str=0;
+ UBool isTrue=FALSE;
+
+ log_verbose("Testing the API uprv_modf()\n");
+ y1 = uprv_modf(value1, &n1);
+ expn1=0;
+ expy1=0.021;
+ if(y1 != expy1 || n1 != expn1){
+ log_err("Error in uprv_modf. Expected IntegralValue=%f, Got=%f, \n Expected FractionalValue=%f, Got=%f\n",
+ expn1, n1, expy1, y1);
+ }
+ if(VERBOSITY){
+ log_verbose("[float] x = %f n = %f y = %f\n", value1, n1, y1);
+ }
+ log_verbose("Testing the API uprv_fmod()\n");
+ expn1=uprv_fmod(30.50, 15.00);
+ doAssert(expn1, 0.5, "uprv_fmod(30.50, 15.00) failed.");
+
+ log_verbose("Testing the API uprv_ceil()\n");
+ expn1=uprv_ceil(value1);
+ doAssert(expn1, 1, "uprv_ceil(0.021) failed.");
+
+ log_verbose("Testing the API uprv_floor()\n");
+ expn1=uprv_floor(value1);
+ doAssert(expn1, 0, "uprv_floor(0.021) failed.");
+
+ log_verbose("Testing the API uprv_fabs()\n");
+ expn1=uprv_fabs((2.02-1.345));
+ doAssert(expn1, 0.675, "uprv_fabs(2.02-1.345) failed.");
+
+ log_verbose("Testing the API uprv_fmax()\n");
+ doAssert(uprv_fmax(2.4, 1.2), 2.4, "uprv_fmax(2.4, 1.2) failed.");
+
+ log_verbose("Testing the API uprv_fmax() with x value= NaN\n");
+ expn1=uprv_fmax(uprv_getNaN(), 1.2);
+ doAssert(expn1, uprv_getNaN(), "uprv_fmax(uprv_getNaN(), 1.2) failed. when one parameter is NaN");
+
+ log_verbose("Testing the API uprv_fmin()\n");
+ doAssert(uprv_fmin(2.4, 1.2), 1.2, "uprv_fmin(2.4, 1.2) failed.");
+
+ log_verbose("Testing the API uprv_fmin() with x value= NaN\n");
+ expn1=uprv_fmin(uprv_getNaN(), 1.2);
+ doAssert(expn1, uprv_getNaN(), "uprv_fmin(uprv_getNaN(), 1.2) failed. when one parameter is NaN");
+
+ log_verbose("Testing the API uprv_max()\n");
+ doAssert(uprv_max(4, 2), 4, "uprv_max(4, 2) failed.");
+
+ log_verbose("Testing the API uprv_min()\n");
+ doAssert(uprv_min(-4, 2), -4, "uprv_min(-4, 2) failed.");
+
+ log_verbose("Testing the API uprv_trunc()\n");
+ doAssert(uprv_trunc(12.3456), 12, "uprv_trunc(12.3456) failed.");
+ doAssert(uprv_trunc(12.234E2), 1223, "uprv_trunc(12.234E2) failed.");
+ doAssert(uprv_trunc(uprv_getNaN()), uprv_getNaN(), "uprv_trunc(uprv_getNaN()) failed. with parameter=NaN");
+ doAssert(uprv_trunc(uprv_getInfinity()), uprv_getInfinity(), "uprv_trunc(uprv_getInfinity()) failed. with parameter=Infinity");
+
+
+ log_verbose("Testing the API uprv_pow10()\n");
+ doAssert(uprv_pow10(4), 10000, "uprv_pow10(4) failed.");
+
+ log_verbose("Testing the API uprv_isNegativeInfinity()\n");
+ isTrue=uprv_isNegativeInfinity(uprv_getInfinity() * -1);
+ if(isTrue != TRUE){
+ log_err("ERROR: uprv_isNegativeInfinity failed.\n");
+ }
+ log_verbose("Testing the API uprv_isPositiveInfinity()\n");
+ isTrue=uprv_isPositiveInfinity(uprv_getInfinity());
+ if(isTrue != TRUE){
+ log_err("ERROR: uprv_isPositiveInfinity failed.\n");
+ }
+ log_verbose("Testing the API uprv_isInfinite()\n");
+ isTrue=uprv_isInfinite(uprv_getInfinity());
+ if(isTrue != TRUE){
+ log_err("ERROR: uprv_isInfinite failed.\n");
+ }
+
+#if 0
+ log_verbose("Testing the API uprv_digitsAfterDecimal()....\n");
+ doAssert(uprv_digitsAfterDecimal(value1), 3, "uprv_digitsAfterDecimal() failed.");
+ doAssert(uprv_digitsAfterDecimal(1.2345E2), 2, "uprv_digitsAfterDecimal(1.2345E2) failed.");
+ doAssert(uprv_digitsAfterDecimal(1.2345E-2), 6, "uprv_digitsAfterDecimal(1.2345E-2) failed.");
+ doAssert(uprv_digitsAfterDecimal(1.2345E2), 2, "uprv_digitsAfterDecimal(1.2345E2) failed.");
+ doAssert(uprv_digitsAfterDecimal(-1.2345E-20), 24, "uprv_digitsAfterDecimal(1.2345E-20) failed.");
+ doAssert(uprv_digitsAfterDecimal(1.2345E20), 0, "uprv_digitsAfterDecimal(1.2345E20) failed.");
+ doAssert(uprv_digitsAfterDecimal(-0.021), 3, "uprv_digitsAfterDecimal(-0.021) failed.");
+ doAssert(uprv_digitsAfterDecimal(23.0), 0, "uprv_digitsAfterDecimal(23.0) failed.");
+ doAssert(uprv_digitsAfterDecimal(0.022223333321), 9, "uprv_digitsAfterDecimal(0.022223333321) failed.");
+#endif
+
+
+ log_verbose("Testing the API u_versionToString().....\n");
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "1.0.2.2") != 0){
+ log_err("ERROR: u_versionToString() failed. Expected: 1.0.2.2, Got=%s\n", versionString);
+ }
+ log_verbose("Testing the API u_versionToString().....with versionArray=NULL\n");
+ u_versionToString(NULL, versionString);
+ if(strcmp(versionString, "") != 0){
+ log_err("ERROR: u_versionToString() failed. with versionArray=NULL. It should just return\n");
+ }
+ log_verbose("Testing the API u_versionToString().....with versionArray=NULL\n");
+ u_versionToString(NULL, versionString);
+ if(strcmp(versionString, "") != 0){
+ log_err("ERROR: u_versionToString() failed . It should just return\n");
+ }
+ log_verbose("Testing the API u_versionToString().....with versionString=NULL\n");
+ u_versionToString(versionArray, NULL);
+ if(strcmp(versionString, "") != 0){
+ log_err("ERROR: u_versionToString() failed. with versionArray=NULL It should just return\n");
+ }
+ versionArray[0] = 0x0a;
+ log_verbose("Testing the API u_versionToString().....\n");
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "10.0.2.2") != 0){
+ log_err("ERROR: u_versionToString() failed. Expected: 10.0.2.2, Got=%s\n", versionString);
+ }
+ versionArray[0] = 0xa0;
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "160.0.2.2") != 0){
+ log_err("ERROR: u_versionToString() failed. Expected: 160.0.2.2, Got=%s\n", versionString);
+ }
+ versionArray[0] = 0xa0;
+ versionArray[1] = 0xa0;
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "160.160.2.2") != 0){
+ log_err("ERROR: u_versionToString() failed. Expected: 160.160.2.2, Got=%s\n", versionString);
+ }
+ versionArray[0] = 0x01;
+ versionArray[1] = 0x0a;
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "1.10.2.2") != 0){
+ log_err("ERROR: u_versionToString() failed. Expected: 160.160.2.2, Got=%s\n", versionString);
+ }
+
+ log_verbose("Testing the API u_versionFromString() ....\n");
+ u_versionFromString(versionArray, "1.3.5.6");
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "1.3.5.6") != 0){
+ log_err("ERROR: u_getVersion() failed. Expected: 1.3.5.6, Got=%s\n", versionString);
+ }
+ log_verbose("Testing the API u_versionFromString() where versionArray=NULL....\n");
+ u_versionFromString(NULL, "1.3.5.6");
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, "1.3.5.6") != 0){
+ log_err("ERROR: u_getVersion() failed. Expected: 1.3.5.6, Got=%s\n", versionString);
+ }
+
+ log_verbose("Testing the API u_getVersion().....\n");
+ u_getVersion(versionArray);
+ u_versionToString(versionArray, versionString);
+ if(strcmp(versionString, U_ICU_VERSION) != 0){
+ log_err("ERROR: u_getVersion() failed. Got=%s, expected %s\n", versionString, U_ICU_VERSION);
+ }
+ log_verbose("Testing the API u_errorName()...\n");
+ str=(char*)u_errorName((UErrorCode)0);
+ if(strcmp(str, "U_ZERO_ERROR") != 0){
+ log_err("ERROR: u_getVersion() failed. Expected: U_ZERO_ERROR Got=%s\n", str);
+ }
+ log_verbose("Testing the API u_errorName()...\n");
+ str=(char*)u_errorName((UErrorCode)-127);
+ if(strcmp(str, "U_USING_DEFAULT_WARNING") != 0){
+ log_err("ERROR: u_getVersion() failed. Expected: U_USING_DEFAULT_WARNING Got=%s\n", str);
+ }
+ log_verbose("Testing the API u_errorName().. with BOGUS ERRORCODE...\n");
+ str=(char*)u_errorName((UErrorCode)200);
+ if(strcmp(str, "[BOGUS UErrorCode]") != 0){
+ log_err("ERROR: u_getVersion() failed. Expected: [BOGUS UErrorCode] Got=%s\n", str);
+ }
+
+ {
+ const char* dataDirectory;
+ int32_t dataDirectoryLen;
+ UChar *udataDir=0;
+ UChar temp[100];
+ char *charvalue=0;
+ log_verbose("Testing chars to UChars\n");
+
+ /* This cannot really work on a japanese system. u_uastrcpy will have different results than */
+ /* u_charsToUChars when there is a backslash in the string! */
+ /*dataDirectory=u_getDataDirectory();*/
+
+ dataDirectory="directory1"; /*no backslashes*/
+ dataDirectoryLen=(int32_t)strlen(dataDirectory);
+ udataDir=(UChar*)malloc(sizeof(UChar) * (dataDirectoryLen + 1));
+ u_charsToUChars(dataDirectory, udataDir, (dataDirectoryLen + 1));
+ u_uastrcpy(temp, dataDirectory);
+
+ if(u_strcmp(temp, udataDir) != 0){
+ log_err("ERROR: u_charsToUChars failed. Expected %s, Got %s\n", austrdup(temp), austrdup(udataDir));
+ }
+ log_verbose("Testing UChars to chars\n");
+ charvalue=(char*)malloc(sizeof(char) * (u_strlen(udataDir) + 1));
+
+ u_UCharsToChars(udataDir, charvalue, (u_strlen(udataDir)+1));
+ if(strcmp(charvalue, dataDirectory) != 0){
+ log_err("ERROR: u_UCharsToChars failed. Expected %s, Got %s\n", charvalue, dataDirectory);
+ }
+ free(charvalue);
+ free(udataDir);
+ }
+
+ log_verbose("Testing uprv_timezone()....\n");
+ {
+ int32_t tzoffset = uprv_timezone();
+ log_verbose("Value returned from uprv_timezone = %d\n", tzoffset);
+ if (tzoffset != 28800) {
+ log_verbose("***** WARNING: If testing in the PST timezone, t_timezone should return 28800! *****");
+ }
+ if ((tzoffset % 1800 != 0)) {
+ log_err("FAIL: t_timezone may be incorrect. It is not a multiple of 30min.");
+ }
+ /*tzoffset=uprv_getUTCtime();*/
+
+ }
+}
+
+#if 0
+static void testIEEEremainder()
+{
+ double pinf = uprv_getInfinity();
+ double ninf = -uprv_getInfinity();
+ double nan = uprv_getNaN();
+/* double pzero = 0.0;*/
+/* double nzero = 0.0;
+ nzero *= -1;*/
+
+ /* simple remainder checks*/
+ remainderTest(7.0, 2.5, -0.5);
+ remainderTest(7.0, -2.5, -0.5);
+ /* this should work
+ remainderTest(43.7, 2.5, 1.2);
+ */
+
+ /* infinity and real*/
+ remainderTest(1.0, pinf, 1.0);
+ remainderTest(1.0, ninf, 1.0);
+
+ /*test infinity and real*/
+ remainderTest(nan, 1.0, nan);
+ remainderTest(1.0, nan, nan);
+ /*test infinity and nan*/
+ remainderTest(ninf, nan, nan);
+ remainderTest(pinf, nan, nan);
+
+ /* test infinity and zero */
+/* remainderTest(pinf, pzero, 1.25);
+ remainderTest(pinf, nzero, 1.25);
+ remainderTest(ninf, pzero, 1.25);
+ remainderTest(ninf, nzero, 1.25); */
+}
+
+static void remainderTest(double x, double y, double exp)
+{
+ double result = uprv_IEEEremainder(x,y);
+
+ if( uprv_isNaN(result) &&
+ ! ( uprv_isNaN(x) || uprv_isNaN(y))) {
+ log_err("FAIL: got NaN as result without NaN as argument");
+ log_err(" IEEEremainder(%f, %f) is %f, expected %f\n", x, y, result, exp);
+ }
+ else if(!compareWithNAN(result, exp)) {
+ log_err("FAIL: IEEEremainder(%f, %f) is %f, expected %f\n", x, y, result, exp);
+ } else{
+ log_verbose("OK: IEEEremainder(%f, %f) is %f\n", x, y, result);
+ }
+
+}
+#endif
+
+static UBool compareWithNAN(double x, double y)
+{
+ if( uprv_isNaN(x) || uprv_isNaN(y) ) {
+ if(!uprv_isNaN(x) || !uprv_isNaN(y) ) {
+ return FALSE;
+ }
+ }
+ else if (y != x) { /* no NaN's involved */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void doAssert(double got, double expect, const char *message)
+{
+ if(! compareWithNAN(expect, got) ) {
+ log_err("ERROR : %s. Expected : %lf, Got: %lf\n", message, expect, got);
+ }
+}
+
+
+#define _CODE_ARR_LEN 8
+static const UErrorCode errorCode[_CODE_ARR_LEN] = {
+ U_USING_FALLBACK_WARNING,
+ U_STRING_NOT_TERMINATED_WARNING,
+ U_ILLEGAL_ARGUMENT_ERROR,
+ U_STATE_TOO_OLD_ERROR,
+ U_BAD_VARIABLE_DEFINITION,
+ U_RULE_MASK_ERROR,
+ U_UNEXPECTED_TOKEN,
+ U_UNSUPPORTED_ATTRIBUTE
+};
+
+static const char* str[] = {
+ "U_USING_FALLBACK_WARNING",
+ "U_STRING_NOT_TERMINATED_WARNING",
+ "U_ILLEGAL_ARGUMENT_ERROR",
+ "U_STATE_TOO_OLD_ERROR",
+ "U_BAD_VARIABLE_DEFINITION",
+ "U_RULE_MASK_ERROR",
+ "U_UNEXPECTED_TOKEN",
+ "U_UNSUPPORTED_ATTRIBUTE"
+};
+
+static void TestErrorName(void){
+ int32_t code=0;
+ const char* errorName ;
+ for(;code<U_ERROR_LIMIT;code++){
+ errorName = u_errorName((UErrorCode)code);
+ }
+
+ for(code=0;code<_CODE_ARR_LEN; code++){
+ errorName = u_errorName(errorCode[code]);
+ if(uprv_strcmp(str[code],errorName )!=0){
+ log_err("Error : u_errorName failed. Expected: %s Got: %s \n",str[code],errorName);
+ }
+ }
+}
+
+void addPUtilTest(TestNode** root);
+
+void
+addPUtilTest(TestNode** root)
+{
+ addTest(root, &TestPUtilAPI, "putiltst/TestPUtilAPI");
+/* addTest(root, &testIEEEremainder, "putiltst/testIEEEremainder"); */
+ addTest(root, &TestErrorName, "putiltst/TestErrorName");
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c
new file mode 100644
index 00000000000..74fe674f7dc
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/reapits.c
@@ -0,0 +1,1038 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2004-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/********************************************************************************
+*
+* File reapits.c
+*
+*********************************************************************************/
+/*C API TEST FOR Regular Expressions */
+/**
+* This is an API test for ICU regular expressions in C. It doesn't test very many cases, and doesn't
+* try to test the full functionality. It just calls each function and verifies that it
+* works on a basic level.
+*
+* More complete testing of regular expression functionality is done with the C++ tests.
+**/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_REGULAR_EXPRESSIONS
+
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/uloc.h"
+#include "unicode/uregex.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+
+#define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \
+log_err("Failure at file %s, line %d, error = %s\n", __FILE__, __LINE__, u_errorName(status));}}
+
+#define TEST_ASSERT(expr) {if ((expr)==FALSE) { \
+log_err("Test Failure at file %s, line %d\n", __FILE__, __LINE__);}}
+
+static void test_assert_string(const char *expected, const UChar *actual, UBool nulTerm, const char *file, int line) {
+ char buf_inside_macro[120];
+ int32_t len = (int32_t)strlen(expected);
+ UBool success;
+ if (nulTerm) {
+ u_austrncpy(buf_inside_macro, (actual), len+1);
+ buf_inside_macro[len+2] = 0;
+ success = (strcmp((expected), buf_inside_macro) == 0);
+ } else {
+ u_austrncpy(buf_inside_macro, (actual), len);
+ buf_inside_macro[len+1] = 0;
+ success = (strncmp((expected), buf_inside_macro, len) == 0);
+ }
+ if (success == FALSE) {
+ log_err("Failure at file %s, line %d, expected \"%s\", got \"%s\"\n",
+ file, line, (expected), buf_inside_macro);
+ }
+}
+
+#define TEST_ASSERT_STRING(expected, actual, nulTerm) test_assert_string(expected, actual, nulTerm, __FILE__, __LINE__)
+
+
+
+
+
+static void TestRegexCAPI(void);
+static void TestBug4315(void);
+
+void addURegexTest(TestNode** root);
+
+void addURegexTest(TestNode** root)
+{
+ addTest(root, &TestRegexCAPI, "regex/TestRegexCAPI");
+ addTest(root, &TestBug4315, "regex/TestBug4315");
+}
+
+
+static void TestRegexCAPI(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ URegularExpression *re;
+ UChar pat[200];
+ UChar *minus1;
+
+ memset(&minus1, -1, sizeof(minus1));
+
+ /* Mimimalist open/close */
+ u_uastrncpy(pat, "abc*", sizeof(pat)/2);
+ re = uregex_open(pat, -1, 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ uregex_close(re);
+
+ /* Open with all flag values set */
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1,
+ UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD,
+ 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ uregex_close(re);
+
+ /* Open with an invalid flag */
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1, 0x40000000, 0, &status);
+ TEST_ASSERT(status == U_REGEX_INVALID_FLAG);
+ uregex_close(re);
+
+ /* openC with an invalid parameter */
+ status = U_ZERO_ERROR;
+ re = uregex_openC(NULL,
+ UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status);
+ TEST_ASSERT(status == U_ILLEGAL_ARGUMENT_ERROR && re == NULL);
+
+ /* openC with an invalid parameter */
+ status = U_USELESS_COLLATOR_ERROR;
+ re = uregex_openC(NULL,
+ UREGEX_CASE_INSENSITIVE | UREGEX_COMMENTS | UREGEX_DOTALL | UREGEX_MULTILINE | UREGEX_UWORD, 0, &status);
+ TEST_ASSERT(status == U_USELESS_COLLATOR_ERROR && re == NULL);
+
+ /* openC open from a C string */
+ {
+ const UChar *p;
+ int32_t len;
+ status = U_ZERO_ERROR;
+ re = uregex_openC("abc*", 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ p = uregex_pattern(re, &len, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS above should change too... */
+ if(U_SUCCESS(status)) {
+ u_uastrncpy(pat, "abc*", sizeof(pat)/2);
+ TEST_ASSERT(u_strcmp(pat, p) == 0);
+ TEST_ASSERT(len==(int32_t)strlen("abc*"));
+ }
+
+ uregex_close(re);
+
+ /* TODO: Open with ParseError parameter */
+ }
+
+ /*
+ * clone
+ */
+ {
+ URegularExpression *clone1;
+ URegularExpression *clone2;
+ URegularExpression *clone3;
+ UChar testString1[30];
+ UChar testString2[30];
+ UBool result;
+
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("abc*", 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ clone1 = uregex_clone(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(clone1 != NULL);
+
+ status = U_ZERO_ERROR;
+ clone2 = uregex_clone(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(clone2 != NULL);
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ clone3 = uregex_clone(clone2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(clone3 != NULL);
+
+ u_uastrncpy(testString1, "abcccd", sizeof(pat)/2);
+ u_uastrncpy(testString2, "xxxabcccd", sizeof(pat)/2);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(clone1, testString1, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+ result = uregex_lookingAt(clone1, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(result==TRUE);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(clone2, testString2, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+ result = uregex_lookingAt(clone2, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(result==FALSE);
+ result = uregex_find(clone2, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(result==TRUE);
+
+ uregex_close(clone1);
+ uregex_close(clone2);
+ uregex_close(clone3);
+
+ }
+
+ /*
+ * pattern()
+ */
+ {
+ const UChar *resultPat;
+ int32_t resultLen;
+ u_uastrncpy(pat, "hello", sizeof(pat)/2);
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1, 0, NULL, &status);
+ resultPat = uregex_pattern(re, &resultLen, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS above should change too... */
+ if (U_SUCCESS(status)) {
+ TEST_ASSERT(resultLen == -1);
+ TEST_ASSERT(u_strcmp(resultPat, pat) == 0);
+ }
+
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, 3, 0, NULL, &status);
+ resultPat = uregex_pattern(re, &resultLen, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS above should change too... */
+ if (U_SUCCESS(status)) {
+ TEST_ASSERT(resultLen == 3);
+ TEST_ASSERT(u_strncmp(resultPat, pat, 3) == 0);
+ TEST_ASSERT(u_strlen(resultPat) == 3);
+ }
+
+ uregex_close(re);
+ }
+
+ /*
+ * flags()
+ */
+ {
+ int32_t t;
+
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1, 0, NULL, &status);
+ t = uregex_flags(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(t == 0);
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1, 0, NULL, &status);
+ t = uregex_flags(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(t == 0);
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ re = uregex_open(pat, -1, UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL, NULL, &status);
+ t = uregex_flags(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(t == (UREGEX_CASE_INSENSITIVE | UREGEX_DOTALL));
+ uregex_close(re);
+ }
+
+ /*
+ * setText() and lookingAt()
+ */
+ {
+ UChar text1[50];
+ UChar text2[50];
+ UBool result;
+
+ u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
+ u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
+ status = U_ZERO_ERROR;
+ u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ re = uregex_open(pat, -1, 0, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* Operation before doing a setText should fail... */
+ status = U_ZERO_ERROR;
+ uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT( status== U_REGEX_INVALID_STATE);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text2, -1, &status);
+ result = uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, 5, &status);
+ result = uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, 6, &status);
+ result = uregex_lookingAt(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_close(re);
+ }
+
+
+ /*
+ * getText()
+ */
+ {
+ UChar text1[50];
+ UChar text2[50];
+ const UChar *result;
+ int32_t textLength;
+
+ u_uastrncpy(text1, "abcccd", sizeof(text1)/2);
+ u_uastrncpy(text2, "abcccxd", sizeof(text2)/2);
+ status = U_ZERO_ERROR;
+ u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ re = uregex_open(pat, -1, 0, NULL, &status);
+
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_getText(re, &textLength, &status);
+ TEST_ASSERT(result == text1);
+ TEST_ASSERT(textLength == -1);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text2, 7, &status);
+ result = uregex_getText(re, &textLength, &status);
+ TEST_ASSERT(result == text2);
+ TEST_ASSERT(textLength == 7);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text2, 4, &status);
+ result = uregex_getText(re, &textLength, &status);
+ TEST_ASSERT(result == text2);
+ TEST_ASSERT(textLength == 4);
+ TEST_ASSERT_SUCCESS(status);
+ uregex_close(re);
+ }
+
+ /*
+ * matches()
+ */
+ {
+ UChar text1[50];
+ UBool result;
+ int len;
+ UChar nullString[] = {0,0,0};
+
+ u_uastrncpy(text1, "abcccde", sizeof(text1)/2);
+ status = U_ZERO_ERROR;
+ u_uastrncpy(pat, "abc*d", sizeof(pat)/2);
+ re = uregex_open(pat, -1, 0, NULL, &status);
+
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_matches(re, 0, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, 6, &status);
+ result = uregex_matches(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, 6, &status);
+ result = uregex_matches(re, 1, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC(".?", 0, NULL, &status);
+ uregex_setText(re, text1, -1, &status);
+ len = u_strlen(text1);
+ result = uregex_matches(re, len, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_setText(re, nullString, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+ result = uregex_matches(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT_SUCCESS(status);
+ uregex_close(re);
+ }
+
+
+ /*
+ * lookingAt() Used in setText test.
+ */
+
+
+ /*
+ * find(), findNext, start, end, reset
+ */
+ {
+ UChar text1[50];
+ UBool result;
+ u_uastrncpy(text1, "012rx5rx890rxrx...", sizeof(text1)/2);
+ status = U_ZERO_ERROR;
+ re = uregex_openC("rx", 0, NULL, &status);
+
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_find(re, 0, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT(uregex_start(re, 0, &status) == 3);
+ TEST_ASSERT(uregex_end(re, 0, &status) == 5);
+ TEST_ASSERT_SUCCESS(status);
+
+ result = uregex_find(re, 9, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT(uregex_start(re, 0, &status) == 11);
+ TEST_ASSERT(uregex_end(re, 0, &status) == 13);
+ TEST_ASSERT_SUCCESS(status);
+
+ result = uregex_find(re, 14, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_reset(re, 0, &status);
+
+ result = uregex_findNext(re, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT(uregex_start(re, 0, &status) == 3);
+ TEST_ASSERT(uregex_end(re, 0, &status) == 5);
+ TEST_ASSERT_SUCCESS(status);
+
+ result = uregex_findNext(re, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT(uregex_start(re, 0, &status) == 6);
+ TEST_ASSERT(uregex_end(re, 0, &status) == 8);
+ TEST_ASSERT_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ uregex_reset(re, 12, &status);
+
+ result = uregex_findNext(re, &status);
+ TEST_ASSERT(result == TRUE);
+ TEST_ASSERT(uregex_start(re, 0, &status) == 13);
+ TEST_ASSERT(uregex_end(re, 0, &status) == 15);
+ TEST_ASSERT_SUCCESS(status);
+
+ result = uregex_findNext(re, &status);
+ TEST_ASSERT(result == FALSE);
+ TEST_ASSERT_SUCCESS(status);
+
+ uregex_close(re);
+ }
+
+ /*
+ * groupCount
+ */
+ {
+ int32_t result;
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("abc", 0, NULL, &status);
+ result = uregex_groupCount(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(result == 0);
+ uregex_close(re);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("abc(def)(ghi(j))", 0, NULL, &status);
+ result = uregex_groupCount(re, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT(result == 3);
+ uregex_close(re);
+
+ }
+
+
+ /*
+ * group()
+ */
+ {
+ UChar text1[80];
+ UChar buf[80];
+ UBool result;
+ int32_t resultSz;
+ u_uastrncpy(text1, "noise abc interior def, and this is off the end", sizeof(text1)/2);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("abc(.*?)def", 0, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+
+ uregex_setText(re, text1, -1, &status);
+ result = uregex_find(re, 0, &status);
+ TEST_ASSERT(result==TRUE);
+
+ /* Capture Group 0, the full match. Should succeed. */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_group(re, 0, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("abc interior def", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
+
+ /* Capture group #1. Should succeed. */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_group(re, 1, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING(" interior ", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen(" interior "));
+
+ /* Capture group out of range. Error. */
+ status = U_ZERO_ERROR;
+ uregex_group(re, 2, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT(status == U_INDEX_OUTOFBOUNDS_ERROR);
+
+ /* NULL buffer, pure pre-flight */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_group(re, 0, NULL, 0, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
+
+ /* Too small buffer, truncated string */
+ status = U_ZERO_ERROR;
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_group(re, 0, buf, 5, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT_STRING("abc i", buf, FALSE);
+ TEST_ASSERT(buf[5] == (UChar)0xffff);
+ TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
+
+ /* Output string just fits buffer, no NUL term. */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_group(re, 0, buf, (int32_t)strlen("abc interior def"), &status);
+ TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
+ TEST_ASSERT_STRING("abc interior def", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("abc interior def"));
+ TEST_ASSERT(buf[strlen("abc interior def")] == (UChar)0xffff);
+
+ uregex_close(re);
+
+ }
+
+ /*
+ * replaceFirst()
+ */
+ {
+ UChar text1[80];
+ UChar text2[80];
+ UChar replText[80];
+ UChar buf[80];
+ int32_t resultSz;
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
+ u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("x(.*?)x", 0, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* Normal case, with match */
+ uregex_setText(re, text1, -1, &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+
+ /* No match. Text should copy to output with no changes. */
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text2, -1, &status);
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("No match here.", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("No match here."));
+
+ /* Match, output just fills buffer, no termination warning. */
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, -1, &status);
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
+ TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
+ TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+ TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
+
+ /* Do the replaceFirst again, without first resetting anything.
+ * Should give the same results.
+ */
+ status = U_ZERO_ERROR;
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x."), &status);
+ TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
+ TEST_ASSERT_STRING("Replace <aa> x1x x...x.", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+ TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
+
+ /* NULL buffer, zero buffer length */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_replaceFirst(re, replText, -1, NULL, 0, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+
+ /* Buffer too small by one */
+ status = U_ZERO_ERROR;
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceFirst(re, replText, -1, buf, strlen("Replace <aa> x1x x...x.")-1, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT_STRING("Replace <aa> x1x x...x", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+ TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
+
+ uregex_close(re);
+ }
+
+
+ /*
+ * replaceAll()
+ */
+ {
+ UChar text1[80];
+ UChar text2[80];
+ UChar replText[80];
+ UChar buf[80];
+ int32_t resultSz;
+ int32_t expectedResultSize;
+ int32_t i;
+
+ u_uastrncpy(text1, "Replace xaax x1x x...x.", sizeof(text1)/2);
+ u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+ u_uastrncpy(replText, "<$1>", sizeof(replText)/2);
+ expectedResultSize = u_strlen(text1);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("x(.*?)x", 0, NULL, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* Normal case, with match */
+ uregex_setText(re, text1, -1, &status);
+ resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace xaax x1x x...x."));
+
+ /* No match. Text should copy to output with no changes. */
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text2, -1, &status);
+ resultSz = uregex_replaceAll(re, replText, -1, buf, sizeof(buf)/2, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("No match here.", buf, TRUE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("No match here."));
+
+ /* Match, output just fills buffer, no termination warning. */
+ status = U_ZERO_ERROR;
+ uregex_setText(re, text1, -1, &status);
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status);
+ TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
+ TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
+ TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
+
+ /* Do the replaceFirst again, without first resetting anything.
+ * Should give the same results.
+ */
+ status = U_ZERO_ERROR;
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceAll(re, replText, -1, buf, strlen("Replace xaax x1x x...x."), &status);
+ TEST_ASSERT(status == U_STRING_NOT_TERMINATED_WARNING);
+ TEST_ASSERT_STRING("Replace <aa> <1> <...>.", buf, FALSE);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
+ TEST_ASSERT(buf[resultSz] == (UChar)0xffff);
+
+ /* NULL buffer, zero buffer length */
+ status = U_ZERO_ERROR;
+ resultSz = uregex_replaceAll(re, replText, -1, NULL, 0, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(resultSz == (int32_t)strlen("Replace <aa> <1> <...>."));
+
+ /* Buffer too small. Try every size, which will tickle edge cases
+ * in uregex_appendReplacement (used by replaceAll) */
+ for (i=0; i<expectedResultSize; i++) {
+ char expected[80];
+ status = U_ZERO_ERROR;
+ memset(buf, -1, sizeof(buf));
+ resultSz = uregex_replaceAll(re, replText, -1, buf, i, &status);
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ strcpy(expected, "Replace <aa> <1> <...>.");
+ expected[i] = 0;
+ TEST_ASSERT_STRING(expected, buf, FALSE);
+ TEST_ASSERT(resultSz == expectedResultSize);
+ TEST_ASSERT(buf[i] == (UChar)0xffff);
+ }
+
+ uregex_close(re);
+ }
+
+
+ /*
+ * appendReplacement()
+ */
+ {
+ UChar text[100];
+ UChar repl[100];
+ UChar buf[100];
+ UChar *bufPtr;
+ int32_t bufCap;
+
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC(".*", 0, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ u_uastrncpy(text, "whatever", sizeof(text)/2);
+ u_uastrncpy(repl, "some other", sizeof(repl)/2);
+ uregex_setText(re, text, -1, &status);
+
+ /* match covers whole target string */
+ uregex_find(re, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ bufPtr = buf;
+ bufCap = sizeof(buf) / 2;
+ uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("some other", buf, TRUE);
+
+ /* Match has \u \U escapes */
+ uregex_find(re, 0, &status);
+ TEST_ASSERT_SUCCESS(status);
+ bufPtr = buf;
+ bufCap = sizeof(buf) / 2;
+ u_uastrncpy(repl, "abc\\u0041\\U00000042 \\\\ $ \\abc", sizeof(repl)/2);
+ uregex_appendReplacement(re, repl, -1, &bufPtr, &bufCap, &status);
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("abcAB \\ $ abc", buf, TRUE);
+
+ uregex_close(re);
+ }
+
+
+ /*
+ * appendTail(). Checked in ReplaceFirst(), replaceAll().
+ */
+
+ /*
+ * split()
+ */
+ {
+ UChar textToSplit[80];
+ UChar text2[80];
+ UChar buf[200];
+ UChar *fields[10];
+ int32_t numFields;
+ int32_t requiredCapacity;
+ int32_t spaceNeeded;
+ int32_t sz;
+
+ u_uastrncpy(textToSplit, "first : second: third", sizeof(textToSplit)/2);
+ u_uastrncpy(text2, "No match here.", sizeof(text2)/2);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC(":", 0, NULL, &status);
+
+
+ /* Simple split */
+
+ uregex_setText(re, textToSplit, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if (U_SUCCESS(status)) {
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 3);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING(" second", fields[1], TRUE);
+ TEST_ASSERT_STRING(" third", fields[2], TRUE);
+ TEST_ASSERT(fields[3] == NULL);
+
+ spaceNeeded = u_strlen(textToSplit) -
+ (numFields - 1) + /* Field delimiters do not appear in output */
+ numFields; /* Each field gets a NUL terminator */
+
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+ }
+
+ uregex_close(re);
+
+
+ /* Split with too few output strings available */
+ status = U_ZERO_ERROR;
+ re = uregex_openC(":", 0, NULL, &status);
+ uregex_setText(re, textToSplit, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 2);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING(" second: third", fields[1], TRUE);
+ TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*)));
+
+ spaceNeeded = u_strlen(textToSplit) -
+ (numFields - 1) + /* Field delimiters do not appear in output */
+ numFields; /* Each field gets a NUL terminator */
+
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+
+ /* Split with a range of output buffer sizes. */
+ spaceNeeded = u_strlen(textToSplit) -
+ (numFields - 1) + /* Field delimiters do not appear in output */
+ numFields; /* Each field gets a NUL terminator */
+
+ for (sz=0; sz < spaceNeeded+1; sz++) {
+ memset(fields, -1, sizeof(fields));
+ status = U_ZERO_ERROR;
+ numFields =
+ uregex_split(re, buf, sz, &requiredCapacity, fields, 10, &status);
+ if (sz >= spaceNeeded) {
+ TEST_ASSERT_SUCCESS(status);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING(" second", fields[1], TRUE);
+ TEST_ASSERT_STRING(" third", fields[2], TRUE);
+ } else {
+ TEST_ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+ }
+ TEST_ASSERT(numFields == 3);
+ TEST_ASSERT(fields[3] == NULL);
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+ }
+ }
+
+ uregex_close(re);
+ }
+
+
+
+
+ /* Split(), part 2. Patterns with capture groups. The capture group text
+ * comes out as additional fields. */
+ {
+ UChar textToSplit[80];
+ UChar buf[200];
+ UChar *fields[10];
+ int32_t numFields;
+ int32_t requiredCapacity;
+ int32_t spaceNeeded;
+ int32_t sz;
+
+ u_uastrncpy(textToSplit, "first <tag-a> second<tag-b> third", sizeof(textToSplit)/2);
+
+ status = U_ZERO_ERROR;
+ re = uregex_openC("<(.*?)>", 0, NULL, &status);
+
+ uregex_setText(re, textToSplit, -1, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 10, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 5);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
+ TEST_ASSERT_STRING(" second", fields[2], TRUE);
+ TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
+ TEST_ASSERT_STRING(" third", fields[4], TRUE);
+ TEST_ASSERT(fields[5] == NULL);
+ spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+ }
+
+ /* Split with too few output strings available (2) */
+ status = U_ZERO_ERROR;
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 2, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 2);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING(" second<tag-b> third", fields[1], TRUE);
+ TEST_ASSERT(!memcmp(&fields[2],&minus1,sizeof(UChar*)));
+
+ spaceNeeded = strlen("first . second<tag-b> third."); /* "." at NUL positions */
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+
+ /* Split with too few output strings available (3) */
+ status = U_ZERO_ERROR;
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 3, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 3);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
+ TEST_ASSERT_STRING(" second<tag-b> third", fields[2], TRUE);
+ TEST_ASSERT(!memcmp(&fields[3],&minus1,sizeof(UChar*)));
+
+ spaceNeeded = strlen("first .tag-a. second<tag-b> third."); /* "." at NUL positions */
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+
+ /* Split with just enough output strings available (5) */
+ status = U_ZERO_ERROR;
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 5, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 5);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
+ TEST_ASSERT_STRING(" second", fields[2], TRUE);
+ TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
+ TEST_ASSERT_STRING(" third", fields[4], TRUE);
+ TEST_ASSERT(!memcmp(&fields[5],&minus1,sizeof(UChar*)));
+
+ spaceNeeded = strlen("first .tag-a. second.tag-b. third."); /* "." at NUL positions */
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+
+ /* Split, end of text is a field delimiter. */
+ status = U_ZERO_ERROR;
+ sz = strlen("first <tag-a> second<tag-b>");
+ uregex_setText(re, textToSplit, sz, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ memset(fields, -1, sizeof(fields));
+ numFields =
+ uregex_split(re, buf, sizeof(buf)/2, &requiredCapacity, fields, 9, &status);
+ TEST_ASSERT_SUCCESS(status);
+
+ /* The TEST_ASSERT_SUCCESS call above should change too... */
+ if(U_SUCCESS(status)) {
+ TEST_ASSERT(numFields == 4);
+ TEST_ASSERT_STRING("first ", fields[0], TRUE);
+ TEST_ASSERT_STRING("tag-a", fields[1], TRUE);
+ TEST_ASSERT_STRING(" second", fields[2], TRUE);
+ TEST_ASSERT_STRING("tag-b", fields[3], TRUE);
+ TEST_ASSERT(fields[4] == NULL);
+ TEST_ASSERT(fields[8] == NULL);
+ TEST_ASSERT(!memcmp(&fields[9],&minus1,sizeof(UChar*)));
+ spaceNeeded = strlen("first .tag-a. second.tag-b."); /* "." at NUL positions */
+ TEST_ASSERT(spaceNeeded == requiredCapacity);
+ }
+ }
+
+ uregex_close(re);
+ }
+
+}
+
+static void TestBug4315(void) {
+ UErrorCode theICUError = U_ZERO_ERROR;
+ URegularExpression *theRegEx;
+ UChar *textBuff;
+ const char *thePattern;
+ UChar theString[100];
+ UChar *destFields[24];
+ int32_t neededLength1;
+ int32_t neededLength2;
+
+ int32_t wordCount = 0;
+ int32_t destFieldsSize = 24;
+
+ thePattern = "ck ";
+ u_uastrcpy(theString, "The quick brown fox jumped over the slow black turtle.");
+
+ /* open a regex */
+ theRegEx = uregex_openC(thePattern, 0, NULL, &theICUError);
+ TEST_ASSERT_SUCCESS(theICUError);
+
+ /* set the input string */
+ uregex_setText(theRegEx, theString, u_strlen(theString), &theICUError);
+ TEST_ASSERT_SUCCESS(theICUError);
+
+ /* split */
+ /*explicitly pass NULL and 0 to force the overflow error -> this is where the
+ * error occurs! */
+ wordCount = uregex_split(theRegEx, NULL, 0, &neededLength1, destFields,
+ destFieldsSize, &theICUError);
+
+ TEST_ASSERT(theICUError == U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(wordCount==3);
+
+ if(theICUError == U_BUFFER_OVERFLOW_ERROR)
+ {
+ theICUError = U_ZERO_ERROR;
+ textBuff = (UChar *) malloc(sizeof(UChar) * (neededLength1 + 1));
+ wordCount = uregex_split(theRegEx, textBuff, neededLength1+1, &neededLength2,
+ destFields, destFieldsSize, &theICUError);
+ TEST_ASSERT(wordCount==3);
+ TEST_ASSERT_SUCCESS(theICUError);
+ TEST_ASSERT(neededLength1 == neededLength2);
+ TEST_ASSERT_STRING("The qui", destFields[0], TRUE);
+ TEST_ASSERT_STRING("brown fox jumped over the slow bla", destFields[1], TRUE);
+ TEST_ASSERT_STRING("turtle.", destFields[2], TRUE);
+ TEST_ASSERT(destFields[3] == NULL);
+ free(textBuff);
+ }
+ uregex_close(theRegEx);
+}
+
+#endif /* !UCONFIG_NO_REGULAR_EXPRESSIONS */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c
new file mode 100644
index 00000000000..c99ce507196
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/sorttest.c
@@ -0,0 +1,89 @@
+/*
+*******************************************************************************
+*
+* Copyright (C) 2003, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+*******************************************************************************
+* file name: csorttst.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2003aug04
+* created by: Markus W. Scherer
+*
+* Test internal sorting functions.
+*/
+
+#include "unicode/utypes.h"
+#include "cmemory.h"
+#include "cintltst.h"
+#include "uarrsort.h"
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void
+SortTest(void) {
+ uint16_t small[]={ 8, 1, 2, 5, 4, 3, 7, 6 };
+ int32_t medium[]={ 10, 8, 1, 2, 5, 5, -1, 6, 4, 3, 9, 7, 5 };
+ uint32_t large[]={ 21, 10, 20, 19, 11, 12, 13, 10, 10, 10, 10,
+ 8, 1, 2, 5, 10, 10, 4, 17, 18, 3, 9, 10, 7, 6, 14, 15, 16 };
+
+ int32_t i;
+ UErrorCode errorCode;
+
+ /* sort small array (stable) */
+ errorCode=U_ZERO_ERROR;
+ uprv_sortArray(small, LENGTHOF(small), sizeof(small[0]), uprv_uint16Comparator, NULL, TRUE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("uprv_sortArray(small) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ for(i=1; i<LENGTHOF(small); ++i) {
+ if(small[i-1]>small[i]) {
+ log_err("uprv_sortArray(small) mis-sorted [%d]=%u > [%d]=%u\n", i-1, small[i-1], i, small[i]);
+ return;
+ }
+ }
+
+ /* for medium, add bits that will not be compared, to test stability */
+ for(i=0; i<LENGTHOF(medium); ++i) {
+ medium[i]=(medium[i]<<4)|i;
+ }
+
+ /* sort medium array (stable) */
+ uprv_sortArray(medium, LENGTHOF(medium), sizeof(medium[0]), uprv_int32Comparator, NULL, TRUE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("uprv_sortArray(medium) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ for(i=1; i<LENGTHOF(medium); ++i) {
+ if(medium[i-1]>=medium[i]) {
+ log_err("uprv_sortArray(medium) mis-sorted [%d]=%u > [%d]=%u\n", i-1, medium[i-1], i, medium[i]);
+ return;
+ }
+ }
+
+ /* sort large array (not stable) */
+ errorCode=U_ZERO_ERROR;
+ uprv_sortArray(large, LENGTHOF(large), sizeof(large[0]), uprv_uint32Comparator, NULL, FALSE, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("uprv_sortArray(large) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ for(i=1; i<LENGTHOF(large); ++i) {
+ if(large[i-1]>large[i]) {
+ log_err("uprv_sortArray(large) mis-sorted [%d]=%u > [%d]=%u\n", i-1, large[i-1], i, large[i]);
+ return;
+ }
+ }
+}
+
+void
+addSortTest(TestNode** root);
+
+void
+addSortTest(TestNode** root) {
+ addTest(root, &SortTest, "tsutil/sorttest/SortTest");
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c
new file mode 100644
index 00000000000..1652984b520
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/spreptst.c
@@ -0,0 +1,641 @@
+/*
+ *******************************************************************************
+ *
+ * Copyright (C) 2003-2006, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *
+ *******************************************************************************
+ * file name: spreptst.c
+ * encoding: US-ASCII
+ * tab size: 8 (not used)
+ * indentation:4
+ *
+ * created on: 2003jul11
+ * created by: Ram Viswanadha
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_IDNA
+
+#include "unicode/ustring.h"
+#include "unicode/usprep.h"
+#include "cintltst.h"
+#include "nfsprep.h"
+
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+void addUStringPrepTest(TestNode** root);
+void doStringPrepTest(const char* binFileName, const char* txtFileName,
+ int32_t options, UErrorCode* errorCode);
+
+static void Test_nfs4_cs_prep_data(void);
+static void Test_nfs4_cis_prep_data(void);
+static void Test_nfs4_mixed_prep_data(void);
+static void Test_nfs4_cs_prep(void);
+static void Test_nfs4_cis_prep(void);
+static void Test_nfs4_mixed_prep(void);
+static void TestBEAMWarning(void);
+static void TestCoverage(void);
+
+void
+addUStringPrepTest(TestNode** root)
+{
+ addTest(root, &Test_nfs4_cs_prep_data, "spreptst/Test_nfs4_cs_prep_data");
+ addTest(root, &Test_nfs4_cis_prep_data, "spreptst/Test_nfs4_cis_prep_data");
+ addTest(root, &Test_nfs4_mixed_prep_data, "spreptst/Test_nfs4_mixed_prep_data");
+ addTest(root, &Test_nfs4_cs_prep, "spreptst/Test_nfs4_cs_prep");
+ addTest(root, &Test_nfs4_cis_prep, "spreptst/Test_nfs4_cis_prep");
+ addTest(root, &Test_nfs4_mixed_prep, "spreptst/Test_nfs4_mixed_prep");
+ addTest(root, &TestBEAMWarning, "spreptst/TestBEAMWarning");
+ addTest(root, &TestCoverage, "spreptst/TestCoverage");
+}
+
+static void
+Test_nfs4_cs_prep_data(void){
+ UErrorCode errorCode = U_ZERO_ERROR;
+ loadTestData(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ log_verbose("Testing nfs4_cs_prep_ci.txt\n");
+ doStringPrepTest("nfscsi","nfs4_cs_prep_ci.txt", USPREP_DEFAULT, &errorCode);
+
+ log_verbose("Testing nfs4_cs_prep_cs.txt\n");
+ errorCode = U_ZERO_ERROR;
+ doStringPrepTest("nfscss","nfs4_cs_prep_cs.txt", USPREP_DEFAULT, &errorCode);
+
+
+}
+static void
+Test_nfs4_cis_prep_data(void){
+ UErrorCode errorCode = U_ZERO_ERROR;
+ log_verbose("Testing nfs4_cis_prep.txt\n");
+ doStringPrepTest("nfscis","nfs4_cis_prep.txt", USPREP_DEFAULT, &errorCode);
+}
+static void
+Test_nfs4_mixed_prep_data(void){
+ UErrorCode errorCode = U_ZERO_ERROR;
+ loadTestData(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ log_verbose("Testing nfs4_mixed_prep_s.txt\n");
+ doStringPrepTest("nfsmxs","nfs4_mixed_prep_s.txt", USPREP_DEFAULT, &errorCode);
+
+ errorCode = U_ZERO_ERROR;
+ log_verbose("Testing nfs4_mixed_prep_p.txt\n");
+ doStringPrepTest("nfsmxp","nfs4_mixed_prep_p.txt", USPREP_DEFAULT, &errorCode);
+
+}
+
+static const struct ConformanceTestCases
+ {
+ const char *comment;
+ const char *in;
+ const char *out;
+ const char *profile;
+ UErrorCode expectedStatus;
+ }
+ conformanceTestCases[] =
+ {
+
+ {/*0*/
+ "Case folding ASCII U+0043 U+0041 U+0046 U+0045",
+ "\x43\x41\x46\x45", "\x63\x61\x66\x65",
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+
+ },
+ {/*1*/
+ "Case folding 8bit U+00DF (german sharp s)",
+ "\xC3\x9F", "\x73\x73",
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+ },
+ {/*2*/
+ "Non-ASCII multibyte space character U+1680",
+ "\xE1\x9A\x80", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*3*/
+ "Non-ASCII 8bit control character U+0085",
+ "\xC2\x85", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*4*/
+ "Non-ASCII multibyte control character U+180E",
+ "\xE1\xA0\x8E", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*5*/
+ "Non-ASCII control character U+1D175",
+ "\xF0\x9D\x85\xB5", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*6*/
+ "Plane 0 private use character U+F123",
+ "\xEF\x84\xA3", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*7*/
+ "Plane 15 private use character U+F1234",
+ "\xF3\xB1\x88\xB4", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*8*/
+ "Plane 16 private use character U+10F234",
+ "\xF4\x8F\x88\xB4", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*9*/
+ "Non-character code point U+8FFFE",
+ "\xF2\x8F\xBF\xBE", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*10*/
+ "Non-character code point U+10FFFF",
+ "\xF4\x8F\xBF\xBF", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ /*
+ {
+ "Surrogate code U+DF42",
+ "\xED\xBD\x82", NULL, "nfs4_cis_prep", UIDNA_DEFAULT,
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+*/
+ {/*11*/
+ "Non-plain text character U+FFFD",
+ "\xEF\xBF\xBD", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*12*/
+ "Ideographic description character U+2FF5",
+ "\xE2\xBF\xB5", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*13*/
+ "Display property character U+0341",
+ "\xCD\x81", "\xCC\x81",
+ "nfs4_cis_prep", U_ZERO_ERROR
+
+ },
+
+ {/*14*/
+ "Left-to-right mark U+200E",
+ "\xE2\x80\x8E", "\xCC\x81",
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*15*/
+
+ "Deprecated U+202A",
+ "\xE2\x80\xAA", "\xCC\x81",
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*16*/
+ "Language tagging character U+E0001",
+ "\xF3\xA0\x80\x81", "\xCC\x81",
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*17*/
+ "Language tagging character U+E0042",
+ "\xF3\xA0\x81\x82", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_PROHIBITED_ERROR
+ },
+ {/*18*/
+ "Bidi: RandALCat character U+05BE and LCat characters",
+ "\x66\x6F\x6F\xD6\xBE\x62\x61\x72", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_CHECK_BIDI_ERROR
+ },
+ {/*19*/
+ "Bidi: RandALCat character U+FD50 and LCat characters",
+ "\x66\x6F\x6F\xEF\xB5\x90\x62\x61\x72", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_CHECK_BIDI_ERROR
+ },
+ {/*20*/
+ "Bidi: RandALCat character U+FB38 and LCat characters",
+ "\x66\x6F\x6F\xEF\xB9\xB6\x62\x61\x72", "\x66\x6F\x6F\x20\xd9\x8e\x62\x61\x72",
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+ },
+ {/*21*/
+ "Bidi: RandALCat without trailing RandALCat U+0627 U+0031",
+ "\xD8\xA7\x31", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_CHECK_BIDI_ERROR
+ },
+ {/*22*/
+ "Bidi: RandALCat character U+0627 U+0031 U+0628",
+ "\xD8\xA7\x31\xD8\xA8", "\xD8\xA7\x31\xD8\xA8",
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+ },
+ {/*23*/
+ "Unassigned code point U+E0002",
+ "\xF3\xA0\x80\x82", NULL,
+ "nfs4_cis_prep",
+ U_STRINGPREP_UNASSIGNED_ERROR
+ },
+
+/* // Invalid UTF-8
+ {
+ "Larger test (shrinking)",
+ "X\xC2\xAD\xC3\xDF\xC4\xB0\xE2\x84\xA1\x6a\xcc\x8c\xc2\xa0\xc2"
+ "\xaa\xce\xb0\xe2\x80\x80", "xssi\xcc\x87""tel\xc7\xb0 a\xce\xb0 ",
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+ },
+ {
+
+ "Larger test (expanding)",
+ "X\xC3\xDF\xe3\x8c\x96\xC4\xB0\xE2\x84\xA1\xE2\x92\x9F\xE3\x8c\x80",
+ "xss\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88"
+ "\xe3\x83\xab""i\xcc\x87""tel\x28""d\x29\xe3\x82\xa2\xe3\x83\x91"
+ "\xe3\x83\xbc\xe3\x83\x88"
+ "nfs4_cis_prep",
+ U_ZERO_ERROR
+ },
+ */
+};
+
+#define MAX_BUFFER_SIZE 1000
+
+static int32_t
+unescapeData(const char* src, int32_t srcLen,
+ char* dest, int32_t destCapacity,
+ UErrorCode* status){
+
+ UChar b1Stack[MAX_BUFFER_SIZE];
+ int32_t b1Capacity = MAX_BUFFER_SIZE,
+ b1Len = 0,
+ destLen = 0;
+
+ UChar* b1 = b1Stack;
+
+ b1Len = u_unescape(src,b1,b1Capacity);
+
+ u_strToUTF8(dest, destCapacity, &destLen, b1, b1Len, status);
+
+ return destLen;
+}
+
+
+static void Test_nfs4_cis_prep(void){
+ int32_t i=0;
+ UErrorCode loadStatus = U_ZERO_ERROR;
+ loadTestData(&loadStatus);
+ if (U_FAILURE(loadStatus)) {
+ log_err("Test could not initialize. Got %s\n", u_errorName(loadStatus));
+ return;
+ }
+
+ for(i=0;i< (int32_t)(sizeof(conformanceTestCases)/sizeof(conformanceTestCases[0]));i++){
+ const char* src = conformanceTestCases[i].in;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+ UErrorCode expectedStatus = conformanceTestCases[i].expectedStatus;
+ const char* expectedDest = conformanceTestCases[i].out;
+ char* dest = NULL;
+ int32_t destLen = 0;
+
+ destLen = nfs4_cis_prepare(src , (int32_t)strlen(src), dest, destLen, &parseError, &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR;
+ dest = (char*) malloc(++destLen);
+ destLen = nfs4_cis_prepare( src , (int32_t)strlen(src), dest, destLen, &parseError, &status);
+ }
+
+ if(expectedStatus != status){
+ log_err("Did not get the expected status for nfs4_cis_prep at index %i. Expected: %s Got: %s\n",i, u_errorName(expectedStatus), u_errorName(status));
+ }
+ if(U_SUCCESS(status) && (strcmp(expectedDest,dest) !=0)){
+ log_err("Did not get the expected output for nfs4_cis_prep at index %i.\n", i);
+ }
+ free(dest);
+ }
+}
+
+
+
+/*
+ There are several special identifiers ("who") which need to be
+ understood universally, rather than in the context of a particular
+ DNS domain. Some of these identifiers cannot be understood when an
+ NFS client accesses the server, but have meaning when a local process
+ accesses the file. The ability to display and modify these
+ permissions is permitted over NFS, even if none of the access methods
+ on the server understands the identifiers.
+
+ Who Description
+ _______________________________________________________________
+
+ "OWNER" The owner of the file.
+ "GROUP" The group associated with the file.
+ "EVERYONE" The world.
+ "INTERACTIVE" Accessed from an interactive terminal.
+ "NETWORK" Accessed via the network.
+ "DIALUP" Accessed as a dialup user to the server.
+ "BATCH" Accessed from a batch job.
+ "ANONYMOUS" Accessed without any authentication.
+ "AUTHENTICATED" Any authenticated user (opposite of
+ ANONYMOUS)
+ "SERVICE" Access from a system service.
+
+ To avoid conflict, these special identifiers are distinguish by an
+ appended "@" and should appear in the form "xxxx@" (note: no domain
+ name after the "@"). For example: ANONYMOUS@.
+*/
+static const char* mixed_prep_data[] ={
+ "OWNER@",
+ "GROUP@",
+ "EVERYONE@",
+ "INTERACTIVE@",
+ "NETWORK@",
+ "DIALUP@",
+ "BATCH@",
+ "ANONYMOUS@",
+ "AUTHENTICATED@",
+ "\\u0930\\u094D\\u092E\\u094D\\u0915\\u094D\\u0937\\u0947\\u0924\\u094D@slip129-37-118-146.nc.us.ibm.net",
+ "\\u0936\\u094d\\u0930\\u0940\\u092e\\u0926\\u094d@saratoga.pe.utexas.edu",
+ "\\u092d\\u0917\\u0935\\u0926\\u094d\\u0917\\u0940\\u0924\\u093e@dial-120-45.ots.utexas.edu",
+ "\\u0905\\u0927\\u094d\\u092f\\u093e\\u092f@woo-085.dorms.waller.net",
+ "\\u0905\\u0930\\u094d\\u091c\\u0941\\u0928@hd30-049.hil.compuserve.com",
+ "\\u0935\\u093f\\u0937\\u093e\\u0926@pem203-31.pe.ttu.edu",
+ "\\u092f\\u094b\\u0917@56K-227.MaxTNT3.pdq.net",
+ "\\u0927\\u0943\\u0924\\u0930\\u093e\\u0937\\u094d\\u091f\\u094d\\u0930@dial-36-2.ots.utexas.edu",
+ "\\u0909\\u0935\\u093E\\u091A\\u0943@slip129-37-23-152.ga.us.ibm.net",
+ "\\u0927\\u0930\\u094d\\u092e\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947@ts45ip119.cadvision.com",
+ "\\u0915\\u0941\\u0930\\u0941\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947@sdn-ts-004txaustP05.dialsprint.net",
+ "\\u0938\\u092e\\u0935\\u0947\\u0924\\u093e@bar-tnt1s66.erols.com",
+ "\\u092f\\u0941\\u092f\\u0941\\u0924\\u094d\\u0938\\u0935\\u0903@101.st-louis-15.mo.dial-access.att.net",
+ "\\u092e\\u093e\\u092e\\u0915\\u093e\\u0903@h92-245.Arco.COM",
+ "\\u092a\\u093e\\u0923\\u094d\\u0921\\u0935\\u093e\\u0936\\u094d\\u091a\\u0948\\u0935@dial-13-2.ots.utexas.edu",
+ "\\u0915\\u093f\\u092e\\u0915\\u0941\\u0930\\u094d\\u0935\\u0924@net-redynet29.datamarkets.com.ar",
+ "\\u0938\\u0902\\u091c\\u0935@ccs-shiva28.reacciun.net.ve",
+ "\\u0c30\\u0c18\\u0c41\\u0c30\\u0c3e\\u0c2e\\u0c4d@7.houston-11.tx.dial-access.att.net",
+ "\\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27@ingw129-37-120-26.mo.us.ibm.net",
+ "\\u0c06\\u0c28\\u0c02\\u0c26\\u0c4d@dialup6.austintx.com",
+ "\\u0C35\\u0C26\\u0C4D\\u0C26\\u0C3F\\u0C30\\u0C3E\\u0C1C\\u0C41@dns2.tpao.gov.tr",
+ "\\u0c30\\u0c3e\\u0c1c\\u0c40\\u0c35\\u0c4d@slip129-37-119-194.nc.us.ibm.net",
+ "\\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26@cs7.dillons.co.uk.203.119.193.in-addr.arpa",
+ "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c35\\u0c4d@swprd1.innovplace.saskatoon.sk.ca",
+ "\\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26@bikini.bologna.maraut.it",
+ "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c2c\\u0c4d@node91.subnet159-198-79.baxter.com",
+ "\\u0c38\\u0c46\\u0c28\\u0c4d\\u0c17\\u0c41\\u0c2a\\u0c4d\\u0c24@cust19.max5.new-york.ny.ms.uu.net",
+ "\\u0c05\\u0c2e\\u0c30\\u0c47\\u0c02\\u0c26\\u0c4d\\u0c30@balexander.slip.andrew.cmu.edu",
+ "\\u0c39\\u0c28\\u0c41\\u0c2e\\u0c3e\\u0c28\\u0c41\\u0c32@pool029.max2.denver.co.dynip.alter.net",
+ "\\u0c30\\u0c35\\u0c3f@cust49.max9.new-york.ny.ms.uu.net",
+ "\\u0c15\\u0c41\\u0c2e\\u0c3e\\u0c30\\u0c4d@s61.abq-dialin2.hollyberry.com",
+ "\\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27@\\u0917\\u0928\\u0947\\u0936.sanjose.ibm.com",
+ "\\u0c06\\u0c26\\u0c3f\\u0c24\\u0c4d\\u0c2f@www.\\u00E0\\u00B3\\u00AF.com",
+ "\\u0C15\\u0C02\\u0C26\\u0C4D\\u0C30\\u0C47\\u0C17\\u0C41\\u0c32@www.\\u00C2\\u00A4.com",
+ "\\u0c36\\u0c4d\\u0c30\\u0c40\\u0C27\\u0C30\\u0C4D@www.\\u00C2\\u00A3.com",
+ "\\u0c15\\u0c02\\u0c1f\\u0c2e\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f@\\u0025",
+ "\\u0c2e\\u0c3e\\u0c27\\u0c35\\u0c4d@\\u005C\\u005C",
+ "\\u0c26\\u0c46\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f@www.\\u0021.com",
+ "test@www.\\u0024.com",
+ "help@\\u00C3\\u00BC.com",
+
+};
+
+
+static void
+Test_nfs4_mixed_prep(void){
+ UErrorCode loadStatus = U_ZERO_ERROR;
+ loadTestData(&loadStatus);
+ if (U_FAILURE(loadStatus)) {
+ log_err("Test could not initialize. Got %s\n", u_errorName(loadStatus));
+ return;
+ }
+
+ {
+ int32_t i=0;
+ char src[MAX_BUFFER_SIZE];
+ int32_t srcLen;
+
+ for(i=0; i< LENGTHOF(mixed_prep_data); i++){
+ int32_t destLen=0;
+ char* dest = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+ srcLen = unescapeData(mixed_prep_data[i], (int32_t)strlen(mixed_prep_data[i]), src, MAX_BUFFER_SIZE, &status);
+ if(U_FAILURE(status)){
+ log_err("Conversion of data at index %i failed. Error: %s\n", i, u_errorName(status));
+ continue;
+ }
+ destLen = nfs4_mixed_prepare(src, srcLen, NULL, 0, &parseError, &status);
+ if(status == U_BUFFER_OVERFLOW_ERROR){
+ status = U_ZERO_ERROR;
+ dest = (char*)malloc(++destLen);
+ destLen = nfs4_mixed_prepare(src, srcLen, dest, destLen, &parseError, &status);
+ }
+ free(dest);
+ if(U_FAILURE(status)){
+ log_err("Preparation of string at index %i failed. Error: %s\n", i, u_errorName(status));
+ continue;
+ }
+ }
+ }
+ /* test the error condition */
+ {
+ const char* source = "OWNER@oss.software.ibm.com";
+ char dest[MAX_BUFFER_SIZE];
+ char src[MAX_BUFFER_SIZE] = {0};
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+
+ int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status);
+
+ nfs4_mixed_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, &parseError, &status);
+
+ if(status != U_PARSE_ERROR){
+ log_err("Did not get the expected error.Expected: %s Got: %s\n", u_errorName(U_PARSE_ERROR), u_errorName(status));
+ }
+ }
+
+
+}
+
+static void
+Test_nfs4_cs_prep(void){
+ UErrorCode errorCode = U_ZERO_ERROR;
+ loadTestData(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ {
+ /* BiDi checking is turned off */
+ const char *source = "\\uC138\\uACC4\\uC758\\uBAA8\\uB4E0\\uC0AC\\uB78C\\uB4E4\\uC774\\u0644\\u064A\\u0647\\uD55C\\uAD6D\\uC5B4\\uB97C\\uC774\\uD574\\uD55C\\uB2E4\\uBA74";
+ UErrorCode status = U_ZERO_ERROR;
+ char src[MAX_BUFFER_SIZE]={'\0'};
+ UParseError parseError;
+ int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status);
+ if(U_SUCCESS(status)){
+ char dest[MAX_BUFFER_SIZE] = {'\0'};
+ int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status);
+ if(U_FAILURE(status)){
+ log_err("StringPrep failed for case: BiDi Checking Turned OFF with error: %s\n", u_errorName(status));
+ }
+ if(strcmp(dest,src)!=0){
+ log_err("Did not get the expected output for case: BiDi Checking Turned OFF\n");
+ }
+ if(destLen != srcLen){
+ log_err("Did not get the expected length for the output for case: BiDi Checking Turned OFF. Expected: %i Got: %i\n", srcLen, destLen);
+ }
+ }else{
+ log_err("Conversion failed for case: BiDi Checking Turned OFF with error: %s\n", u_errorName(status));
+ }
+ }
+ {
+ /* Normalization turned off */
+ const char *source = "www.\\u00E0\\u00B3\\u00AF.com";
+ UErrorCode status = U_ZERO_ERROR;
+ char src[MAX_BUFFER_SIZE]={'\0'};
+ UParseError parseError;
+ int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status);
+ if(U_SUCCESS(status)){
+ char dest[MAX_BUFFER_SIZE] = {'\0'};
+ int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status);
+ if(U_FAILURE(status)){
+ log_err("StringPrep failed for case: Normalization Turned OFF with error: %s\n", u_errorName(status));
+ }
+ if(strcmp(dest,src)!=0){
+ log_err("Did not get the expected output for case: Normalization Turned OFF\n");
+ }
+ if(destLen != srcLen){
+ log_err("Did not get the expected length for the output for case: Normalization Turned OFF. Expected: %i Got: %i\n", srcLen, destLen);
+ }
+ }else{
+ log_err("Conversion failed for case: Normalization Turned OFF with error: %s\n", u_errorName(status));
+ }
+ }
+ {
+ /* case mapping turned off */
+ const char *source = "THISISATEST";
+ UErrorCode status = U_ZERO_ERROR;
+ char src[MAX_BUFFER_SIZE]={'\0'};
+ UParseError parseError;
+ int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status);
+ if(U_SUCCESS(status)){
+ char dest[MAX_BUFFER_SIZE] = {'\0'};
+ int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, TRUE, &parseError, &status);
+ if(U_FAILURE(status)){
+ log_err("StringPrep failed for case: Case Mapping Turned OFF with error: %s\n", u_errorName(status));
+ }
+ if(strcmp(dest,src)!=0){
+ log_err("Did not get the expected output for case: Case Mapping Turned OFF\n");
+ }
+ if(destLen != srcLen){
+ log_err("Did not get the expected length for the output for case: Case Mapping Turned OFF. Expected: %i Got: %i\n", srcLen, destLen);
+ }
+ }else{
+ log_err("Conversion failed for case: Case Mapping Turned OFF with error: %s\n", u_errorName(status));
+ }
+ }
+ {
+ /* case mapping turned on */
+ const char *source = "THISISATEST";
+ const char *expected = "thisisatest";
+ UErrorCode status = U_ZERO_ERROR;
+ char src[MAX_BUFFER_SIZE]={'\0'};
+ char exp[MAX_BUFFER_SIZE]={'\0'};
+ UParseError parseError;
+ int32_t srcLen = unescapeData(source, (int32_t)strlen(source), src, MAX_BUFFER_SIZE, &status);
+ int32_t expLen = unescapeData(expected, (int32_t)strlen(expected), exp, MAX_BUFFER_SIZE, &status);
+ if(U_SUCCESS(status)){
+ char dest[MAX_BUFFER_SIZE] = {'\0'};
+ int32_t destLen = nfs4_cs_prepare(src, srcLen, dest, MAX_BUFFER_SIZE, FALSE, &parseError, &status);
+ if(U_FAILURE(status)){
+ log_err("StringPrep failed for case: Case Mapping Turned On with error: %s\n", u_errorName(status));
+ }
+ if(strcmp(exp, dest)!=0){
+ log_err("Did not get the expected output for case: Case Mapping Turned On!\n");
+ }
+ if(destLen != expLen){
+ log_err("Did not get the expected length for the outputfor case: Case Mapping Turned On. Expected: %i Got: %i\n", strlen(expected), destLen);
+ }
+ }else{
+ log_err("Conversion failed for case: Case Mapping Turned ON with error: %s\n", u_errorName(status));
+ }
+ }
+}
+
+
+
+static void TestBEAMWarning(){
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseError;
+ UStringPrepProfile* profile = NULL;
+ /* get the test data path */
+ const char *testdatapath = NULL;
+ UChar src =0x0000;
+ testdatapath = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+ /* open the profile */
+ profile = usprep_open(testdatapath, "nfscis", &status);
+ usprep_prepare(profile,&src , 0, NULL, 0, USPREP_DEFAULT, &parseError, &status);
+
+ usprep_close(profile);
+}
+
+static void TestCoverage(void) {
+ UErrorCode status = U_USELESS_COLLATOR_ERROR;
+ UParseError parseError;
+
+ usprep_open(NULL, NULL, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("usprep_open didn't react correctly to a bad UErrorCode\n");
+ }
+ usprep_prepare(NULL, NULL, 0, NULL, 0, USPREP_DEFAULT, &parseError, &status);
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("usprep_prepare didn't react correctly to a bad UErrorCode\n");
+ }
+ status = U_ZERO_ERROR;
+ usprep_prepare(NULL, NULL, 0, NULL, 0, USPREP_DEFAULT, &parseError, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("usprep_prepare didn't check its arguments\n");
+ }
+
+ /* Don't crash */
+ usprep_close(NULL);
+}
+
+#endif
+
+/*
+ * Hey, Emacs, please set the following:
+ *
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c b/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c
new file mode 100644
index 00000000000..0349541c4be
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/sprpdata.c
@@ -0,0 +1,312 @@
+/*
+ *******************************************************************************
+ *
+ * Copyright (C) 2003-2004, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *
+ *******************************************************************************
+ * file name: spreptst.c
+ * encoding: US-ASCII
+ * tab size: 8 (not used)
+ * indentation:4
+ *
+ * created on: 2003jul11
+ * created by: Ram Viswanadha
+ */
+#define USPREP_TYPE_NAMES_ARRAY
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_IDNA
+
+#include "unicode/ustring.h"
+#include "unicode/putil.h"
+#include "cintltst.h"
+#include "unicode/usprep.h"
+#include "sprpimpl.h"
+#include "uparse.h"
+#include "cmemory.h"
+#include "ustr_imp.h"
+#include "cstring.h"
+
+static void
+parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode);
+
+static void
+compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping, int32_t mapLength,
+ UStringPrepType option);
+
+static void
+compareFlagsForRange(UStringPrepProfile* data, uint32_t start, uint32_t end,UStringPrepType option);
+
+void
+doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode);
+
+static void U_CALLCONV
+strprepProfileLineFn(void *context,
+ char *fields[][2], int32_t fieldCount,
+ UErrorCode *pErrorCode) {
+ uint32_t mapping[40];
+ char *end, *map;
+ uint32_t code;
+ int32_t length;
+ UStringPrepProfile* data = (UStringPrepProfile*) context;
+ const char* typeName;
+ uint32_t rangeStart=0,rangeEnd =0;
+
+ typeName = fields[2][0];
+ map = fields[1][0];
+
+ if(strstr(typeName, usprepTypeNames[USPREP_UNASSIGNED])!=NULL){
+
+ u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode);
+
+ /* store the range */
+ compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_UNASSIGNED);
+
+ }else if(strstr(typeName, usprepTypeNames[USPREP_PROHIBITED])!=NULL){
+
+ u_parseCodePointRange(fields[0][0], &rangeStart,&rangeEnd, pErrorCode);
+
+ /* store the range */
+ compareFlagsForRange(data, rangeStart,rangeEnd,USPREP_PROHIBITED);
+
+ }else if(strstr(typeName, usprepTypeNames[USPREP_MAP])!=NULL){
+ /* get the character code, field 0 */
+ code=(uint32_t)uprv_strtoul(fields[0][0], &end, 16);
+
+ /* parse the mapping string */
+ length=u_parseCodePoints(map, mapping, sizeof(mapping)/4, pErrorCode);
+
+ /* compare the mapping */
+ compareMapping(data, code,mapping, length,USPREP_MAP);
+ }else{
+ *pErrorCode = U_INVALID_FORMAT_ERROR;
+ }
+
+}
+
+
+
+static void
+parseMappings(const char *filename, UStringPrepProfile* data, UBool reportError, UErrorCode *pErrorCode) {
+ char *fields[3][2];
+
+ if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
+ return;
+ }
+
+ u_parseDelimitedFile(filename, ';', fields, 3, strprepProfileLineFn, (void*)data, pErrorCode);
+
+ /*fprintf(stdout,"Number of code points that have mappings with length >1 : %i\n",len);*/
+
+ if(U_FAILURE(*pErrorCode) && (reportError || *pErrorCode!=U_FILE_ACCESS_ERROR)) {
+ log_err( "testidn error: u_parseDelimitedFile(\"%s\") failed - %s\n", filename, u_errorName(*pErrorCode));
+ }
+}
+
+
+static UStringPrepType
+getValues(uint32_t result, int32_t* value, UBool* isIndex){
+
+ UStringPrepType type;
+ if(result == 0){
+ /*
+ * Initial value stored in the mapping table
+ * just return USPREP_TYPE_LIMIT .. so that
+ * the source codepoint is copied to the destination
+ */
+ type = USPREP_TYPE_LIMIT;
+ }else if(result >= _SPREP_TYPE_THRESHOLD){
+ type = (UStringPrepType) (result - _SPREP_TYPE_THRESHOLD);
+ }else{
+ /* get the type */
+ type = USPREP_MAP;
+ /* ascertain if the value is index or delta */
+ if(result & 0x02){
+ *isIndex = TRUE;
+ *value = result >> 2;
+
+ }else{
+ *isIndex = FALSE;
+ *value = (int16_t)result;
+ *value = (*value >> 2);
+
+ }
+ if((result>>2) == _SPREP_MAX_INDEX_VALUE){
+ type = USPREP_DELETE;
+ isIndex =FALSE;
+ value = 0;
+ }
+ }
+ return type;
+}
+
+static void
+compareMapping(UStringPrepProfile* data, uint32_t codepoint, uint32_t* mapping,int32_t mapLength,
+ UStringPrepType type){
+ uint32_t result = 0;
+ int32_t length=0;
+ UBool isIndex = FALSE;
+ UStringPrepType retType;
+ int32_t value=0, index=0, delta=0;
+ int32_t* indexes = data->indexes;
+ UTrie trie = data->sprepTrie;
+ const uint16_t* mappingData = data->mappingData;
+ int32_t realLength =0;
+ int32_t j=0;
+ int8_t i=0;
+
+ UTRIE_GET16(&trie, codepoint, result);
+ retType = getValues(result,&value,&isIndex);
+
+
+ if(type != retType && retType != USPREP_DELETE){
+
+ log_err( "Did not get the assigned type for codepoint 0x%08X. Expected: %i Got: %i\n",codepoint, USPREP_MAP, type);
+
+ }
+
+ if(isIndex){
+ index = value;
+ if(index >= indexes[_SPREP_ONE_UCHAR_MAPPING_INDEX_START] &&
+ index < indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START]){
+ length = 1;
+ }else if(index >= indexes[_SPREP_TWO_UCHARS_MAPPING_INDEX_START] &&
+ index < indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START]){
+ length = 2;
+ }else if(index >= indexes[_SPREP_THREE_UCHARS_MAPPING_INDEX_START] &&
+ index < indexes[_SPREP_FOUR_UCHARS_MAPPING_INDEX_START]){
+ length = 3;
+ }else{
+ length = mappingData[index++];
+ }
+ }else{
+ delta = value;
+ length = (retType == USPREP_DELETE)? 0 : 1;
+ }
+
+ /* figure out the real length */
+ for(j=0; j<mapLength; j++){
+ if(mapping[j] > 0xFFFF){
+ realLength +=2;
+ }else{
+ realLength++;
+ }
+ }
+
+ if(realLength != length){
+ log_err( "Did not get the expected length. Expected: %i Got: %i\n", mapLength, length);
+ }
+
+ if(isIndex){
+ for(i =0; i< mapLength; i++){
+ if(mapping[i] <= 0xFFFF){
+ if(mappingData[index+i] != (uint16_t)mapping[i]){
+ log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[i], mappingData[index+i]);
+ }
+ }else{
+ UChar lead = UTF16_LEAD(mapping[i]);
+ UChar trail = UTF16_TRAIL(mapping[i]);
+ if(mappingData[index+i] != lead ||
+ mappingData[index+i+1] != trail){
+ log_err( "Did not get the expected result. Expected: 0x%04X 0x%04X Got: 0x%04X 0x%04X\n", lead, trail, mappingData[index+i], mappingData[index+i+1]);
+ }
+ }
+ }
+ }else{
+ if(retType!=USPREP_DELETE && (codepoint-delta) != (uint16_t)mapping[0]){
+ log_err("Did not get the expected result. Expected: 0x%04X Got: 0x%04X \n", mapping[0],(codepoint-delta));
+ }
+ }
+
+}
+
+static void
+compareFlagsForRange(UStringPrepProfile* data,
+ uint32_t start, uint32_t end,
+ UStringPrepType type){
+
+ uint32_t result =0 ;
+ UStringPrepType retType;
+ UBool isIndex=FALSE;
+ int32_t value=0;
+ UTrie trie = data->sprepTrie;
+/*
+ // supplementary code point
+ UChar __lead16=UTF16_LEAD(0x2323E);
+ int32_t __offset;
+
+ // get data for lead surrogate
+ (result)=_UTRIE_GET_RAW((&idnTrie), index, 0, (__lead16));
+ __offset=(&idnTrie)->getFoldingOffset(result);
+
+ // get the real data from the folded lead/trail units
+ if(__offset>0) {
+ (result)=_UTRIE_GET_RAW((&idnTrie), index, __offset, (0x2323E)&0x3ff);
+ } else {
+ (result)=(uint32_t)((&idnTrie)->initialValue);
+ }
+
+ UTRIE_GET16(&idnTrie,0x2323E, result);
+*/
+ while(start < end+1){
+ UTRIE_GET16(&trie,start, result);
+ retType = getValues(result, &value, &isIndex);
+ if(result > _SPREP_TYPE_THRESHOLD){
+ if(retType != type){
+ log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]);
+ }
+ }else{
+ if(type == USPREP_PROHIBITED && ((result & 0x01) != 0x01)){
+ log_err( "FAIL: Did not get the expected type for 0x%06X. Expected: %s Got: %s\n",start,usprepTypeNames[type], usprepTypeNames[retType]);
+ }
+ }
+
+ start++;
+ }
+
+}
+
+void
+doStringPrepTest(const char* binFileName, const char* txtFileName, int32_t options, UErrorCode* errorCode){
+
+ const char *testdatapath = loadTestData(errorCode);
+ const char *srcdatapath = NULL;
+ const char *relativepath = NULL;
+ char *filename = NULL;
+ UStringPrepProfile* profile = NULL;
+
+#ifdef U_TOPSRCDIR
+ srcdatapath = U_TOPSRCDIR;
+ relativepath = U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
+#else
+ srcdatapath = ctest_dataOutDir();
+ relativepath = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
+#endif
+
+ filename = (char*) malloc(strlen(srcdatapath)+strlen(relativepath)+strlen(txtFileName)+10 );
+ profile = usprep_open(testdatapath, binFileName, errorCode);
+
+ if(U_FAILURE(*errorCode)){
+ log_err("Failed to load %s data file. Error: %s \n", binFileName, u_errorName(*errorCode));
+ return;
+ }
+ /* open and load the txt file */
+ strcpy(filename,srcdatapath);
+ strcat(filename,relativepath);
+ strcat(filename,txtFileName);
+
+ parseMappings(filename,profile, TRUE,errorCode);
+
+ free(filename);
+}
+#endif
+/*
+ * Hey, Emacs, please set the following:
+ *
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c
new file mode 100644
index 00000000000..2da96145b3c
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/stdnmtst.c
@@ -0,0 +1,297 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2000-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File stdnmtst.c
+*
+* Modification History:
+*
+* Date Name Description
+* 08/05/2000 Yves Creation
+******************************************************************************
+*/
+
+#include "unicode/ucnv.h"
+#include "unicode/ustring.h"
+#include "cstring.h"
+#include "cintltst.h"
+
+#define ARRAY_SIZE(array) (int32_t)(sizeof array / sizeof array[0])
+
+static void TestStandardName(void);
+static void TestStandardNames(void);
+static void TestCanonicalName(void);
+
+void addStandardNamesTest(TestNode** root);
+
+
+void
+addStandardNamesTest(TestNode** root)
+{
+ addTest(root, &TestStandardName, "tsconv/stdnmtst/TestStandardName");
+ addTest(root, &TestStandardNames, "tsconv/stdnmtst/TestStandardNames");
+ addTest(root, &TestCanonicalName, "tsconv/stdnmtst/TestCanonicalName");
+}
+
+static int dotestname(const char *name, const char *standard, const char *expected) {
+ int res = 1;
+
+ UErrorCode error;
+ const char *tag;
+
+ error = U_ZERO_ERROR;
+ tag = ucnv_getStandardName(name, standard, &error);
+ if (!tag && expected) {
+ log_err("FAIL: could not find %s standard name for %s\n", standard, name);
+ res = 0;
+ } else if (expected && (name == tag || uprv_strcmp(expected, tag))) {
+ log_err("FAIL: expected %s for %s standard name for %s, got %s\n", expected, standard, name, tag);
+ res = 0;
+ }
+
+ return res;
+}
+
+static void TestStandardName()
+{
+ int res = 1;
+
+ uint16_t i, count;
+ UErrorCode err;
+
+ /* Iterate over all standards. */
+ for (i = 0, count = ucnv_countStandards(); i < count-1; ++i) {
+ const char *standard;
+
+ err = U_ZERO_ERROR;
+ standard = ucnv_getStandard(i, &err);
+ if (U_FAILURE(err)) {
+ log_err("FAIL: ucnv_getStandard(%d), error=%s\n", i, u_errorName(err));
+ res = 0;
+ } else if (!standard || !*standard) {
+ log_err("FAIL: %s standard name at index %d\n", (standard ? "empty" :
+ "null"), i);
+ res = 0;
+ }
+ }
+ err = U_ZERO_ERROR;
+ /* "" must be last */
+ if(!count) {
+ log_data_err("No standards. You probably have no data.\n");
+ } else if (*ucnv_getStandard((uint16_t)(count-1), &err) != 0) {
+ log_err("FAIL: ucnv_getStandard(%d) should return ""\n", count-1);
+ res = 0;
+ }
+ err = U_ZERO_ERROR;
+ if (ucnv_getStandard(++i, &err)) {
+ log_err("FAIL: ucnv_getStandard(%d) should return NULL\n", i);
+ res = 0;
+ }
+
+ if (res) {
+ log_verbose("PASS: iterating over standard names works\n");
+ }
+
+ /* Test for some expected results. */
+
+ if (dotestname("ibm-1208", "MIME", "UTF-8") &&
+ /*dotestname("cp1252", "MIME", "windows-1252") &&*/
+ dotestname("ascii", "MIME", "US-ASCII") &&
+ dotestname("csiso2022jp2", "MIME", "ISO-2022-JP-2") &&
+ dotestname("Iso20-22__cN", "IANA", "ISO-2022-CN") &&
+ dotestname("ascii", "IANA", "ANSI_X3.4-1968") &&
+ dotestname("cp850", "IANA", "IBM850") &&
+ dotestname("crazy", "MIME", NULL) &&
+ dotestname("ASCII", "crazy", NULL) &&
+ dotestname("LMBCS-1", "MIME", NULL))
+ {
+ log_verbose("PASS: getting IANA and MIME standard names works\n");
+ }
+}
+
+static int dotestconv(const char *name, const char *standard, const char *expected) {
+ int res = 1;
+
+ UErrorCode error;
+ const char *tag;
+
+ error = U_ZERO_ERROR;
+ tag = ucnv_getCanonicalName(name, standard, &error);
+ if (tag && !expected) {
+ log_err("FAIL: Unexpectedly found %s canonical name for %s, got %s\n", standard, name, tag);
+ res = 0;
+ }
+ else if (!tag && expected) {
+ log_err("FAIL: could not find %s canonical name for %s\n", (standard ? "\"\"" : standard), name);
+ res = 0;
+ }
+ else if (expected && (name == tag || uprv_strcmp(expected, tag) != 0)) {
+ log_err("FAIL: expected %s for %s canonical name for %s, got %s\n", expected, standard, name, tag);
+ res = 0;
+ }
+ else {
+ log_verbose("PASS: (\"%s\", \"%s\") -> %s == %s \n", name, standard, tag, expected);
+ }
+
+ return res;
+}
+
+static void TestCanonicalName()
+{
+ /* Test for some expected results. */
+
+ if (dotestconv("UTF-8", "IANA", "UTF-8") && /* default name */
+ dotestconv("UTF-8", "MIME", "UTF-8") && /* default name */
+ dotestconv("ibm-1208", "IBM", "UTF-8") && /* default name */
+ dotestconv("ibm-5305", "IBM", "UTF-8") && /* non-default name */
+ dotestconv("ibm-5305", "MIME", NULL) && /* mapping does not exist */
+ dotestconv("ascii", "MIME", NULL) && /* mapping does not exist */
+ dotestconv("ibm-1208", "IANA", NULL) && /* mapping does not exist */
+ dotestconv("ibm-5305", "IANA", NULL) && /* mapping does not exist */
+ dotestconv("cp1208", "", "UTF-8") && /* default name due to ordering */
+ dotestconv("UTF16_BigEndian", "", "UTF-16BE") && /* non-default name due to ordering */
+ dotestconv("ISO-2022-CN", "IANA", "ISO_2022,locale=zh,version=0") &&/* default name */
+ dotestconv("Shift_JIS", "MIME", "ibm-943_P15A-2003") &&/* ambiguous alias */
+ dotestconv("Shift_JIS", "", "ibm-943_P130-1999") &&/* ambiguous alias */
+ dotestconv("ibm-943", "", "ibm-943_P15A-2003") &&/* ambiguous alias */
+ dotestconv("ibm-943", "IBM", "ibm-943_P130-1999") &&/* ambiguous alias */
+ dotestconv("ibm-1363", "", "ibm-1363_P11B-1998") &&/* ambiguous alias */
+ dotestconv("ibm-1363", "IBM", "ibm-1363_P110-1997") &&/* ambiguous alias */
+ dotestconv("crazy", "MIME", NULL) &&
+ dotestconv("ASCII", "crazy", NULL))
+ {
+ log_verbose("PASS: getting IANA and MIME canonical names works\n");
+ }
+}
+
+
+static UBool doTestNames(const char *name, const char *standard, const char **expected, int32_t size) {
+ UErrorCode err = U_ZERO_ERROR;
+ UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err);
+ const char *enumName, *testName;
+ int32_t enumCount = uenum_count(myEnum, &err);
+ int32_t idx, len, repeatTimes = 3;
+ if (size != enumCount) {
+ log_err("FAIL: different size arrays for %s. Got %d. Expected %d\n", name, enumCount, size);
+ return 0;
+ }
+ if (size < 0 && myEnum) {
+ log_err("FAIL: size < 0, but recieved an actual object\n");
+ return 0;
+ }
+ log_verbose("\n%s %s\n", name, standard);
+ while (repeatTimes-- > 0) {
+ for (idx = 0; idx < enumCount; idx++) {
+ enumName = uenum_next(myEnum, &len, &err);
+ testName = expected[idx];
+ if (uprv_strcmp(enumName, testName) != 0 || U_FAILURE(err)
+ || len != (int32_t)uprv_strlen(expected[idx]))
+ {
+ log_err("FAIL: uenum_next(%d) == \"%s\". expected \"%s\", len=%d, error=%s\n",
+ idx, enumName, testName, len, u_errorName(err));
+ }
+ log_verbose("%s\n", enumName);
+ err = U_ZERO_ERROR;
+ }
+ if (enumCount >= 0) {
+ /* one past the list of all names must return NULL */
+ enumName = uenum_next(myEnum, &len, &err);
+ if (enumName != NULL || len != 0 || U_FAILURE(err)) {
+ log_err("FAIL: uenum_next(past the list) did not return NULL[0] with U_SUCCESS(). name=%s standard=%s len=%d err=%s\n", name, standard, len, u_errorName(err));
+ }
+ }
+ log_verbose("\n reset\n");
+ uenum_reset(myEnum, &err);
+ if (U_FAILURE(err)) {
+ log_err("FAIL: uenum_reset() for %s{%s} failed with %s\n",
+ name, standard, u_errorName(err));
+ err = U_ZERO_ERROR;
+ }
+ }
+ uenum_close(myEnum);
+ return 1;
+}
+
+static UBool doTestUCharNames(const char *name, const char *standard, const char **expected, int32_t size) {
+ UErrorCode err = U_ZERO_ERROR;
+ UEnumeration *myEnum = ucnv_openStandardNames(name, standard, &err);
+ int32_t enumCount = uenum_count(myEnum, &err);
+ int32_t idx, repeatTimes = 3;
+ if (size != enumCount) {
+ log_err("FAIL: different size arrays. Got %d. Expected %d\n", enumCount, size);
+ return 0;
+ }
+ if (size < 0 && myEnum) {
+ log_err("FAIL: size < 0, but recieved an actual object\n");
+ return 0;
+ }
+ log_verbose("\n%s %s\n", name, standard);
+ while (repeatTimes-- > 0) {
+ for (idx = 0; idx < enumCount; idx++) {
+ UChar testName[256];
+ int32_t len;
+ const UChar *enumName = uenum_unext(myEnum, &len, &err);
+ u_uastrncpy(testName, expected[idx], sizeof(testName)/sizeof(testName[0]));
+ if (u_strcmp(enumName, testName) != 0 || U_FAILURE(err)
+ || len != (int32_t)uprv_strlen(expected[idx]))
+ {
+ log_err("FAIL: uenum_next(%d) == \"%s\". expected \"%s\", len=%d, error=%s\n",
+ idx, enumName, testName, len, u_errorName(err));
+ }
+ log_verbose("%s\n", expected[idx]);
+ err = U_ZERO_ERROR;
+ }
+ log_verbose("\n reset\n");
+ uenum_reset(myEnum, &err);
+ if (U_FAILURE(err)) {
+ log_err("FAIL: uenum_reset() for %s{%s} failed with %s\n",
+ name, standard, u_errorName(err));
+ err = U_ZERO_ERROR;
+ }
+ }
+ uenum_close(myEnum);
+ return 1;
+}
+
+static void TestStandardNames()
+{
+ static const char *asciiIANA[] = {
+ "ANSI_X3.4-1968",
+ "US-ASCII",
+ "ASCII",
+ "ANSI_X3.4-1986",
+ "ISO_646.irv:1991",
+ "ISO646-US",
+ "us",
+ "csASCII",
+ "iso-ir-6",
+ "cp367",
+ "IBM367",
+ };
+ static const char *asciiMIME[] = {
+ "US-ASCII"
+ };
+
+ static const char *iso2022MIME[] = {
+ "ISO-2022-KR",
+ };
+
+ doTestNames("ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA));
+ doTestNames("US-ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA));
+ doTestNames("ASCII", "MIME", asciiMIME, ARRAY_SIZE(asciiMIME));
+ doTestNames("ascii", "mime", asciiMIME, ARRAY_SIZE(asciiMIME));
+
+ doTestNames("ASCII", "crazy", asciiMIME, -1);
+ doTestNames("crazy", "MIME", asciiMIME, -1);
+
+ doTestNames("LMBCS-1", "MIME", asciiMIME, 0);
+
+ doTestNames("ISO_2022,locale=ko,version=0", "MIME", iso2022MIME, ARRAY_SIZE(iso2022MIME));
+ doTestNames("csiso2022kr", "MIME", iso2022MIME, ARRAY_SIZE(iso2022MIME));
+
+ log_verbose(" Testing unext()\n");
+ doTestUCharNames("ASCII", "IANA", asciiIANA, ARRAY_SIZE(asciiIANA));
+
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c
new file mode 100644
index 00000000000..d61804482a1
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/tracetst.c
@@ -0,0 +1,379 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2003-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+ * File tracetst.c
+ *
+ */
+
+
+#include "unicode/utypes.h"
+#include "unicode/utrace.h"
+#include "unicode/uclean.h"
+#include "unicode/uchar.h"
+#include "unicode/ures.h"
+#include "unicode/ucnv.h"
+#include "cintltst.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* We define the following to always test tracing, even when it's off in the library. */
+#if U_ENABLE_TRACING
+#define ENABLE_TRACING_ORIG_VAL 1
+#else
+#define ENABLE_TRACING_ORIG_VAL 0
+#endif
+#undef U_ENABLE_TRACING
+#define U_ENABLE_TRACING 1
+#include "utracimp.h"
+
+
+static void TestTraceAPI(void);
+
+
+void
+addUTraceTest(TestNode** root);
+
+void
+addUTraceTest(TestNode** root)
+{
+ addTest(root, &TestTraceAPI, "tsutil/TraceTest/TestTraceAPI" );
+}
+
+
+/*
+ * Macro for assert style tests.
+ */
+#define TEST_ASSERT(expr) \
+if (!(expr)) { \
+ log_err("FAILED Assertion \"" #expr "\" at %s:%d.\n", __FILE__, __LINE__); \
+}
+
+
+/*
+ * test_format. Helper function for checking the results of a formatting
+ * operation. Executes the format op and compares actual
+ * results with the expected results.
+ *
+ * params: format: the format to be applied.
+ * bufCap buffer size to pass to formatter.
+ * indent: indent value to give to formatter
+ * result expected result. Do not truncate for short bufCap -
+ * this function will do it.
+ * line __LINE__, so we can report where failure happened.
+ * ... variable args to pass to formatter
+ *
+ */
+static void test_format(const char *format, int32_t bufCap, int32_t indent,
+ const char *result, int32_t line, ...) {
+ int32_t len;
+ va_list args;
+ char buf[300];
+ char expectedResult[300];
+
+ /* check that local buffers are big enough for the test case */
+ if (sizeof(buf) <= bufCap) {
+ log_err("At file:line %s:%d, requested bufCap too large.\n");
+ return;
+ }
+ if (strlen(result) >= sizeof(expectedResult)) {
+ log_err("At file:line %s:%d, expected result too large.\n");
+ return;
+ }
+
+ /* Guarantee a nul term if buffer is smaller than output */
+ strcpy(expectedResult, result);
+ expectedResult[bufCap] = 0;
+
+ /* run the formatter */
+ va_start(args, line);
+ memset(buf, 0, sizeof(buf));
+ len = utrace_vformat(buf, bufCap, indent, format, args);
+
+ /* Check results. */
+ if (strcmp(expectedResult, buf) != 0) {
+ log_err("At file:line %s:%d Expected \"%s\", got \"%s\" \n",
+ __FILE__, line, expectedResult, buf);
+ }
+ va_end(args);
+}
+
+
+/*
+ * define trace functions for use in this test.
+ */
+static int gTraceEntryCount;
+static int gTraceExitCount;
+static int gTraceDataCount;
+static UBool gFnNameError = FALSE;
+static UBool gFnFormatError = FALSE;
+
+static void U_CALLCONV testTraceEntry(const void *context, int32_t fnNumber) {
+ const char *fnName;
+ const char *bogusFnName;
+
+ gTraceEntryCount++;
+
+ /* Verify that a name is available for the fnNumber passed to us */
+ bogusFnName = utrace_functionName(-1);
+ fnName = utrace_functionName(fnNumber);
+ if (strcmp(fnName, bogusFnName) == 0) {
+ gFnNameError = TRUE;
+ }
+ /* printf("%s() Enter\n", fnName); */
+
+}
+
+static void U_CALLCONV testTraceExit(const void *context, int32_t fnNumber,
+ const char *fmt, va_list args) {
+ char buf[1000];
+ const char *fnName;
+ const char *bogusFnName;
+
+ gTraceExitCount++;
+
+ /* Verify that a name is available for the fnNumber passed to us */
+ bogusFnName = utrace_functionName(-1);
+ fnName = utrace_functionName(fnNumber);
+ if (strcmp(fnName, bogusFnName) == 0) {
+ gFnNameError = TRUE;
+ }
+
+ /* Verify that the format can be used. */
+ buf[0] = 0;
+ utrace_vformat(buf, sizeof(buf), 0, fmt, args);
+ if (strlen(buf) == 0) {
+ gFnFormatError = TRUE;
+ }
+
+ /* printf("%s() %s\n", fnName, buf); */
+
+}
+
+static void U_CALLCONV testTraceData(const void *context, int32_t fnNumber, int32_t level,
+ const char *fmt, va_list args) {
+ char buf[1000];
+ const char *fnName;
+ const char *bogusFnName;
+
+ gTraceDataCount++;
+
+ /* Verify that a name is available for the fnNumber passed to us */
+ bogusFnName = utrace_functionName(-1);
+ fnName = utrace_functionName(fnNumber);
+ if (strcmp(fnName, bogusFnName) == 0) {
+ gFnNameError = TRUE;
+ }
+
+ /* Verify that the format can be used. */
+ buf[0] = 0;
+ utrace_vformat(buf, sizeof(buf), 0, fmt, args);
+ if (strlen(buf) == 0) {
+ gFnFormatError = TRUE;
+ }
+
+ /* printf(" %s() %s\n", fnName, buf); */
+}
+
+static UConverter * psuedo_ucnv_open(const char *name, UErrorCode * err)
+{
+ UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD);
+
+ UTRACE_DATA2(UTRACE_OPEN_CLOSE, "error code is %s for %s", u_errorName(*err), name);
+
+ UTRACE_EXIT_PTR_STATUS(NULL, *err);
+ return NULL;
+}
+static void psuedo_ucnv_close(UConverter * cnv)
+{
+ UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD);
+ UTRACE_DATA1(UTRACE_OPEN_CLOSE, "unload converter %p", cnv);
+ UTRACE_EXIT_VALUE((int32_t)TRUE);
+}
+
+
+/*
+ * TestTraceAPI
+ */
+static void TestTraceAPI() {
+
+
+ UTraceEntry *originalTEntryFunc;
+ UTraceExit *originalTExitFunc;
+ UTraceData *originalTDataFunc;
+ const void *originalTContext;
+ int32_t originalLevel;
+
+ /*
+ * Save the original tracing state so that we can restore it after the test.
+ */
+ utrace_getFunctions(&originalTContext, &originalTEntryFunc, &originalTExitFunc,
+ &originalTDataFunc);
+ originalLevel = utrace_getLevel();
+
+
+ /* verify that set/get of tracing functions returns what was set. */
+ {
+ UTraceEntry *e;
+ UTraceExit *x;
+ UTraceData *d;
+ const void *context;
+ const void *newContext = (const char *)originalTContext + 1;
+
+ TEST_ASSERT(originalTEntryFunc != testTraceEntry);
+ TEST_ASSERT(originalTExitFunc != testTraceExit);
+ TEST_ASSERT(originalTDataFunc != testTraceData);
+
+ utrace_setFunctions(newContext, testTraceEntry, testTraceExit, testTraceData);
+ utrace_getFunctions(&context, &e, &x, &d);
+ TEST_ASSERT(e == testTraceEntry);
+ TEST_ASSERT(x == testTraceExit);
+ TEST_ASSERT(d == testTraceData);
+ TEST_ASSERT(context == newContext);
+ }
+
+ /* verify that set/get level work as a pair, and that the level
+ * identifiers all exist.
+ */
+
+ {
+ int32_t level;
+
+ utrace_setLevel(UTRACE_OFF);
+ level = utrace_getLevel();
+ TEST_ASSERT(level==UTRACE_OFF);
+ utrace_setLevel(UTRACE_VERBOSE);
+ level = utrace_getLevel();
+ TEST_ASSERT(level==UTRACE_VERBOSE);
+ utrace_setLevel(UTRACE_ERROR);
+ utrace_setLevel(UTRACE_WARNING);
+ utrace_setLevel(UTRACE_OPEN_CLOSE);
+ utrace_setLevel(UTRACE_INFO);
+ }
+
+ /*
+ * Open and close a converter with tracing enabled.
+ * Verify that our tracing callback functions get called.
+ */
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv;
+
+ gTraceEntryCount = 0;
+ gTraceExitCount = 0;
+ gTraceDataCount = 0;
+ gFnNameError = FALSE;
+ gFnFormatError = FALSE;
+ utrace_setLevel(UTRACE_OPEN_CLOSE);
+#if ENABLE_TRACING_ORIG_VAL
+ cnv = ucnv_open(NULL, &status);
+ TEST_ASSERT(U_SUCCESS(status));
+ ucnv_close(cnv);
+#else
+ cnv = psuedo_ucnv_open(NULL, &status);
+ TEST_ASSERT(U_SUCCESS(status));
+ psuedo_ucnv_close(cnv);
+#endif
+ TEST_ASSERT(gTraceEntryCount > 0);
+ TEST_ASSERT(gTraceExitCount > 0);
+ TEST_ASSERT(gTraceDataCount > 0);
+ TEST_ASSERT(gFnNameError == FALSE);
+ TEST_ASSERT(gFnFormatError == FALSE);
+ }
+
+
+
+ /*
+ * trace data formatter operation.
+ */
+ {
+ UChar s1[] = {0x41fe, 0x42, 0x43, 00};
+ const char *a1[] = {"s1", "s2", "s3"};
+ void *ptr;
+
+ test_format("hello, world", 50, 0, "hello, world", __LINE__);
+ test_format("hello, world", 50, 4, " hello, world", __LINE__);
+ test_format("hello, world", 3, 0, "hello, world", __LINE__);
+
+ test_format("a character %c", 50, 0, "a character x", __LINE__, 'x');
+ test_format("a string %s ", 50, 0, "a string hello ", __LINE__, "hello");
+ test_format("uchars %S ", 50, 0, "uchars 41fe 0042 0043 0000 ", __LINE__, s1, -1);
+ test_format("uchars %S ", 50, 0, "uchars 41fe 0042 ", __LINE__, s1, 2);
+
+ test_format("a byte %b--", 50, 0, "a byte dd--", __LINE__, 0xdd);
+ test_format("a 16 bit val %h", 50, 0, "a 16 bit val 1234", __LINE__, 0x1234);
+ test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd);
+ test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0"
+ , __LINE__, INT64_C(0x123456780abcdef0));
+
+ if (sizeof(void *) == 4) {
+ ptr = (void *)0xdeadbeef;
+ test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr);
+ } else if (sizeof(void *) == 8) {
+ ptr = (void *) INT64_C(0x1000200030004000);
+ test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr);
+ } else if (sizeof(void *) == 16) {
+ /* iSeries */
+ union {
+ int32_t arr[4];
+ void *ptr;
+ } massiveBigEndianPtr = {{ 0x10002000, 0x30004000, 0x50006000, 0x70008000 }};
+ ptr = massiveBigEndianPtr.ptr;
+ test_format("a 128 bit ptr %p", 50, 0, "a 128 bit ptr 10002000300040005000600070008000", __LINE__, ptr);
+ } else {
+ TEST_ASSERT(FALSE);
+ /* TODO: others? */
+ }
+
+ test_format("%vc", 100, 0, "abc[ffffffff]", __LINE__, "abc", -1);
+ test_format("%vs", 100, 0, "s1\ns2\n[00000002]", __LINE__, a1, 2);
+ test_format("%vs", 100, 4, " s1\n s2\n [00000002]", __LINE__, a1, 2);
+
+ test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "\x41\x42\x43", 3);
+
+ /* Null ptrs for strings, vectors */
+ test_format("Null string - %s", 50, 0, "Null string - *NULL*", __LINE__, NULL);
+ test_format("Null string - %S", 50, 0, "Null string - *NULL*", __LINE__, NULL);
+ test_format("Null vector - %vc", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
+ test_format("Null vector - %vC", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
+ test_format("Null vector - %vd", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
+
+ }
+
+ /*
+ * utrace_format. Only need a minimal test to see that the function works at all.
+ * Full functionality is tested via utrace_vformat.
+ */
+ {
+ char buf[100];
+ int32_t x;
+ x = utrace_format(buf, 100, 0, "%s", "Hello, World.");
+ TEST_ASSERT(strcmp(buf, "Hello, World.") == 0);
+ TEST_ASSERT(x == 14);
+ }
+
+ /*
+ * utrace_functionName. Just spot-check a couple of them.
+ */
+ {
+ const char *name;
+ name = utrace_functionName(UTRACE_U_INIT);
+ TEST_ASSERT(strcmp(name, "u_init") == 0);
+ name = utrace_functionName(UTRACE_UCNV_OPEN);
+ TEST_ASSERT(strcmp(name, "ucnv_open") == 0);
+ name = utrace_functionName(UTRACE_UCOL_GET_SORTKEY);
+ TEST_ASSERT(strcmp(name, "ucol_getSortKey") == 0);
+ }
+
+
+
+ /* Restore the trace function settings to their original values. */
+ utrace_setFunctions(originalTContext, originalTEntryFunc, originalTExitFunc, originalTDataFunc);
+ utrace_setLevel(originalLevel);
+}
+
+
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c
new file mode 100644
index 00000000000..c4a7c1733fc
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/trietest.c
@@ -0,0 +1,877 @@
+/*
+******************************************************************************
+*
+* Copyright (C) 2001-2006, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+******************************************************************************
+* file name: trietest.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2001nov20
+* created by: Markus W. Scherer
+*/
+
+#include <stdio.h>
+#include "unicode/utypes.h"
+#include "utrie.h"
+#include "cstring.h"
+#include "cmemory.h"
+
+#if 1
+#include "cintltst.h"
+#else
+/* definitions from standalone utrie development */
+#define log_err printf
+#define log_verbose printf
+
+#undef u_errorName
+#define u_errorName(errorCode) "some error code"
+#endif
+
+#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
+
+/* Values for setting possibly overlapping, out-of-order ranges of values */
+typedef struct SetRange {
+ UChar32 start, limit;
+ uint32_t value;
+ UBool overwrite;
+} SetRange;
+
+/*
+ * Values for testing:
+ * value is set from the previous boundary's limit to before
+ * this boundary's limit
+ */
+typedef struct CheckRange {
+ UChar32 limit;
+ uint32_t value;
+} CheckRange;
+
+
+static uint32_t U_CALLCONV
+_testFoldedValue32(UNewTrie *trie, UChar32 start, int32_t offset) {
+ uint32_t foldedValue, value;
+ UChar32 limit;
+ UBool inBlockZero;
+
+ foldedValue=0;
+
+ limit=start+0x400;
+ while(start<limit) {
+ value=utrie_get32(trie, start, &inBlockZero);
+ if(inBlockZero) {
+ start+=UTRIE_DATA_BLOCK_LENGTH;
+ } else {
+ foldedValue|=value;
+ ++start;
+ }
+ }
+
+ if(foldedValue!=0) {
+ return ((uint32_t)offset<<16)|foldedValue;
+ } else {
+ return 0;
+ }
+}
+
+static int32_t U_CALLCONV
+_testFoldingOffset32(uint32_t data) {
+ return (int32_t)(data>>16);
+}
+
+static uint32_t U_CALLCONV
+_testFoldedValue16(UNewTrie *trie, UChar32 start, int32_t offset) {
+ uint32_t foldedValue, value;
+ UChar32 limit;
+ UBool inBlockZero;
+
+ foldedValue=0;
+
+ limit=start+0x400;
+ while(start<limit) {
+ value=utrie_get32(trie, start, &inBlockZero);
+ if(inBlockZero) {
+ start+=UTRIE_DATA_BLOCK_LENGTH;
+ } else {
+ foldedValue|=value;
+ ++start;
+ }
+ }
+
+ if(foldedValue!=0) {
+ return (uint32_t)(offset|0x8000);
+ } else {
+ return 0;
+ }
+}
+
+static int32_t U_CALLCONV
+_testFoldingOffset16(uint32_t data) {
+ if(data&0x8000) {
+ return (int32_t)(data&0x7fff);
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t U_CALLCONV
+_testEnumValue(const void *context, uint32_t value) {
+ return value^0x5555;
+}
+
+static UBool U_CALLCONV
+_testEnumRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) {
+ const CheckRange **pb=(const CheckRange **)context;
+ const CheckRange *b=(*pb)++;
+
+ value^=0x5555;
+ if(start!=(b-1)->limit || limit!=b->limit || value!=b->value) {
+ log_err("error: utrie_enum() delivers wrong range [U+%04lx..U+%04lx[.0x%lx instead of [U+%04lx..U+%04lx[.0x%lx\n",
+ start, limit, value,
+ (b-1)->limit, b->limit, b->value);
+ }
+ return TRUE;
+}
+
+static void
+testTrieIteration(const char *testName,
+ const UTrie *trie,
+ const CheckRange checkRanges[], int32_t countCheckRanges) {
+ UChar s[100];
+ uint32_t values[30];
+
+ const UChar *p, *limit;
+
+ uint32_t value;
+ UChar32 c;
+ int32_t i, length, countValues;
+ UChar c2;
+
+ /* write a string */
+ length=countValues=0;
+ for(i=0; i<countCheckRanges; ++i) {
+ c=checkRanges[i].limit;
+ if(c!=0) {
+ --c;
+ UTF_APPEND_CHAR_UNSAFE(s, length, c);
+ values[countValues++]=checkRanges[i].value;
+ }
+ }
+ limit=s+length;
+
+ /* try forward */
+ p=s;
+ i=0;
+ while(p<limit) {
+ c=c2=0x33;
+ if(trie->data32!=NULL) {
+ UTRIE_NEXT32(trie, p, limit, c, c2, value);
+ } else {
+ UTRIE_NEXT16(trie, p, limit, c, c2, value);
+ }
+ if(value!=values[i]) {
+ log_err("error: wrong value from UTRIE_NEXT(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
+ testName, c, c2, value, values[i]);
+ }
+ if(
+ c2==0 ?
+ c!=*(p-1) :
+ !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*(p-2) || c2!=*(p-1)
+ ) {
+ log_err("error: wrong (c, c2) from UTRIE_NEXT(%s): (U+%04lx, U+%04lx)\n",
+ testName, c, c2);
+ continue;
+ }
+ if(c2!=0) {
+ int32_t offset;
+
+ if(trie->data32==NULL) {
+ value=UTRIE_GET16_FROM_LEAD(trie, c);
+ offset=trie->getFoldingOffset(value);
+ if(offset>0) {
+ value=UTRIE_GET16_FROM_OFFSET_TRAIL(trie, offset, c2);
+ } else {
+ value=trie->initialValue;
+ }
+ } else {
+ value=UTRIE_GET32_FROM_LEAD(trie, c);
+ offset=trie->getFoldingOffset(value);
+ if(offset>0) {
+ value=UTRIE_GET32_FROM_OFFSET_TRAIL(trie, offset, c2);
+ } else {
+ value=trie->initialValue;
+ }
+ }
+ if(value!=values[i]) {
+ log_err("error: wrong value from UTRIE_GETXX_FROM_OFFSET_TRAIL(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
+ testName, c, c2, value, values[i]);
+ }
+ }
+ if(c2!=0) {
+ value=0x44;
+ if(trie->data32==NULL) {
+ UTRIE_GET16_FROM_PAIR(trie, c, c2, value);
+ } else {
+ UTRIE_GET32_FROM_PAIR(trie, c, c2, value);
+ }
+ if(value!=values[i]) {
+ log_err("error: wrong value from UTRIE_GETXX_FROM_PAIR(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
+ testName, c, c2, value, values[i]);
+ }
+ }
+ ++i;
+ }
+
+ /* try backward */
+ p=limit;
+ i=countValues;
+ while(s<p) {
+ --i;
+ c=c2=0x33;
+ if(trie->data32!=NULL) {
+ UTRIE_PREVIOUS32(trie, s, p, c, c2, value);
+ } else {
+ UTRIE_PREVIOUS16(trie, s, p, c, c2, value);
+ }
+ if(value!=values[i]) {
+ log_err("error: wrong value from UTRIE_PREVIOUS(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
+ testName, c, c2, value, values[i]);
+ }
+ if(
+ c2==0 ?
+ c!=*p:
+ !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*p || c2!=*(p+1)
+ ) {
+ log_err("error: wrong (c, c2) from UTRIE_PREVIOUS(%s): (U+%04lx, U+%04lx)\n",
+ testName, c, c2);
+ }
+ }
+}
+
+static void
+testTrieRangesWithMalloc(const char *testName,
+ const SetRange setRanges[], int32_t countSetRanges,
+ const CheckRange checkRanges[], int32_t countCheckRanges,
+ UBool dataIs32, UBool latin1Linear) {
+ UTrieGetFoldingOffset *getFoldingOffset;
+ const CheckRange *enumRanges;
+ UNewTrie *newTrie;
+ UTrie trie={ 0 };
+ uint32_t value, value2;
+ UChar32 start, limit;
+ int32_t i, length;
+ UErrorCode errorCode;
+ UBool overwrite, ok;
+ uint8_t* storage =NULL;
+ static const int32_t DEFAULT_STORAGE_SIZE = 32768;
+ storage = (uint8_t*) uprv_malloc(sizeof(uint8_t)*DEFAULT_STORAGE_SIZE);
+
+ log_verbose("\ntesting Trie '%s'\n", testName);
+ newTrie=utrie_open(NULL, NULL, 2000,
+ checkRanges[0].value, checkRanges[0].value,
+ latin1Linear);
+
+ /* set values from setRanges[] */
+ ok=TRUE;
+ for(i=0; i<countSetRanges; ++i) {
+ start=setRanges[i].start;
+ limit=setRanges[i].limit;
+ value=setRanges[i].value;
+ overwrite=setRanges[i].overwrite;
+ if((limit-start)==1 && overwrite) {
+ ok&=utrie_set32(newTrie, start, value);
+ } else {
+ ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
+ }
+ }
+ if(!ok) {
+ log_err("error: setting values into a trie failed (%s)\n", testName);
+ return;
+ }
+
+ /* verify that all these values are in the new Trie */
+ start=0;
+ for(i=0; i<countCheckRanges; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ while(start<limit) {
+ if(value!=utrie_get32(newTrie, start, NULL)) {
+ log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
+ testName, start, utrie_get32(newTrie, start, NULL), value);
+ }
+ ++start;
+ }
+ }
+
+ if(dataIs32) {
+ getFoldingOffset=_testFoldingOffset32;
+ } else {
+ getFoldingOffset=_testFoldingOffset16;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=utrie_serialize(newTrie, storage, DEFAULT_STORAGE_SIZE,
+ dataIs32 ? _testFoldedValue32 : _testFoldedValue16,
+ (UBool)!dataIs32,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
+ utrie_close(newTrie);
+ return;
+ }
+
+ /* test linear Latin-1 range from utrie_getData() */
+ if(latin1Linear) {
+ uint32_t *data;
+ int32_t dataLength;
+
+ data=utrie_getData(newTrie, &dataLength);
+ start=0;
+ for(i=0; i<countCheckRanges && start<=0xff; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ while(start<limit && start<=0xff) {
+ if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
+ log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
+ testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
+ }
+ ++start;
+ }
+ }
+ }
+
+ utrie_close(newTrie);
+
+ errorCode=U_ZERO_ERROR;
+ if(!utrie_unserialize(&trie, storage, length, &errorCode)) {
+ log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
+ return;
+ }
+ trie.getFoldingOffset=getFoldingOffset;
+
+ if(dataIs32!=(trie.data32!=NULL)) {
+ log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
+ }
+ if(latin1Linear!=trie.isLatin1Linear) {
+ log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
+ }
+
+ /* verify that all these values are in the unserialized Trie */
+ start=0;
+ for(i=0; i<countCheckRanges; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ if(start==0xd800) {
+ /* skip surrogates */
+ start=limit;
+ continue;
+ }
+
+ while(start<limit) {
+ if(start<=0xffff) {
+ if(dataIs32) {
+ value2=UTRIE_GET32_FROM_BMP(&trie, start);
+ } else {
+ value2=UTRIE_GET16_FROM_BMP(&trie, start);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ if(!UTF_IS_LEAD(start)) {
+ if(dataIs32) {
+ value2=UTRIE_GET32_FROM_LEAD(&trie, start);
+ } else {
+ value2=UTRIE_GET16_FROM_LEAD(&trie, start);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ }
+ }
+ if(dataIs32) {
+ UTRIE_GET32(&trie, start, value2);
+ } else {
+ UTRIE_GET16(&trie, start, value2);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ ++start;
+ }
+ }
+
+ /* enumerate and verify all ranges */
+ enumRanges=checkRanges+1;
+ utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
+
+ /* test linear Latin-1 range */
+ if(trie.isLatin1Linear) {
+ if(trie.data32!=NULL) {
+ const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
+
+ for(start=0; start<0x100; ++start) {
+ if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
+ log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
+ testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
+ }
+ }
+ } else {
+ const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
+
+ for(start=0; start<0x100; ++start) {
+ if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
+ log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
+ testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
+ }
+ }
+ }
+ }
+
+ testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
+ uprv_free(storage);
+}
+
+static void
+testTrieRanges(const char *testName,
+ const SetRange setRanges[], int32_t countSetRanges,
+ const CheckRange checkRanges[], int32_t countCheckRanges,
+ UBool dataIs32, UBool latin1Linear) {
+ union{
+ double bogus; /* needed for aligining the storage */
+ uint8_t storage[32768];
+ } storageHolder;
+ UTrieGetFoldingOffset *getFoldingOffset;
+ UNewTrieGetFoldedValue *getFoldedValue;
+ const CheckRange *enumRanges;
+ UNewTrie *newTrie;
+ UTrie trie={ 0 };
+ uint32_t value, value2;
+ UChar32 start, limit;
+ int32_t i, length;
+ UErrorCode errorCode;
+ UBool overwrite, ok;
+
+ log_verbose("\ntesting Trie '%s'\n", testName);
+ newTrie=utrie_open(NULL, NULL, 2000,
+ checkRanges[0].value, checkRanges[0].value,
+ latin1Linear);
+
+ /* set values from setRanges[] */
+ ok=TRUE;
+ for(i=0; i<countSetRanges; ++i) {
+ start=setRanges[i].start;
+ limit=setRanges[i].limit;
+ value=setRanges[i].value;
+ overwrite=setRanges[i].overwrite;
+ if((limit-start)==1 && overwrite) {
+ ok&=utrie_set32(newTrie, start, value);
+ } else {
+ ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
+ }
+ }
+ if(!ok) {
+ log_err("error: setting values into a trie failed (%s)\n", testName);
+ return;
+ }
+
+ /* verify that all these values are in the new Trie */
+ start=0;
+ for(i=0; i<countCheckRanges; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ while(start<limit) {
+ if(value!=utrie_get32(newTrie, start, NULL)) {
+ log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
+ testName, start, utrie_get32(newTrie, start, NULL), value);
+ }
+ ++start;
+ }
+ }
+
+ if(dataIs32) {
+ getFoldingOffset=_testFoldingOffset32;
+ getFoldedValue=_testFoldedValue32;
+ } else {
+ getFoldingOffset=_testFoldingOffset16;
+ getFoldedValue=_testFoldedValue16;
+ }
+
+ /*
+ * code coverage for utrie.c/defaultGetFoldedValue(),
+ * pick some combination of parameters for selecting the UTrie defaults
+ */
+ if(!dataIs32 && latin1Linear) {
+ getFoldingOffset=NULL;
+ getFoldedValue=NULL;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ length=utrie_serialize(newTrie, storageHolder.storage, sizeof(storageHolder.storage),
+ getFoldedValue,
+ (UBool)!dataIs32,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
+ utrie_close(newTrie);
+ return;
+ }
+ if (length >= (int32_t)sizeof(storageHolder.storage)) {
+ log_err("error: utrie_serialize(%s) needs more memory\n", testName);
+ utrie_close(newTrie);
+ return;
+ }
+
+ /* test linear Latin-1 range from utrie_getData() */
+ if(latin1Linear) {
+ uint32_t *data;
+ int32_t dataLength;
+
+ data=utrie_getData(newTrie, &dataLength);
+ start=0;
+ for(i=0; i<countCheckRanges && start<=0xff; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ while(start<limit && start<=0xff) {
+ if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
+ log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
+ testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
+ }
+ ++start;
+ }
+ }
+ }
+
+ utrie_close(newTrie);
+
+ errorCode=U_ZERO_ERROR;
+ if(!utrie_unserialize(&trie, storageHolder.storage, length, &errorCode)) {
+ log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
+ return;
+ }
+ if(getFoldingOffset!=NULL) {
+ trie.getFoldingOffset=getFoldingOffset;
+ }
+
+ if(dataIs32!=(trie.data32!=NULL)) {
+ log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
+ }
+ if(latin1Linear!=trie.isLatin1Linear) {
+ log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
+ }
+
+ /* verify that all these values are in the unserialized Trie */
+ start=0;
+ for(i=0; i<countCheckRanges; ++i) {
+ limit=checkRanges[i].limit;
+ value=checkRanges[i].value;
+
+ if(start==0xd800) {
+ /* skip surrogates */
+ start=limit;
+ continue;
+ }
+
+ while(start<limit) {
+ if(start<=0xffff) {
+ if(dataIs32) {
+ value2=UTRIE_GET32_FROM_BMP(&trie, start);
+ } else {
+ value2=UTRIE_GET16_FROM_BMP(&trie, start);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ if(!UTF_IS_LEAD(start)) {
+ if(dataIs32) {
+ value2=UTRIE_GET32_FROM_LEAD(&trie, start);
+ } else {
+ value2=UTRIE_GET16_FROM_LEAD(&trie, start);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ }
+ }
+ if(dataIs32) {
+ UTRIE_GET32(&trie, start, value2);
+ } else {
+ UTRIE_GET16(&trie, start, value2);
+ }
+ if(value!=value2) {
+ log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
+ testName, start, value2, value);
+ }
+ ++start;
+ }
+ }
+
+ /* enumerate and verify all ranges */
+ enumRanges=checkRanges+1;
+ utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
+
+ /* test linear Latin-1 range */
+ if(trie.isLatin1Linear) {
+ if(trie.data32!=NULL) {
+ const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
+
+ for(start=0; start<0x100; ++start) {
+ if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
+ log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
+ testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
+ }
+ }
+ } else {
+ const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
+
+ for(start=0; start<0x100; ++start) {
+ if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
+ log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
+ testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
+ }
+ }
+ }
+ }
+
+ testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
+}
+
+static void
+testTrieRanges2(const char *testName,
+ const SetRange setRanges[], int32_t countSetRanges,
+ const CheckRange checkRanges[], int32_t countCheckRanges,
+ UBool dataIs32) {
+ char name[40];
+
+ testTrieRanges(testName,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ dataIs32, FALSE);
+ testTrieRangesWithMalloc(testName,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ dataIs32, FALSE);
+
+ uprv_strcpy(name, testName);
+ uprv_strcat(name, "-latin1Linear");
+ testTrieRanges(name,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ dataIs32, TRUE);
+ testTrieRangesWithMalloc(name,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ dataIs32, TRUE);
+}
+
+static void
+testTrieRanges4(const char *testName,
+ const SetRange setRanges[], int32_t countSetRanges,
+ const CheckRange checkRanges[], int32_t countCheckRanges) {
+ char name[40];
+
+ uprv_strcpy(name, testName);
+ uprv_strcat(name, ".32");
+ testTrieRanges2(name,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ TRUE);
+
+ uprv_strcpy(name, testName);
+ uprv_strcat(name, ".16");
+ testTrieRanges2(name,
+ setRanges, countSetRanges,
+ checkRanges, countCheckRanges,
+ FALSE);
+}
+
+/* test data ----------------------------------------------------------------*/
+
+/* set consecutive ranges, even with value 0 */
+static const SetRange
+setRanges1[]={
+ {0, 0x20, 0, FALSE},
+ {0x20, 0xa7, 0x1234, FALSE},
+ {0xa7, 0x3400, 0, FALSE},
+ {0x3400, 0x9fa6, 0x6162, FALSE},
+ {0x9fa6, 0xda9e, 0x3132, FALSE},
+ {0xdada, 0xeeee, 0x87ff, FALSE}, /* try to disrupt _testFoldingOffset16() */
+ {0xeeee, 0x11111, 1, FALSE},
+ {0x11111, 0x44444, 0x6162, FALSE},
+ {0x44444, 0x60003, 0, FALSE},
+ {0xf0003, 0xf0004, 0xf, FALSE},
+ {0xf0004, 0xf0006, 0x10, FALSE},
+ {0xf0006, 0xf0007, 0x11, FALSE},
+ {0xf0007, 0xf0020, 0x12, FALSE},
+ {0xf0020, 0x110000, 0, FALSE}
+};
+
+static const CheckRange
+checkRanges1[]={
+ {0, 0}, /* dummy start range to make _testEnumRange() simpler */
+ {0x20, 0},
+ {0xa7, 0x1234},
+ {0x3400, 0},
+ {0x9fa6, 0x6162},
+ {0xda9e, 0x3132},
+ {0xdada, 0},
+ {0xeeee, 0x87ff},
+ {0x11111,1},
+ {0x44444,0x6162},
+ {0xf0003,0},
+ {0xf0004,0xf},
+ {0xf0006,0x10},
+ {0xf0007,0x11},
+ {0xf0020,0x12},
+ {0x110000, 0}
+};
+
+/* set some interesting overlapping ranges */
+static const SetRange
+setRanges2[]={
+ {0x21, 0x7f, 0x5555, TRUE},
+ {0x2f800,0x2fedc, 0x7a, TRUE},
+ {0x72, 0xdd, 3, TRUE},
+ {0xdd, 0xde, 4, FALSE},
+ {0x2f987,0x2fa98, 5, TRUE},
+ {0x2f777,0x2f833, 0, TRUE},
+ {0x2f900,0x2ffee, 1, FALSE},
+ {0x2ffee,0x2ffef, 2, TRUE}
+};
+
+static const CheckRange
+checkRanges2[]={
+ {0, 0}, /* dummy start range to make _testEnumRange() simpler */
+ {0x21, 0},
+ {0x72, 0x5555},
+ {0xdd, 3},
+ {0xde, 4},
+ {0x2f833,0},
+ {0x2f987,0x7a},
+ {0x2fa98,5},
+ {0x2fedc,0x7a},
+ {0x2ffee,1},
+ {0x2ffef,2},
+ {0x110000, 0}
+};
+
+/* use a non-zero initial value */
+static const SetRange
+setRanges3[]={
+ {0x31, 0xa4, 1, FALSE},
+ {0x3400, 0x6789, 2, FALSE},
+ {0x30000,0x34567,9, TRUE},
+ {0x45678,0x56789,3, TRUE}
+};
+
+static const CheckRange
+checkRanges3[]={
+ {0, 9}, /* dummy start range, also carries the initial value */
+ {0x31, 9},
+ {0xa4, 1},
+ {0x3400, 9},
+ {0x6789, 2},
+ {0x45678,9},
+ {0x56789,3},
+ {0x110000,9}
+};
+
+static void
+TrieTest(void) {
+ testTrieRanges4("set1",
+ setRanges1, ARRAY_LENGTH(setRanges1),
+ checkRanges1, ARRAY_LENGTH(checkRanges1));
+ testTrieRanges4("set2-overlap",
+ setRanges2, ARRAY_LENGTH(setRanges2),
+ checkRanges2, ARRAY_LENGTH(checkRanges2));
+ testTrieRanges4("set3-initial-9",
+ setRanges3, ARRAY_LENGTH(setRanges3),
+ checkRanges3, ARRAY_LENGTH(checkRanges3));
+}
+
+/* test utrie_unserializeDummy() -------------------------------------------- */
+
+static int32_t U_CALLCONV
+dummyGetFoldingOffset(uint32_t data) {
+ return -1; /* never get non-initialValue data for supplementary code points */
+}
+
+static void
+dummyTest(UBool make16BitTrie) {
+ int32_t mem[UTRIE_DUMMY_SIZE/4];
+
+ UTrie trie;
+ UErrorCode errorCode;
+ UChar32 c;
+
+ uint32_t value, initialValue, leadUnitValue;
+
+ if(make16BitTrie) {
+ initialValue=0x313;
+ leadUnitValue=0xaffe;
+ } else {
+ initialValue=0x01234567;
+ leadUnitValue=0x89abcdef;
+ }
+
+ errorCode=U_ZERO_ERROR;
+ utrie_unserializeDummy(&trie, mem, sizeof(mem), initialValue, leadUnitValue, make16BitTrie, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("utrie_unserializeDummy(make16BitTrie=%d) failed - %s\n", make16BitTrie, u_errorName(errorCode));
+ return;
+ }
+ trie.getFoldingOffset=dummyGetFoldingOffset;
+
+ /* test that all code points have initialValue */
+ for(c=0; c<=0x10ffff; ++c) {
+ if(make16BitTrie) {
+ UTRIE_GET16(&trie, c, value);
+ } else {
+ UTRIE_GET32(&trie, c, value);
+ }
+ if(value!=initialValue) {
+ log_err("UTRIE_GET%s(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
+ make16BitTrie ? "16" : "32", (long)c, (long)value, (long)initialValue);
+ }
+ }
+
+ /* test that the lead surrogate code units have leadUnitValue */
+ for(c=0xd800; c<=0xdbff; ++c) {
+ if(make16BitTrie) {
+ value=UTRIE_GET16_FROM_LEAD(&trie, c);
+ } else {
+ value=UTRIE_GET32_FROM_LEAD(&trie, c);
+ }
+ if(value!=leadUnitValue) {
+ log_err("UTRIE_GET%s_FROM_LEAD(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
+ make16BitTrie ? "16" : "32", (long)c, (long)value, (long)leadUnitValue);
+ }
+ }
+}
+
+static void
+DummyTrieTest(void) {
+ dummyTest(TRUE);
+ dummyTest(FALSE);
+}
+
+void
+addTrieTest(TestNode** root);
+
+void
+addTrieTest(TestNode** root) {
+ addTest(root, &TrieTest, "tsutil/trietest/TrieTest");
+ addTest(root, &DummyTrieTest, "tsutil/trietest/DummyTrieTest");
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c
new file mode 100644
index 00000000000..9bc18d329ea
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/ucsdetst.c
@@ -0,0 +1,355 @@
+/*
+ ****************************************************************************
+ * Copyright (c) 2005-2006, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ ****************************************************************************
+ */
+
+#include "unicode/utypes.h"
+
+#include "unicode/ucsdet.h"
+#include "unicode/ucnv.h"
+#include "unicode/ustring.h"
+
+#include "cintltst.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+
+#define NEW_ARRAY(type,count) (type *) malloc((count) * sizeof(type))
+#define DELETE_ARRAY(array) free(array)
+
+static void TestConstruction(void);
+static void TestUTF8(void);
+static void TestUTF16(void);
+static void TestC1Bytes(void);
+static void TestInputFilter(void);
+static void TestChaining(void);
+
+void addUCsdetTest(TestNode** root);
+
+void addUCsdetTest(TestNode** root)
+{
+ addTest(root, &TestConstruction, "ucsdetst/TestConstruction");
+ addTest(root, &TestUTF8, "ucsdetst/TestUTF8");
+ addTest(root, &TestUTF16, "ucsdetst/TestUTF16");
+ addTest(root, &TestC1Bytes, "ucsdetst/TestC1Bytes");
+ addTest(root, &TestInputFilter, "ucsdetst/TestInputFilter");
+ addTest(root, &TestChaining, "ucsdetst/TestErrorChaining");
+}
+
+static int32_t preflight(const UChar *src, int32_t length, UConverter *cnv)
+{
+ UErrorCode status;
+ char buffer[1024];
+ char *dest, *destLimit = buffer + sizeof(buffer);
+ const UChar *srcLimit = src + length;
+ int32_t result = 0;
+
+ do {
+ dest = buffer;
+ status = U_ZERO_ERROR;
+ ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &status);
+ result += (int32_t) (dest - buffer);
+ } while (status == U_BUFFER_OVERFLOW_ERROR);
+
+ return result;
+}
+
+static char *extractBytes(const UChar *src, int32_t length, const char *codepage, int32_t *byteLength)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv = ucnv_open(codepage, &status);
+ int32_t byteCount = preflight(src, length, cnv);
+ const UChar *srcLimit = src + length;
+ char *bytes = NEW_ARRAY(char, byteCount + 1);
+ char *dest = bytes, *destLimit = bytes + byteCount + 1;
+
+ ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, &status);
+ ucnv_close(cnv);
+
+ *byteLength = byteCount;
+ return bytes;
+}
+
+static void freeBytes(char *bytes)
+{
+ DELETE_ARRAY(bytes);
+}
+
+static void TestConstruction(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UCharsetDetector *csd = ucsdet_open(&status);
+ UEnumeration *e = ucsdet_getAllDetectableCharsets(csd, &status);
+ const char *name;
+ int32_t count = uenum_count(e, &status);
+ int32_t i, length;
+
+ for(i = 0; i < count; i += 1) {
+ name = uenum_next(e, &length, &status);
+
+ if(name == NULL || length <= 0) {
+ log_err("ucsdet_getAllDetectableCharsets() returned a null or empty name!\n");
+ }
+ }
+ /* one past the list of all names must return NULL */
+ name = uenum_next(e, &length, &status);
+ if(name != NULL || length != 0 || U_FAILURE(status)) {
+ log_err("ucsdet_getAllDetectableCharsets(past the list) returned a non-null name!\n");
+ }
+
+ uenum_close(e);
+ ucsdet_close(csd);
+}
+
+static void TestUTF8(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ static const char ss[] = "This is a string with some non-ascii characters that will "
+ "be converted to UTF-8, then shoved through the detection process. "
+ "\\u0391\\u0392\\u0393\\u0394\\u0395"
+ "Sure would be nice if our source could contain Unicode directly!";
+ int32_t byteLength = 0, sLength = 0, dLength = 0;
+ UChar s[sizeof(ss)];
+ char *bytes;
+ UCharsetDetector *csd = ucsdet_open(&status);
+ const UCharsetMatch *match;
+ UChar detected[sizeof(ss)];
+
+ sLength = u_unescape(ss, s, sizeof(ss));
+ bytes = extractBytes(s, sLength, "UTF-8", &byteLength);
+
+ ucsdet_setText(csd, bytes, byteLength, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("Detection failure for UTF-8: got no matches.\n");
+ goto bail;
+ }
+
+ dLength = ucsdet_getUChars(match, detected, sLength, &status);
+
+ if (u_strCompare(detected, dLength, s, sLength, FALSE) != 0) {
+ log_err("Round-trip test failed!\n");
+ }
+
+ ucsdet_setDeclaredEncoding(csd, "UTF-8", 5, &status); /* for coverage */
+
+bail:
+ freeBytes(bytes);
+ ucsdet_close(csd);
+}
+
+static void TestUTF16(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ /* Notice the BOM on the start of this string */
+ static const UChar chars[] = {
+ 0xFEFF, 0x0623, 0x0648, 0x0631, 0x0648, 0x0628, 0x0627, 0x002C,
+ 0x0020, 0x0628, 0x0631, 0x0645, 0x062c, 0x064a, 0x0627, 0x062a,
+ 0x0020, 0x0627, 0x0644, 0x062d, 0x0627, 0x0633, 0x0648, 0x0628,
+ 0x0020, 0x002b, 0x0020, 0x0627, 0x0646, 0x062a, 0x0631, 0x0646,
+ 0x064a, 0x062a, 0x0000};
+ int32_t beLength = 0, leLength = 0, cLength = ARRAY_SIZE(chars);
+ char *beBytes = extractBytes(chars, cLength, "UTF-16BE", &beLength);
+ char *leBytes = extractBytes(chars, cLength, "UTF-16LE", &leLength);
+ UCharsetDetector *csd = ucsdet_open(&status);
+ const UCharsetMatch *match;
+ const char *name;
+ int32_t conf;
+
+ ucsdet_setText(csd, beBytes, beLength, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("Encoding detection failure for UTF-16BE: got no matches.\n");
+ goto try_le;
+ }
+
+ name = ucsdet_getName(match, &status);
+ conf = ucsdet_getConfidence(match, &status);
+
+ if (strcmp(name, "UTF-16BE") != 0) {
+ log_err("Encoding detection failure for UTF-16BE: got %s\n", name);
+ }
+
+ if (conf != 100) {
+ log_err("Did not get 100%% confidence for UTF-16BE: got %d\n", conf);
+ }
+
+try_le:
+ ucsdet_setText(csd, leBytes, leLength, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("Encoding detection failure for UTF-16LE: got no matches.\n");
+ goto bail;
+ }
+
+ name = ucsdet_getName(match, &status);
+ conf = ucsdet_getConfidence(match, &status);
+
+
+ if (strcmp(name, "UTF-16LE") != 0) {
+ log_err("Enconding detection failure for UTF-16LE: got %s\n", name);
+ }
+
+ if (conf != 100) {
+ log_err("Did not get 100%% confidence for UTF-16LE: got %d\n", conf);
+ }
+
+bail:
+ freeBytes(leBytes);
+ freeBytes(beBytes);
+ ucsdet_close(csd);
+}
+
+static void TestC1Bytes(void)
+{
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode status = U_ZERO_ERROR;
+ static const char ssISO[] = "This is a small sample of some English text. Just enough to be sure that it detects correctly.";
+ static const char ssWindows[] = "This is another small sample of some English text. Just enough to be sure that it detects correctly. It also includes some \\u201CC1\\u201D bytes.";
+ int32_t sISOLength = 0, sWindowsLength = 0;
+ UChar sISO[sizeof(ssISO)];
+ UChar sWindows[sizeof(ssWindows)];
+ int32_t lISO = 0, lWindows = 0;
+ char *bISO;
+ char *bWindows;
+ UCharsetDetector *csd = ucsdet_open(&status);
+ const UCharsetMatch *match;
+ const char *name;
+
+ sISOLength = u_unescape(ssISO, sISO, sizeof(ssISO));
+ sWindowsLength = u_unescape(ssWindows, sWindows, sizeof(ssWindows));
+ bISO = extractBytes(sISO, sISOLength, "ISO-8859-1", &lISO);
+ bWindows = extractBytes(sWindows, sWindowsLength, "windows-1252", &lWindows);
+
+ ucsdet_setText(csd, bWindows, lWindows, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("English test with C1 bytes got no matches.\n");
+ goto bail;
+ }
+
+ name = ucsdet_getName(match, &status);
+
+ if (strcmp(name, "windows-1252") != 0) {
+ log_err("English text with C1 bytes does not detect as windows-1252, but as %s\n", name);
+ }
+
+ ucsdet_setText(csd, bISO, lISO, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("English text without C1 bytes got no matches.\n");
+ goto bail;
+ }
+
+ name = ucsdet_getName(match, &status);
+
+ if (strcmp(name, "ISO-8859-1") != 0) {
+ log_err("English text without C1 bytes does not detect as ISO-8859-1, but as %s\n", name);
+ }
+
+bail:
+ freeBytes(bWindows);
+ freeBytes(bISO);
+
+ ucsdet_close(csd);
+#endif
+}
+
+static void TestInputFilter(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ static const char ss[] = "<a> <lot> <of> <English> <inside> <the> <markup> Un tr\\u00E8s petit peu de Fran\\u00E7ais. <to> <confuse> <the> <detector>";
+ int32_t sLength = 0;
+ UChar s[sizeof(ss)];
+ int32_t byteLength = 0;
+ char *bytes;
+ UCharsetDetector *csd = ucsdet_open(&status);
+ const UCharsetMatch *match;
+ const char *lang, *name;
+
+ sLength = u_unescape(ss, s, sizeof(ss));
+ bytes = extractBytes(s, sLength, "ISO-8859-1", &byteLength);
+
+ ucsdet_enableInputFilter(csd, TRUE);
+
+ if (!ucsdet_isInputFilterEnabled(csd)) {
+ log_err("ucsdet_enableInputFilter(csd, TRUE) did not enable input filter!\n");
+ }
+
+
+ ucsdet_setText(csd, bytes, byteLength, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("Turning on the input filter resulted in no matches.\n");
+ goto turn_off;
+ }
+
+ name = ucsdet_getName(match, &status);
+
+ if (name == NULL || strcmp(name, "ISO-8859-1") != 0) {
+ log_err("Turning on the input filter resulted in %s rather than ISO-8859-1\n", name);
+ } else {
+ lang = ucsdet_getLanguage(match, &status);
+
+ if (lang == NULL || strcmp(lang, "fr") != 0) {
+ log_err("Input filter did not strip markup!\n");
+ }
+ }
+
+turn_off:
+ ucsdet_enableInputFilter(csd, FALSE);
+ ucsdet_setText(csd, bytes, byteLength, &status);
+ match = ucsdet_detect(csd, &status);
+
+ if (match == NULL) {
+ log_err("Turning off the input filter resulted in no matches.\n");
+ goto bail;
+ }
+
+ name = ucsdet_getName(match, &status);
+
+ if (name == NULL || strcmp(name, "ISO-8859-1") != 0) {
+ log_err("Turning off the input filter resulted in %s rather than ISO-8859-1\n", name);
+ } else {
+ lang = ucsdet_getLanguage(match, &status);
+
+ if (lang == NULL || strcmp(lang, "en") != 0) {
+ log_err("Unfiltered input did not detect as English!\n");
+ }
+ }
+
+bail:
+ freeBytes(bytes);
+ ucsdet_close(csd);
+}
+
+static void TestChaining(void) {
+ UErrorCode status = U_USELESS_COLLATOR_ERROR;
+
+ ucsdet_open(&status);
+ ucsdet_setText(NULL, NULL, 0, &status);
+ ucsdet_getName(NULL, &status);
+ ucsdet_getConfidence(NULL, &status);
+ ucsdet_getLanguage(NULL, &status);
+ ucsdet_detect(NULL, &status);
+ ucsdet_setDeclaredEncoding(NULL, NULL, 0, &status);
+ ucsdet_detectAll(NULL, NULL, &status);
+ ucsdet_getUChars(NULL, NULL, 0, &status);
+ ucsdet_getUChars(NULL, NULL, 0, &status);
+ ucsdet_close(NULL);
+
+ /* All of this code should have done nothing. */
+ if (status != U_USELESS_COLLATOR_ERROR) {
+ log_err("Status got changed to %s\n", u_errorName(status));
+ }
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c
new file mode 100644
index 00000000000..73b8f089ca3
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/udatatst.c
@@ -0,0 +1,1761 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1998-2007, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File test.c
+*
+* Modification History:
+*
+* Date Name Description
+* 02/22/2000 Madhu Creation
+******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "unicode/udata.h"
+#include "unicode/uchar.h"
+#include "unicode/ucnv.h"
+#include "unicode/ures.h"
+#include "unicode/ustring.h"
+#include "unicode/uclean.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "filestrm.h"
+#include "udatamem.h"
+#include "cintltst.h"
+#include "ubrkimpl.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef U_WINDOWS
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+/* includes for TestSwapData() */
+#include "udataswp.h"
+
+/* swapping implementations in common */
+#include "uresdata.h"
+#include "ucnv_io.h"
+#include "uprops.h"
+#include "ucase.h"
+#include "ucol_swp.h"
+#include "ucnv_bld.h"
+#include "unormimp.h"
+#include "sprpimpl.h"
+#include "propname.h"
+#include "rbbidata.h"
+
+/* other definitions and prototypes */
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+static void TestUDataOpen(void);
+static void TestUDataOpenChoiceDemo1(void);
+static void TestUDataOpenChoiceDemo2(void);
+static void TestUDataGetInfo(void);
+static void TestUDataGetMemory(void);
+static void TestUDataSetAppData(void);
+static void TestErrorConditions(void);
+static void TestAppData(void);
+static void TestICUDataName(void);
+static void TestSwapData(void);
+static void PointerTableOfContents(void);
+static void SetBadCommonData(void);
+static void TestUDataFileAccess(void);
+
+
+void addUDataTest(TestNode** root);
+
+void
+addUDataTest(TestNode** root)
+{
+ addTest(root, &TestUDataOpen, "udatatst/TestUDataOpen" );
+ addTest(root, &TestUDataOpenChoiceDemo1, "udatatst/TestUDataOpenChoiceDemo1");
+ addTest(root, &TestUDataOpenChoiceDemo2, "udatatst/TestUDataOpenChoiceDemo2");
+ addTest(root, &TestUDataGetInfo, "udatatst/TestUDataGetInfo" );
+ addTest(root, &TestUDataGetMemory, "udatatst/TestUDataGetMemory" );
+ addTest(root, &TestUDataSetAppData, "udatatst/TestUDataSetAppData" );
+ addTest(root, &TestErrorConditions, "udatatst/TestErrorConditions");
+ addTest(root, &TestAppData, "udatatst/TestAppData" );
+ addTest(root, &TestICUDataName, "udatatst/TestICUDataName" );
+ addTest(root, &TestSwapData, "udatatst/TestSwapData" );
+ addTest(root, &PointerTableOfContents, "udatatst/PointerTableOfContents" );
+ addTest(root, &SetBadCommonData, "udatatst/SetBadCommonData" );
+ addTest(root, &TestUDataFileAccess, "udatatst/TestUDataFileAccess" );
+}
+
+#if 0
+static void lots_of_mallocs()
+{
+ int q;
+ for(q=1;q<100;q++)
+ {
+ free(malloc(q));
+ malloc(q*2);
+ }
+
+}
+#endif
+
+static void TestUDataOpen(){
+ UDataMemory *result;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* memMap[][2]={
+ {"root", "res"},
+ {"pnames", "icu"},
+ {"cnvalias", "icu"},
+ {"unames", "icu"},
+ {"ibm-37_P100-1995", "cnv"}
+ };
+ const char* name = "test";
+ const char* type = "icu";
+ const char dirSepString[] = {U_FILE_SEP_CHAR, 0};
+ const char pathSepString[] = {U_PATH_SEP_CHAR, 0};
+
+
+ char* path=(char*)malloc(sizeof(char) * (strlen(ctest_dataOutDir())
+ + strlen(U_ICUDATA_NAME)
+ + strlen("/build")+1 ) );
+
+ char *icuDataFilePath = 0;
+ struct stat stat_buf;
+
+ const char* testPath=loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ /* lots_of_mallocs(); */
+
+ strcat(strcpy(path, ctest_dataOutDir()), U_ICUDATA_NAME);
+
+ log_verbose("Testing udata_open()\n");
+ result=udata_open(testPath, type, name, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", testPath, name, type, myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_open worked\n");
+ udata_close(result);
+ }
+
+ /* If the ICU system common data file is present in this confiugration,
+ * verify that udata_open can explicitly fetch items from it.
+ * If packaging mode == dll, the file may not exist. So, if the file is
+ * missing, skip this test without error.
+ */
+ icuDataFilePath = (char *)malloc(strlen(path) + 10);
+ strcpy(icuDataFilePath, path);
+ strcat(icuDataFilePath, ".dat");
+ /* lots_of_mallocs(); */
+ if (stat(icuDataFilePath, &stat_buf) == 0)
+ {
+ int i;
+ log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
+ for(i=0; i<sizeof(memMap)/sizeof(memMap[0]); i++){
+ /* lots_of_mallocs(); */
+ status=U_ZERO_ERROR;
+ result=udata_open(path, memMap[i][1], memMap[i][0], &status);
+ if(U_FAILURE(status)) {
+ log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", path, memMap[i][0], memMap[i][1], myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", path, memMap[i][0], memMap[i][1]);
+ udata_close(result);
+ }
+ }
+ }
+ else
+ {
+ /* lots_of_mallocs(); */
+ log_verbose("Skipping tests of udata_open() on %s. File not present in this configuration.\n",
+ icuDataFilePath);
+ }
+ free(icuDataFilePath);
+ icuDataFilePath = NULL;
+ /* lots_of_mallocs(); */
+
+ /* If the ICU individual files used to build the ICU system common data are
+ * present in this configuration,
+ * verify that udata_open can explicitly open them.
+ * These data files are present in the ICU data/build directory after a build
+ * completes. Tests are most commonly run with the data directory pointing
+ * back into this directory structure, but this is not required. Soooo, if
+ * the files are missing, skip this test without error.
+ */
+ /* lots_of_mallocs(); */
+ icuDataFilePath = (char *)malloc(strlen(ctest_dataOutDir()) + 50);
+ strcpy(icuDataFilePath, ctest_dataOutDir());
+ strcat(icuDataFilePath, "build");
+ strcat(icuDataFilePath, dirSepString);
+ strcat(icuDataFilePath, U_ICUDATA_NAME);
+ strcat(icuDataFilePath, "_");
+ strcat(icuDataFilePath, "cnvalias.icu");
+
+ /* lots_of_mallocs(); */
+ if (stat(icuDataFilePath, &stat_buf) == 0)
+ {
+ int i;
+ log_verbose("%s exists, so..\n", icuDataFilePath);
+ strcpy(icuDataFilePath, ctest_dataOutDir());
+ strcat(icuDataFilePath, "build");
+ strcat(icuDataFilePath, dirSepString);
+ strcat(icuDataFilePath, U_ICUDATA_NAME);
+ log_verbose("Testing udata_open() on %s\n", icuDataFilePath);
+ for(i=0; i<sizeof(memMap)/sizeof(memMap[0]); i++){
+ status=U_ZERO_ERROR;
+ result=udata_open(icuDataFilePath, memMap[i][1], memMap[i][0], &status);
+ if(U_FAILURE(status)) {
+ log_data_err("FAIL: udata_open() failed for path = %s, name=%s, type=%s, \n errorcode=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1], myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_open worked for path = %s, name=%s, type=%s\n", icuDataFilePath, memMap[i][0], memMap[i][1]);
+ udata_close(result);
+ }
+ }
+ }
+ else
+ {
+ log_verbose("Skipping tests of udata_open() on %s. File not present in this configuration.\n",
+ icuDataFilePath);
+ }
+
+ free(icuDataFilePath);
+ icuDataFilePath = NULL;
+
+ /*
+ * Test fallback file names for open of separate data files.
+ * With these params to udata_open:
+ * path = wherever/testdata
+ * type = typ
+ * name = nam
+ * these files will be tried first:
+ * wherever/testudata_nam.typ
+ * testudata_nam.typ
+ * A test data file named testudata_nam.typ exists for the purpose of testing this.
+ */
+ log_verbose("Testing udata_open, with base_name.type style fallback to individual file.\n");
+
+ status = U_ZERO_ERROR;
+ result = udata_open( testPath, "typ", "nam", &status);
+ if (status != U_ZERO_ERROR) {
+ log_err("FAIL: udata_open( \"%s\", \"typ\", \"nam\") returned status %s\n", testPath, u_errorName(status));
+ }
+ udata_close(result);
+ free(icuDataFilePath);
+
+
+ /* This type of path is deprecated */
+ /*
+ * Another fallback test. Paths ending with a trailing directory separator
+ * take a slightly different code path, with the "base name" from the path
+ * being empty in the internal udata_open logic.
+ */
+
+/* log_verbose("Testing udata_open, with path containing a trailing directory separator.\n"); */
+/* icuDataFilePath = (char *)malloc(strlen(u_getDataDirectory()) + 50); */
+/* strcpy(icuDataFilePath, testPath); */
+/* status = U_ZERO_ERROR; */
+/* result = udata_open( icuDataFilePath, "cnv", "test1", &status); */
+/* if (status != U_ZERO_ERROR) { */
+/* log_err("FAIL: udata_open( \"%s\", \"cnv\", \"test1\") returned status %s\n", icuDataFilePath, u_errorName(status)); */
+/* } */
+/* udata_close(result); */
+/* free(icuDataFilePath); */
+
+
+ log_verbose("Testing udata_open() with a non existing binary file\n");
+ result=udata_open("testdata", "tst", "nonexist", &status);
+ if(status==U_FILE_ACCESS_ERROR){
+ log_verbose("Opening udata_open with non-existing file handled correctly.\n");
+ status=U_ZERO_ERROR;
+ } else {
+ log_err("calling udata_open with non-existing file [testdata | nonexist.tst] not handled correctly\n. Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status));
+ if(U_SUCCESS(status)) {
+ udata_close(result);
+ }
+ }
+
+ if(result != NULL){
+ log_err("calling udata_open with non-existing file didn't return a null value\n");
+ } else {
+ log_verbose("calling udat_open with non-existing file returned null as expected\n");
+ }
+
+ /*
+ * Try opening data with absurdly long path and name, to trigger buffer size
+ * overflow handling code.
+ */
+ {
+ char longTestPath[1024]; /* Implementation goes to heap at length of 128. */
+ char longName[1024];
+
+ /* Try a very long nonexistent directory path.
+ * udata_open should still succeed. Opening with the path will fail,
+ * then fall back to skipping the directory portion of the path.
+ */
+ log_verbose("Testing udata_open() with really long names\n");
+ longTestPath[0] = 0;
+ strcat(longTestPath, "bogus_directory_name");
+ while (strlen(longTestPath) < 500) {
+ strcat(longTestPath, dirSepString);
+ strcat(longTestPath, "bogus_directory_name");
+ }
+ strcat(longTestPath, pathSepString);
+ strcat(longTestPath, testPath);
+ result=udata_open(longTestPath, type, name, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
+ longTestPath, name, type, myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_open worked\n");
+ udata_close(result);
+ }
+
+ /* Try a very long name. Won't open, but shouldn't blow up.
+ */
+ longName[0] = 0;
+ while (strlen(longName) < 500) {
+ strcat(longName, name);
+ strcat(longName, "_");
+ }
+ strcat(longName, dirSepString);
+ strcat(longName, name);
+
+ result=udata_open(longTestPath, type, longName, &status);
+ if (status != U_FILE_ACCESS_ERROR) {
+ log_err("FAIL: udata_open() failed for path = %s\n name=%s, type=%s, \n errorcode=%s\n",
+ longTestPath, longName, type, myErrorName(status));
+ }
+ udata_close(result);
+ }
+
+ free(path);
+}
+
+typedef struct {
+ uint16_t headerSize;
+ uint8_t magic1, magic2;
+ UDataInfo info;
+ char padding[8];
+ uint32_t count, reserved;
+ /*
+ const struct {
+ const char *const name;
+ const void *const data;
+ } toc[1];
+ */
+ int32_t fakeNameAndData[4];
+} ICU_COMMON_Data_Header;
+
+static const ICU_COMMON_Data_Header gEmptyHeader = {
+ 32, /* headerSize */
+ 0xda, /* magic1, (see struct MappedData in udata.c) */
+ 0x27, /* magic2 */
+ { /*UDataInfo */
+ sizeof(UDataInfo), /* size */
+ 0, /* reserved */
+
+#if U_IS_BIG_ENDIAN
+ 1,
+#else
+ 0,
+#endif
+
+ U_CHARSET_FAMILY,
+ sizeof(UChar),
+ 0, /* reserved */
+ { /* data format identifier */
+ 0x43, 0x6d, 0x6e, 0x44}, /* "CmnD" */
+ {1, 0, 0, 0}, /* format version major, minor, milli, micro */
+ {0, 0, 0, 0} /* dataVersion */
+ },
+ {0,0,0,0,0,0,0,0}, /* Padding[8] */
+ 0, /* count */
+ 0, /* Reserved */
+ { /* TOC structure */
+/* { */
+ 0 , 0 , 0, 0 /* name and data entries. Count says there are none, */
+ /* but put one in just in case. */
+/* } */
+ }
+};
+
+
+static void TestUDataSetAppData(){
+/* UDataMemory *dataItem;*/
+
+ UErrorCode status=U_ZERO_ERROR;
+
+ /*
+ * First we try some monkey business and try to do bad things.
+ */
+
+ status=U_ZERO_ERROR;
+ udata_setAppData("appData1", NULL, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", NULL, status) should have failed."
+ " It returned status of %s\n", u_errorName(status));
+ return;
+ }
+ /* The following call should fail.
+ If the following works with a bad UErrorCode, then later calls to appData1 should fail. */
+ udata_setAppData("appData1", &gEmptyHeader, &status);
+
+ /*
+ * Got testdata.dat into memory, now we try setAppData using the memory image.
+ */
+
+ status=U_ZERO_ERROR;
+ udata_setAppData("appData1", &gEmptyHeader, &status);
+ if (status != U_ZERO_ERROR) {
+ log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) "
+ " returned status of %s\n", u_errorName(status));
+ return;
+ }
+
+ udata_setAppData("appData2", &gEmptyHeader, &status);
+ if (status != U_ZERO_ERROR) {
+ log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) "
+ " returned status of %s\n", u_errorName(status));
+ return;
+ }
+
+ /* If we try to setAppData with the same name a second time, we should get a
+ * a using default warning.
+ */
+ udata_setAppData("appData2", &gEmptyHeader, &status);
+ if (status != U_USING_DEFAULT_WARNING) {
+ log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData2\", fileBuf, status) "
+ " returned status of %s, expected U_USING_DEFAULT_WARNING.\n", u_errorName(status));
+ }
+
+
+ /** It is no longer correct to use udata_setAppData to change the
+ package of a contained item.
+
+ dataItem = udata_open("appData1", "res", "te_IN", &status); **/
+}
+
+static char *safeGetICUDataDirectory() {
+ const char *dataDir = u_getDataDirectory(); /* Returned string vanashes with u_cleanup */
+ char *retStr = NULL;
+ if (dataDir != NULL) {
+ retStr = (char *)malloc(strlen(dataDir)+1);
+ strcpy(retStr, dataDir);
+ }
+ return retStr;
+}
+
+static void TestUDataFileAccess(){
+ UErrorCode status;
+ char *icuDataDir;
+ icuDataDir = safeGetICUDataDirectory(); /* save icu data dir, so we can put it back
+ * after doing u_cleanup(). */
+
+ /** UDATA_NO_FILES, ICU does not access the file system for data loading. */
+ status=U_ZERO_ERROR;
+ u_cleanup();
+ udata_setFileAccess(UDATA_NO_FILES,&status);
+ u_init(&status);
+ if(U_FAILURE(status) && *icuDataDir == 0){
+ log_data_err("udata_setFileAccess(UDATA_NO_FILES) failed with ICU_DATA=\"\" err=%s\n", u_errorName(status));
+ }
+
+ /** UDATA_ONLY_PACKAGES, ICU only loads data from packages, not from single files. */
+ status=U_ZERO_ERROR;
+ u_cleanup();
+ udata_setFileAccess(UDATA_ONLY_PACKAGES,&status);
+ u_init(&status);
+
+ /** UDATA_PACKAGES_FIRST, ICU loads data from packages first, and only from single files
+ if the data cannot be found in a package. */
+ status=U_ZERO_ERROR;
+ u_cleanup();
+ udata_setFileAccess(UDATA_PACKAGES_FIRST,&status);
+ u_init(&status);
+
+ /** UDATA_FILES_FIRST, ICU looks for data in single files first, then in packages. (default) */
+ status=U_ZERO_ERROR;
+ u_cleanup();
+ udata_setFileAccess(UDATA_FILES_FIRST,&status);
+ u_init(&status);
+
+ /** An alias for the default access mode. */
+ status=U_ZERO_ERROR;
+ u_cleanup();
+ udata_setFileAccess(UDATA_DEFAULT_ACCESS,&status);
+ u_setDataDirectory(icuDataDir);
+ u_init(&status);
+ if(U_FAILURE(status)){
+ log_err("%s\n", u_errorName(status));
+ }
+ free(icuDataDir);
+}
+
+
+static UBool U_CALLCONV
+isAcceptable1(void *context,
+ const char *type, const char *name,
+ const UDataInfo *pInfo) {
+
+ if( pInfo->size>=20 &&
+ pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily==U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0]==0x43 && /* dataFormat="CvAl" */
+ pInfo->dataFormat[1]==0x76 &&
+ pInfo->dataFormat[2]==0x41 &&
+ pInfo->dataFormat[3]==0x6c &&
+ pInfo->formatVersion[0]==3 )
+ {
+ log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable1()\n", name, type);
+ return TRUE;
+ } else {
+ log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable1():-\n"
+ "\tsize = %d\n"
+ "\tisBigEndian = %d\n"
+ "\tcharsetFamily = %d\n"
+ "\tformatVersion[0] = %d\n"
+ "\tdataVersion[0] = %d\n"
+ "\tdataFormat = %c%c%c%c\n",
+ name, type, pInfo->size, pInfo->isBigEndian, pInfo->charsetFamily, pInfo->formatVersion[0],
+ pInfo->dataVersion[0], pInfo->dataFormat[0], pInfo->dataFormat[1], pInfo->dataFormat[2],
+ pInfo->dataFormat[3]);
+ log_verbose("Call another verifing function to accept the data\n");
+ return FALSE;
+ }
+}
+
+static UBool U_CALLCONV
+isAcceptable2(void *context,
+ const char *type, const char *name,
+ const UDataInfo *pInfo){
+ UVersionInfo unicodeVersion;
+
+ u_getUnicodeVersion(unicodeVersion);
+
+ if( pInfo->size>=20 &&
+ pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily==U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0]==0x75 && /* dataFormat="unam" */
+ pInfo->dataFormat[1]==0x6e &&
+ pInfo->dataFormat[2]==0x61 &&
+ pInfo->dataFormat[3]==0x6d &&
+ pInfo->formatVersion[0]==1 &&
+ pInfo->dataVersion[0]==unicodeVersion[0] )
+ {
+ log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable2()\n", name, type);
+ return TRUE;
+ } else {
+ log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable2()\n", name, type);
+
+ return FALSE;
+ }
+
+
+}
+static UBool U_CALLCONV
+isAcceptable3(void *context,
+ const char *type, const char *name,
+ const UDataInfo *pInfo){
+
+ if( pInfo->size>=20 &&
+ pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily==U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0]==0x54 && /* dataFormat="test" */
+ pInfo->dataFormat[1]==0x65 &&
+ pInfo->dataFormat[2]==0x73 &&
+ pInfo->dataFormat[3]==0x74 &&
+ pInfo->formatVersion[0]==1 &&
+ pInfo->dataVersion[0]==1 ) {
+ log_verbose("The data from \"%s.%s\" IS acceptable using the verifing function isAcceptable3()\n", name, type);
+
+ return TRUE;
+ } else {
+ log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable3()\n", name, type);
+ return FALSE;
+ }
+
+
+}
+
+static void TestUDataOpenChoiceDemo1() {
+ UDataMemory *result;
+ UErrorCode status=U_ZERO_ERROR;
+
+ const char* name[]={
+ "cnvalias",
+ "unames",
+ "test",
+ "nam"
+ };
+ const char* type="icu";
+ const char* testPath="testdata";
+ const char* fullTestDataPath = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ result=udata_openChoice(NULL, "icu", name[0], isAcceptable1, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[0], type, myErrorName(status));
+ } else {
+ log_verbose("PASS: udata_openChoice worked\n");
+ udata_close(result);
+ }
+
+ status=U_ZERO_ERROR;
+ result=udata_openChoice(NULL, type, name[1], isAcceptable1, NULL, &status);
+ if(U_FAILURE(status)){
+ status=U_ZERO_ERROR;
+ result=udata_openChoice(NULL, type, name[1], isAcceptable2, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_openChoice() failed name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status));
+ }
+ }
+ else {
+ log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[1], type, myErrorName(status));
+ }
+
+ if(U_SUCCESS(status)){
+ udata_close(result);
+ }
+
+ status=U_ZERO_ERROR;
+ result=udata_openChoice(testPath, type, name[2], isAcceptable1, NULL, &status);
+ if(U_FAILURE(status)){
+ status=U_ZERO_ERROR;
+ result=udata_openChoice(testPath, type, name[2], isAcceptable3, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_openChoice() failed path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name[2], type, myErrorName(status));
+ }
+ }
+ else {
+ log_err("FAIL: udata_openChoice() unexpectedly passed. name=%s, type=%s, \n errorcode=%s\n", name[2], type, myErrorName(status));
+ }
+
+ if(U_SUCCESS(status)){
+ udata_close(result);
+ }
+
+ status=U_ZERO_ERROR;
+ type="typ";
+ result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status);
+ if(status != U_INVALID_FORMAT_ERROR){
+ log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
+ }
+
+ status=U_USELESS_COLLATOR_ERROR;
+ result=udata_openChoice(fullTestDataPath, type, name[3], isAcceptable1, NULL, &status);
+ if(status != U_USELESS_COLLATOR_ERROR){
+ log_err("FAIL: udata_openChoice() did not fail as expected. name=%s, type=%s, \n errorcode=%s\n", name[3], type, myErrorName(status));
+ }
+}
+
+static UBool U_CALLCONV
+isAcceptable(void *context,
+ const char *type, const char *name,
+ const UDataInfo *pInfo){
+ if( pInfo->size>=20 &&
+ pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily==U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0]==0x54 && /* dataFormat="test" */
+ pInfo->dataFormat[1]==0x65 &&
+ pInfo->dataFormat[2]==0x73 &&
+ pInfo->dataFormat[3]==0x74 &&
+ pInfo->formatVersion[0]==1 &&
+ pInfo->dataVersion[0]==1 &&
+ *((int*)context) == 2 ) {
+ log_verbose("The data from\"%s.%s\" IS acceptable using the verifing function isAcceptable()\n", name, type);
+
+ return TRUE;
+ } else {
+ log_verbose("The data from \"%s.%s\" IS NOT acceptable using the verifing function isAcceptable()\n", name, type);
+ return FALSE;
+ }
+}
+
+
+/* This test checks to see if the isAcceptable function is being called correctly. */
+
+static void TestUDataOpenChoiceDemo2() {
+ UDataMemory *result;
+ UErrorCode status=U_ZERO_ERROR;
+ int i;
+ int p=2;
+
+ const char* name="test";
+ const char* type="icu";
+ const char* path = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
+ if(U_FAILURE(status)){
+ log_err("failed to load data at p=%s t=%s n=%s, isAcceptable", path, type, name);
+ }
+ if(U_SUCCESS(status) ) {
+ udata_close(result);
+ }
+
+ p=0;
+ for(i=0;i<2; i++){
+ result=udata_openChoice(path, type, name, isAcceptable, &p, &status);
+ if(p<2) {
+ if(U_FAILURE(status) && status==U_INVALID_FORMAT_ERROR){
+ log_verbose("Loads the data but rejects it as expected %s\n", myErrorName(status));
+ status=U_ZERO_ERROR;
+ p++;
+ }
+ else {
+ log_err("FAIL: failed to either load the data or to reject the loaded data. ERROR=%s\n", myErrorName(status) );
+ }
+ }
+ else if(p == 2) {
+ if(U_FAILURE(status)) {
+ log_err("FAIL: failed to load the data and accept it. ERROR=%s\n", myErrorName(status) );
+ }
+ else {
+ log_verbose("Loads the data and accepts it for p==2 as expected\n");
+ udata_close(result);
+ }
+ }
+ }
+}
+
+
+static void TestUDataGetInfo() {
+
+ UDataMemory *result;
+ /* UDataInfo cf. udata.h */
+ static UDataInfo dataInfo={
+ 30, /*sizeof(UDataInfo),*/
+ 0,
+
+ U_IS_BIG_ENDIAN,
+ U_CHARSET_FAMILY,
+ sizeof(UChar),
+ 0,
+
+ {0x54, 0x65, 0x73, 0x74}, /* dataFormat="Test" */
+ {9, 0, 0, 0}, /* formatVersion */
+ {4, 0, 0, 0} /* dataVersion */
+ };
+ UErrorCode status=U_ZERO_ERROR;
+ const char* name="cnvalias";
+ const char* name2="test";
+ const char* type="icu";
+
+ const char* testPath=loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ log_verbose("Testing udata_getInfo() for cnvalias.icu\n");
+ result=udata_open(NULL, "icu", name, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_open() failed for path = NULL, name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status));
+ return;
+ }
+ udata_getInfo(result, &dataInfo);
+ if(dataInfo.size==20 && dataInfo.size!=30 &&
+ dataInfo.isBigEndian==U_IS_BIG_ENDIAN &&
+ dataInfo.charsetFamily==U_CHARSET_FAMILY &&
+ dataInfo.dataFormat[0]==0x43 && dataInfo.dataFormat[0]!=0x54 && /* dataFormat="CvAl" and not "Test". The values are set for cnvalias.dat*/
+ dataInfo.dataFormat[1]==0x76 && dataInfo.dataFormat[1]!=0x65 &&
+ dataInfo.dataFormat[2]==0x41 && dataInfo.dataFormat[2]!=0x73 &&
+ dataInfo.dataFormat[3]==0x6c && dataInfo.dataFormat[3]!=0x74 &&
+ dataInfo.formatVersion[0]!=9 && /*formatVersion is also set to the one for cnvalias*/
+ dataInfo.dataVersion[0]!=4 && /*dataVersion*/
+ dataInfo.dataVersion[1]!=0 ){
+ log_verbose("PASS: udata_getInfo() filled in the right values\n");
+ } else {
+ log_err("FAIL: udata_getInfo() filled in the wrong values\n");
+ }
+ udata_close(result);
+
+
+ log_verbose("Testing udata_getInfo() for test.icu\n");
+ result=udata_open(testPath, type, name2, &status);
+ if(U_FAILURE(status)) {
+ log_err("FAIL: udata_open() failed for path=%s name2=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
+ return;
+ }
+ udata_getInfo(result, &dataInfo);
+ if(dataInfo.size==20 &&
+ dataInfo.isBigEndian==U_IS_BIG_ENDIAN &&
+ dataInfo.charsetFamily==U_CHARSET_FAMILY &&
+ dataInfo.dataFormat[0]==0x54 && /* dataFormat="Test". The values are set for test.dat*/
+ dataInfo.dataFormat[1]==0x65 &&
+ dataInfo.dataFormat[2]==0x73 &&
+ dataInfo.dataFormat[3]==0x74 &&
+ dataInfo.formatVersion[0]==1 && /*formatVersion is also set to the one for test*/
+ dataInfo.dataVersion[0]==1 && /*dataVersion*/
+ dataInfo.dataVersion[1]==0 )
+ {
+ log_verbose("PASS: udata_getInfo() filled in the right values\n");
+ } else {
+ log_err("FAIL: udata_getInfo() filled in the wrong values\n");
+ }
+ udata_close(result);
+}
+
+static void TestUDataGetMemory() {
+
+ UDataMemory *result;
+ const int32_t *table=NULL;
+ uint16_t* intValue=0;
+ UErrorCode status=U_ZERO_ERROR;
+ const char* name="cnvalias";
+ const char* type;
+
+ const char* name2="test";
+
+ const char* testPath = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ type="icu";
+ log_verbose("Testing udata_getMemory() for \"cnvalias.icu\"\n");
+ result=udata_openChoice(NULL, type, name, isAcceptable1, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_openChoice() failed for name=%s, type=%s, \n errorcode=%s\n", name, type, myErrorName(status));
+ return;
+ }
+ table=(const int32_t *)udata_getMemory(result);
+
+ /* The alias table may list more converters than what's actually available now. [grhoten] */
+ if(ucnv_countAvailable() > table[1]) /*???*/
+ log_err("FAIL: udata_getMemory() failed ucnv_countAvailable returned = %d, expected = %d\n", ucnv_countAvailable(), table[1+2*(*table)]);
+
+ udata_close(result);
+
+ type="icu";
+ log_verbose("Testing udata_getMemory for \"test.icu\"()\n");
+ result=udata_openChoice(testPath, type, name2, isAcceptable3, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: udata_openChoice() failed for path=%s name=%s, type=%s, \n errorcode=%s\n", testPath, name2, type, myErrorName(status));
+ return;
+ }
+ intValue=(uint16_t *)udata_getMemory(result);
+ /*printf("%d ..... %s", *(intValue), intValue+1));*/
+ if( *intValue != 2000 || strcmp((char*)(intValue+1), "YEAR") != 0 )
+ log_err("FAIL: udata_getMemory() failed: intValue :- Expected:2000 Got:%d \n\tstringValue:- Expected:YEAR Got:%s\n", *intValue, (intValue+1));
+
+ udata_close(result);
+
+}
+
+static void TestErrorConditions(){
+
+ UDataMemory *result=NULL;
+ UErrorCode status=U_ZERO_ERROR;
+ uint16_t* intValue=0;
+ static UDataInfo dataInfo={
+ 30, /*sizeof(UDataInfo),*/
+ 0,
+
+ U_IS_BIG_ENDIAN,
+ U_CHARSET_FAMILY,
+ sizeof(UChar),
+ 0,
+
+ {0x54, 0x65, 0x73, 0x74}, /* dataFormat="Test" */
+ {9, 0, 0, 0}, /* formatVersion */
+ {4, 0, 0, 0} /* dataVersion */
+ };
+
+ const char* name = "test";
+ const char* type="icu";
+
+ const char *testPath = loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ /*Try udata_open with status != U_ZERO_ERROR*/
+ log_verbose("Testing udata_open() with status != U_ZERO_ERROR\n");
+ result=udata_open(testPath, type, name, &status);
+ if(result != NULL){
+ log_err("FAIL: udata_open() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode !=U_ZERO_ERROR\n", testPath, name, type);
+ udata_close(result);
+
+ } else {
+ log_verbose("PASS: udata_open with errorCode != U_ZERO_ERROR failed as expected\n");
+ }
+
+ /*Try udata_open with data name=NULL*/
+ log_verbose("Testing udata_open() with data name=NULL\n");
+ status=U_ZERO_ERROR;
+ result=udata_open(testPath, type, NULL, &status);
+ if(U_FAILURE(status)){
+ if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
+ log_err("FAIL: udata_open() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
+ }else{
+ log_verbose("PASS: udata_open with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
+ }
+ }else{
+ log_err("FAIL: udata_open() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type);
+ udata_close(result);
+ }
+
+
+ /*Try udata_openChoice with status != U_ZERO_ERROR*/
+ log_verbose("Testing udata_openChoice() with status != U_ZERO_ERROR\n");
+ status=U_ILLEGAL_ARGUMENT_ERROR;
+ result=udata_openChoice(testPath, type, name, isAcceptable3, NULL, &status);
+ if(result != NULL){
+ log_err("FAIL: udata_openChoice() is supposed to fail for path = %s, name=%s, type=%s, \n errorcode != U_ZERO_ERROR\n", testPath, name, type);
+ udata_close(result);
+ } else {
+ log_verbose("PASS: udata_openChoice() with errorCode != U_ZERO_ERROR failed as expected\n");
+ }
+
+ /*Try udata_open with data name=NULL*/
+ log_verbose("Testing udata_openChoice() with data name=NULL\n");
+ status=U_ZERO_ERROR;
+ result=udata_openChoice(testPath, type, NULL, isAcceptable3, NULL, &status);
+ if(U_FAILURE(status)){
+ if(status != U_ILLEGAL_ARGUMENT_ERROR || result != NULL){
+ log_err("FAIL: udata_openChoice() with name=NULL should return NULL and errocode U_ILLEGAL_ARGUMENT_ERROR, GOT: errorcode=%s\n", myErrorName(status));
+ }else{
+ log_verbose("PASS: udata_openChoice with name=NULL failed as expected and errorcode = %s as expected\n", myErrorName(status));
+ }
+ }else{
+ log_err("FAIL: udata_openChoice() with data name=NULL is supposed to fail for path = %s, name=NULL type=%s errorcode=U_ZERO_ERROR \n", testPath, type);
+ udata_close(result);
+ }
+
+ /*Try udata_getMemory with UDataMemory=NULL*/
+ log_verbose("Testing udata_getMemory with UDataMemory=NULL\n");
+ intValue=(uint16_t*)udata_getMemory(NULL);
+ if(intValue != NULL){
+ log_err("FAIL: udata_getMemory with UDataMemory = NULL is supposed to fail\n");
+ }
+
+ /*Try udata_getInfo with UDataMemory=NULL*/
+ status=U_ZERO_ERROR;
+ udata_getInfo(NULL, &dataInfo);
+ if(dataInfo.size != 0){
+ log_err("FAIL : udata_getInfo with UDataMemory = NULL us supposed to fail\n");
+ }
+
+ /*Try udata_openChoice with a non existing binary file*/
+ log_verbose("Testing udata_openChoice() with a non existing binary file\n");
+ result=udata_openChoice(testPath, "tst", "nonexist", isAcceptable3, NULL, &status);
+ if(status==U_FILE_ACCESS_ERROR){
+ log_verbose("Opening udata_openChoice with non-existing file handled correctly.\n");
+ status=U_ZERO_ERROR;
+ } else {
+ log_err("calling udata_open with non-existing file not handled correctly\n. Expected: U_FILE_ACCESS_ERROR, Got: %s\n", myErrorName(status));
+ if(U_SUCCESS(status)) {
+ udata_close(result);
+ }
+ }
+
+ if(result != NULL){
+ log_err("calling udata_open with non-existing file didn't return a null value\n");
+ } else {
+ log_verbose("calling udat_open with non-existing file returned null as expected\n");
+ }
+}
+
+/* Test whether apps and ICU can each have their own root.res */
+static void TestAppData()
+{
+ UResourceBundle *icu, *app;
+ UResourceBundle *tmp = NULL;
+ UResourceBundle *tmp2 = NULL;
+
+ const UChar *appString;
+ const UChar *icuString;
+
+ int32_t len;
+
+ UErrorCode status = U_ZERO_ERROR;
+ char testMsgBuf[256];
+
+ const char* testPath=loadTestData(&status);
+ if(U_FAILURE(status)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(status));
+ return;
+ }
+
+ icu = ures_open(NULL, "root", &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't open root ICU bundle- %s", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+ /* log_info("Open icu root: %s size_%d\n", u_errorName(status), ures_getSize(icu)); */
+ status = U_ZERO_ERROR;
+
+ app = ures_open(testPath, "root", &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't open app ICU bundle [%s]- %s", __FILE__, __LINE__, testPath, u_errorName(status));
+ return;
+ }
+ /* log_info("Open app: %s, size %d\n", u_errorName(status), ures_getSize(app)); */
+
+ tmp = ures_getByKey(icu, "Version", tmp, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't get Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ icuString = ures_getString(tmp, &len, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't get string from Version string from ICU root bundle- %s", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+ /* log_info("icuString=%p - %s\n", icuString, austrdup(icuString)); */
+
+
+ tmp2 = ures_getByKey(app, "Version", tmp2, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't get Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ appString = ures_getString(tmp2, &len, &status);
+ if(U_FAILURE(status))
+ {
+ log_err("%s:%d: Couldn't get string from Version string from App root bundle- %s", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ /* log_info("appString=%p - %s\n", appString, austrdup(appString)); */
+
+
+ if(!u_strcmp(icuString, appString))
+ {
+ log_err("%s:%d: Error! Expected ICU and App root version strings to be DIFFERENT but they are both %s and %s\n", __FILE__, __LINE__, austrdup(icuString),
+ austrdup(appString));
+ }
+ else
+ {
+ log_verbose("%s:%d: appstr=%s, icustr=%s\n", __FILE__,
+ __LINE__, u_austrcpy(testMsgBuf, appString), u_austrcpy(testMsgBuf, icuString));
+ }
+
+ ures_close(tmp);
+ ures_close(tmp2);
+ ures_close(icu);
+ ures_close(app);
+}
+
+static void TestICUDataName()
+{
+ UVersionInfo icuVersion;
+ char expectDataName[20];
+ unsigned int expectLen = 8;
+
+ char typeChar = '?';
+
+ /* Print out the version # we have .. */
+ log_verbose("utypes.h says U_ICUDATA_NAME = %s\n", U_ICUDATA_NAME);
+
+ /* Build up the version # we expect to get */
+ u_getVersion(icuVersion);
+
+ switch(U_CHARSET_FAMILY)
+ {
+ case U_ASCII_FAMILY:
+ switch(U_IS_BIG_ENDIAN)
+ {
+ case 1:
+ typeChar = 'b';
+ break;
+ case 0:
+ typeChar = 'l';
+ break;
+ default:
+ log_err("Expected 1 or 0 for U_IS_BIG_ENDIAN, got %d!\n", (int)U_IS_BIG_ENDIAN);
+ /* return; */
+ }
+ break;
+ case U_EBCDIC_FAMILY:
+ typeChar = 'e';
+ break;
+ }
+
+ sprintf(expectDataName, "%s%d%d%c",
+ "icudt",
+ (int)icuVersion[0],
+ (int)icuVersion[1],
+ typeChar);
+
+ log_verbose("Expected: %s\n", expectDataName);
+ if(uprv_strlen(expectDataName) != expectLen)
+ {
+ log_err("*Expected* length is wrong (test err?), should be %d is %d\n",
+ expectLen, uprv_strlen(expectDataName));
+ }
+
+ if(uprv_strlen(U_ICUDATA_NAME) != expectLen)
+ {
+ log_err("U_ICUDATA_NAME length should be %d is %d\n",
+ expectLen, uprv_strlen(U_ICUDATA_NAME));
+ }
+
+ if(uprv_strcmp(U_ICUDATA_NAME, expectDataName))
+ {
+ log_err("U_ICUDATA_NAME should be %s but is %s\n",
+ expectDataName, U_ICUDATA_NAME);
+ }
+
+ /* ICUDATA_NAME comes from the build system on *nix */
+#ifdef ICUDATA_NAME
+ if(uprv_strcmp(U_ICUDATA_NAME, ICUDATA_NAME))
+ {
+ log_err("ICUDATA_NAME and U_ICUDATA_NAME don't match: "
+ "ICUDATA_NAME=%s, U_ICUDATA_NAME=%s. Check configure.in, icudefs.mk.in, utypes.h...\n", ICUDATA_NAME, U_ICUDATA_NAME);
+ }
+ else
+ {
+ log_verbose("ICUDATA_NAME=%s (from icudefs.mk), U_ICUDATA_NAME=%s (from utypes.h)\n", ICUDATA_NAME, U_ICUDATA_NAME);
+ }
+#endif
+
+}
+
+/* test data swapping ------------------------------------------------------- */
+
+#ifdef OS400
+/* See comments in genccode.c on when this special implementation can be removed. */
+static const struct {
+ double bogus;
+ const char *bytes;
+} gOffsetTOCAppDataItem1={ 0.0, /* alignment bytes */
+ "\x00\x14" /* sizeof(UDataInfo) *//* MappedData { */
+ "\xda"
+ "\x27" /* } */
+ "\x00\x14" /* sizeof(UDataInfo) *//* UDataInfo { */
+ "\0\0"
+ "\1" /* U_IS_BIG_ENDIAN */
+ "\1" /* U_CHARSET_FAMILY */
+ "\2" /* U_SIZEOF_WHAR_T */
+ "\0"
+ "\x31\x31\x31\x31"
+ "\0\0\0\0"
+ "\0\0\0\0" /* } */
+};
+#else
+static const struct {
+ double bogus;
+ MappedData bytes1;
+ UDataInfo bytes2;
+ uint8_t bytes3;
+} gOffsetTOCAppDataItem1={
+ 0.0, /* alignment bytes */
+ { sizeof(UDataInfo), 0xda, 0x27 }, /* MappedData */
+
+ {sizeof(UDataInfo),
+ 0,
+
+ U_IS_BIG_ENDIAN,
+ U_CHARSET_FAMILY,
+ sizeof(UChar),
+ 0,
+
+ {0x31, 0x31, 0x31, 0x31}, /* dataFormat="1111" */
+ {0, 0, 0, 0}, /* formatVersion */
+ {0, 0, 0, 0}} /* dataVersion */
+};
+#endif
+
+static const UChar gOffsetTOCGarbage[] = { /* "I have been very naughty!" */
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6E, 0x61, 0x75, 0x67, 0x68, 0x74, 0x79, 0x21
+};
+
+/* Original source: icu/source/tools/genccode */
+static const struct {
+ uint16_t headerSize;
+ uint8_t magic1, magic2;
+ UDataInfo info;
+ char padding[8];
+ uint32_t count, reserved;
+ const struct {
+ const char *const name;
+ const void *const data;
+ } toc[3];
+} gOffsetTOCAppData_dat = {
+ 32, /* headerSize */
+ 0xda, /* magic1, (see struct MappedData in udata.c) */
+ 0x27, /* magic2 */
+ { /*UDataInfo */
+ sizeof(UDataInfo), /* size */
+ 0, /* reserved */
+ U_IS_BIG_ENDIAN,
+ U_CHARSET_FAMILY,
+ sizeof(UChar),
+ 0, /* reserved */
+ { /* data format identifier */
+ 0x54, 0x6f, 0x43, 0x50}, /* "ToCP" */
+ {1, 0, 0, 0}, /* format version major, minor, milli, micro */
+ {0, 0, 0, 0} /* dataVersion */
+ },
+ {0,0,0,0,0,0,0,0}, /* Padding[8] */
+ 3, /* count */
+ 0, /* Reserved */
+ { /* TOC structure */
+ { "OffsetTOCAppData/a/b", &gOffsetTOCAppDataItem1 },
+ { "OffsetTOCAppData/gOffsetTOCAppDataItem1", &gOffsetTOCAppDataItem1 },
+ { "OffsetTOCAppData/gOffsetTOCGarbage", &gOffsetTOCGarbage }
+ }
+};
+
+/* Unfortunately, trie dictionaries are in a C++ header */
+int32_t
+triedict_swap(const UDataSwapper *ds,
+ const void *inData, int32_t length, void *outData,
+ UErrorCode *pErrorCode);
+
+/* test cases for maximum data swapping code coverage */
+static const struct {
+ const char *name, *type;
+ UDataSwapFn *swapFn;
+} swapCases[]={
+ /* resource bundles */
+
+ /* resource bundle with many data types */
+ {"*testtypes", "res", ures_swap},
+ /* resource bundle with collation data */
+ {"ja", "res", ures_swap},
+ /* resource bundle with options-only collation data */
+ {"ru", "res", ures_swap},
+ {"el", "res", ures_swap},
+ /* ICU's root */
+ {"root", "res", ures_swap},
+ /* Test a 32-bit key table. This is large. */
+ {"*testtable32", "res", ures_swap},
+
+ /* ICU 2.6 resource bundle - data format 1.0, without indexes[] (little-endian ASCII) */
+ {"*icu26_testtypes", "res", ures_swap},
+ /* same for big-endian EBCDIC */
+ {"*icu26e_testtypes", "res", ures_swap},
+
+#if !UCONFIG_NO_COLLATION
+ /* standalone collation data files */
+ {"ucadata", "icu", ucol_swap},
+ {"invuca", "icu", ucol_swapInverseUCA},
+#endif
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ /* conversion table files */
+
+ /* SBCS conversion table file without extension */
+ {"ibm-913_P100-2000", "cnv", ucnv_swap},
+ /* EBCDIC_STATEFUL conversion table file with extension */
+ {"ibm-1390_P110-2003", "cnv", ucnv_swap},
+ /* DBCS extension-only conversion table file */
+ {"ibm-16684_P110-2003", "cnv", ucnv_swap},
+ /* EUC-TW (3-byte) conversion table file without extension */
+ {"ibm-964_P110-1999", "cnv", ucnv_swap},
+ /* GB 18030 (4-byte) conversion table file without extension */
+ {"gb18030", "cnv", ucnv_swap},
+ /* MBCS conversion table file with extension */
+ {"*test4x", "cnv", ucnv_swap},
+ /*
+ * MBCS conversion table file without extension,
+ * to test swapping and preflighting of UTF-8-friendly mbcsIndex[].
+ */
+ {"jisx-208", "cnv", ucnv_swap},
+#endif
+
+#if !UCONFIG_NO_CONVERSION
+ /* alias table */
+ {"cnvalias", "icu", ucnv_swapAliases},
+#endif
+
+#if !UCONFIG_NO_IDNA
+ {"uidna", "spp", usprep_swap},
+#endif
+
+#if !UCONFIG_NO_BREAK_ITERATION
+ {"char", "brk", ubrk_swap},
+ {"thaidict", "ctd", triedict_swap},
+#endif
+
+ /* the last item should not be #if'ed so that it can reliably omit the last comma */
+
+ /* Unicode properties */
+ {"pnames", "icu", upname_swap},
+#if 0
+ /*
+ * Starting with ICU4C 3.4, the core Unicode properties files
+ * (uprops.icu, ucase.icu, ubidi.icu, unorm.icu)
+ * are hardcoded in the common DLL and therefore not included
+ * in the data package any more.
+ * Their swapping code is moved from the common DLL to the icuswap tool so that
+ * we need not jump through hoops (like adding snapshots of these files
+ * to testdata) for code coverage in tests.
+ * See Jitterbug 4497.
+ */
+#if !UCONFIG_NO_NORMALIZATION
+ {"unorm", "icu", unorm_swap},
+#endif
+ {"uprops", "icu", uprops_swap},
+ {"ucase", "icu", ucase_swap},
+ {"ubidi", "icu", ubidi_swap},
+#endif
+ {"unames", "icu", uchar_swapNames}
+};
+
+/* Large enough for the largest swappable data item. */
+#define SWAP_BUFFER_SIZE 1800000
+
+static void U_CALLCONV
+printError(void *context, const char *fmt, va_list args) {
+ vlog_info("[swap] ", fmt, args);
+ log_err("\n"); /* Register error */
+}
+
+static void
+TestSwapCase(UDataMemory *pData, const char *name,
+ UDataSwapFn *swapFn,
+ uint8_t *buffer, uint8_t *buffer2) {
+ UDataSwapper *ds;
+ const void *inData, *inHeader;
+ int32_t length, dataLength, length2, headerLength;
+
+ UErrorCode errorCode;
+ UErrorCode badStatus;
+
+ UBool inEndian, oppositeEndian;
+ uint8_t inCharset, oppositeCharset;
+
+ /* First we check that swapFn handles failures as expected. */
+ errorCode = U_UNSUPPORTED_ERROR;
+ length = swapFn(NULL, NULL, 0, buffer, &errorCode);
+ if (length != 0 || errorCode != U_UNSUPPORTED_ERROR) {
+ log_err("%s() did not fail as expected - %s\n", name, u_errorName(errorCode));
+ }
+ errorCode = U_ZERO_ERROR;
+ length = swapFn(NULL, NULL, 0, buffer, &errorCode);
+ if (length != 0 || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("%s() did not fail as expected with bad arguments - %s\n", name, u_errorName(errorCode));
+ }
+
+
+ /* Continue with the rest of the tests. */
+ errorCode = U_ZERO_ERROR;
+ inData=udata_getMemory(pData);
+
+ /*
+ * get the data length if possible, to verify that swapping and preflighting
+ * handles the entire data
+ */
+ dataLength=udata_getLength(pData);
+
+ /*
+ * get the header and its length
+ * all of the swap implementation functions require the header to be included
+ */
+ inHeader=udata_getRawMemory(pData);
+ headerLength=(int32_t)((const char *)inData-(const char *)inHeader);
+
+ /* first swap to opposite endianness but same charset family */
+ errorCode=U_ZERO_ERROR;
+ ds=udata_openSwapperForInputData(inHeader, headerLength,
+ !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapperForInputData(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ inEndian=ds->inIsBigEndian;
+ inCharset=ds->inCharset;
+
+ oppositeEndian=!inEndian;
+ oppositeCharset= inCharset==U_ASCII_FAMILY ? U_EBCDIC_FAMILY : U_ASCII_FAMILY;
+
+ /* make this test work with data files that are built for a different platform */
+ if(inEndian!=U_IS_BIG_ENDIAN || inCharset!=U_CHARSET_FAMILY) {
+ udata_closeSwapper(ds);
+ ds=udata_openSwapper(inEndian, inCharset, oppositeEndian, inCharset, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ }
+
+ /*
+ Check error checking of swappable data not specific to this swapper.
+ This should always fail.
+ */
+ badStatus = U_ZERO_ERROR;
+ length=swapFn(ds, &gOffsetTOCAppData_dat, -1, NULL, &badStatus);
+ if(badStatus != U_UNSUPPORTED_ERROR) {
+ log_err("swapFn(%s->!isBig+same charset) unexpectedly succeeded on bad data - %s\n",
+ name, u_errorName(errorCode));
+ udata_closeSwapper(ds);
+ return;
+ }
+
+ /* Now allow errors to be printed */
+ ds->printError=printError;
+
+ /* preflight the length */
+ length=swapFn(ds, inHeader, -1, NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(preflight %s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ udata_closeSwapper(ds);
+ return;
+ }
+
+ /* compare the preflighted length against the data length */
+ if(dataLength>=0 && (length+15)<(headerLength+dataLength)) {
+ log_err("swapFn(preflight %s->!isBig+same charset) length too small: %d < data length %d\n",
+ name, length, (headerLength+dataLength));
+ udata_closeSwapper(ds);
+ return;
+ }
+
+ /* swap, not in-place */
+ length2=swapFn(ds, inHeader, length, buffer, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->!isBig+same charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the preflighted length */
+ if(length2!=length) {
+ log_err("swapFn(%s->!isBig+same charset) length differs from preflighting: %d != preflighted %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* next swap to opposite charset family */
+ ds=udata_openSwapper(oppositeEndian, inCharset,
+ oppositeEndian, oppositeCharset,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->!isBig+other charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ ds->printError=printError;
+
+ /* swap in-place */
+ length2=swapFn(ds, buffer, length, buffer, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->!isBig+other charset) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the original length */
+ if(length2!=length) {
+ log_err("swapFn(%s->!isBig+other charset) length differs from original: %d != original %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* finally swap to original platform values */
+ ds=udata_openSwapper(oppositeEndian, oppositeCharset,
+ inEndian, inCharset,
+ &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udata_openSwapper(%s->back to original) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+ ds->printError=printError;
+
+ /* swap, not in-place */
+ length2=swapFn(ds, buffer, length, buffer2, &errorCode);
+ udata_closeSwapper(ds);
+ if(U_FAILURE(errorCode)) {
+ log_err("swapFn(%s->back to original) failed - %s\n",
+ name, u_errorName(errorCode));
+ return;
+ }
+
+ /* compare the swap length against the original length */
+ if(length2!=length) {
+ log_err("swapFn(%s->back to original) length differs from original: %d != original %d\n",
+ name, length2, length);
+ return;
+ }
+
+ /* compare the final contents with the original */
+ if(0!=uprv_memcmp(inHeader, buffer2, length)) {
+ const uint8_t *original;
+ uint8_t diff[8];
+ int32_t i, j;
+
+ log_err("swapFn(%s->back to original) contents differs from original\n",
+ name);
+
+ /* find the first difference */
+ original=(const uint8_t *)inHeader;
+ for(i=0; i<length && original[i]==buffer2[i]; ++i) {}
+
+ /* find the next byte that is the same */
+ for(j=i+1; j<length && original[j]!=buffer2[j]; ++j) {}
+ log_info(" difference at index %d=0x%x, until index %d=0x%x\n", i, i, j, j);
+
+ /* round down to the last 4-boundary for better result output */
+ i&=~3;
+ log_info("showing bytes from index %d=0x%x (length %d=0x%x):\n", i, i, length, length);
+
+ /* print 8 bytes but limit to the buffer contents */
+ length2=i+sizeof(diff);
+ if(length2>length) {
+ length2=length;
+ }
+
+ /* print the original bytes */
+ uprv_memset(diff, 0, sizeof(diff));
+ for(j=i; j<length2; ++j) {
+ diff[j-i]=original[j];
+ }
+ log_info(" original: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
+
+ /* print the swapped bytes */
+ uprv_memset(diff, 0, sizeof(diff));
+ for(j=i; j<length2; ++j) {
+ diff[j-i]=buffer2[j];
+ }
+ log_info(" swapped: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ diff[0], diff[1], diff[2], diff[3], diff[4], diff[5], diff[6], diff[7]);
+ }
+}
+
+static void U_CALLCONV
+printErrorToString(void *context, const char *fmt, va_list args) {
+ vsprintf((char *)context, fmt, args);
+}
+
+static void
+TestSwapData() {
+ char name[100];
+ UDataSwapper *ds;
+ UDataMemory *pData;
+ uint8_t *buffer;
+ const char *pkg, *nm, *testPath;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t i;
+
+ buffer=(uint8_t *)uprv_malloc(2*SWAP_BUFFER_SIZE);
+ if(buffer==NULL) {
+ log_err("unable to allocate %d bytes\n", 2*SWAP_BUFFER_SIZE);
+ return;
+ }
+
+ testPath=loadTestData(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("Could not load testdata.dat, status = %s\n", u_errorName(errorCode));
+ }
+
+ /* Test that printError works as expected. */
+ errorCode=U_USELESS_COLLATOR_ERROR;
+ ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ &errorCode);
+ if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
+ log_err("udata_openSwapper should have returned NULL with bad argument\n", name);
+ }
+ errorCode=U_ZERO_ERROR;
+ ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ &errorCode);
+ ds->printError=printErrorToString;
+ ds->printErrorContext=name;
+ udata_printError(ds, "This %s a %s", "is", "test");
+ udata_closeSwapper(ds);
+ if (strcmp(name, "This is a test") != 0) {
+ log_err("udata_printError can't properly print error messages. Got = %s\n", name);
+ }
+ errorCode = U_USELESS_COLLATOR_ERROR;
+ ds=udata_openSwapperForInputData(NULL, 0,
+ !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ &errorCode);
+ if (ds != NULL || errorCode != U_USELESS_COLLATOR_ERROR) {
+ log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
+ }
+ errorCode=U_ZERO_ERROR;
+ ds=udata_openSwapperForInputData(NULL, 0,
+ !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ &errorCode);
+ if (ds != NULL || errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
+ }
+ errorCode=U_ZERO_ERROR;
+ memset(buffer, 0, sizeof(2*SWAP_BUFFER_SIZE));
+ ds=udata_openSwapperForInputData(buffer, 2*SWAP_BUFFER_SIZE,
+ !U_IS_BIG_ENDIAN, U_ASCII_FAMILY,
+ &errorCode);
+ if (ds != NULL || errorCode != U_UNSUPPORTED_ERROR) {
+ log_err("udata_openSwapperForInputData should have returned NULL with bad argument\n", name);
+ }
+ errorCode=U_ZERO_ERROR;
+
+ /* Test argument checking. ucol_swapBinary is normally tested via ures_swap, and isn't normally called directly. */
+#if !UCONFIG_NO_COLLATION
+ ucol_swapBinary(NULL, NULL, -1, NULL, NULL);
+ ucol_swapBinary(NULL, NULL, -1, NULL, &errorCode);
+ if (errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucol_swapBinary did not fail as expected\n", name);
+ }
+ errorCode=U_ZERO_ERROR;
+#endif
+
+ for(i=0; i<LENGTHOF(swapCases); ++i) {
+ /* build the name for logging */
+ errorCode=U_ZERO_ERROR;
+ if(swapCases[i].name[0]=='*') {
+ pkg=testPath;
+ nm=swapCases[i].name+1;
+ uprv_strcpy(name, "testdata");
+ } else if (uprv_strcmp(swapCases[i].type, "brk")==0
+ || uprv_strcmp(swapCases[i].type, "ctd")==0) {
+ pkg=U_ICUDATA_BRKITR;
+ nm=swapCases[i].name;
+ uprv_strcpy(name, U_ICUDATA_BRKITR);
+ } else {
+ pkg=NULL;
+ nm=swapCases[i].name;
+ uprv_strcpy(name, "NULL");
+ }
+ uprv_strcat(name, "/");
+ uprv_strcat(name, nm);
+ uprv_strcat(name, ".");
+ uprv_strcat(name, swapCases[i].type);
+
+ pData=udata_open(pkg, swapCases[i].type, nm, &errorCode);
+ if(U_SUCCESS(errorCode)) {
+ TestSwapCase(pData, name, swapCases[i].swapFn, buffer, buffer+SWAP_BUFFER_SIZE);
+ udata_close(pData);
+ } else {
+ log_data_err("udata_open(%s) failed - %s\n",
+ name, u_errorName(errorCode));
+ }
+ }
+
+ uprv_free(buffer);
+}
+
+
+static void PointerTableOfContents() {
+ UDataMemory *dataItem;
+ UErrorCode status=U_ZERO_ERROR;
+
+ /*
+ * Got testdata.dat into memory, now we try setAppData using the memory image.
+ */
+
+ status=U_ZERO_ERROR;
+ udata_setAppData("OffsetTOCAppData", &gOffsetTOCAppData_dat, &status);
+ if (status != U_ZERO_ERROR) {
+ log_err("FAIL: TestUDataSetAppData(): udata_setAppData(\"appData1\", fileBuf, status) \n"
+ " returned status of %s\n", u_errorName(status));
+ return;
+ }
+
+ dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCAppDataItem1", &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: gOffsetTOCAppDataItem1 could not be opened. status = %s\n", u_errorName(status));
+ }
+ if (udata_getMemory(dataItem) != NULL) {
+ log_verbose("FAIL: udata_getMemory(dataItem) passed\n");
+ }
+ else {
+ log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
+ }
+ udata_close(dataItem);
+
+ dataItem = udata_open("OffsetTOCAppData-a", "", "b", &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: gOffsetTOCAppDataItem1 in tree \"a\" could not be opened. status = %s\n", u_errorName(status));
+ }
+ if (udata_getMemory(dataItem) != NULL) {
+ log_verbose("FAIL: udata_getMemory(dataItem) in tree \"a\" passed\n");
+ }
+ else {
+ log_err("FAIL: udata_getMemory returned NULL\n", u_errorName(status));
+ }
+ udata_close(dataItem);
+
+ dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCGarbage", &status);
+ if (U_SUCCESS(status)) {
+ log_err("FAIL: gOffsetTOCGarbage should not be opened. status = %s\n", u_errorName(status));
+ }
+ dataItem = udata_open("OffsetTOCAppData", "", "gOffsetTOCNonExistent", &status);
+ if (U_SUCCESS(status)) {
+ log_err("FAIL: gOffsetTOCNonExistent should not be found. status = %s\n", u_errorName(status));
+ }
+
+}
+
+static void SetBadCommonData(void) {
+ /* It's difficult to test that udata_setCommonData really works within the test framework.
+ So we just test that foolish people can't do bad things. */
+ UErrorCode status;
+ char badBuffer[sizeof(gOffsetTOCAppData_dat)];
+
+ memset(badBuffer, 0, sizeof(badBuffer));
+ strcpy(badBuffer, "Hello! I'm not good data.");
+
+ /* Check that we don't do anything */
+ status = U_FILE_ACCESS_ERROR;
+ udata_setCommonData(&gOffsetTOCAppData_dat, &status);
+ if (status != U_FILE_ACCESS_ERROR) {
+ log_err("FAIL: udata_setCommonData changed the failure code.\n");
+ }
+ /* Check that we fail correctly */
+ status = U_ZERO_ERROR;
+ udata_setCommonData(NULL, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("FAIL: udata_setCommonData did not fail with bad arguments.\n");
+ }
+ if (u_getDataDirectory() == NULL || u_getDataDirectory()[0] == 0) {
+ /* Check that we don't change the common data. Many ICU tests will fail after this test, if this works. */
+ /* We could do a better test, if we called u_cleanup and udata_setCommonData returned the last value. */
+ status = U_ZERO_ERROR;
+ udata_setCommonData(&gOffsetTOCAppData_dat, &status);
+ if (status != U_USING_DEFAULT_WARNING) {
+ log_err("FAIL: udata_setCommonData allowed the data to be changed after initialization!\n");
+ }
+ }
+ else {
+ log_verbose("Can't test setting common data because files mode may have been used.\n");
+ }
+
+ /* Check that we verify that the data isn't bad */
+ status = U_ZERO_ERROR;
+ udata_setAppData("invalid path", badBuffer, &status);
+ if (status != U_INVALID_FORMAT_ERROR) {
+ log_err("FAIL: udata_setAppData doesn't verify data validity.\n");
+ }
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c b/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c
new file mode 100644
index 00000000000..34542b0bcda
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/udatpg_test.c
@@ -0,0 +1,307 @@
+/*
+*******************************************************************************
+*
+* Copyright (C) 2007, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+*******************************************************************************
+* file name: udatpg_test.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2007aug01
+* created by: Markus W. Scherer
+*
+* Test of the C wrapper for the DateTimePatternGenerator.
+* Calls each C API function and exercises code paths in the wrapper,
+* but the full functionality is tested in the C++ intltest.
+*
+* One item to note: C API functions which return a const UChar *
+* should return a NUL-terminated string.
+* (The C++ implementation needs to use getTerminatedBuffer()
+* on UnicodeString objects which end up being returned this way.)
+*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/udatpg.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+
+void addDateTimePatternGeneratorTest(TestNode** root);
+
+#define TESTCASE(x) addTest(root, &x, "tsformat/udatpg_test/" #x)
+
+static void TestOpenClose(void);
+static void TestUsage(void);
+static void TestBuilder(void);
+
+void addDateTimePatternGeneratorTest(TestNode** root) {
+ TESTCASE(TestOpenClose);
+ TESTCASE(TestUsage);
+ TESTCASE(TestBuilder);
+}
+
+/*
+ * Pipe symbol '|'. We pass only the first UChar without NUL-termination.
+ * The second UChar is just to verify that the API does not pick that up.
+ */
+static const UChar pipeString[]={ 0x7c, 0x0a };
+
+static const UChar testSkeleton1[]={ 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */
+static const UChar expectingBestPattern[]={ 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0 }; /* HH.mm */
+static const UChar testPattern[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0 }; /* HH:mm */
+static const UChar expectingSkeleton[]= { 0x48, 0x48, 0x6d, 0x6d, 0 }; /* HHmm */
+static const UChar expectingBaseSkeleton[]= { 0x48, 0x6d, 0 }; /* HHmm */
+static const UChar redundantPattern[]={ 0x79, 0x79, 0x4d, 0x4d, 0x4d, 0 }; /* yyMMM */
+static const UChar testFormat[]= {0x7B, 0x31, 0x7D, 0x20, 0x7B, 0x30, 0x7D, 0}; /* {1} {0} */
+static const UChar appendItemName[]= {0x68, 0x72, 0}; /* hr */
+static const UChar testPattern2[]={ 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x76, 0 }; /* HH:mm v */
+static const UChar replacedStr[]={ 0x76, 0x76, 0x76, 0x76, 0 }; /* vvvv */
+/* results for getBaseSkeletons() - {Hmv}, {yMMM} */
+static const UChar resultBaseSkeletons[2][10] = {{0x48,0x6d, 0x76, 0}, {0x79, 0x4d, 0x4d, 0x4d, 0 } };
+
+
+static void TestOpenClose() {
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UDateTimePatternGenerator *dtpg, *dtpg2;
+ const UChar *s;
+ int32_t length;
+
+ /* Open a DateTimePatternGenerator for the default locale. */
+ dtpg=udatpg_open(NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_open(NULL) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ udatpg_close(dtpg);
+
+ /* Now one for German. */
+ dtpg=udatpg_open("de", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_open(de) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* Make some modification which we verify gets passed on to the clone. */
+ udatpg_setDecimal(dtpg, pipeString, 1);
+
+ /* Clone the generator. */
+ dtpg2=udatpg_clone(dtpg, &errorCode);
+ if(U_FAILURE(errorCode) || dtpg2==NULL) {
+ log_err("udatpg_clone() failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* Verify that the clone has the custom decimal symbol. */
+ s=udatpg_getDecimal(dtpg2, &length);
+ if(s==pipeString || length!=1 || 0!=u_memcmp(s, pipeString, length) || s[length]!=0) {
+ log_err("udatpg_getDecimal(cloned object) did not return the expected string\n");
+ return;
+ }
+
+ udatpg_close(dtpg);
+ udatpg_close(dtpg2);
+}
+
+static void TestUsage() {
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UDateTimePatternGenerator *dtpg;
+ UChar bestPattern[20];
+ UChar result[20];
+ int32_t length;
+ UChar *s;
+ const UChar *r;
+
+ dtpg=udatpg_open("fi", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_open(fi) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length = udatpg_getBestPattern(dtpg, testSkeleton1, 4,
+ bestPattern, 20, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_getBestPattern failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ if((u_memcmp(bestPattern, expectingBestPattern, length)!=0) || bestPattern[length]!=0) {
+ log_err("udatpg_getBestPattern did not return the expected string\n");
+ return;
+ }
+
+
+ /* Test skeleton == NULL */
+ s=NULL;
+ length = udatpg_getBestPattern(dtpg, s, 0, bestPattern, 20, &errorCode);
+ if(!U_FAILURE(errorCode)&&(length!=0) ) {
+ log_err("udatpg_getBestPattern failed in illegal argument - skeleton is NULL.\n");
+ return;
+ }
+
+ /* Test udatpg_getSkeleton */
+ length = udatpg_getSkeleton(dtpg, testPattern, 5, result, 20, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_getSkeleton failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ if((u_memcmp(result, expectingSkeleton, length)!=0) || result[length]!=0) {
+ log_err("udatpg_getSkeleton did not return the expected string\n");
+ return;
+ }
+
+ /* Test pattern == NULL */
+ s=NULL;
+ length = udatpg_getSkeleton(dtpg, s, 0, result, 20, &errorCode);
+ if(!U_FAILURE(errorCode)&&(length!=0) ) {
+ log_err("udatpg_getSkeleton failed in illegal argument - pattern is NULL.\n");
+ return;
+ }
+
+ /* Test udatpg_getBaseSkeleton */
+ length = udatpg_getBaseSkeleton(dtpg, testPattern, 5, result, 20, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_getBaseSkeleton failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ if((u_memcmp(result, expectingBaseSkeleton, length)!=0) || result[length]!=0) {
+ log_err("udatpg_getBaseSkeleton did not return the expected string\n");
+ return;
+ }
+
+ /* Test pattern == NULL */
+ s=NULL;
+ length = udatpg_getBaseSkeleton(dtpg, s, 0, result, 20, &errorCode);
+ if(!U_FAILURE(errorCode)&&(length!=0) ) {
+ log_err("udatpg_getBaseSkeleton failed in illegal argument - pattern is NULL.\n");
+ return;
+ }
+
+ /* set append format to {1}{0} */
+ udatpg_setAppendItemFormat( dtpg, UDATPG_MONTH_FIELD, testFormat, 7 );
+ r = udatpg_getAppendItemFormat(dtpg, UDATPG_MONTH_FIELD, &length);
+
+
+ if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) {
+ log_err("udatpg_setAppendItemFormat did not return the expected string\n");
+ return;
+ }
+
+ /* set append name to hr */
+ udatpg_setAppendItemName( dtpg, UDATPG_HOUR_FIELD, appendItemName, 7 );
+ r = udatpg_getAppendItemName(dtpg, UDATPG_HOUR_FIELD, &length);
+
+ if(length!=7 || 0!=u_memcmp(r, appendItemName, length) || r[length]!=0) {
+ log_err("udatpg_setAppendItemName did not return the expected string\n");
+ return;
+ }
+
+ /* set date time format to {1}{0} */
+ udatpg_setDateTimeFormat( dtpg, testFormat, 7 );
+ r = udatpg_getDateTimeFormat(dtpg, &length);
+
+ if(length!=7 || 0!=u_memcmp(r, testFormat, length) || r[length]!=0) {
+ log_err("udatpg_setDateTimeFormat did not return the expected string\n");
+ return;
+ }
+ udatpg_close(dtpg);
+}
+
+static void TestBuilder() {
+ UErrorCode errorCode=U_ZERO_ERROR;
+ UDateTimePatternGenerator *dtpg;
+ UDateTimePatternConflict conflict;
+ UEnumeration *en;
+ UChar result[20];
+ int32_t length, pLength;
+ const UChar *s, *p;
+ const UChar* ptrResult[2];
+ int32_t count=0;
+
+ /* test create an empty DateTimePatternGenerator */
+ dtpg=udatpg_openEmpty(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_openEmpty() failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ /* Add a pattern */
+ conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20,
+ &length, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("udatpg_addPattern() failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ /* Add a redundant pattern */
+ conflict = udatpg_addPattern(dtpg, redundantPattern, 5, FALSE, result, 20,
+ &length, &errorCode);
+ if(conflict == UDATPG_NO_CONFLICT) {
+ log_err("udatpg_addPattern() failed to find the duplicate pattern.\n");
+ return;
+ }
+ /* Test pattern == NULL */
+ s=NULL;
+ length = udatpg_addPattern(dtpg, s, 0, FALSE, result, 20,
+ &length, &errorCode);
+ if(!U_FAILURE(errorCode)&&(length!=0) ) {
+ log_err("udatpg_addPattern failed in illegal argument - pattern is NULL.\n");
+ return;
+ }
+
+ /* replace field type */
+ errorCode=U_ZERO_ERROR;
+ conflict = udatpg_addPattern(dtpg, testPattern2, 7, FALSE, result, 20,
+ &length, &errorCode);
+ if((conflict != UDATPG_NO_CONFLICT)||U_FAILURE(errorCode)) {
+ log_err("udatpg_addPattern() failed to add HH:mm v. - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length = udatpg_replaceFieldTypes(dtpg, testPattern2, 7, replacedStr, 4,
+ result, 20, &errorCode);
+ if (U_FAILURE(errorCode) || (length==0) ) {
+ log_err("udatpg_replaceFieldTypes failed!\n");
+ return;
+ }
+
+ /* Get all skeletons and the crroespong pattern for each skeleton. */
+ ptrResult[0] = testPattern2;
+ ptrResult[1] = redundantPattern;
+ count=0;
+ en = udatpg_openSkeletons(dtpg, &errorCode);
+ if (U_FAILURE(errorCode) || (length==0) ) {
+ log_err("udatpg_openSkeletons failed!\n");
+ return;
+ }
+ while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) {
+ p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength);
+ if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, ptrResult[count], pLength)!=0 ) {
+ log_err("udatpg_getPatternForSkeleton failed!\n");
+ return;
+ }
+ count++;
+ }
+ uenum_close(en);
+
+ /* Get all baseSkeletons */
+ en = udatpg_openBaseSkeletons(dtpg, &errorCode);
+ count=0;
+ while ( (s=uenum_unext(en, &length, &errorCode))!= NULL) {
+ p = udatpg_getPatternForSkeleton(dtpg, s, length, &pLength);
+ if (U_FAILURE(errorCode) || p==NULL || u_memcmp(p, resultBaseSkeletons[count], pLength)!=0 ) {
+ log_err("udatpg_getPatternForSkeleton failed!\n");
+ return;
+ }
+ count++;
+ }
+ if (U_FAILURE(errorCode) || (length==0) ) {
+ log_err("udatpg_openSkeletons failed!\n");
+ return;
+ }
+ uenum_close(en);
+
+ udatpg_close(dtpg);
+}
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c
new file mode 100644
index 00000000000..2d9ed6c0ab8
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/uenumtst.c
@@ -0,0 +1,307 @@
+/*
+*******************************************************************************
+*
+* Copyright (C) 2002-2003, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+*******************************************************************************
+* file name: uenumtst.c
+* encoding: US-ASCII
+* tab size: 8 (not used)
+* indentation:2
+*
+* created on: 2002jul08
+* created by: Vladimir Weinstein
+*/
+
+#include "cintltst.h"
+#include "uenumimp.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "unicode/ustring.h"
+
+static char quikBuf[256];
+static char* quikU2C(const UChar* str, int32_t len) {
+ u_UCharsToChars(str, quikBuf, len);
+ quikBuf[len] = 0;
+ return quikBuf;
+}
+
+static const char* test1[] = {
+ "first",
+ "second",
+ "third",
+ "fourth"
+};
+
+struct chArrayContext {
+ int32_t currIndex;
+ int32_t maxIndex;
+ char *currChar;
+ UChar *currUChar;
+ char **array;
+};
+
+typedef struct chArrayContext chArrayContext;
+
+#define cont ((chArrayContext *)en->context)
+
+static void U_CALLCONV
+chArrayClose(UEnumeration *en) {
+ if(cont->currUChar != NULL) {
+ free(cont->currUChar);
+ cont->currUChar = NULL;
+ }
+ free(en);
+}
+
+static int32_t U_CALLCONV
+chArrayCount(UEnumeration *en, UErrorCode *status) {
+ return cont->maxIndex;
+}
+
+static const UChar* U_CALLCONV
+chArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
+ if(cont->currIndex >= cont->maxIndex) {
+ return NULL;
+ }
+
+ if(cont->currUChar == NULL) {
+ cont->currUChar = (UChar *)malloc(1024*sizeof(UChar));
+ }
+
+ cont->currChar = (cont->array)[cont->currIndex];
+ *resultLength = (int32_t)strlen(cont->currChar);
+ u_charsToUChars(cont->currChar, cont->currUChar, *resultLength);
+ cont->currIndex++;
+ return cont->currUChar;
+}
+
+static const char* U_CALLCONV
+chArrayNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
+ if(cont->currIndex >= cont->maxIndex) {
+ return NULL;
+ }
+
+ cont->currChar = (cont->array)[cont->currIndex];
+ *resultLength = (int32_t)strlen(cont->currChar);
+ cont->currIndex++;
+ return cont->currChar;
+}
+
+static void U_CALLCONV
+chArrayReset(UEnumeration *en, UErrorCode *status) {
+ cont->currIndex = 0;
+}
+
+chArrayContext myCont = {
+ 0, 0,
+ NULL, NULL,
+ NULL
+};
+
+UEnumeration chEnum = {
+ NULL,
+ &myCont,
+ chArrayClose,
+ chArrayCount,
+ chArrayUNext,
+ chArrayNext,
+ chArrayReset
+};
+
+static const UEnumeration emptyEnumerator = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static const UEnumeration emptyPartialEnumerator = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ uenum_unextDefault,
+ NULL,
+ NULL,
+};
+
+/********************************************************************/
+static const UChar _first[] = {102,105,114,115,116,0}; /* "first" */
+static const UChar _second[]= {115,101,99,111,110,100,0}; /* "second" */
+static const UChar _third[] = {116,104,105,114,100,0}; /* "third" */
+static const UChar _fourth[]= {102,111,117,114,116,104,0};/* "fourth" */
+
+static const UChar* test2[] = {
+ _first, _second, _third, _fourth
+};
+
+struct uchArrayContext {
+ int32_t currIndex;
+ int32_t maxIndex;
+ UChar *currUChar;
+ UChar **array;
+};
+
+typedef struct uchArrayContext uchArrayContext;
+
+#define ucont ((uchArrayContext *)en->context)
+
+static void U_CALLCONV
+uchArrayClose(UEnumeration *en) {
+ free(en);
+}
+
+static int32_t U_CALLCONV
+uchArrayCount(UEnumeration *en, UErrorCode *status) {
+ return ucont->maxIndex;
+}
+
+static const UChar* U_CALLCONV
+uchArrayUNext(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
+ if(ucont->currIndex >= ucont->maxIndex) {
+ return NULL;
+ }
+
+ ucont->currUChar = (ucont->array)[ucont->currIndex];
+ *resultLength = u_strlen(ucont->currUChar);
+ ucont->currIndex++;
+ return ucont->currUChar;
+}
+
+static void U_CALLCONV
+uchArrayReset(UEnumeration *en, UErrorCode *status) {
+ ucont->currIndex = 0;
+}
+
+uchArrayContext myUCont = {
+ 0, 0,
+ NULL, NULL
+};
+
+UEnumeration uchEnum = {
+ NULL,
+ &myUCont,
+ uchArrayClose,
+ uchArrayCount,
+ uchArrayUNext,
+ uenum_nextDefault,
+ uchArrayReset
+};
+
+/********************************************************************/
+
+static UEnumeration *getchArrayEnum(const char** source, int32_t size) {
+ UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration));
+ memcpy(en, &chEnum, sizeof(UEnumeration));
+ cont->array = (char **)source;
+ cont->maxIndex = size;
+ return en;
+}
+
+static void EnumerationTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+ UEnumeration *en = getchArrayEnum(test1, sizeof(test1)/sizeof(test1[0]));
+ const char *string = NULL;
+ const UChar *uString = NULL;
+ while ((string = uenum_next(en, &len, &status))) {
+ log_verbose("read \"%s\", length %i\n", string, len);
+ }
+ uenum_reset(en, &status);
+ while ((uString = uenum_unext(en, &len, &status))) {
+ log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len);
+ }
+
+ uenum_close(en);
+}
+
+static void EmptyEnumerationTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UEnumeration *emptyEnum = uprv_malloc(sizeof(UEnumeration));
+
+ uprv_memcpy(emptyEnum, &emptyEnumerator, sizeof(UEnumeration));
+ if (uenum_count(emptyEnum, &status) != -1 || status != U_UNSUPPORTED_ERROR) {
+ log_err("uenum_count failed\n");
+ }
+ status = U_ZERO_ERROR;
+ if (uenum_next(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
+ log_err("uenum_next failed\n");
+ }
+ status = U_ZERO_ERROR;
+ if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
+ log_err("uenum_unext failed\n");
+ }
+ status = U_ZERO_ERROR;
+ uenum_reset(emptyEnum, &status);
+ if (status != U_UNSUPPORTED_ERROR) {
+ log_err("uenum_reset failed\n");
+ }
+ uenum_close(emptyEnum);
+
+ status = U_ZERO_ERROR;
+ if (uenum_next(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) {
+ log_err("uenum_next(NULL) failed\n");
+ }
+ status = U_ZERO_ERROR;
+ if (uenum_unext(NULL, NULL, &status) != NULL || status != U_ZERO_ERROR) {
+ log_err("uenum_unext(NULL) failed\n");
+ }
+ status = U_ZERO_ERROR;
+ uenum_reset(NULL, &status);
+ if (status != U_ZERO_ERROR) {
+ log_err("uenum_reset(NULL) failed\n");
+ }
+
+ emptyEnum = uprv_malloc(sizeof(UEnumeration));
+ uprv_memcpy(emptyEnum, &emptyPartialEnumerator, sizeof(UEnumeration));
+ status = U_ZERO_ERROR;
+ if (uenum_unext(emptyEnum, NULL, &status) != NULL || status != U_UNSUPPORTED_ERROR) {
+ log_err("partial uenum_unext failed\n");
+ }
+ uenum_close(emptyEnum);
+}
+
+static UEnumeration *getuchArrayEnum(const UChar** source, int32_t size) {
+ UEnumeration *en = (UEnumeration *)malloc(sizeof(UEnumeration));
+ memcpy(en, &uchEnum, sizeof(UEnumeration));
+ ucont->array = (UChar **)source;
+ ucont->maxIndex = size;
+ return en;
+}
+
+static void DefaultNextTest(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t len = 0;
+ UEnumeration *en = getuchArrayEnum(test2, sizeof(test2)/sizeof(test2[0]));
+ const char *string = NULL;
+ const UChar *uString = NULL;
+ while ((uString = uenum_unext(en, &len, &status))) {
+ log_verbose("read \"%s\" (UChar), length %i\n", quikU2C(uString, len), len);
+ }
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uenum_unext => %s\n", u_errorName(status));
+ }
+ uenum_reset(en, &status);
+ while ((string = uenum_next(en, &len, &status))) {
+ log_verbose("read \"%s\", length %i\n", string, len);
+ }
+ if (U_FAILURE(status)) {
+ log_err("FAIL: uenum_next => %s\n", u_errorName(status));
+ }
+
+ uenum_close(en);
+}
+
+void addEnumerationTest(TestNode** root);
+
+void addEnumerationTest(TestNode** root)
+{
+ addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest");
+ addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest");
+ addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest");
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c
new file mode 100644
index 00000000000..fc2a3e9b055
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usettest.c
@@ -0,0 +1,646 @@
+/*
+**********************************************************************
+* Copyright (c) 2002-2007, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*/
+#include "unicode/uset.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+#define TEST(x) addTest(root, &x, "uset/" # x)
+
+static void TestAPI(void);
+static void Testj2269(void);
+static void TestSerialized(void);
+static void TestNonInvariantPattern(void);
+static void TestBadPattern(void);
+static void TestFreezable(void);
+static void TestSpan(void);
+
+void addUSetTest(TestNode** root);
+
+static void expect(const USet* set,
+ const char* inList,
+ const char* outList,
+ UErrorCode* ec);
+static void expectContainment(const USet* set,
+ const char* list,
+ UBool isIn);
+static char oneUCharToChar(UChar32 c);
+static void expectItems(const USet* set,
+ const char* items);
+
+void
+addUSetTest(TestNode** root) {
+ TEST(TestAPI);
+ TEST(Testj2269);
+ TEST(TestSerialized);
+ TEST(TestNonInvariantPattern);
+ TEST(TestBadPattern);
+ TEST(TestFreezable);
+ TEST(TestSpan);
+}
+
+/*------------------------------------------------------------------
+ * Tests
+ *------------------------------------------------------------------*/
+
+static void Testj2269() {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar a[4] = { 0x61, 0x62, 0x63, 0 };
+ USet *s = uset_open(1, 0);
+ uset_addString(s, a, 3);
+ a[0] = 0x63; a[1] = 0x63;
+ expect(s, "{abc}", "{ccc}", &status);
+ uset_close(s);
+}
+
+static const UChar PAT[] = {91,97,45,99,123,97,98,125,93,0}; /* "[a-c{ab}]" */
+static const int32_t PAT_LEN = (sizeof(PAT) / sizeof(PAT[0])) - 1;
+
+static const UChar PAT_lb[] = {0x6C, 0x62, 0}; /* "lb" */
+static const int32_t PAT_lb_LEN = (sizeof(PAT_lb) / sizeof(PAT_lb[0])) - 1;
+
+static const UChar VAL_SP[] = {0x53, 0x50, 0}; /* "SP" */
+static const int32_t VAL_SP_LEN = (sizeof(VAL_SP) / sizeof(VAL_SP[0])) - 1;
+
+static const UChar STR_bc[] = {98,99,0}; /* "bc" */
+static const int32_t STR_bc_LEN = (sizeof(STR_bc) / sizeof(STR_bc[0])) - 1;
+
+static const UChar STR_ab[] = {97,98,0}; /* "ab" */
+static const int32_t STR_ab_LEN = (sizeof(STR_ab) / sizeof(STR_ab[0])) - 1;
+
+/**
+ * Basic API test for uset.x
+ */
+static void TestAPI() {
+ USet* set;
+ USet* set2;
+ UErrorCode ec;
+
+ /* [] */
+ set = uset_open(1, 1);
+ uset_clear(set);
+ expect(set, "", "abc{ab}", NULL);
+ uset_close(set);
+
+ /* [ABC] */
+ set = uset_open(0x0041, 0x0043);
+ expect(set, "ABC", "DEF{ab}", NULL);
+ uset_close(set);
+
+ /* [a-c{ab}] */
+ ec = U_ZERO_ERROR;
+ set = uset_openPattern(PAT, PAT_LEN, &ec);
+ if(U_FAILURE(ec)) {
+ log_err("uset_openPattern([a-c{ab}]) failed - %s\n", u_errorName(ec));
+ return;
+ }
+ if(!uset_resemblesPattern(PAT, PAT_LEN, 0)) {
+ log_err("uset_resemblesPattern of PAT failed\n");
+ }
+ expect(set, "abc{ab}", "def{bc}", &ec);
+
+ /* [a-d{ab}] */
+ uset_add(set, 0x64);
+ expect(set, "abcd{ab}", "ef{bc}", NULL);
+
+ /* [acd{ab}{bc}] */
+ uset_remove(set, 0x62);
+ uset_addString(set, STR_bc, STR_bc_LEN);
+ expect(set, "acd{ab}{bc}", "bef{cd}", NULL);
+
+ /* [acd{bc}] */
+ uset_removeString(set, STR_ab, STR_ab_LEN);
+ expect(set, "acd{bc}", "bfg{ab}", NULL);
+
+ /* [^acd{bc}] */
+ uset_complement(set);
+ expect(set, "bef{bc}", "acd{ac}", NULL);
+
+ /* [a-e{bc}] */
+ uset_complement(set);
+ uset_addRange(set, 0x0062, 0x0065);
+ expect(set, "abcde{bc}", "fg{ab}", NULL);
+
+ /* [de{bc}] */
+ uset_removeRange(set, 0x0050, 0x0063);
+ expect(set, "de{bc}", "bcfg{ab}", NULL);
+
+ /* [g-l] */
+ uset_set(set, 0x0067, 0x006C);
+ expect(set, "ghijkl", "de{bc}", NULL);
+
+ if (uset_indexOf(set, 0x0067) != 0) {
+ log_err("uset_indexOf failed finding correct index of 'g'\n");
+ }
+
+ if (uset_charAt(set, 0) != 0x0067) {
+ log_err("uset_charAt failed finding correct char 'g' at index 0\n");
+ }
+
+ /* How to test this one...? */
+ uset_compact(set);
+
+ /* [g-i] */
+ uset_retain(set, 0x0067, 0x0069);
+ expect(set, "ghi", "dejkl{bc}", NULL);
+
+ /* UCHAR_ASCII_HEX_DIGIT */
+ uset_applyIntPropertyValue(set, UCHAR_ASCII_HEX_DIGIT, 1, &ec);
+ if(U_FAILURE(ec)) {
+ log_err("uset_applyIntPropertyValue([UCHAR_ASCII_HEX_DIGIT]) failed - %s\n", u_errorName(ec));
+ return;
+ }
+ expect(set, "0123456789ABCDEFabcdef", "GHIjkl{bc}", NULL);
+
+ /* [ab] */
+ uset_clear(set);
+ uset_addAllCodePoints(set, STR_ab, STR_ab_LEN);
+ expect(set, "ab", "def{ab}", NULL);
+ if (uset_containsAllCodePoints(set, STR_bc, STR_bc_LEN)){
+ log_err("set should not conatin all characters of \"bc\" \n");
+ }
+
+ /* [] */
+ set2 = uset_open(1, 1);
+ uset_clear(set2);
+
+ /* space */
+ uset_applyPropertyAlias(set2, PAT_lb, PAT_lb_LEN, VAL_SP, VAL_SP_LEN, &ec);
+ expect(set2, " ", "abcdefghi{bc}", NULL);
+
+ /* [a-c] */
+ uset_set(set2, 0x0061, 0x0063);
+ /* [g-i] */
+ uset_set(set, 0x0067, 0x0069);
+
+ /* [a-c g-i] */
+ if (uset_containsSome(set, set2)) {
+ log_err("set should not contain some of set2 yet\n");
+ }
+ uset_complementAll(set, set2);
+ if (!uset_containsSome(set, set2)) {
+ log_err("set should contain some of set2\n");
+ }
+ expect(set, "abcghi", "def{bc}", NULL);
+
+ /* [g-i] */
+ uset_removeAll(set, set2);
+ expect(set, "ghi", "abcdef{bc}", NULL);
+
+ /* [a-c g-i] */
+ uset_addAll(set2, set);
+ expect(set2, "abcghi", "def{bc}", NULL);
+
+ /* [g-i] */
+ uset_retainAll(set2, set);
+ expect(set2, "ghi", "abcdef{bc}", NULL);
+
+ uset_close(set);
+ uset_close(set2);
+}
+
+/*------------------------------------------------------------------
+ * Support
+ *------------------------------------------------------------------*/
+
+/**
+ * Verifies that the given set contains the characters and strings in
+ * inList, and does not contain those in outList. Also verifies that
+ * 'set' is not NULL and that 'ec' succeeds.
+ * @param set the set to test, or NULL (on error)
+ * @param inList list of set contents, in iteration order. Format is
+ * list of individual strings, in iteration order, followed by sorted
+ * list of strings, delimited by {}. This means we do not test
+ * characters '{' or '}' and we do not test strings containing those
+ * characters either.
+ * @param outList list of things not in the set. Same format as
+ * inList.
+ * @param ec an error code, checked for success. May be NULL in which
+ * case it is ignored.
+ */
+static void expect(const USet* set,
+ const char* inList,
+ const char* outList,
+ UErrorCode* ec) {
+ if (ec!=NULL && U_FAILURE(*ec)) {
+ log_err("FAIL: %s\n", u_errorName(*ec));
+ return;
+ }
+ if (set == NULL) {
+ log_err("FAIL: USet is NULL\n");
+ return;
+ }
+ expectContainment(set, inList, TRUE);
+ expectContainment(set, outList, FALSE);
+ expectItems(set, inList);
+}
+
+static void expectContainment(const USet* set,
+ const char* list,
+ UBool isIn) {
+ const char* p = list;
+ UChar ustr[4096];
+ char *pat;
+ UErrorCode ec;
+ int32_t rangeStart = -1, rangeEnd = -1, length;
+
+ ec = U_ZERO_ERROR;
+ length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec);
+ if(U_FAILURE(ec)) {
+ log_err("FAIL: uset_toPattern() fails in expectContainment() - %s\n", u_errorName(ec));
+ return;
+ }
+ pat=aescstrdup(ustr, length);
+
+ while (*p) {
+ if (*p=='{') {
+ const char* stringStart = ++p;
+ int32_t stringLength = 0;
+ char strCopy[64];
+
+ while (*p++ != '}') {
+ }
+ stringLength = (int32_t)(p - stringStart - 1);
+ strncpy(strCopy, stringStart, stringLength);
+ strCopy[stringLength] = 0;
+
+ u_charsToUChars(stringStart, ustr, stringLength);
+
+ if (uset_containsString(set, ustr, stringLength) == isIn) {
+ log_verbose("Ok: %s %s \"%s\"\n", pat,
+ (isIn ? "contains" : "does not contain"),
+ strCopy);
+ } else {
+ log_err("FAIL: %s %s \"%s\"\n", pat,
+ (isIn ? "does not contain" : "contains"),
+ strCopy);
+ }
+ }
+
+ else {
+ UChar32 c;
+
+ u_charsToUChars(p, ustr, 1);
+ c = ustr[0];
+
+ if (uset_contains(set, c) == isIn) {
+ log_verbose("Ok: %s %s '%c'\n", pat,
+ (isIn ? "contains" : "does not contain"),
+ *p);
+ } else {
+ log_err("FAIL: %s %s '%c'\n", pat,
+ (isIn ? "does not contain" : "contains"),
+ *p);
+ }
+
+ /* Test the range API too by looking for ranges */
+ if (c == rangeEnd+1) {
+ rangeEnd = c;
+ } else {
+ if (rangeStart >= 0) {
+ if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) {
+ log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat,
+ (isIn ? "contains" : "does not contain"),
+ rangeStart, rangeEnd);
+ } else {
+ log_err("FAIL: %s %s U+%04X-U+%04X\n", pat,
+ (isIn ? "does not contain" : "contains"),
+ rangeStart, rangeEnd);
+ }
+ }
+ rangeStart = rangeEnd = c;
+ }
+
+ ++p;
+ }
+ }
+
+ if (rangeStart >= 0) {
+ if (uset_containsRange(set, rangeStart, rangeEnd) == isIn) {
+ log_verbose("Ok: %s %s U+%04X-U+%04X\n", pat,
+ (isIn ? "contains" : "does not contain"),
+ rangeStart, rangeEnd);
+ } else {
+ log_err("FAIL: %s %s U+%04X-U+%04X\n", pat,
+ (isIn ? "does not contain" : "contains"),
+ rangeStart, rangeEnd);
+ }
+ }
+}
+
+/* This only works for invariant BMP chars */
+static char oneUCharToChar(UChar32 c) {
+ UChar ubuf[1];
+ char buf[1];
+ ubuf[0] = (UChar) c;
+ u_UCharsToChars(ubuf, buf, 1);
+ return buf[0];
+}
+
+static void expectItems(const USet* set,
+ const char* items) {
+ const char* p = items;
+ UChar ustr[4096], itemStr[4096];
+ char buf[4096];
+ char *pat;
+ UErrorCode ec;
+ int32_t expectedSize = 0;
+ int32_t itemCount = uset_getItemCount(set);
+ int32_t itemIndex = 0;
+ UChar32 start = 1, end = 0;
+ int32_t itemLen = 0, length;
+
+ ec = U_ZERO_ERROR;
+ length = uset_toPattern(set, ustr, sizeof(ustr), TRUE, &ec);
+ if (U_FAILURE(ec)) {
+ log_err("FAIL: uset_toPattern => %s\n", u_errorName(ec));
+ return;
+ }
+ pat=aescstrdup(ustr, length);
+
+ if (uset_isEmpty(set) != (strlen(items)==0)) {
+ log_err("FAIL: %s should return %s from isEmpty\n",
+ pat,
+ strlen(items)==0 ? "TRUE" : "FALSE");
+ }
+
+ /* Don't test patterns starting with "[^" */
+ if (u_strlen(ustr) > 2 && ustr[1] == 0x5e /*'^'*/) {
+ return;
+ }
+
+ while (*p) {
+
+ ++expectedSize;
+
+ if (start > end || start == -1) {
+ /* Fetch our next item */
+ if (itemIndex >= itemCount) {
+ log_err("FAIL: ran out of items iterating %s\n", pat);
+ return;
+ }
+
+ itemLen = uset_getItem(set, itemIndex, &start, &end,
+ itemStr, sizeof(itemStr), &ec);
+ if (U_FAILURE(ec) || itemLen < 0) {
+ log_err("FAIL: uset_getItem => %s\n", u_errorName(ec));
+ return;
+ }
+
+ if (itemLen == 0) {
+ log_verbose("Ok: %s item %d is %c-%c\n", pat,
+ itemIndex, oneUCharToChar(start),
+ oneUCharToChar(end));
+ } else {
+ itemStr[itemLen] = 0;
+ u_UCharsToChars(itemStr, buf, itemLen+1);
+ log_verbose("Ok: %s item %d is \"%s\"\n", pat, itemIndex, buf);
+ }
+
+ ++itemIndex;
+ }
+
+ if (*p=='{') {
+ const char* stringStart = ++p;
+ int32_t stringLength = 0;
+ char strCopy[64];
+
+ while (*p++ != '}') {
+ }
+ stringLength = (int32_t)(p - stringStart - 1);
+ strncpy(strCopy, stringStart, stringLength);
+ strCopy[stringLength] = 0;
+
+ u_charsToUChars(stringStart, ustr, stringLength);
+ ustr[stringLength] = 0;
+
+ if (itemLen == 0) {
+ log_err("FAIL: for %s expect \"%s\" next, but got a char\n",
+ pat, strCopy);
+ return;
+ }
+
+ if (u_strcmp(ustr, itemStr) != 0) {
+ log_err("FAIL: for %s expect \"%s\" next\n",
+ pat, strCopy);
+ return;
+ }
+ }
+
+ else {
+ UChar32 c;
+
+ u_charsToUChars(p, ustr, 1);
+ c = ustr[0];
+
+ if (itemLen != 0) {
+ log_err("FAIL: for %s expect '%c' next, but got a string\n",
+ pat, *p);
+ return;
+ }
+
+ if (c != start++) {
+ log_err("FAIL: for %s expect '%c' next\n",
+ pat, *p);
+ return;
+ }
+
+ ++p;
+ }
+ }
+
+ if (uset_size(set) == expectedSize) {
+ log_verbose("Ok: %s size is %d\n", pat, expectedSize);
+ } else {
+ log_err("FAIL: %s size is %d, expected %d\n",
+ pat, uset_size(set), expectedSize);
+ }
+}
+
+static void
+TestSerialized() {
+ uint16_t buffer[1000];
+ USerializedSet sset;
+ USet *set;
+ UErrorCode errorCode;
+ UChar32 c;
+ int32_t length;
+
+ /* use a pattern that generates both BMP and supplementary code points */
+ U_STRING_DECL(pattern, "[:Cf:]", 6);
+ U_STRING_INIT(pattern, "[:Cf:]", 6);
+
+ errorCode=U_ZERO_ERROR;
+ set=uset_openPattern(pattern, -1, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("uset_openPattern([:Cf:]) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ length=uset_serialize(set, buffer, LENGTHOF(buffer), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("unable to uset_serialize([:Cf:]) - %s\n", u_errorName(errorCode));
+ uset_close(set);
+ return;
+ }
+
+ uset_getSerializedSet(&sset, buffer, length);
+ for(c=0; c<=0x10ffff; ++c) {
+ if(uset_contains(set, c)!=uset_serializedContains(&sset, c)) {
+ log_err("uset_contains(U+%04x)!=uset_serializedContains(U+%04x)\n", c);
+ break;
+ }
+ }
+
+ uset_close(set);
+}
+
+/**
+ * Make sure that when non-invariant chars are passed to uset_openPattern
+ * they do not cause an ugly failure mode (e.g. assertion failure).
+ * JB#3795.
+ */
+static void
+TestNonInvariantPattern() {
+ UErrorCode ec = U_ZERO_ERROR;
+ /* The critical part of this test is that the following pattern
+ must contain a non-invariant character. */
+ static const char *pattern = "[:ccc!=0:]";
+ UChar buf[256];
+ int32_t len = u_unescape(pattern, buf, 256);
+ /* This test 'fails' by having an assertion failure within the
+ following call. It passes by running to completion with no
+ assertion failure. */
+ USet *set = uset_openPattern(buf, len, &ec);
+ uset_close(set);
+}
+
+static void TestBadPattern(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ USet *pat;
+ U_STRING_DECL(pattern, "[", 1);
+ U_STRING_INIT(pattern, "[", 1);
+ pat = uset_openPatternOptions(pattern, u_strlen(pattern), 0, &status);
+ if (pat != NULL || U_SUCCESS(status)) {
+ log_err("uset_openPatternOptions did not fail as expected %s\n", u_errorName(status));
+ }
+}
+
+static USet *openIDSet() {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ U_STRING_DECL(pattern, "[:ID_Continue:]", 15);
+ U_STRING_INIT(pattern, "[:ID_Continue:]", 15);
+ return uset_openPattern(pattern, 15, &errorCode);
+}
+
+static void TestFreezable() {
+ USet *idSet;
+ USet *frozen;
+ USet *thawed;
+
+ idSet=openIDSet();
+
+ if (idSet == NULL) {
+ log_err("openIDSet() returned NULL");
+ uset_close(idSet);
+ return;
+ }
+
+ frozen=uset_clone(idSet);
+
+ if (frozen == NULL) {
+ log_err("uset_Clone() returned NULL");
+ return;
+ }
+
+ if(!uset_equals(frozen, idSet)) {
+ log_err("uset_clone() did not make an equal copy\n");
+ }
+
+ uset_freeze(frozen);
+ uset_addRange(frozen, 0xd802, 0xd805);
+
+ if(uset_isFrozen(idSet) || !uset_isFrozen(frozen) || !uset_equals(frozen, idSet)) {
+ log_err("uset_freeze() or uset_isFrozen() does not work\n");
+ }
+
+ thawed=uset_cloneAsThawed(frozen);
+
+ if (thawed == NULL) {
+ log_err("uset_cloneAsThawed(frozen) returned NULL");
+ uset_close(frozen);
+ uset_close(idSet);
+ return;
+ }
+
+ uset_addRange(thawed, 0xd802, 0xd805);
+
+ if(uset_isFrozen(thawed) || uset_equals(thawed, idSet) || !uset_containsRange(thawed, 0xd802, 0xd805)) {
+ log_err("uset_cloneAsThawed() does not work\n");
+ }
+
+ uset_close(idSet);
+ uset_close(frozen);
+ uset_close(thawed);
+}
+
+static void TestSpan() {
+ static const UChar s16[2]={ 0xe01, 0x3000 };
+ static const char* s8="\xE0\xB8\x81\xE3\x80\x80";
+
+ USet *idSet=openIDSet();
+
+ if (idSet == NULL) {
+ log_err("openIDSet() returned NULL");
+ return;
+ }
+
+ if(
+ 1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) ||
+ 0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) ||
+ 2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) ||
+ 1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED)
+ ) {
+ log_err("uset_span() or uset_spanBack() does not work\n");
+ }
+
+ if(
+ 3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
+ 0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) ||
+ 6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
+ 3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED)
+ ) {
+ log_err("uset_spanUTF8() or uset_spanBackUTF8() does not work\n");
+ }
+
+ uset_freeze(idSet);
+
+ if(
+ 1!=uset_span(idSet, s16, 2, USET_SPAN_CONTAINED) ||
+ 0!=uset_span(idSet, s16, 2, USET_SPAN_NOT_CONTAINED) ||
+ 2!=uset_spanBack(idSet, s16, 2, USET_SPAN_CONTAINED) ||
+ 1!=uset_spanBack(idSet, s16, 2, USET_SPAN_NOT_CONTAINED)
+ ) {
+ log_err("uset_span(frozen) or uset_spanBack(frozen) does not work\n");
+ }
+
+ if(
+ 3!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
+ 0!=uset_spanUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED) ||
+ 6!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_CONTAINED) ||
+ 3!=uset_spanBackUTF8(idSet, s8, 6, USET_SPAN_NOT_CONTAINED)
+ ) {
+ log_err("uset_spanUTF8(frozen) or uset_spanBackUTF8(frozen) does not work\n");
+ }
+
+ uset_close(idSet);
+}
+
+/*eof*/
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c
new file mode 100644
index 00000000000..7f79e770db9
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchdat.c
@@ -0,0 +1,498 @@
+/********************************************************************
+ * Copyright (c) 2001-2007 International Business Machines
+ * Corporation and others. All Rights Reserved.
+ ********************************************************************
+ * File USRCHDAT.H
+ * Modification History:
+ * Name date Description
+ * synwee July 31 2001 creation
+ ********************************************************************/
+
+
+/*
+Note: This file is included by other C and C++ files. This file should not be directly compiled.
+*/
+#ifndef USRCHDAT_C
+#define USRCHDAT_C
+
+#include "unicode/ucol.h"
+
+#if !UCONFIG_NO_COLLATION
+
+U_CDECL_BEGIN
+struct SearchData {
+ const char *text;
+ const char *pattern;
+ const char *collator;
+ UCollationStrength strength;
+ const char *breaker;
+ int8_t offset[32];
+ uint8_t size[32];
+};
+U_CDECL_END
+
+typedef struct SearchData SearchData;
+
+static const char *TESTCOLLATORRULE = "& o,O ; p,P";
+
+static const char *EXTRACOLLATIONRULE = " & ae ; \\u00e4 & AE ; \\u00c4 & oe ; \\u00f6 & OE ; \\u00d6 & ue ; \\u00fc & UE ; \\u00dc";
+
+static const SearchData BASIC[] = {
+ {"xxxxxxxxxxxxxxxxxxxx", "fisher", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"silly spring string", "string", NULL, UCOL_TERTIARY, NULL, {13, -1},
+ {6}},
+ {"silly spring string string", "string", NULL, UCOL_TERTIARY, NULL,
+ {13, 20, -1}, {6, 6}},
+ {"silly string spring string", "string", NULL, UCOL_TERTIARY, NULL,
+ {6, 20, -1}, {6, 6}},
+ {"string spring string", "string", NULL, UCOL_TERTIARY, NULL, {0, 14, -1},
+ {6, 6}},
+ {"Scott Ganyo", "c", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"Scott Ganyo", " ", NULL, UCOL_TERTIARY, NULL, {5, -1}, {1}},
+ {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ {"a\\u0300b", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"\\u00c9", "e", NULL, UCOL_PRIMARY, NULL, {0, -1}, {1}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData BREAKITERATOREXACT[] = {
+ {"foxy fox", "fox", NULL, UCOL_TERTIARY, "characterbreaker", {0, 5, -1},
+ {3, 3}},
+ {"foxy fox", "fox", NULL, UCOL_TERTIARY, "wordbreaker", {5, -1}, {3}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY,
+ "characterbreaker", {10, 14, -1}, {3, 2}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, "wordbreaker",
+ {10, -1}, {3}},
+ {"Channel, another channel, more channels, and one last Channel",
+ "Channel", "es", UCOL_TERTIARY, "wordbreaker", {0, 54, -1}, {7, 7}},
+ /* jitterbug 1745 */
+ {"testing that \\u00e9 does not match e", "e", NULL, UCOL_TERTIARY,
+ "characterbreaker", {1, 17, 30, -1}, {1, 1, 1}},
+ {"testing that string ab\\u00e9cd does not match e", "e", NULL,
+ UCOL_TERTIARY, "characterbreaker", {1, 28, 41, -1}, {1, 1, 1}},
+ {"\\u00c9", "e", "fr", UCOL_PRIMARY, "characterbreaker", {0, -1}, {1}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData STRENGTH[] = {
+ /*012345678901234567890123456789012345678901234567890123456789*/
+ {"The quick brown fox jumps over the lazy foxes", "fox", "en",
+ UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}},
+ {"The quick brown fox jumps over the lazy foxes", "fox", "en",
+ UCOL_PRIMARY, "wordbreaker", {16, -1}, {3}},
+ {"blackbirds Pat p\\u00E9ch\\u00E9 p\\u00EAche p\\u00E9cher p\\u00EAcher Tod T\\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe",
+ "peche", "fr", UCOL_PRIMARY, NULL, {15, 21, 27, 34, -1}, {5, 5, 5, 5}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, NULL,
+ {10, 14, -1}, {3, 2}},
+ {"A channel, another CHANNEL, more Channels, and one last channel...",
+ "channel", "es", UCOL_PRIMARY, NULL, {2, 19, 33, 56, -1},
+ {7, 7, 7, 7}},
+ {"\\u00c0 should match but not A", "A\\u0300", "en", UCOL_IDENTICAL,
+ NULL, {0, -1}, {1, 0}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData VARIABLE[] = {
+ /*012345678901234567890123456789012345678901234567890123456789*/
+ {"blackbirds black blackbirds blackbird black-bird",
+ "blackbird", NULL, UCOL_TERTIARY, NULL, {0, 17, 28, 38, -1},
+ {9, 9, 9, 10}},
+ /* to see that it doesn't go into an infinite loop if the start of text
+ is a ignorable character */
+ {" on", "go", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"abcdefghijklmnopqrstuvwxyz", " ", NULL, UCOL_PRIMARY, NULL,
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ /* testing tightest match */
+ {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_QUATERNARY,
+ NULL, {1, -1}, {3}},
+ /*012345678901234567890123456789012345678901234567890123456789 */
+ {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_SECONDARY,
+ NULL, {1, 6, 13, 21, 31, -1}, {3, 4, 4, 5, 5}},
+ /* totally ignorable text */
+ {" ---------------", "abc", NULL, UCOL_SECONDARY,
+ NULL, {-1}, {0}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData NORMEXACT[] = {
+ {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData NONNORMEXACT[] = {
+ {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {-1},
+ {0}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData OVERLAP[] = {
+ {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 2, 4, -1},
+ {4, 4, 4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData NONOVERLAP[] = {
+ {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 4, -1}, {4, 4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData COLLATOR[] = {
+ /* english */
+ {"fox fpx", "fox", NULL, UCOL_TERTIARY, NULL, {0, -1}, {3}},
+ /* tailored */
+ {"fox fpx", "fox", NULL, UCOL_PRIMARY, NULL, {0, 4, -1}, {3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData PATTERN[] = {
+ {"The quick brown fox jumps over the lazy foxes", "the", NULL,
+ UCOL_PRIMARY, NULL, {0, 31, -1}, {3, 3}},
+ {"The quick brown fox jumps over the lazy foxes", "fox", NULL,
+ UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData TEXT[] = {
+ {"the foxy brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {4, 15, -1},
+ {3, 3}},
+ {"the quick brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {16, -1},
+ {3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData COMPOSITEBOUNDARIES[] = {
+ {"\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u00C0C", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}},
+ {"\\u00C0A", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}},
+ {"B\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"\\u00C0B", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0300\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, 1, -1},
+ {1, 1}},
+ {"\\u00C0\\u0300", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ /* A + 030A + 0301 */
+ {"\\u01FA", "\\u01FA", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u01FA", "\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u030AA", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "A\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u030A\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FAA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u0F73", "\\u0F73", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0F73", "\\u0F71", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u0F73", "\\u0F72", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u0F73", "\\u0F71\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u0F73", "A\\u0F71", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u0F73A", "\\u0F72A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData MATCH[] = {
+ {"a busy bee is a very busy beeee", "bee", NULL, UCOL_TERTIARY, NULL,
+ {7, 26, -1}, {3, 3}},
+ /* 012345678901234567890123456789012345678901234567890 */
+ {"a busy bee is a very busy beeee with no bee life", "bee", NULL,
+ UCOL_TERTIARY, NULL, {7, 26, 40, -1}, {3, 3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData SUPPLEMENTARY[] = {
+ /* 012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890012345678901234567890123456789 */
+ {"abc \\uD800\\uDC00 \\uD800\\uDC01 \\uD801\\uDC00 \\uD800\\uDC00abc abc\\uD800\\uDC00 \\uD800\\uD800\\uDC00 \\uD800\\uDC00\\uDC00",
+ "\\uD800\\uDC00", NULL, UCOL_TERTIARY, NULL, {4, 13, 22, 26, 29, -1},
+ {2, 2, 2, 2, 2}},
+ {"and\\uD834\\uDDB9this sentence", "\\uD834\\uDDB9", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {2}},
+ {"and \\uD834\\uDDB9 this sentence", " \\uD834\\uDDB9 ", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and-\\uD834\\uDDB9-this sentence", "-\\uD834\\uDDB9-", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and,\\uD834\\uDDB9,this sentence", ",\\uD834\\uDDB9,", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and?\\uD834\\uDDB9?this sentence", "?\\uD834\\uDDB9?", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const char *CONTRACTIONRULE =
+ "&z = ab/c < AB < X\\u0300 < ABC < X\\u0300\\u0315";
+
+static const SearchData CONTRACTION[] = {
+ /* common discontiguous */
+ {"A\\u0300\\u0315", "\\u0300", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"A\\u0300\\u0315", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ /* contraction prefix */
+ {"AB\\u0315C", "A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"AB\\u0315C", "AB", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"AB\\u0315C", "\\u0315", NULL, UCOL_TERTIARY, NULL, {2, -1}, {1}},
+ /* discontiguous problem here for backwards iteration.
+ accents not found because discontiguous stores all information */
+ {"X\\u0300\\u0319\\u0315", "\\u0319", NULL, UCOL_TERTIARY, NULL, {-1},
+ {0}},
+ /* ends not with a contraction character */
+ {"X\\u0315\\u0300D", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {-1},
+ {0}},
+ {"X\\u0315\\u0300D", "X\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL,
+ {0, -1}, {3}},
+ {"X\\u0300\\u031A\\u0315D", "X\\u0300", NULL, UCOL_TERTIARY, NULL, {-1},
+ {0}},
+ /* blocked discontiguous */
+ {"X\\u0300\\u031A\\u0315D", "\\u031A\\u0315D", NULL, UCOL_TERTIARY, NULL,
+ {-1}, {0}},
+ {"ab", "z", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const char *IGNORABLERULE = "&a = \\u0300";
+
+static const SearchData IGNORABLE[] = {
+ {"\\u0300\\u0315 \\u0300\\u0315 ", "\\u0300", NULL, UCOL_PRIMARY, NULL,
+ {0, 3, -1}, {2, 2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData BASICCANONICAL[] = {
+ {"xxxxxxxxxxxxxxxxxxxx", "fisher", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"silly spring string", "string", NULL, UCOL_TERTIARY, NULL, {13, -1},
+ {6}},
+ {"silly spring string string", "string", NULL, UCOL_TERTIARY, NULL,
+ {13, 20, -1}, {6, 6}},
+ {"silly string spring string", "string", NULL, UCOL_TERTIARY, NULL,
+ {6, 20, -1}, {6, 6}},
+ {"string spring string", "string", NULL, UCOL_TERTIARY, NULL, {0, 14, -1},
+ {6, 6}},
+ {"Scott Ganyo", "c", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"Scott Ganyo", " ", NULL, UCOL_TERTIARY, NULL, {5, -1}, {1}},
+ {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}},
+ {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ {"a\\u0300b", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"a\\u0300\\u0325b", "\\u0300b", NULL, UCOL_TERTIARY, NULL, {1, -1}, {3}},
+ {"\\u0325\\u0300A\\u0325\\u0300", "\\u0300A\\u0300", NULL, UCOL_TERTIARY,
+ NULL, {0, -1}, {5}},
+ {"\\u0325\\u0300A\\u0325\\u0300", "\\u0325A\\u0325", NULL, UCOL_TERTIARY,
+ NULL, {0, -1}, {5}},
+ {"a\\u0300\\u0325b\\u0300\\u0325c \\u0325b\\u0300 \\u0300b\\u0325",
+ "\\u0300b\\u0325", NULL, UCOL_TERTIARY, NULL, {1, 12, -1}, {5, 3}},
+ {"\\u00c4\\u0323", "A\\u0323\\u0308", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"\\u0308\\u0323", "\\u0323\\u0308", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData NORMCANONICAL[] = {
+ {"\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"\\u0300\\u0325", "\\u0325", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"a\\u0300\\u0325", "\\u0325\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ {"a\\u0300\\u0325", "\\u0300\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ {"a\\u0300\\u0325", "\\u0325", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}},
+ {"a\\u0300\\u0325", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData BREAKITERATORCANONICAL[] = {
+ {"foxy fox", "fox", NULL, UCOL_TERTIARY, "characterbreaker", {0, 5, -1},
+ {3, 3}},
+ {"foxy fox", "fox", NULL, UCOL_TERTIARY, "wordbreaker", {5, -1}, {3}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY,
+ "characterbreaker", {10, 14, -1}, {3, 2}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, "wordbreaker",
+ {10, -1}, {3}},
+ {"Channel, another channel, more channels, and one last Channel",
+ "Channel", "es", UCOL_TERTIARY, "wordbreaker", {0, 54, -1}, {7, 7}},
+ /* jitterbug 1745 */
+ {"testing that \\u00e9 does not match e", "e", NULL, UCOL_TERTIARY,
+ "characterbreaker", {1, 17, 30, -1}, {1, 1, 1}},
+ {"testing that string ab\\u00e9cd does not match e", "e", NULL,
+ UCOL_TERTIARY, "characterbreaker", {1, 28, 41, -1}, {1, 1, 1}},
+ {"\\u00c9", "e", "fr", UCOL_PRIMARY, "characterbreaker", {0, -1}, {1}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData STRENGTHCANONICAL[] = {
+ /*012345678901234567890123456789012345678901234567890123456789 */
+ {"The quick brown fox jumps over the lazy foxes", "fox", "en",
+ UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}},
+ {"The quick brown fox jumps over the lazy foxes", "fox", "en",
+ UCOL_PRIMARY, "wordbreaker", {16, -1}, {3}},
+ {"blackbirds Pat p\\u00E9ch\\u00E9 p\\u00EAche p\\u00E9cher p\\u00EAcher Tod T\\u00F6ne black Tofu blackbirds Ton PAT toehold blackbird black-bird pat toe big Toe",
+ "peche", "fr", UCOL_PRIMARY, NULL, {15, 21, 27, 34, -1}, {5, 5, 5, 5}},
+ {"This is a toe T\\u00F6ne", "toe", "de", UCOL_PRIMARY, NULL,
+ {10, 14, -1}, {3, 2}},
+ {"A channel, another CHANNEL, more Channels, and one last channel...",
+ "channel", "es", UCOL_PRIMARY, NULL, {2, 19, 33, 56, -1},
+ {7, 7, 7, 7}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData VARIABLECANONICAL[] = {
+ /*012345678901234567890123456789012345678901234567890123456789 */
+ {"blackbirds black blackbirds blackbird black-bird",
+ "blackbird", NULL, UCOL_TERTIARY, NULL, {0, 17, 28, 38, -1},
+ {9, 9, 9, 10}},
+ /* to see that it doesn't go into an infinite loop if the start of text
+ is a ignorable character */
+ {" on", "go", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"abcdefghijklmnopqrstuvwxyz", " ", NULL, UCOL_PRIMARY, NULL,
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, -1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ /* testing tightest match */
+ {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_QUATERNARY,
+ NULL, {1, -1}, {3}},
+ /*012345678901234567890123456789012345678901234567890123456789 */
+ {" abc a bc ab c a bc ab c", "abc", NULL, UCOL_SECONDARY,
+ NULL, {1, 6, 13, 21, 31, -1}, {3, 4, 4, 5, 5}},
+ /* totally ignorable text */
+ {" ---------------", "abc", NULL, UCOL_SECONDARY,
+ NULL, {-1}, {0}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData OVERLAPCANONICAL[] = {
+ {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 2, 4, -1},
+ {4, 4, 4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData NONOVERLAPCANONICAL[] = {
+ {"abababab", "abab", NULL, UCOL_TERTIARY, NULL, {0, 4, -1}, {4, 4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData COLLATORCANONICAL[] = {
+ /* english */
+ {"fox fpx", "fox", NULL, UCOL_TERTIARY, NULL, {0, -1}, {3}},
+ /* tailored */
+ {"fox fpx", "fox", NULL, UCOL_PRIMARY, NULL, {0, 4, -1}, {3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData PATTERNCANONICAL[] = {
+ {"The quick brown fox jumps over the lazy foxes", "the", NULL,
+ UCOL_PRIMARY, NULL, {0, 31, -1}, {3, 3}},
+ {"The quick brown fox jumps over the lazy foxes", "fox", NULL,
+ UCOL_PRIMARY, NULL, {16, 40, -1}, {3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData TEXTCANONICAL[] = {
+ {"the foxy brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {4, 15, -1},
+ {3, 3}},
+ {"the quick brown fox", "fox", NULL, UCOL_TERTIARY, NULL, {16, -1},
+ {3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData COMPOSITEBOUNDARIESCANONICAL[] = {
+ {"\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u00C0C", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}},
+ {"\\u00C0A", "A", NULL, UCOL_TERTIARY, NULL, {0, 1, -1}, {1, 1}},
+ {"B\\u00C0", "A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"\\u00C0B", "A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0300\\u00C0", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, 1, -1},
+ {1, 1}},
+ /* \\u0300 blocked by \\u0300 */
+ {"\\u00C0\\u0300", "\\u0300", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ /* A + 030A + 0301 */
+ {"\\u01FA", "\\u01FA", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u01FA", "\\u030A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u01FA", "\\u030AA", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ /* blocked accent */
+ {"\\u01FA", "A\\u0301", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"\\u01FA", "\\u030A\\u0301", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u01FA", "A\\u030A", NULL, UCOL_TERTIARY, NULL, {1, -1}, {1}},
+ {"\\u01FAA", "\\u0301A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"\\u0F73", "\\u0F73", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0F73", "\\u0F71", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0F73", "\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"\\u0F73", "\\u0F71\\u0F72", NULL, UCOL_TERTIARY, NULL, {0, -1}, {1}},
+ {"A\\u0F73", "A\\u0F71", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"\\u0F73A", "\\u0F72A", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"\\u01FA A\\u0301\\u030A A\\u030A\\u0301 A\\u030A \\u01FA", "A\\u030A",
+ NULL, UCOL_TERTIARY, NULL, {0, 6, 10, 13, -1}, {1, 3, 2, 1}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData MATCHCANONICAL[] = {
+ {"a busy bee is a very busy beeee", "bee", NULL, UCOL_TERTIARY, NULL,
+ {7, 26, -1}, {3, 3}},
+ /*012345678901234567890123456789012345678901234567890 */
+ {"a busy bee is a very busy beeee with no bee life", "bee", NULL,
+ UCOL_TERTIARY, NULL, {7, 26, 40, -1}, {3, 3, 3}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData SUPPLEMENTARYCANONICAL[] = {
+ /*012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890012345678901234567890123456789 */
+ {"abc \\uD800\\uDC00 \\uD800\\uDC01 \\uD801\\uDC00 \\uD800\\uDC00abc abc\\uD800\\uDC00 \\uD800\\uD800\\uDC00 \\uD800\\uDC00\\uDC00",
+ "\\uD800\\uDC00", NULL, UCOL_TERTIARY, NULL, {4, 13, 22, 26, 29, -1},
+ {2, 2, 2, 2, 2}},
+ {"and\\uD834\\uDDB9this sentence", "\\uD834\\uDDB9", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {2}},
+ {"and \\uD834\\uDDB9 this sentence", " \\uD834\\uDDB9 ", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and-\\uD834\\uDDB9-this sentence", "-\\uD834\\uDDB9-", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and,\\uD834\\uDDB9,this sentence", ",\\uD834\\uDDB9,", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {"and?\\uD834\\uDDB9?this sentence", "?\\uD834\\uDDB9?", NULL,
+ UCOL_TERTIARY, NULL, {3, -1}, {4}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData CONTRACTIONCANONICAL[] = {
+ /* common discontiguous */
+ {"A\\u0300\\u0315", "\\u0300", NULL, UCOL_TERTIARY, NULL, {1, -1}, {2}},
+ {"A\\u0300\\u0315", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {1, -1},
+ {2}},
+ /* contraction prefix */
+ {"AB\\u0315C", "A", NULL, UCOL_TERTIARY, NULL, {-1}, {0}},
+ {"AB\\u0315C", "AB", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {"AB\\u0315C", "\\u0315", NULL, UCOL_TERTIARY, NULL, {2, -1}, {1}},
+ /* discontiguous problem here for backwards iteration.
+ forwards gives 0, 4 but backwards give 1, 3 */
+ /* {"X\\u0300\\u0319\\u0315", "\\u0319", NULL, UCOL_TERTIARY, NULL, {0, -1},
+ {4}}, */
+
+ /* ends not with a contraction character */
+ {"X\\u0315\\u0300D", "\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL, {-1},
+ {0}},
+ {"X\\u0315\\u0300D", "X\\u0300\\u0315", NULL, UCOL_TERTIARY, NULL,
+ {0, -1}, {3}},
+ {"X\\u0300\\u031A\\u0315D", "X\\u0300", NULL, UCOL_TERTIARY, NULL,
+ {0, -1}, {4}},
+ /* blocked discontiguous */
+ {"X\\u0300\\u031A\\u0315D", "\\u031A\\u0315D", NULL, UCOL_TERTIARY, NULL,
+ {1, -1}, {4}},
+ {"ab", "z", NULL, UCOL_TERTIARY, NULL, {0, -1}, {2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+static const SearchData DIACTRICMATCH[] = {
+ {"\\u03BA\\u03B1\\u03B9\\u0300\\u0020\\u03BA\\u03B1\\u1F76", "\\u03BA\\u03B1\\u03B9", NULL, UCOL_PRIMARY, NULL, {0, 5,-1}, {4, 3}},
+ {"\\u0061\\u0061\\u00E1", "\\u0061\\u00E1", NULL, UCOL_SECONDARY, NULL, {1, -1}, {2}},
+ {"\\u0020\\u00C2\\u0303\\u0020\\u0041\\u0061\\u1EAA\\u0041\\u0302\\u0303\\u00C2\\u0303\\u1EAB\\u0061\\u0302\\u0303\\u00E2\\u0303\\uD806\\uDC01\\u0300\\u0020",
+ "\\u00C2\\u0303", "LDE_AN_CX_EX_FX_HX_NX_S1", UCOL_PRIMARY, NULL, {1, 4, 5, 6, 7, 10, 12, 13, 16,-1}, {2, 1, 1, 1, 3, 2, 1, 3, 2}},
+ {NULL, NULL, NULL, UCOL_TERTIARY, NULL, {-1}, {0}}
+};
+
+#endif /* #if !UCONFIG_NO_COLLATION */
+
+#endif
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c
new file mode 100644
index 00000000000..80a9f9247da
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/usrchtst.c
@@ -0,0 +1,2249 @@
+/********************************************************************
+ * Copyright (c) 2001-2007 International Business Machines
+ * Corporation and others. All Rights Reserved.
+ ********************************************************************
+ * File usrchtst.c
+ * Modification History:
+ * Name Date Description
+ * synwee July 19 2001 creation
+ ********************************************************************/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_COLLATION
+
+#include "unicode/usearch.h"
+#include "unicode/ustring.h"
+#include "ccolltst.h"
+#include "cmemory.h"
+#include <stdio.h>
+#include "usrchdat.c"
+#include "unicode/ubrk.h"
+
+static UBool TOCLOSE_ = TRUE;
+static UCollator *EN_US_;
+static UCollator *FR_FR_;
+static UCollator *DE_;
+static UCollator *ES_;
+
+/**
+ * CHECK_BREAK(char *brk)
+ * Test if a break iterator is passed in AND break iteration is disabled.
+ * Skip the test if so.
+ * CHECK_BREAK_BOOL(char *brk)
+ * Same as above, but returns 'TRUE' as a passing result
+ */
+
+#if !UCONFIG_NO_BREAK_ITERATION
+static UBreakIterator *EN_WORDBREAKER_;
+static UBreakIterator *EN_CHARACTERBREAKER_;
+#define CHECK_BREAK(x)
+#define CHECK_BREAK_BOOL(x)
+#else
+#define CHECK_BREAK(x) if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return; }
+#define CHECK_BREAK_BOOL(x) if(x) { log_info("Skipping test on %s:%d because UCONFIG_NO_BREAK_ITERATION is on\n", __FILE__, __LINE__); return TRUE; }
+#endif
+
+/**
+* Opening all static collators and break iterators
+*/
+static void open(void)
+{
+ if (TOCLOSE_) {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar rules[1024];
+ int32_t rulelength = 0;
+
+ EN_US_ = ucol_open("en_US", &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator\n");
+ return;
+ }
+ FR_FR_ = ucol_open("fr_FR", &status);
+ DE_ = ucol_open("de_DE", &status);
+ ES_ = ucol_open("es_ES", &status);
+
+ u_strcpy(rules, ucol_getRules(DE_, &rulelength));
+ u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength);
+
+ ucol_close(DE_);
+
+ DE_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY,
+ (UParseError *)NULL, &status);
+ u_strcpy(rules, ucol_getRules(ES_, &rulelength));
+ u_unescape(EXTRACOLLATIONRULE, rules + rulelength, 1024 - rulelength);
+
+ ucol_close(ES_);
+ ES_ = ucol_openRules(rules, u_strlen(rules), UCOL_ON, UCOL_TERTIARY,
+ NULL, &status);
+#if !UCONFIG_NO_BREAK_ITERATION
+ EN_WORDBREAKER_ = ubrk_open(UBRK_WORD, "en_US", NULL, 0, &status);
+ EN_CHARACTERBREAKER_ = ubrk_open(UBRK_CHARACTER, "en_US", NULL, 0,
+ &status);
+#endif
+ TOCLOSE_ = TRUE;
+ }
+}
+
+/**
+* Start opening all static collators and break iterators
+*/
+static void TestStart(void)
+{
+ open();
+ TOCLOSE_ = FALSE;
+}
+
+/**
+* Closing all static collators and break iterators
+*/
+static void close(void)
+{
+ if (TOCLOSE_) {
+ ucol_close(EN_US_);
+ ucol_close(FR_FR_);
+ ucol_close(DE_);
+ ucol_close(ES_);
+#if !UCONFIG_NO_BREAK_ITERATION
+ ubrk_close(EN_WORDBREAKER_);
+ ubrk_close(EN_CHARACTERBREAKER_);
+#endif
+ }
+ TOCLOSE_ = FALSE;
+}
+
+/**
+* End closing all static collators and break iterators
+*/
+static void TestEnd(void)
+{
+ TOCLOSE_ = TRUE;
+ close();
+ TOCLOSE_ = TRUE;
+}
+
+/**
+* output UChar strings for printing.
+*/
+static char *toCharString(const UChar* unichars)
+{
+ static char result[1024];
+ char *temp = result;
+ int count = 0;
+ int length = u_strlen(unichars);
+
+ for (; count < length; count ++) {
+ UChar ch = unichars[count];
+ if (ch >= 0x20 && ch <= 0x7e) {
+ *temp ++ = (char)ch;
+ }
+ else {
+ sprintf(temp, "\\u%04x", ch);
+ temp += 6; /* \uxxxx */
+ }
+ }
+ *temp = 0;
+
+ return result;
+}
+
+/**
+* Getting the collator
+*/
+static UCollator *getCollator(const char *collator)
+{
+ if (collator == NULL) {
+ return EN_US_;
+ }
+ if (strcmp(collator, "fr") == 0) {
+ return FR_FR_;
+ }
+ else if (strcmp(collator, "de") == 0) {
+ return DE_;
+ }
+ else if (strcmp(collator, "es") == 0) {
+ return ES_;
+ }
+ else {
+ return EN_US_;
+ }
+}
+
+/**
+* Getting the breakiterator
+*/
+static UBreakIterator *getBreakIterator(const char *breaker)
+{
+ if (breaker == NULL) {
+ return NULL;
+ }
+#if !UCONFIG_NO_BREAK_ITERATION
+ if (strcmp(breaker, "wordbreaker") == 0) {
+ return EN_WORDBREAKER_;
+ }
+ else {
+ return EN_CHARACTERBREAKER_;
+ }
+#else
+ return NULL;
+#endif
+}
+
+static void TestOpenClose(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *result;
+ const UChar pattern[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
+ const UChar text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67};
+#if !UCONFIG_NO_BREAK_ITERATION
+ UBreakIterator *breakiter = ubrk_open(UBRK_WORD, "en_US",
+ text, 6, &status);
+#endif
+ /* testing null arguments */
+ result = usearch_open(NULL, 0, NULL, 0, NULL, NULL, &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+ status = U_ZERO_ERROR;
+ result = usearch_openFromCollator(NULL, 0, NULL, 0, NULL, NULL, &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+
+ status = U_ZERO_ERROR;
+ result = usearch_open(pattern, 3, NULL, 0, NULL, NULL, &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+ status = U_ZERO_ERROR;
+ result = usearch_openFromCollator(pattern, 3, NULL, 0, NULL, NULL,
+ &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+
+ status = U_ZERO_ERROR;
+ result = usearch_open(pattern, 3, text, 6, NULL, NULL, &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+ status = U_ZERO_ERROR;
+ result = usearch_openFromCollator(pattern, 3, text, 6, NULL, NULL,
+ &status);
+ if (U_SUCCESS(status) || result != NULL) {
+ log_err("Error: NULL arguments should produce an error and a NULL result\n");
+ }
+
+ status = U_ZERO_ERROR;
+ result = usearch_open(pattern, 3, text, 6, "en_US", NULL, &status);
+ if (U_FAILURE(status) || result == NULL) {
+ log_err("Error: NULL break iterator is valid for opening search\n");
+ }
+ else {
+ usearch_close(result);
+ }
+ open();
+ status = U_ZERO_ERROR;
+ result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, NULL,
+ &status);
+ if (U_FAILURE(status) || result == NULL) {
+ log_err("Error: NULL break iterator is valid for opening search\n");
+ }
+ else {
+ usearch_close(result);
+ }
+
+
+ status = U_ZERO_ERROR;
+#if !UCONFIG_NO_BREAK_ITERATION
+
+ result = usearch_open(pattern, 3, text, 6, "en_US", breakiter, &status);
+ if (U_FAILURE(status) || result == NULL) {
+ log_err("Error: Break iterator is valid for opening search\n");
+ }
+ else {
+ usearch_close(result);
+ }
+ status = U_ZERO_ERROR;
+ result = usearch_openFromCollator(pattern, 3, text, 6, EN_US_, breakiter,
+ &status);
+ if (U_FAILURE(status) || result == NULL) {
+ log_err("Error: Break iterator is valid for opening search\n");
+ }
+ else {
+ usearch_close(result);
+ }
+ ubrk_close(breakiter);
+#endif
+ close();
+}
+
+static void TestInitialization(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[512];
+ const UChar text[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
+ int32_t i = 0;
+ UStringSearch *result;
+
+ /* simple test on the pattern ce construction */
+ pattern[0] = 0x41;
+ pattern[1] = 0x42;
+ open();
+ result = usearch_openFromCollator(pattern, 2, text, 3, EN_US_, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening search %s\n", u_errorName(status));
+ }
+ usearch_close(result);
+
+ /* testing if an extremely large pattern will fail the initialization */
+ for(i = 0; i < 512; i++) {
+ pattern[i] = 0x41;
+ }
+ /*uprv_memset(pattern, 0x41, 512);*/
+ result = usearch_openFromCollator(pattern, 512, text, 3, EN_US_, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening search %s\n", u_errorName(status));
+ }
+ usearch_close(result);
+ close();
+}
+
+static UBool assertEqualWithUStringSearch( UStringSearch *strsrch,
+ const SearchData search)
+{
+ int count = 0;
+ int matchlimit = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t matchindex = search.offset[count];
+ int32_t textlength;
+ UChar matchtext[128];
+
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
+ usearch_getMatchedLength(strsrch) != 0) {
+ log_err("Error with the initialization of match start and length\n");
+ }
+ /* start of following matches */
+ while (U_SUCCESS(status) && matchindex >= 0) {
+ uint32_t matchlength = search.size[count];
+ usearch_next(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error following match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return FALSE;
+ }
+ count ++;
+
+ if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
+ (int32_t) matchlength || U_FAILURE(status) ||
+ memcmp(matchtext,
+ usearch_getText(strsrch, &textlength) + matchindex,
+ matchlength * sizeof(UChar)) != 0) {
+ log_err("Error getting following matched text\n");
+ }
+
+ matchindex = search.offset[count];
+ }
+ usearch_next(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
+ usearch_getMatchedLength(strsrch) != 0) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error following match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return FALSE;
+ }
+ /* start of preceding matches */
+ count = count == 0 ? 0 : count - 1;
+ matchlimit = count;
+ matchindex = search.offset[count];
+
+ while (U_SUCCESS(status) && matchindex >= 0) {
+ uint32_t matchlength = search.size[count];
+ usearch_previous(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error preceding match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return FALSE;
+ }
+
+ if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
+ (int32_t) matchlength || U_FAILURE(status) ||
+ memcmp(matchtext,
+ usearch_getText(strsrch, &textlength) + matchindex,
+ matchlength * sizeof(UChar)) != 0) {
+ log_err("Error getting preceding matched text\n");
+ }
+
+ matchindex = count > 0 ? search.offset[count - 1] : -1;
+ count --;
+ }
+ usearch_previous(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
+ usearch_getMatchedLength(strsrch) != 0) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error preceding match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static UBool assertEqual(const SearchData search)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UCollator *collator = getCollator(search.collator);
+ UBreakIterator *breaker = getBreakIterator(search.breaker);
+ UStringSearch *strsrch;
+
+ CHECK_BREAK_BOOL(search.breaker);
+
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ ucol_setStrength(collator, search.strength);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ breaker, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ return FALSE;
+ }
+
+ if (!assertEqualWithUStringSearch(strsrch, search)) {
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return FALSE;
+ }
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return TRUE;
+}
+
+static UBool assertCanonicalEqual(const SearchData search)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UCollator *collator = getCollator(search.collator);
+ UBreakIterator *breaker = getBreakIterator(search.breaker);
+ UStringSearch *strsrch;
+
+ CHECK_BREAK_BOOL(search.breaker);
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ ucol_setStrength(collator, search.strength);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ breaker, &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ return FALSE;
+ }
+
+ if (!assertEqualWithUStringSearch(strsrch, search)) {
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return FALSE;
+ }
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return TRUE;
+}
+
+static UBool assertEqualWithAttribute(const SearchData search,
+ USearchAttributeValue canonical,
+ USearchAttributeValue overlap)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UCollator *collator = getCollator(search.collator);
+ UBreakIterator *breaker = getBreakIterator(search.breaker);
+ UStringSearch *strsrch;
+
+ CHECK_BREAK_BOOL(search.breaker);
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ ucol_setStrength(collator, search.strength);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ breaker, &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, canonical,
+ &status);
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, overlap, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ return FALSE;
+ }
+
+ if (!assertEqualWithUStringSearch(strsrch, search)) {
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return FALSE;
+ }
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ return TRUE;
+}
+
+static void TestBasic(void)
+{
+ int count = 0;
+ open();
+ while (BASIC[count].text != NULL) {
+ if (!assertEqual(BASIC[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestNormExact(void)
+{
+ int count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ open();
+ ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting collation normalization %s\n",
+ u_errorName(status));
+ }
+ while (BASIC[count].text != NULL) {
+ if (!assertEqual(BASIC[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ count = 0;
+ while (NORMEXACT[count].text != NULL) {
+ if (!assertEqual(NORMEXACT[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
+ count = 0;
+ while (NONNORMEXACT[count].text != NULL) {
+ if (!assertEqual(NONNORMEXACT[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestStrength(void)
+{
+ int count = 0;
+ open();
+ while (STRENGTH[count].text != NULL) {
+ if (!assertEqual(STRENGTH[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestBreakIterator(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *strsrch;
+ UChar text[128];
+ UChar pattern[32];
+ int count = 0;
+
+ CHECK_BREAK("x");
+
+#if !UCONFIG_NO_BREAK_ITERATION
+ open();
+ if (usearch_getBreakIterator(NULL) != NULL) {
+ log_err("Expected NULL breakiterator from NULL string search\n");
+ }
+ u_unescape(BREAKITERATOREXACT[0].text, text, 128);
+ u_unescape(BREAKITERATOREXACT[0].pattern, pattern, 32);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ goto ENDTESTBREAKITERATOR;
+ }
+
+ usearch_setBreakIterator(strsrch, NULL, &status);
+ if (U_FAILURE(status) || usearch_getBreakIterator(strsrch) != NULL) {
+ log_err("Error usearch_getBreakIterator returned wrong object");
+ goto ENDTESTBREAKITERATOR;
+ }
+
+ usearch_setBreakIterator(strsrch, EN_CHARACTERBREAKER_, &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != EN_CHARACTERBREAKER_) {
+ log_err("Error usearch_getBreakIterator returned wrong object");
+ goto ENDTESTBREAKITERATOR;
+ }
+
+ usearch_setBreakIterator(strsrch, EN_WORDBREAKER_, &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != EN_WORDBREAKER_) {
+ log_err("Error usearch_getBreakIterator returned wrong object");
+ goto ENDTESTBREAKITERATOR;
+ }
+
+ usearch_close(strsrch);
+
+ count = 0;
+ while (count < 4) {
+ /* 0-3 test are fixed */
+ const SearchData *search = &(BREAKITERATOREXACT[count]);
+ UCollator *collator = getCollator(search->collator);
+ UBreakIterator *breaker = getBreakIterator(search->breaker);
+
+ u_unescape(search->text, text, 128);
+ u_unescape(search->pattern, pattern, 32);
+ ucol_setStrength(collator, search->strength);
+
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ breaker, &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != breaker) {
+ log_err("Error setting break iterator\n");
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ }
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ goto ENDTESTBREAKITERATOR;
+ }
+ search = &(BREAKITERATOREXACT[count + 1]);
+ breaker = getBreakIterator(search->breaker);
+ usearch_setBreakIterator(strsrch, breaker, &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != breaker) {
+ log_err("Error setting break iterator\n");
+ usearch_close(strsrch);
+ goto ENDTESTBREAKITERATOR;
+ }
+ usearch_reset(strsrch);
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ log_err("Error at test number %d\n", count);
+ goto ENDTESTBREAKITERATOR;
+ }
+ usearch_close(strsrch);
+ count += 2;
+ }
+ count = 0;
+ while (BREAKITERATOREXACT[count].text != NULL) {
+ if (!assertEqual(BREAKITERATOREXACT[count])) {
+ log_err("Error at test number %d\n", count);
+ goto ENDTESTBREAKITERATOR;
+ }
+ count ++;
+ }
+
+ENDTESTBREAKITERATOR:
+ close();
+#endif
+}
+
+static void TestVariable(void)
+{
+ int count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ open();
+ ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting collation alternate attribute %s\n",
+ u_errorName(status));
+ }
+ while (VARIABLE[count].text != NULL) {
+ log_verbose("variable %d\n", count);
+ if (!assertEqual(VARIABLE[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
+ UCOL_NON_IGNORABLE, &status);
+ close();
+}
+
+static void TestOverlap(void)
+{
+ int count = 0;
+ open();
+ while (OVERLAP[count].text != NULL) {
+ if (!assertEqualWithAttribute(OVERLAP[count], USEARCH_OFF,
+ USEARCH_ON)) {
+ log_err("Error at overlap test number %d\n", count);
+ }
+ count ++;
+ }
+ count = 0;
+ while (NONOVERLAP[count].text != NULL) {
+ if (!assertEqual(NONOVERLAP[count])) {
+ log_err("Error at non overlap test number %d\n", count);
+ }
+ count ++;
+ }
+
+ count = 0;
+ while (count < 1) {
+ UChar pattern[32];
+ UChar text[128];
+ const SearchData *search = &(OVERLAP[count]);
+ UCollator *collator = getCollator(search->collator);
+ UStringSearch *strsrch;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_unescape(search->text, text, 128);
+ u_unescape(search->pattern, pattern, 32);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
+ log_err("Error setting overlap option\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ usearch_close(strsrch);
+ return;
+ }
+ search = &(NONOVERLAP[count]);
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
+ log_err("Error setting overlap option\n");
+ }
+ usearch_reset(strsrch);
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ usearch_close(strsrch);
+ log_err("Error at test number %d\n", count);
+ }
+
+ count ++;
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestCollator(void)
+{
+ /* test collator that thinks "o" and "p" are the same thing */
+ UChar rules[32];
+ UCollator *tailored = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UStringSearch *strsrch;
+
+ text[0] = 0x41;
+ text[1] = 0x42;
+ text[2] = 0x43;
+ text[3] = 0x44;
+ text[4] = 0x45;
+ pattern[0] = 0x62;
+ pattern[1] = 0x63;
+ strsrch = usearch_open(pattern, 2, text, 5, "en_US", NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+ tailored = usearch_getCollator(strsrch);
+ if (usearch_next(strsrch, &status) != -1) {
+ log_err("Error: Found case insensitive match, when we shouldn't\n");
+ }
+ ucol_setStrength(tailored, UCOL_PRIMARY);
+ usearch_reset(strsrch);
+ if (usearch_next(strsrch, &status) != 1) {
+ log_err("Error: Found case insensitive match not found\n");
+ }
+ usearch_close(strsrch);
+
+ open();
+
+ if (usearch_getCollator(NULL) != NULL) {
+ log_err("Expected NULL collator from NULL string search\n");
+ }
+ u_unescape(COLLATOR[0].text, text, 128);
+ u_unescape(COLLATOR[0].pattern, pattern, 32);
+
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ u_unescape(TESTCOLLATORRULE, rules, 32);
+ tailored = ucol_openRules(rules, -1, UCOL_ON, COLLATOR[1].strength,
+ NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening rule based collator %s\n", u_errorName(status));
+ }
+
+ usearch_setCollator(strsrch, tailored, &status);
+ if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
+ log_err("Error setting rule based collator\n");
+ }
+ usearch_reset(strsrch);
+ if (!assertEqualWithUStringSearch(strsrch, COLLATOR[1])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ usearch_setCollator(strsrch, EN_US_, &status);
+ usearch_reset(strsrch);
+ if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
+ log_err("Error setting rule based collator\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, COLLATOR[0])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ENDTESTCOLLATOR:
+ usearch_close(strsrch);
+ if (tailored != NULL) {
+ ucol_close(tailored);
+ }
+ close();
+}
+
+static void TestPattern(void)
+{
+ UStringSearch *strsrch;
+ UChar pattern[32];
+ UChar bigpattern[512];
+ UChar text[128];
+ const UChar *temp;
+ int32_t templength;
+ UErrorCode status = U_ZERO_ERROR;
+
+ open();
+ if (usearch_getPattern(NULL, &templength) != NULL) {
+ log_err("Error NULL string search expected returning NULL pattern\n");
+ }
+ usearch_setPattern(NULL, pattern, 3, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expected setting pattern in NULL strings search\n");
+ }
+ status = U_ZERO_ERROR;
+ u_unescape(PATTERN[0].text, text, 128);
+ u_unescape(PATTERN[0].pattern, pattern, 32);
+
+ ucol_setStrength(EN_US_, PATTERN[0].strength);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+
+ status = U_ZERO_ERROR;
+ usearch_setPattern(strsrch, NULL, 3, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expected setting NULL pattern in strings search\n");
+ }
+ status = U_ZERO_ERROR;
+ usearch_setPattern(strsrch, pattern, 0, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expected setting pattern with length 0 in strings search\n");
+ }
+ status = U_ZERO_ERROR;
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ goto ENDTESTPATTERN;
+ }
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(PATTERN[1].pattern, pattern, 32);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ goto ENDTESTPATTERN;
+ }
+ usearch_reset(strsrch);
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERN[1])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(PATTERN[0].pattern, pattern, 32);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ goto ENDTESTPATTERN;
+ }
+ usearch_reset(strsrch);
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERN[0])) {
+ goto ENDTESTPATTERN;
+ }
+ /* enormous pattern size to see if this crashes */
+ for (templength = 0; templength != 512; templength ++) {
+ bigpattern[templength] = 0x61;
+ }
+ bigpattern[511] = 0;
+ usearch_setPattern(strsrch, bigpattern, -1, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern with size 512, %s \n",
+ u_errorName(status));
+ }
+ENDTESTPATTERN:
+ ucol_setStrength(EN_US_, UCOL_TERTIARY);
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestText(void)
+{
+ UStringSearch *strsrch;
+ UChar pattern[32];
+ UChar text[128];
+ const UChar *temp;
+ int32_t templength;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_unescape(TEXT[0].text, text, 128);
+ u_unescape(TEXT[0].pattern, pattern, 32);
+
+ open();
+
+ if (usearch_getText(NULL, &templength) != NULL) {
+ log_err("Error NULL string search should return NULL text\n");
+ }
+
+ usearch_setText(NULL, text, 10, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error NULL string search should have an error when setting text\n");
+ }
+
+ status = U_ZERO_ERROR;
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ goto ENDTESTPATTERN;
+ }
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(TEXT[1].text, text, 32);
+ usearch_setText(strsrch, text, -1, &status);
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ goto ENDTESTPATTERN;
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error setting text %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXT[1])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(TEXT[0].text, text, 32);
+ usearch_setText(strsrch, text, -1, &status);
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ goto ENDTESTPATTERN;
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXT[0])) {
+ goto ENDTESTPATTERN;
+ }
+ENDTESTPATTERN:
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestCompositeBoundaries(void)
+{
+ int count = 0;
+ open();
+ while (COMPOSITEBOUNDARIES[count].text != NULL) {
+ log_verbose("composite %d\n", count);
+ if (!assertEqual(COMPOSITEBOUNDARIES[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestGetSetOffset(void)
+{
+ int index = 0;
+ UChar pattern[32];
+ UChar text[128];
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *strsrch;
+ memset(pattern, 0, 32*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ open();
+ if (usearch_getOffset(NULL) != USEARCH_DONE) {
+ log_err("usearch_getOffset(NULL) expected USEARCH_DONE\n");
+ }
+ strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
+ &status);
+ /* testing out of bounds error */
+ usearch_setOffset(strsrch, -1, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expecting set offset error\n");
+ }
+ usearch_setOffset(strsrch, 128, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expecting set offset error\n");
+ }
+ while (BASIC[index].text != NULL) {
+ int count = 0;
+ SearchData search = BASIC[index ++];
+ int32_t matchindex = search.offset[count];
+ int32_t textlength;
+
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ status = U_ZERO_ERROR;
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ ucol_setStrength(usearch_getCollator(strsrch), search.strength);
+ usearch_reset(strsrch);
+ while (U_SUCCESS(status) && matchindex >= 0) {
+ uint32_t matchlength = search.size[count];
+ usearch_next(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch,
+ &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ usearch_setOffset(strsrch, matchindex + matchlength, &status);
+ usearch_previous(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch,
+ &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ usearch_setOffset(strsrch, matchindex + matchlength, &status);
+ matchindex = search.offset[count + 1] == -1 ? -1 :
+ search.offset[count + 2];
+ if (search.offset[count + 1] != -1) {
+ usearch_setOffset(strsrch, search.offset[count + 1] + 1,
+ &status);
+ if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
+ log_err("Error setting offset\n");
+ return;
+ }
+ }
+
+ count += 2;
+ }
+ usearch_next(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ }
+ ucol_setStrength(usearch_getCollator(strsrch), UCOL_TERTIARY);
+ usearch_close(strsrch);
+ close();
+}
+
+static void TestGetSetAttribute(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UStringSearch *strsrch;
+
+ memset(pattern, 0, 32*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ open();
+ if (usearch_getAttribute(NULL, USEARCH_OVERLAP) != USEARCH_DEFAULT ||
+ usearch_getAttribute(NULL, USEARCH_CANONICAL_MATCH) !=
+ USEARCH_DEFAULT) {
+ log_err(
+ "Attributes for NULL string search should be USEARCH_DEFAULT\n");
+ }
+ strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening search %s\n", u_errorName(status));
+ return;
+ }
+
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_DEFAULT, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
+ log_err("Error setting overlap to the default\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
+ log_err("Error setting overlap true\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
+ log_err("Error setting overlap false\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP,
+ USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error setting overlap to illegal value\n");
+ }
+ status = U_ZERO_ERROR;
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_DEFAULT,
+ &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
+ USEARCH_OFF) {
+ log_err("Error setting canonical match to the default\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
+ USEARCH_ON) {
+ log_err("Error setting canonical match true\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_OFF,
+ &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
+ USEARCH_OFF) {
+ log_err("Error setting canonical match false\n");
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH,
+ USEARCH_ATTRIBUTE_VALUE_COUNT, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error setting canonical match to illegal value\n");
+ }
+ status = U_ZERO_ERROR;
+ usearch_setAttribute(strsrch, USEARCH_ATTRIBUTE_COUNT, USEARCH_DEFAULT,
+ &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error setting illegal attribute success\n");
+ }
+
+ usearch_close(strsrch);
+ close();
+}
+
+static void TestGetMatch(void)
+{
+ int count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar text[128];
+ UChar pattern[32];
+ SearchData search = MATCH[0];
+ int32_t matchindex = search.offset[count];
+ UStringSearch *strsrch;
+ int32_t textlength;
+ UChar matchtext[128];
+
+ open();
+
+ if (usearch_getMatchedStart(NULL) != USEARCH_DONE ||
+ usearch_getMatchedLength(NULL) != USEARCH_DONE) {
+ log_err(
+ "Expected start and length of NULL string search should be USEARCH_DONE\n");
+ }
+
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ return;
+ }
+
+ while (U_SUCCESS(status) && matchindex >= 0) {
+ int32_t matchlength = search.size[count];
+ usearch_next(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ count ++;
+
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(NULL, matchtext, 128, &status) !=
+ USEARCH_DONE || U_SUCCESS(status)){
+ log_err("Error expecting errors with NULL string search\n");
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(strsrch, NULL, 0, &status) !=
+ (int32_t)matchlength || U_SUCCESS(status)){
+ log_err("Error pre-flighting match length\n");
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(strsrch, matchtext, 0, &status) !=
+ (int32_t)matchlength || U_SUCCESS(status)){
+ log_err("Error getting match text with buffer size 0\n");
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(strsrch, matchtext, matchlength, &status)
+ != (int32_t)matchlength || matchtext[matchlength - 1] == 0 ||
+ U_FAILURE(status)){
+ log_err("Error getting match text with exact size\n");
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
+ (int32_t) matchlength || U_FAILURE(status) ||
+ memcmp(matchtext,
+ usearch_getText(strsrch, &textlength) + matchindex,
+ matchlength * sizeof(UChar)) != 0 ||
+ matchtext[matchlength] != 0) {
+ log_err("Error getting matched text\n");
+ }
+
+ matchindex = search.offset[count];
+ }
+ status = U_ZERO_ERROR;
+ usearch_next(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE ||
+ usearch_getMatchedLength(strsrch) != 0) {
+ log_err("Error end of match not found\n");
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_getMatchedText(strsrch, matchtext, 128, &status) !=
+ USEARCH_DONE) {
+ log_err("Error getting null matches\n");
+ }
+ usearch_close(strsrch);
+ close();
+}
+
+static void TestSetMatch(void)
+{
+ int count = 0;
+
+ open();
+ while (MATCH[count].text != NULL) {
+ SearchData search = MATCH[count];
+ int size = 0;
+ int index = 0;
+ UChar text[128];
+ UChar pattern[32];
+ UStringSearch *strsrch;
+ UErrorCode status = U_ZERO_ERROR;
+
+ if (usearch_first(NULL, &status) != USEARCH_DONE ||
+ usearch_last(NULL, &status) != USEARCH_DONE) {
+ log_err("Error getting the first and last match of a NULL string search\n");
+ }
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ return;
+ }
+
+ size = 0;
+ while (search.offset[size] != -1) {
+ size ++;
+ }
+
+ if (usearch_first(strsrch, &status) != search.offset[0] ||
+ U_FAILURE(status)) {
+ log_err("Error getting first match\n");
+ }
+ if (usearch_last(strsrch, &status) != search.offset[size -1] ||
+ U_FAILURE(status)) {
+ log_err("Error getting last match\n");
+ }
+
+ while (index < size) {
+ if (index + 2 < size) {
+ if (usearch_following(strsrch, search.offset[index + 2] - 1,
+ &status) != search.offset[index + 2] ||
+ U_FAILURE(status)) {
+ log_err("Error getting following match at index %d\n",
+ search.offset[index + 2] - 1);
+ }
+ }
+ if (index + 1 < size) {
+ if (usearch_preceding(strsrch, search.offset[index + 1] +
+ search.size[index + 1] + 1,
+ &status) != search.offset[index + 1] ||
+ U_FAILURE(status)) {
+ log_err("Error getting preceeding match at index %d\n",
+ search.offset[index + 1] + 1);
+ }
+ }
+ index += 2;
+ }
+ status = U_ZERO_ERROR;
+ if (usearch_following(strsrch, u_strlen(text), &status) !=
+ USEARCH_DONE) {
+ log_err("Error expecting out of bounds match\n");
+ }
+ if (usearch_preceding(strsrch, 0, &status) != USEARCH_DONE) {
+ log_err("Error expecting out of bounds match\n");
+ }
+ count ++;
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestReset(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar text[] = {0x66, 0x69, 0x73, 0x68, 0x20,
+ 0x66, 0x69, 0x73, 0x68};
+ UChar pattern[] = {0x73};
+ UStringSearch *strsrch;
+
+ open();
+ strsrch = usearch_openFromCollator(pattern, 1, text, 9,
+ EN_US_, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ return;
+ }
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ usearch_setOffset(strsrch, 9, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting attributes and offsets\n");
+ }
+ else {
+ usearch_reset(strsrch);
+ if (usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF ||
+ usearch_getAttribute(strsrch, USEARCH_CANONICAL_MATCH) !=
+ USEARCH_OFF ||
+ usearch_getOffset(strsrch) != 0 ||
+ usearch_getMatchedLength(strsrch) != 0 ||
+ usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
+ log_err("Error resetting string search\n");
+ }
+ usearch_previous(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != 7 ||
+ usearch_getMatchedLength(strsrch) != 1) {
+ log_err("Error resetting string search\n");
+ }
+ }
+ usearch_close(strsrch);
+ close();
+}
+
+static void TestSupplementary(void)
+{
+ int count = 0;
+ open();
+ while (SUPPLEMENTARY[count].text != NULL) {
+ if (!assertEqual(SUPPLEMENTARY[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestContraction(void)
+{
+ UChar rules[128];
+ UChar pattern[128];
+ UChar text[128];
+ UCollator *collator;
+ UErrorCode status = U_ZERO_ERROR;
+ int count = 0;
+ UStringSearch *strsrch;
+ memset(rules, 0, 128*sizeof(UChar));
+ memset(pattern, 0, 128*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ u_unescape(CONTRACTIONRULE, rules, 128);
+ collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
+ UCOL_TERTIARY, NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator %s\n", u_errorName(status));
+ return;
+ }
+ strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ }
+
+ while (CONTRACTION[count].text != NULL) {
+ u_unescape(CONTRACTION[count].text, text, 128);
+ u_unescape(CONTRACTION[count].pattern, pattern, 128);
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ if (!assertEqualWithUStringSearch(strsrch, CONTRACTION[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ usearch_close(strsrch);
+ ucol_close(collator);
+}
+
+static void TestIgnorable(void)
+{
+ UChar rules[128];
+ UChar pattern[128];
+ UChar text[128];
+ UCollator *collator;
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *strsrch;
+ uint32_t count = 0;
+
+ memset(rules, 0, 128*sizeof(UChar));
+ memset(pattern, 0, 128*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ u_unescape(IGNORABLERULE, rules, 128);
+ collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
+ IGNORABLE[count].strength, NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator %s\n", u_errorName(status));
+ return;
+ }
+ strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ }
+
+ while (IGNORABLE[count].text != NULL) {
+ u_unescape(IGNORABLE[count].text, text, 128);
+ u_unescape(IGNORABLE[count].pattern, pattern, 128);
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ if (!assertEqualWithUStringSearch(strsrch, IGNORABLE[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ usearch_close(strsrch);
+ ucol_close(collator);
+}
+
+static void TestDiactricMatch(void)
+{
+ UChar pattern[128];
+ UChar text[128];
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *strsrch = NULL;
+ UCollator *coll = NULL;
+ uint32_t count = 0;
+ SearchData search;
+
+ memset(pattern, 0, 128*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ strsrch = usearch_open(pattern, 1, text, 1, uloc_getDefault(), NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ return;
+ }
+
+ search = DIACTRICMATCH[count];
+ while (search.text != NULL) {
+ if (search.collator != NULL) {
+ coll = ucol_openFromShortString(search.collator, FALSE, NULL, &status);
+ } else {
+ coll = ucol_open(uloc_getDefault(), &status);
+ ucol_setStrength(coll, search.strength);
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search collator %s\n", u_errorName(status));
+ return;
+ }
+
+ usearch_setCollator(strsrch, coll, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting string search collator %s\n", u_errorName(status));
+ return;
+ }
+
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 128);
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ if (!assertEqualWithUStringSearch(strsrch, search)) {
+ log_err("Error at test number %d\n", count);
+ }
+ ucol_close(coll);
+
+ search = DIACTRICMATCH[++count];
+ }
+ usearch_close(strsrch);
+}
+
+static void TestCanonical(void)
+{
+ int count = 0;
+ open();
+ while (BASICCANONICAL[count].text != NULL) {
+ if (!assertCanonicalEqual(BASICCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestNormCanonical(void)
+{
+ int count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ open();
+ ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ count = 0;
+ while (NORMCANONICAL[count].text != NULL) {
+ if (!assertCanonicalEqual(NORMCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ ucol_setAttribute(EN_US_, UCOL_NORMALIZATION_MODE, UCOL_OFF, &status);
+ close();
+}
+
+static void TestStrengthCanonical(void)
+{
+ int count = 0;
+ open();
+ while (STRENGTHCANONICAL[count].text != NULL) {
+ if (!assertCanonicalEqual(STRENGTHCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestBreakIteratorCanonical(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ int count = 0;
+
+ CHECK_BREAK("x");
+
+#if !UCONFIG_NO_BREAK_ITERATION
+
+ open();
+ while (count < 4) {
+ /* 0-3 test are fixed */
+ UChar pattern[32];
+ UChar text[128];
+ const SearchData *search = &(BREAKITERATORCANONICAL[count]);
+ UCollator *collator = getCollator(search->collator);
+ UBreakIterator *breaker = getBreakIterator(search->breaker);
+ UStringSearch *strsrch;
+
+ u_unescape(search->text, text, 128);
+ u_unescape(search->pattern, pattern, 32);
+ ucol_setStrength(collator, search->strength);
+
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ breaker, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != breaker) {
+ log_err("Error setting break iterator\n");
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ }
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ ucol_setStrength(collator, UCOL_TERTIARY);
+ usearch_close(strsrch);
+ goto ENDTESTBREAKITERATOR;
+ }
+ search = &(BREAKITERATOREXACT[count + 1]);
+ breaker = getBreakIterator(search->breaker);
+ usearch_setBreakIterator(strsrch, breaker, &status);
+ if (U_FAILURE(status) ||
+ usearch_getBreakIterator(strsrch) != breaker) {
+ log_err("Error setting break iterator\n");
+ usearch_close(strsrch);
+ goto ENDTESTBREAKITERATOR;
+ }
+ usearch_reset(strsrch);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ log_err("Error at test number %d\n", count);
+ goto ENDTESTBREAKITERATOR;
+ }
+ usearch_close(strsrch);
+ count += 2;
+ }
+ count = 0;
+ while (BREAKITERATORCANONICAL[count].text != NULL) {
+ if (!assertEqual(BREAKITERATORCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ goto ENDTESTBREAKITERATOR;
+ }
+ count ++;
+ }
+
+ENDTESTBREAKITERATOR:
+ close();
+#endif
+}
+
+static void TestVariableCanonical(void)
+{
+ int count = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ open();
+ ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting collation alternate attribute %s\n",
+ u_errorName(status));
+ }
+ while (VARIABLE[count].text != NULL) {
+ log_verbose("variable %d\n", count);
+ if (!assertCanonicalEqual(VARIABLE[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ ucol_setAttribute(EN_US_, UCOL_ALTERNATE_HANDLING,
+ UCOL_NON_IGNORABLE, &status);
+ close();
+}
+
+static void TestOverlapCanonical(void)
+{
+ int count = 0;
+ open();
+ while (OVERLAPCANONICAL[count].text != NULL) {
+ if (!assertEqualWithAttribute(OVERLAPCANONICAL[count], USEARCH_ON,
+ USEARCH_ON)) {
+ log_err("Error at overlap test number %d\n", count);
+ }
+ count ++;
+ }
+ count = 0;
+ while (NONOVERLAP[count].text != NULL) {
+ if (!assertCanonicalEqual(NONOVERLAPCANONICAL[count])) {
+ log_err("Error at non overlap test number %d\n", count);
+ }
+ count ++;
+ }
+
+ count = 0;
+ while (count < 1) {
+ UChar pattern[32];
+ UChar text[128];
+ const SearchData *search = &(OVERLAPCANONICAL[count]);
+ UCollator *collator = getCollator(search->collator);
+ UStringSearch *strsrch;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_unescape(search->text, text, 128);
+ u_unescape(search->pattern, pattern, 32);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, collator,
+ NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_ON, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_ON) {
+ log_err("Error setting overlap option\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ usearch_close(strsrch);
+ return;
+ }
+ search = &(NONOVERLAPCANONICAL[count]);
+ usearch_setAttribute(strsrch, USEARCH_OVERLAP, USEARCH_OFF, &status);
+ if (U_FAILURE(status) ||
+ usearch_getAttribute(strsrch, USEARCH_OVERLAP) != USEARCH_OFF) {
+ log_err("Error setting overlap option\n");
+ }
+ usearch_reset(strsrch);
+ if (!assertEqualWithUStringSearch(strsrch, *search)) {
+ usearch_close(strsrch);
+ log_err("Error at test number %d\n", count);
+ }
+
+ count ++;
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestCollatorCanonical(void)
+{
+ /* test collator that thinks "o" and "p" are the same thing */
+ UChar rules[32];
+ UCollator *tailored = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ UChar pattern[32];
+ UChar text[128];
+ UStringSearch *strsrch;
+
+ open();
+ u_unescape(COLLATORCANONICAL[0].text, text, 128);
+ u_unescape(COLLATORCANONICAL[0].pattern, pattern, 32);
+
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening searcher\n");
+ return;
+ }
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ u_unescape(TESTCOLLATORRULE, rules, 32);
+ tailored = ucol_openRules(rules, -1, UCOL_ON,
+ COLLATORCANONICAL[1].strength, NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening rule based collator %s\n", u_errorName(status));
+ }
+
+ usearch_setCollator(strsrch, tailored, &status);
+ if (U_FAILURE(status) || usearch_getCollator(strsrch) != tailored) {
+ log_err("Error setting rule based collator\n");
+ }
+ usearch_reset(strsrch);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[1])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ usearch_setCollator(strsrch, EN_US_, &status);
+ usearch_reset(strsrch);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status) || usearch_getCollator(strsrch) != EN_US_) {
+ log_err("Error setting rule based collator\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, COLLATORCANONICAL[0])) {
+ goto ENDTESTCOLLATOR;
+ }
+
+ENDTESTCOLLATOR:
+ usearch_close(strsrch);
+ if (tailored != NULL) {
+ ucol_close(tailored);
+ }
+ close();
+}
+
+static void TestPatternCanonical(void)
+{
+ UStringSearch *strsrch;
+ UChar pattern[32];
+ UChar text[128];
+ const UChar *temp;
+ int32_t templength;
+ UErrorCode status = U_ZERO_ERROR;
+
+ open();
+ u_unescape(PATTERNCANONICAL[0].text, text, 128);
+ u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
+
+ ucol_setStrength(EN_US_, PATTERNCANONICAL[0].strength);
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ goto ENDTESTPATTERN;
+ }
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(PATTERNCANONICAL[1].pattern, pattern, 32);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ goto ENDTESTPATTERN;
+ }
+ usearch_reset(strsrch);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[1])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(PATTERNCANONICAL[0].pattern, pattern, 32);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ temp = usearch_getPattern(strsrch, &templength);
+ if (u_strcmp(pattern, temp) != 0) {
+ log_err("Error setting pattern\n");
+ goto ENDTESTPATTERN;
+ }
+ usearch_reset(strsrch);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, PATTERNCANONICAL[0])) {
+ goto ENDTESTPATTERN;
+ }
+ENDTESTPATTERN:
+ ucol_setStrength(EN_US_, UCOL_TERTIARY);
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestTextCanonical(void)
+{
+ UStringSearch *strsrch;
+ UChar pattern[32];
+ UChar text[128];
+ const UChar *temp;
+ int32_t templength;
+ UErrorCode status = U_ZERO_ERROR;
+
+ u_unescape(TEXTCANONICAL[0].text, text, 128);
+ u_unescape(TEXTCANONICAL[0].pattern, pattern, 32);
+
+ open();
+ strsrch = usearch_openFromCollator(pattern, -1, text, -1, EN_US_,
+ NULL, &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ goto ENDTESTPATTERN;
+ }
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(TEXTCANONICAL[1].text, text, 32);
+ usearch_setText(strsrch, text, -1, &status);
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ goto ENDTESTPATTERN;
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error setting text %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[1])) {
+ goto ENDTESTPATTERN;
+ }
+
+ u_unescape(TEXTCANONICAL[0].text, text, 32);
+ usearch_setText(strsrch, text, -1, &status);
+ temp = usearch_getText(strsrch, &templength);
+ if (u_strcmp(text, temp) != 0) {
+ log_err("Error setting text\n");
+ goto ENDTESTPATTERN;
+ }
+ if (U_FAILURE(status)) {
+ log_err("Error setting pattern %s\n", u_errorName(status));
+ }
+ if (!assertEqualWithUStringSearch(strsrch, TEXTCANONICAL[0])) {
+ goto ENDTESTPATTERN;
+ }
+ENDTESTPATTERN:
+ if (strsrch != NULL) {
+ usearch_close(strsrch);
+ }
+ close();
+}
+
+static void TestCompositeBoundariesCanonical(void)
+{
+ int count = 0;
+ open();
+ while (COMPOSITEBOUNDARIESCANONICAL[count].text != NULL) {
+ log_verbose("composite %d\n", count);
+ if (!assertCanonicalEqual(COMPOSITEBOUNDARIESCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestGetSetOffsetCanonical(void)
+{
+ int index = 0;
+ UChar pattern[32];
+ UChar text[128];
+ UErrorCode status = U_ZERO_ERROR;
+ UStringSearch *strsrch;
+
+ memset(pattern, 0, 32*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ open();
+ strsrch = usearch_openFromCollator(pattern, 16, text, 32, EN_US_, NULL,
+ &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ /* testing out of bounds error */
+ usearch_setOffset(strsrch, -1, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expecting set offset error\n");
+ }
+ usearch_setOffset(strsrch, 128, &status);
+ if (U_SUCCESS(status)) {
+ log_err("Error expecting set offset error\n");
+ }
+ while (BASICCANONICAL[index].text != NULL) {
+ int count = 0;
+ SearchData search = BASICCANONICAL[index ++];
+ int32_t matchindex = search.offset[count];
+ int32_t textlength;
+
+ if (BASICCANONICAL[index].text == NULL) {
+ /* skip the last one */
+ break;
+ }
+
+ u_unescape(search.text, text, 128);
+ u_unescape(search.pattern, pattern, 32);
+ status = U_ZERO_ERROR;
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ while (U_SUCCESS(status) && matchindex >= 0) {
+ uint32_t matchlength = search.size[count];
+ usearch_next(strsrch, &status);
+ if (matchindex != usearch_getMatchedStart(strsrch) ||
+ matchlength != (uint32_t)usearch_getMatchedLength(strsrch)) {
+ char *str = toCharString(usearch_getText(strsrch,
+ &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ matchindex = search.offset[count + 1] == -1 ? -1 :
+ search.offset[count + 2];
+ if (search.offset[count + 1] != -1) {
+ usearch_setOffset(strsrch, search.offset[count + 1] + 1,
+ &status);
+ if (usearch_getOffset(strsrch) != search.offset[count + 1] + 1) {
+ log_err("Error setting offset\n");
+ return;
+ }
+ }
+
+ count += 2;
+ }
+ usearch_next(strsrch, &status);
+ if (usearch_getMatchedStart(strsrch) != USEARCH_DONE) {
+ char *str = toCharString(usearch_getText(strsrch, &textlength));
+ log_err("Text: %s\n", str);
+ str = toCharString(usearch_getPattern(strsrch, &textlength));
+ log_err("Pattern: %s\n", str);
+ log_err("Error match found at %d %d\n",
+ usearch_getMatchedStart(strsrch),
+ usearch_getMatchedLength(strsrch));
+ return;
+ }
+ }
+ usearch_close(strsrch);
+ close();
+}
+
+static void TestSupplementaryCanonical(void)
+{
+ int count = 0;
+ open();
+ while (SUPPLEMENTARYCANONICAL[count].text != NULL) {
+ if (!assertCanonicalEqual(SUPPLEMENTARYCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ close();
+}
+
+static void TestContractionCanonical(void)
+{
+ UChar rules[128];
+ UChar pattern[128];
+ UChar text[128];
+ UCollator *collator = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+ int count = 0;
+ UStringSearch *strsrch = NULL;
+ memset(rules, 0, 128*sizeof(UChar));
+ memset(pattern, 0, 128*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ u_unescape(CONTRACTIONRULE, rules, 128);
+ collator = ucol_openRules(rules, u_strlen(rules), UCOL_ON,
+ UCOL_TERTIARY, NULL, &status);
+ if(status == U_FILE_ACCESS_ERROR) {
+ log_data_err("Is your data around?\n");
+ return;
+ } else if(U_FAILURE(status)) {
+ log_err("Error opening collator %s\n", u_errorName(status));
+ return;
+ }
+ strsrch = usearch_openFromCollator(pattern, 1, text, 1, collator, NULL,
+ &status);
+ usearch_setAttribute(strsrch, USEARCH_CANONICAL_MATCH, USEARCH_ON,
+ &status);
+ if (U_FAILURE(status)) {
+ log_err("Error opening string search %s\n", u_errorName(status));
+ }
+
+ while (CONTRACTIONCANONICAL[count].text != NULL) {
+ u_unescape(CONTRACTIONCANONICAL[count].text, text, 128);
+ u_unescape(CONTRACTIONCANONICAL[count].pattern, pattern, 128);
+ usearch_setText(strsrch, text, -1, &status);
+ usearch_setPattern(strsrch, pattern, -1, &status);
+ if (!assertEqualWithUStringSearch(strsrch,
+ CONTRACTIONCANONICAL[count])) {
+ log_err("Error at test number %d\n", count);
+ }
+ count ++;
+ }
+ usearch_close(strsrch);
+ ucol_close(collator);
+}
+
+static void TestNumeric(void) {
+ UCollator *coll = NULL;
+ UStringSearch *strsrch = NULL;
+ UErrorCode status = U_ZERO_ERROR;
+
+ UChar pattern[128];
+ UChar text[128];
+ memset(pattern, 0, 128*sizeof(UChar));
+ memset(text, 0, 128*sizeof(UChar));
+
+ coll = ucol_open("", &status);
+ if(U_FAILURE(status)) {
+ log_data_err("Could not open UCA. Is your data around?\n");
+ return;
+ }
+
+ ucol_setAttribute(coll, UCOL_NUMERIC_COLLATION, UCOL_ON, &status);
+
+ strsrch = usearch_openFromCollator(pattern, 1, text, 1, coll, NULL, &status);
+
+ if(status != U_UNSUPPORTED_ERROR || U_SUCCESS(status)) {
+ log_err("Expected U_UNSUPPORTED_ERROR when trying to instantiate a search object from a CODAN collator, got %s instead\n", u_errorName(status));
+ if(strsrch) {
+ usearch_close(strsrch);
+ }
+ }
+
+ ucol_close(coll);
+
+}
+
+void addSearchTest(TestNode** root)
+{
+ addTest(root, &TestStart, "tscoll/usrchtst/TestStart");
+ addTest(root, &TestOpenClose, "tscoll/usrchtst/TestOpenClose");
+ addTest(root, &TestInitialization, "tscoll/usrchtst/TestInitialization");
+ addTest(root, &TestBasic, "tscoll/usrchtst/TestBasic");
+ addTest(root, &TestNormExact, "tscoll/usrchtst/TestNormExact");
+ addTest(root, &TestStrength, "tscoll/usrchtst/TestStrength");
+ addTest(root, &TestBreakIterator, "tscoll/usrchtst/TestBreakIterator");
+ addTest(root, &TestVariable, "tscoll/usrchtst/TestVariable");
+ addTest(root, &TestOverlap, "tscoll/usrchtst/TestOverlap");
+ addTest(root, &TestCollator, "tscoll/usrchtst/TestCollator");
+ addTest(root, &TestPattern, "tscoll/usrchtst/TestPattern");
+ addTest(root, &TestText, "tscoll/usrchtst/TestText");
+ addTest(root, &TestCompositeBoundaries,
+ "tscoll/usrchtst/TestCompositeBoundaries");
+ addTest(root, &TestGetSetOffset, "tscoll/usrchtst/TestGetSetOffset");
+ addTest(root, &TestGetSetAttribute,
+ "tscoll/usrchtst/TestGetSetAttribute");
+ addTest(root, &TestGetMatch, "tscoll/usrchtst/TestGetMatch");
+ addTest(root, &TestSetMatch, "tscoll/usrchtst/TestSetMatch");
+ addTest(root, &TestReset, "tscoll/usrchtst/TestReset");
+ addTest(root, &TestSupplementary, "tscoll/usrchtst/TestSupplementary");
+ addTest(root, &TestContraction, "tscoll/usrchtst/TestContraction");
+ addTest(root, &TestIgnorable, "tscoll/usrchtst/TestIgnorable");
+ addTest(root, &TestCanonical, "tscoll/usrchtst/TestCanonical");
+ addTest(root, &TestNormCanonical, "tscoll/usrchtst/TestNormCanonical");
+ addTest(root, &TestStrengthCanonical,
+ "tscoll/usrchtst/TestStrengthCanonical");
+ addTest(root, &TestBreakIteratorCanonical,
+ "tscoll/usrchtst/TestBreakIteratorCanonical");
+ addTest(root, &TestVariableCanonical,
+ "tscoll/usrchtst/TestVariableCanonical");
+ addTest(root, &TestOverlapCanonical,
+ "tscoll/usrchtst/TestOverlapCanonical");
+ addTest(root, &TestCollatorCanonical,
+ "tscoll/usrchtst/TestCollatorCanonical");
+ addTest(root, &TestPatternCanonical,
+ "tscoll/usrchtst/TestPatternCanonical");
+ addTest(root, &TestTextCanonical, "tscoll/usrchtst/TestTextCanonical");
+ addTest(root, &TestCompositeBoundariesCanonical,
+ "tscoll/usrchtst/TestCompositeBoundariesCanonical");
+ addTest(root, &TestGetSetOffsetCanonical,
+ "tscoll/usrchtst/TestGetSetOffsetCanonical");
+ addTest(root, &TestSupplementaryCanonical,
+ "tscoll/usrchtst/TestSupplementaryCanonical");
+ addTest(root, &TestContractionCanonical,
+ "tscoll/usrchtst/TestContractionCanonical");
+ addTest(root, &TestEnd, "tscoll/usrchtst/TestEnd");
+ addTest(root, &TestNumeric, "tscoll/usrchtst/TestNumeric");
+ addTest(root, &TestDiactricMatch, "tscoll/usrchtst/TestDiactricMatch");
+}
+
+#endif /* #if !UCONFIG_NO_COLLATION */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c
new file mode 100644
index 00000000000..be5941df403
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utexttst.c
@@ -0,0 +1,250 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 2005-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File utexttst.c
+*
+* Modification History:
+*
+* Date Name Description
+* 06/13/2005 Andy Heninger Creation
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/utext.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+#include "memory.h"
+#include "string.h"
+
+
+static void TestAPI(void);
+void addUTextTest(TestNode** root);
+
+
+void
+addUTextTest(TestNode** root)
+{
+ addTest(root, &TestAPI , "tsutil/UTextTest/TestAPI");
+}
+
+
+#define TEST_ASSERT(x) \
+ {if ((x)==FALSE) {log_err("Test failure in file %s at line %d\n", __FILE__, __LINE__);\
+ gFailed = TRUE;\
+ }}
+
+
+#define TEST_SUCCESS(status) \
+ {if (U_FAILURE(status)) {log_err("Test failure in file %s at line %d. Error = \"%s\"\n", \
+ __FILE__, __LINE__, u_errorName(status)); \
+ gFailed = TRUE;\
+ }}
+
+
+
+/*
+ * TestAPI verify that the UText API is accessible from C programs.
+ * This is not intended to be a complete test of the API functionality. That is
+ * in the C++ intltest program.
+ * This test is intended to check that everything can be accessed and built in
+ * a pure C enviornment.
+ */
+
+
+static void TestAPI(void) {
+ UErrorCode status = U_ZERO_ERROR;
+ UBool gFailed = FALSE;
+
+ /* Open */
+ {
+ UText utLoc = UTEXT_INITIALIZER;
+ const char * cString = "\x61\x62\x63\x64";
+ UChar uString[] = {0x41, 0x42, 0x43, 0};
+ UText *uta;
+ UText *utb;
+ UChar c;
+
+ uta = utext_openUChars(NULL, uString, -1, &status);
+ TEST_SUCCESS(status);
+ c = utext_next32(uta);
+ TEST_ASSERT(c == 0x41);
+ utb = utext_close(uta);
+ TEST_ASSERT(utb == NULL);
+
+ uta = utext_openUTF8(&utLoc, cString, -1, &status);
+ TEST_SUCCESS(status);
+ TEST_ASSERT(uta == &utLoc);
+
+ uta = utext_close(&utLoc);
+ TEST_ASSERT(uta == &utLoc);
+ }
+
+ /* utext_clone() */
+ {
+ UChar uString[] = {0x41, 0x42, 0x43, 0};
+ int64_t len;
+ UText *uta;
+ UText *utb;
+
+ status = U_ZERO_ERROR;
+ uta = utext_openUChars(NULL, uString, -1, &status);
+ TEST_SUCCESS(status);
+ utb = utext_clone(NULL, uta, FALSE, FALSE, &status);
+ TEST_SUCCESS(status);
+ TEST_ASSERT(utb != NULL);
+ TEST_ASSERT(utb != uta);
+ len = utext_nativeLength(uta);
+ TEST_ASSERT(len == u_strlen(uString));
+ utext_close(uta);
+ utext_close(utb);
+ }
+
+ /* basic access functions */
+ {
+ UChar uString[] = {0x41, 0x42, 0x43, 0};
+ UText *uta;
+ UChar32 c;
+ int64_t len;
+ UBool b;
+ int64_t i;
+
+ status = U_ZERO_ERROR;
+ uta = utext_openUChars(NULL, uString, -1, &status);
+ TEST_ASSERT(uta!=NULL);
+ TEST_SUCCESS(status);
+ b = utext_isLengthExpensive(uta);
+ TEST_ASSERT(b==TRUE);
+ len = utext_nativeLength(uta);
+ TEST_ASSERT(len == u_strlen(uString));
+ b = utext_isLengthExpensive(uta);
+ TEST_ASSERT(b==FALSE);
+
+ c = utext_char32At(uta, 0);
+ TEST_ASSERT(c==uString[0]);
+
+ c = utext_current32(uta);
+ TEST_ASSERT(c==uString[0]);
+
+ c = utext_next32(uta);
+ TEST_ASSERT(c==uString[0]);
+ c = utext_current32(uta);
+ TEST_ASSERT(c==uString[1]);
+
+ c = utext_previous32(uta);
+ TEST_ASSERT(c==uString[0]);
+ c = utext_current32(uta);
+ TEST_ASSERT(c==uString[0]);
+
+ c = utext_next32From(uta, 1);
+ TEST_ASSERT(c==uString[1]);
+ c = utext_next32From(uta, u_strlen(uString));
+ TEST_ASSERT(c==U_SENTINEL);
+
+ c = utext_previous32From(uta, 2);
+ TEST_ASSERT(c==uString[1]);
+ i = utext_getNativeIndex(uta);
+ TEST_ASSERT(i == 1);
+
+ utext_setNativeIndex(uta, 0);
+ b = utext_moveIndex32(uta, 1);
+ TEST_ASSERT(b==TRUE);
+ i = utext_getNativeIndex(uta);
+ TEST_ASSERT(i==1);
+
+ b = utext_moveIndex32(uta, u_strlen(uString)-1);
+ TEST_ASSERT(b==TRUE);
+ i = utext_getNativeIndex(uta);
+ TEST_ASSERT(i==u_strlen(uString));
+
+ b = utext_moveIndex32(uta, 1);
+ TEST_ASSERT(b==FALSE);
+ i = utext_getNativeIndex(uta);
+ TEST_ASSERT(i==u_strlen(uString));
+
+ utext_setNativeIndex(uta, 0);
+ c = UTEXT_NEXT32(uta);
+ TEST_ASSERT(c==uString[0]);
+ c = utext_current32(uta);
+ TEST_ASSERT(c==uString[1]);
+
+ c = UTEXT_PREVIOUS32(uta);
+ TEST_ASSERT(c==uString[0]);
+ c = UTEXT_PREVIOUS32(uta);
+ TEST_ASSERT(c==U_SENTINEL);
+
+
+ utext_close(uta);
+ }
+
+ {
+ /*
+ * extract
+ */
+ UText *uta;
+ UChar uString[] = {0x41, 0x42, 0x43, 0};
+ UChar buf[100];
+ int32_t i;
+
+ status = U_ZERO_ERROR;
+ uta = utext_openUChars(NULL, uString, -1, &status);
+ TEST_SUCCESS(status);
+
+ status = U_ZERO_ERROR;
+ i = utext_extract(uta, 0, 100, NULL, 0, &status);
+ TEST_ASSERT(status==U_BUFFER_OVERFLOW_ERROR);
+ TEST_ASSERT(i == u_strlen(uString));
+
+ status = U_ZERO_ERROR;
+ memset(buf, 0, sizeof(buf));
+ i = utext_extract(uta, 0, 100, buf, 100, &status);
+ TEST_SUCCESS(status);
+ TEST_ASSERT(i == u_strlen(uString));
+ i = u_strcmp(uString, buf);
+ TEST_ASSERT(i == 0);
+ utext_close(uta);
+ }
+
+ {
+ /*
+ * Copy, Replace, isWritable
+ * Can't create an editable UText from plain C, so all we
+ * can easily do is check that errors returned.
+ */
+ UText *uta;
+ UChar uString[] = {0x41, 0x42, 0x43, 0};
+ UBool b;
+
+ status = U_ZERO_ERROR;
+ uta = utext_openUChars(NULL, uString, -1, &status);
+ TEST_SUCCESS(status);
+
+ b = utext_isWritable(uta);
+ TEST_ASSERT(b == FALSE);
+
+ b = utext_hasMetaData(uta);
+ TEST_ASSERT(b == FALSE);
+
+ utext_replace(uta,
+ 0, 1, /* start, limit */
+ uString, -1, /* replacement, replacement length */
+ &status);
+ TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
+
+
+ utext_copy(uta,
+ 0, 1, /* start, limit */
+ 2, /* destination index */
+ FALSE, /* move flag */
+ &status);
+ TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
+
+ utext_close(uta);
+ }
+
+
+}
+
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c
new file mode 100644
index 00000000000..38b8fb5fcc2
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utf16tst.c
@@ -0,0 +1,734 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1998-2001, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File test.c
+*
+* Modification History:
+*
+* Date Name Description
+* 05/01/2000 Madhu Creation
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/utf16.h"
+#include "unicode/ustring.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "cintltst.h"
+#include <stdio.h>
+
+#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
+
+static void printUChars(const UChar *uchars);
+
+static void TestCodeUnitValues(void);
+static void TestCharLength(void);
+static void TestGetChar(void);
+static void TestNextPrevChar(void);
+static void TestFwdBack(void);
+static void TestSetChar(void);
+static void TestAppendChar(void);
+static void TestAppend(void);
+static void TestSurrogate(void);
+
+void addUTF16Test(TestNode** root);
+
+void
+addUTF16Test(TestNode** root)
+{
+ addTest(root, &TestCodeUnitValues, "utf16tst/TestCodeUnitValues");
+ addTest(root, &TestCharLength, "utf16tst/TestCharLength" );
+ addTest(root, &TestGetChar, "utf16tst/TestGetChar" );
+ addTest(root, &TestNextPrevChar, "utf16tst/TestNextPrevChar" );
+ addTest(root, &TestFwdBack, "utf16tst/TestFwdBack" );
+ addTest(root, &TestSetChar, "utf16tst/TestSetChar" );
+ addTest(root, &TestAppendChar, "utf16tst/TestAppendChar" );
+ addTest(root, &TestAppend, "utf16tst/TestAppend" );
+ addTest(root, &TestSurrogate, "utf16tst/TestSurrogate" );
+}
+
+static void TestCodeUnitValues()
+{
+ static uint16_t codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0};
+
+ int16_t i;
+ for(i=0; i<sizeof(codeunit)/sizeof(codeunit[0]); i++){
+ UChar c=codeunit[i];
+ log_verbose("Testing code unit value of %x\n", c);
+ if(i<4){
+ if(!UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || UTF16_IS_TRAIL(c) || !U16_IS_SINGLE(c) || U16_IS_LEAD(c) || U16_IS_TRAIL(c)){
+ log_err("ERROR: %x is a single character\n", c);
+ }
+ }
+ if(i >= 4 && i< 8){
+ if(!UTF16_IS_LEAD(c) || UTF16_IS_SINGLE(c) || UTF16_IS_TRAIL(c) || !U16_IS_LEAD(c) || U16_IS_SINGLE(c) || U16_IS_TRAIL(c)){
+ log_err("ERROR: %x is a first surrogate\n", c);
+ }
+ }
+ if(i >= 8 && i< 12){
+ if(!UTF16_IS_TRAIL(c) || UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || !U16_IS_TRAIL(c) || U16_IS_SINGLE(c) || U16_IS_LEAD(c)){
+ log_err("ERROR: %x is a second surrogate\n", c);
+ }
+ }
+ }
+}
+
+static void TestCharLength()
+{
+ static uint32_t codepoint[]={
+ 1, 0x0061,
+ 1, 0xe065,
+ 1, 0x20ac,
+ 2, 0x20402,
+ 2, 0x23456,
+ 2, 0x24506,
+ 2, 0x20402,
+ 2, 0x10402,
+ 1, 0xd7ff,
+ 1, 0xe000
+ };
+
+ int16_t i;
+ UBool multiple;
+ for(i=0; i<sizeof(codepoint)/sizeof(codepoint[0]); i=(int16_t)(i+2)){
+ UChar32 c=codepoint[i+1];
+ if(UTF16_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U16_LENGTH(c) != (uint16_t)codepoint[i]){
+ log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF16_CHAR_LENGTH(c));
+ }else{
+ log_verbose("The no: of code units for %lx is %d\n",c, UTF16_CHAR_LENGTH(c) );
+ }
+ multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
+ if(UTF16_NEED_MULTIPLE_UCHAR(c) != multiple){
+ log_err("ERROR: UTF16_NEED_MULTIPLE_UCHAR failed for %lx\n", c);
+ }
+ }
+}
+
+static void TestGetChar()
+{
+ static UChar input[]={
+ /* code unit,*/
+ 0xdc00,
+ 0x20ac,
+ 0xd841,
+ 0x61,
+ 0xd841,
+ 0xdc02,
+ 0xd842,
+ 0xdc06,
+ 0,
+ 0xd842,
+ 0xd7ff,
+ 0xdc41,
+ 0xe000,
+ 0xd800
+ };
+ static UChar32 result[]={
+ /*codepoint-unsafe, codepoint-safe(not strict) codepoint-safe(strict)*/
+ (UChar32)0xfca10000, 0xdc00, UTF_ERROR_VALUE,
+ 0x20ac, 0x20ac, 0x20ac,
+ 0x12861, 0xd841, UTF_ERROR_VALUE,
+ 0x61, 0x61, 0x61,
+ 0x20402, 0x20402, 0x20402,
+ 0x20402, 0x20402, 0x20402,
+ 0x20806, 0x20806, 0x20806,
+ 0x20806, 0x20806, 0x20806,
+ 0x00, 0x00, 0x00,
+ 0x203ff, 0xd842, UTF_ERROR_VALUE,
+ 0xd7ff, 0xd7ff, 0xd7ff,
+ 0xfc41, 0xdc41, UTF_ERROR_VALUE,
+ 0xe000, 0xe000, 0xe000,
+ 0x11734, 0xd800, UTF_ERROR_VALUE
+ };
+ uint16_t i=0;
+ UChar32 c;
+ uint16_t offset=0;
+ for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++) {
+ if(0<offset && offset<sizeof(input)/U_SIZEOF_UCHAR-1){
+ UTF16_GET_CHAR_UNSAFE(input, offset, c);
+ if(c != result[i]){
+ log_err("ERROR: UTF16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+
+ U16_GET_UNSAFE(input, offset, c);
+ if(c != result[i]){
+ log_err("ERROR: U16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+ }
+
+ UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE);
+ if(c != result[i+1]){
+ log_err("ERROR: UTF16_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ U16_GET(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c);
+ if(c != result[i+1]){
+ log_err("ERROR: U16_GET failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE);
+ if(c != result[i+2]){
+ log_err("ERROR: UTF16_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
+ }
+ i=(uint16_t)(i+3);
+ }
+
+}
+
+static void TestNextPrevChar(){
+
+ static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
+ static UChar32 result[]={
+ /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/
+ 0x0061, 0x0061, 0x0061, 0x0000, 0x0000, 0x0000,
+ 0x10000, 0x10000, 0x10000, 0x120400, 0xdc00, UTF_ERROR_VALUE,
+ 0xdc00, 0xdc00, UTF_ERROR_VALUE, 0x20441, 0x20441, 0x20441,
+ 0x10ffff, 0x10ffff, 0x10ffff, 0xd841, 0xd841, UTF_ERROR_VALUE,
+ 0xdfff, 0xdfff, UTF_ERROR_VALUE, 0xd7ff, 0xd7ff, 0xd7ff,
+ 0x0062, 0x0062, 0x0062, 0xd841, 0xd841, UTF_ERROR_VALUE,
+ 0x1ffff, 0xd841, UTF_ERROR_VALUE, 0x0062, 0x0062, 0x0062,
+ 0xd7ff, 0xd7ff, 0xd7ff, 0x10ffff, 0x10ffff, 0x10ffff,
+ 0x20441, 0x20441, 0x20441, 0xdbff, 0xdbff, UTF_ERROR_VALUE,
+ 0xdc41, 0xdc41, UTF_ERROR_VALUE, 0x10000, 0x10000, 0x10000,
+ 0xdc00, 0xdc00, UTF_ERROR_VALUE, 0xd800, 0xd800, UTF_ERROR_VALUE,
+ 0x0000, 0x0000, 0x0000, 0x0061, 0x0061, 0x0061
+ };
+ static uint16_t movedOffset[]={
+ /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/
+ 1, 1, 1, 11, 11, 11,
+ 3, 3, 3, 9, 10 , 10,
+ 3, 3, 3, 8, 8, 8,
+ 5, 5, 4, 8, 8, 8,
+ 5, 5, 5, 7, 7, 7,
+ 6, 6, 6, 6, 6, 6,
+ 8, 7, 7, 5, 5, 5,
+ 8, 8, 8, 3, 3, 3,
+ 10, 10, 10, 3, 3, 3,
+ 10, 10, 10, 1, 1, 1,
+ 11, 11, 11, 1, 1, 1,
+ 12, 12, 12, 0, 0, 0,
+ };
+
+
+ UChar32 c=0x0000;
+ uint16_t i=0;
+ uint16_t offset=0, setOffset=0;
+ for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){
+ setOffset=offset;
+ UTF16_NEXT_CHAR_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i]){
+ log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i], setOffset);
+ }
+ if(c != result[i]){
+ log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+
+ setOffset=offset;
+ U16_NEXT_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i]){
+ log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i], setOffset);
+ }
+ if(c != result[i]){
+ log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+
+ setOffset=offset;
+ UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+1], setOffset);
+ }
+ if(c != result[i+1]){
+ log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ setOffset=offset;
+ U16_NEXT(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: U16_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+1], setOffset);
+ }
+ if(c != result[i+1]){
+ log_err("ERROR: U16_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ setOffset=offset;
+ UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+2], setOffset);
+ }
+ if(c != result[i+2]){
+ log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
+ }
+
+ i=(uint16_t)(i+6);
+ }
+ i=0;
+ for(offset=(uint16_t)sizeof(input)/U_SIZEOF_UCHAR; offset > 0; --offset){
+ setOffset=offset;
+ UTF16_PREV_CHAR_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i+3]){
+ log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+3], setOffset);
+ }
+ if(c != result[i+3]){
+ log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
+ }
+
+ setOffset=offset;
+ U16_PREV_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i+3]){
+ log_err("ERROR: U16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+3], setOffset);
+ }
+ if(c != result[i+3]){
+ log_err("ERROR: U16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
+ }
+
+ setOffset=offset;
+ UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE);
+ if(setOffset != movedOffset[i+4]){
+ log_err("ERROR: UTF16_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+4], setOffset);
+ }
+ if(c != result[i+4]){
+ log_err("ERROR: UTF16_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
+ }
+
+ setOffset=offset;
+ U16_PREV(input, 0, setOffset, c);
+ if(setOffset != movedOffset[i+4]){
+ log_err("ERROR: U16_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+4], setOffset);
+ }
+ if(c != result[i+4]){
+ log_err("ERROR: U16_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
+ }
+
+ setOffset=offset;
+ UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, TRUE);
+ if(setOffset != movedOffset[i+5]){
+ log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+5], setOffset);
+ }
+ if(c != result[i+5]){
+ log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c);
+ }
+
+ i=(uint16_t)(i+6);
+ }
+
+}
+
+static void TestFwdBack(){
+ static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
+ static uint16_t fwd_unsafe[] ={1, 3, 5, 6, 8, 10, 11, 12};
+ static uint16_t fwd_safe[] ={1, 3, 5, 6, 7, 8, 10, 11, 12};
+ static uint16_t back_unsafe[]={11, 9, 8, 7, 6, 5, 3, 1, 0};
+ static uint16_t back_safe[] ={11, 10, 8, 7, 6, 5, 3, 1, 0};
+
+ static uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1};
+ static uint16_t fwd_N_unsafe[] ={0, 1, 5, 10, 11};
+ static uint16_t fwd_N_safe[] ={0, 1, 5, 8, 10, 12, 12}; /*safe macro keeps it at the end of the string */
+ static uint16_t back_N_unsafe[]={12, 11, 8, 5, 3};
+ static uint16_t back_N_safe[] ={12, 11, 8, 5, 3, 0, 0};
+
+ uint16_t offunsafe=0, offsafe=0;
+ uint16_t i=0;
+ while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
+ UTF16_FWD_1_UNSAFE(input, offunsafe);
+ if(offunsafe != fwd_unsafe[i]){
+ log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ offunsafe=0, offsafe=0;
+ i=0;
+ while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
+ U16_FWD_1_UNSAFE(input, offunsafe);
+ if(offunsafe != fwd_unsafe[i]){
+ log_err("ERROR: U16_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
+ UTF16_FWD_1_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
+ if(offsafe != fwd_safe[i]){
+ log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
+ U16_FWD_1(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
+ if(offsafe != fwd_safe[i]){
+ log_err("ERROR: U16_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
+ }
+ i++;
+ }
+
+ offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ offsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ i=0;
+ while(offunsafe > 0){
+ UTF16_BACK_1_UNSAFE(input, offunsafe);
+ if(offunsafe != back_unsafe[i]){
+ log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ offsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ i=0;
+ while(offunsafe > 0){
+ U16_BACK_1_UNSAFE(input, offunsafe);
+ if(offunsafe != back_unsafe[i]){
+ log_err("ERROR: U16_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe > 0){
+ UTF16_BACK_1_SAFE(input,0, offsafe);
+ if(offsafe != back_safe[i]){
+ log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe > 0){
+ U16_BACK_1(input,0, offsafe);
+ if(offsafe != back_safe[i]){
+ log_err("ERROR: U16_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
+ }
+ i++;
+ }
+
+ offunsafe=0;
+ offsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ /*didn't want it to fail(we assume 0<i<length)*/
+ UTF16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != fwd_N_unsafe[i]){
+ log_err("ERROR: Forward_N_unsafe offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offunsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){ /*didn't want it to fail(we assume 0<i<length)*/
+ U16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != fwd_N_unsafe[i]){
+ log_err("ERROR: U16_FWD_N_UNSAFE offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ UTF16_FWD_N_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
+ if(offsafe != fwd_N_safe[i]){
+ log_err("ERROR: Forward_N_safe offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
+ }
+
+ }
+
+ offsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ U16_FWD_N(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
+ if(offsafe != fwd_N_safe[i]){
+ log_err("ERROR: U16_FWD_N offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
+ }
+
+ }
+
+ offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ UTF16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != back_N_unsafe[i]){
+ log_err("ERROR: backward_N_unsafe offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ U16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != back_N_unsafe[i]){
+ log_err("ERROR: U16_BACK_N_UNSAFE offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ UTF16_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]);
+ if(offsafe != back_N_safe[i]){
+ log_err("ERROR: backward_N_safe offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
+ }
+ }
+
+ offsafe=sizeof(input)/U_SIZEOF_UCHAR;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ U16_BACK_N(input, 0, offsafe, Nvalue[i]);
+ if(offsafe != back_N_safe[i]){
+ log_err("ERROR: U16_BACK_N offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
+ }
+ }
+}
+
+static void TestSetChar(){
+ static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
+ static uint16_t start_unsafe[]={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 9, 11};
+ static uint16_t start_safe[] ={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 10, 11};
+ static uint16_t limit_unsafe[]={0, 1, 3, 3, 5, 5, 6, 8, 8, 10, 10, 11};
+ static uint16_t limit_safe[] ={0, 1, 3, 3, 5, 5, 6, 7, 8, 10, 10, 11};
+
+ uint16_t i=0;
+ uint16_t offset=0, setOffset=0;
+ for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){
+ setOffset=offset;
+ UTF16_SET_CHAR_START_UNSAFE(input, setOffset);
+ if(setOffset != start_unsafe[i]){
+ log_err("ERROR: UTF16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U16_SET_CP_START_UNSAFE(input, setOffset);
+ if(setOffset != start_unsafe[i]){
+ log_err("ERROR: U16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ UTF16_SET_CHAR_START_SAFE(input, 0, setOffset);
+ if(setOffset != start_safe[i]){
+ log_err("ERROR: UTF16_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U16_SET_CP_START(input, 0, setOffset);
+ if(setOffset != start_safe[i]){
+ log_err("ERROR: U16_SET_CHAR_START failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
+ }
+
+ if (offset > 0) {
+ setOffset=offset;
+ UTF16_SET_CHAR_LIMIT_UNSAFE(input, setOffset);
+ if(setOffset != limit_unsafe[i]){
+ log_err("ERROR: UTF16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U16_SET_CP_LIMIT_UNSAFE(input, setOffset);
+ if(setOffset != limit_unsafe[i]){
+ log_err("ERROR: U16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
+ }
+ }
+
+ setOffset=offset;
+ U16_SET_CP_LIMIT(input,0, setOffset, sizeof(input)/U_SIZEOF_UCHAR);
+ if(setOffset != limit_safe[i]){
+ log_err("ERROR: U16_SET_CHAR_LIMIT failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_safe[i], setOffset);
+ }
+
+ i++;
+ }
+}
+
+static void TestAppendChar(){
+ static UChar s[5]={0x0061, 0x0062, 0x0063, 0x0064, 0x0000};
+ static uint32_t test[]={
+ /*append-position(unsafe), CHAR to be appended */
+ 0, 0x20441,
+ 2, 0x0028,
+ 2, 0xdc00,
+ 3, 0xd800,
+ 1, 0x20402,
+
+ /*append-position(safe), CHAR to be appended */
+ 0, 0x20441,
+ 2, 0xdc00,
+ 3, 0xd800,
+ 1, 0x20402,
+ 3, 0x20402,
+ 3, 0x10402,
+ 2, 0x10402,
+
+ };
+ static uint16_t movedOffset[]={
+ /*offset-moved-to(unsafe)*/
+ 2, /*for append-pos: 0 , CHAR 0x20441*/
+ 3,
+ 3,
+ 4,
+ 3,
+ /*offse-moved-to(safe)*/
+ 2, /*for append-pos: 0, CHAR 0x20441*/
+ 3,
+ 4,
+ 3,
+ 4,
+ 4,
+ 4
+ };
+
+ static UChar result[][5]={
+ /*unsafe*/
+ {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0x0028, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
+ {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
+
+ /*safe*/
+ {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
+ {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
+ {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
+ {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
+ {0x0061, 0x0062, 0xd801, 0xdc02, 0x0000},
+
+
+ };
+ uint16_t i, count=0;
+ UChar *str=(UChar*)malloc(sizeof(UChar) * (u_strlen(s)+1));
+ uint16_t offset;
+ for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){
+ if(count<5){
+ u_strcpy(str, s);
+ offset=(uint16_t)test[i];
+ UTF16_APPEND_CHAR_UNSAFE(str, offset, test[i+1]);
+ if(offset != movedOffset[count]){
+ log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n",
+ count, movedOffset[count], offset);
+
+ }
+ if(u_strcmp(str, result[count]) !=0){
+ log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed for count=%d. Expected:", count);
+ printUChars(result[count]);
+ printf("\nGot:");
+ printUChars(str);
+ printf("\n");
+ }
+ }else{
+ u_strcpy(str, s);
+ offset=(uint16_t)test[i];
+ UTF16_APPEND_CHAR_SAFE(str, offset, (uint16_t)u_strlen(str), test[i+1]);
+ if(offset != movedOffset[count]){
+ log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n",
+ count, movedOffset[count], offset);
+
+ }
+ if(u_strcmp(str, result[count]) !=0){
+ log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed for count=%d. Expected:", count);
+ printUChars(result[count]);
+ printf("\nGot:");
+ printUChars(str);
+ printf("\n");
+ }
+ }
+ count++;
+ }
+ free(str);
+
+}
+
+static void TestAppend() {
+ static const UChar32 codePoints[]={
+ 0x61, 0xdf, 0x901, 0x3040,
+ 0xac00, 0xd800, 0xdbff, 0xdcde,
+ 0xdffd, 0xe000, 0xffff, 0x10000,
+ 0x12345, 0xe0021, 0x10ffff, 0x110000,
+ 0x234567, 0x7fffffff, -1, -1000,
+ 0, 0x400
+ };
+ static const UChar expectUnsafe[]={
+ 0x61, 0xdf, 0x901, 0x3040,
+ 0xac00, 0xd800, 0xdbff, 0xdcde,
+ 0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
+ 0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
+ /* none from this line */
+ 0, 0x400
+ }, expectSafe[]={
+ 0x61, 0xdf, 0x901, 0x3040,
+ 0xac00, 0xd800, 0xdbff, 0xdcde,
+ 0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
+ 0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
+ /* none from this line */
+ 0, 0x400
+ };
+
+ UChar buffer[100];
+ UChar32 c;
+ int32_t i, length;
+ UBool isError, expectIsError, wrongIsError;
+
+ length=0;
+ for(i=0; i<LENGTHOF(codePoints); ++i) {
+ c=codePoints[i];
+ if(c<0 || 0x10ffff<c) {
+ continue; /* skip non-code points for U16_APPEND_UNSAFE */
+ }
+
+ U16_APPEND_UNSAFE(buffer, length, c);
+ }
+ if(length!=LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length*U_SIZEOF_UCHAR)) {
+ log_err("U16_APPEND_UNSAFE did not generate the expected output\n");
+ }
+
+ length=0;
+ wrongIsError=FALSE;
+ for(i=0; i<LENGTHOF(codePoints); ++i) {
+ c=codePoints[i];
+ expectIsError= c<0 || 0x10ffff<c; /* || U_IS_SURROGATE(c); */ /* surrogates in UTF-32 shouldn't be used, but it's okay to pass them around internally. */
+ isError=FALSE;
+
+ U16_APPEND(buffer, length, LENGTHOF(buffer), c, isError);
+ wrongIsError|= isError!=expectIsError;
+ }
+ if(wrongIsError) {
+ log_err("U16_APPEND did not set isError correctly\n");
+ }
+ if(length!=LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length*U_SIZEOF_UCHAR)) {
+ log_err("U16_APPEND did not generate the expected output\n");
+ }
+}
+
+static void TestSurrogate(){
+ static UChar32 s[] = {0x10000, 0x10ffff, 0x50000, 0x100000, 0x1abcd};
+ int i = 0;
+ while (i < 5) {
+ UChar first = UTF_FIRST_SURROGATE(s[i]);
+ UChar second = UTF_SECOND_SURROGATE(s[i]);
+ /* algorithm from the Unicode consortium */
+ UChar firstresult = (UChar)(((s[i] - 0x10000) / 0x400) + 0xD800);
+ UChar secondresult = (UChar)(((s[i] - 0x10000) % 0x400) + 0xDC00);
+
+ if (first != UTF16_LEAD(s[i]) || first != U16_LEAD(s[i]) || first != firstresult) {
+ log_err("Failure in first surrogate in 0x%x expected to be 0x%x\n",
+ s[i], firstresult);
+ }
+ if (second != UTF16_TRAIL(s[i]) || second != U16_TRAIL(s[i]) || second != secondresult) {
+ log_err("Failure in second surrogate in 0x%x expected to be 0x%x\n",
+ s[i], secondresult);
+ }
+ i ++;
+ }
+}
+
+static void printUChars(const UChar *uchars){
+ int16_t i=0;
+ for(i=0; i<u_strlen(uchars); i++){
+ printf("%x ", *(uchars+i));
+ }
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c
new file mode 100644
index 00000000000..eaa8fb28c54
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utf8tst.c
@@ -0,0 +1,956 @@
+/********************************************************************
+ * COPYRIGHT:
+ * Copyright (c) 1998-2006, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ ********************************************************************/
+/*
+* File test.c
+*
+* Modification History:
+*
+* Date Name Description
+* 07/24/2000 Madhu Creation
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/utf8.h"
+#include "cmemory.h"
+#include "cintltst.h"
+
+#define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
+
+/* lenient UTF-8 ------------------------------------------------------------ */
+
+/*
+ * Lenient UTF-8 differs from conformant UTF-8 in that it allows surrogate
+ * code points with their "natural" encoding.
+ * Effectively, this allows a mix of UTF-8 and CESU-8 as well as encodings of
+ * single surrogates.
+ *
+ * This is not conformant with UTF-8.
+ *
+ * Supplementary code points may be encoded as pairs of 3-byte sequences, but
+ * the macros below do not attempt to assemble such pairs.
+ */
+
+#define L8_NEXT(s, i, length, c) { \
+ (c)=(uint8_t)(s)[(i)++]; \
+ if((c)>=0x80) { \
+ if(U8_IS_LEAD(c)) { \
+ (c)=utf8_nextCharSafeBody((const uint8_t *)s, &(i), (int32_t)(length), c, -2); \
+ } else { \
+ (c)=U_SENTINEL; \
+ } \
+ } \
+}
+
+#define L8_PREV(s, start, i, c) { \
+ (c)=(uint8_t)(s)[--(i)]; \
+ if((c)>=0x80) { \
+ if((c)<=0xbf) { \
+ (c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -2); \
+ } else { \
+ (c)=U_SENTINEL; \
+ } \
+ } \
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void printUChars(const uint8_t *uchars, int16_t len);
+
+static void TestCodeUnitValues(void);
+static void TestCharLength(void);
+static void TestGetChar(void);
+static void TestNextPrevChar(void);
+static void TestFwdBack(void);
+static void TestSetChar(void);
+static void TestAppendChar(void);
+static void TestAppend(void);
+static void TestSurrogates(void);
+
+void addUTF8Test(TestNode** root);
+
+void
+addUTF8Test(TestNode** root)
+{
+ addTest(root, &TestCodeUnitValues, "utf8tst/TestCodeUnitValues");
+ addTest(root, &TestCharLength, "utf8tst/TestCharLength" );
+ addTest(root, &TestGetChar, "utf8tst/TestGetChar" );
+ addTest(root, &TestNextPrevChar, "utf8tst/TestNextPrevChar" );
+ addTest(root, &TestFwdBack, "utf8tst/TestFwdBack" );
+ addTest(root, &TestSetChar, "utf8tst/TestSetChar" );
+ addTest(root, &TestAppendChar, "utf8tst/TestAppendChar" );
+ addTest(root, &TestAppend, "utf8tst/TestAppend" );
+ addTest(root, &TestSurrogates, "utf8tst/TestSurrogates" );
+}
+
+static void TestCodeUnitValues()
+{
+ static const uint8_t codeunit[]={0x00, 0x65, 0x7e, 0x7f, 0xc0, 0xc4, 0xf0, 0xfd, 0x80, 0x81, 0xbc, 0xbe,};
+
+ int16_t i;
+ for(i=0; i<sizeof(codeunit)/sizeof(codeunit[0]); i++){
+ uint8_t c=codeunit[i];
+ log_verbose("Testing code unit value of %x\n", c);
+ if(i<4){
+ if(!UTF8_IS_SINGLE(c) || UTF8_IS_LEAD(c) || UTF8_IS_TRAIL(c) || !U8_IS_SINGLE(c) || U8_IS_LEAD(c) || U8_IS_TRAIL(c)){
+ log_err("ERROR: 0x%02x is a single byte but results in single: %c lead: %c trail: %c\n",
+ c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n');
+ }
+ } else if(i< 8){
+ if(!UTF8_IS_LEAD(c) || UTF8_IS_SINGLE(c) || UTF8_IS_TRAIL(c) || !U8_IS_LEAD(c) || U8_IS_SINGLE(c) || U8_IS_TRAIL(c)){
+ log_err("ERROR: 0x%02x is a lead byte but results in single: %c lead: %c trail: %c\n",
+ c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n');
+ }
+ } else if(i< 12){
+ if(!UTF8_IS_TRAIL(c) || UTF8_IS_SINGLE(c) || UTF8_IS_LEAD(c) || !U8_IS_TRAIL(c) || U8_IS_SINGLE(c) || U8_IS_LEAD(c)){
+ log_err("ERROR: 0x%02x is a trail byte but results in single: %c lead: %c trail: %c\n",
+ c, UTF8_IS_SINGLE(c) ? 'y' : 'n', UTF8_IS_LEAD(c) ? 'y' : 'n', UTF8_IS_TRAIL(c) ? 'y' : 'n');
+ }
+ }
+ }
+}
+
+static void TestCharLength()
+{
+ static const uint32_t codepoint[]={
+ 1, 0x0061,
+ 1, 0x007f,
+ 2, 0x016f,
+ 2, 0x07ff,
+ 3, 0x0865,
+ 3, 0x20ac,
+ 4, 0x20402,
+ 4, 0x23456,
+ 4, 0x24506,
+ 4, 0x20402,
+ 4, 0x10402,
+ 3, 0xd7ff,
+ 3, 0xe000,
+
+ };
+
+ int16_t i;
+ UBool multiple;
+ for(i=0; i<sizeof(codepoint)/sizeof(codepoint[0]); i=(int16_t)(i+2)){
+ UChar32 c=codepoint[i+1];
+ if(UTF8_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U8_LENGTH(c) != (uint16_t)codepoint[i]){
+ log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF8_CHAR_LENGTH(c));
+ }else{
+ log_verbose("The no: of code units for %lx is %d\n",c, UTF8_CHAR_LENGTH(c) );
+ }
+ multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
+ if(UTF8_NEED_MULTIPLE_UCHAR(c) != multiple){
+ log_err("ERROR: UTF8_NEED_MULTIPLE_UCHAR failed for %lx\n", c);
+ }
+ }
+}
+
+static void TestGetChar()
+{
+ static const uint8_t input[]={
+ /* code unit,*/
+ 0x61,
+ 0x7f,
+ 0xe4,
+ 0xba,
+ 0x8c,
+ 0xF0,
+ 0x90,
+ 0x90,
+ 0x81,
+ 0xc0,
+ 0x65,
+ 0x31,
+ 0x9a,
+ 0xc9
+ };
+ static const UChar32 result[]={
+ /*codepoint-unsafe, codepoint-safe(not strict) codepoint-safe(strict)*/
+ 0x61, 0x61, 0x61,
+ 0x7f, 0x7f, 0x7f,
+ 0x4e8c, 0x4e8c, 0x4e8c,
+ 0x4e8c, 0x4e8c, 0x4e8c ,
+ 0x4e8c, 0x4e8c, 0x4e8c,
+ 0x10401, 0x10401, 0x10401 ,
+ 0x10401, 0x10401, 0x10401 ,
+ 0x10401, 0x10401, 0x10401 ,
+ 0x10401, 0x10401, 0x10401,
+ 0x25, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x65, 0x65, 0x65,
+ 0x31, 0x31, 0x31,
+ 0x31, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x240, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1
+ };
+ uint16_t i=0;
+ UChar32 c;
+ uint32_t offset=0;
+
+ for(offset=0; offset<sizeof(input); offset++) {
+ if (offset < sizeof(input) - 1) {
+ UTF8_GET_CHAR_UNSAFE(input, offset, c);
+ if(c != result[i]){
+ log_err("ERROR: UTF8_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+
+ }
+
+ U8_GET_UNSAFE(input, offset, c);
+ if(c != result[i]){
+ log_err("ERROR: U8_GET_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+
+ }
+ }
+
+ U8_GET(input, 0, offset, sizeof(input), c);
+ if(UTF_IS_ERROR(result[i+1]) ? c >= 0 : c != result[i+1]){
+ log_err("ERROR: UTF8_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ UTF8_GET_CHAR_SAFE(input, 0, offset, sizeof(input), c, FALSE);
+ if(c != result[i+1]){
+ log_err("ERROR: UTF8_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ UTF8_GET_CHAR_SAFE(input, 0, offset, sizeof(input), c, TRUE);
+ if(c != result[i+2]){
+ log_err("ERROR: UTF8_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
+ }
+
+ i=(uint16_t)(i+3);
+ }
+}
+
+static void TestNextPrevChar(){
+ static const uint8_t input[]={0x61, 0xf0, 0x90, 0x90, 0x81, 0xc0, 0x80, 0xfd, 0xbe, 0xc2, 0x61, 0x81, 0x90, 0x90, 0xf0, 0x00};
+ static const UChar32 result[]={
+ /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/
+ 0x0061, 0x0061, 0x0061, 0x0000, 0x0000, 0x0000,
+ 0x10401, 0x10401, 0x10401, 0xf0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x2841410, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xa1050, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x81, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x2841, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x00, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, 0x61, 0x61, 0x61,
+ 0x80, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xc2, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0xfd, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2, 0x77e, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2,
+ 0xbe, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xfd, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0xa1, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x00, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2,
+ 0x61, 0x61, 0x61, 0xc0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x81, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x10401, 0x10401, 0x10401,
+ 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x410, UTF_ERROR_VALUE, UTF_ERROR_VALUE,
+ 0x90, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0x410, UTF8_ERROR_VALUE_2, UTF8_ERROR_VALUE_2,
+ 0x0840, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1, 0xf0, UTF8_ERROR_VALUE_1, UTF8_ERROR_VALUE_1,
+ 0x0000, 0x0000, 0x0000, 0x0061, 0x0061, 0x0061
+ };
+ static const int32_t movedOffset[]={
+ /*next_unsafe next_safe_ns next_safe_s prev_unsafe prev_safe_ns prev_safe_s*/
+ 1, 1, 1, 15, 15, 15,
+ 5, 5, 5, 14, 14 , 14,
+ 3, 3, 3, 9, 13, 13,
+ 4, 4, 4, 9, 12, 12,
+ 5, 5, 5, 9, 11, 11,
+ 7, 7, 7, 10, 10, 10,
+ 7, 7, 7, 9, 9, 9,
+ 8, 9, 9, 7, 7, 7,
+ 9, 9, 9, 7, 7, 7,
+ 11, 10, 10, 5, 5, 5,
+ 11, 11, 11, 5, 5, 5,
+ 12, 12, 12, 1, 1, 1,
+ 13, 13, 13, 1, 1, 1,
+ 14, 14, 14, 1, 1, 1,
+ 14, 15, 15, 1, 1, 1,
+ 14, 16, 16, 0, 0, 0,
+
+
+ };
+
+
+ UChar32 c=0x0000;
+ uint32_t i=0;
+ uint32_t offset=0;
+ int32_t setOffset=0;
+ for(offset=0; offset<sizeof(input); offset++){
+ if (offset < sizeof(input) - 2) { /* Can't have it go off the end of the array based on input */
+ setOffset=offset;
+ UTF8_NEXT_CHAR_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i]){
+ log_err("ERROR: UTF8_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i], setOffset);
+ }
+ if(c != result[i]){
+ log_err("ERROR: UTF8_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+
+ setOffset=offset;
+ U8_NEXT_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i]){
+ log_err("ERROR: U8_NEXT_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i], setOffset);
+ }
+ if(c != result[i]){
+ log_err("ERROR: U8_NEXT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
+ }
+ }
+
+ setOffset=offset;
+ UTF8_NEXT_CHAR_SAFE(input, setOffset, sizeof(input), c, FALSE);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: UTF8_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+1], setOffset);
+ }
+ if(c != result[i+1]){
+ log_err("ERROR: UTF8_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ setOffset=offset;
+ U8_NEXT(input, setOffset, sizeof(input), c);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: U8_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+1], setOffset);
+ }
+ if(UTF_IS_ERROR(result[i+1]) ? c >= 0 : c != result[i+1]){
+ log_err("ERROR: U8_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
+ }
+
+ setOffset=offset;
+ UTF8_NEXT_CHAR_SAFE(input, setOffset, sizeof(input), c, TRUE);
+ if(setOffset != movedOffset[i+1]){
+ log_err("ERROR: UTF8_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+2], setOffset);
+ }
+ if(c != result[i+2]){
+ log_err("ERROR: UTF8_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
+ }
+
+ i=i+6;
+ }
+
+ i=0;
+ for(offset=sizeof(input); offset > 0; --offset){
+ setOffset=offset;
+ UTF8_PREV_CHAR_UNSAFE(input, setOffset, c);
+ if(setOffset != movedOffset[i+3]){
+ log_err("ERROR: UTF8_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+3], setOffset);
+ }
+ if(c != result[i+3]){
+ log_err("ERROR: UTF8_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
+ }
+
+ setOffset=offset;
+ UTF8_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE);
+ if(setOffset != movedOffset[i+4]){
+ log_err("ERROR: UTF8_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+4], setOffset);
+ }
+ if(c != result[i+4]){
+ log_err("ERROR: UTF8_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
+ }
+
+ setOffset=offset;
+ U8_PREV(input, 0, setOffset, c);
+ if(setOffset != movedOffset[i+4]){
+ log_err("ERROR: U8_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+4], setOffset);
+ }
+ if(UTF_IS_ERROR(result[i+4]) ? c >= 0 : c != result[i+4]){
+ log_err("ERROR: U8_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
+ }
+
+ setOffset=offset;
+ UTF8_PREV_CHAR_SAFE(input, 0, setOffset, c, TRUE);
+ if(setOffset != movedOffset[i+5]){
+ log_err("ERROR: UTF8_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
+ offset, movedOffset[i+5], setOffset);
+ }
+ if(c != result[i+5]){
+ log_err("ERROR: UTF8_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c);
+ }
+
+ i=i+6;
+ }
+
+ {
+ /* test non-characters */
+ static const uint8_t nonChars[]={
+ 0xef, 0xb7, 0x90, /* U+fdd0 */
+ 0xef, 0xbf, 0xbf, /* U+feff */
+ 0xf0, 0x9f, 0xbf, 0xbe, /* U+1fffe */
+ 0xf0, 0xbf, 0xbf, 0xbf, /* U+3ffff */
+ 0xf4, 0x8f, 0xbf, 0xbe /* U+10fffe */
+ };
+
+ UChar32 ch;
+ int32_t idx;
+
+ for(idx=0; idx<(int32_t)sizeof(nonChars);) {
+ U8_NEXT(nonChars, idx, sizeof(nonChars), ch);
+ if(!U_IS_UNICODE_NONCHAR(ch)) {
+ log_err("U8_NEXT(before %d) failed to read a non-character\n", idx);
+ }
+ }
+ for(idx=(int32_t)sizeof(nonChars); idx>0;) {
+ U8_PREV(nonChars, 0, idx, ch);
+ if(!U_IS_UNICODE_NONCHAR(ch)) {
+ log_err("U8_PREV(at %d) failed to read a non-character\n", idx);
+ }
+ }
+ }
+}
+
+static void TestFwdBack(){
+ static const uint8_t input[]={0x61, 0xF0, 0x90, 0x90, 0x81, 0xff, 0x62, 0xc0, 0x80, 0x7f, 0x8f, 0xc0, 0x63, 0x81, 0x90, 0x90, 0xF0, 0x00};
+ static const uint16_t fwd_unsafe[] ={1, 5, 6, 7, 9, 10, 11, 13, 14, 15, 16, 20, };
+ static const uint16_t fwd_safe[] ={1, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
+ static const uint16_t back_unsafe[]={17, 16, 12, 11, 9, 7, 6, 5, 1, 0};
+ static const uint16_t back_safe[] ={17, 16, 15, 14, 13, 12, 11, 10, 9, 7, 6, 5, 1, 0};
+
+ static const uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1, 5};
+ static const uint16_t fwd_N_unsafe[] ={0, 1, 6, 10, 11, 14, 15};
+ static const uint16_t fwd_N_safe[] ={0, 1, 6, 10, 11, 13, 14, 18}; /*safe macro keeps it at the end of the string */
+ static const uint16_t back_N_unsafe[]={18, 17, 12, 7, 6, 1, 0};
+ static const uint16_t back_N_safe[] ={18, 17, 15, 12, 11, 9, 7, 0};
+
+
+ uint32_t offunsafe=0, offsafe=0;
+
+ uint32_t i=0;
+ while(offunsafe < sizeof(input)){
+ UTF8_FWD_1_UNSAFE(input, offunsafe);
+ if(offunsafe != fwd_unsafe[i]){
+ log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offunsafe < sizeof(input)){
+ U8_FWD_1_UNSAFE(input, offunsafe);
+ if(offunsafe != fwd_unsafe[i]){
+ log_err("ERROR: U8_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe < sizeof(input)){
+ UTF8_FWD_1_SAFE(input, offsafe, sizeof(input));
+ if(offsafe != fwd_safe[i]){
+ log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ while(offsafe < sizeof(input)){
+ U8_FWD_1(input, offsafe, sizeof(input));
+ if(offsafe != fwd_safe[i]){
+ log_err("ERROR: U8_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
+ }
+ i++;
+ }
+
+ offunsafe=sizeof(input);
+ i=0;
+ while(offunsafe > 0){
+ UTF8_BACK_1_UNSAFE(input, offunsafe);
+ if(offunsafe != back_unsafe[i]){
+ log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ offunsafe=sizeof(input);
+ i=0;
+ while(offunsafe > 0){
+ U8_BACK_1_UNSAFE(input, offunsafe);
+ if(offunsafe != back_unsafe[i]){
+ log_err("ERROR: U8_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ offsafe=sizeof(input);
+ while(offsafe > 0){
+ UTF8_BACK_1_SAFE(input, 0, offsafe);
+ if(offsafe != back_safe[i]){
+ log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
+ }
+ i++;
+ }
+
+ i=0;
+ offsafe=sizeof(input);
+ while(offsafe > 0){
+ U8_BACK_1(input, 0, offsafe);
+ if(offsafe != back_safe[i]){
+ log_err("ERROR: U8_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
+ }
+ i++;
+ }
+
+ offunsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ UTF8_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != fwd_N_unsafe[i]){
+ log_err("ERROR: Forward_N_unsafe offset=%d expected:%d, Got:%d\n", i, fwd_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offunsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ U8_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != fwd_N_unsafe[i]){
+ log_err("ERROR: U8_FWD_N_UNSAFE offset=%d expected:%d, Got:%d\n", i, fwd_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ UTF8_FWD_N_SAFE(input, offsafe, sizeof(input), Nvalue[i]);
+ if(offsafe != fwd_N_safe[i]){
+ log_err("ERROR: Forward_N_safe offset=%d expected:%d, Got:%d\n", i, fwd_N_safe[i], offsafe);
+ }
+
+ }
+
+ offsafe=0;
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ U8_FWD_N(input, offsafe, sizeof(input), Nvalue[i]);
+ if(offsafe != fwd_N_safe[i]){
+ log_err("ERROR: U8_FWD_N offset=%d expected:%d, Got:%d\n", i, fwd_N_safe[i], offsafe);
+ }
+
+ }
+
+ offunsafe=sizeof(input);
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ UTF8_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != back_N_unsafe[i]){
+ log_err("ERROR: backward_N_unsafe offset=%d expected:%d, Got:%d\n", i, back_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offunsafe=sizeof(input);
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
+ U8_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
+ if(offunsafe != back_N_unsafe[i]){
+ log_err("ERROR: U8_BACK_N_UNSAFE offset=%d expected:%d, Got:%d\n", i, back_N_unsafe[i], offunsafe);
+ }
+ }
+
+ offsafe=sizeof(input);
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ UTF8_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]);
+ if(offsafe != back_N_safe[i]){
+ log_err("ERROR: backward_N_safe offset=%d expected:%d, Got:%ld\n", i, back_N_safe[i], offsafe);
+ }
+ }
+
+ offsafe=sizeof(input);
+ for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
+ U8_BACK_N(input, 0, offsafe, Nvalue[i]);
+ if(offsafe != back_N_safe[i]){
+ log_err("ERROR: U8_BACK_N offset=%d expected:%d, Got:%ld\n", i, back_N_safe[i], offsafe);
+ }
+ }
+}
+
+static void TestSetChar(){
+ static const uint8_t input[]
+ = {0x61, 0xe4, 0xba, 0x8c, 0x7f, 0xfe, 0x62, 0xc5, 0x7f, 0x61, 0x80, 0x80, 0xe0, 0x00 };
+ static const int16_t start_unsafe[]
+ = {0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 12, 13 };
+ static const int16_t start_safe[]
+ = {0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
+ static const int16_t limit_unsafe[]
+ = {0, 1, 4, 4, 4, 5, 6, 7, 9, 9, 10, 10, 10, 15 };
+ static const int16_t limit_safe[]
+ = {0, 1, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
+
+ uint32_t i=0;
+ int32_t offset=0, setOffset=0;
+ for(offset=0; offset<(int32_t)sizeof(input); offset++){
+ setOffset=offset;
+ UTF8_SET_CHAR_START_UNSAFE(input, setOffset);
+ if(setOffset != start_unsafe[i]){
+ log_err("ERROR: UTF8_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U8_SET_CP_START_UNSAFE(input, setOffset);
+ if(setOffset != start_unsafe[i]){
+ log_err("ERROR: U8_SET_CP_START_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ UTF8_SET_CHAR_START_SAFE(input, 0, setOffset);
+ if(setOffset != start_safe[i]){
+ log_err("ERROR: UTF8_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_safe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U8_SET_CP_START(input, 0, setOffset);
+ if(setOffset != start_safe[i]){
+ log_err("ERROR: U8_SET_CP_START failed for offset=%ld. Expected:%ld Got:%ld\n", offset, start_safe[i], setOffset);
+ }
+
+ if (offset != 0) { /* Can't have it go off the end of the array */
+ setOffset=offset;
+ UTF8_SET_CHAR_LIMIT_UNSAFE(input, setOffset);
+ if(setOffset != limit_unsafe[i]){
+ log_err("ERROR: UTF8_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_unsafe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U8_SET_CP_LIMIT_UNSAFE(input, setOffset);
+ if(setOffset != limit_unsafe[i]){
+ log_err("ERROR: U8_SET_CP_LIMIT_UNSAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_unsafe[i], setOffset);
+ }
+ }
+
+ setOffset=offset;
+ UTF8_SET_CHAR_LIMIT_SAFE(input,0, setOffset, sizeof(input));
+ if(setOffset != limit_safe[i]){
+ log_err("ERROR: UTF8_SET_CHAR_LIMIT_SAFE failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset);
+ }
+
+ setOffset=offset;
+ U8_SET_CP_LIMIT(input,0, setOffset, sizeof(input));
+ if(setOffset != limit_safe[i]){
+ log_err("ERROR: U8_SET_CP_LIMIT failed for offset=%ld. Expected:%ld Got:%ld\n", offset, limit_safe[i], setOffset);
+ }
+
+ i++;
+ }
+}
+
+static void TestAppendChar(){
+ static const uint8_t s[11]={0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00};
+ static const uint32_t test[]={
+ /*append-position(unsafe), CHAR to be appended */
+ 0, 0x10401,
+ 2, 0x0028,
+ 2, 0x007f,
+ 3, 0xd801,
+ 1, 0x20402,
+ 8, 0x10401,
+ 5, 0xc0,
+ 5, 0xc1,
+ 5, 0xfd,
+ 6, 0x80,
+ 6, 0x81,
+ 6, 0xbf,
+ 7, 0xfe,
+
+ /*append-position(safe), CHAR to be appended */
+ 0, 0x10401,
+ 2, 0x0028,
+ 3, 0x7f,
+ 3, 0xd801, /* illegal for UTF-8 starting with Unicode 3.2 */
+ 1, 0x20402,
+ 9, 0x10401,
+ 5, 0xc0,
+ 5, 0xc1,
+ 5, 0xfd,
+ 6, 0x80,
+ 6, 0x81,
+ 6, 0xbf,
+ 7, 0xfe,
+
+ };
+ static const uint16_t movedOffset[]={
+ /*offset-moved-to(unsafe)*/
+ 4, /*for append-pos: 0 , CHAR 0x10401*/
+ 3,
+ 3,
+ 6,
+ 5,
+ 12,
+ 7,
+ 7,
+ 7,
+ 8,
+ 8,
+ 8,
+ 9,
+
+ /*offset-moved-to(safe)*/
+ 4, /*for append-pos: 0, CHAR 0x10401*/
+ 3,
+ 4,
+ 6,
+ 5,
+ 11,
+ 7,
+ 7,
+ 7,
+ 8,
+ 8,
+ 8,
+ 9,
+
+ };
+
+ static const uint8_t result[][11]={
+ /*unsafe*/
+ {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x7f, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0xed, 0xa0, 0x81, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0xF0, 0x90, 0x90},
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00},
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00},
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00},
+ /*safe*/
+ {0xF0, 0x90, 0x90, 0x81, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x28, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x7f, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0xef, 0xbf, 0xbf, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0xF0, 0xa0, 0x90, 0x82, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc2, 0x9f}, /*gets UTF8_ERROR_VALUE_2 which takes 2 bytes 0xc0, 0x9f*/
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x80, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0x81, 0x68, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0xc3, 0xbd, 0x68, 0x69, 0x6a, 0x00},
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x80, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0x81, 0x69, 0x6a, 0x00},
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0xc2, 0xbf, 0x69, 0x6a, 0x00},
+
+ {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0xc3, 0xbe, 0x6a, 0x00},
+
+ };
+ uint16_t i, count=0;
+ uint8_t str[12];
+ uint32_t offset;
+/* UChar32 c=0;*/
+ uint16_t size=sizeof(s)/sizeof(s[0]);
+ for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){
+ uprv_memcpy(str, s, size);
+ offset=test[i];
+ if(count<13){
+ UTF8_APPEND_CHAR_UNSAFE(str, offset, test[i+1]);
+ if(offset != movedOffset[count]){
+ log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n",
+ count, movedOffset[count], offset);
+
+ }
+ if(uprv_memcmp(str, result[count], size) !=0){
+ log_err("ERROR: UTF8_APPEND_CHAR_UNSAFE failed for count=%d. \nExpected:", count);
+ printUChars(result[count], size);
+ log_err("\nGot: ");
+ printUChars(str, size);
+ log_err("\n");
+ }
+ }else{
+ UTF8_APPEND_CHAR_SAFE(str, offset, size, test[i+1]);
+ if(offset != movedOffset[count]){
+ log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n",
+ count, movedOffset[count], offset);
+
+ }
+ if(uprv_memcmp(str, result[count], size) !=0){
+ log_err("ERROR: UTF8_APPEND_CHAR_SAFE failed for count=%d. \nExpected:", count);
+ printUChars(result[count], size);
+ log_err("\nGot: ");
+ printUChars(str, size);
+ log_err("\n");
+ }
+ /*call the API instead of MACRO
+ uprv_memcpy(str, s, size);
+ offset=test[i];
+ c=test[i+1];
+ if((uint32_t)(c)<=0x7f) {
+ (str)[(offset)++]=(uint8_t)(c);
+ } else {
+ (offset)=utf8_appendCharSafeBody(str, (int32_t)(offset), (int32_t)(size), c);
+ }
+ if(offset != movedOffset[count]){
+ log_err("ERROR: utf8_appendCharSafeBody() failed to move the offset correctly for count=%d.\nExpectedOffset=%d currentOffset=%d\n",
+ count, movedOffset[count], offset);
+
+ }
+ if(uprv_memcmp(str, result[count], size) !=0){
+ log_err("ERROR: utf8_appendCharSafeBody() failed for count=%d. \nExpected:", count);
+ printUChars(result[count], size);
+ printf("\nGot: ");
+ printUChars(str, size);
+ printf("\n");
+ }
+ */
+ }
+ count++;
+ }
+
+
+}
+
+static void TestAppend() {
+ static const UChar32 codePoints[]={
+ 0x61, 0xdf, 0x901, 0x3040,
+ 0xac00, 0xd800, 0xdbff, 0xdcde,
+ 0xdffd, 0xe000, 0xffff, 0x10000,
+ 0x12345, 0xe0021, 0x10ffff, 0x110000,
+ 0x234567, 0x7fffffff, -1, -1000,
+ 0, 0x400
+ };
+ static const uint8_t expectUnsafe[]={
+ 0x61, 0xc3, 0x9f, 0xe0, 0xa4, 0x81, 0xe3, 0x81, 0x80,
+ 0xea, 0xb0, 0x80, 0xed, 0xa0, 0x80, 0xed, 0xaf, 0xbf, 0xed, 0xb3, 0x9e,
+ 0xed, 0xbf, 0xbd, 0xee, 0x80, 0x80, 0xef, 0xbf, 0xbf, 0xf0, 0x90, 0x80, 0x80,
+ 0xf0, 0x92, 0x8d, 0x85, 0xf3, 0xa0, 0x80, 0xa1, 0xf4, 0x8f, 0xbf, 0xbf, /* not 0x110000 */
+ /* none from this line */
+ 0, 0xd0, 0x80
+ }, expectSafe[]={
+ 0x61, 0xc3, 0x9f, 0xe0, 0xa4, 0x81, 0xe3, 0x81, 0x80,
+ 0xea, 0xb0, 0x80, /* no surrogates */
+ /* no surrogates */ 0xee, 0x80, 0x80, 0xef, 0xbf, 0xbf, 0xf0, 0x90, 0x80, 0x80,
+ 0xf0, 0x92, 0x8d, 0x85, 0xf3, 0xa0, 0x80, 0xa1, 0xf4, 0x8f, 0xbf, 0xbf, /* not 0x110000 */
+ /* none from this line */
+ 0, 0xd0, 0x80
+ };
+
+ uint8_t buffer[100];
+ UChar32 c;
+ int32_t i, length;
+ UBool isError, expectIsError, wrongIsError;
+
+ length=0;
+ for(i=0; i<LENGTHOF(codePoints); ++i) {
+ c=codePoints[i];
+ if(c<0 || 0x10ffff<c) {
+ continue; /* skip non-code points for U8_APPEND_UNSAFE */
+ }
+
+ U8_APPEND_UNSAFE(buffer, length, c);
+ }
+ if(length!=LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length)) {
+ log_err("U8_APPEND_UNSAFE did not generate the expected output\n");
+ }
+
+ length=0;
+ wrongIsError=FALSE;
+ for(i=0; i<LENGTHOF(codePoints); ++i) {
+ c=codePoints[i];
+ expectIsError= c<0 || 0x10ffff<c || U_IS_SURROGATE(c);
+ isError=FALSE;
+
+ U8_APPEND(buffer, length, LENGTHOF(buffer), c, isError);
+ wrongIsError|= isError!=expectIsError;
+ }
+ if(wrongIsError) {
+ log_err("U8_APPEND did not set isError correctly\n");
+ }
+ if(length!=LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length)) {
+ log_err("U8_APPEND did not generate the expected output\n");
+ }
+}
+
+static void
+TestSurrogates() {
+ static const uint8_t b[]={
+ 0xc3, 0x9f, /* 00DF */
+ 0xed, 0x9f, 0xbf, /* D7FF */
+ 0xed, 0xa0, 0x81, /* D801 */
+ 0xed, 0xbf, 0xbe, /* DFFE */
+ 0xee, 0x80, 0x80, /* E000 */
+ 0xf0, 0x97, 0xbf, 0xbe /* 17FFE */
+ };
+ static const UChar32 cp[]={
+ 0xdf, 0xd7ff, 0xd801, 0xdffe, 0xe000, 0x17ffe
+ };
+
+ UChar32 cu, cs, cl;
+ int32_t i, j, k, iu, is, il, length;
+
+ k=0; /* index into cp[] */
+ length=LENGTHOF(b);
+ for(i=0; i<length;) {
+ j=i;
+ U8_NEXT_UNSAFE(b, j, cu);
+ iu=j;
+
+ j=i;
+ U8_NEXT(b, j, length, cs);
+ is=j;
+
+ j=i;
+ L8_NEXT(b, j, length, cl);
+ il=j;
+
+ if(cu!=cp[k]) {
+ log_err("U8_NEXT_UNSAFE(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cu, (long)cp[k]);
+ }
+
+ /* U8_NEXT() returns <0 for surrogate code points */
+ if(U_IS_SURROGATE(cu) ? cs>=0 : cs!=cu) {
+ log_err("U8_NEXT(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cs, (long)cu);
+ }
+
+ /* L8_NEXT() returns surrogate code points like U8_NEXT_UNSAFE() */
+ if(cl!=cu) {
+ log_err("L8_NEXT(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cl, (long)cu);
+ }
+
+ if(is!=iu || il!=iu) {
+ log_err("U8_NEXT(b[%ld]) or L8_NEXT(b[%ld]) did not advance the index correctly\n", (long)i, (long)i);
+ }
+
+ ++k; /* next code point */
+ i=iu; /* advance by one UTF-8 sequence */
+ }
+
+ while(i>0) {
+ --k; /* previous code point */
+
+ j=i;
+ U8_PREV_UNSAFE(b, j, cu);
+ iu=j;
+
+ j=i;
+ U8_PREV(b, 0, j, cs);
+ is=j;
+
+ j=i;
+ L8_PREV(b, 0, j, cl);
+ il=j;
+
+ if(cu!=cp[k]) {
+ log_err("U8_PREV_UNSAFE(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cu, (long)cp[k]);
+ }
+
+ /* U8_PREV() returns <0 for surrogate code points */
+ if(U_IS_SURROGATE(cu) ? cs>=0 : cs!=cu) {
+ log_err("U8_PREV(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cs, (long)cu);
+ }
+
+ /* L8_PREV() returns surrogate code points like U8_PREV_UNSAFE() */
+ if(cl!=cu) {
+ log_err("L8_PREV(b[%ld])=U+%04lX != U+%04lX\n", (long)i, (long)cl, (long)cu);
+ }
+
+ if(is!=iu || il !=iu) {
+ log_err("U8_PREV(b[%ld]) or L8_PREV(b[%ld]) did not advance the index correctly\n", (long)i, (long)i);
+ }
+
+ i=iu; /* go back by one UTF-8 sequence */
+ }
+}
+
+static void printUChars(const uint8_t *uchars, int16_t len){
+ int16_t i=0;
+ for(i=0; i<len; i++){
+ log_err("0x%02x ", *(uchars+i));
+ }
+}
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c
new file mode 100644
index 00000000000..069a8039479
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utmstest.c
@@ -0,0 +1,487 @@
+/*
+ ****************************************************************************
+ * Copyright (c) 1997-2007, International Business Machines Corporation and *
+ * others. All Rights Reserved. *
+ ****************************************************************************
+ */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/utmscale.h"
+#include "unicode/ucal.h"
+
+#include "cintltst.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+#define LOOP_COUNT 10000
+
+static void TestAPI(void);
+static void TestData(void);
+static void TestMonkey(void);
+static void TestDotNet(void);
+
+void addUtmsTest(TestNode** root);
+
+void addUtmsTest(TestNode** root)
+{
+ addTest(root, &TestAPI, "tsformat/utmstest/TestAPI");
+ addTest(root, &TestData, "tsformat/utmstest/TestData");
+ addTest(root, &TestMonkey, "tsformat/utmstest/TestMonkey");
+ addTest(root, &TestDotNet, "tsformat/utmstest/TestDotNet");
+}
+
+/**
+ * Return a random int64_t where U_INT64_MIN <= ran <= U_INT64_MAX.
+ */
+static uint64_t randomInt64(void)
+{
+ int64_t ran = 0;
+ int32_t i;
+ static UBool initialized = FALSE;
+
+ if (!initialized) {
+ srand((unsigned)time(NULL));
+ initialized = TRUE;
+ }
+
+ /* Assume rand has at least 12 bits of precision */
+ for (i = 0; i < sizeof(ran); i += 1) {
+ ((char*)&ran)[i] = (char)((rand() & 0x0FF0) >> 4);
+ }
+
+ return ran;
+}
+
+static int64_t ranInt;
+static int64_t ranMin;
+static int64_t ranMax;
+
+static void initRandom(int64_t min, int64_t max)
+{
+ uint64_t interval = max - min;
+
+ ranMin = min;
+ ranMax = max;
+ ranInt = 0;
+
+ /* Verify that we don't have a huge interval. */
+ if (interval < (uint64_t)U_INT64_MAX) {
+ ranInt = interval;
+ }
+}
+
+static int64_t randomInRange(void)
+{
+ int64_t value;
+
+ if (ranInt != 0) {
+ value = randomInt64() % ranInt;
+
+ if (value < 0) {
+ value = -value;
+ }
+
+ value += ranMin;
+ } else {
+ do {
+ value = randomInt64();
+ } while (value < ranMin || value > ranMax);
+ }
+
+ return value;
+}
+
+static void roundTripTest(int64_t value, UDateTimeScale scale)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int64_t rt = utmscale_toInt64(utmscale_fromInt64(value, scale, &status), scale, &status);
+
+ if (rt != value) {
+ log_err("Round-trip error: time scale = %d, value = %lld, round-trip = %lld.\n", scale, value, rt);
+ }
+}
+
+static void toLimitTest(int64_t toLimit, int64_t fromLimit, UDateTimeScale scale)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int64_t result = utmscale_toInt64(toLimit, scale, &status);
+
+ if (result != fromLimit) {
+ log_err("toLimit failure: scale = %d, toLimit = %lld , utmscale_toInt64(toLimit, scale, &status) = %lld, fromLimit = %lld.\n",
+ scale, toLimit, result, fromLimit);
+ }
+}
+
+static void epochOffsetTest(int64_t epochOffset, int64_t units, UDateTimeScale scale)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int64_t universal = 0;
+ int64_t universalEpoch = epochOffset * units;
+ int64_t local = utmscale_toInt64(universalEpoch, scale, &status);
+
+ if (local != 0) {
+ log_err("utmscale_toInt64(epochOffset, scale, &status): scale = %d epochOffset = %lld, result = %lld.\n", scale, epochOffset, local);
+ }
+
+ local = utmscale_toInt64(0, scale, &status);
+
+ if (local != -epochOffset) {
+ log_err("utmscale_toInt64(0, scale): scale = %d, result = %lld.\n", scale, local);
+ }
+
+ universal = utmscale_fromInt64(-epochOffset, scale, &status);
+
+ if (universal != 0) {
+ log_err("from(-epochOffest, scale): scale = %d, epochOffset = %lld, result = %lld.\n", scale, epochOffset, universal);
+ }
+
+ universal = utmscale_fromInt64(0, scale, &status);
+
+ if (universal != universalEpoch) {
+ log_err("utmscale_fromInt64(0, scale): scale = %d, result = %lld.\n", scale, universal);
+ }
+}
+
+static void TestEpochOffsets(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t scale;
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t units = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_UNITS_VALUE, &status);
+ int64_t epochOffset = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_EPOCH_OFFSET_VALUE, &status);
+
+ epochOffsetTest(epochOffset, units, (UDateTimeScale)scale);
+ }
+}
+
+static void TestFromLimits(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t scale;
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status);
+ int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status);
+
+ roundTripTest(fromMin, (UDateTimeScale)scale);
+ roundTripTest(fromMax, (UDateTimeScale)scale);
+ }
+}
+
+static void TestToLimits(void)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t scale;
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status);
+ int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status);
+ int64_t toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status);
+ int64_t toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status);
+
+ toLimitTest(toMin, fromMin, (UDateTimeScale)scale);
+ toLimitTest(toMax, fromMax, (UDateTimeScale)scale);
+ }
+}
+
+static void TestFromInt64(void)
+{
+ int32_t scale;
+ int64_t result;
+ UErrorCode status = U_ZERO_ERROR;
+
+ result = utmscale_fromInt64(0, -1, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(0, -1, status) did not set status to U_ILLEGAL_ARGUMENT_ERROR.\n");
+ }
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t fromMin, fromMax;
+
+ status = U_ZERO_ERROR;
+ fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status);
+ fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status);
+
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(0, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(fromMin, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(fromMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ if (fromMin > U_INT64_MIN) {
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(fromMin - 1, (UDateTimeScale)scale, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(fromMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(fromMax, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(fromMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ if (fromMax < U_INT64_MAX) {
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(fromMax + 1, (UDateTimeScale)scale, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(fromMax + 1, %d, &status) didn't generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ result = utmscale_fromInt64(0, UDTS_MAX_SCALE, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_fromInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n");
+ }
+}
+
+static void TestToInt64(void)
+{
+ int32_t scale;
+ int64_t result;
+ UErrorCode status = U_ZERO_ERROR;
+
+ result = utmscale_toInt64(0, -1, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(0, -1, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n");
+ }
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t toMin, toMax;
+
+ status = U_ZERO_ERROR;
+ toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status);
+ toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status);
+
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(0, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(toMin, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(toMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ if (toMin > U_INT64_MIN) {
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(toMin - 1, (UDateTimeScale)scale, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(toMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+ }
+
+
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(toMax, (UDateTimeScale)scale, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(toMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+
+ if (toMax < U_INT64_MAX) {
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(toMax + 1, (UDateTimeScale)scale, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(toMax + 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale);
+ }
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ result = utmscale_toInt64(0, UDTS_MAX_SCALE, &status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("utmscale_toInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n");
+ }
+}
+
+static void TestAPI(void)
+{
+ TestFromInt64();
+ TestToInt64();
+}
+
+static void TestData(void)
+{
+ TestEpochOffsets();
+ TestFromLimits();
+ TestToLimits();
+}
+
+static void TestMonkey(void)
+{
+ int32_t scale;
+ UErrorCode status = U_ZERO_ERROR;
+
+ for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) {
+ int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status);
+ int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status);
+ int32_t i;
+
+ initRandom(fromMin, fromMax);
+
+ for (i = 0; i < LOOP_COUNT; i += 1) {
+ int64_t value = randomInRange();
+
+ roundTripTest(value, (UDateTimeScale)scale);
+ }
+ }
+}
+
+struct DotNetDateTimeTicks {
+ int32_t year;
+ int32_t month;
+ int32_t day;
+ int64_t ticks;
+};
+typedef struct DotNetDateTimeTicks DotNetDateTimeTicks;
+
+/*
+ * This data was generated by C++.Net code like
+ * Console::WriteLine(L" {{ {0}, 1, 1, INT64_C({1}) }},", year, DateTime(year, 1, 1).Ticks);
+ * with the DateTime constructor taking int values for year, month, and date.
+ */
+static const DotNetDateTimeTicks dotNetDateTimeTicks[]={
+ /* year, month, day, ticks */
+ { 100, 1, 1, INT64_C(31241376000000000) },
+ { 100, 3, 1, INT64_C(31292352000000000) },
+ { 200, 1, 1, INT64_C(62798112000000000) },
+ { 200, 3, 1, INT64_C(62849088000000000) },
+ { 300, 1, 1, INT64_C(94354848000000000) },
+ { 300, 3, 1, INT64_C(94405824000000000) },
+ { 400, 1, 1, INT64_C(125911584000000000) },
+ { 400, 3, 1, INT64_C(125963424000000000) },
+ { 500, 1, 1, INT64_C(157469184000000000) },
+ { 500, 3, 1, INT64_C(157520160000000000) },
+ { 600, 1, 1, INT64_C(189025920000000000) },
+ { 600, 3, 1, INT64_C(189076896000000000) },
+ { 700, 1, 1, INT64_C(220582656000000000) },
+ { 700, 3, 1, INT64_C(220633632000000000) },
+ { 800, 1, 1, INT64_C(252139392000000000) },
+ { 800, 3, 1, INT64_C(252191232000000000) },
+ { 900, 1, 1, INT64_C(283696992000000000) },
+ { 900, 3, 1, INT64_C(283747968000000000) },
+ { 1000, 1, 1, INT64_C(315253728000000000) },
+ { 1000, 3, 1, INT64_C(315304704000000000) },
+ { 1100, 1, 1, INT64_C(346810464000000000) },
+ { 1100, 3, 1, INT64_C(346861440000000000) },
+ { 1200, 1, 1, INT64_C(378367200000000000) },
+ { 1200, 3, 1, INT64_C(378419040000000000) },
+ { 1300, 1, 1, INT64_C(409924800000000000) },
+ { 1300, 3, 1, INT64_C(409975776000000000) },
+ { 1400, 1, 1, INT64_C(441481536000000000) },
+ { 1400, 3, 1, INT64_C(441532512000000000) },
+ { 1500, 1, 1, INT64_C(473038272000000000) },
+ { 1500, 3, 1, INT64_C(473089248000000000) },
+ { 1600, 1, 1, INT64_C(504595008000000000) },
+ { 1600, 3, 1, INT64_C(504646848000000000) },
+ { 1700, 1, 1, INT64_C(536152608000000000) },
+ { 1700, 3, 1, INT64_C(536203584000000000) },
+ { 1800, 1, 1, INT64_C(567709344000000000) },
+ { 1800, 3, 1, INT64_C(567760320000000000) },
+ { 1900, 1, 1, INT64_C(599266080000000000) },
+ { 1900, 3, 1, INT64_C(599317056000000000) },
+ { 2000, 1, 1, INT64_C(630822816000000000) },
+ { 2000, 3, 1, INT64_C(630874656000000000) },
+ { 2100, 1, 1, INT64_C(662380416000000000) },
+ { 2100, 3, 1, INT64_C(662431392000000000) },
+ { 2200, 1, 1, INT64_C(693937152000000000) },
+ { 2200, 3, 1, INT64_C(693988128000000000) },
+ { 2300, 1, 1, INT64_C(725493888000000000) },
+ { 2300, 3, 1, INT64_C(725544864000000000) },
+ { 2400, 1, 1, INT64_C(757050624000000000) },
+ { 2400, 3, 1, INT64_C(757102464000000000) },
+ { 2500, 1, 1, INT64_C(788608224000000000) },
+ { 2500, 3, 1, INT64_C(788659200000000000) },
+ { 2600, 1, 1, INT64_C(820164960000000000) },
+ { 2600, 3, 1, INT64_C(820215936000000000) },
+ { 2700, 1, 1, INT64_C(851721696000000000) },
+ { 2700, 3, 1, INT64_C(851772672000000000) },
+ { 2800, 1, 1, INT64_C(883278432000000000) },
+ { 2800, 3, 1, INT64_C(883330272000000000) },
+ { 2900, 1, 1, INT64_C(914836032000000000) },
+ { 2900, 3, 1, INT64_C(914887008000000000) },
+ { 3000, 1, 1, INT64_C(946392768000000000) },
+ { 3000, 3, 1, INT64_C(946443744000000000) },
+ { 1, 1, 1, INT64_C(0) },
+ { 1601, 1, 1, INT64_C(504911232000000000) },
+ { 1899, 12, 31, INT64_C(599265216000000000) },
+ { 1904, 1, 1, INT64_C(600527520000000000) },
+ { 1970, 1, 1, INT64_C(621355968000000000) },
+ { 2001, 1, 1, INT64_C(631139040000000000) },
+ { 9900, 3, 1, INT64_C(3123873216000000000) },
+ { 9999, 12, 31, INT64_C(3155378112000000000) }
+};
+
+/*
+ * ICU's Universal Time Scale is designed to be tick-for-tick compatible with
+ * .Net System.DateTime. Verify that this is so for the
+ * .Net-supported date range (years 1-9999 AD).
+ * This requires a proleptic Gregorian calendar because that's what .Net uses.
+ * Proleptic: No Julian/Gregorian switchover, or a switchover before
+ * any date that we test, that is, before 0001 AD.
+ */
+static void
+TestDotNet() {
+ static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */
+ const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */
+ const int64_t dayTicks = 86400 * INT64_C(10000000);
+ const DotNetDateTimeTicks *dt;
+ UCalendar *cal;
+ UErrorCode errorCode;
+ UDate icuDate;
+ int64_t ticks, millis;
+ int32_t i;
+
+ /* Open a proleptic Gregorian calendar. */
+ errorCode = U_ZERO_ERROR;
+ cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode);
+ ucal_setGregorianChange(cal, -1000000 * (dayMillis * (UDate)1), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucal_open(UTC/proleptic Gregorian) failed: %s\n", u_errorName(errorCode));
+ ucal_close(cal);
+ return;
+ }
+ for(i = 0; i < LENGTHOF(dotNetDateTimeTicks); ++i) {
+ /* Test conversion from .Net/Universal time to ICU time. */
+ dt = dotNetDateTimeTicks + i;
+ millis = utmscale_toInt64(dt->ticks, UDTS_ICU4C_TIME, &errorCode);
+ ucal_clear(cal);
+ ucal_setDate(cal, dt->year, dt->month - 1, dt->day, &errorCode); /* Java & ICU use January = month 0. */
+ icuDate = ucal_getMillis(cal, &errorCode);
+ if(millis != icuDate) {
+ /* Print days not millis to stay within printf() range. */
+ log_err("utmscale_toInt64(ticks[%d], ICU4C)=%dd != %dd=ucal_getMillis(%04d-%02d-%02d)\n",
+ (int)i, (int)(millis/dayMillis), (int)(icuDate/dayMillis), (int)dt->year, (int)dt->month, (int)dt->day);
+ }
+
+ /* Test conversion from ICU time to .Net/Universal time. */
+ ticks = utmscale_fromInt64((int64_t)icuDate, UDTS_ICU4C_TIME, &errorCode);
+ if(ticks != dt->ticks) {
+ /* Print days not ticks to stay within printf() range. */
+ log_err("utmscale_fromInt64(date[%d], ICU4C)=%dd != %dd=.Net System.DateTime(%04d-%02d-%02d).Ticks\n",
+ (int)i, (int)(ticks/dayTicks), (int)(dt->ticks/dayTicks), (int)dt->year, (int)dt->month, (int)dt->day);
+ }
+ }
+
+ ucal_close(cal);
+}
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c b/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c
new file mode 100644
index 00000000000..ec99292aa9f
--- /dev/null
+++ b/Build/source/libs/icu/icu-xetex/test/cintltst/utransts.c
@@ -0,0 +1,707 @@
+/*
+ *******************************************************************************
+ * Copyright (C) 1997-2006, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ *******************************************************************************
+ * Date Name Description
+ * 06/23/00 aliu Creation.
+ *******************************************************************************
+ */
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_TRANSLITERATION
+
+#include <stdlib.h>
+#include <string.h>
+#include "unicode/utrans.h"
+#include "unicode/ustring.h"
+#include "cintltst.h"
+
+#define TEST(x) addTest(root, &x, "utrans/" # x)
+
+static void TestAPI(void);
+static void TestSimpleRules(void);
+static void TestFilter(void);
+static void TestOpenInverse(void);
+static void TestClone(void);
+static void TestRegisterUnregister(void);
+static void TestExtractBetween(void);
+static void TestUnicodeIDs(void);
+
+static void _expectRules(const char*, const char*, const char*);
+static void _expect(const UTransliterator* trans, const char* cfrom, const char* cto);
+
+void addUTransTest(TestNode** root);
+
+
+void
+addUTransTest(TestNode** root) {
+ TEST(TestAPI);
+ TEST(TestSimpleRules);
+ TEST(TestFilter);
+ TEST(TestOpenInverse);
+ TEST(TestClone);
+ TEST(TestRegisterUnregister);
+ TEST(TestExtractBetween);
+ TEST(TestUnicodeIDs);
+}
+
+/*------------------------------------------------------------------
+ * Replaceable glue
+ *
+ * To test the Replaceable glue we have to dummy up a C-based
+ * Replaceable callback. This code is for testing purposes only.
+ *------------------------------------------------------------------*/
+
+typedef struct XReplaceable {
+ UChar* text; /* MUST BE null-terminated */
+} XReplaceable;
+
+static void InitXReplaceable(XReplaceable* rep, const char* cstring) {
+ rep->text = malloc(sizeof(UChar) * (strlen(cstring)+1));
+ u_uastrcpy(rep->text, cstring);
+}
+
+static void FreeXReplaceable(XReplaceable* rep) {
+ if (rep->text != NULL) {
+ free(rep->text);
+ rep->text = NULL;
+ }
+}
+
+/* UReplaceableCallbacks callback */
+static int32_t Xlength(const UReplaceable* rep) {
+ const XReplaceable* x = (const XReplaceable*)rep;
+ return u_strlen(x->text);
+}
+
+/* UReplaceableCallbacks callback */
+static UChar XcharAt(const UReplaceable* rep, int32_t offset) {
+ const XReplaceable* x = (const XReplaceable*)rep;
+ return x->text[offset];
+}
+
+/* UReplaceableCallbacks callback */
+static UChar32 Xchar32At(const UReplaceable* rep, int32_t offset) {
+ const XReplaceable* x = (const XReplaceable*)rep;
+ return x->text[offset];
+}
+
+/* UReplaceableCallbacks callback */
+static void Xreplace(UReplaceable* rep, int32_t start, int32_t limit,
+ const UChar* text, int32_t textLength) {
+ XReplaceable* x = (XReplaceable*)rep;
+ int32_t newLen = Xlength(rep) + limit - start + textLength;
+ UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1));
+ u_strncpy(newText, x->text, start);
+ u_strncpy(newText + start, text, textLength);
+ u_strcpy(newText + start + textLength, x->text + limit);
+ free(x->text);
+ x->text = newText;
+}
+
+/* UReplaceableCallbacks callback */
+static void Xcopy(UReplaceable* rep, int32_t start, int32_t limit, int32_t dest) {
+ XReplaceable* x = (XReplaceable*)rep;
+ int32_t newLen = Xlength(rep) + limit - start;
+ UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1));
+ u_strncpy(newText, x->text, dest);
+ u_strncpy(newText + dest, x->text + start, limit - start);
+ u_strcpy(newText + dest + limit - start, x->text + dest);
+ free(x->text);
+ x->text = newText;
+}
+
+/* UReplaceableCallbacks callback */
+static void Xextract(UReplaceable* rep, int32_t start, int32_t limit, UChar* dst) {
+ XReplaceable* x = (XReplaceable*)rep;
+ int32_t len = limit - start;
+ u_strncpy(dst, x->text, len);
+}
+
+static void InitXReplaceableCallbacks(UReplaceableCallbacks* callbacks) {
+ callbacks->length = Xlength;
+ callbacks->charAt = XcharAt;
+ callbacks->char32At = Xchar32At;
+ callbacks->replace = Xreplace;
+ callbacks->extract = Xextract;
+ callbacks->copy = Xcopy;
+}
+
+/*------------------------------------------------------------------
+ * Tests
+ *------------------------------------------------------------------*/
+
+static void TestAPI() {
+ enum { BUF_CAP = 128 };
+ char buf[BUF_CAP], buf2[BUF_CAP];
+ UErrorCode status = U_ZERO_ERROR;
+ UTransliterator* trans = NULL;
+ int32_t i, n;
+
+ /* Test getAvailableIDs */
+ n = utrans_countAvailableIDs();
+ if (n < 1) {
+ log_err("FAIL: utrans_countAvailableIDs() returned %d\n", n);
+ } else {
+ log_verbose("System ID count: %d\n", n);
+ }
+ for (i=0; i<n; ++i) {
+ utrans_getAvailableID(i, buf, BUF_CAP);
+ if (*buf == 0) {
+ log_err("FAIL: System transliterator %d: \"\"\n", i);
+ } else {
+ log_verbose("System transliterator %d: \"%s\"\n", i, buf);
+ }
+ }
+
+ /* Test open */
+ utrans_getAvailableID(0, buf, BUF_CAP);
+ trans = utrans_open(buf, UTRANS_FORWARD,NULL,0,NULL, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_open(%s) failed, error=%s\n",
+ buf, u_errorName(status));
+ }
+
+ else {
+ /* Test getID */
+ utrans_getID(trans, buf2, BUF_CAP);
+ if (0 != strcmp(buf, buf2)) {
+ log_err("FAIL: utrans_getID(%s) returned %s\n",
+ buf, buf2);
+ }
+ utrans_close(trans);
+ }
+}
+
+static void TestUnicodeIDs() {
+ UEnumeration *uenum;
+ UTransliterator *utrans;
+ const UChar *id, *id2;
+ int32_t idLength, id2Length, count, count2;
+
+ UErrorCode errorCode;
+
+ errorCode=U_ZERO_ERROR;
+ uenum=utrans_openIDs(&errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("utrans_openIDs() failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+
+ count=uenum_count(uenum, &errorCode);
+ if(U_FAILURE(errorCode) || count<1) {
+ log_err("uenum_count(transliterator IDs)=%d - %s\n", count, u_errorName(errorCode));
+ }
+
+ count=0;
+ for(;;) {
+ id=uenum_unext(uenum, &idLength, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("uenum_unext(transliterator ID %d) failed - %s\n", count, u_errorName(errorCode));
+ break;
+ }
+ if(id==NULL) {
+ break;
+ }
+
+ if(++count>10) {
+ /* try to actually open only a few transliterators */
+ continue;
+ }
+
+ utrans=utrans_openU(id, idLength, UTRANS_FORWARD, NULL, 0, NULL, &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("utrans_openU(%s) failed - %s\n", aescstrdup(id, idLength), u_errorName(errorCode));
+ continue;
+ }
+
+ id2=utrans_getUnicodeID(utrans, &id2Length);
+ if(idLength!=id2Length || 0!=u_memcmp(id, id2, idLength)) {
+ log_err("utrans_getUnicodeID(%s) does not match the original ID\n", aescstrdup(id, idLength));
+ }
+
+ utrans_close(utrans);
+ }
+
+ uenum_reset(uenum, &errorCode);
+ if(U_FAILURE(errorCode) || count<1) {
+ log_err("uenum_reset(transliterator IDs) failed - %s\n", u_errorName(errorCode));
+ } else {
+ count2=uenum_count(uenum, &errorCode);
+ if(U_FAILURE(errorCode) || count<1) {
+ log_err("2nd uenum_count(transliterator IDs)=%d - %s\n", count2, u_errorName(errorCode));
+ } else if(count!=count2) {
+ log_err("uenum_unext(transliterator IDs) returned %d IDs but uenum_count() after uenum_reset() claims there are %d\n", count, count2);
+ }
+ }
+
+ uenum_close(uenum);
+}
+
+static void TestOpenInverse(){
+ UErrorCode status=U_ZERO_ERROR;
+ UTransliterator* t1=NULL;
+ UTransliterator* inverse1=NULL;
+ enum { BUF_CAP = 128 };
+ char buf1[BUF_CAP];
+ int32_t i=0;
+
+ const char TransID[][25]={
+ "Halfwidth-Fullwidth",
+ "Fullwidth-Halfwidth",
+ "Greek-Latin" ,
+ "Latin-Greek",
+ /*"Arabic-Latin", // Removed in 2.0*/
+ /*"Latin-Arabic", // Removed in 2.0*/
+ "Katakana-Latin",
+ "Latin-Katakana",
+ /*"Hebrew-Latin", // Removed in 2.0*/
+ /*"Latin-Hebrew", // Removed in 2.0*/
+ "Cyrillic-Latin",
+ "Latin-Cyrillic",
+ "Devanagari-Latin",
+ "Latin-Devanagari",
+ "Any-Hex",
+ "Hex-Any"
+ };
+
+ for(i=0; i<sizeof(TransID)/sizeof(TransID[0]); i=i+2){
+ status = U_ZERO_ERROR;
+ t1=utrans_open(TransID[i], UTRANS_FORWARD,NULL,0,NULL, &status);
+ if(t1 == NULL || U_FAILURE(status)){
+ log_err("FAIL: in instantiation for id=%s\n", TransID[i]);
+ continue;
+ }
+ inverse1=utrans_openInverse(t1, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: utrans_openInverse() failed for id=%s. Error=%s\n", TransID[i], myErrorName(status));
+ continue;
+ }
+ utrans_getID(inverse1, buf1, BUF_CAP);
+ if(strcmp(buf1, TransID[i+1]) != 0){
+ log_err("FAIL :openInverse() for %s returned %s instead of %s\n", TransID[i], buf1, TransID[i+1]);
+ }
+ utrans_close(t1);
+ utrans_close(inverse1);
+ }
+}
+
+static void TestClone(){
+ UErrorCode status=U_ZERO_ERROR;
+ UTransliterator* t1=NULL;
+ UTransliterator* t2=NULL;
+ UTransliterator* t3=NULL;
+ UTransliterator* t4=NULL;
+ enum { BUF_CAP = 128 };
+ char buf1[BUF_CAP], buf2[BUF_CAP], buf3[BUF_CAP];
+
+ t1=utrans_open("Latin-Devanagari", UTRANS_FORWARD, NULL,0,NULL,&status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: construction\n");
+ return;
+ }
+ t2=utrans_open("Latin-Greek", UTRANS_FORWARD, NULL,0,NULL,&status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: construction\n");
+ utrans_close(t1);
+ return;
+ }
+
+ t3=utrans_clone(t1, &status);
+ t4=utrans_clone(t2, &status);
+
+ utrans_getID(t1, buf1, BUF_CAP);
+ utrans_getID(t2, buf2, BUF_CAP);
+ utrans_getID(t3, buf3, BUF_CAP);
+
+ if(strcmp(buf1, buf3) != 0 ||
+ strcmp(buf1, buf2) == 0) {
+ log_err("FAIL: utrans_clone() failed\n");
+ }
+
+ utrans_getID(t4, buf3, BUF_CAP);
+
+ if(strcmp(buf2, buf3) != 0 ||
+ strcmp(buf1, buf3) == 0) {
+ log_err("FAIL: utrans_clone() failed\n");
+ }
+
+ utrans_close(t1);
+ utrans_close(t2);
+ utrans_close(t3);
+ utrans_close(t4);
+
+}
+
+static void TestRegisterUnregister(){
+ UErrorCode status=U_ZERO_ERROR;
+ UTransliterator* t1=NULL;
+ UTransliterator* rules=NULL, *rules2;
+ UTransliterator* inverse1=NULL;
+ UChar rule[]={ 0x0061, 0x003c, 0x003e, 0x0063}; /*a<>b*/
+
+ U_STRING_DECL(ID, "TestA-TestB", 11);
+ U_STRING_INIT(ID, "TestA-TestB", 11);
+
+ /* Make sure it doesn't exist */
+ t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status);
+ if(t1 != NULL || U_SUCCESS(status)) {
+ log_err("FAIL: TestA-TestB already registered\n");
+ return;
+ }
+ status=U_ZERO_ERROR;
+ /* Check inverse too */
+ inverse1=utrans_open("TestA-TestB", UTRANS_REVERSE, NULL,0,NULL,&status);
+ if(inverse1 != NULL || U_SUCCESS(status)) {
+ log_err("FAIL: TestA-TestB already registered\n");
+ return;
+ }
+ status=U_ZERO_ERROR;
+ /* Create it */
+ rules=utrans_open("TestA-TestB",UTRANS_FORWARD, rule, 4, NULL, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: utrans_openRules(a<>B) failed with error=%s\n", myErrorName(status));
+ return;
+ }
+
+ /* clone it so we can register it a second time */
+ rules2=utrans_clone(rules, &status);
+ if(U_FAILURE(status)) {
+ log_err("FAIL: utrans_clone(a<>B) failed with error=%s\n", myErrorName(status));
+ return;
+ }
+
+ status=U_ZERO_ERROR;
+ /* Register it */
+ utrans_register(rules, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: utrans_register failed with error=%s\n", myErrorName(status));
+ return;
+ }
+ status=U_ZERO_ERROR;
+ /* Now check again -- should exist now*/
+ t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status);
+ if(U_FAILURE(status) || t1 == NULL){
+ log_err("FAIL: TestA-TestB not registered\n");
+ return;
+ }
+ utrans_close(t1);
+
+ /*unregister the instance*/
+ status=U_ZERO_ERROR;
+ utrans_unregister("TestA-TestB");
+ /* now Make sure it doesn't exist */
+ t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status);
+ if(U_SUCCESS(status) || t1 != NULL) {
+ log_err("FAIL: TestA-TestB isn't unregistered\n");
+ return;
+ }
+ utrans_close(t1);
+
+ /* now with utrans_unregisterID(const UChar *) */
+ status=U_ZERO_ERROR;
+ utrans_register(rules2, &status);
+ if(U_FAILURE(status)){
+ log_err("FAIL: 2nd utrans_register failed with error=%s\n", myErrorName(status));
+ return;
+ }
+ status=U_ZERO_ERROR;
+ /* Now check again -- should exist now*/
+ t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status);
+ if(U_FAILURE(status) || t1 == NULL){
+ log_err("FAIL: 2nd TestA-TestB not registered\n");
+ return;
+ }
+ utrans_close(t1);
+
+ /*unregister the instance*/
+ status=U_ZERO_ERROR;
+ utrans_unregisterID(ID, -1);
+ /* now Make sure it doesn't exist */
+ t1=utrans_openU(ID, -1, UTRANS_FORWARD,NULL,0,NULL, &status);
+ if(U_SUCCESS(status) || t1 != NULL) {
+ log_err("FAIL: 2nd TestA-TestB isn't unregistered\n");
+ return;
+ }
+
+ utrans_close(t1);
+ utrans_close(inverse1);
+}
+
+static void TestSimpleRules() {
+ /* Test rules */
+ /* Example: rules 1. ab>x|y
+ * 2. yc>z
+ *
+ * []|eabcd start - no match, copy e to tranlated buffer
+ * [e]|abcd match rule 1 - copy output & adjust cursor
+ * [ex|y]cd match rule 2 - copy output & adjust cursor
+ * [exz]|d no match, copy d to transliterated buffer
+ * [exzd]| done
+ */
+ _expectRules("ab>x|y;"
+ "yc>z",
+ "eabcd", "exzd");
+
+ /* Another set of rules:
+ * 1. ab>x|yzacw
+ * 2. za>q
+ * 3. qc>r
+ * 4. cw>n
+ *
+ * []|ab Rule 1
+ * [x|yzacw] No match
+ * [xy|zacw] Rule 2
+ * [xyq|cw] Rule 4
+ * [xyqn]| Done
+ */
+ _expectRules("ab>x|yzacw;"
+ "za>q;"
+ "qc>r;"
+ "cw>n",
+ "ab", "xyqn");
+
+ /* Test categories
+ */
+ _expectRules("$dummy=" "\\uE100" ";" /* careful here with E100 */
+ "$vowel=[aeiouAEIOU];"
+ "$lu=[:Lu:];"
+ "$vowel } $lu > '!';"
+ "$vowel > '&';"
+ "'!' { $lu > '^';"
+ "$lu > '*';"
+ "a > ERROR",
+ "abcdefgABCDEFGU", "&bcd&fg!^**!^*&");
+}
+
+static void TestFilter() {
+ UErrorCode status = U_ZERO_ERROR;
+ UChar filt[128];
+ UChar buf[128];
+ UChar exp[128];
+ char *cbuf;
+ int32_t limit;
+ const char* DATA[] = {
+ "[^c]", /* Filter out 'c' */
+ "abcde",
+ "\\u0061\\u0062c\\u0064\\u0065",
+
+ "", /* No filter */
+ "abcde",
+ "\\u0061\\u0062\\u0063\\u0064\\u0065"
+ };
+ int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]);
+ int32_t i;
+
+ UTransliterator* hex = utrans_open("Any-Hex", UTRANS_FORWARD, NULL,0,NULL,&status);
+
+ if (hex == 0 || U_FAILURE(status)) {
+ log_err("FAIL: utrans_open(Unicode-Hex) failed, error=%s\n",
+ u_errorName(status));
+ goto exit;
+ }
+
+ for (i=0; i<DATA_length; i+=3) {
+ /*u_uastrcpy(filt, DATA[i]);*/
+ u_charsToUChars(DATA[i], filt, (int32_t)strlen(DATA[i])+1);
+ utrans_setFilter(hex, filt, -1, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_setFilter() failed, error=%s\n",
+ u_errorName(status));
+ goto exit;
+ }
+
+ /*u_uastrcpy(buf, DATA[i+1]);*/
+ u_charsToUChars(DATA[i+1], buf, (int32_t)strlen(DATA[i+1])+1);
+ limit = 5;
+ utrans_transUChars(hex, buf, NULL, 128, 0, &limit, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_transUChars() failed, error=%s\n",
+ u_errorName(status));
+ goto exit;
+ }
+
+ cbuf=aescstrdup(buf, -1);
+ u_charsToUChars(DATA[i+2], exp, (int32_t)strlen(DATA[i+2])+1);
+ if (0 == u_strcmp(buf, exp)) {
+ log_verbose("Ok: %s | %s -> %s\n", DATA[i+1], DATA[i], cbuf);
+ } else {
+ log_err("FAIL: %s | %s -> %s, expected %s\n", DATA[i+1], DATA[i], cbuf, DATA[i+2]);
+ }
+ }
+
+ exit:
+ utrans_close(hex);
+}
+
+/**
+ * Test the UReplaceableCallback extractBetween support. We use a
+ * transliterator known to rely on this call.
+ */
+static void TestExtractBetween() {
+
+ UTransliterator *trans;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseErr;
+
+ trans = utrans_open("Lower", UTRANS_FORWARD, NULL, -1,
+ &parseErr, &status);
+
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_open(Lower) failed, error=%s\n",
+ u_errorName(status));
+ } else {
+ _expect(trans, "ABC", "abc");
+
+ utrans_close(trans);
+ }
+}
+
+static void _expectRules(const char* crules,
+ const char* cfrom,
+ const char* cto) {
+ /* u_uastrcpy has no capacity param for the buffer -- so just
+ * make all buffers way too big */
+ enum { CAP = 256 };
+ UChar rules[CAP];
+ UTransliterator *trans;
+ UErrorCode status = U_ZERO_ERROR;
+ UParseError parseErr;
+
+ u_uastrcpy(rules, crules);
+
+ trans = utrans_open(crules /*use rules as ID*/, UTRANS_FORWARD, rules, -1,
+ &parseErr, &status);
+ if (U_FAILURE(status)) {
+ utrans_close(trans);
+ log_err("FAIL: utrans_openRules(%s) failed, error=%s\n",
+ crules, u_errorName(status));
+ return;
+ }
+
+ _expect(trans, cfrom, cto);
+
+ utrans_close(trans);
+}
+
+static void _expect(const UTransliterator* trans,
+ const char* cfrom,
+ const char* cto) {
+ /* u_uastrcpy has no capacity param for the buffer -- so just
+ * make all buffers way too big */
+ enum { CAP = 256 };
+ UChar from[CAP];
+ UChar to[CAP];
+ UChar buf[CAP];
+ const UChar *ID;
+ int32_t IDLength;
+ const char *id;
+
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t limit;
+ UTransPosition pos;
+ XReplaceable xrep;
+ XReplaceable *xrepPtr = &xrep;
+ UReplaceableCallbacks xrepVtable;
+
+ u_uastrcpy(from, cfrom);
+ u_uastrcpy(to, cto);
+
+ ID = utrans_getUnicodeID(trans, &IDLength);
+ id = aescstrdup(ID, IDLength);
+
+ /* utrans_transUChars() */
+ u_strcpy(buf, from);
+ limit = u_strlen(buf);
+ utrans_transUChars(trans, buf, NULL, CAP, 0, &limit, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_transUChars() failed, error=%s\n",
+ u_errorName(status));
+ return;
+ }
+
+ if (0 == u_strcmp(buf, to)) {
+ log_verbose("Ok: utrans_transUChars(%s) x %s -> %s\n",
+ id, cfrom, cto);
+ } else {
+ char actual[CAP];
+ u_austrcpy(actual, buf);
+ log_err("FAIL: utrans_transUChars(%s) x %s -> %s, expected %s\n",
+ id, cfrom, actual, cto);
+ }
+
+ /* utrans_transIncrementalUChars() */
+ u_strcpy(buf, from);
+ pos.start = pos.contextStart = 0;
+ pos.limit = pos.contextLimit = u_strlen(buf);
+ utrans_transIncrementalUChars(trans, buf, NULL, CAP, &pos, &status);
+ utrans_transUChars(trans, buf, NULL, CAP, pos.start, &pos.limit, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_transIncrementalUChars() failed, error=%s\n",
+ u_errorName(status));
+ return;
+ }
+
+ if (0 == u_strcmp(buf, to)) {
+ log_verbose("Ok: utrans_transIncrementalUChars(%s) x %s -> %s\n",
+ id, cfrom, cto);
+ } else {
+ char actual[CAP];
+ u_austrcpy(actual, buf);
+ log_err("FAIL: utrans_transIncrementalUChars(%s) x %s -> %s, expected %s\n",
+ id, cfrom, actual, cto);
+ }
+
+ /* utrans_trans() */
+ InitXReplaceableCallbacks(&xrepVtable);
+ InitXReplaceable(&xrep, cfrom);
+ limit = u_strlen(from);
+ utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, 0, &limit, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_trans() failed, error=%s\n",
+ u_errorName(status));
+ FreeXReplaceable(&xrep);
+ return;
+ }
+
+ if (0 == u_strcmp(xrep.text, to)) {
+ log_verbose("Ok: utrans_trans(%s) x %s -> %s\n",
+ id, cfrom, cto);
+ } else {
+ char actual[CAP];
+ u_austrcpy(actual, xrep.text);
+ log_err("FAIL: utrans_trans(%s) x %s -> %s, expected %s\n",
+ id, cfrom, actual, cto);
+ }
+ FreeXReplaceable(&xrep);
+
+ /* utrans_transIncremental() */
+ InitXReplaceable(&xrep, cfrom);
+ pos.start = pos.contextStart = 0;
+ pos.limit = pos.contextLimit = u_strlen(from);
+ utrans_transIncremental(trans, (UReplaceable*)xrepPtr, &xrepVtable, &pos, &status);
+ utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, pos.start, &pos.limit, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: utrans_transIncremental() failed, error=%s\n",
+ u_errorName(status));
+ FreeXReplaceable(&xrep);
+ return;
+ }
+
+ if (0 == u_strcmp(xrep.text, to)) {
+ log_verbose("Ok: utrans_transIncremental(%s) x %s -> %s\n",
+ id, cfrom, cto);
+ } else {
+ char actual[CAP];
+ u_austrcpy(actual, xrep.text);
+ log_err("FAIL: utrans_transIncremental(%s) x %s -> %s, expected %s\n",
+ id, cfrom, actual, cto);
+ }
+ FreeXReplaceable(&xrep);
+}
+
+#endif /* #if !UCONFIG_NO_TRANSLITERATION */