]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/ccapitst.c
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / test / cintltst / ccapitst.c
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2004, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /********************************************************************************
7 *
8 * File CU_CAPITST.C
9 *
10 * Modification History:
11 * Name Description
12 * Madhu Katragadda Ported for C API
13 *********************************************************************************
14 */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include "unicode/uloc.h"
20 #include "unicode/ucnv.h"
21 #include "unicode/ucnv_err.h"
22 #include "unicode/putil.h"
23 #include "unicode/ustring.h"
24 #include "ucnv_bld.h" /* for sizeof(UConverter) */
25 #include "cintltst.h"
26 #include "ccapitst.h"
27
28 /* for not including "cstring.h" -begin*/
29 #ifdef WIN32
30 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE _stricmp(str1, str2)
31 #elif defined(POSIX)
32 # define ctest_stricmp(str1, str2) U_STANDARD_CPP_NAMESPACE strcasecmp(str1, str2)
33 #else
34 # define ctest_stricmp(str1, str2) T_CString_stricmp(str1, str2)
35 #endif
36
37 static int U_EXPORT2
38 T_CString_stricmp(const char *str1, const char *str2) {
39 if(str1==NULL) {
40 if(str2==NULL) {
41 return 0;
42 } else {
43 return -1;
44 }
45 } else if(str2==NULL) {
46 return 1;
47 } else {
48 /* compare non-NULL strings lexically with lowercase */
49 int rc;
50 unsigned char c1, c2;
51 for(;;) {
52 c1=(unsigned char)*str1;
53 c2=(unsigned char)*str2;
54 if(c1==0) {
55 if(c2==0) {
56 return 0;
57 } else {
58 return -1;
59 }
60 } else if(c2==0) {
61 return 1;
62 } else {
63 /* compare non-zero characters with lowercase */
64 rc=(int)(unsigned char)tolower(c1)-(int)(unsigned char)tolower(c2);
65 if(rc!=0) {
66 return rc;
67 }
68 }
69 ++str1;
70 ++str2;
71 }
72 }
73 }
74 /* for not including "cstring.h" -end*/
75
76 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
77
78 #define NUM_CODEPAGE 1
79 #define MAX_FILE_LEN 1024*20
80 #define UCS_FILE_NAME_SIZE 512
81
82 /*returns an action other than the one provided*/
83 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA);
84 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA);
85
86 static UConverter *
87 cnv_open(const char *name, UErrorCode *pErrorCode) {
88 if(name!=NULL && name[0]=='*') {
89 return ucnv_openPackage(loadTestData(pErrorCode), name+1, pErrorCode);
90 } else {
91 return ucnv_open(name, pErrorCode);
92 }
93 }
94
95
96 static void ListNames(void);
97 static void TestFlushCache(void);
98 static void TestDuplicateAlias(void);
99 static void TestCCSID(void);
100 static void TestJ932(void);
101 static void TestJ1968(void);
102 static void TestLMBCSMaxChar(void);
103 static void TestConvertSafeCloneCallback(void);
104 static void TestEBCDICSwapLFNL(void);
105 static void TestConvertEx(void);
106 static void TestConvertAlgorithmic(void);
107 void TestDefaultConverterError(void); /* defined in cctest.c */
108
109 void addTestConvert(TestNode** root);
110
111 void addTestConvert(TestNode** root)
112 {
113 addTest(root, &ListNames, "tsconv/ccapitst/ListNames");
114 addTest(root, &TestConvert, "tsconv/ccapitst/TestConvert");
115 addTest(root, &TestFlushCache, "tsconv/ccapitst/TestFlushCache");
116 addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias");
117 addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias");
118 addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone");
119 addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback");
120 addTest(root, &TestCCSID, "tsconv/ccapitst/TestCCSID");
121 addTest(root, &TestJ932, "tsconv/ccapitst/TestJ932");
122 addTest(root, &TestJ1968, "tsconv/ccapitst/TestJ1968");
123 addTest(root, &TestLMBCSMaxChar, "tsconv/ccapitst/TestLMBCSMaxChar");
124 addTest(root, &TestEBCDICSwapLFNL, "tsconv/ccapitst/TestEBCDICSwapLFNL");
125 addTest(root, &TestConvertEx, "tsconv/ccapitst/TestConvertEx");
126 addTest(root, &TestConvertAlgorithmic, "tsconv/ccapitst/TestConvertAlgorithmic");
127 addTest(root, &TestDefaultConverterError, "tsconv/ccapitst/TestDefaultConverterError");
128 }
129
130 static void ListNames(void) {
131 UErrorCode err = U_ZERO_ERROR;
132 int32_t testLong1 = 0;
133 const char* available_conv;
134 UEnumeration *allNamesEnum = NULL;
135 int32_t allNamesCount = 0;
136 uint16_t count;
137
138 log_verbose("Testing ucnv_openAllNames()...");
139 allNamesEnum = ucnv_openAllNames(&err);
140 if(U_FAILURE(err)) {
141 log_err("FAILURE! ucnv_openAllNames() -> %s\n", myErrorName(err));
142 }
143 else {
144 const char *string = NULL;
145 int32_t len = 0;
146 int32_t count1 = 0;
147 int32_t count2 = 0;
148 allNamesCount = uenum_count(allNamesEnum, &err);
149 while ((string = uenum_next(allNamesEnum, &len, &err))) {
150 count1++;
151 log_verbose("read \"%s\", length %i\n", string, len);
152 }
153 err = U_ZERO_ERROR;
154 uenum_reset(allNamesEnum, &err);
155 while ((string = uenum_next(allNamesEnum, &len, &err))) {
156 count2++;
157 ucnv_close(ucnv_open(string, &err));
158 log_verbose("read \"%s\", length %i (%s)\n", string, len, U_SUCCESS(err) ? "available" : "unavailable");
159 err = U_ZERO_ERROR;
160 }
161 if (count1 != count2) {
162 log_err("FAILURE! uenum_reset(allNamesEnum, &err); doesn't work\n");
163 }
164 }
165 uenum_close(allNamesEnum);
166 err = U_ZERO_ERROR;
167
168 /*Tests ucnv_getAvailableName(), getAvialableCount()*/
169
170 log_verbose("Testing ucnv_countAvailable()...");
171
172 testLong1=ucnv_countAvailable();
173 log_info("Number of available codepages: %d/%d\n", testLong1, allNamesCount);
174
175 log_verbose("\n---Testing ucnv_getAvailableName.."); /*need to check this out */
176
177 available_conv = ucnv_getAvailableName(testLong1);
178 /*test ucnv_getAvailableName with err condition*/
179 log_verbose("\n---Testing ucnv_getAvailableName..with index < 0 ");
180 available_conv = ucnv_getAvailableName(-1);
181 if(available_conv != NULL){
182 log_err("ucnv_getAvailableName() with index < 0) should return NULL\n");
183 }
184
185 /* Test ucnv_countAliases() etc. */
186 count = ucnv_countAliases("utf-8", &err);
187 if(U_FAILURE(err)) {
188 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %s\n", myErrorName(err));
189 } else if(count <= 0) {
190 log_err("FAILURE! ucnv_countAliases(\"utf-8\") -> %d aliases\n", count);
191 } else {
192 /* try to get the aliases individually */
193 const char *alias;
194 alias = ucnv_getAlias("utf-8", 0, &err);
195 if(U_FAILURE(err)) {
196 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s\n", myErrorName(err));
197 } else if(strcmp("UTF-8", alias) != 0) {
198 log_err("FAILURE! ucnv_getAlias(\"utf-8\", 0) -> %s instead of UTF-8\n", alias);
199 } else {
200 uint16_t aliasNum;
201 for(aliasNum = 0; aliasNum < count; ++aliasNum) {
202 alias = ucnv_getAlias("utf-8", aliasNum, &err);
203 if(U_FAILURE(err)) {
204 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
205 } else if(strlen(alias) > 20) {
206 /* sanity check */
207 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> alias %s insanely long, corrupt?!\n", aliasNum, alias);
208 } else {
209 log_verbose("alias %d for utf-8: %s\n", aliasNum, alias);
210 }
211 }
212 if(U_SUCCESS(err)) {
213 /* try to fill an array with all aliases */
214 const char **aliases;
215 aliases=(const char **)malloc(count * sizeof(const char *));
216 if(aliases != 0) {
217 ucnv_getAliases("utf-8", aliases, &err);
218 if(U_FAILURE(err)) {
219 log_err("FAILURE! ucnv_getAliases(\"utf-8\") -> %s\n", myErrorName(err));
220 } else {
221 for(aliasNum = 0; aliasNum < count; ++aliasNum) {
222 /* compare the pointers with the ones returned individually */
223 alias = ucnv_getAlias("utf-8", aliasNum, &err);
224 if(U_FAILURE(err)) {
225 log_err("FAILURE! ucnv_getAlias(\"utf-8\", %d) -> %s\n", aliasNum, myErrorName(err));
226 } else if(aliases[aliasNum] != alias) {
227 log_err("FAILURE! ucnv_getAliases(\"utf-8\")[%d] != ucnv_getAlias(\"utf-8\", %d)\n", aliasNum, aliasNum);
228 }
229 }
230 }
231 free((char **)aliases);
232 }
233 }
234 }
235 }
236 }
237
238
239 static void TestConvert()
240 {
241 char myptr[4];
242 char save[4];
243 int32_t testLong1 = 0;
244 uint16_t rest = 0;
245 int32_t len = 0;
246 int32_t x = 0;
247 FILE* ucs_file_in = NULL;
248 UChar BOM = 0x0000;
249 UChar myUChar = 0x0000;
250 char* mytarget; /* [MAX_FILE_LEN] */
251 char* mytarget_1;
252 char* mytarget_use;
253 UChar* consumedUni = NULL;
254 char* consumed = NULL;
255 char* output_cp_buffer; /* [MAX_FILE_LEN] */
256 UChar* ucs_file_buffer; /* [MAX_FILE_LEN] */
257 UChar* ucs_file_buffer_use;
258 UChar* my_ucs_file_buffer; /* [MAX_FILE_LEN] */
259 UChar* my_ucs_file_buffer_1;
260 int8_t ii = 0;
261 int32_t j = 0;
262 uint16_t codepage_index = 0;
263 int32_t cp = 0;
264 UErrorCode err = U_ZERO_ERROR;
265 char ucs_file_name[UCS_FILE_NAME_SIZE];
266 UConverterFromUCallback MIA1, MIA1_2;
267 UConverterToUCallback MIA2, MIA2_2;
268 const void *MIA1Context, *MIA1Context2, *MIA2Context, *MIA2Context2;
269 UConverter* someConverters[5];
270 UConverter* myConverter = 0;
271 UChar* displayname = 0;
272
273 const char* locale;
274
275 UChar* uchar1 = 0;
276 UChar* uchar2 = 0;
277 UChar* uchar3 = 0;
278 int32_t targetcapacity2;
279 int32_t targetcapacity;
280 int32_t targetsize;
281 int32_t disnamelen;
282
283 const UChar* tmp_ucs_buf;
284 const UChar* tmp_consumedUni=NULL;
285 const char* tmp_mytarget_use;
286 const char* tmp_consumed;
287
288 /******************************************************************
289 Checking Unicode -> ksc
290 ******************************************************************/
291
292 const char* CodePagesToTest[NUM_CODEPAGE] =
293 {
294 "ibm-949_P110-1999"
295
296
297 };
298 const uint16_t CodePageNumberToTest[NUM_CODEPAGE] =
299 {
300 949
301 };
302
303
304 const int8_t CodePagesMinChars[NUM_CODEPAGE] =
305 {
306 1
307
308 };
309
310 const int8_t CodePagesMaxChars[NUM_CODEPAGE] =
311 {
312 2
313
314 };
315
316 const uint16_t CodePagesSubstitutionChars[NUM_CODEPAGE] =
317 {
318 0xAFFE
319 };
320
321 const char* CodePagesTestFiles[NUM_CODEPAGE] =
322 {
323 "uni-text.bin"
324 };
325
326
327 const UConverterPlatform CodePagesPlatform[NUM_CODEPAGE] =
328 {
329 UCNV_IBM
330
331 };
332
333 const char* CodePagesLocale[NUM_CODEPAGE] =
334 {
335 "ko_KR"
336 };
337
338 UConverterFromUCallback oldFromUAction = NULL;
339 UConverterToUCallback oldToUAction = NULL;
340 const void* oldFromUContext = NULL;
341 const void* oldToUContext = NULL;
342
343 /* Allocate memory */
344 mytarget = (char*) malloc(MAX_FILE_LEN * sizeof(mytarget[0]));
345 output_cp_buffer = (char*) malloc(MAX_FILE_LEN * sizeof(output_cp_buffer[0]));
346 ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(ucs_file_buffer[0]));
347 my_ucs_file_buffer = (UChar*) malloc(MAX_FILE_LEN * sizeof(my_ucs_file_buffer[0]));
348
349 ucs_file_buffer_use = ucs_file_buffer;
350 mytarget_1=mytarget;
351 mytarget_use = mytarget;
352 my_ucs_file_buffer_1=my_ucs_file_buffer;
353
354 /* flush the converter cache to get a consistent state before the flushing is tested */
355 ucnv_flushCache();
356
357 /*Testing ucnv_openU()*/
358 {
359 UChar converterName[]={ 0x0069, 0x0062, 0x006d, 0x002d, 0x0039, 0x0034, 0x0033, 0x0000}; /*ibm-943*/
360 UChar firstSortedName[]={ 0x0021, 0x0000}; /* ! */
361 UChar lastSortedName[]={ 0x007E, 0x0000}; /* ~ */
362 const char *illegalNameChars={ "ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943 ibm-943"};
363 UChar illegalName[100];
364 UConverter *converter=NULL;
365 err=U_ZERO_ERROR;
366 converter=ucnv_openU(converterName, &err);
367 if(U_FAILURE(err)){
368 log_data_err("FAILURE! ucnv_openU(ibm-943, err) failed. %s\n", myErrorName(err));
369 }
370 ucnv_close(converter);
371 err=U_ZERO_ERROR;
372 converter=ucnv_openU(NULL, &err);
373 if(U_FAILURE(err)){
374 log_err("FAILURE! ucnv_openU(NULL, err) failed. %s\n", myErrorName(err));
375 }
376 ucnv_close(converter);
377 /*testing with error value*/
378 err=U_ILLEGAL_ARGUMENT_ERROR;
379 converter=ucnv_openU(converterName, &err);
380 if(!(converter == NULL)){
381 log_data_err("FAILURE! ucnv_openU(ibm-943, U_ILLEGAL_ARGUMENT_ERROR) is expected to fail\n");
382 }
383 ucnv_close(converter);
384 err=U_ZERO_ERROR;
385 u_uastrcpy(illegalName, "");
386 u_uastrcpy(illegalName, illegalNameChars);
387 ucnv_openU(illegalName, &err);
388 if(!(err==U_ILLEGAL_ARGUMENT_ERROR)){
389 log_err("FAILURE! ucnv_openU(illegalName, err) is expected to fail\n");
390 }
391
392 err=U_ZERO_ERROR;
393 ucnv_openU(firstSortedName, &err);
394 if(err!=U_FILE_ACCESS_ERROR){
395 log_err("FAILURE! ucnv_openU(firstSortedName, err) is expected to fail\n");
396 }
397
398 err=U_ZERO_ERROR;
399 ucnv_openU(lastSortedName, &err);
400 if(err!=U_FILE_ACCESS_ERROR){
401 log_err("FAILURE! ucnv_openU(lastSortedName, err) is expected to fail\n");
402 }
403
404 err=U_ZERO_ERROR;
405 }
406 log_verbose("Testing ucnv_open() with converter name greater than 7 characters\n");
407 {
408 UConverter *cnv=NULL;
409 err=U_ZERO_ERROR;
410 cnv=ucnv_open("ibm-949,Madhu", &err);
411 if(U_FAILURE(err)){
412 log_data_err("FAILURE! ucnv_open(\"ibm-949,Madhu\", err) failed. %s\n", myErrorName(err));
413 }
414 ucnv_close(cnv);
415
416 }
417 /*Testing ucnv_convert()*/
418 {
419 int32_t targetLimit=0, sourceLimit=0, i=0, targetCapacity=0;
420 const uint8_t source[]={ 0x00, 0x04, 0x05, 0x06, 0xa2, 0xb4, 0x00};
421 const uint8_t expectedTarget[]={ 0x00, 0x37, 0x2d, 0x2e, 0x0e, 0x49, 0x62, 0x0f, 0x00};
422 char *target=0;
423 sourceLimit=sizeof(source)/sizeof(source[0]);
424 err=U_ZERO_ERROR;
425 targetLimit=0;
426
427 targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", NULL, targetLimit , (const char*)source, sourceLimit, &err);
428 if(err == U_BUFFER_OVERFLOW_ERROR){
429 err=U_ZERO_ERROR;
430 targetLimit=targetCapacity+1;
431 target=(char*)malloc(sizeof(char) * targetLimit);
432 targetCapacity=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
433 }
434 if(U_FAILURE(err)){
435 log_data_err("FAILURE! ucnv_convert(ibm-1363->ibm-1364) failed. %s\n", myErrorName(err));
436 }
437 else {
438 for(i=0; i<targetCapacity; i++){
439 if(target[i] != expectedTarget[i]){
440 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]);
441 }
442 }
443
444 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source+1, -1, &err);
445 if(U_FAILURE(err) || i!=7){
446 log_err("FAILURE! ucnv_convert() with sourceLimit=-1 failed: %s, returned %d instead of 7\n",
447 u_errorName(err), i);
448 }
449
450 /*Test error conditions*/
451 err=U_ZERO_ERROR;
452 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, 0, &err);
453 if(i !=0){
454 log_err("FAILURE! ucnv_convert() with sourceLimit=0 is expected to return 0\n");
455 }
456
457 err=U_ILLEGAL_ARGUMENT_ERROR;
458 sourceLimit=sizeof(source)/sizeof(source[0]);
459 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
460 if(i !=0 ){
461 log_err("FAILURE! ucnv_convert() with err=U_ILLEGAL_ARGUMENT_ERROR is expected to return 0\n");
462 }
463
464 err=U_ZERO_ERROR;
465 sourceLimit=sizeof(source)/sizeof(source[0]);
466 targetLimit=0;
467 i=ucnv_convert("ibm-1364", "ibm-1363", target, targetLimit , (const char*)source, sourceLimit, &err);
468 if(!(U_FAILURE(err) && err==U_BUFFER_OVERFLOW_ERROR)){
469 log_err("FAILURE! ucnv_convert() with targetLimit=0 is expected to throw U_BUFFER_OVERFLOW_ERROR\n");
470 }
471 err=U_ZERO_ERROR;
472 free(target);
473 }
474 }
475
476 /*Testing ucnv_openCCSID and ucnv_open with error conditions*/
477 log_verbose("\n---Testing ucnv_open with err ! = U_ZERO_ERROR...\n");
478 err=U_ILLEGAL_ARGUMENT_ERROR;
479 if(ucnv_open(NULL, &err) != NULL){
480 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
481 }
482 if(ucnv_openCCSID(1051, UCNV_IBM, &err) != NULL){
483 log_err("ucnv_open with err != U_ZERO_ERROR is supposed to fail\n");
484 }
485 err=U_ZERO_ERROR;
486
487 /* Testing ucnv_openCCSID(), ucnv_open(), ucnv_getName() */
488 log_verbose("\n---Testing ucnv_open default...\n");
489 someConverters[0] = ucnv_open(NULL,&err);
490 someConverters[1] = ucnv_open(NULL,&err);
491 someConverters[2] = ucnv_open("utf8", &err);
492 someConverters[3] = ucnv_openCCSID(949,UCNV_IBM,&err);
493 ucnv_close(ucnv_openCCSID(1051, UCNV_IBM, &err)); /* test for j350; ucnv_close(NULL) is safe */
494 if (U_FAILURE(err)){ log_data_err("FAILURE! %s\n", myErrorName(err));}
495
496 /* Testing ucnv_getName()*/
497 /*default code page */
498 ucnv_getName(someConverters[0], &err);
499 if(U_FAILURE(err)) {
500 log_data_err("getName[0] failed\n");
501 } else {
502 log_verbose("getName(someConverters[0]) returned %s\n", ucnv_getName(someConverters[0], &err));
503 }
504 ucnv_getName(someConverters[1], &err);
505 if(U_FAILURE(err)) {
506 log_data_err("getName[1] failed\n");
507 } else {
508 log_verbose("getName(someConverters[1]) returned %s\n", ucnv_getName(someConverters[1], &err));
509 }
510
511 /*Testing ucnv_getDefaultName() and ucnv_setDefaultNAme()*/
512 {
513 static char defaultName[UCNV_MAX_CONVERTER_NAME_LENGTH + 1];
514 strcpy(defaultName, ucnv_getDefaultName());
515
516 log_verbose("getDefaultName returned %s\n", defaultName);
517
518 /*change the default name by setting it */
519 ucnv_setDefaultName("changed");
520 if(strcmp(ucnv_getDefaultName(), "changed")==0)
521 log_verbose("setDefaultName o.k");
522 else
523 log_err("setDefaultName failed");
524 /*set the default name back*/
525 ucnv_setDefaultName(defaultName);
526 }
527
528 ucnv_close(someConverters[0]);
529 ucnv_close(someConverters[1]);
530 ucnv_close(someConverters[2]);
531 ucnv_close(someConverters[3]);
532
533
534 for (codepage_index=0; codepage_index < NUM_CODEPAGE; ++codepage_index)
535 {
536 int32_t i = 0;
537
538 err = U_ZERO_ERROR;
539 #ifdef U_TOPSRCDIR
540 strcpy(ucs_file_name, U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING);
541 #else
542 strcpy(ucs_file_name, loadTestData(&err));
543
544 if(U_FAILURE(err)){
545 log_err("\nCouldn't get the test data directory... Exiting...Error:%s\n", u_errorName(err));
546 return;
547 }
548
549 {
550 char* index = strrchr(ucs_file_name,(char)U_FILE_SEP_CHAR);
551
552 if((unsigned int)(index-ucs_file_name) != (strlen(ucs_file_name)-1)){
553 *(index+1)=0;
554 }
555 }
556
557 strcat(ucs_file_name,".."U_FILE_SEP_STRING);
558 #endif
559 strcat(ucs_file_name, CodePagesTestFiles[codepage_index]);
560
561 ucs_file_in = fopen(ucs_file_name,"rb");
562 if (!ucs_file_in)
563 {
564 log_err("Couldn't open the Unicode file [%s]... Exiting...\n", ucs_file_name);
565 return;
566 }
567
568 /*Creates a converter and testing ucnv_openCCSID(u_int code_page, platform, errstatus*/
569
570 /* myConverter =ucnv_openCCSID(CodePageNumberToTest[codepage_index],UCNV_IBM, &err); */
571 /* ucnv_flushCache(); */
572 myConverter =ucnv_open( "ibm-949", &err);
573 if (!myConverter || U_FAILURE(err))
574 {
575 log_data_err("Error creating the ibm-949 converter - %s \n", u_errorName(err));
576
577 return;
578 }
579
580 /*testing for ucnv_getName() */
581 log_verbose("Testing ucnv_getName()...\n");
582 ucnv_getName(myConverter, &err);
583 if(U_FAILURE(err))
584 log_err("Error in getName\n");
585 else
586 {
587 log_verbose("getName o.k. %s\n", ucnv_getName(myConverter, &err));
588 }
589 if (ctest_stricmp(ucnv_getName(myConverter, &err), CodePagesToTest[codepage_index]))
590 log_err("getName failed\n");
591 else
592 log_verbose("getName ok\n");
593 /*Test getName with error condition*/
594 {
595 const char* name=0;
596 err=U_ILLEGAL_ARGUMENT_ERROR;
597 log_verbose("Testing ucnv_getName with err != U_ZERO_ERROR");
598 name=ucnv_getName(myConverter, &err);
599 if(name != NULL){
600 log_err("ucnv_getName() with err != U_ZERO_ERROR is expected to fail");
601 }
602 err=U_ZERO_ERROR;
603 }
604
605
606 /*Tests ucnv_getMaxCharSize() and ucnv_getMinCharSize()*/
607
608 log_verbose("Testing ucnv_getMaxCharSize()...\n");
609 if (ucnv_getMaxCharSize(myConverter)==CodePagesMaxChars[codepage_index])
610 log_verbose("Max byte per character OK\n");
611 else
612 log_err("Max byte per character failed\n");
613
614 log_verbose("\n---Testing ucnv_getMinCharSize()...\n");
615 if (ucnv_getMinCharSize(myConverter)==CodePagesMinChars[codepage_index])
616 log_verbose("Min byte per character OK\n");
617 else
618 log_err("Min byte per character failed\n");
619
620
621 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars()*/
622 log_verbose("\n---Testing ucnv_getSubstChars...\n");
623 ii=4;
624 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
625 if (ii <= 0) {
626 log_err("ucnv_getSubstChars returned a negative number %d\n", ii);
627 }
628
629 for(x=0;x<ii;x++)
630 rest = (uint16_t)(((unsigned char)rest << 8) + (unsigned char)myptr[x]);
631 if (rest==CodePagesSubstitutionChars[codepage_index])
632 log_verbose("Substitution character ok\n");
633 else
634 log_err("Substitution character failed.\n");
635
636 log_verbose("\n---Testing ucnv_setSubstChars RoundTrip Test ...\n");
637 ucnv_setSubstChars(myConverter, myptr, ii, &err);
638 if (U_FAILURE(err))
639 {
640 log_err("FAILURE! %s\n", myErrorName(err));
641 }
642 ucnv_getSubstChars(myConverter,save, &ii, &err);
643 if (U_FAILURE(err))
644 {
645 log_err("FAILURE! %s\n", myErrorName(err));
646 }
647
648 if (strncmp(save, myptr, ii))
649 log_err("Saved substitution character failed\n");
650 else
651 log_verbose("Saved substitution character ok\n");
652
653 /*Testing for ucnv_getSubstChars() and ucnv_setSubstChars() with error conditions*/
654 log_verbose("\n---Testing ucnv_getSubstChars.. with len < minBytesPerChar\n");
655 ii=1;
656 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
657 if(err != U_INDEX_OUTOFBOUNDS_ERROR){
658 log_err("ucnv_getSubstChars() with len < minBytesPerChar should throw U_INDEX_OUTOFBOUNDS_ERROR Got %s\n", myErrorName(err));
659 }
660 err=U_ZERO_ERROR;
661 ii=4;
662 ucnv_getSubstChars(myConverter, myptr, &ii, &err);
663 log_verbose("\n---Testing ucnv_setSubstChars.. with len < minBytesPerChar\n");
664 ucnv_setSubstChars(myConverter, myptr, 0, &err);
665 if(err != U_ILLEGAL_ARGUMENT_ERROR){
666 log_err("ucnv_setSubstChars() with len < minBytesPerChar should throw U_ILLEGAL_ARGUMENT_ERROR Got %s\n", myErrorName(err));
667 }
668 log_verbose("\n---Testing ucnv_setSubstChars.. with err != U_ZERO_ERROR \n");
669 strcpy(myptr, "abc");
670 ucnv_setSubstChars(myConverter, myptr, ii, &err);
671 err=U_ZERO_ERROR;
672 ucnv_getSubstChars(myConverter, save, &ii, &err);
673 if(strncmp(save, myptr, ii) == 0){
674 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't set the SubstChars and just return\n");
675 }
676 log_verbose("\n---Testing ucnv_getSubstChars.. with err != U_ZERO_ERROR \n");
677 err=U_ZERO_ERROR;
678 strcpy(myptr, "abc");
679 ucnv_setSubstChars(myConverter, myptr, ii, &err);
680 err=U_ILLEGAL_ARGUMENT_ERROR;
681 ucnv_getSubstChars(myConverter, save, &ii, &err);
682 if(strncmp(save, myptr, ii) == 0){
683 log_err("uncv_setSubstChars() with err != U_ZERO_ERROR shouldn't fill the SubstChars in the buffer, it just returns\n");
684 }
685 err=U_ZERO_ERROR;
686 /*------*/
687
688 #ifdef U_ENABLE_GENERIC_ISO_2022
689 /*resetState ucnv_reset()*/
690 log_verbose("\n---Testing ucnv_reset()..\n");
691 ucnv_reset(myConverter);
692 {
693 UChar32 c;
694 const uint8_t in[]={ 0x1b, 0x25, 0x42, 0x31, 0x32, 0x61, 0xc0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80};
695 const char *source=(const char *)in, *limit=(const char *)in+sizeof(in);
696 UConverter *cnv=ucnv_open("ISO_2022", &err);
697 if(U_FAILURE(err)) {
698 log_err("Unable to open a iso-2022 converter: %s\n", u_errorName(err));
699 }
700 c=ucnv_getNextUChar(cnv, &source, limit, &err);
701 if((U_FAILURE(err) || c != (UChar32)0x0031)) {
702 log_err("ucnv_getNextUChar() failed: %s\n", u_errorName(err));
703 }
704 ucnv_reset(cnv);
705 ucnv_close(cnv);
706
707 }
708 #endif
709
710 /*getDisplayName*/
711 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
712 locale=CodePagesLocale[codepage_index];
713 displayname=(UChar*)malloc(1 * sizeof(UChar));
714 len=0;
715 disnamelen = ucnv_getDisplayName(myConverter,locale,displayname, len, &err);
716 if(err==U_BUFFER_OVERFLOW_ERROR)
717 {
718 err=U_ZERO_ERROR;
719 displayname=(UChar*)realloc(displayname, (disnamelen+1) * sizeof(UChar));
720 ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
721 if(U_FAILURE(err))
722 {
723 log_err("getDisplayName failed the error is %s\n", myErrorName(err));
724 }
725 else
726 log_verbose(" getDisplayName o.k.\n");
727 }
728 /*test ucnv_getDiaplayName with error condition*/
729 log_verbose("\n---Testing ucnv_getDisplayName()...\n");
730 err= U_ILLEGAL_ARGUMENT_ERROR;
731 len=ucnv_getDisplayName(myConverter,locale,displayname,disnamelen+1, &err);
732 if( len !=0 ){
733 log_err("ucnv_getDisplayName() with err != U_ZERO_ERROR is supposed to return 0\n");
734 }
735 err=U_ZERO_ERROR;
736
737 /* testing ucnv_setFromUCallBack() and ucnv_getFromUCallBack()*/
738 ucnv_getFromUCallBack(myConverter, &MIA1, &MIA1Context);
739
740 log_verbose("\n---Testing ucnv_setFromUCallBack...\n");
741 ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
742 if (U_FAILURE(err) || oldFromUAction != MIA1 || oldFromUContext != MIA1Context)
743 {
744 log_err("FAILURE! %s\n", myErrorName(err));
745 }
746
747 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
748 if (MIA1_2 != otherUnicodeAction(MIA1) || MIA1Context2 != &BOM)
749 log_err("get From UCallBack failed\n");
750 else
751 log_verbose("get From UCallBack ok\n");
752
753 log_verbose("\n---Testing getFromUCallBack Roundtrip...\n");
754 ucnv_setFromUCallBack(myConverter,MIA1, MIA1Context, &oldFromUAction, &oldFromUContext, &err);
755 if (U_FAILURE(err) || oldFromUAction != otherUnicodeAction(MIA1) || oldFromUContext != &BOM)
756 {
757 log_err("FAILURE! %s\n", myErrorName(err));
758 }
759
760 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
761 if (MIA1_2 != MIA1 || MIA1Context2 != MIA1Context)
762 log_err("get From UCallBack action failed\n");
763 else
764 log_verbose("get From UCallBack action ok\n");
765
766 /*testing ucnv_setToUCallBack with error conditions*/
767 err=U_ILLEGAL_ARGUMENT_ERROR;
768 log_verbose("\n---Testing setFromUCallBack. with err != U_ZERO_ERROR..\n");
769 ucnv_setFromUCallBack(myConverter, otherUnicodeAction(MIA1), &BOM, &oldFromUAction, &oldFromUContext, &err);
770 ucnv_getFromUCallBack(myConverter, &MIA1_2, &MIA1Context2);
771 if(MIA1_2 == otherUnicodeAction(MIA1) || MIA1Context2 == &BOM){
772 log_err("To setFromUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
773 }
774 err=U_ZERO_ERROR;
775
776
777 /*testing ucnv_setToUCallBack() and ucnv_getToUCallBack()*/
778 ucnv_getToUCallBack(myConverter, &MIA2, &MIA2Context);
779
780 log_verbose("\n---Testing setTo UCallBack...\n");
781 ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), &BOM, &oldToUAction, &oldToUContext, &err);
782 if (U_FAILURE(err) || oldToUAction != MIA2 || oldToUContext != MIA2Context)
783 {
784 log_err("FAILURE! %s\n", myErrorName(err));
785 }
786
787 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
788 if (MIA2_2 != otherCharAction(MIA2) || MIA2Context2 != &BOM)
789 log_err("To UCallBack failed\n");
790 else
791 log_verbose("To UCallBack ok\n");
792
793 log_verbose("\n---Testing setTo UCallBack Roundtrip...\n");
794 ucnv_setToUCallBack(myConverter,MIA2, MIA2Context, &oldToUAction, &oldToUContext, &err);
795 if (U_FAILURE(err) || oldToUAction != otherCharAction(MIA2) || oldToUContext != &BOM)
796 { log_err("FAILURE! %s\n", myErrorName(err)); }
797
798 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
799 if (MIA2_2 != MIA2 || MIA2Context2 != MIA2Context)
800 log_err("To UCallBack failed\n");
801 else
802 log_verbose("To UCallBack ok\n");
803
804 /*testing ucnv_setToUCallBack with error conditions*/
805 err=U_ILLEGAL_ARGUMENT_ERROR;
806 log_verbose("\n---Testing setToUCallBack. with err != U_ZERO_ERROR..\n");
807 ucnv_setToUCallBack(myConverter,otherCharAction(MIA2), NULL, &oldToUAction, &oldToUContext, &err);
808 ucnv_getToUCallBack(myConverter, &MIA2_2, &MIA2Context2);
809 if (MIA2_2 == otherCharAction(MIA2) || MIA2Context2 == &BOM){
810 log_err("To setToUCallBack with err != U_ZERO_ERROR is supposed to fail\n");
811 }
812 err=U_ZERO_ERROR;
813
814
815 /*getcodepageid testing ucnv_getCCSID() */
816 log_verbose("\n----Testing getCCSID....\n");
817 cp = ucnv_getCCSID(myConverter,&err);
818 if (U_FAILURE(err))
819 {
820 log_err("FAILURE!..... %s\n", myErrorName(err));
821 }
822 if (cp != CodePageNumberToTest[codepage_index])
823 log_err("Codepage number test failed\n");
824 else
825 log_verbose("Codepage number test OK\n");
826
827 /*testing ucnv_getCCSID() with err != U_ZERO_ERROR*/
828 err=U_ILLEGAL_ARGUMENT_ERROR;
829 if( ucnv_getCCSID(myConverter,&err) != -1){
830 log_err("ucnv_getCCSID() with err != U_ZERO_ERROR is supposed to fail\n");
831 }
832 err=U_ZERO_ERROR;
833
834 /*getCodepagePlatform testing ucnv_getPlatform()*/
835 log_verbose("\n---Testing getCodepagePlatform ..\n");
836 if (CodePagesPlatform[codepage_index]!=ucnv_getPlatform(myConverter, &err))
837 log_err("Platform codepage test failed\n");
838 else
839 log_verbose("Platform codepage test ok\n");
840
841 if (U_FAILURE(err))
842 {
843 log_err("FAILURE! %s\n", myErrorName(err));
844 }
845 /*testing ucnv_getPlatform() with err != U_ZERO_ERROR*/
846 err= U_ILLEGAL_ARGUMENT_ERROR;
847 if(ucnv_getPlatform(myConverter, &err) != UCNV_UNKNOWN){
848 log_err("ucnv)getPlatform with err != U_ZERO_ERROR is supposed to fail\n");
849 }
850 err=U_ZERO_ERROR;
851
852
853 /*Reads the BOM*/
854 fread(&BOM, sizeof(UChar), 1, ucs_file_in);
855 if (BOM!=0xFEFF && BOM!=0xFFFE)
856 {
857 log_err("File Missing BOM...Bailing!\n");
858 return;
859 }
860
861
862 /*Reads in the file*/
863 while(!feof(ucs_file_in)&&(i+=fread(ucs_file_buffer+i, sizeof(UChar), 1, ucs_file_in)))
864 {
865 myUChar = ucs_file_buffer[i-1];
866
867 ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN*/
868 }
869
870 myUChar = ucs_file_buffer[i-1];
871 ucs_file_buffer[i-1] = (UChar)((BOM==0xFEFF)?myUChar:((myUChar >> 8) | (myUChar << 8))); /*adjust if BIG_ENDIAN Corner Case*/
872
873
874 /*testing ucnv_fromUChars() and ucnv_toUChars() */
875 /*uchar1---fromUChar--->output_cp_buffer --toUChar--->uchar2*/
876
877 uchar1=(UChar*)malloc(sizeof(UChar) * (i+1));
878 u_uastrcpy(uchar1,"");
879 u_strncpy(uchar1,ucs_file_buffer,i);
880 uchar1[i] = 0;
881
882 uchar3=(UChar*)malloc(sizeof(UChar)*(i+1));
883 u_uastrcpy(uchar3,"");
884 u_strncpy(uchar3,ucs_file_buffer,i);
885 uchar3[i] = 0;
886
887 /*Calls the Conversion Routine */
888 testLong1 = MAX_FILE_LEN;
889 log_verbose("\n---Testing ucnv_fromUChars()\n");
890 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
891 if (U_FAILURE(err))
892 {
893 log_err("\nFAILURE...%s\n", myErrorName(err));
894 }
895 else
896 log_verbose(" ucnv_fromUChars() o.k.\n");
897
898 /*test the conversion routine */
899 log_verbose("\n---Testing ucnv_toUChars()\n");
900 /*call it first time for trapping the targetcapacity and size needed to allocate memory for the buffer uchar2 */
901 targetcapacity2=0;
902 targetsize = ucnv_toUChars(myConverter,
903 NULL,
904 targetcapacity2,
905 output_cp_buffer,
906 strlen(output_cp_buffer),
907 &err);
908 /*if there is an buffer overflow then trap the values and pass them and make the actual call*/
909
910 if(err==U_BUFFER_OVERFLOW_ERROR)
911 {
912 err=U_ZERO_ERROR;
913 uchar2=(UChar*)malloc((targetsize+1) * sizeof(UChar));
914 targetsize = ucnv_toUChars(myConverter,
915 uchar2,
916 targetsize+1,
917 output_cp_buffer,
918 strlen(output_cp_buffer),
919 &err);
920
921 if(U_FAILURE(err))
922 log_err("ucnv_toUChars() FAILED %s\n", myErrorName(err));
923 else
924 log_verbose(" ucnv_toUChars() o.k.\n");
925
926 if(u_strcmp(uchar1,uchar2)!=0)
927 log_err("equality test failed with conversion routine\n");
928 }
929 else
930 {
931 log_err("ERR: calling toUChars: Didn't get U_BUFFER_OVERFLOW .. expected it.\n");
932 }
933 /*Testing ucnv_fromUChars and ucnv_toUChars with error conditions*/
934 err=U_ILLEGAL_ARGUMENT_ERROR;
935 log_verbose("\n---Testing ucnv_fromUChars() with err != U_ZERO_ERROR\n");
936 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, -1, &err);
937 if (targetcapacity !=0) {
938 log_err("\nFAILURE: ucnv_fromUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
939 }
940 err=U_ZERO_ERROR;
941 log_verbose("\n---Testing ucnv_fromUChars() with converter=NULL\n");
942 targetcapacity = ucnv_fromUChars(NULL, output_cp_buffer, testLong1, uchar1, -1, &err);
943 if (targetcapacity !=0 || err != U_ILLEGAL_ARGUMENT_ERROR) {
944 log_err("\nFAILURE: ucnv_fromUChars with converter=NULL is expected to fail\n");
945 }
946 err=U_ZERO_ERROR;
947 log_verbose("\n---Testing ucnv_fromUChars() with sourceLength = 0\n");
948 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, testLong1, uchar1, 0, &err);
949 if (targetcapacity !=0) {
950 log_err("\nFAILURE: ucnv_fromUChars with sourceLength 0 is expected to return 0\n");
951 }
952 log_verbose("\n---Testing ucnv_fromUChars() with targetLength = 0\n");
953 targetcapacity = ucnv_fromUChars(myConverter, output_cp_buffer, 0, uchar1, -1, &err);
954 if (err != U_BUFFER_OVERFLOW_ERROR) {
955 log_err("\nFAILURE: ucnv_fromUChars with targetLength 0 is expected to fail and throw U_BUFFER_OVERFLOW_ERROR\n");
956 }
957 /*toUChars with error conditions*/
958 targetsize = ucnv_toUChars(myConverter, uchar2, targetsize, output_cp_buffer, strlen(output_cp_buffer), &err);
959 if(targetsize != 0){
960 log_err("\nFAILURE: ucnv_toUChars with err != U_ZERO_ERROR is expected to fail and return 0\n");
961 }
962 err=U_ZERO_ERROR;
963 targetsize = ucnv_toUChars(myConverter, uchar2, -1, output_cp_buffer, strlen(output_cp_buffer), &err);
964 if(targetsize != 0 || err != U_ILLEGAL_ARGUMENT_ERROR){
965 log_err("\nFAILURE: ucnv_toUChars with targetsize < 0 is expected to throw U_ILLEGAL_ARGUMENT_ERROR and return 0\n");
966 }
967 err=U_ZERO_ERROR;
968 targetsize = ucnv_toUChars(myConverter, uchar2, 0, output_cp_buffer, 0, &err);
969 if (targetsize !=0) {
970 log_err("\nFAILURE: ucnv_toUChars with sourceLength 0 is expected to return 0\n");
971 }
972 targetcapacity2=0;
973 targetsize = ucnv_toUChars(myConverter, NULL, targetcapacity2, output_cp_buffer, strlen(output_cp_buffer), &err);
974 if (err != U_STRING_NOT_TERMINATED_WARNING) {
975 log_err("\nFAILURE: ucnv_toUChars(targetLength)->%s instead of U_STRING_NOT_TERMINATED_WARNING\n",
976 u_errorName(err));
977 }
978 err=U_ZERO_ERROR;
979 /*-----*/
980
981
982 /*testing for ucnv_fromUnicode() and ucnv_toUnicode() */
983 /*Clean up re-usable vars*/
984 j=0;
985 log_verbose("Testing ucnv_fromUnicode().....\n");
986 tmp_ucs_buf=ucs_file_buffer_use;
987 ucnv_fromUnicode(myConverter, &mytarget_1,
988 mytarget + MAX_FILE_LEN,
989 &tmp_ucs_buf,
990 ucs_file_buffer_use+i,
991 NULL,
992 TRUE,
993 &err);
994 consumedUni = (UChar*)tmp_consumedUni;
995
996 if (U_FAILURE(err))
997 {
998 log_err("FAILURE! %s\n", myErrorName(err));
999 }
1000 else
1001 log_verbose("ucnv_fromUnicode() o.k.\n");
1002
1003 /*Uni1 ----ToUnicode----> Cp2 ----FromUnicode---->Uni3 */
1004 log_verbose("Testing ucnv_toUnicode().....\n");
1005 tmp_mytarget_use=mytarget_use;
1006 tmp_consumed = consumed;
1007 ucnv_toUnicode(myConverter, &my_ucs_file_buffer_1,
1008 my_ucs_file_buffer + MAX_FILE_LEN,
1009 &tmp_mytarget_use,
1010 mytarget_use + (mytarget_1 - mytarget),
1011 NULL,
1012 FALSE,
1013 &err);
1014 consumed = (char*)tmp_consumed;
1015 if (U_FAILURE(err))
1016 {
1017 log_err("FAILURE! %s\n", myErrorName(err));
1018 }
1019 else
1020 log_verbose("ucnv_toUnicode() o.k.\n");
1021
1022
1023 log_verbose("\n---Testing RoundTrip ...\n");
1024
1025
1026 u_strncpy(uchar3, my_ucs_file_buffer,i);
1027 uchar3[i] = 0;
1028
1029 if(u_strcmp(uchar1,uchar3)==0)
1030 log_verbose("Equality test o.k.\n");
1031 else
1032 log_err("Equality test failed\n");
1033
1034 /*sanity compare */
1035 if(uchar2 == NULL)
1036 {
1037 log_err("uchar2 was NULL (ccapitst.c line %d), couldn't do sanity check\n", __LINE__);
1038 }
1039 else
1040 {
1041 if(u_strcmp(uchar2, uchar3)==0)
1042 log_verbose("Equality test o.k.\n");
1043 else
1044 log_err("Equality test failed\n");
1045 }
1046
1047 fclose(ucs_file_in);
1048 ucnv_close(myConverter);
1049 free(displayname);
1050 if (uchar1 != 0) free(uchar1);
1051 if (uchar2 != 0) free(uchar2);
1052 if (uchar3 != 0) free(uchar3);
1053 }
1054
1055 free((void*)mytarget);
1056 free((void*)output_cp_buffer);
1057 free((void*)ucs_file_buffer);
1058 free((void*)my_ucs_file_buffer);
1059 }
1060
1061 static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA)
1062 {
1063 return (MIA==(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP)?(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_SUBSTITUTE:(UConverterFromUCallback)UCNV_FROM_U_CALLBACK_STOP;
1064 }
1065
1066
1067 static UConverterToUCallback otherCharAction(UConverterToUCallback MIA)
1068 {
1069 return (MIA==(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP)?(UConverterToUCallback)UCNV_TO_U_CALLBACK_SUBSTITUTE:(UConverterToUCallback)UCNV_TO_U_CALLBACK_STOP;
1070 }
1071
1072 static void TestFlushCache(void) {
1073 UErrorCode err = U_ZERO_ERROR;
1074 UConverter* someConverters[5];
1075 int flushCount = 0;
1076
1077 /* flush the converter cache to get a consistent state before the flushing is tested */
1078 ucnv_flushCache();
1079
1080 /*Testing ucnv_open()*/
1081 /* Note: These converters have been chosen because they do NOT
1082 encode the Latin characters (U+0041, ...), and therefore are
1083 highly unlikely to be chosen as system default codepages */
1084
1085 someConverters[0] = ucnv_open("ibm-1047", &err);
1086 if (U_FAILURE(err)) {
1087 log_data_err("FAILURE! %s\n", myErrorName(err));
1088 }
1089
1090 someConverters[1] = ucnv_open("ibm-1047", &err);
1091 if (U_FAILURE(err)) {
1092 log_data_err("FAILURE! %s\n", myErrorName(err));
1093 }
1094
1095 someConverters[2] = ucnv_open("ibm-1047", &err);
1096 if (U_FAILURE(err)) {
1097 log_data_err("FAILURE! %s\n", myErrorName(err));
1098 }
1099
1100 someConverters[3] = ucnv_open("gb18030", &err);
1101 if (U_FAILURE(err)) {
1102 log_data_err("FAILURE! %s\n", myErrorName(err));
1103 }
1104
1105 someConverters[4] = ucnv_open("ibm-954", &err);
1106 if (U_FAILURE(err)) {
1107 log_data_err("FAILURE! %s\n", myErrorName(err));
1108 }
1109
1110
1111 /* Testing ucnv_flushCache() */
1112 log_verbose("\n---Testing ucnv_flushCache...\n");
1113 if ((flushCount=ucnv_flushCache())==0)
1114 log_verbose("Flush cache ok\n");
1115 else
1116 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1117
1118 /*testing ucnv_close() and ucnv_flushCache() */
1119 ucnv_close(someConverters[0]);
1120 ucnv_close(someConverters[1]);
1121
1122 if ((flushCount=ucnv_flushCache())==0)
1123 log_verbose("Flush cache ok\n");
1124 else
1125 log_data_err("Flush Cache failed [line %d], expect 0 got %d \n", __LINE__, flushCount);
1126
1127 ucnv_close(someConverters[2]);
1128 ucnv_close(someConverters[3]);
1129
1130 if ((flushCount=ucnv_flushCache())==2)
1131 log_verbose("Flush cache ok\n"); /*because first, second and third are same */
1132 else
1133 log_data_err("Flush Cache failed line %d, got %d expected 2 or there is an error in ucnv_close()\n",
1134 __LINE__,
1135 flushCount);
1136
1137 ucnv_close(someConverters[4]);
1138 if ( (flushCount=ucnv_flushCache())==1)
1139 log_verbose("Flush cache ok\n");
1140 else
1141 log_data_err("Flush Cache failed line %d, expected 1 got %d \n", __LINE__, flushCount);
1142
1143 }
1144
1145 /**
1146 * Test the converter alias API, specifically the fuzzy matching of
1147 * alias names and the alias table integrity. Make sure each
1148 * converter has at least one alias (itself), and that its listed
1149 * aliases map back to itself. Check some hard-coded UTF-8 and
1150 * ISO_2022 aliases to make sure they work.
1151 */
1152 static void TestAlias() {
1153 int32_t i, ncnv;
1154 UErrorCode status = U_ZERO_ERROR;
1155
1156 /* Predetermined aliases that we expect to map back to ISO_2022
1157 * and UTF-8. UPDATE THIS DATA AS NECESSARY. */
1158 const char* ISO_2022_NAMES[] =
1159 {"ISO_2022,locale=ja,version=2", "ISO-2022-JP-2", "csISO2022JP2",
1160 "Iso-2022jP2", "isO-2022_Jp_2", "iSo--2022,locale=ja,version=2"};
1161 int32_t ISO_2022_NAMES_LENGTH =
1162 sizeof(ISO_2022_NAMES) / sizeof(ISO_2022_NAMES[0]);
1163 const char *UTF8_NAMES[] =
1164 { "UTF-8", "utf-8", "utf8", "ibm-1208",
1165 "utf_8", "ibm1208", "cp1208" };
1166 int32_t UTF8_NAMES_LENGTH =
1167 sizeof(UTF8_NAMES) / sizeof(UTF8_NAMES[0]);
1168
1169 struct {
1170 const char *name;
1171 const char *alias;
1172 } CONVERTERS_NAMES[] = {
1173 { "UTF-32BE", "UTF32_BigEndian" },
1174 { "UTF-32LE", "UTF32_LittleEndian" },
1175 { "UTF-32", "ISO-10646-UCS-4" },
1176 { "UTF32_PlatformEndian", "UTF32_PlatformEndian" },
1177 { "UTF-32", "ucs-4" }
1178 };
1179 int32_t CONVERTERS_NAMES_LENGTH = sizeof(CONVERTERS_NAMES) / sizeof(*CONVERTERS_NAMES);
1180
1181 /* When there are bugs in gencnval or in ucnv_io, converters can
1182 appear to have no aliases. */
1183 ncnv = ucnv_countAvailable();
1184 log_verbose("%d converters\n", ncnv);
1185 for (i=0; i<ncnv; ++i) {
1186 const char *name = ucnv_getAvailableName(i);
1187 const char *alias0;
1188 uint16_t na = ucnv_countAliases(name, &status);
1189 uint16_t j;
1190 UConverter *cnv;
1191
1192 if (na == 0) {
1193 log_err("FAIL: Converter \"%s\" (i=%d)"
1194 " has no aliases; expect at least one\n",
1195 name, i);
1196 continue;
1197 }
1198 cnv = ucnv_open(name, &status);
1199 if (U_FAILURE(status)) {
1200 log_data_err("FAIL: Converter \"%s\" (i=%d)"
1201 " can't be opened.\n",
1202 name, i);
1203 }
1204 else {
1205 if (strcmp(ucnv_getName(cnv, &status), name) != 0
1206 && (strstr(name, "PlatformEndian") == 0 && strstr(name, "OppositeEndian") == 0)) {
1207 log_err("FAIL: Converter \"%s\" returned \"%s\" for getName. "
1208 "The should be the same\n",
1209 name, ucnv_getName(cnv, &status));
1210 }
1211 }
1212 ucnv_close(cnv);
1213
1214 status = U_ZERO_ERROR;
1215 alias0 = ucnv_getAlias(name, 0, &status);
1216 for (j=1; j<na; ++j) {
1217 const char *alias;
1218 /* Make sure each alias maps back to the the same list of
1219 aliases. Assume that if alias 0 is the same, the whole
1220 list is the same (this should always be true). */
1221 const char *mapBack;
1222
1223 status = U_ZERO_ERROR;
1224 alias = ucnv_getAlias(name, j, &status);
1225 if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1226 log_err("FAIL: Converter \"%s\"is ambiguous\n", name);
1227 }
1228
1229 if (alias == NULL) {
1230 log_err("FAIL: Converter \"%s\" -> "
1231 "alias[%d]=NULL\n",
1232 name, j);
1233 continue;
1234 }
1235
1236 mapBack = ucnv_getAlias(alias, 0, &status);
1237
1238 if (mapBack == NULL) {
1239 log_err("FAIL: Converter \"%s\" -> "
1240 "alias[%d]=\"%s\" -> "
1241 "alias[0]=NULL, exp. \"%s\"\n",
1242 name, j, alias, alias0);
1243 continue;
1244 }
1245
1246 if (0 != strcmp(alias0, mapBack)) {
1247 int32_t idx;
1248 UBool foundAlias = FALSE;
1249 if (status == U_AMBIGUOUS_ALIAS_WARNING) {
1250 /* Make sure that we only get this mismapping when there is
1251 an ambiguous alias, and the other converter has this alias too. */
1252 for (idx = 0; idx < ucnv_countAliases(mapBack, &status); idx++) {
1253 if (strcmp(ucnv_getAlias(mapBack, (uint16_t)idx, &status), alias) == 0) {
1254 foundAlias = TRUE;
1255 break;
1256 }
1257 }
1258 }
1259 /* else not ambiguous, and this is a real problem. foundAlias = FALSE */
1260
1261 if (!foundAlias) {
1262 log_err("FAIL: Converter \"%s\" -> "
1263 "alias[%d]=\"%s\" -> "
1264 "alias[0]=\"%s\", exp. \"%s\"\n",
1265 name, j, alias, mapBack, alias0);
1266 }
1267 }
1268 }
1269 }
1270
1271
1272 /* Check a list of predetermined aliases that we expect to map
1273 * back to ISO_2022 and UTF-8. */
1274 for (i=1; i<ISO_2022_NAMES_LENGTH; ++i) {
1275 const char* mapBack = ucnv_getAlias(ISO_2022_NAMES[i], 0, &status);
1276 if(!mapBack) {
1277 log_data_err("Couldn't get alias for %s. You probably have no data\n", ISO_2022_NAMES[i]);
1278 continue;
1279 }
1280 if (0 != strcmp(mapBack, ISO_2022_NAMES[0])) {
1281 log_err("FAIL: \"%s\" -> \"%s\", expect \"ISO_2022,locale=ja,version=2\"\n",
1282 ISO_2022_NAMES[i], mapBack);
1283 }
1284 }
1285
1286
1287 for (i=1; i<UTF8_NAMES_LENGTH; ++i) {
1288 const char* mapBack = ucnv_getAlias(UTF8_NAMES[i], 0, &status);
1289 if(!mapBack) {
1290 log_data_err("Couldn't get alias for %s. You probably have no data\n", UTF8_NAMES[i]);
1291 continue;
1292 }
1293 if (mapBack && 0 != strcmp(mapBack, UTF8_NAMES[0])) {
1294 log_err("FAIL: \"%s\" -> \"%s\", expect UTF-8\n",
1295 UTF8_NAMES[i], mapBack);
1296 }
1297 }
1298
1299 /*
1300 * Check a list of predetermined aliases that we expect to map
1301 * back to predermined converter names.
1302 */
1303
1304 for (i = 0; i < CONVERTERS_NAMES_LENGTH; ++i) {
1305 const char* mapBack = ucnv_getAlias(CONVERTERS_NAMES[i].alias, 0, &status);
1306 if(!mapBack) {
1307 log_data_err("Couldn't get alias for %s. You probably have no data\n", CONVERTERS_NAMES[i]);
1308 continue;
1309 }
1310 if (0 != strcmp(mapBack, CONVERTERS_NAMES[i].name)) {
1311 log_err("FAIL: \"%s\" -> \"%s\", expect %s\n",
1312 CONVERTERS_NAMES[i].alias, mapBack, CONVERTERS_NAMES[i].name);
1313 }
1314 }
1315
1316 }
1317
1318 static void TestDuplicateAlias(void) {
1319 const char *alias;
1320 UErrorCode status = U_ZERO_ERROR;
1321
1322 status = U_ZERO_ERROR;
1323 alias = ucnv_getStandardName("Shift_JIS", "IBM", &status);
1324 if (alias == NULL || strcmp(alias, "ibm-943") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1325 log_err("FAIL: Didn't get ibm-943 for Shift_JIS {IBM}. Got %s\n", alias);
1326 }
1327 status = U_ZERO_ERROR;
1328 alias = ucnv_getStandardName("ibm-943", "IANA", &status);
1329 if (alias == NULL || strcmp(alias, "Shift_JIS") != 0 || status != U_AMBIGUOUS_ALIAS_WARNING) {
1330 log_data_err("FAIL: Didn't get Shift_JIS for ibm-943 {IANA}. Got %s\n", alias);
1331 }
1332 status = U_ZERO_ERROR;
1333 alias = ucnv_getStandardName("ibm-943_P130-2000", "IANA", &status);
1334 if (alias != NULL || status == U_AMBIGUOUS_ALIAS_WARNING) {
1335 log_data_err("FAIL: Didn't get NULL for ibm-943 {IANA}. Got %s\n", alias);
1336 }
1337 }
1338
1339
1340 /* Test safe clone callback */
1341
1342 static uint32_t TSCC_nextSerial()
1343 {
1344 static uint32_t n = 1;
1345
1346 return (n++);
1347 }
1348
1349 typedef struct
1350 {
1351 uint32_t magic; /* 0xC0FFEE to identify that the object is OK */
1352 uint32_t serial; /* minted from nextSerial, above */
1353 UBool wasClosed; /* close happened on the object */
1354 } TSCCContext;
1355
1356 static TSCCContext *TSCC_clone(TSCCContext *ctx)
1357 {
1358 TSCCContext *newCtx = (TSCCContext *)malloc(sizeof(TSCCContext));
1359
1360 newCtx->serial = TSCC_nextSerial();
1361 newCtx->wasClosed = 0;
1362 newCtx->magic = 0xC0FFEE;
1363
1364 log_verbose("TSCC_clone: %p:%d -> new context %p:%d\n", ctx, ctx->serial, newCtx, newCtx->serial);
1365
1366 return newCtx;
1367 }
1368
1369 static void TSCC_fromU(const void *context,
1370 UConverterFromUnicodeArgs *fromUArgs,
1371 const UChar* codeUnits,
1372 int32_t length,
1373 UChar32 codePoint,
1374 UConverterCallbackReason reason,
1375 UErrorCode * err)
1376 {
1377 TSCCContext *ctx = (TSCCContext*)context;
1378 UConverterFromUCallback junkFrom;
1379
1380 log_verbose("TSCC_fromU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, fromUArgs->converter);
1381
1382 if(ctx->magic != 0xC0FFEE) {
1383 log_err("TSCC_fromU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1384 return;
1385 }
1386
1387 if(reason == UCNV_CLONE) {
1388 UErrorCode subErr = U_ZERO_ERROR;
1389 TSCCContext *newCtx;
1390 TSCCContext *junkCtx;
1391
1392 /* "recreate" it */
1393 log_verbose("TSCC_fromU: cloning..\n");
1394 newCtx = TSCC_clone(ctx);
1395
1396 if(newCtx == NULL) {
1397 log_err("TSCC_fromU: internal clone failed on %p\n", ctx);
1398 }
1399
1400 /* now, SET it */
1401 ucnv_getFromUCallBack(fromUArgs->converter, &junkFrom, (const void**)&junkCtx);
1402 ucnv_setFromUCallBack(fromUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1403
1404 if(U_FAILURE(subErr)) {
1405 *err = subErr;
1406 }
1407 }
1408
1409 if(reason == UCNV_CLOSE) {
1410 log_verbose("TSCC_fromU: Context %p:%d closing\n", ctx, ctx->serial);
1411 ctx->wasClosed = TRUE;
1412 }
1413 }
1414
1415
1416 static void TSCC_toU(const void *context,
1417 UConverterToUnicodeArgs *toUArgs,
1418 const char* codeUnits,
1419 int32_t length,
1420 UConverterCallbackReason reason,
1421 UErrorCode * err)
1422 {
1423 TSCCContext *ctx = (TSCCContext*)context;
1424 UConverterToUCallback junkFrom;
1425
1426 log_verbose("TSCC_toU: Context %p:%d called, reason %d on cnv %p\n", ctx, ctx->serial, reason, toUArgs->converter);
1427
1428 if(ctx->magic != 0xC0FFEE) {
1429 log_err("TSCC_toU: Context %p:%d magic is 0x%x should be 0xC0FFEE.\n", ctx,ctx->serial, ctx->magic);
1430 return;
1431 }
1432
1433 if(reason == UCNV_CLONE) {
1434 UErrorCode subErr = U_ZERO_ERROR;
1435 TSCCContext *newCtx;
1436 TSCCContext *junkCtx;
1437
1438 /* "recreate" it */
1439 log_verbose("TSCC_toU: cloning..\n");
1440 newCtx = TSCC_clone(ctx);
1441
1442 if(newCtx == NULL) {
1443 log_err("TSCC_toU: internal clone failed on %p\n", ctx);
1444 }
1445
1446 /* now, SET it */
1447 ucnv_getToUCallBack(toUArgs->converter, &junkFrom, (const void**)&junkCtx);
1448 ucnv_setToUCallBack(toUArgs->converter, junkFrom, newCtx, NULL, NULL, &subErr);
1449
1450 if(U_FAILURE(subErr)) {
1451 *err = subErr;
1452 }
1453 }
1454
1455 if(reason == UCNV_CLOSE) {
1456 log_verbose("TSCC_toU: Context %p:%d closing\n", ctx, ctx->serial);
1457 ctx->wasClosed = TRUE;
1458 }
1459 }
1460
1461 static void TSCC_init(TSCCContext *q)
1462 {
1463 q->magic = 0xC0FFEE;
1464 q->serial = TSCC_nextSerial();
1465 q->wasClosed = 0;
1466 }
1467
1468 static void TSCC_print_log(TSCCContext *q, const char *name)
1469 {
1470 if(q==NULL) {
1471 log_verbose("TSCContext: %s is NULL!!\n", name);
1472 } else {
1473 if(q->magic != 0xC0FFEE) {
1474 log_err("TSCCContext: %p:%d's magic is %x, supposed to be 0xC0FFEE\n",
1475 q,q->serial, q->magic);
1476 }
1477 log_verbose("TSCCContext %p:%d=%s - magic %x, %s\n",
1478 q, q->serial, name, q->magic, q->wasClosed?"CLOSED":"open");
1479 }
1480 }
1481
1482 static void TestConvertSafeCloneCallback()
1483 {
1484 UErrorCode err = U_ZERO_ERROR;
1485 TSCCContext from1, to1;
1486 TSCCContext *from2, *from3, *to2, *to3;
1487 char hunk[8192];
1488 int32_t hunkSize = 8192;
1489 UConverterFromUCallback junkFrom;
1490 UConverterToUCallback junkTo;
1491 UConverter *conv1, *conv2 = NULL;
1492
1493 conv1 = ucnv_open("iso-8859-3", &err);
1494
1495 if(U_FAILURE(err)) {
1496 log_data_err("Err opening iso-8859-3, %s", u_errorName(err));
1497 return;
1498 }
1499
1500 log_verbose("Opened conv1=%p\n", conv1);
1501
1502 TSCC_init(&from1);
1503 TSCC_init(&to1);
1504
1505 TSCC_print_log(&from1, "from1");
1506 TSCC_print_log(&to1, "to1");
1507
1508 ucnv_setFromUCallBack(conv1, TSCC_fromU, &from1, NULL, NULL, &err);
1509 log_verbose("Set from1 on conv1\n");
1510 TSCC_print_log(&from1, "from1");
1511
1512 ucnv_setToUCallBack(conv1, TSCC_toU, &to1, NULL, NULL, &err);
1513 log_verbose("Set to1 on conv1\n");
1514 TSCC_print_log(&to1, "to1");
1515
1516 conv2 = ucnv_safeClone(conv1, hunk, &hunkSize, &err);
1517 if(U_FAILURE(err)) {
1518 log_err("safeClone failed: %s\n", u_errorName(err));
1519 return;
1520 }
1521 log_verbose("Cloned to conv2=%p.\n", conv2);
1522
1523 /********** from *********************/
1524 ucnv_getFromUCallBack(conv2, &junkFrom, (const void**)&from2);
1525 ucnv_getFromUCallBack(conv1, &junkFrom, (const void**)&from3);
1526
1527 TSCC_print_log(from2, "from2");
1528 TSCC_print_log(from3, "from3(==from1)");
1529
1530 if(from2 == NULL) {
1531 log_err("FAIL! from2 is null \n");
1532 return;
1533 }
1534
1535 if(from3 == NULL) {
1536 log_err("FAIL! from3 is null \n");
1537 return;
1538 }
1539
1540 if(from3 != (&from1) ) {
1541 log_err("FAIL! conv1's FROM context changed!\n");
1542 }
1543
1544 if(from2 == (&from1) ) {
1545 log_err("FAIL! conv1's FROM context is the same as conv2's!\n");
1546 }
1547
1548 if(from1.wasClosed) {
1549 log_err("FAIL! from1 is closed \n");
1550 }
1551
1552 if(from2->wasClosed) {
1553 log_err("FAIL! from2 was closed\n");
1554 }
1555
1556 /********** to *********************/
1557 ucnv_getToUCallBack(conv2, &junkTo, (const void**)&to2);
1558 ucnv_getToUCallBack(conv1, &junkTo, (const void**)&to3);
1559
1560 TSCC_print_log(to2, "to2");
1561 TSCC_print_log(to3, "to3(==to1)");
1562
1563 if(to2 == NULL) {
1564 log_err("FAIL! to2 is null \n");
1565 return;
1566 }
1567
1568 if(to3 == NULL) {
1569 log_err("FAIL! to3 is null \n");
1570 return;
1571 }
1572
1573 if(to3 != (&to1) ) {
1574 log_err("FAIL! conv1's TO context changed!\n");
1575 }
1576
1577 if(to2 == (&to1) ) {
1578 log_err("FAIL! conv1's TO context is the same as conv2's!\n");
1579 }
1580
1581 if(to1.wasClosed) {
1582 log_err("FAIL! to1 is closed \n");
1583 }
1584
1585 if(to2->wasClosed) {
1586 log_err("FAIL! to2 was closed\n");
1587 }
1588
1589 /*************************************/
1590
1591 ucnv_close(conv1);
1592 log_verbose("ucnv_closed (conv1)\n");
1593 TSCC_print_log(&from1, "from1");
1594 TSCC_print_log(from2, "from2");
1595 TSCC_print_log(&to1, "to1");
1596 TSCC_print_log(to2, "to2");
1597
1598 if(from1.wasClosed == FALSE) {
1599 log_err("FAIL! from1 is NOT closed \n");
1600 }
1601
1602 if(from2->wasClosed) {
1603 log_err("FAIL! from2 was closed\n");
1604 }
1605
1606 if(to1.wasClosed == FALSE) {
1607 log_err("FAIL! to1 is NOT closed \n");
1608 }
1609
1610 if(to2->wasClosed) {
1611 log_err("FAIL! to2 was closed\n");
1612 }
1613
1614 ucnv_close(conv2);
1615 log_verbose("ucnv_closed (conv2)\n");
1616
1617 TSCC_print_log(&from1, "from1");
1618 TSCC_print_log(from2, "from2");
1619
1620 if(from1.wasClosed == FALSE) {
1621 log_err("FAIL! from1 is NOT closed \n");
1622 }
1623
1624 if(from2->wasClosed == FALSE) {
1625 log_err("FAIL! from2 was NOT closed\n");
1626 }
1627
1628 TSCC_print_log(&to1, "to1");
1629 TSCC_print_log(to2, "to2");
1630
1631 if(to1.wasClosed == FALSE) {
1632 log_err("FAIL! to1 is NOT closed \n");
1633 }
1634
1635 if(to2->wasClosed == FALSE) {
1636 log_err("FAIL! to2 was NOT closed\n");
1637 }
1638
1639 if(to2 != (&to1)) {
1640 free(to2); /* to1 is stack based */
1641 }
1642 if(from2 != (&from1)) {
1643 free(from2); /* from1 is stack based */
1644 }
1645 }
1646
1647 static UBool
1648 containsAnyOtherByte(uint8_t *p, int32_t length, uint8_t b) {
1649 while(length>0) {
1650 if(*p!=b) {
1651 return TRUE;
1652 }
1653 ++p;
1654 --length;
1655 }
1656 return FALSE;
1657 }
1658
1659 static void TestConvertSafeClone()
1660 {
1661 /* one 'regular' & all the 'private stateful' converters */
1662 static const char *const names[] = {
1663 "ibm-1047",
1664 "ISO_2022,locale=zh,version=1",
1665 "SCSU",
1666 "HZ",
1667 "lmbcs",
1668 "ISCII,version=0",
1669 "ISO_2022,locale=kr,version=1",
1670 "ISO_2022,locale=jp,version=2",
1671 "BOCU-1",
1672 "UTF-7",
1673 "IMAP-mailbox-name",
1674 "ibm-1047-s390"
1675 };
1676
1677 static const int32_t bufferSizes[] = {
1678 U_CNV_SAFECLONE_BUFFERSIZE,
1679 (int32_t)(3*sizeof(UConverter))/2, /* 1.5*sizeof(UConverter) */
1680 (int32_t)sizeof(UConverter)/2 /* 0.5*sizeof(UConverter) */
1681 };
1682
1683 char charBuffer [21]; /* Leave at an odd number for alignment testing */
1684 uint8_t buffer [3] [U_CNV_SAFECLONE_BUFFERSIZE];
1685 int32_t bufferSize, maxBufferSize;
1686 const char *maxName;
1687 UConverter * cnv, *cnv2;
1688 UErrorCode err;
1689
1690 char *pCharBuffer;
1691 const char *pConstCharBuffer;
1692 const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
1693 UChar uniBuffer [] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
1694 UChar uniCharBuffer [20];
1695 char charSourceBuffer [] = { 0x1b, 0x24, 0x42 };
1696 const char *pCharSource = charSourceBuffer;
1697 const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
1698 UChar *pUCharTarget = uniCharBuffer;
1699 UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer)/sizeof(*uniCharBuffer);
1700 const UChar * pUniBuffer;
1701 const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
1702 int32_t index, j;
1703
1704 err = U_ZERO_ERROR;
1705 cnv = ucnv_open(names[0], &err);
1706 if(U_SUCCESS(err)) {
1707 /* Check the various error & informational states: */
1708
1709 /* Null status - just returns NULL */
1710 bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1711 if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, 0))
1712 {
1713 log_err("FAIL: Cloned converter failed to deal correctly with null status\n");
1714 }
1715 /* error status - should return 0 & keep error the same */
1716 err = U_MEMORY_ALLOCATION_ERROR;
1717 if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || err != U_MEMORY_ALLOCATION_ERROR)
1718 {
1719 log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n");
1720 }
1721 err = U_ZERO_ERROR;
1722
1723 /* Null buffer size pointer - just returns NULL & set error to U_ILLEGAL_ARGUMENT_ERROR*/
1724 if (0 != ucnv_safeClone(cnv, buffer[0], 0, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
1725 {
1726 log_err("FAIL: Cloned converter failed to deal correctly with null bufferSize pointer\n");
1727 }
1728 err = U_ZERO_ERROR;
1729
1730 /* buffer size pointer is 0 - fill in pbufferSize with a size */
1731 bufferSize = 0;
1732 if (0 != ucnv_safeClone(cnv, buffer[0], &bufferSize, &err) || U_FAILURE(err) || bufferSize <= 0)
1733 {
1734 log_err("FAIL: Cloned converter failed a sizing request ('preflighting')\n");
1735 }
1736 /* Verify our define is large enough */
1737 if (U_CNV_SAFECLONE_BUFFERSIZE < bufferSize)
1738 {
1739 log_err("FAIL: Pre-calculated buffer size is too small\n");
1740 }
1741 /* Verify we can use this run-time calculated size */
1742 if (0 == (cnv2 = ucnv_safeClone(cnv, buffer[0], &bufferSize, &err)) || U_FAILURE(err))
1743 {
1744 log_err("FAIL: Converter can't be cloned with run-time size\n");
1745 }
1746 if (cnv2) {
1747 ucnv_close(cnv2);
1748 }
1749
1750 /* size one byte too small - should allocate & let us know */
1751 --bufferSize;
1752 if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1753 {
1754 log_err("FAIL: Cloned converter failed to deal correctly with too-small buffer size\n");
1755 }
1756 if (cnv2) {
1757 ucnv_close(cnv2);
1758 }
1759
1760 err = U_ZERO_ERROR;
1761 bufferSize = U_CNV_SAFECLONE_BUFFERSIZE;
1762
1763 /* Null buffer pointer - return converter & set error to U_SAFECLONE_ALLOCATED_ERROR */
1764 if (0 == (cnv2 = ucnv_safeClone(cnv, 0, &bufferSize, &err)) || err != U_SAFECLONE_ALLOCATED_WARNING)
1765 {
1766 log_err("FAIL: Cloned converter failed to deal correctly with null buffer pointer\n");
1767 }
1768 if (cnv2) {
1769 ucnv_close(cnv2);
1770 }
1771
1772 err = U_ZERO_ERROR;
1773
1774 /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */
1775 if (0 != ucnv_safeClone(0, buffer[0], &bufferSize, &err) || err != U_ILLEGAL_ARGUMENT_ERROR)
1776 {
1777 log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n");
1778 }
1779
1780 ucnv_close(cnv);
1781 }
1782
1783 maxBufferSize = 0;
1784 maxName = "";
1785
1786 /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/
1787
1788 for(j = 0; j < LENGTHOF(bufferSizes); ++j) {
1789 for (index = 0; index < LENGTHOF(names); index++)
1790 {
1791 err = U_ZERO_ERROR;
1792 cnv = ucnv_open(names[index], &err);
1793 if(U_FAILURE(err)) {
1794 log_data_err("ucnv_open(\"%s\") failed - %s\n", names[index], u_errorName(err));
1795 continue;
1796 }
1797
1798 if(j == 0) {
1799 /* preflight to get maxBufferSize */
1800 bufferSize = 0;
1801 ucnv_safeClone(cnv, NULL, &bufferSize, &err);
1802 if(bufferSize > maxBufferSize) {
1803 maxBufferSize = bufferSize;
1804 maxName = names[index];
1805 }
1806 }
1807
1808 memset(buffer, 0xaa, sizeof(buffer));
1809
1810 bufferSize = bufferSizes[j];
1811 cnv2 = ucnv_safeClone(cnv, buffer[1], &bufferSize, &err);
1812
1813 /* close the original immediately to make sure that the clone works by itself */
1814 ucnv_close(cnv);
1815
1816 /* check if the clone function overwrote any bytes that it is not supposed to touch */
1817 if(bufferSize <= bufferSizes[j]) {
1818 /* used the stack buffer */
1819 if( containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer[0]), 0xaa) ||
1820 containsAnyOtherByte(buffer[1]+bufferSize, (int32_t)(sizeof(buffer)-(sizeof(buffer[0])+bufferSize)), 0xaa)
1821 ) {
1822 log_err("cloning %s in a stack buffer overwrote bytes outside the bufferSize %d (requested %d)\n",
1823 names[index], bufferSize, bufferSizes[j]);
1824 }
1825 } else {
1826 /* heap-allocated the clone */
1827 if(containsAnyOtherByte(buffer[0], (int32_t)sizeof(buffer), 0xaa)) {
1828 log_err("cloning %s used the heap (bufferSize %d, requested %d) but overwrote stack buffer bytes\n",
1829 names[index], bufferSize, bufferSizes[j]);
1830 }
1831 }
1832
1833 pCharBuffer = charBuffer;
1834 pUniBuffer = uniBuffer;
1835
1836 ucnv_fromUnicode(cnv2,
1837 &pCharBuffer,
1838 charBufferLimit,
1839 &pUniBuffer,
1840 uniBufferLimit,
1841 NULL,
1842 TRUE,
1843 &err);
1844 if(U_FAILURE(err)){
1845 log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err));
1846 }
1847 ucnv_toUnicode(cnv2,
1848 &pUCharTarget,
1849 pUCharTargetLimit,
1850 &pCharSource,
1851 pCharSourceLimit,
1852 NULL,
1853 TRUE,
1854 &err
1855 );
1856
1857 if(U_FAILURE(err)){
1858 log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err));
1859 }
1860
1861 pConstCharBuffer = charBuffer;
1862 if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err))
1863 {
1864 log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err));
1865 }
1866 ucnv_close(cnv2);
1867 }
1868 }
1869
1870 log_verbose("ucnv_safeClone(): sizeof(UConverter)=%lu max preflighted clone size=%d (%s) U_CNV_SAFECLONE_BUFFERSIZE=%d\n",
1871 sizeof(UConverter), maxBufferSize, maxName, (int)U_CNV_SAFECLONE_BUFFERSIZE);
1872 }
1873
1874 static void TestCCSID() {
1875 UConverter *cnv;
1876 UErrorCode errorCode;
1877 int32_t ccsids[]={ 37, 850, 943, 949, 950, 1047, 1252, 1392, 33722 };
1878 int32_t i, ccsid;
1879
1880 for(i=0; i<(int32_t)(sizeof(ccsids)/sizeof(int32_t)); ++i) {
1881 ccsid=ccsids[i];
1882
1883 errorCode=U_ZERO_ERROR;
1884 cnv=ucnv_openCCSID(ccsid, UCNV_IBM, &errorCode);
1885 if(U_FAILURE(errorCode)) {
1886 log_data_err("error: ucnv_openCCSID(%ld) failed (%s)\n", ccsid, u_errorName(errorCode));
1887 continue;
1888 }
1889
1890 if(ccsid!=ucnv_getCCSID(cnv, &errorCode)) {
1891 log_err("error: ucnv_getCCSID(ucnv_openCCSID(%ld))=%ld\n", ccsid, ucnv_getCCSID(cnv, &errorCode));
1892 }
1893
1894 /* skip gb18030(ccsid 1392) */
1895 if(ccsid != 1392 && UCNV_IBM!=ucnv_getPlatform(cnv, &errorCode)) {
1896 log_err("error: ucnv_getPlatform(ucnv_openCCSID(%ld))=%ld!=UCNV_IBM\n", ccsid, ucnv_getPlatform(cnv, &errorCode));
1897 }
1898
1899 ucnv_close(cnv);
1900 }
1901 }
1902
1903 /* jitterbug 932: ucnv_convert() bugs --------------------------------------- */
1904
1905 /* CHUNK_SIZE defined in common\ucnv.c: */
1906 #define CHUNK_SIZE 1024
1907
1908 static void bug1(void);
1909 static void bug2(void);
1910 static void bug3(void);
1911
1912 static void
1913 TestJ932(void)
1914 {
1915 bug1(); /* Unicode intermediate buffer straddle bug */
1916 bug2(); /* pre-flighting size incorrect caused by simple overflow */
1917 bug3(); /* pre-flighting size incorrect caused by expansion overflow */
1918 }
1919
1920 /*
1921 * jitterbug 932: test chunking boundary conditions in
1922
1923 int32_t ucnv_convert(const char *toConverterName,
1924 const char *fromConverterName,
1925 char *target,
1926 int32_t targetSize,
1927 const char *source,
1928 int32_t sourceSize,
1929 UErrorCode * err)
1930
1931 * See discussions on the icu mailing list in
1932 * 2001-April with the subject "converter 'flush' question".
1933 *
1934 * Bug report and test code provided by Edward J. Batutis.
1935 */
1936 static void bug1()
1937 {
1938 static char char_in[CHUNK_SIZE+32];
1939 static char char_out[CHUNK_SIZE*2];
1940
1941 /* GB 18030 equivalent of U+10000 is 90308130 */
1942 static const char test_seq[]={ (char)0x90u, 0x30, (char)0x81u, 0x30 };
1943
1944 UErrorCode err = U_ZERO_ERROR;
1945 int32_t i, test_seq_len = sizeof(test_seq);
1946
1947 /*
1948 * causes straddle bug in Unicode intermediate buffer by sliding the test sequence forward
1949 * until the straddle bug appears. I didn't want to hard-code everything so this test could
1950 * be expanded - however this is the only type of straddle bug I can think of at the moment -
1951 * a high surrogate in the last position of the Unicode intermediate buffer. Apparently no
1952 * other Unicode sequences cause a bug since combining sequences are not supported by the
1953 * converters.
1954 */
1955
1956 for (i = test_seq_len; i >= 0; i--) {
1957 /* put character sequence into input buffer */
1958 memset(char_in, 0x61, sizeof(char_in)); /* GB 18030 'a' */
1959 memcpy(char_in + (CHUNK_SIZE - i), test_seq, test_seq_len);
1960
1961 /* do the conversion */
1962 ucnv_convert("us-ascii", /* out */
1963 "gb18030", /* in */
1964 char_out,
1965 sizeof(char_out),
1966 char_in,
1967 sizeof(char_in),
1968 &err);
1969
1970 /* bug1: */
1971 if (err == U_TRUNCATED_CHAR_FOUND) {
1972 /* this happens when surrogate pair straddles the intermediate buffer in
1973 * T_UConverter_fromCodepageToCodepage */
1974 log_err("error j932 bug 1: expected success, got U_TRUNCATED_CHAR_FOUND\n");
1975 }
1976 }
1977 }
1978
1979 /* bug2: pre-flighting loop bug: simple overflow causes bug */
1980 static void bug2()
1981 {
1982 /* US-ASCII "1234567890" */
1983 static const char source[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
1984 static const char sourceUTF8[]={ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, (char)0xef, (char)0x80, (char)0x80 };
1985 static const char sourceUTF32[]={ 0x00, 0x00, 0x00, 0x30,
1986 0x00, 0x00, 0x00, 0x31,
1987 0x00, 0x00, 0x00, 0x32,
1988 0x00, 0x00, 0x00, 0x33,
1989 0x00, 0x00, 0x00, 0x34,
1990 0x00, 0x00, 0x00, 0x35,
1991 0x00, 0x00, 0x00, 0x36,
1992 0x00, 0x00, 0x00, 0x37,
1993 0x00, 0x00, 0x00, 0x38,
1994 0x00, 0x00, (char)0xf0, 0x00};
1995 static char target[5];
1996
1997 UErrorCode err = U_ZERO_ERROR;
1998 int32_t size;
1999
2000 /* do the conversion */
2001 size = ucnv_convert("iso-8859-1", /* out */
2002 "us-ascii", /* in */
2003 target,
2004 sizeof(target),
2005 source,
2006 sizeof(source),
2007 &err);
2008
2009 if ( size != 10 ) {
2010 /* bug2: size is 5, should be 10 */
2011 log_data_err("error j932 bug 2 us-ascii->iso-8859-1: got preflighting size %d instead of 10\n", size);
2012 }
2013
2014 err = U_ZERO_ERROR;
2015 /* do the conversion */
2016 size = ucnv_convert("UTF-32BE", /* out */
2017 "UTF-8", /* in */
2018 target,
2019 sizeof(target),
2020 sourceUTF8,
2021 sizeof(sourceUTF8),
2022 &err);
2023
2024 if ( size != 32 ) {
2025 /* bug2: size is 5, should be 32 */
2026 log_err("error j932 bug 2 UTF-8->UTF-32BE: got preflighting size %d instead of 32\n", size);
2027 }
2028
2029 err = U_ZERO_ERROR;
2030 /* do the conversion */
2031 size = ucnv_convert("UTF-8", /* out */
2032 "UTF-32BE", /* in */
2033 target,
2034 sizeof(target),
2035 sourceUTF32,
2036 sizeof(sourceUTF32),
2037 &err);
2038
2039 if ( size != 12 ) {
2040 /* bug2: size is 5, should be 12 */
2041 log_err("error j932 bug 2 UTF-32BE->UTF-8: got preflighting size %d instead of 12\n", size);
2042 }
2043 }
2044
2045 /*
2046 * bug3: when the characters expand going from source to target codepage
2047 * you get bug3 in addition to bug2
2048 */
2049 static void bug3()
2050 {
2051 static char char_in[CHUNK_SIZE*4];
2052 static char target[5];
2053 UErrorCode err = U_ZERO_ERROR;
2054 int32_t size;
2055
2056 /*
2057 * first get the buggy size from bug2 then
2058 * compare it to buggy size with an expansion
2059 */
2060 memset(char_in, 0x61, sizeof(char_in)); /* US-ASCII 'a' */
2061
2062 /* do the conversion */
2063 size = ucnv_convert("lmbcs", /* out */
2064 "us-ascii", /* in */
2065 target,
2066 sizeof(target),
2067 char_in,
2068 sizeof(char_in),
2069 &err);
2070
2071 if ( size != sizeof(char_in) ) {
2072 /*
2073 * bug2: size is 0x2805 (CHUNK_SIZE*2+5 - maybe 5 is the size of the overflow buffer
2074 * in the converter?), should be CHUNK_SIZE*4
2075 *
2076 * Markus 2001-05-18: 5 is the size of our target[] here, ucnv_convert() did not reset targetSize...
2077 */
2078 log_data_err("error j932 bug 2/3a: expected preflighting size 0x%04x, got 0x%04x\n", sizeof(char_in), size);
2079 }
2080
2081 /*
2082 * now do the conversion with expansion
2083 * ascii 0x08 expands to 0x0F 0x28 in lmbcs
2084 */
2085 memset(char_in, 8, sizeof(char_in));
2086 err = U_ZERO_ERROR;
2087
2088 /* do the conversion */
2089 size = ucnv_convert("lmbcs", /* out */
2090 "us-ascii", /* in */
2091 target,
2092 sizeof(target),
2093 char_in,
2094 sizeof(char_in),
2095 &err);
2096
2097 /* expect 2X expansion */
2098 if ( size != sizeof(char_in) * 2 ) {
2099 /*
2100 * bug3:
2101 * bug2 would lead us to expect 0x2805, but it isn't that either, it is 0x3c05:
2102 */
2103 log_data_err("error j932 bug 3b: expected 0x%04x, got 0x%04x\n", sizeof(char_in) * 2, size);
2104 }
2105 }
2106
2107 static void
2108 convertExStreaming(UConverter *srcCnv, UConverter *targetCnv,
2109 const char *src, int32_t srcLength,
2110 const char *expectTarget, int32_t expectTargetLength,
2111 int32_t chunkSize,
2112 const char *testName,
2113 UErrorCode expectCode) {
2114 UChar pivotBuffer[CHUNK_SIZE];
2115 UChar *pivotSource, *pivotTarget;
2116 const UChar *pivotLimit;
2117
2118 char targetBuffer[CHUNK_SIZE];
2119 char *target;
2120 const char *srcLimit, *finalSrcLimit, *targetLimit;
2121
2122 int32_t targetLength;
2123
2124 UBool flush;
2125
2126 UErrorCode errorCode;
2127
2128 /* setup */
2129 if(chunkSize>CHUNK_SIZE) {
2130 chunkSize=CHUNK_SIZE;
2131 }
2132
2133 pivotSource=pivotTarget=pivotBuffer;
2134 pivotLimit=pivotBuffer+chunkSize;
2135
2136 finalSrcLimit=src+srcLength;
2137 target=targetBuffer;
2138 targetLimit=targetBuffer+chunkSize;
2139
2140 ucnv_resetToUnicode(srcCnv);
2141 ucnv_resetFromUnicode(targetCnv);
2142
2143 errorCode=U_ZERO_ERROR;
2144 flush=FALSE;
2145
2146 /* convert, streaming-style (both converters and pivot keep state) */
2147 for(;;) {
2148 /* for testing, give ucnv_convertEx() at most <chunkSize> input/pivot/output units at a time */
2149 if(src+chunkSize<=finalSrcLimit) {
2150 srcLimit=src+chunkSize;
2151 } else {
2152 srcLimit=finalSrcLimit;
2153 }
2154 ucnv_convertEx(targetCnv, srcCnv,
2155 &target, targetLimit,
2156 &src, srcLimit,
2157 pivotBuffer, &pivotSource, &pivotTarget, pivotLimit,
2158 FALSE, flush, &errorCode);
2159 targetLength=(int32_t)(target-targetBuffer);
2160 if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
2161 /* continue converting another chunk */
2162 errorCode=U_ZERO_ERROR;
2163 if(targetLength+chunkSize<=sizeof(targetBuffer)) {
2164 targetLimit=target+chunkSize;
2165 } else {
2166 targetLimit=targetBuffer+sizeof(targetBuffer);
2167 }
2168 } else if(U_FAILURE(errorCode)) {
2169 /* failure */
2170 break;
2171 } else if(flush) {
2172 /* all done */
2173 break;
2174 } else if(src==finalSrcLimit && pivotSource==pivotTarget) {
2175 /* all consumed, now flush without input (separate from conversion for testing) */
2176 flush=TRUE;
2177 }
2178 }
2179
2180 if(!(errorCode==expectCode || (expectCode==U_ZERO_ERROR && errorCode==U_STRING_NOT_TERMINATED_WARNING))) {
2181 log_err("ucnv_convertEx(%s) chunk[%d] results in %s instead of %s\n",
2182 testName, chunkSize, u_errorName(errorCode), u_errorName(expectCode));
2183 } else if(targetLength!=expectTargetLength) {
2184 log_err("ucnv_convertEx(%s) chunk[%d] writes %d bytes instead of %d\n",
2185 testName, chunkSize, targetLength, expectTargetLength);
2186 } else if(memcmp(targetBuffer, expectTarget, targetLength)!=0) {
2187 log_err("ucnv_convertEx(%s) chunk[%d] writes different bytes than expected\n",
2188 testName, chunkSize);
2189 }
2190 }
2191
2192 static void
2193 convertExMultiStreaming(UConverter *srcCnv, UConverter *targetCnv,
2194 const char *src, int32_t srcLength,
2195 const char *expectTarget, int32_t expectTargetLength,
2196 const char *testName,
2197 UErrorCode expectCode) {
2198 convertExStreaming(srcCnv, targetCnv,
2199 src, srcLength,
2200 expectTarget, expectTargetLength,
2201 1, testName, expectCode);
2202 convertExStreaming(srcCnv, targetCnv,
2203 src, srcLength,
2204 expectTarget, expectTargetLength,
2205 3, testName, expectCode);
2206 convertExStreaming(srcCnv, targetCnv,
2207 src, srcLength,
2208 expectTarget, expectTargetLength,
2209 7, testName, expectCode);
2210 }
2211
2212 static void TestConvertEx() {
2213 static const uint8_t
2214 utf8[]={
2215 /* 4e00 30a1 ff61 0410 */
2216 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2217 },
2218 shiftJIS[]={
2219 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2220 },
2221 errorTarget[]={
2222 /*
2223 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2224 * SUB, SUB, 0x40, SUB, SUB, 0x40
2225 */
2226 0xfc, 0xfc, 0xfc, 0xfc, 0x40, 0xfc, 0xfc, 0xfc, 0xfc, 0x40
2227 };
2228
2229 char srcBuffer[100], targetBuffer[100];
2230
2231 const char *src;
2232 char *target;
2233
2234 UChar pivotBuffer[100];
2235 UChar *pivotSource, *pivotTarget;
2236
2237 UConverter *cnv1, *cnv2;
2238 UErrorCode errorCode;
2239
2240 errorCode=U_ZERO_ERROR;
2241 cnv1=ucnv_open("UTF-8", &errorCode);
2242 if(U_FAILURE(errorCode)) {
2243 log_err("unable to open a UTF-8 converter - %s\n", u_errorName(errorCode));
2244 return;
2245 }
2246
2247 cnv2=ucnv_open("Shift-JIS", &errorCode);
2248 if(U_FAILURE(errorCode)) {
2249 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2250 ucnv_close(cnv1);
2251 return;
2252 }
2253
2254 /* test ucnv_convertEx() with streaming conversion style */
2255 convertExMultiStreaming(cnv1, cnv2,
2256 (const char *)utf8, sizeof(utf8), (const char *)shiftJIS, sizeof(shiftJIS),
2257 "UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2258
2259 convertExMultiStreaming(cnv2, cnv1,
2260 (const char *)shiftJIS, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8),
2261 "Shift-JIS -> UTF-8", U_ZERO_ERROR);
2262
2263 /* U_ZERO_ERROR because by default the SUB callbacks are set */
2264 convertExMultiStreaming(cnv1, cnv2,
2265 (const char *)shiftJIS, sizeof(shiftJIS), (const char *)errorTarget, sizeof(errorTarget),
2266 "shiftJIS[] UTF-8 -> Shift-JIS", U_ZERO_ERROR);
2267
2268 /* test some simple conversions */
2269
2270 /* NUL-terminated source and target */
2271 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2272 memcpy(srcBuffer, utf8, sizeof(utf8));
2273 srcBuffer[sizeof(utf8)]=0;
2274 src=srcBuffer;
2275 target=targetBuffer;
2276 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2277 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2278 if( errorCode!=U_ZERO_ERROR ||
2279 target-targetBuffer!=sizeof(shiftJIS) ||
2280 *target!=0 ||
2281 memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2282 ) {
2283 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s - writes %d bytes, expect %d\n",
2284 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2285 }
2286
2287 /* NUL-terminated source and U_STRING_NOT_TERMINATED_WARNING */
2288 errorCode=U_AMBIGUOUS_ALIAS_WARNING;
2289 memset(targetBuffer, 0xff, sizeof(targetBuffer));
2290 src=srcBuffer;
2291 target=targetBuffer;
2292 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(shiftJIS), &src, NULL,
2293 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2294 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2295 target-targetBuffer!=sizeof(shiftJIS) ||
2296 *target!=(char)0xff ||
2297 memcmp(targetBuffer, shiftJIS, sizeof(shiftJIS))!=0
2298 ) {
2299 log_err("ucnv_convertEx(simple UTF-8 -> Shift_JIS) fails: %s, expect U_STRING_NOT_TERMINATED_WARNING - writes %d bytes, expect %d\n",
2300 u_errorName(errorCode), target-targetBuffer, sizeof(shiftJIS));
2301 }
2302
2303 /* bad arguments */
2304 errorCode=U_MESSAGE_PARSE_ERROR;
2305 src=srcBuffer;
2306 target=targetBuffer;
2307 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2308 NULL, NULL, NULL, NULL, TRUE, TRUE, &errorCode);
2309 if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2310 log_err("ucnv_convertEx(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2311 }
2312
2313 /* pivotLimit==pivotStart */
2314 errorCode=U_ZERO_ERROR;
2315 pivotSource=pivotTarget=pivotBuffer;
2316 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2317 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer, TRUE, TRUE, &errorCode);
2318 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2319 log_err("ucnv_convertEx(pivotLimit==pivotStart) sets %s\n", u_errorName(errorCode));
2320 }
2321
2322 /* *pivotSource==NULL */
2323 errorCode=U_ZERO_ERROR;
2324 pivotSource=NULL;
2325 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2326 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2327 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2328 log_err("ucnv_convertEx(*pivotSource==NULL) sets %s\n", u_errorName(errorCode));
2329 }
2330
2331 /* *source==NULL */
2332 errorCode=U_ZERO_ERROR;
2333 src=NULL;
2334 pivotSource=pivotBuffer;
2335 ucnv_convertEx(cnv2, cnv1, &target, targetBuffer+sizeof(targetBuffer), &src, NULL,
2336 pivotBuffer, &pivotSource, &pivotTarget, pivotBuffer+1, TRUE, TRUE, &errorCode);
2337 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2338 log_err("ucnv_convertEx(*source==NULL) sets %s\n", u_errorName(errorCode));
2339 }
2340
2341 ucnv_close(cnv1);
2342 ucnv_close(cnv2);
2343 }
2344
2345 static void
2346 TestConvertAlgorithmic() {
2347 static const uint8_t
2348 utf8[]={
2349 /* 4e00 30a1 ff61 0410 */
2350 0xe4, 0xb8, 0x80, 0xe3, 0x82, 0xa1, 0xef, 0xbd, 0xa1, 0xd0, 0x90
2351 },
2352 shiftJIS[]={
2353 0x88, 0xea, 0x83, 0x40, 0xa1, 0x84, 0x40
2354 },
2355 /*errorTarget[]={*/
2356 /*
2357 * expected output when converting shiftJIS[] from UTF-8 to Shift-JIS:
2358 * SUB, SUB, 0x40, SUB, SUB, 0x40
2359 */
2360 /* 0x81, 0xa1, 0x81, 0xa1, 0x40, 0x81, 0xa1, 0x81, 0xa1, 0x40*/
2361 /*},*/
2362 utf16[]={
2363 0xfe, 0xff /* BOM only, no text */
2364 },
2365 utf32[]={
2366 0xff, 0xfe, 0, 0 /* BOM only, no text */
2367 };
2368
2369 char target[100], utf8NUL[100], shiftJISNUL[100];
2370
2371 UConverter *cnv;
2372 UErrorCode errorCode;
2373
2374 int32_t length;
2375
2376 errorCode=U_ZERO_ERROR;
2377 cnv=ucnv_open("Shift-JIS", &errorCode);
2378 if(U_FAILURE(errorCode)) {
2379 log_data_err("unable to open a Shift-JIS converter - %s\n", u_errorName(errorCode));
2380 ucnv_close(cnv);
2381 return;
2382 }
2383
2384 memcpy(utf8NUL, utf8, sizeof(utf8));
2385 utf8NUL[sizeof(utf8)]=0;
2386 memcpy(shiftJISNUL, shiftJIS, sizeof(shiftJIS));
2387 shiftJISNUL[sizeof(shiftJIS)]=0;
2388
2389 /*
2390 * The to/from algorithmic convenience functions share a common implementation,
2391 * so we need not test all permutations of them.
2392 */
2393
2394 /* length in, not terminated out */
2395 errorCode=U_ZERO_ERROR;
2396 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF8, target, sizeof(shiftJIS), (const char *)utf8, sizeof(utf8), &errorCode);
2397 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2398 length!=sizeof(shiftJIS) ||
2399 memcmp(target, shiftJIS, length)!=0
2400 ) {
2401 log_err("ucnv_fromAlgorithmic(UTF-8 -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect %d\n",
2402 u_errorName(errorCode), length, sizeof(shiftJIS));
2403 }
2404
2405 /* terminated in and out */
2406 memset(target, 0x55, sizeof(target));
2407 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2408 length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, -1, &errorCode);
2409 if( errorCode!=U_ZERO_ERROR ||
2410 length!=sizeof(utf8) ||
2411 memcmp(target, utf8, length)!=0
2412 ) {
2413 log_err("ucnv_toAlgorithmic(Shift-JIS -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect %d\n",
2414 u_errorName(errorCode), length, sizeof(shiftJIS));
2415 }
2416
2417 /* empty string, some target buffer */
2418 errorCode=U_STRING_NOT_TERMINATED_WARNING;
2419 length=ucnv_toAlgorithmic(UCNV_UTF8, cnv, target, sizeof(target), shiftJISNUL, 0, &errorCode);
2420 if( errorCode!=U_ZERO_ERROR ||
2421 length!=0
2422 ) {
2423 log_err("ucnv_toAlgorithmic(empty string -> UTF-8) fails (%s expect U_ZERO_ERROR), returns %d expect 0\n",
2424 u_errorName(errorCode), length);
2425 }
2426
2427 /* pseudo-empty string, no target buffer */
2428 errorCode=U_ZERO_ERROR;
2429 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2430 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2431 length!=0
2432 ) {
2433 log_err("ucnv_fromAlgorithmic(UTF-16 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2434 u_errorName(errorCode), length);
2435 }
2436
2437 errorCode=U_ZERO_ERROR;
2438 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF32, target, 0, (const char *)utf32, 4, &errorCode);
2439 if( errorCode!=U_STRING_NOT_TERMINATED_WARNING ||
2440 length!=0
2441 ) {
2442 log_err("ucnv_fromAlgorithmic(UTF-32 only BOM -> Shift-JIS) fails (%s expect U_STRING_NOT_TERMINATED_WARNING), returns %d expect 0\n",
2443 u_errorName(errorCode), length);
2444 }
2445
2446 /* bad arguments */
2447 errorCode=U_MESSAGE_PARSE_ERROR;
2448 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, (const char *)utf16, 2, &errorCode);
2449 if(errorCode!=U_MESSAGE_PARSE_ERROR) {
2450 log_err("ucnv_fromAlgorithmic(U_MESSAGE_PARSE_ERROR) sets %s\n", u_errorName(errorCode));
2451 }
2452
2453 /* source==NULL */
2454 errorCode=U_ZERO_ERROR;
2455 length=ucnv_fromAlgorithmic(cnv, UCNV_UTF16, target, 0, NULL, 2, &errorCode);
2456 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2457 log_err("ucnv_fromAlgorithmic(source==NULL) sets %s\n", u_errorName(errorCode));
2458 }
2459
2460 /* illegal alg. type */
2461 errorCode=U_ZERO_ERROR;
2462 length=ucnv_fromAlgorithmic(cnv, (UConverterType)99, target, 0, (const char *)utf16, 2, &errorCode);
2463 if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
2464 log_err("ucnv_fromAlgorithmic(illegal alg. type) sets %s\n", u_errorName(errorCode));
2465 }
2466 ucnv_close(cnv);
2467 }
2468
2469 static void TestLMBCSMaxChar(void) {
2470 static const struct {
2471 int8_t maxSize;
2472 const char *name;
2473 } converter[] = {
2474 /* some non-LMBCS converters - perfect test setup here */
2475 { 1, "US-ASCII"},
2476 { 1, "ISO-8859-1"},
2477
2478 { 2, "UTF-16"},
2479 { 2, "UTF-16BE"},
2480 { 3, "UTF-8"},
2481 { 3, "CESU-8"},
2482 { 3, "SCSU"},
2483 { 4, "UTF-32"},
2484 { 4, "UTF-7"},
2485 { 4, "IMAP-mailbox-name"},
2486 { 4, "BOCU-1"},
2487
2488 { 1, "windows-1256"},
2489 { 2, "Shift-JIS"},
2490 { 2, "ibm-16684"},
2491 { 3, "ibm-930"},
2492 { 3, "ibm-1390"},
2493 { 4, "*test3"},
2494 { 16,"*test4"},
2495
2496 { 4, "ISCII"},
2497 { 4, "HZ"},
2498
2499 { 3, "ISO-2022"},
2500 { 3, "ISO-2022-KR"},
2501 { 6, "ISO-2022-JP"},
2502 { 8, "ISO-2022-CN"},
2503
2504 /* LMBCS */
2505 { 3, "LMBCS-1"},
2506 { 3, "LMBCS-2"},
2507 { 3, "LMBCS-3"},
2508 { 3, "LMBCS-4"},
2509 { 3, "LMBCS-5"},
2510 { 3, "LMBCS-6"},
2511 { 3, "LMBCS-8"},
2512 { 3, "LMBCS-11"},
2513 { 3, "LMBCS-16"},
2514 { 3, "LMBCS-17"},
2515 { 3, "LMBCS-18"},
2516 { 3, "LMBCS-19"}
2517 };
2518 int32_t idx;
2519
2520 for (idx = 0; idx < LENGTHOF(converter); idx++) {
2521 UErrorCode status = U_ZERO_ERROR;
2522 UConverter *cnv = cnv_open(converter[idx].name, &status);
2523 if (U_FAILURE(status)) {
2524 continue;
2525 }
2526 if (converter[idx].maxSize != ucnv_getMaxCharSize(cnv)) {
2527 log_err("error: ucnv_getMaxCharSize(%s) expected %d, got %d\n",
2528 converter[idx].name, converter[idx].maxSize, ucnv_getMaxCharSize(cnv));
2529 }
2530 ucnv_close(cnv);
2531 }
2532
2533 /* mostly test that the macro compiles */
2534 if(UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10) {
2535 log_err("error UCNV_GET_MAX_BYTES_FOR_STRING(1, 2)<10\n");
2536 }
2537 }
2538
2539
2540 static void TestJ1968(void) {
2541 UErrorCode err = U_ZERO_ERROR;
2542 UConverter *cnv;
2543 char myConvName[] = "My really really really really really really really really really really really"
2544 " really really really really really really really really really really really"
2545 " really really really really really really really really long converter name";
2546 UChar myConvNameU[sizeof(myConvName)];
2547
2548 u_charsToUChars(myConvName, myConvNameU, sizeof(myConvName));
2549
2550 err = U_ZERO_ERROR;
2551 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH+1] = 0;
2552 cnv = ucnv_openU(myConvNameU, &err);
2553 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2554 log_err("1U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2555 }
2556
2557 err = U_ZERO_ERROR;
2558 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
2559 cnv = ucnv_openU(myConvNameU, &err);
2560 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2561 log_err("2U) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2562 }
2563
2564 err = U_ZERO_ERROR;
2565 myConvNameU[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
2566 cnv = ucnv_openU(myConvNameU, &err);
2567 if (cnv || err != U_FILE_ACCESS_ERROR) {
2568 log_err("3U) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2569 }
2570
2571
2572
2573
2574 err = U_ZERO_ERROR;
2575 cnv = ucnv_open(myConvName, &err);
2576 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2577 log_err("1) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2578 }
2579
2580 err = U_ZERO_ERROR;
2581 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = ',';
2582 cnv = ucnv_open(myConvName, &err);
2583 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2584 log_err("2) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2585 }
2586
2587 err = U_ZERO_ERROR;
2588 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2589 cnv = ucnv_open(myConvName, &err);
2590 if (cnv || err != U_FILE_ACCESS_ERROR) {
2591 log_err("3) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2592 }
2593
2594 err = U_ZERO_ERROR;
2595 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ',';
2596 strncpy(myConvName + UCNV_MAX_CONVERTER_NAME_LENGTH, "locale=", 7);
2597 cnv = ucnv_open(myConvName, &err);
2598 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2599 log_err("4) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2600 }
2601
2602 /* The comma isn't really a part of the converter name. */
2603 err = U_ZERO_ERROR;
2604 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH] = 0;
2605 cnv = ucnv_open(myConvName, &err);
2606 if (cnv || err != U_FILE_ACCESS_ERROR) {
2607 log_err("5) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2608 }
2609
2610 err = U_ZERO_ERROR;
2611 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = ' ';
2612 cnv = ucnv_open(myConvName, &err);
2613 if (cnv || err != U_ILLEGAL_ARGUMENT_ERROR) {
2614 log_err("6) Didn't get U_ILLEGAL_ARGUMENT_ERROR as expected %s\n", u_errorName(err));
2615 }
2616
2617 err = U_ZERO_ERROR;
2618 myConvName[UCNV_MAX_CONVERTER_NAME_LENGTH-1] = 0;
2619 cnv = ucnv_open(myConvName, &err);
2620 if (cnv || err != U_FILE_ACCESS_ERROR) {
2621 log_err("7) Didn't get U_FILE_ACCESS_ERROR as expected %s\n", u_errorName(err));
2622 }
2623
2624 }
2625
2626 static void
2627 testSwap(const char *name, UBool swap) {
2628 /*
2629 * Test Unicode text.
2630 * Contains characters that are the highest for some of the
2631 * tested conversions, to make sure that the ucnvmbcs.c code that modifies the
2632 * tables copies the entire tables.
2633 */
2634 static const UChar text[]={
2635 0x61, 0xd, 0x62, 0xa, 0x4e00, 0x3000, 0xfffd, 0xa, 0x20, 0x85, 0xff5e, 0x7a
2636 };
2637
2638 UChar uNormal[32], uSwapped[32];
2639 char normal[32], swapped[32];
2640 const UChar *pcu;
2641 UChar *pu;
2642 char *pc;
2643 int32_t i, normalLength, swappedLength;
2644 UChar u;
2645 char c;
2646
2647 const char *swappedName;
2648 UConverter *cnv, *swapCnv;
2649 UErrorCode errorCode;
2650
2651 /* if the swap flag is FALSE, then the test encoding is not EBCDIC and must not swap */
2652
2653 /* open both the normal and the LF/NL-swapping converters */
2654 strcpy(swapped, name);
2655 strcat(swapped, UCNV_SWAP_LFNL_OPTION_STRING);
2656
2657 errorCode=U_ZERO_ERROR;
2658 swapCnv=ucnv_open(swapped, &errorCode);
2659 cnv=ucnv_open(name, &errorCode);
2660 if(U_FAILURE(errorCode)) {
2661 log_data_err("TestEBCDICSwapLFNL error: unable to open %s or %s (%s)\n", name, swapped, u_errorName(errorCode));
2662 goto cleanup;
2663 }
2664
2665 /* the name must contain the swap option if and only if we expect the converter to swap */
2666 swappedName=ucnv_getName(swapCnv, &errorCode);
2667 if(U_FAILURE(errorCode)) {
2668 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl) failed (%s)\n", name, u_errorName(errorCode));
2669 goto cleanup;
2670 }
2671
2672 pc=strstr(swappedName, UCNV_SWAP_LFNL_OPTION_STRING);
2673 if(swap != (pc!=NULL)) {
2674 log_err("TestEBCDICSwapLFNL error: ucnv_getName(%s,swaplfnl)=%s should (%d) contain 'swaplfnl'\n", name, swappedName, swap);
2675 goto cleanup;
2676 }
2677
2678 /* convert to EBCDIC */
2679 pcu=text;
2680 pc=normal;
2681 ucnv_fromUnicode(cnv, &pc, normal+LENGTHOF(normal), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode);
2682 normalLength=(int32_t)(pc-normal);
2683
2684 pcu=text;
2685 pc=swapped;
2686 ucnv_fromUnicode(swapCnv, &pc, swapped+LENGTHOF(swapped), &pcu, text+LENGTHOF(text), NULL, TRUE, &errorCode);
2687 swappedLength=(int32_t)(pc-swapped);
2688
2689 if(U_FAILURE(errorCode)) {
2690 log_err("TestEBCDICSwapLFNL error converting to %s - (%s)\n", name, u_errorName(errorCode));
2691 goto cleanup;
2692 }
2693
2694 /* compare EBCDIC output */
2695 if(normalLength!=swappedLength) {
2696 log_err("TestEBCDICSwapLFNL error converting to %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
2697 goto cleanup;
2698 }
2699 for(i=0; i<normalLength; ++i) {
2700 /* swap EBCDIC LF/NL for comparison */
2701 c=normal[i];
2702 if(swap) {
2703 if(c==0x15) {
2704 c=0x25;
2705 } else if(c==0x25) {
2706 c=0x15;
2707 }
2708 }
2709
2710 if(c!=swapped[i]) {
2711 log_err("TestEBCDICSwapLFNL error converting to %s - did not swap properly, output[%d]=0x%02x\n", name, i, (uint8_t)swapped[i]);
2712 goto cleanup;
2713 }
2714 }
2715
2716 /* convert back to Unicode (may not roundtrip) */
2717 pc=normal;
2718 pu=uNormal;
2719 ucnv_toUnicode(cnv, &pu, uNormal+LENGTHOF(uNormal), (const char **)&pc, normal+normalLength, NULL, TRUE, &errorCode);
2720 normalLength=(int32_t)(pu-uNormal);
2721
2722 pc=normal;
2723 pu=uSwapped;
2724 ucnv_toUnicode(swapCnv, &pu, uSwapped+LENGTHOF(uSwapped), (const char **)&pc, normal+swappedLength, NULL, TRUE, &errorCode);
2725 swappedLength=(int32_t)(pu-uSwapped);
2726
2727 if(U_FAILURE(errorCode)) {
2728 log_err("TestEBCDICSwapLFNL error converting from %s - (%s)\n", name, u_errorName(errorCode));
2729 goto cleanup;
2730 }
2731
2732 /* compare EBCDIC output */
2733 if(normalLength!=swappedLength) {
2734 log_err("TestEBCDICSwapLFNL error converting from %s - output lengths %d vs. %d\n", name, normalLength, swappedLength);
2735 goto cleanup;
2736 }
2737 for(i=0; i<normalLength; ++i) {
2738 /* swap EBCDIC LF/NL for comparison */
2739 u=uNormal[i];
2740 if(swap) {
2741 if(u==0xa) {
2742 u=0x85;
2743 } else if(u==0x85) {
2744 u=0xa;
2745 }
2746 }
2747
2748 if(u!=uSwapped[i]) {
2749 log_err("TestEBCDICSwapLFNL error converting from %s - did not swap properly, output[%d]=U+%04x\n", name, i, uSwapped[i]);
2750 goto cleanup;
2751 }
2752 }
2753
2754 /* clean up */
2755 cleanup:
2756 ucnv_close(cnv);
2757 ucnv_close(swapCnv);
2758 }
2759
2760 static void
2761 TestEBCDICSwapLFNL() {
2762 static const struct {
2763 const char *name;
2764 UBool swap;
2765 } tests[]={
2766 { "ibm-37", TRUE },
2767 { "ibm-1047", TRUE },
2768 { "ibm-1140", TRUE },
2769 { "ibm-930", TRUE },
2770 { "iso-8859-3", FALSE }
2771 };
2772
2773 int i;
2774
2775 for(i=0; i<LENGTHOF(tests); ++i) {
2776 testSwap(tests[i].name, tests[i].swap);
2777 }
2778 }