Files
lazarus-ccr/wst/trunk/binary_streamer.pas
inoussa 8f8b770f34 + Range check error fix
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@225 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2007-07-25 16:37:32 +00:00

523 lines
13 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}
{$RANGECHECKS OFF}
unit binary_streamer;
interface
uses
Classes, SysUtils, Types;
{$INCLUDE wst.inc}
{$INCLUDE wst_delphi.inc}
Const
MAX_ARRAY_LENGTH = 1024*1024;
Type
TInt8U = Byte; TInt8S = ShortInt;
TInt16U = Word; TInt16S = SmallInt;
TInt32U = LongWord; TInt32S = LongInt;
TInt64S = Int64;TInt64U = QWord;
TBoolData = Boolean;
TEnumData = Int64;
TStringData = AnsiString;
TFloat_Single_4 = Single;
TFloat_Double_8 = Double;
TFloat_Extended_10 = Extended;
TFloat_Currency_8 = Currency;
IDataStore = Interface
['{CA767A0E-7660-4765-9959-6960A69B1660}']
procedure WriteInt8U(Const AData : TInt8U);
procedure WriteInt8S(Const AData : TInt8S);
procedure WriteInt16U(Const AData : TInt16U);
procedure WriteInt16S(Const AData : TInt16S);
procedure WriteInt32U(Const AData : TInt32U);
procedure WriteInt32S(Const AData : TInt32S);
procedure WriteInt64U(Const AData : TInt64U);
procedure WriteInt64S(Const AData : TInt64S);
procedure WriteBool(Const AData : TBoolData);
procedure WriteEnum(Const AData : TEnumData);
procedure WriteStr(Const AData : TStringData);
procedure WriteSingle(Const AData : TFloat_Single_4);
procedure WriteDouble(Const AData : TFloat_Double_8);
procedure WriteExtended(Const AData : TFloat_Extended_10);
procedure WriteCurrency(Const AData : TFloat_Currency_8);
End;
IDataStoreReader = Interface
['{AF50317E-6DD6-40C5-A2F6-3ED5F478564F}']
function IsAtEof():Boolean;
function ReadInt8U():TInt8U;
function ReadInt8S():TInt8S;
function ReadInt16U():TInt16U;
function ReadInt16S():TInt16S;
function ReadInt32U():TInt32U;
function ReadInt32S():TInt32S;
function ReadInt64U():TInt64U;
function ReadInt64S():TInt64S;
function ReadBool():TBoolData;
function ReadEnum():TEnumData;
function ReadStr():TStringData;
function ReadSingle():TFloat_Single_4;
function ReadDouble():TFloat_Double_8;
function ReadExtended():TFloat_Extended_10;
function ReadCurrency():TFloat_Currency_8;
End;
function CreateBinaryReader(AStream : TStream):IDataStoreReader;
function CreateBinaryWriter(AStream : TStream):IDataStore;
procedure ReverseBytes(var AData; const ALength : Integer);{$IFDEF USE_INLINE}{$IFDEF ENDIAN_BIG}inline;{$ENDIF}{$ENDIF}
function Reverse_16(const AValue:Word):Word;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_32(const AValue:DWord):DWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_64(const AValue:QWord):QWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_Single(const AValue:Single):Single;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_Double(const AValue:Double):Double;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_Extended(const AValue:Extended):Extended;{$IFDEF USE_INLINE}inline;{$ENDIF}
function Reverse_Currency(const AValue:Currency):Currency;{$IFDEF USE_INLINE}inline;{$ENDIF}
implementation
{$IFDEF ENDIAN_BIG}
procedure ReverseBytes(var AData; const ALength : Integer); {$IFDEF USE_INLINE}inline;{$ENDIF}
begin
end;
{$ELSE} // assume ENDIAN_LITTLE
procedure ReverseBytes(var AData; const ALength : Integer);
Var
i,j : PtrInt;
c : Byte;
pDt : {$IFDEF FPC}^Byte{$ELSE}PByteArray{$ENDIF};
begin
pDt := @AData;
j := ALength div 2;
For i := 0 To Pred(j) Do Begin
c := pDt{$IFNDEF FPC}^{$ENDIF}[i];
pDt[i] := pDt[(ALength - 1 ) - i];
pDt[(ALength - 1 ) - i] := c;
End;
end;
{$ENDIF}
function Reverse_16(const AValue:Word):Word;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,2)
end;
function Reverse_32(const AValue:DWord):DWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,4)
end;
function Reverse_64(const AValue:QWord):QWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,8)
end;
function Reverse_Single(const AValue:Single):Single;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,4)
end;
function Reverse_Double(const AValue:Double):Double;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,8)
end;
function Reverse_Extended(const AValue:Extended):Extended;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,10);
end;
function Reverse_Currency(const AValue:Currency):Currency;{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
Result := AValue;
ReverseBytes(Result,8);
end;
Type
{ TDataStore }
TDataStore = class(TInterfacedObject,IDataStore)
Private
FStream : TStream;
Protected
procedure WriteInt8U(Const AData : TInt8U);
procedure WriteInt8S(Const AData : TInt8S);
procedure WriteInt16U(Const AData : TInt16U);
procedure WriteInt16S(Const AData : TInt16S);
procedure WriteInt32U(Const AData : TInt32U);
procedure WriteInt32S(Const AData : TInt32S);
procedure WriteInt64U(Const AData : TInt64U);
procedure WriteInt64S(Const AData : TInt64S);
procedure WriteBool(Const AData : TBoolData);
procedure WriteEnum(Const AData : TEnumData);
procedure WriteStr(Const AData : TStringData);
procedure WriteSingle(Const AData : TFloat_Single_4);
procedure WriteDouble(Const AData : TFloat_Double_8);
procedure WriteExtended(Const AData : TFloat_Extended_10);
procedure WriteCurrency(Const AData : TFloat_Currency_8);
Public
constructor Create(AStream : TStream);
End;
{ TDataStoreReader }
TDataStoreReader = class(TInterfacedObject,IDataStoreReader)
Private
FStream : TStream;
Protected
function IsAtEof():Boolean;
function ReadInt8U():TInt8U;
function ReadInt8S():TInt8S;
function ReadInt16U():TInt16U;
function ReadInt16S():TInt16S;
function ReadInt32U():TInt32U;
function ReadInt32S():TInt32S;
function ReadInt64U():TInt64U;
function ReadInt64S():TInt64S;
function ReadBool():TBoolData;
function ReadEnum():TEnumData;
function ReadStr():TStringData;
function ReadSingle():TFloat_Single_4;
function ReadDouble():TFloat_Double_8;
function ReadExtended():TFloat_Extended_10;
function ReadCurrency():TFloat_Currency_8;
Public
constructor Create(AStream : TStream);
End;
function CreateBinaryWriter(AStream : TStream):IDataStore;
begin
Result := TDataStore.Create(AStream) As IDataStore;
end;
function CreateBinaryReader(AStream : TStream):IDataStoreReader;
begin
Result := TDataStoreReader.Create(AStream) As IDataStoreReader;
end;
{ TDataStore }
procedure TDataStore.WriteInt8U(const AData: TInt8U);
begin
FStream.Write(AData,SizeOf(AData));
end;
procedure TDataStore.WriteInt8S(const AData: TInt8S);
begin
FStream.Write(AData,SizeOf(AData));
end;
{$IFDEF FPC}
procedure TDataStore.WriteInt16U(const AData: TInt16U);
begin
FStream.Write(Reverse_16(AData),SizeOf(AData));
end;
procedure TDataStore.WriteInt16S(const AData: TInt16S);
begin
FStream.Write(Reverse_16(AData),SizeOf(AData));
end;
procedure TDataStore.WriteInt32U(const AData: TInt32U);
begin
FStream.Write(Reverse_32(AData),SizeOf(AData));
end;
procedure TDataStore.WriteInt32S(const AData: TInt32S);
begin
FStream.Write(Reverse_32(AData),SizeOf(AData));
end;
procedure TDataStore.WriteInt64U(const AData: TInt64U);
begin
FStream.Write(Reverse_64(AData),SizeOf(AData));
end;
procedure TDataStore.WriteInt64S(const AData: TInt64S);
begin
FStream.Write(Reverse_64(AData),SizeOf(AData));
end;
{$ELSE}
procedure TDataStore.WriteInt16U(const AData: TInt16U);
var
bffr : TInt16U;
begin
bffr := Reverse_16(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteInt16S(const AData: TInt16S);
var
bffr : TInt16U;
begin
bffr := Reverse_16(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteInt32U(const AData: TInt32U);
var
bffr : TInt32U;
begin
bffr := Reverse_32(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteInt32S(const AData: TInt32S);
var
bffr : TInt32U;
begin
bffr := Reverse_32(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteInt64U(const AData: TInt64U);
var
bffr : TInt64U;
begin
bffr := Reverse_64(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteInt64S(const AData: TInt64S);
var
bffr : TInt64U;
begin
bffr := Reverse_64(AData);
FStream.Write(bffr,SizeOf(AData));
end;
{$ENDIF}
procedure TDataStore.WriteBool(const AData: TBoolData);
Var
i : TInt8U;
begin
If AData Then
i := 1
Else
i := 0;
WriteInt8U(i);
end;
procedure TDataStore.WriteEnum(const AData: TEnumData);
begin
WriteInt64S(AData);
end;
procedure TDataStore.WriteStr(const AData: TStringData);
Var
i : TInt32S;
begin
i := Length(AData);
WriteInt32S(i);
If ( i > 0 ) Then
FStream.Write(AData[1],i);
end;
{
procedure TDataStore.WriteSingle(const AData: TFloat_Single_4);
begin
FStream.Write(Reverse_Single(AData),SizeOf(AData));
end;
procedure TDataStore.WriteDouble(const AData: TFloat_Double_8);
begin
FStream.Write(Reverse_Double(AData),SizeOf(AData));
end;
procedure TDataStore.WriteExtended(const AData: TFloat_Extended_10);
begin
FStream.Write(Reverse_Extended(AData),SizeOf(AData));
end;
procedure TDataStore.WriteCurrency(const AData: TFloat_Currency_8);
begin
FStream.Write(Reverse_Currency(AData),SizeOf(AData));
end;
}
procedure TDataStore.WriteSingle(const AData: TFloat_Single_4);
var
bffr : TFloat_Single_4;
begin
bffr := Reverse_Single(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteDouble(const AData: TFloat_Double_8);
var
bffr : TFloat_Double_8;
begin
bffr := Reverse_Double(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteExtended(const AData: TFloat_Extended_10);
var
bffr : TFloat_Extended_10;
begin
bffr := Reverse_Extended(AData);
FStream.Write(bffr,SizeOf(AData));
end;
procedure TDataStore.WriteCurrency(const AData: TFloat_Currency_8);
var
bffr : TFloat_Currency_8;
begin
bffr := Reverse_Currency(AData);
FStream.Write(bffr,SizeOf(AData));
end;
constructor TDataStore.Create(AStream: TStream);
begin
Assert(Assigned(AStream));
FStream := AStream;
end;
{ TDataStoreReader }
function TDataStoreReader.IsAtEof(): Boolean;
begin
Result := ( FStream.Position >= FStream.Size );
end;
function TDataStoreReader.ReadInt8U(): TInt8U;
begin
FStream.Read(Result,SizeOf(Result));
end;
function TDataStoreReader.ReadInt8S(): TInt8S;
begin
FStream.Read(Result,SizeOf(Result));
end;
function TDataStoreReader.ReadInt16U(): TInt16U;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_16(Result);
end;
function TDataStoreReader.ReadInt16S(): TInt16S;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_16(Result);
end;
function TDataStoreReader.ReadInt32U(): TInt32U;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_32(Result);
end;
function TDataStoreReader.ReadInt32S(): TInt32S;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_32(Result);
end;
function TDataStoreReader.ReadInt64U(): TInt64U;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_64(Result);
end;
function TDataStoreReader.ReadInt64S(): TInt64S;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_64(Result);
end;
function TDataStoreReader.ReadBool(): TBoolData;
begin
Result := ( ReadInt8U() > 0 );
end;
function TDataStoreReader.ReadEnum(): TEnumData;
begin
Result := ReadInt64S();
end;
function TDataStoreReader.ReadStr(): TStringData;
Var
i : TInt32S;
begin
i := ReadInt32S();
SetLength(Result,i);
If ( i > 0 ) Then
FStream.ReadBuffer(Result[1],i);
end;
function TDataStoreReader.ReadSingle(): TFloat_Single_4;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_Single(Result);
end;
function TDataStoreReader.ReadDouble(): TFloat_Double_8;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_Double(Result);
end;
function TDataStoreReader.ReadExtended(): TFloat_Extended_10;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_Extended(Result);
end;
function TDataStoreReader.ReadCurrency(): TFloat_Currency_8;
begin
FStream.Read(Result,SizeOf(Result));
Result := Reverse_Currency(Result);
end;
constructor TDataStoreReader.Create(AStream: TStream);
begin
Assert(Assigned(AStream));
FStream := AStream;
end;
end.