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