Custom streamer with the TStreamerInfo method

Dear ROOTers,

I need to write a custom streamer for class like this:

[...]

class test {
   int nch;
   short *ch;
   list<short> chlist; //!
   [...]
   void PackData();
};

where I have an additional transient member that “duplicate” the information, the STL list in this example, and a method, PackData(), to repack data in the C array when all the elements have been inserted in the correct position.
So I have to modify the automatic streamer to pack data just before writing on the file. As an explanation, if I use the old streamer system, I would add:

void test::Streamer(TBuffer &R__b)
{
   // Stream an object of class test.
   UInt_t R__s, R__c;
   if (R__b.IsReading()) {
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
      R__b >> nch;
      delete [] ch;
      ch = new short[nch];
      R__b.ReadFastArray(ch,nch);
      R__b.CheckByteCount(R__s, R__c, test::IsA());
   } else {
      PackData();   // <--------------------------- Added the method here!!!!
      R__c = R__b.WriteVersion(test::IsA(), kTRUE);
      R__b << nch;
      R__b.WriteFastArray(ch,nch);
      R__b.SetByteCount(R__c, kTRUE);
   }
}

I have not understood how to use the actual streamer system with the notations introduced in some 5.2x version (BTW at the moment I’m using ROOT 5.28)

I’m refering to this presentation
indico.cern.ch/getFile.py/access … nfId=35523
that I found in another post, and in particular I’m looking at the #pragma specifications that you can add in the _linkdef file.

  • How can I specify that I want to execute a method JUST BEFORE the standard write streamer? (after packing the data the automatic streamer would make his job…)
  • If I include the object in a Tree, will the customized streamer (and by conseguence the repacking) be executed at every TTree::Fill() or is it acting at the moment of the writing on file? (I’m still confused on such details)

Thanks a lot in advance,
Matteo

Hi,

Currently the schema evolution rules are not yet enable for writing. To be slight more modern, you could use:class test { int nch; short *ch; //[nch] list<short> chlist; //! [...] void PackData(); }; ... void test::Streamer(TBuffer &R__b) { // Stream an object of class test. if (R__b.IsReading()) { R__b.ReadClassBuffer(TBranchRef::Class(),this); } else { PackData(); // <--------------------------- Added the method here!!!! R__b.WriteClassBuffer(TBranchRef::Class(),this); } }

Cheers,
Philippe.

Dear Philippe,

I see that it is working where I Write() the object to a ROOT file, but if I embed the object in a TTree branch, the PackData() method is not called when I TTree::Fill()

if it is the intended behaviour, I have to call the method just before calling Fill(). Not too bad… but I’m wondering if a handle or workaround exist in order to hook some code just before filling a TTree

Hi,

This exact the need that the write rule will fill. At the moment you need to either explicitly call it before calling Fill or you need to make sure that the branch or sub-branch containing you object is not split.

Cheers,
Philippe.