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