Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 09:11:42

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/RNTupleUtil.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 VisitAtomicField(const ROOT::RAtomicField &field) { VisitField(field); }
0065    virtual void VisitBitsetField(const ROOT::RBitsetField &field) { VisitField(field); }
0066    virtual void VisitBoolField(const ROOT::RField<bool> &field) { VisitField(field); }
0067    virtual void VisitClassField(const ROOT::RClassField &field) { VisitField(field); }
0068    virtual void VisitTObjectField(const ROOT::RField<TObject> &field) { VisitField(field); }
0069    virtual void VisitStreamerField(const ROOT::RStreamerField &field) { VisitField(field); }
0070    virtual void VisitProxiedCollectionField(const ROOT::RProxiedCollectionField &field) { VisitField(field); }
0071    virtual void VisitRecordField(const ROOT::RRecordField &field) { VisitField(field); }
0072    virtual void VisitCardinalityField(const ROOT::RCardinalityField &field) { VisitField(field); }
0073    virtual void VisitDoubleField(const ROOT::RField<double> &field) { VisitField(field); }
0074    virtual void VisitEnumField(const ROOT::REnumField &field) { VisitField(field); }
0075    virtual void VisitFloatField(const ROOT::RField<float> &field) { VisitField(field); }
0076    virtual void VisitByteField(const ROOT::RField<std::byte> &field) { VisitField(field); }
0077    virtual void VisitCharField(const ROOT::RField<char> &field) { VisitField(field); }
0078    // We have to accept RIntegralField here because there can be multiple basic types that map to the same fixed-width
0079    // integer type; for example on 64-bit Unix systems, both long and long long map to std::int64_t.
0080    virtual void VisitInt8Field(const ROOT::RIntegralField<std::int8_t> &field) { VisitField(field); }
0081    virtual void VisitInt16Field(const ROOT::RIntegralField<std::int16_t> &field) { VisitField(field); }
0082    virtual void VisitInt32Field(const ROOT::RIntegralField<std::int32_t> &field) { VisitField(field); }
0083    virtual void VisitInt64Field(const ROOT::RIntegralField<std::int64_t> &field) { VisitField(field); }
0084    virtual void VisitNullableField(const ROOT::RNullableField &field) { VisitField(field); }
0085    virtual void VisitStringField(const ROOT::RField<std::string> &field) { VisitField(field); }
0086    virtual void VisitUInt8Field(const ROOT::RIntegralField<std::uint8_t> &field) { VisitField(field); }
0087    virtual void VisitUInt16Field(const ROOT::RIntegralField<std::uint16_t> &field) { VisitField(field); }
0088    virtual void VisitUInt32Field(const ROOT::RIntegralField<std::uint32_t> &field) { VisitField(field); }
0089    virtual void VisitUInt64Field(const ROOT::RIntegralField<std::uint64_t> &field) { VisitField(field); }
0090    virtual void VisitVectorField(const ROOT::RVectorField &field) { VisitField(field); }
0091    virtual void VisitVectorBoolField(const ROOT::RField<std::vector<bool>> &field) { VisitField(field); }
0092    virtual void VisitRVecField(const ROOT::RRVecField &field) { VisitField(field); }
0093 }; // class RFieldVisitor
0094 
0095 } // namespace Detail
0096 
0097 namespace Internal {
0098 
0099 // clang-format off
0100 /**
0101 \class ROOT::Internal::RPrepareVisitor
0102 \ingroup NTuple
0103 \brief Visitor used for a pre-processing run to collect information needed by another visitor class.
0104 
0105  Currently used for RPrintSchemaVisitor in RNTupleReader::PrintInfo() to collect information about levels, max depth etc.
0106 */
0107 // clang-format on
0108 class RPrepareVisitor : public Detail::RFieldVisitor {
0109 private:
0110    unsigned int fDeepestLevel = 1;
0111    unsigned int fNumFields = 1;
0112 
0113 public:
0114    RPrepareVisitor() = default;
0115    void VisitField(const ROOT::RFieldBase &field) final;
0116    void VisitFieldZero(const ROOT::RFieldZero &field) final;
0117 
0118    unsigned int GetDeepestLevel() const { return fDeepestLevel; }
0119    unsigned int GetNumFields() const { return fNumFields; }
0120 };
0121 
0122 // clang-format off
0123 /**
0124 \class ROOT::Internal::RPrintSchemaVisitor
0125 \ingroup NTuple
0126 \brief Contains settings for printing and prints a summary of an RField instance.
0127 
0128 This visitor is used by RNTupleReader::PrintInfo()
0129 */
0130 // clang-format on
0131 class RPrintSchemaVisitor : public Detail::RFieldVisitor {
0132 private:
0133    /// Where to write the printout to
0134    std::ostream &fOutput;
0135    /// To render the output, use an asterix (*) by default to draw table lines and boundaries
0136    char fFrameSymbol;
0137    /// Indicates maximal number of allowed characters per line
0138    int fWidth;
0139    int fDeepestLevel;
0140    int fNumFields;
0141    int fAvailableSpaceKeyString;
0142    int fAvailableSpaceValueString;
0143    int fFieldNo = 1;
0144    std::string fTreePrefix;
0145    std::string fFieldNoPrefix;
0146 
0147 public:
0148    RPrintSchemaVisitor(std::ostream &out = std::cout, char frameSymbol = '*', int width = 80, int deepestLevel = 1,
0149                        int numFields = 1)
0150       : fOutput{out}, fFrameSymbol{frameSymbol}, fWidth{width}, fDeepestLevel{deepestLevel}, fNumFields{numFields}
0151    {
0152       SetAvailableSpaceForStrings();
0153    }
0154    /// Prints summary of Field
0155    void VisitField(const ROOT::RFieldBase &field) final;
0156    void VisitFieldZero(const ROOT::RFieldZero &fieldZero) final;
0157    void SetFrameSymbol(char s) { fFrameSymbol = s; }
0158    void SetWidth(int w) { fWidth = w; }
0159    void SetDeepestLevel(int d);
0160    void SetNumFields(int n);
0161    /// Computes how many characters should be placed between the frame symbol and ':' for left and right side of ':' for
0162    /// visually pleasing output.
0163    // E.g.
0164    // * Field 1       : vpx (std::vector<float>)                                     *
0165    // * |__Field 1.1  : vpx/vpx (float)                                              *
0166    // int fAvailableSpaceKeyString (num characters on left side between "* " and " : ")
0167    //    deepestlevel here is 2 (1.1 is deepest and has 2 numbers).
0168    //    For every additional level an additional "|_" and ".1" (4 characters) is added, so the number of required
0169    //    additional characters is 4 * fDeepestLevel. For level 1, 8 characters are required ("Field 1 "), so an
0170    //    additional + 4 is added. To account for cases where the total number of fields is not a single digit number and
0171    //    more space is required to output big numbers, fNumFields is incorporated into the calculation. To make sure
0172    //    that there is still enough space for the right side of " : ", an std::min comparision with fWidth - 15 is done.
0173    // int fAvailableSpaceValueString(num characters on right side between " : " and '*')
0174    //    The 6 subtracted characters are "* " (2) in the beginning,  " : " (3) and '*' (1) on the far right.
0175    void SetAvailableSpaceForStrings()
0176    {
0177       fAvailableSpaceKeyString =
0178          std::min(4 * fDeepestLevel + 4 + static_cast<int>(std::to_string(fNumFields).size()), fWidth - 15);
0179       fAvailableSpaceValueString = fWidth - 6 - fAvailableSpaceKeyString;
0180    }
0181 };
0182 
0183 // clang-format off
0184 /**
0185 \class ROOT::Internal::RPrintValueVisitor
0186 \ingroup NTuple
0187 \brief Renders a JSON value corresponding to the field.
0188 */
0189 // clang-format on
0190 class RPrintValueVisitor : public Detail::RFieldVisitor {
0191 public:
0192    struct RPrintOptions {
0193       bool fPrintSingleLine;
0194       bool fPrintName;
0195 
0196       RPrintOptions() : fPrintSingleLine(false), fPrintName(true) {}
0197    };
0198 
0199 private:
0200    ROOT::RFieldBase::RValue fValue;
0201    /// The output is directed to fOutput which may differ from std::cout.
0202    std::ostream &fOutput;
0203    unsigned int fLevel;
0204    RPrintOptions fPrintOptions;
0205 
0206    void PrintIndent();
0207    void PrintName(const ROOT::RFieldBase &field);
0208    void PrintCollection(const ROOT::RFieldBase &field);
0209    void PrintRecord(const ROOT::RFieldBase &field);
0210 
0211 public:
0212    RPrintValueVisitor(ROOT::RFieldBase::RValue value, std::ostream &output, unsigned int level = 0,
0213                       RPrintOptions options = RPrintOptions())
0214       : fValue(value), fOutput{output}, fLevel(level), fPrintOptions(options)
0215    {
0216    }
0217 
0218    void VisitField(const ROOT::RFieldBase &field) final;
0219 
0220    void VisitBoolField(const ROOT::RField<bool> &field) final;
0221    void VisitDoubleField(const ROOT::RField<double> &field) final;
0222    void VisitFloatField(const ROOT::RField<float> &field) final;
0223    void VisitByteField(const ROOT::RField<std::byte> &field) final;
0224    void VisitCharField(const ROOT::RField<char> &field) final;
0225    void VisitInt8Field(const ROOT::RIntegralField<std::int8_t> &field) final;
0226    void VisitInt16Field(const ROOT::RIntegralField<std::int16_t> &field) final;
0227    void VisitInt32Field(const ROOT::RIntegralField<std::int32_t> &field) final;
0228    void VisitInt64Field(const ROOT::RIntegralField<std::int64_t> &field) final;
0229    void VisitStringField(const ROOT::RField<std::string> &field) final;
0230    void VisitUInt8Field(const ROOT::RIntegralField<std::uint8_t> &field) final;
0231    void VisitUInt16Field(const ROOT::RIntegralField<std::uint16_t> &field) final;
0232    void VisitUInt32Field(const ROOT::RIntegralField<std::uint32_t> &field) final;
0233    void VisitUInt64Field(const ROOT::RIntegralField<std::uint64_t> &field) final;
0234 
0235    void VisitCardinalityField(const ROOT::RCardinalityField &field) final;
0236    void VisitArrayField(const ROOT::RArrayField &field) final;
0237    void VisitArrayAsRVecField(const ROOT::RArrayAsRVecField &field) final;
0238    void VisitClassField(const ROOT::RClassField &field) final;
0239    void VisitTObjectField(const ROOT::RField<TObject> &field) final;
0240    void VisitStreamerField(const ROOT::RStreamerField &field) final;
0241    void VisitRecordField(const ROOT::RRecordField &field) final;
0242    void VisitProxiedCollectionField(const ROOT::RProxiedCollectionField &field) final;
0243    void VisitVectorField(const ROOT::RVectorField &field) final;
0244    void VisitVectorBoolField(const ROOT::RField<std::vector<bool>> &field) final;
0245    void VisitRVecField(const ROOT::RRVecField &field) final;
0246    void VisitBitsetField(const ROOT::RBitsetField &field) final;
0247    void VisitNullableField(const ROOT::RNullableField &field) final;
0248    void VisitEnumField(const ROOT::REnumField &field) final;
0249    void VisitAtomicField(const ROOT::RAtomicField &field) final;
0250 };
0251 
0252 // clang-format off
0253 /**
0254 \class ROOT::Internal::RNTupleFormatter
0255 \ingroup NTuple
0256 \brief Contains helper functions for RNTupleReader::PrintInfo() and RPrintSchemaVisitor::VisitField()
0257 
0258 The functions in this class format strings which are displayed by RNTupleReader::PrintInfo() and RNTupleReader::Show().
0259 */
0260 // clang-format on
0261 class RNTupleFormatter {
0262 public:
0263    // Can abbreviate long strings, e.g. ("ExampleString" , space= 8) => "Examp..."
0264    static std::string FitString(const std::string &str, int availableSpace);
0265 };
0266 
0267 } // namespace Internal
0268 } // namespace ROOT
0269 
0270 #endif