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