1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /*****************************************************************************
12 * Modification History:
14 * Madhu Katragadda Ported for C API
15 ******************************************************************************
21 #include "unicode/uloc.h"
22 #include "unicode/ucnv.h"
23 #include "unicode/ucnv_err.h"
24 #include "unicode/putil.h"
25 #include "unicode/uset.h"
26 #include "unicode/ustring.h"
27 #include "unicode/utf8.h"
28 #include "ucnv_bld.h" /* for sizeof(UConverter) */
29 #include "cmemory.h" /* for UAlignedMemory */
34 #define NUM_CODEPAGE 1
35 #define MAX_FILE_LEN 1024*20
36 #define UCS_FILE_NAME_SIZE 512
38 /*returns an action other than the one provided*/
39 #if !UCONFIG_NO_LEGACY_CONVERSION
40 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
);
41 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
);
45 cnv_open(const char *name
, UErrorCode
*pErrorCode
) {
46 if(name
!=NULL
&& name
[0]=='*') {
47 return ucnv_openPackage(loadTestData(pErrorCode
), name
+1, pErrorCode
);
49 return ucnv_open(name
, pErrorCode
);
54 static void ListNames(void);
55 static void TestFlushCache(void);
56 static void TestDuplicateAlias(void);
57 static void TestCCSID(void);
58 static void TestJ932(void);
59 static void TestJ1968(void);
60 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
61 static void TestLMBCSMaxChar(void);
64 #if !UCONFIG_NO_LEGACY_CONVERSION
65 static void TestConvertSafeCloneCallback(void);
68 static void TestEBCDICSwapLFNL(void);
69 static void TestConvertEx(void);
70 static void TestConvertExFromUTF8(void);
71 static void TestConvertExFromUTF8_C5F0(void);
72 static void TestConvertAlgorithmic(void);
73 void TestDefaultConverterError(void); /* defined in cctest.c */
74 void TestDefaultConverterSet(void); /* defined in cctest.c */
75 static void TestToUCountPending(void);
76 static void TestFromUCountPending(void);
77 static void TestDefaultName(void);
78 static void TestCompareNames(void);
79 static void TestSubstString(void);
80 static void InvalidArguments(void);
81 static void TestGetName(void);
82 static void TestUTFBOM(void);
84 void addTestConvert(TestNode
** root
);
86 void addTestConvert(TestNode
** root
)
88 addTest(root
, &ListNames
, "tsconv/ccapitst/ListNames");
89 addTest(root
, &TestConvert
, "tsconv/ccapitst/TestConvert");
90 addTest(root
, &TestFlushCache
, "tsconv/ccapitst/TestFlushCache");
91 addTest(root
, &TestAlias
, "tsconv/ccapitst/TestAlias");
92 addTest(root
, &TestDuplicateAlias
, "tsconv/ccapitst/TestDuplicateAlias");
93 addTest(root
, &TestConvertSafeClone
, "tsconv/ccapitst/TestConvertSafeClone");
94 #if !UCONFIG_NO_LEGACY_CONVERSION
95 addTest(root
, &TestConvertSafeCloneCallback
,"tsconv/ccapitst/TestConvertSafeCloneCallback");
97 addTest(root
, &TestCCSID
, "tsconv/ccapitst/TestCCSID");
98 addTest(root
, &TestJ932
, "tsconv/ccapitst/TestJ932");
99 addTest(root
, &TestJ1968
, "tsconv/ccapitst/TestJ1968");
100 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
101 addTest(root
, &TestLMBCSMaxChar
, "tsconv/ccapitst/TestLMBCSMaxChar");
103 addTest(root
, &TestEBCDICSwapLFNL
, "tsconv/ccapitst/TestEBCDICSwapLFNL");
104 addTest(root
, &TestConvertEx
, "tsconv/ccapitst/TestConvertEx");
105 addTest(root
, &TestConvertExFromUTF8
, "tsconv/ccapitst/TestConvertExFromUTF8");
106 addTest(root
, &TestConvertExFromUTF8_C5F0
, "tsconv/ccapitst/TestConvertExFromUTF8_C5F0");
107 addTest(root
, &TestConvertAlgorithmic
, "tsconv/ccapitst/TestConvertAlgorithmic");
108 addTest(root
, &TestDefaultConverterError
, "tsconv/ccapitst/TestDefaultConverterError");
109 addTest(root
, &TestDefaultConverterSet
, "tsconv/ccapitst/TestDefaultConverterSet");
110 #if !UCONFIG_NO_FILE_IO
111 addTest(root
, &TestToUCountPending
, "tsconv/ccapitst/TestToUCountPending");
112 addTest(root
, &TestFromUCountPending
, "tsconv/ccapitst/TestFromUCountPending");
114 addTest(root
, &TestDefaultName
, "tsconv/ccapitst/TestDefaultName");
115 addTest(root
, &TestCompareNames
, "tsconv/ccapitst/TestCompareNames");
116 addTest(root
, &TestSubstString
, "tsconv/ccapitst/TestSubstString");
117 addTest(root
, &InvalidArguments
, "tsconv/ccapitst/InvalidArguments");
118 addTest(root
, &TestGetName
, "tsconv/ccapitst/TestGetName");
119 addTest(root
, &TestUTFBOM
, "tsconv/ccapitst/TestUTFBOM");
122 static void ListNames(void) {
123 UErrorCode err
= U_ZERO_ERROR
;
124 int32_t testLong1
= 0;
125 const char* available_conv
;
126 UEnumeration
*allNamesEnum
= NULL
;
127 int32_t allNamesCount
= 0;
130 log_verbose("Testing ucnv_openAllNames()...");
131 allNamesEnum
= ucnv_openAllNames(&err
);
133 log_data_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err
));
136 const char *string
= NULL
;
140 allNamesCount
= uenum_count(allNamesEnum
, &err
);
141 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
143 log_verbose("read \"%s\", length %i\n", string
, len
);
145 if (U_FAILURE(err
)) {
146 log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err
));
149 uenum_reset(allNamesEnum
, &err
);
150 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
152 ucnv_close(ucnv_open(string
, &err
));
153 log_verbose("read \"%s\", length %i (%s)\n", string
, len
, U_SUCCESS(err
) ? "available" : "unavailable");
156 if (count1
!= count2
) {
157 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
160 uenum_close(allNamesEnum
);
163 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
165 log_verbose("Testing ucnv_countAvailable()...");
167 testLong1
=ucnv_countAvailable();
168 log_info("Number of available codepages: %d/%d\n", testLong1
, allNamesCount
);
170 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
172 available_conv
= ucnv_getAvailableName(testLong1
);
173 /*test ucnv_getAvailableName with err condition*/
174 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
175 available_conv
= ucnv_getAvailableName(-1);
176 if(available_conv
!= NULL
){
177 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
180 /* Test ucnv_countAliases() etc. */
181 count
= ucnv_countAliases("utf-8", &err
);
183 log_data_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err
));
184 } else if(count
<= 0) {
185 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count
);
187 /* try to get the aliases individually */
189 alias
= ucnv_getAlias("utf-8", 0, &err
);
191 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err
));
192 } else if(strcmp("UTF-8", alias
) != 0) {
193 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias
);
196 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
197 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
199 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
200 } else if(strlen(alias
) > 20) {
202 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum
, alias
);
204 log_verbose("alias %d for utf-8: %s\n", aliasNum
, alias
);
208 /* try to fill an array with all aliases */
209 const char **aliases
;
210 aliases
=(const char **)malloc(count
* sizeof(const char *));
212 ucnv_getAliases("utf-8", aliases
, &err
);
214 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err
));
216 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
217 /* compare the pointers with the ones returned individually */
218 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
220 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
221 } else if(aliases
[aliasNum
] != alias
) {
222 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum
, aliasNum
);
226 free((char **)aliases
);
234 static void TestConvert()
236 #if !UCONFIG_NO_LEGACY_CONVERSION
239 int32_t testLong1
= 0;
243 FILE* ucs_file_in
= NULL
;
245 UChar myUChar
= 0x0000;
246 char* mytarget
; /* [MAX_FILE_LEN] */
249 UChar
* consumedUni
= NULL
;
250 char* consumed
= NULL
;
251 char* output_cp_buffer
; /* [MAX_FILE_LEN] */
252 UChar
* ucs_file_buffer
; /* [MAX_FILE_LEN] */
253 UChar
* ucs_file_buffer_use
;
254 UChar
* my_ucs_file_buffer
; /* [MAX_FILE_LEN] */
255 UChar
* my_ucs_file_buffer_1
;
257 uint16_t codepage_index
= 0;
259 UErrorCode err
= U_ZERO_ERROR
;
260 char ucs_file_name
[UCS_FILE_NAME_SIZE
];
261 UConverterFromUCallback MIA1
, MIA1_2
;
262 UConverterToUCallback MIA2
, MIA2_2
;
263 const void *MIA1Context
, *MIA1Context2
, *MIA2Context
, *MIA2Context2
;
264 UConverter
* someConverters
[5];
265 UConverter
* myConverter
= 0;
266 UChar
* displayname
= 0;
273 int32_t targetcapacity2
;
274 int32_t targetcapacity
;
278 const UChar
* tmp_ucs_buf
;
279 const UChar
* tmp_consumedUni
=NULL
;
280 const char* tmp_mytarget_use
;
281 const char* tmp_consumed
;
283 /******************************************************************
284 Checking Unicode -> ksc
285 ******************************************************************/
287 const char* CodePagesToTest
[NUM_CODEPAGE
] =
293 const uint16_t CodePageNumberToTest
[NUM_CODEPAGE
] =
299 const int8_t CodePagesMinChars
[NUM_CODEPAGE
] =
305 const int8_t CodePagesMaxChars
[NUM_CODEPAGE
] =
311 const uint16_t CodePagesSubstitutionChars
[NUM_CODEPAGE
] =
316 const char* CodePagesTestFiles
[NUM_CODEPAGE
] =
322 const UConverterPlatform CodePagesPlatform
[NUM_CODEPAGE
] =
328 const char* CodePagesLocale
[NUM_CODEPAGE
] =
333 UConverterFromUCallback oldFromUAction
= NULL
;
334 UConverterToUCallback oldToUAction
= NULL
;
335 const void* oldFromUContext
= NULL
;
336 const void* oldToUContext
= NULL
;
338 /* Allocate memory */
339 mytarget
= (char*) malloc(MAX_FILE_LEN
* sizeof(mytarget
[0]));
340 output_cp_buffer
= (char*) malloc(MAX_FILE_LEN
* sizeof(output_cp_buffer
[0]));
341 ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(ucs_file_buffer
[0]));
342 my_ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(my_ucs_file_buffer
[0]));
344 ucs_file_buffer_use
= ucs_file_buffer
;
346 mytarget_use
= mytarget
;
347 my_ucs_file_buffer_1
=my_ucs_file_buffer
;
349 /* flush the converter cache to get a consistent state before the flushing is tested */
352 /*Testing ucnv_openU()*/
354 UChar converterName
[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
355 UChar firstSortedName
[]={ 0x0021, 0x0000}; /* ! */
356 UChar lastSortedName
[]={ 0x007E, 0x0000}; /* ~ */
357 const char *illegalNameChars
={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
358 UChar illegalName
[100];
359 UConverter
*converter
=NULL
;
361 converter
=ucnv_openU(converterName
, &err
);
363 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err
));
365 ucnv_close(converter
);
367 converter
=ucnv_openU(NULL
, &err
);
369 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err
));
371 ucnv_close(converter
);
372 /*testing with error value*/
373 err
=U_ILLEGAL_ARGUMENT_ERROR
;
374 converter
=ucnv_openU(converterName
, &err
);
375 if(!(converter
== NULL
)){
376 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
378 ucnv_close(converter
);
380 u_uastrcpy(illegalName
, "");
381 u_uastrcpy(illegalName
, illegalNameChars
);
382 ucnv_openU(illegalName
, &err
);
383 if(!(err
==U_ILLEGAL_ARGUMENT_ERROR
)){
384 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
388 ucnv_openU(firstSortedName
, &err
);
389 if(err
!=U_FILE_ACCESS_ERROR
){
390 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
394 ucnv_openU(lastSortedName
, &err
);
395 if(err
!=U_FILE_ACCESS_ERROR
){
396 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
401 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
403 UConverter
*cnv
=NULL
;
405 cnv
=ucnv_open("ibm-949,Madhu", &err
);
407 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err
));
412 /*Testing ucnv_convert()*/
414 int32_t targetLimit
=0, sourceLimit
=0, i
=0, targetCapacity
=0;
415 const uint8_t source
[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
416 const uint8_t expectedTarget
[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
418 sourceLimit
=UPRV_LENGTHOF(source
);
422 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", NULL
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
423 if(err
== U_BUFFER_OVERFLOW_ERROR
){
425 targetLimit
=targetCapacity
+1;
426 target
=(char*)malloc(sizeof(char) * targetLimit
);
427 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
430 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err
));
433 for(i
=0; i
<targetCapacity
; i
++){
434 if(target
[i
] != expectedTarget
[i
]){
435 log_err("FAIL: ucnv_convert(ibm-1363->ibm-1364) failed.at index \n i=%d, Expected: %lx Got: %lx\n", i
, (UChar
)expectedTarget
[i
], (uint8_t)target
[i
]);
439 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
+1, -1, &err
);
440 if(U_FAILURE(err
) || i
!=7){
441 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
442 u_errorName(err
), i
);
445 /*Test error conditions*/
447 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, 0, &err
);
449 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
452 err
=U_ILLEGAL_ARGUMENT_ERROR
;
453 sourceLimit
=UPRV_LENGTHOF(source
);
454 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
456 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
460 sourceLimit
=UPRV_LENGTHOF(source
);
462 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
463 if(!(U_FAILURE(err
) && err
==U_BUFFER_OVERFLOW_ERROR
)){
464 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
471 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
472 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
473 err
=U_ILLEGAL_ARGUMENT_ERROR
;
474 if(ucnv_open(NULL
, &err
) != NULL
){
475 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
477 if(ucnv_openCCSID(1051, UCNV_IBM
, &err
) != NULL
){
478 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
482 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
483 log_verbose("\n---Testing ucnv_open default...\n");
484 someConverters
[0] = ucnv_open(NULL
,&err
);
485 someConverters
[1] = ucnv_open(NULL
,&err
);
486 someConverters
[2] = ucnv_open("utf8", &err
);
487 someConverters
[3] = ucnv_openCCSID(949,UCNV_IBM
,&err
);
488 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM
, &err
)); /* test for j350; ucnv_close(NULL) is safe */
489 if (U_FAILURE(err
)){ log_data_err("FAILURE! %s\n", myErrorName(err
));}
491 /* Testing ucnv_getName()*/
492 /*default code page */
493 ucnv_getName(someConverters
[0], &err
);
495 log_data_err("getName[0] failed\n");
497 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters
[0], &err
));
499 ucnv_getName(someConverters
[1], &err
);
501 log_data_err("getName[1] failed\n");
503 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters
[1], &err
));
506 ucnv_close(someConverters
[0]);
507 ucnv_close(someConverters
[1]);
508 ucnv_close(someConverters
[2]);
509 ucnv_close(someConverters
[3]);
512 for (codepage_index
=0; codepage_index
< NUM_CODEPAGE
; ++codepage_index
)
518 strcpy(ucs_file_name
, U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
);
520 strcpy(ucs_file_name
, loadTestData(&err
));
523 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err
));
528 char* index
= strrchr(ucs_file_name
,(char)U_FILE_SEP_CHAR
);
530 if((unsigned int)(index
-ucs_file_name
) != (strlen(ucs_file_name
)-1)){
535 strcat(ucs_file_name
,".."U_FILE_SEP_STRING
);
537 strcat(ucs_file_name
, CodePagesTestFiles
[codepage_index
]);
539 ucs_file_in
= fopen(ucs_file_name
,"rb");
542 log_data_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name
);
546 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
548 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
549 /* ucnv_flushCache(); */
550 myConverter
=ucnv_open( "ibm-949", &err
);
551 if (!myConverter
|| U_FAILURE(err
))
553 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err
));
558 /*testing for ucnv_getName() */
559 log_verbose("Testing ucnv_getName()...\n");
560 ucnv_getName(myConverter
, &err
);
562 log_err("Error in getName\n");
565 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter
, &err
));
567 if (uprv_stricmp(ucnv_getName(myConverter
, &err
), CodePagesToTest
[codepage_index
]))
568 log_err("getName failed\n");
570 log_verbose("getName ok\n");
571 /*Test getName with error condition*/
574 err
=U_ILLEGAL_ARGUMENT_ERROR
;
575 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
576 name
=ucnv_getName(myConverter
, &err
);
578 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
584 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
586 log_verbose("Testing ucnv_getMaxCharSize()...\n");
587 if (ucnv_getMaxCharSize(myConverter
)==CodePagesMaxChars
[codepage_index
])
588 log_verbose("Max byte per character OK\n");
590 log_err("Max byte per character failed\n");
592 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
593 if (ucnv_getMinCharSize(myConverter
)==CodePagesMinChars
[codepage_index
])
594 log_verbose("Min byte per character OK\n");
596 log_err("Min byte per character failed\n");
599 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
600 log_verbose("\n---Testing ucnv_getSubstChars...\n");
602 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
604 log_err("ucnv_getSubstChars returned a negative number %d\n", ii
);
608 rest
= (uint16_t)(((unsigned char)rest
<< 8) + (unsigned char)myptr
[x
]);
609 if (rest
==CodePagesSubstitutionChars
[codepage_index
])
610 log_verbose("Substitution character ok\n");
612 log_err("Substitution character failed.\n");
614 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
615 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
618 log_err("FAILURE! %s\n", myErrorName(err
));
620 ucnv_getSubstChars(myConverter
,save
, &ii
, &err
);
623 log_err("FAILURE! %s\n", myErrorName(err
));
626 if (strncmp(save
, myptr
, ii
))
627 log_err("Saved substitution character failed\n");
629 log_verbose("Saved substitution character ok\n");
631 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
632 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
634 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
635 if(err
!= U_INDEX_OUTOFBOUNDS_ERROR
){
636 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err
));
640 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
641 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
642 ucnv_setSubstChars(myConverter
, myptr
, 0, &err
);
643 if(err
!= U_ILLEGAL_ARGUMENT_ERROR
){
644 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err
));
646 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
647 strcpy(myptr
, "abc");
648 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
650 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
651 if(strncmp(save
, myptr
, ii
) == 0){
652 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
654 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
656 strcpy(myptr
, "abc");
657 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
658 err
=U_ILLEGAL_ARGUMENT_ERROR
;
659 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
660 if(strncmp(save
, myptr
, ii
) == 0){
661 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
666 #ifdef U_ENABLE_GENERIC_ISO_2022
667 /*resetState ucnv_reset()*/
668 log_verbose("\n---Testing ucnv_reset()..\n");
669 ucnv_reset(myConverter
);
672 const uint8_t in
[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
673 const char *source
=(const char *)in
, *limit
=(const char *)in
+sizeof(in
);
674 UConverter
*cnv
=ucnv_open("ISO_2022", &err
);
676 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err
));
678 c
=ucnv_getNextUChar(cnv
, &source
, limit
, &err
);
679 if((U_FAILURE(err
) || c
!= (UChar32
)0x0031)) {
680 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err
));
689 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
690 locale
=CodePagesLocale
[codepage_index
];
693 disnamelen
= ucnv_getDisplayName(myConverter
, locale
, displayname
, len
, &err
);
694 if(err
==U_BUFFER_OVERFLOW_ERROR
) {
696 displayname
=(UChar
*)malloc((disnamelen
+1) * sizeof(UChar
));
697 ucnv_getDisplayName(myConverter
,locale
,displayname
,disnamelen
+1, &err
);
699 log_err("getDisplayName failed. The error is %s\n", myErrorName(err
));
702 log_verbose(" getDisplayName o.k.\n");
708 log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err
));
710 /*test ucnv_getDiaplayName with error condition*/
711 err
= U_ILLEGAL_ARGUMENT_ERROR
;
712 len
=ucnv_getDisplayName(myConverter
,locale
,NULL
,0, &err
);
714 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
716 /*test ucnv_getDiaplayName with error condition*/
718 len
=ucnv_getDisplayName(NULL
,locale
,NULL
,0, &err
);
719 if( len
!=0 || U_SUCCESS(err
)){
720 log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
724 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
725 ucnv_getFromUCallBack(myConverter
, &MIA1
, &MIA1Context
);
727 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
728 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
729 if (U_FAILURE(err
) || oldFromUAction
!= MIA1
|| oldFromUContext
!= MIA1Context
)
731 log_err("FAILURE! %s\n", myErrorName(err
));
734 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
735 if (MIA1_2
!= otherUnicodeAction(MIA1
) || MIA1Context2
!= &BOM
)
736 log_err("get From UCallBack failed\n");
738 log_verbose("get From UCallBack ok\n");
740 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
741 ucnv_setFromUCallBack(myConverter
,MIA1
, MIA1Context
, &oldFromUAction
, &oldFromUContext
, &err
);
742 if (U_FAILURE(err
) || oldFromUAction
!= otherUnicodeAction(MIA1
) || oldFromUContext
!= &BOM
)
744 log_err("FAILURE! %s\n", myErrorName(err
));
747 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
748 if (MIA1_2
!= MIA1
|| MIA1Context2
!= MIA1Context
)
749 log_err("get From UCallBack action failed\n");
751 log_verbose("get From UCallBack action ok\n");
753 /*testing ucnv_setToUCallBack with error conditions*/
754 err
=U_ILLEGAL_ARGUMENT_ERROR
;
755 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
756 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
757 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
758 if(MIA1_2
== otherUnicodeAction(MIA1
) || MIA1Context2
== &BOM
){
759 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
764 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
765 ucnv_getToUCallBack(myConverter
, &MIA2
, &MIA2Context
);
767 log_verbose("\n---Testing setTo UCallBack...\n");
768 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), &BOM
, &oldToUAction
, &oldToUContext
, &err
);
769 if (U_FAILURE(err
) || oldToUAction
!= MIA2
|| oldToUContext
!= MIA2Context
)
771 log_err("FAILURE! %s\n", myErrorName(err
));
774 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
775 if (MIA2_2
!= otherCharAction(MIA2
) || MIA2Context2
!= &BOM
)
776 log_err("To UCallBack failed\n");
778 log_verbose("To UCallBack ok\n");
780 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
781 ucnv_setToUCallBack(myConverter
,MIA2
, MIA2Context
, &oldToUAction
, &oldToUContext
, &err
);
782 if (U_FAILURE(err
) || oldToUAction
!= otherCharAction(MIA2
) || oldToUContext
!= &BOM
)
783 { log_err("FAILURE! %s\n", myErrorName(err
)); }
785 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
786 if (MIA2_2
!= MIA2
|| MIA2Context2
!= MIA2Context
)
787 log_err("To UCallBack failed\n");
789 log_verbose("To UCallBack ok\n");
791 /*testing ucnv_setToUCallBack with error conditions*/
792 err
=U_ILLEGAL_ARGUMENT_ERROR
;
793 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
794 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), NULL
, &oldToUAction
, &oldToUContext
, &err
);
795 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
796 if (MIA2_2
== otherCharAction(MIA2
) || MIA2Context2
== &BOM
){
797 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
802 /*getcodepageid testing ucnv_getCCSID() */
803 log_verbose("\n----Testing getCCSID....\n");
804 cp
= ucnv_getCCSID(myConverter
,&err
);
807 log_err("FAILURE!..... %s\n", myErrorName(err
));
809 if (cp
!= CodePageNumberToTest
[codepage_index
])
810 log_err("Codepage number test failed\n");
812 log_verbose("Codepage number test OK\n");
814 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
815 err
=U_ILLEGAL_ARGUMENT_ERROR
;
816 if( ucnv_getCCSID(myConverter
,&err
) != -1){
817 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
821 /*getCodepagePlatform testing ucnv_getPlatform()*/
822 log_verbose("\n---Testing getCodepagePlatform ..\n");
823 if (CodePagesPlatform
[codepage_index
]!=ucnv_getPlatform(myConverter
, &err
))
824 log_err("Platform codepage test failed\n");
826 log_verbose("Platform codepage test ok\n");
830 log_err("FAILURE! %s\n", myErrorName(err
));
832 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
833 err
= U_ILLEGAL_ARGUMENT_ERROR
;
834 if(ucnv_getPlatform(myConverter
, &err
) != UCNV_UNKNOWN
){
835 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
842 // Note: gcc produces a compile warning if the return value from fread() is ignored.
843 size_t numRead
= fread(&BOM
, sizeof(UChar
), 1, ucs_file_in
);
846 if (BOM
!=0xFEFF && BOM
!=0xFFFE)
848 log_err("File Missing BOM...Bailing!\n");
854 /*Reads in the file*/
855 while(!feof(ucs_file_in
)&&(i
+=fread(ucs_file_buffer
+i
, sizeof(UChar
), 1, ucs_file_in
)))
857 myUChar
= ucs_file_buffer
[i
-1];
859 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN*/
862 myUChar
= ucs_file_buffer
[i
-1];
863 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN Corner Case*/
866 /*testing ucnv_fromUChars() and ucnv_toUChars() */
867 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
869 uchar1
=(UChar
*)malloc(sizeof(UChar
) * (i
+1));
870 u_uastrcpy(uchar1
,"");
871 u_strncpy(uchar1
,ucs_file_buffer
,i
);
874 uchar3
=(UChar
*)malloc(sizeof(UChar
)*(i
+1));
875 u_uastrcpy(uchar3
,"");
876 u_strncpy(uchar3
,ucs_file_buffer
,i
);
879 /*Calls the Conversion Routine */
880 testLong1
= MAX_FILE_LEN
;
881 log_verbose("\n---Testing ucnv_fromUChars()\n");
882 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
885 log_err("\nFAILURE...%s\n", myErrorName(err
));
888 log_verbose(" ucnv_fromUChars() o.k.\n");
890 /*test the conversion routine */
891 log_verbose("\n---Testing ucnv_toUChars()\n");
892 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
894 targetsize
= ucnv_toUChars(myConverter
,
898 strlen(output_cp_buffer
),
900 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
902 if(err
==U_BUFFER_OVERFLOW_ERROR
)
905 uchar2
=(UChar
*)malloc((targetsize
+1) * sizeof(UChar
));
906 targetsize
= ucnv_toUChars(myConverter
,
910 strlen(output_cp_buffer
),
914 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err
));
916 log_verbose(" ucnv_toUChars() o.k.\n");
918 if(u_strcmp(uchar1
,uchar2
)!=0)
919 log_err("equality test failed with conversion routine\n");
923 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
925 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
926 err
=U_ILLEGAL_ARGUMENT_ERROR
;
927 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
928 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
929 if (targetcapacity
!=0) {
930 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
933 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
934 targetcapacity
= ucnv_fromUChars(NULL
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
935 if (targetcapacity
!=0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
936 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
939 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
940 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, 0, &err
);
941 if (targetcapacity
!=0) {
942 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
944 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
945 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, 0, uchar1
, -1, &err
);
946 if (err
!= U_BUFFER_OVERFLOW_ERROR
) {
947 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
949 /*toUChars with error conditions*/
950 targetsize
= ucnv_toUChars(myConverter
, uchar2
, targetsize
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
952 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
955 targetsize
= ucnv_toUChars(myConverter
, uchar2
, -1, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
956 if(targetsize
!= 0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
){
957 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
960 targetsize
= ucnv_toUChars(myConverter
, uchar2
, 0, output_cp_buffer
, 0, &err
);
961 if (targetsize
!=0) {
962 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
965 targetsize
= ucnv_toUChars(myConverter
, NULL
, targetcapacity2
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
966 if (err
!= U_STRING_NOT_TERMINATED_WARNING
) {
967 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
974 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
975 /*Clean up re-usable vars*/
976 log_verbose("Testing ucnv_fromUnicode().....\n");
977 tmp_ucs_buf
=ucs_file_buffer_use
;
978 ucnv_fromUnicode(myConverter
, &mytarget_1
,
979 mytarget
+ MAX_FILE_LEN
,
981 ucs_file_buffer_use
+i
,
985 consumedUni
= (UChar
*)tmp_consumedUni
;
986 (void)consumedUni
; /* Suppress set but not used warning. */
990 log_err("FAILURE! %s\n", myErrorName(err
));
993 log_verbose("ucnv_fromUnicode() o.k.\n");
995 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
996 log_verbose("Testing ucnv_toUnicode().....\n");
997 tmp_mytarget_use
=mytarget_use
;
998 tmp_consumed
= consumed
;
999 ucnv_toUnicode(myConverter
, &my_ucs_file_buffer_1
,
1000 my_ucs_file_buffer
+ MAX_FILE_LEN
,
1002 mytarget_use
+ (mytarget_1
- mytarget
),
1006 consumed
= (char*)tmp_consumed
;
1009 log_err("FAILURE! %s\n", myErrorName(err
));
1012 log_verbose("ucnv_toUnicode() o.k.\n");
1015 log_verbose("\n---Testing RoundTrip ...\n");
1018 u_strncpy(uchar3
, my_ucs_file_buffer
,i
);
1021 if(u_strcmp(uchar1
,uchar3
)==0)
1022 log_verbose("Equality test o.k.\n");
1024 log_err("Equality test failed\n");
1029 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__
);
1033 if(u_strcmp(uchar2
, uchar3
)==0)
1034 log_verbose("Equality test o.k.\n");
1036 log_err("Equality test failed\n");
1039 fclose(ucs_file_in
);
1040 ucnv_close(myConverter
);
1041 if (uchar1
!= 0) free(uchar1
);
1042 if (uchar2
!= 0) free(uchar2
);
1043 if (uchar3
!= 0) free(uchar3
);
1046 free((void*)mytarget
);
1047 free((void*)output_cp_buffer
);
1048 free((void*)ucs_file_buffer
);
1049 free((void*)my_ucs_file_buffer
);
1053 #if !UCONFIG_NO_LEGACY_CONVERSION
1054 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
)
1056 return (MIA
==(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
)?(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_SUBSTITUTE
:(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
;
1059 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
)
1061 return (MIA
==(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
)?(UConverterToUCallback
)UCNV_TO_U_CALLBACK_SUBSTITUTE
:(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
;
1065 static void TestFlushCache(void) {
1066 #if !UCONFIG_NO_LEGACY_CONVERSION
1067 UErrorCode err
= U_ZERO_ERROR
;
1068 UConverter
* someConverters
[5];
1071 /* flush the converter cache to get a consistent state before the flushing is tested */
1074 /*Testing ucnv_open()*/
1075 /* Note: These converters have been chosen because they do NOT
1076 encode the Latin characters (U+0041, ...), and therefore are
1077 highly unlikely to be chosen as system default codepages */
1079 someConverters
[0] = ucnv_open("ibm-1047", &err
);
1080 if (U_FAILURE(err
)) {
1081 log_data_err("FAILURE! %s\n", myErrorName(err
));
1084 someConverters
[1] = ucnv_open("ibm-1047", &err
);
1085 if (U_FAILURE(err
)) {
1086 log_data_err("FAILURE! %s\n", myErrorName(err
));
1089 someConverters
[2] = ucnv_open("ibm-1047", &err
);
1090 if (U_FAILURE(err
)) {
1091 log_data_err("FAILURE! %s\n", myErrorName(err
));
1094 someConverters
[3] = ucnv_open("gb18030", &err
);
1095 if (U_FAILURE(err
)) {
1096 log_data_err("FAILURE! %s\n", myErrorName(err
));
1099 someConverters
[4] = ucnv_open("ibm-954", &err
);
1100 if (U_FAILURE(err
)) {
1101 log_data_err("FAILURE! %s\n", myErrorName(err
));
1105 /* Testing ucnv_flushCache() */
1106 log_verbose("\n---Testing ucnv_flushCache...\n");
1107 if ((flushCount
=ucnv_flushCache())==0)
1108 log_verbose("Flush cache ok\n");
1110 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1112 /*testing ucnv_close() and ucnv_flushCache() */
1113 ucnv_close(someConverters
[0]);
1114 ucnv_close(someConverters
[1]);
1116 if ((flushCount
=ucnv_flushCache())==0)
1117 log_verbose("Flush cache ok\n");
1119 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1121 ucnv_close(someConverters
[2]);
1122 ucnv_close(someConverters
[3]);
1124 if ((flushCount
=ucnv_flushCache())==2)
1125 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1127 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1131 ucnv_close(someConverters
[4]);
1132 if ( (flushCount
=ucnv_flushCache())==1)
1133 log_verbose("Flush cache ok\n");
1135 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__
, flushCount
);
1140 * Test the converter alias API, specifically the fuzzy matching of
1141 * alias names and the alias table integrity. Make sure each
1142 * converter has at least one alias (itself), and that its listed
1143 * aliases map back to itself. Check some hard-coded UTF-8 and
1144 * ISO_2022 aliases to make sure they work.
1146 static void TestAlias() {
1148 UErrorCode status
= U_ZERO_ERROR
;
1150 /* Predetermined aliases that we expect to map back to ISO_2022
1151 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1152 const char* ISO_2022_NAMES
[] =
1153 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1154 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1155 int32_t ISO_2022_NAMES_LENGTH
= UPRV_LENGTHOF(ISO_2022_NAMES
);
1156 const char *UTF8_NAMES
[] =
1157 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1158 "utf_8", "ibm1208", "cp1208" };
1159 int32_t UTF8_NAMES_LENGTH
= UPRV_LENGTHOF(UTF8_NAMES
);
1164 } CONVERTERS_NAMES
[] = {
1165 { "UTF-32BE", "UTF32_BigEndian" },
1166 { "UTF-32LE", "UTF32_LittleEndian" },
1167 { "UTF-32", "ISO-10646-UCS-4" },
1168 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1169 { "UTF-32", "ucs-4" }
1171 int32_t CONVERTERS_NAMES_LENGTH
= UPRV_LENGTHOF(CONVERTERS_NAMES
);
1173 /* When there are bugs in gencnval or in ucnv_io, converters can
1174 appear to have no aliases. */
1175 ncnv
= ucnv_countAvailable();
1176 log_verbose("%d converters\n", ncnv
);
1177 for (i
=0; i
<ncnv
; ++i
) {
1178 const char *name
= ucnv_getAvailableName(i
);
1180 uint16_t na
= ucnv_countAliases(name
, &status
);
1185 log_err("FAIL: Converter \"%s\" (i=%d)"
1186 " has no aliases; expect at least one\n",
1190 cnv
= ucnv_open(name
, &status
);
1191 if (U_FAILURE(status
)) {
1192 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1193 " can't be opened.\n",
1197 if (strcmp(ucnv_getName(cnv
, &status
), name
) != 0
1198 && (strstr(name
, "PlatformEndian") == 0 && strstr(name
, "OppositeEndian") == 0)) {
1199 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1200 "They should be the same\n",
1201 name
, ucnv_getName(cnv
, &status
));
1206 status
= U_ZERO_ERROR
;
1207 alias0
= ucnv_getAlias(name
, 0, &status
);
1208 for (j
=1; j
<na
; ++j
) {
1210 /* Make sure each alias maps back to the the same list of
1211 aliases. Assume that if alias 0 is the same, the whole
1212 list is the same (this should always be true). */
1213 const char *mapBack
;
1215 status
= U_ZERO_ERROR
;
1216 alias
= ucnv_getAlias(name
, j
, &status
);
1217 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1218 log_err("FAIL: Converter \"%s\"is ambiguous\n", name
);
1221 if (alias
== NULL
) {
1222 log_err("FAIL: Converter \"%s\" -> "
1228 mapBack
= ucnv_getAlias(alias
, 0, &status
);
1230 if (mapBack
== NULL
) {
1231 log_err("FAIL: Converter \"%s\" -> "
1232 "alias[%d]=\"%s\" -> "
1233 "alias[0]=NULL, exp. \"%s\"\n",
1234 name
, j
, alias
, alias0
);
1238 if (0 != strcmp(alias0
, mapBack
)) {
1240 UBool foundAlias
= FALSE
;
1241 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1242 /* Make sure that we only get this mismapping when there is
1243 an ambiguous alias, and the other converter has this alias too. */
1244 for (idx
= 0; idx
< ucnv_countAliases(mapBack
, &status
); idx
++) {
1245 if (strcmp(ucnv_getAlias(mapBack
, (uint16_t)idx
, &status
), alias
) == 0) {
1251 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1254 log_err("FAIL: Converter \"%s\" -> "
1255 "alias[%d]=\"%s\" -> "
1256 "alias[0]=\"%s\", exp. \"%s\"\n",
1257 name
, j
, alias
, mapBack
, alias0
);
1264 /* Check a list of predetermined aliases that we expect to map
1265 * back to ISO_2022 and UTF-8. */
1266 for (i
=1; i
<ISO_2022_NAMES_LENGTH
; ++i
) {
1267 const char* mapBack
= ucnv_getAlias(ISO_2022_NAMES
[i
], 0, &status
);
1269 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES
[i
]);
1272 if (0 != strcmp(mapBack
, ISO_2022_NAMES
[0])) {
1273 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1274 ISO_2022_NAMES
[i
], mapBack
);
1279 for (i
=1; i
<UTF8_NAMES_LENGTH
; ++i
) {
1280 const char* mapBack
= ucnv_getAlias(UTF8_NAMES
[i
], 0, &status
);
1282 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES
[i
]);
1285 if (mapBack
&& 0 != strcmp(mapBack
, UTF8_NAMES
[0])) {
1286 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1287 UTF8_NAMES
[i
], mapBack
);
1292 * Check a list of predetermined aliases that we expect to map
1293 * back to predermined converter names.
1296 for (i
= 0; i
< CONVERTERS_NAMES_LENGTH
; ++i
) {
1297 const char* mapBack
= ucnv_getAlias(CONVERTERS_NAMES
[i
].alias
, 0, &status
);
1299 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES
[i
].name
);
1302 if (0 != strcmp(mapBack
, CONVERTERS_NAMES
[i
].name
)) {
1303 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1304 CONVERTERS_NAMES
[i
].alias
, mapBack
, CONVERTERS_NAMES
[i
].name
);
1310 static void TestDuplicateAlias(void) {
1312 UErrorCode status
= U_ZERO_ERROR
;
1314 status
= U_ZERO_ERROR
;
1315 alias
= ucnv_getStandardName("Shift_JIS", "IBM", &status
);
1316 if (alias
== NULL
|| strcmp(alias
, "ibm-943") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1317 log_data_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias
);
1319 status
= U_ZERO_ERROR
;
1320 alias
= ucnv_getStandardName("ibm-943", "IANA", &status
);
1321 if (alias
== NULL
|| strcmp(alias
, "Shift_JIS") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1322 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias
);
1324 status
= U_ZERO_ERROR
;
1325 alias
= ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status
);
1326 if (alias
!= NULL
|| status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1327 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias
);
1332 /* Test safe clone callback */
1334 static uint32_t TSCC_nextSerial()
1336 static uint32_t n
= 1;
1343 uint32_t magic
; /* 0xC0FFEE to identify that the object is OK */
1344 uint32_t serial
; /* minted from nextSerial, above */
1345 UBool wasClosed
; /* close happened on the object */
1348 static TSCCContext
*TSCC_clone(TSCCContext
*ctx
)
1350 TSCCContext
*newCtx
= (TSCCContext
*)malloc(sizeof(TSCCContext
));
1352 newCtx
->serial
= TSCC_nextSerial();
1353 newCtx
->wasClosed
= 0;
1354 newCtx
->magic
= 0xC0FFEE;
1356 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
1361 #if !UCONFIG_NO_LEGACY_CONVERSION
1362 static void TSCC_fromU(const void *context
,
1363 UConverterFromUnicodeArgs
*fromUArgs
,
1364 const UChar
* codeUnits
,
1367 UConverterCallbackReason reason
,
1370 TSCCContext
*ctx
= (TSCCContext
*)context
;
1371 UConverterFromUCallback junkFrom
;
1373 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
);
1375 if(ctx
->magic
!= 0xC0FFEE) {
1376 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1380 if(reason
== UCNV_CLONE
) {
1381 UErrorCode subErr
= U_ZERO_ERROR
;
1382 TSCCContext
*newCtx
;
1383 TSCCContext
*junkCtx
;
1384 TSCCContext
**pjunkCtx
= &junkCtx
;
1387 log_verbose("TSCC_fromU: cloning..\n");
1388 newCtx
= TSCC_clone(ctx
);
1390 if(newCtx
== NULL
) {
1391 log_err("TSCC_fromU: internal clone failed on %p\n", ctx
);
1395 ucnv_getFromUCallBack(fromUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1396 ucnv_setFromUCallBack(fromUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1398 if(U_FAILURE(subErr
)) {
1403 if(reason
== UCNV_CLOSE
) {
1404 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1405 ctx
->wasClosed
= TRUE
;
1409 static void TSCC_toU(const void *context
,
1410 UConverterToUnicodeArgs
*toUArgs
,
1411 const char* codeUnits
,
1413 UConverterCallbackReason reason
,
1416 TSCCContext
*ctx
= (TSCCContext
*)context
;
1417 UConverterToUCallback junkFrom
;
1419 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, toUArgs
->converter
);
1421 if(ctx
->magic
!= 0xC0FFEE) {
1422 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1426 if(reason
== UCNV_CLONE
) {
1427 UErrorCode subErr
= U_ZERO_ERROR
;
1428 TSCCContext
*newCtx
;
1429 TSCCContext
*junkCtx
;
1430 TSCCContext
**pjunkCtx
= &junkCtx
;
1433 log_verbose("TSCC_toU: cloning..\n");
1434 newCtx
= TSCC_clone(ctx
);
1436 if(newCtx
== NULL
) {
1437 log_err("TSCC_toU: internal clone failed on %p\n", ctx
);
1441 ucnv_getToUCallBack(toUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1442 ucnv_setToUCallBack(toUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1444 if(U_FAILURE(subErr
)) {
1449 if(reason
== UCNV_CLOSE
) {
1450 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1451 ctx
->wasClosed
= TRUE
;
1455 static void TSCC_init(TSCCContext
*q
)
1457 q
->magic
= 0xC0FFEE;
1458 q
->serial
= TSCC_nextSerial();
1462 static void TSCC_print_log(TSCCContext
*q
, const char *name
)
1465 log_verbose("TSCContext: %s is NULL!!\n", name
);
1467 if(q
->magic
!= 0xC0FFEE) {
1468 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1469 q
,q
->serial
, q
->magic
);
1471 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1472 q
, q
->serial
, name
, q
->magic
, q
->wasClosed
?"CLOSED":"open");
1476 static void TestConvertSafeCloneCallback()
1478 UErrorCode err
= U_ZERO_ERROR
;
1479 TSCCContext from1
, to1
;
1480 TSCCContext
*from2
, *from3
, *to2
, *to3
;
1481 TSCCContext
**pfrom2
= &from2
, **pfrom3
= &from3
, **pto2
= &to2
, **pto3
= &to3
;
1483 int32_t hunkSize
= 8192;
1484 UConverterFromUCallback junkFrom
;
1485 UConverterToUCallback junkTo
;
1486 UConverter
*conv1
, *conv2
= NULL
;
1488 conv1
= ucnv_open("iso-8859-3", &err
);
1490 if(U_FAILURE(err
)) {
1491 log_data_err("Err opening iso-8859-3, %s\n", u_errorName(err
));
1495 log_verbose("Opened conv1=%p\n", conv1
);
1500 TSCC_print_log(&from1
, "from1");
1501 TSCC_print_log(&to1
, "to1");
1503 ucnv_setFromUCallBack(conv1
, TSCC_fromU
, &from1
, NULL
, NULL
, &err
);
1504 log_verbose("Set from1 on conv1\n");
1505 TSCC_print_log(&from1
, "from1");
1507 ucnv_setToUCallBack(conv1
, TSCC_toU
, &to1
, NULL
, NULL
, &err
);
1508 log_verbose("Set to1 on conv1\n");
1509 TSCC_print_log(&to1
, "to1");
1511 conv2
= ucnv_safeClone(conv1
, hunk
, &hunkSize
, &err
);
1512 if(U_FAILURE(err
)) {
1513 log_err("safeClone failed: %s\n", u_errorName(err
));
1516 log_verbose("Cloned to conv2=%p.\n", conv2
);
1518 /********** from *********************/
1519 ucnv_getFromUCallBack(conv2
, &junkFrom
, (const void**)pfrom2
);
1520 ucnv_getFromUCallBack(conv1
, &junkFrom
, (const void**)pfrom3
);
1522 TSCC_print_log(from2
, "from2");
1523 TSCC_print_log(from3
, "from3(==from1)");
1526 log_err("FAIL! from2 is null \n");
1531 log_err("FAIL! from3 is null \n");
1535 if(from3
!= (&from1
) ) {
1536 log_err("FAIL! conv1's FROM context changed!\n");
1539 if(from2
== (&from1
) ) {
1540 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1543 if(from1
.wasClosed
) {
1544 log_err("FAIL! from1 is closed \n");
1547 if(from2
->wasClosed
) {
1548 log_err("FAIL! from2 was closed\n");
1551 /********** to *********************/
1552 ucnv_getToUCallBack(conv2
, &junkTo
, (const void**)pto2
);
1553 ucnv_getToUCallBack(conv1
, &junkTo
, (const void**)pto3
);
1555 TSCC_print_log(to2
, "to2");
1556 TSCC_print_log(to3
, "to3(==to1)");
1559 log_err("FAIL! to2 is null \n");
1564 log_err("FAIL! to3 is null \n");
1568 if(to3
!= (&to1
) ) {
1569 log_err("FAIL! conv1's TO context changed!\n");
1572 if(to2
== (&to1
) ) {
1573 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1577 log_err("FAIL! to1 is closed \n");
1580 if(to2
->wasClosed
) {
1581 log_err("FAIL! to2 was closed\n");
1584 /*************************************/
1587 log_verbose("ucnv_closed (conv1)\n");
1588 TSCC_print_log(&from1
, "from1");
1589 TSCC_print_log(from2
, "from2");
1590 TSCC_print_log(&to1
, "to1");
1591 TSCC_print_log(to2
, "to2");
1593 if(from1
.wasClosed
== FALSE
) {
1594 log_err("FAIL! from1 is NOT closed \n");
1597 if(from2
->wasClosed
) {
1598 log_err("FAIL! from2 was closed\n");
1601 if(to1
.wasClosed
== FALSE
) {
1602 log_err("FAIL! to1 is NOT closed \n");
1605 if(to2
->wasClosed
) {
1606 log_err("FAIL! to2 was closed\n");
1610 log_verbose("ucnv_closed (conv2)\n");
1612 TSCC_print_log(&from1
, "from1");
1613 TSCC_print_log(from2
, "from2");
1615 if(from1
.wasClosed
== FALSE
) {
1616 log_err("FAIL! from1 is NOT closed \n");
1619 if(from2
->wasClosed
== FALSE
) {
1620 log_err("FAIL! from2 was NOT closed\n");
1623 TSCC_print_log(&to1
, "to1");
1624 TSCC_print_log(to2
, "to2");
1626 if(to1
.wasClosed
== FALSE
) {
1627 log_err("FAIL! to1 is NOT closed \n");
1630 if(to2
->wasClosed
== FALSE
) {
1631 log_err("FAIL! to2 was NOT closed\n");
1635 free(to2
); /* to1 is stack based */
1637 if(from2
!= (&from1
)) {
1638 free(from2
); /* from1 is stack based */
1644 containsAnyOtherByte(uint8_t *p
, int32_t length
, uint8_t b
) {
1655 static void TestConvertSafeClone()
1657 /* one 'regular' & all the 'private stateful' converters */
1658 static const char *const names
[] = {
1659 #if !UCONFIG_NO_LEGACY_CONVERSION
1661 "ISO_2022,locale=zh,version=1",
1664 #if !UCONFIG_NO_LEGACY_CONVERSION
1668 "ISO_2022,locale=kr,version=1",
1669 "ISO_2022,locale=jp,version=2",
1673 #if !UCONFIG_NO_LEGACY_CONVERSION
1674 "IMAP-mailbox-name",
1681 /* store the actual sizes of each converter */
1682 int32_t actualSizes
[UPRV_LENGTHOF(names
)];
1684 static const int32_t bufferSizes
[] = {
1685 U_CNV_SAFECLONE_BUFFERSIZE
,
1686 (int32_t)(3*sizeof(UConverter
))/2, /* 1.5*sizeof(UConverter) */
1687 (int32_t)sizeof(UConverter
)/2 /* 0.5*sizeof(UConverter) */
1690 char charBuffer
[21]; /* Leave at an odd number for alignment testing */
1691 uint8_t buffer
[3] [U_CNV_SAFECLONE_BUFFERSIZE
];
1692 int32_t bufferSize
, maxBufferSize
;
1693 const char *maxName
;
1694 UConverter
* cnv
, *cnv2
;
1698 const char *pConstCharBuffer
;
1699 const char *charBufferLimit
= charBuffer
+ UPRV_LENGTHOF(charBuffer
);
1700 UChar uniBuffer
[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1701 UChar uniCharBuffer
[20];
1702 char charSourceBuffer
[] = { 0x1b, 0x24, 0x42 };
1703 const char *pCharSource
= charSourceBuffer
;
1704 const char *pCharSourceLimit
= charSourceBuffer
+ sizeof(charSourceBuffer
);
1705 UChar
*pUCharTarget
= uniCharBuffer
;
1706 UChar
*pUCharTargetLimit
= uniCharBuffer
+ UPRV_LENGTHOF(uniCharBuffer
);
1707 const UChar
* pUniBuffer
;
1708 const UChar
*uniBufferLimit
= uniBuffer
+ UPRV_LENGTHOF(uniBuffer
);
1712 cnv
= ucnv_open(names
[0], &err
);
1713 if(U_SUCCESS(err
)) {
1714 /* Check the various error & informational states: */
1716 /* Null status - just returns NULL */
1717 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1718 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, NULL
))
1720 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1722 /* error status - should return 0 & keep error the same */
1723 err
= U_MEMORY_ALLOCATION_ERROR
;
1724 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || err
!= U_MEMORY_ALLOCATION_ERROR
)
1726 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1730 /* Null buffer size pointer is ok */
1731 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, buffer
[0], NULL
, &err
)) || U_FAILURE(err
))
1733 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1738 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1740 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || U_FAILURE(err
) || bufferSize
<= 0)
1742 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1744 /* Verify our define is large enough */
1745 if (U_CNV_SAFECLONE_BUFFERSIZE
< bufferSize
)
1747 log_err("FAIL: Pre-calculated buffer size is too small\n");
1749 /* Verify we can use this run-time calculated size */
1750 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
)) || U_FAILURE(err
))
1752 log_err("FAIL: Converter can't be cloned with run-time size\n");
1758 /* size one byte too small - should allocate & let us know */
1760 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, NULL
, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1762 log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1769 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1771 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1772 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, NULL
, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1774 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1782 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1783 if (NULL
!= ucnv_safeClone(NULL
, buffer
[0], &bufferSize
, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1785 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1794 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1796 for(j
= 0; j
< UPRV_LENGTHOF(bufferSizes
); ++j
) {
1797 for (idx
= 0; idx
< UPRV_LENGTHOF(names
); idx
++)
1800 cnv
= ucnv_open(names
[idx
], &err
);
1801 if(U_FAILURE(err
)) {
1802 log_data_err("ucnv_open(\"%s\") failed - %s\n", names
[idx
], u_errorName(err
));
1807 /* preflight to get maxBufferSize */
1808 actualSizes
[idx
] = 0;
1809 ucnv_safeClone(cnv
, NULL
, &actualSizes
[idx
], &err
);
1810 if(actualSizes
[idx
] > maxBufferSize
) {
1811 maxBufferSize
= actualSizes
[idx
];
1812 maxName
= names
[idx
];
1816 memset(buffer
, 0xaa, sizeof(buffer
));
1818 bufferSize
= bufferSizes
[j
];
1819 cnv2
= ucnv_safeClone(cnv
, buffer
[1], &bufferSize
, &err
);
1821 /* close the original immediately to make sure that the clone works by itself */
1824 if( actualSizes
[idx
] <= (bufferSizes
[j
] - (int32_t)sizeof(UAlignedMemory
)) &&
1825 err
== U_SAFECLONE_ALLOCATED_WARNING
1827 log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names
[idx
]);
1830 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1831 if(bufferSize
<= bufferSizes
[j
]) {
1832 /* used the stack buffer */
1833 if( containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
[0]), 0xaa) ||
1834 containsAnyOtherByte(buffer
[1]+bufferSize
, (int32_t)(sizeof(buffer
)-(sizeof(buffer
[0])+bufferSize
)), 0xaa)
1836 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1837 names
[idx
], bufferSize
, bufferSizes
[j
]);
1840 /* heap-allocated the clone */
1841 if(containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
), 0xaa)) {
1842 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1843 names
[idx
], bufferSize
, bufferSizes
[j
]);
1847 pCharBuffer
= charBuffer
;
1848 pUniBuffer
= uniBuffer
;
1850 ucnv_fromUnicode(cnv2
,
1859 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err
));
1861 ucnv_toUnicode(cnv2
,
1872 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err
));
1875 pConstCharBuffer
= charBuffer
;
1876 if (uniBuffer
[0] != ucnv_getNextUChar(cnv2
, &pConstCharBuffer
, pCharBuffer
, &err
))
1878 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err
));
1884 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1885 sizeof(UConverter
), maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1886 if(maxBufferSize
> U_CNV_SAFECLONE_BUFFERSIZE
) {
1887 log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1888 maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1892 static void TestCCSID() {
1893 #if !UCONFIG_NO_LEGACY_CONVERSION
1895 UErrorCode errorCode
;
1896 int32_t ccsids
[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1899 for(i
=0; i
<UPRV_LENGTHOF(ccsids
); ++i
) {
1902 errorCode
=U_ZERO_ERROR
;
1903 cnv
=ucnv_openCCSID(ccsid
, UCNV_IBM
, &errorCode
);
1904 if(U_FAILURE(errorCode
)) {
1905 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid
, u_errorName(errorCode
));
1909 if(ccsid
!=ucnv_getCCSID(cnv
, &errorCode
)) {
1910 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid
, ucnv_getCCSID(cnv
, &errorCode
));
1913 /* skip gb18030(ccsid 1392) */
1914 if(ccsid
!= 1392 && UCNV_IBM
!=ucnv_getPlatform(cnv
, &errorCode
)) {
1915 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid
, ucnv_getPlatform(cnv
, &errorCode
));
1923 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1925 /* CHUNK_SIZE defined in common\ucnv.c: */
1926 #define CHUNK_SIZE 1024
1928 static void bug1(void);
1929 static void bug2(void);
1930 static void bug3(void);
1935 bug1(); /* Unicode intermediate buffer straddle bug */
1936 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1937 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1941 * jitterbug 932: test chunking boundary conditions in
1943 int32_t ucnv_convert(const char *toConverterName,
1944 const char *fromConverterName,
1951 * See discussions on the icu mailing list in
1952 * 2001-April with the subject "converter 'flush' question".
1954 * Bug report and test code provided by Edward J. Batutis.
1958 #if !UCONFIG_NO_LEGACY_CONVERSION
1959 char char_in
[CHUNK_SIZE
+32];
1960 char char_out
[CHUNK_SIZE
*2];
1962 /* GB 18030 equivalent of U+10000 is 90308130 */
1963 static const char test_seq
[]={ (char)0x90u
, 0x30, (char)0x81u
, 0x30 };
1965 UErrorCode err
= U_ZERO_ERROR
;
1966 int32_t i
, test_seq_len
= sizeof(test_seq
);
1969 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1970 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1971 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1972 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1973 * other Unicode sequences cause a bug since combining sequences are not supported by the
1977 for (i
= test_seq_len
; i
>= 0; i
--) {
1978 /* put character sequence into input buffer */
1979 memset(char_in
, 0x61, sizeof(char_in
)); /* GB 18030 'a' */
1980 memcpy(char_in
+ (CHUNK_SIZE
- i
), test_seq
, test_seq_len
);
1982 /* do the conversion */
1983 ucnv_convert("us-ascii", /* out */
1992 if (err
== U_TRUNCATED_CHAR_FOUND
) {
1993 /* this happens when surrogate pair straddles the intermediate buffer in
1994 * T_UConverter_fromCodepageToCodepage */
1995 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
2001 /* bug2: pre-flighting loop bug: simple overflow causes bug */
2004 /* US-ASCII "1234567890" */
2005 static const char source
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
2006 #if !UCONFIG_ONLY_HTML_CONVERSION
2007 static const char sourceUTF8
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
2008 static const char sourceUTF32
[]={ 0x00, 0x00, 0x00, 0x30,
2009 0x00, 0x00, 0x00, 0x31,
2010 0x00, 0x00, 0x00, 0x32,
2011 0x00, 0x00, 0x00, 0x33,
2012 0x00, 0x00, 0x00, 0x34,
2013 0x00, 0x00, 0x00, 0x35,
2014 0x00, 0x00, 0x00, 0x36,
2015 0x00, 0x00, 0x00, 0x37,
2016 0x00, 0x00, 0x00, 0x38,
2017 0x00, 0x00, (char)0xf0, 0x00};
2020 static char target
[5];
2022 UErrorCode err
= U_ZERO_ERROR
;
2025 /* do the conversion */
2026 size
= ucnv_convert("iso-8859-1", /* out */
2027 "us-ascii", /* in */
2035 /* bug2: size is 5, should be 10 */
2036 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size
);
2039 #if !UCONFIG_ONLY_HTML_CONVERSION
2041 /* do the conversion */
2042 size
= ucnv_convert("UTF-32BE", /* out */
2051 /* bug2: size is 5, should be 32 */
2052 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size
);
2056 /* do the conversion */
2057 size
= ucnv_convert("UTF-8", /* out */
2058 "UTF-32BE", /* in */
2062 sizeof(sourceUTF32
),
2066 /* bug2: size is 5, should be 12 */
2067 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size
);
2073 * bug3: when the characters expand going from source to target codepage
2074 * you get bug3 in addition to bug2
2078 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
2079 char char_in
[CHUNK_SIZE
*4];
2081 UErrorCode err
= U_ZERO_ERROR
;
2085 * first get the buggy size from bug2 then
2086 * compare it to buggy size with an expansion
2088 memset(char_in
, 0x61, sizeof(char_in
)); /* US-ASCII 'a' */
2090 /* do the conversion */
2091 size
= ucnv_convert("lmbcs", /* out */
2092 "us-ascii", /* in */
2099 if ( size
!= sizeof(char_in
) ) {
2101 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2102 * in the converter?), should be CHUNK_SIZE*4
2104 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2106 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in
), size
);
2110 * now do the conversion with expansion
2111 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2113 memset(char_in
, 8, sizeof(char_in
));
2116 /* do the conversion */
2117 size
= ucnv_convert("lmbcs", /* out */
2118 "us-ascii", /* in */
2125 /* expect 2X expansion */
2126 if ( size
!= sizeof(char_in
) * 2 ) {
2129 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2131 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in
) * 2, size
);
2137 convertExStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2138 const char *src
, int32_t srcLength
,
2139 const char *expectTarget
, int32_t expectTargetLength
,
2141 const char *testName
,
2142 UErrorCode expectCode
) {
2143 UChar pivotBuffer
[CHUNK_SIZE
];
2144 UChar
*pivotSource
, *pivotTarget
;
2145 const UChar
*pivotLimit
;
2147 char targetBuffer
[CHUNK_SIZE
];
2149 const char *srcLimit
, *finalSrcLimit
, *targetLimit
;
2151 int32_t targetLength
;
2155 UErrorCode errorCode
;
2158 if(chunkSize
>CHUNK_SIZE
) {
2159 chunkSize
=CHUNK_SIZE
;
2162 pivotSource
=pivotTarget
=pivotBuffer
;
2163 pivotLimit
=pivotBuffer
+chunkSize
;
2165 finalSrcLimit
=src
+srcLength
;
2166 target
=targetBuffer
;
2167 targetLimit
=targetBuffer
+chunkSize
;
2169 ucnv_resetToUnicode(srcCnv
);
2170 ucnv_resetFromUnicode(targetCnv
);
2172 errorCode
=U_ZERO_ERROR
;
2175 /* convert, streaming-style (both converters and pivot keep state) */
2177 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2178 if(src
+chunkSize
<=finalSrcLimit
) {
2179 srcLimit
=src
+chunkSize
;
2181 srcLimit
=finalSrcLimit
;
2183 ucnv_convertEx(targetCnv
, srcCnv
,
2184 &target
, targetLimit
,
2186 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotLimit
,
2187 FALSE
, flush
, &errorCode
);
2188 targetLength
=(int32_t)(target
-targetBuffer
);
2189 if(target
>targetLimit
) {
2190 log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
2191 testName
, chunkSize
, target
, targetLimit
);
2192 break; /* TODO: major problem! */
2194 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
2195 /* continue converting another chunk */
2196 errorCode
=U_ZERO_ERROR
;
2197 if(targetLength
+chunkSize
<=sizeof(targetBuffer
)) {
2198 targetLimit
=target
+chunkSize
;
2200 targetLimit
=targetBuffer
+sizeof(targetBuffer
);
2202 } else if(U_FAILURE(errorCode
)) {
2208 } else if(src
==finalSrcLimit
&& pivotSource
==pivotTarget
) {
2209 /* all consumed, now flush without input (separate from conversion for testing) */
2214 if(!(errorCode
==expectCode
|| (expectCode
==U_ZERO_ERROR
&& errorCode
==U_STRING_NOT_TERMINATED_WARNING
))) {
2215 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2216 testName
, chunkSize
, u_errorName(errorCode
), u_errorName(expectCode
));
2217 } else if(targetLength
!=expectTargetLength
) {
2218 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2219 testName
, chunkSize
, targetLength
, expectTargetLength
);
2220 } else if(memcmp(targetBuffer
, expectTarget
, targetLength
)!=0) {
2221 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2222 testName
, chunkSize
);
2227 convertExMultiStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2228 const char *src
, int32_t srcLength
,
2229 const char *expectTarget
, int32_t expectTargetLength
,
2230 const char *testName
,
2231 UErrorCode expectCode
) {
2232 convertExStreaming(srcCnv
, targetCnv
,
2234 expectTarget
, expectTargetLength
,
2235 1, testName
, expectCode
);
2236 convertExStreaming(srcCnv
, targetCnv
,
2238 expectTarget
, expectTargetLength
,
2239 3, testName
, expectCode
);
2240 convertExStreaming(srcCnv
, targetCnv
,
2242 expectTarget
, expectTargetLength
,
2243 7, testName
, expectCode
);
2246 static void TestConvertEx() {
2247 #if !UCONFIG_NO_LEGACY_CONVERSION
2248 static const uint8_t
2250 /* 4e00 30a1 ff61 0410 */
2251 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2254 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2258 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2259 * SUB, SUB, 0x40, SUB, SUB, 0x40
2261 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2264 char srcBuffer
[100], targetBuffer
[100];
2269 UChar pivotBuffer
[100];
2270 UChar
*pivotSource
, *pivotTarget
;
2272 UConverter
*cnv1
, *cnv2
;
2273 UErrorCode errorCode
;
2275 errorCode
=U_ZERO_ERROR
;
2276 cnv1
=ucnv_open("UTF-8", &errorCode
);
2277 if(U_FAILURE(errorCode
)) {
2278 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode
));
2282 cnv2
=ucnv_open("Shift-JIS", &errorCode
);
2283 if(U_FAILURE(errorCode
)) {
2284 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2289 /* test ucnv_convertEx() with streaming conversion style */
2290 convertExMultiStreaming(cnv1
, cnv2
,
2291 (const char *)utf8
, sizeof(utf8
), (const char *)shiftJIS
, sizeof(shiftJIS
),
2292 "UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2294 convertExMultiStreaming(cnv2
, cnv1
,
2295 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
),
2296 "Shift-JIS -> UTF-8", U_ZERO_ERROR
);
2298 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2299 convertExMultiStreaming(cnv1
, cnv2
,
2300 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)errorTarget
, sizeof(errorTarget
),
2301 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2303 /* test some simple conversions */
2305 /* NUL-terminated source and target */
2306 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2307 memcpy(srcBuffer
, utf8
, sizeof(utf8
));
2308 srcBuffer
[sizeof(utf8
)]=0;
2310 target
=targetBuffer
;
2311 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2312 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2313 if( errorCode
!=U_ZERO_ERROR
||
2314 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2316 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2318 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2319 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2322 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2323 errorCode
=U_AMBIGUOUS_ALIAS_WARNING
;
2324 memset(targetBuffer
, 0xff, sizeof(targetBuffer
));
2326 target
=targetBuffer
;
2327 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(shiftJIS
), &src
, NULL
,
2328 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2329 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2330 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2331 *target
!=(char)0xff ||
2332 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2334 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2335 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2339 errorCode
=U_MESSAGE_PARSE_ERROR
;
2341 target
=targetBuffer
;
2342 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2343 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2344 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2345 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2348 /* pivotLimit==pivotStart */
2349 errorCode
=U_ZERO_ERROR
;
2350 pivotSource
=pivotTarget
=pivotBuffer
;
2351 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2352 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
, TRUE
, TRUE
, &errorCode
);
2353 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2354 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode
));
2357 /* *pivotSource==NULL */
2358 errorCode
=U_ZERO_ERROR
;
2360 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2361 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2362 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2363 log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode
));
2367 errorCode
=U_ZERO_ERROR
;
2369 pivotSource
=pivotBuffer
;
2370 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2371 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2372 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2373 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode
));
2376 /* streaming conversion without a pivot buffer */
2377 errorCode
=U_ZERO_ERROR
;
2379 pivotSource
=pivotBuffer
;
2380 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2381 NULL
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, FALSE
, &errorCode
);
2382 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2383 log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode
));
2391 /* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
2392 static const char *const badUTF8
[]={
2396 /* truncated multi-byte sequences */
2433 "\xfc\x80\x80\x80\x80",
2435 /* complete sequences but non-shortest forms or out of range etc. */
2441 "\xf8\x80\x80\x80\x80",
2442 "\xfc\x80\x80\x80\x80\x80",
2447 #define ARG_CHAR_ARR_SIZE 8
2449 /* get some character that can be converted and convert it */
2450 static UBool
getTestChar(UConverter
*cnv
, const char *converterName
,
2451 char charUTF8
[4], int32_t *pCharUTF8Length
,
2452 char char0
[ARG_CHAR_ARR_SIZE
], int32_t *pChar0Length
,
2453 char char1
[ARG_CHAR_ARR_SIZE
], int32_t *pChar1Length
) {
2454 UChar utf16
[U16_MAX_LENGTH
];
2455 int32_t utf16Length
;
2457 const UChar
*utf16Source
;
2462 UErrorCode errorCode
;
2464 errorCode
=U_ZERO_ERROR
;
2465 set
=uset_open(1, 0);
2466 ucnv_getUnicodeSet(cnv
, set
, UCNV_ROUNDTRIP_SET
, &errorCode
);
2467 c
=uset_charAt(set
, uset_size(set
)/2);
2471 U16_APPEND_UNSAFE(utf16
, utf16Length
, c
);
2473 U8_APPEND_UNSAFE(charUTF8
, *pCharUTF8Length
, c
);
2477 ucnv_fromUnicode(cnv
,
2478 &target
, char0
+ARG_CHAR_ARR_SIZE
,
2479 &utf16Source
, utf16
+utf16Length
,
2480 NULL
, FALSE
, &errorCode
);
2481 *pChar0Length
=(int32_t)(target
-char0
);
2485 ucnv_fromUnicode(cnv
,
2486 &target
, char1
+ARG_CHAR_ARR_SIZE
,
2487 &utf16Source
, utf16
+utf16Length
,
2488 NULL
, FALSE
, &errorCode
);
2489 *pChar1Length
=(int32_t)(target
-char1
);
2491 if(U_FAILURE(errorCode
)) {
2492 log_err("unable to get test character for %s - %s\n", converterName
, u_errorName(errorCode
));
2498 static UBool
isOneTruncatedUTF8(const char *s
, int32_t length
) {
2501 } else if(length
==1) {
2502 return U8_IS_LEAD(s
[0]);
2504 int32_t count
=U8_COUNT_TRAIL_BYTES(s
[0]);
2506 // 2 or more bytes, but fewer than the lead byte indicates.
2507 int32_t oneLength
=0;
2508 U8_FWD_1(s
, oneLength
, length
);
2509 // Truncated if we reach the end of the string.
2510 // Not true if the lead byte and first trail byte do not start a valid sequence,
2511 // e.g., E0 80 -> oneLength=1.
2512 return oneLength
==length
;
2518 static void testFromTruncatedUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2519 char charUTF8
[4], int32_t charUTF8Length
,
2520 char char0
[8], int32_t char0Length
,
2521 char char1
[8], int32_t char1Length
) {
2526 int32_t outputLength
;
2528 char invalidChars
[8];
2529 int8_t invalidLength
;
2534 UChar pivotBuffer
[8];
2535 UChar
*pivotSource
, *pivotTarget
;
2537 UErrorCode errorCode
;
2540 /* test truncated sequences */
2541 errorCode
=U_ZERO_ERROR
;
2542 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, NULL
, NULL
, &errorCode
);
2544 memcpy(utf8
, charUTF8
, charUTF8Length
);
2546 for(i
=0; i
<UPRV_LENGTHOF(badUTF8
); ++i
) {
2547 /* truncated sequence? */
2548 int32_t length
=strlen(badUTF8
[i
]);
2549 if(!isOneTruncatedUTF8(badUTF8
[i
], length
)) {
2553 /* assemble a string with the test character and the truncated sequence */
2554 memcpy(utf8
+charUTF8Length
, badUTF8
[i
], length
);
2555 utf8Length
=charUTF8Length
+length
;
2557 /* convert and check the invalidChars */
2560 pivotSource
=pivotTarget
=pivotBuffer
;
2561 errorCode
=U_ZERO_ERROR
;
2562 ucnv_convertEx(cnv
, utf8Cnv
,
2563 &target
, output
+sizeof(output
),
2564 &source
, utf8
+utf8Length
,
2565 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+UPRV_LENGTHOF(pivotBuffer
),
2566 TRUE
, TRUE
, /* reset & flush */
2568 outputLength
=(int32_t)(target
-output
);
2569 (void)outputLength
; /* Suppress set but not used warning. */
2570 if(errorCode
!=U_TRUNCATED_CHAR_FOUND
|| pivotSource
!=pivotBuffer
) {
2571 log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode
), converterName
, (long)i
);
2575 errorCode
=U_ZERO_ERROR
;
2576 invalidLength
=(int8_t)sizeof(invalidChars
);
2577 ucnv_getInvalidChars(utf8Cnv
, invalidChars
, &invalidLength
, &errorCode
);
2578 if(invalidLength
!=length
|| 0!=memcmp(invalidChars
, badUTF8
[i
], length
)) {
2579 log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName
, (long)i
);
2584 static void testFromBadUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2585 char charUTF8
[4], int32_t charUTF8Length
,
2586 char char0
[8], int32_t char0Length
,
2587 char char1
[8], int32_t char1Length
) {
2588 char utf8
[600], expect
[600];
2589 int32_t utf8Length
, expectLength
;
2593 UErrorCode errorCode
;
2596 errorCode
=U_ZERO_ERROR
;
2597 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_SKIP
, NULL
, NULL
, NULL
, &errorCode
);
2600 * assemble an input string with the test character between each
2602 * and an expected string with repeated test character output
2604 memcpy(utf8
, charUTF8
, charUTF8Length
);
2605 utf8Length
=charUTF8Length
;
2607 memcpy(expect
, char0
, char0Length
);
2608 expectLength
=char0Length
;
2610 for(i
=0; i
<UPRV_LENGTHOF(badUTF8
); ++i
) {
2611 int32_t length
=strlen(badUTF8
[i
]);
2612 memcpy(utf8
+utf8Length
, badUTF8
[i
], length
);
2615 memcpy(utf8
+utf8Length
, charUTF8
, charUTF8Length
);
2616 utf8Length
+=charUTF8Length
;
2618 memcpy(expect
+expectLength
, char1
, char1Length
);
2619 expectLength
+=char1Length
;
2622 /* expect that each bad UTF-8 sequence is detected and skipped */
2623 strcpy(testName
, "from bad UTF-8 to ");
2624 strcat(testName
, converterName
);
2626 convertExMultiStreaming(utf8Cnv
, cnv
,
2628 expect
, expectLength
,
2633 /* Test illegal UTF-8 input. */
2634 static void TestConvertExFromUTF8() {
2635 static const char *const converterNames
[]={
2636 #if !UCONFIG_NO_LEGACY_CONVERSION
2645 UConverter
*utf8Cnv
, *cnv
;
2646 UErrorCode errorCode
;
2649 /* fromUnicode versions of some character, from initial state and later */
2650 char charUTF8
[4], char0
[8], char1
[8];
2651 int32_t charUTF8Length
, char0Length
, char1Length
;
2653 errorCode
=U_ZERO_ERROR
;
2654 utf8Cnv
=ucnv_open("UTF-8", &errorCode
);
2655 if(U_FAILURE(errorCode
)) {
2656 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode
));
2660 for(i
=0; i
<UPRV_LENGTHOF(converterNames
); ++i
) {
2661 errorCode
=U_ZERO_ERROR
;
2662 cnv
=ucnv_open(converterNames
[i
], &errorCode
);
2663 if(U_FAILURE(errorCode
)) {
2664 log_data_err("unable to open %s converter - %s\n", converterNames
[i
], u_errorName(errorCode
));
2667 if(!getTestChar(cnv
, converterNames
[i
], charUTF8
, &charUTF8Length
, char0
, &char0Length
, char1
, &char1Length
)) {
2670 testFromTruncatedUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2671 testFromBadUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2674 ucnv_close(utf8Cnv
);
2677 static void TestConvertExFromUTF8_C5F0() {
2678 static const char *const converterNames
[]={
2679 #if !UCONFIG_NO_LEGACY_CONVERSION
2688 UConverter
*utf8Cnv
, *cnv
;
2689 UErrorCode errorCode
;
2692 static const char bad_utf8
[2]={ (char)0xC5, (char)0xF0 };
2693 /* Expect "��" (2x U+FFFD as decimal NCRs) */
2694 static const char twoNCRs
[16]={
2695 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B,
2696 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B
2698 static const char twoFFFD
[6]={
2699 (char)0xef, (char)0xbf, (char)0xbd,
2700 (char)0xef, (char)0xbf, (char)0xbd
2702 const char *expected
;
2703 int32_t expectedLength
;
2704 char dest
[20]; /* longer than longest expectedLength */
2709 UChar pivotBuffer
[128];
2710 UChar
*pivotSource
, *pivotTarget
;
2712 errorCode
=U_ZERO_ERROR
;
2713 utf8Cnv
=ucnv_open("UTF-8", &errorCode
);
2714 if(U_FAILURE(errorCode
)) {
2715 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode
));
2719 for(i
=0; i
<UPRV_LENGTHOF(converterNames
); ++i
) {
2720 errorCode
=U_ZERO_ERROR
;
2721 cnv
=ucnv_open(converterNames
[i
], &errorCode
);
2722 ucnv_setFromUCallBack(cnv
, UCNV_FROM_U_CALLBACK_ESCAPE
, UCNV_ESCAPE_XML_DEC
,
2723 NULL
, NULL
, &errorCode
);
2724 if(U_FAILURE(errorCode
)) {
2725 log_data_err("unable to open %s converter - %s\n",
2726 converterNames
[i
], u_errorName(errorCode
));
2731 uprv_memset(dest
, 9, sizeof(dest
));
2732 if(i
==UPRV_LENGTHOF(converterNames
)-1) {
2733 /* conversion to UTF-8 yields two U+FFFD directly */
2737 /* conversion to a non-Unicode charset yields two NCRs */
2744 pivotSource
=pivotTarget
=pivotBuffer
;
2747 &target
, dest
+expectedLength
,
2748 &src
, bad_utf8
+sizeof(bad_utf8
),
2749 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+UPRV_LENGTHOF(pivotBuffer
),
2750 TRUE
, TRUE
, &errorCode
);
2751 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
|| src
!=bad_utf8
+2 ||
2752 target
!=dest
+expectedLength
|| 0!=uprv_memcmp(dest
, expected
, expectedLength
) ||
2753 dest
[expectedLength
]!=9
2755 log_err("ucnv_convertEx(UTF-8 C5 F0 -> %s/decimal NCRs) failed\n", converterNames
[i
]);
2759 ucnv_close(utf8Cnv
);
2763 TestConvertAlgorithmic() {
2764 #if !UCONFIG_NO_LEGACY_CONVERSION
2765 static const uint8_t
2767 /* 4e00 30a1 ff61 0410 */
2768 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2771 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2775 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2776 * SUB, SUB, 0x40, SUB, SUB, 0x40
2778 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2781 0xfe, 0xff /* BOM only, no text */
2783 #if !UCONFIG_ONLY_HTML_CONVERSION
2784 static const uint8_t utf32
[]={
2785 0xff, 0xfe, 0, 0 /* BOM only, no text */
2789 char target
[100], utf8NUL
[100], shiftJISNUL
[100];
2792 UErrorCode errorCode
;
2796 errorCode
=U_ZERO_ERROR
;
2797 cnv
=ucnv_open("Shift-JIS", &errorCode
);
2798 if(U_FAILURE(errorCode
)) {
2799 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2804 memcpy(utf8NUL
, utf8
, sizeof(utf8
));
2805 utf8NUL
[sizeof(utf8
)]=0;
2806 memcpy(shiftJISNUL
, shiftJIS
, sizeof(shiftJIS
));
2807 shiftJISNUL
[sizeof(shiftJIS
)]=0;
2810 * The to/from algorithmic convenience functions share a common implementation,
2811 * so we need not test all permutations of them.
2814 /* length in, not terminated out */
2815 errorCode
=U_ZERO_ERROR
;
2816 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF8
, target
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
), &errorCode
);
2817 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2818 length
!=sizeof(shiftJIS
) ||
2819 memcmp(target
, shiftJIS
, length
)!=0
2821 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2822 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2825 /* terminated in and out */
2826 memset(target
, 0x55, sizeof(target
));
2827 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2828 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, -1, &errorCode
);
2829 if( errorCode
!=U_ZERO_ERROR
||
2830 length
!=sizeof(utf8
) ||
2831 memcmp(target
, utf8
, length
)!=0
2833 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2834 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2837 /* empty string, some target buffer */
2838 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2839 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, 0, &errorCode
);
2840 if( errorCode
!=U_ZERO_ERROR
||
2843 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2844 u_errorName(errorCode
), length
);
2847 /* pseudo-empty string, no target buffer */
2848 errorCode
=U_ZERO_ERROR
;
2849 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2850 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2853 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2854 u_errorName(errorCode
), length
);
2857 #if !UCONFIG_ONLY_HTML_CONVERSION
2858 errorCode
=U_ZERO_ERROR
;
2859 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF32
, target
, 0, (const char *)utf32
, 4, &errorCode
);
2860 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2863 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2864 u_errorName(errorCode
), length
);
2869 errorCode
=U_MESSAGE_PARSE_ERROR
;
2870 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2871 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2872 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2876 errorCode
=U_ZERO_ERROR
;
2877 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, NULL
, 2, &errorCode
);
2878 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2879 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode
));
2882 /* illegal alg. type */
2883 errorCode
=U_ZERO_ERROR
;
2884 length
=ucnv_fromAlgorithmic(cnv
, (UConverterType
)99, target
, 0, (const char *)utf16
, 2, &errorCode
);
2885 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2886 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode
));
2892 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
2893 static void TestLMBCSMaxChar(void) {
2894 static const struct {
2898 /* some non-LMBCS converters - perfect test setup here */
2909 { 4, "IMAP-mailbox-name"},
2912 { 1, "windows-1256"},
2924 { 8, "ISO-2022-KR"},
2925 { 6, "ISO-2022-JP"},
2926 { 8, "ISO-2022-CN"},
2944 for (idx
= 0; idx
< UPRV_LENGTHOF(converter
); idx
++) {
2945 UErrorCode status
= U_ZERO_ERROR
;
2946 UConverter
*cnv
= cnv_open(converter
[idx
].name
, &status
);
2947 if (U_FAILURE(status
)) {
2950 if (converter
[idx
].maxSize
!= ucnv_getMaxCharSize(cnv
)) {
2951 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2952 converter
[idx
].name
, converter
[idx
].maxSize
, ucnv_getMaxCharSize(cnv
));
2957 /* mostly test that the macro compiles */
2958 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2959 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2964 static void TestJ1968(void) {
2965 UErrorCode err
= U_ZERO_ERROR
;
2967 char myConvName
[] = "My really really really really really really really really really really really"
2968 " really really really really really really really really really really really"
2969 " really really really really really really really really long converter name";
2970 UChar myConvNameU
[sizeof(myConvName
)];
2972 u_charsToUChars(myConvName
, myConvNameU
, sizeof(myConvName
));
2975 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
+1] = 0;
2976 cnv
= ucnv_openU(myConvNameU
, &err
);
2977 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2978 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2982 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
2983 cnv
= ucnv_openU(myConvNameU
, &err
);
2984 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2985 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2989 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
2990 cnv
= ucnv_openU(myConvNameU
, &err
);
2991 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2992 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2999 cnv
= ucnv_open(myConvName
, &err
);
3000 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3001 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3005 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = ',';
3006 cnv
= ucnv_open(myConvName
, &err
);
3007 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3008 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3012 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
3013 cnv
= ucnv_open(myConvName
, &err
);
3014 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3015 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3019 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
3020 strncpy(myConvName
+ UCNV_MAX_CONVERTER_NAME_LENGTH
, "locale=", 7);
3021 cnv
= ucnv_open(myConvName
, &err
);
3022 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3023 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3026 /* The comma isn't really a part of the converter name. */
3028 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
3029 cnv
= ucnv_open(myConvName
, &err
);
3030 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3031 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3035 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ' ';
3036 cnv
= ucnv_open(myConvName
, &err
);
3037 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3038 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3042 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
3043 cnv
= ucnv_open(myConvName
, &err
);
3044 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3045 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3050 #if !UCONFIG_NO_LEGACY_CONVERSION
3052 testSwap(const char *name
, UBool swap
) {
3054 * Test Unicode text.
3055 * Contains characters that are the highest for some of the
3056 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
3057 * tables copies the entire tables.
3059 static const UChar text
[]={
3060 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
3063 UChar uNormal
[32], uSwapped
[32];
3064 char normal
[32], swapped
[32];
3068 int32_t i
, normalLength
, swappedLength
;
3072 const char *swappedName
;
3073 UConverter
*cnv
, *swapCnv
;
3074 UErrorCode errorCode
;
3076 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
3078 /* open both the normal and the LF/NL-swapping converters */
3079 strcpy(swapped
, name
);
3080 strcat(swapped
, UCNV_SWAP_LFNL_OPTION_STRING
);
3082 errorCode
=U_ZERO_ERROR
;
3083 swapCnv
=ucnv_open(swapped
, &errorCode
);
3084 cnv
=ucnv_open(name
, &errorCode
);
3085 if(U_FAILURE(errorCode
)) {
3086 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name
, swapped
, u_errorName(errorCode
));
3090 /* the name must contain the swap option if and only if we expect the converter to swap */
3091 swappedName
=ucnv_getName(swapCnv
, &errorCode
);
3092 if(U_FAILURE(errorCode
)) {
3093 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name
, u_errorName(errorCode
));
3097 pc
=strstr(swappedName
, UCNV_SWAP_LFNL_OPTION_STRING
);
3098 if(swap
!= (pc
!=NULL
)) {
3099 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name
, swappedName
, swap
);
3103 /* convert to EBCDIC */
3106 ucnv_fromUnicode(cnv
, &pc
, normal
+UPRV_LENGTHOF(normal
), &pcu
, text
+UPRV_LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3107 normalLength
=(int32_t)(pc
-normal
);
3111 ucnv_fromUnicode(swapCnv
, &pc
, swapped
+UPRV_LENGTHOF(swapped
), &pcu
, text
+UPRV_LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3112 swappedLength
=(int32_t)(pc
-swapped
);
3114 if(U_FAILURE(errorCode
)) {
3115 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name
, u_errorName(errorCode
));
3119 /* compare EBCDIC output */
3120 if(normalLength
!=swappedLength
) {
3121 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3124 for(i
=0; i
<normalLength
; ++i
) {
3125 /* swap EBCDIC LF/NL for comparison */
3130 } else if(c
==0x25) {
3136 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name
, i
, (uint8_t)swapped
[i
]);
3141 /* convert back to Unicode (may not roundtrip) */
3144 ucnv_toUnicode(cnv
, &pu
, uNormal
+UPRV_LENGTHOF(uNormal
), (const char **)&pc
, normal
+normalLength
, NULL
, TRUE
, &errorCode
);
3145 normalLength
=(int32_t)(pu
-uNormal
);
3149 ucnv_toUnicode(swapCnv
, &pu
, uSwapped
+UPRV_LENGTHOF(uSwapped
), (const char **)&pc
, normal
+swappedLength
, NULL
, TRUE
, &errorCode
);
3150 swappedLength
=(int32_t)(pu
-uSwapped
);
3152 if(U_FAILURE(errorCode
)) {
3153 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name
, u_errorName(errorCode
));
3157 /* compare EBCDIC output */
3158 if(normalLength
!=swappedLength
) {
3159 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3162 for(i
=0; i
<normalLength
; ++i
) {
3163 /* swap EBCDIC LF/NL for comparison */
3168 } else if(u
==0x85) {
3173 if(u
!=uSwapped
[i
]) {
3174 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name
, i
, uSwapped
[i
]);
3182 ucnv_close(swapCnv
);
3186 TestEBCDICSwapLFNL() {
3187 static const struct {
3192 { "ibm-1047", TRUE
},
3193 { "ibm-1140", TRUE
},
3194 { "ibm-930", TRUE
},
3195 { "iso-8859-3", FALSE
}
3200 for(i
=0; i
<UPRV_LENGTHOF(tests
); ++i
) {
3201 testSwap(tests
[i
].name
, tests
[i
].swap
);
3206 TestEBCDICSwapLFNL() {
3207 /* test nothing... */
3211 static void TestFromUCountPending(){
3212 #if !UCONFIG_NO_LEGACY_CONVERSION
3213 UErrorCode status
= U_ZERO_ERROR
;
3214 /* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
3215 static const struct {
3219 }fromUnicodeTests
[] = {
3222 {{ 0xdbc4, 0xde34, 0xd84d},3,1},
3223 {{ 0xdbc4, 0xde34, 0xd900},3,3},
3226 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3227 if(U_FAILURE(status
)){
3228 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3231 for(i
=0; i
<UPRV_LENGTHOF(fromUnicodeTests
); ++i
) {
3234 char* targetLimit
= target
+ 10;
3235 const UChar
* source
= fromUnicodeTests
[i
].input
;
3236 const UChar
* sourceLimit
= source
+ fromUnicodeTests
[i
].len
;
3239 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3240 len
= ucnv_fromUCountPending(cnv
, &status
);
3241 if(U_FAILURE(status
)){
3242 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3243 status
= U_ZERO_ERROR
;
3246 if(len
!= fromUnicodeTests
[i
].exp
){
3247 log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
3250 status
= U_ZERO_ERROR
;
3253 * The converter has to read the tail before it knows that
3254 * only head alone matches.
3255 * At the end, the output for head will overflow the target,
3256 * middle will be pending, and tail will not have been consumed.
3259 \U00101234 -> x (<U101234> \x07 |0)
3260 \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
3261 \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
3262 \U00060007 -> unassigned
3264 static const UChar head
[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
3265 static const UChar middle
[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
3266 static const UChar tail
[] = {0xDC07,0x0000};/* second half of \U00060007 */
3269 char* targetLimit
= target
+ 2; /* expect overflow from converting \U00101234\U00050005 */
3270 const UChar
* source
= head
;
3271 const UChar
* sourceLimit
= source
+ u_strlen(head
);
3274 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3275 len
= ucnv_fromUCountPending(cnv
, &status
);
3276 if(U_FAILURE(status
)){
3277 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3278 status
= U_ZERO_ERROR
;
3281 log_err("ucnv_fromUInputHeld did not return correct length for head\n");
3284 sourceLimit
= source
+ u_strlen(middle
);
3285 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3286 len
= ucnv_fromUCountPending(cnv
, &status
);
3287 if(U_FAILURE(status
)){
3288 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3289 status
= U_ZERO_ERROR
;
3292 log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
3295 sourceLimit
= source
+ u_strlen(tail
);
3296 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3297 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3298 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3300 status
= U_ZERO_ERROR
;
3301 len
= ucnv_fromUCountPending(cnv
, &status
);
3302 /* middle[1] is pending, tail has not been consumed */
3303 if(U_FAILURE(status
)){
3304 log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status
));
3307 log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
3315 TestToUCountPending(){
3316 #if !UCONFIG_NO_LEGACY_CONVERSION
3317 UErrorCode status
= U_ZERO_ERROR
;
3318 static const struct {
3322 }toUnicodeTests
[] = {
3324 {{0x05, 0x01, 0x02},3,3},
3326 {{0x07, 0x00, 0x01, 0x02},4,4},
3330 UConverterToUCallback
*oldToUAction
= NULL
;
3331 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3332 if(U_FAILURE(status
)){
3333 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3336 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3337 for(i
=0; i
<UPRV_LENGTHOF(toUnicodeTests
); ++i
) {
3339 UChar
* target
= tgt
;
3340 UChar
* targetLimit
= target
+ 20;
3341 const char* source
= toUnicodeTests
[i
].input
;
3342 const char* sourceLimit
= source
+ toUnicodeTests
[i
].len
;
3345 ucnv_toUnicode(cnv
, &target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3346 len
= ucnv_toUCountPending(cnv
,&status
);
3347 if(U_FAILURE(status
)){
3348 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3349 status
= U_ZERO_ERROR
;
3352 if(len
!= toUnicodeTests
[i
].exp
){
3353 log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
3356 status
= U_ZERO_ERROR
;
3361 * The converter has to read the tail before it knows that
3362 * only head alone matches.
3363 * At the end, the output for head will overflow the target,
3364 * mid will be pending, and tail will not have been consumed.
3366 char head
[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
3367 char mid
[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
3368 char tail
[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
3370 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
3371 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
3372 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
3373 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
3376 UChar
* target
= tgt
;
3377 UChar
* targetLimit
= target
+ 1; /* expect overflow from converting */
3378 const char* source
= head
;
3379 const char* sourceLimit
= source
+ strlen(head
);
3381 cnv
= ucnv_openPackage(loadTestData(&status
), "test4", &status
);
3382 if(U_FAILURE(status
)){
3383 log_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3386 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3387 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3388 len
= ucnv_toUCountPending(cnv
,&status
);
3389 if(U_FAILURE(status
)){
3390 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3393 log_err("Did not get the expected len for head.\n");
3396 sourceLimit
= source
+strlen(mid
);
3397 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3398 len
= ucnv_toUCountPending(cnv
,&status
);
3399 if(U_FAILURE(status
)){
3400 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3403 log_err("Did not get the expected len for mid.\n");
3407 sourceLimit
= source
+strlen(tail
);
3408 targetLimit
= target
;
3409 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3410 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3411 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3413 status
= U_ZERO_ERROR
;
3414 len
= ucnv_toUCountPending(cnv
,&status
);
3415 /* mid[4] is pending, tail has not been consumed */
3416 if(U_FAILURE(status
)){
3417 log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status
));
3420 log_err("Did not get the expected len for tail.\n");
3427 static void TestOneDefaultNameChange(const char *name
, const char *expected
) {
3428 UErrorCode status
= U_ZERO_ERROR
;
3430 ucnv_setDefaultName(name
);
3431 if(strcmp(ucnv_getDefaultName(), expected
)==0)
3432 log_verbose("setDefaultName of %s works.\n", name
);
3434 log_err("setDefaultName of %s failed\n", name
);
3435 cnv
=ucnv_open(NULL
, &status
);
3436 if (U_FAILURE(status
) || cnv
== NULL
) {
3437 log_err("opening the default converter of %s failed\n", name
);
3440 if(strcmp(ucnv_getName(cnv
, &status
), expected
)==0)
3441 log_verbose("ucnv_getName of %s works.\n", name
);
3443 log_err("ucnv_getName of %s failed\n", name
);
3447 static void TestDefaultName(void) {
3448 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
3449 static char defaultName
[UCNV_MAX_CONVERTER_NAME_LENGTH
+ 1];
3450 strcpy(defaultName
, ucnv_getDefaultName());
3452 log_verbose("getDefaultName returned %s\n", defaultName
);
3454 /*change the default name by setting it */
3455 TestOneDefaultNameChange("UTF-8", "UTF-8");
3456 #if U_CHARSET_IS_UTF8
3457 TestOneDefaultNameChange("ISCII,version=1", "UTF-8");
3458 TestOneDefaultNameChange("ISCII,version=2", "UTF-8");
3459 TestOneDefaultNameChange("ISO-8859-1", "UTF-8");
3461 # if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
3462 TestOneDefaultNameChange("ISCII,version=1", "ISCII,version=1");
3463 TestOneDefaultNameChange("ISCII,version=2", "ISCII,version=2");
3465 TestOneDefaultNameChange("ISO-8859-1", "ISO-8859-1");
3468 /*set the default name back*/
3469 ucnv_setDefaultName(defaultName
);
3472 /* Test that ucnv_compareNames() matches names according to spec. ----------- */
3486 compareNames(const char **names
) {
3487 const char *relation
, *name1
, *name2
;
3491 if(*relation
=='=') {
3493 } else if(*relation
=='<') {
3503 while((name2
=*names
++)!=NULL
) {
3504 result
=ucnv_compareNames(name1
, name2
);
3505 if(sign(result
)!=rel
) {
3506 log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1
, name2
, result
, rel
);
3513 TestCompareNames() {
3514 static const char *equalUTF8
[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL
};
3515 static const char *equalIBM
[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL
};
3516 static const char *lessMac
[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL
};
3517 static const char *lessUTF080
[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL
};
3519 compareNames(equalUTF8
);
3520 compareNames(equalIBM
);
3521 compareNames(lessMac
);
3522 compareNames(lessUTF080
);
3527 static const UChar surrogate
[1]={ 0xd900 };
3530 static const UChar sub
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3531 static const char subChars
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3533 UErrorCode errorCode
;
3537 /* UTF-16/32: test that the BOM is output before the sub character */
3538 errorCode
=U_ZERO_ERROR
;
3539 cnv
=ucnv_open("UTF-16", &errorCode
);
3540 if(U_FAILURE(errorCode
)) {
3541 log_data_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode
));
3544 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3546 if(U_FAILURE(errorCode
) ||
3548 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3550 log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
3553 errorCode
=U_ZERO_ERROR
;
3554 cnv
=ucnv_open("UTF-32", &errorCode
);
3555 if(U_FAILURE(errorCode
)) {
3556 log_data_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode
));
3559 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3561 if(U_FAILURE(errorCode
) ||
3563 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3565 log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
3568 /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
3569 errorCode
=U_ZERO_ERROR
;
3570 cnv
=ucnv_open("ISO-8859-1", &errorCode
);
3571 if(U_FAILURE(errorCode
)) {
3572 log_data_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode
));
3575 ucnv_setSubstString(cnv
, sub
, UPRV_LENGTHOF(sub
), &errorCode
);
3576 if(U_FAILURE(errorCode
)) {
3577 log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode
));
3579 len8
= sizeof(buffer
);
3580 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3581 /* Stateless converter, we expect the string converted to charset bytes. */
3582 if(U_FAILURE(errorCode
) || len8
!=sizeof(subChars
) || 0!=uprv_memcmp(buffer
, subChars
, len8
)) {
3583 log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode
));
3588 #if !UCONFIG_NO_LEGACY_CONVERSION
3589 errorCode
=U_ZERO_ERROR
;
3590 cnv
=ucnv_open("HZ", &errorCode
);
3591 if(U_FAILURE(errorCode
)) {
3592 log_data_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode
));
3595 ucnv_setSubstString(cnv
, sub
, UPRV_LENGTHOF(sub
), &errorCode
);
3596 if(U_FAILURE(errorCode
)) {
3597 log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode
));
3599 len8
= sizeof(buffer
);
3600 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3601 /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
3602 if(U_FAILURE(errorCode
) || len8
!=0) {
3603 log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode
));
3609 * Further testing of ucnv_setSubstString() is done via intltest convert.
3610 * We do not test edge cases of illegal arguments and similar because the
3611 * function implementation uses all of its parameters in calls to other
3612 * functions with UErrorCode parameters.
3617 InvalidArguments() {
3619 UErrorCode errorCode
;
3620 char charBuffer
[2] = {1, 1};
3621 char ucharAsCharBuffer
[2] = {2, 2};
3622 char *charsPtr
= charBuffer
;
3623 UChar
*ucharsPtr
= (UChar
*)ucharAsCharBuffer
;
3624 UChar
*ucharsBadPtr
= (UChar
*)(ucharAsCharBuffer
+ 1);
3626 errorCode
=U_ZERO_ERROR
;
3627 cnv
=ucnv_open("UTF-8", &errorCode
);
3628 if(U_FAILURE(errorCode
)) {
3629 log_err("ucnv_open() failed - %s\n", u_errorName(errorCode
));
3633 errorCode
=U_ZERO_ERROR
;
3634 /* This one should fail because an incomplete UChar is being passed in */
3635 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsPtr
, ucharsBadPtr
, NULL
, TRUE
, &errorCode
);
3636 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3637 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3640 errorCode
=U_ZERO_ERROR
;
3641 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3642 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsBadPtr
, ucharsPtr
, NULL
, TRUE
, &errorCode
);
3643 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3644 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3647 errorCode
=U_ZERO_ERROR
;
3648 /* This one should fail because an incomplete UChar is being passed in */
3649 ucnv_toUnicode(cnv
, &ucharsPtr
, ucharsBadPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3650 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3651 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3654 errorCode
=U_ZERO_ERROR
;
3655 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3656 ucnv_toUnicode(cnv
, &ucharsBadPtr
, ucharsPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3657 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3658 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3661 if (charBuffer
[0] != 1 || charBuffer
[1] != 1
3662 || ucharAsCharBuffer
[0] != 2 || ucharAsCharBuffer
[1] != 2)
3664 log_err("Data was incorrectly written to buffers\n");
3670 static void TestGetName() {
3671 static const char *const names
[] = {
3672 "Unicode", "UTF-16",
3673 "UnicodeBigUnmarked", "UTF-16BE",
3674 "UnicodeBig", "UTF-16BE,version=1",
3675 "UnicodeLittleUnmarked", "UTF-16LE",
3676 "UnicodeLittle", "UTF-16LE,version=1",
3677 "x-UTF-16LE-BOM", "UTF-16LE,version=1"
3680 for(i
= 0; i
< UPRV_LENGTHOF(names
); i
+= 2) {
3681 UErrorCode errorCode
= U_ZERO_ERROR
;
3682 UConverter
*cnv
= ucnv_open(names
[i
], &errorCode
);
3683 if(U_SUCCESS(errorCode
)) {
3684 const char *name
= ucnv_getName(cnv
, &errorCode
);
3685 if(U_FAILURE(errorCode
) || 0 != strcmp(name
, names
[i
+1])) {
3686 log_err("ucnv_getName(%s) = %s != %s -- %s\n",
3687 names
[i
], name
, names
[i
+1], u_errorName(errorCode
));
3694 static void TestUTFBOM() {
3695 static const UChar a16
[] = { 0x61 };
3696 static const char *const names
[] = {
3704 static const uint8_t expected
[][5] = {
3706 { 4, 0xfe, 0xff, 0, 0x61 },
3707 { 4, 0xfe, 0xff, 0, 0x61 },
3709 { 4, 0xff, 0xfe, 0x61, 0 },
3710 { 4, 0xff, 0xfe, 0x61, 0 },
3714 { 4, 0xfe, 0xff, 0, 0x61 },
3717 { 4, 0xff, 0xfe, 0x61, 0 }
3723 for(i
= 0; i
< UPRV_LENGTHOF(names
); ++i
) {
3724 UErrorCode errorCode
= U_ZERO_ERROR
;
3725 UConverter
*cnv
= ucnv_open(names
[i
], &errorCode
);
3727 const uint8_t *exp
= expected
[i
];
3728 if (U_FAILURE(errorCode
)) {
3729 log_err_status(errorCode
, "Unable to open converter: %s got error code: %s\n", names
[i
], u_errorName(errorCode
));
3732 length
= ucnv_fromUChars(cnv
, bytes
, (int32_t)sizeof(bytes
), a16
, 1, &errorCode
);
3734 if(U_FAILURE(errorCode
) || length
!= exp
[0] || 0 != memcmp(bytes
, exp
+1, length
)) {
3735 log_err("unexpected %s BOM writing behavior -- %s\n",
3736 names
[i
], u_errorName(errorCode
));