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