Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:14:20

0001 /// \file ROOT/RField/Fundamental.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_Record
0015 #define ROOT_RField_Record
0016 
0017 #ifndef ROOT_RField
0018 #error "Please include RField.hxx!"
0019 #endif
0020 
0021 #include <ROOT/RFieldBase.hxx>
0022 #include <ROOT/RNTupleUtil.hxx>
0023 
0024 #include <string>
0025 #include <string_view>
0026 #include <tuple>
0027 #include <utility>
0028 #include <vector>
0029 
0030 namespace ROOT {
0031 
0032 namespace Detail {
0033 class RFieldVisitor;
0034 } // namespace Detail
0035 
0036 namespace Internal {
0037 std::unique_ptr<RFieldBase> CreateEmulatedField(std::string_view fieldName,
0038                                                 std::vector<std::unique_ptr<RFieldBase>> itemFields,
0039                                                 std::string_view emulatedFromType);
0040 }
0041 
0042 /// The field for an untyped record. The subfields are stored consecutively in a memory block, i.e.
0043 /// the memory layout is identical to one that a C++ struct would have
0044 class RRecordField : public RFieldBase {
0045    friend std::unique_ptr<RFieldBase> Internal::CreateEmulatedField(std::string_view fieldName,
0046                                                                     std::vector<std::unique_ptr<RFieldBase>> itemFields,
0047                                                                     std::string_view emulatedFromType);
0048 
0049    class RRecordDeleter : public RDeleter {
0050    private:
0051       std::vector<std::unique_ptr<RDeleter>> fItemDeleters;
0052       std::vector<std::size_t> fOffsets;
0053 
0054    public:
0055       RRecordDeleter(std::vector<std::unique_ptr<RDeleter>> itemDeleters, const std::vector<std::size_t> &offsets)
0056          : fItemDeleters(std::move(itemDeleters)), fOffsets(offsets)
0057       {
0058       }
0059       void operator()(void *objPtr, bool dtorOnly) final;
0060    };
0061 
0062    RRecordField(std::string_view name, const RRecordField &source); // Used by CloneImpl()
0063 
0064    /// If `emulatedFromType` is non-empty, this field was created as a replacement for a ClassField that we lack a
0065    /// dictionary for and reconstructed from the on-disk information.
0066    RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
0067                 std::string_view emulatedFromType);
0068 
0069 protected:
0070    std::size_t fMaxAlignment = 1;
0071    std::size_t fSize = 0;
0072    std::vector<std::size_t> fOffsets;
0073 
0074    std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const;
0075 
0076    std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0077 
0078    void ConstructValue(void *where) const final;
0079    std::unique_ptr<RDeleter> GetDeleter() const final;
0080 
0081    std::size_t AppendImpl(const void *from) final;
0082    void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0083    void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0084 
0085    RRecordField(std::string_view fieldName, std::string_view typeName);
0086 
0087    void AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields);
0088 
0089    template <std::size_t N>
0090    void AttachItemFields(std::array<std::unique_ptr<RFieldBase>, N> itemFields)
0091    {
0092       fTraits |= kTraitTrivialType;
0093       for (unsigned i = 0; i < N; ++i) {
0094          fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
0095          fSize += GetItemPadding(fSize, itemFields[i]->GetAlignment()) + itemFields[i]->GetValueSize();
0096          fTraits &= itemFields[i]->GetTraits();
0097          Attach(std::move(itemFields[i]));
0098       }
0099       // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
0100       // requirements of the type with strictest alignment
0101       fSize += GetItemPadding(fSize, fMaxAlignment);
0102    }
0103 
0104 public:
0105    /// Construct a RRecordField based on a vector of child fields. The ownership of the child fields is transferred
0106    /// to the RRecordField instance.
0107    RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
0108    RRecordField(RRecordField &&other) = default;
0109    RRecordField &operator=(RRecordField &&other) = default;
0110    ~RRecordField() override = default;
0111 
0112    std::vector<RValue> SplitValue(const RValue &value) const final;
0113    size_t GetValueSize() const final
0114    {
0115       // The minimum size is 1 to support having vectors of empty records
0116       return std::max<size_t>(1ul, fSize);
0117    }
0118    size_t GetAlignment() const final { return fMaxAlignment; }
0119    void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0120 
0121    const std::vector<std::size_t> &GetOffsets() const { return fOffsets; }
0122 };
0123 
0124 ////////////////////////////////////////////////////////////////////////////////
0125 /// Template specializations for C++ std::pair
0126 ////////////////////////////////////////////////////////////////////////////////
0127 
0128 /// The generic field for `std::pair<T1, T2>` types
0129 class RPairField : public RRecordField {
0130 private:
0131    static std::string GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);
0132 
0133 protected:
0134    RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
0135               const std::array<std::size_t, 2> &offsets);
0136 
0137 public:
0138    RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields);
0139    RPairField(RPairField &&other) = default;
0140    RPairField &operator=(RPairField &&other) = default;
0141    ~RPairField() override = default;
0142 };
0143 
0144 template <typename T1, typename T2>
0145 class RField<std::pair<T1, T2>> final : public RPairField {
0146    using ContainerT = typename std::pair<T1, T2>;
0147 
0148 private:
0149    static std::array<std::unique_ptr<RFieldBase>, 2> BuildItemFields()
0150    {
0151       return {std::make_unique<RField<T1>>("_0"), std::make_unique<RField<T2>>("_1")};
0152    }
0153 
0154    static std::array<std::size_t, 2> BuildItemOffsets()
0155    {
0156       auto pair = ContainerT();
0157       auto offsetFirst = reinterpret_cast<std::uintptr_t>(&(pair.first)) - reinterpret_cast<std::uintptr_t>(&pair);
0158       auto offsetSecond = reinterpret_cast<std::uintptr_t>(&(pair.second)) - reinterpret_cast<std::uintptr_t>(&pair);
0159       return {offsetFirst, offsetSecond};
0160    }
0161 
0162 public:
0163    static std::string TypeName() { return "std::pair<" + RField<T1>::TypeName() + "," + RField<T2>::TypeName() + ">"; }
0164    explicit RField(std::string_view name) : RPairField(name, BuildItemFields(), BuildItemOffsets())
0165    {
0166       R__ASSERT(fMaxAlignment >= std::max(alignof(T1), alignof(T2)));
0167       R__ASSERT(fSize >= sizeof(ContainerT));
0168    }
0169    RField(RField &&other) = default;
0170    RField &operator=(RField &&other) = default;
0171    ~RField() final = default;
0172 };
0173 
0174 ////////////////////////////////////////////////////////////////////////////////
0175 /// Template specializations for C++ std::tuple
0176 ////////////////////////////////////////////////////////////////////////////////
0177 
0178 /// The generic field for `std::tuple<Ts...>` types
0179 class RTupleField : public RRecordField {
0180 private:
0181    static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);
0182 
0183 protected:
0184    RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
0185                const std::vector<std::size_t> &offsets);
0186 
0187 public:
0188    RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
0189    RTupleField(RTupleField &&other) = default;
0190    RTupleField &operator=(RTupleField &&other) = default;
0191    ~RTupleField() override = default;
0192 };
0193 
0194 template <typename... ItemTs>
0195 class RField<std::tuple<ItemTs...>> final : public RTupleField {
0196    using ContainerT = typename std::tuple<ItemTs...>;
0197 
0198 private:
0199    template <typename HeadT, typename... TailTs>
0200    static std::string BuildItemTypes()
0201    {
0202       std::string result = RField<HeadT>::TypeName();
0203       if constexpr (sizeof...(TailTs) > 0)
0204          result += "," + BuildItemTypes<TailTs...>();
0205       return result;
0206    }
0207 
0208    template <typename HeadT, typename... TailTs>
0209    static void _BuildItemFields(std::vector<std::unique_ptr<RFieldBase>> &itemFields, unsigned int index = 0)
0210    {
0211       itemFields.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
0212       if constexpr (sizeof...(TailTs) > 0)
0213          _BuildItemFields<TailTs...>(itemFields, index + 1);
0214    }
0215    static std::vector<std::unique_ptr<RFieldBase>> BuildItemFields()
0216    {
0217       std::vector<std::unique_ptr<RFieldBase>> result;
0218       _BuildItemFields<ItemTs...>(result);
0219       return result;
0220    }
0221 
0222    template <unsigned Index, typename HeadT, typename... TailTs>
0223    static void _BuildItemOffsets(std::vector<std::size_t> &offsets, const ContainerT &tuple)
0224    {
0225       auto offset =
0226          reinterpret_cast<std::uintptr_t>(&std::get<Index>(tuple)) - reinterpret_cast<std::uintptr_t>(&tuple);
0227       offsets.emplace_back(offset);
0228       if constexpr (sizeof...(TailTs) > 0)
0229          _BuildItemOffsets<Index + 1, TailTs...>(offsets, tuple);
0230    }
0231    static std::vector<std::size_t> BuildItemOffsets()
0232    {
0233       std::vector<std::size_t> result;
0234       _BuildItemOffsets<0, ItemTs...>(result, ContainerT());
0235       return result;
0236    }
0237 
0238 public:
0239    static std::string TypeName() { return "std::tuple<" + BuildItemTypes<ItemTs...>() + ">"; }
0240    explicit RField(std::string_view name) : RTupleField(name, BuildItemFields(), BuildItemOffsets())
0241    {
0242       R__ASSERT(fMaxAlignment >= std::max({alignof(ItemTs)...}));
0243       R__ASSERT(fSize >= sizeof(ContainerT));
0244    }
0245    RField(RField &&other) = default;
0246    RField &operator=(RField &&other) = default;
0247    ~RField() final = default;
0248 };
0249 
0250 } // namespace ROOT
0251 
0252 #endif