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