/* *********************************************************************** * © 2016 and later: Unicode, Inc. and others. * License & terms of use: http://www.unicode.org/copyright.html *********************************************************************** *********************************************************************** * Copyright (c) 2002-2016,International Business Machines * Corporation and others. All Rights Reserved. *********************************************************************** *********************************************************************** */ #ifndef _DATEFMTPERF_H #define _DATEFMTPERF_H #include "cmemory.h" #include "unicode/stringpiece.h" #include "unicode/unistr.h" #include "unicode/uperf.h" #include "unicode/dtitvfmt.h" #include "unicode/utypes.h" #include "unicode/datefmt.h" #include "unicode/calendar.h" #include "unicode/uclean.h" #include "unicode/brkiter.h" #include "unicode/numfmt.h" #include "unicode/coll.h" #include "util.h" #include "datedata.h" #include "breakdata.h" #include "collationdata.h" #include #include #include #include using namespace std; // Stubs for Windows API functions when building on UNIXes. // #if U_PLATFORM_USES_ONLY_WIN32_API // do nothing #else #define _UNICODE typedef int DWORD; inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest); #endif class BreakItFunction : public UPerfFunction { private: int num; bool wordIteration; public: BreakItFunction(){num = -1;} BreakItFunction(int a, bool b){num = a; wordIteration = b;} virtual void call(UErrorCode * status) { BreakIterator* boundary; if(wordIteration) { for(int i = 0; i < num; i++) { boundary = BreakIterator::createWordInstance("en", *status); boundary->setText(str); int32_t start = boundary->first(); for (int32_t end = boundary->next(); end != BreakIterator::DONE; start = end, end = boundary->next()) { printTextRange( *boundary, start, end ); } } } else // character iteration { for(int i = 0; i < num; i++) { boundary = BreakIterator::createCharacterInstance(Locale::getUS(), *status); boundary->setText(str); int32_t start = boundary->first(); for (int32_t end = boundary->next(); end != BreakIterator::DONE; start = end, end = boundary->next()) { printTextRange( *boundary, start, end ); } } } } virtual long getOperationsPerIteration() { if(wordIteration) return 125*num; else return 355*num; } void printUnicodeString(const UnicodeString &s) { char charBuf[1000]; s.extract(0, s.length(), charBuf, sizeof(charBuf)-1, 0); charBuf[sizeof(charBuf)-1] = 0; printf("%s", charBuf); } void printTextRange( BreakIterator& iterator, int32_t start, int32_t end ) { CharacterIterator *strIter = iterator.getText().clone(); UnicodeString s; strIter->getText(s); //printUnicodeString(UnicodeString(s, start, end-start)); //puts(""); delete strIter; } // Print the given string to stdout (for debugging purposes) void uprintf(const UnicodeString &str) { char *buf = 0; int32_t len = str.length(); int32_t bufLen = len + 16; int32_t actualLen; buf = new char[bufLen + 1]; actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion buf[actualLen] = 0; printf("%s", buf); delete[] buf; } }; class DateFmtFunction : public UPerfFunction { private: int num; char locale[25]; public: DateFmtFunction() { num = -1; } DateFmtFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* status) { UErrorCode status2 = U_ZERO_ERROR; Calendar *cal; TimeZone *zone; UnicodeString str; UDate date; cal = Calendar::createInstance(status2); check(status2, "Calendar::createInstance"); zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone cal->adoptTimeZone(zone); Locale loc(locale); DateFormat *fmt; fmt = DateFormat::createDateTimeInstance( DateFormat::kShort, DateFormat::kFull, loc); // (dates are imported from datedata.h) for(int j = 0; j < num; j++) for(int i = 0; i < NUM_DATES; i++) { cal->clear(); cal->set(years[i], months[i], days[i]); date = cal->getTime(status2); check(status2, "Calendar::getTime"); fmt->setCalendar(*cal); // Format the date str.remove(); fmt->format(date, str, status2); // Display the formatted date string //uprintf(str); //printf("\n"); } delete fmt; delete cal; //u_cleanup(); } virtual long getOperationsPerIteration() { return NUM_DATES * num; } // Print the given string to stdout (for debugging purposes) void uprintf(const UnicodeString &str) { char *buf = 0; int32_t len = str.length(); int32_t bufLen = len + 16; int32_t actualLen; buf = new char[bufLen + 1]; actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion buf[actualLen] = 0; printf("%s", buf); delete[] buf; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class DateFmtCreateFunction : public UPerfFunction { private: int num; char locale[25]; public: DateFmtCreateFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { Locale loc(locale); DateFormat *fmt; // (dates are imported from datedata.h) for(int j = 0; j < num; j++) { fmt = DateFormat::createDateTimeInstance( DateFormat::kShort, DateFormat::kFull, loc); delete fmt; } } virtual long getOperationsPerIteration() { return num; } }; class DateFmtCopyFunction : public UPerfFunction { private: int num; char locale[25]; public: DateFmtCopyFunction() { num = -1; } DateFmtCopyFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { Locale loc(locale); UErrorCode status2 = U_ZERO_ERROR; DateFormat *fmt = DateFormat::createDateTimeInstance( DateFormat::kShort, DateFormat::kFull, loc); for(int j = 0; j < num; j++) { Format *cp = fmt->clone(); delete cp; } delete fmt; } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class DIFCreateFunction : public UPerfFunction { private: int num; char locale[25]; public: DIFCreateFunction() { num = -1; } DIFCreateFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { UErrorCode status2 = U_ZERO_ERROR; Calendar *cal; TimeZone *zone; cal = Calendar::createInstance(status2); check(status2, "Calendar::createInstance"); zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone cal->adoptTimeZone(zone); Locale loc(locale); UnicodeString skeleton("yMMMMdHms"); for(int j = 0; j < num; j++) { DateIntervalFormat* fmt(DateIntervalFormat::createInstance(skeleton, loc, status2)); delete fmt; } delete cal; } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class TimeZoneCreateFunction : public UPerfFunction { private: int num; char locale[25]; public: TimeZoneCreateFunction() { num = -1; } TimeZoneCreateFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { Locale loc(locale); UnicodeString tzname("UTC"); for(int j = 0; j < num; j++) { TimeZone* tz(TimeZone::createTimeZone(tzname)); delete tz; } } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class DTPatternGeneratorCreateFunction : public UPerfFunction { private: int num; char locale[25]; public: DTPatternGeneratorCreateFunction() { num = -1; } DTPatternGeneratorCreateFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { UErrorCode status2 = U_ZERO_ERROR; Locale loc(locale); for(int j = 0; j < num; j++) { DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2)); delete gen; } } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class DTPatternGeneratorCopyFunction : public UPerfFunction { private: int num; char locale[25]; public: DTPatternGeneratorCopyFunction() { num = -1; } DTPatternGeneratorCopyFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { UErrorCode status2 = U_ZERO_ERROR; Locale loc(locale); DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2)); for(int j = 0; j < num; j++) { DateTimePatternGenerator *cl = gen->clone(); delete cl; } delete gen; } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class DTPatternGeneratorBestValueFunction : public UPerfFunction { private: int num; char locale[25]; public: DTPatternGeneratorBestValueFunction() { num = -1; } DTPatternGeneratorBestValueFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* /* status */) { UErrorCode status2 = U_ZERO_ERROR; Locale loc(locale); DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2)); UnicodeString skeleton("yMMMMdHms"); for(int j = 0; j < num; j++) { gen->getBestPattern(skeleton, status2); } check(status2, "getBestPattern"); delete gen; } virtual long getOperationsPerIteration() { return num; } // Verify that a UErrorCode is successful; exit(1) if not void check(UErrorCode& status, const char* msg) { if (U_FAILURE(status)) { printf("ERROR: %s (%s)\n", u_errorName(status), msg); exit(1); } } }; class NumFmtFunction : public UPerfFunction { private: int num; char locale[25]; public: NumFmtFunction() { num = -1; } NumFmtFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* status2) { Locale loc(locale); UErrorCode status = U_ZERO_ERROR; // Create a number formatter for the locale NumberFormat *fmt = NumberFormat::createInstance(loc, status); // Parse a string. The string uses the digits '0' through '9' // and the decimal separator '.', standard in the US locale for(int i = 0; i < num; i++) { UnicodeString str("9876543210.123"); Formattable result; fmt->parse(str, result, status); //uprintf(formattableToString(result)); //printf("\n"); // Take the number parsed above, and use the formatter to // format it. str.remove(); // format() will APPEND to this string fmt->format(result, str, status); //uprintf(str); //printf("\n"); } delete fmt; // Release the storage used by the formatter } enum { U_SPACE=0x20, U_DQUOTE=0x22, U_COMMA=0x2c, U_LEFT_SQUARE_BRACKET=0x5b, U_BACKSLASH=0x5c, U_RIGHT_SQUARE_BRACKET=0x5d, U_SMALL_U=0x75 }; // Create a display string for a formattable UnicodeString formattableToString(const Formattable& f) { switch (f.getType()) { case Formattable::kDate: // TODO: Finish implementing this return UNICODE_STRING_SIMPLE("Formattable_DATE_TBD"); case Formattable::kDouble: { char buf[256]; sprintf(buf, "%gD", f.getDouble()); return UnicodeString(buf, ""); } case Formattable::kLong: case Formattable::kInt64: { char buf[256]; sprintf(buf, "%ldL", f.getLong()); return UnicodeString(buf, ""); } case Formattable::kString: return UnicodeString((UChar)U_DQUOTE).append(f.getString()).append((UChar)U_DQUOTE); case Formattable::kArray: { int32_t i, count; const Formattable* array = f.getArray(count); UnicodeString result((UChar)U_LEFT_SQUARE_BRACKET); for (i=0; i 0) { (result += (UChar)U_COMMA) += (UChar)U_SPACE; } result += formattableToString(array[i]); } result += (UChar)U_RIGHT_SQUARE_BRACKET; return result; } default: return UNICODE_STRING_SIMPLE("INVALID_Formattable"); } } virtual long getOperationsPerIteration() { return num; } // Print the given string to stdout using the UTF-8 converter (for debugging purposes only) void uprintf(const UnicodeString &str) { char stackBuffer[100]; char *buf = 0; int32_t bufLen = str.extract(0, 0x7fffffff, stackBuffer, sizeof(stackBuffer), "UTF-8"); if(bufLen < sizeof(stackBuffer)) { buf = stackBuffer; } else { buf = new char[bufLen + 1]; bufLen = str.extract(0, 0x7fffffff, buf, bufLen + 1, "UTF-8"); } printf("%s", buf); if(buf != stackBuffer) { delete[] buf; } } }; #define NUM_STRING "9876543210.123" #define NUM_NUM 9876543210.123 class StdioNumFmtFunction : public UPerfFunction { private: int num; char locale[25]; public: StdioNumFmtFunction() { num = -1; } StdioNumFmtFunction(int a, const char* loc) { num = a; strcpy(locale, loc); } virtual void call(UErrorCode* status2) { Locale loc(locale); UErrorCode status = U_ZERO_ERROR; // Parse a string. The string uses the digits '0' through '9' // and the decimal separator '.', standard in the US locale double result; char outbuf[500]; const char *str = NUM_STRING; for(int i = 0; i < num; i++) { if(sscanf(str, "%lg", &result)!=1) { cout << "Failed Stdio: failed to sscanf" << endl; *status2 = U_PARSE_ERROR; return; } sprintf(outbuf, "%lg", result); } if(result!=NUM_NUM) { cout << "Failed Stdio: sscanf got wrong result, expected " << NUM_NUM << " got " << result << endl; *status2 = U_PARSE_ERROR; } if(strcmp(str,NUM_STRING)) { cout << "Failed Stdio: sprintf got wrong result, expected " << NUM_STRING << " got " << str << endl; *status2 = U_PARSE_ERROR; } } virtual long getOperationsPerIteration() { return num; } }; class CollationFunction : public UPerfFunction { private: int num; char locale[25]; UnicodeString *collation_strings; /** * Unescape the strings */ void init() { uint32_t listSize = UPRV_LENGTHOF(collation_strings_escaped); collation_strings = new UnicodeString[listSize]; for(uint32_t k=0;k=1; i--) { for(j=0; jcompare(collation_strings[j], collation_strings[j+1]) == UCOL_LESS) { //cout << "Success!" << endl; } } } } delete coll; } virtual long getOperationsPerIteration() { return num; } }; class DateFormatPerfTest : public UPerfTest { private: public: DateFormatPerfTest(int32_t argc, const char* argv[], UErrorCode& status); ~DateFormatPerfTest(); virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,const char* &name, char* par); UPerfFunction* DateFmt250(); UPerfFunction* DateFmt10000(); UPerfFunction* DateFmt100000(); UPerfFunction* DateFmtCreate250(); UPerfFunction* DateFmtCreate10000(); UPerfFunction* DateFmtCopy250(); UPerfFunction* DateFmtCopy10000(); UPerfFunction* BreakItWord250(); UPerfFunction* BreakItWord10000(); UPerfFunction* BreakItChar250(); UPerfFunction* BreakItChar10000(); UPerfFunction* NumFmt10000(); UPerfFunction* NumFmt100000(); UPerfFunction* Collation10000(); UPerfFunction* Collation100000(); UPerfFunction* DIFCreate250(); UPerfFunction* DIFCreate10000(); UPerfFunction* TimeZoneCreate250(); UPerfFunction* TimeZoneCreate10000(); UPerfFunction* DTPatternGeneratorCreate250(); UPerfFunction* DTPatternGeneratorCreate10000(); UPerfFunction* DTPatternGeneratorCopy250(); UPerfFunction* DTPatternGeneratorCopy10000(); UPerfFunction* DTPatternGeneratorBestValue250(); UPerfFunction* DTPatternGeneratorBestValue10000(); }; #endif // DateFmtPerf