{******************************************************************************} { } { Library: Fundamentals 5.00 } { File name: flcUtils.pas } { File version: 5.69 } { Description: Utility functions. } { } { Copyright: Copyright (c) 2000-2020, David J Butler } { All rights reserved. } { Redistribution and use in source and binary forms, with } { or without modification, are permitted provided that } { the following conditions are met: } { Redistributions of source code must retain the above } { copyright notice, this list of conditions and the } { following disclaimer. } { THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND } { CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED } { WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED } { WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A } { PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL } { THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, } { INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR } { CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, } { PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF } { USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) } { HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER } { IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING } { NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE } { USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE } { POSSIBILITY OF SUCH DAMAGE. } { } { Github: https://github.com/fundamentalslib } { E-mail: fundamentals.library at gmail.com } { } { Revision history: } { } { 2000/02/02 0.01 Initial version. } { 2000/03/08 1.02 Added array functions. } { 2000/04/10 1.03 Added Append, Renamed Delete to Remove and added } { StringArrays. } { 2000/05/03 1.04 Added Path functions. } { 2000/05/08 1.05 Revision. } { 2000/06/01 1.06 Added Range and Dup constructors for dynamic arrays. } { 2000/06/03 1.07 Added ArrayInsert functions. } { 2000/06/06 1.08 Added bit functions from cMaths. } { 2000/06/08 1.09 Removed data structure classes. } { 2000/06/10 1.10 Added linked lists for Integer, Int64, Extended and } { String. } { 2000/06/14 1.11 cUtils now generated from a template using a source } { pre-processor. } { 2000/07/04 1.12 Revision for first Fundamentals release. } { 2000/07/24 1.13 Added TrimArray functions. } { 2000/07/26 1.14 Added Difference functions. } { 2000/09/02 1.15 Added RemoveDuplicates functions. } { Added Count functions. } { 2000/09/27 1.16 Fixed bug in ArrayInsert. } { 2000/11/29 1.17 Moved SetFPUPrecision to cSysUtils. } { 2001/05/03 1.18 Improved bit functions. Added Pascal versions of } { assembly routines. } { 2001/05/13 1.19 Added CharCount. } { 2001/05/15 1.20 Added PosNext (ClassType, ObjectArray). } { 2001/05/18 1.21 Added hashing functions from cMaths. } { 2001/07/07 1.22 Added TBinaryTreeNode. } { 2001/11/11 2.23 Revision. } { 2002/01/03 2.24 Added EncodeBase64, DecodeBase64 from cMaths and } { optimized. Added LongWordToHex, HexToLongWord. } { 2002/03/30 2.25 Fixed bug in DecodeBase64. } { 2002/04/02 2.26 Removed dependencies on all other units to remove } { initialization code associated with SysUtils. This } { allows usage of cUtils in projects and still have } { very small binaries. } { Fixed bug in LongWordToHex. } { 2002/05/31 3.27 Refactored for Fundamentals 3. } { Moved linked lists to cLinkedLists. } { 2002/08/09 3.28 Added HashInteger. } { 2002/10/06 3.29 Renamed Cond to iif. } { 2002/12/12 3.30 Small revisions. } { 2003/03/14 3.31 Removed ApproxZero. Added FloatZero, FloatsEqual and } { FloatsCompare. Added documentation and test cases for } { comparison functions. } { Added support for Currency type. } { 2003/07/27 3.32 Added fast ZeroMem and FillMem routines. } { 2003/09/11 3.33 Added InterfaceArray functions. } { 2004/01/18 3.34 Added WideStringArray functions. } { 2004/07/24 3.35 Optimizations of Sort functions. } { 2004/08/01 3.36 Improved validation in base conversion routines. } { 2004/08/22 3.37 Compilable with Delphi 8. } { 2005/06/10 4.38 Compilable with FreePascal 2 Win32 i386. } { 2005/08/19 4.39 Compilable with FreePascal 2 Linux i386. } { 2005/09/21 4.40 Revised for Fundamentals 4. } { 2006/03/04 4.41 Compilable with Delphi 2006 Win32/.NET. } { 2007/06/08 4.42 Compilable with FreePascal 2.04 Win32 i386 } { 2007/08/08 4.43 Changes to memory functions for Delphi 2006/2007. } { 2008/06/06 4.44 Fixed bug in case insensitive hashing functions. } { 2009/10/09 4.45 Compilable with Delphi 2009 Win32/.NET. } { 2010/06/27 4.46 Compilable with FreePascal 2.4.0 OSX x86-64. } { 2012/04/03 4.47 Support for Delphi XE string and integer types. } { 2012/04/04 4.48 Moved dynamic arrays functions to cDynArrays. } { 2012/04/11 4.49 StringToFloat/FloatToStr functions. } { 2012/08/26 4.50 UnicodeString versions of functions. } { 2013/01/29 4.51 Compilable with Delphi XE3 x86-64. } { 2013/03/22 4.52 Minor fixes. } { 2013/05/12 4.53 Added string type definitions. } { 2013/11/15 4.54 Revision. } { 2015/03/13 4.55 RawByteString functions. } { 2015/05/06 4.56 Add UTF functions from unit cUnicodeCodecs. } { 2015/06/07 4.57 Moved bit functions to unit cBits32. } { 2016/01/09 5.58 Revised for Fundamentals 5. } { 2016/01/29 5.59 StringRefCount functions. } { 2017/10/07 5.60 Moved functions to units flcBase64, flcUTF, flcCharSet. } { 2017/11/01 5.61 Added TBytes functions. } { 2018/07/11 5.62 Moved functions to units flcFloats, flcASCII. } { 2018/07/11 5.63 Moved standard types to unit flcStdTypes. } { 2018/08/12 5.64 Removed WideString functions and CLR code. } { 2018/08/14 5.65 ByteChar changes. } { 2019/04/02 5.66 Swap changes. } { 2020/03/13 5.67 NativeInt changes. } { 2020/03/30 5.68 EqualMem optimisations and tests. } { 2020/06/02 5.69 String to/from UInt64 conversion functions. } { } { Supported compilers: } { } { Delphi 2010-10.4 Win32/Win64 5.69 2020/06/02 } { Delphi 10.2-10.4 Linux64 5.69 2020/06/02 } { FreePascal 3.0.4 Win64 5.69 2020/06/02 } { } {******************************************************************************} {$INCLUDE ..\flcInclude.inc} {$IFDEF FREEPASCAL} {$WARNINGS OFF} {$HINTS OFF} {$ENDIF} {$IFDEF DEBUG} {$IFDEF TEST} {$DEFINE UTILS_TEST} {$ENDIF} {$ENDIF} unit flcUtils; interface uses { System } SysUtils, { Fundamentals } flcStdTypes; { } { Version } { } const FundamentalsVersion = '5.0.6'; { } { Exception } { } type ERangeCheckError = class(Exception) public constructor Create; end; { } { Compare result } { Generic compare result enumeration. } { } type TCompareResult = ( crLess, crEqual, crGreater, crUndefined ); TCompareResultSet = set of TCompareResult; function InverseCompareResult(const C: TCompareResult): TCompareResult; { } { Integer functions } { } { Min returns smallest of A and B } { Max returns greatest of A and B } function MinInt(const A, B: Integer): Integer; {$IFDEF UseInline}inline;{$ENDIF} function MaxInt(const A, B: Integer): Integer; {$IFDEF UseInline}inline;{$ENDIF} function MinCrd(const A, B: Cardinal): Cardinal; {$IFDEF UseInline}inline;{$ENDIF} function MaxCrd(const A, B: Cardinal): Cardinal; {$IFDEF UseInline}inline;{$ENDIF} { Bounded returns Value if in Min..Max range, otherwise Min or Max } function Int32Bounded(const Value: Int32; const Min, Max: Int32): Int32; {$IFDEF UseInline}inline;{$ENDIF} function Int64Bounded(const Value: Int64; const Min, Max: Int64): Int64; {$IFDEF UseInline}inline;{$ENDIF} function Int32BoundedByte(const Value: Int32): Int32; {$IFDEF UseInline}inline;{$ENDIF} function Int64BoundedByte(const Value: Int64): Int64; {$IFDEF UseInline}inline;{$ENDIF} function Int32BoundedWord(const Value: Int32): Int32; {$IFDEF UseInline}inline;{$ENDIF} function Int64BoundedWord(const Value: Int64): Int64; {$IFDEF UseInline}inline;{$ENDIF} function Int64BoundedWord32(const Value: Int64): Word32; {$IFDEF UseInline}inline;{$ENDIF} { } { String construction from buffer } { } {$IFDEF SupportAnsiString} function StrPToStrA(const P: PAnsiChar; const L: NativeInt): AnsiString; {$ENDIF} function StrPToStrB(const P: Pointer; const L: NativeInt): RawByteString; function StrPToStrU(const P: PWideChar; const L: NativeInt): UnicodeString; function StrPToStr(const P: PChar; const L: NativeInt): String; function StrZLenA(const S: Pointer): NativeInt; function StrZLenW(const S: PWideChar): NativeInt; function StrZLen(const S: PChar): NativeInt; {$IFDEF SupportAnsiString} function StrZPasA(const A: PAnsiChar): AnsiString; {$ENDIF} function StrZPasB(const A: PByteChar): RawByteString; function StrZPasU(const A: PWideChar): UnicodeString; function StrZPas(const A: PChar): String; { } { RawByteString conversion functions } { } procedure RawByteBufToWideBuf(const Buf: Pointer; const BufSize: NativeInt; const DestBuf: Pointer); function RawByteStrPtrToUnicodeString(const S: Pointer; const Len: NativeInt): UnicodeString; function RawByteStringToUnicodeString(const S: RawByteString): UnicodeString; procedure WideBufToRawByteBuf(const Buf: Pointer; const Len: NativeInt; const DestBuf: Pointer); function WideBufToRawByteString(const P: PWideChar; const Len: NativeInt): RawByteString; function UnicodeStringToRawByteString(const S: UnicodeString): RawByteString; { } { String conversion functions } { } {$IFDEF SupportAnsiString} function ToAnsiString(const A: String): AnsiString; {$IFDEF UseInline}inline;{$ENDIF} {$ENDIF} function ToRawByteString(const A: String): RawByteString; {$IFDEF UseInline}inline;{$ENDIF} function ToUnicodeString(const A: String): UnicodeString; {$IFDEF UseInline}inline;{$ENDIF} { } { String internals } { } {$IFNDEF SupportStringRefCount} {$IFDEF DELPHI} function StringRefCount(const S: RawByteString): Integer; overload; {$IFDEF UseInline}inline;{$ENDIF} function StringRefCount(const S: UnicodeString): Integer; overload; {$IFDEF UseInline}inline;{$ENDIF} {$DEFINE ImplementsStringRefCount} {$ENDIF} {$ENDIF} { } { String append functions } { } {$IFDEF SupportAnsiString} procedure StrAppendChA(var A: AnsiString; const C: AnsiChar); {$IFDEF UseInline}inline;{$ENDIF} {$ENDIF} procedure StrAppendChB(var A: RawByteString; const C: ByteChar); {$IFDEF UseInline}inline;{$ENDIF} procedure StrAppendChU(var A: UnicodeString; const C: WideChar); {$IFDEF UseInline}inline;{$ENDIF} procedure StrAppendCh(var A: String; const C: Char); {$IFDEF UseInline}inline;{$ENDIF} { } { ByteCharSet functions } { } function WideCharInCharSet(const A: WideChar; const C: ByteCharSet): Boolean; {$IFDEF UseInline}inline;{$ENDIF} function CharInCharSet(const A: Char; const C: ByteCharSet): Boolean; {$IFDEF UseInline}inline;{$ENDIF} { } { String compare functions } { } { Returns -1 if A < B } { 0 if A = B } { 1 if A > B } { } function CharCompareB(const A, B: ByteChar): Integer; {$IFDEF UseInline}inline;{$ENDIF} function CharCompareW(const A, B: WideChar): Integer; {$IFDEF UseInline}inline;{$ENDIF} function CharCompare(const A, B: Char): Integer; {$IFDEF UseInline}inline;{$ENDIF} function StrPCompareB(const A, B: Pointer; const Len: NativeInt): Integer; function StrPCompareW(const A, B: PWideChar; const Len: NativeInt): Integer; function StrPCompare(const A, B: PChar; const Len: NativeInt): Integer; {$IFDEF SupportAnsiString} function StrCompareA(const A, B: AnsiString): Integer; {$ENDIF} function StrCompareB(const A, B: RawByteString): Integer; function StrCompareU(const A, B: UnicodeString): Integer; function StrCompare(const A, B: String): Integer; { } { Swap } { } procedure Swap(var X, Y: Boolean); overload; procedure Swap(var X, Y: Byte); overload; procedure Swap(var X, Y: Word); overload; procedure Swap(var X, Y: Word32); overload; procedure Swap(var X, Y: ShortInt); overload; procedure Swap(var X, Y: SmallInt); overload; procedure Swap(var X, Y: Int32); overload; procedure Swap(var X, Y: Int64); overload; {$IFDEF UseInline}inline;{$ENDIF} procedure SwapLW(var X, Y: LongWord); {$IFDEF UseInline}inline;{$ENDIF} procedure SwapLI(var X, Y: LongInt); {$IFDEF UseInline}inline;{$ENDIF} procedure SwapInt(var X, Y: Integer); {$IFDEF UseInline}inline;{$ENDIF} procedure SwapCrd(var X, Y: Cardinal); {$IFDEF UseInline}inline;{$ENDIF} procedure Swap(var X, Y: Single); overload; {$IFDEF UseInline}inline;{$ENDIF} procedure Swap(var X, Y: Double); overload; {$IFDEF UseInline}inline;{$ENDIF} procedure SwapExt(var X, Y: Extended); {$IFDEF UseInline}inline;{$ENDIF} procedure Swap(var X, Y: Currency); overload; {$IFDEF UseInline}inline;{$ENDIF} {$IFDEF SupportAnsiString} procedure SwapA(var X, Y: AnsiString); {$IFDEF UseInline}inline;{$ENDIF} {$ENDIF} procedure SwapB(var X, Y: RawByteString); {$IFDEF UseInline}inline;{$ENDIF} procedure SwapU(var X, Y: UnicodeString); {$IFDEF UseInline}inline;{$ENDIF} procedure Swap(var X, Y: String); overload; {$IFDEF UseInline}inline;{$ENDIF} procedure Swap(var X, Y: TObject); overload; procedure SwapObjects(var X, Y); procedure Swap(var X, Y: Pointer); overload; { } { Inline if } { } { iif returns TrueValue if Expr is True, otherwise it returns FalseValue. } { } function iif(const Expr: Boolean; const TrueValue: Integer; const FalseValue: Integer = 0): Integer; overload; {$IFDEF UseInline}inline;{$ENDIF} function iif(const Expr: Boolean; const TrueValue: Int64; const FalseValue: Int64 = 0): Int64; overload; {$IFDEF UseInline}inline;{$ENDIF} function iif(const Expr: Boolean; const TrueValue: Extended; const FalseValue: Extended = 0.0): Extended; overload; {$IFDEF UseInline}inline;{$ENDIF} {$IFDEF SupportAnsiString} function iifA(const Expr: Boolean; const TrueValue: AnsiString; const FalseValue: AnsiString = ''): AnsiString; {$IFDEF UseInline}inline;{$ENDIF} {$ENDIF} function iifB(const Expr: Boolean; const TrueValue: RawByteString; const FalseValue: RawByteString = ''): RawByteString; {$IFDEF UseInline}inline;{$ENDIF} function iifU(const Expr: Boolean; const TrueValue: UnicodeString; const FalseValue: UnicodeString = ''): UnicodeString; {$IFDEF UseInline}inline;{$ENDIF} function iif(const Expr: Boolean; const TrueValue: String; const FalseValue: String = ''): String; overload; {$IFDEF UseInline}inline;{$ENDIF} function iif(const Expr: Boolean; const TrueValue: TObject; const FalseValue: TObject = nil): TObject; overload; {$IFDEF UseInline}inline;{$ENDIF} { } { Direct comparison } { } { Compare(I1, I2) returns crLess if I1 < I2, crEqual if I1 = I2 or } { crGreater if I1 > I2. } { } function Compare(const I1, I2: Boolean): TCompareResult; overload; function Compare(const I1, I2: Integer): TCompareResult; overload; function Compare(const I1, I2: Int64): TCompareResult; overload; function Compare(const I1, I2: Extended): TCompareResult; overload; {$IFDEF SupportAnsiString} function CompareA(const I1, I2: AnsiString): TCompareResult; {$ENDIF} function CompareB(const I1, I2: RawByteString): TCompareResult; function CompareU(const I1, I2: UnicodeString): TCompareResult; function CompareChB(const I1, I2: ByteChar): TCompareResult; function CompareChW(const I1, I2: WideChar): TCompareResult; function Sgn(const A: Int64): Integer; overload; function Sgn(const A: Extended): Integer; overload; { } { Convert result } { } type TConvertResult = ( convertOK, convertFormatError, convertOverflow ); { } { Integer-String conversions } { } const StrHexDigitsUpper : String = '0123456789ABCDEF'; StrHexDigitsLower : String = '0123456789abcdef'; function ByteCharDigitToInt(const A: ByteChar): Integer; {$IFDEF UseInline}inline;{$ENDIF} function WideCharDigitToInt(const A: WideChar): Integer; {$IFDEF UseInline}inline;{$ENDIF} function CharDigitToInt(const A: Char): Integer; {$IFDEF UseInline}inline;{$ENDIF} function IntToByteCharDigit(const A: Integer): ByteChar; {$IFDEF UseInline}inline;{$ENDIF} function IntToWideCharDigit(const A: Integer): WideChar; {$IFDEF UseInline}inline;{$ENDIF} function IntToCharDigit(const A: Integer): Char; {$IFDEF UseInline}inline;{$ENDIF} function IsHexByteCharDigit(const Ch: ByteChar): Boolean; function IsHexWideCharDigit(const Ch: WideChar): Boolean; function IsHexCharDigit(const Ch: Char): Boolean; {$IFDEF UseInline}inline;{$ENDIF} function HexByteCharDigitToInt(const A: ByteChar): Integer; function HexWideCharDigitToInt(const A: WideChar): Integer; function HexCharDigitToInt(const A: Char): Integer; {$IFDEF UseInline}inline;{$ENDIF} function IntToUpperHexByteCharDigit(const A: Integer): ByteChar; function IntToUpperHexWideCharDigit(const A: Integer): WideChar; function IntToUpperHexCharDigit(const A: Integer): Char; {$IFDEF UseInline}inline;{$ENDIF} function IntToLowerHexByteCharDigit(const A: Integer): ByteChar; function IntToLowerHexWideCharDigit(const A: Integer): WideChar; function IntToLowerHexCharDigit(const A: Integer): Char; {$IFDEF UseInline}inline;{$ENDIF} {$IFDEF SupportAnsiString} function IntToStringA(const A: Int64): AnsiString; {$ENDIF} function IntToStringB(const A: Int64): RawByteString; function IntToStringU(const A: Int64): UnicodeString; function IntToString(const A: Int64): String; {$IFDEF SupportAnsiString} function UIntToStringA(const A: UInt64): AnsiString; {$ENDIF} function UIntToStringB(const A: UInt64): RawByteString; function UIntToStringU(const A: UInt64): UnicodeString; function UIntToString(const A: UInt64): String; {$IFDEF SupportAnsiString} function Word32ToStrA(const A: Word32; const Digits: Integer = 0): AnsiString; {$ENDIF} function Word32ToStrB(const A: Word32; const Digits: Integer = 0): RawByteString; function Word32ToStrU(const A: Word32; const Digits: Integer = 0): UnicodeString; function Word32ToStr(const A: Word32; const Digits: Integer = 0): String; {$IFDEF SupportAnsiString} function Word32ToHexA(const A: Word32; const Digits: Integer = 0; const UpperCase: Boolean = True): AnsiString; {$ENDIF} function Word32ToHexB(const A: Word32; const Digits: Integer = 0; const UpperCase: Boolean = True): RawByteString; function Word32ToHexU(const A: Word32; const Digits: Integer = 0; const UpperCase: Boolean = True): UnicodeString; function Word32ToHex(const A: Word32; const Digits: Integer = 0; const UpperCase: Boolean = True): String; {$IFDEF SupportAnsiString} function Word32ToOctA(const A: Word32; const Digits: Integer = 0): AnsiString; {$ENDIF} function Word32ToOctB(const A: Word32; const Digits: Integer = 0): RawByteString; function Word32ToOctU(const A: Word32; const Digits: Integer = 0): UnicodeString; function Word32ToOct(const A: Word32; const Digits: Integer = 0): String; {$IFDEF SupportAnsiString} function Word32ToBinA(const A: Word32; const Digits: Integer = 0): AnsiString; {$ENDIF} function Word32ToBinB(const A: Word32; const Digits: Integer = 0): RawByteString; function Word32ToBinU(const A: Word32; const Digits: Integer = 0): UnicodeString; function Word32ToBin(const A: Word32; const Digits: Integer = 0): String; function TryStringToInt64PB(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; function TryStringToInt64PW(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; function TryStringToInt64P(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; {$IFDEF SupportAnsiString} function TryStringToInt64A(const S: AnsiString; out A: Int64): Boolean; {$ENDIF} function TryStringToInt64B(const S: RawByteString; out A: Int64): Boolean; function TryStringToInt64U(const S: UnicodeString; out A: Int64): Boolean; function TryStringToInt64(const S: String; out A: Int64): Boolean; {$IFDEF SupportAnsiString} function TryStringToUInt64A(const S: AnsiString; out A: UInt64): Boolean; {$ENDIF} function TryStringToUInt64B(const S: RawByteString; out A: UInt64): Boolean; function TryStringToUInt64U(const S: UnicodeString; out A: UInt64): Boolean; function TryStringToUInt64(const S: String; out A: UInt64): Boolean; {$IFDEF SupportAnsiString} function StringToInt64DefA(const S: AnsiString; const Default: Int64): Int64; {$ENDIF} function StringToInt64DefB(const S: RawByteString; const Default: Int64): Int64; function StringToInt64DefU(const S: UnicodeString; const Default: Int64): Int64; function StringToInt64Def(const S: String; const Default: Int64): Int64; {$IFDEF SupportAnsiString} function StringToUInt64DefA(const S: AnsiString; const Default: UInt64): UInt64; {$ENDIF} function StringToUInt64DefB(const S: RawByteString; const Default: UInt64): UInt64; function StringToUInt64DefU(const S: UnicodeString; const Default: UInt64): UInt64; function StringToUInt64Def(const S: String; const Default: UInt64): UInt64; {$IFDEF SupportAnsiString} function StringToInt64A(const S: AnsiString): Int64; {$ENDIF} function StringToInt64B(const S: RawByteString): Int64; function StringToInt64U(const S: UnicodeString): Int64; function StringToInt64(const S: String): Int64; {$IFDEF SupportAnsiString} function StringToUInt64A(const S: AnsiString): UInt64; {$ENDIF} function StringToUInt64B(const S: RawByteString): UInt64; function StringToUInt64U(const S: UnicodeString): UInt64; function StringToUInt64(const S: String): UInt64; {$IFDEF SupportAnsiString} function TryStringToIntA(const S: AnsiString; out A: Integer): Boolean; {$ENDIF} function TryStringToIntB(const S: RawByteString; out A: Integer): Boolean; function TryStringToIntU(const S: UnicodeString; out A: Integer): Boolean; function TryStringToInt(const S: String; out A: Integer): Boolean; {$IFDEF SupportAnsiString} function StringToIntDefA(const S: AnsiString; const Default: Integer): Integer; {$ENDIF} function StringToIntDefB(const S: RawByteString; const Default: Integer): Integer; function StringToIntDefU(const S: UnicodeString; const Default: Integer): Integer; function StringToIntDef(const S: String; const Default: Integer): Integer; {$IFDEF SupportAnsiString} function StringToIntA(const S: AnsiString): Integer; {$ENDIF} function StringToIntB(const S: RawByteString): Integer; function StringToIntU(const S: UnicodeString): Integer; function StringToInt(const S: String): Integer; {$IFDEF SupportAnsiString} function TryStringToWord32A(const S: AnsiString; out A: Word32): Boolean; {$ENDIF} function TryStringToWord32B(const S: RawByteString; out A: Word32): Boolean; function TryStringToWord32U(const S: UnicodeString; out A: Word32): Boolean; function TryStringToWord32(const S: String; out A: Word32): Boolean; {$IFDEF SupportAnsiString} function StringToWord32A(const S: AnsiString): Word32; {$ENDIF} function StringToWord32B(const S: RawByteString): Word32; function StringToWord32U(const S: UnicodeString): Word32; function StringToWord32(const S: String): Word32; {$IFDEF SupportAnsiString} function HexToUIntA(const S: AnsiString): UInt64; {$ENDIF} function HexToUIntB(const S: RawByteString): UInt64; function HexToUIntU(const S: UnicodeString): UInt64; function HexToUInt(const S: String): UInt64; {$IFDEF SupportAnsiString} function TryHexToWord32A(const S: AnsiString; out A: Word32): Boolean; {$ENDIF} function TryHexToWord32B(const S: RawByteString; out A: Word32): Boolean; function TryHexToWord32U(const S: UnicodeString; out A: Word32): Boolean; function TryHexToWord32(const S: String; out A: Word32): Boolean; {$IFDEF SupportAnsiString} function HexToWord32A(const S: AnsiString): Word32; {$ENDIF} function HexToWord32B(const S: RawByteString): Word32; function HexToWord32U(const S: UnicodeString): Word32; function HexToWord32(const S: String): Word32; {$IFDEF SupportAnsiString} function TryOctToWord32A(const S: AnsiString; out A: Word32): Boolean; {$ENDIF} function TryOctToWord32B(const S: RawByteString; out A: Word32): Boolean; function TryOctToWord32U(const S: UnicodeString; out A: Word32): Boolean; function TryOctToWord32(const S: String; out A: Word32): Boolean; {$IFDEF SupportAnsiString} function OctToWord32A(const S: AnsiString): Word32; {$ENDIF} function OctToWord32B(const S: RawByteString): Word32; function OctToWord32U(const S: UnicodeString): Word32; function OctToWord32(const S: String): Word32; {$IFDEF SupportAnsiString} function TryBinToWord32A(const S: AnsiString; out A: Word32): Boolean; {$ENDIF} function TryBinToWord32B(const S: RawByteString; out A: Word32): Boolean; function TryBinToWord32U(const S: UnicodeString; out A: Word32): Boolean; function TryBinToWord32(const S: String; out A: Word32): Boolean; {$IFDEF SupportAnsiString} function BinToWord32A(const S: AnsiString): Word32; {$ENDIF} function BinToWord32B(const S: RawByteString): Word32; function BinToWord32U(const S: UnicodeString): Word32; function BinToWord32(const S: String): Word32; {$IFDEF SupportAnsiString} function BytesToHexA(const P: Pointer; const Count: NativeInt; const UpperCase: Boolean = True): AnsiString; {$ENDIF} { } { Network byte order } { } function hton16(const A: Word): Word; function ntoh16(const A: Word): Word; function hton32(const A: Word32): Word32; function ntoh32(const A: Word32): Word32; function hton64(const A: Int64): Int64; function ntoh64(const A: Int64): Int64; { } { Pointer-String conversions } { } {$IFDEF SupportAnsiString} function PointerToStrA(const P: Pointer): AnsiString; {$ENDIF} function PointerToStrB(const P: Pointer): RawByteString; function PointerToStrU(const P: Pointer): UnicodeString; function PointerToStr(const P: Pointer): String; {$IFDEF SupportAnsiString} function StrToPointerA(const S: AnsiString): Pointer; {$ENDIF} function StrToPointerB(const S: RawByteString): Pointer; function StrToPointerU(const S: UnicodeString): Pointer; function StrToPointer(const S: String): Pointer; {$IFDEF SupportInterface} {$IFDEF SupportAnsiString} function InterfaceToStrA(const I: IInterface): AnsiString; {$ENDIF} function InterfaceToStrB(const I: IInterface): RawByteString; function InterfaceToStrU(const I: IInterface): UnicodeString; function InterfaceToStr(const I: IInterface): String; {$ENDIF} function ObjectClassName(const O: TObject): String; function ClassClassName(const C: TClass): String; function ObjectToStr(const O: TObject): String; { } { Hashing functions } { } { HashBuf uses a every byte in the buffer to calculate a hash. } { } { HashStr is a general purpose string hashing function. } { } { If Slots = 0 the hash value is in the Word32 range (0-$FFFFFFFF), } { otherwise the value is in the range from 0 to Slots-1. Note that the } { 'mod' operation, which is used when Slots <> 0, is comparitively slow. } { } function HashBuf(const Hash: Word32; const Buf; const BufSize: NativeInt): Word32; {$IFDEF SupportAnsiString} function HashStrA(const S: AnsiString; const Index: NativeInt = 1; const Count: NativeInt = -1; const AsciiCaseSensitive: Boolean = True; const Slots: Word32 = 0): Word32; {$ENDIF} function HashStrB(const S: RawByteString; const Index: NativeInt = 1; const Count: NativeInt = -1; const AsciiCaseSensitive: Boolean = True; const Slots: Word32 = 0): Word32; function HashStrU(const S: UnicodeString; const Index: NativeInt = 1; const Count: NativeInt = -1; const AsciiCaseSensitive: Boolean = True; const Slots: Word32 = 0): Word32; function HashStr(const S: String; const Index: NativeInt = 1; const Count: NativeInt = -1; const AsciiCaseSensitive: Boolean = True; const Slots: Word32 = 0): Word32; function HashInteger(const I: Integer; const Slots: Word32 = 0): Word32; function HashNativeUInt(const I: NativeUInt; const Slots: Word32): Word32; function HashWord32(const I: Word32; const Slots: Word32 = 0): Word32; { } { Memory operations } { } const Bytes1KB = 1024; Bytes1MB = 1024 * Bytes1KB; Bytes1GB = 1024 * Bytes1MB; Bytes64KB = 64 * Bytes1KB; Bytes64MB = 64 * Bytes1MB; Bytes2GB = 2 * Word32(Bytes1GB); procedure FillMem(var Buf; const Count: NativeInt; const Value: Byte); {$IFDEF UseInline}inline;{$ENDIF} procedure ZeroMem(var Buf; const Count: NativeInt); {$IFDEF UseInline}inline;{$ENDIF} procedure GetZeroMem(var P: Pointer; const Size: NativeInt); {$IFDEF UseInline}inline;{$ENDIF} procedure MoveMem(const Source; var Dest; const Count: NativeInt); {$IFDEF UseInline}inline;{$ENDIF} function EqualMem(const Buf1; const Buf2; const Count: NativeInt): Boolean; function EqualMemNoAsciiCase(const Buf1; const Buf2; const Count: NativeInt): Boolean; function CompareMem(const Buf1; const Buf2; const Count: NativeInt): Integer; function CompareMemNoAsciiCase(const Buf1; const Buf2; const Count: NativeInt): Integer; function LocateMem(const Buf1; const Size1: NativeInt; const Buf2; const Size2: NativeInt): NativeInt; function LocateMemNoAsciiCase(const Buf1; const Size1: NativeInt; const Buf2; const Size2: NativeInt): NativeInt; procedure ReverseMem(var Buf; const Size: NativeInt); { } { IInterface } { } {$IFDEF DELPHI5_DOWN} type IInterface = interface ['{00000000-0000-0000-C000-000000000046}'] function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; {$ENDIF} { } { Dynamic arrays } { } procedure FreeObjectArray(var V); overload; procedure FreeObjectArray(var V; const LoIdx, HiIdx: Integer); overload; procedure FreeAndNilObjectArray(var V: ObjectArray); { } { TBytes functions } { } procedure BytesSetLengthAndZero(var V: TBytes; const NewLength: NativeInt); procedure BytesInit(var V: TBytes; const R: Byte); overload; procedure BytesInit(var V: TBytes; const S: String); overload; function BytesAppend(var V: TBytes; const R: Byte): NativeInt; overload; function BytesAppend(var V: TBytes; const R: TBytes): NativeInt; overload; function BytesAppend(var V: TBytes; const R: array of Byte): NativeInt; overload; function BytesAppend(var V: TBytes; const R: String): NativeInt; overload; function BytesCompare(const A, B: TBytes): Integer; function BytesEqual(const A, B: TBytes): Boolean; { } { Test cases } { } {$IFDEF UTILS_TEST} procedure Test; {$ENDIF} implementation uses { System } Math; { } { CPU identification } { } {$IFDEF ASM386_DELPHI} var CPUIDInitialised : Boolean = False; CPUIDSupport : Boolean = False; MMXSupport : Boolean = False; procedure InitialiseCPUID; assembler; asm // Set CPUID flag PUSHFD POP EAX OR EAX, $200000 PUSH EAX POPFD // Check if CPUID flag is still set PUSHFD POP EAX AND EAX, $200000 JNZ @CPUIDSupported // CPUID not supported MOV BYTE PTR [CPUIDSupport], 0 MOV BYTE PTR [MMXSupport], 0 JMP @CPUIDFin // CPUID supported @CPUIDSupported: MOV BYTE PTR [CPUIDSupport], 1 PUSH EBX // Perform CPUID function 1 MOV EAX, 1 {$IFDEF DELPHI5_DOWN} DW 0FA2h {$ELSE} CPUID {$ENDIF} // Check if MMX feature flag is set AND EDX, $800000 SETNZ AL MOV BYTE PTR [MMXSupport], AL POP EBX @CPUIDFin: MOV BYTE PTR [CPUIDInitialised], 1 end; {$ENDIF} { } { Range check error } { } constructor ERangeCheckError.Create; begin inherited Create('Range check error'); end; { } { Integer } { } function MinInt(const A, B: Integer): Integer; begin if A < B then Result := A else Result := B; end; function MaxInt(const A, B: Integer): Integer; begin if A > B then Result := A else Result := B; end; function MinCrd(const A, B: Cardinal): Cardinal; begin if A < B then Result := A else Result := B; end; function MaxCrd(const A, B: Cardinal): Cardinal; begin if A > B then Result := A else Result := B; end; function Int32Bounded(const Value: Int32; const Min, Max: Int32): Int32; begin if Value < Min then Result := Min else if Value > Max then Result := Max else Result := Value; end; function Int64Bounded(const Value: Int64; const Min, Max: Int64): Int64; begin if Value < Min then Result := Min else if Value > Max then Result := Max else Result := Value; end; function Int32BoundedByte(const Value: Int32): Int32; begin if Value < MinByte then Result := MinByte else if Value > MaxByte then Result := MaxByte else Result := Value; end; function Int64BoundedByte(const Value: Int64): Int64; begin if Value < MinByte then Result := MinByte else if Value > MaxByte then Result := MaxByte else Result := Value; end; function Int32BoundedWord(const Value: Int32): Int32; begin if Value < MinWord then Result := MinWord else if Value > MaxWord then Result := MaxWord else Result := Value; end; function Int64BoundedWord(const Value: Int64): Int64; begin if Value < MinWord then Result := MinWord else if Value > MaxWord then Result := MaxWord else Result := Value; end; function Int64BoundedWord32(const Value: Int64): Word32; begin if Value < MinWord32 then Result := MinWord32 else if Value > MaxWord32 then Result := MaxWord32 else Result := Word32(Value); end; { } { String construction from buffer } { } {$IFDEF SupportAnsiString} function StrPToStrA(const P: PAnsiChar; const L: NativeInt): AnsiString; begin if L <= 0 then SetLength(Result, 0) else begin SetLength(Result, L); MoveMem(P^, Pointer(Result)^, L); end; end; {$ENDIF} function StrPToStrB(const P: Pointer; const L: NativeInt): RawByteString; begin if L <= 0 then SetLength(Result, 0) else begin SetLength(Result, L); MoveMem(P^, Pointer(Result)^, L); end; end; function StrPToStrU(const P: PWideChar; const L: NativeInt): UnicodeString; begin if L <= 0 then SetLength(Result, 0) else begin SetLength(Result, L); MoveMem(P^, Pointer(Result)^, L * SizeOf(WideChar)); end; end; function StrPToStr(const P: PChar; const L: NativeInt): String; begin if L <= 0 then SetLength(Result, 0) else begin SetLength(Result, L); MoveMem(P^, Pointer(Result)^, L * SizeOf(Char)); end; end; { } { String construction from zero terminated buffer } { } function StrZLenA(const S: Pointer): NativeInt; var P : PByteChar; begin if not Assigned(S) then Result := 0 else begin Result := 0; P := S; while Ord(P^) <> 0 do begin Inc(Result); Inc(P); end; end; end; function StrZLenW(const S: PWideChar): NativeInt; var P : PWideChar; begin if not Assigned(S) then Result := 0 else begin Result := 0; P := S; while P^ <> #0 do begin Inc(Result); Inc(P); end; end; end; function StrZLen(const S: PChar): NativeInt; var P : PChar; begin if not Assigned(S) then Result := 0 else begin Result := 0; P := S; while P^ <> #0 do begin Inc(Result); Inc(P); end; end; end; {$IFDEF SupportAnsiString} function StrZPasA(const A: PAnsiChar): AnsiString; var I, L : NativeInt; P : PAnsiChar; begin L := StrZLenA(A); SetLength(Result, L); if L = 0 then exit; I := 0; P := A; while I < L do begin Result[I + 1] := P^; Inc(I); Inc(P); end; end; {$ENDIF} function StrZPasB(const A: PByteChar): RawByteString; var I, L : NativeInt; P : PByteChar; begin L := StrZLenA(A); SetLength(Result, L); if L = 0 then exit; I := 0; P := A; while I < L do begin Result[I + 1] := P^; Inc(I); Inc(P); end; end; function StrZPasU(const A: PWideChar): UnicodeString; var I, L : NativeInt; begin L := StrZLenW(A); SetLength(Result, L); if L = 0 then exit; I := 0; while I < L do begin Result[I + 1] := A[I]; Inc(I); end; end; function StrZPas(const A: PChar): String; var I, L : NativeInt; begin L := StrZLen(A); SetLength(Result, L); if L = 0 then exit; I := 0; while I < L do begin Result[I + 1] := A[I]; Inc(I); end; end; { } { RawByteString conversion functions } { } const SRawByteStringConvertError = 'RawByteString conversion error'; procedure RawByteBufToWideBuf( const Buf: Pointer; const BufSize: NativeInt; const DestBuf: Pointer); var I : NativeInt; P : Pointer; Q : Pointer; V : Word32; begin if BufSize <= 0 then exit; P := Buf; Q := DestBuf; for I := 1 to BufSize div 4 do begin // convert 4 characters per iteration V := PWord32(P)^; Inc(PWord32(P)); PWord32(Q)^ := (V and $FF) or ((V and $FF00) shl 8); Inc(PWord32(Q)); V := V shr 16; PWord32(Q)^ := (V and $FF) or ((V and $FF00) shl 8); Inc(PWord32(Q)); end; // convert remaining (<4) for I := 1 to BufSize mod 4 do begin PWord(Q)^ := PByte(P)^; Inc(PByte(P)); Inc(PWord(Q)); end; end; function RawByteStrPtrToUnicodeString(const S: Pointer; const Len: NativeInt): UnicodeString; begin if Len <= 0 then Result := '' else begin SetLength(Result, Len); RawByteBufToWideBuf(S, Len, PWideChar(Result)); end; end; function RawByteStringToUnicodeString(const S: RawByteString): UnicodeString; var L : Integer; begin L := Length(S); SetLength(Result, L); if L > 0 then RawByteBufToWideBuf(Pointer(S), L, PWideChar(Result)); end; procedure WideBufToRawByteBuf( const Buf: Pointer; const Len: NativeInt; const DestBuf: Pointer); var I : NativeInt; S : PWideChar; Q : PByte; V : Word32; W : Word; begin if Len <= 0 then exit; S := Buf; Q := DestBuf; for I := 1 to Len div 2 do begin // convert 2 characters per iteration V := PWord32(S)^; if V and $FF00FF00 <> 0 then raise EConvertError.Create(SRawByteStringConvertError); Q^ := Byte(V); Inc(Q); Q^ := Byte(V shr 16); Inc(Q); Inc(S, 2); end; // convert remaining character if Len mod 2 = 1 then begin W := Ord(S^); if W > $FF then raise EConvertError.Create(SRawByteStringConvertError); Q^ := Byte(W); end; end; function WideBufToRawByteString(const P: PWideChar; const Len: NativeInt): RawByteString; var I : NativeInt; S : PWideChar; Q : PByte; V : WideChar; begin if Len <= 0 then begin Result := ''; exit; end; SetLength(Result, Len); S := P; Q := Pointer(Result); for I := 1 to Len do begin V := S^; if Ord(V) > $FF then raise EConvertError.Create(SRawByteStringConvertError); Q^ := Byte(V); Inc(S); Inc(Q); end; end; function UnicodeStringToRawByteString(const S: UnicodeString): RawByteString; begin Result := WideBufToRawByteString(PWideChar(S), Length(S)); end; { } { String conversion functions } { } {$IFDEF SupportAnsiString} function ToAnsiString(const A: String): AnsiString; begin {$IFDEF StringIsUnicode} Result := AnsiString(A); {$ELSE} Result := A; {$ENDIF} end; {$ENDIF} function ToRawByteString(const A: String): RawByteString; begin {$IFDEF StringIsUnicode} Result := RawByteString(A); {$ELSE} Result := A; {$ENDIF} end; function ToUnicodeString(const A: String): UnicodeString; begin Result := UnicodeString(A); end; { } { String internals functions } { } {$IFNDEF SupportStringRefCount} {$IFDEF DELPHI} function StringRefCount(const S: UnicodeString): Integer; var P : PInt32; begin P := Pointer(S); if not Assigned(P) then Result := 0 else begin Dec(P, 2); Result := P^; end; end; function StringRefCount(const S: RawByteString): Integer; var P : PInt32; begin P := Pointer(S); if not Assigned(P) then Result := 0 else begin Dec(P, 2); Result := P^; end; end; {$ENDIF} {$ENDIF} { } { String append functions } { } {$IFDEF SupportAnsiString} procedure StrAppendChA(var A: AnsiString; const C: AnsiChar); begin A := A + C; end; {$ENDIF} procedure StrAppendChB(var A: RawByteString; const C: ByteChar); begin A := A + C; end; procedure StrAppendChU(var A: UnicodeString; const C: WideChar); begin A := A + C; end; procedure StrAppendCh(var A: String; const C: Char); begin A := A + C; end; { } { ByteCharSet functions } { } function WideCharInCharSet(const A: WideChar; const C: ByteCharSet): Boolean; begin if Ord(A) >= $100 then Result := False else Result := ByteChar(Ord(A)) in C; end; function CharInCharSet(const A: Char; const C: ByteCharSet): Boolean; begin {$IFDEF CharIsWide} if Ord(A) >= $100 then Result := False else Result := ByteChar(Ord(A)) in C; {$ELSE} Result := A in C; {$ENDIF} end; { } { Compare } { } function CharCompareB(const A, B: ByteChar): Integer; begin if Ord(A) < Ord(B) then Result := -1 else if Ord(A) > Ord(B) then Result := 1 else Result := 0; end; function CharCompareW(const A, B: WideChar): Integer; begin if Ord(A) < Ord(B) then Result := -1 else if Ord(A) > Ord(B) then Result := 1 else Result := 0; end; function CharCompare(const A, B: Char): Integer; begin {$IFDEF CharIsWide} Result := CharCompareW(A, B); {$ELSE} Result := CharCompareB(A, B); {$ENDIF} end; function StrPCompareB(const A, B: Pointer; const Len: NativeInt): Integer; var P, Q : PByte; I : NativeInt; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if P^ = Q^ then begin Inc(P); Inc(Q); end else begin if Ord(P^) < Ord(Q^) then Result := -1 else Result := 1; exit; end; Result := 0; end; function StrPCompareW(const A, B: PWideChar; const Len: NativeInt): Integer; var P, Q : PWideChar; I : NativeInt; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin if Ord(P^) < Ord(Q^) then Result := -1 else Result := 1; exit; end; Result := 0; end; function StrPCompare(const A, B: PChar; const Len: NativeInt): Integer; var P, Q : PChar; I : NativeInt; begin P := A; Q := B; if P <> Q then for I := 1 to Len do if Ord(P^) = Ord(Q^) then begin Inc(P); Inc(Q); end else begin if Ord(P^) < Ord(Q^) then Result := -1 else Result := 1; exit; end; Result := 0; end; {$IFDEF SupportAnsiString} function StrCompareA(const A, B: AnsiString): Integer; var L, M, I : NativeInt; begin L := Length(A); M := Length(B); if L < M then I := L else I := M; Result := StrPCompareB(Pointer(A), Pointer(B), I); if Result <> 0 then exit; if L = M then Result := 0 else if L < M then Result := -1 else Result := 1; end; {$ENDIF} function StrCompareB(const A, B: RawByteString): Integer; var L, M, I : NativeInt; begin L := Length(A); M := Length(B); if L < M then I := L else I := M; Result := StrPCompareB(Pointer(A), Pointer(B), I); if Result <> 0 then exit; if L = M then Result := 0 else if L < M then Result := -1 else Result := 1; end; function StrCompareU(const A, B: UnicodeString): Integer; var L, M, I : NativeInt; begin L := Length(A); M := Length(B); if L < M then I := L else I := M; Result := StrPCompareW(Pointer(A), Pointer(B), I); if Result <> 0 then exit; if L = M then Result := 0 else if L < M then Result := -1 else Result := 1; end; function StrCompare(const A, B: String): Integer; var L, M, I : NativeInt; begin L := Length(A); M := Length(B); if L < M then I := L else I := M; Result := StrPCompare(Pointer(A), Pointer(B), I); if Result <> 0 then exit; if L = M then Result := 0 else if L < M then Result := -1 else Result := 1; end; { } { Swap } { } {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Boolean); register; assembler; asm MOV CL, [EDX] XCHG BYTE PTR [EAX], CL MOV [EDX], CL end; {$ELSE} procedure Swap(var X, Y: Boolean); var F : Boolean; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Byte); register; assembler; asm MOV CL, [EDX] XCHG BYTE PTR [EAX], CL MOV [EDX], CL end; {$ELSE} procedure Swap(var X, Y: Byte); var F : Byte; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: ShortInt); register; assembler; asm MOV CL, [EDX] XCHG BYTE PTR [EAX], CL MOV [EDX], CL end; {$ELSE} procedure Swap(var X, Y: ShortInt); var F : ShortInt; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Word); register; assembler; asm MOV CX, [EDX] XCHG WORD PTR [EAX], CX MOV [EDX], CX end; {$ELSE} procedure Swap(var X, Y: Word); var F : Word; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: SmallInt); register; assembler; asm MOV CX, [EDX] XCHG WORD PTR [EAX], CX MOV [EDX], CX end; {$ELSE} procedure Swap(var X, Y: SmallInt); var F : SmallInt; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Int32); register; assembler; asm MOV ECX, [EDX] XCHG [EAX], ECX MOV [EDX], ECX end; {$ELSE} procedure Swap(var X, Y: Int32); var F : Int32; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Word32); register; assembler; asm MOV ECX, [EDX] XCHG [EAX], ECX MOV [EDX], ECX end; {$ELSE} procedure Swap(var X, Y: Word32); var F : Word32; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: Pointer); register; assembler; asm MOV ECX, [EDX] XCHG [EAX], ECX MOV [EDX], ECX end; {$ELSE} procedure Swap(var X, Y: Pointer); var F : Pointer; begin F := X; X := Y; Y := F; end; {$ENDIF} {$IFDEF ASM386_DELPHI} procedure Swap(var X, Y: TObject); register; assembler; asm MOV ECX, [EDX] XCHG [EAX], ECX MOV [EDX], ECX end; {$ELSE} procedure Swap(var X, Y: TObject); var F : TObject; begin F := X; X := Y; Y := F; end; {$ENDIF} procedure Swap(var X, Y: Int64); var F : Int64; begin F := X; X := Y; Y := F; end; procedure SwapLW(var X, Y: LongWord); var F : LongWord; begin F := X; X := Y; Y := F; end; procedure SwapLI(var X, Y: LongInt); var F : LongInt; begin F := X; X := Y; Y := F; end; procedure SwapInt(var X, Y: Integer); var F : Integer; begin F := X; X := Y; Y := F; end; procedure SwapCrd(var X, Y: Cardinal); var F : Cardinal; begin F := X; X := Y; Y := F; end; procedure Swap(var X, Y: Single); var F : Single; begin F := X; X := Y; Y := F; end; procedure Swap(var X, Y: Double); var F : Double; begin F := X; X := Y; Y := F; end; procedure SwapExt(var X, Y: Extended); var F : Extended; begin F := X; X := Y; Y := F; end; procedure Swap(var X, Y: Currency); var F : Currency; begin F := X; X := Y; Y := F; end; {$IFDEF SupportAnsiString} procedure SwapA(var X, Y: AnsiString); var F : AnsiString; begin F := X; X := Y; Y := F; end; {$ENDIF} procedure SwapB(var X, Y: RawByteString); var F : RawByteString; begin F := X; X := Y; Y := F; end; procedure SwapU(var X, Y: UnicodeString); var F : UnicodeString; begin F := X; X := Y; Y := F; end; procedure Swap(var X, Y: String); var F : String; begin F := X; X := Y; Y := F; end; {$IFDEF ASM386_DELPHI} procedure SwapObjects(var X, Y); register; assembler; asm MOV ECX, [EDX] XCHG [EAX], ECX MOV [EDX], ECX end; {$ELSE} procedure SwapObjects(var X, Y); var F: TObject; begin F := TObject(X); TObject(X) := TObject(Y); TObject(Y) := F; end; {$ENDIF} { } { iif } { } function iif(const Expr: Boolean; const TrueValue, FalseValue: Integer): Integer; begin if Expr then Result := TrueValue else Result := FalseValue; end; function iif(const Expr: Boolean; const TrueValue, FalseValue: Int64): Int64; begin if Expr then Result := TrueValue else Result := FalseValue; end; function iif(const Expr: Boolean; const TrueValue, FalseValue: Extended): Extended; begin if Expr then Result := TrueValue else Result := FalseValue; end; function iif(const Expr: Boolean; const TrueValue, FalseValue: String): String; begin if Expr then Result := TrueValue else Result := FalseValue; end; {$IFDEF SupportAnsiString} function iifA(const Expr: Boolean; const TrueValue, FalseValue: AnsiString): AnsiString; begin if Expr then Result := TrueValue else Result := FalseValue; end; {$ENDIF} function iifB(const Expr: Boolean; const TrueValue, FalseValue: RawByteString): RawByteString; begin if Expr then Result := TrueValue else Result := FalseValue; end; function iifU(const Expr: Boolean; const TrueValue, FalseValue: UnicodeString): UnicodeString; begin if Expr then Result := TrueValue else Result := FalseValue; end; function iif(const Expr: Boolean; const TrueValue, FalseValue: TObject): TObject; begin if Expr then Result := TrueValue else Result := FalseValue; end; { } { Compare } { } function InverseCompareResult(const C: TCompareResult): TCompareResult; begin if C = crLess then Result := crGreater else if C = crGreater then Result := crLess else Result := C; end; function Compare(const I1, I2: Integer): TCompareResult; begin if I1 < I2 then Result := crLess else if I1 > I2 then Result := crGreater else Result := crEqual; end; function Compare(const I1, I2: Int64): TCompareResult; begin if I1 < I2 then Result := crLess else if I1 > I2 then Result := crGreater else Result := crEqual; end; function Compare(const I1, I2: Extended): TCompareResult; begin if I1 < I2 then Result := crLess else if I1 > I2 then Result := crGreater else Result := crEqual; end; function Compare(const I1, I2: Boolean): TCompareResult; begin if I1 = I2 then Result := crEqual else if I1 then Result := crGreater else Result := crLess; end; {$IFDEF SupportAnsiString} function CompareA(const I1, I2: AnsiString): TCompareResult; begin case StrCompareA(I1, I2) of -1 : Result := crLess; 1 : Result := crGreater; else Result := crEqual; end; end; {$ENDIF} function CompareB(const I1, I2: RawByteString): TCompareResult; begin case StrCompareB(I1, I2) of -1 : Result := crLess; 1 : Result := crGreater; else Result := crEqual; end; end; function CompareU(const I1, I2: UnicodeString): TCompareResult; begin if I1 = I2 then Result := crEqual else if I1 > I2 then Result := crGreater else Result := crLess; end; function CompareChB(const I1, I2: ByteChar): TCompareResult; begin if I1 = I2 then Result := crEqual else if I1 > I2 then Result := crGreater else Result := crLess; end; function CompareChW(const I1, I2: WideChar): TCompareResult; begin if I1 = I2 then Result := crEqual else if I1 > I2 then Result := crGreater else Result := crLess; end; function Sgn(const A: Int64): Integer; begin if A < 0 then Result := -1 else if A > 0 then Result := 1 else Result := 0; end; function Sgn(const A: Extended): Integer; begin if A < 0 then Result := -1 else if A > 0 then Result := 1 else Result := 0; end; { } { Ascii char conversion lookup } { } const AsciiHexLookup: array[Byte] of Byte = ( $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, $FF, $FF, $FF, $FF, $FF, $FF, $FF, 10, 11, 12, 13, 14, 15, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, 10, 11, 12, 13, 14, 15, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF); { } { Integer-String conversions } { } function ByteCharDigitToInt(const A: ByteChar): Integer; begin if A in [ByteChar(Ord('0'))..ByteChar(Ord('9'))] then Result := Ord(A) - Ord('0') else Result := -1; end; function WideCharDigitToInt(const A: WideChar): Integer; begin if (Ord(A) >= Ord('0')) and (Ord(A) <= Ord('9')) then Result := Ord(A) - Ord('0') else Result := -1; end; function CharDigitToInt(const A: Char): Integer; begin {$IFDEF CharIsWide} Result := WideCharDigitToInt(A); {$ELSE} Result := ByteCharToInt(A); {$ENDIF} end; function IntToByteCharDigit(const A: Integer): ByteChar; begin if (A < 0) or (A > 9) then Result := ByteChar($00) else Result := ByteChar(48 + A); end; function IntToWideCharDigit(const A: Integer): WideChar; begin if (A < 0) or (A > 9) then Result := WideChar($00) else Result := WideChar(48 + A); end; function IntToCharDigit(const A: Integer): Char; begin {$IFDEF CharIsWide} Result := IntToWideCharDigit(A); {$ELSE} Result := IntToByteChar(A); {$ENDIF} end; function IsHexByteCharDigit(const Ch: ByteChar): Boolean; begin Result := AsciiHexLookup[Ord(Ch)] <= 15; end; function IsHexWideCharDigit(const Ch: WideChar): Boolean; begin if Ord(Ch) <= $FF then Result := AsciiHexLookup[Ord(Ch)] <= 15 else Result := False; end; function IsHexCharDigit(const Ch: Char): Boolean; begin {$IFDEF CharIsWide} Result := IsHexWideCharDigit(Ch); {$ELSE} Result := IsHexByteChar(Ch); {$ENDIF} end; function HexByteCharDigitToInt(const A: ByteChar): Integer; var B : Byte; begin B := AsciiHexLookup[Ord(A)]; if B = $FF then Result := -1 else Result := B; end; function HexWideCharDigitToInt(const A: WideChar): Integer; var B : Byte; begin if Ord(A) > $FF then Result := -1 else begin B := AsciiHexLookup[Ord(A)]; if B = $FF then Result := -1 else Result := B; end; end; function HexCharDigitToInt(const A: Char): Integer; begin {$IFDEF CharIsWide} Result := HexWideCharDigitToInt(A); {$ELSE} Result := HexByteCharToInt(A); {$ENDIF} end; function IntToUpperHexByteCharDigit(const A: Integer): ByteChar; begin if (A < 0) or (A > 15) then Result := ByteChar($00) else if A <= 9 then Result := ByteChar(48 + A) else Result := ByteChar(55 + A); end; function IntToUpperHexWideCharDigit(const A: Integer): WideChar; begin if (A < 0) or (A > 15) then Result := #$00 else if A <= 9 then Result := WideChar(48 + A) else Result := WideChar(55 + A); end; function IntToUpperHexCharDigit(const A: Integer): Char; begin {$IFDEF CharIsWide} Result := IntToUpperHexWideCharDigit(A); {$ELSE} Result := IntToUpperHexByteChar(A); {$ENDIF} end; function IntToLowerHexByteCharDigit(const A: Integer): ByteChar; begin if (A < 0) or (A > 15) then Result := ByteChar($00) else if A <= 9 then Result := ByteChar(48 + A) else Result := ByteChar(87 + A); end; function IntToLowerHexWideCharDigit(const A: Integer): WideChar; begin if (A < 0) or (A > 15) then Result := #$00 else if A <= 9 then Result := WideChar(48 + A) else Result := WideChar(87 + A); end; function IntToLowerHexCharDigit(const A: Integer): Char; begin {$IFDEF CharIsWide} Result := IntToLowerHexWideCharDigit(A); {$ELSE} Result := IntToLowerHexByteChar(A); {$ENDIF} end; {$IFDEF SupportAnsiString} function IntToStringA(const A: Int64): AnsiString; var T : Int64; L : Integer; I : Integer; begin // special cases if A = 0 then begin Result := ToAnsiString('0'); exit; end; if A = MinInt64 then begin Result := ToAnsiString('-9223372036854775808'); exit; end; // calculate string length if A < 0 then L := 1 else L := 0; T := A; while T <> 0 do begin T := T div 10; Inc(L); end; // convert SetLength(Result, L); I := 0; T := A; if T < 0 then begin Result[1] := ByteChar(Ord('-')); T := -T; end; while T > 0 do begin Result[L - I] := IntToByteCharDigit(T mod 10); T := T div 10; Inc(I); end; end; {$ENDIF} function IntToStringB(const A: Int64): RawByteString; var T : Int64; L : Integer; I : Integer; begin // special cases if A = 0 then begin Result := ToRawByteString('0'); exit; end; if A = MinInt64 then begin Result := ToRawByteString('-9223372036854775808'); exit; end; // calculate string length if A < 0 then L := 1 else L := 0; T := A; while T <> 0 do begin T := T div 10; Inc(L); end; // convert SetLength(Result, L); I := 0; T := A; if T < 0 then begin Result[1] := '-'; T := -T; end; while T > 0 do begin Result[L - I] := UTF8Char(IntToByteCharDigit(T mod 10)); T := T div 10; Inc(I); end; end; function IntToStringU(const A: Int64): UnicodeString; var T : Int64; L : Integer; I : Integer; begin // special cases if A = 0 then begin Result := '0'; exit; end; if A = MinInt64 then begin Result := '-9223372036854775808'; exit; end; // calculate string length if A < 0 then L := 1 else L := 0; T := A; while T <> 0 do begin T := T div 10; Inc(L); end; // convert SetLength(Result, L); I := 0; T := A; if T < 0 then begin Result[1] := '-'; T := -T; end; while T > 0 do begin Result[L - I] := IntToWideCharDigit(T mod 10); T := T div 10; Inc(I); end; end; function IntToString(const A: Int64): String; var T : Int64; L : Integer; I : Integer; begin // special cases if A = 0 then begin Result := '0'; exit; end; if A = MinInt64 then begin Result := '-9223372036854775808'; exit; end; // calculate string length if A < 0 then L := 1 else L := 0; T := A; while T <> 0 do begin T := T div 10; Inc(L); end; // convert SetLength(Result, L); I := 0; T := A; if T < 0 then begin Result[1] := '-'; T := -T; end; while T > 0 do begin Result[L - I] := IntToCharDigit(T mod 10); T := T div 10; Inc(I); end; end; {$IFDEF SupportAnsiString} function UIntToBaseA( const Value: UInt64; const Digits: Integer; const Base: Byte; const UpperCase: Boolean = True): AnsiString; var D : UInt64; L : Integer; V : Byte; begin Assert((Base >= 2) and (Base <= 16)); if Value = 0 then // handle zero value begin if Digits = 0 then L := 1 else L := Digits; SetLength(Result, L); for V := 0 to L - 1 do Result[1 + V] := ByteChar(Ord('0')); exit; end; // determine number of digits in result L := 0; D := Value; while D > 0 do begin Inc(L); D := D div Base; end; if L < Digits then L := Digits; // do conversion SetLength(Result, L); D := Value; while D > 0 do begin V := D mod Base + 1; if UpperCase then Result[L] := ByteChar(StrHexDigitsUpper[V]) else Result[L] := ByteChar(StrHexDigitsLower[V]); Dec(L); D := D div Base; end; while L > 0 do begin Result[L] := ByteChar(Ord('0')); Dec(L); end; end; {$ENDIF} function UIntToBaseB( const Value: UInt64; const Digits: Integer; const Base: Byte; const UpperCase: Boolean = True): RawByteString; var D : UInt64; L : Integer; V : Byte; begin Assert((Base >= 2) and (Base <= 16)); if Value = 0 then // handle zero value begin if Digits = 0 then L := 1 else L := Digits; SetLength(Result, L); for V := 0 to L - 1 do Result[1 + V] := '0'; exit; end; // determine number of digits in result L := 0; D := Value; while D > 0 do begin Inc(L); D := D div Base; end; if L < Digits then L := Digits; // do conversion SetLength(Result, L); D := Value; while D > 0 do begin V := D mod Base + 1; if UpperCase then Result[L] := UTF8Char(StrHexDigitsUpper[V]) else Result[L] := UTF8Char(StrHexDigitsLower[V]); Dec(L); D := D div Base; end; while L > 0 do begin Result[L] := '0'; Dec(L); end; end; function UIntToBaseU( const Value: UInt64; const Digits: Integer; const Base: Byte; const UpperCase: Boolean = True): UnicodeString; var D : UInt64; L : Integer; V : Byte; begin Assert((Base >= 2) and (Base <= 16)); if Value = 0 then // handle zero value begin if Digits = 0 then L := 1 else L := Digits; SetLength(Result, L); for V := 1 to L do Result[V] := '0'; exit; end; // determine number of digits in result L := 0; D := Value; while D > 0 do begin Inc(L); D := D div Base; end; if L < Digits then L := Digits; // do conversion SetLength(Result, L); D := Value; while D > 0 do begin V := D mod Base + 1; if UpperCase then Result[L] := WideChar(StrHexDigitsUpper[V]) else Result[L] := WideChar(StrHexDigitsLower[V]); Dec(L); D := D div Base; end; while L > 0 do begin Result[L] := '0'; Dec(L); end; end; function UIntToBase( const Value: UInt64; const Digits: Integer; const Base: Byte; const UpperCase: Boolean = True): String; var D : UInt64; L : Integer; V : Byte; begin Assert((Base >= 2) and (Base <= 16)); if Value = 0 then // handle zero value begin if Digits = 0 then L := 1 else L := Digits; SetLength(Result, L); for V := 1 to L do Result[V] := '0'; exit; end; // determine number of digits in result L := 0; D := Value; while D > 0 do begin Inc(L); D := D div Base; end; if L < Digits then L := Digits; // do conversion SetLength(Result, L); D := Value; while D > 0 do begin V := D mod Base + 1; if UpperCase then Result[L] := Char(StrHexDigitsUpper[V]) else Result[L] := Char(StrHexDigitsLower[V]); Dec(L); D := D div Base; end; while L > 0 do begin Result[L] := '0'; Dec(L); end; end; {$IFDEF SupportAnsiString} function UIntToStringA(const A: UInt64): AnsiString; begin Result := UIntToBaseA(A, 0, 10); end; {$ENDIF} function UIntToStringB(const A: UInt64): RawByteString; begin Result := UIntToBaseB(A, 0, 10); end; function UIntToStringU(const A: UInt64): UnicodeString; begin Result := UIntToBaseU(A, 0, 10); end; function UIntToString(const A: UInt64): String; begin Result := UIntToBase(A, 0, 10); end; {$IFDEF SupportAnsiString} function Word32ToStrA(const A: Word32; const Digits: Integer): AnsiString; begin Result := UIntToBaseA(A, Digits, 10); end; {$ENDIF} function Word32ToStrB(const A: Word32; const Digits: Integer): RawByteString; begin Result := UIntToBaseB(A, Digits, 10); end; function Word32ToStrU(const A: Word32; const Digits: Integer): UnicodeString; begin Result := UIntToBaseU(A, Digits, 10); end; function Word32ToStr(const A: Word32; const Digits: Integer): String; begin Result := UIntToBase(A, Digits, 10); end; {$IFDEF SupportAnsiString} function Word32ToHexA(const A: Word32; const Digits: Integer; const UpperCase: Boolean): AnsiString; begin Result := UIntToBaseA(A, Digits, 16, UpperCase); end; {$ENDIF} function Word32ToHexB(const A: Word32; const Digits: Integer; const UpperCase: Boolean): RawByteString; begin Result := UIntToBaseB(A, Digits, 16, UpperCase); end; function Word32ToHexU(const A: Word32; const Digits: Integer; const UpperCase: Boolean): UnicodeString; begin Result := UIntToBaseU(A, Digits, 16, UpperCase); end; function Word32ToHex(const A: Word32; const Digits: Integer; const UpperCase: Boolean): String; begin Result := UIntToBase(A, Digits, 16, UpperCase); end; {$IFDEF SupportAnsiString} function Word32ToOctA(const A: Word32; const Digits: Integer): AnsiString; begin Result := UIntToBaseA(A, Digits, 8); end; {$ENDIF} function Word32ToOctB(const A: Word32; const Digits: Integer): RawByteString; begin Result := UIntToBaseB(A, Digits, 8); end; function Word32ToOctU(const A: Word32; const Digits: Integer): UnicodeString; begin Result := UIntToBaseU(A, Digits, 8); end; function Word32ToOct(const A: Word32; const Digits: Integer): String; begin Result := UIntToBase(A, Digits, 8); end; {$IFDEF SupportAnsiString} function Word32ToBinA(const A: Word32; const Digits: Integer): AnsiString; begin Result := UIntToBaseA(A, Digits, 2); end; {$ENDIF} function Word32ToBinB(const A: Word32; const Digits: Integer): RawByteString; begin Result := UIntToBaseB(A, Digits, 2); end; function Word32ToBinU(const A: Word32; const Digits: Integer): UnicodeString; begin Result := UIntToBaseU(A, Digits, 2); end; function Word32ToBin(const A: Word32; const Digits: Integer): String; begin Result := UIntToBase(A, Digits, 2); end; {$IFOPT Q+}{$DEFINE QOn}{$Q-}{$ELSE}{$UNDEF QOn}{$ENDIF} // Delphi 7 incorrectly overflowing for -922337203685477580 * 10 function TryStringToUInt64PB(const BufP: Pointer; const BufLen: Integer; out Value: UInt64; out StrLen: Integer): TConvertResult; var ChP : PByte; Len : Integer; HasDig : Boolean; Res : UInt64; Ch : Byte; DigVal : Integer; begin if BufLen <= 0 then begin Value := 0; StrLen := 0; Result := convertFormatError; exit; end; Assert(Assigned(BufP)); ChP := BufP; Len := 0; HasDig := False; // skip leading zeros while (Len < BufLen) and (ChP^ = Ord('0')) do begin Inc(Len); Inc(ChP); HasDig := True; end; // convert digits Res := 0; while Len < BufLen do begin Ch := ChP^; if Ch in [Ord('0')..Ord('9')] then begin HasDig := True; if (Res > 1844674407370955161) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Res := Res * 10; DigVal := ByteCharDigitToInt(ByteChar(Ch)); if (Res = 18446744073709551610) and (DigVal > 5) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Inc(Res, DigVal); Inc(Len); Inc(ChP); end else break; end; StrLen := Len; if not HasDig then begin Value := 0; Result := convertFormatError; end else begin Value := Res; Result := convertOK; end; end; function TryStringToUInt64PW(const BufP: Pointer; const BufLen: Integer; out Value: UInt64; out StrLen: Integer): TConvertResult; var ChP : PWideChar; Len : Integer; HasDig : Boolean; Res : UInt64; Ch : WideChar; DigVal : Integer; begin if BufLen <= 0 then begin Value := 0; StrLen := 0; Result := convertFormatError; exit; end; Assert(Assigned(BufP)); ChP := BufP; Len := 0; HasDig := False; // skip leading zeros while (Len < BufLen) and (ChP^ = '0') do begin Inc(Len); Inc(ChP); HasDig := True; end; // convert digits Res := 0; while Len < BufLen do begin Ch := ChP^; if (Ch >= '0') and (Ch <= '9') then begin HasDig := True; if (Res > 1844674407370955161) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Res := Res * 10; DigVal := WideCharDigitToInt(Ch); if (Res = 18446744073709551610) and (DigVal > 5) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Inc(Res, DigVal); Inc(Len); Inc(ChP); end else break; end; StrLen := Len; if not HasDig then begin Value := 0; Result := convertFormatError; end else begin Value := Res; Result := convertOK; end; end; function TryStringToUInt64P(const BufP: Pointer; const BufLen: Integer; out Value: UInt64; out StrLen: Integer): TConvertResult; {$IFDEF UseInline}inline;{$ENDIF} begin {$IFDEF StringIsUnicode} Result := TryStringToUInt64PW(BufP, BufLen, Value, StrLen); {$ELSE} Result := TryStringToUInt64PB(BufP, BufLen, Value, StrLen); {$ENDIF} end; function TryStringToInt64PB(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; var Len : Integer; DigVal : Integer; P : PByte; Ch : Byte; HasDig : Boolean; Neg : Boolean; Res : Int64; begin if BufLen <= 0 then begin Value := 0; StrLen := 0; Result := convertFormatError; exit; end; P := BufP; Len := 0; // check sign Ch := P^; if Ch in [Ord('+'), Ord('-')] then begin Inc(Len); Inc(P); Neg := Ch = Ord('-'); end else Neg := False; // skip leading zeros HasDig := False; while (Len < BufLen) and (P^ = Ord('0')) do begin Inc(Len); Inc(P); HasDig := True; end; // convert digits Res := 0; while Len < BufLen do begin Ch := P^; if Ch in [Ord('0')..Ord('9')] then begin HasDig := True; if (Res > 922337203685477580) or (Res < -922337203685477580) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Res := Res * 10; DigVal := ByteCharDigitToInt(ByteChar(Ch)); if ((Res = 9223372036854775800) and (DigVal > 7)) or ((Res = -9223372036854775800) and (DigVal > 8)) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; if Neg then Dec(Res, DigVal) else Inc(Res, DigVal); Inc(Len); Inc(P); end else break; end; StrLen := Len; if not HasDig then begin Value := 0; Result := convertFormatError; end else begin Value := Res; Result := convertOK; end; end; function TryStringToInt64PW(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; var Len : Integer; DigVal : Integer; P : PWideChar; Ch : WideChar; HasDig : Boolean; Neg : Boolean; Res : Int64; begin if BufLen <= 0 then begin Value := 0; StrLen := 0; Result := convertFormatError; exit; end; P := BufP; Len := 0; // check sign Ch := P^; if (Ch = '+') or (Ch = '-') then begin Inc(Len); Inc(P); Neg := Ch = '-'; end else Neg := False; // skip leading zeros HasDig := False; while (Len < BufLen) and (P^ = '0') do begin Inc(Len); Inc(P); HasDig := True; end; // convert digits Res := 0; while Len < BufLen do begin Ch := P^; if (Ch >= '0') and (Ch <= '9') then begin HasDig := True; if (Res > 922337203685477580) or (Res < -922337203685477580) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Res := Res * 10; DigVal := WideCharDigitToInt(Ch); if ((Res = 9223372036854775800) and (DigVal > 7)) or ((Res = -9223372036854775800) and (DigVal > 8)) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; if Neg then Dec(Res, DigVal) else Inc(Res, DigVal); Inc(Len); Inc(P); end else break; end; StrLen := Len; if not HasDig then begin Value := 0; Result := convertFormatError; end else begin Value := Res; Result := convertOK; end; end; function TryStringToInt64P(const BufP: Pointer; const BufLen: Integer; out Value: Int64; out StrLen: Integer): TConvertResult; var Len : Integer; DigVal : Integer; P : PChar; Ch : Char; HasDig : Boolean; Neg : Boolean; Res : Int64; begin if BufLen <= 0 then begin Value := 0; StrLen := 0; Result := convertFormatError; exit; end; P := BufP; Len := 0; // check sign Ch := P^; if (Ch = '+') or (Ch = '-') then begin Inc(Len); Inc(P); Neg := Ch = '-'; end else Neg := False; // skip leading zeros HasDig := False; while (Len < BufLen) and (P^ = '0') do begin Inc(Len); Inc(P); HasDig := True; end; // convert digits Res := 0; while Len < BufLen do begin Ch := P^; if (Ch >= '0') and (Ch <= '9') then begin HasDig := True; if (Res > 922337203685477580) or (Res < -922337203685477580) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; Res := Res * 10; DigVal := CharDigitToInt(Ch); if ((Res = 9223372036854775800) and (DigVal > 7)) or ((Res = -9223372036854775800) and (DigVal > 8)) then begin Value := 0; StrLen := Len; Result := convertOverflow; exit; end; if Neg then Dec(Res, DigVal) else Inc(Res, DigVal); Inc(Len); Inc(P); end else break; end; StrLen := Len; if not HasDig then begin Value := 0; Result := convertFormatError; end else begin Value := Res; Result := convertOK; end; end; {$IFDEF QOn}{$Q+}{$ENDIF} {$IFDEF SupportAnsiString} function TryStringToInt64A(const S: AnsiString; out A: Int64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToInt64PB(PAnsiChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; {$ENDIF} function TryStringToInt64B(const S: RawByteString; out A: Int64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToInt64PB(Pointer(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; function TryStringToInt64U(const S: UnicodeString; out A: Int64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToInt64PW(PWideChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; function TryStringToInt64(const S: String; out A: Int64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToInt64P(PChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; {$IFDEF SupportAnsiString} function TryStringToUInt64A(const S: AnsiString; out A: UInt64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToUInt64PB(PAnsiChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; {$ENDIF} function TryStringToUInt64B(const S: RawByteString; out A: UInt64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToUInt64PB(Pointer(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; function TryStringToUInt64U(const S: UnicodeString; out A: UInt64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToUInt64PW(PWideChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; function TryStringToUInt64(const S: String; out A: UInt64): Boolean; var L, N : Integer; begin L := Length(S); Result := TryStringToUInt64P(PChar(S), L, A, N) = convertOK; if Result then if N < L then Result := False; end; {$IFDEF SupportAnsiString} function StringToInt64DefA(const S: AnsiString; const Default: Int64): Int64; begin if not TryStringToInt64A(S, Result) then Result := Default; end; {$ENDIF} function StringToInt64DefB(const S: RawByteString; const Default: Int64): Int64; begin if not TryStringToInt64B(S, Result) then Result := Default; end; function StringToInt64DefU(const S: UnicodeString; const Default: Int64): Int64; begin if not TryStringToInt64U(S, Result) then Result := Default; end; function StringToInt64Def(const S: String; const Default: Int64): Int64; begin if not TryStringToInt64(S, Result) then Result := Default; end; {$IFDEF SupportAnsiString} function StringToUInt64DefA(const S: AnsiString; const Default: UInt64): UInt64; begin if not TryStringToUInt64A(S, Result) then Result := Default; end; {$ENDIF} function StringToUInt64DefB(const S: RawByteString; const Default: UInt64): UInt64; begin if not TryStringToUInt64B(S, Result) then Result := Default; end; function StringToUInt64DefU(const S: UnicodeString; const Default: UInt64): UInt64; begin if not TryStringToUInt64U(S, Result) then Result := Default; end; function StringToUInt64Def(const S: String; const Default: UInt64): UInt64; begin if not TryStringToUInt64(S, Result) then Result := Default; end; {$IFDEF SupportAnsiString} function StringToInt64A(const S: AnsiString): Int64; begin if not TryStringToInt64A(S, Result) then raise ERangeCheckError.Create; end; {$ENDIF} function StringToInt64B(const S: RawByteString): Int64; begin if not TryStringToInt64B(S, Result) then raise ERangeCheckError.Create; end; function StringToInt64U(const S: UnicodeString): Int64; begin if not TryStringToInt64U(S, Result) then raise ERangeCheckError.Create; end; function StringToInt64(const S: String): Int64; begin if not TryStringToInt64(S, Result) then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function StringToUInt64A(const S: AnsiString): UInt64; begin if not TryStringToUInt64A(S, Result) then raise ERangeCheckError.Create; end; {$ENDIF} function StringToUInt64B(const S: RawByteString): UInt64; begin if not TryStringToUInt64B(S, Result) then raise ERangeCheckError.Create; end; function StringToUInt64U(const S: UnicodeString): UInt64; begin if not TryStringToUInt64U(S, Result) then raise ERangeCheckError.Create; end; function StringToUInt64(const S: String): UInt64; begin if not TryStringToUInt64(S, Result) then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function TryStringToIntA(const S: AnsiString; out A: Integer): Boolean; var B : Int64; begin Result := TryStringToInt64A(S, B); if not Result then begin A := 0; exit; end; if (B < MinInteger) or (B > MaxInteger) then begin A := 0; Result := False; exit; end; A := Integer(B); Result := True; end; {$ENDIF} function TryStringToIntB(const S: RawByteString; out A: Integer): Boolean; var B : Int64; begin Result := TryStringToInt64B(S, B); if not Result then begin A := 0; exit; end; if (B < MinInteger) or (B > MaxInteger) then begin A := 0; Result := False; exit; end; A := Integer(B); Result := True; end; function TryStringToIntU(const S: UnicodeString; out A: Integer): Boolean; var B : Int64; begin Result := TryStringToInt64U(S, B); if not Result then begin A := 0; exit; end; if (B < MinInteger) or (B > MaxInteger) then begin A := 0; Result := False; exit; end; A := Integer(B); Result := True; end; function TryStringToInt(const S: String; out A: Integer): Boolean; var B : Int64; begin Result := TryStringToInt64(S, B); if not Result then begin A := 0; exit; end; if (B < MinInteger) or (B > MaxInteger) then begin A := 0; Result := False; exit; end; A := Integer(B); Result := True; end; {$IFDEF SupportAnsiString} function StringToIntDefA(const S: AnsiString; const Default: Integer): Integer; begin if not TryStringToIntA(S, Result) then Result := Default; end; {$ENDIF} function StringToIntDefB(const S: RawByteString; const Default: Integer): Integer; begin if not TryStringToIntB(S, Result) then Result := Default; end; function StringToIntDefU(const S: UnicodeString; const Default: Integer): Integer; begin if not TryStringToIntU(S, Result) then Result := Default; end; function StringToIntDef(const S: String; const Default: Integer): Integer; begin if not TryStringToInt(S, Result) then Result := Default; end; {$IFDEF SupportAnsiString} function StringToIntA(const S: AnsiString): Integer; begin if not TryStringToIntA(S, Result) then raise ERangeCheckError.Create; end; {$ENDIF} function StringToIntB(const S: RawByteString): Integer; begin if not TryStringToIntB(S, Result) then raise ERangeCheckError.Create; end; function StringToIntU(const S: UnicodeString): Integer; begin if not TryStringToIntU(S, Result) then raise ERangeCheckError.Create; end; function StringToInt(const S: String): Integer; begin if not TryStringToInt(S, Result) then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function TryStringToWord32A(const S: AnsiString; out A: Word32): Boolean; var B : Int64; begin Result := TryStringToInt64A(S, B); if not Result then begin A := 0; exit; end; if (B < MinWord32) or (B > MaxWord32) then begin A := 0; Result := False; exit; end; A := Word32(B); Result := True; end; {$ENDIF} function TryStringToWord32B(const S: RawByteString; out A: Word32): Boolean; var B : Int64; begin Result := TryStringToInt64B(S, B); if not Result then begin A := 0; exit; end; if (B < MinWord32) or (B > MaxWord32) then begin A := 0; Result := False; exit; end; A := Word32(B); Result := True; end; function TryStringToWord32U(const S: UnicodeString; out A: Word32): Boolean; var B : Int64; begin Result := TryStringToInt64U(S, B); if not Result then begin A := 0; exit; end; if (B < MinWord32) or (B > MaxWord32) then begin A := 0; Result := False; exit; end; A := Word32(B); Result := True; end; function TryStringToWord32(const S: String; out A: Word32): Boolean; var B : Int64; begin Result := TryStringToInt64(S, B); if not Result then begin A := 0; exit; end; if (B < MinWord32) or (B > MaxWord32) then begin A := 0; Result := False; exit; end; A := Word32(B); Result := True; end; {$IFDEF SupportAnsiString} function StringToWord32A(const S: AnsiString): Word32; begin if not TryStringToWord32A(S, Result) then raise ERangeCheckError.Create; end; {$ENDIF} function StringToWord32B(const S: RawByteString): Word32; begin if not TryStringToWord32B(S, Result) then raise ERangeCheckError.Create; end; function StringToWord32U(const S: UnicodeString): Word32; begin if not TryStringToWord32U(S, Result) then raise ERangeCheckError.Create; end; function StringToWord32(const S: String): Word32; begin if not TryStringToWord32(S, Result) then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function BaseStrToUIntA(const S: AnsiString; const BaseLog2: Byte; var Valid: Boolean): UInt64; var N : Byte; L : Integer; M : Byte; C : Byte; begin Assert(BaseLog2 <= 4); // maximum base 16 L := Length(S); if L = 0 then // empty string is invalid begin Valid := False; Result := 0; exit; end; M := (1 shl BaseLog2) - 1; // maximum digit value N := 0; Result := 0; repeat C := AsciiHexLookup[Ord(S[L])]; if C > M then // invalid digit begin Valid := False; Result := 0; exit; end; {$IFDEF FPC} Result := Result + UInt64(C) shl N; {$ELSE} Inc(Result, UInt64(C) shl N); {$ENDIF} Inc(N, BaseLog2); if N > 64 then // overflow begin Valid := False; Result := 0; exit; end; Dec(L); until L = 0; Valid := True; end; {$ENDIF} function BaseStrToUIntB(const S: RawByteString; const BaseLog2: Byte; var Valid: Boolean): UInt64; var N : Byte; L : Integer; M : Byte; C : Byte; begin Assert(BaseLog2 <= 4); // maximum base 16 L := Length(S); if L = 0 then // empty string is invalid begin Valid := False; Result := 0; exit; end; M := (1 shl BaseLog2) - 1; // maximum digit value N := 0; Result := 0; repeat C := AsciiHexLookup[Ord(S[L])]; if C > M then // invalid digit begin Valid := False; Result := 0; exit; end; {$IFDEF FPC} Result := Result + UInt64(C) shl N; {$ELSE} Inc(Result, UInt64(C) shl N); {$ENDIF} Inc(N, BaseLog2); if N > 64 then // overflow begin Valid := False; Result := 0; exit; end; Dec(L); until L = 0; Valid := True; end; function BaseStrToUIntU(const S: UnicodeString; const BaseLog2: Byte; var Valid: Boolean): UInt64; var N : Byte; L : Integer; M : Byte; C : Byte; D : WideChar; begin Assert(BaseLog2 <= 4); // maximum base 16 L := Length(S); if L = 0 then // empty string is invalid begin Valid := False; Result := 0; exit; end; M := (1 shl BaseLog2) - 1; // maximum digit value N := 0; Result := 0; repeat D := S[L]; if Ord(D) > $FF then C := $FF else C := AsciiHexLookup[Ord(D)]; if C > M then // invalid digit begin Valid := False; Result := 0; exit; end; {$IFDEF FPC} Result := Result + UInt64(C) shl N; {$ELSE} Inc(Result, UInt64(C) shl N); {$ENDIF} Inc(N, BaseLog2); if N > 64 then // overflow begin Valid := False; Result := 0; exit; end; Dec(L); until L = 0; Valid := True; end; function BaseStrToUInt(const S: String; const BaseLog2: Byte; var Valid: Boolean): UInt64; var N : Byte; L : Integer; M : Byte; C : Byte; D : Char; begin Assert(BaseLog2 <= 4); // maximum base 16 L := Length(S); if L = 0 then // empty string is invalid begin Valid := False; Result := 0; exit; end; M := (1 shl BaseLog2) - 1; // maximum digit value N := 0; Result := 0; repeat D := S[L]; {$IFDEF CharIsWide} if Ord(D) > $FF then C := $FF else C := AsciiHexLookup[Ord(D)]; {$ELSE} C := HexLookup[Ord(D)]; {$ENDIF} if C > M then // invalid digit begin Valid := False; Result := 0; exit; end; {$IFDEF FPC} Result := Result + UInt64(C) shl N; {$ELSE} Inc(Result, UInt64(C) shl N); {$ENDIF} Inc(N, BaseLog2); if N > 64 then // overflow begin Valid := False; Result := 0; exit; end; Dec(L); until L = 0; Valid := True; end; {$IFDEF SupportAnsiString} function HexToUIntA(const S: AnsiString): UInt64; var R : Boolean; begin Result := BaseStrToUIntA(S, 4, R); if not R then raise ERangeCheckError.Create; end; {$ENDIF} function HexToUIntB(const S: RawByteString): UInt64; var R : Boolean; begin Result := BaseStrToUIntB(S, 4, R); if not R then raise ERangeCheckError.Create; end; function HexToUIntU(const S: UnicodeString): UInt64; var R : Boolean; begin Result := BaseStrToUIntU(S, 4, R); if not R then raise ERangeCheckError.Create; end; function HexToUInt(const S: String): UInt64; var R : Boolean; begin Result := BaseStrToUInt(S, 4, R); if not R then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function TryHexToWord32A(const S: AnsiString; out A: Word32): Boolean; begin A := BaseStrToUIntA(S, 4, Result); end; {$ENDIF} function TryHexToWord32B(const S: RawByteString; out A: Word32): Boolean; begin A := BaseStrToUIntB(S, 4, Result); end; function TryHexToWord32U(const S: UnicodeString; out A: Word32): Boolean; begin A := BaseStrToUIntU(S, 4, Result); end; function TryHexToWord32(const S: String; out A: Word32): Boolean; begin A := BaseStrToUInt(S, 4, Result); end; {$IFDEF SupportAnsiString} function HexToWord32A(const S: AnsiString): Word32; var R : Boolean; begin Result := BaseStrToUIntA(S, 4, R); if not R then raise ERangeCheckError.Create; end; {$ENDIF} function HexToWord32B(const S: RawByteString): Word32; var R : Boolean; begin Result := BaseStrToUIntB(S, 4, R); if not R then raise ERangeCheckError.Create; end; function HexToWord32U(const S: UnicodeString): Word32; var R : Boolean; begin Result := BaseStrToUIntU(S, 4, R); if not R then raise ERangeCheckError.Create; end; function HexToWord32(const S: String): Word32; var R : Boolean; begin Result := BaseStrToUInt(S, 4, R); if not R then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function TryOctToWord32A(const S: AnsiString; out A: Word32): Boolean; begin A := BaseStrToUIntA(S, 3, Result); end; {$ENDIF} function TryOctToWord32B(const S: RawByteString; out A: Word32): Boolean; begin A := BaseStrToUIntB(S, 3, Result); end; function TryOctToWord32U(const S: UnicodeString; out A: Word32): Boolean; begin A := BaseStrToUIntU(S, 3, Result); end; function TryOctToWord32(const S: String; out A: Word32): Boolean; begin A := BaseStrToUInt(S, 3, Result); end; {$IFDEF SupportAnsiString} function OctToWord32A(const S: AnsiString): Word32; var R : Boolean; begin Result := BaseStrToUIntA(S, 3, R); if not R then raise ERangeCheckError.Create; end; {$ENDIF} function OctToWord32B(const S: RawByteString): Word32; var R : Boolean; begin Result := BaseStrToUIntB(S, 3, R); if not R then raise ERangeCheckError.Create; end; function OctToWord32U(const S: UnicodeString): Word32; var R : Boolean; begin Result := BaseStrToUIntU(S, 3, R); if not R then raise ERangeCheckError.Create; end; function OctToWord32(const S: String): Word32; var R : Boolean; begin Result := BaseStrToUInt(S, 3, R); if not R then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function TryBinToWord32A(const S: AnsiString; out A: Word32): Boolean; begin A := BaseStrToUIntA(S, 1, Result); end; {$ENDIF} function TryBinToWord32B(const S: RawByteString; out A: Word32): Boolean; begin A := BaseStrToUIntB(S, 1, Result); end; function TryBinToWord32U(const S: UnicodeString; out A: Word32): Boolean; begin A := BaseStrToUIntU(S, 1, Result); end; function TryBinToWord32(const S: String; out A: Word32): Boolean; begin A := BaseStrToUInt(S, 1, Result); end; {$IFDEF SupportAnsiString} function BinToWord32A(const S: AnsiString): Word32; var R : Boolean; begin Result := BaseStrToUIntA(S, 1, R); if not R then raise ERangeCheckError.Create; end; {$ENDIF} function BinToWord32B(const S: RawByteString): Word32; var R : Boolean; begin Result := BaseStrToUIntB(S, 1, R); if not R then raise ERangeCheckError.Create; end; function BinToWord32U(const S: UnicodeString): Word32; var R : Boolean; begin Result := BaseStrToUIntU(S, 1, R); if not R then raise ERangeCheckError.Create; end; function BinToWord32(const S: String): Word32; var R : Boolean; begin Result := BaseStrToUInt(S, 1, R); if not R then raise ERangeCheckError.Create; end; {$IFDEF SupportAnsiString} function BytesToHexA(const P: Pointer; const Count: NativeInt; const UpperCase: Boolean): AnsiString; var Q : PByte; D : PAnsiChar; L : NativeInt; V : Byte; begin Q := P; L := Count; if (L <= 0) or not Assigned(Q) then begin Result := ''; exit; end; SetLength(Result, Count * 2); D := Pointer(Result); while L > 0 do begin V := Q^ shr 4 + 1; if UpperCase then D^ := AnsiChar(StrHexDigitsUpper[V]) else D^ := AnsiChar(StrHexDigitsLower[V]); Inc(D); V := Q^ and $F + 1; if UpperCase then D^ := AnsiChar(StrHexDigitsUpper[V]) else D^ := AnsiChar(StrHexDigitsLower[V]); Inc(D); Inc(Q); Dec(L); end; end; {$ENDIF} { } { Network byte order } { } function hton16(const A: Word): Word; begin Result := Word(A shr 8) or Word(A shl 8); end; function ntoh16(const A: Word): Word; begin Result := Word(A shr 8) or Word(A shl 8); end; function hton32(const A: Word32): Word32; var BufH : array[0..3] of Byte; BufN : array[0..3] of Byte; begin PWord32(@BufH)^ := A; BufN[0] := BufH[3]; BufN[1] := BufH[2]; BufN[2] := BufH[1]; BufN[3] := BufH[0]; Result := PWord32(@BufN)^; end; function ntoh32(const A: Word32): Word32; var BufH : array[0..3] of Byte; BufN : array[0..3] of Byte; begin PWord32(@BufH)^ := A; BufN[0] := BufH[3]; BufN[1] := BufH[2]; BufN[2] := BufH[1]; BufN[3] := BufH[0]; Result := PWord32(@BufN)^; end; function hton64(const A: Int64): Int64; var BufH : array[0..7] of Byte; BufN : array[0..7] of Byte; begin PInt64(@BufH)^ := A; BufN[0] := BufH[7]; BufN[1] := BufH[6]; BufN[2] := BufH[5]; BufN[3] := BufH[4]; BufN[4] := BufH[3]; BufN[5] := BufH[2]; BufN[6] := BufH[1]; BufN[7] := BufH[0]; Result := PInt64(@BufN)^; end; function ntoh64(const A: Int64): Int64; var BufH : array[0..7] of Byte; BufN : array[0..7] of Byte; begin PInt64(@BufH)^ := A; BufN[0] := BufH[7]; BufN[1] := BufH[6]; BufN[2] := BufH[5]; BufN[3] := BufH[4]; BufN[4] := BufH[3]; BufN[5] := BufH[2]; BufN[6] := BufH[1]; BufN[7] := BufH[0]; Result := PInt64(@BufN)^; end; { } { Pointer-String conversions } { } {$IFDEF SupportAnsiString} function PointerToStrA(const P: Pointer): AnsiString; begin Result := UIntToBaseA(NativeUInt(P), NativeWordSize * 2, 16, True); end; {$ENDIF} function PointerToStrB(const P: Pointer): RawByteString; begin Result := UIntToBaseB(NativeUInt(P), NativeWordSize * 2, 16, True); end; function PointerToStrU(const P: Pointer): UnicodeString; begin Result := UIntToBaseU(NativeUInt(P), NativeWordSize * 2, 16, True); end; function PointerToStr(const P: Pointer): String; begin Result := UIntToBase(NativeUInt(P), NativeWordSize * 2, 16, True); end; {$IFDEF SupportAnsiString} function StrToPointerA(const S: AnsiString): Pointer; var V : Boolean; begin Result := Pointer(BaseStrToUIntA(S, 4, V)); end; {$ENDIF} function StrToPointerB(const S: RawByteString): Pointer; var V : Boolean; begin Result := Pointer(BaseStrToUIntB(S, 4, V)); end; function StrToPointerU(const S: UnicodeString): Pointer; var V : Boolean; begin Result := Pointer(BaseStrToUIntU(S, 4, V)); end; function StrToPointer(const S: String): Pointer; var V : Boolean; begin Result := Pointer(BaseStrToUInt(S, 4, V)); end; {$IFDEF SupportInterface} {$IFDEF SupportAnsiString} function InterfaceToStrA(const I: IInterface): AnsiString; begin Result := UIntToBaseA(NativeUInt(I), NativeWordSize * 2, 16, True); end; {$ENDIF} function InterfaceToStrB(const I: IInterface): RawByteString; begin Result := UIntToBaseB(NativeUInt(I), NativeWordSize * 2, 16, True); end; function InterfaceToStrU(const I: IInterface): UnicodeString; begin Result := UIntToBaseU(NativeUInt(I), NativeWordSize * 2, 16, True); end; function InterfaceToStr(const I: IInterface): String; begin Result := UIntToBase(NativeUInt(I), NativeWordSize * 2, 16, True); end; {$ENDIF} function ObjectClassName(const O: TObject): String; begin if not Assigned(O) then Result := 'nil' else Result := O.ClassName; end; function ClassClassName(const C: TClass): String; begin if not Assigned(C) then Result := 'nil' else Result := C.ClassName; end; function ObjectToStr(const O: TObject): String; begin if not Assigned(O) then Result := 'nil' else Result := O.ClassName + '@' + PointerToStr(Pointer(O)); end; { } { Hash functions } { Derived from a CRC32 algorithm. } { } var HashTableInit : Boolean = False; HashTable : array[Byte] of Word32; HashPoly : Word32 = $EDB88320; procedure InitHashTable; var I, J : Byte; R : Word32; begin for I := $00 to $FF do begin R := I; for J := 8 downto 1 do if R and 1 <> 0 then R := (R shr 1) xor HashPoly else R := R shr 1; HashTable[I] := R; end; HashTableInit := True; end; function HashByte(const Hash: Word32; const C: Byte): Word32; {$IFDEF UseInline}inline;{$ENDIF} begin Result := HashTable[Byte(Hash) xor C] xor (Hash shr 8); end; function HashCharB(const Hash: Word32; const Ch: ByteChar): Word32; {$IFDEF UseInline}inline;{$ENDIF} begin Result := HashByte(Hash, Byte(Ch)); end; function HashCharW(const Hash: Word32; const Ch: WideChar): Word32; {$IFDEF UseInline}inline;{$ENDIF} var C1, C2 : Byte; begin C1 := Byte(Ord(Ch) and $FF); C2 := Byte(Ord(Ch) shr 8); Result := Hash; Result := HashByte(Result, C1); Result := HashByte(Result, C2); end; function HashChar(const Hash: Word32; const Ch: Char): Word32; {$IFDEF UseInline}inline;{$ENDIF} begin {$IFDEF CharIsWide} Result := HashCharW(Hash, Ch); {$ELSE} Result := HashCharB(Hash, Ch); {$ENDIF} end; function HashCharNoAsciiCaseB(const Hash: Word32; const Ch: ByteChar): Word32; {$IFDEF UseInline}inline;{$ENDIF} var C : Byte; begin C := Byte(Ch); if C in [Ord('A')..Ord('Z')] then C := C or 32; Result := HashCharB(Hash, ByteChar(C)); end; function HashCharNoAsciiCaseW(const Hash: Word32; const Ch: WideChar): Word32; {$IFDEF UseInline}inline;{$ENDIF} var C : Word; begin C := Word(Ch); if C <= $FF then if Byte(C) in [Ord('A')..Ord('Z')] then C := C or 32; Result := HashCharW(Hash, WideChar(C)); end; function HashCharNoAsciiCase(const Hash: Word32; const Ch: Char): Word32; {$IFDEF UseInline}inline;{$ENDIF} begin {$IFDEF CharIsWide} Result := HashCharNoAsciiCaseW(Hash, Ch); {$ELSE} Result := HashCharNoAsciiCaseB(Hash, Ch); {$ENDIF} end; function HashBuf(const Hash: Word32; const Buf; const BufSize: NativeInt): Word32; var P : PByte; I : NativeInt; begin if not HashTableInit then InitHashTable; Result := Hash; P := @Buf; for I := 0 to BufSize - 1 do begin Result := HashByte(Result, P^); Inc(P); end; end; {$IFDEF SupportAnsiString} function HashStrA( const S: AnsiString; const Index: NativeInt; const Count: NativeInt; const AsciiCaseSensitive: Boolean; const Slots: Word32): Word32; var I, L, A, B : NativeInt; begin if not HashTableInit then InitHashTable; A := Index; if A < 1 then A := 1; L := Length(S); B := Count; if B < 0 then B := L else begin B := A + B - 1; if B > L then B := L; end; Result := $FFFFFFFF; if AsciiCaseSensitive then for I := A to B do Result := HashCharB(Result, S[I]) else for I := A to B do Result := HashCharNoAsciiCaseB(Result, S[I]); if Slots > 0 then Result := Result mod Slots; end; {$ENDIF} function HashStrB( const S: RawByteString; const Index: NativeInt; const Count: NativeInt; const AsciiCaseSensitive: Boolean; const Slots: Word32): Word32; var I, L, A, B : NativeInt; begin if not HashTableInit then InitHashTable; A := Index; if A < 1 then A := 1; L := Length(S); B := Count; if B < 0 then B := L else begin B := A + B - 1; if B > L then B := L; end; Result := $FFFFFFFF; if AsciiCaseSensitive then for I := A to B do Result := HashCharB(Result, ByteChar(S[I])) else for I := A to B do Result := HashCharNoAsciiCaseB(Result, ByteChar(S[I])); if Slots > 0 then Result := Result mod Slots; end; function HashStrU( const S: UnicodeString; const Index: NativeInt; const Count: NativeInt; const AsciiCaseSensitive: Boolean; const Slots: Word32): Word32; var I, L, A, B : NativeInt; begin if not HashTableInit then InitHashTable; A := Index; if A < 1 then A := 1; L := Length(S); B := Count; if B < 0 then B := L else begin B := A + B - 1; if B > L then B := L; end; Result := $FFFFFFFF; if AsciiCaseSensitive then for I := A to B do Result := HashCharW(Result, S[I]) else for I := A to B do Result := HashCharNoAsciiCaseW(Result, S[I]); if Slots > 0 then Result := Result mod Slots; end; function HashStr( const S: String; const Index: NativeInt; const Count: NativeInt; const AsciiCaseSensitive: Boolean; const Slots: Word32): Word32; var I, L, A, B : NativeInt; begin if not HashTableInit then InitHashTable; A := Index; if A < 1 then A := 1; L := Length(S); B := Count; if B < 0 then B := L else begin B := A + B - 1; if B > L then B := L; end; Result := $FFFFFFFF; if AsciiCaseSensitive then for I := A to B do Result := HashChar(Result, S[I]) else for I := A to B do Result := HashCharNoAsciiCase(Result, S[I]); if Slots > 0 then Result := Result mod Slots; end; { HashInteger based on the CRC32 algorithm. It is a very good all purpose hash } { with a highly uniform distribution of results. } function HashInteger(const I: Integer; const Slots: Word32): Word32; var P : PByte; J : Integer; begin if not HashTableInit then InitHashTable; Result := $FFFFFFFF; P := @I; for J := 0 to SizeOf(Integer) - 1 do begin Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); Inc(P); end; if Slots <> 0 then Result := Result mod Slots; end; function HashNativeUInt(const I: NativeUInt; const Slots: Word32): Word32; var P : PByte; J : Integer; begin if not HashTableInit then InitHashTable; Result := $FFFFFFFF; P := @I; for J := 0 to SizeOf(NativeUInt) - 1 do begin Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); Inc(P); end; if Slots <> 0 then Result := Result mod Slots; end; function HashWord32(const I: Word32; const Slots: Word32): Word32; var P : PByte; begin if not HashTableInit then InitHashTable; Result := $FFFFFFFF; P := @I; Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); Inc(P); Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); Inc(P); Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); Inc(P); Result := HashTable[Byte(Result) xor P^] xor (Result shr 8); if Slots <> 0 then Result := Result mod Slots; end; { } { Memory } { } procedure FillMem(var Buf; const Count: NativeInt; const Value: Byte); begin FillChar(Buf, Count, Value); end; procedure ZeroMem(var Buf; const Count: NativeInt); begin FillChar(Buf, Count, #0); end; procedure GetZeroMem(var P: Pointer; const Size: NativeInt); begin GetMem(P, Size); ZeroMem(P^, Size); end; procedure MoveMem(const Source; var Dest; const Count: NativeInt); begin Move(Source, Dest, Count); end; function EqualMem64(const Buf1; const Buf2; const Count: NativeInt): Boolean; {$IFDEF UseInline}inline;{$ENDIF} var P : Pointer; Q : Pointer; begin P := @Buf1; Q := @Buf2; case Count of 1 : Result := PByte(P)^ = PByte(Q)^; 2 : Result := PWord16(P)^ = PWord16(Q)^; 3 : begin Result := PWord16(P)^ = PWord16(Q)^; if Result then begin Inc(PWord16(P)); Inc(PWord16(Q)); Result := PByte(P)^ = PByte(Q)^; end; end; 4 : Result := PWord32(P)^ = PWord32(Q)^; 5 : begin Result := PWord32(P)^ = PWord32(Q)^; if Result then begin Inc(PWord32(P)); Inc(PWord32(Q)); Result := PByte(P)^ = PByte(Q)^; end; end; 6 : begin Result := PWord32(P)^ = PWord32(Q)^; if Result then begin Inc(PWord32(P)); Inc(PWord32(Q)); Result := PWord16(P)^ = PWord16(Q)^; end; end; 7 : begin Result := PWord32(P)^ = PWord32(Q)^; if Result then begin Inc(PWord32(P)); Inc(PWord32(Q)); Result := PWord16(P)^ = PWord16(Q)^; if Result then begin Inc(PWord16(P)); Inc(PWord16(Q)); Result := PByte(P)^ = PByte(Q)^; end; end; end; 8 : Result := PWord64(P)^ = PWord64(Q)^; else Result := True; end; end; function EqualMem(const Buf1; const Buf2; const Count: NativeInt): Boolean; var P : PNativeUInt; Q : PNativeUInt; D : NativeInt; begin if Count <= 0 then begin Result := True; exit; end; P := @Buf1; Q := @Buf2; if P = Q then begin Result := True; exit; end; if Count <= 8 then begin Result := EqualMem64(P^, Q^, Count); exit; end; {$IFDEF CPU_64} D := Count shr 3; {$ELSE}{$IFDEF CPU_32} D := Count shr 2; {$ELSE} D := Count div SizeOf(NativeInt); {$ENDIF}{$ENDIF} while D > 0 do if P^ = Q^ then begin Inc(P); Inc(Q); Dec(D); end else begin Result := False; exit; end; D := Count and (SizeOf(NativeInt) - 1); if D > 0 then begin Assert(D < SizeOf(NativeInt)); Result := EqualMem64(P^, Q^, D); end else Result := True; end; function EqualMemNoAsciiCase(const Buf1; const Buf2; const Count: NativeInt): Boolean; var P, Q : Pointer; I : NativeInt; C, D : Byte; begin if Count <= 0 then begin Result := True; exit; end; P := @Buf1; Q := @Buf2; if P = Q then begin Result := True; exit; end; for I := 1 to Count do begin C := PByte(P)^; D := PByte(Q)^; if C in [Ord('A')..Ord('Z')] then C := C or 32; if D in [Ord('A')..Ord('Z')] then D := D or 32; if C = D then begin Inc(PByte(P)); Inc(PByte(Q)); end else begin Result := False; exit; end; end; Result := True; end; function CompareMem(const Buf1; const Buf2; const Count: NativeInt): Integer; var P, Q : Pointer; I : NativeInt; C, D : Byte; begin if Count <= 0 then begin Result := 0; exit; end; P := @Buf1; Q := @Buf2; if P = Q then begin Result := 0; exit; end; for I := 1 to Count do begin C := PByte(P)^; D := PByte(Q)^; if C = D then begin Inc(PByte(P)); Inc(PByte(Q)); end else begin if C < D then Result := -1 else Result := 1; exit; end; end; Result := 0; end; function CompareMemNoAsciiCase(const Buf1; const Buf2; const Count: NativeInt): Integer; var P, Q : Pointer; I : Integer; C, D : Byte; begin if Count <= 0 then begin Result := 0; exit; end; P := @Buf1; Q := @Buf2; if P = Q then begin Result := 0; exit; end; for I := 1 to Count do begin C := PByte(P)^; D := PByte(Q)^; if C in [Ord('A')..Ord('Z')] then C := C or 32; if D in [Ord('A')..Ord('Z')] then D := D or 32; if C = D then begin Inc(PByte(P)); Inc(PByte(Q)); end else begin if C < D then Result := -1 else Result := 1; exit; end; end; Result := 0; end; function LocateMem(const Buf1; const Size1: NativeInt; const Buf2; const Size2: NativeInt): NativeInt; var P, Q : PByte; I : NativeInt; begin if (Size1 <= 0) or (Size2 <= 0) or (Size2 > Size1) then begin Result := -1; exit; end; for I := 0 to Size1 - Size2 do begin P := @Buf1; Inc(P, I); Q := @Buf2; if P = Q then begin Result := I; exit; end; if EqualMem(P^, Q^, Size2) then begin Result := I; exit; end; end; Result := -1; end; function LocateMemNoAsciiCase(const Buf1; const Size1: NativeInt; const Buf2; const Size2: NativeInt): NativeInt; var P, Q : PByte; I : NativeInt; begin if (Size1 <= 0) or (Size2 <= 0) or (Size2 > Size1) then begin Result := -1; exit; end; for I := 0 to Size1 - Size2 do begin P := @Buf1; Inc(P, I); Q := @Buf2; if P = Q then begin Result := I; exit; end; if EqualMemNoAsciiCase(P^, Q^, Size2) then begin Result := I; exit; end; end; Result := -1; end; procedure ReverseMem(var Buf; const Size: NativeInt); var I : NativeInt; P : PByte; Q : PByte; T : Byte; begin P := @Buf; Q := P; Inc(Q, Size - 1); for I := 1 to Size div 2 do begin T := P^; P^ := Q^; Q^ := T; Inc(P); Dec(Q); end; end; { } { FreeAndNil } { } procedure FreeAndNil(var Obj); var Temp : TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end; procedure FreeObjectArray(var V); var I : Integer; A : ObjectArray absolute V; begin for I := Length(A) - 1 downto 0 do FreeAndNil(A[I]); end; procedure FreeObjectArray(var V; const LoIdx, HiIdx: Integer); var I : Integer; A : ObjectArray absolute V; begin for I := HiIdx downto LoIdx do FreeAndNil(A[I]); end; // Note: The parameter can not be changed to be untyped and then typecasted // using an absolute variable, as in FreeObjectArray. The reference counting // will be done incorrectly. procedure FreeAndNilObjectArray(var V: ObjectArray); var W : ObjectArray; begin W := V; V := nil; FreeObjectArray(W); end; { } { TBytes functions } { } procedure BytesSetLengthAndZero(var V: TBytes; const NewLength: NativeInt); var OldLen, NewLen : NativeInt; begin NewLen := NewLength; if NewLen < 0 then NewLen := 0; OldLen := Length(V); if OldLen = NewLen then exit; SetLength(V, NewLen); if OldLen > NewLen then exit; ZeroMem(V[OldLen], NewLen - OldLen); end; procedure BytesInit(var V: TBytes; const R: Byte); begin SetLength(V, 1); V[0] := R; end; procedure BytesInit(var V: TBytes; const S: String); var L, I : Integer; begin L := Length(S); SetLength(V, L); for I := 0 to L - 1 do V[I] := Ord(S[I + 1]); end; function BytesAppend(var V: TBytes; const R: Byte): NativeInt; begin Result := Length(V); SetLength(V, Result + 1); V[Result] := R; end; function BytesAppend(var V: TBytes; const R: TBytes): NativeInt; var L : NativeInt; begin Result := Length(V); L := Length(R); if L > 0 then begin SetLength(V, Result + L); MoveMem(R[0], V[Result], L); end; end; function BytesAppend(var V: TBytes; const R: array of Byte): NativeInt; var L : NativeInt; begin Result := Length(V); L := Length(R); if L > 0 then begin SetLength(V, Result + L); MoveMem(R[0], V[Result], L); end; end; function BytesAppend(var V: TBytes; const R: String): NativeInt; var L, I : NativeInt; begin Result := Length(V); L := Length(R); if L > 0 then begin SetLength(V, Result + L); for I := 1 to L do V[Result] := Ord(R[I]); end; end; function BytesCompare(const A, B: TBytes): Integer; var L, N : NativeInt; begin L := Length(A); N := Length(B); if L < N then Result := -1 else if L > N then Result := 1 else Result := CompareMem(Pointer(A)^, Pointer(B)^, L); end; function BytesEqual(const A, B: TBytes): Boolean; var L, N : NativeInt; begin L := Length(A); N := Length(B); if L <> N then Result := False else Result := EqualMem(Pointer(A)^, Pointer(B)^, L); end; { } { Test cases } { } {$IFDEF UTILS_TEST} {$ASSERTIONS ON} procedure Test_Misc; var A, B : Byte; C, D : Word32; P, Q : TObject; begin // Integer types Assert(Sizeof(Int16Rec) = Sizeof(Int16), 'Int16Rec'); Assert(Sizeof(Int32Rec) = Sizeof(Int32), 'Int32Rec'); // Min / Max Assert(MinInt(-1, 1) = -1, 'MinI'); Assert(MaxInt(-1, 1) = 1, 'MaxI'); Assert(MinCrd(1, 2) = 1, 'MinC'); Assert(MaxCrd(1, 2) = 2, 'MaxC'); Assert(MaxCrd($FFFFFFFF, 0) = $FFFFFFFF, 'MaxC'); Assert(MinCrd($FFFFFFFF, 0) = 0, 'MinC'); // Bouded Assert(Int32Bounded(10, 5, 12) = 10, 'Bounded'); Assert(Int32Bounded(3, 5, 12) = 5, 'Bounded'); Assert(Int32Bounded(15, 5, 12) = 12, 'Bounded'); Assert(Int32BoundedByte(256) = 255, 'BoundedByte'); Assert(Int32BoundedWord(-5) = 0, 'BoundedWord'); Assert(Int64BoundedWord32($100000000) = $FFFFFFFF, 'BoundedWord'); // Swap A := $11; B := $22; Swap(A, B); Assert((A = $22) and (B = $11), 'Swap'); C := $11111111; D := $22222222; Swap(C, D); Assert((C = $22222222) and (D = $11111111), 'Swap'); P := TObject.Create; Q := nil; SwapObjects(P, Q); Assert(Assigned(Q) and not Assigned(P), 'SwapObjects'); Q.Free; // iif Assert(iif(True, 1, 2) = 1, 'iif'); Assert(iif(False, 1, 2) = 2, 'iif'); Assert(iif(True, -1, -2) = -1, 'iif'); Assert(iif(False, -1, -2) = -2, 'iif'); Assert(iif(True, '1', '2') = '1', 'iif'); Assert(iif(False, '1', '2') = '2', 'iif'); Assert(iifU(True, '1', '2') = '1', 'iif'); Assert(iifU(False, '1', '2') = '2', 'iif'); Assert(iif(True, 1.1, 2.2) = 1.1, 'iif'); Assert(iif(False, 1.1, 2.2) = 2.2, 'iif'); // Compare Assert(Compare(1, 1) = crEqual, 'Compare'); Assert(Compare(1, 2) = crLess, 'Compare'); Assert(Compare(1, 0) = crGreater, 'Compare'); Assert(Compare(1.0, 1.0) = crEqual, 'Compare'); Assert(Compare(1.0, 1.1) = crLess, 'Compare'); Assert(Compare(1.0, 0.9) = crGreater, 'Compare'); Assert(Compare(False, False) = crEqual, 'Compare'); Assert(Compare(True, True) = crEqual, 'Compare'); Assert(Compare(False, True) = crLess, 'Compare'); Assert(Compare(True, False) = crGreater, 'Compare'); {$IFDEF SupportAnsiString} Assert(CompareA(ToAnsiString(''), ToAnsiString('')) = crEqual, 'Compare'); Assert(CompareA(ToAnsiString('a'), ToAnsiString('a')) = crEqual, 'Compare'); Assert(CompareA(ToAnsiString('a'), ToAnsiString('b')) = crLess, 'Compare'); Assert(CompareA(ToAnsiString('b'), ToAnsiString('a')) = crGreater, 'Compare'); Assert(CompareA(ToAnsiString(''), ToAnsiString('a')) = crLess, 'Compare'); Assert(CompareA(ToAnsiString('a'), ToAnsiString('')) = crGreater, 'Compare'); Assert(CompareA(ToAnsiString('aa'), ToAnsiString('a')) = crGreater, 'Compare'); {$ENDIF} Assert(CompareB(ToRawByteString(''), ToRawByteString('')) = crEqual, 'Compare'); Assert(CompareB(ToRawByteString('a'), ToRawByteString('a')) = crEqual, 'Compare'); Assert(CompareB(ToRawByteString('a'), ToRawByteString('b')) = crLess, 'Compare'); Assert(CompareB(ToRawByteString('b'), ToRawByteString('a')) = crGreater, 'Compare'); Assert(CompareB(ToRawByteString(''), ToRawByteString('a')) = crLess, 'Compare'); Assert(CompareB(ToRawByteString('a'), ToRawByteString('')) = crGreater, 'Compare'); Assert(CompareB(ToRawByteString('aa'), ToRawByteString('a')) = crGreater, 'Compare'); Assert(CompareU(ToUnicodeString(''), ToUnicodeString('')) = crEqual, 'Compare'); Assert(CompareU(ToUnicodeString('a'), ToUnicodeString('a')) = crEqual, 'Compare'); Assert(CompareU(ToUnicodeString('a'), ToUnicodeString('b')) = crLess, 'Compare'); Assert(CompareU(ToUnicodeString('b'), ToUnicodeString('a')) = crGreater, 'Compare'); Assert(CompareU(ToUnicodeString(''), ToUnicodeString('a')) = crLess, 'Compare'); Assert(CompareU(ToUnicodeString('a'), ToUnicodeString('')) = crGreater, 'Compare'); Assert(CompareU(ToUnicodeString('aa'), ToUnicodeString('a')) = crGreater, 'Compare'); Assert(Sgn(1) = 1, 'Sign'); Assert(Sgn(0) = 0, 'Sign'); Assert(Sgn(-1) = -1, 'Sign'); Assert(Sgn(2) = 1, 'Sign'); Assert(Sgn(-2) = -1, 'Sign'); Assert(Sgn(-1.5) = -1, 'Sign'); Assert(Sgn(1.5) = 1, 'Sign'); Assert(Sgn(0.0) = 0, 'Sign'); Assert(InverseCompareResult(crLess) = crGreater, 'ReverseCompareResult'); Assert(InverseCompareResult(crGreater) = crLess, 'ReverseCompareResult'); end; procedure Test_IntStr; var I : Int64; U : UInt64; W : Word32; L : Integer; {$IFDEF SupportAnsiString} A : AnsiString; {$ENDIF} begin Assert(HexCharDigitToInt('A') = 10, 'HexCharDigitToInt'); Assert(HexCharDigitToInt('a') = 10, 'HexCharDigitToInt'); Assert(HexCharDigitToInt('1') = 1, 'HexCharDigitToInt'); Assert(HexCharDigitToInt('0') = 0, 'HexCharDigitToInt'); Assert(HexCharDigitToInt('F') = 15, 'HexCharDigitToInt'); Assert(HexCharDigitToInt('G') = -1, 'HexCharDigitToInt'); {$IFDEF SupportAnsiString} Assert(IntToStringA(0) = ToAnsiString('0'), 'IntToStringA'); Assert(IntToStringA(1) = ToAnsiString('1'), 'IntToStringA'); Assert(IntToStringA(-1) = ToAnsiString('-1'), 'IntToStringA'); Assert(IntToStringA(10) = ToAnsiString('10'), 'IntToStringA'); Assert(IntToStringA(-10) = ToAnsiString('-10'), 'IntToStringA'); Assert(IntToStringA(123) = ToAnsiString('123'), 'IntToStringA'); Assert(IntToStringA(-123) = ToAnsiString('-123'), 'IntToStringA'); Assert(IntToStringA(MinInt32) = ToAnsiString('-2147483648'), 'IntToStringA'); {$IFNDEF DELPHI7_DOWN} Assert(IntToStringA(-2147483649) = ToAnsiString('-2147483649'), 'IntToStringA'); {$ENDIF} Assert(IntToStringA(MaxInt32) = ToAnsiString('2147483647'), 'IntToStringA'); Assert(IntToStringA(2147483648) = ToAnsiString('2147483648'), 'IntToStringA'); Assert(IntToStringA(MinInt64) = ToAnsiString('-9223372036854775808'), 'IntToStringA'); Assert(IntToStringA(MaxInt64) = ToAnsiString('9223372036854775807'), 'IntToStringA'); {$ENDIF} Assert(IntToStringB(0) = ToRawByteString('0'), 'IntToStringB'); Assert(IntToStringB(1) = ToRawByteString('1'), 'IntToStringB'); Assert(IntToStringB(-1) = ToRawByteString('-1'), 'IntToStringB'); Assert(IntToStringB(10) = ToRawByteString('10'), 'IntToStringB'); Assert(IntToStringB(-10) = ToRawByteString('-10'), 'IntToStringB'); Assert(IntToStringB(123) = ToRawByteString('123'), 'IntToStringB'); Assert(IntToStringB(-123) = ToRawByteString('-123'), 'IntToStringB'); Assert(IntToStringB(MinInt32) = ToRawByteString('-2147483648'), 'IntToStringB'); {$IFNDEF DELPHI7_DOWN} Assert(IntToStringB(-2147483649) = ToRawByteString('-2147483649'), 'IntToStringB'); {$ENDIF} Assert(IntToStringB(MaxInt32) = ToRawByteString('2147483647'), 'IntToStringB'); Assert(IntToStringB(2147483648) = ToRawByteString('2147483648'), 'IntToStringB'); Assert(IntToStringB(MinInt64) = ToRawByteString('-9223372036854775808'), 'IntToStringB'); Assert(IntToStringB(MaxInt64) = ToRawByteString('9223372036854775807'), 'IntToStringB'); Assert(IntToStringU(0) = '0', 'IntToString'); Assert(IntToStringU(1) = '1', 'IntToString'); Assert(IntToStringU(-1) = '-1', 'IntToString'); Assert(IntToStringU(1234567890) = '1234567890', 'IntToString'); Assert(IntToStringU(-1234567890) = '-1234567890', 'IntToString'); Assert(IntToString(0) = '0', 'IntToString'); Assert(IntToString(1) = '1', 'IntToString'); Assert(IntToString(-1) = '-1', 'IntToString'); Assert(IntToString(1234567890) = '1234567890', 'IntToString'); Assert(IntToString(-1234567890) = '-1234567890', 'IntToString'); {$IFDEF SupportAnsiString} Assert(UIntToStringA(0) = ToAnsiString('0'), 'UIntToString'); Assert(UIntToStringA($FFFFFFFF) = ToAnsiString('4294967295'), 'UIntToString'); {$ENDIF} Assert(UIntToStringU(0) = '0', 'UIntToString'); Assert(UIntToStringU($FFFFFFFF) = '4294967295', 'UIntToString'); Assert(UIntToString(0) = '0', 'UIntToString'); Assert(UIntToString($FFFFFFFF) = '4294967295', 'UIntToString'); {$IFDEF SupportAnsiString} Assert(Word32ToStrA(0, 8) = ToAnsiString('00000000'), 'Word32ToStr'); Assert(Word32ToStrA($FFFFFFFF, 0) = ToAnsiString('4294967295'), 'Word32ToStr'); {$ENDIF} Assert(Word32ToStrB(0, 8) = ToRawByteString('00000000'), 'Word32ToStr'); Assert(Word32ToStrB($FFFFFFFF, 0) = ToRawByteString('4294967295'), 'Word32ToStr'); Assert(Word32ToStrU(0, 8) = '00000000', 'Word32ToStr'); Assert(Word32ToStrU($FFFFFFFF, 0) = '4294967295', 'Word32ToStr'); Assert(Word32ToStr(0, 8) = '00000000', 'Word32ToStr'); Assert(Word32ToStr($FFFFFFFF, 0) = '4294967295', 'Word32ToStr'); Assert(Word32ToStr(123) = '123', 'Word32ToStr'); Assert(Word32ToStr(10000) = '10000', 'Word32ToStr'); Assert(Word32ToStr(99999) = '99999', 'Word32ToStr'); Assert(Word32ToStr(1, 1) = '1', 'Word32ToStr'); Assert(Word32ToStr(1, 3) = '001', 'Word32ToStr'); Assert(Word32ToStr(1234, 3) = '1234', 'Word32ToStr'); {$IFDEF SupportAnsiString} Assert(UIntToStringA(0) = ToAnsiString('0'), 'UIntToString'); Assert(UIntToStringA($FFFFFFFF) = ToAnsiString('4294967295'), 'UIntToString'); {$ENDIF} Assert(UIntToStringB(0) = ToRawByteString('0'), 'UIntToString'); Assert(UIntToStringB($FFFFFFFF) = ToRawByteString('4294967295'), 'UIntToString'); Assert(UIntToStringU(0) = '0', 'UIntToString'); Assert(UIntToStringU($FFFFFFFF) = '4294967295', 'UIntToString'); Assert(UIntToString(0) = '0', 'UIntToString'); Assert(UIntToString($FFFFFFFF) = '4294967295', 'UIntToString'); Assert(UIntToString(123) = '123', 'UIntToString'); Assert(UIntToString(10000) = '10000', 'UIntToString'); Assert(UIntToString(99999) = '99999', 'UIntToString'); Assert(UIntToString(1) = '1', 'UIntToString'); Assert(UIntToString(1234) = '1234', 'UIntToString'); Assert(UIntToString($100000000) = '4294967296', 'UIntToString'); Assert(UIntToString(MaxUInt64) = '18446744073709551615', 'UIntToString'); Assert(UIntToString(MaxUInt64 - 5) = '18446744073709551610', 'UIntToString'); {$IFDEF SupportAnsiString} Assert(Word32ToHexA(0, 8) = ToAnsiString('00000000'), 'Word32ToHex'); Assert(Word32ToHexA($FFFFFFFF, 0) = ToAnsiString('FFFFFFFF'), 'Word32ToHex'); Assert(Word32ToHexA($10000) = ToAnsiString('10000'), 'Word32ToHex'); Assert(Word32ToHexA($12345678) = ToAnsiString('12345678'), 'Word32ToHex'); Assert(Word32ToHexA($AB, 4) = ToAnsiString('00AB'), 'Word32ToHex'); Assert(Word32ToHexA($ABCD, 8) = ToAnsiString('0000ABCD'), 'Word32ToHex'); Assert(Word32ToHexA($CDEF, 2) = ToAnsiString('CDEF'), 'Word32ToHex'); Assert(Word32ToHexA($ABC3, 0, False) = ToAnsiString('abc3'), 'Word32ToHex'); {$ENDIF} Assert(Word32ToHexU(0, 8) = '00000000', 'Word32ToHex'); Assert(Word32ToHexU(0) = '0', 'Word32ToHex'); Assert(Word32ToHexU($FFFFFFFF, 0) = 'FFFFFFFF', 'Word32ToHex'); Assert(Word32ToHexU($AB, 4) = '00AB', 'Word32ToHex'); Assert(Word32ToHexU($ABC3, 0, False) = 'abc3', 'Word32ToHex'); Assert(Word32ToHex(0, 8) = '00000000', 'Word32ToHex'); Assert(Word32ToHex($FFFFFFFF, 0) = 'FFFFFFFF', 'Word32ToHex'); Assert(Word32ToHex(0) = '0', 'Word32ToHex'); Assert(Word32ToHex($ABCD, 8) = '0000ABCD', 'Word32ToHex'); Assert(Word32ToHex($ABC3, 0, False) = 'abc3', 'Word32ToHex'); {$IFDEF SupportAnsiString} Assert(StringToIntA(ToAnsiString('0')) = 0, 'StringToInt'); Assert(StringToIntA(ToAnsiString('1')) = 1, 'StringToInt'); Assert(StringToIntA(ToAnsiString('-1')) = -1, 'StringToInt'); Assert(StringToIntA(ToAnsiString('10')) = 10, 'StringToInt'); Assert(StringToIntA(ToAnsiString('01')) = 1, 'StringToInt'); Assert(StringToIntA(ToAnsiString('-10')) = -10, 'StringToInt'); Assert(StringToIntA(ToAnsiString('-01')) = -1, 'StringToInt'); Assert(StringToIntA(ToAnsiString('123')) = 123, 'StringToInt'); Assert(StringToIntA(ToAnsiString('-123')) = -123, 'StringToInt'); {$ENDIF} Assert(StringToIntB(ToRawByteString('321')) = 321, 'StringToInt'); Assert(StringToIntB(ToRawByteString('-321')) = -321, 'StringToInt'); Assert(StringToIntU('321') = 321, 'StringToInt'); Assert(StringToIntU('-321') = -321, 'StringToInt'); {$IFDEF SupportAnsiString} A := ToAnsiString('-012A'); Assert(TryStringToInt64PB(PAnsiChar(A), Length(A), I, L) = convertOK, 'StringToInt'); Assert((I = -12) and (L = 4), 'StringToInt'); A := ToAnsiString('-A012'); Assert(TryStringToInt64PB(PAnsiChar(A), Length(A), I, L) = convertFormatError, 'StringToInt'); Assert((I = 0) and (L = 1), 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('0'), I), 'StringToInt'); Assert(I = 0, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('-0'), I), 'StringToInt'); Assert(I = 0, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('+0'), I), 'StringToInt'); Assert(I = 0, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('1234'), I), 'StringToInt'); Assert(I = 1234, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('-1234'), I), 'StringToInt'); Assert(I = -1234, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('000099999'), I), 'StringToInt'); Assert(I = 99999, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('999999999999999999'), I), 'StringToInt'); Assert(I = 999999999999999999, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('-999999999999999999'), I), 'StringToInt'); Assert(I = -999999999999999999, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('4294967295'), I), 'StringToInt'); Assert(I = $FFFFFFFF, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('4294967296'), I), 'StringToInt'); Assert(I = $100000000, 'StringToInt'); Assert(TryStringToInt64A(ToAnsiString('9223372036854775807'), I), 'StringToInt'); Assert(I = 9223372036854775807, 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(TryStringToInt64A(ToAnsiString('-9223372036854775808'), I), 'StringToInt'); Assert(I = -9223372036854775808, 'StringToInt'); {$ENDIF} Assert(not TryStringToInt64A(ToAnsiString(''), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('-'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('+'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('+-0'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('0A'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('1A'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString(' 0'), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('0 '), I), 'StringToInt'); Assert(not TryStringToInt64A(ToAnsiString('9223372036854775808'), I), 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(not TryStringToInt64A(ToAnsiString('-9223372036854775809'), I), 'StringToInt'); {$ENDIF} {$ENDIF} {$IFDEF SupportAnsiString} Assert(TryStringToUInt64A(ToAnsiString('0'), U), 'StringToInt'); Assert(U = 0, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('1234'), U), 'StringToInt'); Assert(U = 1234, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('000099999'), U), 'StringToInt'); Assert(U = 99999, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('999999999999999999'), U), 'StringToInt'); Assert(U = 999999999999999999, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('4294967295'), U), 'StringToInt'); Assert(U = $FFFFFFFF, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('4294967296'), U), 'StringToInt'); Assert(U = $100000000, 'StringToInt'); Assert(TryStringToUInt64A(ToAnsiString('18446744073709551615'), U), 'StringToInt'); Assert(U = 18446744073709551615, 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString(''), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('-'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('+'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('+-0'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('0A'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('1A'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString(' 0'), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('0 '), U), 'StringToInt'); Assert(not TryStringToUInt64A(ToAnsiString('18446744073709551616'), U), 'StringToInt'); {$ENDIF} Assert(TryStringToInt64U('9223372036854775807', I), 'StringToInt'); Assert(I = 9223372036854775807, 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(TryStringToInt64U('-9223372036854775808', I), 'StringToInt'); Assert(I = -9223372036854775808, 'StringToInt'); Assert(not TryStringToInt64U('', I), 'StringToInt'); Assert(not TryStringToInt64U('-', I), 'StringToInt'); Assert(not TryStringToInt64U('0A', I), 'StringToInt'); Assert(not TryStringToInt64U('9223372036854775808', I), 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(not TryStringToInt64U('-9223372036854775809', I), 'StringToInt'); {$ENDIF} {$ENDIF} Assert(TryStringToInt64('9223372036854775807', I), 'StringToInt'); Assert(I = 9223372036854775807, 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(TryStringToInt64('-9223372036854775808', I), 'StringToInt'); Assert(I = -9223372036854775808, 'StringToInt'); {$ENDIF} Assert(not TryStringToInt64('', I), 'StringToInt'); Assert(not TryStringToInt64('-', I), 'StringToInt'); Assert(not TryStringToInt64('9223372036854775808', I), 'StringToInt'); {$IFNDEF DELPHI7_DOWN} Assert(not TryStringToInt64('-9223372036854775809', I), 'StringToInt'); {$ENDIF} {$IFDEF SupportAnsiString} Assert(StringToInt64A(ToAnsiString('0')) = 0, 'StringToInt64'); Assert(StringToInt64A(ToAnsiString('1')) = 1, 'StringToInt64'); Assert(StringToInt64A(ToAnsiString('-123')) = -123, 'StringToInt64'); Assert(StringToInt64A(ToAnsiString('-0001')) = -1, 'StringToInt64'); Assert(StringToInt64A(ToAnsiString('-9223372036854775807')) = -9223372036854775807, 'StringToInt64'); {$IFNDEF DELPHI7_DOWN} Assert(StringToInt64A(ToAnsiString('-9223372036854775808')) = -9223372036854775808, 'StringToInt64'); {$ENDIF} Assert(StringToInt64A(ToAnsiString('9223372036854775807')) = 9223372036854775807, 'StringToInt64'); Assert(HexToUIntA(ToAnsiString('FFFFFFFF')) = $FFFFFFFF, 'HexStringToUInt'); Assert(HexToUIntA(ToAnsiString('FFFFFFFF')) = $FFFFFFFF, 'HexStringToUInt'); {$ENDIF} Assert(HexToUInt('FFFFFFFF') = $FFFFFFFF, 'HexStringToUInt'); Assert(HexToWord32('FFFFFFFF') = $FFFFFFFF, 'HexToWord32'); Assert(HexToWord32('0') = 0, 'HexToWord32'); Assert(HexToWord32('123456') = $123456, 'HexToWord32'); Assert(HexToWord32('ABC') = $ABC, 'HexToWord32'); Assert(HexToWord32('abc') = $ABC, 'HexToWord32'); Assert(not TryHexToWord32('', W), 'HexToWord32'); Assert(not TryHexToWord32('x', W), 'HexToWord32'); {$IFDEF SupportAnsiString} Assert(HexToWord32A(ToAnsiString('FFFFFFFF')) = $FFFFFFFF, 'HexToWord32'); Assert(HexToWord32A(ToAnsiString('0')) = 0, 'HexToWord32'); Assert(HexToWord32A(ToAnsiString('ABC')) = $ABC, 'HexToWord32'); Assert(HexToWord32A(ToAnsiString('abc')) = $ABC, 'HexToWord32'); Assert(not TryHexToWord32A(ToAnsiString(''), W), 'HexToWord32'); Assert(not TryHexToWord32A(ToAnsiString('x'), W), 'HexToWord32'); {$ENDIF} Assert(HexToWord32B(ToRawByteString('FFFFFFFF')) = $FFFFFFFF, 'HexToWord32'); Assert(HexToWord32B(ToRawByteString('0')) = 0, 'HexToWord32'); Assert(HexToWord32B(ToRawByteString('ABC')) = $ABC, 'HexToWord32'); Assert(HexToWord32B(ToRawByteString('abc')) = $ABC, 'HexToWord32'); Assert(not TryHexToWord32B(ToRawByteString(''), W), 'HexToWord32'); Assert(not TryHexToWord32B(ToRawByteString('x'), W), 'HexToWord32'); Assert(HexToWord32U('FFFFFFFF') = $FFFFFFFF, 'HexToWord32'); Assert(HexToWord32U('0') = 0, 'HexToWord32'); Assert(HexToWord32U('123456') = $123456, 'HexToWord32'); Assert(HexToWord32U('ABC') = $ABC, 'HexToWord32'); Assert(HexToWord32U('abc') = $ABC, 'HexToWord32'); Assert(not TryHexToWord32U('', W), 'HexToWord32'); Assert(not TryHexToWord32U('x', W), 'HexToWord32'); {$IFDEF SupportAnsiString} Assert(not TryStringToWord32A(ToAnsiString(''), W), 'StringToWord32'); Assert(StringToWord32A(ToAnsiString('123')) = 123, 'StringToWord32'); Assert(StringToWord32A(ToAnsiString('4294967295')) = $FFFFFFFF, 'StringToWord32'); Assert(StringToWord32A(ToAnsiString('999999999')) = 999999999, 'StringToWord32'); {$ENDIF} Assert(StringToWord32B(ToRawByteString('0')) = 0, 'StringToWord32'); Assert(StringToWord32B(ToRawByteString('4294967295')) = $FFFFFFFF, 'StringToWord32'); Assert(StringToWord32U('0') = 0, 'StringToWord32'); Assert(StringToWord32U('4294967295') = $FFFFFFFF, 'StringToWord32'); Assert(StringToWord32('0') = 0, 'StringToWord32'); Assert(StringToWord32('4294967295') = $FFFFFFFF, 'StringToWord32'); end; procedure Test_Hash; begin // HashStr {$IFDEF SupportAnsiString} Assert(HashStrA(ToAnsiString('Fundamentals')) = $3FB7796E, 'HashStr'); Assert(HashStrA(ToAnsiString('0')) = $B2420DE, 'HashStr'); Assert(HashStrA(ToAnsiString('Fundamentals'), 1, -1, False) = HashStrA(ToAnsiString('FUNdamentals'), 1, -1, False), 'HashStr'); Assert(HashStrA(ToAnsiString('Fundamentals'), 1, -1, True) <> HashStrA(ToAnsiString('FUNdamentals'), 1, -1, True), 'HashStr'); {$ENDIF} Assert(HashStrB(ToRawByteString('Fundamentals')) = $3FB7796E, 'HashStr'); Assert(HashStrB(ToRawByteString('0')) = $B2420DE, 'HashStr'); Assert(HashStrB(ToRawByteString('Fundamentals'), 1, -1, False) = HashStrB(ToRawByteString('FUNdamentals'), 1, -1, False), 'HashStr'); Assert(HashStrB(ToRawByteString('Fundamentals'), 1, -1, True) <> HashStrB(ToRawByteString('FUNdamentals'), 1, -1, True), 'HashStr'); Assert(HashStrU(ToUnicodeString('Fundamentals')) = $FD6ED837, 'HashStr'); Assert(HashStrU(ToUnicodeString('0')) = $6160DBF3, 'HashStr'); Assert(HashStrU(ToUnicodeString('Fundamentals'), 1, -1, False) = HashStrU(ToUnicodeString('FUNdamentals'), 1, -1, False), 'HashStr'); Assert(HashStrU(ToUnicodeString('Fundamentals'), 1, -1, True) <> HashStrU(ToUnicodeString('FUNdamentals'), 1, -1, True), 'HashStr'); {$IFDEF StringIsUnicode} Assert(HashStr('Fundamentals') = $FD6ED837, 'HashStr'); Assert(HashStr('0') = $6160DBF3, 'HashStr'); {$ELSE} Assert(HashStr('Fundamentals') = $3FB7796E, 'HashStr'); Assert(HashStr('0') = $B2420DE, 'HashStr'); {$ENDIF} Assert(HashStr('Fundamentals', 1, -1, False) = HashStr('FUNdamentals', 1, -1, False), 'HashStr'); Assert(HashStr('Fundamentals', 1, -1, True) <> HashStr('FUNdamentals', 1, -1, True), 'HashStr'); end; procedure Test_Memory; var I, J : Integer; {$IFDEF SupportAnsiString} A, B : AnsiString; {$ENDIF} begin {$IFDEF SupportAnsiString} A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); B := ToAnsiString('0123456789ABC '); Assert(EqualMem(A[1], B[1], 0)); Assert(EqualMem(A[1], B[1], 1)); Assert(EqualMem(A[1], B[1], 13)); Assert(EqualMem(A[13], B[13], 1)); Assert(not EqualMem(A[1], B[1], 14)); Assert(not EqualMem(A[13], B[13], 2)); Assert(not EqualMem(A[14], B[14], 1)); Assert(EqualMem(A[14], B[14], 0)); for I := 1 to 13 do Assert(EqualMem(A[1], B[1], I)); for I := 1 to 13 do Assert(EqualMem(A[I], B[I], 14 - I)); for I := 14 to Length(A) do Assert(not EqualMem(A[1], B[1], I)); for I := 14 to Length(A) do Assert(not EqualMem(A[I], B[I], Length(A) - I + 1)); A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); B := ToAnsiString('0123456789ABC '); Assert(CompareMem(A[1], B[1], 0) = 0); Assert(CompareMem(A[1], B[1], -1) = 0); for I := 1 to 13 do Assert(CompareMem(A[1], B[1], I) = 0); Assert(CompareMem(A[1], B[1], 14) > 0); Assert(CompareMem(A[1], B[1], Length(A)) > 0); for I := 1 to 13 do Assert(CompareMem(B[1], A[1], I) = 0); Assert(CompareMem(B[1], A[1], 14) < 0); Assert(CompareMem(B[1], A[1], Length(A)) < 0); Assert(CompareMem(A[1], A[1], 0) = 0); Assert(CompareMem(A[1], A[1], 1) = 0); Assert(CompareMem(A[1], A[1], Length(A)) = 0); Assert(CompareMem(A[1], A[2], 1) < 0); Assert(CompareMem(A[2], A[1], 1) > 0); Assert(CompareMem(A[1], A[2], 0) = 0); Assert(CompareMem(A[1], A[2], -1) = 0); Assert(CompareMem(Pointer(A), Pointer(A), 1) = 0); Assert(CompareMem(Pointer(A), Pointer(A), Length(A)) = 0); A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); B := ToAnsiString('0123456789ABCDE '); for I := 1 to 15 do Assert(EqualMem(A[1], B[1], I)); Assert(not EqualMem(A[1], B[1], 16)); for I := 1 to 15 do Assert(CompareMem(A[1], B[1], I) = 0); Assert(CompareMem(A[1], B[1], 16) > 0); for I := -1 to 33 do begin A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); B := ToAnsiString(' '); if I > 0 then Assert(not EqualMem(A[1], B[1], I), 'EqualMem'); MoveMem(A[1], B[1], I); for J := 1 to MinInt(I, 10) do Assert(B[J] = AnsiChar(48 + J - 1), 'MoveMem'); for J := 11 to MinInt(I, 36) do Assert(B[J] = AnsiChar(65 + J - 11), 'MoveMem'); for J := MaxInt(I + 1, 1) to 36 do Assert(B[J] = AnsiChar(Ord(' ')), 'MoveMem'); Assert(EqualMem(A[1], B[1], I), 'EqualMem'); end; for J := 1000 to 1500 do begin SetLength(A, 4096); for I := 1 to 4096 do A[I] := AnsiChar(Ord('A')); SetLength(B, 4096); for I := 1 to 4096 do B[I] := AnsiChar(Ord('B')); Assert(not EqualMem(A[1], B[1], J), 'EqualMem'); MoveMem(A[1], B[1], J); for I := 1 to J do Assert(B[I] = AnsiChar(Ord('A')), 'MoveMem'); for I := J + 1 to 4096 do Assert(B[I] = AnsiChar(Ord('B')), 'MoveMem'); Assert(EqualMem(A[1], B[1], J), 'EqualMem'); end; B := ToAnsiString('1234567890'); MoveMem(B[1], B[3], 4); Assert(B = ToAnsiString('1212347890'), 'MoveMem'); MoveMem(B[3], B[2], 4); Assert(B = ToAnsiString('1123447890'), 'MoveMem'); MoveMem(B[1], B[3], 2); Assert(B = ToAnsiString('1111447890'), 'MoveMem'); MoveMem(B[5], B[7], 3); Assert(B = ToAnsiString('1111444470'), 'MoveMem'); MoveMem(B[9], B[10], 1); Assert(B = ToAnsiString('1111444477'), 'MoveMem'); for I := -1 to 33 do begin A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); ZeroMem(A[1], I); for J := 1 to I do Assert(A[J] = AnsiChar(0), 'ZeroMem'); for J := MaxInt(I + 1, 1) to 10 do Assert(A[J] = AnsiChar(48 + J - 1), 'ZeroMem'); for J := MaxInt(I + 1, 11) to 36 do Assert(A[J] = AnsiChar(65 + J - 11), 'ZeroMem'); end; for I := -1 to 33 do begin A := ToAnsiString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); FillMem(A[1], I, Ord('!')); for J := 1 to I do Assert(A[J] = AnsiChar(Ord('!')), 'FillMem'); for J := MaxInt(I + 1, 1) to 10 do Assert(A[J] = AnsiChar(48 + J - 1), 'FillMem'); for J := MaxInt(I + 1, 11) to 36 do Assert(A[J] = AnsiChar(65 + J - 11), 'FillMem'); end; {$ENDIF} end; {$IFDEF ImplementsStringRefCount} procedure Test_StringRefCount; const C1 = 'ABC'; var B, C : RawByteString; {$IFDEF SupportUnicodeString} U, V : UnicodeString; {$ENDIF} begin B := C1; Assert(StringRefCount(B) = -1); C := B; Assert(StringRefCount(C) = -1); C[1] := '1'; Assert(StringRefCount(C) = 1); B := C; Assert(StringRefCount(B) = 2); {$IFDEF SupportUnicodeString} U := C1; Assert(StringRefCount(U) = -1); V := U; Assert(StringRefCount(V) = -1); V[1] := '1'; Assert(StringRefCount(V) = 1); U := V; Assert(StringRefCount(U) = 2); {$ENDIF} end; {$ENDIF} procedure Test; begin {$IFDEF CPU_INTEL386} Set8087CW(Default8087CW); {$ENDIF} Test_Misc; Test_IntStr; Test_Hash; Test_Memory; {$IFDEF ImplementsStringRefCount} Test_StringRefCount; {$ENDIF} end; {$ENDIF} end.