Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RFieldVisitor.hxx
Go to the documentation of this file.
1 /// \file ROOT/RFieldVisitor.hxx
2 /// \ingroup NTuple ROOT7
3 /// \author Simon Leisibach <simon.satoshi.rene.leisibach@cern.ch>
4 /// \date 2019-06-11
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #ifndef ROOT7_RFieldVisitor
17 #define ROOT7_RFieldVisitor
18 
19 #include <algorithm>
20 #include <iostream>
21 #include <sstream>
22 #include <string>
23 #include <vector>
24 
25 namespace ROOT {
26 namespace Experimental {
27 class RFieldRoot;
28 namespace Detail {
29 class RFieldBase;
30 
31 
32 // clang-format off
33 /**
34 \class ROOT::Experimental::Detail::RNTupleVisitor
35 \ingroup NTuple
36 \brief Abstract base class for classes implementing the visitor design pattern.
37 
38  RNTupleVisitor::VisitField() is invoked by RFieldBase::AcceptVisitor(). VisitField() is inherited for instance by the RPrintVisitor class. The RFieldBase Class and classes which inherit from it will be visited.
39 */
40 // clang-format on
41 class RNTupleVisitor {
42 public:
43  virtual void VisitField(const Detail::RFieldBase &field, int level) = 0;
44  virtual void VisitRootField(const RFieldRoot &field, int level) = 0;
45 };
46 } // namespace Detail
47 // clang-format off
48 /**
49 \class ROOT::Experimental::RPrepareVisitor
50 \ingroup NTuple
51 \brief Visitor used for a prepare run to collect information needed by another visitor class.
52 
53  Currently used for RPrintVisitor in RNTupleReader::Print() to collect information about levels, maximal depth etc.
54 */
55 // clang-format on
56 class RPrepareVisitor: public Detail::RNTupleVisitor {
57 private:
58  int fDeepestLevel;
59  int fNumFields;
60 public:
61  RPrepareVisitor(int deepestLevel=0, int numFields=0): fDeepestLevel{deepestLevel}, fNumFields{numFields} { }
62  void VisitField(const Detail::RFieldBase &field, int level) final;
63  void VisitRootField(const RFieldRoot &/*field*/, int /*level*/) final { }
64  int GetDeepestLevel() const {return fDeepestLevel;}
65  int GetNumFields() const {return fNumFields;}
66 };
67 
68 // clang-format off
69 /**
70 \class ROOT::Experimental::RPrintVisitor
71 \ingroup NTuple
72 \brief Contains settings for printing and prints a summary of an RField instance.
73 
74  Instances of this class are currently only invoked by RNTupleReader::Print() -> RFieldBase::AcceptVisitor()
75 */
76 // clang-format on
77 class RPrintVisitor : public Detail::RNTupleVisitor {
78 private:
79  /// Where to write the printout to
80  std::ostream &fOutput;
81  char fFrameSymbol;
82  /// Indicates maximal number of allowed characters per line
83  int fWidth;
84  int fDeepestLevel;
85  int fNumFields;
86  int fAvailableSpaceKeyString;
87  int fAvailableSpaceValueString;
88  /// Keeps track when | is used for the tree-like structure.
89  // E.g. in
90  // * | | |__Field
91  // * | |__Field 2
92  // * | |__Field <- '|' in position 1, but no '|' in position 2
93  // * |__Field 2.4
94  // * |__Field 2 <- no '|' in position 1
95  // * |__Field
96  std::vector<bool> fFlagForVerticalLines;
97  /// KeyString refers to the left side containing the word "Field" and its hierarchial order
98  std::string MakeKeyString(const Detail::RFieldBase &field, int level);
99  /// ValueString refers to the right side containing the type and name
100  std::string MakeValueString(const Detail::RFieldBase &field);
101 public:
102  RPrintVisitor(std::ostream &out = std::cout, char fillSymbol = '*', int width = 80, int deepestLevel = 1, int numFields = 1)
103  : fOutput{out}, fFrameSymbol{fillSymbol}, fWidth{width}, fDeepestLevel{deepestLevel}, fNumFields{numFields}
104  {SetAvailableSpaceForStrings();}
105  /// Prints summary of Field
106  void VisitField(const Detail::RFieldBase &field, int level) final;
107  void VisitRootField(const RFieldRoot &/*field*/, int /*level*/) final { };
108  void SetFrameSymbol(char s) {fFrameSymbol = s;}
109  void SetWidth(int w) {fWidth = w;}
110  void SetDeepestLevel(int d);
111  void SetNumFields(int n);
112  /// Computes how many characters should be placed between the frame symbol and ':' for left and right side of ':' for visually pleasing output.
113  // E.g.
114  // * Field 1 : vpx (std::vector<float>) *
115  // * |__Field 1.1 : vpx/vpx (float) *
116  // int fAvailableSpaceKeyString (num characters on left side between "* " and " : ")
117  // deepestlevel here is 2 (1.1 is deepest and has 2 numbers).
118  // For every additional level an additional "|_" and ".1" (4 characters) is added, so the number of required additional characters is 4 * fDeepestLevel.
119  // For level 1, 8 characters are required ("Field 1 "), so an additional + 4 is added.
120  // To account for cases where the total number of fields is not a single digit number and more space is required to output big numbers, fNumFields is incorporated into the calculation.
121  // To make sure that there is still enough space for the right side of " : ", an std::min comparision with fWidth - 15 is done.
122  // int fAvailableSpaceValueString(num characters on right side between " : " and '*')
123  // The 6 subtracted characters are "* " (2) in the beginning, " : " (3) and '*' (1) on the far right.
124  void SetAvailableSpaceForStrings() {
125  fAvailableSpaceKeyString = std::min(4 * fDeepestLevel + 4 + static_cast<int>(std::to_string(fNumFields).size()), fWidth - 15);
126  fAvailableSpaceValueString = fWidth - 6 - fAvailableSpaceKeyString;
127  }
128 };
129 
130 
131 // clang-format off
132 /**
133 \class ROOT::Experimental::RNTupleFormatter
134 \ingroup NTuple
135 \brief Contains helper functions for RNTupleReader::PrintInfo() and RPrintVisitor::VisitField()
136 
137  The functions in this class format strings which are displayed when RNTupleReader::PrinfInfo() is called.
138 */
139 // clang-format on
140 class RNTupleFormatter {
141 public:
142  static std::string FitString(const std::string &str, int availableSpace);
143  static std::string HierarchialFieldOrder(const Detail::RFieldBase &field);
144 };
145 
146 } // namespace Experimental
147 } // namespace ROOT
148 
149 #endif