12e5b6d6dSopenharmony_ci/*
22e5b6d6dSopenharmony_ci ***********************************************************************
32e5b6d6dSopenharmony_ci * © 2016 and later: Unicode, Inc. and others.
42e5b6d6dSopenharmony_ci * License & terms of use: http://www.unicode.org/copyright.html
52e5b6d6dSopenharmony_ci ***********************************************************************
62e5b6d6dSopenharmony_ci ***********************************************************************
72e5b6d6dSopenharmony_ci *   Copyright (C) 2002-2014, International Business Machines
82e5b6d6dSopenharmony_ci *   Corporation and others.  All Rights Reserved.
92e5b6d6dSopenharmony_ci ***********************************************************************
102e5b6d6dSopenharmony_ci *  file name:  utrie2perf.cpp
112e5b6d6dSopenharmony_ci *  encoding:   UTF-8
122e5b6d6dSopenharmony_ci *  tab size:   8 (not used)
132e5b6d6dSopenharmony_ci *  indentation:4
142e5b6d6dSopenharmony_ci *
152e5b6d6dSopenharmony_ci *  created on: 2008sep07
162e5b6d6dSopenharmony_ci *  created by: Markus W. Scherer
172e5b6d6dSopenharmony_ci *
182e5b6d6dSopenharmony_ci *  Performance test program for UTrie2.
192e5b6d6dSopenharmony_ci */
202e5b6d6dSopenharmony_ci
212e5b6d6dSopenharmony_ci#include <stdio.h>
222e5b6d6dSopenharmony_ci#include <stdlib.h>
232e5b6d6dSopenharmony_ci#include "unicode/uchar.h"
242e5b6d6dSopenharmony_ci#include "unicode/unorm.h"
252e5b6d6dSopenharmony_ci#include "unicode/uperf.h"
262e5b6d6dSopenharmony_ci#include "uoptions.h"
272e5b6d6dSopenharmony_ci
282e5b6d6dSopenharmony_ci#if 0
292e5b6d6dSopenharmony_ci// Left over from when icu/branches/markus/utf8 could use both old UTrie
302e5b6d6dSopenharmony_ci// and new UTrie2, switched with #if in unorm.cpp and ubidi_props.c.
312e5b6d6dSopenharmony_ci// Comparative benchmarks were done in that branch on revision r24630
322e5b6d6dSopenharmony_ci// and earlier.
332e5b6d6dSopenharmony_ciU_CAPI void U_EXPORT2
342e5b6d6dSopenharmony_ciunorm_initUTrie2(UErrorCode *pErrorCode);
352e5b6d6dSopenharmony_ci
362e5b6d6dSopenharmony_ciU_CAPI void U_EXPORT2
372e5b6d6dSopenharmony_ciubidi_initUTrie2(UErrorCode *pErrorCode);
382e5b6d6dSopenharmony_ci#endif
392e5b6d6dSopenharmony_ci
402e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN
412e5b6d6dSopenharmony_ci
422e5b6d6dSopenharmony_ciclass UnicodeSet;
432e5b6d6dSopenharmony_ci
442e5b6d6dSopenharmony_ciU_NAMESPACE_END
452e5b6d6dSopenharmony_ci
462e5b6d6dSopenharmony_ci// Test object.
472e5b6d6dSopenharmony_ciclass UTrie2PerfTest : public UPerfTest {
482e5b6d6dSopenharmony_cipublic:
492e5b6d6dSopenharmony_ci    UTrie2PerfTest(int32_t argc, const char *argv[], UErrorCode &status)
502e5b6d6dSopenharmony_ci            : UPerfTest(argc, argv, NULL, 0, "", status),
512e5b6d6dSopenharmony_ci              utf8(NULL), utf8Length(0), countInputCodePoints(0) {
522e5b6d6dSopenharmony_ci        if (U_SUCCESS(status)) {
532e5b6d6dSopenharmony_ci#if 0       // See comment at unorm_initUTrie2() forward declaration.
542e5b6d6dSopenharmony_ci            unorm_initUTrie2(&status);
552e5b6d6dSopenharmony_ci            ubidi_initUTrie2(&status);
562e5b6d6dSopenharmony_ci#endif
572e5b6d6dSopenharmony_ci            int32_t inputLength;
582e5b6d6dSopenharmony_ci            UPerfTest::getBuffer(inputLength, status);
592e5b6d6dSopenharmony_ci            if(U_SUCCESS(status) && inputLength>0) {
602e5b6d6dSopenharmony_ci                countInputCodePoints = u_countChar32(buffer, bufferLen);
612e5b6d6dSopenharmony_ci
622e5b6d6dSopenharmony_ci                // Preflight the UTF-8 length and allocate utf8.
632e5b6d6dSopenharmony_ci                u_strToUTF8(NULL, 0, &utf8Length, buffer, bufferLen, &status);
642e5b6d6dSopenharmony_ci                if(status==U_BUFFER_OVERFLOW_ERROR) {
652e5b6d6dSopenharmony_ci                    utf8=(char *)malloc(utf8Length);
662e5b6d6dSopenharmony_ci                    if(utf8!=NULL) {
672e5b6d6dSopenharmony_ci                        status=U_ZERO_ERROR;
682e5b6d6dSopenharmony_ci                        u_strToUTF8(utf8, utf8Length, NULL, buffer, bufferLen, &status);
692e5b6d6dSopenharmony_ci                    } else {
702e5b6d6dSopenharmony_ci                        status=U_MEMORY_ALLOCATION_ERROR;
712e5b6d6dSopenharmony_ci                    }
722e5b6d6dSopenharmony_ci                }
732e5b6d6dSopenharmony_ci
742e5b6d6dSopenharmony_ci                if(verbose) {
752e5b6d6dSopenharmony_ci                    printf("code points:%ld  len16:%ld  len8:%ld  "
762e5b6d6dSopenharmony_ci                           "B/cp:%.3g\n",
772e5b6d6dSopenharmony_ci                           (long)countInputCodePoints, (long)bufferLen, (long)utf8Length,
782e5b6d6dSopenharmony_ci                           (double)utf8Length/countInputCodePoints);
792e5b6d6dSopenharmony_ci                }
802e5b6d6dSopenharmony_ci            }
812e5b6d6dSopenharmony_ci        }
822e5b6d6dSopenharmony_ci    }
832e5b6d6dSopenharmony_ci
842e5b6d6dSopenharmony_ci    virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL);
852e5b6d6dSopenharmony_ci
862e5b6d6dSopenharmony_ci    const UChar *getBuffer() const { return buffer; }
872e5b6d6dSopenharmony_ci    int32_t getBufferLen() const { return bufferLen; }
882e5b6d6dSopenharmony_ci
892e5b6d6dSopenharmony_ci    char *utf8;
902e5b6d6dSopenharmony_ci    int32_t utf8Length;
912e5b6d6dSopenharmony_ci
922e5b6d6dSopenharmony_ci    // Number of code points in the input text.
932e5b6d6dSopenharmony_ci    int32_t countInputCodePoints;
942e5b6d6dSopenharmony_ci};
952e5b6d6dSopenharmony_ci
962e5b6d6dSopenharmony_ci// Performance test function object.
972e5b6d6dSopenharmony_ciclass Command : public UPerfFunction {
982e5b6d6dSopenharmony_ciprotected:
992e5b6d6dSopenharmony_ci    Command(const UTrie2PerfTest &testcase) : testcase(testcase) {}
1002e5b6d6dSopenharmony_ci
1012e5b6d6dSopenharmony_cipublic:
1022e5b6d6dSopenharmony_ci    virtual ~Command() {}
1032e5b6d6dSopenharmony_ci
1042e5b6d6dSopenharmony_ci    // virtual void call(UErrorCode* pErrorCode) { ... }
1052e5b6d6dSopenharmony_ci
1062e5b6d6dSopenharmony_ci    virtual long getOperationsPerIteration() {
1072e5b6d6dSopenharmony_ci        // Number of code points tested.
1082e5b6d6dSopenharmony_ci        return testcase.countInputCodePoints;
1092e5b6d6dSopenharmony_ci    }
1102e5b6d6dSopenharmony_ci
1112e5b6d6dSopenharmony_ci    // virtual long getEventsPerIteration();
1122e5b6d6dSopenharmony_ci
1132e5b6d6dSopenharmony_ci    const UTrie2PerfTest &testcase;
1142e5b6d6dSopenharmony_ci    UNormalizationCheckResult qcResult;
1152e5b6d6dSopenharmony_ci};
1162e5b6d6dSopenharmony_ci
1172e5b6d6dSopenharmony_ciclass CheckFCD : public Command {
1182e5b6d6dSopenharmony_ciprotected:
1192e5b6d6dSopenharmony_ci    CheckFCD(const UTrie2PerfTest &testcase) : Command(testcase) {}
1202e5b6d6dSopenharmony_cipublic:
1212e5b6d6dSopenharmony_ci    static UPerfFunction* get(const UTrie2PerfTest &testcase) {
1222e5b6d6dSopenharmony_ci        return new CheckFCD(testcase);
1232e5b6d6dSopenharmony_ci    }
1242e5b6d6dSopenharmony_ci    virtual void call(UErrorCode* pErrorCode) {
1252e5b6d6dSopenharmony_ci        UErrorCode errorCode=U_ZERO_ERROR;
1262e5b6d6dSopenharmony_ci        qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(),
1272e5b6d6dSopenharmony_ci                                  UNORM_FCD, &errorCode);
1282e5b6d6dSopenharmony_ci        if(U_FAILURE(errorCode)) {
1292e5b6d6dSopenharmony_ci            fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n",
1302e5b6d6dSopenharmony_ci                    u_errorName(errorCode));
1312e5b6d6dSopenharmony_ci        }
1322e5b6d6dSopenharmony_ci    }
1332e5b6d6dSopenharmony_ci};
1342e5b6d6dSopenharmony_ci
1352e5b6d6dSopenharmony_ci#if 0  // See comment at unorm_initUTrie2() forward declaration.
1362e5b6d6dSopenharmony_ci
1372e5b6d6dSopenharmony_ciclass CheckFCDAlwaysGet : public Command {
1382e5b6d6dSopenharmony_ciprotected:
1392e5b6d6dSopenharmony_ci    CheckFCDAlwaysGet(const UTrie2PerfTest &testcase) : Command(testcase) {}
1402e5b6d6dSopenharmony_cipublic:
1412e5b6d6dSopenharmony_ci    static UPerfFunction* get(const UTrie2PerfTest &testcase) {
1422e5b6d6dSopenharmony_ci        return new CheckFCDAlwaysGet(testcase);
1432e5b6d6dSopenharmony_ci    }
1442e5b6d6dSopenharmony_ci    virtual void call(UErrorCode* pErrorCode) {
1452e5b6d6dSopenharmony_ci        UErrorCode errorCode=U_ZERO_ERROR;
1462e5b6d6dSopenharmony_ci        qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(),
1472e5b6d6dSopenharmony_ci                                  UNORM_FCD_ALWAYS_GET, &errorCode);
1482e5b6d6dSopenharmony_ci        if(U_FAILURE(errorCode)) {
1492e5b6d6dSopenharmony_ci            fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n",
1502e5b6d6dSopenharmony_ci                    u_errorName(errorCode));
1512e5b6d6dSopenharmony_ci        }
1522e5b6d6dSopenharmony_ci    }
1532e5b6d6dSopenharmony_ci};
1542e5b6d6dSopenharmony_ci
1552e5b6d6dSopenharmony_ciU_CAPI UBool U_EXPORT2
1562e5b6d6dSopenharmony_ciunorm_checkFCDUTF8(const uint8_t *src, int32_t srcLength, const UnicodeSet *nx);
1572e5b6d6dSopenharmony_ci
1582e5b6d6dSopenharmony_ciclass CheckFCDUTF8 : public Command {
1592e5b6d6dSopenharmony_ciprotected:
1602e5b6d6dSopenharmony_ci    CheckFCDUTF8(const UTrie2PerfTest &testcase) : Command(testcase) {}
1612e5b6d6dSopenharmony_cipublic:
1622e5b6d6dSopenharmony_ci    static UPerfFunction* get(const UTrie2PerfTest &testcase) {
1632e5b6d6dSopenharmony_ci        return new CheckFCDUTF8(testcase);
1642e5b6d6dSopenharmony_ci    }
1652e5b6d6dSopenharmony_ci    virtual void call(UErrorCode* pErrorCode) {
1662e5b6d6dSopenharmony_ci        UBool isFCD=unorm_checkFCDUTF8((const uint8_t *)testcase.utf8, testcase.utf8Length, NULL);
1672e5b6d6dSopenharmony_ci        if(isFCD>1) {
1682e5b6d6dSopenharmony_ci            fprintf(stderr, "error: bogus result from unorm_checkFCDUTF8()\n");
1692e5b6d6dSopenharmony_ci        }
1702e5b6d6dSopenharmony_ci    }
1712e5b6d6dSopenharmony_ci};
1722e5b6d6dSopenharmony_ci
1732e5b6d6dSopenharmony_ci#endif
1742e5b6d6dSopenharmony_ci
1752e5b6d6dSopenharmony_ciclass ToNFC : public Command {
1762e5b6d6dSopenharmony_ciprotected:
1772e5b6d6dSopenharmony_ci    ToNFC(const UTrie2PerfTest &testcase) : Command(testcase) {
1782e5b6d6dSopenharmony_ci        UErrorCode errorCode=U_ZERO_ERROR;
1792e5b6d6dSopenharmony_ci        destCapacity=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(),
1802e5b6d6dSopenharmony_ci                                     UNORM_NFC, 0,
1812e5b6d6dSopenharmony_ci                                     NULL, 0,
1822e5b6d6dSopenharmony_ci                                     &errorCode);
1832e5b6d6dSopenharmony_ci        dest=new UChar[destCapacity];
1842e5b6d6dSopenharmony_ci    }
1852e5b6d6dSopenharmony_ci    ~ToNFC() {
1862e5b6d6dSopenharmony_ci        delete [] dest;
1872e5b6d6dSopenharmony_ci    }
1882e5b6d6dSopenharmony_cipublic:
1892e5b6d6dSopenharmony_ci    static UPerfFunction* get(const UTrie2PerfTest &testcase) {
1902e5b6d6dSopenharmony_ci        return new ToNFC(testcase);
1912e5b6d6dSopenharmony_ci    }
1922e5b6d6dSopenharmony_ci    virtual void call(UErrorCode* pErrorCode) {
1932e5b6d6dSopenharmony_ci        UErrorCode errorCode=U_ZERO_ERROR;
1942e5b6d6dSopenharmony_ci        int32_t destLength=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(),
1952e5b6d6dSopenharmony_ci                                           UNORM_NFC, 0,
1962e5b6d6dSopenharmony_ci                                           dest, destCapacity,
1972e5b6d6dSopenharmony_ci                                           &errorCode);
1982e5b6d6dSopenharmony_ci        if(U_FAILURE(errorCode) || destLength!=destCapacity) {
1992e5b6d6dSopenharmony_ci            fprintf(stderr, "error: unorm_normalize(UNORM_NFC) failed: %s\n",
2002e5b6d6dSopenharmony_ci                    u_errorName(errorCode));
2012e5b6d6dSopenharmony_ci        }
2022e5b6d6dSopenharmony_ci    }
2032e5b6d6dSopenharmony_ci
2042e5b6d6dSopenharmony_ciprivate:
2052e5b6d6dSopenharmony_ci    UChar *dest;
2062e5b6d6dSopenharmony_ci    int32_t destCapacity;
2072e5b6d6dSopenharmony_ci};
2082e5b6d6dSopenharmony_ci
2092e5b6d6dSopenharmony_ciclass GetBiDiClass : public Command {
2102e5b6d6dSopenharmony_ciprotected:
2112e5b6d6dSopenharmony_ci    GetBiDiClass(const UTrie2PerfTest &testcase) : Command(testcase) {}
2122e5b6d6dSopenharmony_cipublic:
2132e5b6d6dSopenharmony_ci    static UPerfFunction* get(const UTrie2PerfTest &testcase) {
2142e5b6d6dSopenharmony_ci        return new GetBiDiClass(testcase);
2152e5b6d6dSopenharmony_ci    }
2162e5b6d6dSopenharmony_ci    virtual void call(UErrorCode* pErrorCode) {
2172e5b6d6dSopenharmony_ci        const UChar *buffer=testcase.getBuffer();
2182e5b6d6dSopenharmony_ci        int32_t length=testcase.getBufferLen();
2192e5b6d6dSopenharmony_ci        UChar32 c;
2202e5b6d6dSopenharmony_ci        int32_t i;
2212e5b6d6dSopenharmony_ci        uint32_t bitSet=0;
2222e5b6d6dSopenharmony_ci        for(i=0; i<length;) {
2232e5b6d6dSopenharmony_ci            U16_NEXT(buffer, i, length, c);
2242e5b6d6dSopenharmony_ci            bitSet|=(uint32_t)1<<u_charDirection(c);
2252e5b6d6dSopenharmony_ci        }
2262e5b6d6dSopenharmony_ci        if(length>0 && bitSet==0) {
2272e5b6d6dSopenharmony_ci            fprintf(stderr, "error: GetBiDiClass() did not collect bits\n");
2282e5b6d6dSopenharmony_ci        }
2292e5b6d6dSopenharmony_ci    }
2302e5b6d6dSopenharmony_ci};
2312e5b6d6dSopenharmony_ci
2322e5b6d6dSopenharmony_ciUPerfFunction* UTrie2PerfTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* par) {
2332e5b6d6dSopenharmony_ci    switch (index) {
2342e5b6d6dSopenharmony_ci        case 0: name = "CheckFCD";              if (exec) return CheckFCD::get(*this); break;
2352e5b6d6dSopenharmony_ci        case 1: name = "ToNFC";                 if (exec) return ToNFC::get(*this); break;
2362e5b6d6dSopenharmony_ci        case 2: name = "GetBiDiClass";          if (exec) return GetBiDiClass::get(*this); break;
2372e5b6d6dSopenharmony_ci#if 0  // See comment at unorm_initUTrie2() forward declaration.
2382e5b6d6dSopenharmony_ci        case 3: name = "CheckFCDAlwaysGet";     if (exec) return CheckFCDAlwaysGet::get(*this); break;
2392e5b6d6dSopenharmony_ci        case 4: name = "CheckFCDUTF8";          if (exec) return CheckFCDUTF8::get(*this); break;
2402e5b6d6dSopenharmony_ci#endif
2412e5b6d6dSopenharmony_ci        default: name = ""; break;
2422e5b6d6dSopenharmony_ci    }
2432e5b6d6dSopenharmony_ci    return NULL;
2442e5b6d6dSopenharmony_ci}
2452e5b6d6dSopenharmony_ci
2462e5b6d6dSopenharmony_ciint main(int argc, const char *argv[]) {
2472e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
2482e5b6d6dSopenharmony_ci    UTrie2PerfTest test(argc, argv, status);
2492e5b6d6dSopenharmony_ci
2502e5b6d6dSopenharmony_ci	if (U_FAILURE(status)){
2512e5b6d6dSopenharmony_ci        printf("The error is %s\n", u_errorName(status));
2522e5b6d6dSopenharmony_ci        test.usage();
2532e5b6d6dSopenharmony_ci        return status;
2542e5b6d6dSopenharmony_ci    }
2552e5b6d6dSopenharmony_ci
2562e5b6d6dSopenharmony_ci    if (test.run() == false){
2572e5b6d6dSopenharmony_ci        fprintf(stderr, "FAILED: Tests could not be run please check the "
2582e5b6d6dSopenharmony_ci			            "arguments.\n");
2592e5b6d6dSopenharmony_ci        return -1;
2602e5b6d6dSopenharmony_ci    }
2612e5b6d6dSopenharmony_ci
2622e5b6d6dSopenharmony_ci    return 0;
2632e5b6d6dSopenharmony_ci}
264