Recent

Author Topic: is it possible to stream TObjectList?  (Read 4428 times)

Michael Collier

  • Sr. Member
  • ****
  • Posts: 301
is it possible to stream TObjectList?
« on: April 22, 2018, 09:32:06 pm »
Is possible to stream the objects held within TObjectList?

I have a class structure as follows..

A base class from which all other classes are derived
Code: Pascal  [Select][+][-]
  1.   t_cmd_base = class ( TComponent )
  2.   end;

A list class that is derived from the base class , but contains TObjectList
Code: Pascal  [Select][+][-]
  1.   t_cmd_list_base = class (t_cmd_base)
  2.   private
  3.     f_object_list : TObjectList ;
  4.   protected
  5.     procedure DefineProperties(Filer: TFiler); override;
  6.     procedure do_read(Reader: TReader);
  7.     procedure do_write(Writer: TWriter);
  8.   public
  9.     // create & free object list ----
  10.     constructor Create(AOwner: TComponent); override;
  11.     destructor  Destroy; override;
  12.     // ------------------------------
  13.   end;
  14.  

OK, so any class I define comes from t_cmd_base, and it can have as its property a t_cmd_list_base. The t_cmd_list_base always holds items that inherit from the t_cmd_base.
The idea being that a "tree structure" can be populated from these classes.

I'd like to stream this structure using WriteComponentAsTextToStream ..

i.e.
Code: Pascal  [Select][+][-]
  1. my_cmd_base.WriteComponentAsTextToStream

To ensure the list held within my_cmd_base is streamed I have included GetChildren in its definition
Code: Pascal  [Select][+][-]
  1. procedure t_cmd_c.GetChildren(Proc: TGetChildProc; Root: TComponent);
  2. begin
  3.   inherited GetChildren(Proc, Root);
  4.   Proc(f_cmd_list);
  5. end;
  6.  

To handle the list, I implemented DefineProperties method, and created 2 routines to read/write the individual items in the list..

Here is code to write the tobjectlist items to the stream, as you can see I have commented out the code that writes the actual component ( because it gives stream read error), and left the code that simply streams the classname..

Code: Pascal  [Select][+][-]
  1. procedure t_cmd_list_base.do_write(Writer: TWriter);
  2. var i : integer ;
  3. begin
  4.   with Writer do begin
  5.     WriteListBegin;
  6.     WriteInteger(f_object_list.Count);
  7.     for i := 0 to f_object_list.Count-1 do begin
  8.       WriteString( f_object_list[i].ClassName );
  9.       //WriteComponent( TComponent(f_object_list[i]) );
  10.     end;
  11.     WriteListEnd;
  12.   end;
  13. end;

Here is a sample of the stream as text..

object t_unit
  dbg = 'copy'
  object t_cmd_c
    dbg = 'dbg'
    object t_cmd_list
      t_cmd_list = (
        2
        't_cmd_a'
        't_cmd_b'
      )
    end
  end
end

Am I an the right road to being able to do this? Ideally I'd like to stream an object and for it to recursively stream itself and and list classes it holds...

I tried a few other methods using TCollection, but found it didn't handle the range of classes that I need (it seemed to handle only 1 class of object).

Thanks in advance..

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: is it possible to stream TObjectList?
« Reply #1 on: April 23, 2018, 04:27:16 am »
You want to write a component to stream. Someone hopefully pops in and shows exactly how to do that. I have done something similar, saving object data to streams, field by field. This is more work of course. Anyway, lets say you want to save an instance of TMyObject this way. Add a SaveToStream procedure to TMyObject and iterate through the list of objects, calling SaveToStream for each object in the list. In the example below there is only one field in the class. If there are more fields, they have to be saved in the same manner.

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyObject = class
  3.   public
  4.     Name: string;
  5.     procedure SaveToStream(AStream: TStream);
  6.     procedure LoadFromStream(AStream: TStream);
  7.   end;
  8.  
  9. procedure TMyObject.SaveToStream(AStream: TStream);
  10. var
  11.   Len: Integer;
  12. begin
  13.   Len := Length(Name);
  14.   AStream.Write(Len, SizeOf(Len));
  15.   AStream.Write(PChar(Name)^, Len);
  16. end;
  17.  
  18. procedure TMyObject.LoadFromStream(AStream: TStream);
  19. var
  20.   Len: Integer;
  21. begin
  22.   AStream.Read(Len, SizeOf(Len));
  23.   SetString(Name, PChar(nil), Len);
  24.   AStream.Read(PChar(Name)^, Len);
  25. end;
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

Michael Collier

  • Sr. Member
  • ****
  • Posts: 301
Re: is it possible to stream TObjectList?
« Reply #2 on: April 23, 2018, 05:03:25 pm »
Thanks, I can write to streams if I'm forced to but I'd like to use the existing streaming mechanism, specifically the WriteComponent() procedure, if possible. As you can see in my example I have commented that line out because it gives stream read error when I use it, I can write any other stream data though ( string, integer etc). Maybe the WriteComponent should not be used, it doesn't say anything here https://www.freepascal.org/docs-html/rtl/classes/twriter.writecomponent.html

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: is it possible to stream TObjectList?
« Reply #3 on: April 23, 2018, 05:49:06 pm »
Here's a nice article https://www.codeproject.com/articles/1060345/dfm-serialization-in-depth
Also applies to Lazarus/FPC
Specialize a type, not a var.

mse

  • Sr. Member
  • ****
  • Posts: 286
Re: is it possible to stream TObjectList?
« Reply #4 on: April 23, 2018, 06:59:41 pm »
Is possible to stream the objects held within TObjectList?
Normally a TCollection descendant or a specialized "parent" component must be used as container in order to use component array streaming.
In MSEgui there is also TPersistentArrayProp.

BeniBela

  • Hero Member
  • *****
  • Posts: 905
    • homepage
Re: is it possible to stream TObjectList?
« Reply #5 on: April 23, 2018, 07:18:51 pm »
Is possible to stream the objects held within TObjectList?


Depends. Are those objects videos?

Michael Collier

  • Sr. Member
  • ****
  • Posts: 301
Re: is it possible to stream TObjectList?
« Reply #6 on: April 23, 2018, 07:34:56 pm »
Depends. Are those objects videos?

No - just ordinary TComponents,
http://wiki.freepascal.org/Streaming_components
maybe you are thinking of streaming in terms of sound/vision..

PatBayford

  • Full Member
  • ***
  • Posts: 125
Re: is it possible to stream TObjectList?
« Reply #7 on: April 24, 2018, 12:12:21 am »
Two thoughts -
1) It is possible to write ANY object to a stream, but you have do do ALL the donkey work yourself - the Filer/Reader/Writer concept inherited from Delphi is so poorly documented as to be unusable for mere mortals. However, several Delphi add-ons have addressed some of these issues, and should be portable to FPC/Lazarus.
2) Your assumption about TCollection, and all it's descendants - they are designed to hold just one type of object per collection. However, if you can accept that limitation, it is possible to achieve your objective.
Lazarus 1.8.0 FPC 3.0.2 SVN 56594 Windows 10 64bit (i386-win32-win32/win64)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: is it possible to stream TObjectList?
« Reply #8 on: April 24, 2018, 12:47:05 am »
Is possible to stream the objects held within TObjectList?

I have a class structure as follows..


It is possible you just need to take in to account 2 things,
1) there is no single line to save a object list you need to provide the loop to save them one by one.
2) keep track of how many objects you need to read.
in short save the objectlist.count first then save one by one your components.

there is a good example of this method in the simplegraph component. If you can't find it post a complete sample and I'll add it in for you.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Michael Collier

  • Sr. Member
  • ****
  • Posts: 301
Re: is it possible to stream TObjectList?
« Reply #9 on: April 24, 2018, 04:54:04 pm »
there is a good example of this method in the simplegraph component. If you can't find it post a complete sample and I'll add it in for you.

Thanks, I have attached an example project laz_example.zip

I don't seem to have simplegraph on my hard drive, it would be good to see how you did it because I am using some workarounds that I'd like to fix.. They are commented in the example code.

The example I have attached creates a hierarchy 2 levels deep, then uses built in streaming routines to make a copy of the hierarchy and dump its contents as text, see screenshot.

I hope this can be made to work because my existing (non streaming) method of copy/paste requires a lot of code that this streaming method may not require.. :-)





taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: is it possible to stream TObjectList?
« Reply #10 on: April 26, 2018, 04:00:30 pm »
there is a good example of this method in the simplegraph component. If you can't find it post a complete sample and I'll add it in for you.

Thanks, I have attached an example project laz_example.zip

I don't seem to have simplegraph on my hard drive, it would be good to see how you did it because I am using some workarounds that I'd like to fix.. They are commented in the example code.

The example I have attached creates a hierarchy 2 levels deep, then uses built in streaming routines to make a copy of the hierarchy and dump its contents as text, see screenshot.

I hope this can be made to work because my existing (non streaming) method of copy/paste requires a lot of code that this streaming method may not require.. :-)
sorry mate I just show the sample I'll work on it later tonight and post something tomorrow or the the day after tomorrow.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Michael Collier

  • Sr. Member
  • ****
  • Posts: 301
Re: is it possible to stream TObjectList?
« Reply #11 on: April 26, 2018, 06:20:27 pm »
Thanks taazz.. much appreciated..

 

TinyPortal © 2005-2018