1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*****************************************************************************
7 *
8 * File ccapitst.c
9 *
10 * Modification History:
11 * Name Description
12 * Madhu Katragadda Ported for C API
13 ******************************************************************************
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
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 */
27 #include "cintltst.h"
28 #include "ccapitst.h"
29 #include "cstring.h"
30
31 #define NUM_CODEPAGE 1
32 #define MAX_FILE_LEN 1024*20
33 #define UCS_FILE_NAME_SIZE 512
34
35 /*returns an action other than the one provided*/
36 #if !UCONFIG_NO_LEGACY_CONVERSION
37 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA);
38 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA);
39 #endif
40
41 static UConverter *
cnv_open(const char * name,UErrorCode * pErrorCode)42 cnv_open(const char *name, UErrorCode *pErrorCode) {
43 if(name!=NULL && name[0]=='*') {
44 return ucnv_openPackage(loadTestData(pErrorCode), name+1, pErrorCode);
45 } else {
46 return ucnv_open(name, pErrorCode);
47 }
48 }
49
50
51 static void ListNames(void);
52 static void TestFlushCache(void);
53 static void TestDuplicateAlias(void);
54 static void TestCCSID(void);
55 static void TestJ932(void);
56 static void TestJ1968(void);
57 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
58 static void TestLMBCSMaxChar(void);
59 #endif
60
61 #if !UCONFIG_NO_LEGACY_CONVERSION
62 static void TestConvertSafeCloneCallback(void);
63 #endif
64
65 static void TestEBCDICSwapLFNL(void);
66 static void TestConvertEx(void);
67 static void TestConvertExFromUTF8(void);
68 static void TestConvertExFromUTF8_C5F0(void);
69 static void TestConvertAlgorithmic(void);
70 void TestDefaultConverterError(void); /* defined in cctest.c */
71 void TestDefaultConverterSet(void); /* defined in cctest.c */
72 static void TestToUCountPending(void);
73 static void TestFromUCountPending(void);
74 static void TestDefaultName(void);
75 static void TestCompareNames(void);
76 static void TestSubstString(void);
77 static void InvalidArguments(void);
78 static void TestGetName(void);
79 static void TestUTFBOM(void);
80
81 void addTestConvert(TestNode** root);
82
addTestConvert(TestNode ** root)83 void addTestConvert(TestNode** root)
84 {
85 addTest(root, &ListNames, "tsconv/ccapitst/ListNames");
86 addTest(root, &TestConvert, "tsconv/ccapitst/TestConvert");
87 addTest(root, &TestFlushCache, "tsconv/ccapitst/TestFlushCache");
88 addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias");
89 addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias");
90 addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone");
91 #if !UCONFIG_NO_LEGACY_CONVERSION
92 addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
93 #endif
94 addTest(root, &TestCCSID, "tsconv/ccapitst/TestCCSID");
95 addTest(root, &TestJ932, "tsconv/ccapitst/TestJ932");
96 addTest(root, &TestJ1968, "tsconv/ccapitst/TestJ1968");
97 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
98 addTest(root, &TestLMBCSMaxChar, "tsconv/ccapitst/TestLMBCSMaxChar");
99 #endif
100 addTest(root, &TestEBCDICSwapLFNL, "tsconv/ccapitst/TestEBCDICSwapLFNL");
101 addTest(root, &TestConvertEx, "tsconv/ccapitst/TestConvertEx");
102 addTest(root, &TestConvertExFromUTF8, "tsconv/ccapitst/TestConvertExFromUTF8");
103 addTest(root, &TestConvertExFromUTF8_C5F0, "tsconv/ccapitst/TestConvertExFromUTF8_C5F0");
104 addTest(root, &TestConvertAlgorithmic, "tsconv/ccapitst/TestConvertAlgorithmic");
105 addTest(root, &TestDefaultConverterError, "tsconv/ccapitst/TestDefaultConverterError");
106 addTest(root, &TestDefaultConverterSet, "tsconv/ccapitst/TestDefaultConverterSet");
107 #if !UCONFIG_NO_FILE_IO
108 addTest(root, &TestToUCountPending, "tsconv/ccapitst/TestToUCountPending");
109 addTest(root, &TestFromUCountPending, "tsconv/ccapitst/TestFromUCountPending");
110 #endif
111 addTest(root, &TestDefaultName, "tsconv/ccapitst/TestDefaultName");
112 addTest(root, &TestCompareNames, "tsconv/ccapitst/TestCompareNames");
113 addTest(root, &TestSubstString, "tsconv/ccapitst/TestSubstString");
114 addTest(root, &InvalidArguments, "tsconv/ccapitst/InvalidArguments");
115 addTest(root, &TestGetName, "tsconv/ccapitst/TestGetName");
116 addTest(root, &TestUTFBOM, "tsconv/ccapitst/TestUTFBOM");
117 }
118
ListNames(void)119 static void ListNames(void) {
120 UErrorCode err = U_ZERO_ERROR;
121 int32_t testLong1 = 0;
122 const char* available_conv;
123 UEnumeration *allNamesEnum = NULL;
124 int32_t allNamesCount = 0;
125 uint16_t count;
126
127 log_verbose("Testing ucnv_openAllNames()...");
128 allNamesEnum = ucnv_openAllNames(&err);
129 if(U_FAILURE(err)) {
130 log_data_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err));
131 }
132 else {
133 const char *string = NULL;
134 int32_t len = 0;
135 int32_t count1 = 0;
136 int32_t count2 = 0;
137 allNamesCount = uenum_count(allNamesEnum, &err);
138 while ((string = uenum_next(allNamesEnum, &len, &err))) {
139 count1++;
140 log_verbose("read \"%s\", length %i\n", string, len);
141 }
142 if (U_FAILURE(err)) {
143 log_err("FAILURE! uenum_next(allNamesEnum...) set an error: %s\n", u_errorName(err));
144 err = U_ZERO_ERROR;
145 }
146 uenum_reset(allNamesEnum, &err);
147 while ((string = uenum_next(allNamesEnum, &len, &err))) {
148 count2++;
149 ucnv_close(ucnv_open(string, &err));
150 log_verbose("read \"%s\", length %i (%s)\n", string, len, U_SUCCESS(err) ? "available" : "unavailable");
151 err = U_ZERO_ERROR;
152 }
153 if (count1 != count2) {
154 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
155 }
156 }
157 uenum_close(allNamesEnum);
158 err = U_ZERO_ERROR;
159
160 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
161
162 log_verbose("Testing ucnv_countAvailable()...");
163
164 testLong1=ucnv_countAvailable();
165 log_info("Number of available codepages: %d/%d\n", testLong1, allNamesCount);
166
167 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
168
169 available_conv = ucnv_getAvailableName(testLong1);
170 /*test ucnv_getAvailableName with err condition*/
171 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
172 available_conv = ucnv_getAvailableName(-1);
173 if(available_conv != NULL){
174 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
175 }
176
177 /* Test ucnv_countAliases() etc. */
178 count = ucnv_countAliases("utf-8", &err);
179 if(U_FAILURE(err)) {
180 log_data_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err));
181 } else if(count <= 0) {
182 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count);
183 } else {
184 /* try to get the aliases individually */
185 const char *alias;
186 alias = ucnv_getAlias("utf-8", 0, &err);
187 if(U_FAILURE(err)) {
188 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err));
189 } else if(strcmp("UTF-8", alias) != 0) {
190 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias);
191 } else {
192 uint16_t aliasNum;
193 for(aliasNum = 0; aliasNum < count; ++aliasNum) {
194 alias = ucnv_getAlias("utf-8", aliasNum, &err);
195 if(U_FAILURE(err)) {
196 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
197 } else if(strlen(alias) > 20) {
198 /* sanity check */
199 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum, alias);
200 } else {
201 log_verbose("alias %d for utf-8: %s\n", aliasNum, alias);
202 }
203 }
204 if(U_SUCCESS(err)) {
205 /* try to fill an array with all aliases */
206 const char **aliases;
207 aliases=(const char **)malloc(count * sizeof(const char *));
208 if(aliases != 0) {
209 ucnv_getAliases("utf-8", aliases, &err);
210 if(U_FAILURE(err)) {
211 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err));
212 } else {
213 for(aliasNum = 0; aliasNum < count; ++aliasNum) {
214 /* compare the pointers with the ones returned individually */
215 alias = ucnv_getAlias("utf-8", aliasNum, &err);
216 if(U_FAILURE(err)) {
217 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
218 } else if(aliases[aliasNum] != alias) {
219 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum, aliasNum);
220 }
221 }
222 }
223 free((char **)aliases);
224 }
225 }
226 }
227 }
228 }
229
230
TestConvert()231 static void TestConvert()
232 {
233 #if !UCONFIG_NO_LEGACY_CONVERSION
234 char myptr[4];
235 char save[4];
236 int32_t testLong1 = 0;
237 uint16_t rest = 0;
238 int32_t len = 0;
239 int32_t x = 0;
240 FILE* ucs_file_in = NULL;
241 UChar BOM = 0x0000;
242 UChar myUChar = 0x0000;
243 char* mytarget; /* [MAX_FILE_LEN] */
244 char* mytarget_1;
245 char* mytarget_use;
246 UChar* consumedUni = NULL;
247 char* consumed = NULL;
248 char* output_cp_buffer; /* [MAX_FILE_LEN] */
249 UChar* ucs_file_buffer; /* [MAX_FILE_LEN] */
250 UChar* ucs_file_buffer_use;
251 UChar* my_ucs_file_buffer; /* [MAX_FILE_LEN] */
252 UChar* my_ucs_file_buffer_1;
253 int8_t ii = 0;
254 uint16_t codepage_index = 0;
255 int32_t cp = 0;
256 UErrorCode err = U_ZERO_ERROR;
257 char ucs_file_name[UCS_FILE_NAME_SIZE];
258 UConverterFromUCallback MIA1, MIA1_2;
259 UConverterToUCallback MIA2, MIA2_2;
260 const void *MIA1Context, *MIA1Context2, *MIA2Context, *MIA2Context2;
261 UConverter* someConverters[5];
262 UConverter* myConverter = 0;
263 UChar* displayname = 0;
264
265 const char* locale;
266
267 UChar* uchar1 = 0;
268 UChar* uchar2 = 0;
269 UChar* uchar3 = 0;
270 int32_t targetcapacity2;
271 int32_t targetcapacity;
272 int32_t targetsize;
273 int32_t disnamelen;
274
275 const UChar* tmp_ucs_buf;
276 const UChar* tmp_consumedUni=NULL;
277 const char* tmp_mytarget_use;
278 const char* tmp_consumed;
279
280 /******************************************************************
281 Checking Unicode -> ksc
282 ******************************************************************/
283
284 const char* CodePagesToTest[NUM_CODEPAGE] =
285 {
286 "ibm-949_P110-1999"
287
288
289 };
290 const uint16_t CodePageNumberToTest[NUM_CODEPAGE] =
291 {
292 949
293 };
294
295
296 const int8_t CodePagesMinChars[NUM_CODEPAGE] =
297 {
298 1
299
300 };
301
302 const int8_t CodePagesMaxChars[NUM_CODEPAGE] =
303 {
304 2
305
306 };
307
308 const uint16_t CodePagesSubstitutionChars[NUM_CODEPAGE] =
309 {
310 0xAFFE
311 };
312
313 const char* CodePagesTestFiles[NUM_CODEPAGE] =
314 {
315 "uni-text.bin"
316 };
317
318
319 const UConverterPlatform CodePagesPlatform[NUM_CODEPAGE] =
320 {
321 UCNV_IBM
322
323 };
324
325 const char* CodePagesLocale[NUM_CODEPAGE] =
326 {
327 "ko_KR"
328 };
329
330 UConverterFromUCallback oldFromUAction = NULL;
331 UConverterToUCallback oldToUAction = NULL;
332 const void* oldFromUContext = NULL;
333 const void* oldToUContext = NULL;
334
335 /* Allocate memory */
336 mytarget = (char*) malloc(MAX_FILE_LEN * sizeof(mytarget[0]));
337 output_cp_buffer = (char*) malloc(MAX_FILE_LEN * sizeof(output_cp_buffer[0]));
338 ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(ucs_file_buffer[0]));
339 my_ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(my_ucs_file_buffer[0]));
340
341 ucs_file_buffer_use = ucs_file_buffer;
342 mytarget_1=mytarget;
343 mytarget_use = mytarget;
344 my_ucs_file_buffer_1=my_ucs_file_buffer;
345
346 /* flush the converter cache to get a consistent state before the flushing is tested */
347 ucnv_flushCache();
348
349 /*Testing ucnv_openU()*/
350 {
351 UChar converterName[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
352 UChar firstSortedName[]={ 0x0021, 0x0000}; /* ! */
353 UChar lastSortedName[]={ 0x007E, 0x0000}; /* ~ */
354 const char *illegalNameChars={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
355 UChar illegalName[100];
356 UConverter *converter=NULL;
357 err=U_ZERO_ERROR;
358 converter=ucnv_openU(converterName, &err);
359 if(U_FAILURE(err)){
360 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err));
361 }
362 ucnv_close(converter);
363 err=U_ZERO_ERROR;
364 converter=ucnv_openU(NULL, &err);
365 if(U_FAILURE(err)){
366 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err));
367 }
368 ucnv_close(converter);
369 /*testing with error value*/
370 err=U_ILLEGAL_ARGUMENT_ERROR;
371 converter=ucnv_openU(converterName, &err);
372 if(!(converter == NULL)){
373 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
374 }
375 ucnv_close(converter);
376 err=U_ZERO_ERROR;
377 u_uastrcpy(illegalName, "");
378 u_uastrcpy(illegalName, illegalNameChars);
379 ucnv_openU(illegalName, &err);
380 if(!(err==U_ILLEGAL_ARGUMENT_ERROR)){
381 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
382 }
383
384 err=U_ZERO_ERROR;
385 ucnv_openU(firstSortedName, &err);
386 if(err!=U_FILE_ACCESS_ERROR){
387 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
388 }
389
390 err=U_ZERO_ERROR;
391 ucnv_openU(lastSortedName, &err);
392 if(err!=U_FILE_ACCESS_ERROR){
393 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
394 }
395
396 err=U_ZERO_ERROR;
397 }
398 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
399 {
400 UConverter *cnv=NULL;
401 err=U_ZERO_ERROR;
402 cnv=ucnv_open("ibm-949,Madhu", &err);
403 if(U_FAILURE(err)){
404 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err));
405 }
406 ucnv_close(cnv);
407
408 }
409 /*Testing ucnv_convert()*/
410 {
411 int32_t targetLimit=0, sourceLimit=0, i=0, targetCapacity=0;
412 const uint8_t source[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
413 const uint8_t expectedTarget[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
414 char *target=0;
415 sourceLimit=sizeof(source)/sizeof(source[0]);
416 err=U_ZERO_ERROR;
417 targetLimit=0;
418
419 targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", NULL, targetLimit , (const char*)source, sourceLimit, &err);
420 if(err == U_BUFFER_OVERFLOW_ERROR){
421 err=U_ZERO_ERROR;
422 targetLimit=targetCapacity+1;
423 target=(char*)malloc(sizeof(char) * targetLimit);
424 targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
425 }
426 if(U_FAILURE(err)){
427 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err));
428 }
429 else {
430 for(i=0; i<targetCapacity; i++){
431 if(target[i] != expectedTarget[i]){
432 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]);
433 }
434 }
435
436 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source+1, -1, &err);
437 if(U_FAILURE(err) || i!=7){
438 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
439 u_errorName(err), i);
440 }
441
442 /*Test error conditions*/
443 err=U_ZERO_ERROR;
444 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, 0, &err);
445 if(i !=0){
446 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
447 }
448
449 err=U_ILLEGAL_ARGUMENT_ERROR;
450 sourceLimit=sizeof(source)/sizeof(source[0]);
451 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
452 if(i !=0 ){
453 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
454 }
455
456 err=U_ZERO_ERROR;
457 sourceLimit=sizeof(source)/sizeof(source[0]);
458 targetLimit=0;
459 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
460 if(!(U_FAILURE(err) && err==U_BUFFER_OVERFLOW_ERROR)){
461 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
462 }
463 err=U_ZERO_ERROR;
464 free(target);
465 }
466 }
467
468 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
469 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
470 err=U_ILLEGAL_ARGUMENT_ERROR;
471 if(ucnv_open(NULL, &err) != NULL){
472 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
473 }
474 if(ucnv_openCCSID(1051, UCNV_IBM, &err) != NULL){
475 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
476 }
477 err=U_ZERO_ERROR;
478
479 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
480 log_verbose("\n---Testing ucnv_open default...\n");
481 someConverters[0] = ucnv_open(NULL,&err);
482 someConverters[1] = ucnv_open(NULL,&err);
483 someConverters[2] = ucnv_open("utf8", &err);
484 someConverters[3] = ucnv_openCCSID(949,UCNV_IBM,&err);
485 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM, &err)); /* test for j350; ucnv_close(NULL) is safe */
486 if (U_FAILURE(err)){ log_data_err("FAILURE! %s\n", myErrorName(err));}
487
488 /* Testing ucnv_getName()*/
489 /*default code page */
490 ucnv_getName(someConverters[0], &err);
491 if(U_FAILURE(err)) {
492 log_data_err("getName[0] failed\n");
493 } else {
494 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters[0], &err));
495 }
496 ucnv_getName(someConverters[1], &err);
497 if(U_FAILURE(err)) {
498 log_data_err("getName[1] failed\n");
499 } else {
500 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err));
501 }
502
503 ucnv_close(someConverters[0]);
504 ucnv_close(someConverters[1]);
505 ucnv_close(someConverters[2]);
506 ucnv_close(someConverters[3]);
507
508
509 for (codepage_index=0; codepage_index < NUM_CODEPAGE; ++codepage_index)
510 {
511 int32_t i = 0;
512
513 err = U_ZERO_ERROR;
514 #ifdef U_TOPSRCDIR
515 strcpy(ucs_file_name, U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING);
516 #else
517 strcpy(ucs_file_name, loadTestData(&err));
518
519 if(U_FAILURE(err)){
520 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err));
521 return;
522 }
523
524 {
525 char* index = strrchr(ucs_file_name,(char)U_FILE_SEP_CHAR);
526
527 if((unsigned int)(index-ucs_file_name) != (strlen(ucs_file_name)-1)){
528 *(index+1)=0;
529 }
530 }
531
532 strcat(ucs_file_name,".."U_FILE_SEP_STRING);
533 #endif
534 strcat(ucs_file_name, CodePagesTestFiles[codepage_index]);
535
536 ucs_file_in = fopen(ucs_file_name,"rb");
537 if (!ucs_file_in)
538 {
539 log_data_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name);
540 return;
541 }
542
543 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
544
545 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
546 /* ucnv_flushCache(); */
547 myConverter =ucnv_open( "ibm-949", &err);
548 if (!myConverter || U_FAILURE(err))
549 {
550 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err));
551 fclose(ucs_file_in);
552 break;
553 }
554
555 /*testing for ucnv_getName() */
556 log_verbose("Testing ucnv_getName()...\n");
557 ucnv_getName(myConverter, &err);
558 if(U_FAILURE(err))
559 log_err("Error in getName\n");
560 else
561 {
562 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter, &err));
563 }
564 if (uprv_stricmp(ucnv_getName(myConverter, &err), CodePagesToTest[codepage_index]))
565 log_err("getName failed\n");
566 else
567 log_verbose("getName ok\n");
568 /*Test getName with error condition*/
569 {
570 const char* name=0;
571 err=U_ILLEGAL_ARGUMENT_ERROR;
572 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
573 name=ucnv_getName(myConverter, &err);
574 if(name != NULL){
575 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
576 }
577 err=U_ZERO_ERROR;
578 }
579
580
581 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
582
583 log_verbose("Testing ucnv_getMaxCharSize()...\n");
584 if (ucnv_getMaxCharSize(myConverter)==CodePagesMaxChars[codepage_index])
585 log_verbose("Max byte per character OK\n");
586 else
587 log_err("Max byte per character failed\n");
588
589 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
590 if (ucnv_getMinCharSize(myConverter)==CodePagesMinChars[codepage_index])
591 log_verbose("Min byte per character OK\n");
592 else
593 log_err("Min byte per character failed\n");
594
595
596 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
597 log_verbose("\n---Testing ucnv_getSubstChars...\n");
598 ii=4;
599 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
600 if (ii <= 0) {
601 log_err("ucnv_getSubstChars returned a negative number %d\n", ii);
602 }
603
604 for(x=0;x<ii;x++)
605 rest = (uint16_t)(((unsigned char)rest << 8) + (unsigned char)myptr[x]);
606 if (rest==CodePagesSubstitutionChars[codepage_index])
607 log_verbose("Substitution character ok\n");
608 else
609 log_err("Substitution character failed.\n");
610
611 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
612 ucnv_setSubstChars(myConverter, myptr, ii, &err);
613 if (U_FAILURE(err))
614 {
615 log_err("FAILURE! %s\n", myErrorName(err));
616 }
617 ucnv_getSubstChars(myConverter,save, &ii, &err);
618 if (U_FAILURE(err))
619 {
620 log_err("FAILURE! %s\n", myErrorName(err));
621 }
622
623 if (strncmp(save, myptr, ii))
624 log_err("Saved substitution character failed\n");
625 else
626 log_verbose("Saved substitution character ok\n");
627
628 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
629 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
630 ii=1;
631 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
632 if(err != U_INDEX_OUTOFBOUNDS_ERROR){
633 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err));
634 }
635 err=U_ZERO_ERROR;
636 ii=4;
637 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
638 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
639 ucnv_setSubstChars(myConverter, myptr, 0, &err);
640 if(err != U_ILLEGAL_ARGUMENT_ERROR){
641 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err));
642 }
643 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
644 strcpy(myptr, "abc");
645 ucnv_setSubstChars(myConverter, myptr, ii, &err);
646 err=U_ZERO_ERROR;
647 ucnv_getSubstChars(myConverter, save, &ii, &err);
648 if(strncmp(save, myptr, ii) == 0){
649 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
650 }
651 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
652 err=U_ZERO_ERROR;
653 strcpy(myptr, "abc");
654 ucnv_setSubstChars(myConverter, myptr, ii, &err);
655 err=U_ILLEGAL_ARGUMENT_ERROR;
656 ucnv_getSubstChars(myConverter, save, &ii, &err);
657 if(strncmp(save, myptr, ii) == 0){
658 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
659 }
660 err=U_ZERO_ERROR;
661 /*------*/
662
663 #ifdef U_ENABLE_GENERIC_ISO_2022
664 /*resetState ucnv_reset()*/
665 log_verbose("\n---Testing ucnv_reset()..\n");
666 ucnv_reset(myConverter);
667 {
668 UChar32 c;
669 const uint8_t in[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
670 const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
671 UConverter *cnv=ucnv_open("ISO_2022", &err);
672 if(U_FAILURE(err)) {
673 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
674 }
675 c=ucnv_getNextUChar(cnv, &source, limit, &err);
676 if((U_FAILURE(err) || c != (UChar32)0x0031)) {
677 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err));
678 }
679 ucnv_reset(cnv);
680 ucnv_close(cnv);
681
682 }
683 #endif
684
685 /*getDisplayName*/
686 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
687 locale=CodePagesLocale[codepage_index];
688 len=0;
689 displayname=NULL;
690 disnamelen = ucnv_getDisplayName(myConverter, locale, displayname, len, &err);
691 if(err==U_BUFFER_OVERFLOW_ERROR) {
692 err=U_ZERO_ERROR;
693 displayname=(UChar*)malloc((disnamelen+1) * sizeof(UChar));
694 ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
695 if(U_FAILURE(err)) {
696 log_err("getDisplayName failed. The error is %s\n", myErrorName(err));
697 }
698 else {
699 log_verbose(" getDisplayName o.k.\n");
700 }
701 free(displayname);
702 displayname=NULL;
703 }
704 else {
705 log_err("getDisplayName preflight doesn't work. Error is %s\n", myErrorName(err));
706 }
707 /*test ucnv_getDiaplayName with error condition*/
708 err= U_ILLEGAL_ARGUMENT_ERROR;
709 len=ucnv_getDisplayName(myConverter,locale,NULL,0, &err);
710 if( len !=0 ){
711 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
712 }
713 /*test ucnv_getDiaplayName with error condition*/
714 err=U_ZERO_ERROR;
715 len=ucnv_getDisplayName(NULL,locale,NULL,0, &err);
716 if( len !=0 || U_SUCCESS(err)){
717 log_err("ucnv_getDisplayName(NULL) with cnv == NULL is supposed to return 0\n");
718 }
719 err=U_ZERO_ERROR;
720
721 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
722 ucnv_getFromUCallBack(myConverter, &MIA1, &MIA1Context);
723
724 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
725 ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
726 if (U_FAILURE(err) || oldFromUAction != MIA1 || oldFromUContext != MIA1Context)
727 {
728 log_err("FAILURE! %s\n", myErrorName(err));
729 }
730
731 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
732 if (MIA1_2 != otherUnicodeAction(MIA1) || MIA1Context2 != &BOM)
733 log_err("get From UCallBack failed\n");
734 else
735 log_verbose("get From UCallBack ok\n");
736
737 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
738 ucnv_setFromUCallBack(myConverter,MIA1, MIA1Context, &oldFromUAction, &oldFromUContext, &err);
739 if (U_FAILURE(err) || oldFromUAction != otherUnicodeAction(MIA1) || oldFromUContext != &BOM)
740 {
741 log_err("FAILURE! %s\n", myErrorName(err));
742 }
743
744 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
745 if (MIA1_2 != MIA1 || MIA1Context2 != MIA1Context)
746 log_err("get From UCallBack action failed\n");
747 else
748 log_verbose("get From UCallBack action ok\n");
749
750 /*testing ucnv_setToUCallBack with error conditions*/
751 err=U_ILLEGAL_ARGUMENT_ERROR;
752 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
753 ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
754 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
755 if(MIA1_2 == otherUnicodeAction(MIA1) || MIA1Context2 == &BOM){
756 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
757 }
758 err=U_ZERO_ERROR;
759
760
761 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
762 ucnv_getToUCallBack(myConverter, &MIA2, &MIA2Context);
763
764 log_verbose("\n---Testing setTo UCallBack...\n");
765 ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), &BOM, &oldToUAction, &oldToUContext, &err);
766 if (U_FAILURE(err) || oldToUAction != MIA2 || oldToUContext != MIA2Context)
767 {
768 log_err("FAILURE! %s\n", myErrorName(err));
769 }
770
771 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
772 if (MIA2_2 != otherCharAction(MIA2) || MIA2Context2 != &BOM)
773 log_err("To UCallBack failed\n");
774 else
775 log_verbose("To UCallBack ok\n");
776
777 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
778 ucnv_setToUCallBack(myConverter,MIA2, MIA2Context, &oldToUAction, &oldToUContext, &err);
779 if (U_FAILURE(err) || oldToUAction != otherCharAction(MIA2) || oldToUContext != &BOM)
780 { log_err("FAILURE! %s\n", myErrorName(err)); }
781
782 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
783 if (MIA2_2 != MIA2 || MIA2Context2 != MIA2Context)
784 log_err("To UCallBack failed\n");
785 else
786 log_verbose("To UCallBack ok\n");
787
788 /*testing ucnv_setToUCallBack with error conditions*/
789 err=U_ILLEGAL_ARGUMENT_ERROR;
790 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
791 ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), NULL, &oldToUAction, &oldToUContext, &err);
792 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
793 if (MIA2_2 == otherCharAction(MIA2) || MIA2Context2 == &BOM){
794 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
795 }
796 err=U_ZERO_ERROR;
797
798
799 /*getcodepageid testing ucnv_getCCSID() */
800 log_verbose("\n----Testing getCCSID....\n");
801 cp = ucnv_getCCSID(myConverter,&err);
802 if (U_FAILURE(err))
803 {
804 log_err("FAILURE!..... %s\n", myErrorName(err));
805 }
806 if (cp != CodePageNumberToTest[codepage_index])
807 log_err("Codepage number test failed\n");
808 else
809 log_verbose("Codepage number test OK\n");
810
811 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
812 err=U_ILLEGAL_ARGUMENT_ERROR;
813 if( ucnv_getCCSID(myConverter,&err) != -1){
814 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
815 }
816 err=U_ZERO_ERROR;
817
818 /*getCodepagePlatform testing ucnv_getPlatform()*/
819 log_verbose("\n---Testing getCodepagePlatform ..\n");
820 if (CodePagesPlatform[codepage_index]!=ucnv_getPlatform(myConverter, &err))
821 log_err("Platform codepage test failed\n");
822 else
823 log_verbose("Platform codepage test ok\n");
824
825 if (U_FAILURE(err))
826 {
827 log_err("FAILURE! %s\n", myErrorName(err));
828 }
829 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
830 err= U_ILLEGAL_ARGUMENT_ERROR;
831 if(ucnv_getPlatform(myConverter, &err) != UCNV_UNKNOWN){
832 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
833 }
834 err=U_ZERO_ERROR;
835
836
837 /*Reads the BOM*/
838 {
839 // Note: gcc produces a compile warning if the return value from fread() is ignored.
840 size_t numRead = fread(&BOM, sizeof(UChar), 1, ucs_file_in);
841 (void)numRead;
842 }
843 if (BOM!=0xFEFF && BOM!=0xFFFE)
844 {
845 log_err("File Missing BOM...Bailing!\n");
846 fclose(ucs_file_in);
847 break;
848 }
849
850
851 /*Reads in the file*/
852 while(!feof(ucs_file_in)&&(i+=fread(ucs_file_buffer+i, sizeof(UChar), 1, ucs_file_in)))
853 {
854 myUChar = ucs_file_buffer[i-1];
855
856 ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN*/
857 }
858
859 myUChar = ucs_file_buffer[i-1];
860 ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN Corner Case*/
861
862
863 /*testing ucnv_fromUChars() and ucnv_toUChars() */
864 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
865
866 uchar1=(UChar*)malloc(sizeof(UChar) * (i+1));
867 u_uastrcpy(uchar1,"");
868 u_strncpy(uchar1,ucs_file_buffer,i);
869 uchar1[i] = 0;
870
871 uchar3=(UChar*)malloc(sizeof(UChar)*(i+1));
872 u_uastrcpy(uchar3,"");
873 u_strncpy(uchar3,ucs_file_buffer,i);
874 uchar3[i] = 0;
875
876 /*Calls the Conversion Routine */
877 testLong1 = MAX_FILE_LEN;
878 log_verbose("\n---Testing ucnv_fromUChars()\n");
879 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
880 if (U_FAILURE(err))
881 {
882 log_err("\nFAILURE...%s\n", myErrorName(err));
883 }
884 else
885 log_verbose(" ucnv_fromUChars() o.k.\n");
886
887 /*test the conversion routine */
888 log_verbose("\n---Testing ucnv_toUChars()\n");
889 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
890 targetcapacity2=0;
891 targetsize = ucnv_toUChars(myConverter,
892 NULL,
893 targetcapacity2,
894 output_cp_buffer,
895 strlen(output_cp_buffer),
896 &err);
897 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
898
899 if(err==U_BUFFER_OVERFLOW_ERROR)
900 {
901 err=U_ZERO_ERROR;
902 uchar2=(UChar*)malloc((targetsize+1) * sizeof(UChar));
903 targetsize = ucnv_toUChars(myConverter,
904 uchar2,
905 targetsize+1,
906 output_cp_buffer,
907 strlen(output_cp_buffer),
908 &err);
909
910 if(U_FAILURE(err))
911 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err));
912 else
913 log_verbose(" ucnv_toUChars() o.k.\n");
914
915 if(u_strcmp(uchar1,uchar2)!=0)
916 log_err("equality test failed with conversion routine\n");
917 }
918 else
919 {
920 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
921 }
922 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
923 err=U_ILLEGAL_ARGUMENT_ERROR;
924 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
925 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
926 if (targetcapacity !=0) {
927 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
928 }
929 err=U_ZERO_ERROR;
930 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
931 targetcapacity = ucnv_fromUChars(NULL, output_cp_buffer, testLong1, uchar1, -1, &err);
932 if (targetcapacity !=0 || err != U_ILLEGAL_ARGUMENT_ERROR) {
933 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
934 }
935 err=U_ZERO_ERROR;
936 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
937 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, 0, &err);
938 if (targetcapacity !=0) {
939 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
940 }
941 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
942 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, 0, uchar1, -1, &err);
943 if (err != U_BUFFER_OVERFLOW_ERROR) {
944 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
945 }
946 /*toUChars with error conditions*/
947 targetsize = ucnv_toUChars(myConverter, uchar2, targetsize, output_cp_buffer, strlen(output_cp_buffer), &err);
948 if(targetsize != 0){
949 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
950 }
951 err=U_ZERO_ERROR;
952 targetsize = ucnv_toUChars(myConverter, uchar2, -1, output_cp_buffer, strlen(output_cp_buffer), &err);
953 if(targetsize != 0 || err != U_ILLEGAL_ARGUMENT_ERROR){
954 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
955 }
956 err=U_ZERO_ERROR;
957 targetsize = ucnv_toUChars(myConverter, uchar2, 0, output_cp_buffer, 0, &err);
958 if (targetsize !=0) {
959 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
960 }
961 targetcapacity2=0;
962 targetsize = ucnv_toUChars(myConverter, NULL, targetcapacity2, output_cp_buffer, strlen(output_cp_buffer), &err);
963 if (err != U_STRING_NOT_TERMINATED_WARNING) {
964 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
965 u_errorName(err));
966 }
967 err=U_ZERO_ERROR;
968 /*-----*/
969
970
971 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
972 /*Clean up re-usable vars*/
973 log_verbose("Testing ucnv_fromUnicode().....\n");
974 tmp_ucs_buf=ucs_file_buffer_use;
975 ucnv_fromUnicode(myConverter, &mytarget_1,
976 mytarget + MAX_FILE_LEN,
977 &tmp_ucs_buf,
978 ucs_file_buffer_use+i,
979 NULL,
980 TRUE,
981 &err);
982 consumedUni = (UChar*)tmp_consumedUni;
983 (void)consumedUni; /* Suppress set but not used warning. */
984
985 if (U_FAILURE(err))
986 {
987 log_err("FAILURE! %s\n", myErrorName(err));
988 }
989 else
990 log_verbose("ucnv_fromUnicode() o.k.\n");
991
992 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
993 log_verbose("Testing ucnv_toUnicode().....\n");
994 tmp_mytarget_use=mytarget_use;
995 tmp_consumed = consumed;
996 ucnv_toUnicode(myConverter, &my_ucs_file_buffer_1,
997 my_ucs_file_buffer + MAX_FILE_LEN,
998 &tmp_mytarget_use,
999 mytarget_use + (mytarget_1 - mytarget),
1000 NULL,
1001 FALSE,
1002 &err);
1003 consumed = (char*)tmp_consumed;
1004 if (U_FAILURE(err))
1005 {
1006 log_err("FAILURE! %s\n", myErrorName(err));
1007 }
1008 else
1009 log_verbose("ucnv_toUnicode() o.k.\n");
1010
1011
1012 log_verbose("\n---Testing RoundTrip ...\n");
1013
1014
1015 u_strncpy(uchar3, my_ucs_file_buffer,i);
1016 uchar3[i] = 0;
1017
1018 if(u_strcmp(uchar1,uchar3)==0)
1019 log_verbose("Equality test o.k.\n");
1020 else
1021 log_err("Equality test failed\n");
1022
1023 /*sanity compare */
1024 if(uchar2 == NULL)
1025 {
1026 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__);
1027 }
1028 else
1029 {
1030 if(u_strcmp(uchar2, uchar3)==0)
1031 log_verbose("Equality test o.k.\n");
1032 else
1033 log_err("Equality test failed\n");
1034 }
1035
1036 fclose(ucs_file_in);
1037 ucnv_close(myConverter);
1038 if (uchar1 != 0) free(uchar1);
1039 if (uchar2 != 0) free(uchar2);
1040 if (uchar3 != 0) free(uchar3);
1041 }
1042
1043 free((void*)mytarget);
1044 free((void*)output_cp_buffer);
1045 free((void*)ucs_file_buffer);
1046 free((void*)my_ucs_file_buffer);
1047 #endif
1048 }
1049
1050 #if !UCONFIG_NO_LEGACY_CONVERSION
otherUnicodeAction(UConverterFromUCallback MIA)1051 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA)
1052 {
1053 return (MIA==(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP)?(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_SUBSTITUTE:(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP;
1054 }
1055
otherCharAction(UConverterToUCallback MIA)1056 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA)
1057 {
1058 return (MIA==(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP)?(UConverterToUCallback)UCNV_TO_U_CALLBACK_SUBSTITUTE:(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP;
1059 }
1060 #endif
1061
TestFlushCache(void)1062 static void TestFlushCache(void) {
1063 #if !UCONFIG_NO_LEGACY_CONVERSION
1064 UErrorCode err = U_ZERO_ERROR;
1065 UConverter* someConverters[5];
1066 int flushCount = 0;
1067
1068 /* flush the converter cache to get a consistent state before the flushing is tested */
1069 ucnv_flushCache();
1070
1071 /*Testing ucnv_open()*/
1072 /* Note: These converters have been chosen because they do NOT
1073 encode the Latin characters (U+0041, ...), and therefore are
1074 highly unlikely to be chosen as system default codepages */
1075
1076 someConverters[0] = ucnv_open("ibm-1047", &err);
1077 if (U_FAILURE(err)) {
1078 log_data_err("FAILURE! %s\n", myErrorName(err));
1079 }
1080
1081 someConverters[1] = ucnv_open("ibm-1047", &err);
1082 if (U_FAILURE(err)) {
1083 log_data_err("FAILURE! %s\n", myErrorName(err));
1084 }
1085
1086 someConverters[2] = ucnv_open("ibm-1047", &err);
1087 if (U_FAILURE(err)) {
1088 log_data_err("FAILURE! %s\n", myErrorName(err));
1089 }
1090
1091 someConverters[3] = ucnv_open("gb18030", &err);
1092 if (U_FAILURE(err)) {
1093 log_data_err("FAILURE! %s\n", myErrorName(err));
1094 }
1095
1096 someConverters[4] = ucnv_open("ibm-954", &err);
1097 if (U_FAILURE(err)) {
1098 log_data_err("FAILURE! %s\n", myErrorName(err));
1099 }
1100
1101
1102 /* Testing ucnv_flushCache() */
1103 log_verbose("\n---Testing ucnv_flushCache...\n");
1104 if ((flushCount=ucnv_flushCache())==0)
1105 log_verbose("Flush cache ok\n");
1106 else
1107 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1108
1109 /*testing ucnv_close() and ucnv_flushCache() */
1110 ucnv_close(someConverters[0]);
1111 ucnv_close(someConverters[1]);
1112
1113 if ((flushCount=ucnv_flushCache())==0)
1114 log_verbose("Flush cache ok\n");
1115 else
1116 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1117
1118 ucnv_close(someConverters[2]);
1119 ucnv_close(someConverters[3]);
1120
1121 if ((flushCount=ucnv_flushCache())==2)
1122 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1123 else
1124 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1125 __LINE__,
1126 flushCount);
1127
1128 ucnv_close(someConverters[4]);
1129 if ( (flushCount=ucnv_flushCache())==1)
1130 log_verbose("Flush cache ok\n");
1131 else
1132 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount);
1133 #endif
1134 }
1135
1136 /**
1137 * Test the converter alias API, specifically the fuzzy matching of
1138 * alias names and the alias table integrity. Make sure each
1139 * converter has at least one alias (itself), and that its listed
1140 * aliases map back to itself. Check some hard-coded UTF-8 and
1141 * ISO_2022 aliases to make sure they work.
1142 */
TestAlias()1143 static void TestAlias() {
1144 int32_t i, ncnv;
1145 UErrorCode status = U_ZERO_ERROR;
1146
1147 /* Predetermined aliases that we expect to map back to ISO_2022
1148 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1149 const char* ISO_2022_NAMES[] =
1150 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1151 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1152 int32_t ISO_2022_NAMES_LENGTH = UPRV_LENGTHOF(ISO_2022_NAMES);
1153 const char *UTF8_NAMES[] =
1154 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1155 "utf_8", "ibm1208", "cp1208" };
1156 int32_t UTF8_NAMES_LENGTH = UPRV_LENGTHOF(UTF8_NAMES);
1157
1158 struct {
1159 const char *name;
1160 const char *alias;
1161 } CONVERTERS_NAMES[] = {
1162 { "UTF-32BE", "UTF32_BigEndian" },
1163 { "UTF-32LE", "UTF32_LittleEndian" },
1164 { "UTF-32", "ISO-10646-UCS-4" },
1165 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1166 { "UTF-32", "ucs-4" }
1167 };
1168 int32_t CONVERTERS_NAMES_LENGTH = sizeof(CONVERTERS_NAMES) / sizeof(*CONVERTERS_NAMES);
1169
1170 /* When there are bugs in gencnval or in ucnv_io, converters can
1171 appear to have no aliases. */
1172 ncnv = ucnv_countAvailable();
1173 log_verbose("%d converters\n", ncnv);
1174 for (i=0; i<ncnv; ++i) {
1175 const char *name = ucnv_getAvailableName(i);
1176 const char *alias0;
1177 uint16_t na = ucnv_countAliases(name, &status);
1178 uint16_t j;
1179 UConverter *cnv;
1180
1181 if (na == 0) {
1182 log_err("FAIL: Converter \"%s\" (i=%d)"
1183 " has no aliases; expect at least one\n",
1184 name, i);
1185 continue;
1186 }
1187 cnv = ucnv_open(name, &status);
1188 if (U_FAILURE(status)) {
1189 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1190 " can't be opened.\n",
1191 name, i);
1192 }
1193 else {
1194 if (strcmp(ucnv_getName(cnv, &status), name) != 0
1195 && (strstr(name, "PlatformEndian") == 0 && strstr(name, "OppositeEndian") == 0)) {
1196 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1197 "They should be the same\n",
1198 name, ucnv_getName(cnv, &status));
1199 }
1200 }
1201 ucnv_close(cnv);
1202
1203 status = U_ZERO_ERROR;
1204 alias0 = ucnv_getAlias(name, 0, &status);
1205 for (j=1; j<na; ++j) {
1206 const char *alias;
1207 /* Make sure each alias maps back to the the same list of
1208 aliases. Assume that if alias 0 is the same, the whole
1209 list is the same (this should always be true). */
1210 const char *mapBack;
1211
1212 status = U_ZERO_ERROR;
1213 alias = ucnv_getAlias(name, j, &status);
1214 if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1215 log_err("FAIL: Converter \"%s\"is ambiguous\n", name);
1216 }
1217
1218 if (alias == NULL) {
1219 log_err("FAIL: Converter \"%s\" -> "
1220 "alias[%d]=NULL\n",
1221 name, j);
1222 continue;
1223 }
1224
1225 mapBack = ucnv_getAlias(alias, 0, &status);
1226
1227 if (mapBack == NULL) {
1228 log_err("FAIL: Converter \"%s\" -> "
1229 "alias[%d]=\"%s\" -> "
1230 "alias[0]=NULL, exp. \"%s\"\n",
1231 name, j, alias, alias0);
1232 continue;
1233 }
1234
1235 if (0 != strcmp(alias0, mapBack)) {
1236 int32_t idx;
1237 UBool foundAlias = FALSE;
1238 if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1239 /* Make sure that we only get this mismapping when there is
1240 an ambiguous alias, and the other converter has this alias too. */
1241 for (idx = 0; idx < ucnv_countAliases(mapBack, &status); idx++) {
1242 if (strcmp(ucnv_getAlias(mapBack, (uint16_t)idx, &status), alias) == 0) {
1243 foundAlias = TRUE;
1244 break;
1245 }
1246 }
1247 }
1248 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1249
1250 if (!foundAlias) {
1251 log_err("FAIL: Converter \"%s\" -> "
1252 "alias[%d]=\"%s\" -> "
1253 "alias[0]=\"%s\", exp. \"%s\"\n",
1254 name, j, alias, mapBack, alias0);
1255 }
1256 }
1257 }
1258 }
1259
1260
1261 /* Check a list of predetermined aliases that we expect to map
1262 * back to ISO_2022 and UTF-8. */
1263 for (i=1; i<ISO_2022_NAMES_LENGTH; ++i) {
1264 const char* mapBack = ucnv_getAlias(ISO_2022_NAMES[i], 0, &status);
1265 if(!mapBack) {
1266 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES[i]);
1267 continue;
1268 }
1269 if (0 != strcmp(mapBack, ISO_2022_NAMES[0])) {
1270 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1271 ISO_2022_NAMES[i], mapBack);
1272 }
1273 }
1274
1275
1276 for (i=1; i<UTF8_NAMES_LENGTH; ++i) {
1277 const char* mapBack = ucnv_getAlias(UTF8_NAMES[i], 0, &status);
1278 if(!mapBack) {
1279 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES[i]);
1280 continue;
1281 }
1282 if (mapBack && 0 != strcmp(mapBack, UTF8_NAMES[0])) {
1283 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1284 UTF8_NAMES[i], mapBack);
1285 }
1286 }
1287
1288 /*
1289 * Check a list of predetermined aliases that we expect to map
1290 * back to predermined converter names.
1291 */
1292
1293 for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) {
1294 const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status);
1295 if(!mapBack) {
1296 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i].name);
1297 continue;
1298 }
1299 if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) {
1300 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1301 CONVERTERS_NAMES[i].alias, mapBack, CONVERTERS_NAMES[i].name);
1302 }
1303 }
1304
1305 }
1306
TestDuplicateAlias(void)1307 static void TestDuplicateAlias(void) {
1308 const char *alias;
1309 UErrorCode status = U_ZERO_ERROR;
1310
1311 status = U_ZERO_ERROR;
1312 alias = ucnv_getStandardName("Shift_JIS", "IBM", &status);
1313 if (alias == NULL || strcmp(alias, "ibm-943") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1314 log_data_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias);
1315 }
1316 status = U_ZERO_ERROR;
1317 alias = ucnv_getStandardName("ibm-943", "IANA", &status);
1318 if (alias == NULL || strcmp(alias, "Shift_JIS") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1319 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias);
1320 }
1321 status = U_ZERO_ERROR;
1322 alias = ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status);
1323 if (alias != NULL || status == U_AMBIGUOUS_ALIAS_WARNING) {
1324 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias);
1325 }
1326 }
1327
1328
1329 /* Test safe clone callback */
1330
TSCC_nextSerial()1331 static uint32_t TSCC_nextSerial()
1332 {
1333 static uint32_t n = 1;
1334
1335 return (n++);
1336 }
1337
1338 typedef struct
1339 {
1340 uint32_t magic; /* 0xC0FFEE to identify that the object is OK */
1341 uint32_t serial; /* minted from nextSerial, above */
1342 UBool wasClosed; /* close happened on the object */
1343 } TSCCContext;
1344
TSCC_clone(TSCCContext * ctx)1345 static TSCCContext *TSCC_clone(TSCCContext *ctx)
1346 {
1347 TSCCContext *newCtx = (TSCCContext *)malloc(sizeof(TSCCContext));
1348
1349 newCtx->serial = TSCC_nextSerial();
1350 newCtx->wasClosed = 0;
1351 newCtx->magic = 0xC0FFEE;
1352
1353 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
1354
1355 return newCtx;
1356 }
1357
1358 #if !UCONFIG_NO_LEGACY_CONVERSION
TSCC_fromU(const void * context,UConverterFromUnicodeArgs * fromUArgs,const UChar * codeUnits,int32_t length,UChar32 codePoint,UConverterCallbackReason reason,UErrorCode * err)1359 static void TSCC_fromU(const void *context,
1360 UConverterFromUnicodeArgs *fromUArgs,
1361 const UChar* codeUnits,
1362 int32_t length,
1363 UChar32 codePoint,
1364 UConverterCallbackReason reason,
1365 UErrorCode * err)
1366 {
1367 TSCCContext *ctx = (TSCCContext*)context;
1368 UConverterFromUCallback junkFrom;
1369
1370 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, fromUArgs->converter);
1371
1372 if(ctx->magic != 0xC0FFEE) {
1373 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1374 return;
1375 }
1376
1377 if(reason == UCNV_CLONE) {
1378 UErrorCode subErr = U_ZERO_ERROR;
1379 TSCCContext *newCtx;
1380 TSCCContext *junkCtx;
1381 TSCCContext **pjunkCtx = &junkCtx;
1382
1383 /* "recreate" it */
1384 log_verbose("TSCC_fromU: cloning..\n");
1385 newCtx = TSCC_clone(ctx);
1386
1387 if(newCtx == NULL) {
1388 log_err("TSCC_fromU: internal clone failed on %p\n", ctx);
1389 }
1390
1391 /* now, SET it */
1392 ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)pjunkCtx);
1393 ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1394
1395 if(U_FAILURE(subErr)) {
1396 *err = subErr;
1397 }
1398 }
1399
1400 if(reason == UCNV_CLOSE) {
1401 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx, ctx->serial);
1402 ctx->wasClosed = TRUE;
1403 }
1404 }
1405
TSCC_toU(const void * context,UConverterToUnicodeArgs * toUArgs,const char * codeUnits,int32_t length,UConverterCallbackReason reason,UErrorCode * err)1406 static void TSCC_toU(const void *context,
1407 UConverterToUnicodeArgs *toUArgs,
1408 const char* codeUnits,
1409 int32_t length,
1410 UConverterCallbackReason reason,
1411 UErrorCode * err)
1412 {
1413 TSCCContext *ctx = (TSCCContext*)context;
1414 UConverterToUCallback junkFrom;
1415
1416 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, toUArgs->converter);
1417
1418 if(ctx->magic != 0xC0FFEE) {
1419 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1420 return;
1421 }
1422
1423 if(reason == UCNV_CLONE) {
1424 UErrorCode subErr = U_ZERO_ERROR;
1425 TSCCContext *newCtx;
1426 TSCCContext *junkCtx;
1427 TSCCContext **pjunkCtx = &junkCtx;
1428
1429 /* "recreate" it */
1430 log_verbose("TSCC_toU: cloning..\n");
1431 newCtx = TSCC_clone(ctx);
1432
1433 if(newCtx == NULL) {
1434 log_err("TSCC_toU: internal clone failed on %p\n", ctx);
1435 }
1436
1437 /* now, SET it */
1438 ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)pjunkCtx);
1439 ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1440
1441 if(U_FAILURE(subErr)) {
1442 *err = subErr;
1443 }
1444 }
1445
1446 if(reason == UCNV_CLOSE) {
1447 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx, ctx->serial);
1448 ctx->wasClosed = TRUE;
1449 }
1450 }
1451
TSCC_init(TSCCContext * q)1452 static void TSCC_init(TSCCContext *q)
1453 {
1454 q->magic = 0xC0FFEE;
1455 q->serial = TSCC_nextSerial();
1456 q->wasClosed = 0;
1457 }
1458
TSCC_print_log(TSCCContext * q,const char * name)1459 static void TSCC_print_log(TSCCContext *q, const char *name)
1460 {
1461 if(q==NULL) {
1462 log_verbose("TSCContext: %s is NULL!!\n", name);
1463 } else {
1464 if(q->magic != 0xC0FFEE) {
1465 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1466 q,q->serial, q->magic);
1467 }
1468 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1469 q, q->serial, name, q->magic, q->wasClosed?"CLOSED":"open");
1470 }
1471 }
1472
TestConvertSafeCloneCallback()1473 static void TestConvertSafeCloneCallback()
1474 {
1475 UErrorCode err = U_ZERO_ERROR;
1476 TSCCContext from1, to1;
1477 TSCCContext *from2, *from3, *to2, *to3;
1478 TSCCContext **pfrom2 = &from2, **pfrom3 = &from3, **pto2 = &to2, **pto3 = &to3;
1479 char hunk[8192];
1480 int32_t hunkSize = 8192;
1481 UConverterFromUCallback junkFrom;
1482 UConverterToUCallback junkTo;
1483 UConverter *conv1, *conv2 = NULL;
1484
1485 conv1 = ucnv_open("iso-8859-3", &err);
1486
1487 if(U_FAILURE(err)) {
1488 log_data_err("Err opening iso-8859-3, %s\n", u_errorName(err));
1489 return;
1490 }
1491
1492 log_verbose("Opened conv1=%p\n", conv1);
1493
1494 TSCC_init(&from1);
1495 TSCC_init(&to1);
1496
1497 TSCC_print_log(&from1, "from1");
1498 TSCC_print_log(&to1, "to1");
1499
1500 ucnv_setFromUCallBack(conv1, TSCC_fromU, &from1, NULL, NULL, &err);
1501 log_verbose("Set from1 on conv1\n");
1502 TSCC_print_log(&from1, "from1");
1503
1504 ucnv_setToUCallBack(conv1, TSCC_toU, &to1, NULL, NULL, &err);
1505 log_verbose("Set to1 on conv1\n");
1506 TSCC_print_log(&to1, "to1");
1507
1508 conv2 = ucnv_safeClone(conv1, hunk, &hunkSize, &err);
1509 if(U_FAILURE(err)) {
1510 log_err("safeClone failed: %s\n", u_errorName(err));
1511 return;
1512 }
1513 log_verbose("Cloned to conv2=%p.\n", conv2);
1514
1515 /********** from *********************/
1516 ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)pfrom2);
1517 ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)pfrom3);
1518
1519 TSCC_print_log(from2, "from2");
1520 TSCC_print_log(from3, "from3(==from1)");
1521
1522 if(from2 == NULL) {
1523 log_err("FAIL! from2 is null \n");
1524 return;
1525 }
1526
1527 if(from3 == NULL) {
1528 log_err("FAIL! from3 is null \n");
1529 return;
1530 }
1531
1532 if(from3 != (&from1) ) {
1533 log_err("FAIL! conv1's FROM context changed!\n");
1534 }
1535
1536 if(from2 == (&from1) ) {
1537 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1538 }
1539
1540 if(from1.wasClosed) {
1541 log_err("FAIL! from1 is closed \n");
1542 }
1543
1544 if(from2->wasClosed) {
1545 log_err("FAIL! from2 was closed\n");
1546 }
1547
1548 /********** to *********************/
1549 ucnv_getToUCallBack(conv2, &junkTo, (const void**)pto2);
1550 ucnv_getToUCallBack(conv1, &junkTo, (const void**)pto3);
1551
1552 TSCC_print_log(to2, "to2");
1553 TSCC_print_log(to3, "to3(==to1)");
1554
1555 if(to2 == NULL) {
1556 log_err("FAIL! to2 is null \n");
1557 return;
1558 }
1559
1560 if(to3 == NULL) {
1561 log_err("FAIL! to3 is null \n");
1562 return;
1563 }
1564
1565 if(to3 != (&to1) ) {
1566 log_err("FAIL! conv1's TO context changed!\n");
1567 }
1568
1569 if(to2 == (&to1) ) {
1570 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1571 }
1572
1573 if(to1.wasClosed) {
1574 log_err("FAIL! to1 is closed \n");
1575 }
1576
1577 if(to2->wasClosed) {
1578 log_err("FAIL! to2 was closed\n");
1579 }
1580
1581 /*************************************/
1582
1583 ucnv_close(conv1);
1584 log_verbose("ucnv_closed (conv1)\n");
1585 TSCC_print_log(&from1, "from1");
1586 TSCC_print_log(from2, "from2");
1587 TSCC_print_log(&to1, "to1");
1588 TSCC_print_log(to2, "to2");
1589
1590 if(from1.wasClosed == FALSE) {
1591 log_err("FAIL! from1 is NOT closed \n");
1592 }
1593
1594 if(from2->wasClosed) {
1595 log_err("FAIL! from2 was closed\n");
1596 }
1597
1598 if(to1.wasClosed == FALSE) {
1599 log_err("FAIL! to1 is NOT closed \n");
1600 }
1601
1602 if(to2->wasClosed) {
1603 log_err("FAIL! to2 was closed\n");
1604 }
1605
1606 ucnv_close(conv2);
1607 log_verbose("ucnv_closed (conv2)\n");
1608
1609 TSCC_print_log(&from1, "from1");
1610 TSCC_print_log(from2, "from2");
1611
1612 if(from1.wasClosed == FALSE) {
1613 log_err("FAIL! from1 is NOT closed \n");
1614 }
1615
1616 if(from2->wasClosed == FALSE) {
1617 log_err("FAIL! from2 was NOT closed\n");
1618 }
1619
1620 TSCC_print_log(&to1, "to1");
1621 TSCC_print_log(to2, "to2");
1622
1623 if(to1.wasClosed == FALSE) {
1624 log_err("FAIL! to1 is NOT closed \n");
1625 }
1626
1627 if(to2->wasClosed == FALSE) {
1628 log_err("FAIL! to2 was NOT closed\n");
1629 }
1630
1631 if(to2 != (&to1)) {
1632 free(to2); /* to1 is stack based */
1633 }
1634 if(from2 != (&from1)) {
1635 free(from2); /* from1 is stack based */
1636 }
1637 }
1638 #endif
1639
1640 static UBool
containsAnyOtherByte(uint8_t * p,int32_t length,uint8_t b)1641 containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) {
1642 while(length>0) {
1643 if(*p!=b) {
1644 return TRUE;
1645 }
1646 ++p;
1647 --length;
1648 }
1649 return FALSE;
1650 }
1651
TestConvertSafeClone()1652 static void TestConvertSafeClone()
1653 {
1654 /* one 'regular' & all the 'private stateful' converters */
1655 static const char *const names[] = {
1656 #if !UCONFIG_NO_LEGACY_CONVERSION
1657 "ibm-1047",
1658 "ISO_2022,locale=zh,version=1",
1659 #endif
1660 "SCSU",
1661 #if !UCONFIG_NO_LEGACY_CONVERSION
1662 "HZ",
1663 "lmbcs",
1664 "ISCII,version=0",
1665 "ISO_2022,locale=kr,version=1",
1666 "ISO_2022,locale=jp,version=2",
1667 #endif
1668 "BOCU-1",
1669 "UTF-7",
1670 #if !UCONFIG_NO_LEGACY_CONVERSION
1671 "IMAP-mailbox-name",
1672 "ibm-1047-s390"
1673 #else
1674 "IMAP=mailbox-name"
1675 #endif
1676 };
1677
1678 /* store the actual sizes of each converter */
1679 int32_t actualSizes[UPRV_LENGTHOF(names)];
1680
1681 static const int32_t bufferSizes[] = {
1682 U_CNV_SAFECLONE_BUFFERSIZE,
1683 (int32_t)(3*sizeof(UConverter))/2, /* 1.5*sizeof(UConverter) */
1684 (int32_t)sizeof(UConverter)/2 /* 0.5*sizeof(UConverter) */
1685 };
1686
1687 char charBuffer[21]; /* Leave at an odd number for alignment testing */
1688 uint8_t buffer[3] [U_CNV_SAFECLONE_BUFFERSIZE];
1689 int32_t bufferSize, maxBufferSize;
1690 const char *maxName;
1691 UConverter * cnv, *cnv2;
1692 UErrorCode err;
1693
1694 char *pCharBuffer;
1695 const char *pConstCharBuffer;
1696 const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
1697 UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1698 UChar uniCharBuffer[20];
1699 char charSourceBuffer[] = { 0x1b, 0x24, 0x42 };
1700 const char *pCharSource = charSourceBuffer;
1701 const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
1702 UChar *pUCharTarget = uniCharBuffer;
1703 UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer)/sizeof(*uniCharBuffer);
1704 const UChar * pUniBuffer;
1705 const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
1706 int32_t idx, j;
1707
1708 err = U_ZERO_ERROR;
1709 cnv = ucnv_open(names[0], &err);
1710 if(U_SUCCESS(err)) {
1711 /* Check the various error & informational states: */
1712
1713 /* Null status - just returns NULL */
1714 bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1715 if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, NULL))
1716 {
1717 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1718 }
1719 /* error status - should return 0 & keep error the same */
1720 err = U_MEMORY_ALLOCATION_ERROR;
1721 if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR)
1722 {
1723 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1724 }
1725 err = U_ZERO_ERROR;
1726
1727 /* Null buffer size pointer is ok */
1728 if (NULL == (cnv2 = ucnv_safeClone(cnv, buffer[0], NULL, &err)) || U_FAILURE(err))
1729 {
1730 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1731 }
1732 ucnv_close(cnv2);
1733 err = U_ZERO_ERROR;
1734
1735 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1736 bufferSize = 0;
1737 if (NULL != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0)
1738 {
1739 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1740 }
1741 /* Verify our define is large enough */
1742 if (U_CNV_SAFECLONE_BUFFERSIZE < bufferSize)
1743 {
1744 log_err("FAIL: Pre-calculated buffer size is too small\n");
1745 }
1746 /* Verify we can use this run-time calculated size */
1747 if (NULL == (cnv2 = ucnv_safeClone(cnv, buffer[0], &bufferSize, &err)) || U_FAILURE(err))
1748 {
1749 log_err("FAIL: Converter can't be cloned with run-time size\n");
1750 }
1751 if (cnv2) {
1752 ucnv_close(cnv2);
1753 }
1754
1755 /* size one byte too small - should allocate & let us know */
1756 --bufferSize;
1757 if (NULL == (cnv2 = ucnv_safeClone(cnv, NULL, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1758 {
1759 log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1760 }
1761 if (cnv2) {
1762 ucnv_close(cnv2);
1763 }
1764
1765 err = U_ZERO_ERROR;
1766 bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1767
1768 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1769 if (NULL == (cnv2 = ucnv_safeClone(cnv, NULL, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1770 {
1771 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1772 }
1773 if (cnv2) {
1774 ucnv_close(cnv2);
1775 }
1776
1777 err = U_ZERO_ERROR;
1778
1779 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1780 if (NULL != ucnv_safeClone(NULL, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
1781 {
1782 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1783 }
1784
1785 ucnv_close(cnv);
1786 }
1787
1788 maxBufferSize = 0;
1789 maxName = "";
1790
1791 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1792
1793 for(j = 0; j < UPRV_LENGTHOF(bufferSizes); ++j) {
1794 for (idx = 0; idx < UPRV_LENGTHOF(names); idx++)
1795 {
1796 err = U_ZERO_ERROR;
1797 cnv = ucnv_open(names[idx], &err);
1798 if(U_FAILURE(err)) {
1799 log_data_err("ucnv_open(\"%s\") failed - %s\n", names[idx], u_errorName(err));
1800 continue;
1801 }
1802
1803 if(j == 0) {
1804 /* preflight to get maxBufferSize */
1805 actualSizes[idx] = 0;
1806 ucnv_safeClone(cnv, NULL, &actualSizes[idx], &err);
1807 if(actualSizes[idx] > maxBufferSize) {
1808 maxBufferSize = actualSizes[idx];
1809 maxName = names[idx];
1810 }
1811 }
1812
1813 memset(buffer, 0xaa, sizeof(buffer));
1814
1815 bufferSize = bufferSizes[j];
1816 cnv2 = ucnv_safeClone(cnv, buffer[1], &bufferSize, &err);
1817
1818 /* close the original immediately to make sure that the clone works by itself */
1819 ucnv_close(cnv);
1820
1821 if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) &&
1822 err == U_SAFECLONE_ALLOCATED_WARNING
1823 ) {
1824 log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[idx]);
1825 }
1826
1827 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1828 if(bufferSize <= bufferSizes[j]) {
1829 /* used the stack buffer */
1830 if( containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer[0]), 0xaa) ||
1831 containsAnyOtherByte(buffer[1]+bufferSize, (int32_t)(sizeof(buffer)-(sizeof(buffer[0])+bufferSize)), 0xaa)
1832 ) {
1833 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1834 names[idx], bufferSize, bufferSizes[j]);
1835 }
1836 } else {
1837 /* heap-allocated the clone */
1838 if(containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer), 0xaa)) {
1839 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1840 names[idx], bufferSize, bufferSizes[j]);
1841 }
1842 }
1843
1844 pCharBuffer = charBuffer;
1845 pUniBuffer = uniBuffer;
1846
1847 ucnv_fromUnicode(cnv2,
1848 &pCharBuffer,
1849 charBufferLimit,
1850 &pUniBuffer,
1851 uniBufferLimit,
1852 NULL,
1853 TRUE,
1854 &err);
1855 if(U_FAILURE(err)){
1856 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err));
1857 }
1858 ucnv_toUnicode(cnv2,
1859 &pUCharTarget,
1860 pUCharTargetLimit,
1861 &pCharSource,
1862 pCharSourceLimit,
1863 NULL,
1864 TRUE,
1865 &err
1866 );
1867
1868 if(U_FAILURE(err)){
1869 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err));
1870 }
1871
1872 pConstCharBuffer = charBuffer;
1873 if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err))
1874 {
1875 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err));
1876 }
1877 ucnv_close(cnv2);
1878 }
1879 }
1880
1881 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1882 sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
1883 if(maxBufferSize > U_CNV_SAFECLONE_BUFFERSIZE) {
1884 log_err("ucnv_safeClone(): max preflighted clone size=%d (%s) is larger than U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1885 maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
1886 }
1887 }
1888
TestCCSID()1889 static void TestCCSID() {
1890 #if !UCONFIG_NO_LEGACY_CONVERSION
1891 UConverter *cnv;
1892 UErrorCode errorCode;
1893 int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1894 int32_t i, ccsid;
1895
1896 for(i=0; i<(int32_t)(sizeof(ccsids)/sizeof(int32_t)); ++i) {
1897 ccsid=ccsids[i];
1898
1899 errorCode=U_ZERO_ERROR;
1900 cnv=ucnv_openCCSID(ccsid, UCNV_IBM, &errorCode);
1901 if(U_FAILURE(errorCode)) {
1902 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid, u_errorName(errorCode));
1903 continue;
1904 }
1905
1906 if(ccsid!=ucnv_getCCSID(cnv, &errorCode)) {
1907 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid, ucnv_getCCSID(cnv, &errorCode));
1908 }
1909
1910 /* skip gb18030(ccsid 1392) */
1911 if(ccsid != 1392 && UCNV_IBM!=ucnv_getPlatform(cnv, &errorCode)) {
1912 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid, ucnv_getPlatform(cnv, &errorCode));
1913 }
1914
1915 ucnv_close(cnv);
1916 }
1917 #endif
1918 }
1919
1920 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1921
1922 /* CHUNK_SIZE defined in common\ucnv.c: */
1923 #define CHUNK_SIZE 1024
1924
1925 static void bug1(void);
1926 static void bug2(void);
1927 static void bug3(void);
1928
1929 static void
TestJ932(void)1930 TestJ932(void)
1931 {
1932 bug1(); /* Unicode intermediate buffer straddle bug */
1933 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1934 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1935 }
1936
1937 /*
1938 * jitterbug 932: test chunking boundary conditions in
1939
1940 int32_t ucnv_convert(const char *toConverterName,
1941 const char *fromConverterName,
1942 char *target,
1943 int32_t targetSize,
1944 const char *source,
1945 int32_t sourceSize,
1946 UErrorCode * err)
1947
1948 * See discussions on the icu mailing list in
1949 * 2001-April with the subject "converter 'flush' question".
1950 *
1951 * Bug report and test code provided by Edward J. Batutis.
1952 */
bug1()1953 static void bug1()
1954 {
1955 #if !UCONFIG_NO_LEGACY_CONVERSION
1956 char char_in[CHUNK_SIZE+32];
1957 char char_out[CHUNK_SIZE*2];
1958
1959 /* GB 18030 equivalent of U+10000 is 90308130 */
1960 static const char test_seq[]={ (char)0x90u, 0x30, (char)0x81u, 0x30 };
1961
1962 UErrorCode err = U_ZERO_ERROR;
1963 int32_t i, test_seq_len = sizeof(test_seq);
1964
1965 /*
1966 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1967 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1968 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1969 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1970 * other Unicode sequences cause a bug since combining sequences are not supported by the
1971 * converters.
1972 */
1973
1974 for (i = test_seq_len; i >= 0; i--) {
1975 /* put character sequence into input buffer */
1976 memset(char_in, 0x61, sizeof(char_in)); /* GB 18030 'a' */
1977 memcpy(char_in + (CHUNK_SIZE - i), test_seq, test_seq_len);
1978
1979 /* do the conversion */
1980 ucnv_convert("us-ascii", /* out */
1981 "gb18030", /* in */
1982 char_out,
1983 sizeof(char_out),
1984 char_in,
1985 sizeof(char_in),
1986 &err);
1987
1988 /* bug1: */
1989 if (err == U_TRUNCATED_CHAR_FOUND) {
1990 /* this happens when surrogate pair straddles the intermediate buffer in
1991 * T_UConverter_fromCodepageToCodepage */
1992 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
1993 }
1994 }
1995 #endif
1996 }
1997
1998 /* bug2: pre-flighting loop bug: simple overflow causes bug */
bug2()1999 static void bug2()
2000 {
2001 /* US-ASCII "1234567890" */
2002 static const char source[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
2003 #if !UCONFIG_ONLY_HTML_CONVERSION
2004 static const char sourceUTF8[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
2005 static const char sourceUTF32[]={ 0x00, 0x00, 0x00, 0x30,
2006 0x00, 0x00, 0x00, 0x31,
2007 0x00, 0x00, 0x00, 0x32,
2008 0x00, 0x00, 0x00, 0x33,
2009 0x00, 0x00, 0x00, 0x34,
2010 0x00, 0x00, 0x00, 0x35,
2011 0x00, 0x00, 0x00, 0x36,
2012 0x00, 0x00, 0x00, 0x37,
2013 0x00, 0x00, 0x00, 0x38,
2014 0x00, 0x00, (char)0xf0, 0x00};
2015 #endif
2016
2017 static char target[5];
2018
2019 UErrorCode err = U_ZERO_ERROR;
2020 int32_t size;
2021
2022 /* do the conversion */
2023 size = ucnv_convert("iso-8859-1", /* out */
2024 "us-ascii", /* in */
2025 target,
2026 sizeof(target),
2027 source,
2028 sizeof(source),
2029 &err);
2030
2031 if ( size != 10 ) {
2032 /* bug2: size is 5, should be 10 */
2033 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size);
2034 }
2035
2036 #if !UCONFIG_ONLY_HTML_CONVERSION
2037 err = U_ZERO_ERROR;
2038 /* do the conversion */
2039 size = ucnv_convert("UTF-32BE", /* out */
2040 "UTF-8", /* in */
2041 target,
2042 sizeof(target),
2043 sourceUTF8,
2044 sizeof(sourceUTF8),
2045 &err);
2046
2047 if ( size != 32 ) {
2048 /* bug2: size is 5, should be 32 */
2049 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size);
2050 }
2051
2052 err = U_ZERO_ERROR;
2053 /* do the conversion */
2054 size = ucnv_convert("UTF-8", /* out */
2055 "UTF-32BE", /* in */
2056 target,
2057 sizeof(target),
2058 sourceUTF32,
2059 sizeof(sourceUTF32),
2060 &err);
2061
2062 if ( size != 12 ) {
2063 /* bug2: size is 5, should be 12 */
2064 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size);
2065 }
2066 #endif
2067 }
2068
2069 /*
2070 * bug3: when the characters expand going from source to target codepage
2071 * you get bug3 in addition to bug2
2072 */
bug3()2073 static void bug3()
2074 {
2075 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
2076 char char_in[CHUNK_SIZE*4];
2077 char target[5];
2078 UErrorCode err = U_ZERO_ERROR;
2079 int32_t size;
2080
2081 /*
2082 * first get the buggy size from bug2 then
2083 * compare it to buggy size with an expansion
2084 */
2085 memset(char_in, 0x61, sizeof(char_in)); /* US-ASCII 'a' */
2086
2087 /* do the conversion */
2088 size = ucnv_convert("lmbcs", /* out */
2089 "us-ascii", /* in */
2090 target,
2091 sizeof(target),
2092 char_in,
2093 sizeof(char_in),
2094 &err);
2095
2096 if ( size != sizeof(char_in) ) {
2097 /*
2098 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2099 * in the converter?), should be CHUNK_SIZE*4
2100 *
2101 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2102 */
2103 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in), size);
2104 }
2105
2106 /*
2107 * now do the conversion with expansion
2108 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2109 */
2110 memset(char_in, 8, sizeof(char_in));
2111 err = U_ZERO_ERROR;
2112
2113 /* do the conversion */
2114 size = ucnv_convert("lmbcs", /* out */
2115 "us-ascii", /* in */
2116 target,
2117 sizeof(target),
2118 char_in,
2119 sizeof(char_in),
2120 &err);
2121
2122 /* expect 2X expansion */
2123 if ( size != sizeof(char_in) * 2 ) {
2124 /*
2125 * bug3:
2126 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2127 */
2128 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size);
2129 }
2130 #endif
2131 }
2132
2133 static void
convertExStreaming(UConverter * srcCnv,UConverter * targetCnv,const char * src,int32_t srcLength,const char * expectTarget,int32_t expectTargetLength,int32_t chunkSize,const char * testName,UErrorCode expectCode)2134 convertExStreaming(UConverter *srcCnv, UConverter *targetCnv,
2135 const char *src, int32_t srcLength,
2136 const char *expectTarget, int32_t expectTargetLength,
2137 int32_t chunkSize,
2138 const char *testName,
2139 UErrorCode expectCode) {
2140 UChar pivotBuffer[CHUNK_SIZE];
2141 UChar *pivotSource, *pivotTarget;
2142 const UChar *pivotLimit;
2143
2144 char targetBuffer[CHUNK_SIZE];
2145 char *target;
2146 const char *srcLimit, *finalSrcLimit, *targetLimit;
2147
2148 int32_t targetLength;
2149
2150 UBool flush;
2151
2152 UErrorCode errorCode;
2153
2154 /* setup */
2155 if(chunkSize>CHUNK_SIZE) {
2156 chunkSize=CHUNK_SIZE;
2157 }
2158
2159 pivotSource=pivotTarget=pivotBuffer;
2160 pivotLimit=pivotBuffer+chunkSize;
2161
2162 finalSrcLimit=src+srcLength;
2163 target=targetBuffer;
2164 targetLimit=targetBuffer+chunkSize;
2165
2166 ucnv_resetToUnicode(srcCnv);
2167 ucnv_resetFromUnicode(targetCnv);
2168
2169 errorCode=U_ZERO_ERROR;
2170 flush=FALSE;
2171
2172 /* convert, streaming-style (both converters and pivot keep state) */
2173 for(;;) {
2174 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2175 if(src+chunkSize<=finalSrcLimit) {
2176 srcLimit=src+chunkSize;
2177 } else {
2178 srcLimit=finalSrcLimit;
2179 }
2180 ucnv_convertEx(targetCnv, srcCnv,
2181 &target, targetLimit,
2182 &src, srcLimit,
2183 pivotBuffer, &pivotSource, &pivotTarget, pivotLimit,
2184 FALSE, flush, &errorCode);
2185 targetLength=(int32_t)(target-targetBuffer);
2186 if(target>targetLimit) {
2187 log_err("ucnv_convertEx(%s) chunk[%d] target %p exceeds targetLimit %p\n",
2188 testName, chunkSize, target, targetLimit);
2189 break; /* TODO: major problem! */
2190 }
2191 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
2192 /* continue converting another chunk */
2193 errorCode=U_ZERO_ERROR;
2194 if(targetLength+chunkSize<=sizeof(targetBuffer)) {
2195 targetLimit=target+chunkSize;
2196 } else {
2197 targetLimit=targetBuffer+sizeof(targetBuffer);
2198 }
2199 } else if(U_FAILURE(errorCode)) {
2200 /* failure */
2201 break;
2202 } else if(flush) {
2203 /* all done */
2204 break;
2205 } else if(src==finalSrcLimit && pivotSource==pivotTarget) {
2206 /* all consumed, now flush without input (separate from conversion for testing) */
2207 flush=TRUE;
2208 }
2209 }
2210
2211 if(!(errorCode==expectCode || (expectCode==U_ZERO_ERROR && errorCode==U_STRING_NOT_TERMINATED_WARNING))) {
2212 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2213 testName, chunkSize, u_errorName(errorCode), u_errorName(expectCode));
2214 } else if(targetLength!=expectTargetLength) {
2215 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2216 testName, chunkSize, targetLength, expectTargetLength);
2217 } else if(memcmp(targetBuffer, expectTarget, targetLength)!=0) {
2218 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2219 testName, chunkSize);
2220 }
2221 }
2222
2223 static void
convertExMultiStreaming(UConverter * srcCnv,UConverter * targetCnv,const char * src,int32_t srcLength,const char * expectTarget,int32_t expectTargetLength,const char * testName,UErrorCode expectCode)2224 convertExMultiStreaming(UConverter *srcCnv, UConverter *targetCnv,
2225 const char *src, int32_t srcLength,
2226 const char *expectTarget, int32_t expectTargetLength,
2227 const char *testName,
2228 UErrorCode expectCode) {
2229 convertExStreaming(srcCnv, targetCnv,
2230 src, srcLength,
2231 expectTarget, expectTargetLength,
2232 1, testName, expectCode);
2233 convertExStreaming(srcCnv, targetCnv,
2234 src, srcLength,
2235 expectTarget, expectTargetLength,
2236 3, testName, expectCode);
2237 convertExStreaming(srcCnv, targetCnv,
2238 src, srcLength,
2239 expectTarget, expectTargetLength,
2240 7, testName, expectCode);
2241 }
2242
TestConvertEx()2243 static void TestConvertEx() {
2244 #if !UCONFIG_NO_LEGACY_CONVERSION
2245 static const uint8_t
2246 utf8[]={
2247 /* 4e00 30a1 ff61 0410 */
2248 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2249 },
2250 shiftJIS[]={
2251 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2252 },
2253 errorTarget[]={
2254 /*
2255 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2256 * SUB, SUB, 0x40, SUB, SUB, 0x40
2257 */
2258 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2259 };
2260
2261 char srcBuffer[100], targetBuffer[100];
2262
2263 const char *src;
2264 char *target;
2265
2266 UChar pivotBuffer[100];
2267 UChar *pivotSource, *pivotTarget;
2268
2269 UConverter *cnv1, *cnv2;
2270 UErrorCode errorCode;
2271
2272 errorCode=U_ZERO_ERROR;
2273 cnv1=ucnv_open("UTF-8", &errorCode);
2274 if(U_FAILURE(errorCode)) {
2275 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode));
2276 return;
2277 }
2278
2279 cnv2=ucnv_open("Shift-JIS", &errorCode);
2280 if(U_FAILURE(errorCode)) {
2281 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2282 ucnv_close(cnv1);
2283 return;
2284 }
2285
2286 /* test ucnv_convertEx() with streaming conversion style */
2287 convertExMultiStreaming(cnv1, cnv2,
2288 (const char *)utf8, sizeof(utf8), (const char *)shiftJIS, sizeof(shiftJIS),
2289 "UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2290
2291 convertExMultiStreaming(cnv2, cnv1,
2292 (const char *)shiftJIS, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8),
2293 "Shift-JIS -> UTF-8", U_ZERO_ERROR);
2294
2295 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2296 convertExMultiStreaming(cnv1, cnv2,
2297 (const char *)shiftJIS, sizeof(shiftJIS), (const char *)errorTarget, sizeof(errorTarget),
2298 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2299
2300 /* test some simple conversions */
2301
2302 /* NUL-terminated source and target */
2303 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2304 memcpy(srcBuffer, utf8, sizeof(utf8));
2305 srcBuffer[sizeof(utf8)]=0;
2306 src=srcBuffer;
2307 target=targetBuffer;
2308 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2309 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2310 if( errorCode!=U_ZERO_ERROR ||
2311 target-targetBuffer!=sizeof(shiftJIS) ||
2312 *target!=0 ||
2313 memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2314 ) {
2315 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2316 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2317 }
2318
2319 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2320 errorCode=U_AMBIGUOUS_ALIAS_WARNING;
2321 memset(targetBuffer, 0xff, sizeof(targetBuffer));
2322 src=srcBuffer;
2323 target=targetBuffer;
2324 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(shiftJIS), &src, NULL,
2325 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2326 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2327 target-targetBuffer!=sizeof(shiftJIS) ||
2328 *target!=(char)0xff ||
2329 memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2330 ) {
2331 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2332 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2333 }
2334
2335 /* bad arguments */
2336 errorCode=U_MESSAGE_PARSE_ERROR;
2337 src=srcBuffer;
2338 target=targetBuffer;
2339 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2340 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2341 if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2342 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2343 }
2344
2345 /* pivotLimit==pivotStart */
2346 errorCode=U_ZERO_ERROR;
2347 pivotSource=pivotTarget=pivotBuffer;
2348 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2349 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer, TRUE, TRUE, &errorCode);
2350 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2351 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode));
2352 }
2353
2354 /* *pivotSource==NULL */
2355 errorCode=U_ZERO_ERROR;
2356 pivotSource=NULL;
2357 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2358 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2359 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2360 log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode));
2361 }
2362
2363 /* *source==NULL */
2364 errorCode=U_ZERO_ERROR;
2365 src=NULL;
2366 pivotSource=pivotBuffer;
2367 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2368 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2369 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2370 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode));
2371 }
2372
2373 /* streaming conversion without a pivot buffer */
2374 errorCode=U_ZERO_ERROR;
2375 src=srcBuffer;
2376 pivotSource=pivotBuffer;
2377 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2378 NULL, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, FALSE, &errorCode);
2379 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2380 log_err("ucnv_convertEx(pivotStart==NULL) sets %s\n", u_errorName(errorCode));
2381 }
2382
2383 ucnv_close(cnv1);
2384 ucnv_close(cnv2);
2385 #endif
2386 }
2387
2388 /* Test illegal UTF-8 input: Data and functions for TestConvertExFromUTF8(). */
2389 static const char *const badUTF8[]={
2390 /* trail byte */
2391 "\x80",
2392
2393 /* truncated multi-byte sequences */
2394 "\xd0",
2395 "\xe0",
2396 "\xe1",
2397 "\xed",
2398 "\xee",
2399 "\xf0",
2400 "\xf1",
2401 "\xf4",
2402 "\xf8",
2403 "\xfc",
2404
2405 "\xe0\x80",
2406 "\xe0\xa0",
2407 "\xe1\x80",
2408 "\xed\x80",
2409 "\xed\xa0",
2410 "\xee\x80",
2411 "\xf0\x80",
2412 "\xf0\x90",
2413 "\xf1\x80",
2414 "\xf4\x80",
2415 "\xf4\x90",
2416 "\xf8\x80",
2417 "\xfc\x80",
2418
2419 "\xf0\x80\x80",
2420 "\xf0\x90\x80",
2421 "\xf1\x80\x80",
2422 "\xf4\x80\x80",
2423 "\xf4\x90\x80",
2424 "\xf8\x80\x80",
2425 "\xfc\x80\x80",
2426
2427 "\xf8\x80\x80\x80",
2428 "\xfc\x80\x80\x80",
2429
2430 "\xfc\x80\x80\x80\x80",
2431
2432 /* complete sequences but non-shortest forms or out of range etc. */
2433 "\xc0\x80",
2434 "\xe0\x80\x80",
2435 "\xed\xa0\x80",
2436 "\xf0\x80\x80\x80",
2437 "\xf4\x90\x80\x80",
2438 "\xf8\x80\x80\x80\x80",
2439 "\xfc\x80\x80\x80\x80\x80",
2440 "\xfe",
2441 "\xff"
2442 };
2443
2444 #define ARG_CHAR_ARR_SIZE 8
2445
2446 /* get some character that can be converted and convert it */
getTestChar(UConverter * cnv,const char * converterName,char charUTF8[4],int32_t * pCharUTF8Length,char char0[ARG_CHAR_ARR_SIZE],int32_t * pChar0Length,char char1[ARG_CHAR_ARR_SIZE],int32_t * pChar1Length)2447 static UBool getTestChar(UConverter *cnv, const char *converterName,
2448 char charUTF8[4], int32_t *pCharUTF8Length,
2449 char char0[ARG_CHAR_ARR_SIZE], int32_t *pChar0Length,
2450 char char1[ARG_CHAR_ARR_SIZE], int32_t *pChar1Length) {
2451 UChar utf16[U16_MAX_LENGTH];
2452 int32_t utf16Length;
2453
2454 const UChar *utf16Source;
2455 char *target;
2456
2457 USet *set;
2458 UChar32 c;
2459 UErrorCode errorCode;
2460
2461 errorCode=U_ZERO_ERROR;
2462 set=uset_open(1, 0);
2463 ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &errorCode);
2464 c=uset_charAt(set, uset_size(set)/2);
2465 uset_close(set);
2466
2467 utf16Length=0;
2468 U16_APPEND_UNSAFE(utf16, utf16Length, c);
2469 *pCharUTF8Length=0;
2470 U8_APPEND_UNSAFE(charUTF8, *pCharUTF8Length, c);
2471
2472 utf16Source=utf16;
2473 target=char0;
2474 ucnv_fromUnicode(cnv,
2475 &target, char0+ARG_CHAR_ARR_SIZE,
2476 &utf16Source, utf16+utf16Length,
2477 NULL, FALSE, &errorCode);
2478 *pChar0Length=(int32_t)(target-char0);
2479
2480 utf16Source=utf16;
2481 target=char1;
2482 ucnv_fromUnicode(cnv,
2483 &target, char1+ARG_CHAR_ARR_SIZE,
2484 &utf16Source, utf16+utf16Length,
2485 NULL, FALSE, &errorCode);
2486 *pChar1Length=(int32_t)(target-char1);
2487
2488 if(U_FAILURE(errorCode)) {
2489 log_err("unable to get test character for %s - %s\n", converterName, u_errorName(errorCode));
2490 return FALSE;
2491 }
2492 return TRUE;
2493 }
2494
testFromTruncatedUTF8(UConverter * utf8Cnv,UConverter * cnv,const char * converterName,char charUTF8[4],int32_t charUTF8Length,char char0[8],int32_t char0Length,char char1[8],int32_t char1Length)2495 static void testFromTruncatedUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
2496 char charUTF8[4], int32_t charUTF8Length,
2497 char char0[8], int32_t char0Length,
2498 char char1[8], int32_t char1Length) {
2499 char utf8[16];
2500 int32_t utf8Length;
2501
2502 char output[16];
2503 int32_t outputLength;
2504
2505 char invalidChars[8];
2506 int8_t invalidLength;
2507
2508 const char *source;
2509 char *target;
2510
2511 UChar pivotBuffer[8];
2512 UChar *pivotSource, *pivotTarget;
2513
2514 UErrorCode errorCode;
2515 int32_t i;
2516
2517 /* test truncated sequences */
2518 errorCode=U_ZERO_ERROR;
2519 ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
2520
2521 memcpy(utf8, charUTF8, charUTF8Length);
2522
2523 for(i=0; i<UPRV_LENGTHOF(badUTF8); ++i) {
2524 /* truncated sequence? */
2525 int32_t length=strlen(badUTF8[i]);
2526 if(length>=(1+U8_COUNT_TRAIL_BYTES(badUTF8[i][0]))) {
2527 continue;
2528 }
2529
2530 /* assemble a string with the test character and the truncated sequence */
2531 memcpy(utf8+charUTF8Length, badUTF8[i], length);
2532 utf8Length=charUTF8Length+length;
2533
2534 /* convert and check the invalidChars */
2535 source=utf8;
2536 target=output;
2537 pivotSource=pivotTarget=pivotBuffer;
2538 errorCode=U_ZERO_ERROR;
2539 ucnv_convertEx(cnv, utf8Cnv,
2540 &target, output+sizeof(output),
2541 &source, utf8+utf8Length,
2542 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+UPRV_LENGTHOF(pivotBuffer),
2543 TRUE, TRUE, /* reset & flush */
2544 &errorCode);
2545 outputLength=(int32_t)(target-output);
2546 (void)outputLength; /* Suppress set but not used warning. */
2547 if(errorCode!=U_TRUNCATED_CHAR_FOUND || pivotSource!=pivotBuffer) {
2548 log_err("unexpected error %s from %s badUTF8[%ld]\n", u_errorName(errorCode), converterName, (long)i);
2549 continue;
2550 }
2551
2552 errorCode=U_ZERO_ERROR;
2553 invalidLength=(int8_t)sizeof(invalidChars);
2554 ucnv_getInvalidChars(utf8Cnv, invalidChars, &invalidLength, &errorCode);
2555 if(invalidLength!=length || 0!=memcmp(invalidChars, badUTF8[i], length)) {
2556 log_err("wrong invalidChars from %s badUTF8[%ld]\n", converterName, (long)i);
2557 }
2558 }
2559 }
2560
testFromBadUTF8(UConverter * utf8Cnv,UConverter * cnv,const char * converterName,char charUTF8[4],int32_t charUTF8Length,char char0[8],int32_t char0Length,char char1[8],int32_t char1Length)2561 static void testFromBadUTF8(UConverter *utf8Cnv, UConverter *cnv, const char *converterName,
2562 char charUTF8[4], int32_t charUTF8Length,
2563 char char0[8], int32_t char0Length,
2564 char char1[8], int32_t char1Length) {
2565 char utf8[600], expect[600];
2566 int32_t utf8Length, expectLength;
2567
2568 char testName[32];
2569
2570 UErrorCode errorCode;
2571 int32_t i;
2572
2573 errorCode=U_ZERO_ERROR;
2574 ucnv_setToUCallBack(utf8Cnv, UCNV_TO_U_CALLBACK_SKIP, NULL, NULL, NULL, &errorCode);
2575
2576 /*
2577 * assemble an input string with the test character between each
2578 * bad sequence,
2579 * and an expected string with repeated test character output
2580 */
2581 memcpy(utf8, charUTF8, charUTF8Length);
2582 utf8Length=charUTF8Length;
2583
2584 memcpy(expect, char0, char0Length);
2585 expectLength=char0Length;
2586
2587 for(i=0; i<UPRV_LENGTHOF(badUTF8); ++i) {
2588 int32_t length=strlen(badUTF8[i]);
2589 memcpy(utf8+utf8Length, badUTF8[i], length);
2590 utf8Length+=length;
2591
2592 memcpy(utf8+utf8Length, charUTF8, charUTF8Length);
2593 utf8Length+=charUTF8Length;
2594
2595 memcpy(expect+expectLength, char1, char1Length);
2596 expectLength+=char1Length;
2597 }
2598
2599 /* expect that each bad UTF-8 sequence is detected and skipped */
2600 strcpy(testName, "from bad UTF-8 to ");
2601 strcat(testName, converterName);
2602
2603 convertExMultiStreaming(utf8Cnv, cnv,
2604 utf8, utf8Length,
2605 expect, expectLength,
2606 testName,
2607 U_ZERO_ERROR);
2608 }
2609
2610 /* Test illegal UTF-8 input. */
TestConvertExFromUTF8()2611 static void TestConvertExFromUTF8() {
2612 static const char *const converterNames[]={
2613 #if !UCONFIG_NO_LEGACY_CONVERSION
2614 "windows-1252",
2615 "shift-jis",
2616 #endif
2617 "us-ascii",
2618 "iso-8859-1",
2619 "utf-8"
2620 };
2621
2622 UConverter *utf8Cnv, *cnv;
2623 UErrorCode errorCode;
2624 int32_t i;
2625
2626 /* fromUnicode versions of some character, from initial state and later */
2627 char charUTF8[4], char0[8], char1[8];
2628 int32_t charUTF8Length, char0Length, char1Length;
2629
2630 errorCode=U_ZERO_ERROR;
2631 utf8Cnv=ucnv_open("UTF-8", &errorCode);
2632 if(U_FAILURE(errorCode)) {
2633 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode));
2634 return;
2635 }
2636
2637 for(i=0; i<UPRV_LENGTHOF(converterNames); ++i) {
2638 errorCode=U_ZERO_ERROR;
2639 cnv=ucnv_open(converterNames[i], &errorCode);
2640 if(U_FAILURE(errorCode)) {
2641 log_data_err("unable to open %s converter - %s\n", converterNames[i], u_errorName(errorCode));
2642 continue;
2643 }
2644 if(!getTestChar(cnv, converterNames[i], charUTF8, &charUTF8Length, char0, &char0Length, char1, &char1Length)) {
2645 continue;
2646 }
2647 testFromTruncatedUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
2648 testFromBadUTF8(utf8Cnv, cnv, converterNames[i], charUTF8, charUTF8Length, char0, char0Length, char1, char1Length);
2649 ucnv_close(cnv);
2650 }
2651 ucnv_close(utf8Cnv);
2652 }
2653
TestConvertExFromUTF8_C5F0()2654 static void TestConvertExFromUTF8_C5F0() {
2655 static const char *const converterNames[]={
2656 #if !UCONFIG_NO_LEGACY_CONVERSION
2657 "windows-1251",
2658 "shift-jis",
2659 #endif
2660 "us-ascii",
2661 "iso-8859-1",
2662 "utf-8"
2663 };
2664
2665 UConverter *utf8Cnv, *cnv;
2666 UErrorCode errorCode;
2667 int32_t i;
2668
2669 static const char bad_utf8[2]={ (char)0xC5, (char)0xF0 };
2670 /* Expect "��" (2x U+FFFD as decimal NCRs) */
2671 static const char twoNCRs[16]={
2672 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B,
2673 0x26, 0x23, 0x36, 0x35, 0x35, 0x33, 0x33, 0x3B
2674 };
2675 static const char twoFFFD[6]={
2676 (char)0xef, (char)0xbf, (char)0xbd,
2677 (char)0xef, (char)0xbf, (char)0xbd
2678 };
2679 const char *expected;
2680 int32_t expectedLength;
2681 char dest[20]; /* longer than longest expectedLength */
2682
2683 const char *src;
2684 char *target;
2685
2686 UChar pivotBuffer[128];
2687 UChar *pivotSource, *pivotTarget;
2688
2689 errorCode=U_ZERO_ERROR;
2690 utf8Cnv=ucnv_open("UTF-8", &errorCode);
2691 if(U_FAILURE(errorCode)) {
2692 log_data_err("unable to open UTF-8 converter - %s\n", u_errorName(errorCode));
2693 return;
2694 }
2695
2696 for(i=0; i<UPRV_LENGTHOF(converterNames); ++i) {
2697 errorCode=U_ZERO_ERROR;
2698 cnv=ucnv_open(converterNames[i], &errorCode);
2699 ucnv_setFromUCallBack(cnv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_XML_DEC,
2700 NULL, NULL, &errorCode);
2701 if(U_FAILURE(errorCode)) {
2702 log_data_err("unable to open %s converter - %s\n",
2703 converterNames[i], u_errorName(errorCode));
2704 continue;
2705 }
2706 src=bad_utf8;
2707 target=dest;
2708 uprv_memset(dest, 9, sizeof(dest));
2709 if(i==UPRV_LENGTHOF(converterNames)-1) {
2710 /* conversion to UTF-8 yields two U+FFFD directly */
2711 expected=twoFFFD;
2712 expectedLength=6;
2713 } else {
2714 /* conversion to a non-Unicode charset yields two NCRs */
2715 expected=twoNCRs;
2716 expectedLength=16;
2717 }
2718 pivotBuffer[0]=0;
2719 pivotBuffer[1]=1;
2720 pivotBuffer[2]=2;
2721 pivotSource=pivotTarget=pivotBuffer;
2722 ucnv_convertEx(
2723 cnv, utf8Cnv,
2724 &target, dest+expectedLength,
2725 &src, bad_utf8+sizeof(bad_utf8),
2726 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+UPRV_LENGTHOF(pivotBuffer),
2727 TRUE, TRUE, &errorCode);
2728 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING || src!=bad_utf8+2 ||
2729 target!=dest+expectedLength || 0!=uprv_memcmp(dest, expected, expectedLength) ||
2730 dest[expectedLength]!=9
2731 ) {
2732 log_err("ucnv_convertEx(UTF-8 C5 F0 -> %s/decimal NCRs) failed\n", converterNames[i]);
2733 }
2734 ucnv_close(cnv);
2735 }
2736 ucnv_close(utf8Cnv);
2737 }
2738
2739 static void
TestConvertAlgorithmic()2740 TestConvertAlgorithmic() {
2741 #if !UCONFIG_NO_LEGACY_CONVERSION
2742 static const uint8_t
2743 utf8[]={
2744 /* 4e00 30a1 ff61 0410 */
2745 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2746 },
2747 shiftJIS[]={
2748 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2749 },
2750 /*errorTarget[]={*/
2751 /*
2752 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2753 * SUB, SUB, 0x40, SUB, SUB, 0x40
2754 */
2755 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2756 /*},*/
2757 utf16[]={
2758 0xfe, 0xff /* BOM only, no text */
2759 };
2760 #if !UCONFIG_ONLY_HTML_CONVERSION
2761 static const uint8_t utf32[]={
2762 0xff, 0xfe, 0, 0 /* BOM only, no text */
2763 };
2764 #endif
2765
2766 char target[100], utf8NUL[100], shiftJISNUL[100];
2767
2768 UConverter *cnv;
2769 UErrorCode errorCode;
2770
2771 int32_t length;
2772
2773 errorCode=U_ZERO_ERROR;
2774 cnv=ucnv_open("Shift-JIS", &errorCode);
2775 if(U_FAILURE(errorCode)) {
2776 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2777 ucnv_close(cnv);
2778 return;
2779 }
2780
2781 memcpy(utf8NUL, utf8, sizeof(utf8));
2782 utf8NUL[sizeof(utf8)]=0;
2783 memcpy(shiftJISNUL, shiftJIS, sizeof(shiftJIS));
2784 shiftJISNUL[sizeof(shiftJIS)]=0;
2785
2786 /*
2787 * The to/from algorithmic convenience functions share a common implementation,
2788 * so we need not test all permutations of them.
2789 */
2790
2791 /* length in, not terminated out */
2792 errorCode=U_ZERO_ERROR;
2793 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF8, target, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), &errorCode);
2794 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2795 length!=sizeof(shiftJIS) ||
2796 memcmp(target, shiftJIS, length)!=0
2797 ) {
2798 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2799 u_errorName(errorCode), length, sizeof(shiftJIS));
2800 }
2801
2802 /* terminated in and out */
2803 memset(target, 0x55, sizeof(target));
2804 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2805 length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, -1, &errorCode);
2806 if( errorCode!=U_ZERO_ERROR ||
2807 length!=sizeof(utf8) ||
2808 memcmp(target, utf8, length)!=0
2809 ) {
2810 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2811 u_errorName(errorCode), length, sizeof(shiftJIS));
2812 }
2813
2814 /* empty string, some target buffer */
2815 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2816 length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, 0, &errorCode);
2817 if( errorCode!=U_ZERO_ERROR ||
2818 length!=0
2819 ) {
2820 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2821 u_errorName(errorCode), length);
2822 }
2823
2824 /* pseudo-empty string, no target buffer */
2825 errorCode=U_ZERO_ERROR;
2826 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2827 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2828 length!=0
2829 ) {
2830 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2831 u_errorName(errorCode), length);
2832 }
2833
2834 #if !UCONFIG_ONLY_HTML_CONVERSION
2835 errorCode=U_ZERO_ERROR;
2836 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF32, target, 0, (const char *)utf32, 4, &errorCode);
2837 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2838 length!=0
2839 ) {
2840 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2841 u_errorName(errorCode), length);
2842 }
2843 #endif
2844
2845 /* bad arguments */
2846 errorCode=U_MESSAGE_PARSE_ERROR;
2847 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2848 if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2849 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2850 }
2851
2852 /* source==NULL */
2853 errorCode=U_ZERO_ERROR;
2854 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, NULL, 2, &errorCode);
2855 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2856 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode));
2857 }
2858
2859 /* illegal alg. type */
2860 errorCode=U_ZERO_ERROR;
2861 length=ucnv_fromAlgorithmic(cnv, (UConverterType)99, target, 0, (const char *)utf16, 2, &errorCode);
2862 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2863 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode));
2864 }
2865 ucnv_close(cnv);
2866 #endif
2867 }
2868
2869 #if !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION
TestLMBCSMaxChar(void)2870 static void TestLMBCSMaxChar(void) {
2871 static const struct {
2872 int8_t maxSize;
2873 const char *name;
2874 } converter[] = {
2875 /* some non-LMBCS converters - perfect test setup here */
2876 { 1, "US-ASCII"},
2877 { 1, "ISO-8859-1"},
2878
2879 { 2, "UTF-16"},
2880 { 2, "UTF-16BE"},
2881 { 3, "UTF-8"},
2882 { 3, "CESU-8"},
2883 { 3, "SCSU"},
2884 { 4, "UTF-32"},
2885 { 4, "UTF-7"},
2886 { 4, "IMAP-mailbox-name"},
2887 { 4, "BOCU-1"},
2888
2889 { 1, "windows-1256"},
2890 { 2, "Shift-JIS"},
2891 { 2, "ibm-16684"},
2892 { 3, "ibm-930"},
2893 { 3, "ibm-1390"},
2894 { 4, "*test3"},
2895 { 16,"*test4"},
2896
2897 { 4, "ISCII"},
2898 { 4, "HZ"},
2899
2900 { 3, "ISO-2022"},
2901 { 3, "ISO-2022-KR"},
2902 { 6, "ISO-2022-JP"},
2903 { 8, "ISO-2022-CN"},
2904
2905 /* LMBCS */
2906 { 3, "LMBCS-1"},
2907 { 3, "LMBCS-2"},
2908 { 3, "LMBCS-3"},
2909 { 3, "LMBCS-4"},
2910 { 3, "LMBCS-5"},
2911 { 3, "LMBCS-6"},
2912 { 3, "LMBCS-8"},
2913 { 3, "LMBCS-11"},
2914 { 3, "LMBCS-16"},
2915 { 3, "LMBCS-17"},
2916 { 3, "LMBCS-18"},
2917 { 3, "LMBCS-19"}
2918 };
2919 int32_t idx;
2920
2921 for (idx = 0; idx < UPRV_LENGTHOF(converter); idx++) {
2922 UErrorCode status = U_ZERO_ERROR;
2923 UConverter *cnv = cnv_open(converter[idx].name, &status);
2924 if (U_FAILURE(status)) {
2925 continue;
2926 }
2927 if (converter[idx].maxSize != ucnv_getMaxCharSize(cnv)) {
2928 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2929 converter[idx].name, converter[idx].maxSize, ucnv_getMaxCharSize(cnv));
2930 }
2931 ucnv_close(cnv);
2932 }
2933
2934 /* mostly test that the macro compiles */
2935 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2936 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2937 }
2938 }
2939 #endif
2940
TestJ1968(void)2941 static void TestJ1968(void) {
2942 UErrorCode err = U_ZERO_ERROR;
2943 UConverter *cnv;
2944 char myConvName[] = "My really really really really really really really really really really really"
2945 " really really really really really really really really really really really"
2946 " really really really really really really really really long converter name";
2947 UChar myConvNameU[sizeof(myConvName)];
2948
2949 u_charsToUChars(myConvName, myConvNameU, sizeof(myConvName));
2950
2951 err = U_ZERO_ERROR;
2952 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH+1] = 0;
2953 cnv = ucnv_openU(myConvNameU, &err);
2954 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2955 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2956 }
2957
2958 err = U_ZERO_ERROR;
2959 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
2960 cnv = ucnv_openU(myConvNameU, &err);
2961 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2962 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2963 }
2964
2965 err = U_ZERO_ERROR;
2966 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
2967 cnv = ucnv_openU(myConvNameU, &err);
2968 if (cnv || err != U_FILE_ACCESS_ERROR) {
2969 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2970 }
2971
2972
2973
2974
2975 err = U_ZERO_ERROR;
2976 cnv = ucnv_open(myConvName, &err);
2977 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2978 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2979 }
2980
2981 err = U_ZERO_ERROR;
2982 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = ',';
2983 cnv = ucnv_open(myConvName, &err);
2984 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2985 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2986 }
2987
2988 err = U_ZERO_ERROR;
2989 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2990 cnv = ucnv_open(myConvName, &err);
2991 if (cnv || err != U_FILE_ACCESS_ERROR) {
2992 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2993 }
2994
2995 err = U_ZERO_ERROR;
2996 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2997 strncpy(myConvName + UCNV_MAX_CONVERTER_NAME_LENGTH, "locale=", 7);
2998 cnv = ucnv_open(myConvName, &err);
2999 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
3000 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
3001 }
3002
3003 /* The comma isn't really a part of the converter name. */
3004 err = U_ZERO_ERROR;
3005 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
3006 cnv = ucnv_open(myConvName, &err);
3007 if (cnv || err != U_FILE_ACCESS_ERROR) {
3008 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
3009 }
3010
3011 err = U_ZERO_ERROR;
3012 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ' ';
3013 cnv = ucnv_open(myConvName, &err);
3014 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
3015 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
3016 }
3017
3018 err = U_ZERO_ERROR;
3019 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
3020 cnv = ucnv_open(myConvName, &err);
3021 if (cnv || err != U_FILE_ACCESS_ERROR) {
3022 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
3023 }
3024
3025 }
3026
3027 #if !UCONFIG_NO_LEGACY_CONVERSION
3028 static void
testSwap(const char * name,UBool swap)3029 testSwap(const char *name, UBool swap) {
3030 /*
3031 * Test Unicode text.
3032 * Contains characters that are the highest for some of the
3033 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
3034 * tables copies the entire tables.
3035 */
3036 static const UChar text[]={
3037 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
3038 };
3039
3040 UChar uNormal[32], uSwapped[32];
3041 char normal[32], swapped[32];
3042 const UChar *pcu;
3043 UChar *pu;
3044 char *pc;
3045 int32_t i, normalLength, swappedLength;
3046 UChar u;
3047 char c;
3048
3049 const char *swappedName;
3050 UConverter *cnv, *swapCnv;
3051 UErrorCode errorCode;
3052
3053 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
3054
3055 /* open both the normal and the LF/NL-swapping converters */
3056 strcpy(swapped, name);
3057 strcat(swapped, UCNV_SWAP_LFNL_OPTION_STRING);
3058
3059 errorCode=U_ZERO_ERROR;
3060 swapCnv=ucnv_open(swapped, &errorCode);
3061 cnv=ucnv_open(name, &errorCode);
3062 if(U_FAILURE(errorCode)) {
3063 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name, swapped, u_errorName(errorCode));
3064 goto cleanup;
3065 }
3066
3067 /* the name must contain the swap option if and only if we expect the converter to swap */
3068 swappedName=ucnv_getName(swapCnv, &errorCode);
3069 if(U_FAILURE(errorCode)) {
3070 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name, u_errorName(errorCode));
3071 goto cleanup;
3072 }
3073
3074 pc=strstr(swappedName, UCNV_SWAP_LFNL_OPTION_STRING);
3075 if(swap != (pc!=NULL)) {
3076 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name, swappedName, swap);
3077 goto cleanup;
3078 }
3079
3080 /* convert to EBCDIC */
3081 pcu=text;
3082 pc=normal;
3083 ucnv_fromUnicode(cnv, &pc, normal+UPRV_LENGTHOF(normal), &pcu, text+UPRV_LENGTHOF(text), NULL, TRUE, &errorCode);
3084 normalLength=(int32_t)(pc-normal);
3085
3086 pcu=text;
3087 pc=swapped;
3088 ucnv_fromUnicode(swapCnv, &pc, swapped+UPRV_LENGTHOF(swapped), &pcu, text+UPRV_LENGTHOF(text), NULL, TRUE, &errorCode);
3089 swappedLength=(int32_t)(pc-swapped);
3090
3091 if(U_FAILURE(errorCode)) {
3092 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name, u_errorName(errorCode));
3093 goto cleanup;
3094 }
3095
3096 /* compare EBCDIC output */
3097 if(normalLength!=swappedLength) {
3098 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
3099 goto cleanup;
3100 }
3101 for(i=0; i<normalLength; ++i) {
3102 /* swap EBCDIC LF/NL for comparison */
3103 c=normal[i];
3104 if(swap) {
3105 if(c==0x15) {
3106 c=0x25;
3107 } else if(c==0x25) {
3108 c=0x15;
3109 }
3110 }
3111
3112 if(c!=swapped[i]) {
3113 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name, i, (uint8_t)swapped[i]);
3114 goto cleanup;
3115 }
3116 }
3117
3118 /* convert back to Unicode (may not roundtrip) */
3119 pc=normal;
3120 pu=uNormal;
3121 ucnv_toUnicode(cnv, &pu, uNormal+UPRV_LENGTHOF(uNormal), (const char **)&pc, normal+normalLength, NULL, TRUE, &errorCode);
3122 normalLength=(int32_t)(pu-uNormal);
3123
3124 pc=normal;
3125 pu=uSwapped;
3126 ucnv_toUnicode(swapCnv, &pu, uSwapped+UPRV_LENGTHOF(uSwapped), (const char **)&pc, normal+swappedLength, NULL, TRUE, &errorCode);
3127 swappedLength=(int32_t)(pu-uSwapped);
3128
3129 if(U_FAILURE(errorCode)) {
3130 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name, u_errorName(errorCode));
3131 goto cleanup;
3132 }
3133
3134 /* compare EBCDIC output */
3135 if(normalLength!=swappedLength) {
3136 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
3137 goto cleanup;
3138 }
3139 for(i=0; i<normalLength; ++i) {
3140 /* swap EBCDIC LF/NL for comparison */
3141 u=uNormal[i];
3142 if(swap) {
3143 if(u==0xa) {
3144 u=0x85;
3145 } else if(u==0x85) {
3146 u=0xa;
3147 }
3148 }
3149
3150 if(u!=uSwapped[i]) {
3151 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name, i, uSwapped[i]);
3152 goto cleanup;
3153 }
3154 }
3155
3156 /* clean up */
3157 cleanup:
3158 ucnv_close(cnv);
3159 ucnv_close(swapCnv);
3160 }
3161
3162 static void
TestEBCDICSwapLFNL()3163 TestEBCDICSwapLFNL() {
3164 static const struct {
3165 const char *name;
3166 UBool swap;
3167 } tests[]={
3168 { "ibm-37", TRUE },
3169 { "ibm-1047", TRUE },
3170 { "ibm-1140", TRUE },
3171 { "ibm-930", TRUE },
3172 { "iso-8859-3", FALSE }
3173 };
3174
3175 int i;
3176
3177 for(i=0; i<UPRV_LENGTHOF(tests); ++i) {
3178 testSwap(tests[i].name, tests[i].swap);
3179 }
3180 }
3181 #else
3182 static void
TestEBCDICSwapLFNL()3183 TestEBCDICSwapLFNL() {
3184 /* test nothing... */
3185 }
3186 #endif
3187
TestFromUCountPending()3188 static void TestFromUCountPending(){
3189 #if !UCONFIG_NO_LEGACY_CONVERSION
3190 UErrorCode status = U_ZERO_ERROR;
3191 /* const UChar expectedUnicode[] = { 0x20ac, 0x0005, 0x0006, 0x000b, 0xdbc4, 0xde34, 0xd84d, 0xdc56, 0xfffd}; */
3192 static const struct {
3193 UChar input[6];
3194 int32_t len;
3195 int32_t exp;
3196 }fromUnicodeTests[] = {
3197 /*m:n conversion*/
3198 {{0xdbc4},1,1},
3199 {{ 0xdbc4, 0xde34, 0xd84d},3,1},
3200 {{ 0xdbc4, 0xde34, 0xd900},3,3},
3201 };
3202 int i;
3203 UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
3204 if(U_FAILURE(status)){
3205 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3206 return;
3207 }
3208 for(i=0; i<UPRV_LENGTHOF(fromUnicodeTests); ++i) {
3209 char tgt[10];
3210 char* target = tgt;
3211 char* targetLimit = target + 10;
3212 const UChar* source = fromUnicodeTests[i].input;
3213 const UChar* sourceLimit = source + fromUnicodeTests[i].len;
3214 int32_t len = 0;
3215 ucnv_reset(cnv);
3216 ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3217 len = ucnv_fromUCountPending(cnv, &status);
3218 if(U_FAILURE(status)){
3219 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3220 status = U_ZERO_ERROR;
3221 continue;
3222 }
3223 if(len != fromUnicodeTests[i].exp){
3224 log_err("Did not get the expeced output for ucnv_fromUInputConsumed.\n");
3225 }
3226 }
3227 status = U_ZERO_ERROR;
3228 {
3229 /*
3230 * The converter has to read the tail before it knows that
3231 * only head alone matches.
3232 * At the end, the output for head will overflow the target,
3233 * middle will be pending, and tail will not have been consumed.
3234 */
3235 /*
3236 \U00101234 -> x (<U101234> \x07 |0)
3237 \U00101234\U00050005 -> y (<U101234>+<U50005> \x07+\x00+\x01\x02\x0e+\x05 |0)
3238 \U00101234\U00050005\U00060006 -> z (<U101234>+<U50005>+<U60006> \x07+\x00+\x01\x02\x0f+\x09 |0)
3239 \U00060007 -> unassigned
3240 */
3241 static const UChar head[] = {0xDBC4,0xDE34,0xD900,0xDC05,0x0000};/* \U00101234\U00050005 */
3242 static const UChar middle[] = {0xD940,0x0000}; /* first half of \U00060006 or \U00060007 */
3243 static const UChar tail[] = {0xDC07,0x0000};/* second half of \U00060007 */
3244 char tgt[10];
3245 char* target = tgt;
3246 char* targetLimit = target + 2; /* expect overflow from converting \U00101234\U00050005 */
3247 const UChar* source = head;
3248 const UChar* sourceLimit = source + u_strlen(head);
3249 int32_t len = 0;
3250 ucnv_reset(cnv);
3251 ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3252 len = ucnv_fromUCountPending(cnv, &status);
3253 if(U_FAILURE(status)){
3254 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3255 status = U_ZERO_ERROR;
3256 }
3257 if(len!=4){
3258 log_err("ucnv_fromUInputHeld did not return correct length for head\n");
3259 }
3260 source = middle;
3261 sourceLimit = source + u_strlen(middle);
3262 ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3263 len = ucnv_fromUCountPending(cnv, &status);
3264 if(U_FAILURE(status)){
3265 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3266 status = U_ZERO_ERROR;
3267 }
3268 if(len!=5){
3269 log_err("ucnv_fromUInputHeld did not return correct length for middle\n");
3270 }
3271 source = tail;
3272 sourceLimit = source + u_strlen(tail);
3273 ucnv_fromUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3274 if(status != U_BUFFER_OVERFLOW_ERROR){
3275 log_err("ucnv_fromUnicode call did not succeed. Error: %s\n", u_errorName(status));
3276 }
3277 status = U_ZERO_ERROR;
3278 len = ucnv_fromUCountPending(cnv, &status);
3279 /* middle[1] is pending, tail has not been consumed */
3280 if(U_FAILURE(status)){
3281 log_err("ucnv_fromUInputHeld call did not succeed. Error: %s\n", u_errorName(status));
3282 }
3283 if(len!=1){
3284 log_err("ucnv_fromUInputHeld did not return correct length for tail\n");
3285 }
3286 }
3287 ucnv_close(cnv);
3288 #endif
3289 }
3290
3291 static void
TestToUCountPending()3292 TestToUCountPending(){
3293 #if !UCONFIG_NO_LEGACY_CONVERSION
3294 UErrorCode status = U_ZERO_ERROR;
3295 static const struct {
3296 char input[6];
3297 int32_t len;
3298 int32_t exp;
3299 }toUnicodeTests[] = {
3300 /*m:n conversion*/
3301 {{0x05, 0x01, 0x02},3,3},
3302 {{0x01, 0x02},2,2},
3303 {{0x07, 0x00, 0x01, 0x02},4,4},
3304 };
3305
3306 int i;
3307 UConverterToUCallback *oldToUAction= NULL;
3308 UConverter* cnv = ucnv_openPackage(loadTestData(&status), "test3", &status);
3309 if(U_FAILURE(status)){
3310 log_data_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3311 return;
3312 }
3313 ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
3314 for(i=0; i<UPRV_LENGTHOF(toUnicodeTests); ++i) {
3315 UChar tgt[20];
3316 UChar* target = tgt;
3317 UChar* targetLimit = target + 20;
3318 const char* source = toUnicodeTests[i].input;
3319 const char* sourceLimit = source + toUnicodeTests[i].len;
3320 int32_t len = 0;
3321 ucnv_reset(cnv);
3322 ucnv_toUnicode(cnv, &target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3323 len = ucnv_toUCountPending(cnv,&status);
3324 if(U_FAILURE(status)){
3325 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3326 status = U_ZERO_ERROR;
3327 continue;
3328 }
3329 if(len != toUnicodeTests[i].exp){
3330 log_err("Did not get the expeced output for ucnv_toUInputConsumed.\n");
3331 }
3332 }
3333 status = U_ZERO_ERROR;
3334 ucnv_close(cnv);
3335
3336 {
3337 /*
3338 * The converter has to read the tail before it knows that
3339 * only head alone matches.
3340 * At the end, the output for head will overflow the target,
3341 * mid will be pending, and tail will not have been consumed.
3342 */
3343 char head[] = { 0x01, 0x02, 0x03, 0x0a , 0x00};
3344 char mid[] = { 0x01, 0x02, 0x03, 0x0b, 0x00 };
3345 char tail[] = { 0x01, 0x02, 0x03, 0x0d, 0x00 };
3346 /*
3347 0x01, 0x02, 0x03, 0x0a -> x (<U23456> \x01\x02\x03\x0a |0)
3348 0x01, 0x02, 0x03, 0x0b -> y (<U000b> \x01\x02\x03\x0b |0)
3349 0x01, 0x02, 0x03, 0x0d -> z (<U34567> \x01\x02\x03\x0d |3)
3350 0x01, 0x02, 0x03, 0x0a + 0x01, 0x02, 0x03, 0x0b + 0x01 + many more -> z (see test4 "many bytes, and bytes per UChar")
3351 */
3352 UChar tgt[10];
3353 UChar* target = tgt;
3354 UChar* targetLimit = target + 1; /* expect overflow from converting */
3355 const char* source = head;
3356 const char* sourceLimit = source + strlen(head);
3357 int32_t len = 0;
3358 cnv = ucnv_openPackage(loadTestData(&status), "test4", &status);
3359 if(U_FAILURE(status)){
3360 log_err("Could not create converter for test3. Error: %s\n", u_errorName(status));
3361 return;
3362 }
3363 ucnv_setToUCallBack(cnv, UCNV_TO_U_CALLBACK_STOP, NULL, oldToUAction, NULL, &status);
3364 ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3365 len = ucnv_toUCountPending(cnv,&status);
3366 if(U_FAILURE(status)){
3367 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3368 }
3369 if(len != 4){
3370 log_err("Did not get the expected len for head.\n");
3371 }
3372 source=mid;
3373 sourceLimit = source+strlen(mid);
3374 ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3375 len = ucnv_toUCountPending(cnv,&status);
3376 if(U_FAILURE(status)){
3377 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3378 }
3379 if(len != 8){
3380 log_err("Did not get the expected len for mid.\n");
3381 }
3382
3383 source=tail;
3384 sourceLimit = source+strlen(tail);
3385 targetLimit = target;
3386 ucnv_toUnicode(cnv,&target, targetLimit, &source, sourceLimit, NULL, FALSE, &status);
3387 if(status != U_BUFFER_OVERFLOW_ERROR){
3388 log_err("ucnv_toUnicode call did not succeed. Error: %s\n", u_errorName(status));
3389 }
3390 status = U_ZERO_ERROR;
3391 len = ucnv_toUCountPending(cnv,&status);
3392 /* mid[4] is pending, tail has not been consumed */
3393 if(U_FAILURE(status)){
3394 log_err("ucnv_toUCountPending call did not succeed. Error: %s\n", u_errorName(status));
3395 }
3396 if(len != 4){
3397 log_err("Did not get the expected len for tail.\n");
3398 }
3399 ucnv_close(cnv);
3400 }
3401 #endif
3402 }
3403
TestOneDefaultNameChange(const char * name,const char * expected)3404 static void TestOneDefaultNameChange(const char *name, const char *expected) {
3405 UErrorCode status = U_ZERO_ERROR;
3406 UConverter *cnv;
3407 ucnv_setDefaultName(name);
3408 if(strcmp(ucnv_getDefaultName(), expected)==0)
3409 log_verbose("setDefaultName of %s works.\n", name);
3410 else
3411 log_err("setDefaultName of %s failed\n", name);
3412 cnv=ucnv_open(NULL, &status);
3413 if (U_FAILURE(status) || cnv == NULL) {
3414 log_err("opening the default converter of %s failed\n", name);
3415 return;
3416 }
3417 if(strcmp(ucnv_getName(cnv, &status), expected)==0)
3418 log_verbose("ucnv_getName of %s works.\n", name);
3419 else
3420 log_err("ucnv_getName of %s failed\n", name);
3421 ucnv_close(cnv);
3422 }
3423
TestDefaultName(void)3424 static void TestDefaultName(void) {
3425 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
3426 static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
3427 strcpy(defaultName, ucnv_getDefaultName());
3428
3429 log_verbose("getDefaultName returned %s\n", defaultName);
3430
3431 /*change the default name by setting it */
3432 TestOneDefaultNameChange("UTF-8", "UTF-8");
3433 #if U_CHARSET_IS_UTF8
3434 TestOneDefaultNameChange("ISCII,version=1", "UTF-8");
3435 TestOneDefaultNameChange("ISCII,version=2", "UTF-8");
3436 TestOneDefaultNameChange("ISO-8859-1", "UTF-8");
3437 #else
3438 # if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
3439 TestOneDefaultNameChange("ISCII,version=1", "ISCII,version=1");
3440 TestOneDefaultNameChange("ISCII,version=2", "ISCII,version=2");
3441 # endif
3442 TestOneDefaultNameChange("ISO-8859-1", "ISO-8859-1");
3443 #endif
3444
3445 /*set the default name back*/
3446 ucnv_setDefaultName(defaultName);
3447 }
3448
3449 /* Test that ucnv_compareNames() matches names according to spec. ----------- */
3450
3451 static int
sign(int n)3452 sign(int n) {
3453 if(n==0) {
3454 return 0;
3455 } else if(n<0) {
3456 return -1;
3457 } else /* n>0 */ {
3458 return 1;
3459 }
3460 }
3461
3462 static void
compareNames(const char ** names)3463 compareNames(const char **names) {
3464 const char *relation, *name1, *name2;
3465 int rel, result;
3466
3467 relation=*names++;
3468 if(*relation=='=') {
3469 rel = 0;
3470 } else if(*relation=='<') {
3471 rel = -1;
3472 } else {
3473 rel = 1;
3474 }
3475
3476 name1=*names++;
3477 if(name1==NULL) {
3478 return;
3479 }
3480 while((name2=*names++)!=NULL) {
3481 result=ucnv_compareNames(name1, name2);
3482 if(sign(result)!=rel) {
3483 log_err("ucnv_compareNames(\"%s\", \"%s\")=%d, sign!=%d\n", name1, name2, result, rel);
3484 }
3485 name1=name2;
3486 }
3487 }
3488
3489 static void
TestCompareNames()3490 TestCompareNames() {
3491 static const char *equalUTF8[]={ "=", "UTF-8", "utf_8", "u*T@f08", "Utf 8", NULL };
3492 static const char *equalIBM[]={ "=", "ibm-37", "IBM037", "i-B-m 00037", "ibm-0037", "IBM00037", NULL };
3493 static const char *lessMac[]={ "<", "macos-0_1-10.2", "macos-1-10.0.2", "macos-1-10.2", NULL };
3494 static const char *lessUTF080[]={ "<", "UTF-0008", "utf$080", "u*T@f0800", "Utf 0000000009", NULL };
3495
3496 compareNames(equalUTF8);
3497 compareNames(equalIBM);
3498 compareNames(lessMac);
3499 compareNames(lessUTF080);
3500 }
3501
3502 static void
TestSubstString()3503 TestSubstString() {
3504 static const UChar surrogate[1]={ 0xd900 };
3505 char buffer[16];
3506
3507 static const UChar sub[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3508 static const char subChars[5]={ 0x61, 0x62, 0x63, 0x64, 0x65 };
3509 UConverter *cnv;
3510 UErrorCode errorCode;
3511 int32_t length;
3512 int8_t len8;
3513
3514 /* UTF-16/32: test that the BOM is output before the sub character */
3515 errorCode=U_ZERO_ERROR;
3516 cnv=ucnv_open("UTF-16", &errorCode);
3517 if(U_FAILURE(errorCode)) {
3518 log_data_err("ucnv_open(UTF-16) failed - %s\n", u_errorName(errorCode));
3519 return;
3520 }
3521 length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
3522 ucnv_close(cnv);
3523 if(U_FAILURE(errorCode) ||
3524 length!=4 ||
3525 NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
3526 ) {
3527 log_err("ucnv_fromUChars(UTF-16, U+D900) did not write a BOM\n");
3528 }
3529
3530 errorCode=U_ZERO_ERROR;
3531 cnv=ucnv_open("UTF-32", &errorCode);
3532 if(U_FAILURE(errorCode)) {
3533 log_data_err("ucnv_open(UTF-32) failed - %s\n", u_errorName(errorCode));
3534 return;
3535 }
3536 length=ucnv_fromUChars(cnv, buffer, (int32_t)sizeof(buffer), surrogate, 1, &errorCode);
3537 ucnv_close(cnv);
3538 if(U_FAILURE(errorCode) ||
3539 length!=8 ||
3540 NULL == ucnv_detectUnicodeSignature(buffer, length, NULL, &errorCode)
3541 ) {
3542 log_err("ucnv_fromUChars(UTF-32, U+D900) did not write a BOM\n");
3543 }
3544
3545 /* Simple API test of ucnv_setSubstString() + ucnv_getSubstChars(). */
3546 errorCode=U_ZERO_ERROR;
3547 cnv=ucnv_open("ISO-8859-1", &errorCode);
3548 if(U_FAILURE(errorCode)) {
3549 log_data_err("ucnv_open(ISO-8859-1) failed - %s\n", u_errorName(errorCode));
3550 return;
3551 }
3552 ucnv_setSubstString(cnv, sub, UPRV_LENGTHOF(sub), &errorCode);
3553 if(U_FAILURE(errorCode)) {
3554 log_err("ucnv_setSubstString(ISO-8859-1, sub[5]) failed - %s\n", u_errorName(errorCode));
3555 } else {
3556 len8 = sizeof(buffer);
3557 ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
3558 /* Stateless converter, we expect the string converted to charset bytes. */
3559 if(U_FAILURE(errorCode) || len8!=sizeof(subChars) || 0!=uprv_memcmp(buffer, subChars, len8)) {
3560 log_err("ucnv_getSubstChars(ucnv_setSubstString(ISO-8859-1, sub[5])) failed - %s\n", u_errorName(errorCode));
3561 }
3562 }
3563 ucnv_close(cnv);
3564
3565 #if !UCONFIG_NO_LEGACY_CONVERSION
3566 errorCode=U_ZERO_ERROR;
3567 cnv=ucnv_open("HZ", &errorCode);
3568 if(U_FAILURE(errorCode)) {
3569 log_data_err("ucnv_open(HZ) failed - %s\n", u_errorName(errorCode));
3570 return;
3571 }
3572 ucnv_setSubstString(cnv, sub, UPRV_LENGTHOF(sub), &errorCode);
3573 if(U_FAILURE(errorCode)) {
3574 log_err("ucnv_setSubstString(HZ, sub[5]) failed - %s\n", u_errorName(errorCode));
3575 } else {
3576 len8 = sizeof(buffer);
3577 ucnv_getSubstChars(cnv, buffer, &len8, &errorCode);
3578 /* Stateful converter, we expect that the Unicode string was set and that we get an empty char * string now. */
3579 if(U_FAILURE(errorCode) || len8!=0) {
3580 log_err("ucnv_getSubstChars(ucnv_setSubstString(HZ, sub[5])) failed - %s\n", u_errorName(errorCode));
3581 }
3582 }
3583 ucnv_close(cnv);
3584 #endif
3585 /*
3586 * Further testing of ucnv_setSubstString() is done via intltest convert.
3587 * We do not test edge cases of illegal arguments and similar because the
3588 * function implementation uses all of its parameters in calls to other
3589 * functions with UErrorCode parameters.
3590 */
3591 }
3592
3593 static void
InvalidArguments()3594 InvalidArguments() {
3595 UConverter *cnv;
3596 UErrorCode errorCode;
3597 char charBuffer[2] = {1, 1};
3598 char ucharAsCharBuffer[2] = {2, 2};
3599 char *charsPtr = charBuffer;
3600 UChar *ucharsPtr = (UChar *)ucharAsCharBuffer;
3601 UChar *ucharsBadPtr = (UChar *)(ucharAsCharBuffer + 1);
3602
3603 errorCode=U_ZERO_ERROR;
3604 cnv=ucnv_open("UTF-8", &errorCode);
3605 if(U_FAILURE(errorCode)) {
3606 log_err("ucnv_open() failed - %s\n", u_errorName(errorCode));
3607 return;
3608 }
3609
3610 errorCode=U_ZERO_ERROR;
3611 /* This one should fail because an incomplete UChar is being passed in */
3612 ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsPtr, ucharsBadPtr, NULL, TRUE, &errorCode);
3613 if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3614 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
3615 }
3616
3617 errorCode=U_ZERO_ERROR;
3618 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3619 ucnv_fromUnicode(cnv, &charsPtr, charsPtr, (const UChar **)&ucharsBadPtr, ucharsPtr, NULL, TRUE, &errorCode);
3620 if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3621 log_err("ucnv_fromUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
3622 }
3623
3624 errorCode=U_ZERO_ERROR;
3625 /* This one should fail because an incomplete UChar is being passed in */
3626 ucnv_toUnicode(cnv, &ucharsPtr, ucharsBadPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
3627 if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3628 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for incomplete UChar * buffer - %s\n", u_errorName(errorCode));
3629 }
3630
3631 errorCode=U_ZERO_ERROR;
3632 /* This one should fail because ucharsBadPtr is > than ucharsPtr */
3633 ucnv_toUnicode(cnv, &ucharsBadPtr, ucharsPtr, (const char **)&charsPtr, charsPtr, NULL, TRUE, &errorCode);
3634 if(errorCode != U_ILLEGAL_ARGUMENT_ERROR) {
3635 log_err("ucnv_toUnicode() failed to return U_ILLEGAL_ARGUMENT_ERROR for bad limit pointer - %s\n", u_errorName(errorCode));
3636 }
3637
3638 if (charBuffer[0] != 1 || charBuffer[1] != 1
3639 || ucharAsCharBuffer[0] != 2 || ucharAsCharBuffer[1] != 2)
3640 {
3641 log_err("Data was incorrectly written to buffers\n");
3642 }
3643
3644 ucnv_close(cnv);
3645 }
3646
TestGetName()3647 static void TestGetName() {
3648 static const char *const names[] = {
3649 "Unicode", "UTF-16",
3650 "UnicodeBigUnmarked", "UTF-16BE",
3651 "UnicodeBig", "UTF-16BE,version=1",
3652 "UnicodeLittleUnmarked", "UTF-16LE",
3653 "UnicodeLittle", "UTF-16LE,version=1",
3654 "x-UTF-16LE-BOM", "UTF-16LE,version=1"
3655 };
3656 int32_t i;
3657 for(i = 0; i < UPRV_LENGTHOF(names); i += 2) {
3658 UErrorCode errorCode = U_ZERO_ERROR;
3659 UConverter *cnv = ucnv_open(names[i], &errorCode);
3660 if(U_SUCCESS(errorCode)) {
3661 const char *name = ucnv_getName(cnv, &errorCode);
3662 if(U_FAILURE(errorCode) || 0 != strcmp(name, names[i+1])) {
3663 log_err("ucnv_getName(%s) = %s != %s -- %s\n",
3664 names[i], name, names[i+1], u_errorName(errorCode));
3665 }
3666 ucnv_close(cnv);
3667 }
3668 }
3669 }
3670
TestUTFBOM()3671 static void TestUTFBOM() {
3672 static const UChar a16[] = { 0x61 };
3673 static const char *const names[] = {
3674 "UTF-16",
3675 "UTF-16,version=1",
3676 "UTF-16BE",
3677 "UnicodeBig",
3678 "UTF-16LE",
3679 "UnicodeLittle"
3680 };
3681 static const uint8_t expected[][5] = {
3682 #if U_IS_BIG_ENDIAN
3683 { 4, 0xfe, 0xff, 0, 0x61 },
3684 { 4, 0xfe, 0xff, 0, 0x61 },
3685 #else
3686 { 4, 0xff, 0xfe, 0x61, 0 },
3687 { 4, 0xff, 0xfe, 0x61, 0 },
3688 #endif
3689
3690 { 2, 0, 0x61 },
3691 { 4, 0xfe, 0xff, 0, 0x61 },
3692
3693 { 2, 0x61, 0 },
3694 { 4, 0xff, 0xfe, 0x61, 0 }
3695 };
3696
3697 char bytes[10];
3698 int32_t i;
3699
3700 for(i = 0; i < UPRV_LENGTHOF(names); ++i) {
3701 UErrorCode errorCode = U_ZERO_ERROR;
3702 UConverter *cnv = ucnv_open(names[i], &errorCode);
3703 int32_t length = 0;
3704 const uint8_t *exp = expected[i];
3705 if (U_FAILURE(errorCode)) {
3706 log_err_status(errorCode, "Unable to open converter: %s got error code: %s\n", names[i], u_errorName(errorCode));
3707 continue;
3708 }
3709 length = ucnv_fromUChars(cnv, bytes, (int32_t)sizeof(bytes), a16, 1, &errorCode);
3710
3711 if(U_FAILURE(errorCode) || length != exp[0] || 0 != memcmp(bytes, exp+1, length)) {
3712 log_err("unexpected %s BOM writing behavior -- %s\n",
3713 names[i], u_errorName(errorCode));
3714 }
3715 ucnv_close(cnv);
3716 }
3717 }
3718