/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2004, International Business Machines Corporation and
+ * Copyright (c) 1997-2006, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
-/********************************************************************************
+/*******************************************************************************
*
* File CU_CAPITST.C
*
* Modification History:
* Name Description
* Madhu Katragadda Ported for C API
-*********************************************************************************
+********************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include "unicode/putil.h"
#include "unicode/ustring.h"
#include "ucnv_bld.h" /* for sizeof(UConverter) */
+#include "cmemory.h" /* for UAlignedMemory */
#include "cintltst.h"
#include "ccapitst.h"
/* for not including "cstring.h" -begin*/
-#ifdef WIN32
+#ifdef U_WINDOWS
# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2)
#elif defined(POSIX)
# define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2)
static void TestJ932(void);
static void TestJ1968(void);
static void TestLMBCSMaxChar(void);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
static void TestConvertSafeCloneCallback(void);
+#endif
+
static void TestEBCDICSwapLFNL(void);
static void TestConvertEx(void);
static void TestConvertAlgorithmic(void);
void TestDefaultConverterError(void); /* defined in cctest.c */
+static void TestToUCountPending(void);
+static void TestFromUCountPending(void);
+static void TestDefaultName(void);
+static void TestCompareNames(void);
+static void TestSubstString(void);
void addTestConvert(TestNode** root);
addTest(root, &TestFlushCache, "tsconv/ccapitst/TestFlushCache");
addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias");
addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias");
- addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone");
- addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
+ addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone");
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
+#endif
+
addTest(root, &TestCCSID, "tsconv/ccapitst/TestCCSID");
addTest(root, &TestJ932, "tsconv/ccapitst/TestJ932");
addTest(root, &TestJ1968, "tsconv/ccapitst/TestJ1968");
addTest(root, &TestConvertEx, "tsconv/ccapitst/TestConvertEx");
addTest(root, &TestConvertAlgorithmic, "tsconv/ccapitst/TestConvertAlgorithmic");
addTest(root, &TestDefaultConverterError, "tsconv/ccapitst/TestDefaultConverterError");
+ addTest(root, &TestToUCountPending, "tsconv/ccapitst/TestToUCountPending");
+ addTest(root, &TestFromUCountPending, "tsconv/ccapitst/TestFromUCountPending");
+ addTest(root, &TestDefaultName, "tsconv/ccapitst/TestDefaultName");
+ addTest(root, &TestCompareNames, "tsconv/ccapitst/TestCompareNames");
+ addTest(root, &TestSubstString, "tsconv/ccapitst/TestSubstString");
}
static void ListNames(void) {
count1++;
log_verbose("read \"%s\", length %i\n", string, len);
}
- err = U_ZERO_ERROR;
+ if (U_FAILURE(err)) {
+ log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err));
+ err = U_ZERO_ERROR;
+ }
uenum_reset(allNamesEnum, &err);
while ((string = uenum_next(allNamesEnum, &len, &err))) {
count2++;
static void TestConvert()
{
+#if !UCONFIG_NO_LEGACY_CONVERSION
char myptr[4];
char save[4];
int32_t testLong1 = 0;
log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err));
}
- /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
- {
- static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
- strcpy(defaultName, ucnv_getDefaultName());
-
- log_verbose("getDefaultName returned %s\n", defaultName);
-
- /*change the default name by setting it */
- ucnv_setDefaultName("changed");
- if(strcmp(ucnv_getDefaultName(), "changed")==0)
- log_verbose("setDefaultName o.k");
- else
- log_err("setDefaultName failed");
- /*set the default name back*/
- ucnv_setDefaultName(defaultName);
- }
-
ucnv_close(someConverters[0]);
ucnv_close(someConverters[1]);
ucnv_close(someConverters[2]);
/*getDisplayName*/
log_verbose("\n---Testing ucnv_getDisplayName()...\n");
locale=CodePagesLocale[codepage_index];
- displayname=(UChar*)malloc(1 * sizeof(UChar));
len=0;
- disnamelen = ucnv_getDisplayName(myConverter,locale,displayname, len, &err);
- if(err==U_BUFFER_OVERFLOW_ERROR)
- {
+ displayname=NULL;
+ disnamelen = ucnv_getDisplayName(myConverter, locale, displayname, len, &err);
+ if(err==U_BUFFER_OVERFLOW_ERROR) {
err=U_ZERO_ERROR;
- displayname=(UChar*)realloc(displayname, (disnamelen+1) * sizeof(UChar));
+ displayname=(UChar*)malloc((disnamelen+1) * sizeof(UChar));
ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
- if(U_FAILURE(err))
- {
- log_err("getDisplayName failed the error is %s\n", myErrorName(err));
+ if(U_FAILURE(err)) {
+ log_err("getDisplayName failed. The error is %s\n", myErrorName(err));
}
- else
+ else {
log_verbose(" getDisplayName o.k.\n");
+ }
+ free(displayname);
+ displayname=NULL;
+ }
+ else {
+ log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err));
}
/*test ucnv_getDiaplayName with error condition*/
- log_verbose("\n---Testing ucnv_getDisplayName()...\n");
err= U_ILLEGAL_ARGUMENT_ERROR;
- len=ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
+ len=ucnv_getDisplayName(myConverter,locale,NULL,0, &err);
if( len !=0 ){
log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
}
+ /*test ucnv_getDiaplayName with error condition*/
+ err=U_ZERO_ERROR;
+ len=ucnv_getDisplayName(NULL,locale,NULL,0, &err);
+ if( len !=0 || U_SUCCESS(err)){
+ log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
+ }
err=U_ZERO_ERROR;
/* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
fclose(ucs_file_in);
ucnv_close(myConverter);
- free(displayname);
if (uchar1 != 0) free(uchar1);
if (uchar2 != 0) free(uchar2);
if (uchar3 != 0) free(uchar3);
free((void*)output_cp_buffer);
free((void*)ucs_file_buffer);
free((void*)my_ucs_file_buffer);
+#endif
}
static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA)
}
static void TestFlushCache(void) {
+#if !UCONFIG_NO_LEGACY_CONVERSION
UErrorCode err = U_ZERO_ERROR;
UConverter* someConverters[5];
int flushCount = 0;
log_verbose("Flush cache ok\n");
else
log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount);
-
+#endif
}
/**
for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) {
const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status);
if(!mapBack) {
- log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i]);
+ log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i].name);
continue;
}
if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) {
UErrorCode subErr = U_ZERO_ERROR;
TSCCContext *newCtx;
TSCCContext *junkCtx;
+ TSCCContext **pjunkCtx = &junkCtx;
/* "recreate" it */
log_verbose("TSCC_fromU: cloning..\n");
}
/* now, SET it */
- ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)&junkCtx);
+ ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)pjunkCtx);
ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
if(U_FAILURE(subErr)) {
UErrorCode subErr = U_ZERO_ERROR;
TSCCContext *newCtx;
TSCCContext *junkCtx;
+ TSCCContext **pjunkCtx = &junkCtx;
/* "recreate" it */
log_verbose("TSCC_toU: cloning..\n");
}
/* now, SET it */
- ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)&junkCtx);
+ ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)pjunkCtx);
ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
if(U_FAILURE(subErr)) {
}
}
+#if !UCONFIG_NO_LEGACY_CONVERSION
static void TestConvertSafeCloneCallback()
{
UErrorCode err = U_ZERO_ERROR;
TSCCContext from1, to1;
TSCCContext *from2, *from3, *to2, *to3;
+ TSCCContext **pfrom2 = &from2, **pfrom3 = &from3, **pto2 = &to2, **pto3 = &to3;
char hunk[8192];
int32_t hunkSize = 8192;
UConverterFromUCallback junkFrom;
log_verbose("Cloned to conv2=%p.\n", conv2);
/********** from *********************/
- ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)&from2);
- ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)&from3);
+ ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)pfrom2);
+ ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)pfrom3);
TSCC_print_log(from2, "from2");
TSCC_print_log(from3, "from3(==from1)");
}
/********** to *********************/
- ucnv_getToUCallBack(conv2, &junkTo, (const void**)&to2);
- ucnv_getToUCallBack(conv1, &junkTo, (const void**)&to3);
+ ucnv_getToUCallBack(conv2, &junkTo, (const void**)pto2);
+ ucnv_getToUCallBack(conv1, &junkTo, (const void**)pto3);
TSCC_print_log(to2, "to2");
TSCC_print_log(to3, "to3(==to1)");
free(from2); /* from1 is stack based */
}
}
+#endif
static UBool
containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) {
{
/* one 'regular' & all the 'private stateful' converters */
static const char *const names[] = {
+#if !UCONFIG_NO_LEGACY_CONVERSION
"ibm-1047",
"ISO_2022,locale=zh,version=1",
+#endif
"SCSU",
+#if !UCONFIG_NO_LEGACY_CONVERSION
"HZ",
"lmbcs",
"ISCII,version=0",
"ISO_2022,locale=kr,version=1",
"ISO_2022,locale=jp,version=2",
+#endif
"BOCU-1",
"UTF-7",
+#if !UCONFIG_NO_LEGACY_CONVERSION
"IMAP-mailbox-name",
"ibm-1047-s390"
+#else
+ "IMAP=mailbox-name"
+#endif
};
+ /* store the actual sizes of each converter */
+ int32_t actualSizes[LENGTHOF(names)];
+
static const int32_t bufferSizes[] = {
U_CNV_SAFECLONE_BUFFERSIZE,
(int32_t)(3*sizeof(UConverter))/2, /* 1.5*sizeof(UConverter) */
(int32_t)sizeof(UConverter)/2 /* 0.5*sizeof(UConverter) */
};
- char charBuffer [21]; /* Leave at an odd number for alignment testing */
- uint8_t buffer [3] [U_CNV_SAFECLONE_BUFFERSIZE];
+ char charBuffer[21]; /* Leave at an odd number for alignment testing */
+ uint8_t buffer[3] [U_CNV_SAFECLONE_BUFFERSIZE];
int32_t bufferSize, maxBufferSize;
const char *maxName;
UConverter * cnv, *cnv2;
char *pCharBuffer;
const char *pConstCharBuffer;
const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
- UChar uniBuffer [] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
- UChar uniCharBuffer [20];
- char charSourceBuffer [] = { 0x1b, 0x24, 0x42 };
+ UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
+ UChar uniCharBuffer[20];
+ char charSourceBuffer[] = { 0x1b, 0x24, 0x42 };
const char *pCharSource = charSourceBuffer;
const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
UChar *pUCharTarget = uniCharBuffer;
if(j == 0) {
/* preflight to get maxBufferSize */
- bufferSize = 0;
- ucnv_safeClone(cnv, NULL, &bufferSize, &err);
- if(bufferSize > maxBufferSize) {
- maxBufferSize = bufferSize;
+ actualSizes[index] = 0;
+ ucnv_safeClone(cnv, NULL, &actualSizes[index], &err);
+ if(actualSizes[index] > maxBufferSize) {
+ maxBufferSize = actualSizes[index];
maxName = names[index];
}
}
/* close the original immediately to make sure that the clone works by itself */
ucnv_close(cnv);
+ if( actualSizes[index] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) &&
+ err == U_SAFECLONE_ALLOCATED_WARNING
+ ) {
+ log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[index]);
+ }
+
/* check if the clone function overwrote any bytes that it is not supposed to touch */
if(bufferSize <= bufferSizes[j]) {
/* used the stack buffer */
log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
+ if(maxBufferSize > U_CNV_SAFECLONE_BUFFERSIZE) {
+ log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
+ maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
+ }
}
static void TestCCSID() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
UConverter *cnv;
UErrorCode errorCode;
int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
ucnv_close(cnv);
}
+#endif
}
/* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
*/
static void bug1()
{
+#if !UCONFIG_NO_LEGACY_CONVERSION
static char char_in[CHUNK_SIZE+32];
static char char_out[CHUNK_SIZE*2];
log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
}
}
+#endif
}
/* bug2: pre-flighting loop bug: simple overflow causes bug */
*/
static void bug3()
{
+#if !UCONFIG_NO_LEGACY_CONVERSION
static char char_in[CHUNK_SIZE*4];
static char target[5];
UErrorCode err = U_ZERO_ERROR;
*/
log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size);
}
+#endif
}
static void
}
static void TestConvertEx() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
static const uint8_t
utf8[]={
/* 4e00 30a1 ff61 0410 */
log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode));
}
+ /* streaming conversion without a pivot buffer */
+ errorCode=U_ZERO_ERROR;
+ src=srcBuffer;
+ pivotSource=pivotBuffer;
+ ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
+ NULL, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, FALSE, &errorCode);
+ if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
+ log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode));
+ }
+
ucnv_close(cnv1);
ucnv_close(cnv2);
+#endif
}
static void
TestConvertAlgorithmic() {
+#if !UCONFIG_NO_LEGACY_CONVERSION
static const uint8_t
utf8[]={
/* 4e00 30a1 ff61 0410 */
log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode));
}
ucnv_close(cnv);
+#endif
}
static void TestLMBCSMaxChar(void) {
}
+#if !UCONFIG_NO_LEGACY_CONVERSION
static void
testSwap(const char *name, UBool swap) {
/*
testSwap(tests[i].name, tests[i].swap);
}
}
+#else
+static void
+TestEBCDICSwapLFNL() {
+ /* test nothing... */
+}
+#endif
+
+static const UVersionInfo ICU_34 = {3,4,0,0};
+
+static void TestFromUCountPending(){
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode status = U_ZERO_ERROR;
+/* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
+ static const struct {
+ UChar input[6];
+ int32_t len;
+ int32_t exp;
+ }fromUnicodeTests[] = {
+ /*m:n conversion*/
+ {{0xdbc4},1,1},
+ {{ 0xdbc4, 0xde34, 0xd84d},3,1},
+ {{ 0xdbc4, 0xde34, 0xd900},3,3},
+ };
+ int i;
+ UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ for(i=0; i<LENGTHOF(fromUnicodeTests); ++i) {
+ char tgt[10];
+ char* target = tgt;
+ char* targetLimit = target + 10;
+ const UChar* source = fromUnicodeTests[i].input;
+ const UChar* sourceLimit = source + fromUnicodeTests[i].len;
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+ if(len != fromUnicodeTests[i].exp){
+ log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
+ }
+ }
+ status = U_ZERO_ERROR;
+ {
+ /*
+ * The converter has to read the tail before it knows that
+ * only head alone matches.
+ * At the end, the output for head will overflow the target,
+ * middle will be pending, and tail will not have been consumed.
+ */
+ /*
+ \U00101234 -> x (<U101234> \x07 |0)
+ \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
+ \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
+ \U00060007 -> unassigned
+ */
+ static const UChar head[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
+ static const UChar middle[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
+ static const UChar tail[] = {0xDC07,0x0000};/* second half of \U00060007 */
+ char tgt[10];
+ char* target = tgt;
+ char* targetLimit = target + 2; /* expect overflow from converting \U00101234\U00050005 */
+ const UChar* source = head;
+ const UChar* sourceLimit = source + u_strlen(head);
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ if(len!=4){
+ log_err("ucnv_fromUInputHeld did not return correct length for head\n");
+ }
+ source = middle;
+ sourceLimit = source + u_strlen(middle);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_fromUCountPending(cnv, &status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ }
+ if(len!=5){
+ log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
+ }
+ source = tail;
+ sourceLimit = source + u_strlen(tail);
+ ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ if(status != U_BUFFER_OVERFLOW_ERROR){
+ log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ len = ucnv_fromUCountPending(cnv, &status);
+ /* middle[1] is pending, tail has not been consumed */
+ if(U_FAILURE(status)){
+ log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len!=1){
+ log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
+ }
+ }
+ ucnv_close(cnv);
+#endif
+}
+
+static void
+TestToUCountPending(){
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ UErrorCode status = U_ZERO_ERROR;
+ static const struct {
+ char input[6];
+ int32_t len;
+ int32_t exp;
+ }toUnicodeTests[] = {
+ /*m:n conversion*/
+ {{0x05, 0x01, 0x02},3,3},
+ {{0x01, 0x02},2,2},
+ {{0x07, 0x00, 0x01, 0x02},4,4},
+ };
+
+ int i;
+ UConverterToUCallback *oldToUAction= NULL;
+ UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
+ for(i=0; i<LENGTHOF(toUnicodeTests); ++i) {
+ UChar tgt[10];
+ UChar* target = tgt;
+ UChar* targetLimit = target + 20;
+ const char* source = toUnicodeTests[i].input;
+ const char* sourceLimit = source + toUnicodeTests[i].len;
+ int32_t len = 0;
+ ucnv_reset(cnv);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ status = U_ZERO_ERROR;
+ continue;
+ }
+ if(len != toUnicodeTests[i].exp){
+ log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
+ }
+ }
+ status = U_ZERO_ERROR;
+ ucnv_close(cnv);
+
+ {
+ /*
+ * The converter has to read the tail before it knows that
+ * only head alone matches.
+ * At the end, the output for head will overflow the target,
+ * mid will be pending, and tail will not have been consumed.
+ */
+ char head[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
+ char mid[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
+ char tail[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
+ /*
+ 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
+ 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
+ 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
+ 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
+ */
+ UChar tgt[10];
+ UChar* target = tgt;
+ UChar* targetLimit = target + 1; /* expect overflow from converting */
+ const char* source = head;
+ const char* sourceLimit = source + strlen(head);
+ int32_t len = 0;
+ cnv = ucnv_openPackage(loadTestData(&status), "test4", &status);
+ if(U_FAILURE(status)){
+ log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
+ return;
+ }
+ ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 4){
+ log_err("Did not get the expected len for head.\n");
+ }
+ source=mid;
+ sourceLimit = source+strlen(mid);
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ len = ucnv_toUCountPending(cnv,&status);
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 8){
+ log_err("Did not get the expected len for mid.\n");
+ }
+
+ source=tail;
+ sourceLimit = source+strlen(tail);
+ targetLimit = target;
+ ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
+ if(status != U_BUFFER_OVERFLOW_ERROR){
+ log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ status = U_ZERO_ERROR;
+ len = ucnv_toUCountPending(cnv,&status);
+ /* mid[4] is pending, tail has not been consumed */
+ if(U_FAILURE(status)){
+ log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status));
+ }
+ if(len != 4){
+ log_err("Did not get the expected len for tail.\n");
+ }
+ ucnv_close(cnv);
+ }
+#endif
+}
+
+static void TestOneDefaultNameChange(const char *name) {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *cnv;
+ ucnv_setDefaultName(name);
+ if(strcmp(ucnv_getDefaultName(), name)==0)
+ log_verbose("setDefaultName of %s works.\n", name);
+ else
+ log_err("setDefaultName of %s failed\n", name);
+ cnv=ucnv_open(NULL, &status);
+ if (U_FAILURE(status) || cnv == NULL) {
+ log_err("opening the default converter of %s failed\n", name);
+ return;
+ }
+ if(strcmp(ucnv_getName(cnv, &status), name)==0)
+ log_verbose("ucnv_getName of %s works.\n", name);
+ else
+ log_err("ucnv_getName of %s failed\n", name);
+ ucnv_close(cnv);
+}
+
+static void TestDefaultName(void) {
+ /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
+ static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
+ strcpy(defaultName, ucnv_getDefaultName());
+
+ log_verbose("getDefaultName returned %s\n", defaultName);
+
+ /*change the default name by setting it */
+ TestOneDefaultNameChange("UTF-8");
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ TestOneDefaultNameChange("ISCII,version=1");
+ TestOneDefaultNameChange("ISCII,version=2");
+#endif
+ TestOneDefaultNameChange("ISO-8859-1");
+
+ /*set the default name back*/
+ ucnv_setDefaultName(defaultName);
+}
+
+/* Test that ucnv_compareNames() matches names according to spec. ----------- */
+
+static U_INLINE int
+sign(int n) {
+ if(n==0) {
+ return 0;
+ } else if(n<0) {
+ return -1;
+ } else /* n>0 */ {
+ return 1;
+ }
+}
+
+static void
+compareNames(const char **names) {
+ const char *relation, *name1, *name2;
+ int rel, result;
+
+ relation=*names++;
+ if(*relation=='=') {
+ rel = 0;
+ } else if(*relation=='<') {
+ rel = -1;
+ } else {
+ rel = 1;
+ }
+
+ name1=*names++;
+ if(name1==NULL) {
+ return;
+ }
+ while((name2=*names++)!=NULL) {
+ result=ucnv_compareNames(name1, name2);
+ if(sign(result)!=rel) {
+ log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1, name2, result, rel);
+ }
+ name1=name2;
+ }
+}
+
+static void
+TestCompareNames() {
+ static const char *equalUTF8[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL };
+ static const char *equalIBM[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL };
+ static const char *lessMac[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL };
+ static const char *lessUTF080[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL };
+
+ compareNames(equalUTF8);
+ compareNames(equalIBM);
+ compareNames(lessMac);
+ compareNames(lessUTF080);
+}
+
+static void
+TestSubstString() {
+ static const UChar surrogate[1]={ 0xd900 };
+ char buffer[16];
+
+ static const UChar sub[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
+ static const char subChars[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
+ UConverter *cnv;
+ UErrorCode errorCode;
+ int32_t length;
+ int8_t len8;
+
+ /* UTF-16/32: test that the BOM is output before the sub character */
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-16", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
+ ucnv_close(cnv);
+ if(U_FAILURE(errorCode) ||
+ length!=4 ||
+ NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
+ ) {
+ log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
+ }
+
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("UTF-32", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
+ ucnv_close(cnv);
+ if(U_FAILURE(errorCode) ||
+ length!=8 ||
+ NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
+ ) {
+ log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
+ }
+
+ /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("ISO-8859-1", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode));
+ } else {
+ len8 = sizeof(buffer);
+ ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
+ /* Stateless converter, we expect the string converted to charset bytes. */
+ if(U_FAILURE(errorCode) || len8!=sizeof(subChars) || 0!=uprv_memcmp(buffer, subChars, len8)) {
+ log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode));
+ }
+ }
+ ucnv_close(cnv);
+
+#if !UCONFIG_NO_LEGACY_CONVERSION
+ errorCode=U_ZERO_ERROR;
+ cnv=ucnv_open("HZ", &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode));
+ return;
+ }
+ ucnv_setSubstString(cnv, sub, LENGTHOF(sub), &errorCode);
+ if(U_FAILURE(errorCode)) {
+ log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode));
+ } else {
+ len8 = sizeof(buffer);
+ ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
+ /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
+ if(U_FAILURE(errorCode) || len8!=0) {
+ log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode));
+ }
+ }
+ ucnv_close(cnv);
+#endif
+ /*
+ * Further testing of ucnv_setSubstString() is done via intltest convert.
+ * We do not test edge cases of illegal arguments and similar because the
+ * function implementation uses all of its parameters in calls to other
+ * functions with UErrorCode parameters.
+ */
+}