Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
RNTupleProcessorEntry.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleProcessor.hxx
2/// \author Florine de Geus <florine.de.geus@cern.ch>
3/// \date 2025-06-25
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15#ifndef ROOT_RNTupleProcessorEntry
16#define ROOT_RNTupleProcessorEntry
17
18#include <ROOT/RNTupleModel.hxx>
19#include <ROOT/RFieldBase.hxx>
20
21#include <cassert>
22#include <string>
23#include <string_view>
24#include <unordered_map>
25#include <vector>
26
27namespace ROOT {
28namespace Experimental {
29namespace Internal {
30/**
31\class ROOT::Experimental::RNTupleProcessorProvenance
32\ingroup NTuple
33\brief Identifies how a processor is composed.
34
35The processor provenance is used in RNTupleProcessorEntry to identify how an (auxiliary) field in a composed processor
36can be accessed.
37*/
38// clang-format on
40private:
41 std::string fProvenance{};
42
43public:
45 RNTupleProcessorProvenance(const std::string &provenance) : fProvenance(provenance) {}
46
47 /////////////////////////////////////////////////////////////////////////////
48 /// \brief Get the full processor provenance, in the form of "x.y.z".
49 std::string Get() const { return fProvenance; }
50
51 /////////////////////////////////////////////////////////////////////////////
52 /// \brief Add a new processor to the provenance.
53 ///
54 /// \param[in] processorName Name of the processor to add.
55 ///
56 /// \return The updated provenance.
57 RNTupleProcessorProvenance Evolve(const std::string &processorName) const
58 {
59 if (fProvenance.empty())
60 return RNTupleProcessorProvenance(processorName);
61
62 return RNTupleProcessorProvenance(fProvenance + "." + processorName);
63 }
64
65 /////////////////////////////////////////////////////////////////////////////
66 /// \brief Check whether the provenance subsumes the provenance in `other`.
67 ///
68 /// \param[in] other The other provenance
69 bool Contains(const RNTupleProcessorProvenance &other) const
70 {
71 return fProvenance.rfind(other.fProvenance) != std::string::npos;
72 }
73
74 /////////////////////////////////////////////////////////////////////////////
75 /// \brief Check whether the provided field name contains this provenance.
76 ///
77 /// \param[in] fieldName Field name to check.
78 bool IsPresentInFieldName(std::string_view fieldName) const
79 {
80 return !fProvenance.empty() && fieldName.find(fProvenance + ".") == 0;
81 }
82};
83
84// clang-format off
85/**
86\class ROOT::Experimental::Internal::RNTupleProcessorEntry
87\ingroup NTuple
88\brief Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing values.
89*/
90// clang-format on
92public:
93 // We don't use RFieldTokens here, because it (semantically) does not make sense for the entry to be fixed to the
94 // schema ID of a particular model.
95 using FieldIndex_t = std::uint64_t;
96
97private:
108
109 std::vector<RProcessorValue> fProcessorValues;
110 std::unordered_map<std::string, FieldIndex_t> fFieldName2Index;
111
112public:
113 /////////////////////////////////////////////////////////////////////////////
114 /// \brief Set the validity of a field, i.e. whether it is possible to read its value in the current entry.
115 ///
116 /// \param[in] fieldIdx The index of the field in the entry.
117 /// \param[in] isValid The new validity of the field.
118 void SetFieldValidity(FieldIndex_t fieldIdx, bool isValid)
119 {
120 assert(fieldIdx < fProcessorValues.size());
121 fProcessorValues[fieldIdx].fIsValid = isValid;
122 }
123
124 /////////////////////////////////////////////////////////////////////////////
125 /// \brief Check whether a field is valid for reading.
126 ///
127 /// \param[in] fieldIdx The index of the field in the entry.
128 bool IsValidField(FieldIndex_t fieldIdx) const
129 {
130 assert(fieldIdx < fProcessorValues.size());
131 return fProcessorValues[fieldIdx].fIsValid;
132 }
133
134 /////////////////////////////////////////////////////////////////////////////
135 /// \brief Find the name of a field from its field index.
136 ///
137 /// \param[in] fieldIdx The index of the field in the entry.
138 ///
139 /// \warning This function has linear complexity, only use it for more helpful error messages!
140 const std::string &FindFieldName(FieldIndex_t fieldIdx) const
141 {
142 assert(fieldIdx < fProcessorValues.size());
143
144 for (const auto &[fieldName, index] : fFieldName2Index) {
145 if (index == fieldIdx) {
146 return fieldName;
147 }
148 }
149 // Should never happen, but avoid compiler warning about "returning reference to local temporary object".
150 R__ASSERT(false);
151 static const std::string empty = "";
152 return empty;
153 }
154
155 /////////////////////////////////////////////////////////////////////////////
156 /// \brief Find the field index of the provided field in the entry.
157 ///
158 /// \param[in] fieldName The name of the field in the entry.
159 ///
160 /// \return A `std::optional` containing the field index if it was found.
161 std::optional<FieldIndex_t> FindFieldIndex(std::string_view fieldName) const
162 {
163 auto it = fFieldName2Index.find(std::string(fieldName));
164 if (it == fFieldName2Index.end()) {
165 return std::nullopt;
166 }
167 return it->second;
168 }
169
170 /////////////////////////////////////////////////////////////////////////////
171 /// \brief Add a new field to the entry.
172 ///
173 /// \param[in] fieldName Name of the field to add.
174 /// \param[in] field Reference to the field to add, used to to create its corresponding RValue.
175 /// \param[in] valuePtr Pointer to an object corresponding to the field's type to bind to its value. If this is a
176 /// `nullptr`, a pointer will be created.
177 /// \param[in] provenance Processor provenance of the field.
178 ///
179 /// \return The field index of the newly added field.
180 FieldIndex_t AddField(std::string_view fieldName, ROOT::RFieldBase &field, void *valuePtr,
181 const RNTupleProcessorProvenance &provenance)
182 {
183 if (FindFieldIndex(fieldName))
184 throw ROOT::RException(
185 R__FAIL("field \"" + field.GetQualifiedFieldName() + "\" is already present in the entry"));
186
187 auto value = field.CreateValue();
188 if (valuePtr)
189 value.BindRawPtr(valuePtr);
190 auto fieldIdx = fProcessorValues.size();
191 fFieldName2Index[std::string(fieldName)] = fieldIdx;
192 fProcessorValues.emplace_back(RProcessorValue(std::move(value), true, provenance));
193
194 return fieldIdx;
195 }
196
197 /////////////////////////////////////////////////////////////////////////////
198 /// \brief Update a field in the entry, preserving the value pointer.
199 ///
200 /// \param[in] fieldIdx Index of the field to update.
201 /// \param[in] field The new field to use in the entry.
203 {
204 assert(fieldIdx < fProcessorValues.size());
205
206 auto currValuePtr = fProcessorValues[fieldIdx].fValue.GetPtr<void>();
207 auto value = field.CreateValue();
208 value.Bind(currValuePtr);
209 fProcessorValues[fieldIdx].fValue = value;
210 }
211
212 /////////////////////////////////////////////////////////////////////////////
213 /// \brief Bind a new value pointer to a field in the entry.
214 ///
215 /// \param[in] fieldIdx The index of the field in the entry.
216 /// \param[in] valuePtr Pointer to the value to bind to the field.
217 void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr)
218 {
219 assert(fieldIdx < fProcessorValues.size());
220 fProcessorValues[fieldIdx].fValue.BindRawPtr(valuePtr);
221 }
222
223 /////////////////////////////////////////////////////////////////////////////
224 /// \brief Read the field value corresponding to the given field index for the provided entry index.
225 ///
226 /// \param[in] fieldIdx The index of the field in the entry.
227 /// \param[in] entryIdx The entry number to read.
229 {
230 assert(fieldIdx < fProcessorValues.size());
231
232 if (fProcessorValues[fieldIdx].fIsValid) {
233 fProcessorValues[fieldIdx].fValue.Read(entryIdx);
234 }
235 }
236
237 /////////////////////////////////////////////////////////////////////////////
238 /// \brief Get a pointer to the value for the field represented by the provided field index.
239 ///
240 /// \tparam T The type of the pointer.
241 ///
242 /// \param[in] fieldIdx The index of the field in the entry.
243 ///
244 /// \return A shared pointer of type `T` with the field's value.
245 template <typename T>
246 std::shared_ptr<T> GetPtr(FieldIndex_t fieldIdx) const
247 {
248 assert(fieldIdx < fProcessorValues.size());
249
250 if (fProcessorValues[fieldIdx].fIsValid)
251 return fProcessorValues[fieldIdx].fValue.GetPtr<T>();
252
253 return nullptr;
254 }
255
256 /////////////////////////////////////////////////////////////////////////////
257 /// \brief Get a reference to a field in the entry.
258 ///
259 /// \param[in] fieldIdx The index of the field in the entry.
261 {
262 assert(fieldIdx < fProcessorValues.size());
263 return fProcessorValues[fieldIdx].fValue.GetField();
264 }
265
266 /////////////////////////////////////////////////////////////////////////////
267 /// \brief Get the processor provenance of a field in the entry.
268 ///
269 /// \param[in] fieldIdx The index of the field in the entry.
271 {
272 assert(fieldIdx < fProcessorValues.size());
273 return fProcessorValues[fieldIdx].fProcessorProvenance;
274 }
275
276 /////////////////////////////////////////////////////////////////////////////
277 /// \brief Get the name of a field in the entry, including processor name prefixes in the case of auxiliary fields.
278 ///
279 /// \param[in] fieldIdx The index of the field in the entry.
280 std::string GetFieldName(FieldIndex_t fieldIdx) const
281 {
282 assert(fieldIdx < fProcessorValues.size());
283 return fProcessorValues[fieldIdx].fProcessorProvenance.Get() + "." +
284 fProcessorValues[fieldIdx].fValue.GetField().GetQualifiedFieldName();
285 }
286
287 /////////////////////////////////////////////////////////////////////////////
288 /// \brief Get all field indices of this entry.
289 std::unordered_set<FieldIndex_t> GetFieldIndices() const
290 {
291 // Field indices are sequentially assigned, and the entry (currently) offers no way to remove fields, so we can
292 // just generate and return a set {0, ..., |fProcessorValues| - 1}.
293 std::unordered_set<FieldIndex_t> fieldIdxs(fProcessorValues.size());
294 std::generate_n(std::inserter(fieldIdxs, fieldIdxs.begin()), fProcessorValues.size(),
295 [i = 0]() mutable { return i++; });
296 return fieldIdxs;
297 }
298};
299} // namespace Internal
300} // namespace Experimental
301} // namespace ROOT
302
303#endif // ROOT_RNTupleProcessorEntry
#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
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
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
Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing...
FieldIndex_t AddField(std::string_view fieldName, ROOT::RFieldBase &field, void *valuePtr, const RNTupleProcessorProvenance &provenance)
Add a new field to the entry.
std::unordered_set< FieldIndex_t > GetFieldIndices() const
Get all field indices of this entry.
std::string GetFieldName(FieldIndex_t fieldIdx) const
Get the name of a field in the entry, including processor name prefixes in the case of auxiliary fiel...
void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr)
Bind a new value pointer to a field in the entry.
void UpdateField(FieldIndex_t fieldIdx, ROOT::RFieldBase &field)
Update a field in the entry, preserving the value pointer.
const ROOT::RFieldBase & GetField(FieldIndex_t fieldIdx) const
Get a reference to a field in the entry.
std::optional< FieldIndex_t > FindFieldIndex(std::string_view fieldName) const
Find the field index of the provided field in the entry.
bool IsValidField(FieldIndex_t fieldIdx) const
Check whether a field is valid for reading.
const std::string & FindFieldName(FieldIndex_t fieldIdx) const
Find the name of a field from its field index.
std::unordered_map< std::string, FieldIndex_t > fFieldName2Index
void ReadValue(FieldIndex_t fieldIdx, ROOT::NTupleSize_t entryIdx)
Read the field value corresponding to the given field index for the provided entry index.
void SetFieldValidity(FieldIndex_t fieldIdx, bool isValid)
Set the validity of a field, i.e.
const RNTupleProcessorProvenance & GetFieldProvenance(FieldIndex_t fieldIdx) const
Get the processor provenance of a field in the entry.
std::shared_ptr< T > GetPtr(FieldIndex_t fieldIdx) const
Get a pointer to the value for the field represented by the provided field index.
std::string Get() const
Get the full processor provenance, in the form of "x.y.z".
bool Contains(const RNTupleProcessorProvenance &other) const
Check whether the provenance subsumes the provenance in other.
bool IsPresentInFieldName(std::string_view fieldName) const
Check whether the provided field name contains this provenance.
RNTupleProcessorProvenance Evolve(const std::string &processorName) const
Add a new processor to the provenance.
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.
A field translates read and write calls from/to underlying columns to/from tree values.
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....
Namespace for ROOT features in testing.
Definition TROOT.h:100
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RProcessorValue(ROOT::RFieldBase::RValue &&value, bool isValid, RNTupleProcessorProvenance provenance)