1 /****************************************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 * Modification History:
6 *
7 * Date Name Description
8 * 05/22/2000 Madhu Added tests for testing new API for utf16 support and more
9 ****************************************************************************************/
10
11 #include <string.h>
12 #include "utypeinfo.h" // for 'typeid' to work
13
14 #include "unicode/chariter.h"
15 #include "unicode/ustring.h"
16 #include "unicode/unistr.h"
17 #include "unicode/schriter.h"
18 #include "unicode/uchriter.h"
19 #include "unicode/uiter.h"
20 #include "unicode/putil.h"
21 #include "unicode/utf16.h"
22 #include "citrtest.h"
23 #include "cmemory.h"
24
25
26 class SCharacterIterator : public CharacterIterator {
27 public:
SCharacterIterator(const UnicodeString & textStr)28 SCharacterIterator(const UnicodeString& textStr){
29 text = textStr;
30 pos=0;
31 textLength = textStr.length();
32 begin = 0;
33 end=textLength;
34
35 }
36
~SCharacterIterator()37 virtual ~SCharacterIterator(){};
38
39
setText(const UnicodeString & newText)40 void setText(const UnicodeString& newText){
41 text = newText;
42 }
43
getText(UnicodeString & result)44 virtual void getText(UnicodeString& result) {
45 text.extract(0,text.length(),result);
46 }
getStaticClassID(void)47 static UClassID getStaticClassID(void){
48 return (UClassID)(&fgClassID);
49 }
getDynamicClassID(void) const50 virtual UClassID getDynamicClassID(void) const{
51 return getStaticClassID();
52 }
53
operator ==(const ForwardCharacterIterator &) const54 virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{
55 return TRUE;
56 }
57
clone(void) const58 virtual CharacterIterator* clone(void) const {
59 return NULL;
60 }
hashCode(void) const61 virtual int32_t hashCode(void) const{
62 return DONE;
63 }
nextPostInc(void)64 virtual UChar nextPostInc(void){ return text.charAt(pos++);}
next32PostInc(void)65 virtual UChar32 next32PostInc(void){return text.char32At(pos++);}
hasNext()66 virtual UBool hasNext() { return TRUE;};
first()67 virtual UChar first(){return DONE;};
first32()68 virtual UChar32 first32(){return DONE;};
last()69 virtual UChar last(){return DONE;};
last32()70 virtual UChar32 last32(){return DONE;};
setIndex(int32_t)71 virtual UChar setIndex(int32_t /*pos*/){return DONE;};
setIndex32(int32_t)72 virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;};
current() const73 virtual UChar current() const{return DONE;};
current32() const74 virtual UChar32 current32() const{return DONE;};
next()75 virtual UChar next(){return DONE;};
next32()76 virtual UChar32 next32(){return DONE;};
previous()77 virtual UChar previous(){return DONE;};
previous32()78 virtual UChar32 previous32(){return DONE;};
move(int32_t delta,CharacterIterator::EOrigin origin)79 virtual int32_t move(int32_t delta,CharacterIterator::EOrigin origin){
80 switch(origin) {
81 case kStart:
82 pos = begin + delta;
83 break;
84 case kCurrent:
85 pos += delta;
86 break;
87 case kEnd:
88 pos = end + delta;
89 break;
90 default:
91 break;
92 }
93
94 if(pos < begin) {
95 pos = begin;
96 } else if(pos > end) {
97 pos = end;
98 }
99
100 return pos;
101 };
move32(int32_t delta,CharacterIterator::EOrigin origin)102 virtual int32_t move32(int32_t delta, CharacterIterator::EOrigin origin){
103 switch(origin) {
104 case kStart:
105 pos = begin;
106 if(delta > 0) {
107 U16_FWD_N(text, pos, end, delta);
108 }
109 break;
110 case kCurrent:
111 if(delta > 0) {
112 U16_FWD_N(text, pos, end, delta);
113 } else {
114 U16_BACK_N(text, begin, pos, -delta);
115 }
116 break;
117 case kEnd:
118 pos = end;
119 if(delta < 0) {
120 U16_BACK_N(text, begin, pos, -delta);
121 }
122 break;
123 default:
124 break;
125 }
126
127 return pos;
128 };
hasPrevious()129 virtual UBool hasPrevious() {return TRUE;};
130
operator =(const SCharacterIterator & that)131 SCharacterIterator& operator=(const SCharacterIterator& that){
132 text = that.text;
133 return *this;
134 }
135
136
137 private:
138 UnicodeString text;
139 static const char fgClassID;
140 };
141 const char SCharacterIterator::fgClassID=0;
142
CharIterTest()143 CharIterTest::CharIterTest()
144 {
145 }
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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
TestCoverage()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 }
TestConstructionAndEquality()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 }
TestConstructionAndEqualityUChariter()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
TestIteration()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
TestIterationUChar32()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() != U16_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
TestUCharIterator(UCharIterator * iter,CharacterIterator & ci,const char * moves,const char * which)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
TestUCharIterator()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()
SubCharIter()968 SubCharIter() : CharacterIterator() {
969 textLength=end=UPRV_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
nextPostInc()977 virtual UChar nextPostInc() {
978 if(pos<UPRV_LENGTHOF(s)) {
979 return s[pos++];
980 } else {
981 return DONE;
982 }
983 }
984
next32PostInc()985 virtual UChar32 next32PostInc() {
986 if(pos<UPRV_LENGTHOF(s)) {
987 UChar32 c;
988 U16_NEXT(s, pos, UPRV_LENGTHOF(s), c);
989 return c;
990 } else {
991 return DONE;
992 }
993 }
994
hasNext()995 virtual UBool hasNext() {
996 return pos<UPRV_LENGTHOF(s);
997 }
998
first()999 virtual UChar first() {
1000 pos=0;
1001 return s[0];
1002 }
1003
first32()1004 virtual UChar32 first32() {
1005 UChar32 c;
1006 pos=0;
1007 U16_NEXT(s, pos, UPRV_LENGTHOF(s), c);
1008 pos=0;
1009 return c;
1010 }
1011
setIndex(int32_t position)1012 virtual UChar setIndex(int32_t position) {
1013 if(0<=position && position<=UPRV_LENGTHOF(s)) {
1014 pos=position;
1015 if(pos<UPRV_LENGTHOF(s)) {
1016 return s[pos];
1017 }
1018 }
1019 return DONE;
1020 }
1021
setIndex32(int32_t position)1022 virtual UChar32 setIndex32(int32_t position) {
1023 if(0<=position && position<=UPRV_LENGTHOF(s)) {
1024 pos=position;
1025 if(pos<UPRV_LENGTHOF(s)) {
1026 UChar32 c;
1027 U16_GET(s, 0, pos, UPRV_LENGTHOF(s), c);
1028 return c;
1029 }
1030 }
1031 return DONE;
1032 }
1033
current() const1034 virtual UChar current() const {
1035 if(pos<UPRV_LENGTHOF(s)) {
1036 return s[pos];
1037 } else {
1038 return DONE;
1039 }
1040 }
1041
current32() const1042 virtual UChar32 current32() const {
1043 if(pos<UPRV_LENGTHOF(s)) {
1044 UChar32 c;
1045 U16_GET(s, 0, pos, UPRV_LENGTHOF(s), c);
1046 return c;
1047 } else {
1048 return DONE;
1049 }
1050 }
1051
next()1052 virtual UChar next() {
1053 if(pos<UPRV_LENGTHOF(s) && ++pos<UPRV_LENGTHOF(s)) {
1054 return s[pos];
1055 } else {
1056 return DONE;
1057 }
1058 }
1059
next32()1060 virtual UChar32 next32() {
1061 if(pos<UPRV_LENGTHOF(s)) {
1062 U16_FWD_1(s, pos, UPRV_LENGTHOF(s));
1063 }
1064 if(pos<UPRV_LENGTHOF(s)) {
1065 UChar32 c;
1066 int32_t i=pos;
1067 U16_NEXT(s, i, UPRV_LENGTHOF(s), c);
1068 return c;
1069 } else {
1070 return DONE;
1071 }
1072 }
1073
hasPrevious()1074 virtual UBool hasPrevious() {
1075 return pos>0;
1076 }
1077
getText(UnicodeString & result)1078 virtual void getText(UnicodeString &result) {
1079 result.setTo(s, UPRV_LENGTHOF(s));
1080 }
1081
1082 // dummy implementations of other pure virtual base class functions
operator ==(const ForwardCharacterIterator & that) const1083 virtual UBool operator==(const ForwardCharacterIterator &that) const {
1084 return
1085 this==&that ||
1086 (typeid(*this)==typeid(that) && pos==((SubCharIter &)that).pos);
1087 }
1088
hashCode() const1089 virtual int32_t hashCode() const {
1090 return 2;
1091 }
1092
clone() const1093 virtual CharacterIterator *clone() const {
1094 return NULL;
1095 }
1096
last()1097 virtual UChar last() {
1098 return 0;
1099 }
1100
last32()1101 virtual UChar32 last32() {
1102 return 0;
1103 }
1104
previous()1105 virtual UChar previous() {
1106 return 0;
1107 }
1108
previous32()1109 virtual UChar32 previous32() {
1110 return 0;
1111 }
1112
move(int32_t,EOrigin)1113 virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) {
1114 return 0;
1115 }
1116
move32(int32_t,EOrigin)1117 virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) {
1118 return 0;
1119 }
1120
1121 // RTTI
getStaticClassID()1122 static UClassID getStaticClassID() {
1123 return (UClassID)(&fgClassID);
1124 }
1125
getDynamicClassID() const1126 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:
SubStringCharIter()1141 SubStringCharIter() {
1142 setText(UNICODE_STRING("abc", 3));
1143 }
1144 };
1145
1146 class SubUCharCharIter : public UCharCharacterIterator {
1147 public:
SubUCharCharIter()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
TestCharIteratorSubClasses()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