* Serialization : array and collection now have a "Options" property that can be used to indicate that they should be serialized, empty or not. To do so just include "ioAlwaysSerialize" in the "Options" property of the instance you want to customize.

* Test

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@861 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
inoussa
2009-06-25 13:54:10 +00:00
parent 02f81dec33
commit abf1f15cde
2 changed files with 233 additions and 48 deletions

View File

@ -47,6 +47,8 @@ type
TScopeType = Integer; TScopeType = Integer;
TArrayStyle = ( asScoped, asEmbeded, asNone ); TArrayStyle = ( asScoped, asEmbeded, asNone );
TInstanceOption = ( ioAlwaysSerialize );
TInstanceOptions = set of TInstanceOption;
THeaderDirection = ( hdOut, hdIn ); THeaderDirection = ( hdOut, hdIn );
THeaderDirections = set of THeaderDirection; THeaderDirections = set of THeaderDirection;
const const
@ -847,6 +849,7 @@ type
TObjectCollectionRemotable = class(TAbstractComplexRemotable) TObjectCollectionRemotable = class(TAbstractComplexRemotable)
private private
FList : TObjectList; FList : TObjectList;
FOptions : TInstanceOptions;
protected protected
function GetItem(AIndex : PtrInt) : TBaseRemotable;{$IFDEF USE_INLINE}inline;{$ENDIF} function GetItem(AIndex : PtrInt) : TBaseRemotable;{$IFDEF USE_INLINE}inline;{$ENDIF}
class function GetItemName():string;virtual; class function GetItemName():string;virtual;
@ -883,6 +886,7 @@ type
property Item[AIndex:PtrInt] : TBaseRemotable read GetItem;default; property Item[AIndex:PtrInt] : TBaseRemotable read GetItem;default;
property Length : PtrInt read GetLength; property Length : PtrInt read GetLength;
property Options : TInstanceOptions read FOptions write FOptions;
end; end;
TBaseArrayRemotableClass = class of TBaseArrayRemotable; TBaseArrayRemotableClass = class of TBaseArrayRemotable;
@ -890,6 +894,8 @@ type
{ TBaseArrayRemotable } { TBaseArrayRemotable }
TBaseArrayRemotable = class(TAbstractComplexRemotable) TBaseArrayRemotable = class(TAbstractComplexRemotable)
private
FOptions : TInstanceOptions;
protected protected
class function GetItemName():string;virtual; class function GetItemName():string;virtual;
class function GetStyle():TArrayStyle;virtual; class function GetStyle():TArrayStyle;virtual;
@ -901,6 +907,7 @@ type
procedure SetLength(const ANewSize : Integer);virtual;abstract; procedure SetLength(const ANewSize : Integer);virtual;abstract;
property Length : Integer Read GetLength; property Length : Integer Read GetLength;
property Options : TInstanceOptions read FOptions write FOptions;
end; end;
{ TBaseObjectArrayRemotable { TBaseObjectArrayRemotable
@ -2456,16 +2463,13 @@ Var
itmName : string; itmName : string;
styl : TArrayStyle; styl : TArrayStyle;
begin begin
if Assigned(AObject) then begin if ( AObject <> nil ) then begin
Assert(AObject.InheritsFrom(TBaseObjectArrayRemotable)); Assert(AObject.InheritsFrom(TBaseObjectArrayRemotable));
nativObj := AObject as TBaseObjectArrayRemotable; nativObj := AObject as TBaseObjectArrayRemotable;
arrayLen := nativObj.Length; arrayLen := nativObj.Length;
end else begin styl := GetStyle();
arrayLen := 0;
end;
if ( arrayLen > 0 ) then begin if ( arrayLen > 0 ) then begin
itmTypInfo := PTypeInfo(GetItemClass().ClassInfo); itmTypInfo := PTypeInfo(GetItemClass().ClassInfo);
styl := GetStyle();
AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),itmTypInfo,[0,Pred(arrayLen)],styl); AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),itmTypInfo,[0,Pred(arrayLen)],styl);
try try
if ( styl = asScoped ) then begin if ( styl = asScoped ) then begin
@ -2480,6 +2484,17 @@ begin
finally finally
AStore.EndScope(); AStore.EndScope();
end; end;
end else if ( styl = asScoped ) and ( ioAlwaysSerialize in nativObj.Options ) then begin
AStore.BeginArray(
AName, PTypeInfo(Self.ClassInfo),
PTypeInfo(GetItemClass().ClassInfo),[0,-1],styl
);
try
AStore.NilCurrentScope();
finally
AStore.EndScope();
end;
end;
end; end;
end; end;
@ -3313,11 +3328,8 @@ begin
Assert(AObject.InheritsFrom(TBaseSimpleTypeArrayRemotable)); Assert(AObject.InheritsFrom(TBaseSimpleTypeArrayRemotable));
nativObj := AObject as TBaseSimpleTypeArrayRemotable; nativObj := AObject as TBaseSimpleTypeArrayRemotable;
arrayLen := nativObj.Length; arrayLen := nativObj.Length;
end else begin
arrayLen := 0;
end;
if ( arrayLen > 0 ) then begin
styl := GetStyle(); styl := GetStyle();
if ( arrayLen > 0 ) then begin
AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),GetItemTypeInfo(),[0,Pred(arrayLen)],styl); AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),GetItemTypeInfo(),[0,Pred(arrayLen)],styl);
try try
if ( styl = asScoped ) then begin if ( styl = asScoped ) then begin
@ -3331,6 +3343,14 @@ begin
finally finally
AStore.EndScope(); AStore.EndScope();
end; end;
end else if ( styl = asScoped ) and ( ioAlwaysSerialize in nativObj.Options ) then begin
AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),GetItemTypeInfo(),[0,-1],styl);
try
AStore.NilCurrentScope();
finally
AStore.EndScope();
end;
end;
end; end;
end; end;
@ -3519,13 +3539,10 @@ begin
if Assigned(AObject) then begin if Assigned(AObject) then begin
Assert(AObject.InheritsFrom(TObjectCollectionRemotable)); Assert(AObject.InheritsFrom(TObjectCollectionRemotable));
nativObj := AObject as TObjectCollectionRemotable; nativObj := AObject as TObjectCollectionRemotable;
styl := GetStyle();
arrayLen := nativObj.Length; arrayLen := nativObj.Length;
end else begin
arrayLen := 0;
end;
if ( arrayLen > 0 ) then begin if ( arrayLen > 0 ) then begin
itmTypInfo := PTypeInfo(GetItemClass().ClassInfo); itmTypInfo := PTypeInfo(GetItemClass().ClassInfo);
styl := GetStyle();
AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),itmTypInfo,[0,Pred(arrayLen)],styl); AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),itmTypInfo,[0,Pred(arrayLen)],styl);
try try
if ( styl = asScoped ) then begin if ( styl = asScoped ) then begin
@ -3540,6 +3557,14 @@ begin
finally finally
AStore.EndScope(); AStore.EndScope();
end; end;
end else if ( styl = asScoped ) and ( ioAlwaysSerialize in nativObj.Options ) then begin
AStore.BeginArray(AName,PTypeInfo(Self.ClassInfo),itmTypInfo,[0,-1],styl);
try
AStore.NilCurrentScope();
finally
AStore.EndScope();
end;
end;
end; end;
end; end;

View File

@ -491,6 +491,7 @@ type
procedure Test_StringArray(); procedure Test_StringArray();
procedure Test_StringArray_Embedded(); procedure Test_StringArray_Embedded();
procedure Test_StringArrayZeroLength(); procedure Test_StringArrayZeroLength();
procedure Test_StringArrayZeroLength_serializeOption();
procedure Test_BooleanArray(); procedure Test_BooleanArray();
procedure Test_Int8UArray(); procedure Test_Int8UArray();
@ -512,7 +513,9 @@ type
procedure Test_ObjectArray(); procedure Test_ObjectArray();
procedure Test_ObjectArray_ReadEmptyArray(); procedure Test_ObjectArray_ReadEmptyArray();
procedure Test_ObjectArrayZeroLength_serializeOption();
procedure Test_ObjectCollection(); procedure Test_ObjectCollection();
procedure Test_ObjectCollectionZeroLength_serializeOption();
procedure Test_ObjectCollection_ReadEmptyCollection(); procedure Test_ObjectCollection_ReadEmptyCollection();
procedure Test_SimpleTypeArray_ReadEmptyArray(); procedure Test_SimpleTypeArray_ReadEmptyArray();
@ -3215,6 +3218,61 @@ begin
end; end;
end; end;
procedure TTestFormatter.Test_StringArrayZeroLength_serializeOption();
var
a : TArrayOfStringRemotable;
f : IFormatterBase;
s : TMemoryStream;
x : string;
ls : TStringList;
begin
a := nil;
s := nil;
ls := TStringList.Create();
try
a := TArrayOfStringRemotable.Create();
CheckEquals(0,a.Length);
a.Options := [];
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TArrayOfStringRemotable),a);
f.EndScope();
s := TMemoryStream.Create();
f.SaveToStream(s);
f := CreateFormatter(TypeInfo(TClass_B));
s.Position := 0;
f.LoadFromStream(s);
x := 'Root';
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(0,f.GetScopeItemNames(ls));
f.EndScopeRead();
a.Options := [ioAlwaysSerialize];
s.Clear();
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TArrayOfStringRemotable),a);
f.EndScope();
f.SaveToStream(s);
f := CreateFormatter(TypeInfo(TClass_B));
s.Position := 0;
f.LoadFromStream(s);
x := 'Root';
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(1,f.GetScopeItemNames(ls));
CheckEquals('a',ls[0]);
f.EndScopeRead();
finally
ls.Free();
a.Free();
s.Free();
end;
end;
procedure TTestFormatter.Test_BooleanArray(); procedure TTestFormatter.Test_BooleanArray();
const AR_LEN = 5; VAL_AR : array[0..(AR_LEN-1)] of Boolean = (True,True,False,True,False); const AR_LEN = 5; VAL_AR : array[0..(AR_LEN-1)] of Boolean = (True,True,False,True,False);
var var
@ -4009,6 +4067,57 @@ begin
end; end;
end; end;
procedure TTestFormatter.Test_ObjectArrayZeroLength_serializeOption();
var
a : TClass_A_Array;
f : IFormatterBase;
s : TMemoryStream;
x : string;
ls : TStringList;
begin
a := nil;
s := nil;
ls := TStringList.Create();
try
s := TMemoryStream.Create();
a := TClass_A_Array.Create();
a.SetLength(0);
a.Options := [];
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TClass_A_Array),a);
f.EndScope();
f.SaveToStream(s);
s.Position := 0;
f.LoadFromStream(s);
x := 'Root';
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(0, f.GetScopeItemNames(ls));
f.EndScopeRead();
a.Options := [ioAlwaysSerialize];
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TClass_A_Array),a);
f.EndScope();
s.Clear();
f.SaveToStream(s);
s.Position := 0;
f.LoadFromStream(s);
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(1, f.GetScopeItemNames(ls));
f.EndScopeRead();
CheckEquals('a', ls[0]);
finally
ls.Free();
a.Free();
s.Free();
end;
end;
procedure TTestFormatter.Test_ObjectCollection(); procedure TTestFormatter.Test_ObjectCollection();
const AR_LEN = 5; const AR_LEN = 5;
@ -4085,6 +4194,57 @@ begin
end; end;
end; end;
procedure TTestFormatter.Test_ObjectCollectionZeroLength_serializeOption();
var
a : TClass_A_Collection;
f : IFormatterBase;
s : TMemoryStream;
x : string;
ls : TStringList;
begin
a := nil;
s := nil;
ls := TStringList.Create();
try
s := TMemoryStream.Create();
a := TClass_A_Collection.Create();
a.Clear();
a.Options := [];
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TClass_A_Collection),a);
f.EndScope();
f.SaveToStream(s);
s.Position := 0;
f.LoadFromStream(s);
x := 'Root';
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(0, f.GetScopeItemNames(ls));
f.EndScopeRead();
a.Options := [ioAlwaysSerialize];
f := CreateFormatter(TypeInfo(TClass_B));
f.BeginObject('Root',TypeInfo(TClass_B));
f.Put('a',TypeInfo(TClass_A_Collection),a);
f.EndScope();
s.Clear();
f.SaveToStream(s);
s.Position := 0;
f.LoadFromStream(s);
f.BeginObjectRead(x,TypeInfo(TClass_B));
CheckEquals(1, f.GetScopeItemNames(ls));
f.EndScopeRead();
CheckEquals('a', ls[0]);
finally
ls.Free();
a.Free();
s.Free();
end;
end;
procedure TTestFormatter.Test_ObjectCollection_ReadEmptyCollection(); procedure TTestFormatter.Test_ObjectCollection_ReadEmptyCollection();
var var
a, areaded : TClass_A_Collection; a, areaded : TClass_A_Collection;