1/*
2**********************************************************************
3* Copyright (c) 2002-2014,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/dtitvfmt.h"
18#include "unicode/utypes.h"
19#include "unicode/datefmt.h"
20#include "unicode/calendar.h"
21#include "unicode/uclean.h"
22#include "unicode/brkiter.h"
23#include "unicode/numfmt.h"
24#include "unicode/coll.h"
25#include "util.h"
26
27#include "datedata.h"
28#include "breakdata.h"
29#include "collationdata.h"
30
31#include <stdlib.h>
32#include <string.h>
33
34#include <fstream>
35
36#include <iostream>
37using namespace std;
38
39//  Stubs for Windows API functions when building on UNIXes.
40//
41#if U_PLATFORM_USES_ONLY_WIN32_API
42// do nothing
43#else
44#define _UNICODE
45typedef int DWORD;
46inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest);
47#endif
48
49class BreakItFunction : public UPerfFunction
50{
51private:
52	int num;
53	bool wordIteration;
54
55public:
56
57	BreakItFunction(){num = -1;}
58	BreakItFunction(int a, bool b){num = a; wordIteration = b;}
59
60	virtual void call(UErrorCode * status)
61	{
62		BreakIterator* boundary;
63
64		if(wordIteration)
65		{
66			for(int i = 0; i < num; i++)
67			{
68				boundary = BreakIterator::createWordInstance("en", *status);
69				boundary->setText(str);
70
71				int32_t start = boundary->first();
72				for (int32_t end = boundary->next();
73					 end != BreakIterator::DONE;
74					 start = end, end = boundary->next())
75				{
76					printTextRange( *boundary, start, end );
77				}
78			}
79		}
80
81		else // character iteration
82		{
83			for(int i = 0; i < num; i++)
84            {
85				boundary = BreakIterator::createCharacterInstance(Locale::getUS(), *status);
86				boundary->setText(str);
87
88				int32_t start = boundary->first();
89				for (int32_t end = boundary->next();
90					 end != BreakIterator::DONE;
91					 start = end, end = boundary->next())
92				{
93					printTextRange( *boundary, start, end );
94				}
95			}
96		}
97
98
99	}
100
101	virtual long getOperationsPerIteration()
102	{
103		if(wordIteration) return 125*num;
104		else return 355*num;
105	}
106
107	void printUnicodeString(const UnicodeString &s) {
108		char charBuf[1000];
109		s.extract(0, s.length(), charBuf, sizeof(charBuf)-1, 0);
110		charBuf[sizeof(charBuf)-1] = 0;
111		printf("%s", charBuf);
112	}
113
114
115	void printTextRange( BreakIterator& iterator,
116						int32_t start, int32_t end )
117	{
118		CharacterIterator *strIter = iterator.getText().clone();
119		UnicodeString  s;
120		strIter->getText(s);
121		//printUnicodeString(UnicodeString(s, start, end-start));
122		//puts("");
123		delete strIter;
124	}
125
126	// Print the given string to stdout (for debugging purposes)
127	void uprintf(const UnicodeString &str) {
128		char *buf = 0;
129		int32_t len = str.length();
130		int32_t bufLen = len + 16;
131		int32_t actualLen;
132		buf = new char[bufLen + 1];
133		actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion
134		buf[actualLen] = 0;
135		printf("%s", buf);
136		delete[] buf;
137	}
138
139};
140
141class DateFmtFunction : public UPerfFunction
142{
143
144private:
145	int num;
146    char locale[25];
147public:
148
149	DateFmtFunction()
150	{
151		num = -1;
152	}
153
154	DateFmtFunction(int a, const char* loc)
155	{
156		num = a;
157        strcpy(locale, loc);
158	}
159
160	virtual void call(UErrorCode* status)
161	{
162
163		UErrorCode status2 = U_ZERO_ERROR;
164		Calendar *cal;
165		TimeZone *zone;
166		UnicodeString str;
167		UDate date;
168
169		cal = Calendar::createInstance(status2);
170		check(status2, "Calendar::createInstance");
171		zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone
172		cal->adoptTimeZone(zone);
173
174		Locale loc(locale);
175		DateFormat *fmt;
176		fmt = DateFormat::createDateTimeInstance(
177								DateFormat::kShort, DateFormat::kFull, loc);
178
179
180		// (dates are imported from datedata.h)
181		for(int j = 0; j < num; j++)
182			for(int i = 0; i < NUM_DATES; i++)
183			{
184				cal->clear();
185				cal->set(years[i], months[i], days[i]);
186				date = cal->getTime(status2);
187				check(status2, "Calendar::getTime");
188
189				fmt->setCalendar(*cal);
190
191				// Format the date
192				str.remove();
193				fmt->format(date, str, status2);
194
195
196				// Display the formatted date string
197				//uprintf(str);
198				//printf("\n");
199
200			}
201
202		delete fmt;
203		delete cal;
204		//u_cleanup();
205	}
206
207	virtual long getOperationsPerIteration()
208	{
209		return NUM_DATES * num;
210	}
211
212	// Print the given string to stdout (for debugging purposes)
213	void uprintf(const UnicodeString &str) {
214		char *buf = 0;
215		int32_t len = str.length();
216		int32_t bufLen = len + 16;
217		int32_t actualLen;
218		buf = new char[bufLen + 1];
219		actualLen = str.extract(0, len, buf/*, bufLen*/); // Default codepage conversion
220		buf[actualLen] = 0;
221		printf("%s", buf);
222		delete[] buf;
223	}
224
225	// Verify that a UErrorCode is successful; exit(1) if not
226	void check(UErrorCode& status, const char* msg) {
227		if (U_FAILURE(status)) {
228			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
229			exit(1);
230		}
231	}
232
233};
234
235class DateFmtCreateFunction : public UPerfFunction
236{
237
238private:
239        int num;
240        char locale[25];
241public:
242
243        DateFmtCreateFunction(int a, const char* loc)
244        {
245                num = a;
246                strcpy(locale, loc);
247        }
248
249        virtual void call(UErrorCode* /* status */)
250        {
251
252                Locale loc(locale);
253                DateFormat *fmt;
254                // (dates are imported from datedata.h)
255                for(int j = 0; j < num; j++) {
256                    fmt = DateFormat::createDateTimeInstance(
257                            DateFormat::kShort, DateFormat::kFull, loc);
258                    delete fmt;
259                }
260        }
261
262        virtual long getOperationsPerIteration()
263        {
264                return num;
265        }
266
267};
268
269class DateFmtCopyFunction : public UPerfFunction
270{
271
272private:
273        int num;
274    char locale[25];
275public:
276
277        DateFmtCopyFunction()
278        {
279                num = -1;
280        }
281
282        DateFmtCopyFunction(int a, const char* loc)
283        {
284                num = a;
285        strcpy(locale, loc);
286        }
287
288        virtual void call(UErrorCode* /* status */)
289        {
290                Locale loc(locale);
291                UErrorCode status2 = U_ZERO_ERROR;
292                DateFormat *fmt = DateFormat::createDateTimeInstance(
293                            DateFormat::kShort, DateFormat::kFull, loc);
294                for(int j = 0; j < num; j++) {
295                    Format *cp = fmt->clone();
296                    delete cp;
297                }
298                delete fmt;
299        }
300
301        virtual long getOperationsPerIteration()
302        {
303                return num;
304        }
305
306        // Verify that a UErrorCode is successful; exit(1) if not
307        void check(UErrorCode& status, const char* msg) {
308                if (U_FAILURE(status)) {
309                        printf("ERROR: %s (%s)\n", u_errorName(status), msg);
310                        exit(1);
311                }
312        }
313
314};
315
316class DIFCreateFunction : public UPerfFunction
317{
318
319private:
320	int num;
321    char locale[25];
322public:
323
324	DIFCreateFunction()
325	{
326		num = -1;
327	}
328
329	DIFCreateFunction(int a, const char* loc)
330	{
331		num = a;
332        strcpy(locale, loc);
333	}
334
335	virtual void call(UErrorCode* /* status */)
336	{
337		UErrorCode status2 = U_ZERO_ERROR;
338		Calendar *cal;
339		TimeZone *zone;
340
341		cal = Calendar::createInstance(status2);
342		check(status2, "Calendar::createInstance");
343		zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone
344		cal->adoptTimeZone(zone);
345
346		Locale loc(locale);
347                UnicodeString skeleton("yMMMMdHms");
348
349		for(int j = 0; j < num; j++) {
350                    DateIntervalFormat* fmt(DateIntervalFormat::createInstance(skeleton, loc, status2));
351                    delete fmt;
352                }
353                delete cal;
354	}
355
356	virtual long getOperationsPerIteration()
357	{
358		return num;
359	}
360
361	// Verify that a UErrorCode is successful; exit(1) if not
362	void check(UErrorCode& status, const char* msg) {
363		if (U_FAILURE(status)) {
364			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
365			exit(1);
366		}
367	}
368
369};
370
371class TimeZoneCreateFunction : public UPerfFunction
372{
373
374private:
375	int num;
376    char locale[25];
377public:
378
379	TimeZoneCreateFunction()
380	{
381		num = -1;
382	}
383
384	TimeZoneCreateFunction(int a, const char* loc)
385	{
386		num = a;
387        strcpy(locale, loc);
388	}
389
390	virtual void call(UErrorCode* /* status */)
391	{
392		Locale loc(locale);
393                UnicodeString tzname("UTC");
394		for(int j = 0; j < num; j++) {
395                    TimeZone* tz(TimeZone::createTimeZone(tzname));
396                    delete tz;
397                }
398	}
399
400	virtual long getOperationsPerIteration()
401	{
402		return num;
403	}
404
405	// Verify that a UErrorCode is successful; exit(1) if not
406	void check(UErrorCode& status, const char* msg) {
407		if (U_FAILURE(status)) {
408			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
409			exit(1);
410		}
411	}
412
413};
414
415class DTPatternGeneratorCreateFunction : public UPerfFunction
416{
417
418private:
419	int num;
420    char locale[25];
421public:
422
423	DTPatternGeneratorCreateFunction()
424	{
425		num = -1;
426	}
427
428	DTPatternGeneratorCreateFunction(int a, const char* loc)
429	{
430		num = a;
431        strcpy(locale, loc);
432	}
433
434	virtual void call(UErrorCode* /* status */)
435	{
436		UErrorCode status2 = U_ZERO_ERROR;
437		Locale loc(locale);
438
439		for(int j = 0; j < num; j++) {
440                    DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
441                    delete gen;
442                }
443	}
444
445	virtual long getOperationsPerIteration()
446	{
447		return num;
448	}
449
450	// Verify that a UErrorCode is successful; exit(1) if not
451	void check(UErrorCode& status, const char* msg) {
452		if (U_FAILURE(status)) {
453			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
454			exit(1);
455		}
456	}
457
458};
459
460class DTPatternGeneratorCopyFunction : public UPerfFunction
461{
462
463private:
464	int num;
465    char locale[25];
466public:
467
468	DTPatternGeneratorCopyFunction()
469	{
470		num = -1;
471	}
472
473	DTPatternGeneratorCopyFunction(int a, const char* loc)
474	{
475		num = a;
476        strcpy(locale, loc);
477	}
478
479	virtual void call(UErrorCode* /* status */)
480	{
481		UErrorCode status2 = U_ZERO_ERROR;
482		Locale loc(locale);
483                DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
484
485		for(int j = 0; j < num; j++) {
486                    DateTimePatternGenerator *cl = gen->clone();
487                    delete cl;
488                }
489                delete gen;
490	}
491
492	virtual long getOperationsPerIteration()
493	{
494		return num;
495	}
496
497	// Verify that a UErrorCode is successful; exit(1) if not
498	void check(UErrorCode& status, const char* msg) {
499		if (U_FAILURE(status)) {
500			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
501			exit(1);
502		}
503	}
504
505};
506
507class DTPatternGeneratorBestValueFunction : public UPerfFunction
508{
509
510private:
511	int num;
512    char locale[25];
513public:
514
515	DTPatternGeneratorBestValueFunction()
516	{
517		num = -1;
518	}
519
520	DTPatternGeneratorBestValueFunction(int a, const char* loc)
521	{
522		num = a;
523        strcpy(locale, loc);
524	}
525
526	virtual void call(UErrorCode* /* status */)
527	{
528		UErrorCode status2 = U_ZERO_ERROR;
529		Locale loc(locale);
530                DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
531                UnicodeString skeleton("yMMMMdHms");
532
533		for(int j = 0; j < num; j++) {
534                    gen->getBestPattern(skeleton, status2);
535                }
536                check(status2, "getBestPattern");
537                delete gen;
538	}
539
540	virtual long getOperationsPerIteration()
541	{
542		return num;
543	}
544
545	// Verify that a UErrorCode is successful; exit(1) if not
546	void check(UErrorCode& status, const char* msg) {
547		if (U_FAILURE(status)) {
548			printf("ERROR: %s (%s)\n", u_errorName(status), msg);
549			exit(1);
550		}
551	}
552
553};
554
555class NumFmtFunction : public UPerfFunction
556{
557
558private:
559	int num;
560    char locale[25];
561public:
562
563	NumFmtFunction()
564	{
565		num = -1;
566	}
567
568	NumFmtFunction(int a, const char* loc)
569	{
570		num = a;
571        strcpy(locale, loc);
572	}
573
574	virtual void call(UErrorCode* status2)
575	{
576        Locale loc(locale);
577        UErrorCode status = U_ZERO_ERROR;
578
579        // Create a number formatter for the locale
580        NumberFormat *fmt = NumberFormat::createInstance(loc, status);
581
582        // Parse a string.  The string uses the digits '0' through '9'
583        // and the decimal separator '.', standard in the US locale
584
585        for(int i = 0; i < num; i++)
586        {
587            UnicodeString str("9876543210.123");
588            Formattable result;
589            fmt->parse(str, result, status);
590
591            //uprintf(formattableToString(result));
592            //printf("\n");
593
594            // Take the number parsed above, and use the formatter to
595            // format it.
596            str.remove(); // format() will APPEND to this string
597            fmt->format(result, str, status);
598
599            //uprintf(str);
600            //printf("\n");
601        }
602
603        delete fmt; // Release the storage used by the formatter
604    }
605
606    enum {
607        U_SPACE=0x20,
608        U_DQUOTE=0x22,
609        U_COMMA=0x2c,
610        U_LEFT_SQUARE_BRACKET=0x5b,
611        U_BACKSLASH=0x5c,
612        U_RIGHT_SQUARE_BRACKET=0x5d,
613        U_SMALL_U=0x75
614    };
615
616    // Create a display string for a formattable
617    UnicodeString formattableToString(const Formattable& f) {
618        switch (f.getType()) {
619        case Formattable::kDate:
620            // TODO: Finish implementing this
621            return UNICODE_STRING_SIMPLE("Formattable_DATE_TBD");
622        case Formattable::kDouble:
623            {
624                char buf[256];
625                sprintf(buf, "%gD", f.getDouble());
626                return UnicodeString(buf, "");
627            }
628        case Formattable::kLong:
629        case Formattable::kInt64:
630            {
631                char buf[256];
632                sprintf(buf, "%ldL", f.getLong());
633                return UnicodeString(buf, "");
634            }
635        case Formattable::kString:
636            return UnicodeString((UChar)U_DQUOTE).append(f.getString()).append((UChar)U_DQUOTE);
637        case Formattable::kArray:
638            {
639                int32_t i, count;
640                const Formattable* array = f.getArray(count);
641                UnicodeString result((UChar)U_LEFT_SQUARE_BRACKET);
642                for (i=0; i<count; ++i) {
643                    if (i > 0) {
644                        (result += (UChar)U_COMMA) += (UChar)U_SPACE;
645                    }
646                    result += formattableToString(array[i]);
647                }
648                result += (UChar)U_RIGHT_SQUARE_BRACKET;
649                return result;
650            }
651        default:
652            return UNICODE_STRING_SIMPLE("INVALID_Formattable");
653        }
654    }
655
656	virtual long getOperationsPerIteration()
657	{
658		return num;
659	}
660
661    // Print the given string to stdout using the UTF-8 converter (for debugging purposes only)
662    void uprintf(const UnicodeString &str) {
663        char stackBuffer[100];
664        char *buf = 0;
665
666        int32_t bufLen = str.extract(0, 0x7fffffff, stackBuffer, sizeof(stackBuffer), "UTF-8");
667        if(bufLen < sizeof(stackBuffer)) {
668            buf = stackBuffer;
669        } else {
670            buf = new char[bufLen + 1];
671            bufLen = str.extract(0, 0x7fffffff, buf, bufLen + 1, "UTF-8");
672        }
673        printf("%s", buf);
674        if(buf != stackBuffer) {
675            delete[] buf;
676        }
677    }
678};
679
680
681
682#define NUM_STRING "9876543210.123"
683#define NUM_NUM 9876543210.123
684class StdioNumFmtFunction : public UPerfFunction
685{
686
687 private:
688  int num;
689  char locale[25];
690 public:
691
692  StdioNumFmtFunction()
693    {
694      num = -1;
695    }
696
697  StdioNumFmtFunction(int a, const char* loc)
698    {
699      num = a;
700      strcpy(locale, loc);
701    }
702
703  virtual void call(UErrorCode* status2)
704  {
705    Locale loc(locale);
706    UErrorCode status = U_ZERO_ERROR;
707
708    // Parse a string.  The string uses the digits '0' through '9'
709    // and the decimal separator '.', standard in the US locale
710
711    double result;
712    char outbuf[500];
713    const char *str = NUM_STRING;
714
715    for(int i = 0; i < num; i++)
716      {
717        if(sscanf(str, "%lg", &result)!=1) {
718          cout << "Failed Stdio: failed to sscanf" << endl;
719          *status2 = U_PARSE_ERROR;
720          return;
721        }
722
723        sprintf(outbuf, "%lg", result);
724      }
725
726    if(result!=NUM_NUM) {
727      cout << "Failed Stdio: sscanf got wrong result, expected " << NUM_NUM << " got " << result << endl;
728      *status2 = U_PARSE_ERROR;
729    }
730    if(strcmp(str,NUM_STRING)) {
731      cout << "Failed Stdio: sprintf got wrong result, expected " << NUM_STRING << " got " << str << endl;
732      *status2 = U_PARSE_ERROR;
733    }
734  }
735
736  virtual long getOperationsPerIteration()
737  {
738    return num;
739  }
740
741};
742
743class CollationFunction : public UPerfFunction
744{
745
746private:
747	int num;
748    char locale[25];
749	UnicodeString *collation_strings;
750
751	/**
752	 * Unescape the strings
753	 */
754	void init() {
755        uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]);
756		collation_strings = new UnicodeString[listSize];
757		for(uint32_t k=0;k<listSize;k++) {
758			collation_strings[k] = collation_strings_escaped[k].unescape();
759		}
760		UnicodeString shorty((UChar32)0x12345);
761	}
762public:
763
764	CollationFunction()
765	{
766		num = -1;
767
768		init();
769	}
770
771	~CollationFunction() {
772		delete [] collation_strings;
773	}
774
775	CollationFunction(int a, const char* loc)
776	{
777		num = a;
778        strcpy(locale, loc);
779		init();
780	}
781
782	virtual void call(UErrorCode* status2)
783	{
784        uint32_t listSize = sizeof(collation_strings_escaped)/sizeof(collation_strings_escaped[0]);
785        UErrorCode status = U_ZERO_ERROR;
786        Collator *coll = Collator::createInstance(Locale(locale), status);
787
788        for(int k = 0; k < num; k++)
789        {
790            uint32_t i, j;
791            for(i=listSize-1; i>=1; i--) {
792                for(j=0; j<i; j++) {
793                    if(coll->compare(collation_strings[j], collation_strings[j+1]) == UCOL_LESS) {
794                    //cout << "Success!" << endl;
795                     }
796                }
797            }
798         }
799        delete coll;
800    }
801
802	virtual long getOperationsPerIteration()
803	{
804		return num;
805	}
806};
807
808class DateFormatPerfTest : public UPerfTest
809{
810private:
811
812public:
813
814	DateFormatPerfTest(int32_t argc, const char* argv[], UErrorCode& status);
815	~DateFormatPerfTest();
816	virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,const char* &name, char* par);
817
818	UPerfFunction* DateFmt250();
819	UPerfFunction* DateFmt10000();
820	UPerfFunction* DateFmt100000();
821	UPerfFunction* DateFmtCreate250();
822	UPerfFunction* DateFmtCreate10000();
823	UPerfFunction* DateFmtCopy250();
824	UPerfFunction* DateFmtCopy10000();
825	UPerfFunction* BreakItWord250();
826	UPerfFunction* BreakItWord10000();
827	UPerfFunction* BreakItChar250();
828	UPerfFunction* BreakItChar10000();
829    UPerfFunction* NumFmt10000();
830    UPerfFunction* NumFmt100000();
831    UPerfFunction* Collation10000();
832    UPerfFunction* Collation100000();
833    UPerfFunction* DIFCreate250();
834    UPerfFunction* DIFCreate10000();
835    UPerfFunction* TimeZoneCreate250();
836    UPerfFunction* TimeZoneCreate10000();
837    UPerfFunction* DTPatternGeneratorCreate250();
838    UPerfFunction* DTPatternGeneratorCreate10000();
839    UPerfFunction* DTPatternGeneratorCopy250();
840    UPerfFunction* DTPatternGeneratorCopy10000();
841    UPerfFunction* DTPatternGeneratorBestValue250();
842    UPerfFunction* DTPatternGeneratorBestValue10000();
843};
844
845#endif // DateFmtPerf
846