1/*
2***********************************************************************
3* Copyright (C) 2016 and later: Unicode, Inc. and others.
4* License & terms of use: http://www.unicode.org/copyright.html#License
5***********************************************************************
6***********************************************************************
7* Copyright (c) 2002-2016, International Business Machines
8* Corporation and others.  All Rights Reserved.
9***********************************************************************
10*/
11#ifndef _STRINGPERF_H
12#define _STRINGPERF_H
13
14#include "cmemory.h"
15#include "unicode/utypes.h"
16#include "unicode/unistr.h"
17
18#include "unicode/uperf.h"
19
20#include <string.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24typedef std::wstring stlstring;
25
26/* Define all constants for test case operations */
27#define MAXNUMLINES	40000	//Max number of lines in a test data file
28#define MAXSRCLEN 20		//Max length of one line. maybe a larger number, but it need more mem
29#define LOOPS 100			//Iterations
30//#define LOOPS 10
31#define catenate_STRLEN 2
32
33const UChar uTESTCHAR1 =  'a';
34const wchar_t wTESTCHAR1 = 'a';
35const UnicodeString uEMPTY;
36const stlstring sEMPTY;
37UnicodeString unistr;
38stlstring stlstr;
39// Simulate construction with a single-char string for basic_string
40wchar_t simulate[2]={wTESTCHAR1, 0};
41
42/* Constants for scan operation */
43U_STRING_DECL(scan_STRING, "Dot. 123. Some more data.", 25);
44const UnicodeString uScan_STRING=UnicodeString(scan_STRING);
45const stlstring sScan_STRING=stlstring(L"Dot. 123. Some more data.");
46
47/* global variables or constants for concatenation operation */
48U_STRING_DECL(uCatenate_STR, "!!", 2);
49const stlstring sCatenate_STR=stlstring(L"!!");
50static UnicodeString* catICU;
51static stlstring* catStd;
52UBool bCatenatePrealloc;
53
54/* type defines */
55typedef struct WLine WLine;
56struct  WLine {
57    wchar_t   name[100];
58    int32_t   len;
59}; //struct to store one line of wchar_t string
60
61enum FnType { Fn_ICU, Fn_STD };
62typedef FnType FnType;
63typedef void (*ICUStringPerfFn)(const UChar* src,int32_t srcLen, UnicodeString s0);
64typedef void (*StdStringPerfFn)(const wchar_t* src,int32_t srcLen, stlstring s0);
65
66
67class StringPerfFunction : public UPerfFunction
68{
69public:
70
71    virtual long getEventsPerIteration(){
72        int loops = LOOPS;
73        if (catICU) { delete catICU;}
74        if (catStd) { delete catStd;}
75
76        if (bCatenatePrealloc) {
77
78            int to_alloc = loops * MAXNUMLINES * (MAXSRCLEN + catenate_STRLEN);
79            catICU = new UnicodeString(to_alloc,'a',0);
80            //catICU = new UnicodeString();
81
82            catStd = new stlstring();
83            //catStd -> reserve(loops * MAXNUMLINES * (MAXSRCLEN + catenate_STRLEN));
84            catStd -> reserve(110000000);
85        } else {
86            catICU = new UnicodeString();
87            catStd = new stlstring();
88        }
89
90        return -1;
91    }
92
93    virtual void call(UErrorCode* status)
94    {
95        if(line_mode_==TRUE){
96            if(uselen_){
97                for(int32_t i = 0; i< numLines_; i++){
98                    if (fnType_==Fn_ICU) {
99                        (*fn1_)(lines_[i].name,lines_[i].len,uS0_[i]);
100                    } else {
101                        (*fn2_)(wlines_[i].name,wlines_[i].len,sS0_[i]);
102                    }
103                }
104            }else{
105                for(int32_t i = 0; i< numLines_; i++){
106                    if (fnType_==Fn_ICU) {
107                        (*fn1_)(lines_[i].name,-1,uS0_[i]);
108                    } else {
109                        (*fn2_)(wlines_[i].name,-1,sS0_[i]);
110                    }
111                }
112            }
113        }else{
114            if(uselen_){
115                if (fnType_==Fn_ICU) {
116                    (*fn1_)(src_,srcLen_,*ubulk_);
117                } else {
118                    (*fn2_)(wsrc_,wsrcLen_,*sbulk_);
119                }
120            }else{
121                if (fnType_==Fn_ICU) {
122                    (*fn1_)(src_,-1,*ubulk_);
123                } else {
124                    (*fn2_)(wsrc_,-1,*sbulk_);
125                }
126            }
127        }
128    }
129
130    virtual long getOperationsPerIteration()
131    {
132        if(line_mode_==TRUE){
133            return numLines_;
134        }else{
135            return 1;
136        }
137    }
138
139    StringPerfFunction(ICUStringPerfFn func, ULine* srcLines, int32_t srcNumLines, UBool uselen)
140    {
141
142        fn1_ = func;
143        lines_=srcLines;
144        wlines_=NULL;
145        numLines_=srcNumLines;
146        uselen_=uselen;
147        line_mode_=TRUE;
148        src_ = NULL;
149        srcLen_ = 0;
150        wsrc_ = NULL;
151        wsrcLen_ = 0;
152        fnType_ = Fn_ICU;
153
154        uS0_=new UnicodeString[numLines_];
155        for(int32_t i=0; i<numLines_; i++) {
156            uS0_[i]=UnicodeString(lines_[i].name, lines_[i].len);
157        }
158        sS0_=NULL;
159        ubulk_=NULL;
160        sbulk_=NULL;
161    }
162
163    StringPerfFunction(StdStringPerfFn func, ULine* srcLines, int32_t srcNumLines, UBool uselen)
164    {
165
166        fn2_ = func;
167        lines_=srcLines;
168        wlines_=NULL;
169        numLines_=srcNumLines;
170        uselen_=uselen;
171        line_mode_=TRUE;
172        src_ = NULL;
173        srcLen_ = 0;
174        wsrc_ = NULL;
175        wsrcLen_ = 0;
176        fnType_ = Fn_STD;
177
178        uS0_=NULL;
179        ubulk_=NULL;
180        sbulk_=NULL;
181
182        //fillin wlines_[], sS0_[]
183        prepareLinesForStd();
184    }
185
186    StringPerfFunction(ICUStringPerfFn func, UChar* source, int32_t sourceLen, UBool uselen)
187    {
188
189        fn1_ = func;
190        lines_=NULL;
191        wlines_=NULL;
192        numLines_=0;
193        uselen_=uselen;
194        line_mode_=FALSE;
195        src_ = new UChar[sourceLen];
196        memcpy(src_, source, sourceLen * U_SIZEOF_UCHAR);
197        srcLen_ = sourceLen;
198        wsrc_ = NULL;
199        wsrcLen_ = 0;
200        fnType_ = Fn_ICU;
201
202        uS0_=NULL;
203        sS0_=NULL;
204        ubulk_=new UnicodeString(src_,srcLen_);
205        sbulk_=NULL;
206    }
207
208    StringPerfFunction(StdStringPerfFn func, UChar* source, int32_t sourceLen, UBool uselen)
209    {
210
211        fn2_ = func;
212        lines_=NULL;
213        wlines_=NULL;
214        numLines_=0;
215        uselen_=uselen;
216        line_mode_=FALSE;
217        src_ = new UChar[sourceLen];
218        memcpy(src_, source, sourceLen * U_SIZEOF_UCHAR);
219        srcLen_ = sourceLen;
220        fnType_ = Fn_STD;
221
222        uS0_=NULL;
223        sS0_=NULL;
224        ubulk_=NULL;
225
226        //fillin wsrc_, sbulk_
227        prepareBulkForStd();
228
229    }
230
231    ~StringPerfFunction()
232    {
233        //free(src_);
234        free(wsrc_);
235        delete[] src_;
236        delete ubulk_;
237        delete sbulk_;
238        delete[] uS0_;
239        delete[] sS0_;
240        delete[] wlines_;
241    }
242
243private:
244    void prepareLinesForStd(void)
245    {
246        UErrorCode err=U_ZERO_ERROR;
247
248        wlines_=new WLine[numLines_];
249        wchar_t ws[100];
250        int32_t wcap = UPRV_LENGTHOF(ws);
251        int32_t wl;
252        wchar_t* wcs;
253
254        sS0_=new stlstring[numLines_];
255        for(int32_t i=0; i<numLines_; i++) {
256            if(uselen_) {
257                wcs = u_strToWCS(ws, wcap, &wl, lines_[i].name, lines_[i].len, &err);
258                memcpy(wlines_[i].name, wcs, wl * sizeof(wchar_t));
259                wlines_[i].len = wl;
260                sS0_[i]=stlstring(wlines_[i].name, wlines_[i].len);
261            } else {
262                wcs = u_strToWCS(ws, wcap, &wl, lines_[i].name, lines_[i].len-1, &err);
263                memcpy(wlines_[i].name, wcs, wl*sizeof(wchar_t));
264                wlines_[i].len = wl;
265                sS0_[i]=stlstring(wlines_[i].name, wlines_[i].len+1);
266            }
267
268            if (U_FAILURE(err)) {
269                return;
270            }
271        }
272
273    }
274
275    void prepareBulkForStd(void)
276    {
277        UErrorCode err=U_ZERO_ERROR;
278
279        const UChar* uSrc = src_;
280        int32_t uSrcLen = srcLen_;
281        wchar_t* wDest = NULL;
282        int32_t wDestLen = 0;
283        int32_t reqLen= 0 ;
284
285        if(uselen_) {
286            /* pre-flight*/
287            u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen,&err);
288
289            if(err == U_BUFFER_OVERFLOW_ERROR){
290                err=U_ZERO_ERROR;
291                wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen));
292                wDestLen = reqLen;
293                u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen,&err);
294            }
295
296            if (U_SUCCESS(err)) {
297                wsrc_ = wDest;
298                wsrcLen_ = wDestLen;
299                sbulk_=new stlstring(wsrc_,wsrcLen_);
300            }
301
302        } else {
303            /* pre-flight*/
304            u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
305
306            if(err == U_BUFFER_OVERFLOW_ERROR){
307                err=U_ZERO_ERROR;
308                wDest =(wchar_t*) malloc(sizeof(wchar_t) * (reqLen+1));
309                wDestLen = reqLen+1;
310                u_strToWCS(wDest,wDestLen,&reqLen,uSrc,uSrcLen-1,&err);
311            }
312
313            if (U_SUCCESS(err)) {
314                wsrc_ = wDest;
315                wsrcLen_ = wDestLen;
316                sbulk_=new stlstring(wsrc_);
317            }
318        }
319
320        //free(wDest);
321    }
322
323
324private:
325    ICUStringPerfFn fn1_;
326    StdStringPerfFn fn2_;
327
328    ULine* lines_;
329    WLine* wlines_;
330    int32_t numLines_;
331
332    UBool uselen_;
333    UChar* src_;
334    int32_t srcLen_;
335    wchar_t* wsrc_;
336    int32_t wsrcLen_;
337    UBool line_mode_;
338
339    //added for preparing testing data
340    UnicodeString* uS0_;
341    stlstring* sS0_;
342    UnicodeString* ubulk_;
343    stlstring* sbulk_;
344    FnType fnType_;
345};
346
347
348class StringPerformanceTest : public UPerfTest
349{
350public:
351    StringPerformanceTest(int32_t argc, const char *argv[], UErrorCode &status);
352    ~StringPerformanceTest();
353    virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,
354                                          const char *&name,
355                                          char *par = NULL);
356    UPerfFunction* TestCtor();
357    UPerfFunction* TestCtor1();
358    UPerfFunction* TestCtor2();
359    UPerfFunction* TestCtor3();
360    UPerfFunction* TestAssign();
361    UPerfFunction* TestAssign1();
362    UPerfFunction* TestAssign2();
363    UPerfFunction* TestGetch();
364    UPerfFunction* TestCatenate();
365    UPerfFunction* TestScan();
366    UPerfFunction* TestScan1();
367    UPerfFunction* TestScan2();
368
369    UPerfFunction* TestStdLibCtor();
370    UPerfFunction* TestStdLibCtor1();
371    UPerfFunction* TestStdLibCtor2();
372    UPerfFunction* TestStdLibCtor3();
373    UPerfFunction* TestStdLibAssign();
374    UPerfFunction* TestStdLibAssign1();
375    UPerfFunction* TestStdLibAssign2();
376    UPerfFunction* TestStdLibGetch();
377    UPerfFunction* TestStdLibCatenate();
378    UPerfFunction* TestStdLibScan();
379    UPerfFunction* TestStdLibScan1();
380    UPerfFunction* TestStdLibScan2();
381
382private:
383    long COUNT_;
384    ULine* filelines_;
385    UChar* StrBuffer;
386    int32_t StrBufferLen;
387
388};
389
390
391inline void ctor(const UChar* src,int32_t srcLen, UnicodeString s0)
392{
393    UnicodeString a;
394}
395
396inline void ctor1(const UChar* src,int32_t srcLen, UnicodeString s0)
397{
398    UnicodeString b(uTESTCHAR1);
399}
400
401inline void ctor2(const UChar* src,int32_t srcLen, UnicodeString s0)
402{
403    UnicodeString c(uEMPTY);
404}
405
406inline void ctor3(const UChar* src,int32_t srcLen, UnicodeString s0)
407{
408    UnicodeString d(src,srcLen);
409}
410
411inline UnicodeString icu_assign_helper(const UChar* src,int32_t srcLen)
412{
413    if (srcLen==-1) { return src;}
414    else { return UnicodeString(src, srcLen);}
415}
416
417inline void assign(const UChar* src,int32_t srcLen, UnicodeString s0)
418{
419    unistr = icu_assign_helper(src,srcLen);
420}
421
422inline void assign1(const UChar* src,int32_t srcLen, UnicodeString s0)
423{
424    unistr.setTo(src, srcLen);
425}
426
427inline void assign2(const UChar* src,int32_t srcLen, UnicodeString s0)
428{
429    unistr = s0;
430}
431
432inline void getch(const UChar* src,int32_t srcLen, UnicodeString s0)
433{
434    s0.charAt(0);
435}
436
437
438inline void catenate(const UChar* src,int32_t srcLen, UnicodeString s0)
439{
440    UTimer mystart, mystop;
441    utimer_getTime(&mystart);
442
443    *catICU += s0;
444
445    utimer_getTime(&mystop);
446    double mytime = utimer_getDeltaSeconds(&mystart,&mystop);
447    printf("\nmytime=%f \n", mytime);
448
449    *catICU += uCatenate_STR;
450}
451
452volatile int scan_idx;
453U_STRING_DECL(SCAN1, "123", 3);
454
455inline void scan(const UChar* src,int32_t srcLen, UnicodeString s0)
456{
457    UChar c='.';
458    scan_idx = uScan_STRING.indexOf(c);
459}
460
461inline void scan1(const UChar* src,int32_t srcLen, UnicodeString s0)
462{
463    scan_idx = uScan_STRING.indexOf(SCAN1,3);
464}
465
466inline void scan2(const UChar* src,int32_t srcLen, UnicodeString s0)
467{
468    UChar c1='s';
469    UChar c2='m';
470    scan_idx = uScan_STRING.indexOf(c1);
471    scan_idx = uScan_STRING.indexOf(c2);
472}
473
474
475inline void StdLibCtor(const wchar_t* src,int32_t srcLen, stlstring s0)
476{
477    stlstring a;
478}
479
480inline void StdLibCtor1(const wchar_t* src,int32_t srcLen, stlstring s0)
481{
482    stlstring b(simulate);
483}
484
485inline void StdLibCtor2(const wchar_t* src,int32_t srcLen, stlstring s0)
486{
487    stlstring c(sEMPTY);
488}
489
490inline void StdLibCtor3(const wchar_t* src,int32_t srcLen, stlstring s0)
491{
492    if (srcLen==-1) {
493        stlstring d(src);
494    }else {
495        stlstring d(src, srcLen);
496    }
497}
498
499inline stlstring stl_assign_helper(const wchar_t* src,int32_t srcLen)
500{
501    if (srcLen==-1) { return src;}
502    else { return stlstring(src, srcLen);}
503}
504
505inline void StdLibAssign(const wchar_t* src,int32_t srcLen, stlstring s0)
506{
507    stlstr = stl_assign_helper(src,srcLen);
508}
509
510inline void StdLibAssign1(const wchar_t* src,int32_t srcLen, stlstring s0)
511{
512    if (srcLen==-1) { stlstr=src;}
513    else { stlstr.assign(src, srcLen);}
514}
515
516inline void StdLibAssign2(const wchar_t* src,int32_t srcLen, stlstring s0)
517{
518    stlstr=s0;
519}
520
521inline void StdLibGetch(const wchar_t* src,int32_t srcLen, stlstring s0)
522{
523    s0.at(0);
524}
525
526inline void StdLibCatenate(const wchar_t* src,int32_t srcLen, stlstring s0)
527{
528    UTimer mystart, mystop;
529    utimer_getTime(&mystart);
530
531    *catStd += s0;
532    *catStd += sCatenate_STR;
533
534    utimer_getTime(&mystop);
535    double mytime = utimer_getDeltaSeconds(&mystart,&mystop);
536    printf("\nmytime=%f \n", mytime);
537
538}
539
540inline void StdLibScan(const wchar_t* src,int32_t srcLen, stlstring s0)
541{
542    scan_idx = (int) sScan_STRING.find('.');
543}
544
545inline void StdLibScan1(const wchar_t* src,int32_t srcLen, stlstring s0)
546{
547    scan_idx = (int) sScan_STRING.find(L"123");
548}
549
550inline void StdLibScan2(const wchar_t* src,int32_t srcLen, stlstring s0)
551{
552    scan_idx = (int) sScan_STRING.find_first_of(L"sm");
553}
554
555#endif // STRINGPERF_H
556
557