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>
36using 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
44typedef int DWORD;
45inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest);
46#endif
47
48class BreakItFunction : public UPerfFunction
49{
50private:
51	int num;
52	bool wordIteration;
53
54public:
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
140class DateFmtFunction : public UPerfFunction
141{
142
143private:
144	int num;
145    char locale[25];
146public:
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
234class NumFmtFunction : public UPerfFunction
235{
236
237private:
238	int num;
239    char locale[25];
240public:
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
363class 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
422class CollationFunction : public UPerfFunction
423{
424
425private:
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	}
441public:
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
487class DateFormatPerfTest : public UPerfTest
488{
489private:
490
491public:
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