1 /**************************************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2012, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 * Modification History: 6 * 7 * Date Name Description 8 * 05/22/2000 Madhu Added tests for testing new API for utf16 support and more 9 ****************************************************************************************/ 10 11 #include <string.h> 12 #include "utypeinfo.h" // for 'typeid' to work 13 14 #include "unicode/chariter.h" 15 #include "unicode/ustring.h" 16 #include "unicode/unistr.h" 17 #include "unicode/schriter.h" 18 #include "unicode/uchriter.h" 19 #include "unicode/uiter.h" 20 #include "unicode/putil.h" 21 #include "unicode/utf16.h" 22 #include "citrtest.h" 23 24 25 class SCharacterIterator : public CharacterIterator { 26 public: 27 SCharacterIterator(const UnicodeString& textStr){ 28 text = textStr; 29 pos=0; 30 textLength = textStr.length(); 31 begin = 0; 32 end=textLength; 33 34 } 35 36 virtual ~SCharacterIterator(){}; 37 38 39 void setText(const UnicodeString& newText){ 40 text = newText; 41 } 42 43 virtual void getText(UnicodeString& result) { 44 text.extract(0,text.length(),result); 45 } 46 static UClassID getStaticClassID(void){ 47 return (UClassID)(&fgClassID); 48 } 49 virtual UClassID getDynamicClassID(void) const{ 50 return getStaticClassID(); 51 } 52 53 virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{ 54 return TRUE; 55 } 56 57 virtual CharacterIterator* clone(void) const { 58 return NULL; 59 } 60 virtual int32_t hashCode(void) const{ 61 return DONE; 62 } 63 virtual UChar nextPostInc(void){ return text.charAt(pos++);} 64 virtual UChar32 next32PostInc(void){return text.char32At(pos++);} 65 virtual UBool hasNext() { return TRUE;}; 66 virtual UChar first(){return DONE;}; 67 virtual UChar32 first32(){return DONE;}; 68 virtual UChar last(){return DONE;}; 69 virtual UChar32 last32(){return DONE;}; 70 virtual UChar setIndex(int32_t /*pos*/){return DONE;}; 71 virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;}; 72 virtual UChar current() const{return DONE;}; 73 virtual UChar32 current32() const{return DONE;}; 74 virtual UChar next(){return DONE;}; 75 virtual UChar32 next32(){return DONE;}; 76 virtual UChar previous(){return DONE;}; 77 virtual UChar32 previous32(){return DONE;}; 78 virtual int32_t move(int32_t delta,CharacterIterator::EOrigin origin){ 79 switch(origin) { 80 case kStart: 81 pos = begin + delta; 82 break; 83 case kCurrent: 84 pos += delta; 85 break; 86 case kEnd: 87 pos = end + delta; 88 break; 89 default: 90 break; 91 } 92 93 if(pos < begin) { 94 pos = begin; 95 } else if(pos > end) { 96 pos = end; 97 } 98 99 return pos; 100 }; 101 virtual int32_t move32(int32_t delta, CharacterIterator::EOrigin origin){ 102 switch(origin) { 103 case kStart: 104 pos = begin; 105 if(delta > 0) { 106 U16_FWD_N(text, pos, end, delta); 107 } 108 break; 109 case kCurrent: 110 if(delta > 0) { 111 U16_FWD_N(text, pos, end, delta); 112 } else { 113 U16_BACK_N(text, begin, pos, -delta); 114 } 115 break; 116 case kEnd: 117 pos = end; 118 if(delta < 0) { 119 U16_BACK_N(text, begin, pos, -delta); 120 } 121 break; 122 default: 123 break; 124 } 125 126 return pos; 127 }; 128 virtual UBool hasPrevious() {return TRUE;}; 129 130 SCharacterIterator& operator=(const SCharacterIterator& that){ 131 text = that.text; 132 return *this; 133 } 134 135 136 private: 137 UnicodeString text; 138 static const char fgClassID; 139 }; 140 const char SCharacterIterator::fgClassID=0; 141 142 #define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0]))) 143 144 CharIterTest::CharIterTest() 145 { 146 } 147 void CharIterTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 148 { 149 if (exec) logln("TestSuite CharIterTest: "); 150 switch (index) { 151 case 0: name = "TestConstructionAndEquality"; if (exec) TestConstructionAndEquality(); break; 152 case 1: name = "TestConstructionAndEqualityUChariter"; if (exec) TestConstructionAndEqualityUChariter(); break; 153 case 2: name = "TestIteration"; if (exec) TestIteration(); break; 154 case 3: name = "TestIterationUChar32"; if (exec) TestIterationUChar32(); break; 155 case 4: name = "TestUCharIterator"; if (exec) TestUCharIterator(); break; 156 case 5: name = "TestCoverage"; if(exec) TestCoverage(); break; 157 case 6: name = "TestCharIteratorSubClasses"; if (exec) TestCharIteratorSubClasses(); break; 158 default: name = ""; break; //needed to end loop 159 } 160 } 161 162 void CharIterTest::TestCoverage(){ 163 UnicodeString testText("Now is the time for all good men to come to the aid of their country."); 164 UnicodeString testText2("\\ud800\\udc01deadbeef"); 165 testText2 = testText2.unescape(); 166 SCharacterIterator* test = new SCharacterIterator(testText); 167 if(test->firstPostInc()!= 0x004E){ 168 errln("Failed: firstPostInc() failed"); 169 } 170 if(test->getIndex()!=1){ 171 errln("Failed: getIndex()."); 172 } 173 if(test->getLength()!=testText.length()){ 174 errln("Failed: getLength()"); 175 } 176 test->setToStart(); 177 if(test->getIndex()!=0){ 178 errln("Failed: setToStart()."); 179 } 180 test->setToEnd(); 181 if(test->getIndex()!=testText.length()){ 182 errln("Failed: setToEnd()."); 183 } 184 if(test->startIndex() != 0){ 185 errln("Failed: startIndex()"); 186 } 187 test->setText(testText2); 188 if(test->first32PostInc()!= testText2.char32At(0)){ 189 errln("Failed: first32PostInc() failed"); 190 } 191 192 delete test; 193 194 } 195 void CharIterTest::TestConstructionAndEquality() { 196 UnicodeString testText("Now is the time for all good men to come to the aid of their country."); 197 UnicodeString testText2("Don't bother using this string."); 198 UnicodeString result1, result2, result3; 199 200 CharacterIterator* test1 = new StringCharacterIterator(testText); 201 CharacterIterator* test1b= new StringCharacterIterator(testText, -1); 202 CharacterIterator* test1c= new StringCharacterIterator(testText, 100); 203 CharacterIterator* test1d= new StringCharacterIterator(testText, -2, 100, 5); 204 CharacterIterator* test1e= new StringCharacterIterator(testText, 100, 20, 5); 205 CharacterIterator* test2 = new StringCharacterIterator(testText, 5); 206 CharacterIterator* test3 = new StringCharacterIterator(testText, 2, 20, 5); 207 CharacterIterator* test4 = new StringCharacterIterator(testText2); 208 CharacterIterator* test5 = test1->clone(); 209 210 if (test1d->startIndex() < 0) 211 errln("Construction failed: startIndex is negative"); 212 if (test1d->endIndex() > testText.length()) 213 errln("Construction failed: endIndex is greater than the text length"); 214 if (test1d->getIndex() < test1d->startIndex() || test1d->endIndex() < test1d->getIndex()) 215 errln("Construction failed: index is invalid"); 216 217 if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4) 218 errln("Construction or operator== failed: Unequal objects compared equal"); 219 if (*test1 != *test5) 220 errln("clone() or equals() failed: Two clones tested unequal"); 221 222 if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode() 223 || test1->hashCode() == test4->hashCode()) 224 errln("hashCode() failed: different objects have same hash code"); 225 226 if (test1->hashCode() != test5->hashCode()) 227 errln("hashCode() failed: identical objects have different hash codes"); 228 229 if(test1->getLength() != testText.length()){ 230 errln("getLength of CharacterIterator failed"); 231 } 232 test1->getText(result1); 233 test1b->getText(result2); 234 test1c->getText(result3); 235 if(result1 != result2 || result1 != result3) 236 errln("construction failed or getText() failed"); 237 238 239 test1->setIndex(5); 240 if (*test1 != *test2 || *test1 == *test5) 241 errln("setIndex() failed"); 242 243 *((StringCharacterIterator*)test1) = *((StringCharacterIterator*)test3); 244 if (*test1 != *test3 || *test1 == *test5) 245 errln("operator= failed"); 246 247 delete test2; 248 delete test3; 249 delete test4; 250 delete test5; 251 delete test1b; 252 delete test1c; 253 delete test1d; 254 delete test1e; 255 256 257 StringCharacterIterator* testChar1=new StringCharacterIterator(testText); 258 StringCharacterIterator* testChar2=new StringCharacterIterator(testText2); 259 StringCharacterIterator* testChar3=(StringCharacterIterator*)test1->clone(); 260 261 testChar1->getText(result1); 262 testChar2->getText(result2); 263 testChar3->getText(result3); 264 if(result1 != result3 || result1 == result2) 265 errln("getText() failed"); 266 testChar3->setText(testText2); 267 testChar3->getText(result3); 268 if(result1 == result3 || result2 != result3) 269 errln("setText() or getText() failed"); 270 testChar3->setText(testText); 271 testChar3->getText(result3); 272 if(result1 != result3 || result1 == result2) 273 errln("setText() or getText() round-trip failed"); 274 275 delete testChar1; 276 delete testChar2; 277 delete testChar3; 278 delete test1; 279 280 } 281 void CharIterTest::TestConstructionAndEqualityUChariter() { 282 U_STRING_DECL(testText, "Now is the time for all good men to come to the aid of their country.", 69); 283 U_STRING_DECL(testText2, "Don't bother using this string.", 31); 284 285 U_STRING_INIT(testText, "Now is the time for all good men to come to the aid of their country.", 69); 286 U_STRING_INIT(testText2, "Don't bother using this string.", 31); 287 288 UnicodeString result, result4, result5; 289 290 UCharCharacterIterator* test1 = new UCharCharacterIterator(testText, u_strlen(testText)); 291 UCharCharacterIterator* test2 = new UCharCharacterIterator(testText, u_strlen(testText), 5); 292 UCharCharacterIterator* test3 = new UCharCharacterIterator(testText, u_strlen(testText), 2, 20, 5); 293 UCharCharacterIterator* test4 = new UCharCharacterIterator(testText2, u_strlen(testText2)); 294 UCharCharacterIterator* test5 = (UCharCharacterIterator*)test1->clone(); 295 UCharCharacterIterator* test6 = new UCharCharacterIterator(*test1); 296 297 // j785: length=-1 will use u_strlen() 298 UCharCharacterIterator* test7a = new UCharCharacterIterator(testText, -1); 299 UCharCharacterIterator* test7b = new UCharCharacterIterator(testText, -1); 300 UCharCharacterIterator* test7c = new UCharCharacterIterator(testText, -1, 2, 20, 5); 301 302 // Bad parameters. 303 UCharCharacterIterator* test8a = new UCharCharacterIterator(testText, -1, -1, 20, 5); 304 UCharCharacterIterator* test8b = new UCharCharacterIterator(testText, -1, 2, 100, 5); 305 UCharCharacterIterator* test8c = new UCharCharacterIterator(testText, -1, 2, 20, 100); 306 307 if (test8a->startIndex() < 0) 308 errln("Construction failed: startIndex is negative"); 309 if (test8b->endIndex() != u_strlen(testText)) 310 errln("Construction failed: endIndex is different from the text length"); 311 if (test8c->getIndex() < test8c->startIndex() || test8c->endIndex() < test8c->getIndex()) 312 errln("Construction failed: index is invalid"); 313 314 if (*test1 == *test2 || *test1 == *test3 || *test1 == *test4 ) 315 errln("Construction or operator== failed: Unequal objects compared equal"); 316 if (*test1 != *test5 ) 317 errln("clone() or equals() failed: Two clones tested unequal"); 318 319 if (*test6 != *test1 ) 320 errln("copy construction or equals() failed: Two copies tested unequal"); 321 322 if (test1->hashCode() == test2->hashCode() || test1->hashCode() == test3->hashCode() 323 || test1->hashCode() == test4->hashCode()) 324 errln("hashCode() failed: different objects have same hash code"); 325 326 if (test1->hashCode() != test5->hashCode()) 327 errln("hashCode() failed: identical objects have different hash codes"); 328 329 test7a->getText(result); 330 test7b->getText(result4); 331 test7c->getText(result5); 332 333 if(result != UnicodeString(testText) || result4 != result || result5 != result) 334 errln("error in construction"); 335 336 test1->getText(result); 337 test4->getText(result4); 338 test5->getText(result5); 339 if(result != result5 || result == result4) 340 errln("getText() failed"); 341 test5->setText(testText2, u_strlen(testText2)); 342 test5->getText(result5); 343 if(result == result5 || result4 != result5) 344 errln("setText() or getText() failed"); 345 test5->setText(testText, u_strlen(testText)); 346 test5->getText(result5); 347 if(result != result5 || result == result4) 348 errln("setText() or getText() round-trip failed"); 349 350 351 test1->setIndex(5); 352 if (*test1 != *test2 || *test1 == *test5) 353 errln("setIndex() failed"); 354 test8b->setIndex32(5); 355 if (test8b->getIndex()!=5) 356 errln("setIndex32() failed"); 357 358 *test1 = *test3; 359 if (*test1 != *test3 || *test1 == *test5) 360 errln("operator= failed"); 361 362 delete test1; 363 delete test2; 364 delete test3; 365 delete test4; 366 delete test5; 367 delete test6; 368 delete test7a; 369 delete test7b; 370 delete test7c; 371 delete test8a; 372 delete test8b; 373 delete test8c; 374 } 375 376 377 void CharIterTest::TestIteration() { 378 UnicodeString text("Now is the time for all good men to come to the aid of their country."); 379 380 UChar c; 381 int32_t i; 382 { 383 StringCharacterIterator iter(text, 5); 384 385 UnicodeString iterText; 386 iter.getText(iterText); 387 if (iterText != text) 388 errln("iter.getText() failed"); 389 390 if (iter.current() != text[(int32_t)5]) 391 errln("Iterator didn't start out in the right place."); 392 393 c = iter.first(); 394 i = 0; 395 396 if (iter.startIndex() != 0 || iter.endIndex() != text.length()) 397 errln("startIndex() or endIndex() failed"); 398 399 logln("Testing forward iteration..."); 400 do { 401 if (c == CharacterIterator::DONE && i != text.length()) 402 errln("Iterator reached end prematurely"); 403 else if (c != text[i]) 404 errln((UnicodeString)"Character mismatch at position " + i + 405 ", iterator has " + UCharToUnicodeString(c) + 406 ", string has " + UCharToUnicodeString(text[i])); 407 408 if (iter.current() != c) 409 errln("current() isn't working right"); 410 if (iter.getIndex() != i) 411 errln("getIndex() isn't working right"); 412 413 if (c != CharacterIterator::DONE) { 414 c = iter.next(); 415 i++; 416 } 417 } while (c != CharacterIterator::DONE); 418 c=iter.next(); 419 if(c!= CharacterIterator::DONE) 420 errln("next() didn't return DONE at the end"); 421 c=iter.setIndex(text.length()+1); 422 if(c!= CharacterIterator::DONE) 423 errln("setIndex(len+1) didn't return DONE"); 424 425 c = iter.last(); 426 i = text.length() - 1; 427 428 logln("Testing backward iteration..."); 429 do { 430 if (c == CharacterIterator::DONE && i >= 0) 431 errln("Iterator reached end prematurely"); 432 else if (c != text[i]) 433 errln((UnicodeString)"Character mismatch at position " + i + 434 ", iterator has " + UCharToUnicodeString(c) + 435 ", string has " + UCharToUnicodeString(text[i])); 436 437 if (iter.current() != c) 438 errln("current() isn't working right"); 439 if (iter.getIndex() != i) 440 errln("getIndex() isn't working right"); 441 if(iter.setIndex(i) != c) 442 errln("setIndex() isn't working right"); 443 444 if (c != CharacterIterator::DONE) { 445 c = iter.previous(); 446 i--; 447 } 448 } while (c != CharacterIterator::DONE); 449 450 c=iter.previous(); 451 if(c!= CharacterIterator::DONE) 452 errln("previous didn't return DONE at the beginning"); 453 454 455 //testing firstPostInc, nextPostInc, setTostart 456 i = 0; 457 c=iter.firstPostInc(); 458 if(c != text[i]) 459 errln((UnicodeString)"firstPostInc failed. Expected->" + 460 UCharToUnicodeString(text[i]) + " Got->" + UCharToUnicodeString(c)); 461 if(iter.getIndex() != i+1) 462 errln((UnicodeString)"getIndex() after firstPostInc() failed"); 463 464 iter.setToStart(); 465 i=0; 466 if (iter.startIndex() != 0) 467 errln("setToStart failed"); 468 469 logln("Testing forward iteration..."); 470 do { 471 if (c != CharacterIterator::DONE) 472 c = iter.nextPostInc(); 473 474 if(c != text[i]) 475 errln((UnicodeString)"Character mismatch at position " + i + 476 (UnicodeString)", iterator has " + UCharToUnicodeString(c) + 477 (UnicodeString)", string has " + UCharToUnicodeString(text[i])); 478 479 i++; 480 if(iter.getIndex() != i) 481 errln("getIndex() aftr nextPostInc() isn't working right"); 482 if(iter.current() != text[i]) 483 errln("current() after nextPostInc() isn't working right"); 484 } while (iter.hasNext()); 485 c=iter.nextPostInc(); 486 if(c!= CharacterIterator::DONE) 487 errln("nextPostInc() didn't return DONE at the beginning"); 488 } 489 490 { 491 StringCharacterIterator iter(text, 5, 15, 10); 492 if (iter.startIndex() != 5 || iter.endIndex() != 15) 493 errln("creation of a restricted-range iterator failed"); 494 495 if (iter.getIndex() != 10 || iter.current() != text[(int32_t)10]) 496 errln("starting the iterator in the middle didn't work"); 497 498 c = iter.first(); 499 i = 5; 500 501 logln("Testing forward iteration over a range..."); 502 do { 503 if (c == CharacterIterator::DONE && i != 15) 504 errln("Iterator reached end prematurely"); 505 else if (c != text[i]) 506 errln((UnicodeString)"Character mismatch at position " + i + 507 ", iterator has " + UCharToUnicodeString(c) + 508 ", string has " + UCharToUnicodeString(text[i])); 509 510 if (iter.current() != c) 511 errln("current() isn't working right"); 512 if (iter.getIndex() != i) 513 errln("getIndex() isn't working right"); 514 if(iter.setIndex(i) != c) 515 errln("setIndex() isn't working right"); 516 517 if (c != CharacterIterator::DONE) { 518 c = iter.next(); 519 i++; 520 } 521 } while (c != CharacterIterator::DONE); 522 523 c = iter.last(); 524 i = 14; 525 526 logln("Testing backward iteration over a range..."); 527 do { 528 if (c == CharacterIterator::DONE && i >= 5) 529 errln("Iterator reached end prematurely"); 530 else if (c != text[i]) 531 errln((UnicodeString)"Character mismatch at position " + i + 532 ", iterator has " + UCharToUnicodeString(c) + 533 ", string has " + UCharToUnicodeString(text[i])); 534 535 if (iter.current() != c) 536 errln("current() isn't working right"); 537 if (iter.getIndex() != i) 538 errln("getIndex() isn't working right"); 539 540 if (c != CharacterIterator::DONE) { 541 c = iter.previous(); 542 i--; 543 } 544 } while (c != CharacterIterator::DONE); 545 546 547 } 548 } 549 550 //Tests for new API for utf-16 support 551 void CharIterTest::TestIterationUChar32() { 552 UChar textChars[]={ 0x0061, 0x0062, 0xd841, 0xdc02, 0x20ac, 0xd7ff, 0xd842, 0xdc06, 0xd801, 0xdc00, 0x0061, 0x0000}; 553 UnicodeString text(textChars); 554 UChar32 c; 555 int32_t i; 556 { 557 StringCharacterIterator iter(text, 1); 558 559 UnicodeString iterText; 560 iter.getText(iterText); 561 if (iterText != text) 562 errln("iter.getText() failed"); 563 564 if (iter.current32() != text[(int32_t)1]) 565 errln("Iterator didn't start out in the right place."); 566 567 c=iter.setToStart(); 568 i=0; 569 i=iter.move32(1, CharacterIterator::kStart); 570 c=iter.current32(); 571 if(c != text.char32At(1) || i!=1) 572 errln("move32(1, kStart) didn't work correctly expected %X got %X", c, text.char32At(1) ); 573 574 i=iter.move32(2, CharacterIterator::kCurrent); 575 c=iter.current32(); 576 if(c != text.char32At(4) || i!=4) 577 errln("move32(2, kCurrent) didn't work correctly expected %X got %X i=%ld", c, text.char32At(4), i); 578 579 i=iter.move32(-2, CharacterIterator::kCurrent); 580 c=iter.current32(); 581 if(c != text.char32At(1) || i!=1) 582 errln("move32(-2, kCurrent) didn't work correctly expected %X got %X i=%d", c, text.char32At(1), i); 583 584 585 i=iter.move32(-2, CharacterIterator::kEnd); 586 c=iter.current32(); 587 if(c != text.char32At((text.length()-3)) || i!=(text.length()-3)) 588 errln("move32(-2, kEnd) didn't work correctly expected %X got %X i=%d", c, text.char32At((text.length()-3)), i); 589 590 591 c = iter.first32(); 592 i = 0; 593 594 if (iter.startIndex() != 0 || iter.endIndex() != text.length()) 595 errln("startIndex() or endIndex() failed"); 596 597 logln("Testing forward iteration..."); 598 do { 599 /* logln("c=%d i=%d char32At=%d", c, i, text.char32At(i)); */ 600 if (c == CharacterIterator::DONE && i != text.length()) 601 errln("Iterator reached end prematurely"); 602 else if(iter.hasNext() == FALSE && i != text.length()) 603 errln("Iterator reached end prematurely. Failed at hasNext"); 604 else if (c != text.char32At(i)) 605 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i)); 606 607 if (iter.current32() != c) 608 errln("current32() isn't working right"); 609 if(iter.setIndex32(i) != c) 610 errln("setIndex32() isn't working right"); 611 if (c != CharacterIterator::DONE) { 612 c = iter.next32(); 613 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1; 614 } 615 } while (c != CharacterIterator::DONE); 616 if(iter.hasNext() == TRUE) 617 errln("hasNext() returned true at the end of the string"); 618 619 620 621 c=iter.setToEnd(); 622 if(iter.getIndex() != text.length() || iter.hasNext() != FALSE) 623 errln("setToEnd failed"); 624 625 c=iter.next32(); 626 if(c!= CharacterIterator::DONE) 627 errln("next32 didn't return DONE at the end"); 628 c=iter.setIndex32(text.length()+1); 629 if(c!= CharacterIterator::DONE) 630 errln("setIndex32(len+1) didn't return DONE"); 631 632 633 c = iter.last32(); 634 i = text.length()-1; 635 logln("Testing backward iteration..."); 636 do { 637 if (c == CharacterIterator::DONE && i >= 0) 638 errln((UnicodeString)"Iterator reached start prematurely for i=" + i); 639 else if(iter.hasPrevious() == FALSE && i>0) 640 errln((UnicodeString)"Iterator reached start prematurely for i=" + i); 641 else if (c != text.char32At(i)) 642 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i)); 643 644 if (iter.current32() != c) 645 errln("current32() isn't working right"); 646 if(iter.setIndex32(i) != c) 647 errln("setIndex32() isn't working right"); 648 if (iter.getIndex() != i) 649 errln("getIndex() isn't working right"); 650 if (c != CharacterIterator::DONE) { 651 c = iter.previous32(); 652 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1; 653 } 654 } while (c != CharacterIterator::DONE); 655 if(iter.hasPrevious() == TRUE) 656 errln("hasPrevious returned true after reaching the start"); 657 658 c=iter.previous32(); 659 if(c!= CharacterIterator::DONE) 660 errln("previous32 didn't return DONE at the beginning"); 661 662 663 664 665 //testing first32PostInc, next32PostInc, setTostart 666 i = 0; 667 c=iter.first32PostInc(); 668 if(c != text.char32At(i)) 669 errln("first32PostInc failed. Expected->%X Got->%X", text.char32At(i), c); 670 if(iter.getIndex() != U16_LENGTH(c) + i) 671 errln((UnicodeString)"getIndex() after first32PostInc() failed"); 672 673 iter.setToStart(); 674 i=0; 675 if (iter.startIndex() != 0) 676 errln("setToStart failed"); 677 678 logln("Testing forward iteration..."); 679 do { 680 if (c != CharacterIterator::DONE) 681 c = iter.next32PostInc(); 682 683 if(c != text.char32At(i)) 684 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i)); 685 686 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1; 687 if(iter.getIndex() != i) 688 errln("getIndex() aftr next32PostInc() isn't working right"); 689 if(iter.current32() != text.char32At(i)) 690 errln("current() after next32PostInc() isn't working right"); 691 } while (iter.hasNext()); 692 c=iter.next32PostInc(); 693 if(c!= CharacterIterator::DONE) 694 errln("next32PostInc() didn't return DONE at the beginning"); 695 696 697 } 698 699 { 700 StringCharacterIterator iter(text, 1, 11, 10); 701 if (iter.startIndex() != 1 || iter.endIndex() != 11) 702 errln("creation of a restricted-range iterator failed"); 703 704 if (iter.getIndex() != 10 || iter.current32() != text.char32At(10)) 705 errln("starting the iterator in the middle didn't work"); 706 707 c = iter.first32(); 708 709 i = 1; 710 711 logln("Testing forward iteration over a range..."); 712 do { 713 if (c == CharacterIterator::DONE && i != 11) 714 errln("Iterator reached end prematurely"); 715 else if(iter.hasNext() == FALSE) 716 errln("Iterator reached end prematurely"); 717 else if (c != text.char32At(i)) 718 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i)); 719 720 if (iter.current32() != c) 721 errln("current32() isn't working right"); 722 if(iter.setIndex32(i) != c) 723 errln("setIndex32() isn't working right"); 724 725 if (c != CharacterIterator::DONE) { 726 c = iter.next32(); 727 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i+2 : i+1; 728 } 729 } while (c != CharacterIterator::DONE); 730 c=iter.next32(); 731 if(c != CharacterIterator::DONE) 732 errln("error in next32()"); 733 734 735 736 c=iter.last32(); 737 i = 10; 738 logln("Testing backward iteration over a range..."); 739 do { 740 if (c == CharacterIterator::DONE && i >= 5) 741 errln("Iterator reached start prematurely"); 742 else if(iter.hasPrevious() == FALSE && i > 5) 743 errln("Iterator reached start prematurely"); 744 else if (c != text.char32At(i)) 745 errln("Character mismatch at position %d, iterator has %X, string has %X", i, c, text.char32At(i)); 746 if (iter.current32() != c) 747 errln("current32() isn't working right"); 748 if (iter.getIndex() != i) 749 errln("getIndex() isn't working right"); 750 if(iter.setIndex32(i) != c) 751 errln("setIndex32() isn't working right"); 752 753 if (c != CharacterIterator::DONE) { 754 c = iter.previous32(); 755 i=UTF16_NEED_MULTIPLE_UCHAR(c) ? i-2 : i-1; 756 } 757 758 } while (c != CharacterIterator::DONE); 759 c=iter.previous32(); 760 if(c!= CharacterIterator::DONE) 761 errln("error on previous32"); 762 763 764 } 765 } 766 767 void CharIterTest::TestUCharIterator(UCharIterator *iter, CharacterIterator &ci, 768 const char *moves, const char *which) { 769 int32_t m; 770 UChar32 c, c2; 771 UBool h, h2; 772 773 for(m=0;; ++m) { 774 // move both iter and s[index] 775 switch(moves[m]) { 776 case '0': 777 h=iter->hasNext(iter); 778 h2=ci.hasNext(); 779 c=iter->current(iter); 780 c2=ci.current(); 781 break; 782 case '|': 783 h=iter->hasNext(iter); 784 h2=ci.hasNext(); 785 c=uiter_current32(iter); 786 c2=ci.current32(); 787 break; 788 789 case '+': 790 h=iter->hasNext(iter); 791 h2=ci.hasNext(); 792 c=iter->next(iter); 793 c2=ci.nextPostInc(); 794 break; 795 case '>': 796 h=iter->hasNext(iter); 797 h2=ci.hasNext(); 798 c=uiter_next32(iter); 799 c2=ci.next32PostInc(); 800 break; 801 802 case '-': 803 h=iter->hasPrevious(iter); 804 h2=ci.hasPrevious(); 805 c=iter->previous(iter); 806 c2=ci.previous(); 807 break; 808 case '<': 809 h=iter->hasPrevious(iter); 810 h2=ci.hasPrevious(); 811 c=uiter_previous32(iter); 812 c2=ci.previous32(); 813 break; 814 815 case '2': 816 h=h2=FALSE; 817 c=(UChar32)iter->move(iter, 2, UITER_CURRENT); 818 c2=(UChar32)ci.move(2, CharacterIterator::kCurrent); 819 break; 820 821 case '8': 822 h=h2=FALSE; 823 c=(UChar32)iter->move(iter, -2, UITER_CURRENT); 824 c2=(UChar32)ci.move(-2, CharacterIterator::kCurrent); 825 break; 826 827 case 0: 828 return; 829 default: 830 errln("error: unexpected move character '%c' in \"%s\"", moves[m], moves); 831 return; 832 } 833 834 // compare results 835 if(c2==0xffff) { 836 c2=(UChar32)-1; 837 } 838 if(c!=c2 || h!=h2 || ci.getIndex()!=iter->getIndex(iter, UITER_CURRENT)) { 839 errln("error: UCharIterator(%s) misbehaving at \"%s\"[%d]='%c'", which, moves, m, moves[m]); 840 } 841 } 842 } 843 844 void CharIterTest::TestUCharIterator() { 845 // test string of length 8 846 UnicodeString s=UnicodeString("a \\U00010001b\\U0010fffdz", "").unescape(); 847 const char *const moves= 848 "0+++++++++" // 10 moves per line 849 "----0-----" 850 ">>|>>>>>>>" 851 "<<|<<<<<<<" 852 "22+>8>-8+2"; 853 854 StringCharacterIterator sci(s), compareCI(s); 855 856 UCharIterator sIter, cIter, rIter; 857 858 uiter_setString(&sIter, s.getBuffer(), s.length()); 859 uiter_setCharacterIterator(&cIter, &sci); 860 uiter_setReplaceable(&rIter, &s); 861 862 TestUCharIterator(&sIter, compareCI, moves, "uiter_setString"); 863 compareCI.setIndex(0); 864 TestUCharIterator(&cIter, compareCI, moves, "uiter_setCharacterIterator"); 865 compareCI.setIndex(0); 866 TestUCharIterator(&rIter, compareCI, moves, "uiter_setReplaceable"); 867 868 // test move & getIndex some more 869 sIter.start=2; 870 sIter.index=3; 871 sIter.limit=5; 872 if( sIter.getIndex(&sIter, UITER_ZERO)!=0 || 873 sIter.getIndex(&sIter, UITER_START)!=2 || 874 sIter.getIndex(&sIter, UITER_CURRENT)!=3 || 875 sIter.getIndex(&sIter, UITER_LIMIT)!=5 || 876 sIter.getIndex(&sIter, UITER_LENGTH)!=s.length() 877 ) { 878 errln("error: UCharIterator(string).getIndex returns wrong index"); 879 } 880 881 if( sIter.move(&sIter, 4, UITER_ZERO)!=4 || 882 sIter.move(&sIter, 1, UITER_START)!=3 || 883 sIter.move(&sIter, 3, UITER_CURRENT)!=5 || 884 sIter.move(&sIter, -1, UITER_LIMIT)!=4 || 885 sIter.move(&sIter, -5, UITER_LENGTH)!=3 || 886 sIter.move(&sIter, 0, UITER_CURRENT)!=sIter.getIndex(&sIter, UITER_CURRENT) || 887 sIter.getIndex(&sIter, UITER_CURRENT)!=3 888 ) { 889 errln("error: UCharIterator(string).move sets/returns wrong index"); 890 } 891 892 sci=StringCharacterIterator(s, 2, 5, 3); 893 uiter_setCharacterIterator(&cIter, &sci); 894 if( cIter.getIndex(&cIter, UITER_ZERO)!=0 || 895 cIter.getIndex(&cIter, UITER_START)!=2 || 896 cIter.getIndex(&cIter, UITER_CURRENT)!=3 || 897 cIter.getIndex(&cIter, UITER_LIMIT)!=5 || 898 cIter.getIndex(&cIter, UITER_LENGTH)!=s.length() 899 ) { 900 errln("error: UCharIterator(character iterator).getIndex returns wrong index"); 901 } 902 903 if( cIter.move(&cIter, 4, UITER_ZERO)!=4 || 904 cIter.move(&cIter, 1, UITER_START)!=3 || 905 cIter.move(&cIter, 3, UITER_CURRENT)!=5 || 906 cIter.move(&cIter, -1, UITER_LIMIT)!=4 || 907 cIter.move(&cIter, -5, UITER_LENGTH)!=3 || 908 cIter.move(&cIter, 0, UITER_CURRENT)!=cIter.getIndex(&cIter, UITER_CURRENT) || 909 cIter.getIndex(&cIter, UITER_CURRENT)!=3 910 ) { 911 errln("error: UCharIterator(character iterator).move sets/returns wrong index"); 912 } 913 914 915 if(cIter.getIndex(&cIter, (enum UCharIteratorOrigin)-1) != -1) 916 { 917 errln("error: UCharIterator(char iter).getIndex did not return error value"); 918 } 919 920 if(cIter.move(&cIter, 0, (enum UCharIteratorOrigin)-1) != -1) 921 { 922 errln("error: UCharIterator(char iter).move did not return error value"); 923 } 924 925 926 if(rIter.getIndex(&rIter, (enum UCharIteratorOrigin)-1) != -1) 927 { 928 errln("error: UCharIterator(repl iter).getIndex did not return error value"); 929 } 930 931 if(rIter.move(&rIter, 0, (enum UCharIteratorOrigin)-1) != -1) 932 { 933 errln("error: UCharIterator(repl iter).move did not return error value"); 934 } 935 936 937 if(sIter.getIndex(&sIter, (enum UCharIteratorOrigin)-1) != -1) 938 { 939 errln("error: UCharIterator(string iter).getIndex did not return error value"); 940 } 941 942 if(sIter.move(&sIter, 0, (enum UCharIteratorOrigin)-1) != -1) 943 { 944 errln("error: UCharIterator(string iter).move did not return error value"); 945 } 946 947 /* Testing function coverage on bad input */ 948 UErrorCode status = U_ZERO_ERROR; 949 uiter_setString(&sIter, NULL, 1); 950 uiter_setState(&sIter, 1, &status); 951 if (status != U_UNSUPPORTED_ERROR) { 952 errln("error: uiter_setState returned %s instead of U_UNSUPPORTED_ERROR", u_errorName(status)); 953 } 954 status = U_ZERO_ERROR; 955 uiter_setState(NULL, 1, &status); 956 if (status != U_ILLEGAL_ARGUMENT_ERROR) { 957 errln("error: uiter_setState returned %s instead of U_ILLEGAL_ARGUMENT_ERROR", u_errorName(status)); 958 } 959 if (uiter_getState(&sIter) != UITER_NO_STATE) { 960 errln("error: uiter_getState did not return UITER_NO_STATE on bad input"); 961 } 962 } 963 964 // subclass test, and completing API coverage ------------------------------- 965 966 class SubCharIter : public CharacterIterator { 967 public: 968 // public default constructor, to get coverage of CharacterIterator() 969 SubCharIter() : CharacterIterator() { 970 textLength=end=LENGTHOF(s); 971 s[0]=0x61; // 'a' 972 s[1]=0xd900; // U+50400 973 s[2]=0xdd00; 974 s[3]=0x2029; // PS 975 } 976 977 // useful stuff, mostly dummy but testing coverage and subclassability 978 virtual UChar nextPostInc() { 979 if(pos<LENGTHOF(s)) { 980 return s[pos++]; 981 } else { 982 return DONE; 983 } 984 } 985 986 virtual UChar32 next32PostInc() { 987 if(pos<LENGTHOF(s)) { 988 UChar32 c; 989 U16_NEXT(s, pos, LENGTHOF(s), c); 990 return c; 991 } else { 992 return DONE; 993 } 994 } 995 996 virtual UBool hasNext() { 997 return pos<LENGTHOF(s); 998 } 999 1000 virtual UChar first() { 1001 pos=0; 1002 return s[0]; 1003 } 1004 1005 virtual UChar32 first32() { 1006 UChar32 c; 1007 pos=0; 1008 U16_NEXT(s, pos, LENGTHOF(s), c); 1009 pos=0; 1010 return c; 1011 } 1012 1013 virtual UChar setIndex(int32_t position) { 1014 if(0<=position && position<=LENGTHOF(s)) { 1015 pos=position; 1016 if(pos<LENGTHOF(s)) { 1017 return s[pos]; 1018 } 1019 } 1020 return DONE; 1021 } 1022 1023 virtual UChar32 setIndex32(int32_t position) { 1024 if(0<=position && position<=LENGTHOF(s)) { 1025 pos=position; 1026 if(pos<LENGTHOF(s)) { 1027 UChar32 c; 1028 U16_GET(s, 0, pos, LENGTHOF(s), c); 1029 return c; 1030 } 1031 } 1032 return DONE; 1033 } 1034 1035 virtual UChar current() const { 1036 if(pos<LENGTHOF(s)) { 1037 return s[pos]; 1038 } else { 1039 return DONE; 1040 } 1041 } 1042 1043 virtual UChar32 current32() const { 1044 if(pos<LENGTHOF(s)) { 1045 UChar32 c; 1046 U16_GET(s, 0, pos, LENGTHOF(s), c); 1047 return c; 1048 } else { 1049 return DONE; 1050 } 1051 } 1052 1053 virtual UChar next() { 1054 if(pos<LENGTHOF(s) && ++pos<LENGTHOF(s)) { 1055 return s[pos]; 1056 } else { 1057 return DONE; 1058 } 1059 } 1060 1061 virtual UChar32 next32() { 1062 if(pos<LENGTHOF(s)) { 1063 U16_FWD_1(s, pos, LENGTHOF(s)); 1064 } 1065 if(pos<LENGTHOF(s)) { 1066 UChar32 c; 1067 int32_t i=pos; 1068 U16_NEXT(s, i, LENGTHOF(s), c); 1069 return c; 1070 } else { 1071 return DONE; 1072 } 1073 } 1074 1075 virtual UBool hasPrevious() { 1076 return pos>0; 1077 } 1078 1079 virtual void getText(UnicodeString &result) { 1080 result.setTo(s, LENGTHOF(s)); 1081 } 1082 1083 // dummy implementations of other pure virtual base class functions 1084 virtual UBool operator==(const ForwardCharacterIterator &that) const { 1085 return 1086 this==&that || 1087 (typeid(*this)==typeid(that) && pos==((SubCharIter &)that).pos); 1088 } 1089 1090 virtual int32_t hashCode() const { 1091 return 2; 1092 } 1093 1094 virtual CharacterIterator *clone() const { 1095 return NULL; 1096 } 1097 1098 virtual UChar last() { 1099 return 0; 1100 } 1101 1102 virtual UChar32 last32() { 1103 return 0; 1104 } 1105 1106 virtual UChar previous() { 1107 return 0; 1108 } 1109 1110 virtual UChar32 previous32() { 1111 return 0; 1112 } 1113 1114 virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) { 1115 return 0; 1116 } 1117 1118 virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) { 1119 return 0; 1120 } 1121 1122 // RTTI 1123 static UClassID getStaticClassID() { 1124 return (UClassID)(&fgClassID); 1125 } 1126 1127 virtual UClassID getDynamicClassID() const { 1128 return getStaticClassID(); 1129 } 1130 1131 private: 1132 // dummy string data 1133 UChar s[4]; 1134 1135 static const char fgClassID; 1136 }; 1137 1138 const char SubCharIter::fgClassID = 0; 1139 1140 class SubStringCharIter : public StringCharacterIterator { 1141 public: 1142 SubStringCharIter() { 1143 setText(UNICODE_STRING("abc", 3)); 1144 } 1145 }; 1146 1147 class SubUCharCharIter : public UCharCharacterIterator { 1148 public: 1149 SubUCharCharIter() { 1150 setText(u, 3); 1151 } 1152 1153 private: 1154 static const UChar u[3]; 1155 }; 1156 1157 const UChar SubUCharCharIter::u[3]={ 0x61, 0x62, 0x63 }; 1158 1159 void CharIterTest::TestCharIteratorSubClasses() { 1160 SubCharIter *p; 1161 1162 // coverage - call functions that are not otherwise tested 1163 // first[32]PostInc() are default implementations that are overridden 1164 // in ICU's own CharacterIterator subclasses 1165 p=new SubCharIter; 1166 if(p->firstPostInc()!=0x61) { 1167 errln("SubCharIter.firstPosInc() failed\n"); 1168 } 1169 delete p; 1170 1171 p=new SubCharIter[2]; 1172 if(p[1].first32PostInc()!=0x61) { 1173 errln("SubCharIter.first32PosInc() failed\n"); 1174 } 1175 delete [] p; 1176 1177 // coverage: StringCharacterIterator default constructor 1178 SubStringCharIter sci; 1179 if(sci.firstPostInc()!=0x61) { 1180 errln("SubStringCharIter.firstPostInc() failed\n"); 1181 } 1182 1183 // coverage: UCharCharacterIterator default constructor 1184 SubUCharCharIter uci; 1185 if(uci.firstPostInc()!=0x61) { 1186 errln("SubUCharCharIter.firstPostInc() failed\n"); 1187 } 1188 } 1189