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