You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

850 lines
19 KiB

/*
***********************************************************************
* © 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 <stdlib.h>
#include <string.h>
#include <fstream>
#include <iostream>
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<count; ++i) {
if (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<listSize;k++) {
collation_strings[k] = collation_strings_escaped[k].unescape();
}
UnicodeString shorty((UChar32)0x12345);
}
public:
CollationFunction()
{
num = -1;
init();
}
~CollationFunction() {
delete [] collation_strings;
}
CollationFunction(int a, const char* loc)
{
num = a;
strcpy(locale, loc);
init();
}
virtual void call(UErrorCode* status2)
{
uint32_t listSize = UPRV_LENGTHOF(collation_strings_escaped);
UErrorCode status = U_ZERO_ERROR;
Collator *coll = Collator::createInstance(Locale(locale), status);
for(int k = 0; k < num; k++)
{
uint32_t i, j;
for(i=listSize-1; i>=1; i--) {
for(j=0; j<i; j++) {
if(coll->compare(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