StreamerInfo version for std::string and std::vector<T=builtin>

hi there,

I am looking at a file with the following data:

$> root-ls -sinfos ./o.root 
=== [./o.root] ===
version: 61600
streamer-infos:
 StreamerInfo for "Event" version=1 title=""
  TString                Beg       offset=  0 type= 65 size= 24  
  short                  I16       offset=  0 type=  2 size=  2  
  int                    I32       offset=  0 type=  3 size=  4  
  long                   I64       offset=  0 type=  4 size=  8  
  unsigned short         U16       offset=  0 type= 12 size=  2  
  unsigned int           U32       offset=  0 type= 13 size=  4  
  unsigned long          U64       offset=  0 type= 14 size=  8  
  float                  F32       offset=  0 type=  5 size=  4  
  double                 F64       offset=  0 type=  8 size=  8  
  TString                Str       offset=  0 type= 65 size= 24  
  P3                     P3        offset=  0 type= 62 size= 24  
  short                  ArrayI16  offset=  0 type= 22 size= 20  
  int                    ArrayI32  offset=  0 type= 23 size= 40  
  long                   ArrayI64  offset=  0 type= 24 size= 80  
  unsigned short         ArrayU16  offset=  0 type= 32 size= 20  
  unsigned int           ArrayU32  offset=  0 type= 33 size= 40  
  unsigned long          ArrayU64  offset=  0 type= 34 size= 80  
  float                  ArrayF32  offset=  0 type= 25 size= 40  
  double                 ArrayF64  offset=  0 type= 28 size= 80  
  int                    N         offset=  0 type=  6 size=  4  
  short*                 SliceI16  offset=  0 type= 42 size=  2  [N]
  int*                   SliceI32  offset=  0 type= 43 size=  4  [N]
  long*                  SliceI64  offset=  0 type= 44 size=  8  [N]
  unsigned short*        SliceU16  offset=  0 type= 52 size=  2  [N]
  unsigned int*          SliceU32  offset=  0 type= 53 size=  4  [N]
  unsigned long*         SliceU64  offset=  0 type= 54 size=  8  [N]
  float*                 SliceF32  offset=  0 type= 45 size=  4  [N]
  double*                SliceF64  offset=  0 type= 48 size=  8  [N]
  string                 StdStr    offset=  0 type=500 size= 32  
  vector<short>          StlVecI16 offset=  0 type=500 size= 24  
  vector<int>            StlVecI32 offset=  0 type=500 size= 24  
  vector<long>           StlVecI64 offset=  0 type=500 size= 24  
  vector<unsigned short> StlVecU16 offset=  0 type=500 size= 24  
  vector<unsigned int>   StlVecU32 offset=  0 type=500 size= 24  
  vector<unsigned long>  StlVecU64 offset=  0 type=500 size= 24  
  vector<float>          StlVecF32 offset=  0 type=500 size= 24  
  vector<double>         StlVecF64 offset=  0 type=500 size= 24  
  vector<string>         StlVecStr offset=  0 type=500 size= 24  
  TString                End       offset=  0 type= 65 size= 24  
 StreamerInfo for "P3" version=1 title=""
  int    Px      offset=  0 type=  3 size=  4  
  double Py      offset=  0 type=  8 size=  8  
  int    Pz      offset=  0 type=  3 size=  4  
---
Event   evt     object title (cycle=1)

inspecting it further, I see that the StreamerInfo version for StlVecXXX and StlStr are:

vers[string]= 9
vers[vector<short>]= 9
vers[vector<int>]= 9
vers[vector<long>]= 9
vers[vector<unsigned short>]= 9
vers[vector<unsigned int>]= 9
vers[vector<unsigned long>]= 9
vers[vector<float>]= 9
vers[vector<double>]= 9
vers[vector<string>]= 9

where is this information stored in ROOT? (not the ROOT file, obviously I managed to extract it from that file :P)
and under which conditions is the version subject to be bumped?
are all the versions of all STL containers bumped together? (std::string, std::vector, std::set, std::map, …)

thanks,
-s


ROOT Version: 6.16/00
Platform: Linux/amd64
Compiler: Not Provided


bonus question: when I add a std::vector< ::P3 > member to that Event struct like so:

$> root-ls -sinfos ./o.root
[...]
  vector<P3>             StlVecP3s offset=  0 type=500 size= 24
  TString                End       offset=  0 type= 65 size= 24
 StreamerInfo for "P3" version=1 title=""
  int    Px      offset=  0 type=  3 size=  4
  double Py      offset=  0 type=  8 size=  8
  int    Pz      offset=  0 type=  3 size=  4
[...]

I see the following bytes, just before reading the data for that member:

00000000  40 00 00 2c 40 09 00 00  64 04 49 17 00 00 00 02  |@..,@...d.I.....|
00000010  00 00 00 00 00 00 00 01  40 00 00 00 00 00 00 00  |........@.......|
00000020  40 00 00 00 00 00 00 00  00 00 00 03 00 00 00 03  |@...............|
00000030  07 65 6e 64 2d 30 30 32                           |.end-002|

I understand the last 00 00 00 02 from the first line: that’s the length of the vector.
then:

  • 00 00 00 00 00 00 00 01: the 2 values for Px (int32_t)
  • 40 00 00 00 00 00 00 00: the 2 values for Py (double)
  • 00 00 00 03 00 00 00 03: the 2 values for Pz (int32_t)
    and finally the value for the End data member (07 65 6e 64 2d 30 30 32).

but I have trouble interpreting the first bytes…
40 00 00 2c seems to be the usual “version, bytecount” except that 40 09 is a bit too much for a version: I suspect the proper version should be 9 instead of 16393. is there a mask to apply or test for?
then, what are the remaining 6 bytes 00 00 64 04 49 17 ? an index into something to get a reference to the streamer of P3 ?

progress: 00 00 64 04 49 17 seems to be a uint16_t (a version) + a uint32_t (the checksum of the streamer for P3.)

are std::vector<T> (with T not a builtin) always written like that? (with a std::vector<TObjString> it seems I only get the uint16_t version, not the checksum.)

Just in the bytestream (same place as other class version, with an extra flag for recording whether the content has been stream member-wise or object-wise).

Yes (In first approximation the file format for all collection is the same (with map<T,Q> being the same as vector<pair<P,Q>>)

is there a mask to apply or test for?

Yes :slight_smile:

TStreamerInfoReadBuffer.cxx:1216:

               UInt_t start, count;
               Version_t vers = b.ReadVersion(&start, &count, cle);

               if ( vers & TBufferFile::kStreamedMemberWise ) {
                  // Collection was saved member-wise
                  vers &= ~( TBufferFile::kStreamedMemberWise );
                  ....
              } else {
                 // Collection was saved object-wise
              }

thanks, I was confused because the mask value looked a lot like kByteCountVMask

sorry, I wasn’t very articulate. my issue is that just by reading the ROOT file, I don’t seem to be able to locate a StreamerInfo for, e.g. ,"vector<double>" (the groot equivalent of TFile::GetStreamerInfoList() only returns the StreamerInfos for Event and P3.)
but I realize now that the version 9 isn’t the version of the class being written out but, actually, the version of TStreamerInfo :slight_smile:

thanks.

Yes, the ‘streamerInfo’ for the STL collection does not contains any interesting/persistent information so we don’t write them out. The version ‘9’ is really a descriptor of the version number of the STL on-disk layout (and since change to such are usually change to TStreamerInfo, I re-used the StreamerInfo version number).

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.