
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4268 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2257 lines
63 KiB
ObjectPascal
2257 lines
63 KiB
ObjectPascal
{ This file is part of the Web Service Toolkit
|
|
Copyright (c) 2006 by Inoussa OUEDRAOGO
|
|
|
|
This file is provide under modified LGPL licence
|
|
( the files COPYING.modifiedLGPL and COPYING.LGPL).
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
}
|
|
{$INCLUDE wst_global.inc}
|
|
unit base_binary_formatter;
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Contnrs, TypInfo,
|
|
base_service_intf, binary_streamer, wst_types;
|
|
|
|
{$DEFINE wst_binary_header}
|
|
|
|
const
|
|
sBINARY_FORMAT_NAME = 'wst-binary';
|
|
sROOT = 'ROOT';
|
|
sSCOPE_INNER_NAME = 'INNER_VAL';
|
|
sFORMAT = 'format';
|
|
{$IFDEF wst_binary_header}
|
|
sHEADER = 'HEADER';
|
|
{$ENDIF}
|
|
|
|
type
|
|
EBinaryFormatterException = class(EServiceException)
|
|
end;
|
|
|
|
EBinaryException = class(EBaseRemoteException)
|
|
end;
|
|
|
|
TDataName = String;
|
|
TDataType = (
|
|
dtInt8U = 1, dtInt8S = 2,
|
|
dtInt16U = 3, dtInt16S = 4,
|
|
dtInt32U = 5, dtInt32S = 6,
|
|
dtInt64U = 7, dtInt64S = 8,
|
|
dtBool = 9,
|
|
dtAnsiChar = 10, dtWideChar = 11, dtEnum = 12,
|
|
dtSingle = 13, dtDouble = 14, dtExtended = 15, dtCurrency = 16,
|
|
dtAnsiString = 17, dtWideString = 18,
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString = 19,
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtObject = 30, dtArray = 31
|
|
);
|
|
const
|
|
dtDefaultString =
|
|
{$IFDEF WST_UNICODESTRING}
|
|
{$IFDEF WST_DELPHI}
|
|
dtUnicodeString
|
|
{$ENDIF WST_DELPHI}
|
|
{$IFDEF FPC}
|
|
dtAnsiString
|
|
{$ENDIF FPC}
|
|
{$ELSE WST_UNICODESTRING}
|
|
dtAnsiString
|
|
{$ENDIF WST_UNICODESTRING}
|
|
;
|
|
|
|
type
|
|
|
|
PAnsiStringBuffer = ^TAnsiStringBuffer;
|
|
PWideStringBuffer = ^TWideStringBuffer;
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
PUnicodeStringBuffer = ^TUnicodeStringBuffer;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
PObjectBuffer = ^TObjectBuffer;
|
|
PArrayBuffer = ^TArrayBuffer;
|
|
PDataBuffer = ^TDataBuffer;
|
|
|
|
TDataBuffer = Record
|
|
Name : TDataName;
|
|
Case DataType : TDataType of
|
|
dtInt8S : ( Int8S : TInt8S );
|
|
dtInt8U : ( Int8U : TInt8U );
|
|
dtInt16U : ( Int16U : TInt16U );
|
|
dtInt16S : ( Int16S : TInt16S );
|
|
dtInt32U : ( Int32U : TInt32U );
|
|
dtInt32S : ( Int32S : TInt32S );
|
|
dtInt64U : ( Int64U : TInt64U );
|
|
dtInt64S : ( Int64S : TInt64S );
|
|
dtBool : ( BoolData : TBoolData );
|
|
dtAnsiChar : ( AnsiCharData : TAnsiCharacter; );
|
|
dtWideChar : ( WideCharData : TWideCharacter; );
|
|
dtEnum : ( EnumData : TEnumData );
|
|
dtSingle : ( SingleData : TFloat_Single_4 );
|
|
dtDouble : ( DoubleData : TFloat_Double_8 );
|
|
dtExtended : ( ExtendedData : TFloat_Extended_10 );
|
|
dtCurrency : ( CurrencyData : TFloat_Currency_8 );
|
|
|
|
dtAnsiString : ( AnsiStrData : PAnsiStringBuffer );
|
|
dtWideString : ( WideStrData : PWideStringBuffer );
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString : ( UnicodeStrData : PUnicodeStringBuffer );
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtObject : ( ObjectData : PObjectBuffer );
|
|
dtArray : ( ArrayData : PArrayBuffer );
|
|
End;
|
|
|
|
TAnsiStringBuffer = record
|
|
Data : TAnsiStringData;
|
|
end;
|
|
|
|
TWideStringBuffer = record
|
|
Data : TWideStringData;
|
|
end;
|
|
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
TUnicodeStringBuffer = record
|
|
Data : TUnicodeStringData;
|
|
end;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
|
|
|
|
|
|
PObjectBufferItem = ^TObjectBufferItem;
|
|
TObjectBufferItem = Record
|
|
Data : PDataBuffer;
|
|
Next : PObjectBufferItem;
|
|
End;
|
|
|
|
TObjectBuffer = Record
|
|
NilObject : TBoolData;
|
|
Count : Integer;
|
|
Head : PObjectBufferItem;
|
|
Last : PObjectBufferItem;
|
|
Attributes : PObjectBuffer;
|
|
InnerData : PDataBuffer;
|
|
End;
|
|
|
|
PDataBufferList = ^TDataBufferList;
|
|
TDataBufferList = array[0..MAX_ARRAY_LENGTH] of PDataBuffer;
|
|
TArrayBuffer = Record
|
|
Count : Integer;
|
|
Items : PDataBufferList;
|
|
Attributes : PObjectBuffer;
|
|
End;
|
|
|
|
{ TStackItem }
|
|
|
|
TStackItem = class
|
|
private
|
|
FScopeObject: PDataBuffer;
|
|
FScopeType: TScopeType;
|
|
Public
|
|
constructor Create(const AScopeObject : PDataBuffer;AScopeType : TScopeType);
|
|
function GetItemCount():Integer;virtual;abstract;
|
|
function Find(var AName : TDataName):PDataBuffer;virtual;abstract;
|
|
function GetByIndex(const AIndex : Integer):PDataBuffer;virtual;abstract;
|
|
function CreateBuffer(
|
|
Const AName : String;
|
|
const ADataType : TDataType
|
|
):PDataBuffer;virtual;abstract;
|
|
function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;virtual;abstract;
|
|
function GetInnerBuffer():PDataBuffer;virtual;abstract;
|
|
procedure NilCurrentScope();virtual;abstract;
|
|
function IsCurrentScopeNil():Boolean;virtual;abstract;
|
|
property ScopeObject : PDataBuffer Read FScopeObject;
|
|
property ScopeType : TScopeType Read FScopeType;
|
|
|
|
function GetScopeItemNames(const AReturnList : TStrings) : Integer;virtual;abstract;
|
|
End;
|
|
|
|
{ TObjectStackItem }
|
|
|
|
TObjectStackItem = class(TStackItem)
|
|
Public
|
|
constructor Create(const AScopeObject : PDataBuffer);
|
|
function GetItemCount():Integer;override;
|
|
function Find(var AName : TDataName):PDataBuffer;override;
|
|
function GetByIndex(const AIndex : Integer):PDataBuffer;override;
|
|
function CreateBuffer(
|
|
Const AName : String;
|
|
const ADataType : TDataType
|
|
):PDataBuffer;override;
|
|
function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;override;
|
|
function GetInnerBuffer():PDataBuffer;override;
|
|
procedure NilCurrentScope();override;
|
|
function IsCurrentScopeNil():Boolean;override;
|
|
function GetScopeItemNames(const AReturnList : TStrings) : Integer;override;
|
|
End;
|
|
|
|
{ TArrayStackItem }
|
|
|
|
TArrayStackItem = class(TStackItem)
|
|
Private
|
|
FIndex : Integer;
|
|
Public
|
|
constructor Create(const AScopeObject : PDataBuffer);
|
|
function GetItemCount():Integer;override;
|
|
function Find(var AName : TDataName):PDataBuffer;override;
|
|
function GetByIndex(const AIndex : Integer):PDataBuffer;override;
|
|
function CreateBuffer(
|
|
Const AName : String;
|
|
const ADataType : TDataType
|
|
):PDataBuffer;override;
|
|
function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;override;
|
|
function GetInnerBuffer():PDataBuffer;overload;override;
|
|
procedure NilCurrentScope();override;
|
|
function IsCurrentScopeNil():Boolean;override;
|
|
function GetScopeItemNames(const AReturnList : TStrings) : Integer;override;
|
|
End;
|
|
|
|
{ TBaseBinaryFormatter }
|
|
|
|
TBaseBinaryFormatter = class(TSimpleFactoryItem,IFormatterBase)
|
|
private
|
|
FRootData : PDataBuffer;
|
|
FStack : TObjectStack;
|
|
FSerializationStyle : TSerializationStyle;
|
|
FPropMngr : IPropertyManager;
|
|
{$IFDEF wst_binary_header}
|
|
FHeaderEnterCount : Integer;
|
|
{$ENDIF}
|
|
protected
|
|
function GetCurrentScope: String;
|
|
function GetCurrentScopeObject():PDataBuffer;
|
|
procedure SetSerializationStyle(const ASerializationStyle : TSerializationStyle);
|
|
function GetSerializationStyle():TSerializationStyle;
|
|
protected
|
|
function HasScope():Boolean;
|
|
procedure CheckScope();
|
|
procedure ClearStack();{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PushStack(AScopeObject : PDataBuffer;Const AScopeType : TScopeType = stObject);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function StackTop():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function PopStack():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetRootData() : PDataBuffer;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
protected
|
|
procedure PutFloat(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : TFloat_Extended_10
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutInt(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : TInt64S
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutAnsiStr(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : AnsiString
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutWideStr(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : WideString
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
procedure PutUnicodeStr(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : UnicodeString
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
procedure PutEnum(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : TEnumData
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutBool(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : Boolean
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutAnsiChar(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : AnsiChar
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutWideChar(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : WideChar
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutInt64(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : Int64
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{$IFDEF HAS_QWORD}
|
|
procedure PutUInt64(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : QWord
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{$ENDIF HAS_QWORD}
|
|
procedure PutObj(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData : TObject
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
procedure PutRecord(
|
|
const AName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData : Pointer
|
|
);{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
|
|
function GetDataBuffer(
|
|
var AName : string;
|
|
out AResultBuffer : PDataBuffer
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetEnum(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : TEnumData
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetBool(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : Boolean
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetAnsiChar(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : AnsiChar
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetWideChar(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : WideChar
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetFloat(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : TFloat_Extended_10
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetInt(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : TInt64S
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetInt64(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : Int64
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{$IFDEF HAS_QWORD}
|
|
function GetUInt64(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : QWord
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{$ENDIF}
|
|
function GetAnsiStr(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : AnsiString
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetWideStr(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : String;
|
|
var AData : WideString
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
function GetUnicodeStr(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : String;
|
|
var AData : UnicodeString
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
function GetObj(
|
|
Const ATypeInfo : PTypeInfo;
|
|
Var AName : String;
|
|
Var AData : TObject
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
function GetRecord(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : String;
|
|
var AData : Pointer
|
|
) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
|
|
public
|
|
constructor Create();override;
|
|
destructor Destroy();override;
|
|
function GetFormatName() : string;
|
|
function GetPropertyManager():IPropertyManager;
|
|
|
|
procedure Clear();
|
|
|
|
procedure BeginObject(
|
|
Const AName : string;
|
|
Const ATypeInfo : PTypeInfo
|
|
);
|
|
procedure BeginArray(
|
|
const AName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AItemTypeInfo : PTypeInfo;
|
|
const ABounds : Array Of Integer;
|
|
const AStyle : TArrayStyle
|
|
);
|
|
procedure NilCurrentScope();
|
|
function IsCurrentScopeNil():Boolean;
|
|
procedure EndScope();
|
|
procedure AddScopeAttribute(Const AName,AValue : string);
|
|
function BeginObjectRead(
|
|
var AScopeName : string;
|
|
const ATypeInfo : PTypeInfo
|
|
) : Integer;
|
|
function BeginArrayRead(
|
|
var AScopeName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AStyle : TArrayStyle;
|
|
const AItemName : string
|
|
):Integer;
|
|
function GetScopeItemNames(const AReturnList : TStrings) : Integer;
|
|
procedure EndScopeRead();
|
|
|
|
procedure BeginHeader();
|
|
procedure EndHeader();
|
|
|
|
property CurrentScope : String Read GetCurrentScope;
|
|
|
|
procedure Put(
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData
|
|
);overload;
|
|
procedure Put(
|
|
const ANameSpace : string;
|
|
Const AName : String;
|
|
Const ATypeInfo : PTypeInfo;
|
|
Const AData
|
|
);overload;
|
|
procedure PutScopeInnerValue(
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData
|
|
);
|
|
function Get(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : string;
|
|
var AData
|
|
) : Boolean;overload;
|
|
function Get(
|
|
const ATypeInfo : PTypeInfo;
|
|
const ANameSpace : string;
|
|
var AName : string;
|
|
var AData
|
|
) : Boolean; overload;
|
|
procedure GetScopeInnerValue(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AData
|
|
);
|
|
function ReadBuffer(const AName : string; out AResBuffer : string) : Boolean;
|
|
procedure WriteBuffer(const AValue : string);
|
|
|
|
procedure SaveToStream(AStream : TStream);
|
|
procedure LoadFromStream(AStream : TStream);
|
|
|
|
procedure Error(Const AMsg:string);overload;
|
|
procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
|
|
End;
|
|
|
|
TDBGPinterProc = procedure(const AMsg:string);
|
|
|
|
procedure ClearObj(const AOwner: PDataBuffer);
|
|
procedure FreeObjectBuffer(var ABuffer : PDataBuffer); overload;
|
|
function LoadObjectFromStream(const AStoreRdr : IDataStoreReader):PDataBuffer;
|
|
procedure SaveObjectToStream(const ARoot: PDataBuffer; const ADest : IDataStore);
|
|
function CreateArrayBuffer(
|
|
const ALength : Integer;
|
|
const AName : TDataName;
|
|
const AOwner : PDataBuffer = nil
|
|
):PDataBuffer;
|
|
function CreateObjBuffer(
|
|
const ADataType : TDataType;
|
|
const AName : TDataName;
|
|
const AOwner : PDataBuffer = nil
|
|
):PDataBuffer;
|
|
|
|
procedure PrintObj(const ARoot: PDataBuffer; const ALevel : Integer; const APrinterProc : TDBGPinterProc);
|
|
|
|
implementation
|
|
uses
|
|
imp_utils, wst_consts;
|
|
|
|
{$INCLUDE wst_rtl_imp.inc}
|
|
|
|
procedure PrintObj(const ARoot: PDataBuffer; const ALevel : Integer; const APrinterProc : TDBGPinterProc);
|
|
Var
|
|
p : PObjectBufferItem;
|
|
s : string;
|
|
i ,j: Integer;
|
|
Begin
|
|
If Not Assigned(ARoot) Then
|
|
Exit;
|
|
s := StringOfChar(' ',ALevel);
|
|
Case ARoot^.DataType Of
|
|
dtInt8S : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int8S) );
|
|
dtInt8U : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int8U) );
|
|
dtInt32U : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int32U) );
|
|
dtInt32S : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int32S) );
|
|
dtInt64U : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int64U) );
|
|
dtInt64S : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int64S) );
|
|
|
|
dtSingle : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.SingleData) );
|
|
dtDouble : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.DoubleData) );
|
|
dtExtended : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.ExtendedData) );
|
|
dtCurrency : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.CurrencyData) );
|
|
|
|
dtAnsiString : APrinterProc( s + ARoot^.Name + ' = ' + ARoot^.AnsiStrData^.Data );
|
|
dtWideString : APrinterProc( s + ARoot^.Name + ' = ' + ARoot^.WideStrData^.Data );
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString : APrinterProc( s + ARoot^.Name + ' = ' + ARoot^.UnicodeStrData^.Data );
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtObject :
|
|
Begin
|
|
APrinterProc( s + ARoot^.Name + ' = ');
|
|
If Not Assigned(ARoot^.ObjectData) Then Begin
|
|
APrinterProc(s + ' <Vide>');
|
|
End Else Begin
|
|
APrinterProc('( ' + IntToStr(ARoot^.ObjectData^.Count) + ' Objects )');
|
|
p := ARoot^.ObjectData^.Head;
|
|
i := ALevel + 1;
|
|
While Assigned(p) Do Begin
|
|
PrintObj(p^.Data,i,APrinterProc);
|
|
p := p^.Next;
|
|
End;
|
|
End;
|
|
End;
|
|
dtArray :
|
|
Begin
|
|
APrinterProc( s + ARoot^.Name + ' = ');
|
|
If Not Assigned(ARoot^.ArrayData) Then Begin
|
|
APrinterProc(s + ' <Vide>');
|
|
End Else Begin
|
|
j := ARoot^.ArrayData^.Count;
|
|
APrinterProc('( Objects[ '+ IntToStr(j)+ '] )');
|
|
i := ALevel + 1;
|
|
For j := 0 To Pred(j) Do Begin
|
|
PrintObj(ARoot^.ArrayData^.Items^[j],i,APrinterProc);
|
|
End;
|
|
End;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
function FindObj(const AOwner: PDataBuffer; const AName : TDataName) : PDataBuffer;
|
|
Var
|
|
p : PObjectBufferItem;
|
|
Begin
|
|
Assert(AOwner^.DataType >= dtObject);
|
|
Result := Nil;
|
|
p:= AOwner^.ObjectData^.Head;
|
|
While Assigned(p) Do Begin
|
|
If AnsiSameText(AName,p^.Data^.Name) Then Begin
|
|
Result := p^.Data;
|
|
Exit;
|
|
End;
|
|
p := p^.Next;
|
|
End;
|
|
End;
|
|
|
|
procedure AddObj(
|
|
const AOwner, AChildData: PDataBuffer;
|
|
const AIndex : Integer = -1
|
|
);
|
|
Var
|
|
p : PObjectBufferItem;
|
|
Begin
|
|
If ( AOwner^.DataType = dtObject ) Then Begin
|
|
p := wst_GetMem(SizeOf(TObjectBufferItem));
|
|
p^.Data := AChildData;
|
|
p^.Next := Nil;
|
|
If Assigned(AOwner^.ObjectData^.Head) Then Begin
|
|
AOwner^.ObjectData^.Last^.Next := p;
|
|
End Else Begin
|
|
AOwner^.ObjectData^.Head := p;
|
|
End;
|
|
AOwner^.ObjectData^.Last := p;
|
|
Inc(AOwner^.ObjectData^.Count);
|
|
End Else If ( AOwner^.DataType = dtArray ) Then Begin
|
|
If ( AIndex >= 0 ) And ( AIndex < AOwner^.ArrayData^.Count ) Then
|
|
AOwner^.ArrayData^.Items^[AIndex] := AChildData
|
|
Else
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_IndexOutOfBound,[AIndex])
|
|
End Else Begin
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_InvalidDataTypeInContext,[IntToStr(Ord(AOwner^.DataType))])
|
|
End;
|
|
End;
|
|
|
|
function CreateObjBuffer(
|
|
const ADataType : TDataType;
|
|
const AName : TDataName;
|
|
const AOwner : PDataBuffer = nil
|
|
):PDataBuffer;
|
|
var
|
|
resLen, i : Integer;
|
|
begin
|
|
resLen := SizeOf(TDataBuffer);
|
|
Result := wst_GetMem(resLen);
|
|
Try
|
|
FillChar(Result^,resLen,#0);
|
|
Result^.Name := AName;
|
|
Result^.DataType := ADataType;
|
|
Case Result^.DataType Of
|
|
dtAnsiString :
|
|
Begin
|
|
i := SizeOf(TAnsiStringBuffer);
|
|
Result^.AnsiStrData := wst_GetMem(i);
|
|
FillChar(Result^.AnsiStrData^,i,#0);
|
|
Result^.AnsiStrData^.Data := '';
|
|
End;
|
|
dtWideString :
|
|
begin
|
|
i := SizeOf(TWideStringBuffer);
|
|
Result^.WideStrData := wst_GetMem(i);
|
|
FillChar(Result^.WideStrData^,i,#0);
|
|
Result^.WideStrData^.Data := '';
|
|
end;
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString :
|
|
begin
|
|
i := SizeOf(TUnicodeStringBuffer);
|
|
Result^.UnicodeStrData := wst_GetMem(i);
|
|
FillChar(Result^.UnicodeStrData^,i,#0);
|
|
Result^.UnicodeStrData^.Data := '';
|
|
end;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtObject :
|
|
Begin
|
|
Result^.ObjectData := wst_GetMem(SizeOf(TObjectBuffer));
|
|
FillChar(Result^.ObjectData^,SizeOf(TObjectBuffer),#0);
|
|
End;
|
|
End;
|
|
If Assigned(AOwner) Then
|
|
AddObj(AOwner,Result);
|
|
Except
|
|
Freemem(Result,resLen);
|
|
Raise;
|
|
End;
|
|
end;
|
|
|
|
function CreateArrayBuffer(
|
|
const ALength : Integer;
|
|
const AName : TDataName;
|
|
const AOwner : PDataBuffer = nil
|
|
):PDataBuffer;
|
|
Var
|
|
i, resLen : Integer;
|
|
begin
|
|
Assert(ALength>=0);
|
|
resLen := SizeOf(TDataBuffer);
|
|
Result := wst_GetMem(resLen);
|
|
Try
|
|
FillChar(Result^,resLen,#0);
|
|
Result^.Name := AName;
|
|
Result^.DataType := dtArray;
|
|
Result^.ArrayData := wst_GetMem(SizeOf(TArrayBuffer));
|
|
FillChar(Result^.ArrayData^,SizeOf(TArrayBuffer),#0);
|
|
Result^.ArrayData^.Count := ALength;
|
|
If ( ALength > 0 ) Then Begin
|
|
i := ALength*SizeOf(PDataBuffer);
|
|
Result^.ArrayData^.Items := wst_GetMem(i);
|
|
FillChar(Result^.ArrayData^.Items^[0],i,#0);
|
|
End Else Begin
|
|
Result^.ArrayData^.Items := Nil;
|
|
End;
|
|
If Assigned(AOwner) Then
|
|
AddObj(AOwner,Result);
|
|
Except
|
|
Freemem(Result,resLen);
|
|
Raise;
|
|
End;
|
|
end;
|
|
|
|
procedure SaveObjectToStream(const ARoot: PDataBuffer; const ADest : IDataStore);
|
|
Var
|
|
p : PObjectBufferItem;
|
|
i : TInt32S;
|
|
Begin
|
|
If Not Assigned(ARoot) Then
|
|
Exit;
|
|
i := Ord(ARoot^.DataType);
|
|
ADest.WriteInt32S(i);
|
|
ADest.WriteAnsiStr(ARoot^.Name);
|
|
Case ARoot^.DataType Of
|
|
dtInt8S : ADest.WriteInt8S(ARoot^.Int8S);
|
|
dtInt8U : ADest.WriteInt8U(ARoot^.Int8U);
|
|
dtInt16U : ADest.WriteInt16U(ARoot^.Int16U);
|
|
dtInt16S : ADest.WriteInt16S(ARoot^.Int16S);
|
|
dtInt32U : ADest.WriteInt32U(ARoot^.Int32U);
|
|
dtInt32S : ADest.WriteInt32S(ARoot^.Int32S);
|
|
dtInt64U : ADest.WriteInt64U(ARoot^.Int64U);
|
|
dtInt64S : ADest.WriteInt64S(ARoot^.Int64S);
|
|
|
|
dtSingle : ADest.WriteSingle(ARoot^.SingleData);
|
|
dtDouble : ADest.WriteDouble(ARoot^.DoubleData);
|
|
dtExtended : ADest.WriteExtended(ARoot^.ExtendedData);
|
|
dtCurrency : ADest.WriteCurrency(ARoot^.CurrencyData);
|
|
|
|
dtAnsiString : ADest.WriteAnsiStr(ARoot^.AnsiStrData^.Data);
|
|
dtWideString : ADest.WriteWideStr(ARoot^.WideStrData^.Data);
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString : ADest.WriteUnicodeStr(ARoot^.UnicodeStrData^.Data);
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtBool : ADest.WriteBool(ARoot^.BoolData);
|
|
dtAnsiChar : ADest.WriteAnsiChar(ARoot^.AnsiCharData);
|
|
dtWideChar : ADest.WriteWideChar(ARoot^.WideCharData);
|
|
dtEnum : ADest.WriteEnum(ARoot^.EnumData);
|
|
dtObject :
|
|
Begin
|
|
ADest.WriteBool(ARoot^.ObjectData^.NilObject) ;
|
|
if not ARoot^.ObjectData^.NilObject then begin
|
|
i := ARoot^.ObjectData^.Count;
|
|
ADest.WriteInt32S(i);
|
|
|
|
If ( i > 0 ) Then Begin
|
|
p := ARoot^.ObjectData^.Head;
|
|
For i := 1 To i Do Begin
|
|
SaveObjectToStream(p^.Data,ADest);
|
|
p := p^.Next;
|
|
End;
|
|
End;
|
|
ADest.WriteBool(Assigned(ARoot^.ObjectData^.InnerData));
|
|
if Assigned(ARoot^.ObjectData^.InnerData) then
|
|
SaveObjectToStream(ARoot^.ObjectData^.InnerData,ADest);
|
|
end;
|
|
End;
|
|
dtArray :
|
|
Begin
|
|
i := ARoot^.ArrayData^.Count;
|
|
ADest.WriteInt32S(i);
|
|
|
|
If ( i > 0 ) Then Begin
|
|
For i := 0 To Pred(i) Do Begin
|
|
SaveObjectToStream(ARoot^.ArrayData^.Items^[i],ADest);
|
|
End;
|
|
End;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
function LoadObjectFromStream(const AStoreRdr : IDataStoreReader):PDataBuffer;
|
|
Var
|
|
i : TInt32S;
|
|
s : string;
|
|
Begin
|
|
Result := Nil;
|
|
If AStoreRdr.IsAtEof() Then
|
|
Exit;
|
|
i := AStoreRdr.ReadInt32S();
|
|
s := AStoreRdr.ReadAnsiStr();
|
|
If ( TDataType(i) < dtArray ) Then
|
|
Result := CreateObjBuffer(TDataType(i),s);
|
|
Case TDataType(i) Of
|
|
dtInt8S : Result^.Int8S := AStoreRdr.ReadInt8S();
|
|
dtInt8U : Result^.Int8U := AStoreRdr.ReadInt8U();
|
|
dtInt16U : Result^.Int16U := AStoreRdr.ReadInt16U();
|
|
dtInt16S : Result^.Int16S := AStoreRdr.ReadInt16S();
|
|
dtInt32U : Result^.Int32U := AStoreRdr.ReadInt32U();
|
|
dtInt32S : Result^.Int32S := AStoreRdr.ReadInt32S();
|
|
dtInt64U : Result^.Int64U := AStoreRdr.ReadInt64U();
|
|
dtInt64S : Result^.Int64S := AStoreRdr.ReadInt64S();
|
|
|
|
dtSingle : Result^.SingleData := AStoreRdr.ReadSingle();
|
|
dtDouble : Result^.DoubleData := AStoreRdr.ReadDouble();
|
|
dtExtended : Result^.ExtendedData := AStoreRdr.ReadExtended();
|
|
dtCurrency : Result^.CurrencyData := AStoreRdr.ReadCurrency();
|
|
|
|
dtAnsiString : Result^.AnsiStrData^.Data := AStoreRdr.ReadAnsiStr();
|
|
dtWideString : Result^.WideStrData^.Data := AStoreRdr.ReadWideStr();
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString : Result^.UnicodeStrData^.Data := AStoreRdr.ReadUnicodeStr();
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtBool : Result^.BoolData := AStoreRdr.ReadBool();
|
|
dtAnsiChar : Result^.AnsiCharData := AStoreRdr.ReadAnsiChar();
|
|
dtWideChar : Result^.WideCharData := AStoreRdr.ReadWideChar();
|
|
dtEnum : Result^.EnumData := AStoreRdr.ReadEnum();
|
|
dtObject :
|
|
Begin
|
|
Result^.ObjectData^.NilObject := AStoreRdr.ReadBool();
|
|
if not Result^.ObjectData^.NilObject then begin
|
|
i := AStoreRdr.ReadInt32S();
|
|
For i := 1 To i Do Begin
|
|
AddObj(Result,LoadObjectFromStream(AStoreRdr));
|
|
End;
|
|
if AStoreRdr.ReadBool() then
|
|
Result^.ObjectData^.InnerData := LoadObjectFromStream(AStoreRdr);
|
|
end;
|
|
end;
|
|
dtArray :
|
|
Begin
|
|
i := AStoreRdr.ReadInt32S();
|
|
Result := CreateArrayBuffer(i,s);
|
|
For i := 0 To Pred(i) Do Begin
|
|
AddObj(Result,LoadObjectFromStream(AStoreRdr),i);
|
|
End;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
procedure FreeObjectBuffer(var ABuffer : PObjectBuffer);overload;
|
|
var
|
|
p,q : PObjectBufferItem;
|
|
begin
|
|
if Assigned(ABuffer) then begin
|
|
if Assigned(ABuffer^.Attributes) then
|
|
FreeObjectBuffer(ABuffer^.Attributes);
|
|
p := ABuffer^.Head;
|
|
while Assigned(p) do begin
|
|
q := p;
|
|
p := p^.Next;
|
|
ClearObj(q^.Data);
|
|
Freemem(q^.Data);
|
|
q^.Data := Nil;
|
|
Freemem(q);
|
|
end;
|
|
if Assigned(ABuffer^.InnerData) then begin
|
|
ClearObj(ABuffer^.InnerData);
|
|
Freemem(ABuffer^.InnerData);
|
|
ABuffer^.InnerData := nil;
|
|
end;
|
|
//ABuffer^.Head := nil;
|
|
//ABuffer^.Last := nil;
|
|
Freemem(ABuffer);
|
|
ABuffer := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure FreeObjectBuffer(var ABuffer : PDataBuffer);
|
|
var
|
|
tmpBuffer : PDataBuffer;
|
|
begin
|
|
if ( ABuffer <> nil ) then begin
|
|
tmpBuffer := ABuffer;
|
|
ABuffer := nil;
|
|
ClearObj(tmpBuffer);
|
|
FreeMem(tmpBuffer)
|
|
end;
|
|
end;
|
|
|
|
procedure ClearObj(const AOwner: PDataBuffer);
|
|
Var
|
|
i , j: Integer;
|
|
eltLen : Integer;
|
|
Begin
|
|
AOwner^.Name := '';
|
|
Case AOwner^.DataType Of
|
|
dtAnsiString :
|
|
Begin
|
|
AOwner^.AnsiStrData^.Data := '';
|
|
Freemem(AOwner^.AnsiStrData);
|
|
AOwner^.AnsiStrData := Nil;
|
|
End;
|
|
dtWideString :
|
|
begin
|
|
AOwner^.WideStrData^.Data := '';
|
|
Freemem(AOwner^.WideStrData);
|
|
AOwner^.WideStrData := Nil;
|
|
end;
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
dtUnicodeString :
|
|
begin
|
|
AOwner^.UnicodeStrData^.Data := '';
|
|
Freemem(AOwner^.UnicodeStrData);
|
|
AOwner^.UnicodeStrData := Nil;
|
|
end;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
dtObject :
|
|
Begin
|
|
FreeObjectBuffer(AOwner^.ObjectData);
|
|
End;
|
|
dtArray :
|
|
Begin
|
|
eltLen := SizeOf(TDataBuffer);
|
|
For j := 0 to Pred(AOwner^.ArrayData^.Count) Do Begin
|
|
ClearObj(AOwner^.ArrayData^.Items^[j]);
|
|
Freemem(AOwner^.ArrayData^.Items^[j],eltLen);
|
|
AOwner^.ArrayData^.Items^[j] := Nil;
|
|
End;
|
|
i := AOwner^.ArrayData^.Count * SizeOf(PDataBuffer);
|
|
Freemem(AOwner^.ArrayData^.Items,i);
|
|
AOwner^.ArrayData^.Items := Nil;
|
|
FreeObjectBuffer(AOwner^.ArrayData^.Attributes);
|
|
i := SizeOf(TArrayBuffer);
|
|
Freemem(AOwner^.ArrayData,i);
|
|
AOwner^.ArrayData := Nil;
|
|
End;
|
|
End;
|
|
End;
|
|
|
|
|
|
{ TStackItem }
|
|
|
|
constructor TStackItem.Create(const AScopeObject: PDataBuffer; AScopeType: TScopeType);
|
|
begin
|
|
Assert(Assigned(AScopeObject));
|
|
FScopeObject := AScopeObject;
|
|
FScopeType := AScopeType;
|
|
end;
|
|
|
|
{ TObjectStackItem }
|
|
|
|
constructor TObjectStackItem.Create(const AScopeObject: PDataBuffer);
|
|
begin
|
|
Inherited Create(AScopeObject,stObject);
|
|
end;
|
|
|
|
function TObjectStackItem.GetItemCount(): Integer;
|
|
begin
|
|
Result := ScopeObject^.ObjectData^.Count;
|
|
end;
|
|
|
|
function TObjectStackItem.Find(var AName: TDataName): PDataBuffer;
|
|
begin
|
|
Result := FindObj(ScopeObject,AName);
|
|
end;
|
|
|
|
function TObjectStackItem.GetByIndex(const AIndex: Integer): PDataBuffer;
|
|
Var
|
|
p : PObjectBufferItem;
|
|
i : Integer;
|
|
begin
|
|
If ( AIndex >=0 ) And ( AIndex < ScopeObject^.ObjectData^.Count) Then Begin
|
|
p := ScopeObject^.ObjectData^.Head;
|
|
For i := 1 To AIndex Do
|
|
p := p^.Next;
|
|
Result := p^.Data;
|
|
End Else
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_IndexOutOfBound,[AIndex]);
|
|
end;
|
|
|
|
function TObjectStackItem.CreateBuffer(
|
|
Const AName : String;
|
|
const ADataType : TDataType
|
|
):PDataBuffer;
|
|
begin
|
|
Result := CreateObjBuffer(ADataType,AName,ScopeObject);
|
|
end;
|
|
|
|
function TObjectStackItem.CreateInnerBuffer(const ADataType: TDataType): PDataBuffer;
|
|
begin
|
|
Result := CreateObjBuffer(ADataType,sSCOPE_INNER_NAME,nil);
|
|
ScopeObject^.ObjectData^.InnerData := Result;
|
|
end;
|
|
|
|
function TObjectStackItem.GetInnerBuffer(): PDataBuffer;
|
|
begin
|
|
Result := ScopeObject^.ObjectData^.InnerData;
|
|
end;
|
|
|
|
procedure TObjectStackItem.NilCurrentScope();
|
|
begin
|
|
Assert(ScopeObject^.ObjectData^.Count = 0);
|
|
ScopeObject^.ObjectData^.NilObject := True;
|
|
end;
|
|
|
|
function TObjectStackItem.IsCurrentScopeNil(): Boolean;
|
|
begin
|
|
Result := ScopeObject^.ObjectData^.NilObject;
|
|
end;
|
|
|
|
//----------------------------------------------------------------
|
|
function TObjectStackItem.GetScopeItemNames(const AReturnList: TStrings): Integer;
|
|
var
|
|
locBuffer : PObjectBufferItem;
|
|
begin
|
|
AReturnList.Clear();
|
|
if Assigned(ScopeObject) and ( ScopeObject^.ObjectData^.Count > 0 ) then begin
|
|
locBuffer := ScopeObject^.ObjectData^.Head;
|
|
while Assigned(locBuffer) do begin
|
|
AReturnList.Add(locBuffer^.Data^.Name);
|
|
locBuffer := locBuffer^.Next;
|
|
end;
|
|
end;
|
|
Result := AReturnList.Count;
|
|
end;
|
|
|
|
{ TBaseBinaryFormatter }
|
|
|
|
procedure TBaseBinaryFormatter.ClearStack();
|
|
Var
|
|
i, c : Integer;
|
|
begin
|
|
c := FStack.Count;
|
|
For I := 1 To c Do
|
|
FStack.Pop().Free();
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PushStack(AScopeObject: PDataBuffer;const AScopeType: TScopeType);
|
|
begin
|
|
If ( AScopeType = stObject ) Then
|
|
FStack.Push(TObjectStackItem.Create(AScopeObject))
|
|
Else If ( AScopeType = stArray ) Then
|
|
FStack.Push(TArrayStackItem.Create(AScopeObject))
|
|
Else
|
|
Assert(False);
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.StackTop(): TStackItem;
|
|
begin
|
|
Result := FStack.Peek() as TStackItem;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.PopStack(): TStackItem;
|
|
begin
|
|
Result := FStack.Pop() as TStackItem;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetRootData(): PDataBuffer;
|
|
begin
|
|
Result := FRootData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutFloat(
|
|
const AName : String;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData : TFloat_Extended_10
|
|
);
|
|
begin
|
|
Case GetTypeData(ATypeInfo)^.FloatType Of
|
|
ftSingle : StackTop().CreateBuffer(AName,dtSingle)^.SingleData := AData;
|
|
ftDouble : StackTop().CreateBuffer(AName,dtDouble)^.DoubleData := AData;
|
|
ftExtended : StackTop().CreateBuffer(AName,dtExtended)^.ExtendedData := AData;
|
|
ftCurr : StackTop().CreateBuffer(AName,dtCurrency)^.CurrencyData := AData;
|
|
Else
|
|
StackTop().CreateBuffer(AName,dtExtended)^.ExtendedData := AData;
|
|
End;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetCurrentScopeObject(): PDataBuffer;
|
|
begin
|
|
Result := StackTop().ScopeObject;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.SetSerializationStyle(
|
|
const ASerializationStyle: TSerializationStyle
|
|
);
|
|
begin
|
|
FSerializationStyle := ASerializationStyle;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetSerializationStyle(): TSerializationStyle;
|
|
begin
|
|
Result := FSerializationStyle;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.HasScope(): Boolean;
|
|
begin
|
|
Result := ( FStack.Peek <> nil );
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.CheckScope();
|
|
begin
|
|
If Not HasScope() Then
|
|
Error(SERR_NoScope);
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetCurrentScope: String;
|
|
begin
|
|
Result := GetCurrentScopeObject()^.Name;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutInt(
|
|
const AName : String;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData : TInt64S
|
|
);
|
|
begin
|
|
Case GetTypeData(ATypeInfo)^.OrdType Of
|
|
otSByte : StackTop().CreateBuffer(AName,dtInt8S)^.Int8S := AData;
|
|
otUByte : StackTop().CreateBuffer(AName,dtInt8U)^.Int8U := AData;
|
|
otSWord : StackTop().CreateBuffer(AName,dtInt16S)^.Int16S := AData;
|
|
otUWord : StackTop().CreateBuffer(AName,dtInt16U)^.Int16U := AData;
|
|
otULong : StackTop().CreateBuffer(AName,dtInt32U)^.Int32U := AData;
|
|
otSLong : StackTop().CreateBuffer(AName,dtInt32S)^.Int32S := AData;
|
|
End;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutAnsiStr(
|
|
const AName : String;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData : AnsiString
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtAnsiString)^.AnsiStrData^.Data := AData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutWideStr(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: WideString
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtWideString)^.WideStrData^.Data := AData;
|
|
end;
|
|
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
procedure TBaseBinaryFormatter.PutUnicodeStr(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: UnicodeString
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtUnicodeString)^.UnicodeStrData^.Data := AData;
|
|
end;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
|
|
procedure TBaseBinaryFormatter.PutEnum(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: TEnumData
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtEnum)^.EnumData := AData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutBool(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: Boolean
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtBool)^.BoolData := AData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutAnsiChar(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: AnsiChar
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtAnsiChar)^.AnsiCharData := AData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutWideChar(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: WideChar
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtWideChar)^.WideCharData := AData;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutInt64(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: Int64
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtInt64S)^.Int64S := AData;
|
|
end;
|
|
|
|
{$IFDEF HAS_QWORD}
|
|
procedure TBaseBinaryFormatter.PutUInt64(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: QWord
|
|
);
|
|
begin
|
|
StackTop().CreateBuffer(AName,dtInt64U)^.Int64U := AData;
|
|
end;
|
|
{$ENDIF HAS_QWORD}
|
|
|
|
procedure TBaseBinaryFormatter.PutObj(
|
|
const AName: String;
|
|
const ATypeInfo: PTypeInfo;
|
|
const AData: TObject
|
|
);
|
|
begin
|
|
TBaseRemotableClass(GetTypeData(ATypeInfo)^.ClassType).Save(AData As TBaseRemotable, Self,AName,ATypeInfo);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutRecord(
|
|
const AName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData : Pointer
|
|
);
|
|
begin
|
|
TRemotableRecordEncoder.Save(AData,Self,AName,ATypeInfo);
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetDataBuffer(
|
|
var AName: string;
|
|
out AResultBuffer : PDataBuffer
|
|
) : Boolean;
|
|
begin
|
|
AResultBuffer := StackTop().Find(AName);
|
|
Result := ( AResultBuffer <> nil );
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetEnum(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: TEnumData
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.EnumData;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetBool(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: Boolean
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.BoolData;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetAnsiChar(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: AnsiChar
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.AnsiCharData;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetWideChar(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: WideChar
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.WideCharData;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetFloat(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : String;
|
|
var AData : TFloat_Extended_10
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then begin
|
|
case GetTypeData(ATypeInfo)^.FloatType Of
|
|
ftSingle : AData := locBuffer^.SingleData;
|
|
ftDouble : AData := locBuffer^.DoubleData;
|
|
ftExtended : AData := locBuffer^.ExtendedData;
|
|
ftCurr : AData := locBuffer^.CurrencyData;
|
|
else
|
|
AData := locBuffer^.ExtendedData;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetInt(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: TInt64S
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then begin
|
|
case GetTypeData(ATypeInfo)^.OrdType of
|
|
otSByte : AData := locBuffer^.Int8S;
|
|
otUByte : AData := locBuffer^.Int8U;
|
|
otSWord : AData := locBuffer^.Int16S;
|
|
otUWord : AData := locBuffer^.Int16U;
|
|
otSLong : AData := locBuffer^.Int32S;
|
|
otULong : AData := locBuffer^.Int32U;
|
|
Else
|
|
Assert(False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetInt64(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: Int64
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.Int64S;
|
|
end;
|
|
|
|
{$IFDEF HAS_QWORD}
|
|
function TBaseBinaryFormatter.GetUInt64(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: QWord
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then
|
|
AData := locBuffer^.Int64U;
|
|
end;
|
|
{$ENDIF HAS_QWORD}
|
|
|
|
function TBaseBinaryFormatter.GetAnsiStr(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: AnsiString
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then begin
|
|
case locBuffer^.DataType of
|
|
dtUnicodeString : AData := locBuffer^.UnicodeStrData^.Data;
|
|
dtWideString : AData := locBuffer^.WideStrData^.Data;
|
|
else
|
|
AData := locBuffer^.AnsiStrData^.Data;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetWideStr(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: WideString
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then begin
|
|
case locBuffer^.DataType of
|
|
dtAnsiString : AData := locBuffer^.AnsiStrData^.Data;
|
|
dtUnicodeString : AData := locBuffer^.UnicodeStrData^.Data;
|
|
else
|
|
AData := locBuffer^.WideStrData^.Data;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ $IFDEF WST_UNICODESTRING}
|
|
function TBaseBinaryFormatter.GetUnicodeStr(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: UnicodeString
|
|
) : Boolean;
|
|
var
|
|
locBuffer : PDataBuffer;
|
|
begin
|
|
Result := GetDataBuffer(AName,locBuffer);
|
|
if Result then begin
|
|
case locBuffer^.DataType of
|
|
dtAnsiString : AData := locBuffer^.AnsiStrData^.Data;
|
|
dtWideString : AData := locBuffer^.WideStrData^.Data;
|
|
else
|
|
AData := locBuffer^.UnicodeStrData^.Data;
|
|
end;
|
|
end;
|
|
end;
|
|
{ $ENDIF WST_UNICODESTRING}
|
|
|
|
function TBaseBinaryFormatter.GetObj(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData: TObject
|
|
) : Boolean;
|
|
begin
|
|
{ TODO -cEXCEPTION_SAFE : Load() should be a function ! }
|
|
TBaseRemotableClass(GetTypeData(ATypeInfo)^.ClassType).Load(AData, Self,AName,ATypeInfo);
|
|
Result := True;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetRecord(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AName : String;
|
|
var AData : Pointer
|
|
) : Boolean;
|
|
begin
|
|
{ TODO -cEXCEPTION_SAFE : Load() should be a function ! }
|
|
TRemotableRecordEncoder.Load(AData, Self,AName,ATypeInfo);
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.Clear();
|
|
begin
|
|
ClearStack();
|
|
ClearObj(FRootData);
|
|
Freemem(FRootData);
|
|
FRootData := CreateObjBuffer(dtObject,sROOT);
|
|
PushStack(FRootData,stObject);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.BeginArray(
|
|
const AName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AItemTypeInfo : PTypeInfo;
|
|
const ABounds : Array Of Integer;
|
|
const AStyle : TArrayStyle
|
|
);
|
|
var
|
|
i, j, k : Integer;
|
|
begin
|
|
If ( Length(ABounds) < 2 ) Then
|
|
Raise EBinaryFormatterException.Create(SERR_InvalidArrayBounds);
|
|
i := ABounds[0];
|
|
j := ABounds[1];
|
|
k := ( j - i + 1 );
|
|
If ( k < 0 ) Then
|
|
Raise EBinaryFormatterException.Create(SERR_InvalidArrayBounds);
|
|
PushStack(CreateArrayBuffer(k,AName,StackTop().ScopeObject),stArray);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.NilCurrentScope();
|
|
begin
|
|
CheckScope();
|
|
StackTop().NilCurrentScope();
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.IsCurrentScopeNil(): Boolean;
|
|
begin
|
|
Result := StackTop().IsCurrentScopeNil();
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.BeginObject(
|
|
const AName: string;
|
|
const ATypeInfo: PTypeInfo
|
|
);
|
|
begin
|
|
PushStack(StackTop().CreateBuffer(AName,dtObject));
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.EndScope();
|
|
begin
|
|
FStack.Pop().Free();
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.AddScopeAttribute(const AName, AValue: string);
|
|
begin
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.BeginObjectRead(
|
|
var AScopeName : string;
|
|
const ATypeInfo : PTypeInfo
|
|
): Integer;
|
|
var
|
|
locNode : PDataBuffer;
|
|
stk : TStackItem;
|
|
begin
|
|
stk := StackTop();
|
|
locNode := stk.Find(AScopeName);
|
|
if (locNode <> nil) then begin
|
|
PushStack(locNode,stObject);
|
|
Result := StackTop().GetItemCount();
|
|
end else begin
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.BeginArrayRead(
|
|
var AScopeName : string;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AStyle : TArrayStyle;
|
|
const AItemName : string
|
|
): Integer;
|
|
var
|
|
locNode : PDataBuffer;
|
|
stk : TStackItem;
|
|
begin
|
|
stk := StackTop();
|
|
locNode := stk.Find(AScopeName);
|
|
if ( locNode <> nil ) then begin
|
|
PushStack(locNode,stArray);
|
|
Result := StackTop().GetItemCount();
|
|
end else begin
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetScopeItemNames(const AReturnList : TStrings) : Integer;
|
|
begin
|
|
CheckScope();
|
|
Result := StackTop.GetScopeItemNames(AReturnList);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.EndScopeRead();
|
|
begin
|
|
PopStack().Free();
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.BeginHeader();
|
|
begin
|
|
{$IFDEF wst_binary_header}
|
|
if ( FHeaderEnterCount <= 0 ) then begin
|
|
Inc(FHeaderEnterCount);
|
|
BeginObject(sHEADER,nil);
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.EndHeader();
|
|
begin
|
|
{$IFDEF wst_binary_header}
|
|
if ( FHeaderEnterCount > 0 ) then begin
|
|
Dec(FHeaderEnterCount);
|
|
EndScope();
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.Put(const AName: String; const ATypeInfo: PTypeInfo;const AData);
|
|
Var
|
|
int64Data : Int64;
|
|
{$IFDEF HAS_QWORD}
|
|
uint64Data : QWOrd;
|
|
{$ENDIF HAS_QWORD}
|
|
ansiStrData : AnsiString;
|
|
objData : TObject;
|
|
boolData : Boolean;
|
|
enumData : TEnumData;
|
|
floatDt : TFloat_Extended_10;
|
|
wideStrData : WideString;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
unicodeStrData : UnicodeString;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
ansiCharData : AnsiChar;
|
|
wideCharData : WideChar;
|
|
begin
|
|
Case ATypeInfo^.Kind Of
|
|
tkChar :
|
|
begin
|
|
ansiCharData := AnsiChar(AData);
|
|
PutAnsiChar(AName,ATypeInfo,ansiCharData);
|
|
end;
|
|
tkWChar :
|
|
begin
|
|
wideCharData := WideChar(AData);
|
|
PutWideChar(AName,ATypeInfo,wideCharData);
|
|
end;
|
|
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
|
|
Begin
|
|
ansiStrData := AnsiString(AData);
|
|
PutAnsiStr(AName,ATypeInfo,ansiStrData);
|
|
End;
|
|
tkWString :
|
|
begin
|
|
wideStrData := WideString(AData);
|
|
PutWideStr(AName,ATypeInfo,wideStrData);
|
|
end;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
tkUString :
|
|
begin
|
|
unicodeStrData := UnicodeString(AData);
|
|
PutUnicodeStr(AName,ATypeInfo,unicodeStrData);
|
|
end;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
tkInt64 :
|
|
Begin
|
|
int64Data := Int64(AData);
|
|
PutInt64(AName,ATypeInfo,int64Data);
|
|
End;
|
|
{$IFDEF HAS_QWORD}
|
|
tkQWord :
|
|
Begin
|
|
uint64Data := QWord(AData);
|
|
PutUInt64(AName,ATypeInfo,uint64Data);
|
|
End;
|
|
{$ENDIF HAS_QWORD}
|
|
tkClass :
|
|
Begin
|
|
objData := TObject(AData);
|
|
PutObj(AName,ATypeInfo,objData);
|
|
End;
|
|
tkRecord :
|
|
begin
|
|
PutRecord(AName,ATypeInfo,Pointer(@AData));
|
|
end;
|
|
{$IFDEF FPC}
|
|
tkBool :
|
|
Begin
|
|
boolData := Boolean(AData);
|
|
PutBool(AName,ATypeInfo,boolData);
|
|
End;
|
|
{$ENDIF}
|
|
tkInteger, tkEnumeration :
|
|
begin
|
|
{$IFNDEF FPC}
|
|
if ( ATypeInfo^.Kind = tkEnumeration ) and
|
|
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
|
|
then begin
|
|
boolData := Boolean(AData);
|
|
PutBool(AName,ATypeInfo,boolData);
|
|
end else begin
|
|
{$ENDIF}
|
|
enumData := 0;
|
|
Case GetTypeData(ATypeInfo)^.OrdType Of
|
|
otSByte : enumData := ShortInt(AData);
|
|
otUByte : enumData := Byte(AData);
|
|
otSWord : enumData := SmallInt(AData);
|
|
otUWord : enumData := Word(AData);
|
|
otSLong : enumData := LongInt(AData);
|
|
otULong : enumData := LongWord(AData);
|
|
End;
|
|
If ( ATypeInfo^.Kind = tkInteger ) Then
|
|
PutInt(AName,ATypeInfo,enumData)
|
|
Else
|
|
PutEnum(AName,ATypeInfo,enumData);
|
|
{$IFNDEF FPC}
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
tkFloat :
|
|
Begin
|
|
floatDt := 0;
|
|
Case GetTypeData(ATypeInfo)^.FloatType Of
|
|
ftSingle : floatDt := Single(AData);
|
|
ftDouble : floatDt := Double(AData);
|
|
ftExtended : floatDt := Extended(AData);
|
|
ftCurr : floatDt := Currency(AData);
|
|
ftComp : floatDt := Comp(AData);
|
|
End;
|
|
PutFloat(AName,ATypeInfo,floatDt);
|
|
End;
|
|
End;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.Put(
|
|
const ANameSpace : string;
|
|
const AName : String;
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData
|
|
);
|
|
begin
|
|
Put(AName,ATypeInfo,AData);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.PutScopeInnerValue(
|
|
const ATypeInfo : PTypeInfo;
|
|
const AData
|
|
);
|
|
var
|
|
int64SData : Int64;
|
|
{$IFDEF HAS_QWORD}
|
|
uint64Data : QWord;
|
|
{$ENDIF HAS_QWORD}
|
|
strData : string;
|
|
boolData : Boolean;
|
|
enumData : TEnumData;
|
|
floatDt : TFloat_Extended_10;
|
|
wideStrData : WideString;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
unicodeStrData : UnicodeString;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
ansiCharData : AnsiChar;
|
|
wideCharData : WideChar;
|
|
begin
|
|
CheckScope();
|
|
case ATypeInfo^.Kind of
|
|
tkChar :
|
|
begin
|
|
ansiCharData := AnsiChar(AData);
|
|
StackTop().CreateInnerBuffer(dtAnsiChar)^.AnsiCharData:= ansiCharData;
|
|
end;
|
|
tkWChar :
|
|
begin
|
|
wideCharData := WideChar(AData);
|
|
StackTop().CreateInnerBuffer(dtWideChar)^.WideCharData:= wideCharData;
|
|
end;
|
|
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
|
|
begin
|
|
strData := AnsiString(AData);
|
|
StackTop().CreateInnerBuffer(dtAnsiString)^.AnsiStrData^.Data := strData;
|
|
end;
|
|
tkWString :
|
|
begin
|
|
wideStrData := WideString(AData);
|
|
StackTop().CreateInnerBuffer(dtWideString)^.WideStrData^.Data := wideStrData;
|
|
end;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
tkUString :
|
|
begin
|
|
unicodeStrData := UnicodeString(AData);
|
|
StackTop().CreateInnerBuffer(dtUnicodeString)^.UnicodeStrData^.Data := unicodeStrData;
|
|
end;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
tkInt64 :
|
|
begin
|
|
int64SData := Int64(AData);
|
|
StackTop().CreateInnerBuffer(dtInt64S)^.Int64S := int64SData;
|
|
end;
|
|
{$IFDEF HAS_QWORD}
|
|
tkQWord :
|
|
begin
|
|
uint64Data := QWord(AData);
|
|
StackTop().CreateInnerBuffer(dtInt64U)^.Int64U := uint64Data;
|
|
end;
|
|
{$ENDIF HAS_QWORD}
|
|
tkClass, tkRecord :
|
|
begin
|
|
raise EBinaryFormatterException.Create(SERR_InnerScopeMustBeSimpleType);
|
|
end;
|
|
{$IFDEF FPC}
|
|
tkBool :
|
|
begin
|
|
boolData := Boolean(AData);
|
|
StackTop().CreateInnerBuffer(dtBool)^.BoolData := boolData;
|
|
end;
|
|
{$ENDIF}
|
|
tkInteger :
|
|
begin
|
|
enumData := 0;
|
|
case GetTypeData(ATypeInfo)^.OrdType of
|
|
otSByte :
|
|
begin
|
|
enumData := ShortInt(AData);
|
|
StackTop().CreateInnerBuffer(dtInt8S)^.Int8S := enumData;
|
|
end;
|
|
otUByte :
|
|
begin
|
|
enumData := Byte(AData);
|
|
StackTop().CreateInnerBuffer(dtInt8U)^.Int8U := enumData;
|
|
end;
|
|
otSWord :
|
|
begin
|
|
enumData := SmallInt(AData);
|
|
StackTop().CreateInnerBuffer(dtInt16S)^.Int16S := enumData;
|
|
end;
|
|
otUWord :
|
|
begin
|
|
enumData := Word(AData);
|
|
StackTop().CreateInnerBuffer(dtInt16U)^.Int16U := enumData;
|
|
end;
|
|
otSLong :
|
|
begin
|
|
enumData := LongInt(AData);
|
|
StackTop().CreateInnerBuffer(dtInt32S)^.Int32S := enumData;
|
|
end;
|
|
otULong :
|
|
begin
|
|
enumData := LongWord(AData);
|
|
StackTop().CreateInnerBuffer(dtInt32U)^.Int32U := enumData;
|
|
end;
|
|
end;
|
|
end;
|
|
tkEnumeration :
|
|
begin
|
|
{$IFNDEF FPC}
|
|
if ( ATypeInfo^.Kind = tkEnumeration ) and
|
|
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
|
|
then begin
|
|
boolData := Boolean(AData);
|
|
StackTop().CreateInnerBuffer(dtBool)^.BoolData := boolData;
|
|
end else begin
|
|
{$ENDIF}
|
|
enumData := 0;
|
|
case GetTypeData(ATypeInfo)^.OrdType of
|
|
otSByte : enumData := ShortInt(AData);
|
|
otUByte : enumData := Byte(AData);
|
|
otSWord : enumData := SmallInt(AData);
|
|
otUWord : enumData := Word(AData);
|
|
otSLong : enumData := LongInt(AData);
|
|
otULong : enumData := LongWord(AData);
|
|
end;
|
|
StackTop().CreateInnerBuffer(dtEnum)^.EnumData := enumData;
|
|
{$IFNDEF FPC}
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
tkFloat :
|
|
begin
|
|
floatDt := 0;
|
|
case GetTypeData(ATypeInfo)^.FloatType of
|
|
ftSingle :
|
|
begin
|
|
floatDt := Single(AData);
|
|
StackTop().CreateInnerBuffer(dtSingle)^.SingleData := floatDt;
|
|
end;
|
|
ftDouble :
|
|
begin
|
|
floatDt := Double(AData);
|
|
StackTop().CreateInnerBuffer(dtDouble)^.DoubleData := floatDt;
|
|
end;
|
|
ftExtended :
|
|
begin
|
|
floatDt := Extended(AData);
|
|
StackTop().CreateInnerBuffer(dtExtended)^.ExtendedData := floatDt;
|
|
end;
|
|
ftCurr :
|
|
begin
|
|
floatDt := Currency(AData);
|
|
StackTop().CreateInnerBuffer(dtExtended)^.CurrencyData := floatDt;
|
|
end;
|
|
ftComp :
|
|
begin
|
|
floatDt := Comp(AData);
|
|
StackTop().CreateInnerBuffer(dtCurrency)^.CurrencyData := floatDt;
|
|
end;
|
|
else
|
|
StackTop().CreateInnerBuffer(dtExtended)^.ExtendedData := floatDt;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.Get(
|
|
const ATypeInfo: PTypeInfo;
|
|
var AName: String;
|
|
var AData
|
|
) : Boolean;
|
|
Var
|
|
int64Data : Int64;
|
|
{$IFDEF HAS_QWORD}
|
|
uint64Data : QWOrd;
|
|
{$ENDIF HAS_QWORD}
|
|
strData : AnsiString;
|
|
objData : TObject;
|
|
boolData : Boolean;
|
|
enumData : TEnumData;
|
|
floatDt : TFloat_Extended_10;
|
|
recObject : Pointer;
|
|
wideStrData : WideString;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
unicodeStrData : UnicodeString;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
ansiCharData : AnsiChar;
|
|
wideCharData : WideChar;
|
|
begin
|
|
Case ATypeInfo^.Kind Of
|
|
tkInt64 :
|
|
Begin
|
|
int64Data := 0;
|
|
Result := GetInt64(ATypeInfo,AName,int64Data);
|
|
if Result then
|
|
Int64(AData) := int64Data;
|
|
End;
|
|
{$IFDEF HAS_QWORD}
|
|
tkQWord :
|
|
Begin
|
|
uint64Data := 0;
|
|
Result := GetUInt64(ATypeInfo,AName,uint64Data);
|
|
if Result then
|
|
QWord(AData) := uint64Data;
|
|
End;
|
|
{$ENDIF HAS_QWORD}
|
|
tkLString{$IFDEF FPC},tkAString{$ENDIF} :
|
|
Begin
|
|
strData := '';
|
|
Result := GetAnsiStr(ATypeInfo,AName,strData);
|
|
if Result then
|
|
AnsiString(AData) := strData;
|
|
End;
|
|
tkWString :
|
|
begin
|
|
wideStrData := '';
|
|
Result := GetWideStr(ATypeInfo,AName,wideStrData);
|
|
if Result then
|
|
WideString(AData) := wideStrData;
|
|
end;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
tkUString :
|
|
begin
|
|
unicodeStrData := '';
|
|
Result := GetUnicodeStr(ATypeInfo,AName,unicodeStrData);
|
|
if Result then
|
|
UnicodeString(AData) := unicodeStrData;
|
|
end;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
tkClass :
|
|
Begin
|
|
objData := TObject(AData);
|
|
Result := GetObj(ATypeInfo,AName,objData);
|
|
if Result then
|
|
TObject(AData) := objData;
|
|
End;
|
|
tkRecord :
|
|
begin
|
|
recObject := Pointer(@AData);
|
|
Result := GetRecord(ATypeInfo,AName,recObject);
|
|
end;
|
|
{$IFDEF FPC}
|
|
tkBool :
|
|
Begin
|
|
boolData := False;
|
|
Result := GetBool(ATypeInfo,AName,boolData);
|
|
if Result then
|
|
Boolean(AData) := boolData;
|
|
End;
|
|
{$ENDIF}
|
|
tkChar :
|
|
begin
|
|
ansiCharData := #0;
|
|
Result := GetAnsiChar(ATypeInfo,AName,ansiCharData);
|
|
if Result then
|
|
AnsiChar(AData) := ansiCharData;
|
|
end;
|
|
tkWChar :
|
|
begin
|
|
wideCharData := #0;
|
|
Result := GetWideChar(ATypeInfo,AName,wideCharData);
|
|
if Result then
|
|
WideChar(AData) := wideCharData;
|
|
end;
|
|
tkInteger, tkEnumeration :
|
|
Begin
|
|
{$IFNDEF FPC}
|
|
if ( ATypeInfo^.Kind = tkEnumeration ) and
|
|
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
|
|
then begin
|
|
boolData := False;
|
|
Result := GetBool(ATypeInfo,AName,boolData);
|
|
if Result then
|
|
Boolean(AData) := boolData;
|
|
end else begin
|
|
{$ENDIF}
|
|
enumData := 0;
|
|
If ( ATypeInfo^.Kind = tkInteger ) Then
|
|
Result := GetInt(ATypeInfo,AName,enumData)
|
|
Else
|
|
Result := GetEnum(ATypeInfo,AName,enumData);
|
|
if Result then begin
|
|
Case GetTypeData(ATypeInfo)^.OrdType Of
|
|
otSByte : ShortInt(AData) := enumData;
|
|
otUByte : Byte(AData) := enumData;
|
|
otSWord : SmallInt(AData) := enumData;
|
|
otUWord : Word(AData) := enumData;
|
|
otSLong : LongInt(AData) := enumData;
|
|
otULong : LongWord(AData) := enumData;
|
|
End;
|
|
end;
|
|
{$IFNDEF FPC}
|
|
end;
|
|
{$ENDIF}
|
|
End;
|
|
tkFloat :
|
|
Begin
|
|
floatDt := 0;
|
|
Result := GetFloat(ATypeInfo,AName,floatDt);
|
|
if Result then begin
|
|
Case GetTypeData(ATypeInfo)^.FloatType Of
|
|
ftSingle : Single(AData) := floatDt;
|
|
ftDouble : Double(AData) := floatDt;
|
|
ftExtended : Extended(AData) := floatDt;
|
|
ftCurr : Currency(AData) := floatDt;
|
|
{$IFDEF HAS_COMP}
|
|
ftComp : Comp(AData) := floatDt;
|
|
{$ENDIF}
|
|
End;
|
|
end
|
|
end;
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.Get(
|
|
const ATypeInfo : PTypeInfo;
|
|
const ANameSpace : string;
|
|
var AName : string;
|
|
var AData
|
|
) : Boolean;
|
|
begin
|
|
Result := Get(ATypeInfo,AName,AData);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.GetScopeInnerValue(
|
|
const ATypeInfo : PTypeInfo;
|
|
var AData
|
|
);
|
|
Var
|
|
dataBuffer : PDataBuffer;
|
|
begin
|
|
CheckScope();
|
|
dataBuffer := StackTop().GetInnerBuffer();
|
|
Case ATypeInfo^.Kind Of
|
|
tkChar : AnsiChar(AData) := dataBuffer^.AnsiCharData ;
|
|
tkWChar : WideChar(AData) := dataBuffer^.WideCharData ;
|
|
tkInt64 : Int64(AData) := dataBuffer^.Int64S;
|
|
{$IFDEF HAS_QWORD}
|
|
tkQWord : QWord(AData) := dataBuffer^.Int64U;
|
|
{$ENDIF HAS_QWORD}
|
|
|
|
tkLString
|
|
{$IFDEF FPC},
|
|
tkAString
|
|
{$ENDIF} :
|
|
begin
|
|
case dataBuffer^.DataType of
|
|
dtUnicodeString : AnsiString(AData) := dataBuffer^.UnicodeStrData^.Data;
|
|
dtWideString : AnsiString(AData) := dataBuffer^.WideStrData^.Data;
|
|
else
|
|
AnsiString(AData) := dataBuffer^.AnsiStrData^.Data;
|
|
end;
|
|
end;
|
|
tkWString :
|
|
begin
|
|
case dataBuffer^.DataType of
|
|
dtUnicodeString : WideString(AData) := dataBuffer^.UnicodeStrData^.Data;
|
|
dtAnsiString : WideString(AData) := dataBuffer^.AnsiStrData^.Data;
|
|
else
|
|
WideString(AData) := dataBuffer^.WideStrData^.Data;
|
|
end;
|
|
end;
|
|
{$IFDEF WST_UNICODESTRING}
|
|
tkUString :
|
|
begin
|
|
case dataBuffer^.DataType of
|
|
dtAnsiString : UnicodeString(AData) := dataBuffer^.AnsiStrData^.Data;
|
|
dtWideString : UnicodeString(AData) := dataBuffer^.WideStrData^.Data;
|
|
else
|
|
UnicodeString(AData) := dataBuffer^.UnicodeStrData^.Data;
|
|
end;
|
|
end;
|
|
{$ENDIF WST_UNICODESTRING}
|
|
|
|
tkClass, tkRecord : raise EBinaryFormatterException.Create(SERR_InnerScopeMustBeSimpleType);
|
|
{$IFDEF FPC}
|
|
tkBool : Boolean(AData) := dataBuffer^.BoolData;
|
|
{$ENDIF}
|
|
tkInteger :
|
|
begin
|
|
case GetTypeData(ATypeInfo)^.OrdType Of
|
|
otSByte : ShortInt(AData) := dataBuffer^.Int8S;
|
|
otUByte : Byte(AData) := dataBuffer^.Int8U;
|
|
otSWord : SmallInt(AData) := dataBuffer^.Int16S;
|
|
otUWord : Word(AData) := dataBuffer^.Int16U;
|
|
otSLong : LongInt(AData) := dataBuffer^.Int32S;
|
|
otULong : LongWord(AData) := dataBuffer^.Int32U;
|
|
end;
|
|
end;
|
|
tkEnumeration :
|
|
begin
|
|
{$IFNDEF FPC}
|
|
if ( ATypeInfo^.Kind = tkEnumeration ) and
|
|
( GetTypeData(ATypeInfo)^.BaseType^ = TypeInfo(Boolean) )
|
|
then begin
|
|
Boolean(AData) := dataBuffer^.BoolData;
|
|
end else begin
|
|
{$ENDIF}
|
|
case GetTypeData(ATypeInfo)^.OrdType Of
|
|
otSByte : ShortInt(AData) := dataBuffer^.EnumData;
|
|
otUByte : Byte(AData) := dataBuffer^.EnumData;
|
|
otSWord : SmallInt(AData) := dataBuffer^.EnumData;
|
|
otUWord : Word(AData) := dataBuffer^.EnumData;
|
|
otSLong : LongInt(AData) := dataBuffer^.EnumData;
|
|
otULong : LongWord(AData) := dataBuffer^.EnumData;
|
|
end;
|
|
{$IFNDEF FPC}
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
tkFloat :
|
|
begin
|
|
case GetTypeData(ATypeInfo)^.FloatType of
|
|
ftSingle : Single(AData) := dataBuffer^.SingleData;
|
|
ftDouble : Double(AData) := dataBuffer^.DoubleData;
|
|
ftExtended : Extended(AData) := dataBuffer^.ExtendedData;
|
|
ftCurr : Currency(AData) := dataBuffer^.CurrencyData;
|
|
{$IFDEF HAS_COMP}
|
|
else
|
|
Comp(AData) := dataBuffer^.ExtendedData;
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.ReadBuffer (const AName : string; out AResBuffer : string) : Boolean;
|
|
Var
|
|
locStore : IDataStore;
|
|
bffr : PDataBuffer;
|
|
locName : string;
|
|
locStream : TStringStream;
|
|
begin
|
|
locName := AName;
|
|
Result := GetDataBuffer(locName,bffr);
|
|
if Result then begin
|
|
locStream := TStringStream.Create('');
|
|
try
|
|
locStore := CreateBinaryWriter(locStream);
|
|
SaveObjectToStream(bffr,locStore);
|
|
AResBuffer := locStream.DataString;
|
|
finally
|
|
locStream.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.SaveToStream(AStream: TStream);
|
|
Var
|
|
locStore : IDataStore;
|
|
begin
|
|
locStore := CreateBinaryWriter(AStream);
|
|
SaveObjectToStream(FRootData,locStore);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.LoadFromStream(AStream: TStream);
|
|
Var
|
|
locRdr : IDataStoreReader;
|
|
tmpRoot : PDataBuffer;
|
|
begin
|
|
locRdr := CreateBinaryReader(AStream);
|
|
tmpRoot := LoadObjectFromStream(locRdr);
|
|
|
|
ClearStack();
|
|
ClearObj(FRootData);
|
|
Freemem(FRootData);
|
|
FRootData := tmpRoot;
|
|
PushStack(FRootData,stObject);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.Error(const AMsg: string);
|
|
begin
|
|
Raise EBinaryFormatterException.Create(AMsg);
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.Error(const AMsg: string;const AArgs: array of const);
|
|
begin
|
|
Raise EBinaryFormatterException.CreateFmt(AMsg,AArgs);
|
|
end;
|
|
|
|
constructor TBaseBinaryFormatter.Create();
|
|
begin
|
|
FRootData := CreateObjBuffer(dtObject,sROOT);
|
|
FStack := TObjectStack.Create();
|
|
PushStack(FRootData,stObject);
|
|
end;
|
|
|
|
destructor TBaseBinaryFormatter.Destroy();
|
|
begin
|
|
ClearStack();
|
|
FreeAndNil(FStack);
|
|
ClearObj(FRootData);
|
|
Freemem(FRootData);
|
|
inherited Destroy();
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetFormatName() : string;
|
|
begin
|
|
Result := sBINARY_FORMAT_NAME;
|
|
end;
|
|
|
|
function TBaseBinaryFormatter.GetPropertyManager() : IPropertyManager;
|
|
begin
|
|
If Not Assigned(FPropMngr) Then
|
|
FPropMngr := TPublishedPropertyManager.Create(Self);
|
|
Result := FPropMngr;
|
|
end;
|
|
|
|
procedure TBaseBinaryFormatter.WriteBuffer(const AValue: string);
|
|
var
|
|
locStore : IDataStoreReader;
|
|
bffr : PDataBuffer;
|
|
locStream : TStringStream;
|
|
begin
|
|
CheckScope();
|
|
locStream := TStringStream.Create(AValue);
|
|
try
|
|
locStream.Position := 0;
|
|
locStore := CreateBinaryReader(locStream);
|
|
bffr := LoadObjectFromStream(locStore);
|
|
AddObj(StackTop.ScopeObject,bffr);
|
|
finally
|
|
locStream.Free();
|
|
end;
|
|
end;
|
|
|
|
{ TArrayStackItem }
|
|
|
|
constructor TArrayStackItem.Create(const AScopeObject: PDataBuffer);
|
|
begin
|
|
Inherited Create(AScopeObject,stArray);
|
|
FIndex := 0;
|
|
end;
|
|
|
|
function TArrayStackItem.GetItemCount(): Integer;
|
|
begin
|
|
Result := ScopeObject^.ArrayData^.Count;
|
|
end;
|
|
|
|
function TArrayStackItem.Find(var AName: TDataName): PDataBuffer;
|
|
begin
|
|
If ( FIndex >= 0 ) And ( FIndex < ScopeObject^.ArrayData^.Count ) Then
|
|
Result := ScopeObject^.ArrayData^.Items^[FIndex]
|
|
Else
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_IndexOutOfBound,[FIndex]);
|
|
Inc(FIndex);
|
|
end;
|
|
|
|
function TArrayStackItem.GetByIndex(const AIndex: Integer): PDataBuffer;
|
|
begin
|
|
If ( AIndex >= 0 ) And ( AIndex < ScopeObject^.ArrayData^.Count ) Then
|
|
Result := ScopeObject^.ArrayData^.Items^[AIndex]
|
|
Else
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_IndexOutOfBound,[AIndex]);
|
|
end;
|
|
|
|
function TArrayStackItem.CreateBuffer(
|
|
const AName : String;
|
|
const ADataType : TDataType
|
|
): PDataBuffer;
|
|
begin
|
|
If ( FIndex >= 0 ) And ( FIndex < ScopeObject^.ArrayData^.Count ) Then
|
|
Result := CreateObjBuffer(ADataType,AName,Nil)
|
|
Else
|
|
Raise EBinaryFormatterException.CreateFmt(SERR_IndexOutOfBound,[FIndex]);
|
|
ScopeObject^.ArrayData^.Items^[FIndex] := Result;
|
|
Inc(FIndex);
|
|
end;
|
|
|
|
{$WARNINGS OFF}
|
|
function TArrayStackItem.CreateInnerBuffer(const ADataType: TDataType): PDataBuffer;
|
|
begin
|
|
raise EBinaryFormatterException.CreateFmt(SERR_UnsupportedOperation,['TArrayStackItem.CreateInnerBuffer']);
|
|
end;
|
|
|
|
function TArrayStackItem.GetInnerBuffer(): PDataBuffer;
|
|
begin
|
|
raise EBinaryFormatterException.CreateFmt(SERR_UnsupportedOperation,['TArrayStackItem.GetInnerBuffer']);
|
|
end;
|
|
{$WARNINGS ON}
|
|
|
|
procedure TArrayStackItem.NilCurrentScope();
|
|
begin
|
|
end;
|
|
|
|
function TArrayStackItem.IsCurrentScopeNil(): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TArrayStackItem.GetScopeItemNames(const AReturnList: TStrings): Integer;
|
|
var
|
|
locBuffer : PDataBufferList;
|
|
i : Integer;
|
|
begin
|
|
AReturnList.Clear();
|
|
if Assigned(ScopeObject) and ( ScopeObject^.ArrayData^.Count > 0 ) then begin
|
|
locBuffer := ScopeObject^.ArrayData^.Items;
|
|
for i := 0 to Pred(ScopeObject^.ArrayData^.Count) do begin
|
|
AReturnList.Add(locBuffer^[i]^.Name);
|
|
end;
|
|
end;
|
|
Result := AReturnList.Count;
|
|
end;
|
|
|
|
end.
|