]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/citrtest.cpp
ICU-511.31.tar.gz
[apple/icu.git] / icuSources / test / intltest / citrtest.cpp
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:
27 SCharacterIterator(const UnicodeString& textStr){
28 text = textStr;
29 pos=0;
30 textLength = textStr.length();
31 begin = 0;
32 end=textLength;
33
34 }
35
36 virtual ~SCharacterIterator(){};
37
38
39 void setText(const UnicodeString& newText){
40 text = newText;
41 }
42
43 virtual void getText(UnicodeString& result) {
44 text.extract(0,text.length(),result);
45 }
46 static UClassID getStaticClassID(void){
47 return (UClassID)(&fgClassID);
48 }
49 virtual UClassID getDynamicClassID(void) const{
50 return getStaticClassID();
51 }
52
53 virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{
54 return TRUE;
55 }
56
57 virtual CharacterIterator* clone(void) const {
58 return NULL;
59 }
60 virtual int32_t hashCode(void) const{
61 return DONE;
62 }
63 virtual UChar nextPostInc(void){ return text.charAt(pos++);}
64 virtual UChar32 next32PostInc(void){return text.char32At(pos++);}
65 virtual UBool hasNext() { return TRUE;};
66 virtual UChar first(){return DONE;};
67 virtual UChar32 first32(){return DONE;};
68 virtual UChar last(){return DONE;};
69 virtual UChar32 last32(){return DONE;};
70 virtual UChar setIndex(int32_t /*pos*/){return DONE;};
71 virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;};
72 virtual UChar current() const{return DONE;};
73 virtual UChar32 current32() const{return DONE;};
74 virtual UChar next(){return DONE;};
75 virtual UChar32 next32(){return DONE;};
76 virtual UChar previous(){return DONE;};
77 virtual UChar32 previous32(){return DONE;};
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 };
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 };
128 virtual UBool hasPrevious() {return TRUE;};
129
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
144 CharIterTest::CharIterTest()
145 {
146 }
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
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 }
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 }
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
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
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
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
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()
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
978 virtual UChar nextPostInc() {
979 if(pos<LENGTHOF(s)) {
980 return s[pos++];
981 } else {
982 return DONE;
983 }
984 }
985
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
996 virtual UBool hasNext() {
997 return pos<LENGTHOF(s);
998 }
999
1000 virtual UChar first() {
1001 pos=0;
1002 return s[0];
1003 }
1004
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
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
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
1035 virtual UChar current() const {
1036 if(pos<LENGTHOF(s)) {
1037 return s[pos];
1038 } else {
1039 return DONE;
1040 }
1041 }
1042
1043 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
1053 virtual UChar next() {
1054 if(pos<LENGTHOF(s) && ++pos<LENGTHOF(s)) {
1055 return s[pos];
1056 } else {
1057 return DONE;
1058 }
1059 }
1060
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
1075 virtual UBool hasPrevious() {
1076 return pos>0;
1077 }
1078
1079 virtual void getText(UnicodeString &result) {
1080 result.setTo(s, LENGTHOF(s));
1081 }
1082
1083 // dummy implementations of other pure virtual base class functions
1084 virtual UBool operator==(const ForwardCharacterIterator &that) const {
1085 return
1086 this==&that ||
1087 (typeid(*this)==typeid(that) && pos==((SubCharIter &)that).pos);
1088 }
1089
1090 virtual int32_t hashCode() const {
1091 return 2;
1092 }
1093
1094 virtual CharacterIterator *clone() const {
1095 return NULL;
1096 }
1097
1098 virtual UChar last() {
1099 return 0;
1100 }
1101
1102 virtual UChar32 last32() {
1103 return 0;
1104 }
1105
1106 virtual UChar previous() {
1107 return 0;
1108 }
1109
1110 virtual UChar32 previous32() {
1111 return 0;
1112 }
1113
1114 virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) {
1115 return 0;
1116 }
1117
1118 virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) {
1119 return 0;
1120 }
1121
1122 // RTTI
1123 static UClassID getStaticClassID() {
1124 return (UClassID)(&fgClassID);
1125 }
1126
1127 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:
1142 SubStringCharIter() {
1143 setText(UNICODE_STRING("abc", 3));
1144 }
1145 };
1146
1147 class SubUCharCharIter : public UCharCharacterIterator {
1148 public:
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
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 }