| 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 |