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 /* Similar to C++ alignof(type) */
39 #define ALIGNOF(type) offsetof (struct { char c; type member; }, member)
41 /*returns an action other than the one provided*/
42 #if !UCONFIG_NO_LEGACY_CONVERSION
43 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
);
44 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
);
48 cnv_open(const char *name
, UErrorCode
*pErrorCode
) {
49 if(name
!=NULL
&& name
[0]=='*') {
50 return ucnv_openPackage(loadTestData(pErrorCode
), name
+1, pErrorCode
);
52 return ucnv_open(name
, pErrorCode
);
57 static void ListNames(void);
58 static void TestFlushCache(void);
59 static void TestDuplicateAlias(void);
60 static void TestCCSID(void);
61 static void TestJ932(void);
62 static void TestJ1968(void);
63 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
64 static void TestLMBCSMaxChar(void);
67 #if !UCONFIG_NO_LEGACY_CONVERSION
68 static void TestConvertSafeCloneCallback(void);
71 static void TestEBCDICSwapLFNL(void);
72 static void TestConvertEx(void);
73 static void TestConvertExFromUTF8(void);
74 static void TestConvertExFromUTF8_C5F0(void);
75 static void TestConvertAlgorithmic(void);
76 void TestDefaultConverterError(void); /* defined in cctest.c */
77 void TestDefaultConverterSet(void); /* defined in cctest.c */
78 static void TestToUCountPending(void);
79 static void TestFromUCountPending(void);
80 static void TestDefaultName(void);
81 static void TestCompareNames(void);
82 static void TestSubstString(void);
83 static void InvalidArguments(void);
84 static void TestGetName(void);
85 static void TestUTFBOM(void);
87 void addTestConvert(TestNode
** root
);
89 void addTestConvert(TestNode
** root
)
91 addTest(root
, &ListNames
, "tsconv/ccapitst/ListNames");
92 addTest(root
, &TestConvert
, "tsconv/ccapitst/TestConvert");
93 addTest(root
, &TestFlushCache
, "tsconv/ccapitst/TestFlushCache");
94 addTest(root
, &TestAlias
, "tsconv/ccapitst/TestAlias");
95 addTest(root
, &TestDuplicateAlias
, "tsconv/ccapitst/TestDuplicateAlias");
96 addTest(root
, &TestConvertSafeClone
, "tsconv/ccapitst/TestConvertSafeClone");
97 #if !UCONFIG_NO_LEGACY_CONVERSION
98 addTest(root
, &TestConvertSafeCloneCallback
,"tsconv/ccapitst/TestConvertSafeCloneCallback");
100 addTest(root
, &TestCCSID
, "tsconv/ccapitst/TestCCSID");
101 addTest(root
, &TestJ932
, "tsconv/ccapitst/TestJ932");
102 addTest(root
, &TestJ1968
, "tsconv/ccapitst/TestJ1968");
103 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
104 addTest(root
, &TestLMBCSMaxChar
, "tsconv/ccapitst/TestLMBCSMaxChar");
106 addTest(root
, &TestEBCDICSwapLFNL
, "tsconv/ccapitst/TestEBCDICSwapLFNL");
107 addTest(root
, &TestConvertEx
, "tsconv/ccapitst/TestConvertEx");
108 addTest(root
, &TestConvertExFromUTF8
, "tsconv/ccapitst/TestConvertExFromUTF8");
109 addTest(root
, &TestConvertExFromUTF8_C5F0
, "tsconv/ccapitst/TestConvertExFromUTF8_C5F0");
110 addTest(root
, &TestConvertAlgorithmic
, "tsconv/ccapitst/TestConvertAlgorithmic");
111 addTest(root
, &TestDefaultConverterError
, "tsconv/ccapitst/TestDefaultConverterError");
112 addTest(root
, &TestDefaultConverterSet
, "tsconv/ccapitst/TestDefaultConverterSet");
113 #if !UCONFIG_NO_FILE_IO
114 addTest(root
, &TestToUCountPending
, "tsconv/ccapitst/TestToUCountPending");
115 addTest(root
, &TestFromUCountPending
, "tsconv/ccapitst/TestFromUCountPending");
117 addTest(root
, &TestDefaultName
, "tsconv/ccapitst/TestDefaultName");
118 addTest(root
, &TestCompareNames
, "tsconv/ccapitst/TestCompareNames");
119 addTest(root
, &TestSubstString
, "tsconv/ccapitst/TestSubstString");
120 addTest(root
, &InvalidArguments
, "tsconv/ccapitst/InvalidArguments");
121 addTest(root
, &TestGetName
, "tsconv/ccapitst/TestGetName");
122 addTest(root
, &TestUTFBOM
, "tsconv/ccapitst/TestUTFBOM");
125 static void ListNames(void) {
126 UErrorCode err
= U_ZERO_ERROR
;
127 int32_t testLong1
= 0;
128 const char* available_conv
;
129 UEnumeration
*allNamesEnum
= NULL
;
130 int32_t allNamesCount
= 0;
133 log_verbose("Testing ucnv_openAllNames()...");
134 allNamesEnum
= ucnv_openAllNames(&err
);
136 log_data_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err
));
139 const char *string
= NULL
;
143 allNamesCount
= uenum_count(allNamesEnum
, &err
);
144 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
146 log_verbose("read \"%s\", length %i\n", string
, len
);
148 if (U_FAILURE(err
)) {
149 log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err
));
152 uenum_reset(allNamesEnum
, &err
);
153 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
155 ucnv_close(ucnv_open(string
, &err
));
156 log_verbose("read \"%s\", length %i (%s)\n", string
, len
, U_SUCCESS(err
) ? "available" : "unavailable");
159 if (count1
!= count2
) {
160 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
163 uenum_close(allNamesEnum
);
166 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
168 log_verbose("Testing ucnv_countAvailable()...");
170 testLong1
=ucnv_countAvailable();
171 log_info("Number of available codepages: %d/%d\n", testLong1
, allNamesCount
);
173 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
175 available_conv
= ucnv_getAvailableName(testLong1
);
176 /*test ucnv_getAvailableName with err condition*/
177 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
178 available_conv
= ucnv_getAvailableName(-1);
179 if(available_conv
!= NULL
){
180 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
183 /* Test ucnv_countAliases() etc. */
184 count
= ucnv_countAliases("utf-8", &err
);
186 log_data_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err
));
187 } else if(count
<= 0) {
188 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count
);
190 /* try to get the aliases individually */
192 alias
= ucnv_getAlias("utf-8", 0, &err
);
194 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err
));
195 } else if(strcmp("UTF-8", alias
) != 0) {
196 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias
);
199 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
200 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
202 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
203 } else if(strlen(alias
) > 20) {
205 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum
, alias
);
207 log_verbose("alias %d for utf-8: %s\n", aliasNum
, alias
);
211 /* try to fill an array with all aliases */
212 const char **aliases
;
213 aliases
=(const char **)malloc(count
* sizeof(const char *));
215 ucnv_getAliases("utf-8", aliases
, &err
);
217 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err
));
219 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
220 /* compare the pointers with the ones returned individually */
221 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
223 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
224 } else if(aliases
[aliasNum
] != alias
) {
225 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum
, aliasNum
);
229 free((char **)aliases
);
237 static void TestConvert()
239 #if !UCONFIG_NO_LEGACY_CONVERSION
242 int32_t testLong1
= 0;
246 FILE* ucs_file_in
= NULL
;
248 UChar myUChar
= 0x0000;
249 char* mytarget
; /* [MAX_FILE_LEN] */
252 UChar
* consumedUni
= NULL
;
253 char* consumed
= NULL
;
254 char* output_cp_buffer
; /* [MAX_FILE_LEN] */
255 UChar
* ucs_file_buffer
; /* [MAX_FILE_LEN] */
256 UChar
* ucs_file_buffer_use
;
257 UChar
* my_ucs_file_buffer
; /* [MAX_FILE_LEN] */
258 UChar
* my_ucs_file_buffer_1
;
260 uint16_t codepage_index
= 0;
262 UErrorCode err
= U_ZERO_ERROR
;
263 char ucs_file_name
[UCS_FILE_NAME_SIZE
];
264 UConverterFromUCallback MIA1
, MIA1_2
;
265 UConverterToUCallback MIA2
, MIA2_2
;
266 const void *MIA1Context
, *MIA1Context2
, *MIA2Context
, *MIA2Context2
;
267 UConverter
* someConverters
[5];
268 UConverter
* myConverter
= 0;
269 UChar
* displayname
= 0;
276 int32_t targetcapacity2
;
277 int32_t targetcapacity
;
281 const UChar
* tmp_ucs_buf
;
282 const UChar
* tmp_consumedUni
=NULL
;
283 const char* tmp_mytarget_use
;
284 const char* tmp_consumed
;
286 /******************************************************************
287 Checking Unicode -> ksc
288 ******************************************************************/
290 const char* CodePagesToTest
[NUM_CODEPAGE
] =
296 const uint16_t CodePageNumberToTest
[NUM_CODEPAGE
] =
302 const int8_t CodePagesMinChars
[NUM_CODEPAGE
] =
308 const int8_t CodePagesMaxChars
[NUM_CODEPAGE
] =
314 const uint16_t CodePagesSubstitutionChars
[NUM_CODEPAGE
] =
319 const char* CodePagesTestFiles
[NUM_CODEPAGE
] =
325 const UConverterPlatform CodePagesPlatform
[NUM_CODEPAGE
] =
331 const char* CodePagesLocale
[NUM_CODEPAGE
] =
336 UConverterFromUCallback oldFromUAction
= NULL
;
337 UConverterToUCallback oldToUAction
= NULL
;
338 const void* oldFromUContext
= NULL
;
339 const void* oldToUContext
= NULL
;
341 /* Allocate memory */
342 mytarget
= (char*) malloc(MAX_FILE_LEN
* sizeof(mytarget
[0]));
343 output_cp_buffer
= (char*) malloc(MAX_FILE_LEN
* sizeof(output_cp_buffer
[0]));
344 ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(ucs_file_buffer
[0]));
345 my_ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(my_ucs_file_buffer
[0]));
347 ucs_file_buffer_use
= ucs_file_buffer
;
349 mytarget_use
= mytarget
;
350 my_ucs_file_buffer_1
=my_ucs_file_buffer
;
352 /* flush the converter cache to get a consistent state before the flushing is tested */
355 /*Testing ucnv_openU()*/
357 UChar converterName
[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
358 UChar firstSortedName
[]={ 0x0021, 0x0000}; /* ! */
359 UChar lastSortedName
[]={ 0x007E, 0x0000}; /* ~ */
360 const char *illegalNameChars
={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
361 UChar illegalName
[100];
362 UConverter
*converter
=NULL
;
364 converter
=ucnv_openU(converterName
, &err
);
366 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err
));
368 ucnv_close(converter
);
370 converter
=ucnv_openU(NULL
, &err
);
372 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err
));
374 ucnv_close(converter
);
375 /*testing with error value*/
376 err
=U_ILLEGAL_ARGUMENT_ERROR
;
377 converter
=ucnv_openU(converterName
, &err
);
378 if(!(converter
== NULL
)){
379 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
381 ucnv_close(converter
);
383 u_uastrcpy(illegalName
, "");
384 u_uastrcpy(illegalName
, illegalNameChars
);
385 ucnv_openU(illegalName
, &err
);
386 if(!(err
==U_ILLEGAL_ARGUMENT_ERROR
)){
387 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
391 ucnv_openU(firstSortedName
, &err
);
392 if(err
!=U_FILE_ACCESS_ERROR
){
393 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
397 ucnv_openU(lastSortedName
, &err
);
398 if(err
!=U_FILE_ACCESS_ERROR
){
399 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
404 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
406 UConverter
*cnv
=NULL
;
408 cnv
=ucnv_open("ibm-949,Madhu", &err
);
410 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err
));
415 /*Testing ucnv_convert()*/
417 int32_t targetLimit
=0, sourceLimit
=0, i
=0, targetCapacity
=0;
418 const uint8_t source
[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
419 const uint8_t expectedTarget
[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
421 sourceLimit
=UPRV_LENGTHOF(source
);
425 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", NULL
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
426 if(err
== U_BUFFER_OVERFLOW_ERROR
){
428 targetLimit
=targetCapacity
+1;
429 target
=(char*)malloc(sizeof(char) * targetLimit
);
430 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
433 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err
));
436 for(i
=0; i
<targetCapacity
; i
++){
437 if(target
[i
] != expectedTarget
[i
]){
438 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
]);
442 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
+1, -1, &err
);
443 if(U_FAILURE(err
) || i
!=7){
444 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
445 u_errorName(err
), i
);
448 /*Test error conditions*/
450 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, 0, &err
);
452 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
455 err
=U_ILLEGAL_ARGUMENT_ERROR
;
456 sourceLimit
=UPRV_LENGTHOF(source
);
457 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
459 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
463 sourceLimit
=UPRV_LENGTHOF(source
);
465 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
466 if(!(U_FAILURE(err
) && err
==U_BUFFER_OVERFLOW_ERROR
)){
467 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
474 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
475 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
476 err
=U_ILLEGAL_ARGUMENT_ERROR
;
477 if(ucnv_open(NULL
, &err
) != NULL
){
478 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
480 if(ucnv_openCCSID(1051, UCNV_IBM
, &err
) != NULL
){
481 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
485 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
486 log_verbose("\n---Testing ucnv_open default...\n");
487 someConverters
[0] = ucnv_open(NULL
,&err
);
488 someConverters
[1] = ucnv_open(NULL
,&err
);
489 someConverters
[2] = ucnv_open("utf8", &err
);
490 someConverters
[3] = ucnv_openCCSID(949,UCNV_IBM
,&err
);
491 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM
, &err
)); /* test for j350; ucnv_close(NULL) is safe */
492 if (U_FAILURE(err
)){ log_data_err("FAILURE! %s\n", myErrorName(err
));}
494 /* Testing ucnv_getName()*/
495 /*default code page */
496 ucnv_getName(someConverters
[0], &err
);
498 log_data_err("getName[0] failed\n");
500 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters
[0], &err
));
502 ucnv_getName(someConverters
[1], &err
);
504 log_data_err("getName[1] failed\n");
506 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters
[1], &err
));
509 ucnv_close(someConverters
[0]);
510 ucnv_close(someConverters
[1]);
511 ucnv_close(someConverters
[2]);
512 ucnv_close(someConverters
[3]);
515 for (codepage_index
=0; codepage_index
< NUM_CODEPAGE
; ++codepage_index
)
521 strcpy(ucs_file_name
, U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
);
523 strcpy(ucs_file_name
, loadTestData(&err
));
526 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err
));
531 char* index
= strrchr(ucs_file_name
,(char)U_FILE_SEP_CHAR
);
533 if((unsigned int)(index
-ucs_file_name
) != (strlen(ucs_file_name
)-1)){
538 strcat(ucs_file_name
,".."U_FILE_SEP_STRING
);
540 strcat(ucs_file_name
, CodePagesTestFiles
[codepage_index
]);
542 ucs_file_in
= fopen(ucs_file_name
,"rb");
545 log_data_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name
);
549 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
551 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
552 /* ucnv_flushCache(); */
553 myConverter
=ucnv_open( "ibm-949", &err
);
554 if (!myConverter
|| U_FAILURE(err
))
556 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err
));
561 /*testing for ucnv_getName() */
562 log_verbose("Testing ucnv_getName()...\n");
563 ucnv_getName(myConverter
, &err
);
565 log_err("Error in getName\n");
568 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter
, &err
));
570 if (uprv_stricmp(ucnv_getName(myConverter
, &err
), CodePagesToTest
[codepage_index
]))
571 log_err("getName failed\n");
573 log_verbose("getName ok\n");
574 /*Test getName with error condition*/
577 err
=U_ILLEGAL_ARGUMENT_ERROR
;
578 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
579 name
=ucnv_getName(myConverter
, &err
);
581 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
587 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
589 log_verbose("Testing ucnv_getMaxCharSize()...\n");
590 if (ucnv_getMaxCharSize(myConverter
)==CodePagesMaxChars
[codepage_index
])
591 log_verbose("Max byte per character OK\n");
593 log_err("Max byte per character failed\n");
595 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
596 if (ucnv_getMinCharSize(myConverter
)==CodePagesMinChars
[codepage_index
])
597 log_verbose("Min byte per character OK\n");
599 log_err("Min byte per character failed\n");
602 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
603 log_verbose("\n---Testing ucnv_getSubstChars...\n");
605 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
607 log_err("ucnv_getSubstChars returned a negative number %d\n", ii
);
611 rest
= (uint16_t)(((unsigned char)rest
<< 8) + (unsigned char)myptr
[x
]);
612 if (rest
==CodePagesSubstitutionChars
[codepage_index
])
613 log_verbose("Substitution character ok\n");
615 log_err("Substitution character failed.\n");
617 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
618 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
621 log_err("FAILURE! %s\n", myErrorName(err
));
623 ucnv_getSubstChars(myConverter
,save
, &ii
, &err
);
626 log_err("FAILURE! %s\n", myErrorName(err
));
629 if (strncmp(save
, myptr
, ii
))
630 log_err("Saved substitution character failed\n");
632 log_verbose("Saved substitution character ok\n");
634 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
635 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
637 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
638 if(err
!= U_INDEX_OUTOFBOUNDS_ERROR
){
639 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err
));
643 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
644 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
645 ucnv_setSubstChars(myConverter
, myptr
, 0, &err
);
646 if(err
!= U_ILLEGAL_ARGUMENT_ERROR
){
647 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err
));
649 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
650 strcpy(myptr
, "abc");
651 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
653 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
654 if(strncmp(save
, myptr
, ii
) == 0){
655 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
657 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
659 strcpy(myptr
, "abc");
660 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
661 err
=U_ILLEGAL_ARGUMENT_ERROR
;
662 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
663 if(strncmp(save
, myptr
, ii
) == 0){
664 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
669 #ifdef U_ENABLE_GENERIC_ISO_2022
670 /*resetState ucnv_reset()*/
671 log_verbose("\n---Testing ucnv_reset()..\n");
672 ucnv_reset(myConverter
);
675 const uint8_t in
[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
676 const char *source
=(const char *)in
, *limit
=(const char *)in
+sizeof(in
);
677 UConverter
*cnv
=ucnv_open("ISO_2022", &err
);
679 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err
));
681 c
=ucnv_getNextUChar(cnv
, &source
, limit
, &err
);
682 if((U_FAILURE(err
) || c
!= (UChar32
)0x0031)) {
683 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err
));
692 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
693 locale
=CodePagesLocale
[codepage_index
];
696 disnamelen
= ucnv_getDisplayName(myConverter
, locale
, displayname
, len
, &err
);
697 if(err
==U_BUFFER_OVERFLOW_ERROR
) {
699 displayname
=(UChar
*)malloc((disnamelen
+1) * sizeof(UChar
));
700 ucnv_getDisplayName(myConverter
,locale
,displayname
,disnamelen
+1, &err
);
702 log_err("getDisplayName failed. The error is %s\n", myErrorName(err
));
705 log_verbose(" getDisplayName o.k.\n");
711 log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err
));
713 /*test ucnv_getDiaplayName with error condition*/
714 err
= U_ILLEGAL_ARGUMENT_ERROR
;
715 len
=ucnv_getDisplayName(myConverter
,locale
,NULL
,0, &err
);
717 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
719 /*test ucnv_getDiaplayName with error condition*/
721 len
=ucnv_getDisplayName(NULL
,locale
,NULL
,0, &err
);
722 if( len
!=0 || U_SUCCESS(err
)){
723 log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
727 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
728 ucnv_getFromUCallBack(myConverter
, &MIA1
, &MIA1Context
);
730 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
731 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
732 if (U_FAILURE(err
) || oldFromUAction
!= MIA1
|| oldFromUContext
!= MIA1Context
)
734 log_err("FAILURE! %s\n", myErrorName(err
));
737 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
738 if (MIA1_2
!= otherUnicodeAction(MIA1
) || MIA1Context2
!= &BOM
)
739 log_err("get From UCallBack failed\n");
741 log_verbose("get From UCallBack ok\n");
743 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
744 ucnv_setFromUCallBack(myConverter
,MIA1
, MIA1Context
, &oldFromUAction
, &oldFromUContext
, &err
);
745 if (U_FAILURE(err
) || oldFromUAction
!= otherUnicodeAction(MIA1
) || oldFromUContext
!= &BOM
)
747 log_err("FAILURE! %s\n", myErrorName(err
));
750 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
751 if (MIA1_2
!= MIA1
|| MIA1Context2
!= MIA1Context
)
752 log_err("get From UCallBack action failed\n");
754 log_verbose("get From UCallBack action ok\n");
756 /*testing ucnv_setToUCallBack with error conditions*/
757 err
=U_ILLEGAL_ARGUMENT_ERROR
;
758 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
759 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
760 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
761 if(MIA1_2
== otherUnicodeAction(MIA1
) || MIA1Context2
== &BOM
){
762 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
767 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
768 ucnv_getToUCallBack(myConverter
, &MIA2
, &MIA2Context
);
770 log_verbose("\n---Testing setTo UCallBack...\n");
771 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), &BOM
, &oldToUAction
, &oldToUContext
, &err
);
772 if (U_FAILURE(err
) || oldToUAction
!= MIA2
|| oldToUContext
!= MIA2Context
)
774 log_err("FAILURE! %s\n", myErrorName(err
));
777 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
778 if (MIA2_2
!= otherCharAction(MIA2
) || MIA2Context2
!= &BOM
)
779 log_err("To UCallBack failed\n");
781 log_verbose("To UCallBack ok\n");
783 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
784 ucnv_setToUCallBack(myConverter
,MIA2
, MIA2Context
, &oldToUAction
, &oldToUContext
, &err
);
785 if (U_FAILURE(err
) || oldToUAction
!= otherCharAction(MIA2
) || oldToUContext
!= &BOM
)
786 { log_err("FAILURE! %s\n", myErrorName(err
)); }
788 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
789 if (MIA2_2
!= MIA2
|| MIA2Context2
!= MIA2Context
)
790 log_err("To UCallBack failed\n");
792 log_verbose("To UCallBack ok\n");
794 /*testing ucnv_setToUCallBack with error conditions*/
795 err
=U_ILLEGAL_ARGUMENT_ERROR
;
796 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
797 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), NULL
, &oldToUAction
, &oldToUContext
, &err
);
798 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
799 if (MIA2_2
== otherCharAction(MIA2
) || MIA2Context2
== &BOM
){
800 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
805 /*getcodepageid testing ucnv_getCCSID() */
806 log_verbose("\n----Testing getCCSID....\n");
807 cp
= ucnv_getCCSID(myConverter
,&err
);
810 log_err("FAILURE!..... %s\n", myErrorName(err
));
812 if (cp
!= CodePageNumberToTest
[codepage_index
])
813 log_err("Codepage number test failed\n");
815 log_verbose("Codepage number test OK\n");
817 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
818 err
=U_ILLEGAL_ARGUMENT_ERROR
;
819 if( ucnv_getCCSID(myConverter
,&err
) != -1){
820 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
824 /*getCodepagePlatform testing ucnv_getPlatform()*/
825 log_verbose("\n---Testing getCodepagePlatform ..\n");
826 if (CodePagesPlatform
[codepage_index
]!=ucnv_getPlatform(myConverter
, &err
))
827 log_err("Platform codepage test failed\n");
829 log_verbose("Platform codepage test ok\n");
833 log_err("FAILURE! %s\n", myErrorName(err
));
835 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
836 err
= U_ILLEGAL_ARGUMENT_ERROR
;
837 if(ucnv_getPlatform(myConverter
, &err
) != UCNV_UNKNOWN
){
838 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
845 // Note: gcc produces a compile warning if the return value from fread() is ignored.
846 size_t numRead
= fread(&BOM
, sizeof(UChar
), 1, ucs_file_in
);
849 if (BOM
!=0xFEFF && BOM
!=0xFFFE)
851 log_err("File Missing BOM...Bailing!\n");
857 /*Reads in the file*/
858 while(!feof(ucs_file_in
)&&(i
+=(int32_t)fread(ucs_file_buffer
+i
, sizeof(UChar
), 1, ucs_file_in
)))
860 myUChar
= ucs_file_buffer
[i
-1];
862 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN*/
865 myUChar
= ucs_file_buffer
[i
-1];
866 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN Corner Case*/
869 /*testing ucnv_fromUChars() and ucnv_toUChars() */
870 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
872 uchar1
=(UChar
*)malloc(sizeof(UChar
) * (i
+1));
873 u_uastrcpy(uchar1
,"");
874 u_strncpy(uchar1
,ucs_file_buffer
,i
);
877 uchar3
=(UChar
*)malloc(sizeof(UChar
)*(i
+1));
878 u_uastrcpy(uchar3
,"");
879 u_strncpy(uchar3
,ucs_file_buffer
,i
);
882 /*Calls the Conversion Routine */
883 testLong1
= MAX_FILE_LEN
;
884 log_verbose("\n---Testing ucnv_fromUChars()\n");
885 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
888 log_err("\nFAILURE...%s\n", myErrorName(err
));
891 log_verbose(" ucnv_fromUChars() o.k.\n");
893 /*test the conversion routine */
894 log_verbose("\n---Testing ucnv_toUChars()\n");
895 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
897 targetsize
= ucnv_toUChars(myConverter
,
901 (int32_t)strlen(output_cp_buffer
),
903 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
905 if(err
==U_BUFFER_OVERFLOW_ERROR
)
908 uchar2
=(UChar
*)malloc((targetsize
+1) * sizeof(UChar
));
909 targetsize
= ucnv_toUChars(myConverter
,
913 (int32_t)strlen(output_cp_buffer
),
917 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err
));
919 log_verbose(" ucnv_toUChars() o.k.\n");
921 if(u_strcmp(uchar1
,uchar2
)!=0)
922 log_err("equality test failed with conversion routine\n");
926 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
928 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
929 err
=U_ILLEGAL_ARGUMENT_ERROR
;
930 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
931 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
932 if (targetcapacity
!=0) {
933 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
936 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
937 targetcapacity
= ucnv_fromUChars(NULL
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
938 if (targetcapacity
!=0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
939 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
942 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
943 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, 0, &err
);
944 if (targetcapacity
!=0) {
945 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
947 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
948 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, 0, uchar1
, -1, &err
);
949 if (err
!= U_BUFFER_OVERFLOW_ERROR
) {
950 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
952 /*toUChars with error conditions*/
953 targetsize
= ucnv_toUChars(myConverter
, uchar2
, targetsize
, output_cp_buffer
, (int32_t)strlen(output_cp_buffer
), &err
);
955 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
958 targetsize
= ucnv_toUChars(myConverter
, uchar2
, -1, output_cp_buffer
, (int32_t)strlen(output_cp_buffer
), &err
);
959 if(targetsize
!= 0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
){
960 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
963 targetsize
= ucnv_toUChars(myConverter
, uchar2
, 0, output_cp_buffer
, 0, &err
);
964 if (targetsize
!=0) {
965 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
968 targetsize
= ucnv_toUChars(myConverter
, NULL
, targetcapacity2
, output_cp_buffer
, (int32_t)strlen(output_cp_buffer
), &err
);
969 if (err
!= U_STRING_NOT_TERMINATED_WARNING
) {
970 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
977 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
978 /*Clean up re-usable vars*/
979 log_verbose("Testing ucnv_fromUnicode().....\n");
980 tmp_ucs_buf
=ucs_file_buffer_use
;
981 ucnv_fromUnicode(myConverter
, &mytarget_1
,
982 mytarget
+ MAX_FILE_LEN
,
984 ucs_file_buffer_use
+i
,
988 consumedUni
= (UChar
*)tmp_consumedUni
;
989 (void)consumedUni
; /* Suppress set but not used warning. */
993 log_err("FAILURE! %s\n", myErrorName(err
));
996 log_verbose("ucnv_fromUnicode() o.k.\n");
998 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
999 log_verbose("Testing ucnv_toUnicode().....\n");
1000 tmp_mytarget_use
=mytarget_use
;
1001 tmp_consumed
= consumed
;
1002 ucnv_toUnicode(myConverter
, &my_ucs_file_buffer_1
,
1003 my_ucs_file_buffer
+ MAX_FILE_LEN
,
1005 mytarget_use
+ (mytarget_1
- mytarget
),
1009 consumed
= (char*)tmp_consumed
;
1012 log_err("FAILURE! %s\n", myErrorName(err
));
1015 log_verbose("ucnv_toUnicode() o.k.\n");
1018 log_verbose("\n---Testing RoundTrip ...\n");
1021 u_strncpy(uchar3
, my_ucs_file_buffer
,i
);
1024 if(u_strcmp(uchar1
,uchar3
)==0)
1025 log_verbose("Equality test o.k.\n");
1027 log_err("Equality test failed\n");
1032 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__
);
1036 if(u_strcmp(uchar2
, uchar3
)==0)
1037 log_verbose("Equality test o.k.\n");
1039 log_err("Equality test failed\n");
1042 fclose(ucs_file_in
);
1043 ucnv_close(myConverter
);
1044 if (uchar1
!= 0) free(uchar1
);
1045 if (uchar2
!= 0) free(uchar2
);
1046 if (uchar3
!= 0) free(uchar3
);
1049 free((void*)mytarget
);
1050 free((void*)output_cp_buffer
);
1051 free((void*)ucs_file_buffer
);
1052 free((void*)my_ucs_file_buffer
);
1056 #if !UCONFIG_NO_LEGACY_CONVERSION
1057 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
)
1059 return (MIA
==(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
)?(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_SUBSTITUTE
:(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
;
1062 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
)
1064 return (MIA
==(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
)?(UConverterToUCallback
)UCNV_TO_U_CALLBACK_SUBSTITUTE
:(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
;
1068 static void TestFlushCache(void) {
1069 #if !UCONFIG_NO_LEGACY_CONVERSION
1070 UErrorCode err
= U_ZERO_ERROR
;
1071 UConverter
* someConverters
[5];
1074 /* flush the converter cache to get a consistent state before the flushing is tested */
1077 /*Testing ucnv_open()*/
1078 /* Note: These converters have been chosen because they do NOT
1079 encode the Latin characters (U+0041, ...), and therefore are
1080 highly unlikely to be chosen as system default codepages */
1082 someConverters
[0] = ucnv_open("ibm-1047", &err
);
1083 if (U_FAILURE(err
)) {
1084 log_data_err("FAILURE! %s\n", myErrorName(err
));
1087 someConverters
[1] = ucnv_open("ibm-1047", &err
);
1088 if (U_FAILURE(err
)) {
1089 log_data_err("FAILURE! %s\n", myErrorName(err
));
1092 someConverters
[2] = ucnv_open("ibm-1047", &err
);
1093 if (U_FAILURE(err
)) {
1094 log_data_err("FAILURE! %s\n", myErrorName(err
));
1097 someConverters
[3] = ucnv_open("gb18030", &err
);
1098 if (U_FAILURE(err
)) {
1099 log_data_err("FAILURE! %s\n", myErrorName(err
));
1102 someConverters
[4] = ucnv_open("ibm-954", &err
);
1103 if (U_FAILURE(err
)) {
1104 log_data_err("FAILURE! %s\n", myErrorName(err
));
1108 /* Testing ucnv_flushCache() */
1109 log_verbose("\n---Testing ucnv_flushCache...\n");
1110 if ((flushCount
=ucnv_flushCache())==0)
1111 log_verbose("Flush cache ok\n");
1113 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1115 /*testing ucnv_close() and ucnv_flushCache() */
1116 ucnv_close(someConverters
[0]);
1117 ucnv_close(someConverters
[1]);
1119 if ((flushCount
=ucnv_flushCache())==0)
1120 log_verbose("Flush cache ok\n");
1122 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1124 ucnv_close(someConverters
[2]);
1125 ucnv_close(someConverters
[3]);
1127 if ((flushCount
=ucnv_flushCache())==2)
1128 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1130 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1134 ucnv_close(someConverters
[4]);
1135 if ( (flushCount
=ucnv_flushCache())==1)
1136 log_verbose("Flush cache ok\n");
1138 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__
, flushCount
);
1143 * Test the converter alias API, specifically the fuzzy matching of
1144 * alias names and the alias table integrity. Make sure each
1145 * converter has at least one alias (itself), and that its listed
1146 * aliases map back to itself. Check some hard-coded UTF-8 and
1147 * ISO_2022 aliases to make sure they work.
1149 static void TestAlias() {
1151 UErrorCode status
= U_ZERO_ERROR
;
1153 /* Predetermined aliases that we expect to map back to ISO_2022
1154 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1155 const char* ISO_2022_NAMES
[] =
1156 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1157 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1158 int32_t ISO_2022_NAMES_LENGTH
= UPRV_LENGTHOF(ISO_2022_NAMES
);
1159 const char *UTF8_NAMES
[] =
1160 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1161 "utf_8", "ibm1208", "cp1208" };
1162 int32_t UTF8_NAMES_LENGTH
= UPRV_LENGTHOF(UTF8_NAMES
);
1167 } CONVERTERS_NAMES
[] = {
1168 { "UTF-32BE", "UTF32_BigEndian" },
1169 { "UTF-32LE", "UTF32_LittleEndian" },
1170 { "UTF-32", "ISO-10646-UCS-4" },
1171 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1172 { "UTF-32", "ucs-4" }
1174 int32_t CONVERTERS_NAMES_LENGTH
= UPRV_LENGTHOF(CONVERTERS_NAMES
);
1176 /* When there are bugs in gencnval or in ucnv_io, converters can
1177 appear to have no aliases. */
1178 ncnv
= ucnv_countAvailable();
1179 log_verbose("%d converters\n", ncnv
);
1180 for (i
=0; i
<ncnv
; ++i
) {
1181 const char *name
= ucnv_getAvailableName(i
);
1183 uint16_t na
= ucnv_countAliases(name
, &status
);
1188 log_err("FAIL: Converter \"%s\" (i=%d)"
1189 " has no aliases; expect at least one\n",
1193 cnv
= ucnv_open(name
, &status
);
1194 if (U_FAILURE(status
)) {
1195 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1196 " can't be opened.\n",
1200 if (strcmp(ucnv_getName(cnv
, &status
), name
) != 0
1201 && (strstr(name
, "PlatformEndian") == 0 && strstr(name
, "OppositeEndian") == 0)) {
1202 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1203 "They should be the same\n",
1204 name
, ucnv_getName(cnv
, &status
));
1209 status
= U_ZERO_ERROR
;
1210 alias0
= ucnv_getAlias(name
, 0, &status
);
1211 for (j
=1; j
<na
; ++j
) {
1213 /* Make sure each alias maps back to the the same list of
1214 aliases. Assume that if alias 0 is the same, the whole
1215 list is the same (this should always be true). */
1216 const char *mapBack
;
1218 status
= U_ZERO_ERROR
;
1219 alias
= ucnv_getAlias(name
, j
, &status
);
1220 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1221 log_err("FAIL: Converter \"%s\"is ambiguous\n", name
);
1224 if (alias
== NULL
) {
1225 log_err("FAIL: Converter \"%s\" -> "
1231 mapBack
= ucnv_getAlias(alias
, 0, &status
);
1233 if (mapBack
== NULL
) {
1234 log_err("FAIL: Converter \"%s\" -> "
1235 "alias[%d]=\"%s\" -> "
1236 "alias[0]=NULL, exp. \"%s\"\n",
1237 name
, j
, alias
, alias0
);
1241 if (0 != strcmp(alias0
, mapBack
)) {
1243 UBool foundAlias
= FALSE
;
1244 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1245 /* Make sure that we only get this mismapping when there is
1246 an ambiguous alias, and the other converter has this alias too. */
1247 for (idx
= 0; idx
< ucnv_countAliases(mapBack
, &status
); idx
++) {
1248 if (strcmp(ucnv_getAlias(mapBack
, (uint16_t)idx
, &status
), alias
) == 0) {
1254 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1257 log_err("FAIL: Converter \"%s\" -> "
1258 "alias[%d]=\"%s\" -> "
1259 "alias[0]=\"%s\", exp. \"%s\"\n",
1260 name
, j
, alias
, mapBack
, alias0
);
1267 /* Check a list of predetermined aliases that we expect to map
1268 * back to ISO_2022 and UTF-8. */
1269 for (i
=1; i
<ISO_2022_NAMES_LENGTH
; ++i
) {
1270 const char* mapBack
= ucnv_getAlias(ISO_2022_NAMES
[i
], 0, &status
);
1272 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES
[i
]);
1275 if (0 != strcmp(mapBack
, ISO_2022_NAMES
[0])) {
1276 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1277 ISO_2022_NAMES
[i
], mapBack
);
1282 for (i
=1; i
<UTF8_NAMES_LENGTH
; ++i
) {
1283 const char* mapBack
= ucnv_getAlias(UTF8_NAMES
[i
], 0, &status
);
1285 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES
[i
]);
1288 if (mapBack
&& 0 != strcmp(mapBack
, UTF8_NAMES
[0])) {
1289 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1290 UTF8_NAMES
[i
], mapBack
);
1295 * Check a list of predetermined aliases that we expect to map
1296 * back to predermined converter names.
1299 for (i
= 0; i
< CONVERTERS_NAMES_LENGTH
; ++i
) {
1300 const char* mapBack
= ucnv_getAlias(CONVERTERS_NAMES
[i
].alias
, 0, &status
);
1302 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES
[i
].name
);
1305 if (0 != strcmp(mapBack
, CONVERTERS_NAMES
[i
].name
)) {
1306 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1307 CONVERTERS_NAMES
[i
].alias
, mapBack
, CONVERTERS_NAMES
[i
].name
);
1313 static void TestDuplicateAlias(void) {
1315 UErrorCode status
= U_ZERO_ERROR
;
1317 status
= U_ZERO_ERROR
;
1318 alias
= ucnv_getStandardName("Shift_JIS", "IBM", &status
);
1319 if (alias
== NULL
|| strcmp(alias
, "ibm-943") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1320 log_data_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias
);
1322 status
= U_ZERO_ERROR
;
1323 alias
= ucnv_getStandardName("ibm-943", "IANA", &status
);
1324 if (alias
== NULL
|| strcmp(alias
, "Shift_JIS") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1325 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias
);
1327 status
= U_ZERO_ERROR
;
1328 alias
= ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status
);
1329 if (alias
!= NULL
|| status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1330 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias
);
1335 /* Test safe clone callback */
1337 static uint32_t TSCC_nextSerial()
1339 static uint32_t n
= 1;
1346 uint32_t magic
; /* 0xC0FFEE to identify that the object is OK */
1347 uint32_t serial
; /* minted from nextSerial, above */
1348 UBool wasClosed
; /* close happened on the object */
1351 static TSCCContext
*TSCC_clone(TSCCContext
*ctx
)
1353 TSCCContext
*newCtx
= (TSCCContext
*)malloc(sizeof(TSCCContext
));
1355 newCtx
->serial
= TSCC_nextSerial();
1356 newCtx
->wasClosed
= 0;
1357 newCtx
->magic
= 0xC0FFEE;
1359 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
1364 #if !UCONFIG_NO_LEGACY_CONVERSION
1365 static void TSCC_fromU(const void *context
,
1366 UConverterFromUnicodeArgs
*fromUArgs
,
1367 const UChar
* codeUnits
,
1370 UConverterCallbackReason reason
,
1373 // suppress compiler warnings about unused variables
1378 TSCCContext
*ctx
= (TSCCContext
*)context
;
1379 UConverterFromUCallback junkFrom
;
1381 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
);
1383 if(ctx
->magic
!= 0xC0FFEE) {
1384 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1388 if(reason
== UCNV_CLONE
) {
1389 UErrorCode subErr
= U_ZERO_ERROR
;
1390 TSCCContext
*newCtx
;
1391 TSCCContext
*junkCtx
;
1392 TSCCContext
**pjunkCtx
= &junkCtx
;
1395 log_verbose("TSCC_fromU: cloning..\n");
1396 newCtx
= TSCC_clone(ctx
);
1398 if(newCtx
== NULL
) {
1399 log_err("TSCC_fromU: internal clone failed on %p\n", ctx
);
1403 ucnv_getFromUCallBack(fromUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1404 ucnv_setFromUCallBack(fromUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1406 if(U_FAILURE(subErr
)) {
1411 if(reason
== UCNV_CLOSE
) {
1412 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1413 ctx
->wasClosed
= TRUE
;
1417 static void TSCC_toU(const void *context
,
1418 UConverterToUnicodeArgs
*toUArgs
,
1419 const char* codeUnits
,
1421 UConverterCallbackReason reason
,
1424 // suppress compiler warnings about unused variables
1428 TSCCContext
*ctx
= (TSCCContext
*)context
;
1429 UConverterToUCallback junkFrom
;
1431 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, toUArgs
->converter
);
1433 if(ctx
->magic
!= 0xC0FFEE) {
1434 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1438 if(reason
== UCNV_CLONE
) {
1439 UErrorCode subErr
= U_ZERO_ERROR
;
1440 TSCCContext
*newCtx
;
1441 TSCCContext
*junkCtx
;
1442 TSCCContext
**pjunkCtx
= &junkCtx
;
1445 log_verbose("TSCC_toU: cloning..\n");
1446 newCtx
= TSCC_clone(ctx
);
1448 if(newCtx
== NULL
) {
1449 log_err("TSCC_toU: internal clone failed on %p\n", ctx
);
1453 ucnv_getToUCallBack(toUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1454 ucnv_setToUCallBack(toUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1456 if(U_FAILURE(subErr
)) {
1461 if(reason
== UCNV_CLOSE
) {
1462 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1463 ctx
->wasClosed
= TRUE
;
1467 static void TSCC_init(TSCCContext
*q
)
1469 q
->magic
= 0xC0FFEE;
1470 q
->serial
= TSCC_nextSerial();
1474 static void TSCC_print_log(TSCCContext
*q
, const char *name
)
1477 log_verbose("TSCContext: %s is NULL!!\n", name
);
1479 if(q
->magic
!= 0xC0FFEE) {
1480 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1481 q
,q
->serial
, q
->magic
);
1483 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1484 q
, q
->serial
, name
, q
->magic
, q
->wasClosed
?"CLOSED":"open");
1488 static void TestConvertSafeCloneCallback()
1490 UErrorCode err
= U_ZERO_ERROR
;
1491 TSCCContext from1
, to1
;
1492 TSCCContext
*from2
, *from3
, *to2
, *to3
;
1493 TSCCContext
**pfrom2
= &from2
, **pfrom3
= &from3
, **pto2
= &to2
, **pto3
= &to3
;
1495 int32_t hunkSize
= 8192;
1496 UConverterFromUCallback junkFrom
;
1497 UConverterToUCallback junkTo
;
1498 UConverter
*conv1
, *conv2
= NULL
;
1500 conv1
= ucnv_open("iso-8859-3", &err
);
1502 if(U_FAILURE(err
)) {
1503 log_data_err("Err opening iso-8859-3, %s\n", u_errorName(err
));
1507 log_verbose("Opened conv1=%p\n", conv1
);
1512 TSCC_print_log(&from1
, "from1");
1513 TSCC_print_log(&to1
, "to1");
1515 ucnv_setFromUCallBack(conv1
, TSCC_fromU
, &from1
, NULL
, NULL
, &err
);
1516 log_verbose("Set from1 on conv1\n");
1517 TSCC_print_log(&from1
, "from1");
1519 ucnv_setToUCallBack(conv1
, TSCC_toU
, &to1
, NULL
, NULL
, &err
);
1520 log_verbose("Set to1 on conv1\n");
1521 TSCC_print_log(&to1
, "to1");
1523 conv2
= ucnv_safeClone(conv1
, hunk
, &hunkSize
, &err
);
1524 if(U_FAILURE(err
)) {
1525 log_err("safeClone failed: %s\n", u_errorName(err
));
1528 log_verbose("Cloned to conv2=%p.\n", conv2
);
1530 /********** from *********************/
1531 ucnv_getFromUCallBack(conv2
, &junkFrom
, (const void**)pfrom2
);
1532 ucnv_getFromUCallBack(conv1
, &junkFrom
, (const void**)pfrom3
);
1534 TSCC_print_log(from2
, "from2");
1535 TSCC_print_log(from3
, "from3(==from1)");
1538 log_err("FAIL! from2 is null \n");
1543 log_err("FAIL! from3 is null \n");
1547 if(from3
!= (&from1
) ) {
1548 log_err("FAIL! conv1's FROM context changed!\n");
1551 if(from2
== (&from1
) ) {
1552 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1555 if(from1
.wasClosed
) {
1556 log_err("FAIL! from1 is closed \n");
1559 if(from2
->wasClosed
) {
1560 log_err("FAIL! from2 was closed\n");
1563 /********** to *********************/
1564 ucnv_getToUCallBack(conv2
, &junkTo
, (const void**)pto2
);
1565 ucnv_getToUCallBack(conv1
, &junkTo
, (const void**)pto3
);
1567 TSCC_print_log(to2
, "to2");
1568 TSCC_print_log(to3
, "to3(==to1)");
1571 log_err("FAIL! to2 is null \n");
1576 log_err("FAIL! to3 is null \n");
1580 if(to3
!= (&to1
) ) {
1581 log_err("FAIL! conv1's TO context changed!\n");
1584 if(to2
== (&to1
) ) {
1585 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1589 log_err("FAIL! to1 is closed \n");
1592 if(to2
->wasClosed
) {
1593 log_err("FAIL! to2 was closed\n");
1596 /*************************************/
1599 log_verbose("ucnv_closed (conv1)\n");
1600 TSCC_print_log(&from1
, "from1");
1601 TSCC_print_log(from2
, "from2");
1602 TSCC_print_log(&to1
, "to1");
1603 TSCC_print_log(to2
, "to2");
1605 if(from1
.wasClosed
== FALSE
) {
1606 log_err("FAIL! from1 is NOT closed \n");
1609 if(from2
->wasClosed
) {
1610 log_err("FAIL! from2 was closed\n");
1613 if(to1
.wasClosed
== FALSE
) {
1614 log_err("FAIL! to1 is NOT closed \n");
1617 if(to2
->wasClosed
) {
1618 log_err("FAIL! to2 was closed\n");
1622 log_verbose("ucnv_closed (conv2)\n");
1624 TSCC_print_log(&from1
, "from1");
1625 TSCC_print_log(from2
, "from2");
1627 if(from1
.wasClosed
== FALSE
) {
1628 log_err("FAIL! from1 is NOT closed \n");
1631 if(from2
->wasClosed
== FALSE
) {
1632 log_err("FAIL! from2 was NOT closed\n");
1635 TSCC_print_log(&to1
, "to1");
1636 TSCC_print_log(to2
, "to2");
1638 if(to1
.wasClosed
== FALSE
) {
1639 log_err("FAIL! to1 is NOT closed \n");
1642 if(to2
->wasClosed
== FALSE
) {
1643 log_err("FAIL! to2 was NOT closed\n");
1647 free(to2
); /* to1 is stack based */
1649 if(from2
!= (&from1
)) {
1650 free(from2
); /* from1 is stack based */
1656 containsAnyOtherByte(uint8_t *p
, int32_t length
, uint8_t b
) {
1667 static void TestConvertSafeClone()
1669 /* one 'regular' & all the 'private stateful' converters */
1670 static const char *const names
[] = {
1671 #if !UCONFIG_NO_LEGACY_CONVERSION
1673 "ISO_2022,locale=zh,version=1",
1676 #if !UCONFIG_NO_LEGACY_CONVERSION
1680 "ISO_2022,locale=kr,version=1",
1681 "ISO_2022,locale=jp,version=2",
1685 #if !UCONFIG_NO_LEGACY_CONVERSION
1686 "IMAP-mailbox-name",
1693 /* store the actual sizes of each converter */
1694 int32_t actualSizes
[UPRV_LENGTHOF(names
)];
1696 static const int32_t bufferSizes
[] = {
1697 U_CNV_SAFECLONE_BUFFERSIZE
,
1698 (int32_t)(3*sizeof(UConverter
))/2, /* 1.5*sizeof(UConverter) */
1699 (int32_t)sizeof(UConverter
)/2 /* 0.5*sizeof(UConverter) */
1702 char charBuffer
[21]; /* Leave at an odd number for alignment testing */
1703 uint8_t buffer
[3] [U_CNV_SAFECLONE_BUFFERSIZE
];
1704 int32_t bufferSize
, maxBufferSize
;
1705 const char *maxName
;
1706 UConverter
* cnv
, *cnv2
;
1710 const char *pConstCharBuffer
;
1711 const char *charBufferLimit
= charBuffer
+ UPRV_LENGTHOF(charBuffer
);
1712 UChar uniBuffer
[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1713 UChar uniCharBuffer
[20];
1714 char charSourceBuffer
[] = { 0x1b, 0x24, 0x42 };
1715 const char *pCharSource
= charSourceBuffer
;
1716 const char *pCharSourceLimit
= charSourceBuffer
+ sizeof(charSourceBuffer
);
1717 UChar
*pUCharTarget
= uniCharBuffer
;
1718 UChar
*pUCharTargetLimit
= uniCharBuffer
+ UPRV_LENGTHOF(uniCharBuffer
);
1719 const UChar
* pUniBuffer
;
1720 const UChar
*uniBufferLimit
= uniBuffer
+ UPRV_LENGTHOF(uniBuffer
);
1724 cnv
= ucnv_open(names
[0], &err
);
1725 if(U_SUCCESS(err
)) {
1726 /* Check the various error & informational states: */
1728 /* Null status - just returns NULL */
1729 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1730 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, NULL
))
1732 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1734 /* error status - should return 0 & keep error the same */
1735 err
= U_MEMORY_ALLOCATION_ERROR
;
1736 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || err
!= U_MEMORY_ALLOCATION_ERROR
)
1738 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1742 /* Null buffer size pointer is ok */
1743 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, buffer
[0], NULL
, &err
)) || U_FAILURE(err
))
1745 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1750 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1752 if (NULL
!= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || U_FAILURE(err
) || bufferSize
<= 0)
1754 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1756 /* Verify our define is large enough */
1757 if (U_CNV_SAFECLONE_BUFFERSIZE
< bufferSize
)
1759 log_err("FAIL: Pre-calculated buffer size is too small\n");
1761 /* Verify we can use this run-time calculated size */
1762 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
)) || U_FAILURE(err
))
1764 log_err("FAIL: Converter can't be cloned with run-time size\n");
1770 /* size one byte too small - should allocate & let us know */
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 too-small buffer size\n");
1781 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1783 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1784 if (NULL
== (cnv2
= ucnv_safeClone(cnv
, NULL
, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1786 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1794 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1795 if (NULL
!= ucnv_safeClone(NULL
, buffer
[0], &bufferSize
, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1797 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1806 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1808 for(j
= 0; j
< UPRV_LENGTHOF(bufferSizes
); ++j
) {
1809 for (idx
= 0; idx
< UPRV_LENGTHOF(names
); idx
++)
1812 cnv
= ucnv_open(names
[idx
], &err
);
1813 if(U_FAILURE(err
)) {
1814 log_data_err("ucnv_open(\"%s\") failed - %s\n", names
[idx
], u_errorName(err
));
1819 /* preflight to get maxBufferSize */
1820 actualSizes
[idx
] = 0;
1821 ucnv_safeClone(cnv
, NULL
, &actualSizes
[idx
], &err
);
1822 if(actualSizes
[idx
] > maxBufferSize
) {
1823 maxBufferSize
= actualSizes
[idx
];
1824 maxName
= names
[idx
];
1828 memset(buffer
, 0xaa, sizeof(buffer
));
1830 bufferSize
= bufferSizes
[j
];
1831 cnv2
= ucnv_safeClone(cnv
, buffer
[1], &bufferSize
, &err
);
1833 /* close the original immediately to make sure that the clone works by itself */
1836 if( actualSizes
[idx
] <= (bufferSizes
[j
] - (int32_t)ALIGNOF(UConverter
)) &&
1837 err
== U_SAFECLONE_ALLOCATED_WARNING
1839 log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names
[idx
]);
1842 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1843 if(bufferSize
<= bufferSizes
[j
]) {
1844 /* used the stack buffer */
1845 if( containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
[0]), 0xaa) ||
1846 containsAnyOtherByte(buffer
[1]+bufferSize
, (int32_t)(sizeof(buffer
)-(sizeof(buffer
[0])+bufferSize
)), 0xaa)
1848 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1849 names
[idx
], bufferSize
, bufferSizes
[j
]);
1852 /* heap-allocated the clone */
1853 if(containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
), 0xaa)) {
1854 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1855 names
[idx
], bufferSize
, bufferSizes
[j
]);
1859 pCharBuffer
= charBuffer
;
1860 pUniBuffer
= uniBuffer
;
1862 ucnv_fromUnicode(cnv2
,
1871 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err
));
1873 ucnv_toUnicode(cnv2
,
1884 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err
));
1887 pConstCharBuffer
= charBuffer
;
1888 if (uniBuffer
[0] != ucnv_getNextUChar(cnv2
, &pConstCharBuffer
, pCharBuffer
, &err
))
1890 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err
));
1896 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1897 sizeof(UConverter
), maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1898 if(maxBufferSize
> U_CNV_SAFECLONE_BUFFERSIZE
) {
1899 log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1900 maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1904 static void TestCCSID() {
1905 #if !UCONFIG_NO_LEGACY_CONVERSION
1907 UErrorCode errorCode
;
1908 int32_t ccsids
[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1911 for(i
=0; i
<UPRV_LENGTHOF(ccsids
); ++i
) {
1914 errorCode
=U_ZERO_ERROR
;
1915 cnv
=ucnv_openCCSID(ccsid
, UCNV_IBM
, &errorCode
);
1916 if(U_FAILURE(errorCode
)) {
1917 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid
, u_errorName(errorCode
));
1921 if(ccsid
!=ucnv_getCCSID(cnv
, &errorCode
)) {
1922 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid
, ucnv_getCCSID(cnv
, &errorCode
));
1925 /* skip gb18030(ccsid 1392) */
1926 if(ccsid
!= 1392 && UCNV_IBM
!=ucnv_getPlatform(cnv
, &errorCode
)) {
1927 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid
, ucnv_getPlatform(cnv
, &errorCode
));
1935 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1937 /* CHUNK_SIZE defined in common\ucnv.c: */
1938 #define CHUNK_SIZE 1024
1940 static void bug1(void);
1941 static void bug2(void);
1942 static void bug3(void);
1947 bug1(); /* Unicode intermediate buffer straddle bug */
1948 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1949 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1953 * jitterbug 932: test chunking boundary conditions in
1955 int32_t ucnv_convert(const char *toConverterName,
1956 const char *fromConverterName,
1963 * See discussions on the icu mailing list in
1964 * 2001-April with the subject "converter 'flush' question".
1966 * Bug report and test code provided by Edward J. Batutis.
1970 #if !UCONFIG_NO_LEGACY_CONVERSION
1971 char char_in
[CHUNK_SIZE
+32];
1972 char char_out
[CHUNK_SIZE
*2];
1974 /* GB 18030 equivalent of U+10000 is 90308130 */
1975 static const char test_seq
[]={ (char)0x90u
, 0x30, (char)0x81u
, 0x30 };
1977 UErrorCode err
= U_ZERO_ERROR
;
1978 int32_t i
, test_seq_len
= sizeof(test_seq
);
1981 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1982 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1983 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1984 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1985 * other Unicode sequences cause a bug since combining sequences are not supported by the
1989 for (i
= test_seq_len
; i
>= 0; i
--) {
1990 /* put character sequence into input buffer */
1991 memset(char_in
, 0x61, sizeof(char_in
)); /* GB 18030 'a' */
1992 memcpy(char_in
+ (CHUNK_SIZE
- i
), test_seq
, test_seq_len
);
1994 /* do the conversion */
1995 ucnv_convert("us-ascii", /* out */
2004 if (err
== U_TRUNCATED_CHAR_FOUND
) {
2005 /* this happens when surrogate pair straddles the intermediate buffer in
2006 * T_UConverter_fromCodepageToCodepage */
2007 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
2013 /* bug2: pre-flighting loop bug: simple overflow causes bug */
2016 /* US-ASCII "1234567890" */
2017 static const char source
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
2018 #if !UCONFIG_ONLY_HTML_CONVERSION
2019 static const char sourceUTF8
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
2020 static const char sourceUTF32
[]={ 0x00, 0x00, 0x00, 0x30,
2021 0x00, 0x00, 0x00, 0x31,
2022 0x00, 0x00, 0x00, 0x32,
2023 0x00, 0x00, 0x00, 0x33,
2024 0x00, 0x00, 0x00, 0x34,
2025 0x00, 0x00, 0x00, 0x35,
2026 0x00, 0x00, 0x00, 0x36,
2027 0x00, 0x00, 0x00, 0x37,
2028 0x00, 0x00, 0x00, 0x38,
2029 0x00, 0x00, (char)0xf0, 0x00};
2032 static char target
[5];
2034 UErrorCode err
= U_ZERO_ERROR
;
2037 /* do the conversion */
2038 size
= ucnv_convert("iso-8859-1", /* out */
2039 "us-ascii", /* in */
2047 /* bug2: size is 5, should be 10 */
2048 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size
);
2051 #if !UCONFIG_ONLY_HTML_CONVERSION
2053 /* do the conversion */
2054 size
= ucnv_convert("UTF-32BE", /* out */
2063 /* bug2: size is 5, should be 32 */
2064 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size
);
2068 /* do the conversion */
2069 size
= ucnv_convert("UTF-8", /* out */
2070 "UTF-32BE", /* in */
2074 sizeof(sourceUTF32
),
2078 /* bug2: size is 5, should be 12 */
2079 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size
);
2085 * bug3: when the characters expand going from source to target codepage
2086 * you get bug3 in addition to bug2
2090 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
2091 char char_in
[CHUNK_SIZE
*4];
2093 UErrorCode err
= U_ZERO_ERROR
;
2097 * first get the buggy size from bug2 then
2098 * compare it to buggy size with an expansion
2100 memset(char_in
, 0x61, sizeof(char_in
)); /* US-ASCII 'a' */
2102 /* do the conversion */
2103 size
= ucnv_convert("lmbcs", /* out */
2104 "us-ascii", /* in */
2111 if ( size
!= sizeof(char_in
) ) {
2113 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2114 * in the converter?), should be CHUNK_SIZE*4
2116 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2118 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in
), size
);
2122 * now do the conversion with expansion
2123 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2125 memset(char_in
, 8, sizeof(char_in
));
2128 /* do the conversion */
2129 size
= ucnv_convert("lmbcs", /* out */
2130 "us-ascii", /* in */
2137 /* expect 2X expansion */
2138 if ( size
!= sizeof(char_in
) * 2 ) {
2141 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2143 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in
) * 2, size
);
2149 convertExStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2150 const char *src
, int32_t srcLength
,
2151 const char *expectTarget
, int32_t expectTargetLength
,
2153 const char *testName
,
2154 UErrorCode expectCode
) {
2155 UChar pivotBuffer
[CHUNK_SIZE
];
2156 UChar
*pivotSource
, *pivotTarget
;
2157 const UChar
*pivotLimit
;
2159 char targetBuffer
[CHUNK_SIZE
];
2161 const char *srcLimit
, *finalSrcLimit
, *targetLimit
;
2163 int32_t targetLength
;
2167 UErrorCode errorCode
;
2170 if(chunkSize
>CHUNK_SIZE
) {
2171 chunkSize
=CHUNK_SIZE
;
2174 pivotSource
=pivotTarget
=pivotBuffer
;
2175 pivotLimit
=pivotBuffer
+chunkSize
;
2177 finalSrcLimit
=src
+srcLength
;
2178 target
=targetBuffer
;
2179 targetLimit
=targetBuffer
+chunkSize
;
2181 ucnv_resetToUnicode(srcCnv
);
2182 ucnv_resetFromUnicode(targetCnv
);
2184 errorCode
=U_ZERO_ERROR
;
2187 /* convert, streaming-style (both converters and pivot keep state) */
2189 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2190 if(src
+chunkSize
<=finalSrcLimit
) {
2191 srcLimit
=src
+chunkSize
;
2193 srcLimit
=finalSrcLimit
;
2195 ucnv_convertEx(targetCnv
, srcCnv
,
2196 &target
, targetLimit
,
2198 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotLimit
,
2199 FALSE
, flush
, &errorCode
);
2200 targetLength
=(int32_t)(target
-targetBuffer
);
2201 if(target
>targetLimit
) {
2202 log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
2203 testName
, chunkSize
, target
, targetLimit
);
2204 break; /* TODO: major problem! */
2206 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
2207 /* continue converting another chunk */
2208 errorCode
=U_ZERO_ERROR
;
2209 if(targetLength
+chunkSize
<=(int32_t)sizeof(targetBuffer
)) {
2210 targetLimit
=target
+chunkSize
;
2212 targetLimit
=targetBuffer
+(int32_t)sizeof(targetBuffer
);
2214 } else if(U_FAILURE(errorCode
)) {
2220 } else if(src
==finalSrcLimit
&& pivotSource
==pivotTarget
) {
2221 /* all consumed, now flush without input (separate from conversion for testing) */
2226 if(!(errorCode
==expectCode
|| (expectCode
==U_ZERO_ERROR
&& errorCode
==U_STRING_NOT_TERMINATED_WARNING
))) {
2227 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2228 testName
, chunkSize
, u_errorName(errorCode
), u_errorName(expectCode
));
2229 } else if(targetLength
!=expectTargetLength
) {
2230 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2231 testName
, chunkSize
, targetLength
, expectTargetLength
);
2232 } else if(memcmp(targetBuffer
, expectTarget
, targetLength
)!=0) {
2233 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2234 testName
, chunkSize
);
2239 convertExMultiStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2240 const char *src
, int32_t srcLength
,
2241 const char *expectTarget
, int32_t expectTargetLength
,
2242 const char *testName
,
2243 UErrorCode expectCode
) {
2244 convertExStreaming(srcCnv
, targetCnv
,
2246 expectTarget
, expectTargetLength
,
2247 1, testName
, expectCode
);
2248 convertExStreaming(srcCnv
, targetCnv
,
2250 expectTarget
, expectTargetLength
,
2251 3, testName
, expectCode
);
2252 convertExStreaming(srcCnv
, targetCnv
,
2254 expectTarget
, expectTargetLength
,
2255 7, testName
, expectCode
);
2258 static void TestConvertEx() {
2259 #if !UCONFIG_NO_LEGACY_CONVERSION
2260 static const uint8_t
2262 /* 4e00 30a1 ff61 0410 */
2263 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2266 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2270 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2271 * SUB, SUB, 0x40, SUB, SUB, 0x40
2273 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2276 char srcBuffer
[100], targetBuffer
[100];
2281 UChar pivotBuffer
[100];
2282 UChar
*pivotSource
, *pivotTarget
;
2284 UConverter
*cnv1
, *cnv2
;
2285 UErrorCode errorCode
;
2287 errorCode
=U_ZERO_ERROR
;
2288 cnv1
=ucnv_open("UTF-8", &errorCode
);
2289 if(U_FAILURE(errorCode
)) {
2290 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode
));
2294 cnv2
=ucnv_open("Shift-JIS", &errorCode
);
2295 if(U_FAILURE(errorCode
)) {
2296 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2301 /* test ucnv_convertEx() with streaming conversion style */
2302 convertExMultiStreaming(cnv1
, cnv2
,
2303 (const char *)utf8
, sizeof(utf8
), (const char *)shiftJIS
, sizeof(shiftJIS
),
2304 "UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2306 convertExMultiStreaming(cnv2
, cnv1
,
2307 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
),
2308 "Shift-JIS -> UTF-8", U_ZERO_ERROR
);
2310 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2311 convertExMultiStreaming(cnv1
, cnv2
,
2312 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)errorTarget
, sizeof(errorTarget
),
2313 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2315 /* test some simple conversions */
2317 /* NUL-terminated source and target */
2318 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2319 memcpy(srcBuffer
, utf8
, sizeof(utf8
));
2320 srcBuffer
[sizeof(utf8
)]=0;
2322 target
=targetBuffer
;
2323 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2324 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2325 if( errorCode
!=U_ZERO_ERROR
||
2326 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2328 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2330 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2331 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2334 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2335 errorCode
=U_AMBIGUOUS_ALIAS_WARNING
;
2336 memset(targetBuffer
, 0xff, sizeof(targetBuffer
));
2338 target
=targetBuffer
;
2339 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(shiftJIS
), &src
, NULL
,
2340 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2341 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2342 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2343 *target
!=(char)0xff ||
2344 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2346 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2347 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2351 errorCode
=U_MESSAGE_PARSE_ERROR
;
2353 target
=targetBuffer
;
2354 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2355 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2356 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2357 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2360 /* pivotLimit==pivotStart */
2361 errorCode
=U_ZERO_ERROR
;
2362 pivotSource
=pivotTarget
=pivotBuffer
;
2363 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2364 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
, TRUE
, TRUE
, &errorCode
);
2365 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2366 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode
));
2369 /* *pivotSource==NULL */
2370 errorCode
=U_ZERO_ERROR
;
2372 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2373 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2374 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2375 log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode
));
2379 errorCode
=U_ZERO_ERROR
;
2381 pivotSource
=pivotBuffer
;
2382 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2383 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2384 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2385 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode
));
2388 /* streaming conversion without a pivot buffer */
2389 errorCode
=U_ZERO_ERROR
;
2391 pivotSource
=pivotBuffer
;
2392 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2393 NULL
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, FALSE
, &errorCode
);
2394 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2395 log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode
));
2403 /* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
2404 static const char *const badUTF8
[]={
2408 /* truncated multi-byte sequences */
2445 "\xfc\x80\x80\x80\x80",
2447 /* complete sequences but non-shortest forms or out of range etc. */
2453 "\xf8\x80\x80\x80\x80",
2454 "\xfc\x80\x80\x80\x80\x80",
2459 #define ARG_CHAR_ARR_SIZE 8
2461 /* get some character that can be converted and convert it */
2462 static UBool
getTestChar(UConverter
*cnv
, const char *converterName
,
2463 char charUTF8
[4], int32_t *pCharUTF8Length
,
2464 char char0
[ARG_CHAR_ARR_SIZE
], int32_t *pChar0Length
,
2465 char char1
[ARG_CHAR_ARR_SIZE
], int32_t *pChar1Length
) {
2466 UChar utf16
[U16_MAX_LENGTH
];
2467 int32_t utf16Length
;
2469 const UChar
*utf16Source
;
2474 UErrorCode errorCode
;
2476 errorCode
=U_ZERO_ERROR
;
2477 set
=uset_open(1, 0);
2478 ucnv_getUnicodeSet(cnv
, set
, UCNV_ROUNDTRIP_SET
, &errorCode
);
2479 c
=uset_charAt(set
, uset_size(set
)/2);
2483 U16_APPEND_UNSAFE(utf16
, utf16Length
, c
);
2485 U8_APPEND_UNSAFE(charUTF8
, *pCharUTF8Length
, c
);
2489 ucnv_fromUnicode(cnv
,
2490 &target
, char0
+ARG_CHAR_ARR_SIZE
,
2491 &utf16Source
, utf16
+utf16Length
,
2492 NULL
, FALSE
, &errorCode
);
2493 *pChar0Length
=(int32_t)(target
-char0
);
2497 ucnv_fromUnicode(cnv
,
2498 &target
, char1
+ARG_CHAR_ARR_SIZE
,
2499 &utf16Source
, utf16
+utf16Length
,
2500 NULL
, FALSE
, &errorCode
);
2501 *pChar1Length
=(int32_t)(target
-char1
);
2503 if(U_FAILURE(errorCode
)) {
2504 log_err("unable to get test character for %s - %s\n", converterName
, u_errorName(errorCode
));
2510 static UBool
isOneTruncatedUTF8(const char *s
, int32_t length
) {
2513 } else if(length
==1) {
2514 return U8_IS_LEAD(s
[0]);
2516 int32_t count
=U8_COUNT_TRAIL_BYTES(s
[0]);
2518 // 2 or more bytes, but fewer than the lead byte indicates.
2519 int32_t oneLength
=0;
2520 U8_FWD_1(s
, oneLength
, length
);
2521 // Truncated if we reach the end of the string.
2522 // Not true if the lead byte and first trail byte do not start a valid sequence,
2523 // e.g., E0 80 -> oneLength=1.
2524 return oneLength
==length
;
2530 static void testFromTruncatedUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2531 char charUTF8
[4], int32_t charUTF8Length
,
2532 char char0
[8], int32_t char0Length
,
2533 char char1
[8], int32_t char1Length
) {
2534 // suppress compiler warnings about unused variables
2544 int32_t outputLength
;
2546 char invalidChars
[8];
2547 int8_t invalidLength
;
2552 UChar pivotBuffer
[8];
2553 UChar
*pivotSource
, *pivotTarget
;
2555 UErrorCode errorCode
;
2558 /* test truncated sequences */
2559 errorCode
=U_ZERO_ERROR
;
2560 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, NULL
, NULL
, &errorCode
);
2562 memcpy(utf8
, charUTF8
, charUTF8Length
);
2564 for(i
=0; i
<UPRV_LENGTHOF(badUTF8
); ++i
) {
2565 /* truncated sequence? */
2566 int32_t length
= (int32_t)strlen(badUTF8
[i
]);
2567 if(!isOneTruncatedUTF8(badUTF8
[i
], length
)) {
2571 /* assemble a string with the test character and the truncated sequence */
2572 memcpy(utf8
+charUTF8Length
, badUTF8
[i
], length
);
2573 utf8Length
=charUTF8Length
+length
;
2575 /* convert and check the invalidChars */
2578 pivotSource
=pivotTarget
=pivotBuffer
;
2579 errorCode
=U_ZERO_ERROR
;
2580 ucnv_convertEx(cnv
, utf8Cnv
,
2581 &target
, output
+sizeof(output
),
2582 &source
, utf8
+utf8Length
,
2583 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+UPRV_LENGTHOF(pivotBuffer
),
2584 TRUE
, TRUE
, /* reset & flush */
2586 outputLength
=(int32_t)(target
-output
);
2587 (void)outputLength
; /* Suppress set but not used warning. */
2588 if(errorCode
!=U_TRUNCATED_CHAR_FOUND
|| pivotSource
!=pivotBuffer
) {
2589 log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode
), converterName
, (long)i
);
2593 errorCode
=U_ZERO_ERROR
;
2594 invalidLength
=(int8_t)sizeof(invalidChars
);
2595 ucnv_getInvalidChars(utf8Cnv
, invalidChars
, &invalidLength
, &errorCode
);
2596 if(invalidLength
!=length
|| 0!=memcmp(invalidChars
, badUTF8
[i
], length
)) {
2597 log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName
, (long)i
);
2602 static void testFromBadUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2603 char charUTF8
[4], int32_t charUTF8Length
,
2604 char char0
[8], int32_t char0Length
,
2605 char char1
[8], int32_t char1Length
) {
2606 char utf8
[600], expect
[600];
2607 int32_t utf8Length
, expectLength
;
2611 UErrorCode errorCode
;
2614 errorCode
=U_ZERO_ERROR
;
2615 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_SKIP
, NULL
, NULL
, NULL
, &errorCode
);
2618 * assemble an input string with the test character between each
2620 * and an expected string with repeated test character output
2622 memcpy(utf8
, charUTF8
, charUTF8Length
);
2623 utf8Length
=charUTF8Length
;
2625 memcpy(expect
, char0
, char0Length
);
2626 expectLength
=char0Length
;
2628 for(i
=0; i
<UPRV_LENGTHOF(badUTF8
); ++i
) {
2629 int32_t length
= (int32_t)strlen(badUTF8
[i
]);
2630 memcpy(utf8
+utf8Length
, badUTF8
[i
], length
);
2633 memcpy(utf8
+utf8Length
, charUTF8
, charUTF8Length
);
2634 utf8Length
+=charUTF8Length
;
2636 memcpy(expect
+expectLength
, char1
, char1Length
);
2637 expectLength
+=char1Length
;
2640 /* expect that each bad UTF-8 sequence is detected and skipped */
2641 strcpy(testName
, "from bad UTF-8 to ");
2642 strcat(testName
, converterName
);
2644 convertExMultiStreaming(utf8Cnv
, cnv
,
2646 expect
, expectLength
,
2651 /* Test illegal UTF-8 input. */
2652 static void TestConvertExFromUTF8() {
2653 static const char *const converterNames
[]={
2654 #if !UCONFIG_NO_LEGACY_CONVERSION
2663 UConverter
*utf8Cnv
, *cnv
;
2664 UErrorCode errorCode
;
2667 /* fromUnicode versions of some character, from initial state and later */
2668 char charUTF8
[4], char0
[8], char1
[8];
2669 int32_t charUTF8Length
, char0Length
, char1Length
;
2671 errorCode
=U_ZERO_ERROR
;
2672 utf8Cnv
=ucnv_open("UTF-8", &errorCode
);
2673 if(U_FAILURE(errorCode
)) {
2674 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode
));
2678 for(i
=0; i
<UPRV_LENGTHOF(converterNames
); ++i
) {
2679 errorCode
=U_ZERO_ERROR
;
2680 cnv
=ucnv_open(converterNames
[i
], &errorCode
);
2681 if(U_FAILURE(errorCode
)) {
2682 log_data_err("unable to open %s converter - %s\n", converterNames
[i
], u_errorName(errorCode
));
2685 if(!getTestChar(cnv
, converterNames
[i
], charUTF8
, &charUTF8Length
, char0
, &char0Length
, char1
, &char1Length
)) {
2688 testFromTruncatedUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2689 testFromBadUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2692 ucnv_close(utf8Cnv
);
2695 static void TestConvertExFromUTF8_C5F0() {
2696 static const char *const converterNames
[]={
2697 #if !UCONFIG_NO_LEGACY_CONVERSION
2706 UConverter
*utf8Cnv
, *cnv
;
2707 UErrorCode errorCode
;
2710 static const char bad_utf8
[2]={ (char)0xC5, (char)0xF0 };
2711 /* Expect "��" (2x U+FFFD as decimal NCRs) */
2712 static const char twoNCRs
[16]={
2713 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B,
2714 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B
2716 static const char twoFFFD
[6]={
2717 (char)0xef, (char)0xbf, (char)0xbd,
2718 (char)0xef, (char)0xbf, (char)0xbd
2720 const char *expected
;
2721 int32_t expectedLength
;
2722 char dest
[20]; /* longer than longest expectedLength */
2727 UChar pivotBuffer
[128];
2728 UChar
*pivotSource
, *pivotTarget
;
2730 errorCode
=U_ZERO_ERROR
;
2731 utf8Cnv
=ucnv_open("UTF-8", &errorCode
);
2732 if(U_FAILURE(errorCode
)) {
2733 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode
));
2737 for(i
=0; i
<UPRV_LENGTHOF(converterNames
); ++i
) {
2738 errorCode
=U_ZERO_ERROR
;
2739 cnv
=ucnv_open(converterNames
[i
], &errorCode
);
2740 ucnv_setFromUCallBack(cnv
, UCNV_FROM_U_CALLBACK_ESCAPE
, UCNV_ESCAPE_XML_DEC
,
2741 NULL
, NULL
, &errorCode
);
2742 if(U_FAILURE(errorCode
)) {
2743 log_data_err("unable to open %s converter - %s\n",
2744 converterNames
[i
], u_errorName(errorCode
));
2749 uprv_memset(dest
, 9, sizeof(dest
));
2750 if(i
==UPRV_LENGTHOF(converterNames
)-1) {
2751 /* conversion to UTF-8 yields two U+FFFD directly */
2755 /* conversion to a non-Unicode charset yields two NCRs */
2762 pivotSource
=pivotTarget
=pivotBuffer
;
2765 &target
, dest
+expectedLength
,
2766 &src
, bad_utf8
+sizeof(bad_utf8
),
2767 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+UPRV_LENGTHOF(pivotBuffer
),
2768 TRUE
, TRUE
, &errorCode
);
2769 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
|| src
!=bad_utf8
+2 ||
2770 target
!=dest
+expectedLength
|| 0!=uprv_memcmp(dest
, expected
, expectedLength
) ||
2771 dest
[expectedLength
]!=9
2773 log_err("ucnv_convertEx(UTF-8 C5 F0 -> %s/decimal NCRs) failed\n", converterNames
[i
]);
2777 ucnv_close(utf8Cnv
);
2781 TestConvertAlgorithmic() {
2782 #if !UCONFIG_NO_LEGACY_CONVERSION
2783 static const uint8_t
2785 /* 4e00 30a1 ff61 0410 */
2786 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2789 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2793 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2794 * SUB, SUB, 0x40, SUB, SUB, 0x40
2796 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2799 0xfe, 0xff /* BOM only, no text */
2801 #if !UCONFIG_ONLY_HTML_CONVERSION
2802 static const uint8_t utf32
[]={
2803 0xff, 0xfe, 0, 0 /* BOM only, no text */
2807 char target
[100], utf8NUL
[100], shiftJISNUL
[100];
2810 UErrorCode errorCode
;
2814 errorCode
=U_ZERO_ERROR
;
2815 cnv
=ucnv_open("Shift-JIS", &errorCode
);
2816 if(U_FAILURE(errorCode
)) {
2817 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2822 memcpy(utf8NUL
, utf8
, sizeof(utf8
));
2823 utf8NUL
[sizeof(utf8
)]=0;
2824 memcpy(shiftJISNUL
, shiftJIS
, sizeof(shiftJIS
));
2825 shiftJISNUL
[sizeof(shiftJIS
)]=0;
2828 * The to/from algorithmic convenience functions share a common implementation,
2829 * so we need not test all permutations of them.
2832 /* length in, not terminated out */
2833 errorCode
=U_ZERO_ERROR
;
2834 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF8
, target
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
), &errorCode
);
2835 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2836 length
!=sizeof(shiftJIS
) ||
2837 memcmp(target
, shiftJIS
, length
)!=0
2839 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2840 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2843 /* terminated in and out */
2844 memset(target
, 0x55, sizeof(target
));
2845 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2846 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, -1, &errorCode
);
2847 if( errorCode
!=U_ZERO_ERROR
||
2848 length
!=sizeof(utf8
) ||
2849 memcmp(target
, utf8
, length
)!=0
2851 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2852 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2855 /* empty string, some target buffer */
2856 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2857 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, 0, &errorCode
);
2858 if( errorCode
!=U_ZERO_ERROR
||
2861 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2862 u_errorName(errorCode
), length
);
2865 /* pseudo-empty string, no target buffer */
2866 errorCode
=U_ZERO_ERROR
;
2867 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2868 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2871 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2872 u_errorName(errorCode
), length
);
2875 #if !UCONFIG_ONLY_HTML_CONVERSION
2876 errorCode
=U_ZERO_ERROR
;
2877 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF32
, target
, 0, (const char *)utf32
, 4, &errorCode
);
2878 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2881 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2882 u_errorName(errorCode
), length
);
2887 errorCode
=U_MESSAGE_PARSE_ERROR
;
2888 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2889 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2890 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2894 errorCode
=U_ZERO_ERROR
;
2895 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, NULL
, 2, &errorCode
);
2896 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2897 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode
));
2900 /* illegal alg. type */
2901 errorCode
=U_ZERO_ERROR
;
2902 length
=ucnv_fromAlgorithmic(cnv
, (UConverterType
)99, target
, 0, (const char *)utf16
, 2, &errorCode
);
2903 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2904 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode
));
2910 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
2911 static void TestLMBCSMaxChar(void) {
2912 static const struct {
2916 /* some non-LMBCS converters - perfect test setup here */
2927 { 4, "IMAP-mailbox-name"},
2930 { 1, "windows-1256"},
2942 { 8, "ISO-2022-KR"},
2943 { 6, "ISO-2022-JP"},
2944 { 8, "ISO-2022-CN"},
2962 for (idx
= 0; idx
< UPRV_LENGTHOF(converter
); idx
++) {
2963 UErrorCode status
= U_ZERO_ERROR
;
2964 UConverter
*cnv
= cnv_open(converter
[idx
].name
, &status
);
2965 if (U_FAILURE(status
)) {
2968 if (converter
[idx
].maxSize
!= ucnv_getMaxCharSize(cnv
)) {
2969 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2970 converter
[idx
].name
, converter
[idx
].maxSize
, ucnv_getMaxCharSize(cnv
));
2975 /* mostly test that the macro compiles */
2976 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2977 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2982 static void TestJ1968(void) {
2983 UErrorCode err
= U_ZERO_ERROR
;
2985 char myConvName
[] = "My really really really really really really really really really really really"
2986 " really really really really really really really really really really really"
2987 " really really really really really really really really long converter name";
2988 UChar myConvNameU
[sizeof(myConvName
)];
2990 u_charsToUChars(myConvName
, myConvNameU
, sizeof(myConvName
));
2993 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
+1] = 0;
2994 cnv
= ucnv_openU(myConvNameU
, &err
);
2995 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2996 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3000 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
3001 cnv
= ucnv_openU(myConvNameU
, &err
);
3002 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3003 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3007 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
3008 cnv
= ucnv_openU(myConvNameU
, &err
);
3009 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3010 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3017 cnv
= ucnv_open(myConvName
, &err
);
3018 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3019 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3023 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = ',';
3024 cnv
= ucnv_open(myConvName
, &err
);
3025 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3026 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3030 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
3031 cnv
= ucnv_open(myConvName
, &err
);
3032 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3033 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3037 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
3038 strncpy(myConvName
+ UCNV_MAX_CONVERTER_NAME_LENGTH
, "locale=", 7);
3039 cnv
= ucnv_open(myConvName
, &err
);
3040 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3041 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3044 /* The comma isn't really a part of the converter name. */
3046 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
3047 cnv
= ucnv_open(myConvName
, &err
);
3048 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3049 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3053 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ' ';
3054 cnv
= ucnv_open(myConvName
, &err
);
3055 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3056 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
3060 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
3061 cnv
= ucnv_open(myConvName
, &err
);
3062 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
3063 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
3068 #if !UCONFIG_NO_LEGACY_CONVERSION
3070 testSwap(const char *name
, UBool swap
) {
3072 * Test Unicode text.
3073 * Contains characters that are the highest for some of the
3074 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
3075 * tables copies the entire tables.
3077 static const UChar text
[]={
3078 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
3081 UChar uNormal
[32], uSwapped
[32];
3082 char normal
[32], swapped
[32];
3086 int32_t i
, normalLength
, swappedLength
;
3090 const char *swappedName
;
3091 UConverter
*cnv
, *swapCnv
;
3092 UErrorCode errorCode
;
3094 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
3096 /* open both the normal and the LF/NL-swapping converters */
3097 strcpy(swapped
, name
);
3098 strcat(swapped
, UCNV_SWAP_LFNL_OPTION_STRING
);
3100 errorCode
=U_ZERO_ERROR
;
3101 swapCnv
=ucnv_open(swapped
, &errorCode
);
3102 cnv
=ucnv_open(name
, &errorCode
);
3103 if(U_FAILURE(errorCode
)) {
3104 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name
, swapped
, u_errorName(errorCode
));
3108 /* the name must contain the swap option if and only if we expect the converter to swap */
3109 swappedName
=ucnv_getName(swapCnv
, &errorCode
);
3110 if(U_FAILURE(errorCode
)) {
3111 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name
, u_errorName(errorCode
));
3115 pc
=strstr(swappedName
, UCNV_SWAP_LFNL_OPTION_STRING
);
3116 if(swap
!= (pc
!=NULL
)) {
3117 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name
, swappedName
, swap
);
3121 /* convert to EBCDIC */
3124 ucnv_fromUnicode(cnv
, &pc
, normal
+UPRV_LENGTHOF(normal
), &pcu
, text
+UPRV_LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3125 normalLength
=(int32_t)(pc
-normal
);
3129 ucnv_fromUnicode(swapCnv
, &pc
, swapped
+UPRV_LENGTHOF(swapped
), &pcu
, text
+UPRV_LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3130 swappedLength
=(int32_t)(pc
-swapped
);
3132 if(U_FAILURE(errorCode
)) {
3133 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name
, u_errorName(errorCode
));
3137 /* compare EBCDIC output */
3138 if(normalLength
!=swappedLength
) {
3139 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3142 for(i
=0; i
<normalLength
; ++i
) {
3143 /* swap EBCDIC LF/NL for comparison */
3148 } else if(c
==0x25) {
3154 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name
, i
, (uint8_t)swapped
[i
]);
3159 /* convert back to Unicode (may not roundtrip) */
3162 ucnv_toUnicode(cnv
, &pu
, uNormal
+UPRV_LENGTHOF(uNormal
), (const char **)&pc
, normal
+normalLength
, NULL
, TRUE
, &errorCode
);
3163 normalLength
=(int32_t)(pu
-uNormal
);
3167 ucnv_toUnicode(swapCnv
, &pu
, uSwapped
+UPRV_LENGTHOF(uSwapped
), (const char **)&pc
, normal
+swappedLength
, NULL
, TRUE
, &errorCode
);
3168 swappedLength
=(int32_t)(pu
-uSwapped
);
3170 if(U_FAILURE(errorCode
)) {
3171 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name
, u_errorName(errorCode
));
3175 /* compare EBCDIC output */
3176 if(normalLength
!=swappedLength
) {
3177 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3180 for(i
=0; i
<normalLength
; ++i
) {
3181 /* swap EBCDIC LF/NL for comparison */
3186 } else if(u
==0x85) {
3191 if(u
!=uSwapped
[i
]) {
3192 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name
, i
, uSwapped
[i
]);
3200 ucnv_close(swapCnv
);
3204 TestEBCDICSwapLFNL() {
3205 static const struct {
3210 { "ibm-1047", TRUE
},
3211 { "ibm-1140", TRUE
},
3212 { "ibm-930", TRUE
},
3213 { "iso-8859-3", FALSE
}
3218 for(i
=0; i
<UPRV_LENGTHOF(tests
); ++i
) {
3219 testSwap(tests
[i
].name
, tests
[i
].swap
);
3224 TestEBCDICSwapLFNL() {
3225 /* test nothing... */
3229 static void TestFromUCountPending(){
3230 #if !UCONFIG_NO_LEGACY_CONVERSION
3231 UErrorCode status
= U_ZERO_ERROR
;
3232 /* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
3233 static const struct {
3237 }fromUnicodeTests
[] = {
3240 {{ 0xdbc4, 0xde34, 0xd84d},3,1},
3241 {{ 0xdbc4, 0xde34, 0xd900},3,3},
3244 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3245 if(U_FAILURE(status
)){
3246 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3249 for(i
=0; i
<UPRV_LENGTHOF(fromUnicodeTests
); ++i
) {
3252 char* targetLimit
= target
+ 10;
3253 const UChar
* source
= fromUnicodeTests
[i
].input
;
3254 const UChar
* sourceLimit
= source
+ fromUnicodeTests
[i
].len
;
3257 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3258 len
= ucnv_fromUCountPending(cnv
, &status
);
3259 if(U_FAILURE(status
)){
3260 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3261 status
= U_ZERO_ERROR
;
3264 if(len
!= fromUnicodeTests
[i
].exp
){
3265 log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
3268 status
= U_ZERO_ERROR
;
3271 * The converter has to read the tail before it knows that
3272 * only head alone matches.
3273 * At the end, the output for head will overflow the target,
3274 * middle will be pending, and tail will not have been consumed.
3277 \U00101234 -> x (<U101234> \x07 |0)
3278 \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
3279 \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
3280 \U00060007 -> unassigned
3282 static const UChar head
[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
3283 static const UChar middle
[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
3284 static const UChar tail
[] = {0xDC07,0x0000};/* second half of \U00060007 */
3287 char* targetLimit
= target
+ 2; /* expect overflow from converting \U00101234\U00050005 */
3288 const UChar
* source
= head
;
3289 const UChar
* sourceLimit
= source
+ u_strlen(head
);
3292 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3293 len
= ucnv_fromUCountPending(cnv
, &status
);
3294 if(U_FAILURE(status
)){
3295 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3296 status
= U_ZERO_ERROR
;
3299 log_err("ucnv_fromUInputHeld did not return correct length for head\n");
3302 sourceLimit
= source
+ u_strlen(middle
);
3303 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3304 len
= ucnv_fromUCountPending(cnv
, &status
);
3305 if(U_FAILURE(status
)){
3306 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3307 status
= U_ZERO_ERROR
;
3310 log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
3313 sourceLimit
= source
+ u_strlen(tail
);
3314 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3315 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3316 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3318 status
= U_ZERO_ERROR
;
3319 len
= ucnv_fromUCountPending(cnv
, &status
);
3320 /* middle[1] is pending, tail has not been consumed */
3321 if(U_FAILURE(status
)){
3322 log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status
));
3325 log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
3333 TestToUCountPending(){
3334 #if !UCONFIG_NO_LEGACY_CONVERSION
3335 UErrorCode status
= U_ZERO_ERROR
;
3336 static const struct {
3340 }toUnicodeTests
[] = {
3342 {{0x05, 0x01, 0x02},3,3},
3344 {{0x07, 0x00, 0x01, 0x02},4,4},
3348 UConverterToUCallback
*oldToUAction
= NULL
;
3349 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3350 if(U_FAILURE(status
)){
3351 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3354 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3355 for(i
=0; i
<UPRV_LENGTHOF(toUnicodeTests
); ++i
) {
3357 UChar
* target
= tgt
;
3358 UChar
* targetLimit
= target
+ 20;
3359 const char* source
= toUnicodeTests
[i
].input
;
3360 const char* sourceLimit
= source
+ toUnicodeTests
[i
].len
;
3363 ucnv_toUnicode(cnv
, &target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3364 len
= ucnv_toUCountPending(cnv
,&status
);
3365 if(U_FAILURE(status
)){
3366 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3367 status
= U_ZERO_ERROR
;
3370 if(len
!= toUnicodeTests
[i
].exp
){
3371 log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
3374 status
= U_ZERO_ERROR
;
3379 * The converter has to read the tail before it knows that
3380 * only head alone matches.
3381 * At the end, the output for head will overflow the target,
3382 * mid will be pending, and tail will not have been consumed.
3384 char head
[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
3385 char mid
[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
3386 char tail
[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
3388 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
3389 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
3390 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
3391 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
3394 UChar
* target
= tgt
;
3395 UChar
* targetLimit
= target
+ 1; /* expect overflow from converting */
3396 const char* source
= head
;
3397 const char* sourceLimit
= source
+ strlen(head
);
3399 cnv
= ucnv_openPackage(loadTestData(&status
), "test4", &status
);
3400 if(U_FAILURE(status
)){
3401 log_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3404 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3405 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3406 len
= ucnv_toUCountPending(cnv
,&status
);
3407 if(U_FAILURE(status
)){
3408 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3411 log_err("Did not get the expected len for head.\n");
3414 sourceLimit
= source
+strlen(mid
);
3415 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3416 len
= ucnv_toUCountPending(cnv
,&status
);
3417 if(U_FAILURE(status
)){
3418 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3421 log_err("Did not get the expected len for mid.\n");
3425 sourceLimit
= source
+strlen(tail
);
3426 targetLimit
= target
;
3427 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3428 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3429 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3431 status
= U_ZERO_ERROR
;
3432 len
= ucnv_toUCountPending(cnv
,&status
);
3433 /* mid[4] is pending, tail has not been consumed */
3434 if(U_FAILURE(status
)){
3435 log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status
));
3438 log_err("Did not get the expected len for tail.\n");
3445 static void TestOneDefaultNameChange(const char *name
, const char *expected
) {
3446 UErrorCode status
= U_ZERO_ERROR
;
3448 ucnv_setDefaultName(name
);
3449 if(strcmp(ucnv_getDefaultName(), expected
)==0)
3450 log_verbose("setDefaultName of %s works.\n", name
);
3452 log_err("setDefaultName of %s failed\n", name
);
3453 cnv
=ucnv_open(NULL
, &status
);
3454 if (U_FAILURE(status
) || cnv
== NULL
) {
3455 log_err("opening the default converter of %s failed\n", name
);
3458 if(strcmp(ucnv_getName(cnv
, &status
), expected
)==0)
3459 log_verbose("ucnv_getName of %s works.\n", name
);
3461 log_err("ucnv_getName of %s failed\n", name
);
3465 static void TestDefaultName(void) {
3466 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
3467 static char defaultName
[UCNV_MAX_CONVERTER_NAME_LENGTH
+ 1];
3468 strcpy(defaultName
, ucnv_getDefaultName());
3470 log_verbose("getDefaultName returned %s\n", defaultName
);
3472 /*change the default name by setting it */
3473 TestOneDefaultNameChange("UTF-8", "UTF-8");
3474 #if U_CHARSET_IS_UTF8
3475 TestOneDefaultNameChange("ISCII,version=1", "UTF-8");
3476 TestOneDefaultNameChange("ISCII,version=2", "UTF-8");
3477 TestOneDefaultNameChange("ISO-8859-1", "UTF-8");
3479 # if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
3480 TestOneDefaultNameChange("ISCII,version=1", "ISCII,version=1");
3481 TestOneDefaultNameChange("ISCII,version=2", "ISCII,version=2");
3483 TestOneDefaultNameChange("ISO-8859-1", "ISO-8859-1");
3486 /*set the default name back*/
3487 ucnv_setDefaultName(defaultName
);
3490 /* Test that ucnv_compareNames() matches names according to spec. ----------- */
3504 compareNames(const char **names
) {
3505 const char *relation
, *name1
, *name2
;
3509 if(*relation
=='=') {
3511 } else if(*relation
=='<') {
3521 while((name2
=*names
++)!=NULL
) {
3522 result
=ucnv_compareNames(name1
, name2
);
3523 if(sign(result
)!=rel
) {
3524 log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1
, name2
, result
, rel
);
3531 TestCompareNames() {
3532 static const char *equalUTF8
[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL
};
3533 static const char *equalIBM
[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL
};
3534 static const char *lessMac
[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL
};
3535 static const char *lessUTF080
[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL
};
3537 compareNames(equalUTF8
);
3538 compareNames(equalIBM
);
3539 compareNames(lessMac
);
3540 compareNames(lessUTF080
);
3545 static const UChar surrogate
[1]={ 0xd900 };
3548 static const UChar sub
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3549 static const char subChars
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3551 UErrorCode errorCode
;
3555 /* UTF-16/32: test that the BOM is output before the sub character */
3556 errorCode
=U_ZERO_ERROR
;
3557 cnv
=ucnv_open("UTF-16", &errorCode
);
3558 if(U_FAILURE(errorCode
)) {
3559 log_data_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode
));
3562 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3564 if(U_FAILURE(errorCode
) ||
3566 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3568 log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
3571 errorCode
=U_ZERO_ERROR
;
3572 cnv
=ucnv_open("UTF-32", &errorCode
);
3573 if(U_FAILURE(errorCode
)) {
3574 log_data_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode
));
3577 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3579 if(U_FAILURE(errorCode
) ||
3581 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3583 log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
3586 /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
3587 errorCode
=U_ZERO_ERROR
;
3588 cnv
=ucnv_open("ISO-8859-1", &errorCode
);
3589 if(U_FAILURE(errorCode
)) {
3590 log_data_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode
));
3593 ucnv_setSubstString(cnv
, sub
, UPRV_LENGTHOF(sub
), &errorCode
);
3594 if(U_FAILURE(errorCode
)) {
3595 log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode
));
3597 len8
= sizeof(buffer
);
3598 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3599 /* Stateless converter, we expect the string converted to charset bytes. */
3600 if(U_FAILURE(errorCode
) || len8
!=sizeof(subChars
) || 0!=uprv_memcmp(buffer
, subChars
, len8
)) {
3601 log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode
));
3606 #if !UCONFIG_NO_LEGACY_CONVERSION
3607 errorCode
=U_ZERO_ERROR
;
3608 cnv
=ucnv_open("HZ", &errorCode
);
3609 if(U_FAILURE(errorCode
)) {
3610 log_data_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode
));
3613 ucnv_setSubstString(cnv
, sub
, UPRV_LENGTHOF(sub
), &errorCode
);
3614 if(U_FAILURE(errorCode
)) {
3615 log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode
));
3617 len8
= sizeof(buffer
);
3618 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3619 /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
3620 if(U_FAILURE(errorCode
) || len8
!=0) {
3621 log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode
));
3627 * Further testing of ucnv_setSubstString() is done via intltest convert.
3628 * We do not test edge cases of illegal arguments and similar because the
3629 * function implementation uses all of its parameters in calls to other
3630 * functions with UErrorCode parameters.
3635 InvalidArguments() {
3637 UErrorCode errorCode
;
3638 char charBuffer
[2] = {1, 1};
3639 char ucharAsCharBuffer
[2] = {2, 2};
3640 char *charsPtr
= charBuffer
;
3641 UChar
*ucharsPtr
= (UChar
*)ucharAsCharBuffer
;
3642 UChar
*ucharsBadPtr
= (UChar
*)(ucharAsCharBuffer
+ 1);
3644 errorCode
=U_ZERO_ERROR
;
3645 cnv
=ucnv_open("UTF-8", &errorCode
);
3646 if(U_FAILURE(errorCode
)) {
3647 log_err("ucnv_open() failed - %s\n", u_errorName(errorCode
));
3651 errorCode
=U_ZERO_ERROR
;
3652 /* This one should fail because an incomplete UChar is being passed in */
3653 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsPtr
, ucharsBadPtr
, NULL
, TRUE
, &errorCode
);
3654 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3655 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3658 errorCode
=U_ZERO_ERROR
;
3659 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3660 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsBadPtr
, ucharsPtr
, NULL
, TRUE
, &errorCode
);
3661 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3662 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3665 errorCode
=U_ZERO_ERROR
;
3666 /* This one should fail because an incomplete UChar is being passed in */
3667 ucnv_toUnicode(cnv
, &ucharsPtr
, ucharsBadPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3668 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3669 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3672 errorCode
=U_ZERO_ERROR
;
3673 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3674 ucnv_toUnicode(cnv
, &ucharsBadPtr
, ucharsPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3675 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3676 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3679 if (charBuffer
[0] != 1 || charBuffer
[1] != 1
3680 || ucharAsCharBuffer
[0] != 2 || ucharAsCharBuffer
[1] != 2)
3682 log_err("Data was incorrectly written to buffers\n");
3688 static void TestGetName() {
3689 static const char *const names
[] = {
3690 "Unicode", "UTF-16",
3691 "UnicodeBigUnmarked", "UTF-16BE",
3692 "UnicodeBig", "UTF-16BE,version=1",
3693 "UnicodeLittleUnmarked", "UTF-16LE",
3694 "UnicodeLittle", "UTF-16LE,version=1",
3695 "x-UTF-16LE-BOM", "UTF-16LE,version=1"
3698 for(i
= 0; i
< UPRV_LENGTHOF(names
); i
+= 2) {
3699 UErrorCode errorCode
= U_ZERO_ERROR
;
3700 UConverter
*cnv
= ucnv_open(names
[i
], &errorCode
);
3701 if(U_SUCCESS(errorCode
)) {
3702 const char *name
= ucnv_getName(cnv
, &errorCode
);
3703 if(U_FAILURE(errorCode
) || 0 != strcmp(name
, names
[i
+1])) {
3704 log_err("ucnv_getName(%s) = %s != %s -- %s\n",
3705 names
[i
], name
, names
[i
+1], u_errorName(errorCode
));
3712 static void TestUTFBOM() {
3713 static const UChar a16
[] = { 0x61 };
3714 static const char *const names
[] = {
3722 static const uint8_t expected
[][5] = {
3724 { 4, 0xfe, 0xff, 0, 0x61 },
3725 { 4, 0xfe, 0xff, 0, 0x61 },
3727 { 4, 0xff, 0xfe, 0x61, 0 },
3728 { 4, 0xff, 0xfe, 0x61, 0 },
3732 { 4, 0xfe, 0xff, 0, 0x61 },
3735 { 4, 0xff, 0xfe, 0x61, 0 }
3741 for(i
= 0; i
< UPRV_LENGTHOF(names
); ++i
) {
3742 UErrorCode errorCode
= U_ZERO_ERROR
;
3743 UConverter
*cnv
= ucnv_open(names
[i
], &errorCode
);
3745 const uint8_t *exp
= expected
[i
];
3746 if (U_FAILURE(errorCode
)) {
3747 log_err_status(errorCode
, "Unable to open converter: %s got error code: %s\n", names
[i
], u_errorName(errorCode
));
3750 length
= ucnv_fromUChars(cnv
, bytes
, (int32_t)sizeof(bytes
), a16
, 1, &errorCode
);
3752 if(U_FAILURE(errorCode
) || length
!= exp
[0] || 0 != memcmp(bytes
, exp
+1, length
)) {
3753 log_err("unexpected %s BOM writing behavior -- %s\n",
3754 names
[i
], u_errorName(errorCode
));