Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:43

0001 /// \file ROOT/RFieldVisitor.hxx
0002 /// \ingroup NTuple ROOT7
0003 /// \author Simon Leisibach <simon.satoshi.rene.leisibach@cern.ch>
0004 /// \date 2019-06-11
0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0006 /// is welcome!
0007 
0008 /*************************************************************************
0009  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0010  * All rights reserved.                                                  *
0011  *                                                                       *
0012  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0013  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0014  *************************************************************************/
0015 
0016 #ifndef ROOT7_RFieldVisitor
0017 #define ROOT7_RFieldVisitor
0018 
0019 #include <ROOT/RField.hxx>
0020 #include <ROOT/RNTupleUtil.hxx>
0021 
0022 #include <algorithm>
0023 #include <iostream>
0024 #include <sstream>
0025 #include <string>
0026 #include <vector>
0027 
0028 namespace ROOT {
0029 namespace Experimental {
0030 namespace Detail {
0031 
0032 
0033 // clang-format off
0034 /**
0035 \class ROOT::Experimental::Detail::RFieldVisitor
0036 \ingroup NTuple
0037 \brief Abstract base class for classes implementing the visitor design pattern.
0038 
0039 RFieldVisitor::VisitField() is invoked by RFieldBase::AcceptVisitor(). VisitField() is inherited for instance
0040 by the RPrintSchemaVisitor class. The RFieldBase class and classes which inherit from it will be visited.
0041 */
0042 // clang-format on
0043 class RFieldVisitor {
0044 public:
0045    virtual void VisitField(const RFieldBase &field) = 0;
0046    virtual void VisitFieldZero(const RFieldZero &field) { VisitField(field); }
0047    virtual void VisitArrayField(const RArrayField &field) { VisitField(field); }
0048    virtual void VisitArrayAsRVecField(const RArrayAsRVecField &field) { VisitField(field); }
0049    virtual void VisitAtomicField(const RAtomicField &field) { VisitField(field); }
0050    virtual void VisitBitsetField(const RBitsetField &field) { VisitField(field); }
0051    virtual void VisitBoolField(const RField<bool> &field) { VisitField(field); }
0052    virtual void VisitClassField(const RClassField &field) { VisitField(field); }
0053    virtual void VisitProxiedCollectionField(const RProxiedCollectionField &field) { VisitField(field); }
0054    virtual void VisitRecordField(const RRecordField &field) { VisitField(field); }
0055    virtual void VisitClusterSizeField(const RField<ClusterSize_t> &field) { VisitField(field); }
0056    virtual void VisitCardinalityField(const RCardinalityField &field) { VisitField(field); }
0057    virtual void VisitDoubleField(const RField<double> &field) { VisitField(field); }
0058    virtual void VisitEnumField(const REnumField &field) { VisitField(field); }
0059    virtual void VisitFloatField(const RField<float> &field) { VisitField(field); }
0060    virtual void VisitByteField(const RField<std::byte> &field) { VisitField(field); }
0061    virtual void VisitCharField(const RField<char> &field) { VisitField(field); }
0062    virtual void VisitInt8Field(const RField<std::int8_t> &field) { VisitField(field); }
0063    virtual void VisitInt16Field(const RField<std::int16_t> &field) { VisitField(field); }
0064    virtual void VisitIntField(const RField<int> &field) { VisitField(field); }
0065    virtual void VisitInt64Field(const RField<std::int64_t> &field) { VisitField(field); }
0066    virtual void VisitNullableField(const RNullableField &field) { VisitField(field); }
0067    virtual void VisitStringField(const RField<std::string> &field) { VisitField(field); }
0068    virtual void VisitUInt16Field(const RField<std::uint16_t> &field) { VisitField(field); }
0069    virtual void VisitUInt32Field(const RField<std::uint32_t> &field) { VisitField(field); }
0070    virtual void VisitUInt64Field(const RField<std::uint64_t> &field) { VisitField(field); }
0071    virtual void VisitUInt8Field(const RField<std::uint8_t> &field) { VisitField(field); }
0072    virtual void VisitVectorField(const RVectorField &field) { VisitField(field); }
0073    virtual void VisitVectorBoolField(const RField<std::vector<bool>> &field) { VisitField(field); }
0074    virtual void VisitRVecField(const RRVecField &field) { VisitField(field); }
0075 }; // class RFieldVisitor
0076 
0077 } // namespace Detail
0078 
0079 
0080 // clang-format off
0081 /**
0082 \class ROOT::Experimental::RPrepareVisitor
0083 \ingroup NTuple
0084 \brief Visitor used for a pre-processing run to collect information needed by another visitor class.
0085 
0086  Currently used for RPrintSchemaVisitor in RNTupleReader::Print() to collect information about levels, max depth etc.
0087 */
0088 // clang-format on
0089 class RPrepareVisitor : public Detail::RFieldVisitor {
0090 private:
0091    unsigned int fDeepestLevel = 1;
0092    unsigned int fNumFields = 1;
0093 
0094 public:
0095    RPrepareVisitor() = default;
0096    void VisitField(const RFieldBase &field) final;
0097    void VisitFieldZero(const RFieldZero &field) final;
0098 
0099    unsigned int GetDeepestLevel() const { return fDeepestLevel; }
0100    unsigned int GetNumFields() const { return fNumFields; }
0101 };
0102 
0103 
0104 // clang-format off
0105 /**
0106 \class ROOT::Experimental::RPrintSchemaVisitor
0107 \ingroup NTuple
0108 \brief Contains settings for printing and prints a summary of an RField instance.
0109 
0110 This visitor is used by RNTupleReader::Print()
0111 */
0112 // clang-format on
0113 class RPrintSchemaVisitor : public Detail::RFieldVisitor {
0114 private:
0115    /// Where to write the printout to
0116    std::ostream &fOutput;
0117    /// To render the output, use an asterix (*) by default to draw table lines and boundaries
0118    char fFrameSymbol;
0119    /// Indicates maximal number of allowed characters per line
0120    int fWidth;
0121    int fDeepestLevel;
0122    int fNumFields;
0123    int fAvailableSpaceKeyString;
0124    int fAvailableSpaceValueString;
0125    int fFieldNo = 1;
0126    std::string fTreePrefix;
0127    std::string fFieldNoPrefix;
0128 
0129 public:
0130    RPrintSchemaVisitor(std::ostream &out = std::cout, char frameSymbol = '*', int width = 80, int deepestLevel = 1,
0131                        int numFields = 1)
0132       : fOutput{out}, fFrameSymbol{frameSymbol}, fWidth{width}, fDeepestLevel{deepestLevel}, fNumFields{numFields}
0133    {
0134       SetAvailableSpaceForStrings();
0135    }
0136    /// Prints summary of Field
0137    void VisitField(const RFieldBase &field) final;
0138    void VisitFieldZero(const RFieldZero &fieldZero) final;
0139    void SetFrameSymbol(char s) { fFrameSymbol = s; }
0140    void SetWidth(int w) { fWidth = w; }
0141    void SetDeepestLevel(int d);
0142    void SetNumFields(int n);
0143    /// Computes how many characters should be placed between the frame symbol and ':' for left and right side of ':' for
0144    /// visually pleasing output.
0145    // E.g.
0146    // * Field 1       : vpx (std::vector<float>)                                     *
0147    // * |__Field 1.1  : vpx/vpx (float)                                              *
0148    // int fAvailableSpaceKeyString (num characters on left side between "* " and " : ")
0149    //    deepestlevel here is 2 (1.1 is deepest and has 2 numbers).
0150    //    For every additional level an additional "|_" and ".1" (4 characters) is added, so the number of required
0151    //    additional characters is 4 * fDeepestLevel. For level 1, 8 characters are required ("Field 1 "), so an
0152    //    additional + 4 is added. To account for cases where the total number of fields is not a single digit number and
0153    //    more space is required to output big numbers, fNumFields is incorporated into the calculation. To make sure
0154    //    that there is still enough space for the right side of " : ", an std::min comparision with fWidth - 15 is done.
0155    // int fAvailableSpaceValueString(num characters on right side between " : " and '*')
0156    //    The 6 subtracted characters are "* " (2) in the beginning,  " : " (3) and '*' (1) on the far right.
0157    void SetAvailableSpaceForStrings()
0158    {
0159       fAvailableSpaceKeyString =
0160          std::min(4 * fDeepestLevel + 4 + static_cast<int>(std::to_string(fNumFields).size()), fWidth - 15);
0161       fAvailableSpaceValueString = fWidth - 6 - fAvailableSpaceKeyString;
0162    }
0163 };
0164 
0165 
0166 // clang-format off
0167 /**
0168 \class ROOT::Experimental::RPrintValueVisitor
0169 \ingroup NTuple
0170 \brief Renders a JSON value corresponding to the field.
0171 */
0172 // clang-format on
0173 class RPrintValueVisitor : public Detail::RFieldVisitor {
0174 public:
0175    struct RPrintOptions {
0176       bool fPrintSingleLine;
0177       bool fPrintName;
0178 
0179       RPrintOptions() : fPrintSingleLine(false), fPrintName(true) {}
0180    };
0181 
0182 private:
0183    RFieldBase::RValue fValue;
0184    /// The output is directed to fOutput which may differ from std::cout.
0185    std::ostream &fOutput;
0186    unsigned int fLevel;
0187    RPrintOptions fPrintOptions;
0188 
0189    void PrintIndent();
0190    void PrintName(const RFieldBase &field);
0191    void PrintCollection(const RFieldBase &field);
0192 
0193 public:
0194    RPrintValueVisitor(RFieldBase::RValue value, std::ostream &output, unsigned int level = 0,
0195                       RPrintOptions options = RPrintOptions())
0196       : fValue(value), fOutput{output}, fLevel(level), fPrintOptions(options)
0197    {
0198    }
0199 
0200    void VisitField(const RFieldBase &field) final;
0201 
0202    void VisitBoolField(const RField<bool> &field) final;
0203    void VisitDoubleField(const RField<double> &field) final;
0204    void VisitFloatField(const RField<float> &field) final;
0205    void VisitByteField(const RField<std::byte> &field) final;
0206    void VisitCharField(const RField<char> &field) final;
0207    void VisitInt8Field(const RField<std::int8_t> &field) final;
0208    void VisitInt16Field(const RField<std::int16_t> &field) final;
0209    void VisitIntField(const RField<int> &field) final;
0210    void VisitInt64Field(const RField<std::int64_t> &field) final;
0211    void VisitStringField(const RField<std::string> &field) final;
0212    void VisitUInt8Field(const RField<std::uint8_t> &field) final;
0213    void VisitUInt16Field(const RField<std::uint16_t> &field) final;
0214    void VisitUInt32Field(const RField<std::uint32_t> &field) final;
0215    void VisitUInt64Field(const RField<std::uint64_t> &field) final;
0216 
0217    void VisitCardinalityField(const RCardinalityField &field) final;
0218    void VisitArrayField(const RArrayField &field) final;
0219    void VisitArrayAsRVecField(const RArrayAsRVecField &field) final;
0220    void VisitClassField(const RClassField &field) final;
0221    void VisitRecordField(const RRecordField &field) final;
0222    void VisitProxiedCollectionField(const RProxiedCollectionField &field) final;
0223    void VisitVectorField(const RVectorField &field) final;
0224    void VisitVectorBoolField(const RField<std::vector<bool>> &field) final;
0225    void VisitRVecField(const RRVecField &field) final;
0226    void VisitBitsetField(const RBitsetField &field) final;
0227    void VisitNullableField(const RNullableField &field) final;
0228    void VisitEnumField(const REnumField &field) final;
0229    void VisitAtomicField(const RAtomicField &field) final;
0230 };
0231 
0232 
0233 // clang-format off
0234 /**
0235 \class ROOT::Experimental::RNTupleFormatter
0236 \ingroup NTuple
0237 \brief Contains helper functions for RNTupleReader::PrintInfo() and RPrintSchemaVisitor::VisitField()
0238 
0239 The functions in this class format strings which are displayed by RNTupleReader::PrintInfo() and RNTupleReader::Show().
0240 */
0241 // clang-format on
0242 class RNTupleFormatter {
0243 public:
0244    // Can abbreviate long strings, e.g. ("ExampleString" , space= 8) => "Examp..."
0245    static std::string FitString(const std::string &str, int availableSpace);
0246 };
0247 
0248 } // namespace Experimental
0249 } // namespace ROOT
0250 
0251 #endif