/***********************************************************************
 * © 2016 and later: Unicode, Inc. and others.
 * License & terms of use: http://www.unicode.org/copyright.html
 *
 ***********************************************************************
 ***********************************************************************
 * COPYRIGHT:
 * Copyright (C) 2002-2006 International Business Machines Corporation
 * and others. All Rights Reserved.
 *
 ***********************************************************************/
/*****************************************************************************
* File stringperf.cpp
*
* Modification History:
* Name                     Description
* Doug Wang                Second version
* Doug Wang                First Version
******************************************************************************
*/

/** 
 * This program tests UnicodeString performance.
 * APIs tested: UnicodeString
 * ICU4C  
 * Windows 2000/XP, Linux
 */

#include "stringperf.h"


int main(int argc, const char *argv[])
{
    UErrorCode status = U_ZERO_ERROR;

    bCatenatePrealloc=true;

    StringPerformanceTest test(argc, argv, status);
    if (U_FAILURE(status)){
        return status;
    }

    int loops = LOOPS;
    if (bCatenatePrealloc) {
        int to_alloc = loops * MAXNUMLINES * (MAXSRCLEN + catenate_STRLEN);
        catICU = new UnicodeString(to_alloc,'a',0);
        //catICU = new UnicodeString();

        catStd = new stlstring();
        catStd -> reserve(loops * MAXNUMLINES * (MAXSRCLEN + catenate_STRLEN));
        //catStd -> reserve(110000000);
    } else {
        catICU = new UnicodeString();
        catStd = new stlstring();
    }

    if (test.run() == false){
        fprintf(stderr, "FAILED: Tests could not be run please check the "
            "arguments.\n");
        return -1;
    }

    delete catICU;
    delete catStd;
    return 0;
}

StringPerformanceTest::StringPerformanceTest(int32_t argc, const char *argv[],
                                             UErrorCode &status)
                                             : UPerfTest(argc, argv, status)
{
    filelines_=nullptr;
    StrBuffer=nullptr;
    StrBufferLen=0;

    int32_t len =0;

    if (status== U_ILLEGAL_ARGUMENT_ERROR){
        //fprintf(stderr,gUsageString, "stringperf");
        return;
    }
    if (U_FAILURE(status)){
        fprintf(stderr, "FAILED to create UPerfTest object. Error: %s\n", 
            u_errorName(status));
        return;
    }


    if(line_mode){
        ULine* filelines = getLines(status);
        if(U_FAILURE(status)){
            fprintf(stderr, "FAILED to read lines from file and create UPerfTest object. Error: %s\n", u_errorName(status));
            return;
        }

        filelines_ = new ULine[numLines];
        for (int i =0; i < numLines; i++) {
            len = filelines[i].len;
            filelines_[i].name  = new char16_t[len];
            filelines_[i].len   = len;
            memcpy(filelines_[i].name, filelines[i].name, len * U_SIZEOF_UCHAR);
        }

    }else if(bulk_mode){
        int32_t srcLen = 0;
        const char16_t* src = getBuffer(srcLen,status);
        if(U_FAILURE(status)){
            fprintf(stderr, "FAILED to read buffer from file and create UPerfTest object. Error: %s\n", u_errorName(status));
            return;
        }

        StrBuffer = new char16_t[srcLen];
        StrBufferLen = srcLen;
        memcpy(StrBuffer, src, srcLen * U_SIZEOF_UCHAR);

    }
}

StringPerformanceTest::~StringPerformanceTest()
{
    delete[] filelines_;
    delete[] StrBuffer;
}

UPerfFunction* StringPerformanceTest::runIndexedTest(int32_t index, UBool exec,
                                                   const char *&name, 
                                                   char* par) 
{
    switch (index) {
        TESTCASE(0, TestCtor);
        TESTCASE(1, TestCtor1);
        TESTCASE(2, TestCtor2);
        TESTCASE(3, TestCtor3);
        TESTCASE(4, TestAssign);
        TESTCASE(5, TestAssign1);
        TESTCASE(6, TestAssign2);
        TESTCASE(7, TestGetch);
        TESTCASE(8, TestCatenate);
        TESTCASE(9, TestScan);
        TESTCASE(10, TestScan1);
        TESTCASE(11, TestScan2);

        TESTCASE(12, TestStdLibCtor);
        TESTCASE(13, TestStdLibCtor1);
        TESTCASE(14, TestStdLibCtor2);
        TESTCASE(15, TestStdLibCtor3);
        TESTCASE(16, TestStdLibAssign);
        TESTCASE(17, TestStdLibAssign1);
        TESTCASE(18, TestStdLibAssign2);
        TESTCASE(19, TestStdLibGetch);
        TESTCASE(20, TestStdLibCatenate);
        TESTCASE(21, TestStdLibScan);
        TESTCASE(22, TestStdLibScan1);
        TESTCASE(23, TestStdLibScan2);

        default: 
            name = ""; 
            return nullptr;
    }
    return nullptr;
}

UPerfFunction* StringPerformanceTest::TestCtor()
{
    if (line_mode) {
        return new StringPerfFunction(ctor, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(ctor, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestCtor1()
{
    if (line_mode) {
        return new StringPerfFunction(ctor1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(ctor1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestCtor2()
{
    if (line_mode) {
        return new StringPerfFunction(ctor2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(ctor2, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestCtor3()
{
    if (line_mode) {
        return new StringPerfFunction(ctor3, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(ctor3, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestAssign()
{
    if (line_mode) {
        return new StringPerfFunction(assign, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(assign, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestAssign1()
{
    if (line_mode) {
        return new StringPerfFunction(assign1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(assign1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestAssign2()
{
    if (line_mode) {
        return new StringPerfFunction(assign2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(assign2, StrBuffer, StrBufferLen, uselen);
    }
}


UPerfFunction* StringPerformanceTest::TestGetch()
{
    if (line_mode) {
        return new StringPerfFunction(getch, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(getch, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestCatenate()
{
    if (line_mode) {
        return new StringPerfFunction(catenate, filelines_, numLines, uselen);
    } else {
        //return new StringPerfFunction(catenate, buffer, bufferLen, uselen);
        return new StringPerfFunction(catenate, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestScan()
{
    if (line_mode) {
        return new StringPerfFunction(scan, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(scan, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestScan1()
{
    if (line_mode) {
        return new StringPerfFunction(scan1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(scan1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestScan2()
{
    if (line_mode) {
        return new StringPerfFunction(scan2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(scan2, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibCtor()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibCtor, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibCtor, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibCtor1()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibCtor1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibCtor1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibCtor2()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibCtor2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibCtor2, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibCtor3()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibCtor3, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibCtor3, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibAssign()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibAssign, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibAssign, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibAssign1()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibAssign1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibAssign1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibAssign2()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibAssign2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibAssign2, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibGetch()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibGetch, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibGetch, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibCatenate()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibCatenate, filelines_, numLines, uselen);
    } else {
        //return new StringPerfFunction(StdLibCatenate, buffer, bufferLen, uselen);
        return new StringPerfFunction(StdLibCatenate, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibScan()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibScan, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibScan, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibScan1()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibScan1, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibScan1, StrBuffer, StrBufferLen, uselen);
    }
}

UPerfFunction* StringPerformanceTest::TestStdLibScan2()
{
    if (line_mode) {
        return new StringPerfFunction(StdLibScan2, filelines_, numLines, uselen);
    } else {
        return new StringPerfFunction(StdLibScan2, StrBuffer, StrBufferLen, uselen);
    }
}


