Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/ROOT/RFieldVisitor.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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