Re: [ROOT] semi custom streamers

From: Rene Brun (Rene.Brun@cern.ch)
Date: Fri Aug 10 2001 - 21:46:38 MEST


Hi Andre,
You do not have to modify rootcint to get what you want. Proceed as
follow:
 - in LinkDef.h select option -
   #pragma link C++ class MyClass-;
 - In your member declaration use the "!" to declare it non persistent
   vector<vector<Double_t> >  myVector;   //!

 - The default Streamer function for MyClass is:

void MyClass::Streamer(TBuffer &R__b)
{
   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      MyClass::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);      
   } else {
      MyClass::Class()->WriteBuffer(R__b,this);
   }
}

 - Extend this Streamer function Streamer function with the code
   necessary to Stream the vector


void MyClass::Streamer(TBuffer &R__b)
{
   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      MyClass::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);  
      //add code to read the vector    
   } else {
      MyClass::Class()->WriteBuffer(R__b,this);
      //add the code to write the vector
   }
}


With STL, one can build quickly very complex constructs. Currently
the automatic I/O supports only one level of arguments.
Things such as <vector<vector<basic type > > could be added to the STL 
ROOT parser.

Rene Brun

On Fri, 10 Aug 2001, Andre Holzner wrote:

> Dear rooters,
> 
> I'm facing the problem that I want to have a 
> data member vector<vector<Double_t> >
> in one of my classes which I'd like to write to a root file.
> 
> While I could write my own streamer from scratch or
> start from the generated streamer, 
> I'd like to profit from rootcint's ability to generate 
> the bulk of the streamer code for me (e.g. also when
> I add new fields to the class) 
> and I'd like only to implement the streaming for 
> these 'problematic' data types.
> 
> Looking at an example streamer:
> 
> void MyClass::Streamer(TBuffer &R__b)
> {
>    // Stream an object of class MyClass.
>  
>    UInt_t R__s, R__c;
>    if (R__b.IsReading()) {
>       Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
>       TNamed::Streamer(R__b);
>       R__b >> a;
>       R__b >> b;
>       ...
>       R__b.CheckByteCount(R__s, R__c, MyClass::IsA());
>    } else {
>       R__c = R__b.WriteVersion(MyClass::IsA(), kTRUE);
>       TNamed::Streamer(R__b);
>       R__b << a;
>       R__b << b;
>       ...
>       R__b.SetByteCount(R__c, kTRUE);
>    }
> }
> 
> it looks to me that it should be possible e.g. 
> to call my own function after calling the automatically
> streamer method. This own function streams then out
> the additional fields. The same could be done when reading
> an object back from a TBuffer.
> 
> So my questions:
> 
>  - What do you think about giving rootcint another
>    option to call the Streamer differently ?
>    (in that case, one could implement a method
>    MyClass::Streamer which first calls
>    MyClass::GeneratedStreamer and then handles the
>    other data fields).  [I'd volunteer to try to
>    implement such an option into rootcint]
> 
>  - What about giving TObject an additional virtual
>    method PostStreamer(TBuffer &) which is called
>    at the end of Streamer() ?
>    (one might be concerned about slightly lower 
>    performance..)
> 
> Or is it already possible to implement a 'private
> additional streamer' ? (from the Root User's guide
> p.193, this is not clear to me)
> 
> 
> best regards,
> 
> André
> -- 
> ------------------+----------------------------------
> Andre Holzner     | +41 22 76 76750 
> Bureau 32 2-C13   | Building 32     
> CERN              | Office 2-C13    
> CH-1211 Geneve 23 | http://wwweth.cern.ch/~holzner/
> 



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:57 MET