Componentes.Terceros.SDAC/internal/4.10.0.10/1/Source/MemUtils.pas
2007-10-05 14:48:18 +00:00

1683 lines
44 KiB
ObjectPascal

//////////////////////////////////////////////////
// DB Access Components
// Copyright © 1998-2007 Core Lab. All right reserved.
// Mem Data
// Created: 06.11.03
//////////////////////////////////////////////////
{$IFNDEF CLR}
{$I Dac.inc}
unit MemUtils;
{$ENDIF}
interface
uses
Classes, SysUtils, {$IFDEF VER6P}Variants, {$ENDIF}
{$IFDEF HAVE_COMPRESS_INTERNAL}
ZLib, ZLibConst,
{$ENDIF}
{$IFDEF LINUX}
{$ELSE}
Windows,
{$ENDIF}
{$IFDEF CLR}
System.Xml,
System.Runtime.InteropServices;
{$ELSE}
CLRClasses;
{$ENDIF}
{$IFNDEF VER6P}
const
varShortInt = $0010; { vt_i1 }
varWord = $0012; { vt_ui2 }
varLongWord = $0013; { vt_ui4 }
varInt64 = $0014; { vt_i8 }
type
TVarType = Word;
{$ENDIF}
{$IFDEF CLR}
const
wsAttribute: System.Xml.WriteState = System.Xml.WriteState.Attribute;
wsClosed: System.Xml.WriteState = System.Xml.WriteState.Closed;
wsContent: System.Xml.WriteState = System.Xml.WriteState.Content;
wsElement: System.Xml.WriteState = System.Xml.WriteState.Element;
wsStart: System.Xml.WriteState = System.Xml.WriteState.Start;
fmtNone: System.Xml.Formatting = System.Xml.Formatting.None;
fmtIndented: System.Xml.Formatting = System.Xml.Formatting.Indented;
ntNone: System.Xml.XmlNodeType = System.Xml.XmlNodeType.None;
ntElement: System.Xml.XmlNodeType = System.Xml.XmlNodeType.Element;
ntAttribute: System.Xml.XmlNodeType = System.Xml.XmlNodeType.Attribute;
ntEndElement: System.Xml.XmlNodeType = System.Xml.XmlNodeType.EndElement;
ntComment: System.Xml.XmlNodeType = System.Xml.XmlNodeType.Comment;
ntDeclaration: System.Xml.XmlNodeType = System.Xml.XmlNodeType.XmlDeclaration;
ntDocumentType: System.Xml.XmlNodeType = System.Xml.XmlNodeType.DocumentType;
ntText: System.Xml.XmlNodeType = System.Xml.XmlNodeType.Text;
{$ENDIF}
type
{$IFNDEF CLR}
TValueArr = PChar;
{$ELSE}
TValueArr = TBytes;
PChar = string;
PWideChar = string;
POleVariant = IntPtr;
const
{ TStream seek origins compatibility aliases }
soFromBeginning = soBeginning;
soFromCurrent = soCurrent;
soFromEnd = soEnd;
{$ENDIF}
{$IFNDEF VER7P}
const
MSecsPerSec = 1000;
{$ENDIF}
{ CLR compatibility routines }
{$IFDEF CLR}
function CompareMem(P1, P2: IntPtr; Length: integer): boolean;
{$ENDIF}
function CompareGuid(const g1, g2: TGuid): boolean;
function TimeStampToDateTime(const ATimeStamp: TTimeStamp): TDateTime;
function VarEqual(const Value1, Value2: variant): boolean;
procedure OleVarClear(pValue: POleVariant);
function GetOleVariant(pValue: POleVariant): OleVariant;
procedure SetOleVariant(pValue: POleVariant; const Value: OleVariant);
procedure CopyBuffer(Source, Dest: IntPtr; Count: cardinal);
procedure CopyBufferAnsi(const Source: string; Dest: IntPtr; Count{Bytes (#0 included)}: cardinal);
procedure CopyBufferUni(const Source: WideString; Dest: IntPtr; Count{Bytes (#0 included)}: cardinal);
procedure FillChar(X: IntPtr; Count: integer; Value: byte);
procedure FillStr(var S: string; Count: integer; Value: char);
procedure ArrayCopy(sourceArray: TBytes; sourceIndex: integer; destinationArray: TBytes; destinationIndex: integer; length: integer);
function AllocGCHandle(Obj: {$IFDEF CLR}TObject{$ELSE}pointer{$ENDIF}; Pinned: boolean = False): IntPtr;
function GetGCHandleTarget(Handle: IntPtr): TObject;
function GetAddrOfPinnedObject(Handle: IntPtr): IntPtr;
procedure FreeGCHandle(Handle: IntPtr);
function AllocString(var S: string; Length: integer): IntPtr;
procedure FreeString(P: IntPtr);
function AllocOrdinal(var Obj: IntPtr): IntPtr; overload;
function AllocOrdinal(var Obj: shortint): IntPtr; overload;
function AllocOrdinal(var Obj: byte): IntPtr; overload;
function AllocOrdinal(var Obj: word): IntPtr; overload;
function AllocOrdinal(var Obj: integer): IntPtr; overload;
function AllocOrdinal(var Obj: cardinal): IntPtr; overload;
function OrdinalToPtr(var Obj: double): IntPtr; overload;
function OrdinalToPtr(var Obj: byte): IntPtr; overload;
function OrdinalToPtr(var Obj: smallint): IntPtr; overload;
function OrdinalToPtr(var Obj: integer): IntPtr; overload;
function OrdinalToPtr(var Obj: int64): IntPtr; overload;
function OrdinalToPtr(var Obj: cardinal): IntPtr; overload;
function OrdinalToPtr(var Obj: word): IntPtr; overload;
function OrdinalToPtr(var Obj: IntPtr): IntPtr; overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: shortint); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: byte); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: smallint); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: word); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: integer); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: int64); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: cardinal); overload;
procedure PtrToOrdinal(P: IntPtr; var Obj: IntPtr); overload;
procedure FreeOrdinal(P: IntPtr);
{ PChar and PWideChar routines }
{$IFDEF CLR}
procedure StrCopy(Dest: IntPtr; const Source: IntPtr);
function StrComp(const Str1: IntPtr; const Str2: IntPtr): integer;
procedure StrLCopy(Dest: IntPtr; const Source: IntPtr; MaxLen{Chars}: Cardinal);
function StrLen(const Str: IntPtr): Cardinal;
function AnsiUpperCase(const S: string): string;
function AnsiCompareText(const S1, S2: string): integer;
function AnsiCompareStr(const S1, S2: string): integer;
function AnsiSameText(const S1, S2: string): Boolean;
{$ELSE}
function AnsiStrCompS(S1, S2: PChar): Integer; // SORT_STRINGSORT
function AnsiStrICompS(S1, S2: PChar): Integer; // SORT_STRINGSORT
{$ENDIF}
function AnsiCompareTextS(const S1, S2: string): integer; // SORT_STRINGSORT
function AnsiCompareStrS(const S1, S2: string): integer; // SORT_STRINGSORT
function Utf8ToWs(const Dest: TValueArr; DestIdx: Cardinal; MaxDestBytes{w/wo #0}: Cardinal;
const Source: TValueArr; SourceIdx, SourceBytes: Cardinal;
const AddNull: boolean): Cardinal{bytes w/wo #0};
function StrCopyW(Dest: IntPtr; const Source: IntPtr): IntPtr;
procedure StrLCopyW(Dest: IntPtr; const Source: IntPtr; MaxLen{WideChars}: Cardinal);
function StrLenW(const Str: IntPtr): Cardinal;
procedure StrTrim(const Str: IntPtr; Len: integer = -1);
procedure StrTrimW(const Str: IntPtr; Len: integer = -1);
function AnsiStrLCompWS(const S1, S2: WideString; MaxLen: Cardinal): Integer; // SORT_STRINGSORT
function AnsiStrLICompWS(const S1, S2: WideString; MaxLen: Cardinal): Integer; // SORT_STRINGSORT
function AnsiStrCompWS(const S1, S2: WideString): Integer; // SORT_STRINGSORT
function AnsiStrICompWS(const S1, S2: WideString): Integer; // SORT_STRINGSORT
function IsClass(Obj: TObject; AClass: TClass): boolean;
type
{$IFDEF CLR}
TDAList = class(TObject)
FList: array of TObject;
FCount: Integer;
FCapacity: Integer;
protected
function Get(Index: Integer): TObject;
procedure Grow; virtual;
procedure Put(Index: Integer; Item: TObject);
procedure SetCapacity(NewCapacity: Integer);
public
constructor Create;
destructor Destroy; override;
function Add(Item: TObject): Integer;
procedure Clear; virtual;
procedure Delete(Index: Integer);
function IndexOf(Item: TObject): Integer;
function Last: TObject;
function Remove(Item: TObject): Integer;
procedure Sort(Compare: TListSortCompare);
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount;
property Items[Index: Integer]: TObject read Get write Put; default;
end;
{$ELSE}
TDAList = TList;
{$ENDIF}
{$IFNDEF CLR}
function TryEncodeDate(Year, Month, Day: Word; var Date: TDateTime): Boolean;
function TryEncodeTime(Hour, Min, Sec, MSec: Word; var Time: TDateTime): Boolean;
function TryEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
AMilliSecond: Word; out AValue: TDateTime): Boolean;
function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
AMilliSecond: Word): TDateTime;
{$ENDIF}
{$IFNDEF VER6P}
function BoolToStr(const Value: boolean; UseBoolStrs: Boolean = False): string;
function TryStrToBool(const S: string; out Value: Boolean): Boolean;
function StrToBool(const S: string): Boolean;
procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay,
AHour, AMinute, ASecond, AMilliSecond: Word);
function WideUpperCase(const S: WideString): WideString;
function VarToWideStr(const V: Variant): WideString;
{$ENDIF}
{$IFDEF VER6}
function StrToBool(const S: string): Boolean;
function TryStrToBool(const S: string; out Value: Boolean): Boolean;
{$ENDIF}
function Reverse4(Value: cardinal): cardinal;
{$IFNDEF CLR}
procedure Reverse8(pValue: IntPtr);
{$ENDIF}
{$IFDEF VER8}
type
UTF8String = AnsiString deprecated;
function UTF8Encode(const WS: WideString): UTF8String; deprecated;
function UTF8Decode(const S: UTF8String): WideString; deprecated;
{$ENDIF}
{$IFDEF HAVE_COMPRESS}
const
MIN_COMPRESS_LENGTH = 50; // Don't compress small bl.
procedure CheckZLib;
procedure DoCompress(dest: IntPtr; destLen: IntPtr; const source: IntPtr; sourceLen: longint);
procedure DoUncompress(dest: IntPtr; destlen: IntPtr; source: IntPtr; sourceLne: longint);
type
TCompressProc = function(dest: IntPtr; destLen: IntPtr; const source: IntPtr; sourceLen: longint): longint; {$IFDEF LINUX}cdecl;{$ENDIF}
TUncompressProc = function(dest: IntPtr; destlen: IntPtr; source: IntPtr; sourceLne: longint): longint; {$IFDEF LINUX}cdecl;{$ENDIF}
var
CompressProc: TCompressProc;
UncompressProc: TUncompressProc;
{$ENDIF}
{$IFDEF MSWINDOWS}
var
IsWin9x: boolean;
{$ENDIF}
implementation
{$IFDEF CLR}
uses
ActiveX, System.Text,
RTLConsts;
{$ELSE}
uses
{$IFDEF VER6}
SysConst,
{$ENDIF}
DAConsts;
{$ENDIF}
{$IFNDEF CLR}
{$IFDEF MSWINDOWS}
{$DEFINE SORT_STRINGSORT}
{$ENDIF}
{$ENDIF}
{$IFDEF CLR}
[DllImport('kernel32.dll')]
procedure CopyMemory(Dest, Source: IntPtr; Count: cardinal); external;
[DllImport('kernel32.dll')]
function lstrcpy(lpString1, lpString2: IntPtr): IntPtr; external;
[DllImport('kernel32.dll')]
function lstrcpyn(lpString1, lpString2: IntPtr; iMaxLength: Integer): IntPtr; external;
[DllImport('kernel32.dll')]
function lstrcmp(lpString1, lpString2: IntPtr): integer; external;
[DllImport('kernel32.dll')]
function lstrlen(lpString: IntPtr): Integer; external;
[DllImport('kernel32.dll')]
procedure FillMemory(Destination: IntPtr; Length: DWORD; Fill: Byte); external;
function CompareMem(P1, P2: IntPtr; Length: integer): boolean;
var
i: integer;
begin
Result := False;
for i := 0 to Length - 1 do begin
if Marshal.ReadByte(P1) <> Marshal.ReadByte(P2) then
Exit;
P1 := IntPtr(integer(P1) + 1);
P2 := IntPtr(integer(P2) + 1);
end;
Result := True;
end;
function CompareGuid(const g1, g2: TGuid): boolean;
begin
Result := g1 = g2;
end;
{$ELSE}
function CompareGuid(const g1, g2: TGuid): boolean;
begin
Result := CompareMem(@g1, @g2, SizeOf(TGuid));
end;
{$ENDIF}
function TimeStampToDateTime(const ATimeStamp: TTimeStamp): TDateTime;
procedure ValidateTimeStamp(const ATimeStamp: TTimeStamp);
begin
if (ATimeStamp.Time < 0) or (ATimeStamp.Date <= 0) then
raise EConvertError.Create(Format('''%d.%d'' is not a valid timestamp', [ATimeStamp.Date, ATimeStamp.Time]));
end;
begin
ValidateTimeStamp(ATimeStamp);
Result := ATimeStamp.Date - DateDelta;
{$IFNDEF CLR}
if Result < 0 then
Result := Result - (ATimeStamp.Time / MSecsPerDay)
else
{$ENDIF}
Result := Result + (ATimeStamp.Time / MSecsPerDay);
end;
// bug in D8 in compare strings as variant type
function VarEqual(const Value1, Value2: variant): boolean;
var
{$IFDEF CLR}
va_old, va_new: TBytes;
i: integer;
{$ELSE}
va_old, va_new: PVarArray;
va_data_old, va_data_new: IntPtr;
{$ENDIF}
begin
{$IFDEF CLR}
if (Value1 <> nil) and (Value2 <> nil) and
(integer(Convert.GetTypeCode(Value1)) = 18) and (integer(Convert.GetTypeCode(Value2)) = 18)
then
Result := System.String.CompareOrdinal(string(Value1), string(Value2)) = 0
else
{$ELSE}
// prevent comparing as AnsiString
if (VarType(Value1) = 8) and ((VarType(Value2) = 8) or (VarType(Value2) = 256)) or
(VarType(Value2) = 8) and ((VarType(Value1) = 8) or (VarType(Value1) = 256))
then
Result := WideString(Value1) = WideString(Value2)
else
{$ENDIF}
if (VarType(Value1) = varNull) and (VarType(Value2) = varNull) then
Result := True
else
if (VarType(Value1) = varNull) or (VarType(Value2) = varNull) or
(VarType(Value2) <> VarType(Value2)) then
Result := False
else
if (VarType(Value1) = varArray + varByte) or
(VarType(Value2) = varArray + varByte) then begin
{$IFDEF CLR}
va_old := Value1;
va_new := Value2;
if (va_old = nil) and (va_new = nil) then
Result := True
else
if (va_old = nil) or (va_new = nil) or
(Length(va_old) <> Length(va_new)) then
Result := False
else begin
Result := True;
for i := Low(va_old) to High(va_old) do
if va_old[i] <> va_new[i] then begin
Result := False;
Break;
end;
end;
{$ELSE}
va_old := TVarData(Value1).VArray;
va_new := TVarData(Value2).VArray;
if (va_old = nil) and (va_new = nil) then
Result := True
else
if (va_old = nil) or (va_new = nil) or
(va_old.Bounds[0].ElementCount <> va_new.Bounds[0].ElementCount) then
Result := False
else begin
va_data_old := va_old.Data;
va_data_new := va_new.Data;
if (va_data_old = nil) and (va_data_new = nil) then
Result := True
else
if (va_data_old = nil) or (va_data_new = nil) then
Result := False
else
Result := CompareMem(va_data_old, va_data_new, va_old.Bounds[0].ElementCount);
end;
{$ENDIF}
end
else
Result := Value1 = Value2;
end;
procedure CopyBuffer(Source, Dest: IntPtr; Count: cardinal);
begin
{$IFDEF CLR}
CopyMemory(Dest, Source, Count);
{$ELSE}
Move(Source^, Dest^, Count);
{$ENDIF}
end;
procedure CopyBufferAnsi(const Source: string; Dest: IntPtr; Count{Bytes (#0 included)}: cardinal);
{$IFDEF CLR}
var
buf: TBytes;
CountInt: integer; // To prevent CLR compiler error
begin
SetLength(buf, Count);
CountInt := Convert.ToInt32(Count); // To prevent CLR compiler error
Encoding.Default.GetBytes(Source, 0, CountInt - 1{#0}, buf, 0);
buf[CountInt - 1] := 0;
Marshal.Copy(buf, 0, Dest, CountInt);
end;
{$ELSE}
begin
CopyBuffer(PChar(Source), Dest, Count);
end;
{$ENDIF}
procedure CopyBufferUni(const Source: WideString; Dest: IntPtr; Count{Bytes (#0#0 included)}: cardinal);
{$IFDEF CLR}
var
buf: TBytes;
CountInt: integer; // To prevent CLR compiler error
begin
SetLength(buf, Count);
CountInt := Convert.ToInt32(Count); // To prevent CLR compiler error
Encoding.Unicode.GetBytes(Source, 0, (CountInt - 1{#0}) shr 1, buf, 0);
buf[CountInt - 1] := 0;
buf[CountInt - 2] := 0;
Marshal.Copy(buf, 0, Dest, CountInt);
end;
{$ELSE}
begin
CopyBuffer(PWideChar(Source), Dest, Count);
end;
{$ENDIF}
procedure FillChar(X: IntPtr; Count: integer; Value: byte);
begin
{$IFDEF CLR}
FillMemory(X, Count, Value);
{$ELSE}
System.FillChar(X^, Count, Value);
{$ENDIF}
end;
procedure FillStr(var S: string; Count: integer; Value: char);
begin
{$IFDEF CLR}
S := System.String.Create(Value, Count);
{$ELSE}
SetLength(S, Count);
FillChar(PChar(S), Count, byte(Value));
{$ENDIF}
end;
procedure ArrayCopy(sourceArray: TBytes; sourceIndex: integer; destinationArray: TBytes; destinationIndex: integer; length: integer);
begin
{$IFDEF CLR}
System.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length);
{$ELSE}
System.Move(sourceArray[sourceIndex], destinationArray[destinationIndex], length);
{$ENDIF}
end;
function AllocGCHandle(Obj: {$IFDEF CLR}TObject{$ELSE}pointer{$ENDIF};
Pinned: boolean = False): IntPtr;
begin
{$IFDEF CLR}
if Pinned then
Result := IntPtr(GCHandle.Alloc(Obj, GCHandleType.Pinned))
else
Result := IntPtr(GCHandle.Alloc(Obj, GCHandleType.Normal));
{$ELSE}
Result := Obj;
{$ENDIF}
end;
function GetGCHandleTarget(Handle: IntPtr): TObject;
begin
{$IFDEF CLR}
if Handle = nil then
Result := nil
else
Result := GCHandle(Handle).Target;
{$ELSE}
Result := Handle;
{$ENDIF}
end;
function GetAddrOfPinnedObject(Handle: IntPtr): IntPtr;
begin
{$IFDEF CLR}
Result := GCHandle(Handle).AddrOfPinnedObject;
{$ELSE}
Result := Handle;
{$ENDIF}
end;
procedure FreeGCHandle(Handle: IntPtr);
begin
{$IFDEF CLR}
GCHandle(Handle).Free;
{$ELSE}
{$ENDIF}
end;
function AllocString(var S: string; Length: integer): IntPtr;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(Length + 1);
{$ELSE}
SetLength(S, Length);
Result := PChar(S);
{$ENDIF}
end;
procedure FreeString(P: IntPtr);
begin
{$IFDEF CLR}
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
function AllocOrdinal(var Obj: shortint): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(shortint));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function AllocOrdinal(var Obj: byte): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(byte));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function AllocOrdinal(var Obj: word): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(word));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function AllocOrdinal(var Obj: integer): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(integer));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function AllocOrdinal(var Obj: cardinal): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(integer));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function AllocOrdinal(var Obj: IntPtr): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(IntPtr));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: double): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(Int64));
Marshal.WriteInt64(Result, BitConverter.DoubleToInt64Bits(Obj));
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: byte): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(byte));
Marshal.WriteByte(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: smallint): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(smallint));
Marshal.WriteInt16(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: integer): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(integer));
Marshal.WriteInt32(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: int64): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(int64));
Marshal.WriteInt64(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: cardinal): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(cardinal));
Marshal.WriteInt32(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: word): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(word));
Marshal.WriteInt16(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
function OrdinalToPtr(var Obj: IntPtr): IntPtr; overload;
begin
{$IFDEF CLR}
Result := Marshal.AllocHGlobal(sizeof(integer));
Marshal.WriteIntPtr(Result, Obj);
{$ELSE}
Result := @Obj;
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: shortint); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadByte(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: byte); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadByte(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: smallint); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadInt16(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: word); overload;
begin
{$IFDEF CLR}
Obj := Word(Marshal.ReadInt32(P));
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: integer); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadInt32(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: int64); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadInt64(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: cardinal); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadInt32(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure PtrToOrdinal(P: IntPtr; var Obj: IntPtr); overload;
begin
{$IFDEF CLR}
Obj := Marshal.ReadIntPtr(P);
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
procedure FreeOrdinal(P: IntPtr);
begin
{$IFDEF CLR}
Marshal.FreeHGlobal(P);
{$ELSE}
{$ENDIF}
end;
{$IFDEF CLR}
procedure StrCopy(Dest: IntPtr; const Source: IntPtr);
begin
Win32Check(lstrcpy(Dest, Source) <> nil);
end;
procedure StrLCopy(Dest: IntPtr; const Source: IntPtr; MaxLen{Chars}: Cardinal);
begin
Win32Check(lstrcpyn(Dest, Source, Integer(MaxLen + 1)) <> nil);
end;
function StrComp(const Str1: IntPtr; const Str2: IntPtr): integer;
begin
Result := lstrcmp(Str1, Str2);
end;
function StrLen(const Str: IntPtr): Cardinal;
begin
Result := lstrlen(Str);
end;
function StrLenW(const Str: IntPtr): Cardinal;
var
s: WideString;
begin
s := Marshal.PtrToStringUni(Str);
Result := s.Length;
end;
procedure StrTrim(const Str: IntPtr; Len: integer = -1);
var
i: integer;
v: byte;
begin
if Len = - 1 then // Detect length
Len := StrLen(Str);
i := Integer(Str) + Len - 1;
while True do begin
v := Marshal.ReadByte(IntPtr(i));
if ((v <> 32 {Byte(' ')}) and (v <> 0{Byte(#0)})) or (i < Integer(Str)) then
Exit;
Marshal.WriteByte(IntPtr(i), Byte(#0));
Dec(i);
end;
end;
procedure StrTrimW(const Str: IntPtr; Len: integer = -1);
var
i: integer;
v: smallint;
begin
if Len = - 1 then // Detect length
Len := StrLenW(Str);
i := Integer(Str) + (Len - 1) shl 1;
while True do begin
v := Marshal.ReadInt16(IntPtr(i));
if ((v <> 32 {SmallInt(' ')}) and (v <> 0{SmallInt(#0)})) or (i < Integer(Str)) then
Exit;
Marshal.WriteInt16(IntPtr(i), SmallInt(#0));
Dec(i);
Dec(i);
end;
end;
{$ENDIF}
function StrCopyW(Dest: IntPtr; const Source: IntPtr): IntPtr;
{$IFDEF CLR}
var
Buf: smallint;
i: integer;
begin
i := 0;
repeat
Buf := Marshal.ReadInt16(Source, i);
Marshal.WriteInt16(Dest, i, Buf);
Inc(i, 2);
until Buf = 0;
{$ELSE}
asm
PUSH EDI
PUSH ESI
MOV ESI,EAX
MOV EDI,EDX
MOV ECX,0FFFFFFFFH
XOR AX,AX
REPNE SCASW
NOT ECX
SHL ECX, 1 // Size := Len * sizeof(WideChar)
MOV EDI,ESI
MOV ESI,EDX
MOV EDX,ECX
MOV EAX,EDI
SHR ECX,2
REP MOVSD
MOV ECX,EDX
AND ECX,3
REP MOVSB
POP ESI
POP EDI
{$ENDIF}
end;
procedure StrLCopyW(Dest: IntPtr; const Source: IntPtr; MaxLen{WideChars}: Cardinal);
{$IFDEF CLR}
var
Buf: smallint;
i: cardinal;
begin
i := 0;
Buf := 0;
while i < MaxLen * 2 do begin
Buf := Marshal.ReadInt16(Source, i);
Marshal.WriteInt16(Dest, i, Buf);
if Buf = 0 then
Break;
Inc(i, 2);
end;
if Buf <> 0 then
Marshal.WriteInt16(Dest, i, 0);
{$ELSE}
var
pwc: PWideChar;
begin
pwc := Source;
while (pwc^ <> #0) and (pwc < PWideChar(Source) + MaxLen) do begin
PWideChar(Dest)^ := pwc^;
Inc(PWideChar(Dest));
Inc(pwc);
end;
PWideChar(Dest)^ := #0;
{$ENDIF}
end;
{$IFNDEF CLR}
function StrLenW(const Str: IntPtr): Cardinal; assembler;
asm
MOV EDX,EDI
MOV EDI,EAX
MOV ECX,0FFFFFFFFH
XOR AX,AX
REPNE SCASW
MOV EAX,0FFFFFFFEH
SUB EAX,ECX
MOV EDI,EDX
end;
procedure StrTrim(const Str: IntPtr; Len: integer = -1);
var
pc: PChar;
begin
if Len = - 1 then // Detect length
Len := StrLen(Str);
pc := PChar(Str) + Len - 1;
while ((pc^ = ' ') or (pc^ = #0)) and (pc >= Str) do begin
pc^ := #0;
Dec(pc);
end;
end;
procedure StrTrimW(const Str: IntPtr; Len: integer = -1);
var
pwc: PWideChar;
begin
if Len = - 1 then // Detect length
Len := StrLenW(Str);
pwc := PWideChar(Str) + Len - 1;
while ((pwc^ = ' ') or (pwc^ = #0)) and (pwc >= Str) do begin
PWideChar(pwc)^ := #0;
Dec(pwc);
end;
end;
{$ENDIF}
function AnsiStrLCompWS(const S1, S2: WideString; MaxLen: Cardinal): Integer;
begin
{$IFDEF MSWINDOWS}
Assert(not IsWin9x, 'Unicode support on Win9x');
{$IFDEF CLR}
Result := CompareStringW(LOCALE_USER_DEFAULT, SORT_STRINGSORT, S1, MaxLen, S2, MaxLen) - 2;
{$ELSE}
Result := CompareStringW(LOCALE_USER_DEFAULT, SORT_STRINGSORT, PWideChar(S1), MaxLen,
PWideChar(S2), MaxLen) - 2;
{$ENDIF}
{$ELSE}
Result := 0;
Assert(False);
{$ENDIF}
end;
function AnsiStrLICompWS(const S1, S2: WideString; MaxLen: Cardinal): Integer;
begin
{$IFDEF MSWINDOWS}
Assert(not IsWin9x, 'Unicode support on Win9x');
{$IFDEF CLR}
Result := CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT,
S1, MaxLen, S2, MaxLen) - 2;
{$ELSE}
Result := CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT,
PWideChar(S1), MaxLen, PWideChar(S2), MaxLen) - 2;
{$ENDIF}
{$ELSE}
Result := 0;
Assert(False);
{$ENDIF}
end;
function AnsiStrCompWS(const S1, S2: WideString): Integer;
begin
{$IFDEF MSWINDOWS}
Assert(not IsWin9x, 'Unicode support on Win9x');
{$IFDEF CLR}
Result := CompareStringW(LOCALE_USER_DEFAULT, SORT_STRINGSORT, S1, -1, S2, -1) - 2;
{$ELSE}
Result := CompareStringW(LOCALE_USER_DEFAULT, SORT_STRINGSORT, PWideChar(S1), -1,
PWideChar(S2), -1) - 2;
{$ENDIF}
{$ELSE}
Result := 0;
Assert(False);
{$ENDIF}
end;
function AnsiStrICompWS(const S1, S2: WideString): Integer;
begin
{$IFDEF MSWINDOWS}
Assert(not IsWin9x, 'Unicode support on Win9x');
{$IFDEF CLR}
Result := CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT, S1, -1,
S2, -1) - 2;
{$ELSE}
Result := CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT, PWideChar(S1),
-1, PWideChar(S2), -1) - 2;
{$ENDIF}
{$ELSE}
Result := 0;
Assert(False);
{$ENDIF}
end;
function IsClass(Obj: TObject; AClass: TClass): boolean;
function IsClassByName(Obj: TObject; AClass: TClass): boolean;
var
ParentClass: TClass;
begin
Result := False;
ParentClass := Obj.ClassType;
while ParentClass <> nil do begin
Result := ParentClass.ClassName = AClass.ClassName;
if not Result then
ParentClass := ParentClass.ClassParent
else
Break;
end;
end;
begin
if IsLibrary then
Result := IsClassByName(Obj, AClass)
else
Result := Obj is AClass;
end;
{$IFDEF CLR}
function AnsiUpperCase(const S: string): string;
begin
if S <> nil then
Result := System.String(S).ToUpper
else
Result := '';
end;
function AnsiCompareText(const S1, S2: string): integer;
begin
Result := System.String.Compare(S1, S2, True);
end;
function AnsiCompareStr(const S1, S2: string): integer;
begin
Result := System.String.Compare(S1, S2, False);
end;
function AnsiSameText(const S1, S2: string): Boolean;
begin
Result := System.String.Compare(S1, S2, True) = 0;
end;
{$ELSE}
function AnsiStrCompS(S1, S2: PChar): Integer; // SORT_STRINGSORT
begin
{$IFDEF SORT_STRINGSORT}
Result := CompareString(LOCALE_USER_DEFAULT, SORT_STRINGSORT, S1, -1, S2, -1) - 2;
{$ELSE}
Result := AnsiStrComp(S1, S2);
{$ENDIF}
end;
function AnsiStrICompS(S1, S2: PChar): Integer; // SORT_STRINGSORT
begin
{$IFDEF SORT_STRINGSORT}
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT, S1, -1,
S2, -1) - 2;
{$ELSE}
Result := AnsiStrIComp(S1, S2);
{$ENDIF}
end;
{$ENDIF}
function AnsiCompareTextS(const S1, S2: string): integer; // SORT_STRINGSORT
begin
{$IFDEF SORT_STRINGSORT}
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE + SORT_STRINGSORT, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
{$ELSE}
Result := AnsiCompareText(S1, S2);
{$ENDIF}
end;
function AnsiCompareStrS(const S1, S2: string): integer; // SORT_STRINGSORT
begin
{$IFDEF SORT_STRINGSORT}
Result := CompareString(LOCALE_USER_DEFAULT, SORT_STRINGSORT, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
{$ELSE}
Result := AnsiCompareStr(S1, S2);
{$ENDIF}
end;
// Convert Utf8 buffer to WideString buffer with or without null terminator.
// Nearly copied from System.Utf8ToUnicode
function Utf8ToWs(const Dest: TValueArr; DestIdx: Cardinal; MaxDestBytes{w/wo #0}: Cardinal;
const Source: TValueArr; SourceIdx, SourceBytes: Cardinal;
const AddNull: boolean): Cardinal{bytes w/wo #0};
var
i: Cardinal;
c: Byte;
wc: Cardinal;
begin
Assert(Source <> nil, 'Utf8ToWs: Source is nil');
Assert(Dest <> nil, 'Utf8ToWs: Destination is nil');
{$IFDEF CLR}
Assert(Integer(DestIdx + MaxDestBytes) <= Length(Dest), 'Utf8ToWs: DestIdx = ' + IntToStr(DestIdx) + ', MaxDestBytes = ' + IntToStr(MaxDestBytes) + ', Length(Dest) = ' + IntToStr(Length(Dest)));
Assert(Integer(SourceIdx + SourceBytes) <= Length(Source), 'Utf8ToWs: SourceIdx = ' + IntToStr(SourceIdx) + ', SourceBytes = ' + IntToStr(SourceBytes) + ', Length(Source) = ' + IntToStr(Length(Source)));
{$ENDIF}
Result := 0;
i := SourceIdx;
while i < SourceIdx + SourceBytes do
begin
wc := Cardinal(Source[Integer(i)]);
if wc = 0 then //zero terminator
break;
Inc(i);
if (wc and $80) <> 0 then
begin
Assert(i < SourceIdx + SourceBytes, 'Utf8ToWs: Incomplete multibyte char');
wc := wc and $3F;
if (wc and $20) <> 0 then
begin
c := Byte(Source[Integer(i)]);
Inc(i);
Assert((c and $C0) = $80, 'Utf8ToWs: Malformed trail byte or out of range char');
Assert(i < SourceIdx + SourceBytes, 'Utf8ToWs: Incomplete multibyte char');
wc := (wc shl 6) or (c and $3F);
end;
c := Byte(Source[Integer(i)]);
Inc(i);
Assert((c and $C0) = $80, 'Utf8ToWs: Malformed trail byte');
wc := (wc shl 6) or (c and $3F);
end;
if not (Result + 1 < MaxDestBytes) then
Break;
{$IFDEF CLR}
Dest[Integer(Result + DestIdx)] := Byte(wc);
Dest[Integer(Result + DestIdx + 1)] := Byte(wc shr 8);
{$ELSE}
Cardinal(Pointer(Cardinal(Dest) + DestIdx + Result)^) := wc;
{$ENDIF}
Inc(Result, SizeOf(WideChar));
end;
if AddNull and (MaxDestBytes > 0) then begin
if Result >= MaxDestBytes then
Result := MaxDestBytes - SizeOf(WideChar);
{$IFDEF CLR}
Dest[Integer(Result + DestIdx)] := 0;
Dest[Integer(Result + DestIdx + 1)] := 0;
{$ELSE}
Marshal.WriteInt16(Dest, Integer(DestIdx + Result), 0);
{$ENDIF}
Inc(Result, SizeOf(WideChar));
end;
end;
{$IFDEF CLR}
{ TDAList }
constructor TDAList.Create;
begin
inherited Create;
SetCapacity(10);
end;
destructor TDAList.Destroy;
begin
Clear;
inherited;
end;
procedure TDAList.Clear;
begin
FCount := 0;
SetCapacity(0);
end;
procedure TDAList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then
TList.Error({$IFNDEF CLR}@{$ENDIF}SListIndexError, Index);
Dec(FCount);
if Index < FCount then
{$IFDEF CLR}
System.Array.Copy(FList, Index + 1, FList, Index, FCount - Index);
{$ELSE}//TODO
System.Move(FList[Index + 1], FList[Index],
(FCount - Index) * SizeOf(Pointer));
{$ENDIF}
end;
function TDAList.IndexOf(Item: TObject): Integer;
begin
Result := 0;
while (Result < FCount) and (FList[Result] <> Item) do
Inc(Result);
if Result = FCount then
Result := -1;
end;
function TDAList.Last: TObject;
begin
Result := Get(FCount - 1);
end;
function TDAList.Remove(Item: TObject): Integer;
begin
Result := IndexOf(Item);
if Result >= 0 then
Delete(Result);
end;
procedure QuickSort(var SortList: array of TObject; L, R: Integer;
SCompare: TListSortCompare);
var
I, J: Integer;
P, T: TObject;
begin
repeat
I := L;
J := R;
P := SortList[(L + R) shr 1];
repeat
while SCompare(SortList[I], P) < 0 do
Inc(I);
while SCompare(SortList[J], P) > 0 do
Dec(J);
if I <= J then
begin
T := SortList[I];
SortList[I] := SortList[J];
SortList[J] := T;
Inc(I);
Dec(J);
end;
until I > J;
if L < J then
QuickSort(SortList, L, J, SCompare);
L := I;
until I >= R;
end;
procedure TDAList.Sort(Compare: TListSortCompare);
begin
if (FList <> nil) and (Count > 0) then
QuickSort(FList, 0, Count - 1, Compare);
end;
function TDAList.Add(Item: TObject): Integer;
begin
Result := FCount;
if Result = FCapacity then
Grow;
FList[Result] := Item;
Inc(FCount);
end;
function TDAList.Get(Index: Integer): TObject;
begin
if (Index < 0) or (Index >= FCount) then
TList.Error({$IFNDEF CLR}@{$ENDIF}SListIndexError, Index);
Result := FList[Index];
end;
procedure TDAList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;
procedure TDAList.Put(Index: Integer; Item: TObject);
begin
if (Index < 0) or (Index >= FCount) then
TList.Error({$IFNDEF CLR}@{$ENDIF}SListIndexError, Index);
FList[Index] := Item;
end;
procedure TDAList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
TList.Error({$IFNDEF CLR}@{$ENDIF}SListCapacityError, NewCapacity);
if NewCapacity <> FCapacity then
begin
SetLength(FList, NewCapacity);
FCapacity := NewCapacity;
end;
end;
{$ENDIF}
{$IFDEF CLR}
const
ole32 = 'ole32.dll';
oleaut32 = 'oleaut32.dll';
// Copied from ActiveX.pas (d7)
const
STGM_READ = $00000000;
[DllImport(oleaut32, CharSet = CharSet.Ansi, SetLastError = True, EntryPoint = 'VariantClear')]
function VariantClear(Value: POleVariant): HResult; external;
procedure OleVarClear(pValue: POleVariant);
begin
SetOleVariant(pValue, Unassigned);
end;
function GetOleVariant(pValue: POleVariant): OleVariant;
begin
Result := OleVariant(Marshal.GetObjectForNativeVariant(pValue));
// Result := OleVariant(Marshal.PtrToStructure(pValue, TypeOf(OleVariant)));
end;
procedure SetOleVariant(pValue: POleVariant; const Value: OleVariant);
begin
Marshal.GetNativeVariantForObject(TObject(Value), pValue);
end;
{$ELSE}
procedure OleVarClear(pValue: POleVariant);
begin
pValue^ := Unassigned;
end;
function GetOleVariant(pValue: POleVariant): OleVariant;
begin
Result := pValue^;
end;
procedure SetOleVariant(pValue: POleVariant; const Value: OleVariant);
begin
pValue^ := Value;
end;
{$ENDIF}
{$IFNDEF VER6P}
function BoolToStr(const Value: boolean; UseBoolStrs: Boolean = False): string;
const
cSimpleBoolStrs: array [boolean] of String = ('0', '-1');
begin
if UseBoolStrs then
begin
if Value then
Result := 'True'
else
Result := 'False';
end
else
Result := cSimpleBoolStrs[Value];
end;
function TryStrToBool(const S: string; out Value: Boolean): Boolean;
begin
Result := True;
if SameText(s, 'True') or SameText(s, 'Yes') or SameText(s, '1') then
Value := True
else
if SameText(s, 'False') or SameText(s, 'No') or SameText(s, '0') then
Value := False
else
Result := False;
end;
function StrToBool(const S: string): Boolean;
begin
if not TryStrToBool(S, Result) then
raise EConvertError.Create('InvalidBoolean - ' + S);
end;
type
PWordBool = ^WordBool;
procedure DecodeDateTime(const AValue: TDateTime; out AYear, AMonth, ADay,
AHour, AMinute, ASecond, AMilliSecond: Word);
begin
DecodeDate(AValue, AYear, AMonth, ADay);
DecodeTime(AValue, AHour, AMinute, ASecond, AMilliSecond);
end;
function WideUpperCase(const S: WideString): WideString;
var
Len: Integer;
begin
Len := Length(S);
SetString(Result, PWideChar(S), Len);
if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
end;
function VarToWideStr(const V: Variant): WideString;
begin
if not VarIsNull(V) then
Result := V
else
Result := '';;
end;
{$ENDIF}
{$IFDEF VER6}
procedure ConvertErrorFmt(ResString: PResStringRec; const Args: array of const); local;
begin
raise EConvertError.CreateResFmt(ResString, Args);
end;
function StrToBool(const S: string): Boolean;
begin
if not TryStrToBool(S, Result) then
ConvertErrorFmt(@SInvalidBoolean, [S]);
end;
procedure VerifyBoolStrArray;
begin
if Length(TrueBoolStrs) = 0 then
begin
SetLength(TrueBoolStrs, 1);
TrueBoolStrs[0] := DefaultTrueBoolStr;
end;
if Length(FalseBoolStrs) = 0 then
begin
SetLength(FalseBoolStrs, 1);
FalseBoolStrs[0] := DefaultFalseBoolStr;
end;
end;
function TryStrToBool(const S: string; out Value: Boolean): Boolean;
function CompareWith(const aArray: array of string): Boolean;
var
I: Integer;
begin
Result := False;
for I := Low(aArray) to High(aArray) do
if AnsiSameText(S, aArray[I]) then
begin
Result := True;
Break;
end;
end;
var
LResult: Extended;
begin
Result := TryStrToFloat(S, LResult);
if Result then
Value := LResult <> 0
else
begin
VerifyBoolStrArray;
Result := CompareWith(TrueBoolStrs);
if Result then
Value := True
else
begin
Result := CompareWith(FalseBoolStrs);
if Result then
Value := False;
end;
end;
end;
{$ENDIF}
{$IFNDEF CLR}
function TryEncodeDate(Year, Month, Day: Word; var Date: TDateTime): Boolean;
var
I: Integer;
DayTable: PDayTable;
begin
Result := False;
DayTable := @MonthDays[IsLeapYear(Year)];
if (Year >= 1) and (Year <= 9999) and (Month >= 1) and (Month <= 12) and
(Day >= 1) and (Day <= DayTable^[Month]) then
begin
for I := 1 to Month - 1 do Inc(Day, DayTable^[I]);
I := Year - 1;
Date := I * 365 + I div 4 - I div 100 + I div 400 + Day - DateDelta;
Result := True;
end;
end;
function TryEncodeTime(Hour, Min, Sec, MSec: Word; var Time: TDateTime): Boolean;
begin
Result := False;
if (Hour < 24) and (Min < 60) and (Sec < 60) and (MSec < 1000) then
begin
Time := (Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / MSecsPerDay;
Result := True;
end;
end;
function TryEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
AMilliSecond: Word; out AValue: TDateTime): Boolean;
var
LTime: TDateTime;
begin
Result := TryEncodeDate(AYear, AMonth, ADay, AValue);
if Result then
begin
Result := TryEncodeTime(AHour, AMinute, ASecond, AMilliSecond, LTime);
if Result then
if AValue > 0 then
AValue := AValue + LTime
else
AValue := AValue - LTime;
end;
end;
function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond,
AMilliSecond: Word): TDateTime;
begin
if not TryEncodeDateTime(AYear, AMonth, ADay,
AHour, AMinute, ASecond, AMilliSecond, Result) then
raise EConvertError.Create(SDateEncodeError);
end;
{$ENDIF}
function Reverse4(Value: cardinal): cardinal;
begin
Result := Cardinal((byte(Value) shl 24) or (byte(Value shr 8) shl 16)
or (byte(Value shr 16) shl 8) or byte(Value shr 24));
end;
{$IFNDEF CLR}
procedure Reverse8(pValue: IntPtr);
var
FirstByte: PByte;
LastByte: PByte;
TmpValue: Byte;
i: integer;
begin
FirstByte := PByte(pValue);
LastByte := FirstByte;
Inc(LastByte, SizeOf(Int64) - 1);
for i := 0 to 3 do begin
TmpValue := LastByte^;
LastByte^ := FirstByte^;
FirstByte^ := TmpValue;
Inc(FirstByte);
Dec(LastByte);
end;
end;
{$ENDIF}
{$IFDEF VER8}
function UTF8Encode(const WS: WideString): UTF8String;
begin
Result := UTF8String(System.Array(nil));
if Assigned(WS) then
Result := System.Text.Encoding.UTF8.GetBytes(WS);
end;
function UTF8Decode(const S: UTF8String): WideString;
begin
Result := WideString(System.String(nil));
if Assigned(S) then
Result := System.Text.Encoding.UTF8.GetString(TBytes(S), 0, High(TBytes(S)) + 1);
end;
{$ENDIF}
{$IFDEF HAVE_COMPRESS}
procedure CheckZLib;
begin
if not Assigned(CompressProc) then
raise Exception.Create(SCompressorNotLinked);
if not Assigned(UncompressProc) then
raise Exception.Create(SUncompressorNotLinked);
end;
procedure DoCompress(dest: IntPtr; destLen: IntPtr; const source: IntPtr; sourceLen: longint);
begin
Assert(Assigned(CompressProc), SCompressorNotLinked);
CompressProc(dest, destLen, source, sourceLen)
end;
procedure DoUncompress(dest: IntPtr; destlen: IntPtr; source: IntPtr; sourceLne: longint);
begin
Assert(Assigned(UncompressProc), SUncompressorNotLinked);
UncompressProc(dest, destLen, source, sourceLne)
end;
{$IFDEF HAVE_COMPRESS_INTERNAL}
function CCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
raise ECompressionError.Create(sError);
end;
function DCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
raise EDecompressionError.Create(sError);
end;
function compress(dest: IntPtr; destLen: IntPtr; const source: IntPtr; sourceLen: longint): longint;
var
strm: TZStreamRec;
begin
FillChar(@strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
strm.next_in := source;
strm.avail_in := sourceLen;
strm.next_out := dest;
strm.avail_out := Integer(destLen^);
CCheck(deflateInit_(strm, Z_DEFAULT_COMPRESSION{Z_BEST_COMPRESSION}, zlib_version, sizeof(strm)));
try
Result := CCheck(deflate(strm, Z_FINISH));
if Result <> Z_STREAM_END then
raise EZlibError.CreateRes(@sTargetBufferTooSmall);
finally
CCheck(deflateEnd(strm));
end;
Integer(destLen^) := strm.total_out;
end;
function uncompress(dest: IntPtr; destlen: IntPtr; source: IntPtr; sourceLne: longint): longint;
var
strm: TZStreamRec;
begin
FillChar(@strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
strm.next_in := source;
strm.avail_in := sourcelne;
strm.next_out := dest;
strm.avail_out := Integer(destlen^);
DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
try
Result := DCheck(inflate(strm, Z_FINISH));
if Result <> Z_STREAM_END then
raise EZlibError.CreateRes(@sTargetBufferTooSmall);
finally
DCheck(inflateEnd(strm));
end;
end;
{$ENDIF}
{$ENDIF}
{$IFDEF MSWINDOWS}
var
lpVersionInformation: TOSVersionInfo;
initialization
lpVersionInformation.dwOSVersionInfoSize := sizeof(lpVersionInformation);
{$IFDEF VER6P}
{$WARN SYMBOL_PLATFORM OFF}
{$ENDIF}
{$IFDEF CLR}
IsWin9x := False;
{$ELSE}
Win32Check(GetVersionEx(lpVersionInformation));
IsWin9x := lpVersionInformation.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
{$ENDIF}
{$ENDIF}
{$IFDEF HAVE_COMPRESS_INTERNAL}
CompressProc := compress;
UncompressProc := uncompress;
{$ENDIF}
end.