]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/citrtest.cpp
ICU-6.2.6.tar.gz
[apple/icu.git] / icuSources / test / intltest / citrtest.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2004, 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:
24 SCharacterIterator(const UnicodeString& textStr){
25 text = textStr;
26 pos=0;
27 textLength = textStr.length();
28 begin = 0;
29 end=textLength;
30
31 }
32
33 virtual ~SCharacterIterator(){};
34
35
36 void setText(const UnicodeString& newText){
37 text = newText;
38 }
39
40 virtual void getText(UnicodeString& result) {
41 text.extract(0,text.length(),result);
42 }
43 virtual UClassID getDynamicClassID(void) const{
44 return getStaticClassID();
45 }
46
47 static UClassID getStaticClassID(void){
48 return (UClassID)(&fgClassID);
49 }
50 virtual UBool operator==(const ForwardCharacterIterator& /*that*/) const{
51 return TRUE;
52 }
53
54 virtual CharacterIterator* clone(void) const {
55 return NULL;
56 }
57 virtual int32_t hashCode(void) const{
58 return DONE;
59 }
60 virtual UChar nextPostInc(void){ return text.charAt(pos++);}
61 virtual UChar32 next32PostInc(void){return text.char32At(pos++);}
62 virtual UBool hasNext() { return TRUE;};
63 virtual UChar first(){return DONE;};
64 virtual UChar32 first32(){return DONE;};
65 virtual UChar last(){return DONE;};
66 virtual UChar32 last32(){return DONE;};
67 virtual UChar setIndex(int32_t /*pos*/){return DONE;};
68 virtual UChar32 setIndex32(int32_t /*pos*/){return DONE;};
69 virtual UChar current() const{return DONE;};
70 virtual UChar32 current32() const{return DONE;};
71 virtual UChar next(){return DONE;};
72 virtual UChar32 next32(){return DONE;};
73 virtual UChar previous(){return DONE;};
74 virtual UChar32 previous32(){return DONE;};
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 };
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 };
125 virtual UBool hasPrevious() {return TRUE;};
126
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
141 CharIterTest::CharIterTest()
142 {
143 }
144 void CharIterTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
145 {
146 if (exec) logln("TestSuite LocaleTest: ");
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
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 }
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 }
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
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
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
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
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 }
945
946 // subclass test, and completing API coverage -------------------------------
947
948 class SubCharIter : public CharacterIterator {
949 public:
950 // public default constructor, to get coverage of CharacterIterator()
951 SubCharIter() : CharacterIterator() {
952 textLength=end=LENGTHOF(s);
953 s[0]=0x61; // 'a'
954 s[1]=0xd900; // U+50400
955 s[2]=0xdd00;
956 s[3]=0x2029; // PS
957 }
958
959 // useful stuff, mostly dummy but testing coverage and subclassability
960 virtual UChar nextPostInc() {
961 if(pos<LENGTHOF(s)) {
962 return s[pos++];
963 } else {
964 return DONE;
965 }
966 }
967
968 virtual UChar32 next32PostInc() {
969 if(pos<LENGTHOF(s)) {
970 UChar32 c;
971 U16_NEXT(s, pos, LENGTHOF(s), c);
972 return c;
973 } else {
974 return DONE;
975 }
976 }
977
978 virtual UBool hasNext() {
979 return pos<LENGTHOF(s);
980 }
981
982 virtual UChar first() {
983 pos=0;
984 return s[0];
985 }
986
987 virtual UChar32 first32() {
988 UChar32 c;
989 pos=0;
990 U16_NEXT(s, pos, LENGTHOF(s), c);
991 pos=0;
992 return c;
993 }
994
995 virtual UChar setIndex(int32_t position) {
996 if(0<=position && position<=LENGTHOF(s)) {
997 pos=position;
998 if(pos<LENGTHOF(s)) {
999 return s[pos];
1000 }
1001 }
1002 return DONE;
1003 }
1004
1005 virtual UChar32 setIndex32(int32_t position) {
1006 if(0<=position && position<=LENGTHOF(s)) {
1007 pos=position;
1008 if(pos<LENGTHOF(s)) {
1009 UChar32 c;
1010 U16_GET(s, 0, pos, LENGTHOF(s), c);
1011 return c;
1012 }
1013 }
1014 return DONE;
1015 }
1016
1017 virtual UChar current() const {
1018 if(pos<LENGTHOF(s)) {
1019 return s[pos];
1020 } else {
1021 return DONE;
1022 }
1023 }
1024
1025 virtual UChar32 current32() const {
1026 if(pos<LENGTHOF(s)) {
1027 UChar32 c;
1028 U16_GET(s, 0, pos, LENGTHOF(s), c);
1029 return c;
1030 } else {
1031 return DONE;
1032 }
1033 }
1034
1035 virtual UChar next() {
1036 if(pos<LENGTHOF(s) && ++pos<LENGTHOF(s)) {
1037 return s[pos];
1038 } else {
1039 return DONE;
1040 }
1041 }
1042
1043 virtual UChar32 next32() {
1044 if(pos<LENGTHOF(s)) {
1045 U16_FWD_1(s, pos, LENGTHOF(s));
1046 }
1047 if(pos<LENGTHOF(s)) {
1048 UChar32 c;
1049 int32_t i=pos;
1050 U16_NEXT(s, i, LENGTHOF(s), c);
1051 return c;
1052 } else {
1053 return DONE;
1054 }
1055 }
1056
1057 virtual UBool hasPrevious() {
1058 return pos>0;
1059 }
1060
1061 virtual void getText(UnicodeString &result) {
1062 result.setTo(s, LENGTHOF(s));
1063 }
1064
1065 // dummy implementations of other pure virtual base class functions
1066 virtual UBool operator==(const ForwardCharacterIterator &that) const {
1067 return
1068 this==&that ||
1069 getDynamicClassID()==that.getDynamicClassID() && pos==((SubCharIter &)that).pos;
1070 }
1071
1072 virtual int32_t hashCode() const {
1073 return 2;
1074 }
1075
1076 virtual CharacterIterator *clone() const {
1077 return NULL;
1078 }
1079
1080 virtual UChar last() {
1081 return 0;
1082 }
1083
1084 virtual UChar32 last32() {
1085 return 0;
1086 }
1087
1088 virtual UChar previous() {
1089 return 0;
1090 }
1091
1092 virtual UChar32 previous32() {
1093 return 0;
1094 }
1095
1096 virtual int32_t move(int32_t /*delta*/, EOrigin /*origin*/) {
1097 return 0;
1098 }
1099
1100 virtual int32_t move32(int32_t /*delta*/, EOrigin /*origin*/) {
1101 return 0;
1102 }
1103
1104 // RTTI
1105 virtual UClassID getDynamicClassID() const {
1106 return getStaticClassID();
1107 }
1108
1109 static UClassID getStaticClassID() {
1110 return (UClassID)(&fgClassID);
1111 }
1112
1113 private:
1114 // dummy string data
1115 UChar s[4];
1116
1117 static const char fgClassID;
1118 };
1119
1120 const char SubCharIter::fgClassID = 0;
1121
1122 class SubStringCharIter : public StringCharacterIterator {
1123 public:
1124 SubStringCharIter() {
1125 setText(UNICODE_STRING("abc", 3));
1126 }
1127 };
1128
1129 class SubUCharCharIter : public UCharCharacterIterator {
1130 public:
1131 SubUCharCharIter() {
1132 setText(u, 3);
1133 }
1134
1135 private:
1136 static const UChar u[3];
1137 };
1138
1139 const UChar SubUCharCharIter::u[3]={ 0x61, 0x62, 0x63 };
1140
1141 void CharIterTest::TestCharIteratorSubClasses() {
1142 SubCharIter *p;
1143
1144 // coverage - call functions that are not otherwise tested
1145 // first[32]PostInc() are default implementations that are overridden
1146 // in ICU's own CharacterIterator subclasses
1147 p=new SubCharIter;
1148 if(p->firstPostInc()!=0x61) {
1149 errln("SubCharIter.firstPosInc() failed\n");
1150 }
1151 delete p;
1152
1153 p=new SubCharIter[2];
1154 if(p[1].first32PostInc()!=0x61) {
1155 errln("SubCharIter.first32PosInc() failed\n");
1156 }
1157 delete [] p;
1158
1159 // coverage: StringCharacterIterator default constructor
1160 SubStringCharIter sci;
1161 if(sci.firstPostInc()!=0x61) {
1162 errln("SubStringCharIter.firstPostInc() failed\n");
1163 }
1164
1165 // coverage: UCharCharacterIterator default constructor
1166 SubUCharCharIter uci;
1167 if(uci.firstPostInc()!=0x61) {
1168 errln("SubUCharCharIter.firstPostInc() failed\n");
1169 }
1170 }