File indexing completed on 2025-12-15 10:28:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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/RNTupleTypes.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 }
0035
0036 namespace Internal {
0037 std::unique_ptr<RFieldBase> CreateEmulatedRecordField(std::string_view fieldName,
0038 std::vector<std::unique_ptr<RFieldBase>> itemFields,
0039 std::string_view emulatedFromType);
0040 }
0041
0042
0043
0044 class RRecordField : public RFieldBase {
0045 friend std::unique_ptr<RFieldBase>
0046 Internal::CreateEmulatedRecordField(std::string_view fieldName, 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);
0063
0064
0065
0066
0067 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
0068 std::string_view emulatedFromType);
0069
0070 protected:
0071 std::size_t fMaxAlignment = 1;
0072 std::size_t fSize = 0;
0073 std::vector<std::size_t> fOffsets;
0074
0075 std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const;
0076
0077 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
0078
0079 void ConstructValue(void *where) const final;
0080 std::unique_ptr<RDeleter> GetDeleter() const final;
0081
0082 std::size_t AppendImpl(const void *from) final;
0083 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0084 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0085
0086
0087
0088 RRecordField(std::string_view fieldName, std::string_view typeName);
0089
0090 void AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields);
0091
0092 template <std::size_t N>
0093 void AttachItemFields(std::array<std::unique_ptr<RFieldBase>, N> itemFields)
0094 {
0095 fTraits |= kTraitTrivialType;
0096 for (unsigned i = 0; i < N; ++i) {
0097 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
0098 fSize += GetItemPadding(fSize, itemFields[i]->GetAlignment()) + itemFields[i]->GetValueSize();
0099 fTraits &= itemFields[i]->GetTraits();
0100 Attach(std::move(itemFields[i]));
0101 }
0102
0103
0104 fSize += GetItemPadding(fSize, fMaxAlignment);
0105 }
0106
0107 void ReconcileOnDiskField(const RNTupleDescriptor &desc) override;
0108
0109 public:
0110
0111
0112
0113
0114 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
0115 RRecordField(RRecordField &&other) = default;
0116 RRecordField &operator=(RRecordField &&other) = default;
0117 ~RRecordField() override = default;
0118
0119 std::vector<RValue> SplitValue(const RValue &value) const final;
0120 size_t GetValueSize() const final
0121 {
0122
0123 return std::max<size_t>(1ul, fSize);
0124 }
0125 size_t GetAlignment() const final { return fMaxAlignment; }
0126 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0127
0128 const std::vector<std::size_t> &GetOffsets() const { return fOffsets; }
0129 };
0130
0131
0132
0133
0134
0135
0136 class RPairField : public RRecordField {
0137 private:
0138 static std::string GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);
0139
0140 protected:
0141 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
0142 const std::array<std::size_t, 2> &offsets);
0143
0144 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0145
0146 void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0147
0148 public:
0149 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields);
0150 RPairField(RPairField &&other) = default;
0151 RPairField &operator=(RPairField &&other) = default;
0152 ~RPairField() override = default;
0153 };
0154
0155 template <typename T1, typename T2>
0156 class RField<std::pair<T1, T2>> final : public RPairField {
0157 using ContainerT = typename std::pair<T1, T2>;
0158
0159 private:
0160 static std::array<std::unique_ptr<RFieldBase>, 2> BuildItemFields()
0161 {
0162 return {std::make_unique<RField<T1>>("_0"), std::make_unique<RField<T2>>("_1")};
0163 }
0164
0165 static std::array<std::size_t, 2> BuildItemOffsets()
0166 {
0167 auto pair = ContainerT();
0168 auto offsetFirst = reinterpret_cast<std::uintptr_t>(&(pair.first)) - reinterpret_cast<std::uintptr_t>(&pair);
0169 auto offsetSecond = reinterpret_cast<std::uintptr_t>(&(pair.second)) - reinterpret_cast<std::uintptr_t>(&pair);
0170 return {offsetFirst, offsetSecond};
0171 }
0172
0173 public:
0174 static std::string TypeName() { return "std::pair<" + RField<T1>::TypeName() + "," + RField<T2>::TypeName() + ">"; }
0175 explicit RField(std::string_view name) : RPairField(name, BuildItemFields(), BuildItemOffsets())
0176 {
0177 R__ASSERT(fMaxAlignment >= std::max(alignof(T1), alignof(T2)));
0178 R__ASSERT(fSize >= sizeof(ContainerT));
0179 }
0180 RField(RField &&other) = default;
0181 RField &operator=(RField &&other) = default;
0182 ~RField() final = default;
0183 };
0184
0185
0186
0187
0188
0189
0190 class RTupleField : public RRecordField {
0191 private:
0192 static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);
0193
0194 protected:
0195 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
0196 const std::vector<std::size_t> &offsets);
0197
0198 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0199
0200 void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
0201
0202 public:
0203 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
0204 RTupleField(RTupleField &&other) = default;
0205 RTupleField &operator=(RTupleField &&other) = default;
0206 ~RTupleField() override = default;
0207 };
0208
0209 template <typename... ItemTs>
0210 class RField<std::tuple<ItemTs...>> final : public RTupleField {
0211 using ContainerT = typename std::tuple<ItemTs...>;
0212
0213 private:
0214 template <typename HeadT, typename... TailTs>
0215 static std::string BuildItemTypes()
0216 {
0217 std::string result = RField<HeadT>::TypeName();
0218 if constexpr (sizeof...(TailTs) > 0)
0219 result += "," + BuildItemTypes<TailTs...>();
0220 return result;
0221 }
0222
0223 template <typename HeadT, typename... TailTs>
0224 static void _BuildItemFields(std::vector<std::unique_ptr<RFieldBase>> &itemFields, unsigned int index = 0)
0225 {
0226 itemFields.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
0227 if constexpr (sizeof...(TailTs) > 0)
0228 _BuildItemFields<TailTs...>(itemFields, index + 1);
0229 }
0230 static std::vector<std::unique_ptr<RFieldBase>> BuildItemFields()
0231 {
0232 std::vector<std::unique_ptr<RFieldBase>> result;
0233 _BuildItemFields<ItemTs...>(result);
0234 return result;
0235 }
0236
0237 template <unsigned Index, typename HeadT, typename... TailTs>
0238 static void _BuildItemOffsets(std::vector<std::size_t> &offsets, const ContainerT &tuple)
0239 {
0240 auto offset =
0241 reinterpret_cast<std::uintptr_t>(&std::get<Index>(tuple)) - reinterpret_cast<std::uintptr_t>(&tuple);
0242 offsets.emplace_back(offset);
0243 if constexpr (sizeof...(TailTs) > 0)
0244 _BuildItemOffsets<Index + 1, TailTs...>(offsets, tuple);
0245 }
0246 static std::vector<std::size_t> BuildItemOffsets()
0247 {
0248 std::vector<std::size_t> result;
0249 _BuildItemOffsets<0, ItemTs...>(result, ContainerT());
0250 return result;
0251 }
0252
0253 public:
0254 static std::string TypeName() { return "std::tuple<" + BuildItemTypes<ItemTs...>() + ">"; }
0255 explicit RField(std::string_view name) : RTupleField(name, BuildItemFields(), BuildItemOffsets())
0256 {
0257 R__ASSERT(fMaxAlignment >= std::max({alignof(ItemTs)...}));
0258 R__ASSERT(fSize >= sizeof(ContainerT));
0259 }
0260 RField(RField &&other) = default;
0261 RField &operator=(RField &&other) = default;
0262 ~RField() final = default;
0263 };
0264
0265 }
0266
0267 #endif