1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
427f654740f2a26ad62a5c155af9199af9e69b889claireho*   Copyright (C) 2003-2010, International Business Machines
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   file name:  convtest.cpp
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   encoding:   US-ASCII
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   tab size:   8 (not used)
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   indentation:4
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   created on: 2003jul15
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   created by: Markus W. Scherer
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Test file for data-driven conversion tests.
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_LEGACY_CONVERSION
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Note: Turning off all of convtest.cpp if !UCONFIG_NO_LEGACY_CONVERSION
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is slightly unnecessary - it removes tests for Unicode charsets
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * like UTF-8 that should work.
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * However, there is no easy way for the test to detect whether a test case
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is for a Unicode charset, so it would be difficult to only exclude those.
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Also, regular testing of ICU is done with all modules on, therefore
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * not testing conversion for a custom configuration like this should be ok.
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucnv.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unistr.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/parsepos.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uniset.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "convtest.h"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/tstdtmod.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <string.h>
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdlib.h>
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // characters used in test data for callbacks
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SUB_CB='?',
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SKIP_CB='0',
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    STOP_CB='.',
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ESC_CB='&'
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::ConversionTest() {
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode=U_ZERO_ERROR;
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    utf8Cnv=ucnv_open("UTF-8", &errorCode);
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errln("unable to open UTF-8 converter");
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::~ConversionTest() {
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_close(utf8Cnv);
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (exec) logln("TestSuite ConversionTest: ");
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (index) {
7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if !UCONFIG_NO_FILE_IO
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 0: name="TestToUnicode"; if (exec) TestToUnicode(); break;
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 1: name="TestFromUnicode"; if (exec) TestFromUnicode(); break;
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 2: name="TestGetUnicodeSet"; if (exec) TestGetUnicodeSet(); break;
7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case 0:
7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case 1:
7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        case 2: name="skip"; break;
7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
79c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        case 3: name="TestGetUnicodeSet2"; if (exec) TestGetUnicodeSet2(); break;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default: name=""; break; //needed to end loop
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// test data interface ----------------------------------------------------- ***
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::TestToUnicode() {
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ConversionCase cc;
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char charset[100], cbopt[4];
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *option;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString s, unicode;
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t offsetsLength;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterToUCallback callback;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestDataModule *dataModule;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestData *testData;
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const DataMap *testCase;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dataModule=TestDataModule::getTestDataModule("conversion", *this, errorCode);
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        testData=dataModule->createTestData("toUnicode", errorCode);
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode)) {
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for(i=0; testData->nextCase(testCase, errorCode); ++i) {
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error retrieving conversion/toUnicode test case %d - %s",
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr=i;
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("charset", errorCode);
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s.extract(0, 0x7fffffff, charset, sizeof(charset), "");
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.charset=charset;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12027f654740f2a26ad62a5c155af9199af9e69b889claireho                // BEGIN android-added
121ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // To save space, Android does not build full ISO-2022 tables.
122ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // We skip the TestGetKeywordValuesForLocale for counting available collations.
123ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                if (strlen(charset) >= 8 &&
124ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    strncmp(charset+4, "2022", 4) == 0) {
125ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    continue;
126ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                }
12727f654740f2a26ad62a5c155af9199af9e69b889claireho                // END android-added
128ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.bytes=testCase->getBinary(cc.bytesLength, "bytes", errorCode);
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                unicode=testCase->getString("unicode", errorCode);
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.unicode=unicode.getBuffer();
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.unicodeLength=unicode.length();
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offsetsLength=0;
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.offsets=testCase->getIntVector(offsetsLength, "offsets", errorCode);
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(offsetsLength==0) {
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.offsets=NULL;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(offsetsLength!=unicode.length()) {
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("toUnicode[%d] unicode[%d] and offsets[%d] must have the same length",
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, unicode.length(), offsetsLength);
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ILLEGAL_ARGUMENT_ERROR;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.finalFlush= 0!=testCase->getInt28("flush", errorCode);
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.fallbacks= 0!=testCase->getInt28("fallbacks", errorCode);
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("errorCode", errorCode);
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(s==UNICODE_STRING("invalid", 7)) {
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_INVALID_CHAR_FOUND;
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("illegal", 7)) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_ILLEGAL_CHAR_FOUND;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("truncated", 9)) {
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_TRUNCATED_CHAR_FOUND;
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("illesc", 6)) {
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_ILLEGAL_ESCAPE_SEQUENCE;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("unsuppesc", 9)) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_UNSUPPORTED_ESCAPE_SEQUENCE;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_ZERO_ERROR;
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("callback", errorCode);
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s.extract(0, 0x7fffffff, cbopt, sizeof(cbopt), "");
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.cbopt=cbopt;
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                switch(cbopt[0]) {
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case SUB_CB:
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_TO_U_CALLBACK_SUBSTITUTE;
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case SKIP_CB:
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_TO_U_CALLBACK_SKIP;
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case STOP_CB:
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_TO_U_CALLBACK_STOP;
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case ESC_CB:
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_TO_U_CALLBACK_ESCAPE;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                default:
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=NULL;
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                option=callback==NULL ? cbopt : cbopt+1;
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*option==0) {
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    option=NULL;
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.invalidChars=testCase->getBinary(cc.invalidLength, "invalidChars", errorCode);
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error parsing conversion/toUnicode test case %d - %s",
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    logln("TestToUnicode[%d] %s", i, charset);
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ToUnicodeCase(cc, callback, option);
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete testData;
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete dataModule;
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
20385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        dataerrln("Could not load test conversion data");
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::TestFromUnicode() {
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ConversionCase cc;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char charset[100], cbopt[4];
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *option;
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString s, unicode, invalidUChars;
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t offsetsLength, index;
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverterFromUCallback callback;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestDataModule *dataModule;
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestData *testData;
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const DataMap *testCase;
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *p;
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, length;
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dataModule=TestDataModule::getTestDataModule("conversion", *this, errorCode);
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        testData=dataModule->createTestData("fromUnicode", errorCode);
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode)) {
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for(i=0; testData->nextCase(testCase, errorCode); ++i) {
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error retrieving conversion/fromUnicode test case %d - %s",
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr=i;
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("charset", errorCode);
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s.extract(0, 0x7fffffff, charset, sizeof(charset), "");
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.charset=charset;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24227f654740f2a26ad62a5c155af9199af9e69b889claireho                // BEGIN android-added
243ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // To save space, Android does not build full ISO-2022 tables.
244ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // We skip the TestGetKeywordValuesForLocale for counting available collations.
245ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                if (strlen(charset) >= 8 &&
246ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    strncmp(charset+4, "2022", 4) == 0) {
247ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    continue;
248ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                }
24927f654740f2a26ad62a5c155af9199af9e69b889claireho                // END android-added
250ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                unicode=testCase->getString("unicode", errorCode);
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.unicode=unicode.getBuffer();
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.unicodeLength=unicode.length();
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.bytes=testCase->getBinary(cc.bytesLength, "bytes", errorCode);
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                offsetsLength=0;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.offsets=testCase->getIntVector(offsetsLength, "offsets", errorCode);
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(offsetsLength==0) {
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.offsets=NULL;
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(offsetsLength!=cc.bytesLength) {
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("fromUnicode[%d] bytes[%d] and offsets[%d] must have the same length",
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, cc.bytesLength, offsetsLength);
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ILLEGAL_ARGUMENT_ERROR;
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.finalFlush= 0!=testCase->getInt28("flush", errorCode);
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.fallbacks= 0!=testCase->getInt28("fallbacks", errorCode);
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("errorCode", errorCode);
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(s==UNICODE_STRING("invalid", 7)) {
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_INVALID_CHAR_FOUND;
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("illegal", 7)) {
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_ILLEGAL_CHAR_FOUND;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(s==UNICODE_STRING("truncated", 9)) {
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_TRUNCATED_CHAR_FOUND;
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.outErrorCode=U_ZERO_ERROR;
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("callback", errorCode);
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.setSub=0; // default: no subchar
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if((index=s.indexOf((UChar)0))>0) {
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // read NUL-separated subchar first, if any
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // copy the subchar from Latin-1 characters
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // start after the NUL
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    p=s.getTerminatedBuffer();
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    length=index+1;
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    p+=length;
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    length=s.length()-length;
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(length<=0 || length>=(int32_t)sizeof(cc.subchar)) {
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t j;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        for(j=0; j<length; ++j) {
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            cc.subchar[j]=(char)p[j];
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // NUL-terminate the subchar
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.subchar[j]=0;
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.setSub=1;
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // remove the NUL and subchar from s
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    s.truncate(index);
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if((index=s.indexOf((UChar)0x3d))>0) /* '=' */ {
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // read a substitution string, separated by an equal sign
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    p=s.getBuffer()+index+1;
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    length=s.length()-(index+1);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(length<0 || length>=LENGTHOF(cc.subString)) {
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        u_memcpy(cc.subString, p, length);
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // NUL-terminate the subString
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.subString[length]=0;
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.setSub=-1;
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // remove the equal sign and subString from s
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    s.truncate(index);
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s.extract(0, 0x7fffffff, cbopt, sizeof(cbopt), "");
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.cbopt=cbopt;
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                switch(cbopt[0]) {
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case SUB_CB:
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_FROM_U_CALLBACK_SUBSTITUTE;
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case SKIP_CB:
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_FROM_U_CALLBACK_SKIP;
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case STOP_CB:
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_FROM_U_CALLBACK_STOP;
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                case ESC_CB:
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=UCNV_FROM_U_CALLBACK_ESCAPE;
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                default:
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    callback=NULL;
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                option=callback==NULL ? cbopt : cbopt+1;
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*option==0) {
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    option=NULL;
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                invalidUChars=testCase->getString("invalidUChars", errorCode);
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.invalidUChars=invalidUChars.getBuffer();
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.invalidLength=invalidUChars.length();
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error parsing conversion/fromUnicode test case %d - %s",
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    logln("TestFromUnicode[%d] %s", i, charset);
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    FromUnicodeCase(cc, callback, option);
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete testData;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete dataModule;
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
36585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        dataerrln("Could not load test conversion data");
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ellipsis[]={ 0x2e, 0x2e, 0x2e };
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::TestGetUnicodeSet() {
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char charset[100];
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString s, map, mapnot;
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t which;
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition pos;
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeSet cnvSet, mapSet, mapnotSet, diffSet;
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeSet *cnvSetPtr = &cnvSet;
38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocalUConverterPointer cnv;
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestDataModule *dataModule;
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TestData *testData;
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const DataMap *testCase;
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dataModule=TestDataModule::getTestDataModule("conversion", *this, errorCode);
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        testData=dataModule->createTestData("getUnicodeSet", errorCode);
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_SUCCESS(errorCode)) {
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for(i=0; testData->nextCase(testCase, errorCode); ++i) {
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error retrieving conversion/getUnicodeSet test case %d - %s",
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s=testCase->getString("charset", errorCode);
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                s.extract(0, 0x7fffffff, charset, sizeof(charset), "");
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
40427f654740f2a26ad62a5c155af9199af9e69b889claireho                // BEGIN android-added
405ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // To save space, Android does not build full ISO-2022 tables.
406ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                // We skip the TestGetKeywordValuesForLocale for counting available collations.
407ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                if (strlen(charset) >= 8 &&
408ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    strncmp(charset+4, "2022", 4) == 0) {
409ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                    continue;
410ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho                }
41127f654740f2a26ad62a5c155af9199af9e69b889claireho                // END android-added
412ea1f1813c8b13a850b13f256aeb5152bb0942e81claireho
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                map=testCase->getString("map", errorCode);
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mapnot=testCase->getString("mapnot", errorCode);
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                which=testCase->getInt28("which", errorCode);
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error parsing conversion/getUnicodeSet test case %d - %s",
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode));
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // test this test case
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mapSet.clear();
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mapnotSet.clear();
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pos.setIndex(0);
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mapSet.applyPattern(map, pos, 0, NULL, errorCode);
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode) || pos.getIndex()!=map.length()) {
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error creating the map set for conversion/getUnicodeSet test case %d - %s\n"
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          "    error index %d  index %d  U+%04x",
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode), pos.getErrorIndex(), pos.getIndex(), map.char32At(pos.getIndex()));
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                pos.setIndex(0);
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mapnotSet.applyPattern(mapnot, pos, 0, NULL, errorCode);
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode) || pos.getIndex()!=mapnot.length()) {
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error creating the mapnot set for conversion/getUnicodeSet test case %d - %s\n"
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          "    error index %d  index %d  U+%04x",
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i, u_errorName(errorCode), pos.getErrorIndex(), pos.getIndex(), mapnot.char32At(pos.getIndex()));
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                logln("TestGetUnicodeSet[%d] %s", i, charset);
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cnv.adoptInstead(cnv_open(charset, errorCode));
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
45385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    errcheckln(errorCode, "error opening \"%s\" for conversion/getUnicodeSet test case %d - %s",
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charset, i, u_errorName(errorCode));
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ucnv_getUnicodeSet(cnv.getAlias(), cnvSetPtr->toUSet(), (UConverterUnicodeSet)which, &errorCode);
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(U_FAILURE(errorCode)) {
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error in ucnv_getUnicodeSet(\"%s\") for conversion/getUnicodeSet test case %d - %s",
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charset, i, u_errorName(errorCode));
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode=U_ZERO_ERROR;
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    continue;
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // are there items that must be in cnvSet but are not?
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (diffSet=mapSet).removeAll(cnvSet);
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(!diffSet.isEmpty()) {
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    diffSet.toPattern(s, TRUE);
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(s.length()>100) {
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        s.replace(100, 0x7fffffff, ellipsis, LENGTHOF(ellipsis));
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error: ucnv_getUnicodeSet(\"%s\") is missing items - conversion/getUnicodeSet test case %d",
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charset, i);
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln(s);
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // are there items that must not be in cnvSet but are?
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (diffSet=mapnotSet).retainAll(cnvSet);
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(!diffSet.isEmpty()) {
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    diffSet.toPattern(s, TRUE);
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(s.length()>100) {
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        s.replace(100, 0x7fffffff, ellipsis, LENGTHOF(ellipsis));
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln("error: ucnv_getUnicodeSet(\"%s\") contains unexpected items - conversion/getUnicodeSet test case %d",
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charset, i);
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errln(s);
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete testData;
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete dataModule;
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    else {
49785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        dataerrln("Could not load test conversion data");
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CDECL_BEGIN
50285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void U_CALLCONV
503c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste QuerugetUnicodeSetCallback(const void *context,
50485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UConverterFromUnicodeArgs * /*fromUArgs*/,
50585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      const UChar* /*codeUnits*/,
50685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      int32_t /*length*/,
507c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                      UChar32 codePoint,
508c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                      UConverterCallbackReason reason,
509c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                      UErrorCode *pErrorCode) {
510c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    if(reason<=UCNV_IRREGULAR) {
511c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        ((UnicodeSet *)context)->remove(codePoint);  // the converter cannot convert this code point
512c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        *pErrorCode=U_ZERO_ERROR;                    // skip
513c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }  // else ignore the reset, close and clone calls.
514c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru}
51585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CDECL_END
516c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
517c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru// Compare ucnv_getUnicodeSet() with the set of characters that can be converted.
518c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queruvoid
519c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste QueruConversionTest::TestGetUnicodeSet2() {
520c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // Build a string with all code points.
521c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UChar32 cpLimit;
522c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    int32_t s0Length;
523c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    if(quick) {
524c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        cpLimit=s0Length=0x10000;  // BMP only
525c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    } else {
526c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        cpLimit=0x110000;
527c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        s0Length=0x10000+0x200000;  // BMP + surrogate pairs
528c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
529c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UChar *s0=new UChar[s0Length];
530c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    if(s0==NULL) {
531c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        return;
532c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
533c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UChar *s=s0;
534c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UChar32 c;
535c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    UChar c2;
536c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // low BMP
537c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    for(c=0; c<=0xd7ff; ++c) {
538c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        *s++=(UChar)c;
539c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
540c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // trail surrogates
541c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    for(c=0xdc00; c<=0xdfff; ++c) {
542c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        *s++=(UChar)c;
543c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
544c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // lead surrogates
545c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // (after trails so that there is not even one surrogate pair in between)
546c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    for(c=0xd800; c<=0xdbff; ++c) {
547c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        *s++=(UChar)c;
548c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
549c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // high BMP
550c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    for(c=0xe000; c<=0xffff; ++c) {
551c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        *s++=(UChar)c;
552c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
553c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    // supplementary code points = surrogate pairs
554c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    if(cpLimit==0x110000) {
555c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        for(c=0xd800; c<=0xdbff; ++c) {
556c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            for(c2=0xdc00; c2<=0xdfff; ++c2) {
557c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                *s++=(UChar)c;
558c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                *s++=c2;
559c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
560c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
561c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
562c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
563c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    static const char *const cnvNames[]={
564c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "UTF-8",
565c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "UTF-7",
566c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "UTF-16",
567c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "US-ASCII",
568c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ISO-8859-1",
569c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "windows-1252",
570c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "Shift-JIS",
571c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ibm-1390",  // EBCDIC_STATEFUL table
572c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ibm-16684",  // DBCS-only extension table based on EBCDIC_STATEFUL table
573c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "HZ",
574c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ISO-2022-JP",
575c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "JIS7",
576c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ISO-2022-CN",
577c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "ISO-2022-CN-EXT",
578c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        "LMBCS"
579c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    };
58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocalUConverterPointer cnv;
581c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    char buffer[1024];
582c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    int32_t i;
583c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    for(i=0; i<LENGTHOF(cnvNames); ++i) {
584c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        UErrorCode errorCode=U_ZERO_ERROR;
58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        cnv.adoptInstead(cnv_open(cnvNames[i], errorCode));
586c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(U_FAILURE(errorCode)) {
58785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errcheckln(errorCode, "failed to open converter %s - %s", cnvNames[i], u_errorName(errorCode));
588c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            continue;
589c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
590c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        UnicodeSet expected;
59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ucnv_setFromUCallBack(cnv.getAlias(), getUnicodeSetCallback, &expected, NULL, NULL, &errorCode);
592c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        if(U_FAILURE(errorCode)) {
593c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            errln("failed to set the callback on converter %s - %s", cnvNames[i], u_errorName(errorCode));
594c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            continue;
595c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
596c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        UConverterUnicodeSet which;
597c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        for(which=UCNV_ROUNDTRIP_SET; which<UCNV_SET_COUNT; which=(UConverterUnicodeSet)((int)which+1)) {
598c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(which==UCNV_ROUNDTRIP_AND_FALLBACK_SET) {
59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ucnv_setFallback(cnv.getAlias(), TRUE);
600c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
601c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            expected.add(0, cpLimit-1);
602c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            s=s0;
603c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            UBool flush;
604c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            do {
605c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                char *t=buffer;
606c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                flush=(UBool)(s==s0+s0Length);
60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ucnv_fromUnicode(cnv.getAlias(), &t, buffer+sizeof(buffer), (const UChar **)&s, s0+s0Length, NULL, flush, &errorCode);
608c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                if(U_FAILURE(errorCode)) {
609c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
610c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                        errorCode=U_ZERO_ERROR;
611c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                        continue;
612c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    } else {
613c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                        break;  // unexpected error, should not occur
614c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    }
615c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                }
616c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            } while(!flush);
617c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            UnicodeSet set;
61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ucnv_getUnicodeSet(cnv.getAlias(), set.toUSet(), which, &errorCode);
619c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(cpLimit<0x110000) {
620c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                set.remove(cpLimit, 0x10ffff);
621c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
622c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(which==UCNV_ROUNDTRIP_SET) {
623c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // ignore PUA code points because they will be converted even if they
624c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // are fallbacks and when other fallbacks are turned off,
625c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // but ucnv_getUnicodeSet(UCNV_ROUNDTRIP_SET) delivers true roundtrips
626c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                expected.remove(0xe000, 0xf8ff);
627c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                expected.remove(0xf0000, 0xffffd);
628c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                expected.remove(0x100000, 0x10fffd);
629c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                set.remove(0xe000, 0xf8ff);
630c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                set.remove(0xf0000, 0xffffd);
631c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                set.remove(0x100000, 0x10fffd);
632c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
633c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(set!=expected) {
634c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // First try to see if we have different sets because ucnv_getUnicodeSet()
635c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // added strings: The above conversion method does not tell us what strings might be convertible.
636c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // Remove strings from the set and compare again.
637c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // Unfortunately, there are no good, direct set methods for finding out whether there are strings
638c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // in the set, nor for enumerating or removing just them.
639c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // Intersect all code points with the set. The intersection will not contain strings.
640c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                UnicodeSet temp(0, 0x10ffff);
641c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                temp.retainAll(set);
642c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                set=temp;
643c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
644c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            if(set!=expected) {
645c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                UnicodeSet diffSet;
646c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                UnicodeString out;
647c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
648c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // are there items that must be in the set but are not?
649c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                (diffSet=expected).removeAll(set);
650c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                if(!diffSet.isEmpty()) {
651c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    diffSet.toPattern(out, TRUE);
652c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    if(out.length()>100) {
653c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                        out.replace(100, 0x7fffffff, ellipsis, LENGTHOF(ellipsis));
654c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    }
655c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    errln("error: ucnv_getUnicodeSet(\"%s\") is missing items - which set: %d",
656c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                            cnvNames[i], which);
657c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    errln(out);
658c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                }
659c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
660c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                // are there items that must not be in the set but are?
661c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                (diffSet=set).removeAll(expected);
662c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                if(!diffSet.isEmpty()) {
663c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    diffSet.toPattern(out, TRUE);
664c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    if(out.length()>100) {
665c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                        out.replace(100, 0x7fffffff, ellipsis, LENGTHOF(ellipsis));
666c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    }
667c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    errln("error: ucnv_getUnicodeSet(\"%s\") contains unexpected items - which set: %d",
668c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                            cnvNames[i], which);
669c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                    errln(out);
670c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru                }
671c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru            }
672c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru        }
673c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    }
674c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
675c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru    delete [] s0;
676c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru}
677c0f3e2506e4cc62ff8c220fe72849728e9d6cecfJean-Baptiste Queru
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// open testdata or ICU data converter ------------------------------------- ***
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUConverter *
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::cnv_open(const char *name, UErrorCode &errorCode) {
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(name!=NULL && *name=='*') {
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* loadTestData(): set the data directory */
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return ucnv_openPackage(loadTestData(errorCode), name+1, &errorCode);
68527f654740f2a26ad62a5c155af9199af9e69b889claireho    } else if(name!=NULL && *name=='+') {
68627f654740f2a26ad62a5c155af9199af9e69b889claireho        return ucnv_open((name+1), &errorCode);
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return ucnv_open(name, &errorCode);
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// output helpers ---------------------------------------------------------- ***
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic inline char
695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruhexDigit(uint8_t digit) {
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return digit<=9 ? (char)('0'+digit) : (char)('a'-10+digit);
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char *
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruprintBytes(const uint8_t *bytes, int32_t length, char *out) {
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint8_t b;
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(length>0) {
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        b=*bytes++;
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        --length;
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)(b>>4));
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)(b&0xf));
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while(length>0) {
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        b=*bytes++;
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        --length;
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=' ';
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)(b>>4));
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)(b&0xf));
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *out++=0;
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return out;
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char *
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruprintUnicode(const UChar *unicode, int32_t length, char *out) {
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar32 c;
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=0; i<length;) {
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(i>0) {
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=' ';
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        U16_NEXT(unicode, i, length, c);
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // write 4..6 digits
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(c>=0x100000) {
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='1';
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(c>=0x10000) {
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=hexDigit((uint8_t)((c>>16)&0xf));
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)((c>>12)&0xf));
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)((c>>8)&0xf));
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)((c>>4)&0xf));
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *out++=hexDigit((uint8_t)(c&0xf));
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *out++=0;
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return out;
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char *
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruprintOffsets(const int32_t *offsets, int32_t length, char *out) {
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, o, d;
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(offsets==NULL) {
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length=0;
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=0; i<length; ++i) {
756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(i>0) {
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=' ';
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        o=offsets[i];
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // print all offsets with 2 characters each (-x, -9..99, xx)
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(o<-9) {
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='-';
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='x';
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(o<0) {
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='-';
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=(char)('0'-o);
768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(o<=99) {
769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=(d=o/10)==0 ? ' ' : (char)('0'+d);
770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++=(char)('0'+o%10);
771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else /* o>99 */ {
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='x';
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *out++='x';
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *out++=0;
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return out;
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// toUnicode test worker functions ----------------------------------------- ***
781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerustepToUnicode(ConversionCase &cc, UConverter *cnv,
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UChar *result, int32_t resultCapacity,
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t *resultOffsets, /* also resultCapacity */
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              int32_t step,
787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UErrorCode *pErrorCode) {
788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *source, *sourceLimit, *bytesLimit;
789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *target, *targetLimit, *resultLimit;
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool flush;
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    source=(const char *)cc.bytes;
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    target=result;
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bytesLimit=source+cc.bytesLength;
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLimit=result+resultCapacity;
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(step>=0) {
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // call ucnv_toUnicode() with in/out buffers no larger than (step) at a time
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // move only one buffer (in vs. out) at a time to be extra mean
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // step==0 performs bulk conversion and generates offsets
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // initialize the partial limits for the loop
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(step==0) {
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // use the entire buffers
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceLimit=bytesLimit;
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetLimit=resultLimit;
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flush=cc.finalFlush;
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // start with empty partial buffers
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceLimit=source;
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetLimit=target;
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flush=FALSE;
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // output offsets only for bulk conversion
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            resultOffsets=NULL;
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;;) {
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // resetting the opposite conversion direction must not affect this one
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_resetFromUnicode(cnv);
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // convert
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_toUnicode(cnv,
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                &target, targetLimit,
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                &source, sourceLimit,
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                resultOffsets,
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                flush, pErrorCode);
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // check pointers and errors
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(source>sourceLimit || target>targetLimit) {
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(target!=targetLimit) {
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // buffer overflow must only be set when the target is filled
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(targetLimit==resultLimit) {
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // not just a partial overflow
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // the partial target is filled, set a new limit, reset the error and continue
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                targetLimit=(resultLimit-target)>=step ? target+step : resultLimit;
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_ZERO_ERROR;
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(U_FAILURE(*pErrorCode)) {
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // some other error occurred, done
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(source!=sourceLimit) {
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // when no error occurs, then the input must be consumed
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(sourceLimit==bytesLimit) {
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // we are done
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // the partial conversion succeeded, set a new limit and continue
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                sourceLimit=(bytesLimit-source)>=step ? source+step : bytesLimit;
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                flush=(UBool)(cc.finalFlush && sourceLimit==bytesLimit);
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else /* step<0 */ {
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /*
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * step==-1: call only ucnv_getNextUChar()
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         * otherwise alternate between ucnv_toUnicode() and ucnv_getNextUChar()
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *   if step==-2 or -3, then give ucnv_toUnicode() the whole remaining input,
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *   else give it at most (-step-2)/2 bytes
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         */
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar32 c;
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // end the loop by getting an index out of bounds error
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(;;) {
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // resetting the opposite conversion direction must not affect this one
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_resetFromUnicode(cnv);
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // convert
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if((step&1)!=0 /* odd: -1, -3, -5, ... */) {
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                sourceLimit=source; // use sourceLimit not as a real limit
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                    // but to remember the pre-getNextUChar source pointer
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                c=ucnv_getNextUChar(cnv, &source, bytesLimit, pErrorCode);
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // check pointers and errors
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*pErrorCode==U_INDEX_OUTOFBOUNDS_ERROR) {
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(source!=bytesLimit) {
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else {
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        *pErrorCode=U_ZERO_ERROR;
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(U_FAILURE(*pErrorCode)) {
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // source may not move if c is from previous overflow
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(target==resultLimit) {
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(c<=0xffff) {
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *target++=(UChar)c;
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *target++=U16_LEAD(c);
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(target==resultLimit) {
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *target++=U16_TRAIL(c);
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // alternate between -n-1 and -n but leave -1 alone
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(step<-1) {
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ++step;
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else /* step is even */ {
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // allow only one UChar output
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                targetLimit=target<resultLimit ? target+1 : resultLimit;
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // as with ucnv_getNextUChar(), we always flush (if we go to bytesLimit)
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // and never output offsets
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(step==-2) {
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceLimit=bytesLimit;
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    sourceLimit=source+(-step-2)/2;
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(sourceLimit>bytesLimit) {
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        sourceLimit=bytesLimit;
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_toUnicode(cnv,
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    &target, targetLimit,
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    &source, sourceLimit,
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    NULL, (UBool)(sourceLimit==bytesLimit), pErrorCode);
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // check pointers and errors
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(target!=targetLimit) {
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // buffer overflow must only be set when the target is filled
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    } else if(targetLimit==resultLimit) {
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // not just a partial overflow
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // the partial target is filled, set a new limit and continue
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_ZERO_ERROR;
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if(U_FAILURE(*pErrorCode)) {
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // some other error occurred, done
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if(source!=sourceLimit) {
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        // when no error occurs, then the input must be consumed
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        break;
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // we are done (flush==TRUE) but we continue, to get the index out of bounds error above
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                --step;
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t)(target-result);
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::ToUnicodeCase(ConversionCase &cc, UConverterToUCallback callback, const char *option) {
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // open the converter
97550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    IcuTestErrorCode errorCode(*this, "ToUnicodeCase");
97650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocalUConverterPointer cnv(cnv_open(cc.charset, errorCode));
97750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(errorCode.isFailure()) {
97885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        errcheckln(errorCode, "toUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_open() failed - %s",
97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, errorCode.errorName());
98050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        errorCode.reset();
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set the callback
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(callback!=NULL) {
98650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ucnv_setToUCallBack(cnv.getAlias(), callback, option, NULL, NULL, errorCode);
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(errorCode)) {
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("toUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_setToUCallBack() failed - %s",
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, u_errorName(errorCode));
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resultOffsets[256];
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar result[256];
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resultLength;
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool ok;
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const struct {
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t step;
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *name;
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } steps[]={
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 0, "bulk" }, // must be first for offsets to be checked
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 1, "step=1" },
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 3, "step=3" },
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 7, "step=7" },
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -1, "getNext" },
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -2, "toU(bulk)+getNext" },
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -3, "getNext+toU(bulk)" },
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -4, "toU(1)+getNext" },
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -5, "getNext+toU(1)" },
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -12, "toU(5)+getNext" },
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { -13, "getNext+toU(5)" },
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    };
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, step;
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ok=TRUE;
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=0; i<LENGTHOF(steps) && ok; ++i) {
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        step=steps[i].step;
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(step<0 && !cc.finalFlush) {
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // skip ucnv_getNextUChar() if !finalFlush because
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // ucnv_getNextUChar() always implies flush
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(step!=0) {
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // bulk test is first, then offsets are not checked any more
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            cc.offsets=NULL;
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            memset(resultOffsets, -1, LENGTHOF(resultOffsets));
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(result, -1, LENGTHOF(result));
103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        errorCode.reset();
103450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resultLength=stepToUnicode(cc, cnv.getAlias(),
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                result, LENGTHOF(result),
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                step==0 ? resultOffsets : NULL,
103750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                step, errorCode);
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkToUnicode(
103950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cc, cnv.getAlias(), steps[i].name,
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                result, resultLength,
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.offsets!=NULL ? resultOffsets : NULL,
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
104350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(errorCode.isFailure() || !cc.finalFlush) {
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // reset if an error occurred or we did not flush
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // otherwise do nothing to make sure that flushing resets
104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ucnv_resetToUnicode(cnv.getAlias());
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
104850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (cc.offsets != NULL && resultOffsets[resultLength] != -1) {
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("toUnicode[%d](%s) Conversion wrote too much to offsets at index %d",
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, resultLength);
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result[resultLength] != (UChar)-1) {
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("toUnicode[%d](%s) Conversion wrote too much to result at index %d",
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, resultLength);
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // not a real loop, just a convenience for breaking out of the block
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while(ok && cc.finalFlush) {
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // test ucnv_toUChars()
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(result, 0, sizeof(result));
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        errorCode.reset();
106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resultLength=ucnv_toUChars(cnv.getAlias(),
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        result, LENGTHOF(result),
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        (const char *)cc.bytes, cc.bytesLength,
106750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        errorCode);
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkToUnicode(
106950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cc, cnv.getAlias(), "toUChars",
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                result, resultLength,
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(!ok) {
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // test preflighting
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // keep the correct result for simple checking
107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        errorCode.reset();
108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resultLength=ucnv_toUChars(cnv.getAlias(),
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        NULL, 0,
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        (const char *)cc.bytes, cc.bytesLength,
108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        errorCode);
108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(errorCode.get()==U_STRING_NOT_TERMINATED_WARNING || errorCode.get()==U_BUFFER_OVERFLOW_ERROR) {
108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            errorCode.reset();
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkToUnicode(
108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                cc, cnv.getAlias(), "preflight toUChars",
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                result, resultLength,
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    errorCode.reset();  // all errors have already been reported
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ok;
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::checkToUnicode(ConversionCase &cc, UConverter *cnv, const char *name,
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               const UChar *result, int32_t resultLength,
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               const int32_t *resultOffsets,
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                               UErrorCode resultErrorCode) {
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char resultInvalidChars[8];
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int8_t resultInvalidLength;
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *msg;
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // reset the message; NULL will mean "ok"
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg=NULL;
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultInvalidLength=sizeof(resultInvalidChars);
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_getInvalidChars(cnv, resultInvalidChars, &resultInvalidLength, &errorCode);
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errln("toUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) ucnv_getInvalidChars() failed - %s",
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, u_errorName(errorCode));
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // check everything that might have gone wrong
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cc.unicodeLength!=resultLength) {
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong result length";
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(0!=u_memcmp(cc.unicode, result, cc.unicodeLength)) {
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong result string";
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.offsets!=NULL && 0!=memcmp(cc.offsets, resultOffsets, cc.unicodeLength*sizeof(*cc.offsets))) {
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong offsets";
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.outErrorCode!=resultErrorCode) {
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong error code";
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.invalidLength!=resultInvalidLength) {
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong length of last invalid input";
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(0!=memcmp(cc.invalidChars, resultInvalidChars, cc.invalidLength)) {
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong last invalid input";
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(msg==NULL) {
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char buffer[2000]; // one buffer for all strings
1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char *s, *bytesString, *unicodeString, *resultString,
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *offsetsString, *resultOffsetsString,
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *invalidCharsString, *resultInvalidCharsString;
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bytesString=s=buffer;
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printBytes(cc.bytes, cc.bytesLength, bytesString);
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printUnicode(cc.unicode, cc.unicodeLength, unicodeString=s);
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printUnicode(result, resultLength, resultString=s);
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printOffsets(cc.offsets, cc.unicodeLength, offsetsString=s);
1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printOffsets(resultOffsets, resultLength, resultOffsetsString=s);
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printBytes(cc.invalidChars, cc.invalidLength, invalidCharsString=s);
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printBytes((uint8_t *)resultInvalidChars, resultInvalidLength, resultInvalidCharsString=s);
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((s-buffer)>(int32_t)sizeof(buffer)) {
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("toUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) fatal error: checkToUnicode() test output buffer overflow writing %d chars\n",
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, (int)(s-buffer));
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            exit(1);
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errln("toUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) failed: %s\n"
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  bytes <%s>[%d]\n"
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " expected <%s>[%d]\n"
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  result  <%s>[%d]\n"
1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " offsets         <%s>\n"
1165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  result offsets <%s>\n"
1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " error code expected %s got %s\n"
1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  invalidChars expected <%s> got <%s>\n",
1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, msg,
1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              bytesString, cc.bytesLength,
1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              unicodeString, cc.unicodeLength,
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              resultString, resultLength,
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              offsetsString,
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              resultOffsetsString,
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              u_errorName(cc.outErrorCode), u_errorName(resultErrorCode),
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              invalidCharsString, resultInvalidCharsString);
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// fromUnicode test worker functions --------------------------------------- ***
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerustepFromUTF8(ConversionCase &cc,
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             UConverter *utf8Cnv, UConverter *cnv,
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             char *result, int32_t resultCapacity,
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             int32_t step,
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             UErrorCode *pErrorCode) {
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *source, *sourceLimit, *utf8Limit;
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar pivotBuffer[32];
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *pivotSource, *pivotTarget, *pivotLimit;
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *target, *targetLimit, *resultLimit;
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool flush;
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    source=cc.utf8;
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pivotSource=pivotTarget=pivotBuffer;
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    target=result;
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    utf8Limit=source+cc.utf8Length;
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLimit=result+resultCapacity;
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // call ucnv_convertEx() with in/out buffers no larger than (step) at a time
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // move only one buffer (in vs. out) at a time to be extra mean
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // step==0 performs bulk conversion
1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // initialize the partial limits for the loop
1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(step==0) {
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // use the entire buffers
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=utf8Limit;
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=resultLimit;
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        flush=cc.finalFlush;
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotLimit=pivotBuffer+LENGTHOF(pivotBuffer);
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // start with empty partial buffers
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=source;
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=target;
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        flush=FALSE;
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // empty pivot is not allowed, make it of length step
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        pivotLimit=pivotBuffer+step;
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(;;) {
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // resetting the opposite conversion direction must not affect this one
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_resetFromUnicode(utf8Cnv);
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_resetToUnicode(cnv);
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // convert
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_convertEx(cnv, utf8Cnv,
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &target, targetLimit,
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &source, sourceLimit,
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            pivotBuffer, &pivotSource, &pivotTarget, pivotLimit,
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            FALSE, flush, pErrorCode);
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // check pointers and errors
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(source>sourceLimit || target>targetLimit) {
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(target!=targetLimit) {
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // buffer overflow must only be set when the target is filled
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(targetLimit==resultLimit) {
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // not just a partial overflow
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the partial target is filled, set a new limit, reset the error and continue
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetLimit=(resultLimit-target)>=step ? target+step : resultLimit;
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_ZERO_ERROR;
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(U_FAILURE(*pErrorCode)) {
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(pivotSource==pivotBuffer) {
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // toUnicode error, should not occur
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // toUnicode errors are tested in cintltst TestConvertExFromUTF8()
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // fromUnicode error
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // some other error occurred, done
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(source!=sourceLimit) {
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // when no error occurs, then the input must be consumed
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(sourceLimit==utf8Limit) {
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // we are done
1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if(*pErrorCode==U_STRING_NOT_TERMINATED_WARNING) {
1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // ucnv_convertEx() warns about not terminating the output
1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // but ucnv_fromUnicode() does not and so
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // checkFromUnicode() does not expect it
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    *pErrorCode=U_ZERO_ERROR;
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the partial conversion succeeded, set a new limit and continue
1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceLimit=(utf8Limit-source)>=step ? source+step : utf8Limit;
1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flush=(UBool)(cc.finalFlush && sourceLimit==utf8Limit);
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t)(target-result);
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerustepFromUnicode(ConversionCase &cc, UConverter *cnv,
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                char *result, int32_t resultCapacity,
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t *resultOffsets, /* also resultCapacity */
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t step,
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UErrorCode *pErrorCode) {
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar *source, *sourceLimit, *unicodeLimit;
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *target, *targetLimit, *resultLimit;
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool flush;
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    source=cc.unicode;
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    target=result;
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    unicodeLimit=source+cc.unicodeLength;
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultLimit=result+resultCapacity;
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // call ucnv_fromUnicode() with in/out buffers no larger than (step) at a time
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // move only one buffer (in vs. out) at a time to be extra mean
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // step==0 performs bulk conversion and generates offsets
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // initialize the partial limits for the loop
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(step==0) {
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // use the entire buffers
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=unicodeLimit;
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=resultLimit;
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        flush=cc.finalFlush;
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // start with empty partial buffers
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        sourceLimit=source;
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        targetLimit=target;
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        flush=FALSE;
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // output offsets only for bulk conversion
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultOffsets=NULL;
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(;;) {
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // resetting the opposite conversion direction must not affect this one
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_resetToUnicode(cnv);
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // convert
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_fromUnicode(cnv,
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &target, targetLimit,
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            &source, sourceLimit,
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            resultOffsets,
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flush, pErrorCode);
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // check pointers and errors
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(source>sourceLimit || target>targetLimit) {
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(target!=targetLimit) {
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // buffer overflow must only be set when the target is filled
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if(targetLimit==resultLimit) {
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // not just a partial overflow
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the partial target is filled, set a new limit, reset the error and continue
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            targetLimit=(resultLimit-target)>=step ? target+step : resultLimit;
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *pErrorCode=U_ZERO_ERROR;
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if(U_FAILURE(*pErrorCode)) {
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // some other error occurred, done
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(source!=sourceLimit) {
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // when no error occurs, then the input must be consumed
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(sourceLimit==unicodeLimit) {
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // we are done
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the partial conversion succeeded, set a new limit and continue
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceLimit=(unicodeLimit-source)>=step ? source+step : unicodeLimit;
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            flush=(UBool)(cc.finalFlush && sourceLimit==unicodeLimit);
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (int32_t)(target-result);
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::FromUnicodeCase(ConversionCase &cc, UConverterFromUCallback callback, const char *option) {
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UConverter *cnv;
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // open the converter
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnv=cnv_open(cc.charset, errorCode);
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
138585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        errcheckln(errorCode, "fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_open() failed - %s",
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, u_errorName(errorCode));
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_resetToUnicode(utf8Cnv);
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set the callback
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(callback!=NULL) {
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_setFromUCallBack(cnv, callback, option, NULL, NULL, &errorCode);
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(errorCode)) {
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_setFromUCallBack() failed - %s",
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, u_errorName(errorCode));
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_close(cnv);
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set the fallbacks flag
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO change with Jitterbug 2401, then add a similar call for toUnicode too
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_setFallback(cnv, cc.fallbacks);
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set the subchar
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length;
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cc.setSub>0) {
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        length=(int32_t)strlen(cc.subchar);
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_setSubstChars(cnv, cc.subchar, (int8_t)length, &errorCode);
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(errorCode)) {
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_setSubstChars() failed - %s",
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, u_errorName(errorCode));
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_close(cnv);
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.setSub<0) {
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ucnv_setSubstString(cnv, cc.subString, -1, &errorCode);
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(errorCode)) {
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d) ucnv_setSubstString() failed - %s",
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, u_errorName(errorCode));
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_close(cnv);
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // convert unicode to utf8
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char utf8[256];
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cc.utf8=utf8;
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_strToUTF8(utf8, LENGTHOF(utf8), &cc.utf8Length,
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.unicode, cc.unicodeLength,
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                &errorCode);
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // skip UTF-8 testing of a string with an unpaired surrogate,
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // or of one that's too long
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // toUnicode errors are tested in cintltst TestConvertExFromUTF8()
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cc.utf8Length=-1;
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resultOffsets[256];
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char result[256];
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resultLength;
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool ok;
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const struct {
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t step;
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *name, *utf8Name;
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } steps[]={
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 0, "bulk",   "utf8" }, // must be first for offsets to be checked
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 1, "step=1", "utf8 step=1" },
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 3, "step=3", "utf8 step=3" },
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        { 7, "step=7", "utf8 step=7" }
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    };
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i, step;
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ok=TRUE;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for(i=0; i<LENGTHOF(steps) && ok; ++i) {
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        step=steps[i].step;
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(resultOffsets, -1, LENGTHOF(resultOffsets));
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(result, -1, LENGTHOF(result));
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorCode=U_ZERO_ERROR;
1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLength=stepFromUnicode(cc, cnv,
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                result, LENGTHOF(result),
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                step==0 ? resultOffsets : NULL,
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                step, &errorCode);
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkFromUnicode(
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc, cnv, steps[i].name,
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (uint8_t *)result, resultLength,
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.offsets!=NULL ? resultOffsets : NULL,
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(U_FAILURE(errorCode) || !cc.finalFlush) {
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // reset if an error occurred or we did not flush
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // otherwise do nothing to make sure that flushing resets
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ucnv_resetFromUnicode(cnv);
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (resultOffsets[resultLength] != -1) {
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s) Conversion wrote too much to offsets at index %d",
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, resultLength);
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result[resultLength] != (char)-1) {
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s) Conversion wrote too much to result at index %d",
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, resultLength);
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // bulk test is first, then offsets are not checked any more
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cc.offsets=NULL;
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // test direct conversion from UTF-8
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(cc.utf8Length>=0) {
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errorCode=U_ZERO_ERROR;
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            resultLength=stepFromUTF8(cc, utf8Cnv, cnv,
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                    result, LENGTHOF(result),
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                    step, &errorCode);
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ok=checkFromUnicode(
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc, cnv, steps[i].utf8Name,
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    (uint8_t *)result, resultLength,
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    NULL,
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    errorCode);
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if(U_FAILURE(errorCode) || !cc.finalFlush) {
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // reset if an error occurred or we did not flush
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // otherwise do nothing to make sure that flushing resets
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_resetToUnicode(utf8Cnv);
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ucnv_resetFromUnicode(cnv);
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // not a real loop, just a convenience for breaking out of the block
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while(ok && cc.finalFlush) {
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // test ucnv_fromUChars()
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        memset(result, 0, sizeof(result));
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorCode=U_ZERO_ERROR;
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLength=ucnv_fromUChars(cnv,
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        result, LENGTHOF(result),
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.unicode, cc.unicodeLength,
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        &errorCode);
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkFromUnicode(
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc, cnv, "fromUChars",
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (uint8_t *)result, resultLength,
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(!ok) {
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // test preflighting
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // keep the correct result for simple checking
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errorCode=U_ZERO_ERROR;
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        resultLength=ucnv_fromUChars(cnv,
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        NULL, 0,
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        cc.unicode, cc.unicodeLength,
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        &errorCode);
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if(errorCode==U_STRING_NOT_TERMINATED_WARNING || errorCode==U_BUFFER_OVERFLOW_ERROR) {
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errorCode=U_ZERO_ERROR;
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ok=checkFromUnicode(
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc, cnv, "preflight fromUChars",
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (uint8_t *)result, resultLength,
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                NULL,
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                errorCode);
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_close(cnv);
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ok;
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruConversionTest::checkFromUnicode(ConversionCase &cc, UConverter *cnv, const char *name,
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 const uint8_t *result, int32_t resultLength,
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 const int32_t *resultOffsets,
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                 UErrorCode resultErrorCode) {
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar resultInvalidUChars[8];
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int8_t resultInvalidLength;
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode errorCode;
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *msg;
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // reset the message; NULL will mean "ok"
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg=NULL;
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    resultInvalidLength=LENGTHOF(resultInvalidUChars);
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ucnv_getInvalidUChars(cnv, resultInvalidUChars, &resultInvalidLength, &errorCode);
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) ucnv_getInvalidUChars() failed - %s",
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, u_errorName(errorCode));
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // check everything that might have gone wrong
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cc.bytesLength!=resultLength) {
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong result length";
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(0!=memcmp(cc.bytes, result, cc.bytesLength)) {
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong result string";
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.offsets!=NULL && 0!=memcmp(cc.offsets, resultOffsets, cc.bytesLength*sizeof(*cc.offsets))) {
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong offsets";
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.outErrorCode!=resultErrorCode) {
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong error code";
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(cc.invalidLength!=resultInvalidLength) {
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong length of last invalid input";
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(0!=u_memcmp(cc.invalidUChars, resultInvalidUChars, cc.invalidLength)) {
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        msg="wrong last invalid input";
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(msg==NULL) {
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char buffer[2000]; // one buffer for all strings
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char *s, *unicodeString, *bytesString, *resultString,
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *offsetsString, *resultOffsetsString,
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *invalidCharsString, *resultInvalidUCharsString;
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        unicodeString=s=buffer;
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printUnicode(cc.unicode, cc.unicodeLength, unicodeString);
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printBytes(cc.bytes, cc.bytesLength, bytesString=s);
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printBytes(result, resultLength, resultString=s);
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printOffsets(cc.offsets, cc.bytesLength, offsetsString=s);
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printOffsets(resultOffsets, resultLength, resultOffsetsString=s);
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printUnicode(cc.invalidUChars, cc.invalidLength, invalidCharsString=s);
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s=printUnicode(resultInvalidUChars, resultInvalidLength, resultInvalidUCharsString=s);
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if((s-buffer)>(int32_t)sizeof(buffer)) {
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) fatal error: checkFromUnicode() test output buffer overflow writing %d chars\n",
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, (int)(s-buffer));
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            exit(1);
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        errln("fromUnicode[%d](%s cb=\"%s\" fb=%d flush=%d %s) failed: %s\n"
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  unicode <%s>[%d]\n"
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " expected <%s>[%d]\n"
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  result  <%s>[%d]\n"
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " offsets         <%s>\n"
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  result offsets <%s>\n"
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              " error code expected %s got %s\n"
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              "  invalidChars expected <%s> got <%s>\n",
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              cc.caseNr, cc.charset, cc.cbopt, cc.fallbacks, cc.finalFlush, name, msg,
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              unicodeString, cc.unicodeLength,
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              bytesString, cc.bytesLength,
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              resultString, resultLength,
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              offsetsString,
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              resultOffsetsString,
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              u_errorName(cc.outErrorCode), u_errorName(resultErrorCode),
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              invalidCharsString, resultInvalidUCharsString);
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */
1633