1 /* 2 ********************************************************************** 3 * Copyright (c) 2002-2011,International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 ********************************************************************** 7 */ 8 9 #ifndef _DATEFMTPERF_H 10 #define _DATEFMTPERF_H 11 12 13 #include "unicode/stringpiece.h" 14 #include "unicode/unistr.h" 15 #include "unicode/uperf.h" 16 17 #include "unicode/utypes.h" 18 #include "unicode/datefmt.h" 19 #include "unicode/calendar.h" 20 #include "unicode/uclean.h" 21 #include "unicode/brkiter.h" 22 #include "unicode/numfmt.h" 23 #include "unicode/coll.h" 24 #include "util.h" 25 26 #include "datedata.h" 27 #include "breakdata.h" 28 #include "collationdata.h" 29 30 #include <stdlib.h> 31 #include <string.h> 32 33 #include <fstream> 34 35 #include <iostream> 36 using namespace std; 37 38 // Stubs for Windows API functions when building on UNIXes. 39 // 40 #if U_PLATFORM_USES_ONLY_WIN32_API 41 // do nothing 42 #else 43 #define _UNICODE 44 typedef int DWORD; 45 inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest); 46 #endif 47 48 class BreakItFunction : public UPerfFunction 49 { 50 private: 51 int num; 52 bool wordIteration; 53 54 public: 55 BreakItFunction()56 BreakItFunction(){num = -1;} BreakItFunction(int a,bool b)57 BreakItFunction(int a, bool b){num = a; wordIteration = b;} 58 call(UErrorCode * status)59 virtual void call(UErrorCode *status) 60 { 61 BreakIterator* boundary; 62 63 if(wordIteration) 64 { 65 for(int i = 0; i < num; i++) 66 { 67 boundary = BreakIterator::createWordInstance("en", *status); 68 boundary->setText(str); 69 70 int32_t start = boundary->first(); 71 for (int32_t end = boundary->next(); 72 end != BreakIterator::DONE; 73 start = end, end = boundary->next()) 74 { 75 printTextRange( *boundary, start, end ); 76 } 77 } 78 } 79 80 else // character iteration 81 { 82 for(int i = 0; i < num; i++) 83 { 84 boundary = BreakIterator::createCharacterInstance(Locale::getUS(), *status); 85 boundary->setText(str); 86 87 int32_t start = boundary->first(); 88 for (int32_t end = boundary->next(); 89 end != BreakIterator::DONE; 90 start = end, end = boundary->next()) 91 { 92 printTextRange( *boundary, start, end ); 93 } 94 } 95 } 96 97 98 } 99 getOperationsPerIteration()100 virtual long getOperationsPerIteration() 101 { 102 if(wordIteration) return 125*num; 103 else return 355*num; 104 } 105 printUnicodeString(const UnicodeString & s)106 void printUnicodeString(const UnicodeString &s) { 107 char charBuf[1000]; 108 s.extract(0, s.length(), charBuf, sizeof(charBuf)-1, 0); 109 charBuf[sizeof(charBuf)-1] = 0; 110 printf("%s", charBuf); 111 } 112 113 printTextRange(BreakIterator & iterator,int32_t start,int32_t end)114 void printTextRange( BreakIterator& iterator, 115 int32_t start, int32_t end ) 116 { 117 CharacterIterator *strIter = iterator.getText().clone(); 118 UnicodeString s; 119 strIter->getText(s); 120 //printUnicodeString(UnicodeString(s, start, end-start)); 121 //puts(""); 122 delete strIter; 123 } 124 125 // Print the given string to stdout (for debugging purposes) uprintf(const UnicodeString & str)126 void uprintf(const UnicodeString &str) { 127 char *buf = 0; 128 int32_t len = str.length(); 129 int32_t bufLen = len + 16; 130 int32_t actualLen; 131 buf = new char[bufLen + 1]; 132 actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion 133 buf[actualLen] = 0; 134 printf("%s", buf); 135 delete[] buf; 136 } 137 138 }; 139 140 class DateFmtFunction : public UPerfFunction 141 { 142 143 private: 144 int num; 145 char locale[25]; 146 public: 147 DateFmtFunction()148 DateFmtFunction() 149 { 150 num = -1; 151 } 152 DateFmtFunction(int a,const char * loc)153 DateFmtFunction(int a, const char* loc) 154 { 155 num = a; 156 strcpy(locale, loc); 157 } 158 call(UErrorCode * status)159 virtual void call(UErrorCode* status) 160 { 161 162 UErrorCode status2 = U_ZERO_ERROR; 163 Calendar *cal; 164 TimeZone *zone; 165 UnicodeString str; 166 UDate date; 167 168 cal = Calendar::createInstance(status2); 169 check(status2, "Calendar::createInstance"); 170 zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone 171 cal->adoptTimeZone(zone); 172 173 Locale loc(locale); 174 DateFormat *fmt; 175 fmt = DateFormat::createDateTimeInstance( 176 DateFormat::kShort, DateFormat::kFull, loc); 177 178 179 // (dates are imported from datedata.h) 180 for(int j = 0; j < num; j++) 181 for(int i = 0; i < NUM_DATES; i++) 182 { 183 cal->clear(); 184 cal->set(years[i], months[i], days[i]); 185 date = cal->getTime(status2); 186 check(status2, "Calendar::getTime"); 187 188 fmt->setCalendar(*cal); 189 190 // Format the date 191 str.remove(); 192 fmt->format(date, str, status2); 193 194 195 // Display the formatted date string 196 //uprintf(str); 197 //printf("\n"); 198 199 } 200 201 delete fmt; 202 delete cal; 203 //u_cleanup(); 204 } 205 getOperationsPerIteration()206 virtual long getOperationsPerIteration() 207 { 208 return NUM_DATES * num; 209 } 210 211 // Print the given string to stdout (for debugging purposes) uprintf(const UnicodeString & str)212 void uprintf(const UnicodeString &str) { 213 char *buf = 0; 214 int32_t len = str.length(); 215 int32_t bufLen = len + 16; 216 int32_t actualLen; 217 buf = new char[bufLen + 1]; 218 actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion 219 buf[actualLen] = 0; 220 printf("%s", buf); 221 delete[] buf; 222 } 223 224 // Verify that a UErrorCode is successful; exit(1) if not check(UErrorCode & status,const char * msg)225 void check(UErrorCode& status, const char* msg) { 226 if (U_FAILURE(status)) { 227 printf("ERROR: %s (%s)\n", u_errorName(status), msg); 228 exit(1); 229 } 230 } 231 232 }; 233 234 class NumFmtFunction : public UPerfFunction 235 { 236 237 private: 238 int num; 239 char locale[25]; 240 public: 241 NumFmtFunction()242 NumFmtFunction() 243 { 244 num = -1; 245 } 246 NumFmtFunction(int a,const char * loc)247 NumFmtFunction(int a, const char* loc) 248 { 249 num = a; 250 strcpy(locale, loc); 251 } 252 call(UErrorCode * status2)253 virtual void call(UErrorCode* status2) 254 { 255 Locale loc(locale); 256 UErrorCode status = U_ZERO_ERROR; 257 258 // Create a number formatter for the locale 259 NumberFormat *fmt = NumberFormat::createInstance(loc, status); 260 261 // Parse a string. The string uses the digits '0' through '9' 262 // and the decimal separator '.', standard in the US locale 263 264 for(int i = 0; i < num; i++) 265 { 266 UnicodeString str("9876543210.123"); 267 Formattable result; 268 fmt->parse(str, result, status); 269 270 //uprintf(formattableToString(result)); 271 //printf("\n"); 272 273 // Take the number parsed above, and use the formatter to 274 // format it. 275 str.remove(); // format() will APPEND to this string 276 fmt->format(result, str, status); 277 278 //uprintf(str); 279 //printf("\n"); 280 } 281 282 delete fmt; // Release the storage used by the formatter 283 } 284 285 enum { 286 U_SPACE=0x20, 287 U_DQUOTE=0x22, 288 U_COMMA=0x2c, 289 U_LEFT_SQUARE_BRACKET=0x5b, 290 U_BACKSLASH=0x5c, 291 U_RIGHT_SQUARE_BRACKET=0x5d, 292 U_SMALL_U=0x75 293 }; 294 295 // Create a display string for a formattable formattableToString(const Formattable & f)296 UnicodeString formattableToString(const Formattable& f) { 297 switch (f.getType()) { 298 case Formattable::kDate: 299 // TODO: Finish implementing this 300 return UNICODE_STRING_SIMPLE("Formattable_DATE_TBD"); 301 case Formattable::kDouble: 302 { 303 char buf[256]; 304 sprintf(buf, "%gD", f.getDouble()); 305 return UnicodeString(buf, ""); 306 } 307 case Formattable::kLong: 308 case Formattable::kInt64: 309 { 310 char buf[256]; 311 sprintf(buf, "%ldL", f.getLong()); 312 return UnicodeString(buf, ""); 313 } 314 case Formattable::kString: 315 return UnicodeString((UChar)U_DQUOTE).append(f.getString()).append((UChar)U_DQUOTE); 316 case Formattable::kArray: 317 { 318 int32_t i, count; 319 const Formattable* array = f.getArray(count); 320 UnicodeString result((UChar)U_LEFT_SQUARE_BRACKET); 321 for (i=0; i<count; ++i) { 322 if (i > 0) { 323 (result += (UChar)U_COMMA) += (UChar)U_SPACE; 324 } 325 result += formattableToString(array[i]); 326 } 327 result += (UChar)U_RIGHT_SQUARE_BRACKET; 328 return result; 329 } 330 default: 331 return UNICODE_STRING_SIMPLE("INVALID_Formattable"); 332 } 333 } 334 getOperationsPerIteration()335 virtual long getOperationsPerIteration() 336 { 337 return num; 338 } 339 340 // Print the given string to stdout using the UTF-8 converter (for debugging purposes only) uprintf(const UnicodeString & str)341 void uprintf(const UnicodeString &str) { 342 char stackBuffer[100]; 343 char *buf = 0; 344 345 int32_t bufLen = str.extract(0, 0x7fffffff, stackBuffer, sizeof(stackBuffer), "UTF-8"); 346 if(bufLen < sizeof(stackBuffer)) { 347 buf = stackBuffer; 348 } else { 349 buf = new char[bufLen + 1]; 350 bufLen = str.extract(0, 0x7fffffff, buf, bufLen + 1, "UTF-8"); 351 } 352 printf("%s", buf); 353 if(buf != stackBuffer) { 354 delete[] buf; 355 } 356 } 357 }; 358 359 360 361 #define NUM_STRING "9876543210.123" 362 #define NUM_NUM 9876543210.123 363 class StdioNumFmtFunction : public UPerfFunction 364 { 365 366 private: 367 int num; 368 char locale[25]; 369 public: 370 StdioNumFmtFunction()371 StdioNumFmtFunction() 372 { 373 num = -1; 374 } 375 StdioNumFmtFunction(int a,const char * loc)376 StdioNumFmtFunction(int a, const char* loc) 377 { 378 num = a; 379 strcpy(locale, loc); 380 } 381 call(UErrorCode * status2)382 virtual void call(UErrorCode* status2) 383 { 384 Locale loc(locale); 385 UErrorCode status = U_ZERO_ERROR; 386 387 // Parse a string. The string uses the digits '0' through '9' 388 // and the decimal separator '.', standard in the US locale 389 390 double result; 391 char outbuf[500]; 392 const char *str = NUM_STRING; 393 394 for(int i = 0; i < num; i++) 395 { 396 if(sscanf(str, "%lg", &result)!=1) { 397 cout << "Failed Stdio: failed to sscanf" << endl; 398 *status2 = U_PARSE_ERROR; 399 return; 400 } 401 402 sprintf(outbuf, "%lg", result); 403 } 404 405 if(result!=NUM_NUM) { 406 cout << "Failed Stdio: sscanf got wrong result, expected " << NUM_NUM << " got " << result << endl; 407 *status2 = U_PARSE_ERROR; 408 } 409 if(strcmp(str,NUM_STRING)) { 410 cout << "Failed Stdio: sprintf got wrong result, expected " << NUM_STRING << " got " << str << endl; 411 *status2 = U_PARSE_ERROR; 412 } 413 } 414 getOperationsPerIteration()415 virtual long getOperationsPerIteration() 416 { 417 return num; 418 } 419 420 }; 421 422 class CollationFunction : public UPerfFunction 423 { 424 425 private: 426 int num; 427 char locale[25]; 428 UnicodeString *collation_strings; 429 430 /** 431 * Unescape the strings 432 */ init()433 void init() { 434 uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]); 435 collation_strings = new UnicodeString[listSize]; 436 for(uint32_t k=0;k<listSize;k++) { 437 collation_strings[k] = collation_strings_escaped[k].unescape(); 438 } 439 UnicodeString shorty((UChar32)0x12345); 440 } 441 public: 442 CollationFunction()443 CollationFunction() 444 { 445 num = -1; 446 447 init(); 448 } 449 ~CollationFunction()450 ~CollationFunction() { 451 delete [] collation_strings; 452 } 453 CollationFunction(int a,const char * loc)454 CollationFunction(int a, const char* loc) 455 { 456 num = a; 457 strcpy(locale, loc); 458 init(); 459 } 460 call(UErrorCode * status2)461 virtual void call(UErrorCode* status2) 462 { 463 uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]); 464 UErrorCode status = U_ZERO_ERROR; 465 Collator *coll = Collator::createInstance(Locale(locale), status); 466 467 for(int k = 0; k < num; k++) 468 { 469 uint32_t i, j; 470 for(i=listSize-1; i>=1; i--) { 471 for(j=0; j<i; j++) { 472 if(coll->compare(collation_strings[j], collation_strings[j+1]) == UCOL_LESS) { 473 //cout << "Success!" << endl; 474 } 475 } 476 } 477 } 478 delete coll; 479 } 480 getOperationsPerIteration()481 virtual long getOperationsPerIteration() 482 { 483 return num; 484 } 485 }; 486 487 class DateFormatPerfTest : public UPerfTest 488 { 489 private: 490 491 public: 492 493 DateFormatPerfTest(int32_t argc, const char* argv[], UErrorCode& status); 494 ~DateFormatPerfTest(); 495 virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,const char* &name, char* par); 496 497 UPerfFunction* DateFmt250(); 498 UPerfFunction* DateFmt10000(); 499 UPerfFunction* DateFmt100000(); 500 UPerfFunction* BreakItWord250(); 501 UPerfFunction* BreakItWord10000(); 502 UPerfFunction* BreakItChar250(); 503 UPerfFunction* BreakItChar10000(); 504 UPerfFunction* NumFmt10000(); 505 UPerfFunction* NumFmt100000(); 506 UPerfFunction* Collation10000(); 507 UPerfFunction* Collation100000(); 508 }; 509 510 #endif // DateFmtPerf 511