浏览代码

* Implemented streaming. Note: The writer driver interface is stable, but
the reader interface is not final yet!

sg 25 年之前
父节点
当前提交
0916287bf7
共有 11 个文件被更改,包括 2527 次插入1069 次删除
  1. 472 36
      fcl/inc/classes.inc
  2. 209 305
      fcl/inc/classesh.inc
  3. 20 6
      fcl/inc/compon.inc
  4. 14 10
      fcl/inc/constse.inc
  5. 6 2
      fcl/inc/constsg.inc
  6. 6 2
      fcl/inc/constss.inc
  7. 11 14
      fcl/inc/filer.inc
  8. 1074 198
      fcl/inc/reader.inc
  9. 80 45
      fcl/inc/streams.inc
  10. 7 3
      fcl/inc/twriter.inc
  11. 628 448
      fcl/inc/writer.inc

+ 472 - 36
fcl/inc/classes.inc

@@ -39,16 +39,6 @@
 { TBits implementation }
 {$i bits.inc}
 
-{ TReader implementation }
-{ $i reader.inc}
-
-{ TWriter implementations }
-{$i writer.inc}
-{$i twriter.inc}
-
-{ TFiler implementation }
-{$i filer.inc}
-
 { All streams implementations: }
 { Tstreams THandleStream TFileStream TResourcseStreams TStringStream }
 { TCustomMemoryStream TMemoryStream }
@@ -138,44 +128,200 @@ end;
 
 { Object filing routines }
 
-procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
-  IntToIdent: TIntToIdent);
+var
+  IntConstList: TThreadList;
+
+
+// !!!: INSERTION START, only slightly modified until now
+
+type
+  TIntConst = class
+    IntegerType: PTypeInfo;
+    IdentToIntFn: TIdentToInt;
+    IntToIdentFn: TIntToIdent;
+    constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
+      AIntToIdent: TIntToIdent);
+  end;
 
+constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
+  AIntToIdent: TIntToIdent);
 begin
+  IntegerType := AIntegerType;
+  IdentToIntFn := AIdentToInt;
+  IntToIdentFn := AIntToIdent;
 end;
 
+procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
+  IntToIdentFn: TIntToIdent);
+begin
+  IntConstList.Add(TIntConst.Create(IntegerType, IdentToIntFn, IntToIdentFn));
+end;
 
-function IdentToInt(const Ident: string; var Int: Longint; const Map: array of TIdentMapEntry): Boolean;
+function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
+var
+  I: Integer;
+begin
+  Result := nil;
+  with IntConstList.LockList do
+  try
+    for I := 0 to Count - 1 do
+      with TIntConst(Items[I]) do
+        if AIntegerType = IntegerType then
+        begin
+          Result := IntToIdentFn;
+          Exit;
+        end;
+  finally
+    IntConstList.UnlockList;
+  end;
+end;
 
+function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
+var
+  I: Integer;
 begin
-  IdentToInt:=false;
+  Result := nil;
+  with IntConstList.LockList do
+  try
+    for I := 0 to Count - 1 do
+      with TIntConst(Items[I]) do
+        if AIntegerType = IntegerType then
+        begin
+          Result := IdentToIntFn;
+          Exit;
+        end;
+  finally
+    IntConstList.UnlockList;
+  end;
 end;
 
+function IdentToInt(const Ident: string; var Int: Longint; const Map: array of TIdentMapEntry): Boolean;
+var
+  I: Integer;
+begin
+  for I := Low(Map) to High(Map) do
+    if UpperCase(Map[I].Name) = UpperCase(Ident) then
+    begin
+      Result := True;
+      Int := Map[I].Value;
+      Exit;
+    end;
+  Result := False;
+end;
 
 function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
+var
+  I: Integer;
+begin
+  for I := Low(Map) to High(Map) do
+    if Map[I].Value = Int then
+    begin
+      Result := True;
+      Ident := Map[I].Name;
+      Exit;
+    end;
+  Result := False;
+end;
+
+// !!!: INSERTION END
+
+
+// !!!: INSERTION START
+
+{ TPropFixup }
+
+type
+  TPropFixup = class
+    FInstance: TPersistent;
+    FInstanceRoot: TComponent;
+    FPropInfo: PPropInfo;
+    FRootName: string;
+    FName: string;
+    constructor Create(Instance: TPersistent; InstanceRoot: TComponent;
+      PropInfo: PPropInfo; const RootName, Name: string);
+    function MakeGlobalReference: Boolean;
+  end;
+
+var
+  GlobalFixupList: TThreadList;
 
+constructor TPropFixup.Create(Instance: TPersistent; InstanceRoot: TComponent;
+  PropInfo: PPropInfo; const RootName, Name: string);
 begin
-  IntToIdent:=false;
+  FInstance := Instance;
+  FInstanceRoot := InstanceRoot;
+  FPropInfo := PropInfo;
+  FRootName := RootName;
+  FName := Name;
 end;
 
+function TPropFixup.MakeGlobalReference: Boolean;
+var
+  S: PChar;
+  P: PChar;
+begin
+  Result := False;
+  S := PChar(Pointer(FName));
+  P := S;
+  while not (P^ in ['.', #0]) do Inc(P);
+  if P^ = #0 then Exit;
+  SetString(FRootName, S, P - S);
+  Delete(FName, 1, P - S + 1);
+  Result := True;
+end;
+
+// !!!: INSERTION END
+
 
 function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
 
+  function DoInitClass(ClassType: TClass): Boolean;
+  begin
+    Result := False;
+    if (ClassType <> TComponent) and (ClassType <> RootAncestor) then
+    begin
+      { Init the parent class first }
+      Result := DoInitClass(ClassType.ClassParent);
+
+      { !!!: Too Win32-specific in VCL:
+      Result := InternalReadComponentRes(ClassType.ClassName, FindResourceHInstance(
+        FindClassHInstance(ClassType)), Instance) or Result;}
+      Result := False;
+    end;
+  end;
+
 begin
-  InitInheritedComponent:=false;
+  {!!!: GlobalNameSpace.BeginWrite;
+  try}
+    if (Instance.ComponentState * [csLoading, csInline]) = [] then
+    begin
+      BeginGlobalLoading;
+      try
+        Result := DoInitClass(Instance.ClassType);
+        NotifyGlobalLoading;
+      finally
+        EndGlobalLoading;
+      end;
+    end else
+      Result := DoInitClass(Instance.ClassType);
+  {finally
+    GlobalNameSpace.EndWrite;
+  end;}
 end;
 
 
 function InitComponentRes(const ResName: string; Instance: TComponent): Boolean;
 
 begin
-  InitComponentRes:=false;
+  { !!!: Too Win32-specific in VCL }
+  InitComponentRes:=False;
 end;
 
 
 function ReadComponentRes(const ResName: string; Instance: TComponent): TComponent;
 
 begin
+  { !!!: Too Win32-specific in VCL }
   ReadComponentRes:=nil;
 end;
 
@@ -183,82 +329,334 @@ end;
 function ReadComponentResEx(HInstance: THandle; const ResName: string): TComponent;
 
 begin
+  { !!!: Too Win32-specific in VCL }
   ReadComponentResEx:=nil;
 end;
 
 
 function ReadComponentResFile(const FileName: string; Instance: TComponent): TComponent;
-
+var
+  FileStream: TStream;
 begin
-  ReadComponentResFile:=nil;
+  FileStream := TFileStream.Create(FileName, fmOpenRead {!!!:or fmShareDenyWrite});
+  try
+    Result := FileStream.ReadComponentRes(Instance);
+  finally
+    FileStream.Free;
+  end;
 end;
 
 
 procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
-
+var
+  FileStream: TStream;
 begin
+  FileStream := TFileStream.Create(FileName, fmCreate);
+  try
+    FileStream.WriteComponentRes(Instance.ClassName, Instance);
+  finally
+    FileStream.Free;
+  end;
 end;
 
 
-
+// !!!: INSERTION START
 procedure GlobalFixupReferences;
+var
+  FinishedList: TList;
+  NotFinishedList: TList;
+  GlobalList: TList;
+  I: Integer;
+  Root: TComponent;
+  Instance: TPersistent;
+  Reference: Pointer;
+
+  procedure AddFinished(Instance: TPersistent);
+  begin
+    if (FinishedList.IndexOf(Instance) < 0) and
+      (NotFinishedList.IndexOf(Instance) >= 0) then
+      FinishedList.Add(Instance);
+  end;
+
+  procedure AddNotFinished(Instance: TPersistent);
+  var
+    Index: Integer;
+  begin
+    Index := FinishedList.IndexOf(Instance);
+    if Index <> -1 then FinishedList.Delete(Index);
+    if NotFinishedList.IndexOf(Instance) < 0 then
+      NotFinishedList.Add(Instance);
+  end;
+
+begin
+  if Assigned(FindGlobalComponent) then
+  begin
+    // Fixup resolution requires a stable component / name space
+    // Block construction and destruction of forms / datamodules during fixups
+    {!!!: GlobalNameSpace.BeginWrite;
+    try}
+      GlobalList := GlobalFixupList.LockList;
+      try
+        if GlobalList.Count > 0 then
+        begin
+          FinishedList := TList.Create;
+          try
+            NotFinishedList := TList.Create;
+            try
+              I := 0;
+              while I < GlobalList.Count do
+                with TPropFixup(GlobalList[I]) do
+                begin
+                  Root := FindGlobalComponent(FRootName);
+                  if (Root <> nil) or (GetOrdProp(FInstance, FPropInfo) <> 0) then
+                  begin
+                    if Root <> nil then
+                    begin
+                      Reference := FindNestedComponent(Root, FName);
+                      SetOrdProp(FInstance, FPropInfo, Longint(Reference));
+                    end;
+                    AddFinished(FInstance);
+                    GlobalList.Delete(I);
+                    Free;
+                  end else
+                  begin
+                    AddNotFinished(FInstance);
+                    Inc(I);
+                  end;
+                end;
+            finally
+              NotFinishedList.Free;
+            end;
+            for I := 0 to FinishedList.Count - 1 do
+            begin
+              Instance := TPersistent(FinishedList[I]);
+              if Instance is TComponent then
+                Exclude(TComponent(Instance).FComponentState, csFixups);
+            end;
+          finally
+            FinishedList.Free;
+          end;
+        end;
+      finally
+        GlobalFixupList.UnlockList;
+      end;
+    {finally
+      GlobalNameSpace.EndWrite;
+    end;}
+  end;
+end;
+
+// !!!: INSERTION END
 
+
+// !!!: Rename this function
+function NameInStrings(Strings: TStrings; const Name: String): Boolean;
+var
+  n: String;
+  I: Integer;
 begin
+  n := UpperCase(Name);
+  for i := 0 to Strings.Count - 1 do
+    if UpperCase(Strings[i]) = n then
+    begin
+      Result := True;
+      exit;
+    end;
+  Result := False;
 end;
 
 
 procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
-
+var
+  i: Integer;
+  CurFixup: TPropFixup;
 begin
+  with GlobalFixupList.LockList do
+    try
+      for i := 0 to Count - 1 do
+      begin
+        CurFixup := TPropFixup(Items[i]);
+        if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
+          not NameInStrings(Names, CurFixup.FRootName) then
+          Names.Add(CurFixup.FRootName);
+      end;
+    finally
+      GlobalFixupList.UnlockList;
+    end;
 end;
 
 
 procedure GetFixupInstanceNames(Root: TComponent;
   const ReferenceRootName: string; Names: TStrings);
-
+var
+  i: Integer;
+  CurFixup: TPropFixup;
 begin
+  with GlobalFixupList.LockList do
+    try
+      for i := 0 to Count - 1 do
+      begin
+        CurFixup := TPropFixup(Items[i]);
+        if (CurFixup.FInstanceRoot = Root) and
+          (UpperCase(ReferenceRootName) = UpperCase(CurFixup.FRootName)) and
+          not NameInStrings(Names, CurFixup.FName) then
+          Names.Add(CurFixup.FName);
+      end;
+    finally
+      GlobalFixupList.UnlockList;
+    end;
 end;
 
 
 procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
   NewRootName: string);
-
+var
+  i: Integer;
+  CurFixup: TPropFixup;
 begin
+  with GlobalFixupList.LockList do
+    try
+      for i := 0 to Count - 1 do
+      begin
+        CurFixup := TPropFixup(Items[i]);
+        if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
+          (UpperCase(OldRootName) = UpperCase(CurFixup.FRootName)) then
+          CurFixup.FRootName := NewRootName;
+      end;
+      GlobalFixupReferences;
+    finally
+      GlobalFixupList.Unlocklist;
+    end;
 end;
 
 
 procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
-
+var
+  i: Integer;
+  CurFixup: TPropFixup;
 begin
+  if Assigned(GlobalFixupList) then
+    with GlobalFixupList.LockList do
+      try
+        for i := Count - 1 downto 0 do
+        begin
+          CurFixup := TPropFixup(Items[i]);
+          if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
+            ((Length(RootName) = 0) or
+	    (UpperCase(RootName) = UpperCase(CurFixup.FRootName))) then
+          begin
+            Delete(i);
+            CurFixup.Free;
+          end;
+        end;
+      finally
+        GlobalFixupList.UnlockList;
+      end;
 end;
 
 
 procedure RemoveFixups(Instance: TPersistent);
+var
+  i: Integer;
+  CurFixup: TPropFixup;
+begin
+  if Assigned(GlobalFixupList) then
+    with GlobalFixupList.LockList do
+      try
+        for i := Count - 1 downto 0 do
+        begin
+          CurFixup := TPropFixup(Items[i]);
+          if (CurFixup.FInstance = Instance) then
+          begin
+            Delete(i);
+            CurFixup.Free;
+          end;
+        end;
+      finally
+        GlobalFixupList.UnlockList;
+      end;
+end;
 
+
+function FindNestedComponent(Root: TComponent; const NamePath: string): TComponent;
+var
+  Current, Found: TComponent;
+  s, p: PChar;
+  Name: String;
 begin
+  Result := nil;
+  if Length(NamePath) > 0 then
+  begin
+    Current := Root;
+    p := PChar(NamePath);
+    while p[0] <> #0 do
+    begin
+      s := p;
+      while not (p^ in ['.', '-', #0]) do
+        Inc(p);
+      SetString(Name, s, p - s);
+      Found := Current.FindComponent(Name);
+      if (not Assigned(Found)) and (UpperCase(Name) = 'OWNER') then
+        Found := Current;
+      if not Assigned(Found) then exit;
+
+      // Remove the dereference operator from the name
+      if p[0] = '.' then
+        Inc(P);
+      if p[0] = '-' then
+        Inc(P);
+      if p[0] = '>' then
+        Inc(P);
+
+      Current := Found;
+    end;
+  end;
+  Result := Current;
 end;
 
+{!!!: threadvar block copied from VCL}
+{threadvar  -  doesn't work for all platforms yet!}
+var
+  GlobalLoaded: TList;
+  GlobalLists: TList;
 
 
 procedure BeginGlobalLoading;
 
 begin
+  if not Assigned(GlobalLists) then
+    GlobalLists := TList.Create;
+  GlobalLists.Add(GlobalLoaded);
+  GlobalLoaded := TList.Create;
 end;
 
 
 procedure NotifyGlobalLoading;
-
+var
+  List: TList;
+  i: Integer;
 begin
+  List := GlobalLoaded;
+  { Notify all global components that they have been loaded completely }
+  for i := 0 to List.Count - 1 do
+    TComponent(List[i]).Loaded;
 end;
 
 
 procedure EndGlobalLoading;
-
 begin
+  { Free the memory occupied by BeginGlobalLoading }
+  GlobalLoaded.Free;
+  GlobalLoaded := TList(GlobalLists.Last);
+  GlobalLists.Delete(GlobalLists.Count - 1);
+  if GlobalLists.Count = 0 then
+  begin
+    GlobalLists.Free;
+    GlobalLists := nil;
+  end;
 end;
 
 
-
 function CollectionsEqual(C1, C2: TCollection): Boolean;
 
 begin
@@ -750,12 +1148,57 @@ begin
   end;
 end;
 
+procedure CommonInit;
+begin
+  IntConstList := TThreadList.Create;
+  GlobalFixupList := TThreadList.Create;
+  ClassList := TThreadList.Create;
+  ClassAliasList := TStringList.Create;
+end;
+
+procedure CommonCleanup;
+var
+  i: Integer;
+begin
+  // !!!: GlobalNameSpace.BeginWrite;
+  with IntConstList.LockList do
+    try
+      for i := 0 to Count - 1 do
+        TIntConst(Items[I]).Free;
+    finally
+      IntConstList.UnlockList;
+    end;
+    IntConstList.Free;
+  ClassList.Free;
+  ClassAliasList.Free;
+  RemoveFixupReferences(nil, '');
+  GlobalFixupList.Free;
+  GlobalFixupList := nil;
+  GlobalLists.Free;
+  {!!!: GlobalNameSpace.Free;
+  GlobalNameSpace := nil;}
+end;
 
 
 
+{ TFiler implementation }
+{$i filer.inc}
+
+{ TReader implementation }
+{$i reader.inc}
+
+{ TWriter implementations }
+{$i writer.inc}
+{$i twriter.inc}
+
+
 {
   $Log$
-  Revision 1.16  2000-01-07 01:24:33  peter
+  Revision 1.17  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.16  2000/01/07 01:24:33  peter
     * updated copyright to 2000
 
   Revision 1.15  2000/01/06 01:20:32  peter
@@ -775,11 +1218,4 @@ end;
 
   Revision 1.11  1999/09/11 21:59:31  fcl
   * Moved class and registration functions to cregist.inc  (sg)
-
-  Revision 1.10  1999/04/13 08:52:29  michael
-  + Moved strings.inc to stringl.inc, to avoid conflict with strings unit
-
-  Revision 1.9  1999/04/08 10:18:50  peter
-    * makefile updates
-
 }

+ 209 - 305
fcl/inc/classesh.inc

@@ -123,10 +123,6 @@ type
 { Forward class declarations }
 
   TStream = class;
-  TAbstractFiler = Class;
-  TAbstractWriter = Class;
-  TAbstractReader = Class;
-
   TFiler = class;
   TReader = class;
   TWriter = class;
@@ -476,6 +472,8 @@ type
     procedure WriteComponentRes(const ResName: string; Instance: TComponent);
     procedure WriteDescendent(Instance, Ancestor: TComponent);
     procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
+    procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Integer);
+    procedure FixupResourceHeader(FixupInfo: Integer);
     procedure ReadResHeader;
     function ReadByte : Byte;
     function ReadWord : Word;
@@ -609,289 +607,114 @@ type
     function Clone(out stm: IStream): HResult; stdcall;
   end;
 }
+
 { TFiler }
 
   TValueType = (vaNull, vaList, vaInt8, vaInt16, vaInt32, vaExtended,
     vaString, vaIdent, vaFalse, vaTrue, vaBinary, vaSet, vaLString,
-    vaNil, vaCollection);
+    vaNil, vaCollection, vaSingle, vaCurrency, vaDate, vaWString, vaInt64);
 
-  TFilerFlag = (ffInherited, ffChildPos);
+  TFilerFlag = (ffInherited, ffChildPos, ffInline);
   TFilerFlags = set of TFilerFlag;
 
-(*
   TReaderProc = procedure(Reader: TReader) of object;
   TWriterProc = procedure(Writer: TWriter) of object;
   TStreamProc = procedure(Stream: TStream) of object;
-*)
-
-  TReaderProc = procedure(Reader: TAbstractReader) of object;
-  TWriterProc = procedure(Writer: TAbstractWriter) of object;
-  TStreamProc = procedure(Stream: TStream) of object;
 
-  TAbstractFiler = class(TObject)
+  TFiler = class(TObject)
   private
     FRoot: TComponent;
+    FLookupRoot: TComponent;
     FAncestor: TPersistent;
-     FIgnoreChildren: Boolean;
-     FPrefix : String;
-   public
+    FIgnoreChildren: Boolean;
+  protected
+    procedure SetRoot(ARoot: TComponent); virtual;
+  public
     procedure DefineProperty(const Name: string;
       ReadData: TReaderProc; WriteData: TWriterProc;
       HasData: Boolean); virtual; abstract;
     procedure DefineBinaryProperty(const Name: string;
       ReadData, WriteData: TStreamProc;
       HasData: Boolean); virtual; abstract;
-    property Root: TComponent read FRoot write FRoot;
+    property Root: TComponent read FRoot write SetRoot;
+    property LookupRoot: TComponent read FLookupRoot;
     property Ancestor: TPersistent read FAncestor write FAncestor;
     property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;
   end;
 
-{ TReader }
-
-  TFindMethodEvent = procedure(Reader: TReader; const MethodName: string;
-    var Address: Pointer; var Error: Boolean) of object;
-  TSetNameEvent = procedure(Reader: TReader; Component: TComponent;
-    var Name: string) of object;
-  TReferenceNameEvent = procedure(Reader: TReader; var Name: string) of object;
-  TAncestorNotFoundEvent = procedure(Reader: TReader; const ComponentName: string;
-    ComponentClass: TPersistentClass; var Component: TComponent) of object;
-  TReadComponentsProc = procedure(Component: TComponent) of object;
-  TReaderError = procedure(Reader: TReader; const Message: string; var Handled: Boolean) of object;
-
 
-  TAbstractReader = class(TAbstractFiler);
-(*  private
-  protected
-    function Error(const Message: string): Boolean; virtual;
-    function FindMethod(ARoot: TComponent; const AMethodName: string): Pointer; virtual;
-    procedure SetName(Component: TComponent; var Name: string); virtual;
-    procedure ReferenceName(var Name: string); virtual;
-    function FindAncestorComponent(const Name: string;
-                                   ComponentClass: TPersistentClass): TComponent; virtual;
-  public
-    destructor Destroy; override;
-    procedure BeginReferences;
-    procedure DefineProperty(const Name: string;
-      rd : TReaderProc; wd : TWriterProc;
-      HasData: Boolean); override;
-    procedure DefineBinaryProperty(const Name: string;
-      rd, wd: TStreamProc;
-      HasData: Boolean); override;
-    function EndOfList: Boolean;
-    procedure EndReferences;
-    procedure FixupReferences;
-    procedure FlushBuffer; override;
-    function NextValue: TValueType;
-    procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
-    procedure ReadCollection(Collection: TCollection);
-    function ReadComponent(Component: TComponent): TComponent;
-    procedure ReadComponents(AOwner, AParent: TComponent;
-      Proc: TReadComponentsProc);
-    function ReadRootComponent(ARoot: TComponent): TComponent;
-    { Abstract methods }
-    procedure ReadSignature;
-    function ReadBoolean: Boolean; abstract;
-    function ReadChar: Char; abstract;
-    function ReadFloat: Extended;
-    function ReadIdent: string;
-    function ReadInteger: Longint;
-    procedure ReadListBegin;
-    procedure ReadListEnd;
-    function ReadStr: string;
-    function ReadString: string;
-    function ReadValue: TValueType;
-    procedure CopyValue(Writer: TWriter);
-    {!!!}
-    property Owner: TComponent read FOwner write FOwner;
-    property Parent: TComponent read FParent write FParent;
-    property Position: Longint read GetPosition write SetPosition;
-    property OnError: TReaderError read FOnError write FOnError;
-    property OnFindMethod: TFindMethodEvent read FOnFindMethod write FOnFindMethod;
-    property OnSetName: TSetNameEvent read FOnSetName write FOnSetName;
-    property OnReferenceName: TReferenceNameEvent read FOnReferenceName write FOnReferenceName;
-    property OnAncestorNotFound: TAncestorNotFoundEvent read FOnAncestorNotFound write FOnAncestorNotFound;
-  end;
-*)
+{ TComponent class reference type }
 
-{ TAbstractWriter }
+  TComponentClass = class of TComponent;
 
-  TAbstractWriter = class(TAbstractFiler)
-  private
-    FRootAncestor: TComponent;
-    FPropPath: string;
-    FAncestorList: TList;
-    FAncestorPos: Integer;
-    FChildPos: Integer;
-    procedure AddAncestor(Component: TComponent);
-    procedure WriteData(Instance: TComponent); // linker optimization
-    procedure WriteProperty(Instance: TPersistent; PropInfo: Pointer);
-    procedure WriteProperties(Instance: TPersistent);
-    Procedure DoOrdinalProp(Instance : TPersistent;Propinfo :PPropInfo);
-    Procedure DoStringProp(Instance : TPersistent;Propinfo :PPropInfo);
-    Procedure DoFloatProp(Instance : TPersistent;Propinfo :PPropInfo);
-    Procedure DoCollectionProp(Name: ShortString; Value : TCollection);
-    Procedure DoClassProp(Instance : TPersistent;Propinfo :PPropInfo);
-    Procedure DoMethodProp(Instance : TPersistent;Propinfo :PPropInfo);
-  protected
-    procedure WritePrefix(Flags: TFilerFlags; AChildPos: Integer);Virtual;Abstract;
-    Procedure StartObject(Const AClassName,AName : String);Virtual;abstract;
-    Procedure EndObject;Virtual;Abstract;
-    Procedure StartCollection(Const Name : String);Virtual;abstract;
-    Procedure EndCollection;Virtual;Abstract;
-    Procedure StartCollectionItem;Virtual;abstract;
-    Procedure EndCollectionItem;Virtual;Abstract;
-  public
-    destructor Destroy; override;
-    procedure DefineProperty(const Name: string;
-      rd : TReaderProc; wd : TWriterProc;
-      HasData: Boolean); override;
-    procedure DefineBinaryProperty(const Name: string;
-      rd, wd: TStreamProc;
-      HasData: Boolean); override;
-    procedure WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
-    procedure WriteRootComponent(ARoot: TComponent);
-    procedure WriteComponent(Component: TComponent);virtual;
-    { Abstract }
-    Procedure WriteIntegerProperty(Const Name : Shortstring;Value : Longint);virtual;abstract;
-    Procedure WriteSetProperty (Const Name : ShortString;Value : longint; BaseType : TTypeInfo);virtual;abstract;
-    Procedure WriteEnumerationProperty (Const Name : ShortString;Value : Longint; Const EnumName : ShortSTring);virtual;abstract;
-    Procedure WriteStringProperty(Const Name : ShortString; Const Value : String);virtual;abstract;
-    Procedure WriteFloatProperty(Const Name : ShortString; Value : Extended);virtual;abstract;
-    Procedure WriteCollectionProperty(Const Name : ShortString;Value : TCollection);virtual;abstract;
-    Procedure WriteClassProperty(Instance : TPersistent;Propinfo :PPropInfo);virtual;abstract;
-    Procedure WriteComponentProperty(Const Name : ShortString;Value : TComponent);virtual;abstract;
-    Procedure WriteNilProperty(Const Name : Shortstring);virtual; abstract;
-    Procedure WriteMethodProperty(Const Name,AMethodName : ShortString);virtual;abstract;
-    Procedure WriteBinaryProperty(Const Name; Value : TStream);Virtual;Abstract;
-(*
-    { Abstract compatibility methods}
-    Procedure WriteValue(Value : TValueType);virtual;abstract;
-    procedure Write(const Buf; Count: Longint);virtual;abstract;
-    procedure WriteBoolean(Value: Boolean);virtual;abstract;
-    procedure WriteCollection(Value: TCollection);virtual;abstract;
-    procedure WriteComponent(Component: TComponent);virtual;abstract;
-    procedure WriteChar(Value: Char);virtual;abstract;
-    procedure WriteFloat(Value: Extended);virtual;abstract;
-    procedure WriteIdent(const Ident: string);virtual;abstract;
-    procedure WriteInteger(Value: Longint);virtual;abstract;
-    procedure WriteListBegin;virtual;abstract;
-    procedure WriteListEnd;virtual;abstract;
-    procedure WriteSignature;virtual;abstract;
-    procedure WriteStr(const Value: string);virtual;abstract;
-    procedure WriteString(const Value: string);virtual;abstract;
-*)
-    property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
-  end;
 
-  TWriter = class(TAbstractWriter)
-  Private
-    FStream : TStream;
-    function GetPosition: Longint;
-    procedure SetPosition(Value: Longint);
-    procedure WritePropName(const PropName: string);
-  protected
-    procedure WriteBinary(wd : TStreamProc);
-  public
-    Constructor Create(S : TStream);
-    destructor Destroy; override;
-    { Compatibility }
-    procedure WriteBuffer;
-    Procedure FlushBuffer;
-    { Abstract }
-    Procedure WriteIntegerProperty(Const Name : Shortstring;Value : Longint);override;
-    Procedure WriteSetProperty (Const Name : ShortString;Value : longint; BaseType : TTypeInfo);override;
-    Procedure WriteEnumerationProperty (Const Name : ShortString;Value : Longint; Const EnumName : ShortSTring);override;
-    Procedure WriteStringProperty(Const Name : ShortString; Const Value : String);override;
-    Procedure WriteFloatProperty(Const Name : ShortString; Value : Extended);override;
-    Procedure WriteCollectionProperty(Const Name : ShortString;Value : TCollection);override;
-    Procedure WriteClassProperty(Instance : TPersistent;Propinfo :PPropInfo);override;
-    Procedure WriteComponentProperty(Const Name : ShortSTring; Value : TComponent);override;
-    Procedure WriteNilProperty(Const Name : Shortstring);override;
-    Procedure WriteMethodProperty(Const Name,AMethodName : ShortString);override;
-    { Abstract compatibility methods}
-    procedure WritePrefix(Flags: TFilerFlags; AChildPos: Integer); virtual;
-    Procedure WriteValue(Value : TValueType);virtual;
-    procedure Write(const Buf; Count: Longint);virtual;
-    procedure WriteBoolean(Value: Boolean);virtual;
-    procedure WriteCollection(Value: TCollection);virtual;
-    procedure WriteChar(Value: Char);virtual;
-    procedure WriteFloat(Value: Extended);virtual;
-    procedure WriteIdent(const Ident: string);virtual;
-    procedure WriteInteger(Value: Longint);virtual;
-    procedure WriteListBegin;virtual;
-    procedure WriteListEnd;virtual;
-    procedure WriteSignature;virtual;
-    procedure WriteStr(const Value: string);virtual;
-    procedure WriteString(const Value: string);virtual;
-    procedure DefineProperty(const Name: string;
-      rd : TReaderProc; wd : TWriterProc;
-      HasData: Boolean); override;
-    procedure DefineBinaryProperty(const Name: string;
-      rd, wd: TStreamProc;
-      HasData: Boolean); override;
-    property Position: Longint read GetPosition write SetPosition;
-  end;
+{ TReader }
 
-  TTextWriter = class(TAbstractWriter)
-  Private
-    FStream : TStream;
-    Procedure Write(Const Msg : String);
-    Procedure WriteLn(Const Msg : String);
-    Procedure WriteFmt(Fmt : String; Args :  Array of const);
-    procedure WritePropName(const PropName: string);
-  protected
-   Procedure StartCollection(Const AName : String);
-   Procedure StartCollectionItem;
-   Procedure EndCollectionItem;
-   Procedure EndCollection;
+  TAbstractObjectReader = class
   public
-    Constructor Create(S : TStream);
-    destructor Destroy; override;
-    { Abstract }
-    Procedure StartObject(Const AClassName,AName : String);override;
-    Procedure EndObject;Virtual;override;
-    Procedure WriteIntegerProperty(Const Name : Shortstring;Value : Longint);override;
-    Procedure WriteSetProperty (Const Name : ShortString;Value : longint; BaseType : TTypeInfo);override;
-    Procedure WriteEnumerationProperty (Const Name : ShortString;Value : Longint; Const EnumName : ShortSTring);override;
-    Procedure WriteStringProperty(Const Name : ShortString; Const Value : String);override;
-    Procedure WriteFloatProperty(Const Name : ShortString; Value : Extended);override;
-    Procedure WriteCollectionProperty(Const Name : ShortString;Value : TCollection);override;
-    Procedure WriteClassProperty(Instance : TPersistent;Propinfo :PPropInfo);override;
-    Procedure WriteComponentProperty(Const Name : ShortSTring; Value : TComponent);override;
-    Procedure WriteNilProperty(Const Name : Shortstring);override;
-    Procedure WriteMethodProperty(Const Name,AMethodName : ShortString);override;
+    function NextValue: TValueType; virtual; abstract;
+    function ReadValue: TValueType; virtual; abstract;
+    procedure BeginRootComponent; virtual; abstract;
+    procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
+      var CompClassName, CompName: String); virtual; abstract;
+    function BeginProperty: String; virtual; abstract;
+
+    { All ReadXXX methods are called _after_ the value type has been read! }
+    procedure ReadBinary(const DestData: TMemoryStream); virtual; abstract;
+    function ReadFloat: Extended; virtual; abstract;
+    function ReadSingle: Single; virtual; abstract;
+    {!!!: function ReadCurrency: Currency; virtual; abstract;}
+    function ReadDate: TDateTime; virtual; abstract;
+    function ReadIdent(ValueType: TValueType): String; virtual; abstract;
+    function ReadInt8: ShortInt; virtual; abstract;
+    function ReadInt16: SmallInt; virtual; abstract;
+    function ReadInt32: LongInt; virtual; abstract;
+    function ReadInt64: Int64; virtual; abstract;
+    function ReadSet(EnumType: Pointer): Integer; virtual; abstract;
+    function ReadStr: String; virtual; abstract;
+    function ReadString(StringType: TValueType): String; virtual; abstract;
+    procedure SkipComponent(SkipComponentInfos: Boolean); virtual; abstract;
+    procedure SkipValue; virtual; abstract;
   end;
 
-  TFiler = Class(TAbstractFiler);
-  TReader = Class(TWriter);
-
-(*
-  TFiler = class(TObject)
+  TBinaryObjectReader = class(TAbstractObjectReader)
   private
     FStream: TStream;
     FBuffer: Pointer;
     FBufSize: Integer;
     FBufPos: Integer;
     FBufEnd: Integer;
-    FRoot: TComponent;
-    FAncestor: TPersistent;
-    FIgnoreChildren: Boolean;
+    procedure Read(var Buf; Count: LongInt);
+    procedure SkipProperty;
+    procedure SkipSetBody;
   public
     constructor Create(Stream: TStream; BufSize: Integer);
     destructor Destroy; override;
-    procedure DefineProperty(const Name: string;
-      ReadData: TReaderProc; WriteData: TWriterProc;
-      HasData: Boolean); virtual; abstract;
-    procedure DefineBinaryProperty(const Name: string;
-      ReadData, WriteData: TStreamProc;
-      HasData: Boolean); virtual; abstract;
-    procedure FlushBuffer; virtual; abstract;
-    property Root: TComponent read FRoot write FRoot;
-    property Ancestor: TPersistent read FAncestor write FAncestor;
-    property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;
+
+    function NextValue: TValueType; override;
+    function ReadValue: TValueType; override;
+    procedure BeginRootComponent; override;
+    procedure BeginComponent(var Flags: TFilerFlags; var AChildPos: Integer;
+      var CompClassName, CompName: String); override;
+    function BeginProperty: String; override;
+
+    procedure ReadBinary(const DestData: TMemoryStream); override;
+    function ReadFloat: Extended; override;
+    function ReadSingle: Single; override;
+    {!!!: function ReadCurrency: Currency; override;}
+    function ReadDate: TDateTime; override;
+    function ReadIdent(ValueType: TValueType): String; override;
+    function ReadInt8: ShortInt; override;
+    function ReadInt16: SmallInt; override;
+    function ReadInt32: LongInt; override;
+    function ReadInt64: Int64; override;
+    function ReadSet(EnumType: Pointer): Integer; override;
+    function ReadStr: String; override;
+    function ReadString(StringType: TValueType): String; override;
+    procedure SkipComponent(SkipComponentInfos: Boolean); override;
+    procedure SkipValue; override;
   end;
 
-{ TReader }
 
   TFindMethodEvent = procedure(Reader: TReader; const MethodName: string;
     var Address: Pointer; var Error: Boolean) of object;
@@ -902,9 +725,14 @@ type
     ComponentClass: TPersistentClass; var Component: TComponent) of object;
   TReadComponentsProc = procedure(Component: TComponent) of object;
   TReaderError = procedure(Reader: TReader; const Message: string; var Handled: Boolean) of object;
+  TFindComponentClassEvent = procedure(Reader: TReader; const ClassName: string;
+    var ComponentClass: TComponentClass) of object;
+  TCreateComponentEvent = procedure(Reader: TReader;
+    ComponentClass: TComponentClass; var Component: TComponent) of object;
 
   TReader = class(TFiler)
   private
+    FDriver: TAbstractObjectReader;
     FOwner: TComponent;
     FParent: TComponent;
     FFixups: TList;
@@ -914,46 +742,37 @@ type
     FOnReferenceName: TReferenceNameEvent;
     FOnAncestorNotFound: TAncestorNotFoundEvent;
     FOnError: TReaderError;
-    FCanHandleExcepts: Boolean;
+    FOnFindComponentClass: TFindComponentClassEvent;
+    FOnCreateComponent: TCreateComponentEvent;
     FPropName: string;
-    procedure CheckValue(Value: TValueType);
+    FCanHandleExcepts: Boolean;
     procedure DoFixupReferences;
     procedure FreeFixups;
-    function GetPosition: Longint;
-    procedure PropertyError;
-    procedure ReadBuffer;
-    procedure ReadData(Instance: TComponent);
-    procedure ReadDataInner(Instance: TComponent);
-    procedure ReadProperty(AInstance: TPersistent);
-    procedure ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
-    function ReadSet(SetType: Pointer): Integer;
-    procedure SetPosition(Value: Longint);
-    procedure SkipSetBody;
-    procedure SkipValue;
-    procedure SkipProperty;
-    procedure SkipComponent(SkipHeader: Boolean);
+    function FindComponentClass(const AClassName: string): TComponentClass;
   protected
     function Error(const Message: string): Boolean; virtual;
     function FindMethod(ARoot: TComponent; const AMethodName: string): Pointer; virtual;
-    procedure SetName(Component: TComponent; var Name: string); virtual;
-    procedure ReferenceName(var Name: string); virtual;
-    function FindAncestorComponent(const Name: string;
-      ComponentClass: TPersistentClass): TComponent; virtual;
+    procedure ReadProperty(AInstance: TPersistent);
+    procedure ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
+    procedure PropertyError;
+    procedure ReadData(Instance: TComponent);
+    property PropName: string read FPropName;
+    property CanHandleExceptions: Boolean read FCanHandleExcepts;
   public
+    constructor Create(Stream: TStream; BufSize: Integer);
     destructor Destroy; override;
     procedure BeginReferences;
+    procedure CheckValue(Value: TValueType);
     procedure DefineProperty(const Name: string;
-      rd : TReaderProc; wd : TWriterProc;
+      AReadData: TReaderProc; WriteData: TWriterProc;
       HasData: Boolean); override;
     procedure DefineBinaryProperty(const Name: string;
-      rd, wd: TStreamProc;
+      AReadData, WriteData: TStreamProc;
       HasData: Boolean); override;
     function EndOfList: Boolean;
     procedure EndReferences;
     procedure FixupReferences;
-    procedure FlushBuffer; override;
     function NextValue: TValueType;
-    procedure Read(var Buf; Count: Longint);
     function ReadBoolean: Boolean;
     function ReadChar: Char;
     procedure ReadCollection(Collection: TCollection);
@@ -961,76 +780,155 @@ type
     procedure ReadComponents(AOwner, AParent: TComponent;
       Proc: TReadComponentsProc);
     function ReadFloat: Extended;
+    function ReadSingle: Single;
+    {!!!: function ReadCurrency: Currency;}
+    function ReadDate: TDateTime;
     function ReadIdent: string;
     function ReadInteger: Longint;
+    function ReadInt64: Int64;
     procedure ReadListBegin;
     procedure ReadListEnd;
-    procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
     function ReadRootComponent(ARoot: TComponent): TComponent;
-    procedure ReadSignature;
-    function ReadStr: string;
     function ReadString: string;
+    {!!!: function ReadWideString: WideString;}
     function ReadValue: TValueType;
-    procedure CopyValue(Writer: TWriter); {!!!}
+    procedure CopyValue(Writer: TWriter);
     property Owner: TComponent read FOwner write FOwner;
     property Parent: TComponent read FParent write FParent;
-    property Position: Longint read GetPosition write SetPosition;
     property OnError: TReaderError read FOnError write FOnError;
     property OnFindMethod: TFindMethodEvent read FOnFindMethod write FOnFindMethod;
     property OnSetName: TSetNameEvent read FOnSetName write FOnSetName;
     property OnReferenceName: TReferenceNameEvent read FOnReferenceName write FOnReferenceName;
     property OnAncestorNotFound: TAncestorNotFoundEvent read FOnAncestorNotFound write FOnAncestorNotFound;
+    property OnCreateComponent: TCreateComponentEvent read FOnCreateComponent write FOnCreateComponent;
+    property OnFindComponentClass: TFindComponentClassEvent read FOnFindComponentClass write FOnFindComponentClass;
   end;
 
+
 { TWriter }
 
+  TAbstractObjectWriter = class
+  public
+    { Begin/End markers. Those ones who don't have an end indicator, use
+      "EndList", after the occurrence named in the comment. Note that this
+      only counts for "EndList" calls on the same level; each BeginXXX call
+      increases the current level. }
+    procedure BeginCollection; virtual; abstract;  { Ends with the next "EndList" }
+    procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
+      ChildPos: Integer); virtual; abstract;  { Ends after the second "EndList" }
+    procedure BeginList; virtual; abstract;
+    procedure EndList; virtual; abstract;
+    procedure BeginProperty(const PropName: String); virtual; abstract;
+    procedure EndProperty; virtual; abstract;
+
+    procedure WriteBinary(const Buffer; Count: Longint); virtual; abstract;
+    procedure WriteBoolean(Value: Boolean); virtual; abstract;
+    // procedure WriteChar(Value: Char);
+    procedure WriteFloat(const Value: Extended); virtual; abstract;
+    procedure WriteSingle(const Value: Single); virtual; abstract;
+    {!!!: procedure WriteCurrency(const Value: Currency); virtual; abstract;}
+    procedure WriteDate(const Value: TDateTime); virtual; abstract;
+    procedure WriteIdent(const Ident: string); virtual; abstract;
+    procedure WriteInteger(Value: Int64); virtual; abstract;
+    procedure WriteMethodName(const Name: String); virtual; abstract;
+    procedure WriteSet(Value: LongInt; SetType: Pointer); virtual; abstract;
+    procedure WriteString(const Value: String); virtual; abstract;
+  end;
+
+  TBinaryObjectWriter = class(TAbstractObjectWriter)
+  private
+    FStream: TStream;
+    FBuffer: Pointer;
+    FBufSize: Integer;
+    FBufPos: Integer;
+    FBufEnd: Integer;
+    FSignatureWritten: Boolean;
+    procedure FlushBuffer;
+    procedure Write(const Buffer; Count: Longint);
+    procedure WriteValue(Value: TValueType);
+    procedure WriteStr(const Value: String);
+  public
+    constructor Create(Stream: TStream; BufSize: Integer);
+    destructor Destroy; override;
+
+    procedure BeginCollection; override;
+    procedure BeginComponent(Component: TComponent; Flags: TFilerFlags;
+      ChildPos: Integer); override;
+    procedure BeginList; override;
+    procedure EndList; override;
+    procedure BeginProperty(const PropName: String); override;
+    procedure EndProperty; override;
+
+    procedure WriteBinary(const Buffer; Count: LongInt); override;
+    procedure WriteBoolean(Value: Boolean); override;
+    procedure WriteFloat(const Value: Extended); override;
+    procedure WriteSingle(const Value: Single); override;
+    {!!!: procedure WriteCurrency(const Value: Currency);  override;}
+    procedure WriteDate(const Value: TDateTime); override;
+    procedure WriteIdent(const Ident: string); override;
+    procedure WriteInteger(Value: Int64); override;
+    procedure WriteMethodName(const Name: String); override;
+    procedure WriteSet(Value: LongInt; SetType: Pointer); override;
+    procedure WriteString(const Value: String); override;
+  end;
+
+  TTextObjectWriter = class(TAbstractObjectWriter)
+  end;
+
+
+  TFindAncestorEvent = procedure (Writer: TWriter; Component: TComponent;
+    const Name: string; var Ancestor, RootAncestor: TComponent) of object;
+
   TWriter = class(TFiler)
   private
+    FDriver: TAbstractObjectWriter;
+    FDestroyDriver: Boolean;
     FRootAncestor: TComponent;
-    FPropPath: string;
+    FPropPath: String;
     FAncestorList: TList;
     FAncestorPos: Integer;
     FChildPos: Integer;
-    procedure AddAncestor(Component: TComponent);
-    function GetPosition: Longint;
-    procedure SetPosition(Value: Longint);
-    procedure WriteBuffer;
-    procedure WriteData(Instance: TComponent);
+    FOnFindAncestor: TFindAncestorEvent;
+    procedure AddToAncestorList(Component: TComponent);
+    procedure WriteComponentData(Instance: TComponent);
+  protected
+    procedure SetRoot(ARoot: TComponent); override;
+    procedure WriteBinary(AWriteData: TStreamProc);
     procedure WriteProperty(Instance: TPersistent; PropInfo: Pointer);
     procedure WriteProperties(Instance: TPersistent);
-    procedure WritePropName(const PropName: string);
-  protected
-    procedure WriteBinary(wd : TStreamProc);
-    procedure WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
-    procedure WriteValue(Value: TValueType);
   public
+    constructor Create(ADriver: TAbstractObjectWriter);
+    constructor Create(Stream: TStream; BufSize: Integer);
     destructor Destroy; override;
     procedure DefineProperty(const Name: string;
-      rd : TReaderProc; wd : TWriterProc;
+      ReadData: TReaderProc; AWriteData: TWriterProc;
       HasData: Boolean); override;
     procedure DefineBinaryProperty(const Name: string;
-      rd, wd: TStreamProc;
+      ReadData, AWriteData: TStreamProc;
       HasData: Boolean); override;
-    procedure FlushBuffer; override;
-    procedure Write(const Buf; Count: Longint);
     procedure WriteBoolean(Value: Boolean);
     procedure WriteCollection(Value: TCollection);
     procedure WriteComponent(Component: TComponent);
     procedure WriteChar(Value: Char);
     procedure WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
-    procedure WriteFloat(Value: Extended);
+    procedure WriteFloat(const Value: Extended);
+    procedure WriteSingle(const Value: Single);
+    {!!!: procedure WriteCurrency(const Value: Currency);}
+    procedure WriteDate(const Value: TDateTime);
     procedure WriteIdent(const Ident: string);
-    procedure WriteInteger(Value: Longint);
+    procedure WriteInteger(Value: Longint); overload;
+    procedure WriteInteger(Value: Int64); overload;
     procedure WriteListBegin;
     procedure WriteListEnd;
     procedure WriteRootComponent(ARoot: TComponent);
-    procedure WriteSignature;
-    procedure WriteStr(const Value: string);
     procedure WriteString(const Value: string);
-    property Position: Longint read GetPosition write SetPosition;
+    {!!!: procedure WriteWideString(const Value: WideString);}
     property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
+    property OnFindAncestor: TFindAncestorEvent read FOnFindAncestor write FOnFindAncestor;
+
+    property Driver: TAbstractObjectWriter read FDriver;
   end;
-*)
+
 
 { TParser }
 
@@ -1125,7 +1023,8 @@ type
 
   TOperation = (opInsert, opRemove);
   TComponentState = set of (csLoading, csReading, csWriting, csDestroying,
-    csDesigning, csAncestor, csUpdating, csFixups);
+    csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification,
+    csInline, csDesignInstance);
   TComponentStyle = set of (csInheritable, csCheckPropAvail);
   TGetChildProc = procedure (Child: TComponent) of object;
 
@@ -1179,7 +1078,7 @@ type
     procedure Loaded; virtual;
     procedure Notification(AComponent: TComponent;
       Operation: TOperation); virtual;
-    procedure ReadState(Reader: TAbstractReader); virtual;
+    procedure ReadState(Reader: TReader); virtual;
     procedure SetAncestor(Value: Boolean);
     procedure SetDesigning(Value: Boolean);
     procedure SetName(const NewName: TComponentName); virtual;
@@ -1205,7 +1104,7 @@ type
     //!!!!   Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): Integer; stdcall;
   public
     //!! Moved temporary
-    procedure WriteState(Writer: TAbstractWriter); virtual;
+    procedure WriteState(Writer: TWriter); virtual;
     constructor Create(AOwner: TComponent); virtual;
     destructor Destroy; override;
     procedure DestroyComponents;
@@ -1228,14 +1127,11 @@ type
     property DesignInfo: Longint read FDesignInfo write FDesignInfo;
     property Owner: TComponent read FOwner;
     property VCLComObject: Pointer read FVCLComObject write FVCLComObject;
-//!!  published
-    property Name: TComponentName read FName write SetName ; // stored False;
-    property Tag: Longint read FTag write FTag ; // default 0;
+  published
+    property Name: TComponentName read FName write SetName stored False;
+    property Tag: Longint read FTag write FTag default 0;
   end;
 
-{ TComponent class reference type }
-
-  TComponentClass = class of TComponent;
 
 { Component registration handlers }
 
@@ -1276,6 +1172,9 @@ procedure RegisterNoIcon(ComponentClasses: array of TComponentClass);
 procedure RegisterNonActiveX(ComponentClasses: array of TComponentClass;
   AxRegType: TActiveXRegType);
 
+{!!!: var
+  GlobalNameSpace: TMultiReadExclusiveWriteSynchronizer;}
+
 
 { Object filing routines }
 
@@ -1293,8 +1192,8 @@ var
   MainThreadID: THandle;
   FindGlobalComponent: TFindGlobalComponent;
 
-procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
-  IntToIdent: TIntToIdent);
+procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
+  IntToIdentFn: TIntToIdent);
 function IdentToInt(const Ident: string; var Int: Longint; const Map: array of TIdentMapEntry): Boolean;
 function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
 
@@ -1313,6 +1212,7 @@ procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
   NewRootName: string);
 procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
 procedure RemoveFixups(Instance: TPersistent);
+function FindNestedComponent(Root: TComponent; const NamePath: string): TComponent;
 
 procedure BeginGlobalLoading;
 procedure NotifyGlobalLoading;
@@ -1334,7 +1234,11 @@ function LineStart(Buffer, BufPos: PChar): PChar;
 
 {
   $Log$
-  Revision 1.21  2000-01-07 01:24:33  peter
+  Revision 1.22  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.21  2000/01/07 01:24:33  peter
     * updated copyright to 2000
 
   Revision 1.20  2000/01/06 01:20:32  peter

+ 20 - 6
fcl/inc/compon.inc

@@ -112,8 +112,18 @@ end;
 
 Procedure TComponent.SetReference(Enable: Boolean);
 
+var
+  Field: ^TComponent;
 begin
-  // For delphi compatibility only.
+  if Assigned(Owner) then
+  begin
+    Field := Owner.FieldAddress(Name);
+    if Assigned(Field) then
+      if Enable then
+        Field^ := Self
+      else
+        Field^ := nil;
+  end;
 end;
 
 
@@ -219,10 +229,10 @@ begin
 end;
 
 
-Procedure TComponent.ReadState(Reader: TAbstractReader);
+Procedure TComponent.ReadState(Reader: TReader);
 
 begin
-//!!  Reader.ReadData(Self);
+  Reader.ReadData(Self);
 end;
 
 
@@ -333,10 +343,10 @@ begin
 end;
 
 
-Procedure TComponent.WriteState(Writer: TAbstractWriter);
+Procedure TComponent.WriteState(Writer: TWriter);
 
 begin
-  Writer.WriteData(self);
+  Writer.WriteComponentData(Self);
 end;
 
 
@@ -478,7 +488,11 @@ end;
 
 {
   $Log$
-  Revision 1.11  2000-01-07 01:24:33  peter
+  Revision 1.12  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.11  2000/01/07 01:24:33  peter
     * updated copyright to 2000
 
   Revision 1.10  2000/01/06 01:20:32  peter

+ 14 - 10
fcl/inc/constse.inc

@@ -41,18 +41,18 @@ const
   SInvalidPropertyPath = 'Invalid property path';
   SUnknownProperty = 'Unknown property';
   SReadOnlyProperty = 'Read-only property';
-  SPropertyException = 'Error when reading %s.%s: %s';
-  SAncestorNotFound = 'Ancestor of ''%s'' not found.';
+  SPropertyException = 'Error while reading %s%s%s: %s';
+  SAncestorNotFound = 'Ancestor of ''%s'' not found';
   SInvalidBitmap = 'Invalid Bitmap';
   SInvalidIcon = 'Invalid Icon';
-  SInvalidMetafile = 'Invalid MetaFile';
-  SInvalidPixelFormat = 'Invalid PixelFormat';
+  SInvalidMetafile = 'Invalid Metafile';
+  SInvalidPixelFormat = 'Invalid Pixelformat';
   SBitmapEmpty = 'Bitmap is empty';
   SScanLine = 'Line index out of bounds';
-  SChangeIconSize = 'Can not change Icon size';
+  SChangeIconSize = 'Can not change icon size';
   SOleGraphic = 'Invalid operation for TOleGraphic';
   SUnknownExtension = 'Unknown extension (.%s)';
-  SUnknownClipboardFormat = 'Unknown Clipboard format';
+  SUnknownClipboardFormat = 'Unknown clipboard format';
   SOutOfResources = 'Out of system resources';
   SNoCanvasHandle = 'Canvas handle does not allow drawing';
   SInvalidImageSize = 'Invalid image size';
@@ -60,9 +60,9 @@ const
   SDimsDoNotMatch = 'Image size mismatch';
   SInvalidImageList = 'Invalid ImageList';
   SReplaceImage = 'Image can not be replaced';
-  SImageIndexError = 'Invalid ImageList-Index';
-  SImageReadFail = 'The ImageList data could not be read from Stream';
-  SImageWriteFail = 'The ImageList data could not be written to Stream';
+  SImageIndexError = 'Invalid ImageList index';
+  SImageReadFail = 'The ImageList data could not be read from stream';
+  SImageWriteFail = 'The ImageList data could not be written to stream';
   SWindowDCError = 'Error when??';
   SClientNotSet = 'Client of TDrag was not initialized';
   SWindowClass = 'Error when initializing Window Class';
@@ -272,7 +272,11 @@ const
 
 {
   $Log$
-  Revision 1.8  2000-02-15 21:57:51  sg
+  Revision 1.9  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.8  2000/02/15 21:57:51  sg
   * Added copyright notice and CVS log tags where necessary
 
 }

+ 6 - 2
fcl/inc/constsg.inc

@@ -42,7 +42,7 @@ const
   SInvalidPropertyPath = 'Ungültiger Pfad für Eigenschaft';
   SUnknownProperty = 'Eigenschaft existiert nicht';
   SReadOnlyProperty = 'Eigenschaft kann nur gelesen werden';
-  SPropertyException = 'Fehler beim Lesen von %s.%s: %s';
+  SPropertyException = 'Fehler beim Lesen von %s%s: %s';
   SAncestorNotFound = 'Vorfahr für ''%s'' nicht gefunden';
   SInvalidBitmap = 'Bitmap ist ungültig';
   SInvalidIcon = 'Ungültiges Symbol';
@@ -273,7 +273,11 @@ const
 
 {
   $Log$
-  Revision 1.6  2000-02-15 21:57:51  sg
+  Revision 1.7  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.6  2000/02/15 21:57:51  sg
   * Added copyright notice and CVS log tags where necessary
 
 }

+ 6 - 2
fcl/inc/constss.inc

@@ -41,7 +41,7 @@ const
   SInvalidPropertyPath = 'Path de propiedad no valido';
   SUnknownProperty = 'Propiedad desconocidad';
   SReadOnlyProperty = 'Propiedad de solo lectura';
-  SPropertyException = 'Error leyendo %s.%s: %s';
+  SPropertyException = 'Error leyendo %s%s: %s';
 {N}  SAncestorNotFound = 'Ancestor of ''%s'' not found.';
   SInvalidBitmap = 'Bitmap no valido';
   SInvalidIcon = 'Icono no valido';
@@ -272,7 +272,11 @@ const
 
 {
   $Log$
-  Revision 1.6  2000-02-15 21:57:51  sg
+  Revision 1.7  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.6  2000/02/15 21:57:51  sg
   * Added copyright notice and CVS log tags where necessary
 
 }

+ 11 - 14
fcl/inc/filer.inc

@@ -15,21 +15,18 @@
   *                         TFiler                                    *
   *********************************************************************}
 
-{
-  $Log$
-  Revision 1.5  2000-01-07 01:24:33  peter
-    * updated copyright to 2000
-
-  Revision 1.4  2000/01/06 01:20:33  peter
-    * moved out of packages/ back to topdir
+procedure TFiler.SetRoot(ARoot: TComponent);
+begin
+  FRoot := ARoot;
+end;
 
-  Revision 1.2  2000/01/04 18:07:16  michael
-  + Streaming implemented
 
-  Revision 1.2  1998/08/24 12:38:23  michael
-  small fixes
-
-  Revision 1.1  1998/05/04 14:30:11  michael
-  * Split file according to Class; implemented dummys for all methods, so unit compiles.
+{
+  $Log$
+  Revision 1.6  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
 
+  Revision 1.5  2000/01/07 01:24:33  peter
+    * updated copyright to 2000
 }

+ 1074 - 198
fcl/inc/reader.inc

@@ -12,381 +12,1257 @@
 
  **********************************************************************}
 {****************************************************************************}
-{*                             TREADER                                      *}
+{*                       TBinaryObjectReader                                *}
 {****************************************************************************}
 
-Procedure TReader.CheckValue(Value: TValueType);
-
+constructor TBinaryObjectReader.Create(Stream: TStream; BufSize: Integer);
 begin
+  inherited Create;
+  FStream := Stream;
+  FBufSize := BufSize;
+  GetMem(FBuffer, BufSize);
 end;
 
+destructor TBinaryObjectReader.Destroy;
+begin
+  { Seek back the amount of bytes that we didn't process unitl now: }
+  FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), soFromCurrent);
 
+  if Assigned(FBuffer) then
+    FreeMem(FBuffer, FBufSize);
 
-Procedure TReader.DoFixupReferences;
+  inherited Destroy;
+end;
 
+function TBinaryObjectReader.ReadValue: TValueType;
 begin
+  Result := vaNull; { Necessary in FPC as TValueType is larger than 1 byte! }
+  Read(Result, 1);
 end;
 
-
-
-Procedure TReader.FreeFixups;
-
+function TBinaryObjectReader.NextValue: TValueType;
 begin
+  Result := ReadValue;
+  { We only 'peek' at the next value, so seek back to unget the read value: }
+  Dec(FBufPos);
 end;
 
-
-
-Function TReader.GetPosition: Longint;
-
+procedure TBinaryObjectReader.BeginRootComponent;
+var
+  Signature: LongInt;
 begin
-  GetPosition:=0;
+  { Read filer signature }
+  Read(Signature, 4);
+  if Signature <> LongInt(FilerSignature) then
+    raise EReadError.Create(SInvalidImage);
 end;
 
-
-
-Procedure TReader.PropertyError;
-
+procedure TBinaryObjectReader.BeginComponent(var Flags: TFilerFlags;
+  var AChildPos: Integer; var CompClassName, CompName: String);
+var
+  Prefix: Byte;
+  ValueType: TValueType;
 begin
+  { Every component can start with a special prefix: }
+  Flags := [];
+  if (Byte(NextValue) and $f0) = $f0 then
+  begin
+    Prefix := Byte(ReadValue);
+    Flags := TFilerFlags(Prefix and $0f);
+    if ffChildPos in Flags then
+    begin
+      ValueType := NextValue;
+      case ValueType of
+        vaInt8:
+	  AChildPos := ReadInt8;
+	vaInt16:
+	  AChildPos := ReadInt16;
+        vaInt32:
+	  AChildPos := ReadInt32;
+	else
+	  raise EReadError.Create(SInvalidPropertyValue);
+      end;
+    end;
+  end;
+
+  CompClassName := ReadStr;
+  CompName := ReadStr;
 end;
 
-
-
-Procedure TReader.ReadBuffer;
-
+function TBinaryObjectReader.BeginProperty: String;
 begin
+  Result := ReadStr;
 end;
 
-
-
-Procedure TReader.ReadData(Instance: TComponent);
-
+procedure TBinaryObjectReader.ReadBinary(const DestData: TMemoryStream);
+var
+  BinSize: LongInt;
 begin
+  Read(BinSize, 4);
+  DestData.Size := BinSize;
+  Read(DestData.Memory^, BinSize);
 end;
 
-
-
-Procedure TReader.ReadDataInner(Instance: TComponent);
-
+function TBinaryObjectReader.ReadFloat: Extended;
 begin
+  Read(Result, SizeOf(Extended))
 end;
 
-
-
-Procedure TReader.ReadProperty(AInstance: TPersistent);
-
+function TBinaryObjectReader.ReadSingle: Single;
 begin
+  Read(Result, SizeOf(Single))
 end;
 
+{!!!: function TBinaryObjectReader.ReadCurrency: Currency;
+begin
+  Read(Result, SizeOf(Currency))
+end;}
 
-
-Procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
-
+function TBinaryObjectReader.ReadDate: TDateTime;
 begin
+  Read(Result, SizeOf(TDateTime))
 end;
 
-
-
-Function TReader.ReadSet(SetType: Pointer): Integer;
-
+function TBinaryObjectReader.ReadIdent(ValueType: TValueType): String;
+var
+  i: Byte;
 begin
-  ReadSet:=0;
+  case ValueType of
+    vaIdent:
+      begin
+        Read(i, 1);
+	SetLength(Result, i);
+        Read(Pointer(@Result[1])^, i);
+      end;
+    vaNil:
+      Result := 'nil';
+    vaFalse:
+      Result := 'False';
+    vaTrue:
+      Result := 'True';
+    vaNull:
+      Result := 'Null';
+  end;
 end;
 
-
-
-Procedure TReader.SetPosition(Value: Longint);
-
+function TBinaryObjectReader.ReadInt8: ShortInt;
 begin
+  Read(Result, 1);
 end;
 
-
-
-Procedure TReader.SkipSetBody;
-
+function TBinaryObjectReader.ReadInt16: SmallInt;
 begin
+  Read(Result, 2);
 end;
 
-
-
-Procedure TReader.SkipValue;
-
+function TBinaryObjectReader.ReadInt32: LongInt;
 begin
+  Read(Result, 4);
 end;
 
-
-
-Procedure TReader.SkipProperty;
-
+function TBinaryObjectReader.ReadInt64: Int64;
 begin
+  Read(Result, 8);
 end;
 
-
-
-Procedure TReader.SkipComponent(SkipHeader: Boolean);
-
+function TBinaryObjectReader.ReadSet(EnumType: Pointer): Integer;
+var
+  Name: String;
+  Value: Integer;
 begin
+  try
+    while True do
+    begin
+      Name := ReadStr;
+      if Length(Name) = 0 then
+        break;
+      Value := GetEnumValue(PTypeInfo(EnumType), Name);
+      if Value = -1 then
+        raise EReadError.Create(SInvalidPropertyValue);
+      Result := Result or Value;
+    end;
+  except
+    SkipSetBody;
+    raise;
+  end;
 end;
 
+function TBinaryObjectReader.ReadStr: String;
+var
+  i: Byte;
+begin
+  Read(i, 1);
+  SetLength(Result, i);
+  Read(Pointer(@Result[1])^, i);
+end;
 
+function TBinaryObjectReader.ReadString(StringType: TValueType): String;
+var
+  i: Integer;
+begin
+  case StringType of
+    vaString:
+      begin
+        i := 0;
+        Read(i, 1);
+      end;
+    vaLString:
+      Read(i, 4);
+  end;
+  SetLength(Result, i);
+  if i > 0 then
+    Read(Pointer(@Result[1])^, i);
+end;
 
-Function TReader.Error(const Message: string): Boolean;
-
+{!!!: function TBinaryObjectReader.ReadWideString: WideString;
+var
+  i: Integer;
 begin
-  Error:=false;
+  FDriver.Read(i, 4);
+  SetLength(Result, i);
+  if i > 0 then
+    Read(PWideChar(Result), i * 2);
+end;}
+
+procedure TBinaryObjectReader.SkipComponent(SkipComponentInfos: Boolean);
+var
+  Flags: TFilerFlags;
+  Dummy: Integer;
+  CompClassName, CompName: String;
+begin
+  if SkipComponentInfos then
+    { Skip prefix, component class name and component object name }
+    BeginComponent(Flags, Dummy, CompClassName, CompName);
+
+  { Skip properties }
+  while NextValue <> vaNull do
+    SkipProperty;
+  ReadValue;
+
+  { Skip children }
+  while NextValue <> vaNull do
+    SkipComponent(True);
+  ReadValue;
 end;
 
+procedure TBinaryObjectReader.SkipValue;
+
+  procedure SkipBytes(Count: LongInt);
+  var
+    Dummy: array[0..1023] of Byte;
+    SkipNow: Integer;
+  begin
+    while Count > 0 do
+    begin
+      if Count > 1024 then
+        SkipNow := 1024
+      else
+        SkipNow := Count;
+      Read(Dummy, SkipNow);
+      Dec(Count, SkipNow);
+    end;
+  end;
+
+var
+  Count: LongInt;
+begin
+  case ReadValue of
+    vaNull, vaFalse, vaTrue, vaNil: ;
+    vaList:
+      begin
+        while NextValue <> vaNull do
+          SkipValue;
+	ReadValue;
+      end;
+    vaInt8:
+      SkipBytes(1);
+    vaInt16:
+      SkipBytes(2);
+    vaInt32:
+      SkipBytes(4);
+    vaExtended:
+      SkipBytes(SizeOf(Extended));
+    vaString, vaIdent:
+      ReadStr;
+    vaBinary, vaLString, vaWString:
+      begin
+        Read(Count, 4);
+        SkipBytes(Count);
+      end;
+    vaSet:
+      SkipSetBody;
+    vaCollection:
+      begin
+        while NextValue <> vaNull do
+        begin
+	  { Skip the order value if present }
+          if NextValue in [vaInt8, vaInt16, vaInt32] then
+	    SkipValue;
+          SkipBytes(1);
+          while NextValue <> vaNull do
+	    SkipProperty;
+	  ReadValue;
+        end;
+	ReadValue;
+      end;
+    vaSingle:
+      SkipBytes(Sizeof(Single));
+    {!!!: vaCurrency:
+      SkipBytes(SizeOf(Currency));}
+    vaDate:
+      SkipBytes(Sizeof(TDateTime));
+    vaInt64:
+      SkipBytes(8);
+  end;
+end;
 
+{ private methods }
 
-Function TReader.FindMethod(ARoot: TComponent; const AMethodName: string): Pointer;
+procedure TBinaryObjectReader.Read(var Buf; Count: LongInt);
+var
+  CopyNow: LongInt;
+  Dest: Pointer;
+begin
+  Dest := @Buf;
+  while Count > 0 do
+  begin
+    if FBufPos >= FBufEnd then
+    begin
+      FBufEnd := FStream.Read(FBuffer^, FBufSize);
+      if FBufEnd = 0 then
+        raise EReadError.Create(SReadError);
+      FBufPos := 0;
+    end;
+    CopyNow := FBufEnd - FBufPos;
+    if CopyNow > Count then
+      CopyNow := Count;
+    Move(PChar(FBuffer)[FBufPos], Dest^, CopyNow);
+    Inc(FBufPos, CopyNow);
+    Inc(Dest, CopyNow);
+    Dec(Count, CopyNow);
+  end;
+end;
 
+procedure TBinaryObjectReader.SkipProperty;
 begin
-  FindMethod:=nil;
+  { Skip property name, then the property value }
+  ReadStr;
+  SkipValue;
 end;
 
+procedure TBinaryObjectReader.SkipSetBody;
+begin
+  while Length(ReadStr) > 0 do;
+end;
 
 
-Procedure TReader.SetName(Component: TComponent; var Name: string);
 
-begin
-end;
+{****************************************************************************}
+{*                             TREADER                                      *}
+{****************************************************************************}
 
 
+// This may be better put somewhere else:
 
-Procedure TReader.ReferenceName(var Name: string);
+type
 
-begin
-end;
+  TFieldInfo = packed record
+    FieldOffset: LongWord;
+    ClassTypeIndex: Word;
+    Name: ShortString;
+  end;
 
+  PFieldClassTable = ^TFieldClassTable;
+  TFieldClassTable = packed record
+    Count: Word;
+    Entries: array[Word] of TPersistentClass;
+  end;
 
+  PFieldTable = ^TFieldTable;
+  TFieldTable = packed record
+    FieldCount: Word;
+    ClassTable: PFieldClassTable;
+    // Fields: array[Word] of TFieldInfo;  Elements have variant size!
+  end;
 
-Function TReader.FindAncestorComponent(const Name: string;
-  ComponentClass: TPersistentClass): TComponent;
 
+function GetFieldClass(Instance: TObject; const ClassName: string): TPersistentClass;
+var
+  UClassName: String;
+  ClassType: TClass;
+  ClassTable: PFieldClassTable;
+  i: Integer;
+  FieldTable: PFieldTable;
 begin
-  FindAncestorComponent:=nil;
+  // At first, try to locate the class in the class tables
+  UClassName := UpperCase(ClassName);
+  ClassType := Instance.ClassType;
+  while ClassType <> TPersistent do
+  begin
+    FieldTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^);
+    ClassTable := PFieldTable((Pointer(ClassType) + vmtFieldTable)^)^.ClassTable;
+    if Assigned(ClassTable) then
+      for i := 0 to ClassTable^.Count - 1 do
+      begin
+        Result := ClassTable^.Entries[i];
+        if UpperCase(Result.ClassName) = UClassName then
+          exit;
+      end;
+     // Try again with the parent class type
+     ClassType := ClassType.ClassParent;
+  end;
+  Result := Classes.GetClass(ClassName);
 end;
 
 
+constructor TReader.Create(Stream: TStream; BufSize: Integer);
+begin
+  inherited Create;
+  FDriver := TBinaryObjectReader.Create(Stream, BufSize);
+end;
 
 destructor TReader.Destroy;
-
 begin
+  FDriver.Free;
+  inherited Destroy;
 end;
 
-
-
-Procedure TReader.BeginReferences;
-
+procedure TReader.BeginReferences;
 begin
+  FLoaded := TList.Create;
+  try
+    FFixups := TList.Create;
+  except
+    FLoaded.Free;
+    raise;
+  end;
 end;
 
-
-
-Procedure TReader.DefineProperty(const Name: string;
-  rd : TReaderProc; wd : TWriterProc;
-  HasData: Boolean);
-
+procedure TReader.CheckValue(Value: TValueType);
 begin
+  if FDriver.NextValue <> Value then
+    raise EReadError.Create(SInvalidPropertyValue)
+  else
+    FDriver.ReadValue;
 end;
 
-
-
-Procedure TReader.DefineBinaryProperty(const Name: string;
-  rd, wd: TStreamProc;
-  HasData: Boolean);
-
+procedure TReader.DefineProperty(const Name: String; AReadData: TReaderProc;
+  WriteData: TWriterProc; HasData: Boolean);
 begin
+  if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
+  begin
+    AReadData(Self);
+    SetLength(FPropName, 0);
+  end;
 end;
 
-
-
-Function TReader.EndOfList: Boolean;
-
+procedure TReader.DefineBinaryProperty(const Name: String;
+  AReadData, WriteData: TStreamProc; HasData: Boolean);
+var
+  MemBuffer: TMemoryStream;
 begin
-  EndOfList:=false;
+  if Assigned(AReadData) and (UpperCase(Name) = UpperCase(FPropName)) then
+  begin
+    { Check if the next property really is a binary property}
+    if FDriver.NextValue <> vaBinary then
+    begin
+      FDriver.SkipValue;
+      FCanHandleExcepts := True;
+      raise EReadError.Create(SInvalidPropertyValue);
+    end else
+      FDriver.ReadValue;
+
+    MemBuffer := TMemoryStream.Create;
+    try
+      FDriver.ReadBinary(MemBuffer);
+      FCanHandleExcepts := True;
+      AReadData(MemBuffer);
+    finally
+      MemBuffer.Free;
+    end;
+    SetLength(FPropName, 0);
+  end;
 end;
 
-
-
-Procedure TReader.EndReferences;
-
+function TReader.EndOfList: Boolean;
 begin
+  Result := FDriver.NextValue = vaNull;
 end;
 
-
-
-Procedure TReader.FixupReferences;
-
+procedure TReader.EndReferences;
 begin
+  FreeFixups;
+  FLoaded.Free;
+  FLoaded := nil;
 end;
 
-
-
-Procedure TReader.FlushBuffer;
-
+function TReader.Error(const Message: String): Boolean;
 begin
+  Result := False;
+  if Assigned(FOnError) then
+    FOnError(Self, Message, Result);
 end;
 
+function TReader.FindMethod(ARoot: TComponent; const AMethodName: String): Pointer;
+var
+  ErrorResult: Boolean;
+begin
+  Result := ARoot.MethodAddress(AMethodName);
+  ErrorResult := Result = nil;
 
+  { always give the OnFindMethod callback a chance to locate the method }
+  if Assigned(FOnFindMethod) then
+    FOnFindMethod(Self, AMethodName, Result, ErrorResult);
 
-Function TReader.NextValue: TValueType;
+  if ErrorResult then
+    raise EReadError.Create(SInvalidPropertyValue);
+end;
 
+procedure RemoveGlobalFixup(Fixup: TPropFixup);
+var
+  i: Integer;
 begin
-  NextValue:=vaNull;
+  with GlobalFixupList.LockList do
+    try
+      for i := Count - 1 downto 0 do
+        with TPropFixup(Items[i]) do
+          if (FInstance = Fixup.FInstance) and
+	    (FPropInfo = Fixup.FPropInfo) then
+          begin
+            Free;
+            Delete(i);
+          end;
+    finally
+      GlobalFixupList.UnlockList;
+    end;
 end;
 
-
-
-Procedure TReader.Read(var Buf; Count: Longint);
-
+procedure TReader.DoFixupReferences;
+var
+  i: Integer;
+  CurFixup: TPropFixup;
+  CurName: String;
+  Target: Pointer;
 begin
+  if Assigned(FFixups) then
+    try
+      for i := 0 to FFixups.Count - 1 do
+      begin
+        CurFixup := TPropFixup(FFixups[i]);
+        CurName := CurFixup.FName;
+        if Assigned(FOnReferenceName) then
+          FOnReferenceName(Self, CurName);
+        Target := FindNestedComponent(CurFixup.FInstanceRoot, CurName);
+        RemoveGlobalFixup(CurFixup);
+        if (not Assigned(Target)) and CurFixup.MakeGlobalReference then
+        begin
+          GlobalFixupList.Add(CurFixup);
+          FFixups[i] := nil;
+        end else
+          SetOrdProp(CurFixup.FInstance, CurFixup.FPropInfo, LongInt(Target));
+      end;
+    finally
+      FreeFixups;
+    end;
 end;
 
-
-
-Function TReader.ReadBoolean: Boolean;
-
+procedure TReader.FixupReferences;
+var
+  i: Integer;
 begin
-  ReadBoolean:=false;
+  DoFixupReferences;
+  GlobalFixupReferences;
+  for i := 0 to FLoaded.Count - 1 do
+    TComponent(FLoaded[I]).Loaded;
 end;
 
-
-
-Function TReader.ReadChar: Char;
-
+procedure TReader.FreeFixups;
+var
+  i: Integer;
 begin
-  ReadChar:=#0;
+  if Assigned(FFixups) then
+  begin
+    for i := 0 to FFixups.Count - 1 do
+      TPropFixup(FFixups[I]).Free;
+    FFixups.Free;
+    FFixups := nil;
+  end;
 end;
 
-
-
-Procedure TReader.ReadCollection(Collection: TCollection);
-
+function TReader.NextValue: TValueType;
 begin
+  Result := FDriver.NextValue;
 end;
 
-
-
-Function TReader.ReadComponent(Component: TComponent): TComponent;
-
+procedure TReader.PropertyError;
 begin
-  ReadComponent:=nil;
+  FDriver.SkipValue;
+  raise EReadError.Create(SUnknownProperty);
 end;
 
-
-
-Procedure TReader.ReadComponents(AOwner, AParent: TComponent;
-  Proc: TReadComponentsProc);
-
+function TReader.ReadBoolean: Boolean;
+var
+  ValueType: TValueType;
 begin
+  ValueType := FDriver.ReadValue;
+  if ValueType = vaTrue then
+    Result := True
+  else if ValueType = vaFalse then
+    Result := False
+  else
+    raise EReadError.Create(SInvalidPropertyValue);
 end;
 
-
-
-Function TReader.ReadFloat: Extended;
-
+function TReader.ReadChar: Char;
+var
+  s: String;
 begin
-  ReadFloat:=0.0;
+  s := ReadString;
+  if Length(s) = 1 then
+    Result := s[1]
+  else
+    raise EReadError.Create(SInvalidPropertyValue);
 end;
 
-
-
-Function TReader.ReadIdent: string;
-
+procedure TReader.ReadCollection(Collection: TCollection);
+var
+  Item: TPersistent;
 begin
-  ReadIdent:='';
+  Collection.BeginUpdate;
+  try
+    if not EndOfList then
+      Collection.Clear;
+    while not EndOfList do
+    begin
+      if FDriver.NextValue in [vaInt8, vaInt16, vaInt32] then
+        ReadInteger;		{ Skip order value }
+      Item := Collection.Add;
+      ReadListBegin;
+      while not EndOfList do
+        ReadProperty(Item);
+      ReadListEnd;
+    end;
+    ReadListEnd;
+  finally
+    Collection.EndUpdate;
+  end;
 end;
 
-
-
-Function TReader.ReadInteger: Longint;
-
+function TReader.ReadComponent(Component: TComponent): TComponent;
+var
+  Flags: TFilerFlags;
+
+  function Recover(var Component: TComponent): Boolean;
+  begin
+    Result := False;
+    if ExceptObject.InheritsFrom(Exception) then
+    begin
+      if not ((ffInherited in Flags) or Assigned(Component)) then
+        Component.Free;
+      Component := nil;
+      FDriver.SkipComponent(False);
+      Result := Error(Exception(ExceptObject).Message);
+    end;
+  end;
+
+var
+  CompClassName, Name: String;
+  ChildPos: Integer;
+  SavedParent, SavedLookupRoot: TComponent;
+  ComponentClass: TComponentClass;
+  NewComponent: TComponent;
 begin
-  ReadInteger:=0;
+  FDriver.BeginComponent(Flags, ChildPos, CompClassName, Name);
+  SavedParent := Parent;
+  SavedLookupRoot := FLookupRoot;
+  try
+    Result := Component;
+    if not Assigned(Result) then
+      try
+        if ffInherited in Flags then
+	begin
+          { Try to locate the existing ancestor component }
+
+	  if Assigned(FLookupRoot) then
+	    Result := FLookupRoot.FindComponent(Name)
+	  else
+	    Result := nil;
+
+	  if not Assigned(Result) then
+	  begin
+	    if Assigned(FOnAncestorNotFound) then
+	      FOnAncestorNotFound(Self, Name,
+	        FindComponentClass(CompClassName), Result);
+	    if not Assigned(Result) then
+	      raise EReadError.CreateFmt(SAncestorNotFound, [Name]);
+	  end;
+
+          Parent := Result.GetParentComponent;
+          if not Assigned(Parent) then
+	    Parent := Root;
+	end else
+	begin
+          Result := nil;
+          ComponentClass := FindComponentClass(CompClassName);
+          if Assigned(FOnCreateComponent) then
+            FOnCreateComponent(Self, ComponentClass, Result);
+          if not Assigned(Result) then
+          begin
+//!!!:            NewComponent := TComponent(ComponentClass.NewInstance);
+	    NewComponent := TComponentClass(ComponentClass).Create(Owner);
+            if ffInline in Flags then
+	      NewComponent.FComponentState :=
+	        NewComponent.FComponentState + [csLoading, csInline];
+//!!!:            NewComponent.Create(Owner);
+
+	    { Don't set Result earlier because else we would come in trouble
+	      with the exception recover mechanism! (Result should be NIL if
+	      an error occured) }
+            Result := NewComponent;
+          end;
+          Include(Result.FComponentState, csLoading);
+	end;
+      except
+        if not Recover(Result) then
+	  raise;
+      end;
+
+    if Assigned(Result) then
+      try
+        Include(Result.FComponentState, csLoading);
+        if not (ffInherited in Flags) then
+          try
+            Result.SetParentComponent(Parent);
+	    if Assigned(FOnSetName) then
+	      FOnSetName(Self, Result, Name);
+	    Result.Name := Name;
+            if Assigned(FindGlobalComponent) and
+              (FindGlobalComponent(Name) = Result) then
+              Include(Result.FComponentState, csInline);
+          except
+            if not Recover(Result) then
+	      raise;
+          end;
+        if not Assigned(Result) then
+	  exit;
+        if csInline in Result.ComponentState then
+          FLookupRoot := Result;
+
+	{ Read the component state }
+        Include(Result.FComponentState, csReading);
+        Result.ReadState(Self);
+        Exclude(Result.FComponentState, csReading);
+
+        if ffChildPos in Flags then
+	  Parent.SetChildOrder(Result, ChildPos);
+
+        { Add component to list of loaded components, if necessary }
+	if (not ((ffInherited in Flags) or (csInline in Result.ComponentState))) or
+	  (FLoaded.IndexOf(Result) < 0) then
+	  FLoaded.Add(Result);
+      except
+        if ((ffInherited in Flags) or Assigned(Component)) then
+	  Result.Free;
+        raise;
+      end;
+  finally
+    Parent := SavedParent;
+    FLookupRoot := SavedLookupRoot;
+  end;
 end;
 
-
-
-Procedure TReader.ReadListBegin;
-
+procedure TReader.ReadData(Instance: TComponent);
+var
+  DoFreeFixups: Boolean;
+  SavedOwner, SavedParent: TComponent;
 begin
+  if not Assigned(FFixups) then
+  begin
+    FFixups := TList.Create;
+    DoFreeFixups := True;
+  end else
+    DoFreeFixups := False;
+
+  try
+    { Read properties }
+    while not EndOfList do
+      ReadProperty(Instance);
+    ReadListEnd;
+
+    { Read children }
+    SavedOwner := Owner;
+    SavedParent := Parent;
+    try
+      Owner := Instance.GetChildOwner;
+      if not Assigned(Owner) then
+        Owner := Root;
+      Parent := Instance.GetChildParent;
+
+      while not EndOfList do
+        ReadComponent(nil);
+      ReadListEnd;
+    finally
+      Owner := SavedOwner;
+      Parent := SavedParent;
+    end;
+
+    { Fixup references if necessary (normally only if this is the root) }
+    if DoFreeFixups then
+      DoFixupReferences;
+
+  finally
+    if DoFreeFixups then
+      FreeFixups;
+  end;
 end;
 
-
-
-Procedure TReader.ReadListEnd;
-
+function TReader.ReadFloat: Extended;
 begin
+  if FDriver.NextValue = vaExtended then
+  begin
+    ReadValue;
+    Result := FDriver.ReadFloat
+  end else
+    Result := ReadInteger;
 end;
 
-
-
-Procedure TReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
-
+function TReader.ReadSingle: Single;
 begin
+  if FDriver.NextValue = vaSingle then
+  begin
+    FDriver.ReadValue;
+    Result := FDriver.ReadSingle;
+  end else
+    Result := ReadInteger;
 end;
 
-
-
-Function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
-
+{!!!: function TReader.ReadCurrency: Currency;
+begin
+  if FDriver.NextValue = vaCurrency then
+  begin
+    FDriver.ReadValue;
+    Result := FDriver.ReadCurrency;
+  end else
+    Result := ReadInteger;
+end;}
+
+function TReader.ReadDate: TDateTime;
 begin
-  ReadRootComponent:=nil;
+  if FDriver.NextValue = vaDate then
+  begin
+    FDriver.ReadValue;
+    Result := FDriver.ReadDate;
+  end else
+    Result := ReadInteger;
 end;
 
-
-
-Procedure TReader.ReadSignature;
-
+function TReader.ReadIdent: String;
+var
+  ValueType: TValueType;
 begin
+  ValueType := FDriver.ReadValue;
+  if ValueType in [vaIdent, vaNil, vaFalse, vaTrue, vaNull] then
+    Result := FDriver.ReadIdent(ValueType)
+  else
+    raise EReadError.Create(SInvalidPropertyValue);
 end;
 
 
-
-Function TReader.ReadStr: string;
-
+function TReader.ReadInteger: LongInt;
 begin
-  ReadStr:='';
+  case FDriver.ReadValue of
+    vaInt8:
+      Result := FDriver.ReadInt8;
+    vaInt16:
+      Result := FDriver.ReadInt16;
+    vaInt32:
+      Result := FDriver.ReadInt32;
+  else
+    raise EReadError.Create(SInvalidPropertyValue);
+  end;
 end;
 
+function TReader.ReadInt64: Int64;
+begin
+  if FDriver.NextValue = vaInt64 then
+  begin
+    FDriver.ReadValue;
+    Result := FDriver.ReadInt64;
+  end else
+    Result := ReadInteger;
+end;
 
+procedure TReader.ReadListBegin;
+begin
+  CheckValue(vaList);
+end;
 
-Function TReader.ReadString: string;
-
+procedure TReader.ReadListEnd;
 begin
-  ReadString:='';
+  CheckValue(vaNull);
 end;
 
+procedure TReader.ReadProperty(AInstance: TPersistent);
+var
+  Path: String;
+  Instance: TPersistent;
+  DotPos, NextPos: PChar;
+  PropInfo: PPropInfo;
+  Obj: TObject;
+  Name: String;
+begin
+  try
+    Path := FDriver.BeginProperty;
+    try
+      Instance := AInstance;
+      FCanHandleExcepts := True;
+      DotPos := PChar(Path);
+      while True do
+      begin
+        NextPos := StrScan(DotPos, '.');
+	if Assigned(NextPos) then
+  	  FPropName := Copy(String(DotPos), 1, Integer(NextPos - DotPos))
+        else
+	begin
+	  FPropName := DotPos;
+	  break;
+	end;
+
+        PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
+        if not Assigned(PropInfo) then
+	  PropertyError;
+
+        if PropInfo^.PropType^.Kind = tkClass then
+          Obj := TObject(GetOrdProp(Instance, PropInfo))
+	else
+	  Obj := nil;
+
+        if not Obj.InheritsFrom(TPersistent) then
+	begin
+	  { All path elements must be persistent objects! }
+	  FDriver.SkipValue;
+          raise EReadError.Create(SInvalidPropertyPath);
+	end;
+        Instance := TPersistent(Obj);
+      end;
+
+      PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
+      if Assigned(PropInfo) then
+        ReadPropValue(Instance, PropInfo)
+      else
+      begin
+        FCanHandleExcepts := False;
+        Instance.DefineProperties(Self);
+        FCanHandleExcepts := True;
+        if Length(FPropName) > 0 then
+	  PropertyError;
+      end;
+    except
+      on e: Exception do
+      begin
+        SetLength(Name, 0);
+        if AInstance.InheritsFrom(TComponent) then
+	  Name := TComponent(AInstance).Name;
+        if Length(Name) = 0 then
+	  Name := AInstance.ClassName;
+        raise EReadError.CreateFmt(SPropertyException,
+	  [Name, DotSep, Path, e.Message]);
+      end;
+    end;
+  except
+    on e: Exception do
+      if not FCanHandleExcepts or not Error(E.Message) then
+        raise;
+  end;
+end;
 
+procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
+const
+  NullMethod: TMethod = (Code: nil; Data: nil);
+var
+  PropType: PTypeInfo;
+  Value: LongInt;
+  IdentToIntFn: TIdentToInt;
+  Ident: String;
+  Method: TMethod;
+begin
+  if not Assigned(PPropInfo(PropInfo)^.SetProc) then
+    raise EReadError.Create(SReadOnlyProperty);
+
+  PropType := PPropInfo(PropInfo)^.PropType;
+  case PropType^.Kind of
+    tkInteger:
+      if FDriver.NextValue = vaIdent then
+      begin
+        IdentToIntFn := FindIdentToInt(PPropInfo(PropInfo)^.PropType);
+        Ident := ReadIdent;
+        if Assigned(IdentToIntFn) and IdentToIntFn(Ident, Value) then
+          SetOrdProp(Instance, PropInfo, Value)
+        else
+          raise EReadError.Create(SInvalidPropertyValue);
+      end else
+        SetOrdProp(Instance, PropInfo, ReadInteger);
+    tkChar:
+      SetOrdProp(Instance, PropInfo, Ord(ReadChar));
+    tkEnumeration:
+      begin
+        Value := GetEnumValue(PropType, ReadIdent);
+        if Value = -1 then
+          raise EReadError.Create(SInvalidPropertyValue);
+        SetOrdProp(Instance, PropInfo, Value);
+      end;
+    tkFloat:
+      SetFloatProp(Instance, PropInfo, ReadFloat);
+    tkSet:
+      begin
+        CheckValue(vaSet);
+        SetOrdProp(Instance, PropInfo,
+	  FDriver.ReadSet(GetTypeData(PropType)^.CompType));
+      end;
+    tkMethod:
+      if FDriver.NextValue = vaNil then
+      begin
+        FDriver.ReadValue;
+        SetMethodProp(Instance, PropInfo, NullMethod);
+      end else
+      begin
+        Method.Code := FindMethod(Root, ReadIdent);
+        Method.Data := Root;
+        if Assigned(Method.Code) then
+	  SetMethodProp(Instance, PropInfo, Method);
+      end;
+    tkSString, tkLString, tkAString, tkWString:
+      SetStrProp(Instance, PropInfo, ReadString);
+    {!!!: tkVariant}
+    tkClass:
+      case FDriver.NextValue of
+        vaNil:
+          begin
+            FDriver.ReadValue;
+            SetOrdProp(Instance, PropInfo, 0)
+          end;
+        vaCollection:
+          begin
+            FDriver.ReadValue;
+            ReadCollection(TCollection(GetOrdProp(Instance, PropInfo)));
+          end
+        else
+          FFixups.Add(TPropFixup.Create(Instance, Root, PropInfo, '', ReadIdent));
+      end;
+    tkInt64: SetInt64Prop(Instance, PropInfo, ReadInt64);
+  end;
+end;
 
-Function TReader.ReadValue: TValueType;
+function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
+var
+  Dummy, i: Integer;
+  Flags: TFilerFlags;
+  CompClassName, CompName: String;
+begin
+  FDriver.BeginRootComponent;
+  Result := nil;
+  {!!!: GlobalNameSpace.BeginWrite;  // Loading from stream adds to name space
+  try}
+    try
+      FDriver.BeginComponent(Flags, Dummy, CompClassName, CompName);
+      if not Assigned(ARoot) then
+      begin
+        { Read the class name and the object name and create a new object: }
+        Result := TComponentClass(FindClass(CompClassName)).Create(nil);
+        Result.Name := CompName;
+      end else
+      begin
+        Result := ARoot;
+
+        if not (csDesigning in Result.ComponentState) then
+        begin
+	  Result.FComponentState :=
+	    Result.FComponentState + [csLoading, csReading];
+
+          if Assigned(FindGlobalComponent) then
+          begin
+	    { We need an unique name }
+            i := 0;
+            Result.Name := CompName;
+            while Assigned(FindGlobalComponent(Result.Name)) do
+            begin
+              Inc(i);
+              Result.Name := CompName + '_' + IntToStr(i);
+            end;
+          end else
+            Result.Name := '';
+        end;
+      end;
+
+      FRoot := Result;
+      FLookupRoot := Result;
+      if Assigned(GlobalLoaded) then
+        FLoaded := GlobalLoaded
+      else
+        FLoaded := TList.Create;
+
+      try
+        if FLoaded.IndexOf(FRoot) < 0 then
+          FLoaded.Add(FRoot);
+        FOwner := FRoot;
+	FRoot.FComponentState := FRoot.FComponentState + [csLoading, csReading];
+        FRoot.ReadState(Self);
+        Exclude(FRoot.FComponentState, csReading);
+
+        if not Assigned(GlobalLoaded) then
+          for i := 0 to FLoaded.Count - 1 do
+	    TComponent(FLoaded[i]).Loaded;
+
+      finally
+        if not Assigned(GlobalLoaded) then
+	  FLoaded.Free;
+        FLoaded := nil;
+      end;
+      GlobalFixupReferences;
+    except
+      RemoveFixupReferences(ARoot, '');
+      if not Assigned(ARoot) then
+        Result.Free;
+      raise;
+    end;
+  {finally
+    GlobalNameSpace.EndWrite;
+  end;}
+end;
 
+procedure TReader.ReadComponents(AOwner, AParent: TComponent;
+  Proc: TReadComponentsProc);
+var
+  Component: TComponent;
 begin
-  ReadValue:=vaNull;
+  Root := AOwner;
+  Owner := AOwner;
+  Parent := AParent;
+  BeginReferences;
+  try
+    while not EndOfList do
+    begin
+      FDriver.BeginRootComponent;
+      Component := ReadComponent(nil);
+      if Assigned(Proc) then
+        Proc(Component);
+    end;
+    ReadListEnd;
+    FixupReferences;
+  finally
+    EndReferences;
+  end;
 end;
 
 
+function TReader.ReadString: String;
+var
+  StringType: TValueType;
+begin
+  StringType := FDriver.ReadValue;
+  if StringType in [vaString, vaLString] then
+    Result := FDriver.ReadString(StringType)
+  else
+    raise EReadError.Create(SInvalidPropertyValue);
+end;
 
-Procedure TReader.CopyValue(Writer: TWriter); {!!!}
+{!!!: function TReader.ReadWideString: WideString;
+begin
+  CheckValue(vaWString);
+  Result := FDriver.ReadWideString;
+end;}
 
+function TReader.ReadValue: TValueType;
 begin
+  Result := FDriver.ReadValue;
 end;
-{
-  $Log$
-  Revision 1.6  2000-01-07 01:24:33  peter
-    * updated copyright to 2000
 
-  Revision 1.5  2000/01/06 01:20:33  peter
-    * moved out of packages/ back to topdir
+procedure TReader.CopyValue(Writer: TWriter);
+
+  procedure CopyBytes(Count: Integer);
+  var
+    Buffer: array[0..1023] of Byte;
+  begin
+{!!!:    while Count > 1024 do
+    begin
+      FDriver.Read(Buffer, 1024);
+      Writer.Driver.Write(Buffer, 1024);
+      Dec(Count, 1024);
+    end;
+    if Count > 0 then
+    begin
+      FDriver.Read(Buffer, Count);
+      Writer.Driver.Write(Buffer, Count);
+    end;}
+  end;
+
+var
+  s: String;
+  Count: LongInt;
+begin
+  case FDriver.NextValue of
+    vaNull:
+      Writer.WriteIdent('NULL');
+    vaFalse:
+      Writer.WriteIdent('FALSE');
+    vaTrue:
+      Writer.WriteIdent('TRUE');
+    vaNil:
+      Writer.WriteIdent('NIL');
+    {!!!: vaList, vaCollection:
+      begin
+        Writer.WriteValue(FDriver.ReadValue);
+        while not EndOfList do
+          CopyValue(Writer);
+        ReadListEnd;
+        Writer.WriteListEnd;
+      end;}
+    vaInt8, vaInt16, vaInt32:
+      Writer.WriteInteger(ReadInteger);
+    vaExtended:
+      Writer.WriteFloat(ReadFloat);
+    {!!!: vaString:
+      Writer.WriteStr(ReadStr);}
+    vaIdent:
+      Writer.WriteIdent(ReadIdent);
+    {!!!: vaBinary, vaLString, vaWString:
+      begin
+        Writer.WriteValue(FDriver.ReadValue);
+        FDriver.Read(Count, SizeOf(Count));
+        Writer.Driver.Write(Count, SizeOf(Count));
+        CopyBytes(Count);
+      end;}
+    {!!!: vaSet:
+      Writer.WriteSet(ReadSet);}
+    vaSingle:
+      Writer.WriteSingle(ReadSingle);
+    {!!!: vaCurrency:
+      Writer.WriteCurrency(ReadCurrency);}
+    vaDate:
+      Writer.WriteDate(ReadDate);
+    vaInt64:
+      Writer.WriteInteger(ReadInt64);
+  end;
+end;
 
-  Revision 1.2  2000/01/04 18:07:16  michael
-  + Streaming implemented
+function TReader.FindComponentClass(const AClassName: String): TComponentClass;
+begin
+  TPersistentClass(Result) := GetFieldClass(Root, AClassName);
+  if not Assigned(Result) and Assigned(FLookupRoot) and (FLookupRoot <> Root) then
+    TPersistentClass(Result) := GetFieldClass(FLookupRoot, AClassName);
+  if Assigned(FOnFindComponentClass) then
+    FOnFindComponentClass(Self, AClassName, Result);
+  if not (Assigned(Result) and Result.InheritsFrom(TComponent)) then
+    raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);
+end;
 
-  Revision 1.3  1999/09/13 08:35:16  fcl
-  * Changed some argument names (Root->ARoot etc.) because the new compiler
-    now performs more ambiguity checks  (sg)
 
-  Revision 1.2  1999/04/08 10:18:54  peter
-    * makefile updates
+{
+  $Log$
+  Revision 1.7  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
 
+  Revision 1.6  2000/01/07 01:24:33  peter
+    * updated copyright to 2000
 }

+ 80 - 45
fcl/inc/streams.inc

@@ -85,111 +85,142 @@
   function TStream.ReadComponent(Instance: TComponent): TComponent;
 
     var
-       Reader : TReader;
+      Reader: TReader;
 
     begin
-(*
-       Reader.Create(Self,1024);
-       if assigned(Instance) then
-         ReadComponent:=Reader.ReadRootComponent(Instance)
-       else
-         begin
-            {!!!!!}
-         end;
-       Reader.Destroy;
-*)
+
+      Reader := TReader.Create(Self, 4096);
+      try
+        Result := Reader.ReadRootComponent(Instance);
+      finally
+        Reader.Free;
+      end;
+
     end;
 
   function TStream.ReadComponentRes(Instance: TComponent): TComponent;
 
     begin
-       {!!!!!}
-       ReadComponentRes:=nil;
+
+      ReadResHeader;
+      Result := ReadComponent(Instance);
+
     end;
 
   procedure TStream.WriteComponent(Instance: TComponent);
 
+    begin
+
+      WriteDescendent(Instance, nil);
+
+    end;
+
+  procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
+
+    begin
+
+      WriteDescendentRes(ResName, Instance, nil);
+
+    end;
+
+  procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
+
     var
+       Driver : TAbstractObjectWriter;
        Writer : TWriter;
 
     begin
-(*
+
+       Driver := TBinaryObjectWriter.Create(Self, 4096);
        Try
-         Writer.Create(Self,1024);
-         Writer.WriteRootComponent(Instance);
+         Writer := TWriter.Create(Driver);
+	 Try
+           Writer.WriteDescendent(Instance, Ancestor);
+	 Finally
+	   Writer.Destroy;
+	 end;
        Finally
-         Writer.Destroy;
+	 Driver.Free;
        end;
-*)
+
     end;
 
-  procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
+  procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
 
     var
-       startpos,s : longint;
+      FixupInfo: Integer;
+
+    begin
+
+      { Write a resource header }
+      WriteResourceHeader(ResName, FixupInfo);
+      { Write the instance itself }
+      WriteDescendent(Instance, Ancestor);
+      { Insert the correct resource size into the resource header }
+      FixupResourceHeader(FixupInfo);
+
+    end;
+
+  procedure TStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
 
     begin
-{$ifdef Win16Res}
        { Numeric resource type }
        WriteByte($ff);
        { Application defined data }
        WriteWord($0a);
        { write the name as asciiz }
-//       WriteBuffer(ResName[1],length(ResName));
+       WriteBuffer(ResName[1],length(ResName));
        WriteByte(0);
        { Movable, Pure and Discardable }
        WriteWord($1030);
-       { size isn't known yet }
+       { Placeholder for the resource size }
        WriteDWord(0);
-       startpos:=GetPosition;
-       WriteComponent(Instance);
-       { calculate size }
-       s:=GetPosition-startpos;
-       { back patch size }
-       SetPosition(startpos-4);
-       WriteDWord(s);
-{$endif Win16Res}
+       { Return current stream position so that the resource size can be
+         inserted later }
+       FixupInfo := Position;
     end;
 
-  procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
+  procedure TStream.FixupResourceHeader(FixupInfo: Integer);
+
+    var
+       ResSize : Integer;
 
     begin
-       {!!!!!}
-    end;
 
-  procedure TStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
+      ResSize := Position - FixupInfo;
+
+      { Insert the correct resource size into the placeholder written by
+        WriteResourceHeader }
+      Position := FixupInfo - 4;
+      WriteDWord(ResSize);
+      { Seek back to the end of the resource }
+      Position := FixupInfo + ResSize;
 
-    begin
-       {!!!!!}
     end;
 
   procedure TStream.ReadResHeader;
 
     begin
-{$ifdef Win16Res}
        try
          { application specific resource ? }
          if ReadByte<>$ff then
-           raise EInvalidImage.Create('');
+           raise EInvalidImage.Create(SInvalidImage);
          if ReadWord<>$000a then
-           raise EInvalidImage.Create('');
+           raise EInvalidImage.Create(SInvalidImage);
          { read name }
          while ReadByte<>0 do
            ;
          { check the access specifier }
          if ReadWord<>$1030 then
-           raise EInvalidImage.Create('');
+           raise EInvalidImage.Create(SInvalidImage);
          { ignore the size }
          ReadDWord;
        except
-{/////
          on EInvalidImage do
            raise;
          else
            raise EInvalidImage.create(SInvalidImage);
-}
        end;
-{$endif Win16Res}
     end;
 
   function TStream.ReadByte : Byte;
@@ -625,7 +656,11 @@ end;
 
 {
   $Log$
-  Revision 1.20  2000-01-07 01:24:33  peter
+  Revision 1.21  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.20  2000/01/07 01:24:33  peter
     * updated copyright to 2000
 
   Revision 1.19  2000/01/06 01:20:33  peter

+ 7 - 3
fcl/inc/twriter.inc

@@ -12,7 +12,7 @@
 
  **********************************************************************}
 
-Procedure TTextWriter.WriteLn(Const Msg : String);
+(*Procedure TTextWriter.WriteLn(Const Msg : String);
 
 Const CRLF = #10;
 
@@ -211,11 +211,15 @@ Procedure TTextWriter.WriteMethodProperty(Const Name,AMethodName : ShortString);
 
 begin
   WriteFmt ('%s = %s',[Name,AMethodName]);
-end;
+end;*)
 
 {
   $Log$
-  Revision 1.3  2000-02-15 21:57:51  sg
+  Revision 1.4  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.3  2000/02/15 21:57:51  sg
   * Added copyright notice and CVS log tags where necessary
 
 }

+ 628 - 448
fcl/inc/writer.inc

@@ -11,625 +11,805 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
  **********************************************************************}
-{****************************************************************************}
-{*                             TAbstractWriter                                      *}
-{****************************************************************************}
-
-{ $define serdebug}
-
-Procedure TAbstractWriter.AddAncestor(Component: TComponent);
 
-begin
-  FAncestorList.Add(Component);
-end;
 
-Procedure TAbstractWriter.WriteData(Instance: TComponent);
+{****************************************************************************}
+{*                         TBinaryObjectWriter                              *}
+{****************************************************************************}
 
+constructor TBinaryObjectWriter.Create(Stream: TStream; BufSize: Integer);
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteData');
-{$endif}
-  With Instance do
-    StartObject(ClassName,Name);
-  WriteProperties(Instance);
-  Instance.GetChildren(@WriteComponent,FRoot);
-  EndObject;
+  inherited Create;
+  FStream := Stream;
+  FBufSize := BufSize;
+  GetMem(FBuffer, BufSize);
 end;
 
-{
-  These methods do the main work: decide if a property must be written,
-  and then call the write method.
-  Later on the NeedsWriting function should take the ancestor into
-  account as well, for form inheritance...
-}
-
-
-Procedure TAbstractWriter.DoOrdinalProp(Instance : TPersistent;Propinfo :PPropInfo);
-
-Var
-  Value : longint;
-
+destructor TBinaryObjectWriter.Destroy;
 begin
-  {$ifdef serdebug}
-    Writeln(stderr,'Writer: Starting DoOrdinalProp');
-  {$endif}
-  Value:=GetOrdProp(Instance,Propinfo);
-  If Value<>(PropInfo^.default) then
-    With PropInfo^ do
-      Case PropType^.Kind of
-        tkInteger :  WriteIntegerProperty(Name,Value);
-        tkSet : WriteSetProperty (Name,Value,GetTypeData(Proptype)^.CompType^);
-        tkEnumeration : WriteEnumerationProperty (Name,Value,GetEnumName(Proptype,Value));
-      end;
-end;
+  // Flush all data which hasn't been written yet
+  FlushBuffer;
 
-Procedure TAbstractWriter.DoStringProp(Instance : TPersistent;Propinfo :PPropInfo);
+  if Assigned(FBuffer) then
+    FreeMem(FBuffer, FBufSize);
 
-Var Value : String;
-
-begin
-  {$ifdef serdebug}
-    Writeln(stderr,'Writer: Starting DoStringProp');
-  {$endif}
-  Value:=GetStrProp(Instance,PropInfo);
-  If Value<>'' Then
-    With Propinfo^ do
-      WriteStringProperty(Name,Value);
+  inherited Destroy;
 end;
 
-Procedure TAbstractWriter.DoFloatProp(Instance : TPersistent;Propinfo :PPropInfo);
-
-Var Value : Extended;
-
+procedure TBinaryObjectWriter.BeginCollection;
 begin
-  {$ifdef serdebug}
-    Writeln(stderr,'Writer: Starting DoFloatProp');
-  {$endif}
-  Value:=GetFloatProp(Instance,Propinfo);
-  If (Value<>0.0) then
-    With PropInfo^ do
-      WriteFloatProperty(Name,Value);
+  WriteValue(vaCollection);
 end;
 
-
-Procedure TAbstractWriter.DoCollectionProp(Name: ShortString; Value : TCollection);
-
-Var OldPrefix : String;
-
+procedure TBinaryObjectWriter.BeginComponent(Component: TComponent;
+  Flags: TFilerFlags; ChildPos: Integer);
+var
+  Prefix: Byte;
 begin
-  {$ifdef serdebug}
-    Writeln(stderr,'Writer: Starting DoCollectionProp');
-  {$endif}
-  Try
-    OldPrefix:=FPrefix;
-    FPrefix:='';
-    WriteCollectionProperty(Name,Value)
-  Finally
-    FPrefix:=OldPrefix;
-  end;
-end;
-
-
-Procedure TAbstractWriter.DoClassProp(Instance : TPersistent;Propinfo :PPropInfo);
-
-{
-  Some explanation:
-  1) Only TPersistent properties can be written, since higher has no
-     RTTI (actually, we could test if the class has RTTI if it isn't
-     TPersistent, but Delphi doesn't - We can add it later)
-  2) If it is a TPersistent but not TComponent, then the only
-     thing that is (can be) written is the defineproperties;
-     we have this handled by calling writeproperties again.
-  3) When a property is a TComponent, it is owned by the form or by a
-     TDataModule; This means that the component is streamed also
-     (owner-owned) by the form, so it is sufficient to store a reference
-     to the component, not store the component itself.
-
-     Again, this is very form-oriented; at a later stage, we should see
-     to make this more broader.
-
-}
-
-Var
-  Value : TObject;
-
-  Function NeedsWriting : Boolean;
-
+  if not FSignatureWritten then
   begin
-    Result:=Value<>Nil;
+    Write(FilerSignature, SizeOf(FilerSignature));
+    FSignatureWritten := True;
   end;
 
-  Function GetComponentPath(Component : TComponent): String;
-
+  { Only write the flags if they are needed! }
+  if Flags <> [] then
   begin
-    If Component.Owner=Root Then
-      Result:=Component.Name          // 2 objects In the same form.
-    else if Component=Root then
-      Result:='Owner'                 // Component = Form.
-    else if Component.Owner<>Nil then
-      Result:=Format('%s.%s',[Component.Owner.name,Component.Name]) // Component on other e.g. Datamodule.
-    else
-      Result:=Format('%s.%s',[Component.Name+'owner']); // All other cases.
+    Prefix := Integer(Flags) or $f0;
+    Write(Prefix, 1);
+    if ffChildPos in Flags then
+      WriteInteger(ChildPos);
   end;
 
-Var
-  OldPrefix,CName : String;
+  WriteStr(Component.ClassName);
+  WriteStr(Component.Name);
+end;
 
+procedure TBinaryObjectWriter.BeginList;
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting DoClassProp');
-{$endif}
-  Value:=TObject(GetOrdProp(Instance,PropInfo));  // get as pointer
-{$ifdef serdebug}
-  If Value=Nil then
-    Writeln(stderr,'Writer: value is nil');
-  Writeln(stderr,'name ',propinfo^.Name);
-{$endif}
-  If (Value=Nil) Then
-    begin
-    If Needswriting then
-      With Propinfo^ do
-        WriteNilProperty(Name)
-    end
-  else
-    If Value is TPersistent then
-      begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: value is tpersistent');
-{$endif}
-        If Value is TComponent then
-          { Component is written by itself,
-            just write a reference }
-          begin
-          Cname:=GetComponentPath(TComponent(Value));
-          If NeedsWriting and (Cname<>'') then
-            begin
-              With PropInfo^ do
-                WriteComponentProperty(Name,TComponent(Value));
-            end;
-          end
-        else If Value is TCollection then
-           DoCollectionProp(Propinfo^.Name,TCollection(Value))
-        else
-          With Propinfo^ do
-            begin  // TPersistent, not TComponent.
-            OldPrefix:=FPrefix;
-            FPrefix:=Format('%s%s.',[OldPrefix,Name]); // eg. Memo.Lines.Strings !
-            try
-              WriteProperties(TPersistent(Value));
-            finally
-              FPrefix:=OldPrefix;
-            end;
-          end;
-      end
-   // We can't write it if it isn't a TPersistent...
+  WriteValue(vaList);
 end;
 
-Procedure TAbstractWriter.DoMethodProp(Instance : TPersistent;Propinfo :PPropInfo);
-{
-
-  Some explanation: AFAIK Delphi only allows to assign methods from the
-  current form to an event. (An event is a Method) this means that the
-  instance part of the method IS the Form which IS the 'root' component.
-  this means that we can safely assume that Method.Data = Root...
-
-  Remark also that Form Methods are always in a Published section of the form,
-  Since Delphi manages them, hence the method name is always in RTTI.
-
-  If we want a more general streaming method (i.e. not form oriented) then
-  we would have to write ComponentPath.MethodName or something.
-}
-
-Var
-  Value : TMethod;
-
+procedure TBinaryObjectWriter.EndList;
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting DoMethodProp');
-{$endif}
-  Value:=GetMethodProp(Instance,Propinfo);
-  With Value do
-    If Code<>Nil then
-      WriteMethodProperty(Propinfo^.Name,Root.MethodName(Code));
+  WriteValue(vaNull);
 end;
 
-Procedure TAbstractWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer);
-
-{$ifdef serdebug}
-Const
- TypeNames : Array [TTYpeKind] of string[15] =
-            ('Unknown','Integer','Char','Enumeration',
-             'Float','Set','Method','ShortString','LongString',
-             'AnsiString','WideString','Variant','Array','Record',
-             'Interface','Class','Object','WideChar','Bool');
-
- Const OrdinalTypes = [tkInteger,tkChar,tkENumeration,tkbool];
-{$endif}
-
+procedure TBinaryObjectWriter.BeginProperty(const PropName: String);
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteProperty');
-  With PPropInfo(Propinfo)^ do
-    begin
-    Writeln (stderr,' Type kind: ',TypeNames[PropType^.Kind]);
-    Writeln (stderr,' Type Name: ',PropType^.Name);
-    Writeln (stderr,'Writer: Starting WriteProperty');
-    end;
-{$endif}
-  // Dispatching routine. For compatibility only.
-  With PPropinfo(Propinfo)^ do
-    Case PropType^.Kind of
-      tkchar,tkInteger,tkenumeration,tkset : DoOrdinalProp(Instance,Propinfo);
-      tkAstring,tkstring,tkLString,tkWstring : DoStringProp(Instance,Propinfo);
-      tkfloat : DoFloatProp(Instance,PropInfo);
-      tkClass : DoClassProp(Instance,PropInfo);
-      tkMethod : DoMethodProp(Instance,PropInfo);
-    end;
+  WriteStr(PropName);
 end;
 
-
-Procedure TAbstractWriter.WriteProperties(Instance: TPersistent);
-
-Var I,PropCount : Longint;
-    Props : PPropList;
-
+procedure TBinaryObjectWriter.EndProperty;
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteProperties');
-{$endif}
-  PropCount:=GetTypeData(Instance.ClassInfo)^.PropCount;
-{$ifdef serdebug}
-  Writeln(stderr,'Writer : Propcount: ',PropCount);
-{$endif}
-  Try
-    GetMem (Props,SizeOf(Pointer)*PropCount);
-    GetPropInfos(Instance.ClassInfo,Props);
-    For I:=0 to PropCount-1 do
-      WriteProperty(Instance,Props^[I]);
-  finally
-    FreeMem(Props);
-  end;
-//  Instance.DefineProperties(Self);
 end;
 
-Destructor TAbstractWriter.Destroy;
-
+procedure TBinaryObjectWriter.WriteBinary(const Buffer; Count: LongInt);
 begin
+  WriteValue(vaBinary);
+  Write(Count, 4);
+  Write(Buffer, Count);
 end;
 
-Procedure TAbstractWriter.WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
-
+procedure TBinaryObjectWriter.WriteBoolean(Value: Boolean);
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteDescendent');
-{$endif}
-  FRootAncestor:=AAncestor;
-  FAncestor:=Ancestor;
-  FRoot:=ARoot;
-  WriteComponent(ARoot)
+  if Value then
+    WriteValue(vaTrue)
+  else
+    WriteValue(vaFalse);
 end;
 
-
-Procedure TAbstractWriter.WriteRootComponent(ARoot: TComponent);
-
+procedure TBinaryObjectWriter.WriteFloat(const Value: Extended);
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteRootComponent');
-{$endif}
-  WriteDescendent(ARoot,Nil);
+  WriteValue(vaExtended);
+  Write(Value, SizeOf(Value));
 end;
 
-procedure TAbstractWriter.WriteComponent(Component: TComponent);
-
-Var I : longint;
-    TheAncestor : TComponent;
-
+procedure TBinaryObjectWriter.WriteSingle(const Value: Single);
 begin
-{$ifdef serdebug}
-  Writeln(stderr,'Writer: Starting WriteComponent');
-{$endif}
-  Include(Component.FComponentState,csWriting);
-  TheAncestor:=Nil;
-  If Assigned(FAncestorList) then
-    For I:=0 to FAncestorList.Count-1 do
-      If TComponent(FAncestorList[i]).Name=Component.Name then
-        begin
-        TheAncestor:=Tcomponent(FancestorList[i]);
-        break;
-        end;
-  Ancestor:=TheAncestor;
-  Component.WriteState(Self);
-  Exclude(Component.FComponentState,csWriting);
+  WriteValue(vaSingle);
+  Write(Value, SizeOf(Value));
 end;
 
+{!!!: procedure TBinaryObjectWriter.WriteCurrency(const Value: Currency);
+begin
+  WriteValue(vaCurrency);
+  Write(Value, SizeOf(Value));
+end;}
 
-{ ---------------------------------------------------------------------
-    TWriter Methods
-  ---------------------------------------------------------------------}
-
-Constructor TWriter.Create(S : TStream);
-
+procedure TBinaryObjectWriter.WriteDate(const Value: TDateTime);
 begin
-  FStream:=S;
+  WriteValue(vaDate);
+  Write(Value, SizeOf(Value));
 end;
 
-
-Destructor TWriter.Destroy;
-
+procedure TBinaryObjectWriter.WriteIdent(const Ident: string);
 begin
+  { Check if Ident is a special identifier before trying to just write
+    Ident directly }
+  if UpperCase(Ident) = 'NIL' then
+    WriteValue(vaNil)
+  else if UpperCase(Ident) = 'FALSE' then
+    WriteValue(vaFalse)
+  else if UpperCase(Ident) = 'TRUE' then
+    WriteValue(vaTrue)
+  else if UpperCase(Ident) = 'NULL' then
+    WriteValue(vaNull) else
+  begin
+    WriteValue(vaIdent);
+    WriteStr(Ident);
+  end;
 end;
 
-Procedure TWriter.FlushBuffer;
-
+procedure TBinaryObjectWriter.WriteInteger(Value: Int64);
 begin
-  // For compatibility only.
+  { Use the smallest possible integer type for the given value: }
+  if (Value >= -128) and (Value <= 127) then
+  begin
+    WriteValue(vaInt8);
+    Write(Value, 1);
+  end else if (Value >= -32768) and (Value <= 32767) then
+  begin
+    WriteValue(vaInt16);
+    Write(Value, 2);
+  end else if (Value >= -$80000000) and (Value <= $7fffffff) then
+  begin
+    WriteValue(vaInt32);
+    Write(Value, 4);
+  end else
+  begin
+    WriteValue(vaInt64);
+    Write(Value, 8);
+  end;
 end;
 
-
-Procedure TWriter.Write(const Buf; Count: Longint);
-
+procedure TBinaryObjectWriter.WriteMethodName(const Name: String);
 begin
-  FStream.Write(Buf,Count);
+  if Length(Name) > 0 then
+  begin
+    WriteValue(vaIdent);
+    WriteStr(Name);
+  end else
+    WriteValue(vaNil);
 end;
 
-Procedure TWriter.WriteIntegerProperty(Const Name : Shortstring;Value : Longint);
-
+procedure TBinaryObjectWriter.WriteSet(Value: LongInt; SetType: Pointer);
+var
+  i: Integer;
+  Mask: LongInt;
 begin
-  WritePropName(Name);
-  WriteInteger(Value);
+  WriteValue(vaSet);
+  Mask := 1;
+  for i := 0 to 31 do
+  begin
+    if (Value and Mask) <> 0 then
+      WriteStr(GetEnumName(PTypeInfo(SetType), i));
+    Mask := Mask shl 1;
+  end;
+  WriteStr('');
 end;
 
-
-Procedure TWriter.WriteSetProperty (Const Name : ShortString;Value : longint; BaseType : TTypeInfo);
-
+procedure TBinaryObjectWriter.WriteString(const Value: String);
+var
+  i: Integer;
 begin
-  WritePropName(Name);
+  i := Length(Value);
+  if i <= 255 then
+  begin
+    WriteValue(vaString);
+    Write(i, 1);
+  end else
+  begin
+    WriteValue(vaLString);
+    Write(i, 4);
+  end;
+  if i > 0 then
+    Write(Value[1], i);
 end;
 
+{!!!: procedure TBinaryObjectWriter.WriteWideString(const Value: WideString);
+var
+  i: Integer;
+begin
+  WriteValue(vaWString);
+  i := Length(Value);
+  Write(i, 4);
+  Write(Value[1], i * 2);
+end;}
 
-Procedure TWriter.WriteEnumerationProperty (Const Name : ShortString;Value : Longint; Const EnumName : ShortSTring);
-
+procedure TBinaryObjectWriter.FlushBuffer;
 begin
-  WritePropName(Name);
-  WriteIdent(EnumName);
+  FStream.WriteBuffer(FBuffer^, FBufPos);
+  FBufPos := 0;
 end;
 
-
-Procedure TWriter.WriteStringProperty(Const Name : ShortString; Const Value : String);
-
+procedure TBinaryObjectWriter.Write(const Buffer; Count: LongInt);
+var
+  CopyNow: LongInt;
 begin
-  WritePropName(Name);
-  WriteString(Value);
+  while Count > 0 do
+  begin
+    CopyNow := Count;
+    if CopyNow > FBufSize - FBufPos then
+      CopyNow := FBufSize - FBufPos;
+    Move(Buffer, PChar(FBuffer)[FBufPos], CopyNow);
+    Dec(Count, CopyNow);
+    Inc(FBufPos, CopyNow);
+    if FBufPos = FBufSize then
+      FlushBuffer;
+  end;
 end;
 
-
-Procedure TWriter.WriteFloatProperty(Const Name : ShortString; Value : Extended);
-
+procedure TBinaryObjectWriter.WriteValue(Value: TValueType);
 begin
-  WritePropName(Name);
-  WriteFloat(Value);
+  Write(Value, 1);
 end;
 
-
-Procedure TWriter.WriteCollectionProperty(Const Name : ShortString;Value : TCollection);
-
+procedure TBinaryObjectWriter.WriteStr(const Value: String);
+var
+  i: Integer;
 begin
+  i := Length(Value);
+  if i > 255 then
+    i := 255;
+  Write(i, 1);
+  if i > 0 then
+    Write(Value[1], i);
 end;
 
 
-Procedure TWriter.WriteClassProperty(Instance : TPersistent;Propinfo :PPropInfo);
-
-begin
-end;
 
+{****************************************************************************}
+{*                             TWriter                                      *}
+{****************************************************************************}
 
-Procedure TWriter.WriteComponentProperty(Const Name : ShortString; Value : TComponent);
 
+constructor TWriter.Create(ADriver: TAbstractObjectWriter);
 begin
-  WritePropName(Name);
-  WriteIdent(Value.Name);
+  inherited Create;
+  FDriver := ADriver;
 end;
 
-
-Procedure TWriter.WriteNilProperty(Const Name : Shortstring);
-
+constructor TWriter.Create(Stream: TStream; BufSize: Integer);
 begin
-  WritePropName(Name);
-  WriteValue(vaNil)
+  inherited Create;
+  FDriver := TBinaryObjectWriter.Create(Stream, BufSize);
+  FDestroyDriver := True;
 end;
 
-
-Procedure TWriter.WriteMethodProperty(Const Name,AMethodName : Shortstring);
-
+destructor TWriter.Destroy;
 begin
+  if FDestroyDriver then
+    FDriver.Free;
+  inherited Destroy;
 end;
 
-
-procedure TWriter.WriteBoolean(Value: Boolean);
-
+// Used as argument for calls to TComponent.GetChildren:
+procedure TWriter.AddToAncestorList(Component: TComponent);
 begin
-  If Value then WriteValue(vaTrue) else WriteValue(vaFalse)
+  FAncestorList.Add(Component);
 end;
 
-
-procedure TWriter.WriteCollection(Value: TCollection);
-
+procedure TWriter.DefineProperty(const Name: String;
+  ReadData: TReaderProc; AWriteData: TWriterProc; HasData: Boolean);
 begin
+  if HasData and Assigned(AWriteData) then
+  begin
+    // Write the property name and then the data itself
+    Driver.BeginProperty(FPropPath + Name);
+    AWriteData(Self);
+    Driver.EndProperty;
+  end;
 end;
 
-
-procedure TWriter.WriteChar(Value: Char);
-
+procedure TWriter.DefineBinaryProperty(const Name: String;
+  ReadData, AWriteData: TStreamProc; HasData: Boolean);
 begin
+  if HasData and Assigned(AWriteData) then
+  begin
+    // Write the property name and then the data itself
+    Driver.BeginProperty(FPropPath + Name);
+    WriteBinary(AWriteData);
+    Driver.EndProperty;
+  end;
 end;
 
+procedure TWriter.SetRoot(ARoot: TComponent);
+begin
+  inherited SetRoot(ARoot);
+  // Use the new root as lookup root too
+  FLookupRoot := ARoot;
+end;
 
-procedure TWriter.WriteFloat(Value: Extended);
-
+procedure TWriter.WriteBinary(AWriteData: TStreamProc);
+var
+  MemBuffer: TMemoryStream;
+  BufferSize: Longint;
 begin
+  { First write the binary data into a memory stream, then copy this buffered
+    stream into the writing destination. This is necessary as we have to know
+    the size of the binary data in advance (we're assuming that seeking within
+    the writer stream is not possible) }
+  MemBuffer := TMemoryStream.Create;
+  try
+    AWriteData(MemBuffer);
+    BufferSize := MemBuffer.Size;
+    Driver.WriteBinary(MemBuffer.Memory^, BufferSize);
+  finally
+    MemBuffer.Free;
+  end;
 end;
 
+procedure TWriter.WriteBoolean(Value: Boolean);
+begin
+  Driver.WriteBoolean(Value);
+end;
 
-procedure TWriter.WriteIdent(const Ident: string);
+procedure TWriter.WriteChar(Value: Char);
+begin
+  WriteString(Value);
+end;
 
+procedure TWriter.WriteCollection(Value: TCollection);
+var
+  i: Integer;
 begin
-  if (Ident='Nil') then WriteValue(vaNil) else
-  if (Ident='True') then WriteValue(vaTrue) else
-  If (Ident='False') then WriteValue(vaFalse) else
+  Driver.BeginCollection;
+  if Assigned(Value) then
+    for i := 0 to Value.Count - 1 do
     begin
-    WriteValue(vaIdent);
-    WriteStr(Ident);
-    end
+      { Each collection item needs its own ListBegin/ListEnd tag, or else the
+        reader wouldn't be able to know where an item ends and where the next
+	one starts }
+      WriteListBegin;
+      WriteProperties(Value.Items[i]);
+      WriteListEnd;
+    end;
+  WriteListEnd;
 end;
 
+procedure TWriter.WriteComponent(Component: TComponent);
+var
+  SavedAncestor: TPersistent;
+  SavedRootAncestor, AncestorComponent, CurAncestor: TComponent;
+  i: Integer;
+  s: String;
+begin
+  SavedAncestor := Ancestor;
+  SavedRootAncestor := RootAncestor;
 
-procedure TWriter.WriteInteger(Value: Longint);
+  try
+    // The component has to know that it is being written now...
+    Include(Component.FComponentState, csWriting);
 
-begin
-  If (Value>=-128) and (Value<=127) then
+    // Locate the component in the ancestor list, if necessary
+    if Assigned(FAncestorList) then
     begin
-    WriteValue(vaInt8);
-    Write(Value,SizeOf(ShortInt));
-    end
-  else If (Value>=-32768) and (Value<=32767) then
+      Ancestor := nil;
+      s := UpperCase(Component.Name);
+      for i := 0 to FAncestorList.Count - 1 do
+      begin
+        CurAncestor := TComponent(FAncestorList[i]);
+        if UpperCase(CurAncestor.Name) = s then
+	begin
+	  Ancestor := CurAncestor;
+	  break;
+	end;
+      end;
+    end;
+
+    // Do we have to call the OnFindAncestor callback?
+    if Assigned(FOnFindAncestor) and
+      ((not Assigned(Ancestor)) or Ancestor.InheritsFrom(TComponent)) then
     begin
-    WriteValue(vaInt16);
-    Write(Value,SizeOf(SmallInt));
-    end
- else
-   begin
-   WriteValue(vaInt32);
-   Write(Value,SizeOf(Longint));
-   end;
-end;
+      AncestorComponent := TComponent(Ancestor);
+      FOnFindAncestor(Self, Component, Component.Name,
+        AncestorComponent, FRootAncestor);
+      Ancestor := AncestorComponent;
+    end;
 
+    // Finally write the component state
+    Component.WriteState(Self);
 
-procedure TWriter.WriteListBegin;
+    // The writing has been finished now...
+    Exclude(Component.FComponentState, csWriting);
 
-begin
-  WriteValue(vaList);
+  finally
+    Ancestor := SavedAncestor;
+    FRootAncestor := SavedRootAncestor;
+  end;
 end;
 
+procedure TWriter.WriteComponentData(Instance: TComponent);
+var
+  SavedAncestorList: TList;
+  SavedRoot, SavedRootAncestor: TComponent;
+  SavedAncestorPos, SavedChildPos: Integer;
+  Flags: TFilerFlags;
+begin
+  // Determine the filer flags to store
+  if Assigned(Ancestor) and ((not (csInline in Instance.ComponentState)) or
+    ((csAncestor in Instance.ComponentState) and Assigned(FAncestorList))) then
+    Flags := [ffInherited]
+  else if csInline in Instance.ComponentState then
+    Flags := [ffInline]
+  else
+    Flags := [];
 
-procedure TWriter.WriteListEnd;
+  if Assigned(FAncestorList) and (FAncestorPos < FAncestorList.Count) and
+    ((not Assigned(Ancestor)) or
+    (TPersistent(FAncestorList[FAncestorPos]) <> Ancestor)) then
+    Include(Flags, ffChildPos);
 
-begin
-  WriteValue(vaNull)
-end;
+  Driver.BeginComponent(Instance, Flags, FChildPos);
 
+  if Assigned(FAncestorList) and (FAncestorPos < FAncestorList.Count) then
+  begin
+    if Assigned(Ancestor) then
+      Inc(FAncestorPos);
+    Inc(FChildPos);
+  end;
 
-procedure TWriter.WriteSignature;
+  // Write property list
+  WriteProperties(Instance);
+  WriteListEnd;
+
+  // Write children list
+  SavedAncestorList := FAncestorList;
+  SavedAncestorPos := FAncestorPos;
+  SavedChildPos := FChildPos;
+  SavedRoot := FRoot;
+  SavedRootAncestor := FRootAncestor;
+  try
+    FAncestorList := nil;
+    FAncestorPos := 0;
+    FChildPos := 0;
+    if not IgnoreChildren then
+      try
+        // Set up the ancestor list if we have an ancestor
+        if Assigned(FAncestor) and FAncestor.InheritsFrom(TComponent) then
+        begin
+          if csInline in TComponent(FAncestor).ComponentState then
+            FRootAncestor := TComponent(FAncestor);
+          FAncestorList := TList.Create;
+          TComponent(FAncestor).GetChildren(@AddToAncestorList, FRootAncestor);
+        end;
 
-begin
-  Write(FilerSignature,SizeOf(FilerSignature));
-end;
+        if csInline in Instance.ComponentState then
+          FRoot := Instance;
 
+        Instance.GetChildren(@WriteComponent, FRoot);
 
-procedure TWriter.WriteStr(const Value: string);
+      finally
+        FAncestorList.Free;
+      end;
 
-Var L : longint;
+  finally
+    FAncestorList := SavedAncestorList;
+    FAncestorPos := SavedAncestorPos;
+    FChildPos := SavedChildPos;
+    FRoot := SavedRoot;
+    FRootAncestor := SavedRootAncestor;
+  end;
 
-begin
-  L:=Length(Value);
-  If L>255 then
-    L:=255;
-  Write(L,SizeOf(Byte));
-  Write(Pointer(Value)^,L);
+  WriteListEnd;
 end;
 
+procedure TWriter.WriteDescendent(ARoot: TComponent; AAncestor: TComponent);
+begin
+  FRoot := ARoot;
+  FAncestor := AAncestor;
+  FRootAncestor := AAncestor;
+  FLookupRoot := ARoot;
 
-procedure TWriter.WriteString(const Value: string);
-
-Var L : longint;
+  WriteComponent(ARoot);
+end;
 
+procedure TWriter.WriteFloat(const Value: Extended);
 begin
-  L:=Length(Value);
-  If L<=255 then
-    begin
-    WriteValue(vastring);
-    Write(L,SizeOf(Byte));
-    end
-  else
-    begin
-    WriteValue(vaLstring);
-    Write(L,SizeOf(Longint))
-    end;
-  Write(Pointer(Value)^,L);
+  Driver.WriteFloat(Value);
 end;
 
-Procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
-
+procedure TWriter.WriteSingle(const Value: Single);
 begin
+  Driver.WriteSingle(Value);
 end;
 
-Procedure TWriter.WriteValue(Value : TValueType);
+{!!!: procedure TWriter.WriteCurrency(const Value: Currency);
+begin
+  Driver.WriteCurrency(Value);
+end;}
 
+procedure TWriter.WriteDate(const Value: TDateTime);
 begin
-  Write(Value,SizeOf(Value));
+  Driver.WriteDate(Value);
 end;
 
-Procedure TWriter.WriteBuffer;
-
+procedure TWriter.WriteIdent(const Ident: string);
 begin
-  // For compatibility only.
+  Driver.WriteIdent(Ident);
 end;
 
-function  TWriter.GetPosition: Longint;
-
+procedure TWriter.WriteInteger(Value: LongInt);
 begin
-  GetPosition:=0;
+  Driver.WriteInteger(Value);
 end;
 
-
-Procedure TWriter.SetPosition(Value: Longint);
-
+procedure TWriter.WriteInteger(Value: Int64);
 begin
+  Driver.WriteInteger(Value);
 end;
 
-Procedure TWriter.WriteBinary(wd : TStreamProc);
-
+procedure TWriter.WriteListBegin;
 begin
+  Driver.BeginList;
 end;
 
-Procedure TWriter.WritePropName(const PropName: string);
-
+procedure TWriter.WriteListEnd;
 begin
-  WriteStr(PropName)
+  Driver.EndList;
 end;
 
-Procedure TWriter.DefineProperty(const Name: string;
-  rd : TReaderProc; wd : TWriterProc;
-  HasData: Boolean);
-
+procedure TWriter.WriteProperties(Instance: TPersistent);
+var
+  i, PropCount: Integer;
+  PropInfo: PPropInfo;
+  PropList: PPropList;
 begin
-end;
+  { First step: Write the properties given by the RTTI for Instance }
+  PropCount := GetTypeData(Instance.ClassInfo)^.PropCount;
+  if PropCount > 0 then
+  begin
+    GetMem(PropList, PropCount * SizeOf(PPropInfo));
+    try
+      GetPropInfos(Instance.ClassInfo, PropList);
+      for i := 0 to PropCount - 1 do
+      begin
+        PropInfo := PropList^[i];
+        if IsStoredProp(Instance, PropInfo) then
+          WriteProperty(Instance, PropInfo);
+      end;
+    finally
+      FreeMem(PropList);
+    end;
+  end;
+
+  { Second step: Give Instance the chance to write its own private data }
+  Instance.DefineProperties(Self);
+end;
+
+procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer);
+var
+  HasAncestor: Boolean;
+  PropType: PTypeInfo;
+  Value, DefValue: LongInt;
+  Ident: String;
+  IntToIdentFn: TIntToIdent;
+  FloatValue, DefFloatValue: Extended;
+  MethodValue: TMethod;
+  DefMethodCodeValue: Pointer;
+  StrValue, DefStrValue: String;
+  AncestorObj: TObject;
+  Component: TComponent;
+  ObjValue: TObject;
+  SavedAncestor: TPersistent;
+  SavedPropPath, Name: String;
+  Int64Value, DefInt64Value: Int64;
+begin
+
+  if (not Assigned(PPropInfo(PropInfo)^.SetProc)) or
+    (not Assigned(PPropInfo(PropInfo)^.GetProc)) then
+    exit;
+
+  { Check if the ancestor can be used }
+  HasAncestor := Assigned(Ancestor) and ((Instance = Root) or
+    (Instance.ClassType = Ancestor.ClassType));
+
+  PropType := PPropInfo(PropInfo)^.PropType;
+  case PropType^.Kind of
+    tkInteger, tkChar, tkEnumeration, tkSet:
+      begin
+        Value := GetOrdProp(Instance, PropInfo);
+        if HasAncestor then
+          DefValue := GetOrdProp(Ancestor, PropInfo)
+        else
+          DefValue := PPropInfo(PropInfo)^.Default;
+
+        if Value <> DefValue then
+        begin
+	  Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+          case PropType^.Kind of
+            tkInteger:
+      	      begin
+		// Check if this integer has a string identifier
+		IntToIdentFn := FindIntToIdent(PPropInfo(PropInfo)^.PropType);
+		if Assigned(IntToIdentFn) and IntToIdentFn(Value, Ident) then
+	          // Integer can be written a human-readable identifier
+	          WriteIdent(Ident)
+		else
+	          // Integer has to be written just as number
+	          WriteInteger(Value);
+	      end;
+    	    tkChar:
+              WriteChar(Chr(Value));
+    	    tkSet:
+	      Driver.WriteSet(Value, GetTypeData(PropType)^.CompType);
+    	    tkEnumeration:
+              WriteIdent(GetEnumName(PropType, Value));
+          end;
+	  Driver.EndProperty;
+	end;
+      end;
+    tkFloat:
+      begin
+        FloatValue := GetFloatProp(Instance, PropInfo);
+        if HasAncestor then
+          DefFloatValue := GetFloatProp(Ancestor, PropInfo)
+        else
+          DefFloatValue := 0;
+        if FloatValue <> DefFloatValue then
+        begin
+	  Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+          WriteFloat(FloatValue);
+	  Driver.EndProperty;
+        end;
+      end;
+    tkMethod:
+      begin
+        MethodValue := GetMethodProp(Instance, PropInfo);
+        if HasAncestor then
+          DefMethodCodeValue := GetMethodProp(Ancestor, PropInfo).Code
+        else
+          DefMethodCodeValue := nil;
 
+        if (MethodValue.Code <> DefMethodCodeValue) and
+          ((not Assigned(MethodValue.Code)) or
+          ((Length(FLookupRoot.MethodName(MethodValue.Code)) >= 0))) then
+        begin
+          Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+          if Assigned(MethodValue.Code) then
+            Driver.WriteMethodName(FLookupRoot.MethodName(MethodValue.Code))
+          else
+            Driver.WriteMethodName('');
+	  Driver.EndProperty;
+        end;
+      end;
+    tkSString, tkLString, tkAString, tkWString:
+      // !!!: Can we really handle WideStrings here?
+      begin
+        StrValue := GetStrProp(Instance, PropInfo);
+        if HasAncestor then
+          DefStrValue := GetStrProp(Ancestor, PropInfo)
+        else
+          SetLength(DefStrValue, 0);
 
-Procedure TWriter.DefineBinaryProperty(const Name: string;
-  rd, wd: TStreamProc;
-  HasData: Boolean);
+        if StrValue <> DefStrValue then
+        begin
+          Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+          WriteString(StrValue);
+	  Driver.EndProperty;
+        end;
+      end;
+  {!!!: tkVariant:}
+    tkClass:
+      begin
+        ObjValue := TObject(GetOrdProp(Instance, PropInfo));
+        if HasAncestor then
+        begin
+          AncestorObj := TObject(GetOrdProp(Ancestor, PropInfo));
+          if Assigned(AncestorObj) then
+            if Assigned(ObjValue) and
+              (TComponent(AncestorObj).Owner = FRootAncestor) and
+    	      (TComponent(ObjValue).Owner = Root) and
+              (UpperCase(TComponent(AncestorObj).Name) = UpperCase(TComponent(ObjValue).Name)) then
+              AncestorObj := ObjValue
+	    else
+	      AncestorObj := nil;
+	end else
+          AncestorObj := nil;
+
+	if (not Assigned(ObjValue)) and (ObjValue <> AncestorObj) then
+	begin
+          Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+	  Driver.WriteIdent('NIL');
+	  Driver.EndProperty;
+	end else if ObjValue.InheritsFrom(TPersistent) then
+          if ObjValue.InheritsFrom(TComponent) then
+          begin
+	    Component := TComponent(ObjValue);
+	    if ObjValue <> AncestorObj then
+    	    begin
+	      { Determine the correct name of the component this property contains }
+              if Component.Owner = LookupRoot then
+        	Name := Component.Name
+              else if Component = LookupRoot then
+        	Name := 'Owner'
+              else if Assigned(Component.Owner) and (Length(Component.Owner.Name) > 0)
+        	and (Length(Component.Name) > 0) then
+        	Name := Component.Owner.Name + '.' + Component.Name
+              else if Length(Component.Name) > 0 then
+        	Name := Component.Name + '.Owner'
+              else
+		SetLength(Name, 0);
+
+              if Length(Name) > 0 then
+              begin
+		Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+        	WriteIdent(Name);
+		Driver.EndProperty;
+              end;
+	    end;
+          end else if ObjValue.InheritsFrom(TCollection) then
+          begin
+    	    if (not HasAncestor) or (not CollectionsEqual(TCollection(ObjValue),
+              TCollection(GetOrdProp(Ancestor, PropInfo)))) then
+	    begin
+	      Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+              SavedPropPath := FPropPath;
+              try
+        	SetLength(FPropPath, 0);
+        	WriteCollection(TCollection(ObjValue));
+              finally
+        	FPropPath := SavedPropPath;
+		Driver.EndProperty;
+              end;
+    	    end;
+          end else
+          begin
+    	    SavedAncestor := Ancestor;
+    	    SavedPropPath := FPropPath;
+    	    try
+              FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.';
+              if HasAncestor then
+        	Ancestor := TPersistent(GetOrdProp(Ancestor, PropInfo));
+              WriteProperties(TPersistent(ObjValue));
+    	    finally
+              Ancestor := SavedAncestor;
+              FPropPath := SavedPropPath;
+    	    end;
+          end;
+      end;
+    tkInt64:
+      begin
+        Int64Value := GetInt64Prop(Instance, PropInfo);
+        if HasAncestor then
+          DefInt64Value := GetInt64Prop(Ancestor, PropInfo)
+        else
+          DefInt64Value := 0;
 
-begin
+        if Int64Value <> DefInt64Value then
+        begin
+          Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
+          WriteInteger(Int64Value);
+	  Driver.EndProperty;
+        end;
+      end;
+  end;
 end;
 
-Procedure TAbstractWriter.DefineProperty(const Name: string;
-  rd : TReaderProc; wd : TWriterProc;
-  HasData: Boolean);
-
+procedure TWriter.WriteRootComponent(ARoot: TComponent);
 begin
+  WriteDescendent(ARoot, nil);
 end;
 
-
-Procedure TAbstractWriter.DefineBinaryProperty(const Name: string;
-  rd, wd: TStreamProc;
-  HasData: Boolean);
-
+procedure TWriter.WriteString(const Value: String);
 begin
+  Driver.WriteString(Value);
 end;
 
+{!!!: procedure TWriter.WriteWideString(const Value: WideString);
+begin
+  Driver.WriteWideString(Value);
+end;}
+
+
 {
   $Log$
-  Revision 1.6  2000-01-07 01:24:33  peter
+  Revision 1.7  2000-06-29 16:29:23  sg
+  * Implemented streaming. Note: The writer driver interface is stable, but
+    the reader interface is not final yet!
+
+  Revision 1.6  2000/01/07 01:24:33  peter
     * updated copyright to 2000
 
   Revision 1.5  2000/01/06 01:20:33  peter