]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/trietest.c
2 ******************************************************************************
4 * Copyright (C) 2001-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
8 * file name: trietest.c
10 * tab size: 8 (not used)
13 * created on: 2001nov20
14 * created by: Markus W. Scherer
18 #include "unicode/utypes.h"
26 /* definitions from standalone utrie development */
27 #define log_err printf
28 #define log_verbose printf
31 #define u_errorName(errorCode) "some error code"
34 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
36 /* Values for setting possibly overlapping, out-of-order ranges of values */
37 typedef struct SetRange
{
45 * value is set from the previous boundary's limit to before
46 * this boundary's limit
48 typedef struct CheckRange
{
53 double bogus
; /* needed for aligining the storage */
54 uint8_t storage
[10000000];
58 static uint32_t U_CALLCONV
59 _testFoldedValue32(UNewTrie
*trie
, UChar32 start
, int32_t offset
) {
60 uint32_t foldedValue
, value
;
68 value
=utrie_get32(trie
, start
, &inBlockZero
);
70 start
+=UTRIE_DATA_BLOCK_LENGTH
;
78 return ((uint32_t)offset
<<16)|foldedValue
;
84 static int32_t U_CALLCONV
85 _testFoldingOffset32(uint32_t data
) {
86 return (int32_t)(data
>>16);
89 static uint32_t U_CALLCONV
90 _testFoldedValue16(UNewTrie
*trie
, UChar32 start
, int32_t offset
) {
91 uint32_t foldedValue
, value
;
99 value
=utrie_get32(trie
, start
, &inBlockZero
);
101 start
+=UTRIE_DATA_BLOCK_LENGTH
;
109 return (uint32_t)(offset
|0x8000);
115 static int32_t U_CALLCONV
116 _testFoldingOffset16(uint32_t data
) {
118 return (int32_t)(data
&0x7fff);
124 static uint32_t U_CALLCONV
125 _testEnumValue(const void *context
, uint32_t value
) {
129 static UBool U_CALLCONV
130 _testEnumRange(const void *context
, UChar32 start
, UChar32 limit
, uint32_t value
) {
131 const CheckRange
**pb
=(const CheckRange
**)context
;
132 const CheckRange
*b
=(*pb
)++;
135 if(start
!=(b
-1)->limit
|| limit
!=b
->limit
|| value
!=b
->value
) {
136 log_err("error: utrie_enum() delivers wrong range [U+%04lx..U+%04lx[.0x%lx instead of [U+%04lx..U+%04lx[.0x%lx\n",
138 (b
-1)->limit
, b
->limit
, b
->value
);
144 testTrieIteration(const char *testName
,
146 const CheckRange checkRanges
[], int32_t countCheckRanges
) {
150 const UChar
*p
, *limit
;
154 int32_t i
, length
, countValues
;
158 length
=countValues
=0;
159 for(i
=0; i
<countCheckRanges
; ++i
) {
160 c
=checkRanges
[i
].limit
;
163 UTF_APPEND_CHAR_UNSAFE(s
, length
, c
);
164 values
[countValues
++]=checkRanges
[i
].value
;
174 if(trie
->data32
!=NULL
) {
175 UTRIE_NEXT32(trie
, p
, limit
, c
, c2
, value
);
177 UTRIE_NEXT16(trie
, p
, limit
, c
, c2
, value
);
179 if(value
!=values
[i
]) {
180 log_err("error: wrong value from UTRIE_NEXT(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
181 testName
, c
, c2
, value
, values
[i
]);
186 !UTF_IS_LEAD(c
) || !UTF_IS_TRAIL(c2
) || c
!=*(p
-2) || c2
!=*(p
-1)
188 log_err("error: wrong (c, c2) from UTRIE_NEXT(%s): (U+%04lx, U+%04lx)\n",
195 if(trie
->data32
==NULL
) {
196 value
=UTRIE_GET16_FROM_LEAD(trie
, c
);
197 offset
=trie
->getFoldingOffset(value
);
199 value
=UTRIE_GET16_FROM_OFFSET_TRAIL(trie
, offset
, c2
);
201 value
=trie
->initialValue
;
204 value
=UTRIE_GET32_FROM_LEAD(trie
, c
);
205 offset
=trie
->getFoldingOffset(value
);
207 value
=UTRIE_GET32_FROM_OFFSET_TRAIL(trie
, offset
, c2
);
209 value
=trie
->initialValue
;
212 if(value
!=values
[i
]) {
213 log_err("error: wrong value from UTRIE_GETXX_FROM_OFFSET_TRAIL(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
214 testName
, c
, c2
, value
, values
[i
]);
219 if(trie
->data32
==NULL
) {
220 UTRIE_GET16_FROM_PAIR(trie
, c
, c2
, value
);
222 UTRIE_GET32_FROM_PAIR(trie
, c
, c2
, value
);
224 if(value
!=values
[i
]) {
225 log_err("error: wrong value from UTRIE_GETXX_FROM_PAIR(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
226 testName
, c
, c2
, value
, values
[i
]);
238 if(trie
->data32
!=NULL
) {
239 UTRIE_PREVIOUS32(trie
, s
, p
, c
, c2
, value
);
241 UTRIE_PREVIOUS16(trie
, s
, p
, c
, c2
, value
);
243 if(value
!=values
[i
]) {
244 log_err("error: wrong value from UTRIE_PREVIOUS(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
245 testName
, c
, c2
, value
, values
[i
]);
250 !UTF_IS_LEAD(c
) || !UTF_IS_TRAIL(c2
) || c
!=*p
|| c2
!=*(p
+1)
252 log_err("error: wrong (c, c2) from UTRIE_PREVIOUS(%s): (U+%04lx, U+%04lx)\n",
259 testTrieRangesWithMalloc(const char *testName
,
260 const SetRange setRanges
[], int32_t countSetRanges
,
261 const CheckRange checkRanges
[], int32_t countCheckRanges
,
262 UBool dataIs32
, UBool latin1Linear
) {
263 UTrieGetFoldingOffset
*getFoldingOffset
;
264 const CheckRange
*enumRanges
;
267 uint32_t value
, value2
;
268 UChar32 start
, limit
;
270 UErrorCode errorCode
;
272 uint8_t* storage
=NULL
;
273 storage
= (uint8_t*) uprv_malloc(sizeof(uint8_t)*100000);
275 log_verbose("\ntesting Trie '%s'\n", testName
);
276 newTrie
=utrie_open(NULL
, NULL
, 2000,
277 checkRanges
[0].value
, checkRanges
[0].value
,
280 /* set values from setRanges[] */
282 for(i
=0; i
<countSetRanges
; ++i
) {
283 start
=setRanges
[i
].start
;
284 limit
=setRanges
[i
].limit
;
285 value
=setRanges
[i
].value
;
286 overwrite
=setRanges
[i
].overwrite
;
287 if((limit
-start
)==1 && overwrite
) {
288 ok
&=utrie_set32(newTrie
, start
, value
);
290 ok
&=utrie_setRange32(newTrie
, start
, limit
, value
, overwrite
);
294 log_err("error: setting values into a trie failed (%s)\n", testName
);
298 /* verify that all these values are in the new Trie */
300 for(i
=0; i
<countCheckRanges
; ++i
) {
301 limit
=checkRanges
[i
].limit
;
302 value
=checkRanges
[i
].value
;
305 if(value
!=utrie_get32(newTrie
, start
, NULL
)) {
306 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
307 testName
, start
, utrie_get32(newTrie
, start
, NULL
), value
);
314 getFoldingOffset
=_testFoldingOffset32
;
316 getFoldingOffset
=_testFoldingOffset16
;
319 errorCode
=U_ZERO_ERROR
;
320 length
=utrie_serialize(newTrie
, storage
, 1000000,
321 dataIs32
? _testFoldedValue32
: _testFoldedValue16
,
324 if(U_FAILURE(errorCode
)) {
325 log_err("error: utrie_serialize(%s) failed: %s\n", testName
, u_errorName(errorCode
));
326 utrie_close(newTrie
);
330 /* test linear Latin-1 range from utrie_getData() */
335 data
=utrie_getData(newTrie
, &dataLength
);
337 for(i
=0; i
<countCheckRanges
&& start
<=0xff; ++i
) {
338 limit
=checkRanges
[i
].limit
;
339 value
=checkRanges
[i
].value
;
341 while(start
<limit
&& start
<=0xff) {
342 if(value
!=data
[UTRIE_DATA_BLOCK_LENGTH
+start
]) {
343 log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
344 testName
, start
, data
[UTRIE_DATA_BLOCK_LENGTH
+start
], value
);
351 utrie_close(newTrie
);
353 errorCode
=U_ZERO_ERROR
;
354 if(!utrie_unserialize(&trie
, storage
, length
, &errorCode
)) {
355 log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode
));
358 trie
.getFoldingOffset
=getFoldingOffset
;
360 if(dataIs32
!=(trie
.data32
!=NULL
)) {
361 log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName
);
363 if(latin1Linear
!=trie
.isLatin1Linear
) {
364 log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName
);
367 /* verify that all these values are in the unserialized Trie */
369 for(i
=0; i
<countCheckRanges
; ++i
) {
370 limit
=checkRanges
[i
].limit
;
371 value
=checkRanges
[i
].value
;
374 /* skip surrogates */
382 value2
=UTRIE_GET32_FROM_BMP(&trie
, start
);
384 value2
=UTRIE_GET16_FROM_BMP(&trie
, start
);
387 log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
388 testName
, start
, value2
, value
);
390 if(!UTF_IS_LEAD(start
)) {
392 value2
=UTRIE_GET32_FROM_LEAD(&trie
, start
);
394 value2
=UTRIE_GET16_FROM_LEAD(&trie
, start
);
397 log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
398 testName
, start
, value2
, value
);
403 UTRIE_GET32(&trie
, start
, value2
);
405 UTRIE_GET16(&trie
, start
, value2
);
408 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
409 testName
, start
, value2
, value
);
415 /* enumerate and verify all ranges */
416 enumRanges
=checkRanges
+1;
417 utrie_enum(&trie
, _testEnumValue
, _testEnumRange
, &enumRanges
);
419 /* test linear Latin-1 range */
420 if(trie
.isLatin1Linear
) {
421 if(trie
.data32
!=NULL
) {
422 const uint32_t *latin1
=UTRIE_GET32_LATIN1(&trie
);
424 for(start
=0; start
<0x100; ++start
) {
425 if(latin1
[start
]!=UTRIE_GET32_FROM_LEAD(&trie
, start
)) {
426 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
427 testName
, start
, latin1
[start
], UTRIE_GET32_FROM_LEAD(&trie
, start
), start
);
431 const uint16_t *latin1
=UTRIE_GET16_LATIN1(&trie
);
433 for(start
=0; start
<0x100; ++start
) {
434 if(latin1
[start
]!=UTRIE_GET16_FROM_LEAD(&trie
, start
)) {
435 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
436 testName
, start
, latin1
[start
], UTRIE_GET16_FROM_LEAD(&trie
, start
), start
);
442 testTrieIteration(testName
, &trie
, checkRanges
, countCheckRanges
);
447 testTrieRanges(const char *testName
,
448 const SetRange setRanges
[], int32_t countSetRanges
,
449 const CheckRange checkRanges
[], int32_t countCheckRanges
,
450 UBool dataIs32
, UBool latin1Linear
) {
451 UTrieGetFoldingOffset
*getFoldingOffset
;
452 const CheckRange
*enumRanges
;
455 uint32_t value
, value2
;
456 UChar32 start
, limit
;
458 UErrorCode errorCode
;
461 log_verbose("\ntesting Trie '%s'\n", testName
);
462 newTrie
=utrie_open(NULL
, NULL
, 2000,
463 checkRanges
[0].value
, checkRanges
[0].value
,
466 /* set values from setRanges[] */
468 for(i
=0; i
<countSetRanges
; ++i
) {
469 start
=setRanges
[i
].start
;
470 limit
=setRanges
[i
].limit
;
471 value
=setRanges
[i
].value
;
472 overwrite
=setRanges
[i
].overwrite
;
473 if((limit
-start
)==1 && overwrite
) {
474 ok
&=utrie_set32(newTrie
, start
, value
);
476 ok
&=utrie_setRange32(newTrie
, start
, limit
, value
, overwrite
);
480 log_err("error: setting values into a trie failed (%s)\n", testName
);
484 /* verify that all these values are in the new Trie */
486 for(i
=0; i
<countCheckRanges
; ++i
) {
487 limit
=checkRanges
[i
].limit
;
488 value
=checkRanges
[i
].value
;
491 if(value
!=utrie_get32(newTrie
, start
, NULL
)) {
492 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
493 testName
, start
, utrie_get32(newTrie
, start
, NULL
), value
);
500 getFoldingOffset
=_testFoldingOffset32
;
502 getFoldingOffset
=_testFoldingOffset16
;
505 errorCode
=U_ZERO_ERROR
;
506 length
=utrie_serialize(newTrie
, storageHolder
.storage
, sizeof(storageHolder
.storage
),
507 dataIs32
? _testFoldedValue32
: _testFoldedValue16
,
510 if(U_FAILURE(errorCode
)) {
511 log_err("error: utrie_serialize(%s) failed: %s\n", testName
, u_errorName(errorCode
));
512 utrie_close(newTrie
);
516 /* test linear Latin-1 range from utrie_getData() */
521 data
=utrie_getData(newTrie
, &dataLength
);
523 for(i
=0; i
<countCheckRanges
&& start
<=0xff; ++i
) {
524 limit
=checkRanges
[i
].limit
;
525 value
=checkRanges
[i
].value
;
527 while(start
<limit
&& start
<=0xff) {
528 if(value
!=data
[UTRIE_DATA_BLOCK_LENGTH
+start
]) {
529 log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
530 testName
, start
, data
[UTRIE_DATA_BLOCK_LENGTH
+start
], value
);
537 utrie_close(newTrie
);
539 errorCode
=U_ZERO_ERROR
;
540 if(!utrie_unserialize(&trie
, storageHolder
.storage
, length
, &errorCode
)) {
541 log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode
));
544 trie
.getFoldingOffset
=getFoldingOffset
;
546 if(dataIs32
!=(trie
.data32
!=NULL
)) {
547 log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName
);
549 if(latin1Linear
!=trie
.isLatin1Linear
) {
550 log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName
);
553 /* verify that all these values are in the unserialized Trie */
555 for(i
=0; i
<countCheckRanges
; ++i
) {
556 limit
=checkRanges
[i
].limit
;
557 value
=checkRanges
[i
].value
;
560 /* skip surrogates */
568 value2
=UTRIE_GET32_FROM_BMP(&trie
, start
);
570 value2
=UTRIE_GET16_FROM_BMP(&trie
, start
);
573 log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
574 testName
, start
, value2
, value
);
576 if(!UTF_IS_LEAD(start
)) {
578 value2
=UTRIE_GET32_FROM_LEAD(&trie
, start
);
580 value2
=UTRIE_GET16_FROM_LEAD(&trie
, start
);
583 log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
584 testName
, start
, value2
, value
);
589 UTRIE_GET32(&trie
, start
, value2
);
591 UTRIE_GET16(&trie
, start
, value2
);
594 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
595 testName
, start
, value2
, value
);
601 /* enumerate and verify all ranges */
602 enumRanges
=checkRanges
+1;
603 utrie_enum(&trie
, _testEnumValue
, _testEnumRange
, &enumRanges
);
605 /* test linear Latin-1 range */
606 if(trie
.isLatin1Linear
) {
607 if(trie
.data32
!=NULL
) {
608 const uint32_t *latin1
=UTRIE_GET32_LATIN1(&trie
);
610 for(start
=0; start
<0x100; ++start
) {
611 if(latin1
[start
]!=UTRIE_GET32_FROM_LEAD(&trie
, start
)) {
612 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
613 testName
, start
, latin1
[start
], UTRIE_GET32_FROM_LEAD(&trie
, start
), start
);
617 const uint16_t *latin1
=UTRIE_GET16_LATIN1(&trie
);
619 for(start
=0; start
<0x100; ++start
) {
620 if(latin1
[start
]!=UTRIE_GET16_FROM_LEAD(&trie
, start
)) {
621 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
622 testName
, start
, latin1
[start
], UTRIE_GET16_FROM_LEAD(&trie
, start
), start
);
628 testTrieIteration(testName
, &trie
, checkRanges
, countCheckRanges
);
632 testTrieRanges2(const char *testName
,
633 const SetRange setRanges
[], int32_t countSetRanges
,
634 const CheckRange checkRanges
[], int32_t countCheckRanges
,
638 testTrieRanges(testName
,
639 setRanges
, countSetRanges
,
640 checkRanges
, countCheckRanges
,
642 testTrieRangesWithMalloc(testName
,
643 setRanges
, countSetRanges
,
644 checkRanges
, countCheckRanges
,
647 uprv_strcpy(name
, testName
);
648 uprv_strcat(name
, "-latin1Linear");
650 setRanges
, countSetRanges
,
651 checkRanges
, countCheckRanges
,
653 testTrieRangesWithMalloc(name
,
654 setRanges
, countSetRanges
,
655 checkRanges
, countCheckRanges
,
660 testTrieRanges4(const char *testName
,
661 const SetRange setRanges
[], int32_t countSetRanges
,
662 const CheckRange checkRanges
[], int32_t countCheckRanges
) {
665 uprv_strcpy(name
, testName
);
666 uprv_strcat(name
, ".32");
667 testTrieRanges2(name
,
668 setRanges
, countSetRanges
,
669 checkRanges
, countCheckRanges
,
672 uprv_strcpy(name
, testName
);
673 uprv_strcat(name
, ".16");
674 testTrieRanges2(name
,
675 setRanges
, countSetRanges
,
676 checkRanges
, countCheckRanges
,
680 /* test data ----------------------------------------------------------------*/
682 /* set consecutive ranges, even with value 0 */
683 static const SetRange
686 {0x20, 0xa7, 0x1234, FALSE
},
687 {0xa7, 0x3400, 0, FALSE
},
688 {0x3400, 0x9fa6, 0x6162, FALSE
},
689 {0x9fa6, 0xda9e, 0x3132, FALSE
},
690 {0xdada, 0xeeee, 0x87ff, FALSE
}, /* try to disrupt _testFoldingOffset16() */
691 {0xeeee, 0x11111, 1, FALSE
},
692 {0x11111, 0x44444, 0x6162, FALSE
},
693 {0x44444, 0x60003, 0, FALSE
},
694 {0xf0003, 0xf0004, 0xf, FALSE
},
695 {0xf0004, 0xf0006, 0x10, FALSE
},
696 {0xf0006, 0xf0007, 0x11, FALSE
},
697 {0xf0007, 0xf0020, 0x12, FALSE
},
698 {0xf0020, 0x110000, 0, FALSE
}
701 static const CheckRange
703 {0, 0}, /* dummy start range to make _testEnumRange() simpler */
721 /* set some interesting overlapping ranges */
722 static const SetRange
724 {0x21, 0x7f, 0x5555, TRUE
},
725 {0x2f800,0x2fedc, 0x7a, TRUE
},
726 {0x72, 0xdd, 3, TRUE
},
727 {0xdd, 0xde, 4, FALSE
},
728 {0x2f987,0x2fa98, 5, TRUE
},
729 {0x2f777,0x2f833, 0, TRUE
},
730 {0x2f900,0x2ffee, 1, FALSE
},
731 {0x2ffee,0x2ffef, 2, TRUE
}
734 static const CheckRange
736 {0, 0}, /* dummy start range to make _testEnumRange() simpler */
750 /* use a non-zero initial value */
751 static const SetRange
753 {0x31, 0xa4, 1, FALSE
},
754 {0x3400, 0x6789, 2, FALSE
},
755 {0x30000,0x34567,9, TRUE
},
756 {0x45678,0x56789,3, TRUE
}
759 static const CheckRange
761 {0, 9}, /* dummy start range, also carries the initial value */
773 testTrieRanges4("set1",
774 setRanges1
, ARRAY_LENGTH(setRanges1
),
775 checkRanges1
, ARRAY_LENGTH(checkRanges1
));
776 testTrieRanges4("set2-overlap",
777 setRanges2
, ARRAY_LENGTH(setRanges2
),
778 checkRanges2
, ARRAY_LENGTH(checkRanges2
));
779 testTrieRanges4("set3-initial-9",
780 setRanges3
, ARRAY_LENGTH(setRanges3
),
781 checkRanges3
, ARRAY_LENGTH(checkRanges3
));
786 addTrieTest(TestNode
** root
);
789 addTrieTest(TestNode
** root
) {
790 addTest(root
, &TrieTest
, "tsutil/trietest/TrieTest");
793 /* standalone utrie development */
794 int main(int argc
, const char *argv
[]) {