diff --git a/Pascal/Test/MainUnit.pas b/Pascal/Test/MainUnit.pas index 6c72829..ed6661e 100644 --- a/Pascal/Test/MainUnit.pas +++ b/Pascal/Test/MainUnit.pas @@ -53,6 +53,8 @@ function MsvcrtWcstod(Str: PWideChar; PtrEnd: PPWideChar): Double; cdecl; extern var pure_parse_float_library: HMODULE; pure_parse_float: function(Str: PAnsiChar; Double: PDouble; PtrEnd: PPAnsiChar): Double; cdecl; + dll_pure_parse_float_library: HMODULE; + dll_pure_parse_float: function(Str: PAnsiChar; Double: PDouble; PtrEnd: PPAnsiChar): Double; cdecl; // from ieee_convert32.dll/ieee_convert64.dll function IeeeStringToDouble(Str: UnicodeString; out Value: Double): Integer; @@ -103,6 +105,20 @@ function PureStringToDoubleC(Str: UnicodeString; out Value: Double): Integer; Result := PEnd - PAnsiChar(AnsiStr); end; +// from user dll +function PureStringToDoubleUserDll(Str: UnicodeString; out Value: Double): Integer; +var + AnsiStr: AnsiString; + PEnd: PAnsiChar; +begin + Value := 0.0; + AnsiStr := AnsiString(Str);// unicode -> ansi + + dll_pure_parse_float(PAnsiChar(AnsiStr), @Value, @PEnd); + + Result := PEnd - PAnsiChar(AnsiStr); +end; + // form MSVCRT.dll function MsvcrtStringToDouble(Str: UnicodeString; out Value: Double): Integer; var @@ -159,6 +175,14 @@ procedure AssertEqual(S: UnicodeString); begin CountA := IeeeStringToDouble(S, A); + if @dll_pure_parse_float <> nil then + begin + CountB := PureStringToDoubleUserDll(S, B); + Assert(CountA = CountB); + Assert(ABin = BBin); + exit; + end; + case Mode of ModePure: begin @@ -202,6 +226,21 @@ function UlpDiff(S: UnicodeString): TUlpDiffType; BBin: Int64 absolute B; begin IeeeStringToDouble(S, A); + + if @dll_pure_parse_float <> nil then + begin + PureStringToDoubleUserDll(S, B); + if ABin = BBin then + begin + exit(udtSame); + end; + if (ABin - 1 = BBin) or (ABin + 1 = BBin) then + begin + exit(udtOne); + end; + exit(udtMoreThanOne); + end; + case Mode of ModePure: begin @@ -713,7 +752,7 @@ procedure Benchmark(); AnsiTestStrings := AnsiTestStrings + [AnsiString(S)]; end; - Times := [0, 0, 0, 0, 0]; + Times := [0, 0, 0, 0, 0, 0]; for N := 0 to 400 - 1 do begin // netlib/David M. Gay @@ -762,6 +801,17 @@ procedure Benchmark(); end; Times[4] := Times[4] + Int64(TThread.GetTickCount64() - Time); end; + + // ParseFloat dll + if @dll_pure_parse_float <> nil then + begin + Time := TThread.GetTickCount64(); + for I := 0 to High(AnsiTestStrings) do + begin + dll_pure_parse_float(PAnsiChar(AnsiTestStrings[I]), @D, @PAnsiEnd); + end; + Times[5] := Times[5] + Int64(TThread.GetTickCount64() - Time); + end; end; Writeln('Netlib strtod: ', Times[0], 'ms'); @@ -779,6 +829,10 @@ procedure Benchmark(); Writeln(' ', (Times[4] / Times[3]):0:2, 'x slower'); end; end; + if @dll_pure_parse_float <> nil then + begin + Writeln('User DLL ParseFloat: ', Times[5], 'ms'); + end; end; procedure DoRunTests(); @@ -787,9 +841,57 @@ procedure DoRunTests(); I: Integer; SuccessCount: Integer; CmdSize, CmdMode: UnicodeString; + DllName, DllFunctionName: UnicodeString; begin Writeln('=== PureFloatParser Test ==='); + if FindCmdLineSwitch('dll') then + begin + if not FindCmdLineSwitch('function') then + begin + Writeln('Please use -function with -dll option!'); + exit; + end; + // load dll + {$IFDEF FPC} + DllName := GetCmdLineArg('dll', ['-']); + {$ELSE} + DllName := ''; + FindCmdLineSwitch('dll', DllName, True, [clstValueNextParam]); + {$ENDIF} + if DllName = '' then + begin + Writeln('Bad -dll param!'); + exit; + end; + dll_pure_parse_float_library := LoadLibrary(PWideChar(DllName)); + if pure_parse_float_library = 0 then + begin + Writeln('Can''t open "' + DllName + '" dll!'); + exit; + end; + // load func + {$IFDEF FPC} + DllFunctionName := GetCmdLineArg('function', ['-']); + {$ELSE} + DllFunctionName := ''; + FindCmdLineSwitch('function', DllFunctionName, True, [clstValueNextParam]); + {$ENDIF} + if DllFunctionName = '' then + begin + Writeln('Bad -function param!'); + exit; + end; + @dll_pure_parse_float := GetProcAddress(dll_pure_parse_float_library, PWideChar(DllFunctionName)); + if @dll_pure_parse_float = nil then + begin + Writeln('Can''t load function "' + DllFunctionName + '" from dll!'); + exit; + end; + // print info + Writeln('*** Parser function "' + DllFunctionName + '", from user DLL "', DllName, '" ***'); + end; + if FindCmdLineSwitch('c') then begin if @pure_parse_float = nil then @@ -855,7 +957,8 @@ procedure DoRunTests(); Writeln('Bad param parser!'); exit; end; - end else + end + else if @dll_pure_parse_float = nil then begin Writeln('Use "-parser pure/delphi/microsoft" for change a parser under test.'); Writeln(' Parser=Pure by default.'); @@ -867,11 +970,19 @@ procedure DoRunTests(); else Writeln(' 64 bit cpu'); - case Mode of - ModePure: Writeln(' Parser=Pure'); - ModeDelphi: Writeln(' Parser=Delphi'); - ModeMicrosoft: Writeln(' Parser=Microsoft'); - end; + if @dll_pure_parse_float = nil then + begin + case Mode of + ModePure: Writeln(' Parser=Pure'); + ModeDelphi: Writeln(' Parser=Delphi'); + ModeMicrosoft: Writeln(' Parser=Microsoft'); + end; + if TestCVersion then + begin + Writeln(' Test C Version'); + end; + end else + Writeln(' Parser=User DLL'); case TestCount of SizeSmall: Writeln(' Size=Small'); @@ -879,11 +990,6 @@ procedure DoRunTests(); SizeLarge: Writeln(' Size=Large'); end; - if TestCVersion then - begin - Writeln(' Test C Version'); - end; - Writeln; // make tests @@ -971,6 +1077,7 @@ initialization finalization FreeLibrary(pure_parse_float_library); + FreeLibrary(dll_pure_parse_float_library); end. diff --git a/Pascal/Test/Test.dproj b/Pascal/Test/Test.dproj index 539e174..ceb687c 100644 --- a/Pascal/Test/Test.dproj +++ b/Pascal/Test/Test.dproj @@ -34,6 +34,12 @@ true true + + true + Cfg_1 + true + true + true Base @@ -68,7 +74,7 @@ vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) -size medium -parser pure (None) - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 32.exe 1033 @@ -80,7 +86,7 @@ vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;FMXTee;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) -size medium -parser pure (None) - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 64.exe 1033 @@ -96,6 +102,9 @@ false + + -size medium -parser pure + 0 RELEASE;$(DCC_Define)