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