Logo ROOT  
Reference Guide
RDisplay.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, Danilo Piparo CERN, Massimo Tumolo Politecnico di Torino 08/2018
2
3/*************************************************************************
4 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#ifndef ROOT_RDFDISPLAYER
12#define ROOT_RDFDISPLAYER
13
14#include "ROOT/RDF/Utils.hxx"
15#include "ROOT/TypeTraits.hxx"
16#include "TClassEdit.h"
17
18#include <vector>
19#include <string>
20#include <iostream>
21#include <sstream>
22
23namespace ROOT {
24namespace Internal {
25namespace RDF {
26
27template<typename T>
29std::string PrettyPrintAddr(const void *const addr);
30
32private:
33 enum class PrintingAction { ToBePrinted, ToBeIgnored, ToBeDotted };
34 std::string fRepresentation;
36
37public:
38 RDisplayElement(const std::string &representation);
40 void SetPrint();
41 void SetIgnore();
42 void SetDots();
43 bool IsPrint() const;
44 bool IsIgnore() const;
45 bool IsDot() const;
46 const std::string &GetRepresentation() const;
47 bool IsEmpty() const;
48};
49} // namespace RDF
50} // namespace Internal
51
52namespace RDF {
53
54/**
55 * \class ROOT::RDF::RDisplay
56 * \ingroup dataframe
57 * This class is the textual representation of the content of a columnar dataset.
58 *
59 * This class is provided to the user, and it can be used to print on screen
60 * the entries of the dataset requested through the Display action in a compact
61 * representation or to return the full representation of the events as a string.
62 * In order to apply proper formatting the content is buffered in memory as strings.
63 */
64class RDisplay {
65 template<typename T>
67private:
68 using VecStr_t = std::vector<std::string>;
70 static constexpr char fgSeparator = ' '; ///< Spacing used to align the table entries
71 static constexpr unsigned fgMaxWidth = 80;
72
73 VecStr_t fTypes; ///< This attribute stores the type of each column. It is needed by the interpreter to print it.
74 std::vector<bool> fIsCollection; ///< True if the column contains a collection. Collections are treated differently
75 ///< during the printing.
76 std::vector<std::vector<DElement_t>> fTable; ///< String representation of the data to be printed.
77 std::vector<unsigned short> fWidths; ///< Tracks the maximum width of each column, based on the largest element.
78
79 VecStr_t fRepresentations; ///< Used by the JITted code to store the string representation of the data.
80 std::vector<VecStr_t> fCollectionsRepresentations; ///< Used by the JITted code to store the string representation of
81 ///< the data in case of collection. Each row corresponds to a
82 ///< column, each column to a value of the collection.
83
84 size_t fNColumns; ///< Number of columns to be printed
85
86 size_t fCurrentRow = 0; ///< Row that is being filled
87 size_t fNextRow = 1; ///< Next row to be filled.
88 size_t fCurrentColumn = 0; ///< Column that is being filled.
89
90 size_t fEntries; ///< Number of events to process for each column (i.e. number of rows).
91
92 ////////////////////////////////////////////////////////////////////////////
93 /// Appends a cling::printValue call to the stringstream.
94 /// \tparam T the type of the event to convert
95 /// \param[in] stream Where the conversion function call will be chained.
96 /// \param[in] element The event to convert to its string representation
97 /// \param[in] index To which column the event belongs to
98 /// \return false, the event is not a collection
99 template <typename T, typename std::enable_if<!ROOT::Internal::RDF::IsDataContainer<T>::value, int>::type = 0>
100 bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
101 {
102 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fRepresentations[index]))
103 << ") = cling::printValue((" << fTypes[index] << "*)" << ROOT::Internal::RDF::PrettyPrintAddr(&element) << ");";
104 return false;
105 }
106
107 ////////////////////////////////////////////////////////////////////////////
108 /// Appends collection.size() cling::printValue calls to the stringstream.
109 /// \tparam T the type of the event to convert
110 /// \param[in] stream Where the conversion function call will be chained.
111 /// \param[in] collection The event to convert to its string representation
112 /// \param[in] index To which column the event belongs to
113 /// \return true, the event is a collection
114 /// This function chains a sequence of call to cling::printValue, one for each element of the collection.
115 template <typename T, typename std::enable_if<ROOT::Internal::RDF::IsDataContainer<T>::value, int>::type = 0>
116 bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
117 {
118 size_t collectionSize = std::distance(std::begin(collection), std::end(collection));
119 // Prepare the row to contain as many elements as the number of elements in the collection
120 fCollectionsRepresentations[index] = VecStr_t(collectionSize);
121
122 // Use GetSplit to get the encapsulated type of the collection. For example, GetSplit on
123 // std::vector<std::vector<int>> will return std::vector<int>
125 int nestedLoc = 0;
126 TClassEdit::GetSplit(fTypes[index].c_str(), output, nestedLoc);
127
128 // For each element, append a call and feed the proper type returned by GetSplit
129 for (size_t i = 0; i < collectionSize; ++i) {
130 stream << "*((std::string*)" << ROOT::Internal::RDF::PrettyPrintAddr(&(fCollectionsRepresentations[index][i]))
131 << ") = cling::printValue((" << output[1] << "*)"
132 << ROOT::Internal::RDF::PrettyPrintAddr(&(collection[i])) << ");";
133 }
134 return true;
135 }
136
137 ////////////////////////////////////////////////////////////////////////////
138 /// AddInterpreterString overload for arrays of chars.
139 ///
140 /// \param[in] charArr The character array to convert to string representation
141 /// \param[in] index To which column the event belongs
142 /// \return false, the event is not a collection
143 ///
144 /// This specialization for arrays of characters skips the cling::printValue
145 /// (i.e. appends nothing to the stream) and directly writes to fRepresentations the
146 /// string representation of the array of chars.
147 bool AddInterpreterString(std::stringstream &, ROOT::RVec<char> &charArr, const int &index)
148 {
149 // if null-terminated char array, do not copy the null terminator into std::string, it makes columns misaligned.
150 const auto length = charArr[charArr.size()-1] == '\0' ? charArr.size() - 1 : charArr.size();
151 const std::string arrAsStr(charArr.data(), length); // also works for non-null-terminated strings
152 fRepresentations[index] = arrAsStr;
153 return false; // do not treat this as a collection
154 }
155
156 ////////////////////////////////////////////////////////////////////////////
157 /// AddInterpreterString overload for arrays of booleans.
158 ///
159 /// \param[in] boolArr The bool array to convert to string representation
160 /// \param[in] index To which column the event belongs
161 /// \return true, the event is a collection
162 ///
163 /// This specialization for arrays of booleans skips the cling::printValue
164 /// (i.e. appends nothing to the stream) and directly writes to fCollectionsRepresentations the
165 /// string representation of the array of chars.
166 bool AddInterpreterString(std::stringstream &, ROOT::RVec<bool> &boolArr, const int &index)
167 {
168 fCollectionsRepresentations[index].reserve(boolArr.size());
169 for (bool b : boolArr)
170 fCollectionsRepresentations[index].push_back(b ? "true" : "false");
171
172 return true; // treat this as a collection
173 }
174
175
176 ////////////////////////////////////////////////////////////////////////////
177 /// Adds a single element to the next slot in the table
178 void AddToRow(const std::string &stringEle);
179
180 ////////////////////////////////////////////////////////////////////////////
181 /// Adds a collection to the table
182 ///
183 /// Starting from the slot, the elements are added one under the other, each
184 /// one using a single cell of an entire row
185 void AddCollectionToRow(const VecStr_t &collection);
186
187 ////////////////////////////////////////////////////////////////////////////
188 /// Moves to the next cell
189 ///
190 /// Moves to the next cell, and if the row is full moves to the next row.
191 void MovePosition();
192
193 ////////////////////////////////////////////////////////////////////////////
194 /// Get the number of columns that do NOT fit in the characters limit
195 size_t GetNColumnsToShorten() const;
196
197 ////////////////////////////////////////////////////////////////////////////
198 /// Adds a row of events to the table
199 template <typename... Columns>
200 void AddRow(Columns... columns)
201 {
202 std::stringstream calc; // JITted code
203 int columnIndex = 0;
204 // Unwrapping the parameters to create the JITted code.
205 fIsCollection = {AddInterpreterString(calc, columns, columnIndex++)...};
206
207 // Let cling::printValue handle the conversion. This can be done only through cling-compiled code.
208 const std::string toJit = calc.str();
209 if (!toJit.empty())
210 ROOT::Internal::RDF::InterpreterCalc(calc.str(), "Display");
211
212 // Populate the fTable using the results of the JITted code.
213 for (size_t i = 0; i < fNColumns; ++i) {
214 if (fIsCollection[i]) {
216 } else {
218 }
219 }
220 // This row has been parsed
221 fEntries--;
222 }
223
224 ////////////////////////////////////////////////////////////////////////////
225 /// If the number of required rows has been parsed, returns false.
226 bool HasNext() { return fEntries > 0; }
227
228 void EnsureCurrentColumnWidth(size_t w);
229
230public:
231 ////////////////////////////////////////////////////////////////////////////
232 /// Creates an RDisplay to print the event values
233 /// \param[in] columnNames Columns to print
234 /// \param[in] types The type of each column
235 /// \param[in] entries How many events per column (row) must be processed.
236 RDisplay(const VecStr_t &columnNames, const VecStr_t &types, int entries);
237
238 ////////////////////////////////////////////////////////////////////////////
239 /// Prints the representation to the standard output
240 ///
241 /// Collections are shortened to the first and last element. The overall width
242 /// is shortened to a fixed number of columns that should fit the screen width.
243 void Print() const;
244
245 ////////////////////////////////////////////////////////////////////////////
246 /// Returns the representation as a string
247 std::string AsString() const;
248};
249
250} // namespace RDF
251} // namespace ROOT
252
253#endif
#define b(i)
Definition: RSha256.hxx:100
int type
Definition: TGX11.cxx:120
Helper class to let Display print compact tabular representations of the events.
Definition: RDisplay.hxx:31
bool IsIgnore() const
Return if the cell has to be skipped.
Definition: RDFDisplay.cxx:67
bool IsDot() const
Return if the cell has to be replaced by "...".
Definition: RDFDisplay.cxx:74
const std::string & GetRepresentation() const
Definition: RDFDisplay.cxx:79
bool IsPrint() const
Return if the cell has to be printed.
Definition: RDFDisplay.cxx:60
void SetDots()
Flag this cell to be replaced by "...".
Definition: RDFDisplay.cxx:53
void SetPrint()
Flag this cell as to be printed.
Definition: RDFDisplay.cxx:39
void SetIgnore()
Flag this cell as to be skipped.
Definition: RDFDisplay.cxx:46
RDisplayElement()
Constructor assuming an empty representation to be printed.
Definition: RDFDisplay.cxx:32
This class is the textual representation of the content of a columnar dataset.
Definition: RDisplay.hxx:64
void AddRow(Columns... columns)
Adds a row of events to the table.
Definition: RDisplay.hxx:200
bool AddInterpreterString(std::stringstream &, ROOT::RVec< bool > &boolArr, const int &index)
AddInterpreterString overload for arrays of booleans.
Definition: RDisplay.hxx:166
size_t fEntries
Number of events to process for each column (i.e. number of rows).
Definition: RDisplay.hxx:90
void AddCollectionToRow(const VecStr_t &collection)
Adds a collection to the table.
Definition: RDFDisplay.cxx:117
size_t fCurrentColumn
Column that is being filled.
Definition: RDisplay.hxx:88
bool HasNext()
If the number of required rows has been parsed, returns false.
Definition: RDisplay.hxx:226
std::vector< std::vector< DElement_t > > fTable
String representation of the data to be printed.
Definition: RDisplay.hxx:76
std::vector< bool > fIsCollection
True if the column contains a collection.
Definition: RDisplay.hxx:74
std::string AsString() const
Returns the representation as a string.
Definition: RDFDisplay.cxx:247
void AddToRow(const std::string &stringEle)
Adds a single element to the next slot in the table.
Definition: RDFDisplay.cxx:105
size_t fCurrentRow
Row that is being filled.
Definition: RDisplay.hxx:86
VecStr_t fRepresentations
Used by the JITted code to store the string representation of the data.
Definition: RDisplay.hxx:79
void MovePosition()
Moves to the next cell.
Definition: RDFDisplay.cxx:155
std::vector< unsigned short > fWidths
Tracks the maximum width of each column, based on the largest element.
Definition: RDisplay.hxx:77
bool AddInterpreterString(std::stringstream &stream, T &collection, const int &index)
Appends collection.size() cling::printValue calls to the stringstream.
Definition: RDisplay.hxx:116
static constexpr unsigned fgMaxWidth
Definition: RDisplay.hxx:71
RDisplay(const VecStr_t &columnNames, const VecStr_t &types, int entries)
Creates an RDisplay to print the event values.
Definition: RDFDisplay.cxx:167
void EnsureCurrentColumnWidth(size_t w)
Definition: RDFDisplay.cxx:94
size_t fNextRow
Next row to be filled.
Definition: RDisplay.hxx:87
bool AddInterpreterString(std::stringstream &, ROOT::RVec< char > &charArr, const int &index)
AddInterpreterString overload for arrays of chars.
Definition: RDisplay.hxx:147
std::vector< std::string > VecStr_t
Definition: RDisplay.hxx:68
void Print() const
Prints the representation to the standard output.
Definition: RDFDisplay.cxx:194
std::vector< VecStr_t > fCollectionsRepresentations
Used by the JITted code to store the string representation of the data in case of collection.
Definition: RDisplay.hxx:80
size_t GetNColumnsToShorten() const
Get the number of columns that do NOT fit in the characters limit.
Definition: RDFDisplay.cxx:179
static constexpr char fgSeparator
Spacing used to align the table entries.
Definition: RDisplay.hxx:70
bool AddInterpreterString(std::stringstream &stream, T &element, const int &index)
Appends a cling::printValue call to the stringstream.
Definition: RDisplay.hxx:100
VecStr_t fTypes
This attribute stores the type of each column. It is needed by the interpreter to print it.
Definition: RDisplay.hxx:73
size_t fNColumns
Number of columns to be printed.
Definition: RDisplay.hxx:84
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition: RVec.hxx:275
size_type size() const noexcept
Definition: RVec.hxx:401
data_t data() noexcept
Definition: RVec.hxx:384
RooCmdArg Columns(Int_t ncol)
std::string PrettyPrintAddr(const void *const addr)
Long64_t InterpreterCalc(const std::string &code, const std::string &context)
Definition: RDFUtils.cxx:312
double T(double x)
Definition: ChebyshevPol.h:34
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: StringConv.hxx:21
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
static void output(int code)
Definition: gifencode.c:226