1/*
2***********************************************************************
3* Copyright (C) 2016 and later: Unicode, Inc. and others.
4* License & terms of use: http://www.unicode.org/copyright.html#License
5***********************************************************************
6***********************************************************************
7* Copyright (c) 2013-2014, International Business Machines
8* Corporation and others.  All Rights Reserved.
9***********************************************************************
10*/
11
12#include <string.h>
13#include "unicode/localpointer.h"
14#include "unicode/uperf.h"
15#include "unicode/ucol.h"
16#include "unicode/coll.h"
17#include "unicode/uiter.h"
18#include "unicode/ustring.h"
19#include "unicode/sortkey.h"
20#include "uarrsort.h"
21#include "uoptions.h"
22#include "ustr_imp.h"
23
24#define COMPACT_ARRAY(CompactArrays, UNIT) \
25struct CompactArrays{\
26    CompactArrays(const CompactArrays & );\
27    CompactArrays & operator=(const CompactArrays & );\
28    int32_t   count;/*total number of the strings*/ \
29    int32_t * index;/*relative offset in data*/ \
30    UNIT    * data; /*the real space to hold strings*/ \
31    \
32    ~CompactArrays(){free(index);free(data);} \
33    CompactArrays() : count(0), index(NULL), data(NULL) { \
34        index = (int32_t *) realloc(index, sizeof(int32_t)); \
35        index[0] = 0; \
36    } \
37    void append_one(int32_t theLen){ /*include terminal NULL*/ \
38        count++; \
39        index = (int32_t *) realloc(index, sizeof(int32_t) * (count + 1)); \
40        index[count] = index[count - 1] + theLen; \
41        data = (UNIT *) realloc(data, sizeof(UNIT) * index[count]); \
42    } \
43    UNIT * last(){return data + index[count - 1];} \
44    const UNIT * dataOf(int32_t i) const {return data + index[i];} \
45    int32_t lengthOf(int i) const {return index[i+1] - index[i] - 1; } /*exclude terminating NULL*/  \
46};
47
48COMPACT_ARRAY(CA_uchar, UChar)
49COMPACT_ARRAY(CA_char, char)
50
51#define MAX_TEST_STRINGS_FOR_PERMUTING 1000
52
53// C API test cases
54
55//
56// Test case taking a single test data array, calling ucol_strcoll by permuting the test data
57//
58class Strcoll : public UPerfFunction
59{
60public:
61    Strcoll(const UCollator* coll, const CA_uchar* source, UBool useLen);
62    ~Strcoll();
63    virtual void call(UErrorCode* status);
64    virtual long getOperationsPerIteration();
65
66private:
67    const UCollator *coll;
68    const CA_uchar *source;
69    UBool useLen;
70    int32_t maxTestStrings;
71};
72
73Strcoll::Strcoll(const UCollator* coll, const CA_uchar* source, UBool useLen)
74    :   coll(coll),
75        source(source),
76        useLen(useLen)
77{
78    maxTestStrings = source->count > MAX_TEST_STRINGS_FOR_PERMUTING ? MAX_TEST_STRINGS_FOR_PERMUTING : source->count;
79}
80
81Strcoll::~Strcoll()
82{
83}
84
85void Strcoll::call(UErrorCode* status)
86{
87    if (U_FAILURE(*status)) return;
88
89    // call strcoll for permutation
90    int32_t divisor = source->count / maxTestStrings;
91    int32_t srcLen, tgtLen;
92    int32_t cmp = 0;
93    for (int32_t i = 0, numTestStringsI = 0; i < source->count && numTestStringsI < maxTestStrings; i++) {
94        if (i % divisor) continue;
95        numTestStringsI++;
96        srcLen = useLen ? source->lengthOf(i) : -1;
97        for (int32_t j = 0, numTestStringsJ = 0; j < source->count && numTestStringsJ < maxTestStrings; j++) {
98            if (j % divisor) continue;
99            numTestStringsJ++;
100            tgtLen = useLen ? source->lengthOf(j) : -1;
101            cmp += ucol_strcoll(coll, source->dataOf(i), srcLen, source->dataOf(j), tgtLen);
102        }
103    }
104    // At the end, cmp must be 0
105    if (cmp != 0) {
106        *status = U_INTERNAL_PROGRAM_ERROR;
107    }
108}
109
110long Strcoll::getOperationsPerIteration()
111{
112    return maxTestStrings * maxTestStrings;
113}
114
115//
116// Test case taking two test data arrays, calling ucol_strcoll for strings at a same index
117//
118class Strcoll_2 : public UPerfFunction
119{
120public:
121    Strcoll_2(const UCollator* coll, const CA_uchar* source, const CA_uchar* target, UBool useLen);
122    ~Strcoll_2();
123    virtual void call(UErrorCode* status);
124    virtual long getOperationsPerIteration();
125
126private:
127    const UCollator *coll;
128    const CA_uchar *source;
129    const CA_uchar *target;
130    UBool useLen;
131};
132
133Strcoll_2::Strcoll_2(const UCollator* coll, const CA_uchar* source, const CA_uchar* target, UBool useLen)
134    :   coll(coll),
135        source(source),
136        target(target),
137        useLen(useLen)
138{
139}
140
141Strcoll_2::~Strcoll_2()
142{
143}
144
145void Strcoll_2::call(UErrorCode* status)
146{
147    if (U_FAILURE(*status)) return;
148
149    // call strcoll for two strings at the same index
150    if (source->count < target->count) {
151        *status = U_ILLEGAL_ARGUMENT_ERROR;
152    } else {
153        for (int32_t i = 0; i < source->count; i++) {
154            int32_t srcLen = useLen ? source->lengthOf(i) : -1;
155            int32_t tgtLen = useLen ? target->lengthOf(i) : -1;
156            ucol_strcoll(coll, source->dataOf(i), srcLen, target->dataOf(i), tgtLen);
157        }
158    }
159}
160
161long Strcoll_2::getOperationsPerIteration()
162{
163    return source->count;
164}
165
166
167//
168// Test case taking a single test data array, calling ucol_strcollUTF8 by permuting the test data
169//
170class StrcollUTF8 : public UPerfFunction
171{
172public:
173    StrcollUTF8(const UCollator* coll, const CA_char* source, UBool useLen);
174    ~StrcollUTF8();
175    virtual void call(UErrorCode* status);
176    virtual long getOperationsPerIteration();
177
178private:
179    const UCollator *coll;
180    const CA_char *source;
181    UBool useLen;
182    int32_t maxTestStrings;
183};
184
185StrcollUTF8::StrcollUTF8(const UCollator* coll, const CA_char* source, UBool useLen)
186    :   coll(coll),
187        source(source),
188        useLen(useLen)
189{
190    maxTestStrings = source->count > MAX_TEST_STRINGS_FOR_PERMUTING ? MAX_TEST_STRINGS_FOR_PERMUTING : source->count;
191}
192
193StrcollUTF8::~StrcollUTF8()
194{
195}
196
197void StrcollUTF8::call(UErrorCode* status)
198{
199    if (U_FAILURE(*status)) return;
200
201    // call strcollUTF8 for permutation
202    int32_t divisor = source->count / maxTestStrings;
203    int32_t srcLen, tgtLen;
204    int32_t cmp = 0;
205    for (int32_t i = 0, numTestStringsI = 0; U_SUCCESS(*status) && i < source->count && numTestStringsI < maxTestStrings; i++) {
206        if (i % divisor) continue;
207        numTestStringsI++;
208        srcLen = useLen ? source->lengthOf(i) : -1;
209        for (int32_t j = 0, numTestStringsJ = 0; U_SUCCESS(*status) && j < source->count && numTestStringsJ < maxTestStrings; j++) {
210            if (j % divisor) continue;
211            numTestStringsJ++;
212            tgtLen = useLen ? source->lengthOf(j) : -1;
213            cmp += ucol_strcollUTF8(coll, source->dataOf(i), srcLen, source->dataOf(j), tgtLen, status);
214        }
215    }
216    // At the end, cmp must be 0
217    if (cmp != 0) {
218        *status = U_INTERNAL_PROGRAM_ERROR;
219    }
220}
221
222long StrcollUTF8::getOperationsPerIteration()
223{
224    return maxTestStrings * maxTestStrings;
225}
226
227//
228// Test case taking two test data arrays, calling ucol_strcoll for strings at a same index
229//
230class StrcollUTF8_2 : public UPerfFunction
231{
232public:
233    StrcollUTF8_2(const UCollator* coll, const CA_char* source, const CA_char* target, UBool useLen);
234    ~StrcollUTF8_2();
235    virtual void call(UErrorCode* status);
236    virtual long getOperationsPerIteration();
237
238private:
239    const UCollator *coll;
240    const CA_char *source;
241    const CA_char *target;
242    UBool useLen;
243};
244
245StrcollUTF8_2::StrcollUTF8_2(const UCollator* coll, const CA_char* source, const CA_char* target, UBool useLen)
246    :   coll(coll),
247        source(source),
248        target(target),
249        useLen(useLen)
250{
251}
252
253StrcollUTF8_2::~StrcollUTF8_2()
254{
255}
256
257void StrcollUTF8_2::call(UErrorCode* status)
258{
259    if (U_FAILURE(*status)) return;
260
261    // call strcoll for two strings at the same index
262    if (source->count < target->count) {
263        *status = U_ILLEGAL_ARGUMENT_ERROR;
264    } else {
265        for (int32_t i = 0; U_SUCCESS(*status) && i < source->count; i++) {
266            int32_t srcLen = useLen ? source->lengthOf(i) : -1;
267            int32_t tgtLen = useLen ? target->lengthOf(i) : -1;
268            ucol_strcollUTF8(coll, source->dataOf(i), srcLen, target->dataOf(i), tgtLen, status);
269        }
270    }
271}
272
273long StrcollUTF8_2::getOperationsPerIteration()
274{
275    return source->count;
276}
277
278//
279// Test case taking a single test data array, calling ucol_getSortKey for each
280//
281class GetSortKey : public UPerfFunction
282{
283public:
284    GetSortKey(const UCollator* coll, const CA_uchar* source, UBool useLen);
285    ~GetSortKey();
286    virtual void call(UErrorCode* status);
287    virtual long getOperationsPerIteration();
288
289private:
290    const UCollator *coll;
291    const CA_uchar *source;
292    UBool useLen;
293};
294
295GetSortKey::GetSortKey(const UCollator* coll, const CA_uchar* source, UBool useLen)
296    :   coll(coll),
297        source(source),
298        useLen(useLen)
299{
300}
301
302GetSortKey::~GetSortKey()
303{
304}
305
306#define KEY_BUF_SIZE 512
307
308void GetSortKey::call(UErrorCode* status)
309{
310    if (U_FAILURE(*status)) return;
311
312    uint8_t key[KEY_BUF_SIZE];
313    int32_t len;
314
315    if (useLen) {
316        for (int32_t i = 0; i < source->count; i++) {
317            len = ucol_getSortKey(coll, source->dataOf(i), source->lengthOf(i), key, KEY_BUF_SIZE);
318        }
319    } else {
320        for (int32_t i = 0; i < source->count; i++) {
321            len = ucol_getSortKey(coll, source->dataOf(i), -1, key, KEY_BUF_SIZE);
322        }
323    }
324}
325
326long GetSortKey::getOperationsPerIteration()
327{
328    return source->count;
329}
330
331//
332// Test case taking a single test data array in UTF-16, calling ucol_nextSortKeyPart for each for the
333// given buffer size
334//
335class NextSortKeyPart : public UPerfFunction
336{
337public:
338    NextSortKeyPart(const UCollator* coll, const CA_uchar* source, int32_t bufSize, int32_t maxIteration = -1);
339    ~NextSortKeyPart();
340    virtual void call(UErrorCode* status);
341    virtual long getOperationsPerIteration();
342    virtual long getEventsPerIteration();
343
344private:
345    const UCollator *coll;
346    const CA_uchar *source;
347    int32_t bufSize;
348    int32_t maxIteration;
349    long events;
350};
351
352// Note: maxIteration = -1 -> repeat until the end of collation key
353NextSortKeyPart::NextSortKeyPart(const UCollator* coll, const CA_uchar* source, int32_t bufSize, int32_t maxIteration /* = -1 */)
354    :   coll(coll),
355        source(source),
356        bufSize(bufSize),
357        maxIteration(maxIteration),
358        events(0)
359{
360}
361
362NextSortKeyPart::~NextSortKeyPart()
363{
364}
365
366void NextSortKeyPart::call(UErrorCode* status)
367{
368    if (U_FAILURE(*status)) return;
369
370    uint8_t *part = (uint8_t *)malloc(bufSize);
371    uint32_t state[2];
372    UCharIterator iter;
373
374    events = 0;
375    for (int i = 0; i < source->count && U_SUCCESS(*status); i++) {
376        uiter_setString(&iter, source->dataOf(i), source->lengthOf(i));
377        state[0] = 0;
378        state[1] = 0;
379        int32_t partLen = bufSize;
380        for (int32_t n = 0; U_SUCCESS(*status) && partLen == bufSize && (maxIteration < 0 || n < maxIteration); n++) {
381            partLen = ucol_nextSortKeyPart(coll, &iter, state, part, bufSize, status);
382            events++;
383        }
384    }
385    free(part);
386}
387
388long NextSortKeyPart::getOperationsPerIteration()
389{
390    return source->count;
391}
392
393long NextSortKeyPart::getEventsPerIteration()
394{
395    return events;
396}
397
398//
399// Test case taking a single test data array in UTF-8, calling ucol_nextSortKeyPart for each for the
400// given buffer size
401//
402class NextSortKeyPartUTF8 : public UPerfFunction
403{
404public:
405    NextSortKeyPartUTF8(const UCollator* coll, const CA_char* source, int32_t bufSize, int32_t maxIteration = -1);
406    ~NextSortKeyPartUTF8();
407    virtual void call(UErrorCode* status);
408    virtual long getOperationsPerIteration();
409    virtual long getEventsPerIteration();
410
411private:
412    const UCollator *coll;
413    const CA_char *source;
414    int32_t bufSize;
415    int32_t maxIteration;
416    long events;
417};
418
419// Note: maxIteration = -1 -> repeat until the end of collation key
420NextSortKeyPartUTF8::NextSortKeyPartUTF8(const UCollator* coll, const CA_char* source, int32_t bufSize, int32_t maxIteration /* = -1 */)
421    :   coll(coll),
422        source(source),
423        bufSize(bufSize),
424        maxIteration(maxIteration),
425        events(0)
426{
427}
428
429NextSortKeyPartUTF8::~NextSortKeyPartUTF8()
430{
431}
432
433void NextSortKeyPartUTF8::call(UErrorCode* status)
434{
435    if (U_FAILURE(*status)) return;
436
437    uint8_t *part = (uint8_t *)malloc(bufSize);
438    uint32_t state[2];
439    UCharIterator iter;
440
441    events = 0;
442    for (int i = 0; i < source->count && U_SUCCESS(*status); i++) {
443        uiter_setUTF8(&iter, source->dataOf(i), source->lengthOf(i));
444        state[0] = 0;
445        state[1] = 0;
446        int32_t partLen = bufSize;
447        for (int32_t n = 0; U_SUCCESS(*status) && partLen == bufSize && (maxIteration < 0 || n < maxIteration); n++) {
448            partLen = ucol_nextSortKeyPart(coll, &iter, state, part, bufSize, status);
449            events++;
450        }
451    }
452    free(part);
453}
454
455long NextSortKeyPartUTF8::getOperationsPerIteration()
456{
457    return source->count;
458}
459
460long NextSortKeyPartUTF8::getEventsPerIteration()
461{
462    return events;
463}
464
465// CPP API test cases
466
467//
468// Test case taking a single test data array, calling Collator::compare by permuting the test data
469//
470class CppCompare : public UPerfFunction
471{
472public:
473    CppCompare(const Collator* coll, const CA_uchar* source, UBool useLen);
474    ~CppCompare();
475    virtual void call(UErrorCode* status);
476    virtual long getOperationsPerIteration();
477
478private:
479    const Collator *coll;
480    const CA_uchar *source;
481    UBool useLen;
482    int32_t maxTestStrings;
483};
484
485CppCompare::CppCompare(const Collator* coll, const CA_uchar* source, UBool useLen)
486    :   coll(coll),
487        source(source),
488        useLen(useLen)
489{
490    maxTestStrings = source->count > MAX_TEST_STRINGS_FOR_PERMUTING ? MAX_TEST_STRINGS_FOR_PERMUTING : source->count;
491}
492
493CppCompare::~CppCompare()
494{
495}
496
497void CppCompare::call(UErrorCode* status) {
498    if (U_FAILURE(*status)) return;
499
500    // call compare for permutation of test data
501    int32_t divisor = source->count / maxTestStrings;
502    int32_t srcLen, tgtLen;
503    int32_t cmp = 0;
504    for (int32_t i = 0, numTestStringsI = 0; i < source->count && numTestStringsI < maxTestStrings; i++) {
505        if (i % divisor) continue;
506        numTestStringsI++;
507        srcLen = useLen ? source->lengthOf(i) : -1;
508        for (int32_t j = 0, numTestStringsJ = 0; j < source->count && numTestStringsJ < maxTestStrings; j++) {
509            if (j % divisor) continue;
510            numTestStringsJ++;
511            tgtLen = useLen ? source->lengthOf(j) : -1;
512            cmp += coll->compare(source->dataOf(i), srcLen, source->dataOf(j), tgtLen);
513        }
514    }
515    // At the end, cmp must be 0
516    if (cmp != 0) {
517        *status = U_INTERNAL_PROGRAM_ERROR;
518    }
519}
520
521long CppCompare::getOperationsPerIteration()
522{
523    return maxTestStrings * maxTestStrings;
524}
525
526//
527// Test case taking two test data arrays, calling Collator::compare for strings at a same index
528//
529class CppCompare_2 : public UPerfFunction
530{
531public:
532    CppCompare_2(const Collator* coll, const CA_uchar* source, const CA_uchar* target, UBool useLen);
533    ~CppCompare_2();
534    virtual void call(UErrorCode* status);
535    virtual long getOperationsPerIteration();
536
537private:
538    const Collator *coll;
539    const CA_uchar *source;
540    const CA_uchar *target;
541    UBool useLen;
542};
543
544CppCompare_2::CppCompare_2(const Collator* coll, const CA_uchar* source, const CA_uchar* target, UBool useLen)
545    :   coll(coll),
546        source(source),
547        target(target),
548        useLen(useLen)
549{
550}
551
552CppCompare_2::~CppCompare_2()
553{
554}
555
556void CppCompare_2::call(UErrorCode* status) {
557    if (U_FAILURE(*status)) return;
558
559    // call strcoll for two strings at the same index
560    if (source->count < target->count) {
561        *status = U_ILLEGAL_ARGUMENT_ERROR;
562    } else {
563        for (int32_t i = 0; i < source->count; i++) {
564            int32_t srcLen = useLen ? source->lengthOf(i) : -1;
565            int32_t tgtLen = useLen ? target->lengthOf(i) : -1;
566            coll->compare(source->dataOf(i), srcLen, target->dataOf(i), tgtLen);
567        }
568    }
569}
570
571long CppCompare_2::getOperationsPerIteration()
572{
573    return source->count;
574}
575
576
577//
578// Test case taking a single test data array, calling Collator::compareUTF8 by permuting the test data
579//
580class CppCompareUTF8 : public UPerfFunction
581{
582public:
583    CppCompareUTF8(const Collator* coll, const CA_char* source, UBool useLen);
584    ~CppCompareUTF8();
585    virtual void call(UErrorCode* status);
586    virtual long getOperationsPerIteration();
587
588private:
589    const Collator *coll;
590    const CA_char *source;
591    UBool useLen;
592    int32_t maxTestStrings;
593};
594
595CppCompareUTF8::CppCompareUTF8(const Collator* coll, const CA_char* source, UBool useLen)
596    :   coll(coll),
597        source(source),
598        useLen(useLen)
599{
600    maxTestStrings = source->count > MAX_TEST_STRINGS_FOR_PERMUTING ? MAX_TEST_STRINGS_FOR_PERMUTING : source->count;
601}
602
603CppCompareUTF8::~CppCompareUTF8()
604{
605}
606
607void CppCompareUTF8::call(UErrorCode* status) {
608    if (U_FAILURE(*status)) return;
609
610    // call compareUTF8 for all permutations
611    int32_t divisor = source->count / maxTestStrings;
612    StringPiece src, tgt;
613    int32_t cmp = 0;
614    for (int32_t i = 0, numTestStringsI = 0; U_SUCCESS(*status) && i < source->count && numTestStringsI < maxTestStrings; i++) {
615        if (i % divisor) continue;
616        numTestStringsI++;
617
618        if (useLen) {
619            src.set(source->dataOf(i), source->lengthOf(i));
620        } else {
621            src.set(source->dataOf(i));
622        }
623        for (int32_t j = 0, numTestStringsJ = 0; U_SUCCESS(*status) && j < source->count && numTestStringsJ < maxTestStrings; j++) {
624            if (j % divisor) continue;
625            numTestStringsJ++;
626
627            if (useLen) {
628                tgt.set(source->dataOf(i), source->lengthOf(i));
629            } else {
630                tgt.set(source->dataOf(i));
631            }
632            cmp += coll->compareUTF8(src, tgt, *status);
633        }
634    }
635    // At the end, cmp must be 0
636    if (cmp != 0) {
637        *status = U_INTERNAL_PROGRAM_ERROR;
638    }
639}
640
641long CppCompareUTF8::getOperationsPerIteration()
642{
643    return maxTestStrings * maxTestStrings;
644}
645
646
647//
648// Test case taking two test data arrays, calling Collator::compareUTF8 for strings at a same index
649//
650class CppCompareUTF8_2 : public UPerfFunction
651{
652public:
653    CppCompareUTF8_2(const Collator* coll, const CA_char* source, const CA_char* target, UBool useLen);
654    ~CppCompareUTF8_2();
655    virtual void call(UErrorCode* status);
656    virtual long getOperationsPerIteration();
657
658private:
659    const Collator *coll;
660    const CA_char *source;
661    const CA_char *target;
662    UBool useLen;
663};
664
665CppCompareUTF8_2::CppCompareUTF8_2(const Collator* coll, const CA_char* source, const CA_char* target, UBool useLen)
666    :   coll(coll),
667        source(source),
668        target(target),
669        useLen(useLen)
670{
671}
672
673CppCompareUTF8_2::~CppCompareUTF8_2()
674{
675}
676
677void CppCompareUTF8_2::call(UErrorCode* status) {
678    if (U_FAILURE(*status)) return;
679
680    // call strcoll for two strings at the same index
681    StringPiece src, tgt;
682    if (source->count < target->count) {
683        *status = U_ILLEGAL_ARGUMENT_ERROR;
684    } else {
685        for (int32_t i = 0; U_SUCCESS(*status) && i < source->count; i++) {
686            if (useLen) {
687                src.set(source->dataOf(i), source->lengthOf(i));
688                tgt.set(target->dataOf(i), target->lengthOf(i));
689            } else {
690                src.set(source->dataOf(i));
691                tgt.set(target->dataOf(i));
692            }
693            coll->compareUTF8(src, tgt, *status);
694        }
695    }
696}
697
698long CppCompareUTF8_2::getOperationsPerIteration()
699{
700    return source->count;
701}
702
703
704//
705// Test case taking a single test data array, calling Collator::getCollationKey for each
706//
707class CppGetCollationKey : public UPerfFunction
708{
709public:
710    CppGetCollationKey(const Collator* coll, const CA_uchar* source, UBool useLen);
711    ~CppGetCollationKey();
712    virtual void call(UErrorCode* status);
713    virtual long getOperationsPerIteration();
714
715private:
716    const Collator *coll;
717    const CA_uchar *source;
718    UBool useLen;
719};
720
721CppGetCollationKey::CppGetCollationKey(const Collator* coll, const CA_uchar* source, UBool useLen)
722    :   coll(coll),
723        source(source),
724        useLen(useLen)
725{
726}
727
728CppGetCollationKey::~CppGetCollationKey()
729{
730}
731
732void CppGetCollationKey::call(UErrorCode* status)
733{
734    if (U_FAILURE(*status)) return;
735
736    CollationKey key;
737    for (int32_t i = 0; U_SUCCESS(*status) && i < source->count; i++) {
738        coll->getCollationKey(source->dataOf(i), source->lengthOf(i), key, *status);
739    }
740}
741
742long CppGetCollationKey::getOperationsPerIteration() {
743    return source->count;
744}
745
746namespace {
747
748struct CollatorAndCounter {
749    CollatorAndCounter(const Collator& coll) : coll(coll), ucoll(NULL), counter(0) {}
750    CollatorAndCounter(const Collator& coll, const UCollator *ucoll)
751            : coll(coll), ucoll(ucoll), counter(0) {}
752    const Collator& coll;
753    const UCollator *ucoll;
754    int32_t counter;
755};
756
757int32_t U_CALLCONV
758UniStrCollatorComparator(const void* context, const void* left, const void* right) {
759    CollatorAndCounter& cc = *(CollatorAndCounter*)context;
760    const UnicodeString& leftString = **(const UnicodeString**)left;
761    const UnicodeString& rightString = **(const UnicodeString**)right;
762    UErrorCode errorCode = U_ZERO_ERROR;
763    ++cc.counter;
764    return cc.coll.compare(leftString, rightString, errorCode);
765}
766
767}  // namespace
768
769class CollPerfFunction : public UPerfFunction {
770public:
771    CollPerfFunction(const Collator& coll, const UCollator *ucoll)
772            : coll(coll), ucoll(ucoll), ops(0) {}
773    virtual ~CollPerfFunction();
774    /** Calls call() to set the ops field, and returns that. */
775    virtual long getOperationsPerIteration();
776
777protected:
778    const Collator& coll;
779    const UCollator *ucoll;
780    int32_t ops;
781};
782
783CollPerfFunction::~CollPerfFunction() {}
784
785long CollPerfFunction::getOperationsPerIteration() {
786    UErrorCode errorCode = U_ZERO_ERROR;
787    call(&errorCode);
788    return U_SUCCESS(errorCode) ? ops : 0;
789}
790
791class UniStrCollPerfFunction : public CollPerfFunction {
792public:
793    UniStrCollPerfFunction(const Collator& coll, const UCollator *ucoll, const CA_uchar* data16)
794            : CollPerfFunction(coll, ucoll), d16(data16),
795              source(new UnicodeString*[d16->count]) {
796        for (int32_t i = 0; i < d16->count; ++i) {
797            source[i] = new UnicodeString(TRUE, d16->dataOf(i), d16->lengthOf(i));
798        }
799    }
800    virtual ~UniStrCollPerfFunction();
801
802protected:
803    const CA_uchar* d16;
804    UnicodeString** source;
805};
806
807UniStrCollPerfFunction::~UniStrCollPerfFunction() {
808    for (int32_t i = 0; i < d16->count; ++i) {
809        delete source[i];
810    }
811    delete[] source;
812}
813
814//
815// Test case sorting an array of UnicodeString pointers.
816//
817class UniStrSort : public UniStrCollPerfFunction {
818public:
819    UniStrSort(const Collator& coll, const UCollator *ucoll, const CA_uchar* data16)
820            : UniStrCollPerfFunction(coll, ucoll, data16),
821              dest(new UnicodeString*[d16->count]) {}
822    virtual ~UniStrSort();
823    virtual void call(UErrorCode* status);
824
825private:
826    UnicodeString** dest;  // aliases only
827};
828
829UniStrSort::~UniStrSort() {
830    delete[] dest;
831}
832
833void UniStrSort::call(UErrorCode* status) {
834    if (U_FAILURE(*status)) return;
835
836    CollatorAndCounter cc(coll);
837    int32_t count = d16->count;
838    memcpy(dest, source, count * sizeof(UnicodeString *));
839    uprv_sortArray(dest, count, (int32_t)sizeof(UnicodeString *),
840                   UniStrCollatorComparator, &cc, TRUE, status);
841    ops = cc.counter;
842}
843
844namespace {
845
846int32_t U_CALLCONV
847StringPieceCollatorComparator(const void* context, const void* left, const void* right) {
848    CollatorAndCounter& cc = *(CollatorAndCounter*)context;
849    const StringPiece& leftString = *(const StringPiece*)left;
850    const StringPiece& rightString = *(const StringPiece*)right;
851    UErrorCode errorCode = U_ZERO_ERROR;
852    ++cc.counter;
853    return cc.coll.compareUTF8(leftString, rightString, errorCode);
854}
855
856int32_t U_CALLCONV
857StringPieceUCollatorComparator(const void* context, const void* left, const void* right) {
858    CollatorAndCounter& cc = *(CollatorAndCounter*)context;
859    const StringPiece& leftString = *(const StringPiece*)left;
860    const StringPiece& rightString = *(const StringPiece*)right;
861    UErrorCode errorCode = U_ZERO_ERROR;
862    ++cc.counter;
863    return ucol_strcollUTF8(cc.ucoll,
864                            leftString.data(), leftString.length(),
865                            rightString.data(), rightString.length(), &errorCode);
866}
867
868}  // namespace
869
870class StringPieceCollPerfFunction : public CollPerfFunction {
871public:
872    StringPieceCollPerfFunction(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
873            : CollPerfFunction(coll, ucoll), d8(data8),
874              source(new StringPiece[d8->count]) {
875        for (int32_t i = 0; i < d8->count; ++i) {
876            source[i].set(d8->dataOf(i), d8->lengthOf(i));
877        }
878    }
879    virtual ~StringPieceCollPerfFunction();
880
881protected:
882    const CA_char* d8;
883    StringPiece* source;
884};
885
886StringPieceCollPerfFunction::~StringPieceCollPerfFunction() {
887    delete[] source;
888}
889
890class StringPieceSort : public StringPieceCollPerfFunction {
891public:
892    StringPieceSort(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
893            : StringPieceCollPerfFunction(coll, ucoll, data8),
894              dest(new StringPiece[d8->count]) {}
895    virtual ~StringPieceSort();
896
897protected:
898    StringPiece* dest;
899};
900
901StringPieceSort::~StringPieceSort() {
902    delete[] dest;
903}
904
905//
906// Test case sorting an array of UTF-8 StringPiece's with Collator::compareUTF8().
907//
908class StringPieceSortCpp : public StringPieceSort {
909public:
910    StringPieceSortCpp(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
911            : StringPieceSort(coll, ucoll, data8) {}
912    virtual ~StringPieceSortCpp();
913    virtual void call(UErrorCode* status);
914};
915
916StringPieceSortCpp::~StringPieceSortCpp() {}
917
918void StringPieceSortCpp::call(UErrorCode* status) {
919    if (U_FAILURE(*status)) return;
920
921    CollatorAndCounter cc(coll);
922    int32_t count = d8->count;
923    memcpy(dest, source, count * sizeof(StringPiece));
924    uprv_sortArray(dest, count, (int32_t)sizeof(StringPiece),
925                   StringPieceCollatorComparator, &cc, TRUE, status);
926    ops = cc.counter;
927}
928
929//
930// Test case sorting an array of UTF-8 StringPiece's with ucol_strcollUTF8().
931//
932class StringPieceSortC : public StringPieceSort {
933public:
934    StringPieceSortC(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
935            : StringPieceSort(coll, ucoll, data8) {}
936    virtual ~StringPieceSortC();
937    virtual void call(UErrorCode* status);
938};
939
940StringPieceSortC::~StringPieceSortC() {}
941
942void StringPieceSortC::call(UErrorCode* status) {
943    if (U_FAILURE(*status)) return;
944
945    CollatorAndCounter cc(coll, ucoll);
946    int32_t count = d8->count;
947    memcpy(dest, source, count * sizeof(StringPiece));
948    uprv_sortArray(dest, count, (int32_t)sizeof(StringPiece),
949                   StringPieceUCollatorComparator, &cc, TRUE, status);
950    ops = cc.counter;
951}
952
953//
954// Test case performing binary searches in a sorted array of UnicodeString pointers.
955//
956class UniStrBinSearch : public UniStrCollPerfFunction {
957public:
958    UniStrBinSearch(const Collator& coll, const UCollator *ucoll, const CA_uchar* data16)
959            : UniStrCollPerfFunction(coll, ucoll, data16) {}
960    virtual ~UniStrBinSearch();
961    virtual void call(UErrorCode* status);
962};
963
964UniStrBinSearch::~UniStrBinSearch() {}
965
966void UniStrBinSearch::call(UErrorCode* status) {
967    if (U_FAILURE(*status)) return;
968
969    CollatorAndCounter cc(coll);
970    int32_t count = d16->count;
971    for (int32_t i = 0; i < count; ++i) {
972        (void)uprv_stableBinarySearch((char *)source, count,
973                                      source + i, (int32_t)sizeof(UnicodeString *),
974                                      UniStrCollatorComparator, &cc);
975    }
976    ops = cc.counter;
977}
978
979class StringPieceBinSearch : public StringPieceCollPerfFunction {
980public:
981    StringPieceBinSearch(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
982            : StringPieceCollPerfFunction(coll, ucoll, data8) {}
983    virtual ~StringPieceBinSearch();
984};
985
986StringPieceBinSearch::~StringPieceBinSearch() {}
987
988//
989// Test case performing binary searches in a sorted array of UTF-8 StringPiece's
990// with Collator::compareUTF8().
991//
992class StringPieceBinSearchCpp : public StringPieceBinSearch {
993public:
994    StringPieceBinSearchCpp(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
995            : StringPieceBinSearch(coll, ucoll, data8) {}
996    virtual ~StringPieceBinSearchCpp();
997    virtual void call(UErrorCode* status);
998};
999
1000StringPieceBinSearchCpp::~StringPieceBinSearchCpp() {}
1001
1002void StringPieceBinSearchCpp::call(UErrorCode* status) {
1003    if (U_FAILURE(*status)) return;
1004
1005    CollatorAndCounter cc(coll);
1006    int32_t count = d8->count;
1007    for (int32_t i = 0; i < count; ++i) {
1008        (void)uprv_stableBinarySearch((char *)source, count,
1009                                      source + i, (int32_t)sizeof(StringPiece),
1010                                      StringPieceCollatorComparator, &cc);
1011    }
1012    ops = cc.counter;
1013}
1014
1015//
1016// Test case performing binary searches in a sorted array of UTF-8 StringPiece's
1017// with ucol_strcollUTF8().
1018//
1019class StringPieceBinSearchC : public StringPieceBinSearch {
1020public:
1021    StringPieceBinSearchC(const Collator& coll, const UCollator *ucoll, const CA_char* data8)
1022            : StringPieceBinSearch(coll, ucoll, data8) {}
1023    virtual ~StringPieceBinSearchC();
1024    virtual void call(UErrorCode* status);
1025};
1026
1027StringPieceBinSearchC::~StringPieceBinSearchC() {}
1028
1029void StringPieceBinSearchC::call(UErrorCode* status) {
1030    if (U_FAILURE(*status)) return;
1031
1032    CollatorAndCounter cc(coll, ucoll);
1033    int32_t count = d8->count;
1034    for (int32_t i = 0; i < count; ++i) {
1035        (void)uprv_stableBinarySearch((char *)source, count,
1036                                      source + i, (int32_t)sizeof(StringPiece),
1037                                      StringPieceUCollatorComparator, &cc);
1038    }
1039    ops = cc.counter;
1040}
1041
1042
1043class CollPerf2Test : public UPerfTest
1044{
1045public:
1046    CollPerf2Test(int32_t argc, const char *argv[], UErrorCode &status);
1047    ~CollPerf2Test();
1048    virtual UPerfFunction* runIndexedTest(
1049        int32_t index, UBool exec, const char *&name, char *par = NULL);
1050
1051private:
1052    UCollator* coll;
1053    Collator* collObj;
1054
1055    int32_t count;
1056    CA_uchar* data16;
1057    CA_char* data8;
1058
1059    CA_uchar* modData16;
1060    CA_char* modData8;
1061
1062    CA_uchar* sortedData16;
1063    CA_char* sortedData8;
1064
1065    CA_uchar* randomData16;
1066    CA_char* randomData8;
1067
1068    const CA_uchar* getData16(UErrorCode &status);
1069    const CA_char* getData8(UErrorCode &status);
1070
1071    const CA_uchar* getModData16(UErrorCode &status);
1072    const CA_char* getModData8(UErrorCode &status);
1073
1074    const CA_uchar* getSortedData16(UErrorCode &status);
1075    const CA_char* getSortedData8(UErrorCode &status);
1076
1077    const CA_uchar* getRandomData16(UErrorCode &status);
1078    const CA_char* getRandomData8(UErrorCode &status);
1079
1080    static CA_uchar* sortData16(
1081            const CA_uchar* d16,
1082            UComparator *cmp, const void *context,
1083            UErrorCode &status);
1084    static CA_char* getData8FromData16(const CA_uchar* d16, UErrorCode &status);
1085
1086    UPerfFunction* TestStrcoll();
1087    UPerfFunction* TestStrcollNull();
1088    UPerfFunction* TestStrcollSimilar();
1089
1090    UPerfFunction* TestStrcollUTF8();
1091    UPerfFunction* TestStrcollUTF8Null();
1092    UPerfFunction* TestStrcollUTF8Similar();
1093
1094    UPerfFunction* TestGetSortKey();
1095    UPerfFunction* TestGetSortKeyNull();
1096
1097    UPerfFunction* TestNextSortKeyPart_4All();
1098    UPerfFunction* TestNextSortKeyPart_4x2();
1099    UPerfFunction* TestNextSortKeyPart_4x4();
1100    UPerfFunction* TestNextSortKeyPart_4x8();
1101    UPerfFunction* TestNextSortKeyPart_32All();
1102    UPerfFunction* TestNextSortKeyPart_32x2();
1103
1104    UPerfFunction* TestNextSortKeyPartUTF8_4All();
1105    UPerfFunction* TestNextSortKeyPartUTF8_4x2();
1106    UPerfFunction* TestNextSortKeyPartUTF8_4x4();
1107    UPerfFunction* TestNextSortKeyPartUTF8_4x8();
1108    UPerfFunction* TestNextSortKeyPartUTF8_32All();
1109    UPerfFunction* TestNextSortKeyPartUTF8_32x2();
1110
1111    UPerfFunction* TestCppCompare();
1112    UPerfFunction* TestCppCompareNull();
1113    UPerfFunction* TestCppCompareSimilar();
1114
1115    UPerfFunction* TestCppCompareUTF8();
1116    UPerfFunction* TestCppCompareUTF8Null();
1117    UPerfFunction* TestCppCompareUTF8Similar();
1118
1119    UPerfFunction* TestCppGetCollationKey();
1120    UPerfFunction* TestCppGetCollationKeyNull();
1121
1122    UPerfFunction* TestUniStrSort();
1123    UPerfFunction* TestStringPieceSortCpp();
1124    UPerfFunction* TestStringPieceSortC();
1125
1126    UPerfFunction* TestUniStrBinSearch();
1127    UPerfFunction* TestStringPieceBinSearchCpp();
1128    UPerfFunction* TestStringPieceBinSearchC();
1129};
1130
1131CollPerf2Test::CollPerf2Test(int32_t argc, const char *argv[], UErrorCode &status) :
1132    UPerfTest(argc, argv, status),
1133    coll(NULL),
1134    collObj(NULL),
1135    count(0),
1136    data16(NULL),
1137    data8(NULL),
1138    modData16(NULL),
1139    modData8(NULL),
1140    sortedData16(NULL),
1141    sortedData8(NULL),
1142    randomData16(NULL),
1143    randomData8(NULL)
1144{
1145    if (U_FAILURE(status)) {
1146        return;
1147    }
1148
1149    if (locale == NULL){
1150        locale = "root";
1151    }
1152
1153    // Set up an ICU collator.
1154    // Starting with ICU 54 (ticket #8260), this supports standard collation locale keywords.
1155    coll = ucol_open(locale, &status);
1156    collObj = Collator::createInstance(locale, status);
1157}
1158
1159CollPerf2Test::~CollPerf2Test()
1160{
1161    ucol_close(coll);
1162    delete collObj;
1163
1164    delete data16;
1165    delete data8;
1166    delete modData16;
1167    delete modData8;
1168    delete sortedData16;
1169    delete sortedData8;
1170    delete randomData16;
1171    delete randomData8;
1172}
1173
1174#define MAX_NUM_DATA 10000
1175
1176const CA_uchar* CollPerf2Test::getData16(UErrorCode &status)
1177{
1178    if (U_FAILURE(status)) return NULL;
1179    if (data16) return data16;
1180
1181    CA_uchar* d16 = new CA_uchar();
1182    const UChar *line = NULL;
1183    int32_t len = 0;
1184    int32_t numData = 0;
1185
1186    for (;;) {
1187        line = ucbuf_readline(ucharBuf, &len, &status);
1188        if (line == NULL || U_FAILURE(status)) break;
1189
1190        // Refer to the source code of ucbuf_readline()
1191        // 1. 'len' includes the line terminal symbols
1192        // 2. The length of the line terminal symbols is only one character
1193        // 3. The Windows CR LF line terminal symbols will be converted to CR
1194
1195        if (len == 1 || line[0] == 0x23 /* '#' */) {
1196            continue; // skip empty/comment line
1197        } else {
1198            d16->append_one(len);
1199            UChar *p = d16->last();
1200            u_memcpy(p, line, len - 1);  // exclude the CR
1201            p[len - 1] = 0;  // NUL-terminate
1202
1203            numData++;
1204            if (numData >= MAX_NUM_DATA) break;
1205        }
1206    }
1207
1208    if (U_SUCCESS(status)) {
1209        data16 = d16;
1210    } else {
1211        delete d16;
1212    }
1213
1214    return data16;
1215}
1216
1217const CA_char* CollPerf2Test::getData8(UErrorCode &status)
1218{
1219    if (U_FAILURE(status)) return NULL;
1220    if (data8) return data8;
1221    return data8 = getData8FromData16(getData16(status), status);
1222}
1223
1224const CA_uchar* CollPerf2Test::getModData16(UErrorCode &status)
1225{
1226    if (U_FAILURE(status)) return NULL;
1227    if (modData16) return modData16;
1228
1229    const CA_uchar* d16 = getData16(status);
1230    if (U_FAILURE(status)) return NULL;
1231
1232    CA_uchar* modData16 = new CA_uchar();
1233
1234    for (int32_t i = 0; i < d16->count; i++) {
1235        const UChar *s = d16->dataOf(i);
1236        int32_t len = d16->lengthOf(i) + 1; // including NULL terminator
1237
1238        modData16->append_one(len);
1239        u_memcpy(modData16->last(), s, len);
1240
1241        // replacing the last character with a different character
1242        UChar *lastChar = &modData16->last()[len -2];
1243        for (int32_t j = i + 1; j != i; j++) {
1244            if (j >= d16->count) {
1245                j = 0;
1246            }
1247            const UChar *s1 = d16->dataOf(j);
1248            UChar lastChar1 = s1[d16->lengthOf(j) - 1];
1249            if (*lastChar != lastChar1) {
1250                *lastChar = lastChar1;
1251                break;
1252            }
1253        }
1254    }
1255
1256    return modData16;
1257}
1258
1259const CA_char* CollPerf2Test::getModData8(UErrorCode &status)
1260{
1261    if (U_FAILURE(status)) return NULL;
1262    if (modData8) return modData8;
1263    return modData8 = getData8FromData16(getModData16(status), status);
1264}
1265
1266namespace {
1267
1268struct ArrayAndColl {
1269    ArrayAndColl(const CA_uchar* a, const Collator& c) : d16(a), coll(c) {}
1270    const CA_uchar* d16;
1271    const Collator& coll;
1272};
1273
1274int32_t U_CALLCONV
1275U16CollatorComparator(const void* context, const void* left, const void* right) {
1276    const ArrayAndColl& ac = *(const ArrayAndColl*)context;
1277    const CA_uchar* d16 = ac.d16;
1278    int32_t leftIndex = *(const int32_t*)left;
1279    int32_t rightIndex = *(const int32_t*)right;
1280    UErrorCode errorCode = U_ZERO_ERROR;
1281    return ac.coll.compare(d16->dataOf(leftIndex), d16->lengthOf(leftIndex),
1282                           d16->dataOf(rightIndex), d16->lengthOf(rightIndex),
1283                           errorCode);
1284}
1285
1286int32_t U_CALLCONV
1287U16HashComparator(const void* context, const void* left, const void* right) {
1288    const CA_uchar* d16 = (const CA_uchar*)context;
1289    int32_t leftIndex = *(const int32_t*)left;
1290    int32_t rightIndex = *(const int32_t*)right;
1291    int32_t leftHash = ustr_hashUCharsN(d16->dataOf(leftIndex), d16->lengthOf(leftIndex));
1292    int32_t rightHash = ustr_hashUCharsN(d16->dataOf(rightIndex), d16->lengthOf(rightIndex));
1293    return leftHash < rightHash ? -1 : leftHash == rightHash ? 0 : 1;
1294}
1295
1296}  // namespace
1297
1298const CA_uchar* CollPerf2Test::getSortedData16(UErrorCode &status) {
1299    if (U_FAILURE(status)) return NULL;
1300    if (sortedData16) return sortedData16;
1301
1302    ArrayAndColl ac(getData16(status), *collObj);
1303    return sortedData16 = sortData16(ac.d16, U16CollatorComparator, &ac, status);
1304}
1305
1306const CA_char* CollPerf2Test::getSortedData8(UErrorCode &status) {
1307    if (U_FAILURE(status)) return NULL;
1308    if (sortedData8) return sortedData8;
1309    return sortedData8 = getData8FromData16(getSortedData16(status), status);
1310}
1311
1312const CA_uchar* CollPerf2Test::getRandomData16(UErrorCode &status) {
1313    if (U_FAILURE(status)) return NULL;
1314    if (randomData16) return randomData16;
1315
1316    // Sort the strings by their hash codes, which should be a reasonably pseudo-random order.
1317    const CA_uchar* d16 = getData16(status);
1318    return randomData16 = sortData16(d16, U16HashComparator, d16, status);
1319}
1320
1321const CA_char* CollPerf2Test::getRandomData8(UErrorCode &status) {
1322    if (U_FAILURE(status)) return NULL;
1323    if (randomData8) return randomData8;
1324    return randomData8 = getData8FromData16(getRandomData16(status), status);
1325}
1326
1327CA_uchar* CollPerf2Test::sortData16(const CA_uchar* d16,
1328                                    UComparator *cmp, const void *context,
1329                                    UErrorCode &status) {
1330    if (U_FAILURE(status)) return NULL;
1331
1332    LocalArray<int32_t> indexes(new int32_t[d16->count]);
1333    for (int32_t i = 0; i < d16->count; ++i) {
1334        indexes[i] = i;
1335    }
1336    uprv_sortArray(indexes.getAlias(), d16->count, 4, cmp, context, TRUE, &status);
1337    if (U_FAILURE(status)) return NULL;
1338
1339    // Copy the strings in sorted order into a new array.
1340    LocalPointer<CA_uchar> newD16(new CA_uchar());
1341    for (int32_t i = 0; i < d16->count; i++) {
1342        int32_t j = indexes[i];
1343        const UChar* s = d16->dataOf(j);
1344        int32_t len = d16->lengthOf(j);
1345        int32_t capacity = len + 1;  // including NULL terminator
1346        newD16->append_one(capacity);
1347        u_memcpy(newD16->last(), s, capacity);
1348    }
1349
1350    if (U_SUCCESS(status)) {
1351        return newD16.orphan();
1352    } else {
1353        return NULL;
1354    }
1355}
1356
1357CA_char* CollPerf2Test::getData8FromData16(const CA_uchar* d16, UErrorCode &status) {
1358    if (U_FAILURE(status)) return NULL;
1359
1360    // UTF-16 -> UTF-8 conversion
1361    LocalPointer<CA_char> d8(new CA_char());
1362    for (int32_t i = 0; i < d16->count; i++) {
1363        const UChar *s16 = d16->dataOf(i);
1364        int32_t length16 = d16->lengthOf(i);
1365
1366        // get length in UTF-8
1367        int32_t length8;
1368        u_strToUTF8(NULL, 0, &length8, s16, length16, &status);
1369        if (status == U_BUFFER_OVERFLOW_ERROR || status == U_ZERO_ERROR){
1370            status = U_ZERO_ERROR;
1371        } else {
1372            break;
1373        }
1374        int32_t capacity8 = length8 + 1;  // plus terminal NULL
1375        d8->append_one(capacity8);
1376
1377        // convert to UTF-8
1378        u_strToUTF8(d8->last(), capacity8, NULL, s16, length16, &status);
1379        if (U_FAILURE(status)) break;
1380    }
1381
1382    if (U_SUCCESS(status)) {
1383        return d8.orphan();
1384    } else {
1385        return NULL;
1386    }
1387}
1388
1389UPerfFunction*
1390CollPerf2Test::runIndexedTest(int32_t index, UBool exec, const char *&name, char *par /*= NULL*/)
1391{
1392    (void)par;
1393    TESTCASE_AUTO_BEGIN;
1394
1395    TESTCASE_AUTO(TestStrcoll);
1396    TESTCASE_AUTO(TestStrcollNull);
1397    TESTCASE_AUTO(TestStrcollSimilar);
1398
1399    TESTCASE_AUTO(TestStrcollUTF8);
1400    TESTCASE_AUTO(TestStrcollUTF8Null);
1401    TESTCASE_AUTO(TestStrcollUTF8Similar);
1402
1403    TESTCASE_AUTO(TestGetSortKey);
1404    TESTCASE_AUTO(TestGetSortKeyNull);
1405
1406    TESTCASE_AUTO(TestNextSortKeyPart_4All);
1407    TESTCASE_AUTO(TestNextSortKeyPart_4x4);
1408    TESTCASE_AUTO(TestNextSortKeyPart_4x8);
1409    TESTCASE_AUTO(TestNextSortKeyPart_32All);
1410    TESTCASE_AUTO(TestNextSortKeyPart_32x2);
1411
1412    TESTCASE_AUTO(TestNextSortKeyPartUTF8_4All);
1413    TESTCASE_AUTO(TestNextSortKeyPartUTF8_4x4);
1414    TESTCASE_AUTO(TestNextSortKeyPartUTF8_4x8);
1415    TESTCASE_AUTO(TestNextSortKeyPartUTF8_32All);
1416    TESTCASE_AUTO(TestNextSortKeyPartUTF8_32x2);
1417
1418    TESTCASE_AUTO(TestCppCompare);
1419    TESTCASE_AUTO(TestCppCompareNull);
1420    TESTCASE_AUTO(TestCppCompareSimilar);
1421
1422    TESTCASE_AUTO(TestCppCompareUTF8);
1423    TESTCASE_AUTO(TestCppCompareUTF8Null);
1424    TESTCASE_AUTO(TestCppCompareUTF8Similar);
1425
1426    TESTCASE_AUTO(TestCppGetCollationKey);
1427    TESTCASE_AUTO(TestCppGetCollationKeyNull);
1428
1429    TESTCASE_AUTO(TestUniStrSort);
1430    TESTCASE_AUTO(TestStringPieceSortCpp);
1431    TESTCASE_AUTO(TestStringPieceSortC);
1432
1433    TESTCASE_AUTO(TestUniStrBinSearch);
1434    TESTCASE_AUTO(TestStringPieceBinSearchCpp);
1435    TESTCASE_AUTO(TestStringPieceBinSearchC);
1436
1437    TESTCASE_AUTO_END;
1438    return NULL;
1439}
1440
1441
1442
1443UPerfFunction* CollPerf2Test::TestStrcoll()
1444{
1445    UErrorCode status = U_ZERO_ERROR;
1446    Strcoll *testCase = new Strcoll(coll, getData16(status), TRUE /* useLen */);
1447    if (U_FAILURE(status)) {
1448        delete testCase;
1449        return NULL;
1450    }
1451    return testCase;
1452}
1453
1454UPerfFunction* CollPerf2Test::TestStrcollNull()
1455{
1456    UErrorCode status = U_ZERO_ERROR;
1457    Strcoll *testCase = new Strcoll(coll, getData16(status), FALSE /* useLen */);
1458    if (U_FAILURE(status)) {
1459        delete testCase;
1460        return NULL;
1461    }
1462    return testCase;
1463}
1464
1465UPerfFunction* CollPerf2Test::TestStrcollSimilar()
1466{
1467    UErrorCode status = U_ZERO_ERROR;
1468    Strcoll_2 *testCase = new Strcoll_2(coll, getData16(status), getModData16(status), TRUE /* useLen */);
1469    if (U_FAILURE(status)) {
1470        delete testCase;
1471        return NULL;
1472    }
1473    return testCase;
1474}
1475
1476UPerfFunction* CollPerf2Test::TestStrcollUTF8()
1477{
1478    UErrorCode status = U_ZERO_ERROR;
1479    StrcollUTF8 *testCase = new StrcollUTF8(coll, getData8(status), TRUE /* useLen */);
1480    if (U_FAILURE(status)) {
1481        delete testCase;
1482        return NULL;
1483    }
1484    return testCase;
1485}
1486
1487UPerfFunction* CollPerf2Test::TestStrcollUTF8Null()
1488{
1489    UErrorCode status = U_ZERO_ERROR;
1490    StrcollUTF8 *testCase = new StrcollUTF8(coll, getData8(status),FALSE /* useLen */);
1491    if (U_FAILURE(status)) {
1492        delete testCase;
1493        return NULL;
1494    }
1495    return testCase;
1496}
1497
1498UPerfFunction* CollPerf2Test::TestStrcollUTF8Similar()
1499{
1500    UErrorCode status = U_ZERO_ERROR;
1501    StrcollUTF8_2 *testCase = new StrcollUTF8_2(coll, getData8(status), getModData8(status), TRUE /* useLen */);
1502    if (U_FAILURE(status)) {
1503        delete testCase;
1504        return NULL;
1505    }
1506    return testCase;
1507}
1508
1509UPerfFunction* CollPerf2Test::TestGetSortKey()
1510{
1511    UErrorCode status = U_ZERO_ERROR;
1512    GetSortKey *testCase = new GetSortKey(coll, getData16(status), TRUE /* useLen */);
1513    if (U_FAILURE(status)) {
1514        delete testCase;
1515        return NULL;
1516    }
1517    return testCase;
1518}
1519
1520UPerfFunction* CollPerf2Test::TestGetSortKeyNull()
1521{
1522    UErrorCode status = U_ZERO_ERROR;
1523    GetSortKey *testCase = new GetSortKey(coll, getData16(status), FALSE /* useLen */);
1524    if (U_FAILURE(status)) {
1525        delete testCase;
1526        return NULL;
1527    }
1528    return testCase;
1529}
1530
1531UPerfFunction* CollPerf2Test::TestNextSortKeyPart_4All()
1532{
1533    UErrorCode status = U_ZERO_ERROR;
1534    NextSortKeyPart *testCase = new NextSortKeyPart(coll, getData16(status), 4 /* bufSize */);
1535    if (U_FAILURE(status)) {
1536        delete testCase;
1537        return NULL;
1538    }
1539    return testCase;
1540}
1541
1542UPerfFunction* CollPerf2Test::TestNextSortKeyPart_4x4()
1543{
1544    UErrorCode status = U_ZERO_ERROR;
1545    NextSortKeyPart *testCase = new NextSortKeyPart(coll, getData16(status), 4 /* bufSize */, 4 /* maxIteration */);
1546    if (U_FAILURE(status)) {
1547        delete testCase;
1548        return NULL;
1549    }
1550    return testCase;
1551}
1552
1553UPerfFunction* CollPerf2Test::TestNextSortKeyPart_4x8()
1554{
1555    UErrorCode status = U_ZERO_ERROR;
1556    NextSortKeyPart *testCase = new NextSortKeyPart(coll, getData16(status), 4 /* bufSize */, 8 /* maxIteration */);
1557    if (U_FAILURE(status)) {
1558        delete testCase;
1559        return NULL;
1560    }
1561    return testCase;
1562}
1563
1564UPerfFunction* CollPerf2Test::TestNextSortKeyPart_32All()
1565{
1566    UErrorCode status = U_ZERO_ERROR;
1567    NextSortKeyPart *testCase = new NextSortKeyPart(coll, getData16(status), 32 /* bufSize */);
1568    if (U_FAILURE(status)) {
1569        delete testCase;
1570        return NULL;
1571    }
1572    return testCase;
1573}
1574
1575UPerfFunction* CollPerf2Test::TestNextSortKeyPart_32x2()
1576{
1577    UErrorCode status = U_ZERO_ERROR;
1578    NextSortKeyPart *testCase = new NextSortKeyPart(coll, getData16(status), 32 /* bufSize */, 2 /* maxIteration */);
1579    if (U_FAILURE(status)) {
1580        delete testCase;
1581        return NULL;
1582    }
1583    return testCase;
1584}
1585
1586UPerfFunction* CollPerf2Test::TestNextSortKeyPartUTF8_4All()
1587{
1588    UErrorCode status = U_ZERO_ERROR;
1589    NextSortKeyPartUTF8 *testCase = new NextSortKeyPartUTF8(coll, getData8(status), 4 /* bufSize */);
1590    if (U_FAILURE(status)) {
1591        delete testCase;
1592        return NULL;
1593    }
1594    return testCase;
1595}
1596
1597UPerfFunction* CollPerf2Test::TestNextSortKeyPartUTF8_4x4()
1598{
1599    UErrorCode status = U_ZERO_ERROR;
1600    NextSortKeyPartUTF8 *testCase = new NextSortKeyPartUTF8(coll, getData8(status), 4 /* bufSize */, 4 /* maxIteration */);
1601    if (U_FAILURE(status)) {
1602        delete testCase;
1603        return NULL;
1604    }
1605    return testCase;
1606}
1607
1608UPerfFunction* CollPerf2Test::TestNextSortKeyPartUTF8_4x8()
1609{
1610    UErrorCode status = U_ZERO_ERROR;
1611    NextSortKeyPartUTF8 *testCase = new NextSortKeyPartUTF8(coll, getData8(status), 4 /* bufSize */, 8 /* maxIteration */);
1612    if (U_FAILURE(status)) {
1613        delete testCase;
1614        return NULL;
1615    }
1616    return testCase;
1617}
1618
1619UPerfFunction* CollPerf2Test::TestNextSortKeyPartUTF8_32All()
1620{
1621    UErrorCode status = U_ZERO_ERROR;
1622    NextSortKeyPartUTF8 *testCase = new NextSortKeyPartUTF8(coll, getData8(status), 32 /* bufSize */);
1623    if (U_FAILURE(status)) {
1624        delete testCase;
1625        return NULL;
1626    }
1627    return testCase;
1628}
1629
1630UPerfFunction* CollPerf2Test::TestNextSortKeyPartUTF8_32x2()
1631{
1632    UErrorCode status = U_ZERO_ERROR;
1633    NextSortKeyPartUTF8 *testCase = new NextSortKeyPartUTF8(coll, getData8(status), 32 /* bufSize */, 2 /* maxIteration */);
1634    if (U_FAILURE(status)) {
1635        delete testCase;
1636        return NULL;
1637    }
1638    return testCase;
1639}
1640
1641UPerfFunction* CollPerf2Test::TestCppCompare()
1642{
1643    UErrorCode status = U_ZERO_ERROR;
1644    CppCompare *testCase = new CppCompare(collObj, getData16(status), TRUE /* useLen */);
1645    if (U_FAILURE(status)) {
1646        delete testCase;
1647        return NULL;
1648    }
1649    return testCase;
1650}
1651
1652UPerfFunction* CollPerf2Test::TestCppCompareNull()
1653{
1654    UErrorCode status = U_ZERO_ERROR;
1655    CppCompare *testCase = new CppCompare(collObj, getData16(status), FALSE /* useLen */);
1656    if (U_FAILURE(status)) {
1657        delete testCase;
1658        return NULL;
1659    }
1660    return testCase;
1661}
1662
1663UPerfFunction* CollPerf2Test::TestCppCompareSimilar()
1664{
1665    UErrorCode status = U_ZERO_ERROR;
1666    CppCompare_2 *testCase = new CppCompare_2(collObj, getData16(status), getModData16(status), TRUE /* useLen */);
1667    if (U_FAILURE(status)) {
1668        delete testCase;
1669        return NULL;
1670    }
1671    return testCase;
1672}
1673
1674UPerfFunction* CollPerf2Test::TestCppCompareUTF8()
1675{
1676    UErrorCode status = U_ZERO_ERROR;
1677    CppCompareUTF8 *testCase = new CppCompareUTF8(collObj, getData8(status), TRUE /* useLen */);
1678    if (U_FAILURE(status)) {
1679        delete testCase;
1680        return NULL;
1681    }
1682    return testCase;
1683}
1684
1685UPerfFunction* CollPerf2Test::TestCppCompareUTF8Null()
1686{
1687    UErrorCode status = U_ZERO_ERROR;
1688    CppCompareUTF8 *testCase = new CppCompareUTF8(collObj, getData8(status), FALSE /* useLen */);
1689    if (U_FAILURE(status)) {
1690        delete testCase;
1691        return NULL;
1692    }
1693    return testCase;
1694}
1695
1696UPerfFunction* CollPerf2Test::TestCppCompareUTF8Similar()
1697{
1698    UErrorCode status = U_ZERO_ERROR;
1699    CppCompareUTF8_2 *testCase = new CppCompareUTF8_2(collObj, getData8(status), getModData8(status), TRUE /* useLen */);
1700    if (U_FAILURE(status)) {
1701        delete testCase;
1702        return NULL;
1703    }
1704    return testCase;
1705}
1706
1707UPerfFunction* CollPerf2Test::TestCppGetCollationKey()
1708{
1709    UErrorCode status = U_ZERO_ERROR;
1710    CppGetCollationKey *testCase = new CppGetCollationKey(collObj, getData16(status), TRUE /* useLen */);
1711    if (U_FAILURE(status)) {
1712        delete testCase;
1713        return NULL;
1714    }
1715    return testCase;
1716}
1717
1718UPerfFunction* CollPerf2Test::TestCppGetCollationKeyNull()
1719{
1720    UErrorCode status = U_ZERO_ERROR;
1721    CppGetCollationKey *testCase = new CppGetCollationKey(collObj, getData16(status), FALSE /* useLen */);
1722    if (U_FAILURE(status)) {
1723        delete testCase;
1724        return NULL;
1725    }
1726    return testCase;
1727}
1728
1729UPerfFunction* CollPerf2Test::TestUniStrSort() {
1730    UErrorCode status = U_ZERO_ERROR;
1731    UPerfFunction *testCase = new UniStrSort(*collObj, coll, getRandomData16(status));
1732    if (U_FAILURE(status)) {
1733        delete testCase;
1734        return NULL;
1735    }
1736    return testCase;
1737}
1738
1739UPerfFunction* CollPerf2Test::TestStringPieceSortCpp() {
1740    UErrorCode status = U_ZERO_ERROR;
1741    UPerfFunction *testCase = new StringPieceSortCpp(*collObj, coll, getRandomData8(status));
1742    if (U_FAILURE(status)) {
1743        delete testCase;
1744        return NULL;
1745    }
1746    return testCase;
1747}
1748
1749UPerfFunction* CollPerf2Test::TestStringPieceSortC() {
1750    UErrorCode status = U_ZERO_ERROR;
1751    UPerfFunction *testCase = new StringPieceSortC(*collObj, coll, getRandomData8(status));
1752    if (U_FAILURE(status)) {
1753        delete testCase;
1754        return NULL;
1755    }
1756    return testCase;
1757}
1758
1759UPerfFunction* CollPerf2Test::TestUniStrBinSearch() {
1760    UErrorCode status = U_ZERO_ERROR;
1761    UPerfFunction *testCase = new UniStrBinSearch(*collObj, coll, getSortedData16(status));
1762    if (U_FAILURE(status)) {
1763        delete testCase;
1764        return NULL;
1765    }
1766    return testCase;
1767}
1768
1769UPerfFunction* CollPerf2Test::TestStringPieceBinSearchCpp() {
1770    UErrorCode status = U_ZERO_ERROR;
1771    UPerfFunction *testCase = new StringPieceBinSearchCpp(*collObj, coll, getSortedData8(status));
1772    if (U_FAILURE(status)) {
1773        delete testCase;
1774        return NULL;
1775    }
1776    return testCase;
1777}
1778
1779UPerfFunction* CollPerf2Test::TestStringPieceBinSearchC() {
1780    UErrorCode status = U_ZERO_ERROR;
1781    UPerfFunction *testCase = new StringPieceBinSearchC(*collObj, coll, getSortedData8(status));
1782    if (U_FAILURE(status)) {
1783        delete testCase;
1784        return NULL;
1785    }
1786    return testCase;
1787}
1788
1789
1790int main(int argc, const char *argv[])
1791{
1792    UErrorCode status = U_ZERO_ERROR;
1793    CollPerf2Test test(argc, argv, status);
1794
1795    if (U_FAILURE(status)){
1796        printf("The error is %s\n", u_errorName(status));
1797        //TODO: print usage here
1798        return status;
1799    }
1800
1801    if (test.run() == FALSE){
1802        fprintf(stderr, "FAILED: Tests could not be run please check the arguments.\n");
1803        return -1;
1804    }
1805    return 0;
1806}
1807