Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldRecord.hxx
Go to the documentation of this file.
1/// \file ROOT/RField/Fundamental.hxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-09
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#ifndef ROOT_RField_Record
15#define ROOT_RField_Record
16
17#ifndef ROOT_RField
18#error "Please include RField.hxx!"
19#endif
20
21#include <ROOT/RFieldBase.hxx>
22#include <ROOT/RNTupleTypes.hxx>
23
24#include <string>
25#include <string_view>
26#include <tuple>
27#include <utility>
28#include <vector>
29
30namespace ROOT {
31
32namespace Detail {
33class RFieldVisitor;
34} // namespace Detail
35
36namespace Internal {
37std::unique_ptr<RFieldBase> CreateEmulatedRecordField(std::string_view fieldName,
38 std::vector<std::unique_ptr<RFieldBase>> itemFields,
39 std::string_view emulatedFromType);
40} // namespace Internal
41
42/// The field for an untyped record. The subfields are stored consecutively in a memory block, i.e.
43/// the memory layout is identical to one that a C++ struct would have
44class RRecordField : public RFieldBase {
45 friend std::unique_ptr<RFieldBase>
46 Internal::CreateEmulatedRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
47 std::string_view emulatedFromType);
48
49 class RRecordDeleter : public RDeleter {
50 private:
51 std::vector<std::unique_ptr<RDeleter>> fItemDeleters;
52 std::vector<std::size_t> fOffsets;
53
54 public:
55 RRecordDeleter(std::vector<std::unique_ptr<RDeleter>> itemDeleters, const std::vector<std::size_t> &offsets)
56 : fItemDeleters(std::move(itemDeleters)), fOffsets(offsets)
57 {
58 }
59 void operator()(void *objPtr, bool dtorOnly) final;
60 };
61
62 RRecordField(std::string_view name, const RRecordField &source); // Used by CloneImpl()
63
64 /// If `emulatedFromType` is non-empty, this field was created as a replacement for a ClassField that we lack a
65 /// dictionary for and reconstructed from the on-disk information.
66 /// Used by the public constructor and by Internal::CreateEmulatedRecordField().
67 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
68 std::string_view emulatedFromType);
69
70protected:
71 std::size_t fMaxAlignment = 1;
72 std::size_t fSize = 0;
73 std::vector<std::size_t> fOffsets;
74
75 std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const;
76
77 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
78
79 void ConstructValue(void *where) const final;
80 std::unique_ptr<RDeleter> GetDeleter() const final;
81
82 std::size_t AppendImpl(const void *from) final;
85
86 /// Used by RPairField and RTupleField descendants. These descendants have their own logic to attach the subfields
87 /// that ensure that the resulting memory layout matches std::pair or std::tuple, resp.
88 RRecordField(std::string_view fieldName, std::string_view typeName);
89
90 void AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields);
91
92 template <std::size_t N>
93 void AttachItemFields(std::array<std::unique_ptr<RFieldBase>, N> itemFields)
94 {
96 for (unsigned i = 0; i < N; ++i) {
98 fSize += GetItemPadding(fSize, itemFields[i]->GetAlignment()) + itemFields[i]->GetValueSize();
99 fTraits &= itemFields[i]->GetTraits();
100 Attach(std::move(itemFields[i]));
101 }
102 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
103 // requirements of the type with strictest alignment
105 }
106
107 void ReconcileOnDiskField(const RNTupleDescriptor &desc) override;
108
109public:
110 /// Construct a RRecordField based on a vector of child fields. The ownership of the child fields is transferred
111 /// to the RRecordField instance.
112 /// The resulting field uses a memory layout for its values as if there was a struct consisting of the passed
113 /// item fields.
114 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
117 ~RRecordField() override = default;
118
119 std::vector<RValue> SplitValue(const RValue &value) const final;
121 {
122 // The minimum size is 1 to support having vectors of empty records
123 return std::max<size_t>(1ul, fSize);
124 }
127
128 const std::vector<std::size_t> &GetOffsets() const { return fOffsets; }
129};
130
131////////////////////////////////////////////////////////////////////////////////
132/// Template specializations for C++ std::pair
133////////////////////////////////////////////////////////////////////////////////
134
135/// The generic field for `std::pair<T1, T2>` types
136class RPairField : public RRecordField {
137private:
138 static std::string GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);
139
140protected:
141 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
142 const std::array<std::size_t, 2> &offsets);
143
144 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
145
146 void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
147
148public:
149 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> itemFields);
152 ~RPairField() override = default;
153};
154
155template <typename T1, typename T2>
156class RField<std::pair<T1, T2>> final : public RPairField {
157 using ContainerT = typename std::pair<T1, T2>;
158
159private:
160 static std::array<std::unique_ptr<RFieldBase>, 2> BuildItemFields()
161 {
162 return {std::make_unique<RField<T1>>("_0"), std::make_unique<RField<T2>>("_1")};
163 }
164
165 static std::array<std::size_t, 2> BuildItemOffsets()
166 {
167 auto pair = ContainerT();
168 auto offsetFirst = reinterpret_cast<std::uintptr_t>(&(pair.first)) - reinterpret_cast<std::uintptr_t>(&pair);
169 auto offsetSecond = reinterpret_cast<std::uintptr_t>(&(pair.second)) - reinterpret_cast<std::uintptr_t>(&pair);
170 return {offsetFirst, offsetSecond};
171 }
172
173public:
174 static std::string TypeName() { return "std::pair<" + RField<T1>::TypeName() + "," + RField<T2>::TypeName() + ">"; }
175 explicit RField(std::string_view name) : RPairField(name, BuildItemFields(), BuildItemOffsets())
176 {
177 R__ASSERT(fMaxAlignment >= std::max(alignof(T1), alignof(T2)));
178 R__ASSERT(fSize >= sizeof(ContainerT));
179 }
180 RField(RField &&other) = default;
181 RField &operator=(RField &&other) = default;
183};
184
185////////////////////////////////////////////////////////////////////////////////
186/// Template specializations for C++ std::tuple
187////////////////////////////////////////////////////////////////////////////////
188
189/// The generic field for `std::tuple<Ts...>` types
191private:
192 static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);
193
194protected:
195 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
196 const std::vector<std::size_t> &offsets);
197
198 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
199
200 void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
201
202public:
203 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields);
206 ~RTupleField() override = default;
207};
208
209template <typename... ItemTs>
210class RField<std::tuple<ItemTs...>> final : public RTupleField {
211 using ContainerT = typename std::tuple<ItemTs...>;
212
213private:
214 template <typename HeadT, typename... TailTs>
215 static std::string BuildItemTypes()
216 {
217 std::string result = RField<HeadT>::TypeName();
218 if constexpr (sizeof...(TailTs) > 0)
219 result += "," + BuildItemTypes<TailTs...>();
220 return result;
221 }
222
223 template <typename HeadT, typename... TailTs>
224 static void _BuildItemFields(std::vector<std::unique_ptr<RFieldBase>> &itemFields, unsigned int index = 0)
225 {
226 itemFields.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
227 if constexpr (sizeof...(TailTs) > 0)
228 _BuildItemFields<TailTs...>(itemFields, index + 1);
229 }
230 static std::vector<std::unique_ptr<RFieldBase>> BuildItemFields()
231 {
232 std::vector<std::unique_ptr<RFieldBase>> result;
233 _BuildItemFields<ItemTs...>(result);
234 return result;
235 }
236
237 template <unsigned Index, typename HeadT, typename... TailTs>
238 static void _BuildItemOffsets(std::vector<std::size_t> &offsets, const ContainerT &tuple)
239 {
240 auto offset =
241 reinterpret_cast<std::uintptr_t>(&std::get<Index>(tuple)) - reinterpret_cast<std::uintptr_t>(&tuple);
242 offsets.emplace_back(offset);
243 if constexpr (sizeof...(TailTs) > 0)
244 _BuildItemOffsets<Index + 1, TailTs...>(offsets, tuple);
245 }
246 static std::vector<std::size_t> BuildItemOffsets()
247 {
248 std::vector<std::size_t> result;
249 _BuildItemOffsets<0, ItemTs...>(result, ContainerT());
250 return result;
251 }
252
253public:
254 static std::string TypeName() { return "std::tuple<" + BuildItemTypes<ItemTs...>() + ">"; }
255 explicit RField(std::string_view name) : RTupleField(name, BuildItemFields(), BuildItemOffsets())
256 {
257 R__ASSERT(fMaxAlignment >= std::max({alignof(ItemTs)...}));
258 R__ASSERT(fSize >= sizeof(ContainerT));
259 }
260 RField(RField &&other) = default;
261 RField &operator=(RField &&other) = default;
263};
264
265} // namespace ROOT
266
267#endif
dim_t fSize
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
Abstract base class for classes implementing the visitor design pattern.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::size_t fMaxAlignment
Definition RField.hxx:145
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
A functor to release the memory acquired by CreateValue() (memory and constructor).
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
@ kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:292
~RField() final=default
RField & operator=(RField &&other)=default
static std::string TypeName()
Definition RField.hxx:294
RField(std::string_view name)
Definition RField.hxx:295
The on-storage metadata of an RNTuple.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Template specializations for C++ std::pair.
static std::string GetTypeList(const std::array< std::unique_ptr< RFieldBase >, 2 > &itemFields)
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
~RPairField() override=default
RPairField(std::string_view fieldName, std::array< std::unique_ptr< RFieldBase >, 2 > itemFields, const std::array< std::size_t, 2 > &offsets)
RPairField(RPairField &&other)=default
RPairField & operator=(RPairField &&other)=default
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::vector< std::size_t > fOffsets
RRecordDeleter(std::vector< std::unique_ptr< RDeleter > > itemDeleters, const std::vector< std::size_t > &offsets)
std::vector< std::unique_ptr< RDeleter > > fItemDeleters
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:640
The field for an untyped record.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Definition RField.cxx:658
std::size_t fMaxAlignment
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:580
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:601
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
RRecordField & operator=(RRecordField &&other)=default
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:498
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:670
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:648
void AttachItemFields(std::vector< std::unique_ptr< RFieldBase > > itemFields)
Definition RField.cxx:514
RRecordField(RRecordField &&other)=default
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:570
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:594
~RRecordField() override=default
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Definition RField.cxx:633
std::vector< std::size_t > fOffsets
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:585
const std::vector< std::size_t > & GetOffsets() const
void ReconcileOnDiskField(const RNTupleDescriptor &desc) override
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:608
Template specializations for C++ std::tuple.
~RTupleField() override=default
RTupleField(RTupleField &&other)=default
static std::string GetTypeList(const std::vector< std::unique_ptr< RFieldBase > > &itemFields)
RTupleField & operator=(RTupleField &&other)=default
#define T2
Definition md5.inl:147
#define T1
Definition md5.inl:146
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:529
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.