From 972b5181eb6501c54ce8194c71ce67469a0a5fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Van=20Canneyt?= <michael@freepascal.org> Date: Wed, 8 Nov 2023 11:27:21 +0100 Subject: [PATCH] * Delta stream support --- rtl/objpas/classes/classes.inc | 2 ++ rtl/objpas/classes/classesh.inc | 10 +++++++++- rtl/objpas/classes/compon.inc | 30 ++++++++++++++++++++++++++++++ rtl/objpas/classes/reader.inc | 29 +++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/rtl/objpas/classes/classes.inc b/rtl/objpas/classes/classes.inc index 98ed43a3aa..5cb5506c75 100644 --- a/rtl/objpas/classes/classes.inc +++ b/rtl/objpas/classes/classes.inc @@ -1462,6 +1462,8 @@ function DefaultInitHandler(Instance: TComponent; RootAncestor: TClass): Boolean try {$endif} result:=doinit(Instance.ClassType); + if Result then + Instance.ReadDeltaState; {$ifdef FPC_HAS_FEATURE_THREADING} finally GlobalNameSpace.EndWrite; diff --git a/rtl/objpas/classes/classesh.inc b/rtl/objpas/classes/classesh.inc index 2d7dae7e6d..9be347524d 100644 --- a/rtl/objpas/classes/classesh.inc +++ b/rtl/objpas/classes/classesh.inc @@ -1808,6 +1808,8 @@ type TReadWriteStringPropertyEvent = procedure(Sender:TObject; const Instance: TPersistent; PropInfo: PPropInfo; var Content:string) of object; + TGetStreamProc = procedure (const S: TStream) of object; + TGetDeltaStreamsEvent = procedure (Sender: TObject; Proc: TGetStreamProc; var Handled: Boolean) of object; { TReader } @@ -1888,6 +1890,7 @@ type procedure ReadListBegin; procedure ReadListEnd; function ReadRootComponent(ARoot: TComponent): TComponent; + function ReadComponentDeltaRes(Instance: TComponent; const DeltaCandidates: array of Ansistring; const Proc: TGetStreamProc): TComponent; function ReadVariant: Variant; procedure ReadSignature; function ReadString: RawBytestring; @@ -2381,6 +2384,7 @@ type end; TBasicAction = class; + { TComponent } @@ -2395,6 +2399,7 @@ type FVCLComObject: Pointer; FComponentState: TComponentState; FDObservers : TObservers; + FOnGetDeltaStreams: TGetDeltaStreamsEvent; function GetComObject: IUnknown; function GetComponent(AIndex: Integer): TComponent; function GetComponentCount: Integer; @@ -2411,6 +2416,9 @@ type procedure WriteTop(Writer: TWriter); protected FComponentStyle: TComponentStyle; + procedure GetDeltaStreams(aProc: TGetStreamProc); virtual; + procedure ReadDeltaStream(const S: TStream); + procedure ReadDeltaState; virtual; procedure ChangeName(const NewName: TComponentName); procedure DefineProperties(Filer: TFiler); override; procedure GetChildren(Proc: TGetChildProc; Root: TComponent); dynamic; @@ -2488,6 +2496,7 @@ type property Owner: TComponent read FOwner; property VCLComObject: Pointer read FVCLComObject write FVCLComObject; Property Observers : TObservers Read GetObservers; + property OnGetDeltaStreams: TGetDeltaStreamsEvent read FOnGetDeltaStreams write FOnGetDeltaStreams; published property Name: TComponentName read FName write SetName stored False; property Tag: PtrInt read FTag write FTag default 0; @@ -2811,7 +2820,6 @@ type TIntToIdent = function(Int: Longint; var Ident: string): Boolean; TFindGlobalComponent = function(const Name: string): TComponent; TInitComponentHandler = function(Instance: TComponent; RootAncestor : TClass): boolean; - TGetStreamProc = procedure (const S: TStream) of object; var MainThreadID: TThreadID; diff --git a/rtl/objpas/classes/compon.inc b/rtl/objpas/classes/compon.inc index f91d08d877..ce7bca6e2d 100644 --- a/rtl/objpas/classes/compon.inc +++ b/rtl/objpas/classes/compon.inc @@ -730,3 +730,33 @@ begin else Result := E_NOTIMPL; end; + +{ Delta stream support } + + +procedure TComponent.GetDeltaStreams(aProc: TGetStreamProc); + +begin + // To be implemented by descendants +end; + +procedure TComponent.ReadDeltaStream(const S: TStream); +begin + S.ReadComponent(Self); +end; + +procedure TComponent.ReadDeltaState; + +var + Done : boolean; + +begin + if (csDesigning in ComponentState) then + exit; + Done:=False; + if Assigned(FOnGetDeltaStreams) then + FOnGetDeltaStreams(Self,@ReadDeltaStream,Done); + if not Done then + GetDeltaStreams(@ReadDeltaStream); +end; + diff --git a/rtl/objpas/classes/reader.inc b/rtl/objpas/classes/reader.inc index 9d4448ca47..016e3d02b2 100644 --- a/rtl/objpas/classes/reader.inc +++ b/rtl/objpas/classes/reader.inc @@ -1889,7 +1889,36 @@ begin raise EClassNotFound.CreateFmt(SNoFieldOfClassIn, [AClassName, Root.ClassName]); end; +function TReader.ReadComponentDeltaRes(Instance: TComponent; const DeltaCandidates: array of Ansistring; const Proc: TGetStreamProc): TComponent; +var + ResHandle: THandle; + RootName, Delta, DeltaName: AnsiString; + S: TStream; + +begin + if (Instance=nil) or not Assigned(Proc) then + Raise EArgumentNilException.Create(SArgumentNil); + Result:=Instance; + RootName:=Instance.ClassName; + for Delta in DeltaCandidates do + begin + DeltaName:=RootName+'_'+Delta; + // No module support yet + ResHandle:=FindResource(Nilhandle,PAnsiChar(DeltaName), PAnsiChar(RT_RCDATA)); + if ResHandle<>NilHandle then + Break; + end; + if ResHandle=NilHandle then + exit; + S:=TResourceStream.Create(NilHandle,DeltaName, PChar(RT_RCDATA)); + try + Proc(S); + finally + S.Free; + end; +end; + { TAbstractObjectReader } procedure TAbstractObjectReader.FlushBuffer;