Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
REntry.hxx
Go to the documentation of this file.
1/// \file ROOT/REntry.hxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \date 2018-07-19
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_REntry
14#define ROOT_REntry
15
16#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
18#include <ROOT/RFieldToken.hxx>
19#include <string_view>
20
21#include <TError.h>
22
23#include <algorithm>
24#include <iterator>
25#include <memory>
26#include <type_traits>
27#include <utility>
28#include <vector>
29#include <unordered_map>
30
31namespace ROOT {
32
34class RNTupleReader;
35
36namespace Experimental {
38
39namespace Internal {
40struct RNTupleAttrEntry;
41}
42} // namespace Experimental
43
44// clang-format off
45/**
46\class ROOT::REntry
47\ingroup NTuple
48\brief The REntry is a collection of values in an RNTuple corresponding to a complete row in the data set.
49
50The entry provides a memory-managed binder for a set of values read from fields in an RNTuple. The memory locations that are associated
51with values are managed through shared pointers.
52*/
53// clang-format on
54class REntry {
55 friend class RNTupleFillContext;
56 friend class RNTupleModel;
57 friend class RNTupleReader;
60
61private:
62 /// The entry must be linked to a specific model, identified by a model ID
63 std::uint64_t fModelId = 0;
64 /// The entry and its tokens are also linked to a specific schema, identified by a schema ID
65 std::uint64_t fSchemaId = 0;
66 /// Corresponds to the fields of the linked model
67 std::vector<ROOT::RFieldBase::RValue> fValues;
68 /// For fast lookup of token IDs given a (sub)field name present in the entry
69 std::unordered_map<std::string, std::size_t> fFieldName2Token;
70 /// To ensure that the entry is standalone, a copy of all field types
71 std::vector<std::string> fFieldTypes;
72
73 /// Creation of entries can be done by the RNTupleModel, the RNTupleReader, or the RNTupleWriter.
74 REntry() = default;
75 explicit REntry(std::uint64_t modelId, std::uint64_t schemaId) : fModelId(modelId), fSchemaId(schemaId) {}
76
78 {
79 fFieldName2Token[value.GetField().GetQualifiedFieldName()] = fValues.size();
80 fFieldTypes.push_back(value.GetField().GetTypeName());
81 fValues.emplace_back(std::move(value));
82 }
83
84 /// While building the entry, adds a new value for the field and returns the value's shared pointer
85 template <typename T>
86 std::shared_ptr<T> AddValue(ROOT::RField<T> &field)
87 {
89 fFieldTypes.push_back(field.GetTypeName());
90 auto value = field.CreateValue();
91 fValues.emplace_back(value);
92 // We know that the created RValue has the right type, skip the unnecessary check.
93 return std::static_pointer_cast<T>(value.template GetPtr<void>());
94 }
95
97 {
98 for (auto &v : fValues) {
99 v.Read(index);
100 }
101 }
102
103 std::size_t Append()
104 {
105 std::size_t bytesWritten = 0;
106 for (auto &v : fValues) {
107 bytesWritten += v.Append();
108 }
109 return bytesWritten;
110 }
111
113 {
114 if (fSchemaId != token.fSchemaId) {
115 throw RException(R__FAIL("invalid token for this entry, "
116 "make sure to use a token from a model with the same schema as this entry."));
117 }
118 }
119
120 /// This function has linear complexity, only use it for more helpful error messages!
121 const std::string &FindFieldName(ROOT::RFieldToken token) const
122 {
123 for (const auto &[fieldName, index] : fFieldName2Token) {
124 if (index == token.fIndex) {
125 return fieldName;
126 }
127 }
128 // Should never happen, but avoid compiler warning about "returning reference to local temporary object".
129 static const std::string empty = "";
130 return empty;
131 }
132
133 template <typename T>
134 void EnsureMatchingType(ROOT::RFieldToken token [[maybe_unused]]) const
135 {
136 if constexpr (!std::is_void_v<T>) {
137 if (!Internal::IsMatchingFieldType<T>(fFieldTypes[token.fIndex])) {
138 throw RException(R__FAIL("type mismatch for field " + FindFieldName(token) + ": " +
139 fFieldTypes[token.fIndex] + " vs. " + ROOT::RField<T>::TypeName()));
140 }
141 }
142 }
143
144public:
145 using ConstIterator_t = decltype(fValues)::const_iterator;
146
147 REntry(const REntry &other) = delete;
148 REntry &operator=(const REntry &other) = delete;
149 REntry(REntry &&other) = default;
150 REntry &operator=(REntry &&other) = default;
151 ~REntry() = default;
152
153 /// The ordinal of the (sub)field fieldName; can be used in other methods to address the corresponding value
154 ROOT::RFieldToken GetToken(std::string_view fieldName) const
155 {
156 auto it = fFieldName2Token.find(std::string(fieldName));
157 if (it == fFieldName2Token.end()) {
158 throw RException(R__FAIL("invalid field name: " + std::string(fieldName)));
159 }
160 return ROOT::RFieldToken(it->second, fSchemaId);
161 }
162
163 /// Create a new value for the field referenced by `token`.
165 {
166 EnsureMatchingModel(token);
167 fValues[token.fIndex].EmplaceNew();
168 }
169
170 /// Create a new value for the field referenced by its name.
171 void EmplaceNewValue(std::string_view fieldName) { EmplaceNewValue(GetToken(fieldName)); }
172
173 /// Bind the value for the field, referenced by `token`, to `objPtr`.
174 ///
175 /// \sa BindValue(std::string_view, std::shared_ptr<T>)
176 template <typename T>
177 void BindValue(ROOT::RFieldToken token, std::shared_ptr<T> objPtr)
178 {
179 EnsureMatchingModel(token);
181 fValues[token.fIndex].Bind(objPtr);
182 }
183
184 /// Bind the value for the field, referenced by its name, to `objPtr`.
185 ///
186 /// Ownership is shared with the caller and the object will be kept alive until it is replaced (by a call to
187 /// EmplaceNewValue, BindValue, or BindRawPtr) or the entry is destructed.
188 ///
189 /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to match the field and
190 /// object types.
191 template <typename T>
192 void BindValue(std::string_view fieldName, std::shared_ptr<T> objPtr)
193 {
194 BindValue<T>(GetToken(fieldName), objPtr);
195 }
196
197 /// Bind the value for the field, referenced by `token`, to `rawPtr`.
198 ///
199 /// \sa BindRawPtr(std::string_view, T *)
200 template <typename T>
201 void BindRawPtr(ROOT::RFieldToken token, T *rawPtr)
202 {
203 EnsureMatchingModel(token);
205 fValues[token.fIndex].BindRawPtr(rawPtr);
206 }
207
208 /// Bind the value for the field, referenced by its name, to `rawPtr`.
209 ///
210 /// The caller retains ownership of the object and must ensure it is kept alive when reading or writing using the
211 /// entry.
212 ///
213 /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to match the field and
214 /// object types.
215 template <typename T>
216 void BindRawPtr(std::string_view fieldName, T *rawPtr)
217 {
218 BindRawPtr<void>(GetToken(fieldName), rawPtr);
219 }
220
221 /// Get the (typed) pointer to the value for the field referenced by `token`.
222 ///
223 /// \sa GetPtr(std::string_view)
224 template <typename T>
225 std::shared_ptr<T> GetPtr(ROOT::RFieldToken token) const
226 {
227 EnsureMatchingModel(token);
229 return std::static_pointer_cast<T>(fValues[token.fIndex].GetPtr<void>());
230 }
231
232 /// Get the (typed) pointer to the value for the field referenced by `token`.
233 ///
234 /// Ownership is shared and the caller can continue to use the object after the entry is destructed.
235 ///
236 /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to use the returned pointer
237 /// according to the field type.
238 template <typename T>
239 std::shared_ptr<T> GetPtr(std::string_view fieldName) const
240 {
241 return GetPtr<T>(GetToken(fieldName));
242 }
243
244 const std::string &GetTypeName(ROOT::RFieldToken token) const
245 {
246 EnsureMatchingModel(token);
247 return fFieldTypes[token.fIndex];
248 }
249
250 const std::string &GetTypeName(std::string_view fieldName) const { return GetTypeName(GetToken(fieldName)); }
251
252 bool HasField(std::string_view fieldName) const { return fFieldName2Token.count(std::string(fieldName)) > 0; }
253
254 std::uint64_t GetModelId() const { return fModelId; }
255 std::uint64_t GetSchemaId() const { return fSchemaId; }
256
257 ConstIterator_t begin() const { return fValues.cbegin(); }
258 ConstIterator_t end() const { return fValues.cend(); }
259};
260
261} // namespace ROOT
262
263#endif
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:299
Class used to read a RNTupleAttrSet in the context of a RNTupleReader.
std::uint64_t fModelId
The entry must be linked to a specific model, identified by a model ID.
Definition REntry.hxx:63
friend class RNTupleModel
Definition REntry.hxx:56
void EmplaceNewValue(ROOT::RFieldToken token)
Create a new value for the field referenced by token.
Definition REntry.hxx:164
std::shared_ptr< T > GetPtr(ROOT::RFieldToken token) const
Get the (typed) pointer to the value for the field referenced by token.
Definition REntry.hxx:225
std::vector< ROOT::RFieldBase::RValue > fValues
Corresponds to the fields of the linked model.
Definition REntry.hxx:67
std::uint64_t GetModelId() const
Definition REntry.hxx:254
void BindValue(std::string_view fieldName, std::shared_ptr< T > objPtr)
Bind the value for the field, referenced by its name, to objPtr.
Definition REntry.hxx:192
void BindValue(ROOT::RFieldToken token, std::shared_ptr< T > objPtr)
Bind the value for the field, referenced by token, to objPtr.
Definition REntry.hxx:177
std::uint64_t GetSchemaId() const
Definition REntry.hxx:255
REntry(const REntry &other)=delete
const std::string & FindFieldName(ROOT::RFieldToken token) const
This function has linear complexity, only use it for more helpful error messages!
Definition REntry.hxx:121
const std::string & GetTypeName(ROOT::RFieldToken token) const
Definition REntry.hxx:244
void EnsureMatchingType(ROOT::RFieldToken token) const
Definition REntry.hxx:134
ConstIterator_t begin() const
Definition REntry.hxx:257
void Read(ROOT::NTupleSize_t index)
Definition REntry.hxx:96
std::vector< std::string > fFieldTypes
To ensure that the entry is standalone, a copy of all field types.
Definition REntry.hxx:71
std::uint64_t fSchemaId
The entry and its tokens are also linked to a specific schema, identified by a schema ID.
Definition REntry.hxx:65
void BindRawPtr(std::string_view fieldName, T *rawPtr)
Bind the value for the field, referenced by its name, to rawPtr.
Definition REntry.hxx:216
void AddValue(ROOT::RFieldBase::RValue &&value)
Definition REntry.hxx:77
std::shared_ptr< T > GetPtr(std::string_view fieldName) const
Get the (typed) pointer to the value for the field referenced by token.
Definition REntry.hxx:239
REntry()=default
Creation of entries can be done by the RNTupleModel, the RNTupleReader, or the RNTupleWriter.
REntry(std::uint64_t modelId, std::uint64_t schemaId)
Definition REntry.hxx:75
REntry & operator=(REntry &&other)=default
REntry & operator=(const REntry &other)=delete
ConstIterator_t end() const
Definition REntry.hxx:258
std::shared_ptr< T > AddValue(ROOT::RField< T > &field)
While building the entry, adds a new value for the field and returns the value's shared pointer.
Definition REntry.hxx:86
bool HasField(std::string_view fieldName) const
Definition REntry.hxx:252
void EnsureMatchingModel(ROOT::RFieldToken token) const
Definition REntry.hxx:112
void BindRawPtr(ROOT::RFieldToken token, T *rawPtr)
Bind the value for the field, referenced by token, to rawPtr.
Definition REntry.hxx:201
friend class RNTupleFillContext
Definition REntry.hxx:55
void EmplaceNewValue(std::string_view fieldName)
Create a new value for the field referenced by its name.
Definition REntry.hxx:171
std::size_t Append()
Definition REntry.hxx:103
decltype(fValues)::const_iterator ConstIterator_t
Definition REntry.hxx:145
friend class RNTupleReader
Definition REntry.hxx:57
~REntry()=default
REntry(REntry &&other)=default
ROOT::RFieldToken GetToken(std::string_view fieldName) const
The ordinal of the (sub)field fieldName; can be used in other methods to address the corresponding va...
Definition REntry.hxx:154
std::unordered_map< std::string, std::size_t > fFieldName2Token
For fast lookup of token IDs given a (sub)field name present in the entry.
Definition REntry.hxx:69
const std::string & GetTypeName(std::string_view fieldName) const
Definition REntry.hxx:250
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
RValue CreateValue()
Generates an object of the field's type, wraps it in a shared pointer and returns it as an RValue con...
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots (grandparent.parent....
const std::string & GetTypeName() const
A field token identifies a (sub)field in an entry.
std::size_t fIndex
The index of the field (top-level or registered subfield).
std::uint64_t fSchemaId
Safety check to prevent tokens from other models being used.
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:320
static std::string TypeName()
Definition RField.hxx:322
A context for filling entries (data) into clusters of an RNTuple.
Reads RNTuple data from storage.
Namespace for ROOT features in testing.
Definition TROOT.h:100
bool IsMatchingFieldType(const std::string &actualTypeName)
Helper to check if a given type name is the one expected of Field<T>.
Definition RField.hxx:559
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
A pair of scoped + meta entry used by the RNTupleAttrSetWriter.