OLD | NEW |
1 /* | 1 /* |
2 ****************************************************************************** | 2 ****************************************************************************** |
3 * | 3 * |
4 * Copyright (C) 2002-2010, International Business Machines | 4 * Copyright (C) 2002-2014, International Business Machines |
5 * Corporation and others. All Rights Reserved. | 5 * Corporation and others. All Rights Reserved. |
6 * | 6 * |
7 ****************************************************************************** | 7 ****************************************************************************** |
8 * file name: custrtst.c | 8 * file name: custrtst.c |
9 * encoding: US-ASCII | 9 * encoding: US-ASCII |
10 * tab size: 8 (not used) | 10 * tab size: 8 (not used) |
11 * indentation:4 | 11 * indentation:4 |
12 * | 12 * |
13 * created on: 2002oct09 | 13 * created on: 2002oct09 |
14 * created by: Markus W. Scherer | 14 * created by: Markus W. Scherer |
15 * | 15 * |
16 * Tests of ustring.h Unicode string API functions. | 16 * Tests of ustring.h Unicode string API functions. |
17 */ | 17 */ |
18 | 18 |
19 #include "unicode/ustring.h" | 19 #include "unicode/ustring.h" |
20 #include "unicode/ucnv.h" | 20 #include "unicode/ucnv.h" |
21 #include "unicode/uiter.h" | 21 #include "unicode/uiter.h" |
22 #include "cintltst.h" | 22 #include "cintltst.h" |
| 23 #include "cmemory.h" |
23 #include <string.h> | 24 #include <string.h> |
24 | 25 |
25 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0])) | |
26 | |
27 /* get the sign of an integer */ | 26 /* get the sign of an integer */ |
28 #define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1) | 27 #define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1) |
29 | 28 |
30 /* test setup --------------------------------------------------------------- */ | 29 /* test setup --------------------------------------------------------------- */ |
31 | 30 |
32 static void setUpDataTable(void); | 31 static void setUpDataTable(void); |
33 static void TestStringCopy(void); | 32 static void TestStringCopy(void); |
34 static void TestStringFunctions(void); | 33 static void TestStringFunctions(void); |
35 static void TestStringSearching(void); | 34 static void TestStringSearching(void); |
36 static void TestSurrogateSearching(void); | 35 static void TestSurrogateSearching(void); |
37 static void TestUnescape(void); | 36 static void TestUnescape(void); |
38 static void TestCountChar32(void); | 37 static void TestCountChar32(void); |
39 static void TestUCharIterator(void); | 38 static void TestUCharIterator(void); |
40 static void TestUNormIterator(void); | |
41 static void TestBadUNormIterator(void); | |
42 | 39 |
43 void addUStringTest(TestNode** root); | 40 void addUStringTest(TestNode** root); |
44 | 41 |
45 void addUStringTest(TestNode** root) | 42 void addUStringTest(TestNode** root) |
46 { | 43 { |
47 addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy"); | 44 addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy"); |
48 addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions"); | 45 addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions"); |
49 addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching"); | 46 addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching"); |
50 addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearchi
ng"); | 47 addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearchi
ng"); |
51 addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape"); | 48 addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape"); |
52 addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32"); | 49 addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32"); |
53 addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator"); | 50 addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator"); |
54 addTest(root, &TestUNormIterator, "tsutil/custrtst/TestUNormIterator"); | |
55 addTest(root, &TestBadUNormIterator, "tsutil/custrtst/TestBadUNormIterator")
; | |
56 } | 51 } |
57 | 52 |
58 /* test data for TestStringFunctions ---------------------------------------- */ | 53 /* test data for TestStringFunctions ---------------------------------------- */ |
59 | 54 |
60 UChar*** dataTable = NULL; | 55 UChar*** dataTable = NULL; |
61 | 56 |
62 static const char* raw[3][4] = { | 57 static const char* raw[3][4] = { |
63 | 58 |
64 /* First String */ | 59 /* First String */ |
65 { "English_", "French_", "Croatian_", "English_"}, | 60 { "English_", "French_", "Croatian_", "English_"}, |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456; | 711 static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456; |
717 | 712 |
718 const UChar *first, *last; | 713 const UChar *first, *last; |
719 | 714 |
720 /* search for NUL code point: find end of string */ | 715 /* search for NUL code point: find end of string */ |
721 first=s+u_strlen(s); | 716 first=s+u_strlen(s); |
722 | 717 |
723 if( | 718 if( |
724 first!=u_strchr(s, nul) || | 719 first!=u_strchr(s, nul) || |
725 first!=u_strchr32(s, nul) || | 720 first!=u_strchr32(s, nul) || |
726 first!=u_memchr(s, nul, LENGTHOF(s)) || | 721 first!=u_memchr(s, nul, UPRV_LENGTHOF(s)) || |
727 first!=u_memchr32(s, nul, LENGTHOF(s)) || | 722 first!=u_memchr32(s, nul, UPRV_LENGTHOF(s)) || |
728 first!=u_strrchr(s, nul) || | 723 first!=u_strrchr(s, nul) || |
729 first!=u_strrchr32(s, nul) || | 724 first!=u_strrchr32(s, nul) || |
730 first!=u_memrchr(s, nul, LENGTHOF(s)) || | 725 first!=u_memrchr(s, nul, UPRV_LENGTHOF(s)) || |
731 first!=u_memrchr32(s, nul, LENGTHOF(s)) | 726 first!=u_memrchr32(s, nul, UPRV_LENGTHOF(s)) |
732 ) { | 727 ) { |
733 log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find t
he terminator of s\n"); | 728 log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find t
he terminator of s\n"); |
734 } | 729 } |
735 | 730 |
736 /* search for empty substring: find beginning of string */ | 731 /* search for empty substring: find beginning of string */ |
737 if( | 732 if( |
738 s!=u_strstr(s, &nul) || | 733 s!=u_strstr(s, &nul) || |
739 s!=u_strFindFirst(s, -1, &nul, -1) || | 734 s!=u_strFindFirst(s, -1, &nul, -1) || |
740 s!=u_strFindFirst(s, -1, &nul, 0) || | 735 s!=u_strFindFirst(s, -1, &nul, 0) || |
741 s!=u_strFindFirst(s, LENGTHOF(s), &nul, -1) || | 736 s!=u_strFindFirst(s, UPRV_LENGTHOF(s), &nul, -1) || |
742 s!=u_strFindFirst(s, LENGTHOF(s), &nul, 0) || | 737 s!=u_strFindFirst(s, UPRV_LENGTHOF(s), &nul, 0) || |
743 s!=u_strrstr(s, &nul) || | 738 s!=u_strrstr(s, &nul) || |
744 s!=u_strFindLast(s, -1, &nul, -1) || | 739 s!=u_strFindLast(s, -1, &nul, -1) || |
745 s!=u_strFindLast(s, -1, &nul, 0) || | 740 s!=u_strFindLast(s, -1, &nul, 0) || |
746 s!=u_strFindLast(s, LENGTHOF(s), &nul, -1) || | 741 s!=u_strFindLast(s, UPRV_LENGTHOF(s), &nul, -1) || |
747 s!=u_strFindLast(s, LENGTHOF(s), &nul, 0) | 742 s!=u_strFindLast(s, UPRV_LENGTHOF(s), &nul, 0) |
748 ) { | 743 ) { |
749 log_err("error: one of the u_str[str etc](s, \"\") does not find s itsel
f\n"); | 744 log_err("error: one of the u_str[str etc](s, \"\") does not find s itsel
f\n"); |
750 } | 745 } |
751 | 746 |
752 /* find 'a' in s[1..10[ */ | 747 /* find 'a' in s[1..10[ */ |
753 first=s+3; | 748 first=s+3; |
754 last=s+7; | 749 last=s+7; |
755 if( | 750 if( |
756 first!=u_strchr(s+1, a) || | 751 first!=u_strchr(s+1, a) || |
757 first!=u_strchr32(s+1, a) || | 752 first!=u_strchr32(s+1, a) || |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 0x61, 0x62, 0xd800, 0xdc00, | 1136 0x61, 0x62, 0xd800, 0xdc00, |
1142 0xd801, 0xdc01, 0x63, 0xd802, | 1137 0xd801, 0xdc01, 0x63, 0xd802, |
1143 0x64, 0xdc03, 0x65, 0x66, | 1138 0x64, 0xdc03, 0x65, 0x66, |
1144 0xd804, 0xdc04, 0xd805, 0xdc05, | 1139 0xd804, 0xdc04, 0xd805, 0xdc05, |
1145 0x67 | 1140 0x67 |
1146 }; | 1141 }; |
1147 UChar buffer[100]; | 1142 UChar buffer[100]; |
1148 int32_t i, length, number; | 1143 int32_t i, length, number; |
1149 | 1144 |
1150 /* test u_strHasMoreChar32Than() with length>=0 */ | 1145 /* test u_strHasMoreChar32Than() with length>=0 */ |
1151 length=LENGTHOF(string); | 1146 length=UPRV_LENGTHOF(string); |
1152 while(length>=0) { | 1147 while(length>=0) { |
1153 for(i=0; i<=length; ++i) { | 1148 for(i=0; i<=length; ++i) { |
1154 for(number=-1; number<=((length-i)+2); ++number) { | 1149 for(number=-1; number<=((length-i)+2); ++number) { |
1155 _testStrHasMoreChar32Than(string+i, i, length-i, number); | 1150 _testStrHasMoreChar32Than(string+i, i, length-i, number); |
1156 } | 1151 } |
1157 } | 1152 } |
1158 --length; | 1153 --length; |
1159 } | 1154 } |
1160 | 1155 |
1161 /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */ | 1156 /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */ |
1162 length=LENGTHOF(string); | 1157 length=UPRV_LENGTHOF(string); |
1163 u_memcpy(buffer, string, length); | 1158 u_memcpy(buffer, string, length); |
1164 while(length>=0) { | 1159 while(length>=0) { |
1165 buffer[length]=0; | 1160 buffer[length]=0; |
1166 for(i=0; i<=length; ++i) { | 1161 for(i=0; i<=length; ++i) { |
1167 for(number=-1; number<=((length-i)+2); ++number) { | 1162 for(number=-1; number<=((length-i)+2); ++number) { |
1168 _testStrHasMoreChar32Than(string+i, i, -1, number); | 1163 _testStrHasMoreChar32Than(string+i, i, -1, number); |
1169 } | 1164 } |
1170 } | 1165 } |
1171 --length; | 1166 --length; |
1172 } | 1167 } |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 /* simple API/code coverage - test NOOP UCharIterator */ | 1446 /* simple API/code coverage - test NOOP UCharIterator */ |
1452 uiter_setString(&iter, NULL, 0); | 1447 uiter_setString(&iter, NULL, 0); |
1453 if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!
=-1 || | 1448 if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!
=-1 || |
1454 iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT
)!=0 || | 1449 iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT
)!=0 || |
1455 iter.hasNext(&iter) || iter.hasPrevious(&iter) | 1450 iter.hasNext(&iter) || iter.hasPrevious(&iter) |
1456 ) { | 1451 ) { |
1457 log_err("NOOP UCharIterator behaves unexpectedly\n"); | 1452 log_err("NOOP UCharIterator behaves unexpectedly\n"); |
1458 } | 1453 } |
1459 | 1454 |
1460 /* test get/set state */ | 1455 /* test get/set state */ |
1461 length=LENGTHOF(text)-1; | 1456 length=UPRV_LENGTHOF(text)-1; |
1462 uiter_setString(&iter1, text, -1); | 1457 uiter_setString(&iter1, text, -1); |
1463 uiter_setString(&iter2, text, length); | 1458 uiter_setString(&iter2, text, length); |
1464 testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2); | 1459 testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2); |
1465 testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1); | 1460 testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1); |
1466 | 1461 |
1467 /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */ | 1462 /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */ |
1468 errorCode=U_ZERO_ERROR; | 1463 errorCode=U_ZERO_ERROR; |
1469 u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode); | 1464 u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode); |
1470 if(U_FAILURE(errorCode)) { | 1465 if(U_FAILURE(errorCode)) { |
1471 log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode)); | 1466 log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode)); |
1472 return; | 1467 return; |
1473 } | 1468 } |
1474 | 1469 |
1475 uiter_setString(&iter1, text, -1); | 1470 uiter_setString(&iter1, text, -1); |
1476 uiter_setUTF8(&iter2, bytes, length); | 1471 uiter_setUTF8(&iter2, bytes, length); |
1477 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator"); | 1472 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator"); |
1478 | 1473 |
1479 /* try again with length=-1 */ | 1474 /* try again with length=-1 */ |
1480 uiter_setUTF8(&iter2, bytes, -1); | 1475 uiter_setUTF8(&iter2, bytes, -1); |
1481 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1"); | 1476 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1"); |
1482 | 1477 |
1483 /* test get/set state */ | 1478 /* test get/set state */ |
1484 length=LENGTHOF(text)-1; | 1479 length=UPRV_LENGTHOF(text)-1; |
1485 uiter_setUTF8(&iter1, bytes, -1); | 1480 uiter_setUTF8(&iter1, bytes, -1); |
1486 testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2); | 1481 testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2); |
1487 testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1); | 1482 testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1); |
1488 | 1483 |
1489 /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */ | 1484 /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */ |
1490 errorCode=U_ZERO_ERROR; | 1485 errorCode=U_ZERO_ERROR; |
1491 cnv=ucnv_open("UTF-16BE", &errorCode); | 1486 cnv=ucnv_open("UTF-16BE", &errorCode); |
1492 length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode); | 1487 length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode); |
1493 ucnv_close(cnv); | 1488 ucnv_close(cnv); |
1494 if(U_FAILURE(errorCode)) { | 1489 if(U_FAILURE(errorCode)) { |
(...skipping 12 matching lines...) Expand all Loading... |
1507 uiter_setUTF16BE(&iter2, bytes, -1); | 1502 uiter_setUTF16BE(&iter2, bytes, -1); |
1508 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1"); | 1503 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1"); |
1509 | 1504 |
1510 /* try again after moving the bytes up one, and with length=-1 */ | 1505 /* try again after moving the bytes up one, and with length=-1 */ |
1511 memmove(bytes+1, bytes, length+2); | 1506 memmove(bytes+1, bytes, length+2); |
1512 uiter_setUTF16BE(&iter2, bytes+1, -1); | 1507 uiter_setUTF16BE(&iter2, bytes+1, -1); |
1513 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1"); | 1508 compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1"); |
1514 | 1509 |
1515 /* ### TODO test other iterators: CharacterIterator, Replaceable */ | 1510 /* ### TODO test other iterators: CharacterIterator, Replaceable */ |
1516 } | 1511 } |
1517 | |
1518 #if UCONFIG_NO_COLLATION | |
1519 | |
1520 static void | |
1521 TestUNormIterator() { | |
1522 /* test nothing */ | |
1523 } | |
1524 | |
1525 static void | |
1526 TestBadUNormIterator(void) { | |
1527 /* test nothing, as well */ | |
1528 } | |
1529 | |
1530 #else | |
1531 | |
1532 #include "unicode/unorm.h" | |
1533 #include "unorm_it.h" | |
1534 | |
1535 /* | |
1536 * Compare results from two iterators, should be same. | |
1537 * Assume that the text is not empty and that | |
1538 * iteration start==0 and iteration limit==length. | |
1539 * | |
1540 * Modified version of compareIterators() but does not assume that indexes | |
1541 * are available. | |
1542 */ | |
1543 static void | |
1544 compareIterNoIndexes(UCharIterator *iter1, const char *n1, | |
1545 UCharIterator *iter2, const char *n2, | |
1546 int32_t middle) { | |
1547 uint32_t state; | |
1548 int32_t i; | |
1549 UChar32 c1, c2; | |
1550 UErrorCode errorCode; | |
1551 | |
1552 /* code coverage for unorm_it.c/unormIteratorGetIndex() */ | |
1553 if( | |
1554 iter2->getIndex(iter2, UITER_START)!=0 || | |
1555 iter2->getIndex(iter2, UITER_LENGTH)!=UITER_UNKNOWN_INDEX | |
1556 ) { | |
1557 log_err("UNormIterator.getIndex() failed\n"); | |
1558 } | |
1559 | |
1560 /* set into the middle */ | |
1561 iter1->move(iter1, middle, UITER_ZERO); | |
1562 iter2->move(iter2, middle, UITER_ZERO); | |
1563 | |
1564 /* test current() */ | |
1565 c1=iter1->current(iter1); | |
1566 c2=iter2->current(iter2); | |
1567 if(c1!=c2) { | |
1568 log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n
1, c1, c2, n2, middle); | |
1569 return; | |
1570 } | |
1571 | |
1572 /* move forward 3 UChars */ | |
1573 for(i=0; i<3; ++i) { | |
1574 c1=iter1->next(iter1); | |
1575 c2=iter2->next(iter2); | |
1576 if(c1!=c2) { | |
1577 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in mi
ddle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); | |
1578 return; | |
1579 } | |
1580 } | |
1581 | |
1582 /* move backward 5 UChars */ | |
1583 for(i=0; i<5; ++i) { | |
1584 c1=iter1->previous(iter1); | |
1585 c2=iter2->previous(iter2); | |
1586 if(c1!=c2) { | |
1587 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (start
ed in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); | |
1588 return; | |
1589 } | |
1590 } | |
1591 | |
1592 /* iterate forward from the beginning */ | |
1593 iter1->move(iter1, 0, UITER_START); | |
1594 if(!iter1->hasNext(iter1)) { | |
1595 log_err("%s->hasNext() at the start returns FALSE\n", n1); | |
1596 return; | |
1597 } | |
1598 | |
1599 iter2->move(iter2, 0, UITER_START); | |
1600 if(!iter2->hasNext(iter2)) { | |
1601 log_err("%s->hasNext() at the start returns FALSE\n", n2); | |
1602 return; | |
1603 } | |
1604 | |
1605 do { | |
1606 c1=iter1->next(iter1); | |
1607 c2=iter2->next(iter2); | |
1608 if(c1!=c2) { | |
1609 log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2
, n2, iter1->getIndex(iter1, UITER_CURRENT)); | |
1610 return; | |
1611 } | |
1612 } while(c1>=0); | |
1613 | |
1614 if(iter1->hasNext(iter1)) { | |
1615 log_err("%s->hasNext() at the end returns TRUE\n", n1); | |
1616 return; | |
1617 } | |
1618 if(iter2->hasNext(iter2)) { | |
1619 log_err("%s->hasNext() at the end returns TRUE\n", n2); | |
1620 return; | |
1621 } | |
1622 | |
1623 /* iterate backward */ | |
1624 do { | |
1625 c1=iter1->previous(iter1); | |
1626 c2=iter2->previous(iter2); | |
1627 if(c1!=c2) { | |
1628 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1
, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); | |
1629 return; | |
1630 } | |
1631 } while(c1>=0); | |
1632 | |
1633 /* back to the middle */ | |
1634 iter1->move(iter1, middle, UITER_ZERO); | |
1635 iter2->move(iter2, middle, UITER_ZERO); | |
1636 | |
1637 /* try get/set state */ | |
1638 while((state=uiter_getState(iter2))==UITER_NO_STATE) { | |
1639 if(!iter2->hasNext(iter2)) { | |
1640 log_err("%s has no known state from middle=%d to the end\n", n2, mid
dle); | |
1641 return; | |
1642 } | |
1643 iter2->next(iter2); | |
1644 } | |
1645 | |
1646 errorCode=U_ZERO_ERROR; | |
1647 | |
1648 c2=iter2->current(iter2); | |
1649 iter2->move(iter2, 0, UITER_ZERO); | |
1650 uiter_setState(iter2, state, &errorCode); | |
1651 c1=iter2->current(iter2); | |
1652 if(U_FAILURE(errorCode) || c1!=c2) { | |
1653 log_err("%s->current() differs across get/set state, U+%04x vs. U+%04x\n
", n2, c2, c1); | |
1654 return; | |
1655 } | |
1656 | |
1657 c2=iter2->previous(iter2); | |
1658 iter2->move(iter2, 0, UITER_ZERO); | |
1659 uiter_setState(iter2, state, &errorCode); | |
1660 c1=iter2->previous(iter2); | |
1661 if(U_FAILURE(errorCode) || c1!=c2) { | |
1662 log_err("%s->previous() differs across get/set state, U+%04x vs. U+%04x\
n", n2, c2, c1); | |
1663 return; | |
1664 } | |
1665 | |
1666 /* iterate backward from the end */ | |
1667 iter1->move(iter1, 0, UITER_LIMIT); | |
1668 if(!iter1->hasPrevious(iter1)) { | |
1669 log_err("%s->hasPrevious() at the end returns FALSE\n", n1); | |
1670 return; | |
1671 } | |
1672 | |
1673 iter2->move(iter2, 0, UITER_LIMIT); | |
1674 if(!iter2->hasPrevious(iter2)) { | |
1675 log_err("%s->hasPrevious() at the end returns FALSE\n", n2); | |
1676 return; | |
1677 } | |
1678 | |
1679 do { | |
1680 c1=iter1->previous(iter1); | |
1681 c2=iter2->previous(iter2); | |
1682 if(c1!=c2) { | |
1683 log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1
, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT)); | |
1684 return; | |
1685 } | |
1686 } while(c1>=0); | |
1687 | |
1688 if(iter1->hasPrevious(iter1)) { | |
1689 log_err("%s->hasPrevious() at the start returns TRUE\n", n1); | |
1690 return; | |
1691 } | |
1692 if(iter2->hasPrevious(iter2)) { | |
1693 log_err("%s->hasPrevious() at the start returns TRUE\n", n2); | |
1694 return; | |
1695 } | |
1696 } | |
1697 | |
1698 /* n2 must have a digit 1 at the end, will be incremented with the normalization
mode */ | |
1699 static void | |
1700 testUNormIteratorWithText(const UChar *text, int32_t textLength, int32_t middle, | |
1701 const char *name1, const char *n2) { | |
1702 UChar buffer[600]; | |
1703 char name2[40]; | |
1704 | |
1705 UCharIterator iter1, iter2, *iter; | |
1706 UNormIterator *uni; | |
1707 | |
1708 UNormalizationMode mode; | |
1709 UErrorCode errorCode; | |
1710 int32_t length; | |
1711 | |
1712 /* open a normalizing iterator */ | |
1713 errorCode=U_ZERO_ERROR; | |
1714 uni=unorm_openIter(NULL, 0, &errorCode); | |
1715 if(U_FAILURE(errorCode)) { | |
1716 log_err("unorm_openIter() fails: %s\n", u_errorName(errorCode)); | |
1717 return; | |
1718 } | |
1719 | |
1720 /* set iterator 2 to the original text */ | |
1721 uiter_setString(&iter2, text, textLength); | |
1722 | |
1723 strcpy(name2, n2); | |
1724 | |
1725 /* test the normalizing iterator for each mode */ | |
1726 for(mode=UNORM_NONE; mode<UNORM_MODE_COUNT; ++mode) { | |
1727 length=unorm_normalize(text, textLength, mode, 0, buffer, LENGTHOF(buffe
r), &errorCode); | |
1728 if(U_FAILURE(errorCode)) { | |
1729 log_data_err("unorm_normalize(mode %d) failed: %s - (Are you missing
data?)\n", mode, u_errorName(errorCode)); | |
1730 break; | |
1731 } | |
1732 | |
1733 /* set iterator 1 to the normalized text */ | |
1734 uiter_setString(&iter1, buffer, length); | |
1735 | |
1736 /* set the normalizing iterator to use iter2 */ | |
1737 iter=unorm_setIter(uni, &iter2, mode, &errorCode); | |
1738 if(U_FAILURE(errorCode)) { | |
1739 log_err("unorm_setIter(mode %d) failed: %s\n", mode, u_errorName(err
orCode)); | |
1740 break; | |
1741 } | |
1742 | |
1743 compareIterNoIndexes(&iter1, name1, iter, name2, middle); | |
1744 ++name2[strlen(name2)-1]; | |
1745 } | |
1746 | |
1747 unorm_closeIter(uni); | |
1748 } | |
1749 | |
1750 static void | |
1751 TestUNormIterator() { | |
1752 static const UChar text[]={ /* must contain <00C5 0327> see u_strchr() below
*/ | |
1753 0x61, /* 'a' */ | |
1754 0xe4, 0x61, 0x308, /* variations of
'a'+umlaut */ | |
1755 0xc5, 0x327, 0x41, 0x30a, 0x327, 0x41, 0x327, 0x30a, /* variations of
'A'+ring+cedilla */ | |
1756 0xfb03, 0xfb00, 0x69, 0x66, 0x66, 0x69, 0x66, 0xfb01 /* variations of
'ffi' */ | |
1757 }; | |
1758 static const UChar surrogateText[]={ | |
1759 0x6e, 0xd900, 0x6a, 0xdc00, 0xd900, 0xdc00, 0x61 | |
1760 }; | |
1761 | |
1762 UChar longText[600]; | |
1763 int32_t i, middle, length; | |
1764 | |
1765 length=LENGTHOF(text); | |
1766 testUNormIteratorWithText(text, length, length/2, "UCharIter", "UNormIter1")
; | |
1767 testUNormIteratorWithText(text, length, length, "UCharIterEnd", "UNormIterEn
d1"); | |
1768 | |
1769 /* test again, this time with an insane string to cause internal buffer over
flows */ | |
1770 middle=(int32_t)(u_strchr(text, 0x327)-text); /* see comment at text[] */ | |
1771 memcpy(longText, text, middle*U_SIZEOF_UCHAR); | |
1772 for(i=0; i<150; ++i) { | |
1773 longText[middle+i]=0x30a; /* insert many rings between 'A-ring' and cedi
lla */ | |
1774 } | |
1775 memcpy(longText+middle+i, text+middle, (LENGTHOF(text)-middle)*U_SIZEOF_UCHA
R); | |
1776 length=LENGTHOF(text)+i; | |
1777 | |
1778 /* append another copy of this string for more overflows */ | |
1779 memcpy(longText+length, longText, length*U_SIZEOF_UCHAR); | |
1780 length*=2; | |
1781 | |
1782 /* the first test of the following two starts at length/4, inside the sea of
combining rings */ | |
1783 testUNormIteratorWithText(longText, length, length/4, "UCharIterLong", "UNor
mIterLong1"); | |
1784 testUNormIteratorWithText(longText, length, length, "UCharIterLongEnd", "UNo
rmIterLongEnd1"); | |
1785 | |
1786 length=LENGTHOF(surrogateText); | |
1787 testUNormIteratorWithText(surrogateText, length, length/4, "UCharIterSurr",
"UNormIterSurr1"); | |
1788 testUNormIteratorWithText(surrogateText, length, length, "UCharIterSurrEnd",
"UNormIterSurrEnd1"); | |
1789 } | |
1790 | |
1791 static void | |
1792 TestBadUNormIterator(void) { | |
1793 #if !UCONFIG_NO_NORMALIZATION | |
1794 UErrorCode status = U_ILLEGAL_ESCAPE_SEQUENCE; | |
1795 UNormIterator *uni; | |
1796 | |
1797 unorm_setIter(NULL, NULL, UNORM_NONE, &status); | |
1798 if (status != U_ILLEGAL_ESCAPE_SEQUENCE) { | |
1799 log_err("unorm_setIter changed the error code to: %s\n", u_errorName(sta
tus)); | |
1800 } | |
1801 status = U_ZERO_ERROR; | |
1802 unorm_setIter(NULL, NULL, UNORM_NONE, &status); | |
1803 if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
1804 log_err("unorm_setIter didn't react correctly to bad arguments: %s\n", u
_errorName(status)); | |
1805 } | |
1806 status = U_ZERO_ERROR; | |
1807 uni=unorm_openIter(NULL, 0, &status); | |
1808 if(U_FAILURE(status)) { | |
1809 log_err("unorm_openIter() fails: %s\n", u_errorName(status)); | |
1810 return; | |
1811 } | |
1812 unorm_setIter(uni, NULL, UNORM_NONE, &status); | |
1813 unorm_closeIter(uni); | |
1814 #endif | |
1815 } | |
1816 | |
1817 #endif | |
OLD | NEW |