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