summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu-xetex/test/perf/utfperf/utfperf.cpp
blob: d83538bdbced7651739273e202b8169955cd0aa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*  
**********************************************************************
*   Copyright (C) 2002-2005, International Business Machines
*   Corporation and others.  All Rights Reserved.
**********************************************************************
*   file name:  utfperf.cpp
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 2005Nov17
*   created by: Raymond Yang
*
*   Ported from utfper.c created by Markus W. Scherer
*   Performance test program for Unicode converters
*/

#include <stdio.h>
#include "unicode/uperf.h"


/* definitions and text buffers */

#define INPUT_CAPACITY (1024*1024)
#define INTERMEDIATE_CAPACITY 4096
#define INTERMEDIATE_SMALL_CAPACITY 20
#define OUTPUT_CAPACITY INPUT_CAPACITY

static UChar input[INPUT_CAPACITY];
static UChar output[OUTPUT_CAPACITY];
static char intermediate[INTERMEDIATE_CAPACITY];

static int32_t inputLength, encodedLength, outputLength, countInputCodePoints;


class Command : public UPerfFunction {
private:
    Command(const char * name, int32_t buf_cap):name(name),buf_cap(buf_cap){
        errorCode=U_ZERO_ERROR;
        cnv=ucnv_open(name, &errorCode);
    }
public:
    static UPerfFunction* get(const char * name, int32_t buf_cap){
        Command * t = new Command(name, buf_cap);
        if (U_SUCCESS(t->errorCode)){
            return t;
        } else {
            //fprintf(stderr, "error opening converter for \"%s\" - %s\n", name, u_errorName(errorCode));
            delete t;
            return NULL;
        }
    }
    virtual ~Command(){
        if(U_SUCCESS(errorCode)) {
            ucnv_close(cnv);
        }
    }
    virtual void call(UErrorCode* pErrorCode){
        const UChar *pIn, *pInLimit;
        UChar *pOut, *pOutLimit;
        char *pInter, *pInterLimit;
        const char *p;
        UBool flush;

        ucnv_reset(cnv);

        pIn=input;
        pInLimit=input+inputLength;

        pOut=output;
        pOutLimit=output+OUTPUT_CAPACITY;

        pInterLimit=intermediate+buf_cap;

        encodedLength=outputLength=0;
        flush=FALSE;

        while(pIn<pInLimit || !flush) {
            /* convert a block of [pIn..pInLimit[ to the encoding in intermediate[] */
            pInter=intermediate;
            flush=(UBool)(pIn==pInLimit);
            ucnv_fromUnicode(cnv, &pInter, pInterLimit, &pIn, pInLimit, NULL, flush, pErrorCode);
            encodedLength+=(int32_t)(pInter-intermediate);

            if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
                /* in case flush was TRUE make sure that we convert once more to really flush */
                flush=FALSE;
                *pErrorCode=U_ZERO_ERROR;
            } else if(U_FAILURE(*pErrorCode)) {
                return;
            }

            /* convert the block [intermediate..pInter[ back to UTF-16 */
            p=intermediate;
            ucnv_toUnicode(cnv, &pOut, pOutLimit,&p, pInter,NULL, flush,pErrorCode);
            if(U_FAILURE(*pErrorCode)) {
                return;
            }
            /* intermediate must have been consumed (p==pInter) because of the converter semantics */
        }

        outputLength=pOut-output;
        if(inputLength!=outputLength) {
            fprintf(stderr, "error: roundtrip failed, inputLength %d!=outputLength %d\n", inputLength, outputLength);
            *pErrorCode=U_INTERNAL_PROGRAM_ERROR;
        }
    }
    virtual long getOperationsPerIteration(){
        return countInputCodePoints;
    }
    const char * name;
    int32_t buf_cap;
    UErrorCode errorCode;
    UConverter *cnv;
};

class  UtfPerformanceTest : public UPerfTest{
public:
    UtfPerformanceTest(int32_t argc, const char *argv[], UErrorCode &status) :UPerfTest(argc,argv,status){
        getBuffer(inputLength, status);
        u_strncpy(input, buffer, inputLength);
        countInputCodePoints = u_countChar32(input, inputLength);
    }

    virtual UPerfFunction* runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ){
        switch (index) {
            case 0: name = "UTF_8";     if (exec) return Command::get("UTF-8", INTERMEDIATE_CAPACITY); break;
            case 1: name = "UTF_8_SB";  if (exec) return Command::get("UTF-8",INTERMEDIATE_SMALL_CAPACITY); break;
            case 2: name = "SCSU";      if (exec) return Command::get("SCSU", INTERMEDIATE_CAPACITY); break;
            case 3: name = "SCSU_SB";   if (exec) return Command::get("SCSU", INTERMEDIATE_SMALL_CAPACITY); break;
            case 4: name = "BOCU_1";    if (exec) return Command::get("BOCU-1", INTERMEDIATE_CAPACITY); break;
            case 5: name = "BOCU_1_SB"; if (exec) return Command::get("BOCU-1",INTERMEDIATE_SMALL_CAPACITY); break;
            default: name = ""; break;
        }
        return NULL;
    }
};


int main(int argc, const char *argv[])
{
    UErrorCode status = U_ZERO_ERROR;
    UtfPerformanceTest test(argc, argv, status);

	if (U_FAILURE(status)){
        printf("The error is %s\n", u_errorName(status));
        return status;
    }
        
    if (test.run() == FALSE){
        fprintf(stderr, "FAILED: Tests could not be run please check the "
			            "arguments.\n");
        return -1;
    }
    return 0;
}