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