(*:Various stuff with no other place to go.
@author Primoz Gabrijelcic
@desc
(c) 2008 Primoz Gabrijelcic
Free for personal and commercial use. No rights reserved.
Author : Primoz Gabrijelcic
Creation date : 2006-09-25
Last modification : 2008-10-26
Version : 1.14
*)(*
History:
1.14: 2008-10-26
- Implemented EnumValues enumerator.
1.13: 2008-09-09
- Added >= and <= operators to the TGp4AlignedInt.
1.12: 2008-07-28
- Added int64 support to the OpenArrayToVarArray.
1.11: 2008-07-20
- Implemented 8-aligned integer, TGp8AlignedInt.
- TGp4AlignedInt and TGp8AlignedInt ifdef'd to be only available on D2007+.
1.10: 2008-07-08
- [GJ] ReverseWord/ReverseDWord rewritten in assembler.
1.09: 2008-06-19
- Implemented 4-aligned integer, TGp4AlignedInt.
1.08: 2008-04-08
- Declared MaxInt64 constant.
1.07: 2008-03-31
- Added function OpenArrayToVarArray, written by Thomas Schubbauer.
1.06: 2007-06-13
- ReverseCardinal renamed to ReverseDWord.
- Added function ReverseWord.
1.05: 2007-04-12
- Added function ReverseCardinal.
1.04: 2007-02-26
- Added function TableFindEQ.
- Changed result semantics for TableFind*.
- Inlined everying that could be inlined.
- Changed Asgn implementation so that it doesn't trigger BDS2006 codegen bug.
- Added OffsetPtr method.
1.03: 2007-02-20
- Added function TableFindNE.
1.02: 2007-01-08
- Implemented IFF64 function.
1.01: 2007-01-06
- Moved in stuff from GpIFF.
1.0: 2006-09-25
- Released.
*)
unit GpStuff;
interface
uses
Windows,
DSiWin32;
{$IFDEF ConditionalExpressions}
{$IF CompilerVersion >= 18} //D2006+
{$DEFINE GpStuff_Inline}
{$DEFINE GpStuff_AlignedInt}
{$DEFINE GpStuff_ValuesEnumerators}
{$IFEND}
{$ENDIF}
const
MaxInt64 = $7FFFFFFFFFFFFFFF;
{$IFDEF GpStuff_AlignedInt}
type
TGp4AlignedInt = record
strict private
aiData: int64;
function GetValue: cardinal; inline;
procedure SetValue(value: cardinal); inline;
public
function Addr: PCardinal; inline;
function Decrement: cardinal; inline;
function Increment: cardinal; inline;
class operator Add(const ai: TGp4AlignedInt; i: integer): cardinal; inline;
class operator Equal(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator GreaterThan(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator GreaterThanOrEqual(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator Implicit(const ai: TGp4AlignedInt): integer; inline;
class operator Implicit(const ai: TGp4AlignedInt): cardinal; inline;
class operator Implicit(const ai: TGp4AlignedInt): PCardinal; inline;
class operator LessThan(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator LessThanOrEqual(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator NotEqual(const ai: TGp4AlignedInt; i: cardinal): boolean; inline;
class operator Subtract(ai: TGp4AlignedInt; i: integer): cardinal; inline;
property Value: cardinal read GetValue write SetValue;
end; { TGp4AlignedInt }
TGp8AlignedInt = record
strict private
aiData: packed record
DataLo, DataHi: int64;
end;
function GetValue: int64; inline;
procedure SetValue(value: int64); inline;
public
function Addr: PCardinal; inline;
function Decrement: int64; inline;
function Increment: int64; inline;
property Value: int64 read GetValue write SetValue;
end; { TGp8AlignedInt }
{$ENDIF GpStuff_AlignedInt}
function Asgn(var output: boolean; const value: boolean): boolean; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function Asgn(var output: string; const value: string): string; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function Asgn(var output: integer; const value: integer): integer; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function Asgn(var output: real; const value: real): real; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function Asgn64(var output: int64; const value: int64): int64; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF(condit: boolean; iftrue, iffalse: string): string; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF(condit: boolean; iftrue, iffalse: integer): integer; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF(condit: boolean; iftrue, iffalse: real): real; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF(condit: boolean; iftrue, iffalse: boolean): boolean; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF(condit: boolean; iftrue, iffalse: pointer): pointer; overload; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function IFF64(condit: boolean; iftrue, iffalse: int64): int64; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
function OffsetPtr(ptr: pointer; offset: integer): pointer; {$IFDEF GpStuff_Inline}inline;{$ENDIF}
///Reverses byte order in a 4-byte number.
function ReverseDWord(dw: DWORD): DWORD;
///Reverses byte order in a 2-byte number.
function ReverseWord(w: word): word;
///Locates specified value in a buffer.
///Offset of found value (0..dataLen-1) or -1 if value was not found.
///2007-02-22
function TableFindEQ(value: byte; data: PChar; dataLen: integer): integer; assembler;
///Locates a byte different from the specified value in a buffer.
///Offset of first differing value (0..dataLen-1) or -1 if buffer contains only specified values.
///2007-02-22
function TableFindNE(value: byte; data: PChar; dataLen: integer): integer; assembler;
///Converts open variant array to COM variant array.
/// Written by Thomas Schubbauer and published in borland.public.delphi.objectpascal on
/// Thu, 7 May 1998 09:53:33 +0200. Original function name was MakeVariant.
/// 2008-03-31, Gp: Extended to support vtObject type.
/// 2008-07-28, Gp: Extended to support vtInt64 type.
function OpenArrayToVarArray(aValues: array of const): Variant;
{$IFDEF GpStuff_ValuesEnumerators}
type
IGpIntegerValueEnumerator = interface
function GetCurrent: integer;
function MoveNext: boolean;
property Current: integer read GetCurrent;
end; { IGpIntegerValueEnumerator }
IGpIntegerValueEnumeratorFactory = interface
function GetEnumerator: IGpIntegerValueEnumerator;
end; { IGpIntegerValueEnumeratorFactory }
function EnumValues(aValues: array of integer): IGpIntegerValueEnumeratorFactory;
{$ENDIF GpStuff_ValuesEnumerators}
implementation
uses
{$IFDEF ConditionalExpressions}
Variants,
{$ENDIF ConditionalExpressions}
SysUtils;
{$IFDEF GpStuff_ValuesEnumerators}
type
TGpIntegerValueEnumerator = class(TInterfacedObject, IGpIntegerValueEnumerator)
private
iveIndex : integer;
iveNumValues: integer;
iveValues : PIntegerArray;
public
constructor Create(values: PIntegerArray; numValues: integer);
destructor Destroy; override;
function GetCurrent: integer;
function MoveNext: boolean;
property Current: integer read GetCurrent;
end; { TGpIntegerValueEnumerator }
TGpIntegerValueEnumeratorFactory = class(TInterfacedObject, IGpIntegerValueEnumeratorFactory)
private
ivefNumValues: integer;
ivefValues : PIntegerArray;
public
constructor Create(aValues: array of integer);
function GetEnumerator: IGpIntegerValueEnumerator;
end; { TGpIntegerValueEnumeratorFactory }
{$ENDIF GpStuff_ValuesEnumerators}
function Asgn(var output: boolean; const value: boolean): boolean; overload;
begin
output := value;
Result := output;
end; { Asgn }
function Asgn(var output: string; const value: string): string; overload;
begin
output := value;
Result := output;
end; { Asgn }
function Asgn(var output: real; const value: real): real; overload;
begin
output := value;
Result := output;
end; { Asgn }
function Asgn(var output: integer; const value: integer): integer; overload;
begin
output := value;
Result := output;
end; { Asgn }
function Asgn64(var output: int64; const value: int64): int64; overload;
begin
output := value;
Result := output;
end; { Asgn64 }
function IFF(condit: boolean; iftrue, iffalse: string): string;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF }
function IFF(condit: boolean; iftrue, iffalse: integer): integer;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF }
function IFF(condit: boolean; iftrue, iffalse: real): real;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF }
function IFF(condit: boolean; iftrue, iffalse: boolean): boolean;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF }
function IFF(condit: boolean; iftrue, iffalse: pointer): pointer;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF }
function IFF64(condit: boolean; iftrue, iffalse: int64): int64;
begin
if condit then
Result := iftrue
else
Result := iffalse;
end; { IFF64 }
function OffsetPtr(ptr: pointer; offset: integer): pointer;
begin
Result := pointer(cardinal(int64(ptr) + offset));
end; { OffsetPtr }
function OpenArrayToVarArray(aValues: array of const): Variant;
var
i: integer;
begin
Result := VarArrayCreate([Low(aValues), High(aValues)], varVariant);
for i := Low(aValues) to High(aValues) do begin
with aValues[i] do begin
case VType of
vtInteger: Result[i] := VInteger;
vtBoolean: Result[i] := VBoolean;
vtChar: Result[i] := VChar;
vtExtended: Result[i] := VExtended^;
vtString: Result[i] := VString^;
vtPointer: Result[i] := integer(VPointer);
vtPChar: Result[i] := StrPas(VPChar);
vtAnsiString: Result[i] := string(VAnsiString);
vtCurrency: Result[i] := VCurrency^;
vtVariant: Result[i] := VVariant^;
vtObject: Result[i] := integer(VObject);
vtWideString: Result[i] := WideString(VWideString);
vtInt64: Result[i] := VInt64^;
else
raise Exception.Create ('OpenArrayToVarArray: invalid data type')
end; //case
end; //with
end; //for i
end; { OpenArrayToVarArray }
function ReverseDWord(dw: cardinal): cardinal;
asm
bswap eax
end; { ReverseDWord }
function ReverseWord(w: word): word;
asm
xchg al, ah
end; { ReverseWord }
function TableFindEQ(value: byte; data: PChar; dataLen: integer): integer; assembler;
asm
PUSH EDI
MOV EDI,EDX
REPNE SCASB
MOV EAX,$FFFFFFFF
JNE @@1
MOV EAX,EDI
SUB EAX,EDX
DEC EAX
@@1: POP EDI
end; { TableFindEQ }
function TableFindNE(value: byte; data: PChar; dataLen: integer): integer; assembler;
asm
PUSH EDI
MOV EDI,EDX
REPE SCASB
MOV EAX,$FFFFFFFF
JE @@1
MOV EAX,EDI
SUB EAX,EDX
DEC EAX
@@1: POP EDI
end; { TableFindNE }
{$IFDEF GpStuff_AlignedInt}
{ TGpAlignedInt }
function TGp4AlignedInt.Addr: PCardinal;
begin
Assert(SizeOf(pointer) = SizeOf(cardinal));
Result := PCardinal((cardinal(@aiData) + 3) AND NOT 3);
end; { TGp4AlignedInt.Addr }
function TGp4AlignedInt.Decrement: cardinal;
begin
Result := InterlockedDecrement(PInteger(Addr)^);
end; { TGp4AlignedInt.Decrement }
function TGp4AlignedInt.GetValue: cardinal;
begin
Result := Addr^;
end; { TGp4AlignedInt.GetValue }
function TGp4AlignedInt.Increment: cardinal;
begin
Result := InterlockedIncrement(PInteger(Addr)^);
end; { TGp4AlignedInt.Increment }
procedure TGp4AlignedInt.SetValue(value: cardinal);
begin
Addr^ := value;
end; { TGp4AlignedInt.SetValue }
class operator TGp4AlignedInt.Add(const ai: TGp4AlignedInt; i: integer): cardinal;
begin
Result := cardinal(int64(ai.Value) + i);
end; { TGp4AlignedInt.Add }
class operator TGp4AlignedInt.Equal(const ai: TGp4AlignedInt; i: cardinal): boolean;
begin
Result := (ai.Value = i);
end; { TGp4AlignedInt.Equal }
class operator TGp4AlignedInt.GreaterThan(const ai: TGp4AlignedInt; i: cardinal): boolean;
begin
Result := (ai.Value > i);
end; { TGp4AlignedInt.GreaterThan }
class operator TGp4AlignedInt.GreaterThanOrEqual(const ai: TGp4AlignedInt; i: cardinal):
boolean;
begin
Result := (ai.Value >= i);
end; { TGp4AlignedInt.GreaterThanOrEqual }
class operator TGp4AlignedInt.Implicit(const ai: TGp4AlignedInt): PCardinal;
begin
Result := ai.Addr;
end; { TGp4AlignedInt.Implicit }
class operator TGp4AlignedInt.Implicit(const ai: TGp4AlignedInt): cardinal;
begin
Result := ai.Value;
end; { TGp4AlignedInt.Implicit }
class operator TGp4AlignedInt.Implicit(const ai: TGp4AlignedInt): integer;
begin
Result := integer(ai.Value);
end; { TGp4AlignedInt.Implicit }
class operator TGp4AlignedInt.LessThan(const ai: TGp4AlignedInt; i: cardinal): boolean;
begin
Result := (ai.Value < i);
end; { TGp4AlignedInt.LessThan }
class operator TGp4AlignedInt.LessThanOrEqual(const ai: TGp4AlignedInt; i: cardinal):
boolean;
begin
Result := (ai.Value <= i);
end; { TGp4AlignedInt.LessThanOrEqual }
class operator TGp4AlignedInt.NotEqual(const ai: TGp4AlignedInt; i: cardinal): boolean;
begin
Result := (ai.Value <> i);
end; { TGp4AlignedInt.NotEqual }
class operator TGp4AlignedInt.Subtract(ai: TGp4AlignedInt; i: integer): cardinal;
begin
Result := cardinal(int64(ai.Value) - i);
end; { TGp4AlignedInt.Subtract }
{ TGp8AlignedInt }
function TGp8AlignedInt.Addr: PCardinal;
begin
Assert(SizeOf(pointer) = SizeOf(cardinal));
Result := PCardinal((cardinal(@aiData) + 7) AND NOT 7);
end; { TGp8AlignedInt.Addr }
function TGp8AlignedInt.Decrement: int64;
begin
Result := DSiInterlockedDecrement64(PInt64(Addr)^);
end; { TGp8AlignedInt.Decrement }
function TGp8AlignedInt.GetValue: int64;
begin
Result := Addr^;
end; { TGp8AlignedInt.GetValue }
function TGp8AlignedInt.Increment: int64;
begin
Result := DSiInterlockedIncrement64(PInt64(Addr)^);
end; { TGp8AlignedInt.Increment }
procedure TGp8AlignedInt.SetValue(value: int64);
begin
Addr^ := value;
end; { TGp8AlignedInt.SetValue }
{$ENDIF GpStuff_AlignedInt}
{$IFDEF GpStuff_ValuesEnumerators}
{ TGpIntegerValueEnumerator }
constructor TGpIntegerValueEnumerator.Create(values: PIntegerArray; numValues: integer);
begin
iveValues := values;
iveNumValues := numValues;
iveIndex := -1;
end; { TGpIntegerValueEnumerator.Create }
destructor TGpIntegerValueEnumerator.Destroy;
begin
FreeMem(iveValues);
inherited;
end; { pIntegerValueEnumerator.Destroy }
function TGpIntegerValueEnumerator.GetCurrent: integer;
begin
Result := iveValues^[iveIndex];
end; { TGpIntegerValueEnumerator.GetCurrent }
function TGpIntegerValueEnumerator.MoveNext: boolean;
begin
Inc(iveIndex);
Result := (iveIndex < iveNumValues);
end; { TGpIntegerValueEnumerator.MoveNext }
{ TGpIntegerValueEnumeratorFactory }
constructor TGpIntegerValueEnumeratorFactory.Create(aValues: array of integer);
var
dataSize: integer;
begin
inherited Create;
ivefNumValues := Length(aValues);
Assert(ivefNumValues > 0);
dataSize := ivefNumValues * SizeOf(aValues[0]);
GetMem(ivefValues, dataSize);
Move(aValues[0], ivefValues^[0], dataSize);
end; { TGpIntegerValueEnumeratorFactory.Create }
function TGpIntegerValueEnumeratorFactory.GetEnumerator: IGpIntegerValueEnumerator;
begin
Result := TGpIntegerValueEnumerator.Create(ivefValues, ivefNumValues);
end; { TGpIntegerValueEnumeratorFactory.GetEnumerator }
{ exports }
function EnumValues(aValues: array of integer): IGpIntegerValueEnumeratorFactory;
begin
Result := TGpIntegerValueEnumeratorFactory.Create(aValues);
end; { EnumValues }
{$ENDIF GpStuff_ValuesEnumerators}
end.