Home | History | Annotate | Download | only in DateFmtPerf
      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 
     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 
    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 
    371   StdioNumFmtFunction()
    372     {
    373       num = -1;
    374     }
    375 
    376   StdioNumFmtFunction(int a, const char* loc)
    377     {
    378       num = a;
    379       strcpy(locale, loc);
    380     }
    381 
    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 
    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 	 */
    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 
    443 	CollationFunction()
    444 	{
    445 		num = -1;
    446 
    447 		init();
    448 	}
    449 
    450 	~CollationFunction() {
    451 		delete [] collation_strings;
    452 	}
    453 
    454 	CollationFunction(int a, const char* loc)
    455 	{
    456 		num = a;
    457         strcpy(locale, loc);
    458 		init();
    459 	}
    460 
    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 
    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