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