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 defined(U_WINDOWS) 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 56 BreakItFunction(){num = -1;} 57 BreakItFunction(int a, bool b){num = a; wordIteration = b;} 58 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 100 virtual long getOperationsPerIteration() 101 { 102 if(wordIteration) return 125*num; 103 else return 355*num; 104 } 105 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 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) 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 148 DateFmtFunction() 149 { 150 num = -1; 151 } 152 153 DateFmtFunction(int a, const char* loc) 154 { 155 num = a; 156 strcpy(locale, loc); 157 } 158 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 206 virtual long getOperationsPerIteration() 207 { 208 return NUM_DATES * num; 209 } 210 211 // Print the given string to stdout (for debugging purposes) 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 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 242 NumFmtFunction() 243 { 244 num = -1; 245 } 246 247 NumFmtFunction(int a, const char* loc) 248 { 249 num = a; 250 strcpy(locale, loc); 251 } 252 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 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 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) 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 class CollationFunction : public UPerfFunction 360 { 361 362 private: 363 int num; 364 char locale[25]; 365 UnicodeString *collation_strings; 366 367 /** 368 * Unescape the strings 369 */ 370 void init() { 371 uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]); 372 collation_strings = new UnicodeString[listSize]; 373 for(uint32_t k=0;k<listSize;k++) { 374 collation_strings[k] = collation_strings_escaped[k].unescape(); 375 } 376 UnicodeString shorty((UChar32)0x12345); 377 } 378 public: 379 380 CollationFunction() 381 { 382 num = -1; 383 384 init(); 385 } 386 387 ~CollationFunction() { 388 delete [] collation_strings; 389 } 390 391 CollationFunction(int a, const char* loc) 392 { 393 num = a; 394 strcpy(locale, loc); 395 init(); 396 } 397 398 virtual void call(UErrorCode* status2) 399 { 400 uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]); 401 UErrorCode status = U_ZERO_ERROR; 402 Collator *coll = Collator::createInstance(Locale(locale), status); 403 404 for(int k = 0; k < num; k++) 405 { 406 uint32_t i, j; 407 for(i=listSize-1; i>=1; i--) { 408 for(j=0; j<i; j++) { 409 if(coll->compare(collation_strings[j], collation_strings[j+1]) == UCOL_LESS) { 410 //cout << "Success!" << endl; 411 } 412 } 413 } 414 } 415 delete coll; 416 } 417 418 virtual long getOperationsPerIteration() 419 { 420 return num; 421 } 422 }; 423 424 class DateFormatPerfTest : public UPerfTest 425 { 426 private: 427 428 public: 429 430 DateFormatPerfTest(int32_t argc, const char* argv[], UErrorCode& status); 431 ~DateFormatPerfTest(); 432 virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,const char* &name, char* par); 433 434 UPerfFunction* DateFmt250(); 435 UPerfFunction* DateFmt10000(); 436 UPerfFunction* DateFmt100000(); 437 UPerfFunction* BreakItWord250(); 438 UPerfFunction* BreakItWord10000(); 439 UPerfFunction* BreakItChar250(); 440 UPerfFunction* BreakItChar10000(); 441 UPerfFunction* NumFmt10000(); 442 UPerfFunction* NumFmt100000(); 443 UPerfFunction* Collation10000(); 444 UPerfFunction* Collation100000(); 445 }; 446 447 #endif // DateFmtPerf 448