1 /********************************************************************
3 * Copyright (c) 1997-2008, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
10 * Modification History:
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
19 #include "unicode/uloc.h"
20 #include "unicode/ucnv.h"
21 #include "unicode/ucnv_err.h"
22 #include "unicode/putil.h"
23 #include "unicode/uset.h"
24 #include "unicode/ustring.h"
25 #include "ucnv_bld.h" /* for sizeof(UConverter) */
26 #include "cmemory.h" /* for UAlignedMemory */
30 /* for not including "cstring.h" -begin*/
32 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2)
34 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2)
36 # define ctest_stricmp(str1, str2) T_CString_stricmp(str1, str2)
40 T_CString_stricmp(const char *str1
, const char *str2
) {
47 } else if(str2
==NULL
) {
50 /* compare non-NULL strings lexically with lowercase */
54 c1
=(unsigned char)*str1
;
55 c2
=(unsigned char)*str2
;
65 /* compare non-zero characters with lowercase */
66 rc
=(int)(unsigned char)tolower(c1
)-(int)(unsigned char)tolower(c2
);
76 /* for not including "cstring.h" -end*/
78 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
80 #define NUM_CODEPAGE 1
81 #define MAX_FILE_LEN 1024*20
82 #define UCS_FILE_NAME_SIZE 512
84 /*returns an action other than the one provided*/
85 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
);
86 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
);
89 cnv_open(const char *name
, UErrorCode
*pErrorCode
) {
90 if(name
!=NULL
&& name
[0]=='*') {
91 return ucnv_openPackage(loadTestData(pErrorCode
), name
+1, pErrorCode
);
93 return ucnv_open(name
, pErrorCode
);
98 static void ListNames(void);
99 static void TestFlushCache(void);
100 static void TestDuplicateAlias(void);
101 static void TestCCSID(void);
102 static void TestJ932(void);
103 static void TestJ1968(void);
104 static void TestLMBCSMaxChar(void);
106 #if !UCONFIG_NO_LEGACY_CONVERSION
107 static void TestConvertSafeCloneCallback(void);
110 static void TestEBCDICSwapLFNL(void);
111 static void TestConvertEx(void);
112 static void TestConvertExFromUTF8(void);
113 static void TestConvertAlgorithmic(void);
114 void TestDefaultConverterError(void); /* defined in cctest.c */
115 static void TestToUCountPending(void);
116 static void TestFromUCountPending(void);
117 static void TestDefaultName(void);
118 static void TestCompareNames(void);
119 static void TestSubstString(void);
120 static void InvalidArguments(void);
122 void addTestConvert(TestNode
** root
);
124 void addTestConvert(TestNode
** root
)
126 addTest(root
, &ListNames
, "tsconv/ccapitst/ListNames");
127 addTest(root
, &TestConvert
, "tsconv/ccapitst/TestConvert");
128 addTest(root
, &TestFlushCache
, "tsconv/ccapitst/TestFlushCache");
129 addTest(root
, &TestAlias
, "tsconv/ccapitst/TestAlias");
130 addTest(root
, &TestDuplicateAlias
, "tsconv/ccapitst/TestDuplicateAlias");
131 addTest(root
, &TestConvertSafeClone
, "tsconv/ccapitst/TestConvertSafeClone");
132 #if !UCONFIG_NO_LEGACY_CONVERSION
133 addTest(root
, &TestConvertSafeCloneCallback
,"tsconv/ccapitst/TestConvertSafeCloneCallback");
135 addTest(root
, &TestCCSID
, "tsconv/ccapitst/TestCCSID");
136 addTest(root
, &TestJ932
, "tsconv/ccapitst/TestJ932");
137 addTest(root
, &TestJ1968
, "tsconv/ccapitst/TestJ1968");
138 addTest(root
, &TestLMBCSMaxChar
, "tsconv/ccapitst/TestLMBCSMaxChar");
139 addTest(root
, &TestEBCDICSwapLFNL
, "tsconv/ccapitst/TestEBCDICSwapLFNL");
140 addTest(root
, &TestConvertEx
, "tsconv/ccapitst/TestConvertEx");
141 addTest(root
, &TestConvertExFromUTF8
, "tsconv/ccapitst/TestConvertExFromUTF8");
142 addTest(root
, &TestConvertAlgorithmic
, "tsconv/ccapitst/TestConvertAlgorithmic");
143 addTest(root
, &TestDefaultConverterError
, "tsconv/ccapitst/TestDefaultConverterError");
144 addTest(root
, &TestToUCountPending
, "tsconv/ccapitst/TestToUCountPending");
145 addTest(root
, &TestFromUCountPending
, "tsconv/ccapitst/TestFromUCountPending");
146 addTest(root
, &TestDefaultName
, "tsconv/ccapitst/TestDefaultName");
147 addTest(root
, &TestCompareNames
, "tsconv/ccapitst/TestCompareNames");
148 addTest(root
, &TestSubstString
, "tsconv/ccapitst/TestSubstString");
149 addTest(root
, &InvalidArguments
, "tsconv/ccapitst/InvalidArguments");
152 static void ListNames(void) {
153 UErrorCode err
= U_ZERO_ERROR
;
154 int32_t testLong1
= 0;
155 const char* available_conv
;
156 UEnumeration
*allNamesEnum
= NULL
;
157 int32_t allNamesCount
= 0;
160 log_verbose("Testing ucnv_openAllNames()...");
161 allNamesEnum
= ucnv_openAllNames(&err
);
163 log_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err
));
166 const char *string
= NULL
;
170 allNamesCount
= uenum_count(allNamesEnum
, &err
);
171 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
173 log_verbose("read \"%s\", length %i\n", string
, len
);
175 if (U_FAILURE(err
)) {
176 log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err
));
179 uenum_reset(allNamesEnum
, &err
);
180 while ((string
= uenum_next(allNamesEnum
, &len
, &err
))) {
182 ucnv_close(ucnv_open(string
, &err
));
183 log_verbose("read \"%s\", length %i (%s)\n", string
, len
, U_SUCCESS(err
) ? "available" : "unavailable");
186 if (count1
!= count2
) {
187 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
190 uenum_close(allNamesEnum
);
193 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
195 log_verbose("Testing ucnv_countAvailable()...");
197 testLong1
=ucnv_countAvailable();
198 log_info("Number of available codepages: %d/%d\n", testLong1
, allNamesCount
);
200 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
202 available_conv
= ucnv_getAvailableName(testLong1
);
203 /*test ucnv_getAvailableName with err condition*/
204 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
205 available_conv
= ucnv_getAvailableName(-1);
206 if(available_conv
!= NULL
){
207 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
210 /* Test ucnv_countAliases() etc. */
211 count
= ucnv_countAliases("utf-8", &err
);
213 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err
));
214 } else if(count
<= 0) {
215 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count
);
217 /* try to get the aliases individually */
219 alias
= ucnv_getAlias("utf-8", 0, &err
);
221 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err
));
222 } else if(strcmp("UTF-8", alias
) != 0) {
223 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias
);
226 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
227 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
229 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
230 } else if(strlen(alias
) > 20) {
232 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum
, alias
);
234 log_verbose("alias %d for utf-8: %s\n", aliasNum
, alias
);
238 /* try to fill an array with all aliases */
239 const char **aliases
;
240 aliases
=(const char **)malloc(count
* sizeof(const char *));
242 ucnv_getAliases("utf-8", aliases
, &err
);
244 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err
));
246 for(aliasNum
= 0; aliasNum
< count
; ++aliasNum
) {
247 /* compare the pointers with the ones returned individually */
248 alias
= ucnv_getAlias("utf-8", aliasNum
, &err
);
250 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum
, myErrorName(err
));
251 } else if(aliases
[aliasNum
] != alias
) {
252 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum
, aliasNum
);
256 free((char **)aliases
);
264 static void TestConvert()
266 #if !UCONFIG_NO_LEGACY_CONVERSION
269 int32_t testLong1
= 0;
273 FILE* ucs_file_in
= NULL
;
275 UChar myUChar
= 0x0000;
276 char* mytarget
; /* [MAX_FILE_LEN] */
279 UChar
* consumedUni
= NULL
;
280 char* consumed
= NULL
;
281 char* output_cp_buffer
; /* [MAX_FILE_LEN] */
282 UChar
* ucs_file_buffer
; /* [MAX_FILE_LEN] */
283 UChar
* ucs_file_buffer_use
;
284 UChar
* my_ucs_file_buffer
; /* [MAX_FILE_LEN] */
285 UChar
* my_ucs_file_buffer_1
;
288 uint16_t codepage_index
= 0;
290 UErrorCode err
= U_ZERO_ERROR
;
291 char ucs_file_name
[UCS_FILE_NAME_SIZE
];
292 UConverterFromUCallback MIA1
, MIA1_2
;
293 UConverterToUCallback MIA2
, MIA2_2
;
294 const void *MIA1Context
, *MIA1Context2
, *MIA2Context
, *MIA2Context2
;
295 UConverter
* someConverters
[5];
296 UConverter
* myConverter
= 0;
297 UChar
* displayname
= 0;
304 int32_t targetcapacity2
;
305 int32_t targetcapacity
;
309 const UChar
* tmp_ucs_buf
;
310 const UChar
* tmp_consumedUni
=NULL
;
311 const char* tmp_mytarget_use
;
312 const char* tmp_consumed
;
314 /******************************************************************
315 Checking Unicode -> ksc
316 ******************************************************************/
318 const char* CodePagesToTest
[NUM_CODEPAGE
] =
324 const uint16_t CodePageNumberToTest
[NUM_CODEPAGE
] =
330 const int8_t CodePagesMinChars
[NUM_CODEPAGE
] =
336 const int8_t CodePagesMaxChars
[NUM_CODEPAGE
] =
342 const uint16_t CodePagesSubstitutionChars
[NUM_CODEPAGE
] =
347 const char* CodePagesTestFiles
[NUM_CODEPAGE
] =
353 const UConverterPlatform CodePagesPlatform
[NUM_CODEPAGE
] =
359 const char* CodePagesLocale
[NUM_CODEPAGE
] =
364 UConverterFromUCallback oldFromUAction
= NULL
;
365 UConverterToUCallback oldToUAction
= NULL
;
366 const void* oldFromUContext
= NULL
;
367 const void* oldToUContext
= NULL
;
369 /* Allocate memory */
370 mytarget
= (char*) malloc(MAX_FILE_LEN
* sizeof(mytarget
[0]));
371 output_cp_buffer
= (char*) malloc(MAX_FILE_LEN
* sizeof(output_cp_buffer
[0]));
372 ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(ucs_file_buffer
[0]));
373 my_ucs_file_buffer
= (UChar
*) malloc(MAX_FILE_LEN
* sizeof(my_ucs_file_buffer
[0]));
375 ucs_file_buffer_use
= ucs_file_buffer
;
377 mytarget_use
= mytarget
;
378 my_ucs_file_buffer_1
=my_ucs_file_buffer
;
380 /* flush the converter cache to get a consistent state before the flushing is tested */
383 /*Testing ucnv_openU()*/
385 UChar converterName
[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
386 UChar firstSortedName
[]={ 0x0021, 0x0000}; /* ! */
387 UChar lastSortedName
[]={ 0x007E, 0x0000}; /* ~ */
388 const char *illegalNameChars
={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
389 UChar illegalName
[100];
390 UConverter
*converter
=NULL
;
392 converter
=ucnv_openU(converterName
, &err
);
394 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err
));
396 ucnv_close(converter
);
398 converter
=ucnv_openU(NULL
, &err
);
400 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err
));
402 ucnv_close(converter
);
403 /*testing with error value*/
404 err
=U_ILLEGAL_ARGUMENT_ERROR
;
405 converter
=ucnv_openU(converterName
, &err
);
406 if(!(converter
== NULL
)){
407 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
409 ucnv_close(converter
);
411 u_uastrcpy(illegalName
, "");
412 u_uastrcpy(illegalName
, illegalNameChars
);
413 ucnv_openU(illegalName
, &err
);
414 if(!(err
==U_ILLEGAL_ARGUMENT_ERROR
)){
415 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
419 ucnv_openU(firstSortedName
, &err
);
420 if(err
!=U_FILE_ACCESS_ERROR
){
421 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
425 ucnv_openU(lastSortedName
, &err
);
426 if(err
!=U_FILE_ACCESS_ERROR
){
427 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
432 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
434 UConverter
*cnv
=NULL
;
436 cnv
=ucnv_open("ibm-949,Madhu", &err
);
438 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err
));
443 /*Testing ucnv_convert()*/
445 int32_t targetLimit
=0, sourceLimit
=0, i
=0, targetCapacity
=0;
446 const uint8_t source
[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
447 const uint8_t expectedTarget
[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
449 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
453 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", NULL
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
454 if(err
== U_BUFFER_OVERFLOW_ERROR
){
456 targetLimit
=targetCapacity
+1;
457 target
=(char*)malloc(sizeof(char) * targetLimit
);
458 targetCapacity
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
461 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err
));
464 for(i
=0; i
<targetCapacity
; i
++){
465 if(target
[i
] != expectedTarget
[i
]){
466 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
]);
470 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
+1, -1, &err
);
471 if(U_FAILURE(err
) || i
!=7){
472 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
473 u_errorName(err
), i
);
476 /*Test error conditions*/
478 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, 0, &err
);
480 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
483 err
=U_ILLEGAL_ARGUMENT_ERROR
;
484 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
485 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
487 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
491 sourceLimit
=sizeof(source
)/sizeof(source
[0]);
493 i
=ucnv_convert("ibm-1364", "ibm-1363", target
, targetLimit
, (const char*)source
, sourceLimit
, &err
);
494 if(!(U_FAILURE(err
) && err
==U_BUFFER_OVERFLOW_ERROR
)){
495 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
502 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
503 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
504 err
=U_ILLEGAL_ARGUMENT_ERROR
;
505 if(ucnv_open(NULL
, &err
) != NULL
){
506 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
508 if(ucnv_openCCSID(1051, UCNV_IBM
, &err
) != NULL
){
509 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
513 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
514 log_verbose("\n---Testing ucnv_open default...\n");
515 someConverters
[0] = ucnv_open(NULL
,&err
);
516 someConverters
[1] = ucnv_open(NULL
,&err
);
517 someConverters
[2] = ucnv_open("utf8", &err
);
518 someConverters
[3] = ucnv_openCCSID(949,UCNV_IBM
,&err
);
519 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM
, &err
)); /* test for j350; ucnv_close(NULL) is safe */
520 if (U_FAILURE(err
)){ log_data_err("FAILURE! %s\n", myErrorName(err
));}
522 /* Testing ucnv_getName()*/
523 /*default code page */
524 ucnv_getName(someConverters
[0], &err
);
526 log_data_err("getName[0] failed\n");
528 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters
[0], &err
));
530 ucnv_getName(someConverters
[1], &err
);
532 log_data_err("getName[1] failed\n");
534 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters
[1], &err
));
537 ucnv_close(someConverters
[0]);
538 ucnv_close(someConverters
[1]);
539 ucnv_close(someConverters
[2]);
540 ucnv_close(someConverters
[3]);
543 for (codepage_index
=0; codepage_index
< NUM_CODEPAGE
; ++codepage_index
)
549 strcpy(ucs_file_name
, U_TOPSRCDIR U_FILE_SEP_STRING
"test"U_FILE_SEP_STRING
"testdata"U_FILE_SEP_STRING
);
551 strcpy(ucs_file_name
, loadTestData(&err
));
554 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err
));
559 char* index
= strrchr(ucs_file_name
,(char)U_FILE_SEP_CHAR
);
561 if((unsigned int)(index
-ucs_file_name
) != (strlen(ucs_file_name
)-1)){
566 strcat(ucs_file_name
,".."U_FILE_SEP_STRING
);
568 strcat(ucs_file_name
, CodePagesTestFiles
[codepage_index
]);
570 ucs_file_in
= fopen(ucs_file_name
,"rb");
573 log_data_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name
);
577 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
579 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
580 /* ucnv_flushCache(); */
581 myConverter
=ucnv_open( "ibm-949", &err
);
582 if (!myConverter
|| U_FAILURE(err
))
584 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err
));
589 /*testing for ucnv_getName() */
590 log_verbose("Testing ucnv_getName()...\n");
591 ucnv_getName(myConverter
, &err
);
593 log_err("Error in getName\n");
596 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter
, &err
));
598 if (ctest_stricmp(ucnv_getName(myConverter
, &err
), CodePagesToTest
[codepage_index
]))
599 log_err("getName failed\n");
601 log_verbose("getName ok\n");
602 /*Test getName with error condition*/
605 err
=U_ILLEGAL_ARGUMENT_ERROR
;
606 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
607 name
=ucnv_getName(myConverter
, &err
);
609 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
615 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
617 log_verbose("Testing ucnv_getMaxCharSize()...\n");
618 if (ucnv_getMaxCharSize(myConverter
)==CodePagesMaxChars
[codepage_index
])
619 log_verbose("Max byte per character OK\n");
621 log_err("Max byte per character failed\n");
623 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
624 if (ucnv_getMinCharSize(myConverter
)==CodePagesMinChars
[codepage_index
])
625 log_verbose("Min byte per character OK\n");
627 log_err("Min byte per character failed\n");
630 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
631 log_verbose("\n---Testing ucnv_getSubstChars...\n");
633 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
635 log_err("ucnv_getSubstChars returned a negative number %d\n", ii
);
639 rest
= (uint16_t)(((unsigned char)rest
<< 8) + (unsigned char)myptr
[x
]);
640 if (rest
==CodePagesSubstitutionChars
[codepage_index
])
641 log_verbose("Substitution character ok\n");
643 log_err("Substitution character failed.\n");
645 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
646 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
649 log_err("FAILURE! %s\n", myErrorName(err
));
651 ucnv_getSubstChars(myConverter
,save
, &ii
, &err
);
654 log_err("FAILURE! %s\n", myErrorName(err
));
657 if (strncmp(save
, myptr
, ii
))
658 log_err("Saved substitution character failed\n");
660 log_verbose("Saved substitution character ok\n");
662 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
663 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
665 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
666 if(err
!= U_INDEX_OUTOFBOUNDS_ERROR
){
667 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err
));
671 ucnv_getSubstChars(myConverter
, myptr
, &ii
, &err
);
672 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
673 ucnv_setSubstChars(myConverter
, myptr
, 0, &err
);
674 if(err
!= U_ILLEGAL_ARGUMENT_ERROR
){
675 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err
));
677 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
678 strcpy(myptr
, "abc");
679 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
681 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
682 if(strncmp(save
, myptr
, ii
) == 0){
683 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
685 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
687 strcpy(myptr
, "abc");
688 ucnv_setSubstChars(myConverter
, myptr
, ii
, &err
);
689 err
=U_ILLEGAL_ARGUMENT_ERROR
;
690 ucnv_getSubstChars(myConverter
, save
, &ii
, &err
);
691 if(strncmp(save
, myptr
, ii
) == 0){
692 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
697 #ifdef U_ENABLE_GENERIC_ISO_2022
698 /*resetState ucnv_reset()*/
699 log_verbose("\n---Testing ucnv_reset()..\n");
700 ucnv_reset(myConverter
);
703 const uint8_t in
[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
704 const char *source
=(const char *)in
, *limit
=(const char *)in
+sizeof(in
);
705 UConverter
*cnv
=ucnv_open("ISO_2022", &err
);
707 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err
));
709 c
=ucnv_getNextUChar(cnv
, &source
, limit
, &err
);
710 if((U_FAILURE(err
) || c
!= (UChar32
)0x0031)) {
711 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err
));
720 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
721 locale
=CodePagesLocale
[codepage_index
];
724 disnamelen
= ucnv_getDisplayName(myConverter
, locale
, displayname
, len
, &err
);
725 if(err
==U_BUFFER_OVERFLOW_ERROR
) {
727 displayname
=(UChar
*)malloc((disnamelen
+1) * sizeof(UChar
));
728 ucnv_getDisplayName(myConverter
,locale
,displayname
,disnamelen
+1, &err
);
730 log_err("getDisplayName failed. The error is %s\n", myErrorName(err
));
733 log_verbose(" getDisplayName o.k.\n");
739 log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err
));
741 /*test ucnv_getDiaplayName with error condition*/
742 err
= U_ILLEGAL_ARGUMENT_ERROR
;
743 len
=ucnv_getDisplayName(myConverter
,locale
,NULL
,0, &err
);
745 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
747 /*test ucnv_getDiaplayName with error condition*/
749 len
=ucnv_getDisplayName(NULL
,locale
,NULL
,0, &err
);
750 if( len
!=0 || U_SUCCESS(err
)){
751 log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
755 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
756 ucnv_getFromUCallBack(myConverter
, &MIA1
, &MIA1Context
);
758 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
759 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
760 if (U_FAILURE(err
) || oldFromUAction
!= MIA1
|| oldFromUContext
!= MIA1Context
)
762 log_err("FAILURE! %s\n", myErrorName(err
));
765 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
766 if (MIA1_2
!= otherUnicodeAction(MIA1
) || MIA1Context2
!= &BOM
)
767 log_err("get From UCallBack failed\n");
769 log_verbose("get From UCallBack ok\n");
771 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
772 ucnv_setFromUCallBack(myConverter
,MIA1
, MIA1Context
, &oldFromUAction
, &oldFromUContext
, &err
);
773 if (U_FAILURE(err
) || oldFromUAction
!= otherUnicodeAction(MIA1
) || oldFromUContext
!= &BOM
)
775 log_err("FAILURE! %s\n", myErrorName(err
));
778 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
779 if (MIA1_2
!= MIA1
|| MIA1Context2
!= MIA1Context
)
780 log_err("get From UCallBack action failed\n");
782 log_verbose("get From UCallBack action ok\n");
784 /*testing ucnv_setToUCallBack with error conditions*/
785 err
=U_ILLEGAL_ARGUMENT_ERROR
;
786 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
787 ucnv_setFromUCallBack(myConverter
, otherUnicodeAction(MIA1
), &BOM
, &oldFromUAction
, &oldFromUContext
, &err
);
788 ucnv_getFromUCallBack(myConverter
, &MIA1_2
, &MIA1Context2
);
789 if(MIA1_2
== otherUnicodeAction(MIA1
) || MIA1Context2
== &BOM
){
790 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
795 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
796 ucnv_getToUCallBack(myConverter
, &MIA2
, &MIA2Context
);
798 log_verbose("\n---Testing setTo UCallBack...\n");
799 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), &BOM
, &oldToUAction
, &oldToUContext
, &err
);
800 if (U_FAILURE(err
) || oldToUAction
!= MIA2
|| oldToUContext
!= MIA2Context
)
802 log_err("FAILURE! %s\n", myErrorName(err
));
805 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
806 if (MIA2_2
!= otherCharAction(MIA2
) || MIA2Context2
!= &BOM
)
807 log_err("To UCallBack failed\n");
809 log_verbose("To UCallBack ok\n");
811 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
812 ucnv_setToUCallBack(myConverter
,MIA2
, MIA2Context
, &oldToUAction
, &oldToUContext
, &err
);
813 if (U_FAILURE(err
) || oldToUAction
!= otherCharAction(MIA2
) || oldToUContext
!= &BOM
)
814 { log_err("FAILURE! %s\n", myErrorName(err
)); }
816 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
817 if (MIA2_2
!= MIA2
|| MIA2Context2
!= MIA2Context
)
818 log_err("To UCallBack failed\n");
820 log_verbose("To UCallBack ok\n");
822 /*testing ucnv_setToUCallBack with error conditions*/
823 err
=U_ILLEGAL_ARGUMENT_ERROR
;
824 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
825 ucnv_setToUCallBack(myConverter
,otherCharAction(MIA2
), NULL
, &oldToUAction
, &oldToUContext
, &err
);
826 ucnv_getToUCallBack(myConverter
, &MIA2_2
, &MIA2Context2
);
827 if (MIA2_2
== otherCharAction(MIA2
) || MIA2Context2
== &BOM
){
828 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
833 /*getcodepageid testing ucnv_getCCSID() */
834 log_verbose("\n----Testing getCCSID....\n");
835 cp
= ucnv_getCCSID(myConverter
,&err
);
838 log_err("FAILURE!..... %s\n", myErrorName(err
));
840 if (cp
!= CodePageNumberToTest
[codepage_index
])
841 log_err("Codepage number test failed\n");
843 log_verbose("Codepage number test OK\n");
845 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
846 err
=U_ILLEGAL_ARGUMENT_ERROR
;
847 if( ucnv_getCCSID(myConverter
,&err
) != -1){
848 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
852 /*getCodepagePlatform testing ucnv_getPlatform()*/
853 log_verbose("\n---Testing getCodepagePlatform ..\n");
854 if (CodePagesPlatform
[codepage_index
]!=ucnv_getPlatform(myConverter
, &err
))
855 log_err("Platform codepage test failed\n");
857 log_verbose("Platform codepage test ok\n");
861 log_err("FAILURE! %s\n", myErrorName(err
));
863 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
864 err
= U_ILLEGAL_ARGUMENT_ERROR
;
865 if(ucnv_getPlatform(myConverter
, &err
) != UCNV_UNKNOWN
){
866 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
872 fread(&BOM
, sizeof(UChar
), 1, ucs_file_in
);
873 if (BOM
!=0xFEFF && BOM
!=0xFFFE)
875 log_err("File Missing BOM...Bailing!\n");
880 /*Reads in the file*/
881 while(!feof(ucs_file_in
)&&(i
+=fread(ucs_file_buffer
+i
, sizeof(UChar
), 1, ucs_file_in
)))
883 myUChar
= ucs_file_buffer
[i
-1];
885 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN*/
888 myUChar
= ucs_file_buffer
[i
-1];
889 ucs_file_buffer
[i
-1] = (UChar
)((BOM
==0xFEFF)?myUChar
:((myUChar
>> 8) | (myUChar
<< 8))); /*adjust if BIG_ENDIAN Corner Case*/
892 /*testing ucnv_fromUChars() and ucnv_toUChars() */
893 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
895 uchar1
=(UChar
*)malloc(sizeof(UChar
) * (i
+1));
896 u_uastrcpy(uchar1
,"");
897 u_strncpy(uchar1
,ucs_file_buffer
,i
);
900 uchar3
=(UChar
*)malloc(sizeof(UChar
)*(i
+1));
901 u_uastrcpy(uchar3
,"");
902 u_strncpy(uchar3
,ucs_file_buffer
,i
);
905 /*Calls the Conversion Routine */
906 testLong1
= MAX_FILE_LEN
;
907 log_verbose("\n---Testing ucnv_fromUChars()\n");
908 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
911 log_err("\nFAILURE...%s\n", myErrorName(err
));
914 log_verbose(" ucnv_fromUChars() o.k.\n");
916 /*test the conversion routine */
917 log_verbose("\n---Testing ucnv_toUChars()\n");
918 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
920 targetsize
= ucnv_toUChars(myConverter
,
924 strlen(output_cp_buffer
),
926 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
928 if(err
==U_BUFFER_OVERFLOW_ERROR
)
931 uchar2
=(UChar
*)malloc((targetsize
+1) * sizeof(UChar
));
932 targetsize
= ucnv_toUChars(myConverter
,
936 strlen(output_cp_buffer
),
940 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err
));
942 log_verbose(" ucnv_toUChars() o.k.\n");
944 if(u_strcmp(uchar1
,uchar2
)!=0)
945 log_err("equality test failed with conversion routine\n");
949 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
951 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
952 err
=U_ILLEGAL_ARGUMENT_ERROR
;
953 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
954 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
955 if (targetcapacity
!=0) {
956 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
959 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
960 targetcapacity
= ucnv_fromUChars(NULL
, output_cp_buffer
, testLong1
, uchar1
, -1, &err
);
961 if (targetcapacity
!=0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
962 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
965 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
966 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, testLong1
, uchar1
, 0, &err
);
967 if (targetcapacity
!=0) {
968 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
970 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
971 targetcapacity
= ucnv_fromUChars(myConverter
, output_cp_buffer
, 0, uchar1
, -1, &err
);
972 if (err
!= U_BUFFER_OVERFLOW_ERROR
) {
973 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
975 /*toUChars with error conditions*/
976 targetsize
= ucnv_toUChars(myConverter
, uchar2
, targetsize
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
978 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
981 targetsize
= ucnv_toUChars(myConverter
, uchar2
, -1, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
982 if(targetsize
!= 0 || err
!= U_ILLEGAL_ARGUMENT_ERROR
){
983 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
986 targetsize
= ucnv_toUChars(myConverter
, uchar2
, 0, output_cp_buffer
, 0, &err
);
987 if (targetsize
!=0) {
988 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
991 targetsize
= ucnv_toUChars(myConverter
, NULL
, targetcapacity2
, output_cp_buffer
, strlen(output_cp_buffer
), &err
);
992 if (err
!= U_STRING_NOT_TERMINATED_WARNING
) {
993 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
1000 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
1001 /*Clean up re-usable vars*/
1003 log_verbose("Testing ucnv_fromUnicode().....\n");
1004 tmp_ucs_buf
=ucs_file_buffer_use
;
1005 ucnv_fromUnicode(myConverter
, &mytarget_1
,
1006 mytarget
+ MAX_FILE_LEN
,
1008 ucs_file_buffer_use
+i
,
1012 consumedUni
= (UChar
*)tmp_consumedUni
;
1016 log_err("FAILURE! %s\n", myErrorName(err
));
1019 log_verbose("ucnv_fromUnicode() o.k.\n");
1021 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
1022 log_verbose("Testing ucnv_toUnicode().....\n");
1023 tmp_mytarget_use
=mytarget_use
;
1024 tmp_consumed
= consumed
;
1025 ucnv_toUnicode(myConverter
, &my_ucs_file_buffer_1
,
1026 my_ucs_file_buffer
+ MAX_FILE_LEN
,
1028 mytarget_use
+ (mytarget_1
- mytarget
),
1032 consumed
= (char*)tmp_consumed
;
1035 log_err("FAILURE! %s\n", myErrorName(err
));
1038 log_verbose("ucnv_toUnicode() o.k.\n");
1041 log_verbose("\n---Testing RoundTrip ...\n");
1044 u_strncpy(uchar3
, my_ucs_file_buffer
,i
);
1047 if(u_strcmp(uchar1
,uchar3
)==0)
1048 log_verbose("Equality test o.k.\n");
1050 log_err("Equality test failed\n");
1055 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__
);
1059 if(u_strcmp(uchar2
, uchar3
)==0)
1060 log_verbose("Equality test o.k.\n");
1062 log_err("Equality test failed\n");
1065 fclose(ucs_file_in
);
1066 ucnv_close(myConverter
);
1067 if (uchar1
!= 0) free(uchar1
);
1068 if (uchar2
!= 0) free(uchar2
);
1069 if (uchar3
!= 0) free(uchar3
);
1072 free((void*)mytarget
);
1073 free((void*)output_cp_buffer
);
1074 free((void*)ucs_file_buffer
);
1075 free((void*)my_ucs_file_buffer
);
1079 static UConverterFromUCallback
otherUnicodeAction(UConverterFromUCallback MIA
)
1081 return (MIA
==(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
)?(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_SUBSTITUTE
:(UConverterFromUCallback
)UCNV_FROM_U_CALLBACK_STOP
;
1085 static UConverterToUCallback
otherCharAction(UConverterToUCallback MIA
)
1087 return (MIA
==(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
)?(UConverterToUCallback
)UCNV_TO_U_CALLBACK_SUBSTITUTE
:(UConverterToUCallback
)UCNV_TO_U_CALLBACK_STOP
;
1090 static void TestFlushCache(void) {
1091 #if !UCONFIG_NO_LEGACY_CONVERSION
1092 UErrorCode err
= U_ZERO_ERROR
;
1093 UConverter
* someConverters
[5];
1096 /* flush the converter cache to get a consistent state before the flushing is tested */
1099 /*Testing ucnv_open()*/
1100 /* Note: These converters have been chosen because they do NOT
1101 encode the Latin characters (U+0041, ...), and therefore are
1102 highly unlikely to be chosen as system default codepages */
1104 someConverters
[0] = ucnv_open("ibm-1047", &err
);
1105 if (U_FAILURE(err
)) {
1106 log_data_err("FAILURE! %s\n", myErrorName(err
));
1109 someConverters
[1] = ucnv_open("ibm-1047", &err
);
1110 if (U_FAILURE(err
)) {
1111 log_data_err("FAILURE! %s\n", myErrorName(err
));
1114 someConverters
[2] = ucnv_open("ibm-1047", &err
);
1115 if (U_FAILURE(err
)) {
1116 log_data_err("FAILURE! %s\n", myErrorName(err
));
1119 someConverters
[3] = ucnv_open("gb18030", &err
);
1120 if (U_FAILURE(err
)) {
1121 log_data_err("FAILURE! %s\n", myErrorName(err
));
1124 someConverters
[4] = ucnv_open("ibm-954", &err
);
1125 if (U_FAILURE(err
)) {
1126 log_data_err("FAILURE! %s\n", myErrorName(err
));
1130 /* Testing ucnv_flushCache() */
1131 log_verbose("\n---Testing ucnv_flushCache...\n");
1132 if ((flushCount
=ucnv_flushCache())==0)
1133 log_verbose("Flush cache ok\n");
1135 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1137 /*testing ucnv_close() and ucnv_flushCache() */
1138 ucnv_close(someConverters
[0]);
1139 ucnv_close(someConverters
[1]);
1141 if ((flushCount
=ucnv_flushCache())==0)
1142 log_verbose("Flush cache ok\n");
1144 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__
, flushCount
);
1146 ucnv_close(someConverters
[2]);
1147 ucnv_close(someConverters
[3]);
1149 if ((flushCount
=ucnv_flushCache())==2)
1150 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1152 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1156 ucnv_close(someConverters
[4]);
1157 if ( (flushCount
=ucnv_flushCache())==1)
1158 log_verbose("Flush cache ok\n");
1160 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__
, flushCount
);
1165 * Test the converter alias API, specifically the fuzzy matching of
1166 * alias names and the alias table integrity. Make sure each
1167 * converter has at least one alias (itself), and that its listed
1168 * aliases map back to itself. Check some hard-coded UTF-8 and
1169 * ISO_2022 aliases to make sure they work.
1171 static void TestAlias() {
1173 UErrorCode status
= U_ZERO_ERROR
;
1175 /* Predetermined aliases that we expect to map back to ISO_2022
1176 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1177 const char* ISO_2022_NAMES
[] =
1178 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1179 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1180 int32_t ISO_2022_NAMES_LENGTH
=
1181 sizeof(ISO_2022_NAMES
) / sizeof(ISO_2022_NAMES
[0]);
1182 const char *UTF8_NAMES
[] =
1183 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1184 "utf_8", "ibm1208", "cp1208" };
1185 int32_t UTF8_NAMES_LENGTH
=
1186 sizeof(UTF8_NAMES
) / sizeof(UTF8_NAMES
[0]);
1191 } CONVERTERS_NAMES
[] = {
1192 { "UTF-32BE", "UTF32_BigEndian" },
1193 { "UTF-32LE", "UTF32_LittleEndian" },
1194 { "UTF-32", "ISO-10646-UCS-4" },
1195 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1196 { "UTF-32", "ucs-4" }
1198 int32_t CONVERTERS_NAMES_LENGTH
= sizeof(CONVERTERS_NAMES
) / sizeof(*CONVERTERS_NAMES
);
1200 /* When there are bugs in gencnval or in ucnv_io, converters can
1201 appear to have no aliases. */
1202 ncnv
= ucnv_countAvailable();
1203 log_verbose("%d converters\n", ncnv
);
1204 for (i
=0; i
<ncnv
; ++i
) {
1205 const char *name
= ucnv_getAvailableName(i
);
1207 uint16_t na
= ucnv_countAliases(name
, &status
);
1212 log_err("FAIL: Converter \"%s\" (i=%d)"
1213 " has no aliases; expect at least one\n",
1217 cnv
= ucnv_open(name
, &status
);
1218 if (U_FAILURE(status
)) {
1219 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1220 " can't be opened.\n",
1224 if (strcmp(ucnv_getName(cnv
, &status
), name
) != 0
1225 && (strstr(name
, "PlatformEndian") == 0 && strstr(name
, "OppositeEndian") == 0)) {
1226 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1227 "The should be the same\n",
1228 name
, ucnv_getName(cnv
, &status
));
1233 status
= U_ZERO_ERROR
;
1234 alias0
= ucnv_getAlias(name
, 0, &status
);
1235 for (j
=1; j
<na
; ++j
) {
1237 /* Make sure each alias maps back to the the same list of
1238 aliases. Assume that if alias 0 is the same, the whole
1239 list is the same (this should always be true). */
1240 const char *mapBack
;
1242 status
= U_ZERO_ERROR
;
1243 alias
= ucnv_getAlias(name
, j
, &status
);
1244 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1245 log_err("FAIL: Converter \"%s\"is ambiguous\n", name
);
1248 if (alias
== NULL
) {
1249 log_err("FAIL: Converter \"%s\" -> "
1255 mapBack
= ucnv_getAlias(alias
, 0, &status
);
1257 if (mapBack
== NULL
) {
1258 log_err("FAIL: Converter \"%s\" -> "
1259 "alias[%d]=\"%s\" -> "
1260 "alias[0]=NULL, exp. \"%s\"\n",
1261 name
, j
, alias
, alias0
);
1265 if (0 != strcmp(alias0
, mapBack
)) {
1267 UBool foundAlias
= FALSE
;
1268 if (status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1269 /* Make sure that we only get this mismapping when there is
1270 an ambiguous alias, and the other converter has this alias too. */
1271 for (idx
= 0; idx
< ucnv_countAliases(mapBack
, &status
); idx
++) {
1272 if (strcmp(ucnv_getAlias(mapBack
, (uint16_t)idx
, &status
), alias
) == 0) {
1278 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1281 log_err("FAIL: Converter \"%s\" -> "
1282 "alias[%d]=\"%s\" -> "
1283 "alias[0]=\"%s\", exp. \"%s\"\n",
1284 name
, j
, alias
, mapBack
, alias0
);
1291 /* Check a list of predetermined aliases that we expect to map
1292 * back to ISO_2022 and UTF-8. */
1293 for (i
=1; i
<ISO_2022_NAMES_LENGTH
; ++i
) {
1294 const char* mapBack
= ucnv_getAlias(ISO_2022_NAMES
[i
], 0, &status
);
1296 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES
[i
]);
1299 if (0 != strcmp(mapBack
, ISO_2022_NAMES
[0])) {
1300 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1301 ISO_2022_NAMES
[i
], mapBack
);
1306 for (i
=1; i
<UTF8_NAMES_LENGTH
; ++i
) {
1307 const char* mapBack
= ucnv_getAlias(UTF8_NAMES
[i
], 0, &status
);
1309 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES
[i
]);
1312 if (mapBack
&& 0 != strcmp(mapBack
, UTF8_NAMES
[0])) {
1313 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1314 UTF8_NAMES
[i
], mapBack
);
1319 * Check a list of predetermined aliases that we expect to map
1320 * back to predermined converter names.
1323 for (i
= 0; i
< CONVERTERS_NAMES_LENGTH
; ++i
) {
1324 const char* mapBack
= ucnv_getAlias(CONVERTERS_NAMES
[i
].alias
, 0, &status
);
1326 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES
[i
].name
);
1329 if (0 != strcmp(mapBack
, CONVERTERS_NAMES
[i
].name
)) {
1330 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1331 CONVERTERS_NAMES
[i
].alias
, mapBack
, CONVERTERS_NAMES
[i
].name
);
1337 static void TestDuplicateAlias(void) {
1339 UErrorCode status
= U_ZERO_ERROR
;
1341 status
= U_ZERO_ERROR
;
1342 alias
= ucnv_getStandardName("Shift_JIS", "IBM", &status
);
1343 if (alias
== NULL
|| strcmp(alias
, "ibm-943") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1344 log_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias
);
1346 status
= U_ZERO_ERROR
;
1347 alias
= ucnv_getStandardName("ibm-943", "IANA", &status
);
1348 if (alias
== NULL
|| strcmp(alias
, "Shift_JIS") != 0 || status
!= U_AMBIGUOUS_ALIAS_WARNING
) {
1349 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias
);
1351 status
= U_ZERO_ERROR
;
1352 alias
= ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status
);
1353 if (alias
!= NULL
|| status
== U_AMBIGUOUS_ALIAS_WARNING
) {
1354 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias
);
1359 /* Test safe clone callback */
1361 static uint32_t TSCC_nextSerial()
1363 static uint32_t n
= 1;
1370 uint32_t magic
; /* 0xC0FFEE to identify that the object is OK */
1371 uint32_t serial
; /* minted from nextSerial, above */
1372 UBool wasClosed
; /* close happened on the object */
1375 static TSCCContext
*TSCC_clone(TSCCContext
*ctx
)
1377 TSCCContext
*newCtx
= (TSCCContext
*)malloc(sizeof(TSCCContext
));
1379 newCtx
->serial
= TSCC_nextSerial();
1380 newCtx
->wasClosed
= 0;
1381 newCtx
->magic
= 0xC0FFEE;
1383 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx
, ctx
->serial
, newCtx
, newCtx
->serial
);
1388 static void TSCC_fromU(const void *context
,
1389 UConverterFromUnicodeArgs
*fromUArgs
,
1390 const UChar
* codeUnits
,
1393 UConverterCallbackReason reason
,
1396 TSCCContext
*ctx
= (TSCCContext
*)context
;
1397 UConverterFromUCallback junkFrom
;
1399 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, fromUArgs
->converter
);
1401 if(ctx
->magic
!= 0xC0FFEE) {
1402 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1406 if(reason
== UCNV_CLONE
) {
1407 UErrorCode subErr
= U_ZERO_ERROR
;
1408 TSCCContext
*newCtx
;
1409 TSCCContext
*junkCtx
;
1410 TSCCContext
**pjunkCtx
= &junkCtx
;
1413 log_verbose("TSCC_fromU: cloning..\n");
1414 newCtx
= TSCC_clone(ctx
);
1416 if(newCtx
== NULL
) {
1417 log_err("TSCC_fromU: internal clone failed on %p\n", ctx
);
1421 ucnv_getFromUCallBack(fromUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1422 ucnv_setFromUCallBack(fromUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1424 if(U_FAILURE(subErr
)) {
1429 if(reason
== UCNV_CLOSE
) {
1430 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1431 ctx
->wasClosed
= TRUE
;
1436 static void TSCC_toU(const void *context
,
1437 UConverterToUnicodeArgs
*toUArgs
,
1438 const char* codeUnits
,
1440 UConverterCallbackReason reason
,
1443 TSCCContext
*ctx
= (TSCCContext
*)context
;
1444 UConverterToUCallback junkFrom
;
1446 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx
, ctx
->serial
, reason
, toUArgs
->converter
);
1448 if(ctx
->magic
!= 0xC0FFEE) {
1449 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx
,ctx
->serial
, ctx
->magic
);
1453 if(reason
== UCNV_CLONE
) {
1454 UErrorCode subErr
= U_ZERO_ERROR
;
1455 TSCCContext
*newCtx
;
1456 TSCCContext
*junkCtx
;
1457 TSCCContext
**pjunkCtx
= &junkCtx
;
1460 log_verbose("TSCC_toU: cloning..\n");
1461 newCtx
= TSCC_clone(ctx
);
1463 if(newCtx
== NULL
) {
1464 log_err("TSCC_toU: internal clone failed on %p\n", ctx
);
1468 ucnv_getToUCallBack(toUArgs
->converter
, &junkFrom
, (const void**)pjunkCtx
);
1469 ucnv_setToUCallBack(toUArgs
->converter
, junkFrom
, newCtx
, NULL
, NULL
, &subErr
);
1471 if(U_FAILURE(subErr
)) {
1476 if(reason
== UCNV_CLOSE
) {
1477 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx
, ctx
->serial
);
1478 ctx
->wasClosed
= TRUE
;
1482 static void TSCC_init(TSCCContext
*q
)
1484 q
->magic
= 0xC0FFEE;
1485 q
->serial
= TSCC_nextSerial();
1489 static void TSCC_print_log(TSCCContext
*q
, const char *name
)
1492 log_verbose("TSCContext: %s is NULL!!\n", name
);
1494 if(q
->magic
!= 0xC0FFEE) {
1495 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1496 q
,q
->serial
, q
->magic
);
1498 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1499 q
, q
->serial
, name
, q
->magic
, q
->wasClosed
?"CLOSED":"open");
1503 #if !UCONFIG_NO_LEGACY_CONVERSION
1504 static void TestConvertSafeCloneCallback()
1506 UErrorCode err
= U_ZERO_ERROR
;
1507 TSCCContext from1
, to1
;
1508 TSCCContext
*from2
, *from3
, *to2
, *to3
;
1509 TSCCContext
**pfrom2
= &from2
, **pfrom3
= &from3
, **pto2
= &to2
, **pto3
= &to3
;
1511 int32_t hunkSize
= 8192;
1512 UConverterFromUCallback junkFrom
;
1513 UConverterToUCallback junkTo
;
1514 UConverter
*conv1
, *conv2
= NULL
;
1516 conv1
= ucnv_open("iso-8859-3", &err
);
1518 if(U_FAILURE(err
)) {
1519 log_data_err("Err opening iso-8859-3, %s", u_errorName(err
));
1523 log_verbose("Opened conv1=%p\n", conv1
);
1528 TSCC_print_log(&from1
, "from1");
1529 TSCC_print_log(&to1
, "to1");
1531 ucnv_setFromUCallBack(conv1
, TSCC_fromU
, &from1
, NULL
, NULL
, &err
);
1532 log_verbose("Set from1 on conv1\n");
1533 TSCC_print_log(&from1
, "from1");
1535 ucnv_setToUCallBack(conv1
, TSCC_toU
, &to1
, NULL
, NULL
, &err
);
1536 log_verbose("Set to1 on conv1\n");
1537 TSCC_print_log(&to1
, "to1");
1539 conv2
= ucnv_safeClone(conv1
, hunk
, &hunkSize
, &err
);
1540 if(U_FAILURE(err
)) {
1541 log_err("safeClone failed: %s\n", u_errorName(err
));
1544 log_verbose("Cloned to conv2=%p.\n", conv2
);
1546 /********** from *********************/
1547 ucnv_getFromUCallBack(conv2
, &junkFrom
, (const void**)pfrom2
);
1548 ucnv_getFromUCallBack(conv1
, &junkFrom
, (const void**)pfrom3
);
1550 TSCC_print_log(from2
, "from2");
1551 TSCC_print_log(from3
, "from3(==from1)");
1554 log_err("FAIL! from2 is null \n");
1559 log_err("FAIL! from3 is null \n");
1563 if(from3
!= (&from1
) ) {
1564 log_err("FAIL! conv1's FROM context changed!\n");
1567 if(from2
== (&from1
) ) {
1568 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1571 if(from1
.wasClosed
) {
1572 log_err("FAIL! from1 is closed \n");
1575 if(from2
->wasClosed
) {
1576 log_err("FAIL! from2 was closed\n");
1579 /********** to *********************/
1580 ucnv_getToUCallBack(conv2
, &junkTo
, (const void**)pto2
);
1581 ucnv_getToUCallBack(conv1
, &junkTo
, (const void**)pto3
);
1583 TSCC_print_log(to2
, "to2");
1584 TSCC_print_log(to3
, "to3(==to1)");
1587 log_err("FAIL! to2 is null \n");
1592 log_err("FAIL! to3 is null \n");
1596 if(to3
!= (&to1
) ) {
1597 log_err("FAIL! conv1's TO context changed!\n");
1600 if(to2
== (&to1
) ) {
1601 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1605 log_err("FAIL! to1 is closed \n");
1608 if(to2
->wasClosed
) {
1609 log_err("FAIL! to2 was closed\n");
1612 /*************************************/
1615 log_verbose("ucnv_closed (conv1)\n");
1616 TSCC_print_log(&from1
, "from1");
1617 TSCC_print_log(from2
, "from2");
1618 TSCC_print_log(&to1
, "to1");
1619 TSCC_print_log(to2
, "to2");
1621 if(from1
.wasClosed
== FALSE
) {
1622 log_err("FAIL! from1 is NOT closed \n");
1625 if(from2
->wasClosed
) {
1626 log_err("FAIL! from2 was closed\n");
1629 if(to1
.wasClosed
== FALSE
) {
1630 log_err("FAIL! to1 is NOT closed \n");
1633 if(to2
->wasClosed
) {
1634 log_err("FAIL! to2 was closed\n");
1638 log_verbose("ucnv_closed (conv2)\n");
1640 TSCC_print_log(&from1
, "from1");
1641 TSCC_print_log(from2
, "from2");
1643 if(from1
.wasClosed
== FALSE
) {
1644 log_err("FAIL! from1 is NOT closed \n");
1647 if(from2
->wasClosed
== FALSE
) {
1648 log_err("FAIL! from2 was NOT closed\n");
1651 TSCC_print_log(&to1
, "to1");
1652 TSCC_print_log(to2
, "to2");
1654 if(to1
.wasClosed
== FALSE
) {
1655 log_err("FAIL! to1 is NOT closed \n");
1658 if(to2
->wasClosed
== FALSE
) {
1659 log_err("FAIL! to2 was NOT closed\n");
1663 free(to2
); /* to1 is stack based */
1665 if(from2
!= (&from1
)) {
1666 free(from2
); /* from1 is stack based */
1672 containsAnyOtherByte(uint8_t *p
, int32_t length
, uint8_t b
) {
1683 static void TestConvertSafeClone()
1685 /* one 'regular' & all the 'private stateful' converters */
1686 static const char *const names
[] = {
1687 #if !UCONFIG_NO_LEGACY_CONVERSION
1689 "ISO_2022,locale=zh,version=1",
1692 #if !UCONFIG_NO_LEGACY_CONVERSION
1696 "ISO_2022,locale=kr,version=1",
1697 "ISO_2022,locale=jp,version=2",
1701 #if !UCONFIG_NO_LEGACY_CONVERSION
1702 "IMAP-mailbox-name",
1709 /* store the actual sizes of each converter */
1710 int32_t actualSizes
[LENGTHOF(names
)];
1712 static const int32_t bufferSizes
[] = {
1713 U_CNV_SAFECLONE_BUFFERSIZE
,
1714 (int32_t)(3*sizeof(UConverter
))/2, /* 1.5*sizeof(UConverter) */
1715 (int32_t)sizeof(UConverter
)/2 /* 0.5*sizeof(UConverter) */
1718 char charBuffer
[21]; /* Leave at an odd number for alignment testing */
1719 uint8_t buffer
[3] [U_CNV_SAFECLONE_BUFFERSIZE
];
1720 int32_t bufferSize
, maxBufferSize
;
1721 const char *maxName
;
1722 UConverter
* cnv
, *cnv2
;
1726 const char *pConstCharBuffer
;
1727 const char *charBufferLimit
= charBuffer
+ sizeof(charBuffer
)/sizeof(*charBuffer
);
1728 UChar uniBuffer
[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1729 UChar uniCharBuffer
[20];
1730 char charSourceBuffer
[] = { 0x1b, 0x24, 0x42 };
1731 const char *pCharSource
= charSourceBuffer
;
1732 const char *pCharSourceLimit
= charSourceBuffer
+ sizeof(charSourceBuffer
);
1733 UChar
*pUCharTarget
= uniCharBuffer
;
1734 UChar
*pUCharTargetLimit
= uniCharBuffer
+ sizeof(uniCharBuffer
)/sizeof(*uniCharBuffer
);
1735 const UChar
* pUniBuffer
;
1736 const UChar
*uniBufferLimit
= uniBuffer
+ sizeof(uniBuffer
)/sizeof(*uniBuffer
);
1740 cnv
= ucnv_open(names
[0], &err
);
1741 if(U_SUCCESS(err
)) {
1742 /* Check the various error & informational states: */
1744 /* Null status - just returns NULL */
1745 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1746 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, 0))
1748 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1750 /* error status - should return 0 & keep error the same */
1751 err
= U_MEMORY_ALLOCATION_ERROR
;
1752 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || err
!= U_MEMORY_ALLOCATION_ERROR
)
1754 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1758 /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
1759 if (0 != ucnv_safeClone(cnv
, buffer
[0], 0, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1761 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1765 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1767 if (0 != ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
) || U_FAILURE(err
) || bufferSize
<= 0)
1769 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1771 /* Verify our define is large enough */
1772 if (U_CNV_SAFECLONE_BUFFERSIZE
< bufferSize
)
1774 log_err("FAIL: Pre-calculated buffer size is too small\n");
1776 /* Verify we can use this run-time calculated size */
1777 if (0 == (cnv2
= ucnv_safeClone(cnv
, buffer
[0], &bufferSize
, &err
)) || U_FAILURE(err
))
1779 log_err("FAIL: Converter can't be cloned with run-time size\n");
1785 /* size one byte too small - should allocate & let us know */
1787 if (0 == (cnv2
= ucnv_safeClone(cnv
, 0, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1789 log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1796 bufferSize
= U_CNV_SAFECLONE_BUFFERSIZE
;
1798 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1799 if (0 == (cnv2
= ucnv_safeClone(cnv
, 0, &bufferSize
, &err
)) || err
!= U_SAFECLONE_ALLOCATED_WARNING
)
1801 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1809 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1810 if (0 != ucnv_safeClone(0, buffer
[0], &bufferSize
, &err
) || err
!= U_ILLEGAL_ARGUMENT_ERROR
)
1812 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1821 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1823 for(j
= 0; j
< LENGTHOF(bufferSizes
); ++j
) {
1824 for (index
= 0; index
< LENGTHOF(names
); index
++)
1827 cnv
= ucnv_open(names
[index
], &err
);
1828 if(U_FAILURE(err
)) {
1829 log_data_err("ucnv_open(\"%s\") failed - %s\n", names
[index
], u_errorName(err
));
1834 /* preflight to get maxBufferSize */
1835 actualSizes
[index
] = 0;
1836 ucnv_safeClone(cnv
, NULL
, &actualSizes
[index
], &err
);
1837 if(actualSizes
[index
] > maxBufferSize
) {
1838 maxBufferSize
= actualSizes
[index
];
1839 maxName
= names
[index
];
1843 memset(buffer
, 0xaa, sizeof(buffer
));
1845 bufferSize
= bufferSizes
[j
];
1846 cnv2
= ucnv_safeClone(cnv
, buffer
[1], &bufferSize
, &err
);
1848 /* close the original immediately to make sure that the clone works by itself */
1851 if( actualSizes
[index
] <= (bufferSizes
[j
] - (int32_t)sizeof(UAlignedMemory
)) &&
1852 err
== U_SAFECLONE_ALLOCATED_WARNING
1854 log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names
[index
]);
1857 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1858 if(bufferSize
<= bufferSizes
[j
]) {
1859 /* used the stack buffer */
1860 if( containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
[0]), 0xaa) ||
1861 containsAnyOtherByte(buffer
[1]+bufferSize
, (int32_t)(sizeof(buffer
)-(sizeof(buffer
[0])+bufferSize
)), 0xaa)
1863 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1864 names
[index
], bufferSize
, bufferSizes
[j
]);
1867 /* heap-allocated the clone */
1868 if(containsAnyOtherByte(buffer
[0], (int32_t)sizeof(buffer
), 0xaa)) {
1869 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1870 names
[index
], bufferSize
, bufferSizes
[j
]);
1874 pCharBuffer
= charBuffer
;
1875 pUniBuffer
= uniBuffer
;
1877 ucnv_fromUnicode(cnv2
,
1886 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err
));
1888 ucnv_toUnicode(cnv2
,
1899 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err
));
1902 pConstCharBuffer
= charBuffer
;
1903 if (uniBuffer
[0] != ucnv_getNextUChar(cnv2
, &pConstCharBuffer
, pCharBuffer
, &err
))
1905 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err
));
1911 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1912 sizeof(UConverter
), maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1913 if(maxBufferSize
> U_CNV_SAFECLONE_BUFFERSIZE
) {
1914 log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1915 maxBufferSize
, maxName
, (int)U_CNV_SAFECLONE_BUFFERSIZE
);
1919 static void TestCCSID() {
1920 #if !UCONFIG_NO_LEGACY_CONVERSION
1922 UErrorCode errorCode
;
1923 int32_t ccsids
[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1926 for(i
=0; i
<(int32_t)(sizeof(ccsids
)/sizeof(int32_t)); ++i
) {
1929 errorCode
=U_ZERO_ERROR
;
1930 cnv
=ucnv_openCCSID(ccsid
, UCNV_IBM
, &errorCode
);
1931 if(U_FAILURE(errorCode
)) {
1932 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid
, u_errorName(errorCode
));
1936 if(ccsid
!=ucnv_getCCSID(cnv
, &errorCode
)) {
1937 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid
, ucnv_getCCSID(cnv
, &errorCode
));
1940 /* skip gb18030(ccsid 1392) */
1941 if(ccsid
!= 1392 && UCNV_IBM
!=ucnv_getPlatform(cnv
, &errorCode
)) {
1942 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid
, ucnv_getPlatform(cnv
, &errorCode
));
1950 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1952 /* CHUNK_SIZE defined in common\ucnv.c: */
1953 #define CHUNK_SIZE 1024
1955 static void bug1(void);
1956 static void bug2(void);
1957 static void bug3(void);
1962 bug1(); /* Unicode intermediate buffer straddle bug */
1963 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1964 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1968 * jitterbug 932: test chunking boundary conditions in
1970 int32_t ucnv_convert(const char *toConverterName,
1971 const char *fromConverterName,
1978 * See discussions on the icu mailing list in
1979 * 2001-April with the subject "converter 'flush' question".
1981 * Bug report and test code provided by Edward J. Batutis.
1985 #if !UCONFIG_NO_LEGACY_CONVERSION
1986 char char_in
[CHUNK_SIZE
+32];
1987 char char_out
[CHUNK_SIZE
*2];
1989 /* GB 18030 equivalent of U+10000 is 90308130 */
1990 static const char test_seq
[]={ (char)0x90u
, 0x30, (char)0x81u
, 0x30 };
1992 UErrorCode err
= U_ZERO_ERROR
;
1993 int32_t i
, test_seq_len
= sizeof(test_seq
);
1996 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1997 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1998 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1999 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
2000 * other Unicode sequences cause a bug since combining sequences are not supported by the
2004 for (i
= test_seq_len
; i
>= 0; i
--) {
2005 /* put character sequence into input buffer */
2006 memset(char_in
, 0x61, sizeof(char_in
)); /* GB 18030 'a' */
2007 memcpy(char_in
+ (CHUNK_SIZE
- i
), test_seq
, test_seq_len
);
2009 /* do the conversion */
2010 ucnv_convert("us-ascii", /* out */
2019 if (err
== U_TRUNCATED_CHAR_FOUND
) {
2020 /* this happens when surrogate pair straddles the intermediate buffer in
2021 * T_UConverter_fromCodepageToCodepage */
2022 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
2028 /* bug2: pre-flighting loop bug: simple overflow causes bug */
2031 /* US-ASCII "1234567890" */
2032 static const char source
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
2033 static const char sourceUTF8
[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
2034 static const char sourceUTF32
[]={ 0x00, 0x00, 0x00, 0x30,
2035 0x00, 0x00, 0x00, 0x31,
2036 0x00, 0x00, 0x00, 0x32,
2037 0x00, 0x00, 0x00, 0x33,
2038 0x00, 0x00, 0x00, 0x34,
2039 0x00, 0x00, 0x00, 0x35,
2040 0x00, 0x00, 0x00, 0x36,
2041 0x00, 0x00, 0x00, 0x37,
2042 0x00, 0x00, 0x00, 0x38,
2043 0x00, 0x00, (char)0xf0, 0x00};
2044 static char target
[5];
2046 UErrorCode err
= U_ZERO_ERROR
;
2049 /* do the conversion */
2050 size
= ucnv_convert("iso-8859-1", /* out */
2051 "us-ascii", /* in */
2059 /* bug2: size is 5, should be 10 */
2060 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size
);
2064 /* do the conversion */
2065 size
= ucnv_convert("UTF-32BE", /* out */
2074 /* bug2: size is 5, should be 32 */
2075 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size
);
2079 /* do the conversion */
2080 size
= ucnv_convert("UTF-8", /* out */
2081 "UTF-32BE", /* in */
2085 sizeof(sourceUTF32
),
2089 /* bug2: size is 5, should be 12 */
2090 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size
);
2095 * bug3: when the characters expand going from source to target codepage
2096 * you get bug3 in addition to bug2
2100 #if !UCONFIG_NO_LEGACY_CONVERSION
2101 char char_in
[CHUNK_SIZE
*4];
2103 UErrorCode err
= U_ZERO_ERROR
;
2107 * first get the buggy size from bug2 then
2108 * compare it to buggy size with an expansion
2110 memset(char_in
, 0x61, sizeof(char_in
)); /* US-ASCII 'a' */
2112 /* do the conversion */
2113 size
= ucnv_convert("lmbcs", /* out */
2114 "us-ascii", /* in */
2121 if ( size
!= sizeof(char_in
) ) {
2123 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2124 * in the converter?), should be CHUNK_SIZE*4
2126 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2128 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in
), size
);
2132 * now do the conversion with expansion
2133 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2135 memset(char_in
, 8, sizeof(char_in
));
2138 /* do the conversion */
2139 size
= ucnv_convert("lmbcs", /* out */
2140 "us-ascii", /* in */
2147 /* expect 2X expansion */
2148 if ( size
!= sizeof(char_in
) * 2 ) {
2151 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2153 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in
) * 2, size
);
2159 convertExStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2160 const char *src
, int32_t srcLength
,
2161 const char *expectTarget
, int32_t expectTargetLength
,
2163 const char *testName
,
2164 UErrorCode expectCode
) {
2165 UChar pivotBuffer
[CHUNK_SIZE
];
2166 UChar
*pivotSource
, *pivotTarget
;
2167 const UChar
*pivotLimit
;
2169 char targetBuffer
[CHUNK_SIZE
];
2171 const char *srcLimit
, *finalSrcLimit
, *targetLimit
;
2173 int32_t targetLength
;
2177 UErrorCode errorCode
;
2180 if(chunkSize
>CHUNK_SIZE
) {
2181 chunkSize
=CHUNK_SIZE
;
2184 pivotSource
=pivotTarget
=pivotBuffer
;
2185 pivotLimit
=pivotBuffer
+chunkSize
;
2187 finalSrcLimit
=src
+srcLength
;
2188 target
=targetBuffer
;
2189 targetLimit
=targetBuffer
+chunkSize
;
2191 ucnv_resetToUnicode(srcCnv
);
2192 ucnv_resetFromUnicode(targetCnv
);
2194 errorCode
=U_ZERO_ERROR
;
2197 /* convert, streaming-style (both converters and pivot keep state) */
2199 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2200 if(src
+chunkSize
<=finalSrcLimit
) {
2201 srcLimit
=src
+chunkSize
;
2203 srcLimit
=finalSrcLimit
;
2205 ucnv_convertEx(targetCnv
, srcCnv
,
2206 &target
, targetLimit
,
2208 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotLimit
,
2209 FALSE
, flush
, &errorCode
);
2210 targetLength
=(int32_t)(target
-targetBuffer
);
2211 if(target
>targetLimit
) {
2212 log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
2213 testName
, chunkSize
, target
, targetLimit
);
2214 break; /* TODO: major problem! */
2216 if(errorCode
==U_BUFFER_OVERFLOW_ERROR
) {
2217 /* continue converting another chunk */
2218 errorCode
=U_ZERO_ERROR
;
2219 if(targetLength
+chunkSize
<=sizeof(targetBuffer
)) {
2220 targetLimit
=target
+chunkSize
;
2222 targetLimit
=targetBuffer
+sizeof(targetBuffer
);
2224 } else if(U_FAILURE(errorCode
)) {
2230 } else if(src
==finalSrcLimit
&& pivotSource
==pivotTarget
) {
2231 /* all consumed, now flush without input (separate from conversion for testing) */
2236 if(!(errorCode
==expectCode
|| (expectCode
==U_ZERO_ERROR
&& errorCode
==U_STRING_NOT_TERMINATED_WARNING
))) {
2237 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2238 testName
, chunkSize
, u_errorName(errorCode
), u_errorName(expectCode
));
2239 } else if(targetLength
!=expectTargetLength
) {
2240 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2241 testName
, chunkSize
, targetLength
, expectTargetLength
);
2242 } else if(memcmp(targetBuffer
, expectTarget
, targetLength
)!=0) {
2243 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2244 testName
, chunkSize
);
2249 convertExMultiStreaming(UConverter
*srcCnv
, UConverter
*targetCnv
,
2250 const char *src
, int32_t srcLength
,
2251 const char *expectTarget
, int32_t expectTargetLength
,
2252 const char *testName
,
2253 UErrorCode expectCode
) {
2254 convertExStreaming(srcCnv
, targetCnv
,
2256 expectTarget
, expectTargetLength
,
2257 1, testName
, expectCode
);
2258 convertExStreaming(srcCnv
, targetCnv
,
2260 expectTarget
, expectTargetLength
,
2261 3, testName
, expectCode
);
2262 convertExStreaming(srcCnv
, targetCnv
,
2264 expectTarget
, expectTargetLength
,
2265 7, testName
, expectCode
);
2268 static void TestConvertEx() {
2269 #if !UCONFIG_NO_LEGACY_CONVERSION
2270 static const uint8_t
2272 /* 4e00 30a1 ff61 0410 */
2273 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2276 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2280 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2281 * SUB, SUB, 0x40, SUB, SUB, 0x40
2283 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2286 char srcBuffer
[100], targetBuffer
[100];
2291 UChar pivotBuffer
[100];
2292 UChar
*pivotSource
, *pivotTarget
;
2294 UConverter
*cnv1
, *cnv2
;
2295 UErrorCode errorCode
;
2297 errorCode
=U_ZERO_ERROR
;
2298 cnv1
=ucnv_open("UTF-8", &errorCode
);
2299 if(U_FAILURE(errorCode
)) {
2300 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode
));
2304 cnv2
=ucnv_open("Shift-JIS", &errorCode
);
2305 if(U_FAILURE(errorCode
)) {
2306 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2311 /* test ucnv_convertEx() with streaming conversion style */
2312 convertExMultiStreaming(cnv1
, cnv2
,
2313 (const char *)utf8
, sizeof(utf8
), (const char *)shiftJIS
, sizeof(shiftJIS
),
2314 "UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2316 convertExMultiStreaming(cnv2
, cnv1
,
2317 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
),
2318 "Shift-JIS -> UTF-8", U_ZERO_ERROR
);
2320 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2321 convertExMultiStreaming(cnv1
, cnv2
,
2322 (const char *)shiftJIS
, sizeof(shiftJIS
), (const char *)errorTarget
, sizeof(errorTarget
),
2323 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR
);
2325 /* test some simple conversions */
2327 /* NUL-terminated source and target */
2328 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2329 memcpy(srcBuffer
, utf8
, sizeof(utf8
));
2330 srcBuffer
[sizeof(utf8
)]=0;
2332 target
=targetBuffer
;
2333 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2334 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2335 if( errorCode
!=U_ZERO_ERROR
||
2336 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2338 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2340 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2341 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2344 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2345 errorCode
=U_AMBIGUOUS_ALIAS_WARNING
;
2346 memset(targetBuffer
, 0xff, sizeof(targetBuffer
));
2348 target
=targetBuffer
;
2349 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(shiftJIS
), &src
, NULL
,
2350 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2351 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2352 target
-targetBuffer
!=sizeof(shiftJIS
) ||
2353 *target
!=(char)0xff ||
2354 memcmp(targetBuffer
, shiftJIS
, sizeof(shiftJIS
))!=0
2356 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2357 u_errorName(errorCode
), target
-targetBuffer
, sizeof(shiftJIS
));
2361 errorCode
=U_MESSAGE_PARSE_ERROR
;
2363 target
=targetBuffer
;
2364 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2365 NULL
, NULL
, NULL
, NULL
, TRUE
, TRUE
, &errorCode
);
2366 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2367 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2370 /* pivotLimit==pivotStart */
2371 errorCode
=U_ZERO_ERROR
;
2372 pivotSource
=pivotTarget
=pivotBuffer
;
2373 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2374 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
, TRUE
, TRUE
, &errorCode
);
2375 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2376 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode
));
2379 /* *pivotSource==NULL */
2380 errorCode
=U_ZERO_ERROR
;
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(*pivotSource==NULL) sets %s\n", u_errorName(errorCode
));
2389 errorCode
=U_ZERO_ERROR
;
2391 pivotSource
=pivotBuffer
;
2392 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2393 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, TRUE
, &errorCode
);
2394 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2395 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode
));
2398 /* streaming conversion without a pivot buffer */
2399 errorCode
=U_ZERO_ERROR
;
2401 pivotSource
=pivotBuffer
;
2402 ucnv_convertEx(cnv2
, cnv1
, &target
, targetBuffer
+sizeof(targetBuffer
), &src
, NULL
,
2403 NULL
, &pivotSource
, &pivotTarget
, pivotBuffer
+1, TRUE
, FALSE
, &errorCode
);
2404 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2405 log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode
));
2413 /* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
2414 static const char *const badUTF8
[]={
2418 /* truncated multi-byte sequences */
2455 "\xfc\x80\x80\x80\x80",
2457 /* complete sequences but non-shortest forms or out of range etc. */
2463 "\xf8\x80\x80\x80\x80",
2464 "\xfc\x80\x80\x80\x80\x80",
2469 /* get some character that can be converted and convert it */
2470 static UBool
getTestChar(UConverter
*cnv
, const char *converterName
,
2471 char charUTF8
[4], int32_t *pCharUTF8Length
,
2472 char char0
[8], int32_t *pChar0Length
,
2473 char char1
[8], int32_t *pChar1Length
) {
2474 UChar utf16
[U16_MAX_LENGTH
];
2475 int32_t utf16Length
;
2477 const UChar
*utf16Source
;
2482 UErrorCode errorCode
;
2484 errorCode
=U_ZERO_ERROR
;
2485 set
=uset_open(1, 0);
2486 ucnv_getUnicodeSet(cnv
, set
, UCNV_ROUNDTRIP_SET
, &errorCode
);
2487 c
=uset_charAt(set
, uset_size(set
)/2);
2491 U16_APPEND_UNSAFE(utf16
, utf16Length
, c
);
2493 U8_APPEND_UNSAFE(charUTF8
, *pCharUTF8Length
, c
);
2497 ucnv_fromUnicode(cnv
,
2498 &target
, char0
+sizeof(char0
),
2499 &utf16Source
, utf16
+utf16Length
,
2500 NULL
, FALSE
, &errorCode
);
2501 *pChar0Length
=(int32_t)(target
-char0
);
2505 ucnv_fromUnicode(cnv
,
2506 &target
, char1
+sizeof(char1
),
2507 &utf16Source
, utf16
+utf16Length
,
2508 NULL
, FALSE
, &errorCode
);
2509 *pChar1Length
=(int32_t)(target
-char1
);
2511 if(U_FAILURE(errorCode
)) {
2512 log_err("unable to get test character for %s - %s\n", converterName
, u_errorName(errorCode
));
2518 static void testFromTruncatedUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2519 char charUTF8
[4], int32_t charUTF8Length
,
2520 char char0
[8], int32_t char0Length
,
2521 char char1
[8], int32_t char1Length
) {
2526 int32_t outputLength
;
2528 char invalidChars
[8];
2529 int8_t invalidLength
;
2534 UChar pivotBuffer
[8];
2535 UChar
*pivotSource
, *pivotTarget
;
2537 UErrorCode errorCode
;
2540 /* test truncated sequences */
2541 errorCode
=U_ZERO_ERROR
;
2542 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, NULL
, NULL
, &errorCode
);
2544 memcpy(utf8
, charUTF8
, charUTF8Length
);
2546 for(i
=0; i
<LENGTHOF(badUTF8
); ++i
) {
2547 /* truncated sequence? */
2548 int32_t length
=strlen(badUTF8
[i
]);
2549 if(length
>=(1+U8_COUNT_TRAIL_BYTES(badUTF8
[i
][0]))) {
2553 /* assemble a string with the test character and the truncated sequence */
2554 memcpy(utf8
+charUTF8Length
, badUTF8
[i
], length
);
2555 utf8Length
=charUTF8Length
+length
;
2557 /* convert and check the invalidChars */
2560 pivotSource
=pivotTarget
=pivotBuffer
;
2561 errorCode
=U_ZERO_ERROR
;
2562 ucnv_convertEx(cnv
, utf8Cnv
,
2563 &target
, output
+sizeof(output
),
2564 &source
, utf8
+utf8Length
,
2565 pivotBuffer
, &pivotSource
, &pivotTarget
, pivotBuffer
+LENGTHOF(pivotBuffer
),
2566 TRUE
, TRUE
, /* reset & flush */
2568 outputLength
=(int32_t)(target
-output
);
2569 if(errorCode
!=U_TRUNCATED_CHAR_FOUND
|| pivotSource
!=pivotBuffer
) {
2570 log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode
), converterName
, (long)i
);
2574 errorCode
=U_ZERO_ERROR
;
2575 invalidLength
=(int8_t)sizeof(invalidChars
);
2576 ucnv_getInvalidChars(utf8Cnv
, invalidChars
, &invalidLength
, &errorCode
);
2577 if(invalidLength
!=length
|| 0!=memcmp(invalidChars
, badUTF8
[i
], length
)) {
2578 log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName
, (long)i
);
2583 static void testFromBadUTF8(UConverter
*utf8Cnv
, UConverter
*cnv
, const char *converterName
,
2584 char charUTF8
[4], int32_t charUTF8Length
,
2585 char char0
[8], int32_t char0Length
,
2586 char char1
[8], int32_t char1Length
) {
2587 char utf8
[600], expect
[600];
2588 int32_t utf8Length
, expectLength
;
2592 UErrorCode errorCode
;
2595 errorCode
=U_ZERO_ERROR
;
2596 ucnv_setToUCallBack(utf8Cnv
, UCNV_TO_U_CALLBACK_SKIP
, NULL
, NULL
, NULL
, &errorCode
);
2599 * assemble an input string with the test character between each
2601 * and an expected string with repeated test character output
2603 memcpy(utf8
, charUTF8
, charUTF8Length
);
2604 utf8Length
=charUTF8Length
;
2606 memcpy(expect
, char0
, char0Length
);
2607 expectLength
=char0Length
;
2609 for(i
=0; i
<LENGTHOF(badUTF8
); ++i
) {
2610 int32_t length
=strlen(badUTF8
[i
]);
2611 memcpy(utf8
+utf8Length
, badUTF8
[i
], length
);
2614 memcpy(utf8
+utf8Length
, charUTF8
, charUTF8Length
);
2615 utf8Length
+=charUTF8Length
;
2617 memcpy(expect
+expectLength
, char1
, char1Length
);
2618 expectLength
+=char1Length
;
2621 /* expect that each bad UTF-8 sequence is detected and skipped */
2622 strcpy(testName
, "from bad UTF-8 to ");
2623 strcat(testName
, converterName
);
2625 convertExMultiStreaming(utf8Cnv
, cnv
,
2627 expect
, expectLength
,
2632 /* Test illegal UTF-8 input. */
2633 static void TestConvertExFromUTF8() {
2634 static const char *const converterNames
[]={
2635 #if !UCONFIG_NO_LEGACY_CONVERSION
2644 UConverter
*utf8Cnv
, *cnv
;
2645 UErrorCode errorCode
;
2648 /* fromUnicode versions of some character, from initial state and later */
2649 char charUTF8
[4], char0
[8], char1
[8];
2650 int32_t charUTF8Length
, char0Length
, char1Length
;
2652 errorCode
=U_ZERO_ERROR
;
2653 utf8Cnv
=ucnv_open("UTF-8", &errorCode
);
2654 if(U_FAILURE(errorCode
)) {
2655 log_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode
));
2659 for(i
=0; i
<LENGTHOF(converterNames
); ++i
) {
2660 errorCode
=U_ZERO_ERROR
;
2661 cnv
=ucnv_open(converterNames
[i
], &errorCode
);
2662 if(U_FAILURE(errorCode
)) {
2663 log_err("unable to open %s converter - %s\n", converterNames
[i
], u_errorName(errorCode
));
2666 if(!getTestChar(cnv
, converterNames
[i
], charUTF8
, &charUTF8Length
, char0
, &char0Length
, char1
, &char1Length
)) {
2669 testFromTruncatedUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2670 testFromBadUTF8(utf8Cnv
, cnv
, converterNames
[i
], charUTF8
, charUTF8Length
, char0
, char0Length
, char1
, char1Length
);
2673 ucnv_close(utf8Cnv
);
2677 TestConvertAlgorithmic() {
2678 #if !UCONFIG_NO_LEGACY_CONVERSION
2679 static const uint8_t
2681 /* 4e00 30a1 ff61 0410 */
2682 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2685 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2689 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2690 * SUB, SUB, 0x40, SUB, SUB, 0x40
2692 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2695 0xfe, 0xff /* BOM only, no text */
2698 0xff, 0xfe, 0, 0 /* BOM only, no text */
2701 char target
[100], utf8NUL
[100], shiftJISNUL
[100];
2704 UErrorCode errorCode
;
2708 errorCode
=U_ZERO_ERROR
;
2709 cnv
=ucnv_open("Shift-JIS", &errorCode
);
2710 if(U_FAILURE(errorCode
)) {
2711 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode
));
2716 memcpy(utf8NUL
, utf8
, sizeof(utf8
));
2717 utf8NUL
[sizeof(utf8
)]=0;
2718 memcpy(shiftJISNUL
, shiftJIS
, sizeof(shiftJIS
));
2719 shiftJISNUL
[sizeof(shiftJIS
)]=0;
2722 * The to/from algorithmic convenience functions share a common implementation,
2723 * so we need not test all permutations of them.
2726 /* length in, not terminated out */
2727 errorCode
=U_ZERO_ERROR
;
2728 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF8
, target
, sizeof(shiftJIS
), (const char *)utf8
, sizeof(utf8
), &errorCode
);
2729 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2730 length
!=sizeof(shiftJIS
) ||
2731 memcmp(target
, shiftJIS
, length
)!=0
2733 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2734 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2737 /* terminated in and out */
2738 memset(target
, 0x55, sizeof(target
));
2739 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2740 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, -1, &errorCode
);
2741 if( errorCode
!=U_ZERO_ERROR
||
2742 length
!=sizeof(utf8
) ||
2743 memcmp(target
, utf8
, length
)!=0
2745 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2746 u_errorName(errorCode
), length
, sizeof(shiftJIS
));
2749 /* empty string, some target buffer */
2750 errorCode
=U_STRING_NOT_TERMINATED_WARNING
;
2751 length
=ucnv_toAlgorithmic(UCNV_UTF8
, cnv
, target
, sizeof(target
), shiftJISNUL
, 0, &errorCode
);
2752 if( errorCode
!=U_ZERO_ERROR
||
2755 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2756 u_errorName(errorCode
), length
);
2759 /* pseudo-empty string, no target buffer */
2760 errorCode
=U_ZERO_ERROR
;
2761 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2762 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2765 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2766 u_errorName(errorCode
), length
);
2769 errorCode
=U_ZERO_ERROR
;
2770 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF32
, target
, 0, (const char *)utf32
, 4, &errorCode
);
2771 if( errorCode
!=U_STRING_NOT_TERMINATED_WARNING
||
2774 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2775 u_errorName(errorCode
), length
);
2779 errorCode
=U_MESSAGE_PARSE_ERROR
;
2780 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, (const char *)utf16
, 2, &errorCode
);
2781 if(errorCode
!=U_MESSAGE_PARSE_ERROR
) {
2782 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode
));
2786 errorCode
=U_ZERO_ERROR
;
2787 length
=ucnv_fromAlgorithmic(cnv
, UCNV_UTF16
, target
, 0, NULL
, 2, &errorCode
);
2788 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2789 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode
));
2792 /* illegal alg. type */
2793 errorCode
=U_ZERO_ERROR
;
2794 length
=ucnv_fromAlgorithmic(cnv
, (UConverterType
)99, target
, 0, (const char *)utf16
, 2, &errorCode
);
2795 if(errorCode
!=U_ILLEGAL_ARGUMENT_ERROR
) {
2796 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode
));
2802 static void TestLMBCSMaxChar(void) {
2803 static const struct {
2807 /* some non-LMBCS converters - perfect test setup here */
2818 { 4, "IMAP-mailbox-name"},
2821 { 1, "windows-1256"},
2833 { 3, "ISO-2022-KR"},
2834 { 6, "ISO-2022-JP"},
2835 { 8, "ISO-2022-CN"},
2853 for (idx
= 0; idx
< LENGTHOF(converter
); idx
++) {
2854 UErrorCode status
= U_ZERO_ERROR
;
2855 UConverter
*cnv
= cnv_open(converter
[idx
].name
, &status
);
2856 if (U_FAILURE(status
)) {
2859 if (converter
[idx
].maxSize
!= ucnv_getMaxCharSize(cnv
)) {
2860 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2861 converter
[idx
].name
, converter
[idx
].maxSize
, ucnv_getMaxCharSize(cnv
));
2866 /* mostly test that the macro compiles */
2867 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2868 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2873 static void TestJ1968(void) {
2874 UErrorCode err
= U_ZERO_ERROR
;
2876 char myConvName
[] = "My really really really really really really really really really really really"
2877 " really really really really really really really really really really really"
2878 " really really really really really really really really long converter name";
2879 UChar myConvNameU
[sizeof(myConvName
)];
2881 u_charsToUChars(myConvName
, myConvNameU
, sizeof(myConvName
));
2884 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
+1] = 0;
2885 cnv
= ucnv_openU(myConvNameU
, &err
);
2886 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2887 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2891 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
2892 cnv
= ucnv_openU(myConvNameU
, &err
);
2893 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2894 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2898 myConvNameU
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
2899 cnv
= ucnv_openU(myConvNameU
, &err
);
2900 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2901 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2908 cnv
= ucnv_open(myConvName
, &err
);
2909 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2910 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2914 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = ',';
2915 cnv
= ucnv_open(myConvName
, &err
);
2916 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2917 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2921 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
2922 cnv
= ucnv_open(myConvName
, &err
);
2923 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2924 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2928 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ',';
2929 strncpy(myConvName
+ UCNV_MAX_CONVERTER_NAME_LENGTH
, "locale=", 7);
2930 cnv
= ucnv_open(myConvName
, &err
);
2931 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2932 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2935 /* The comma isn't really a part of the converter name. */
2937 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
] = 0;
2938 cnv
= ucnv_open(myConvName
, &err
);
2939 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2940 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2944 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = ' ';
2945 cnv
= ucnv_open(myConvName
, &err
);
2946 if (cnv
|| err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
2947 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err
));
2951 myConvName
[UCNV_MAX_CONVERTER_NAME_LENGTH
-1] = 0;
2952 cnv
= ucnv_open(myConvName
, &err
);
2953 if (cnv
|| err
!= U_FILE_ACCESS_ERROR
) {
2954 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err
));
2959 #if !UCONFIG_NO_LEGACY_CONVERSION
2961 testSwap(const char *name
, UBool swap
) {
2963 * Test Unicode text.
2964 * Contains characters that are the highest for some of the
2965 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
2966 * tables copies the entire tables.
2968 static const UChar text
[]={
2969 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
2972 UChar uNormal
[32], uSwapped
[32];
2973 char normal
[32], swapped
[32];
2977 int32_t i
, normalLength
, swappedLength
;
2981 const char *swappedName
;
2982 UConverter
*cnv
, *swapCnv
;
2983 UErrorCode errorCode
;
2985 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
2987 /* open both the normal and the LF/NL-swapping converters */
2988 strcpy(swapped
, name
);
2989 strcat(swapped
, UCNV_SWAP_LFNL_OPTION_STRING
);
2991 errorCode
=U_ZERO_ERROR
;
2992 swapCnv
=ucnv_open(swapped
, &errorCode
);
2993 cnv
=ucnv_open(name
, &errorCode
);
2994 if(U_FAILURE(errorCode
)) {
2995 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name
, swapped
, u_errorName(errorCode
));
2999 /* the name must contain the swap option if and only if we expect the converter to swap */
3000 swappedName
=ucnv_getName(swapCnv
, &errorCode
);
3001 if(U_FAILURE(errorCode
)) {
3002 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name
, u_errorName(errorCode
));
3006 pc
=strstr(swappedName
, UCNV_SWAP_LFNL_OPTION_STRING
);
3007 if(swap
!= (pc
!=NULL
)) {
3008 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name
, swappedName
, swap
);
3012 /* convert to EBCDIC */
3015 ucnv_fromUnicode(cnv
, &pc
, normal
+LENGTHOF(normal
), &pcu
, text
+LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3016 normalLength
=(int32_t)(pc
-normal
);
3020 ucnv_fromUnicode(swapCnv
, &pc
, swapped
+LENGTHOF(swapped
), &pcu
, text
+LENGTHOF(text
), NULL
, TRUE
, &errorCode
);
3021 swappedLength
=(int32_t)(pc
-swapped
);
3023 if(U_FAILURE(errorCode
)) {
3024 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name
, u_errorName(errorCode
));
3028 /* compare EBCDIC output */
3029 if(normalLength
!=swappedLength
) {
3030 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3033 for(i
=0; i
<normalLength
; ++i
) {
3034 /* swap EBCDIC LF/NL for comparison */
3039 } else if(c
==0x25) {
3045 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name
, i
, (uint8_t)swapped
[i
]);
3050 /* convert back to Unicode (may not roundtrip) */
3053 ucnv_toUnicode(cnv
, &pu
, uNormal
+LENGTHOF(uNormal
), (const char **)&pc
, normal
+normalLength
, NULL
, TRUE
, &errorCode
);
3054 normalLength
=(int32_t)(pu
-uNormal
);
3058 ucnv_toUnicode(swapCnv
, &pu
, uSwapped
+LENGTHOF(uSwapped
), (const char **)&pc
, normal
+swappedLength
, NULL
, TRUE
, &errorCode
);
3059 swappedLength
=(int32_t)(pu
-uSwapped
);
3061 if(U_FAILURE(errorCode
)) {
3062 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name
, u_errorName(errorCode
));
3066 /* compare EBCDIC output */
3067 if(normalLength
!=swappedLength
) {
3068 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name
, normalLength
, swappedLength
);
3071 for(i
=0; i
<normalLength
; ++i
) {
3072 /* swap EBCDIC LF/NL for comparison */
3077 } else if(u
==0x85) {
3082 if(u
!=uSwapped
[i
]) {
3083 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name
, i
, uSwapped
[i
]);
3091 ucnv_close(swapCnv
);
3095 TestEBCDICSwapLFNL() {
3096 static const struct {
3101 { "ibm-1047", TRUE
},
3102 { "ibm-1140", TRUE
},
3103 { "ibm-930", TRUE
},
3104 { "iso-8859-3", FALSE
}
3109 for(i
=0; i
<LENGTHOF(tests
); ++i
) {
3110 testSwap(tests
[i
].name
, tests
[i
].swap
);
3115 TestEBCDICSwapLFNL() {
3116 /* test nothing... */
3120 static const UVersionInfo ICU_34
= {3,4,0,0};
3122 static void TestFromUCountPending(){
3123 #if !UCONFIG_NO_LEGACY_CONVERSION
3124 UErrorCode status
= U_ZERO_ERROR
;
3125 /* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
3126 static const struct {
3130 }fromUnicodeTests
[] = {
3133 {{ 0xdbc4, 0xde34, 0xd84d},3,1},
3134 {{ 0xdbc4, 0xde34, 0xd900},3,3},
3137 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3138 if(U_FAILURE(status
)){
3139 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3142 for(i
=0; i
<LENGTHOF(fromUnicodeTests
); ++i
) {
3145 char* targetLimit
= target
+ 10;
3146 const UChar
* source
= fromUnicodeTests
[i
].input
;
3147 const UChar
* sourceLimit
= source
+ fromUnicodeTests
[i
].len
;
3150 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3151 len
= ucnv_fromUCountPending(cnv
, &status
);
3152 if(U_FAILURE(status
)){
3153 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3154 status
= U_ZERO_ERROR
;
3157 if(len
!= fromUnicodeTests
[i
].exp
){
3158 log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
3161 status
= U_ZERO_ERROR
;
3164 * The converter has to read the tail before it knows that
3165 * only head alone matches.
3166 * At the end, the output for head will overflow the target,
3167 * middle will be pending, and tail will not have been consumed.
3170 \U00101234 -> x (<U101234> \x07 |0)
3171 \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
3172 \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
3173 \U00060007 -> unassigned
3175 static const UChar head
[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
3176 static const UChar middle
[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
3177 static const UChar tail
[] = {0xDC07,0x0000};/* second half of \U00060007 */
3180 char* targetLimit
= target
+ 2; /* expect overflow from converting \U00101234\U00050005 */
3181 const UChar
* source
= head
;
3182 const UChar
* sourceLimit
= source
+ u_strlen(head
);
3185 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3186 len
= ucnv_fromUCountPending(cnv
, &status
);
3187 if(U_FAILURE(status
)){
3188 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3189 status
= U_ZERO_ERROR
;
3192 log_err("ucnv_fromUInputHeld did not return correct length for head\n");
3195 sourceLimit
= source
+ u_strlen(middle
);
3196 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3197 len
= ucnv_fromUCountPending(cnv
, &status
);
3198 if(U_FAILURE(status
)){
3199 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3200 status
= U_ZERO_ERROR
;
3203 log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
3206 sourceLimit
= source
+ u_strlen(tail
);
3207 ucnv_fromUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3208 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3209 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3211 status
= U_ZERO_ERROR
;
3212 len
= ucnv_fromUCountPending(cnv
, &status
);
3213 /* middle[1] is pending, tail has not been consumed */
3214 if(U_FAILURE(status
)){
3215 log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status
));
3218 log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
3226 TestToUCountPending(){
3227 #if !UCONFIG_NO_LEGACY_CONVERSION
3228 UErrorCode status
= U_ZERO_ERROR
;
3229 static const struct {
3233 }toUnicodeTests
[] = {
3235 {{0x05, 0x01, 0x02},3,3},
3237 {{0x07, 0x00, 0x01, 0x02},4,4},
3241 UConverterToUCallback
*oldToUAction
= NULL
;
3242 UConverter
* cnv
= ucnv_openPackage(loadTestData(&status
), "test3", &status
);
3243 if(U_FAILURE(status
)){
3244 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3247 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3248 for(i
=0; i
<LENGTHOF(toUnicodeTests
); ++i
) {
3250 UChar
* target
= tgt
;
3251 UChar
* targetLimit
= target
+ 20;
3252 const char* source
= toUnicodeTests
[i
].input
;
3253 const char* sourceLimit
= source
+ toUnicodeTests
[i
].len
;
3256 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3257 len
= ucnv_toUCountPending(cnv
,&status
);
3258 if(U_FAILURE(status
)){
3259 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3260 status
= U_ZERO_ERROR
;
3263 if(len
!= toUnicodeTests
[i
].exp
){
3264 log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
3267 status
= U_ZERO_ERROR
;
3272 * The converter has to read the tail before it knows that
3273 * only head alone matches.
3274 * At the end, the output for head will overflow the target,
3275 * mid will be pending, and tail will not have been consumed.
3277 char head
[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
3278 char mid
[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
3279 char tail
[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
3281 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
3282 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
3283 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
3284 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
3287 UChar
* target
= tgt
;
3288 UChar
* targetLimit
= target
+ 1; /* expect overflow from converting */
3289 const char* source
= head
;
3290 const char* sourceLimit
= source
+ strlen(head
);
3292 cnv
= ucnv_openPackage(loadTestData(&status
), "test4", &status
);
3293 if(U_FAILURE(status
)){
3294 log_err("Could not create converter for test3. Error: %s\n", u_errorName(status
));
3297 ucnv_setToUCallBack(cnv
, UCNV_TO_U_CALLBACK_STOP
, NULL
, oldToUAction
, NULL
, &status
);
3298 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3299 len
= ucnv_toUCountPending(cnv
,&status
);
3300 if(U_FAILURE(status
)){
3301 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3304 log_err("Did not get the expected len for head.\n");
3307 sourceLimit
= source
+strlen(mid
);
3308 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3309 len
= ucnv_toUCountPending(cnv
,&status
);
3310 if(U_FAILURE(status
)){
3311 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3314 log_err("Did not get the expected len for mid.\n");
3318 sourceLimit
= source
+strlen(tail
);
3319 targetLimit
= target
;
3320 ucnv_toUnicode(cnv
,&target
, targetLimit
, &source
, sourceLimit
, NULL
, FALSE
, &status
);
3321 if(status
!= U_BUFFER_OVERFLOW_ERROR
){
3322 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status
));
3324 status
= U_ZERO_ERROR
;
3325 len
= ucnv_toUCountPending(cnv
,&status
);
3326 /* mid[4] is pending, tail has not been consumed */
3327 if(U_FAILURE(status
)){
3328 log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status
));
3331 log_err("Did not get the expected len for tail.\n");
3338 static void TestOneDefaultNameChange(const char *name
) {
3339 UErrorCode status
= U_ZERO_ERROR
;
3341 ucnv_setDefaultName(name
);
3342 if(strcmp(ucnv_getDefaultName(), name
)==0)
3343 log_verbose("setDefaultName of %s works.\n", name
);
3345 log_err("setDefaultName of %s failed\n", name
);
3346 cnv
=ucnv_open(NULL
, &status
);
3347 if (U_FAILURE(status
) || cnv
== NULL
) {
3348 log_err("opening the default converter of %s failed\n", name
);
3351 if(strcmp(ucnv_getName(cnv
, &status
), name
)==0)
3352 log_verbose("ucnv_getName of %s works.\n", name
);
3354 log_err("ucnv_getName of %s failed\n", name
);
3358 static void TestDefaultName(void) {
3359 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
3360 static char defaultName
[UCNV_MAX_CONVERTER_NAME_LENGTH
+ 1];
3361 strcpy(defaultName
, ucnv_getDefaultName());
3363 log_verbose("getDefaultName returned %s\n", defaultName
);
3365 /*change the default name by setting it */
3366 TestOneDefaultNameChange("UTF-8");
3367 #if !UCONFIG_NO_LEGACY_CONVERSION
3368 TestOneDefaultNameChange("ISCII,version=1");
3369 TestOneDefaultNameChange("ISCII,version=2");
3371 TestOneDefaultNameChange("ISO-8859-1");
3373 /*set the default name back*/
3374 ucnv_setDefaultName(defaultName
);
3377 /* Test that ucnv_compareNames() matches names according to spec. ----------- */
3391 compareNames(const char **names
) {
3392 const char *relation
, *name1
, *name2
;
3396 if(*relation
=='=') {
3398 } else if(*relation
=='<') {
3408 while((name2
=*names
++)!=NULL
) {
3409 result
=ucnv_compareNames(name1
, name2
);
3410 if(sign(result
)!=rel
) {
3411 log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1
, name2
, result
, rel
);
3418 TestCompareNames() {
3419 static const char *equalUTF8
[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL
};
3420 static const char *equalIBM
[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL
};
3421 static const char *lessMac
[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL
};
3422 static const char *lessUTF080
[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL
};
3424 compareNames(equalUTF8
);
3425 compareNames(equalIBM
);
3426 compareNames(lessMac
);
3427 compareNames(lessUTF080
);
3432 static const UChar surrogate
[1]={ 0xd900 };
3435 static const UChar sub
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3436 static const char subChars
[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3438 UErrorCode errorCode
;
3442 /* UTF-16/32: test that the BOM is output before the sub character */
3443 errorCode
=U_ZERO_ERROR
;
3444 cnv
=ucnv_open("UTF-16", &errorCode
);
3445 if(U_FAILURE(errorCode
)) {
3446 log_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode
));
3449 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3451 if(U_FAILURE(errorCode
) ||
3453 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3455 log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
3458 errorCode
=U_ZERO_ERROR
;
3459 cnv
=ucnv_open("UTF-32", &errorCode
);
3460 if(U_FAILURE(errorCode
)) {
3461 log_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode
));
3464 length
=ucnv_fromUChars(cnv
, buffer
, (int32_t)sizeof(buffer
), surrogate
, 1, &errorCode
);
3466 if(U_FAILURE(errorCode
) ||
3468 NULL
== ucnv_detectUnicodeSignature(buffer
, length
, NULL
, &errorCode
)
3470 log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
3473 /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
3474 errorCode
=U_ZERO_ERROR
;
3475 cnv
=ucnv_open("ISO-8859-1", &errorCode
);
3476 if(U_FAILURE(errorCode
)) {
3477 log_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode
));
3480 ucnv_setSubstString(cnv
, sub
, LENGTHOF(sub
), &errorCode
);
3481 if(U_FAILURE(errorCode
)) {
3482 log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode
));
3484 len8
= sizeof(buffer
);
3485 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3486 /* Stateless converter, we expect the string converted to charset bytes. */
3487 if(U_FAILURE(errorCode
) || len8
!=sizeof(subChars
) || 0!=uprv_memcmp(buffer
, subChars
, len8
)) {
3488 log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode
));
3493 #if !UCONFIG_NO_LEGACY_CONVERSION
3494 errorCode
=U_ZERO_ERROR
;
3495 cnv
=ucnv_open("HZ", &errorCode
);
3496 if(U_FAILURE(errorCode
)) {
3497 log_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode
));
3500 ucnv_setSubstString(cnv
, sub
, LENGTHOF(sub
), &errorCode
);
3501 if(U_FAILURE(errorCode
)) {
3502 log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode
));
3504 len8
= sizeof(buffer
);
3505 ucnv_getSubstChars(cnv
, buffer
, &len8
, &errorCode
);
3506 /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
3507 if(U_FAILURE(errorCode
) || len8
!=0) {
3508 log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode
));
3514 * Further testing of ucnv_setSubstString() is done via intltest convert.
3515 * We do not test edge cases of illegal arguments and similar because the
3516 * function implementation uses all of its parameters in calls to other
3517 * functions with UErrorCode parameters.
3522 InvalidArguments() {
3524 UErrorCode errorCode
;
3525 char charBuffer
[2] = {1, 1};
3526 char ucharAsCharBuffer
[2] = {2, 2};
3527 char *charsPtr
= charBuffer
;
3528 UChar
*ucharsPtr
= (UChar
*)ucharAsCharBuffer
;
3529 UChar
*ucharsBadPtr
= (UChar
*)(ucharAsCharBuffer
+ 1);
3531 errorCode
=U_ZERO_ERROR
;
3532 cnv
=ucnv_open("UTF-8", &errorCode
);
3533 if(U_FAILURE(errorCode
)) {
3534 log_err("ucnv_open() failed - %s\n", u_errorName(errorCode
));
3538 errorCode
=U_ZERO_ERROR
;
3539 /* This one should fail because an incomplete UChar is being passed in */
3540 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsPtr
, ucharsBadPtr
, NULL
, TRUE
, &errorCode
);
3541 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3542 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3545 errorCode
=U_ZERO_ERROR
;
3546 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3547 ucnv_fromUnicode(cnv
, &charsPtr
, charsPtr
, (const UChar
**)&ucharsBadPtr
, ucharsPtr
, NULL
, TRUE
, &errorCode
);
3548 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3549 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3552 errorCode
=U_ZERO_ERROR
;
3553 /* This one should fail because an incomplete UChar is being passed in */
3554 ucnv_toUnicode(cnv
, &ucharsPtr
, ucharsBadPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3555 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3556 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode
));
3559 errorCode
=U_ZERO_ERROR
;
3560 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3561 ucnv_toUnicode(cnv
, &ucharsBadPtr
, ucharsPtr
, (const char **)&charsPtr
, charsPtr
, NULL
, TRUE
, &errorCode
);
3562 if(errorCode
!= U_ILLEGAL_ARGUMENT_ERROR
) {
3563 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode
));
3566 if (charBuffer
[0] != 1 || charBuffer
[1] != 1
3567 || ucharAsCharBuffer
[0] != 2 || ucharAsCharBuffer
[1] != 2)
3569 log_err("Data was incorrectly written to buffers\n");