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>
35using 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
43typedef int DWORD;
44inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest);
45#endif
46
47class BreakItFunction : public UPerfFunction
48{
49private:
50	int num;
51	bool wordIteration;
52
53public:
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
139class DateFmtFunction : public UPerfFunction
140{
141
142private:
143	int num;
144    char locale[25];
145public:
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
233class NumFmtFunction : public UPerfFunction
234{
235
236private:
237	int num;
238    char locale[25];
239public:
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
358class CollationFunction : public UPerfFunction
359{
360
361private:
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	}
377public:
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
423class DateFormatPerfTest : public UPerfTest
424{
425private:
426
427public:
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