1 /* 2 ********************************************************************** 3 * Copyright (C) 2002-2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 * file name: utrie2perf.cpp 7 * encoding: US-ASCII 8 * tab size: 8 (not used) 9 * indentation:4 10 * 11 * created on: 2008sep07 12 * created by: Markus W. Scherer 13 * 14 * Performance test program for UTrie2. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include "unicode/uchar.h" 20 #include "unicode/unorm.h" 21 #include "unicode/uperf.h" 22 #include "uoptions.h" 23 24 #if 0 25 // Left over from when icu/branches/markus/utf8 could use both old UTrie 26 // and new UTrie2, switched with #if in unorm.cpp and ubidi_props.c. 27 // Comparative benchmarks were done in that branch on revision r24630 28 // and earlier. 29 U_CAPI void U_EXPORT2 30 unorm_initUTrie2(UErrorCode *pErrorCode); 31 32 U_CAPI void U_EXPORT2 33 ubidi_initUTrie2(UErrorCode *pErrorCode); 34 #endif 35 36 U_NAMESPACE_BEGIN 37 38 class UnicodeSet; 39 40 U_NAMESPACE_END 41 42 // Test object. 43 class UTrie2PerfTest : public UPerfTest { 44 public: 45 UTrie2PerfTest(int32_t argc, const char *argv[], UErrorCode &status) 46 : UPerfTest(argc, argv, NULL, 0, "", status), 47 utf8(NULL), utf8Length(0), countInputCodePoints(0) { 48 if (U_SUCCESS(status)) { 49 #if 0 // See comment at unorm_initUTrie2() forward declaration. 50 unorm_initUTrie2(&status); 51 ubidi_initUTrie2(&status); 52 #endif 53 int32_t inputLength; 54 UPerfTest::getBuffer(inputLength, status); 55 if(U_SUCCESS(status) && inputLength>0) { 56 countInputCodePoints = u_countChar32(buffer, bufferLen); 57 58 // Preflight the UTF-8 length and allocate utf8. 59 u_strToUTF8(NULL, 0, &utf8Length, buffer, bufferLen, &status); 60 if(status==U_BUFFER_OVERFLOW_ERROR) { 61 utf8=(char *)malloc(utf8Length); 62 if(utf8!=NULL) { 63 status=U_ZERO_ERROR; 64 u_strToUTF8(utf8, utf8Length, NULL, buffer, bufferLen, &status); 65 } else { 66 status=U_MEMORY_ALLOCATION_ERROR; 67 } 68 } 69 70 if(verbose) { 71 printf("code points:%ld len16:%ld len8:%ld " 72 "B/cp:%.3g\n", 73 (long)countInputCodePoints, (long)bufferLen, (long)utf8Length, 74 (double)utf8Length/countInputCodePoints); 75 } 76 } 77 } 78 } 79 80 virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL); 81 82 const UChar *getBuffer() const { return buffer; } 83 int32_t getBufferLen() const { return bufferLen; } 84 85 char *utf8; 86 int32_t utf8Length; 87 88 // Number of code points in the input text. 89 int32_t countInputCodePoints; 90 }; 91 92 // Performance test function object. 93 class Command : public UPerfFunction { 94 protected: 95 Command(const UTrie2PerfTest &testcase) : testcase(testcase) {} 96 97 public: 98 virtual ~Command() {} 99 100 // virtual void call(UErrorCode* pErrorCode) { ... } 101 102 virtual long getOperationsPerIteration() { 103 // Number of code points tested. 104 return testcase.countInputCodePoints; 105 } 106 107 // virtual long getEventsPerIteration(); 108 109 const UTrie2PerfTest &testcase; 110 UNormalizationCheckResult qcResult; 111 }; 112 113 class CheckFCD : public Command { 114 protected: 115 CheckFCD(const UTrie2PerfTest &testcase) : Command(testcase) {} 116 public: 117 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 118 return new CheckFCD(testcase); 119 } 120 virtual void call(UErrorCode* pErrorCode) { 121 UErrorCode errorCode=U_ZERO_ERROR; 122 qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(), 123 UNORM_FCD, &errorCode); 124 if(U_FAILURE(errorCode)) { 125 fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n", 126 u_errorName(errorCode)); 127 } 128 } 129 }; 130 131 #if 0 // See comment at unorm_initUTrie2() forward declaration. 132 133 class CheckFCDAlwaysGet : public Command { 134 protected: 135 CheckFCDAlwaysGet(const UTrie2PerfTest &testcase) : Command(testcase) {} 136 public: 137 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 138 return new CheckFCDAlwaysGet(testcase); 139 } 140 virtual void call(UErrorCode* pErrorCode) { 141 UErrorCode errorCode=U_ZERO_ERROR; 142 qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(), 143 UNORM_FCD_ALWAYS_GET, &errorCode); 144 if(U_FAILURE(errorCode)) { 145 fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n", 146 u_errorName(errorCode)); 147 } 148 } 149 }; 150 151 U_CAPI UBool U_EXPORT2 152 unorm_checkFCDUTF8(const uint8_t *src, int32_t srcLength, const UnicodeSet *nx); 153 154 class CheckFCDUTF8 : public Command { 155 protected: 156 CheckFCDUTF8(const UTrie2PerfTest &testcase) : Command(testcase) {} 157 public: 158 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 159 return new CheckFCDUTF8(testcase); 160 } 161 virtual void call(UErrorCode* pErrorCode) { 162 UBool isFCD=unorm_checkFCDUTF8((const uint8_t *)testcase.utf8, testcase.utf8Length, NULL); 163 if(isFCD>1) { 164 fprintf(stderr, "error: bogus result from unorm_checkFCDUTF8()\n"); 165 } 166 } 167 }; 168 169 #endif 170 171 class ToNFC : public Command { 172 protected: 173 ToNFC(const UTrie2PerfTest &testcase) : Command(testcase) { 174 UErrorCode errorCode=U_ZERO_ERROR; 175 destCapacity=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(), 176 UNORM_NFC, 0, 177 NULL, 0, 178 &errorCode); 179 dest=new UChar[destCapacity]; 180 } 181 ~ToNFC() { 182 delete [] dest; 183 } 184 public: 185 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 186 return new ToNFC(testcase); 187 } 188 virtual void call(UErrorCode* pErrorCode) { 189 UErrorCode errorCode=U_ZERO_ERROR; 190 int32_t destLength=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(), 191 UNORM_NFC, 0, 192 dest, destCapacity, 193 &errorCode); 194 if(U_FAILURE(errorCode) || destLength!=destCapacity) { 195 fprintf(stderr, "error: unorm_normalize(UNORM_NFC) failed: %s\n", 196 u_errorName(errorCode)); 197 } 198 } 199 200 private: 201 UChar *dest; 202 int32_t destCapacity; 203 }; 204 205 class GetBiDiClass : public Command { 206 protected: 207 GetBiDiClass(const UTrie2PerfTest &testcase) : Command(testcase) {} 208 public: 209 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 210 return new GetBiDiClass(testcase); 211 } 212 virtual void call(UErrorCode* pErrorCode) { 213 const UChar *buffer=testcase.getBuffer(); 214 int32_t length=testcase.getBufferLen(); 215 UChar32 c; 216 int32_t i; 217 uint32_t bitSet=0; 218 for(i=0; i<length;) { 219 U16_NEXT(buffer, i, length, c); 220 bitSet|=(uint32_t)1<<u_charDirection(c); 221 } 222 if(length>0 && bitSet==0) { 223 fprintf(stderr, "error: GetBiDiClass() did not collect bits\n"); 224 } 225 } 226 }; 227 228 UPerfFunction* UTrie2PerfTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* par) { 229 switch (index) { 230 case 0: name = "CheckFCD"; if (exec) return CheckFCD::get(*this); break; 231 case 1: name = "ToNFC"; if (exec) return ToNFC::get(*this); break; 232 case 2: name = "GetBiDiClass"; if (exec) return GetBiDiClass::get(*this); break; 233 #if 0 // See comment at unorm_initUTrie2() forward declaration. 234 case 3: name = "CheckFCDAlwaysGet"; if (exec) return CheckFCDAlwaysGet::get(*this); break; 235 case 4: name = "CheckFCDUTF8"; if (exec) return CheckFCDUTF8::get(*this); break; 236 #endif 237 default: name = ""; break; 238 } 239 return NULL; 240 } 241 242 int main(int argc, const char *argv[]) { 243 UErrorCode status = U_ZERO_ERROR; 244 UTrie2PerfTest test(argc, argv, status); 245 246 if (U_FAILURE(status)){ 247 printf("The error is %s\n", u_errorName(status)); 248 test.usage(); 249 return status; 250 } 251 252 if (test.run() == FALSE){ 253 fprintf(stderr, "FAILED: Tests could not be run please check the " 254 "arguments.\n"); 255 return -1; 256 } 257 258 return 0; 259 } 260