OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * Copyright (C) 1997-2009, International Business Machines |
| 4 * Corporation and others. All Rights Reserved. |
| 5 ******************************************************************************* |
| 6 * Date Name Description |
| 7 * 06/23/00 aliu Creation. |
| 8 ******************************************************************************* |
| 9 */ |
| 10 |
| 11 #include "unicode/utypes.h" |
| 12 |
| 13 #if !UCONFIG_NO_TRANSLITERATION |
| 14 |
| 15 #include <stdlib.h> |
| 16 #include <string.h> |
| 17 #include "unicode/utrans.h" |
| 18 #include "unicode/ustring.h" |
| 19 #include "cintltst.h" |
| 20 |
| 21 #define TEST(x) addTest(root, &x, "utrans/" # x) |
| 22 |
| 23 static void TestAPI(void); |
| 24 static void TestSimpleRules(void); |
| 25 static void TestFilter(void); |
| 26 static void TestOpenInverse(void); |
| 27 static void TestClone(void); |
| 28 static void TestRegisterUnregister(void); |
| 29 static void TestExtractBetween(void); |
| 30 static void TestUnicodeIDs(void); |
| 31 |
| 32 static void _expectRules(const char*, const char*, const char*); |
| 33 static void _expect(const UTransliterator* trans, const char* cfrom, const char*
cto); |
| 34 |
| 35 void addUTransTest(TestNode** root); |
| 36 |
| 37 |
| 38 void |
| 39 addUTransTest(TestNode** root) { |
| 40 TEST(TestAPI); |
| 41 TEST(TestSimpleRules); |
| 42 TEST(TestFilter); |
| 43 TEST(TestOpenInverse); |
| 44 TEST(TestClone); |
| 45 TEST(TestRegisterUnregister); |
| 46 TEST(TestExtractBetween); |
| 47 TEST(TestUnicodeIDs); |
| 48 } |
| 49 |
| 50 /*------------------------------------------------------------------ |
| 51 * Replaceable glue |
| 52 * |
| 53 * To test the Replaceable glue we have to dummy up a C-based |
| 54 * Replaceable callback. This code is for testing purposes only. |
| 55 *------------------------------------------------------------------*/ |
| 56 |
| 57 typedef struct XReplaceable { |
| 58 UChar* text; /* MUST BE null-terminated */ |
| 59 } XReplaceable; |
| 60 |
| 61 static void InitXReplaceable(XReplaceable* rep, const char* cstring) { |
| 62 rep->text = malloc(sizeof(UChar) * (strlen(cstring)+1)); |
| 63 u_uastrcpy(rep->text, cstring); |
| 64 } |
| 65 |
| 66 static void FreeXReplaceable(XReplaceable* rep) { |
| 67 if (rep->text != NULL) { |
| 68 free(rep->text); |
| 69 rep->text = NULL; |
| 70 } |
| 71 } |
| 72 |
| 73 /* UReplaceableCallbacks callback */ |
| 74 static int32_t Xlength(const UReplaceable* rep) { |
| 75 const XReplaceable* x = (const XReplaceable*)rep; |
| 76 return u_strlen(x->text); |
| 77 } |
| 78 |
| 79 /* UReplaceableCallbacks callback */ |
| 80 static UChar XcharAt(const UReplaceable* rep, int32_t offset) { |
| 81 const XReplaceable* x = (const XReplaceable*)rep; |
| 82 return x->text[offset]; |
| 83 } |
| 84 |
| 85 /* UReplaceableCallbacks callback */ |
| 86 static UChar32 Xchar32At(const UReplaceable* rep, int32_t offset) { |
| 87 const XReplaceable* x = (const XReplaceable*)rep; |
| 88 return x->text[offset]; |
| 89 } |
| 90 |
| 91 /* UReplaceableCallbacks callback */ |
| 92 static void Xreplace(UReplaceable* rep, int32_t start, int32_t limit, |
| 93 const UChar* text, int32_t textLength) { |
| 94 XReplaceable* x = (XReplaceable*)rep; |
| 95 int32_t newLen = Xlength(rep) + limit - start + textLength; |
| 96 UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); |
| 97 u_strncpy(newText, x->text, start); |
| 98 u_strncpy(newText + start, text, textLength); |
| 99 u_strcpy(newText + start + textLength, x->text + limit); |
| 100 free(x->text); |
| 101 x->text = newText; |
| 102 } |
| 103 |
| 104 /* UReplaceableCallbacks callback */ |
| 105 static void Xcopy(UReplaceable* rep, int32_t start, int32_t limit, int32_t dest)
{ |
| 106 XReplaceable* x = (XReplaceable*)rep; |
| 107 int32_t newLen = Xlength(rep) + limit - start; |
| 108 UChar* newText = (UChar*) malloc(sizeof(UChar) * (newLen+1)); |
| 109 u_strncpy(newText, x->text, dest); |
| 110 u_strncpy(newText + dest, x->text + start, limit - start); |
| 111 u_strcpy(newText + dest + limit - start, x->text + dest); |
| 112 free(x->text); |
| 113 x->text = newText; |
| 114 } |
| 115 |
| 116 /* UReplaceableCallbacks callback */ |
| 117 static void Xextract(UReplaceable* rep, int32_t start, int32_t limit, UChar* dst
) { |
| 118 XReplaceable* x = (XReplaceable*)rep; |
| 119 int32_t len = limit - start; |
| 120 u_strncpy(dst, x->text, len); |
| 121 } |
| 122 |
| 123 static void InitXReplaceableCallbacks(UReplaceableCallbacks* callbacks) { |
| 124 callbacks->length = Xlength; |
| 125 callbacks->charAt = XcharAt; |
| 126 callbacks->char32At = Xchar32At; |
| 127 callbacks->replace = Xreplace; |
| 128 callbacks->extract = Xextract; |
| 129 callbacks->copy = Xcopy; |
| 130 } |
| 131 |
| 132 /*------------------------------------------------------------------ |
| 133 * Tests |
| 134 *------------------------------------------------------------------*/ |
| 135 |
| 136 static void TestAPI() { |
| 137 enum { BUF_CAP = 128 }; |
| 138 char buf[BUF_CAP], buf2[BUF_CAP]; |
| 139 UErrorCode status = U_ZERO_ERROR; |
| 140 UTransliterator* trans = NULL; |
| 141 int32_t i, n; |
| 142 |
| 143 /* Test getAvailableIDs */ |
| 144 n = utrans_countAvailableIDs(); |
| 145 if (n < 1) { |
| 146 log_err("FAIL: utrans_countAvailableIDs() returned %d\n", n); |
| 147 } else { |
| 148 log_verbose("System ID count: %d\n", n); |
| 149 } |
| 150 for (i=0; i<n; ++i) { |
| 151 utrans_getAvailableID(i, buf, BUF_CAP); |
| 152 if (*buf == 0) { |
| 153 log_err("FAIL: System transliterator %d: \"\"\n", i); |
| 154 } else { |
| 155 log_verbose("System transliterator %d: \"%s\"\n", i, buf); |
| 156 } |
| 157 } |
| 158 |
| 159 /* Test open */ |
| 160 utrans_getAvailableID(0, buf, BUF_CAP); |
| 161 trans = utrans_open(buf, UTRANS_FORWARD,NULL,0,NULL, &status); |
| 162 if (U_FAILURE(status)) { |
| 163 log_err("FAIL: utrans_open(%s) failed, error=%s\n", |
| 164 buf, u_errorName(status)); |
| 165 } |
| 166 |
| 167 else { |
| 168 /* Test getID */ |
| 169 utrans_getID(trans, buf2, BUF_CAP); |
| 170 if (0 != strcmp(buf, buf2)) { |
| 171 log_err("FAIL: utrans_getID(%s) returned %s\n", |
| 172 buf, buf2); |
| 173 } |
| 174 utrans_close(trans); |
| 175 } |
| 176 } |
| 177 |
| 178 static void TestUnicodeIDs() { |
| 179 UEnumeration *uenum; |
| 180 UTransliterator *utrans; |
| 181 const UChar *id, *id2; |
| 182 int32_t idLength, id2Length, count, count2; |
| 183 |
| 184 UErrorCode errorCode; |
| 185 |
| 186 errorCode=U_ZERO_ERROR; |
| 187 uenum=utrans_openIDs(&errorCode); |
| 188 if(U_FAILURE(errorCode)) { |
| 189 log_err("utrans_openIDs() failed - %s\n", u_errorName(errorCode)); |
| 190 return; |
| 191 } |
| 192 |
| 193 count=uenum_count(uenum, &errorCode); |
| 194 if(U_FAILURE(errorCode) || count<1) { |
| 195 log_err("uenum_count(transliterator IDs)=%d - %s\n", count, u_errorName(
errorCode)); |
| 196 } |
| 197 |
| 198 count=0; |
| 199 for(;;) { |
| 200 id=uenum_unext(uenum, &idLength, &errorCode); |
| 201 if(U_FAILURE(errorCode)) { |
| 202 log_err("uenum_unext(transliterator ID %d) failed - %s\n", count, u_
errorName(errorCode)); |
| 203 break; |
| 204 } |
| 205 if(id==NULL) { |
| 206 break; |
| 207 } |
| 208 |
| 209 if(++count>10) { |
| 210 /* try to actually open only a few transliterators */ |
| 211 continue; |
| 212 } |
| 213 |
| 214 utrans=utrans_openU(id, idLength, UTRANS_FORWARD, NULL, 0, NULL, &errorC
ode); |
| 215 if(U_FAILURE(errorCode)) { |
| 216 log_err("utrans_openU(%s) failed - %s\n", aescstrdup(id, idLength),
u_errorName(errorCode)); |
| 217 continue; |
| 218 } |
| 219 |
| 220 id2=utrans_getUnicodeID(utrans, &id2Length); |
| 221 if(idLength!=id2Length || 0!=u_memcmp(id, id2, idLength)) { |
| 222 log_err("utrans_getUnicodeID(%s) does not match the original ID\n",
aescstrdup(id, idLength)); |
| 223 } |
| 224 |
| 225 utrans_close(utrans); |
| 226 } |
| 227 |
| 228 uenum_reset(uenum, &errorCode); |
| 229 if(U_FAILURE(errorCode) || count<1) { |
| 230 log_err("uenum_reset(transliterator IDs) failed - %s\n", u_errorName(err
orCode)); |
| 231 } else { |
| 232 count2=uenum_count(uenum, &errorCode); |
| 233 if(U_FAILURE(errorCode) || count<1) { |
| 234 log_err("2nd uenum_count(transliterator IDs)=%d - %s\n", count2, u_e
rrorName(errorCode)); |
| 235 } else if(count!=count2) { |
| 236 log_err("uenum_unext(transliterator IDs) returned %d IDs but uenum_c
ount() after uenum_reset() claims there are %d\n", count, count2); |
| 237 } |
| 238 } |
| 239 |
| 240 uenum_close(uenum); |
| 241 } |
| 242 |
| 243 static void TestOpenInverse(){ |
| 244 UErrorCode status=U_ZERO_ERROR; |
| 245 UTransliterator* t1=NULL; |
| 246 UTransliterator* inverse1=NULL; |
| 247 enum { BUF_CAP = 128 }; |
| 248 char buf1[BUF_CAP]; |
| 249 int32_t i=0; |
| 250 |
| 251 const char TransID[][25]={ |
| 252 "Halfwidth-Fullwidth", |
| 253 "Fullwidth-Halfwidth", |
| 254 "Greek-Latin" , |
| 255 "Latin-Greek", |
| 256 /*"Arabic-Latin", // Removed in 2.0*/ |
| 257 /*"Latin-Arabic", // Removed in 2.0*/ |
| 258 "Katakana-Latin", |
| 259 "Latin-Katakana", |
| 260 /*"Hebrew-Latin", // Removed in 2.0*/ |
| 261 /*"Latin-Hebrew", // Removed in 2.0*/ |
| 262 "Cyrillic-Latin", |
| 263 "Latin-Cyrillic", |
| 264 "Devanagari-Latin", |
| 265 "Latin-Devanagari", |
| 266 "Any-Hex", |
| 267 "Hex-Any" |
| 268 }; |
| 269 |
| 270 for(i=0; i<sizeof(TransID)/sizeof(TransID[0]); i=i+2){ |
| 271 status = U_ZERO_ERROR; |
| 272 t1=utrans_open(TransID[i], UTRANS_FORWARD,NULL,0,NULL, &status); |
| 273 if(t1 == NULL || U_FAILURE(status)){ |
| 274 log_data_err("FAIL: in instantiation for id=%s -> %s (Are you missin
g data?)\n", TransID[i], u_errorName(status)); |
| 275 continue; |
| 276 } |
| 277 inverse1=utrans_openInverse(t1, &status); |
| 278 if(U_FAILURE(status)){ |
| 279 log_err("FAIL: utrans_openInverse() failed for id=%s. Error=%s\n", T
ransID[i], myErrorName(status)); |
| 280 continue; |
| 281 } |
| 282 utrans_getID(inverse1, buf1, BUF_CAP); |
| 283 if(strcmp(buf1, TransID[i+1]) != 0){ |
| 284 log_err("FAIL :openInverse() for %s returned %s instead of %s\n", Tr
ansID[i], buf1, TransID[i+1]); |
| 285 } |
| 286 utrans_close(t1); |
| 287 utrans_close(inverse1); |
| 288 } |
| 289 } |
| 290 |
| 291 static void TestClone(){ |
| 292 UErrorCode status=U_ZERO_ERROR; |
| 293 UTransliterator* t1=NULL; |
| 294 UTransliterator* t2=NULL; |
| 295 UTransliterator* t3=NULL; |
| 296 UTransliterator* t4=NULL; |
| 297 enum { BUF_CAP = 128 }; |
| 298 char buf1[BUF_CAP], buf2[BUF_CAP], buf3[BUF_CAP]; |
| 299 |
| 300 t1=utrans_open("Latin-Devanagari", UTRANS_FORWARD, NULL,0,NULL,&status); |
| 301 if(U_FAILURE(status)){ |
| 302 log_data_err("FAIL: construction -> %s (Are you missing data?)\n", u_err
orName(status)); |
| 303 return; |
| 304 } |
| 305 t2=utrans_open("Latin-Greek", UTRANS_FORWARD, NULL,0,NULL,&status); |
| 306 if(U_FAILURE(status)){ |
| 307 log_err("FAIL: construction\n"); |
| 308 utrans_close(t1); |
| 309 return; |
| 310 } |
| 311 |
| 312 t3=utrans_clone(t1, &status); |
| 313 t4=utrans_clone(t2, &status); |
| 314 |
| 315 utrans_getID(t1, buf1, BUF_CAP); |
| 316 utrans_getID(t2, buf2, BUF_CAP); |
| 317 utrans_getID(t3, buf3, BUF_CAP); |
| 318 |
| 319 if(strcmp(buf1, buf3) != 0 || |
| 320 strcmp(buf1, buf2) == 0) { |
| 321 log_err("FAIL: utrans_clone() failed\n"); |
| 322 } |
| 323 |
| 324 utrans_getID(t4, buf3, BUF_CAP); |
| 325 |
| 326 if(strcmp(buf2, buf3) != 0 || |
| 327 strcmp(buf1, buf3) == 0) { |
| 328 log_err("FAIL: utrans_clone() failed\n"); |
| 329 } |
| 330 |
| 331 utrans_close(t1); |
| 332 utrans_close(t2); |
| 333 utrans_close(t3); |
| 334 utrans_close(t4); |
| 335 |
| 336 } |
| 337 |
| 338 static void TestRegisterUnregister(){ |
| 339 UErrorCode status=U_ZERO_ERROR; |
| 340 UTransliterator* t1=NULL; |
| 341 UTransliterator* rules=NULL, *rules2; |
| 342 UTransliterator* inverse1=NULL; |
| 343 UChar rule[]={ 0x0061, 0x003c, 0x003e, 0x0063}; /*a<>b*/ |
| 344 |
| 345 U_STRING_DECL(ID, "TestA-TestB", 11); |
| 346 U_STRING_INIT(ID, "TestA-TestB", 11); |
| 347 |
| 348 /* Make sure it doesn't exist */ |
| 349 t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); |
| 350 if(t1 != NULL || U_SUCCESS(status)) { |
| 351 log_err("FAIL: TestA-TestB already registered\n"); |
| 352 return; |
| 353 } |
| 354 status=U_ZERO_ERROR; |
| 355 /* Check inverse too */ |
| 356 inverse1=utrans_open("TestA-TestB", UTRANS_REVERSE, NULL,0,NULL,&status); |
| 357 if(inverse1 != NULL || U_SUCCESS(status)) { |
| 358 log_err("FAIL: TestA-TestB already registered\n"); |
| 359 return; |
| 360 } |
| 361 status=U_ZERO_ERROR; |
| 362 /* Create it */ |
| 363 rules=utrans_open("TestA-TestB",UTRANS_FORWARD, rule, 4, NULL, &status); |
| 364 if(U_FAILURE(status)){ |
| 365 log_err("FAIL: utrans_openRules(a<>B) failed with error=%s\n", myErrorNa
me(status)); |
| 366 return; |
| 367 } |
| 368 |
| 369 /* clone it so we can register it a second time */ |
| 370 rules2=utrans_clone(rules, &status); |
| 371 if(U_FAILURE(status)) { |
| 372 log_err("FAIL: utrans_clone(a<>B) failed with error=%s\n", myErrorName(s
tatus)); |
| 373 return; |
| 374 } |
| 375 |
| 376 status=U_ZERO_ERROR; |
| 377 /* Register it */ |
| 378 utrans_register(rules, &status); |
| 379 if(U_FAILURE(status)){ |
| 380 log_err("FAIL: utrans_register failed with error=%s\n", myErrorName(stat
us)); |
| 381 return; |
| 382 } |
| 383 status=U_ZERO_ERROR; |
| 384 /* Now check again -- should exist now*/ |
| 385 t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); |
| 386 if(U_FAILURE(status) || t1 == NULL){ |
| 387 log_err("FAIL: TestA-TestB not registered\n"); |
| 388 return; |
| 389 } |
| 390 utrans_close(t1); |
| 391 |
| 392 /*unregister the instance*/ |
| 393 status=U_ZERO_ERROR; |
| 394 utrans_unregister("TestA-TestB"); |
| 395 /* now Make sure it doesn't exist */ |
| 396 t1=utrans_open("TestA-TestB", UTRANS_FORWARD,NULL,0,NULL, &status); |
| 397 if(U_SUCCESS(status) || t1 != NULL) { |
| 398 log_err("FAIL: TestA-TestB isn't unregistered\n"); |
| 399 return; |
| 400 } |
| 401 utrans_close(t1); |
| 402 |
| 403 /* now with utrans_unregisterID(const UChar *) */ |
| 404 status=U_ZERO_ERROR; |
| 405 utrans_register(rules2, &status); |
| 406 if(U_FAILURE(status)){ |
| 407 log_err("FAIL: 2nd utrans_register failed with error=%s\n", myErrorName(
status)); |
| 408 return; |
| 409 } |
| 410 status=U_ZERO_ERROR; |
| 411 /* Now check again -- should exist now*/ |
| 412 t1= utrans_open("TestA-TestB", UTRANS_FORWARD, NULL,0,NULL,&status); |
| 413 if(U_FAILURE(status) || t1 == NULL){ |
| 414 log_err("FAIL: 2nd TestA-TestB not registered\n"); |
| 415 return; |
| 416 } |
| 417 utrans_close(t1); |
| 418 |
| 419 /*unregister the instance*/ |
| 420 status=U_ZERO_ERROR; |
| 421 utrans_unregisterID(ID, -1); |
| 422 /* now Make sure it doesn't exist */ |
| 423 t1=utrans_openU(ID, -1, UTRANS_FORWARD,NULL,0,NULL, &status); |
| 424 if(U_SUCCESS(status) || t1 != NULL) { |
| 425 log_err("FAIL: 2nd TestA-TestB isn't unregistered\n"); |
| 426 return; |
| 427 } |
| 428 |
| 429 utrans_close(t1); |
| 430 utrans_close(inverse1); |
| 431 } |
| 432 |
| 433 static void TestSimpleRules() { |
| 434 /* Test rules */ |
| 435 /* Example: rules 1. ab>x|y |
| 436 * 2. yc>z |
| 437 * |
| 438 * []|eabcd start - no match, copy e to tranlated buffer |
| 439 * [e]|abcd match rule 1 - copy output & adjust cursor |
| 440 * [ex|y]cd match rule 2 - copy output & adjust cursor |
| 441 * [exz]|d no match, copy d to transliterated buffer |
| 442 * [exzd]| done |
| 443 */ |
| 444 _expectRules("ab>x|y;" |
| 445 "yc>z", |
| 446 "eabcd", "exzd"); |
| 447 |
| 448 /* Another set of rules: |
| 449 * 1. ab>x|yzacw |
| 450 * 2. za>q |
| 451 * 3. qc>r |
| 452 * 4. cw>n |
| 453 * |
| 454 * []|ab Rule 1 |
| 455 * [x|yzacw] No match |
| 456 * [xy|zacw] Rule 2 |
| 457 * [xyq|cw] Rule 4 |
| 458 * [xyqn]| Done |
| 459 */ |
| 460 _expectRules("ab>x|yzacw;" |
| 461 "za>q;" |
| 462 "qc>r;" |
| 463 "cw>n", |
| 464 "ab", "xyqn"); |
| 465 |
| 466 /* Test categories |
| 467 */ |
| 468 _expectRules("$dummy=" "\\uE100" ";" /* careful here with E100 */ |
| 469 "$vowel=[aeiouAEIOU];" |
| 470 "$lu=[:Lu:];" |
| 471 "$vowel } $lu > '!';" |
| 472 "$vowel > '&';" |
| 473 "'!' { $lu > '^';" |
| 474 "$lu > '*';" |
| 475 "a > ERROR", |
| 476 "abcdefgABCDEFGU", "&bcd&fg!^**!^*&"); |
| 477 |
| 478 /* Test multiple passes |
| 479 */ |
| 480 _expectRules("abc > xy;" |
| 481 "::Null;" |
| 482 "aba > z;", |
| 483 "abc ababc aba", "xy abxy z"); |
| 484 } |
| 485 |
| 486 static void TestFilter() { |
| 487 UErrorCode status = U_ZERO_ERROR; |
| 488 UChar filt[128]; |
| 489 UChar buf[128]; |
| 490 UChar exp[128]; |
| 491 char *cbuf; |
| 492 int32_t limit; |
| 493 const char* DATA[] = { |
| 494 "[^c]", /* Filter out 'c' */ |
| 495 "abcde", |
| 496 "\\u0061\\u0062c\\u0064\\u0065", |
| 497 |
| 498 "", /* No filter */ |
| 499 "abcde", |
| 500 "\\u0061\\u0062\\u0063\\u0064\\u0065" |
| 501 }; |
| 502 int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]); |
| 503 int32_t i; |
| 504 |
| 505 UTransliterator* hex = utrans_open("Any-Hex", UTRANS_FORWARD, NULL,0,NULL,&s
tatus); |
| 506 |
| 507 if (hex == 0 || U_FAILURE(status)) { |
| 508 log_err("FAIL: utrans_open(Unicode-Hex) failed, error=%s\n", |
| 509 u_errorName(status)); |
| 510 goto exit; |
| 511 } |
| 512 |
| 513 for (i=0; i<DATA_length; i+=3) { |
| 514 /*u_uastrcpy(filt, DATA[i]);*/ |
| 515 u_charsToUChars(DATA[i], filt, (int32_t)strlen(DATA[i])+1); |
| 516 utrans_setFilter(hex, filt, -1, &status); |
| 517 |
| 518 if (U_FAILURE(status)) { |
| 519 log_err("FAIL: utrans_setFilter() failed, error=%s\n", |
| 520 u_errorName(status)); |
| 521 goto exit; |
| 522 } |
| 523 |
| 524 /*u_uastrcpy(buf, DATA[i+1]);*/ |
| 525 u_charsToUChars(DATA[i+1], buf, (int32_t)strlen(DATA[i+1])+1); |
| 526 limit = 5; |
| 527 utrans_transUChars(hex, buf, NULL, 128, 0, &limit, &status); |
| 528 |
| 529 if (U_FAILURE(status)) { |
| 530 log_err("FAIL: utrans_transUChars() failed, error=%s\n", |
| 531 u_errorName(status)); |
| 532 goto exit; |
| 533 } |
| 534 |
| 535 cbuf=aescstrdup(buf, -1); |
| 536 u_charsToUChars(DATA[i+2], exp, (int32_t)strlen(DATA[i+2])+1); |
| 537 if (0 == u_strcmp(buf, exp)) { |
| 538 log_verbose("Ok: %s | %s -> %s\n", DATA[i+1], DATA[i], cbuf); |
| 539 } else { |
| 540 log_err("FAIL: %s | %s -> %s, expected %s\n", DATA[i+1], DATA[i], cb
uf, DATA[i+2]); |
| 541 } |
| 542 } |
| 543 |
| 544 exit: |
| 545 utrans_close(hex); |
| 546 } |
| 547 |
| 548 /** |
| 549 * Test the UReplaceableCallback extractBetween support. We use a |
| 550 * transliterator known to rely on this call. |
| 551 */ |
| 552 static void TestExtractBetween() { |
| 553 |
| 554 UTransliterator *trans; |
| 555 UErrorCode status = U_ZERO_ERROR; |
| 556 UParseError parseErr; |
| 557 |
| 558 trans = utrans_open("Lower", UTRANS_FORWARD, NULL, -1, |
| 559 &parseErr, &status); |
| 560 |
| 561 if (U_FAILURE(status)) { |
| 562 log_err("FAIL: utrans_open(Lower) failed, error=%s\n", |
| 563 u_errorName(status)); |
| 564 } else { |
| 565 _expect(trans, "ABC", "abc"); |
| 566 |
| 567 utrans_close(trans); |
| 568 } |
| 569 } |
| 570 |
| 571 static void _expectRules(const char* crules, |
| 572 const char* cfrom, |
| 573 const char* cto) { |
| 574 /* u_uastrcpy has no capacity param for the buffer -- so just |
| 575 * make all buffers way too big */ |
| 576 enum { CAP = 256 }; |
| 577 UChar rules[CAP]; |
| 578 UTransliterator *trans; |
| 579 UErrorCode status = U_ZERO_ERROR; |
| 580 UParseError parseErr; |
| 581 |
| 582 u_uastrcpy(rules, crules); |
| 583 |
| 584 trans = utrans_open(crules /*use rules as ID*/, UTRANS_FORWARD, rules, -1, |
| 585 &parseErr, &status); |
| 586 if (U_FAILURE(status)) { |
| 587 utrans_close(trans); |
| 588 log_data_err("FAIL: utrans_openRules(%s) failed, error=%s (Are you missi
ng data?)\n", |
| 589 crules, u_errorName(status)); |
| 590 return; |
| 591 } |
| 592 |
| 593 _expect(trans, cfrom, cto); |
| 594 |
| 595 utrans_close(trans); |
| 596 } |
| 597 |
| 598 static void _expect(const UTransliterator* trans, |
| 599 const char* cfrom, |
| 600 const char* cto) { |
| 601 /* u_uastrcpy has no capacity param for the buffer -- so just |
| 602 * make all buffers way too big */ |
| 603 enum { CAP = 256 }; |
| 604 UChar from[CAP]; |
| 605 UChar to[CAP]; |
| 606 UChar buf[CAP]; |
| 607 const UChar *ID; |
| 608 int32_t IDLength; |
| 609 const char *id; |
| 610 |
| 611 UErrorCode status = U_ZERO_ERROR; |
| 612 int32_t limit; |
| 613 UTransPosition pos; |
| 614 XReplaceable xrep; |
| 615 XReplaceable *xrepPtr = &xrep; |
| 616 UReplaceableCallbacks xrepVtable; |
| 617 |
| 618 u_uastrcpy(from, cfrom); |
| 619 u_uastrcpy(to, cto); |
| 620 |
| 621 ID = utrans_getUnicodeID(trans, &IDLength); |
| 622 id = aescstrdup(ID, IDLength); |
| 623 |
| 624 /* utrans_transUChars() */ |
| 625 u_strcpy(buf, from); |
| 626 limit = u_strlen(buf); |
| 627 utrans_transUChars(trans, buf, NULL, CAP, 0, &limit, &status); |
| 628 if (U_FAILURE(status)) { |
| 629 log_err("FAIL: utrans_transUChars() failed, error=%s\n", |
| 630 u_errorName(status)); |
| 631 return; |
| 632 } |
| 633 |
| 634 if (0 == u_strcmp(buf, to)) { |
| 635 log_verbose("Ok: utrans_transUChars(%s) x %s -> %s\n", |
| 636 id, cfrom, cto); |
| 637 } else { |
| 638 char actual[CAP]; |
| 639 u_austrcpy(actual, buf); |
| 640 log_err("FAIL: utrans_transUChars(%s) x %s -> %s, expected %s\n", |
| 641 id, cfrom, actual, cto); |
| 642 } |
| 643 |
| 644 /* utrans_transIncrementalUChars() */ |
| 645 u_strcpy(buf, from); |
| 646 pos.start = pos.contextStart = 0; |
| 647 pos.limit = pos.contextLimit = u_strlen(buf); |
| 648 utrans_transIncrementalUChars(trans, buf, NULL, CAP, &pos, &status); |
| 649 utrans_transUChars(trans, buf, NULL, CAP, pos.start, &pos.limit, &status); |
| 650 if (U_FAILURE(status)) { |
| 651 log_err("FAIL: utrans_transIncrementalUChars() failed, error=%s\n", |
| 652 u_errorName(status)); |
| 653 return; |
| 654 } |
| 655 |
| 656 if (0 == u_strcmp(buf, to)) { |
| 657 log_verbose("Ok: utrans_transIncrementalUChars(%s) x %s -> %s\n", |
| 658 id, cfrom, cto); |
| 659 } else { |
| 660 char actual[CAP]; |
| 661 u_austrcpy(actual, buf); |
| 662 log_err("FAIL: utrans_transIncrementalUChars(%s) x %s -> %s, expected %s
\n", |
| 663 id, cfrom, actual, cto); |
| 664 } |
| 665 |
| 666 /* utrans_trans() */ |
| 667 InitXReplaceableCallbacks(&xrepVtable); |
| 668 InitXReplaceable(&xrep, cfrom); |
| 669 limit = u_strlen(from); |
| 670 utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, 0, &limit, &status)
; |
| 671 if (U_FAILURE(status)) { |
| 672 log_err("FAIL: utrans_trans() failed, error=%s\n", |
| 673 u_errorName(status)); |
| 674 FreeXReplaceable(&xrep); |
| 675 return; |
| 676 } |
| 677 |
| 678 if (0 == u_strcmp(xrep.text, to)) { |
| 679 log_verbose("Ok: utrans_trans(%s) x %s -> %s\n", |
| 680 id, cfrom, cto); |
| 681 } else { |
| 682 char actual[CAP]; |
| 683 u_austrcpy(actual, xrep.text); |
| 684 log_err("FAIL: utrans_trans(%s) x %s -> %s, expected %s\n", |
| 685 id, cfrom, actual, cto); |
| 686 } |
| 687 FreeXReplaceable(&xrep); |
| 688 |
| 689 /* utrans_transIncremental() */ |
| 690 InitXReplaceable(&xrep, cfrom); |
| 691 pos.start = pos.contextStart = 0; |
| 692 pos.limit = pos.contextLimit = u_strlen(from); |
| 693 utrans_transIncremental(trans, (UReplaceable*)xrepPtr, &xrepVtable, &pos, &s
tatus); |
| 694 utrans_trans(trans, (UReplaceable*)xrepPtr, &xrepVtable, pos.start, &pos.lim
it, &status); |
| 695 if (U_FAILURE(status)) { |
| 696 log_err("FAIL: utrans_transIncremental() failed, error=%s\n", |
| 697 u_errorName(status)); |
| 698 FreeXReplaceable(&xrep); |
| 699 return; |
| 700 } |
| 701 |
| 702 if (0 == u_strcmp(xrep.text, to)) { |
| 703 log_verbose("Ok: utrans_transIncremental(%s) x %s -> %s\n", |
| 704 id, cfrom, cto); |
| 705 } else { |
| 706 char actual[CAP]; |
| 707 u_austrcpy(actual, xrep.text); |
| 708 log_err("FAIL: utrans_transIncremental(%s) x %s -> %s, expected %s\n", |
| 709 id, cfrom, actual, cto); |
| 710 } |
| 711 FreeXReplaceable(&xrep); |
| 712 } |
| 713 |
| 714 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ |
OLD | NEW |