Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:28:35

0001 /// \file ROOT/RField/SequenceContainer.hxx
0002 /// \ingroup NTuple
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-10-09
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_RField_SequenceContainer
0015 #define ROOT_RField_SequenceContainer
0016 
0017 #ifndef ROOT_RField
0018 #error "Please include RField.hxx!"
0019 #endif
0020 
0021 #include <ROOT/RFieldBase.hxx>
0022 #include <ROOT/RNTupleTypes.hxx>
0023 #include <ROOT/RVec.hxx>
0024 
0025 #include <array>
0026 #include <memory>
0027 #include <vector>
0028 
0029 namespace ROOT {
0030 
0031 namespace Detail {
0032 class RFieldVisitor;
0033 } // namespace Detail
0034 
0035 namespace Internal {
0036 std::unique_ptr<RFieldBase> CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
0037                                                       std::string_view emulatedFromType);
0038 }
0039 
0040 ////////////////////////////////////////////////////////////////////////////////
0041 /// Template specializations for C++ std::array and C-style arrays
0042 ////////////////////////////////////////////////////////////////////////////////
0043 
0044 /// The generic field for fixed size arrays, which do not need an offset column
0045 class RArrayField : public RFieldBase {
0046 private:
0047    class RArrayDeleter : public RDeleter {
0048    private:
0049       std::size_t fItemSize = 0;
0050       std::size_t fArrayLength = 0;
0051       std::unique_ptr<RDeleter> fItemDeleter;
0052 
0053    public:
0054       RArrayDeleter(std::size_t itemSize, std::size_t arrayLength, std::unique_ptr<RDeleter> itemDeleter)
0055          : fItemSize(itemSize), fArrayLength(arrayLength), fItemDeleter(std::move(itemDeleter))
0056       {
0057       }
0058       void operator()(void *objPtr, bool dtorOnly) final;
0059    };
0060 
0061    std::size_t fItemSize;
0062    std::size_t fArrayLength;
0063 
0064 protected:
0065    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0066 
0067    void ConstructValue(void *where) const final;
0068    std::unique_ptr<RDeleter> GetDeleter() const final;
0069 
0070    std::size_t AppendImpl(const void *from) final;
0071    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0072    void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0073    std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final;
0074 
0075    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0076 
0077 public:
0078    RArrayField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, std::size_t arrayLength);
0079    RArrayField(RArrayField &&other) = default;
0080    RArrayField &operator=(RArrayField &&other) = default;
0081    ~RArrayField() override = default;
0082 
0083    std::vector<RValue> SplitValue(const RValue &value) const final;
0084    size_t GetLength() const { return fArrayLength; }
0085    size_t GetValueSize() const final { return fItemSize * fArrayLength; }
0086    size_t GetAlignment() const final { return fSubfields[0]->GetAlignment(); }
0087    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0088 };
0089 
0090 template <typename ItemT, std::size_t N>
0091 class RField<std::array<ItemT, N>> : public RArrayField {
0092 public:
0093    static std::string TypeName() { return "std::array<" + RField<ItemT>::TypeName() + "," + std::to_string(N) + ">"; }
0094    explicit RField(std::string_view name) : RArrayField(name, std::make_unique<RField<ItemT>>("_0"), N) {}
0095    RField(RField &&other) = default;
0096    RField &operator=(RField &&other) = default;
0097    ~RField() override = default;
0098 };
0099 
0100 template <typename ItemT, std::size_t N>
0101 class RField<ItemT[N]> final : public RField<std::array<ItemT, N>> {
0102 public:
0103    explicit RField(std::string_view name) : RField<std::array<ItemT, N>>(name) {}
0104    RField(RField &&other) = default;
0105    RField &operator=(RField &&other) = default;
0106    ~RField() final = default;
0107 };
0108 
0109 ////////////////////////////////////////////////////////////////////////////////
0110 /// Template specializations for ROOT's RVec
0111 ////////////////////////////////////////////////////////////////////////////////
0112 
0113 /// The type-erased field for a RVec<Type>
0114 class RRVecField : public RFieldBase {
0115    friend class RArrayAsRVecField; // to use the RRVecDeleter and to call ResizeRVec()
0116 
0117    // Ensures that the RVec pointed to by rvec has at least nItems valid elements
0118    // Returns the possibly new "begin pointer" of the RVec, i.e. the pointer to the data area.
0119    static unsigned char *
0120    ResizeRVec(void *rvec, std::size_t nItems, std::size_t itemSize, const RFieldBase *itemField, RDeleter *itemDeleter);
0121 
0122    class RRVecDeleter : public RDeleter {
0123    private:
0124       std::size_t fItemAlignment;
0125       std::size_t fItemSize = 0;
0126       std::unique_ptr<RDeleter> fItemDeleter;
0127 
0128    public:
0129       explicit RRVecDeleter(std::size_t itemAlignment) : fItemAlignment(itemAlignment) {}
0130       RRVecDeleter(std::size_t itemAlignment, std::size_t itemSize, std::unique_ptr<RDeleter> itemDeleter)
0131          : fItemAlignment(itemAlignment), fItemSize(itemSize), fItemDeleter(std::move(itemDeleter))
0132       {
0133       }
0134       void operator()(void *objPtr, bool dtorOnly) final;
0135    };
0136 
0137    std::unique_ptr<RDeleter> fItemDeleter;
0138 
0139 protected:
0140    std::size_t fItemSize;
0141    ROOT::Internal::RColumnIndex fNWritten;
0142    std::size_t fValueSize;
0143 
0144    // For bulk read optimzation
0145    std::size_t fBulkNRepetition = 1;
0146    /// May be a direct PoD subfield or a sub-subfield of a fixed-size array of PoD
0147    RFieldBase *fBulkSubfield = nullptr;
0148 
0149    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0150    const RColumnRepresentations &GetColumnRepresentations() const final;
0151    void GenerateColumns() final;
0152    void GenerateColumns(const ROOT::RNTupleDescriptor &desc) final;
0153 
0154    void ConstructValue(void *where) const final;
0155    std::unique_ptr<RDeleter> GetDeleter() const final;
0156 
0157    std::size_t AppendImpl(const void *from) final;
0158    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0159    std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final;
0160 
0161    std::unique_ptr<RFieldBase> BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
0162    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0163 
0164    void CommitClusterImpl() final { fNWritten = 0; }
0165 
0166 public:
0167    RRVecField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
0168    RRVecField(RRVecField &&) = default;
0169    RRVecField &operator=(RRVecField &&) = default;
0170    RRVecField(const RRVecField &) = delete;
0171    RRVecField &operator=(RRVecField &) = delete;
0172    ~RRVecField() override = default;
0173 
0174    std::vector<RValue> SplitValue(const RValue &value) const final;
0175    size_t GetValueSize() const final;
0176    size_t GetAlignment() const final;
0177    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0178 };
0179 
0180 template <typename ItemT>
0181 class RField<ROOT::VecOps::RVec<ItemT>> final : public RRVecField {
0182 public:
0183    RField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
0184       : RRVecField(fieldName, std::move(itemField))
0185    {
0186    }
0187 
0188    explicit RField(std::string_view name) : RField(name, std::make_unique<RField<ItemT>>("_0")) {}
0189    RField(RField &&other) = default;
0190    RField &operator=(RField &&other) = default;
0191    ~RField() final = default;
0192 
0193    static std::string TypeName() { return "ROOT::VecOps::RVec<" + RField<ItemT>::TypeName() + ">"; }
0194 };
0195 
0196 ////////////////////////////////////////////////////////////////////////////////
0197 /// Template specializations for C++ std::vector
0198 ////////////////////////////////////////////////////////////////////////////////
0199 
0200 /// The generic field for a (nested) `std::vector<Type>` except for `std::vector<bool>`
0201 /// The field can be constructed as untyped collection through CreateUntyped().
0202 class RVectorField : public RFieldBase {
0203    friend class RArrayAsVectorField; // to get access to the RVectorDeleter
0204    friend std::unique_ptr<RFieldBase> Internal::CreateEmulatedVectorField(std::string_view fieldName,
0205                                                                           std::unique_ptr<RFieldBase> itemField,
0206                                                                           std::string_view emulatedFromType);
0207 
0208    class RVectorDeleter : public RDeleter {
0209    private:
0210       std::size_t fItemSize = 0;
0211       std::unique_ptr<RDeleter> fItemDeleter;
0212 
0213    public:
0214       RVectorDeleter() = default;
0215       RVectorDeleter(std::size_t itemSize, std::unique_ptr<RDeleter> itemDeleter)
0216          : fItemSize(itemSize), fItemDeleter(std::move(itemDeleter))
0217       {
0218       }
0219       void operator()(void *objPtr, bool dtorOnly) final;
0220    };
0221 
0222    std::size_t fItemSize;
0223    ROOT::Internal::RColumnIndex fNWritten;
0224    std::unique_ptr<RDeleter> fItemDeleter;
0225 
0226    // Ensures that the std::vector pointed to by vec has at least nItems valid elements.
0227    static void ResizeVector(void *vec, std::size_t nItems, std::size_t itemSize, const RFieldBase &itemField,
0228                             RDeleter *itemDeleter);
0229 
0230 protected:
0231    /// Creates a possibly-untyped VectorField.
0232    /// If `emulatedFromType` is not nullopt, the field is untyped. If the string is empty, it is a "regular"
0233    /// untyped vector field; otherwise, it was created as an emulated field from the given type name.
0234    RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
0235                 std::optional<std::string_view> emulatedFromType);
0236 
0237    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0238 
0239    const RColumnRepresentations &GetColumnRepresentations() const final;
0240    void GenerateColumns() final;
0241    void GenerateColumns(const ROOT::RNTupleDescriptor &desc) final;
0242 
0243    void ConstructValue(void *where) const final { new (where) std::vector<char>(); }
0244    std::unique_ptr<RDeleter> GetDeleter() const final;
0245 
0246    std::size_t AppendImpl(const void *from) final;
0247    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0248 
0249    std::unique_ptr<RFieldBase> BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
0250    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0251 
0252    void CommitClusterImpl() final { fNWritten = 0; }
0253 
0254 public:
0255    RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
0256    RVectorField(RVectorField &&other) = default;
0257    RVectorField &operator=(RVectorField &&other) = default;
0258    ~RVectorField() override = default;
0259 
0260    static std::unique_ptr<RVectorField>
0261    CreateUntyped(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
0262 
0263    std::vector<RValue> SplitValue(const RValue &value) const final;
0264    size_t GetValueSize() const final { return sizeof(std::vector<char>); }
0265    size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
0266    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0267 };
0268 
0269 template <typename ItemT>
0270 class RField<std::vector<ItemT>> final : public RVectorField {
0271 public:
0272    static std::string TypeName() { return "std::vector<" + RField<ItemT>::TypeName() + ">"; }
0273    explicit RField(std::string_view name) : RVectorField(name, std::make_unique<RField<ItemT>>("_0")) {}
0274    RField(RField &&other) = default;
0275    RField &operator=(RField &&other) = default;
0276    ~RField() final = default;
0277 };
0278 
0279 // `std::vector<bool>` is a template specialization and needs special treatment
0280 template <>
0281 class RField<std::vector<bool>> final : public RFieldBase {
0282 private:
0283    ROOT::Internal::RColumnIndex fNWritten{0};
0284    /// If schema-evolved from an std::array, fOnDiskNRepetition is > 0 and there will be no
0285    /// principal column.
0286    std::size_t fOnDiskNRepetitions = 0;
0287 
0288 protected:
0289    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
0290    {
0291       return std::make_unique<RField>(newName);
0292    }
0293 
0294    const RColumnRepresentations &GetColumnRepresentations() const final;
0295    void GenerateColumns() final;
0296    void GenerateColumns(const ROOT::RNTupleDescriptor &desc) final;
0297 
0298    void ConstructValue(void *where) const final { new (where) std::vector<bool>(); }
0299    std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<std::vector<bool>>>(); }
0300 
0301    std::size_t AppendImpl(const void *from) final;
0302    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0303    void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final;
0304 
0305    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0306 
0307    void CommitClusterImpl() final { fNWritten = 0; }
0308 
0309 public:
0310    static std::string TypeName() { return "std::vector<bool>"; }
0311    explicit RField(std::string_view name);
0312    RField(RField &&other) = default;
0313    RField &operator=(RField &&other) = default;
0314    ~RField() final = default;
0315 
0316    std::vector<RValue> SplitValue(const RValue &value) const final;
0317 
0318    size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
0319    size_t GetAlignment() const final { return std::alignment_of<std::vector<bool>>(); }
0320    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0321 };
0322 
0323 ////////////////////////////////////////////////////////////////////////////////
0324 /// Additional classes related to sequence containers
0325 ////////////////////////////////////////////////////////////////////////////////
0326 
0327 /**
0328 \class ROOT::RArrayAsRVecField
0329 \brief A field for fixed-size arrays that are represented as RVecs in memory.
0330 \ingroup NTuple
0331 This class is used only for reading. In particular, it helps exposing
0332 arbitrarily-nested `std::array` on-disk fields as RVecs for usage in RDataFrame.
0333 */
0334 class RArrayAsRVecField final : public RFieldBase {
0335 private:
0336    std::unique_ptr<RDeleter> fItemDeleter; /// Sub field deleter or nullptr for simple fields
0337    std::size_t fItemSize;                  /// The size of a child field's item
0338    std::size_t fArrayLength;               /// The length of the arrays in this field
0339    std::size_t fValueSize;                 /// The size of a value of this field, i.e. an RVec
0340 
0341 protected:
0342    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0343 
0344    void GenerateColumns() final { throw RException(R__FAIL("RArrayAsRVec fields must only be used for reading")); }
0345    using RFieldBase::GenerateColumns;
0346 
0347    void ConstructValue(void *where) const final;
0348    /// Returns an RRVecField::RRVecDeleter
0349    std::unique_ptr<RDeleter> GetDeleter() const final;
0350 
0351    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0352    void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0353 
0354    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0355 
0356 public:
0357    /**
0358       Constructor of the field. The `itemField` argument represents the inner
0359       item of the on-disk array, i.e. for an `std::array<float>` it is the `float`
0360       field and not the `std::array` itself.
0361    */
0362    RArrayAsRVecField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, std::size_t arrayLength);
0363    RArrayAsRVecField(const RArrayAsRVecField &other) = delete;
0364    RArrayAsRVecField &operator=(const RArrayAsRVecField &other) = delete;
0365    RArrayAsRVecField(RArrayAsRVecField &&other) = default;
0366    RArrayAsRVecField &operator=(RArrayAsRVecField &&other) = default;
0367    ~RArrayAsRVecField() final = default;
0368 
0369    std::size_t GetValueSize() const final { return fValueSize; }
0370    std::size_t GetAlignment() const final;
0371 
0372    std::vector<RFieldBase::RValue> SplitValue(const RFieldBase::RValue &value) const final;
0373    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0374 };
0375 
0376 /**
0377 \class ROOT::RArrayAsVectorField
0378 \brief A field for fixed-size arrays that are represented as std::vector in memory.
0379 \ingroup NTuple
0380 This class is used only for reading. In particular, it helps for schema evolution of fixed-size arrays into vectors.
0381 */
0382 class RArrayAsVectorField final : public RFieldBase {
0383 private:
0384    std::unique_ptr<RDeleter> fItemDeleter; /// Sub field deleter or nullptr for simple fields
0385    std::size_t fItemSize;                  /// The size of a child field's item
0386    std::size_t fArrayLength;               /// The length of the arrays in this field
0387 
0388 protected:
0389    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0390 
0391    void GenerateColumns() final;
0392    using RFieldBase::GenerateColumns;
0393 
0394    void ConstructValue(void *where) const final { new (where) std::vector<char>(); }
0395    /// Returns an RVectorField::RVectorDeleter
0396    std::unique_ptr<RDeleter> GetDeleter() const final;
0397 
0398    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0399    void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0400 
0401    void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0402 
0403 public:
0404    /// The `itemField` argument represents the inner item of the on-disk array,
0405    /// i.e. for an `std::array<float>` it is the `float`
0406    RArrayAsVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, std::size_t arrayLength);
0407    RArrayAsVectorField(const RArrayAsVectorField &other) = delete;
0408    RArrayAsVectorField &operator=(const RArrayAsVectorField &other) = delete;
0409    RArrayAsVectorField(RArrayAsVectorField &&other) = default;
0410    RArrayAsVectorField &operator=(RArrayAsVectorField &&other) = default;
0411    ~RArrayAsVectorField() final = default;
0412 
0413    size_t GetValueSize() const final { return sizeof(std::vector<char>); }
0414    size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
0415 
0416    std::vector<RFieldBase::RValue> SplitValue(const RFieldBase::RValue &value) const final;
0417    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0418 };
0419 
0420 } // namespace ROOT
0421 
0422 #endif