[sword-cvs] icu-sword/source/tools/toolutil .cvsignore,1.2,1.3 Makefile.in,1.2,1.3 toolutil.c,1.2,1.3 toolutil.dsp,1.2,1.3 toolutil.h,1.2,1.3 toolutil.vcproj,NONE,1.1 ucbuf.c,1.4,1.5 ucbuf.h,1.3,1.4 ucmpwrit.c,1.2,1.3 ucmpwrit.h,1.2,1.3 unewdata.c,1.2,1.3 unewdata.h,1.2,1.3 uoptions.c,1.2,1.3 uoptions.h,1.2,1.3 uparse.c,1.2,1.3 uparse.h,1.2,1.3 uperf.cpp,NONE,1.1 uperf.h,NONE,1.1 utimer.h,NONE,1.1

sword@www.crosswire.org sword@www.crosswire.org
Tue, 9 Sep 2003 19:43:13 -0700


Update of /usr/local/cvsroot/icu-sword/source/tools/toolutil
In directory www:/tmp/cvs-serv19862/source/tools/toolutil

Added Files:
	.cvsignore Makefile.in toolutil.c toolutil.dsp toolutil.h 
	toolutil.vcproj ucbuf.c ucbuf.h ucmpwrit.c ucmpwrit.h 
	unewdata.c unewdata.h uoptions.c uoptions.h uparse.c uparse.h 
	uperf.cpp uperf.h utimer.h 
Log Message:
ICU 2.6 commit






--- NEW FILE: toolutil.vcproj ---
<?xml version="1.0" encoding = "Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="7.00"
	Name="toolutil"
	SccProjectName=""
	SccLocalPath="">
	<Platforms>
		<Platform
			Name="Win32"/>
	</Platforms>
	<Configurations>
		<Configuration
			Name="Release|Win32"
			OutputDirectory=".\..\..\..\lib"
			IntermediateDirectory=".\Release"
			ConfigurationType="2"
			UseOfMFC="0"
			ATLMinimizesCRunTimeLibraryUsage="FALSE"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="2"
				ImproveFloatingPointConsistency="TRUE"
				AdditionalIncludeDirectories="..\..\common"
				PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL"
				StringPooling="TRUE"
				RuntimeLibrary="2"
				EnableFunctionLevelLinking="TRUE"
				PrecompiledHeaderFile=".\Release/toolutil.pch"
				AssemblerListingLocation=".\Release/"
				ObjectFile=".\Release/"
				ProgramDataBaseFileName=".\Release/"
				WarningLevel="3"
				SuppressStartupBanner="TRUE"
				CompileAs="0"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				OutputFile="..\..\..\bin\icutu26.dll"
				LinkIncremental="1"
				SuppressStartupBanner="TRUE"
				AdditionalLibraryDirectories="..\..\..\lib"
				ProgramDatabaseFile=".\..\..\..\lib/icutu26.pdb"
				ImportLibrary="..\..\..\lib/icutu.lib"/>
			<Tool
				Name="VCMIDLTool"
				PreprocessorDefinitions="NDEBUG"
				MkTypLibCompatible="TRUE"
				SuppressStartupBanner="TRUE"
				TargetEnvironment="1"
				TypeLibraryName=".\..\..\..\lib/toolutil.tlb"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="NDEBUG"
				Culture="1033"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory=".\..\..\..\lib"
			IntermediateDirectory=".\Debug"
			ConfigurationType="2"
			UseOfMFC="0"
			ATLMinimizesCRunTimeLibraryUsage="FALSE"
			CharacterSet="2">
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				OptimizeForProcessor="2"
				AdditionalIncludeDirectories="..\..\common"
				PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL"
				BasicRuntimeChecks="3"
				RuntimeLibrary="3"
				PrecompiledHeaderFile=".\Debug/toolutil.pch"
				AssemblerListingLocation=".\Debug/"
				ObjectFile=".\Debug/"
				ProgramDataBaseFileName=".\Debug/"
				WarningLevel="3"
				SuppressStartupBanner="TRUE"
				DebugInformationFormat="4"
				CompileAs="0"/>
			<Tool
				Name="VCCustomBuildTool"/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"
				OutputFile="..\..\..\bin\icutu26d.dll"
				LinkIncremental="2"
				SuppressStartupBanner="TRUE"
				AdditionalLibraryDirectories="..\..\..\lib"
				GenerateDebugInformation="TRUE"
				ProgramDatabaseFile=".\..\..\..\lib/icutu26d.pdb"
				ImportLibrary="..\..\..\lib/icutud.lib"/>
			<Tool
				Name="VCMIDLTool"
				PreprocessorDefinitions="_DEBUG"
				MkTypLibCompatible="TRUE"
				SuppressStartupBanner="TRUE"
				TargetEnvironment="1"
				TypeLibraryName=".\..\..\..\lib/toolutil.tlb"/>
			<Tool
				Name="VCPostBuildEventTool"/>
			<Tool
				Name="VCPreBuildEventTool"/>
			<Tool
				Name="VCPreLinkEventTool"/>
			<Tool
				Name="VCResourceCompilerTool"
				PreprocessorDefinitions="_DEBUG"
				Culture="1033"/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"/>
			<Tool
				Name="VCWebDeploymentTool"/>
		</Configuration>
	</Configurations>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
			<File
				RelativePath=".\toolutil.c">
			</File>
			<File
				RelativePath=".\ucbuf.c">
			</File>
			<File
				RelativePath=".\ucmpwrit.c">
			</File>
			<File
				RelativePath=".\unewdata.c">
			</File>
			<File
				RelativePath=".\uoptions.c">
			</File>
			<File
				RelativePath=".\uparse.c">
			</File>
			<File
				RelativePath=".\uperf.cpp">
			</File>
		</Filter>
		<Filter
			Name="Header Files"
			Filter="h;hpp;hxx;hm;inl">
			<File
				RelativePath=".\toolutil.h">
			</File>
			<File
				RelativePath=".\ucbuf.h">
			</File>
			<File
				RelativePath=".\ucmpwrit.h">
			</File>
			<File
				RelativePath=".\unewdata.h">
			</File>
			<File
				RelativePath=".\uoptions.h">
			</File>
			<File
				RelativePath=".\uparse.h">
			</File>
			<File
				RelativePath=".\uperf.h">
			</File>
			<File
				RelativePath=".\utimer.h">
			</File>
		</Filter>
		<Filter
			Name="Resource Files"
			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>











--- NEW FILE: uperf.cpp ---
/********************************************************************
 * COPYRIGHT:
 * Copyright (c) 2002-2003, International Business Machines Corporation and
 * others. All Rights Reserved.
 ********************************************************************/

#include "uperf.h"

static const char delim = '/';
static int32_t execCount = 0;
UPerfTest* UPerfTest::gTest = NULL;
static const int MAXLINES       = 40000;
//static const char *currDir = ".";
                
enum
{
    HELP1,
    HELP2,
    VERBOSE,
    SOURCEDIR,
    ENCODING,
    USELEN,
    FILE_NAME,
    PASSES,
    ITERATIONS,
    TIME,
    LINE_MODE,
    BULK_MODE,
    LOCALE
};


static UOption options[]={
                      UOPTION_HELP_H,
                      UOPTION_HELP_QUESTION_MARK,
                      UOPTION_VERBOSE,
                      UOPTION_SOURCEDIR,
                      UOPTION_ENCODING,
                      UOPTION_DEF( "uselen",        'u', UOPT_NO_ARG),
                      UOPTION_DEF( "file-name",     'f', UOPT_REQUIRES_ARG),
                      UOPTION_DEF( "passes",        'p', UOPT_REQUIRES_ARG),
                      UOPTION_DEF( "iterations",    'i', UOPT_REQUIRES_ARG),                    
                      UOPTION_DEF( "time",          't', UOPT_REQUIRES_ARG),
                      UOPTION_DEF( "line-mode",     'l', UOPT_NO_ARG),
                      UOPTION_DEF( "bulk-mode",     'b', UOPT_NO_ARG),
                      UOPTION_DEF( "locale",        'L', UOPT_REQUIRES_ARG)
                  };

UPerfTest::UPerfTest(int32_t argc, const char* argv[], UErrorCode& status){
    
    _argc = argc;
    _argv = argv;
    ucharBuf = NULL;
    encoding = "";
    uselen = FALSE;
    fileName = NULL;
    sourceDir = ".";
    lines = NULL;
    numLines = 0;
    line_mode = TRUE;
    buffer = NULL;
    bufferLen = 0;
    verbose = FALSE;
    bulk_mode = FALSE;
    passes = iterations = time = 0;
    locale = NULL;
    
    //initialize the argument list
    U_MAIN_INIT_ARGS(argc, argv);
    //parse the arguments
    _remainingArgc = u_parseArgs(argc, (char**)argv, (int32_t)(sizeof(options)/sizeof(options[0])), options);

    // Now setup the arguments
    if(argc==1 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    if(options[VERBOSE].doesOccur) {
        verbose = TRUE;
    }

    if(options[SOURCEDIR].doesOccur) {
        sourceDir = options[SOURCEDIR].value;
    }

    if(options[ENCODING].doesOccur) {
        encoding = options[ENCODING].value;
    }

    if(options[USELEN].doesOccur) {
        uselen = TRUE;
    }

    if(options[FILE_NAME].doesOccur){
        fileName = options[FILE_NAME].value;
    }

    if(options[PASSES].doesOccur) {
        passes = atoi(options[PASSES].value);
    }
    if(options[ITERATIONS].doesOccur) {
        iterations = atoi(options[ITERATIONS].value);
    }
 
    if(options[TIME].doesOccur) {
        time = atoi(options[TIME].value);
    }
    
    if(options[LINE_MODE].doesOccur) {
        line_mode = TRUE;
        bulk_mode = FALSE;
    }

    if(options[BULK_MODE].doesOccur) {
        bulk_mode = TRUE;
        line_mode = FALSE;
    }
    
    if(options[LOCALE].doesOccur) {
      locale = options[LOCALE].value;
    }

    if(time > 0 && iterations >0){
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return;
    }

    int32_t len = 0;
    resolvedFileName = NULL;
    if(fileName!=NULL){
        //pre-flight
        ucbuf_resolveFileName(sourceDir, fileName,resolvedFileName,&len, &status);
        resolvedFileName = (char*) uprv_malloc(len);
        if(fileName==NULL){
            status= U_MEMORY_ALLOCATION_ERROR;
            return;
        }
        if(status == U_BUFFER_OVERFLOW_ERROR){
            status = U_ZERO_ERROR;
        }
        ucbuf_resolveFileName(sourceDir, fileName, resolvedFileName, &len, &status);
        ucharBuf = ucbuf_open(resolvedFileName,&encoding,TRUE,FALSE,&status);

        if(U_FAILURE(status)){
            printf("Could not open the input file %s. Error: %s\n", fileName, u_errorName(status));
            return;
        }
    }
}

ULine* UPerfTest::getLines(UErrorCode& status){
    lines     = new ULine[MAXLINES];
    int maxLines = MAXLINES;
    numLines=0;
    const UChar* line=NULL;
    int32_t len =0;
    for (;;) {
            line = ucbuf_readline(ucharBuf,&len,&status);
            if(status == U_EOF||U_FAILURE(status)){
                break;
            }
            lines[numLines].name  = new UChar[len];
            lines[numLines].len   = len;
            memcpy(lines[numLines].name, line, len * U_SIZEOF_UCHAR);
            
            numLines++;
            len = 0;
            if (numLines >= maxLines) {
                maxLines += MAXLINES;
                ULine *newLines = new ULine[maxLines];
                if(newLines == NULL) {
                    fprintf(stderr, "Out of memory reading line %d.\n", numLines);
                    status= U_MEMORY_ALLOCATION_ERROR;
                    delete lines;
                    return NULL;
                }

                memcpy(newLines, lines, numLines*sizeof(ULine));
                delete lines;
                lines = newLines;
            }
    }
    if(status==U_EOF){
        status =U_ZERO_ERROR;
    }
    return lines;
}
const UChar* UPerfTest::getBuffer(int32_t& len, UErrorCode& status){
    len = ucbuf_size(ucharBuf);
    buffer =  (UChar*) uprv_malloc(U_SIZEOF_UCHAR * (len+1));
    u_strncpy(buffer,ucbuf_getBuffer(ucharBuf,&bufferLen,&status),len);
    buffer[len]=0;
    len = bufferLen;
    return buffer;
}
UBool UPerfTest::run(){
    if(_remainingArgc==1){
        // Testing all methods
        return runTest();
    }
    UBool res=FALSE;
    // Test only the specified fucntion
    for (int i = 1; i < _remainingArgc; ++i) {
        if (_argv[i][0] != '-') {
            char* name = (char*) _argv[i];
            if(verbose==TRUE){
                //fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
                //fprintf(stdout, "\n%s:\n", name);
            }
            char* parameter = strchr( name, '@' );
            if (parameter) {
                *parameter = 0;
                parameter += 1;
            }
            execCount = 0;
            res = runTest( name, parameter );
            if (!res || (execCount <= 0)) {
                fprintf(stdout, "\n---ERROR: Test doesn't exist: %s!\n", name);
                return FALSE;
            }
        }
    }
    return res;
}
UBool UPerfTest::runTest(char* name, char* par ){
    UBool rval;
    char* pos = NULL;

    if (name)
        pos = strchr( name, delim ); // check if name contains path (by looking for '/')
    if (pos) {
        path = pos+1;   // store subpath for calling subtest
        *pos = 0;       // split into two strings
    }else{
        path = NULL;
    }

    if (!name || (name[0] == 0) || (strcmp(name, "*") == 0)) {
        rval = runTestLoop( NULL, NULL );

    }else if (strcmp( name, "LIST" ) == 0) {
        this->usage();
        rval = TRUE;

    }else{
        rval = runTestLoop( name, par );
    }

    if (pos)
        *pos = delim;  // restore original value at pos
    return rval;
}


void UPerfTest::setPath( char* pathVal )
{
    this->path = pathVal;
}

// call individual tests, to be overriden to call implementations
UPerfFunction* UPerfTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
{
    // to be overriden by a method like:
    /*
    switch (index) {
        case 0: name = "First Test"; if (exec) FirstTest( par ); break;
        case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
        default: name = ""; break;
    }
    */
    fprintf(stderr,"*** runIndexedTest needs to be overriden! ***");
    name = ""; exec = exec; index = index; par = par;
    return NULL;
}


UBool UPerfTest::runTestLoop( char* testname, char* par )
{
    int32_t    index = 0;
    const char*   name;
    UBool  run_this_test;
    UBool  rval = FALSE;
    UErrorCode status = U_ZERO_ERROR;
    UPerfTest* saveTest = gTest;
    gTest = this;
    int32_t loops = 0;
    double t=0;
    int32_t n = 1;
    do {
        this->runIndexedTest( index, FALSE, name );
        if (!name || (name[0] == 0))
            break;
        if (!testname) {
            run_this_test = TRUE;
        }else{
            run_this_test = (UBool) (strcmp( name, testname ) == 0);
        }
        if (run_this_test) {
            UPerfFunction* testFunction = this->runIndexedTest( index, TRUE, name, par );
            execCount++;
            rval=TRUE;
            if(testFunction==NULL){
                fprintf(stderr,"%s function returned NULL", name);
                return FALSE;
            }
            if (testFunction->getOperationsPerIteration() < 1) {
                fprintf(stderr, "%s returned an illegal operations/iteration()\n", name);
                return FALSE;
            }
            if(iterations == 0) {
              n = time;
              // Run for specified duration in seconds
              if(verbose==TRUE){
                  fprintf(stdout,"= %s calibrating %i seconds \n" ,name, n);
              }

              //n *=  1000; // s => ms
              //System.out.println("# " + meth.getName() + " " + n + " sec");                            
              int32_t failsafe = 1; // last resort for very fast methods
              t = 0;
              while (t < (int)(n * 0.9)) { // 90% is close enough
                  if (loops == 0 || t == 0) {
                      loops = failsafe;
                      failsafe *= 10;
                  } else {
                      //System.out.println("# " + meth.getName() + " x " + loops + " = " + t);                            
                      loops = (int)((double)n / t * loops + 0.5);
                      if (loops == 0) {
                          fprintf(stderr,"Unable to converge on desired duration");
                          return FALSE;
                      }
                  }
                  //System.out.println("# " + meth.getName() + " x " + loops);
                        t = testFunction->time(loops,&status);
						if(U_FAILURE(status)){
							printf("Performance test failed with error: %s \n", u_errorName(status));
							break;
						}
              }
            } else {
              loops = iterations;
            }

            for(int32_t ps =0; ps < passes; ps++){
              long events = -1;
              fprintf(stdout,"= %s begin " ,name);
              if(verbose==TRUE){
                  if(iterations > 0) {
                    fprintf(stdout, "%i\n", loops);
                  } else {
                    fprintf(stdout, "%i\n", n);
                  }
              } else {
                fprintf(stdout, "\n");
              }
              t = testFunction->time(loops, &status);
						if(U_FAILURE(status)){
							printf("Performance test failed with error: %s \n", u_errorName(status));
							break;
						}
              events = testFunction->getEventsPerIteration();
              //print info only in verbose mode
              if(verbose==TRUE){
/*
                  if(events == -1){
                      fprintf(stdout,"= %s end %f %i %i\n",name , t , loops, testFunction->getOperationsPerIteration());
                  }else{
                      fprintf(stdout,"= %s end %f %i %i %i\n",name , t , loops, testFunction->getOperationsPerIteration(), events);
                  }
*/
                  if(events == -1){
                      fprintf(stdout,"= %s end: %f loops: %i operations: %li \n",name , t , loops, testFunction->getOperationsPerIteration());
                  }else{
                      fprintf(stdout,"= %s end: %f loops: %i operations: %li events: %li\n",name , t , loops, testFunction->getOperationsPerIteration(), events);
                  }
              }else{
/*
                   if(events == -1){
                      fprintf(stdout,"= %f %i %i \n", t , loops, testFunction->getOperationsPerIteration());
                  }else{
                      fprintf(stdout,"= %f %i %i %i\n", t , loops, testFunction->getOperationsPerIteration(), events);
                  }                   
*/
                  if(events == -1){
                      fprintf(stdout,"= %s end %f %i %li\n",name , t , loops, testFunction->getOperationsPerIteration());
                  }else{
                      fprintf(stdout,"= %s end %f %i %li %li\n",name , t , loops, testFunction->getOperationsPerIteration(), events);
                  }
              }
            }
            delete testFunction;
        }
        index++;
    }while(name);

    gTest = saveTest;
    return rval;
}

/**
* Print a usage message for this test class.
*/
void UPerfTest::usage( void )
{
    UBool save_verbose = verbose;
    verbose = TRUE;
    fprintf(stdout,"Test names:\n");
    fprintf(stdout,"-----------\n");

    int32_t index = 0;
    const char* name = NULL;
    do{
        this->runIndexedTest( index, FALSE, name );
        if (!name) break;
        fprintf(stdout,name);
        fprintf(stdout,"\n");
        index++;
    }while (name && (name[0] != 0));
    verbose = save_verbose;
}




void UPerfTest::setCaller( UPerfTest* callingTest )
{
    caller = callingTest;
    if (caller) {
        verbose = caller->verbose;
    }
}

UBool UPerfTest::callTest( UPerfTest& testToBeCalled, char* par )
{
    execCount--; // correct a previously assumed test-exec, as this only calls a subtest
    testToBeCalled.setCaller( this );
    return testToBeCalled.runTest( path, par );
}

UPerfTest::~UPerfTest(){
    if(lines!=NULL){
        delete[] lines;
    }
    if(buffer!=NULL){
        uprv_free(buffer);
    }
    ucbuf_close(ucharBuf);
}



--- NEW FILE: uperf.h ---
/*
**********************************************************************
* Copyright (c) 2002-2003, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
**********************************************************************
*/
#ifndef _UPERF_H
#define _UPERF_H

#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "unicode/ustring.h"
#include "utimer.h"
#include "uoptions.h"
#include "ucbuf.h"

U_NAMESPACE_USE
// Use the TESTCASE macro in subclasses of IntlTest.  Define the
// runIndexedTest method in this fashion:
//
//| void MyTest::runIndexedTest(int32_t index, UBool exec,
//|                             const char* &name, char* /*par*/) {
//|     switch (index) {
//|         TESTCASE(0,TestSomething);
//|         TESTCASE(1,TestSomethingElse);
//|         TESTCASE(2,TestAnotherThing);
//|         default: 
//|             name = ""; 
//|             return NULL;
//|     }
//| }
#if 0
#define TESTCASE(id,test)                       \
    case id:                                    \
        name = #test;                           \
        if (exec) {                             \
            fprintf(stdout,#test "---");        \
            fprintf(stdout,"\n");               \
            return test();                      \
        }                                       \
        break

#endif
#define TESTCASE(id,test)                       \
    case id:                                    \
        name = #test;                           \
        if (exec) {                             \
            return test();                      \
        }                                       \
        break

/**
 * Subclasses of PerfTest will need to create subclasses of
 * Function that define a call() method which contains the code to
 * be timed.  They then call setTestFunction() in their "Test..."
 * method to establish this as the current test functor.
 */
class U_EXPORT UPerfFunction {
public:
    /**
     * Subclasses must implement this method to do the action to be
     * measured.
     */
    virtual void call(UErrorCode* status)=0;

    /**
     * Subclasses must implement this method to return positive
     * integer indicating the number of operations in a single
     * call to this object's call() method.
     */
    virtual long getOperationsPerIteration()=0;
    /**
     * Subclasses should override this method to return either positive
     * or negative integer indicating the number of events in a single
     * call to this object's call() method, if applicable
     * e.g: Number of breaks / iterations for break iterator
     */
    virtual long getEventsPerIteration(){
        return -1;
    }

    /**
     * Call call() n times in a tight loop and return the elapsed
     * milliseconds.  If n is small and call() is fast the return
     * result may be zero.  Small return values have limited
     * meaningfulness, depending on the underlying CPU and OS.
     */
     double time(int32_t n, UErrorCode* status) {
        UTimer start, stop;
        utimer_getTime(&start); 
        while (n-- > 0) {
            call(status);
        }
        utimer_getTime(&stop);
        return utimer_getDeltaSeconds(&start,&stop); // ms
    }

};


class U_EXPORT UPerfTest {
public:
    UBool run();
    UBool runTest( char* name = NULL, char* par = NULL ); // not to be overidden
        
    virtual void usage( void ) ;
    
    virtual ~UPerfTest();

    void setCaller( UPerfTest* callingTest ); // for internal use only
    
    void setPath( char* path ); // for internal use only
    
    ULine* getLines(UErrorCode& status);

    const UChar* getBuffer(int32_t& len,UErrorCode& status);

protected:
    UPerfTest(int32_t argc, const char* argv[], UErrorCode& status);

    virtual UPerfFunction* runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide !

    virtual UBool runTestLoop( char* testname, char* par );

    virtual UBool callTest( UPerfTest& testToBeCalled, char* par );

    UBool        verbose;
    const char*  sourceDir;
    const char*  fileName;
    char*        resolvedFileName;
    const char*  encoding;
    UBool        uselen;
    int32_t      iterations;
    int32_t      passes;
    int32_t      time;
    const char** _argv;
    int32_t      _argc;
    int32_t      _remainingArgc;
    ULine*       lines;
    int32_t      numLines;
    UCHARBUF*    ucharBuf;
    UBool        line_mode;
    UBool        bulk_mode;
    UChar* buffer;
    int32_t      bufferLen;
    const char*  locale;
private:
    UPerfTest*   caller;
    char*        path;           // specifies subtests

// static members
public:
    static UPerfTest* gTest;
    static const char* gUsageString;
};

const char* UPerfTest::gUsageString =
                "Usage: %s [OPTIONS] [FILES]\n"
                "\tReads the input file and prints out time taken in seconds\n"
                "Options:\n"
                "\t-h or -? or --help       this usage text\n"
                "\t-v or --verbose          print extra information when processing files\n"
                "\t-s or --sourcedir        source directory for files followed by path\n"
                "\t                         followed by path\n"
                "\t-e or --encoding         encoding of source files\n"
                "\t-u or --uselen           perform timing analysis on non-null terminated buffer using length\n"
                "\t-f or --file-name        file to be used as input data\n"
                "\t-p or --passes           Number of passes to be performed. Requires Numeric argument. Cannot be used with --time\n"
                "\t-i or --iterations       Number of iterations to be performed. Requires Numeric argument\n"
                "\t-t or --time             Threshold time for looping until in seconds. Requires Numeric argument.Cannot be used with --iterations\n"
                "\t-l or --line-mode        The data file should be processed in line mode\n"
                "\t-b or --bulk-mode        The data file should be processed in file based. Cannot be used with --line-mode\n"
                "\t-L or --locale           Locale for the test\n";

#endif


--- NEW FILE: utimer.h ---
/*
************************************************************************
* Copyright (c) 1997-2002, International Business Machines
* Corporation and others.  All Rights Reserved.
************************************************************************
*/

#ifndef _UTIMER_H
#define _UTIMER_H

#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#   include <windows.h>
#else
#   include <sys/time.h> 
#   include <unistd.h> 
#endif

/**
 * This API provides functions for performing performance measurement
 * There are 3 main usage scenarios.
 * i) Loop until a threshold time is reached:
 *    Example:
 *    <code>
 *      typedef Params Params;
 *      struct Params{
 *          UChar* target;
 *          int32_t targetLen;
 *          const UChar* source;
 *          int32_t sourceLen;
 *          UNormalizationMode mode;
 *      }
 *      void NormFn( void* param){
 *          Params* parameters = ( Params*) param;
 *          UErrorCode error = U_ZERO_ERROR;
 *          unorm_normalize(parameters->source, parameters->sourceLen, parameters->mode, 0, parameters->target, parameters->targetLen, &error);
 *          if(U_FAILURE(error)){
 *              printf("Normalization failed\n");
 *          }
 *      }
 *  
 *      int main(){
 *          // time the normalization function 
 *          double timeTaken = 0;
 *          Params param;
 *          param.source  // set up the source buffer 
 *          param.target   // set up the target buffer
 *          .... so on ...
 *          UTimer timer;
 *          // time the loop for 10 seconds at least and find out the loop count and time taken
 *          timeTaken = utimer_loopUntilDone((double)10,(void*) param, NormFn, &loopCount);
 *      }
 *     </code>
 *
 * ii) Measure the time taken
 *     Example:
 *     <code>
 *          double perfNormalization(NormFn fn,const char* mode,Line* fileLines,int32_t loopCount){
 *              int  line;
 *              int  loops;
 *              UErrorCode error = U_ZERO_ERROR;
 *              UChar* dest=NULL;
 *              int32_t destCapacity=0;
 *              int len =-1;
 *              double elapsedTime = 0; 
 *              int retVal=0;
 *
 *              UChar arr[5000];
 *              dest=arr;
 *              destCapacity = 5000;
 *              UTimer start;
 *
 *              // Initialize cache and ensure the data is loaded.
 *              // This loop checks for errors in Normalization. Once we pass the initialization
 *              // without errors we can safelly assume that there are no errors while timing the 
 *              // funtion
 *              for (loops=0; loops<10; loops++) {
 *                  for (line=0; line < gNumFileLines; line++) {
 *                      if (opt_uselen) {
 *                          len = fileLines[line].len;
 *                      }
 *
 *                      retVal= fn(fileLines[line].name,len,dest,destCapacity,&error);
 *          #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
 *                      if(retVal==0 ){
 *                          fprintf(stderr,"Normalization of string in Windows API failed for mode %s. ErrorNo: %i at line number %i\n",mode,GetLastError(),line);
 *                          return 0;
 *                      }
 *          #endif
 *                      if(U_FAILURE(error)){
 *                          fprintf(stderr,"Normalization of string in ICU API failed for mode %s. Error: %s at line number %i\n",mode,u_errorName(error),line);
 *                          return 0;
 *                      }
 *            
 *                  }
 *              }
 *
 *              //compute the time
 *
 *              utimer_getTime(&start);
 *              for (loops=0; loops<loopCount; loops++) {
 *                  for (line=0; line < gNumFileLines; line++) {
 *                      if (opt_uselen) {
 *                          len = fileLines[line].len;
 *                      }
 *
 *                      retVal= fn(fileLines[line].name,len,dest,destCapacity,&error);
 *           
 *                  }
 *              }
 *
 *              return utimer_getElapsedSeconds(&start);
 *          }
 *      </code>
 *
 * iii) Let a higher level function do the calculation of confidence levels etc.
 *     Example:
 *     <code>
 *       void perf(UTimer* timer, UChar* source, int32_t sourceLen, UChar* target, int32_t targetLen, int32_t loopCount,UNormalizationMode mode, UErrorCode* error){
 *              int32_t loops;
 *              for (loops=0; loops<loopCount; loops++) {
 *                  unorm_normalize(source,sourceLen,target, targetLen,mode,error);
 *              }
 *              utimer_getTime(timer);
 *       }
 *       void main(const char* argsc, int argv){
 *          // read the file and setup the data
 *          // set up options
 *          UTimer start,timer1, timer2, timer3, timer4;
 *          double NFDTimeTaken, NFCTimeTaken, FCDTimeTaken;
 *          switch(opt){
 *              case 0:
 *                  utimer_getTime(start);
 *                  perf(timer1, source,sourceLen, target, targetLen,loopCount,UNORM_NFD,&error);
 *                  NFDTimeTaken = utimer_getDeltaSeconds(start,timer1);
 *              case 1:
 *                  timer_getTime(start);
 *                  perf(timer2,source,sourceLen,target,targetLen,loopCount,UNORM_NFC,&error);
 *                  NFCTimeTaken = utimer_getDeltaSeconds(start,timer2);
 *                  perf(timer3, source, sourceLen, target,targetLen, loopCount, UNORM_FCD,&error);
 *              // ........so on .............          
 *           }
 *          // calculate confidence levels etc and print            
 *
 *       }
 *           
 *     </code>
 *      
 */

typedef struct UTimer UTimer;

typedef void FuntionToBeTimed(void* param);


#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)

    struct UTimer{
        LARGE_INTEGER start;
        LARGE_INTEGER placeHolder;
    };      
        
    int uprv_initFrequency(UTimer* timer)
    {
        return QueryPerformanceFrequency(&timer->placeHolder);
    }
    void uprv_start(UTimer* timer)
    {
        QueryPerformanceCounter(&timer->start);
    }
    double uprv_delta(UTimer* timer1, UTimer* timer2){
        return ((double)(timer2->start.QuadPart - timer1->start.QuadPart))/((double)timer1->placeHolder.QuadPart);
    }
    UBool uprv_compareFrequency(UTimer* timer1, UTimer* timer2){
        return (timer1->placeHolder.QuadPart == timer2->placeHolder.QuadPart);
    }

#else

    struct UTimer{
        struct timeval start;
        struct timeval placeHolder;
    };
    
    int32_t uprv_initFrequency(UTimer* /*timer*/)
    {
        return 0;
    }
    void uprv_start(UTimer* timer)
    {
        gettimeofday(&timer->start, 0);
    }
    double uprv_delta(UTimer* timer1, UTimer* timer2){
        double t1, t2;

        t1 =  (double)timer1->start.tv_sec + (double)timer1->start.tv_usec/(1000*1000);
        t2 =  (double)timer2->start.tv_sec + (double)timer2->start.tv_usec/(1000*1000);
        return (t2-t1);
    }
    UBool uprv_compareFrequency(UTimer* /*timer1*/, UTimer* /*timer2*/){
        return TRUE;
    }

#endif
/**
 * Intializes the timer with the current time
 *
 * @param timer A pointer to UTimer struct to recieve the current time
 */
U_CAPI void U_EXPORT2
utimer_getTime(UTimer* timer){
    uprv_initFrequency(timer);
    uprv_start(timer);
}

/**
 * Returns the difference in times between timer1 and timer2 by subtracting
 * timer1's time from timer2's time
 *
 * @param timer1 A pointer to UTimer struct to be used as starting time
 * @param timer2 A pointer to UTimer struct to be used as end time
 * @return Time in seconds
 */
U_CAPI double U_EXPORT2
utimer_getDeltaSeconds(UTimer* timer1, UTimer* timer2){
    if(uprv_compareFrequency(timer1,timer2)){
        return uprv_delta(timer1,timer2);
    }
    /* got error return -1 */
    return -1;
}

/**
 * Returns the time elapsed from the starting time represented by the 
 * UTimer struct pointer passed
 * @param timer A pointer to UTimer struct to be used as starting time
 * @return Time elapsed in seconds
 */
U_CAPI double U_EXPORT2
utimer_getElapsedSeconds(UTimer* timer){
    UTimer temp;
    utimer_getTime(&temp);
    return uprv_delta(timer,&temp);
}

/**
 * Executes the function pointed to for a given time and returns exact time
 * taken and number of iterations of the loop
 * @param thresholTimeVal 
 * @param loopCount output param to recieve the number of iterations
 * @param fn    The funtion to be executed
 * @param param Parameters to be passed to the fn
 * @return the time elapsed in seconds
 */
U_CAPI double U_EXPORT2
utimer_loopUntilDone(double thresholdTimeVal,
                     int32_t* loopCount, 
                     FuntionToBeTimed fn, 
                     void* param){
    UTimer timer;
    double currentVal=0;
    *loopCount = 0;
    utimer_getTime(&timer);
    for(;currentVal<thresholdTimeVal;){
        fn(param);
        currentVal = utimer_getElapsedSeconds(&timer);
        *loopCount++;
    }
    return currentVal;
}

#endif