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/RFieldBase.hxx>
19
20#include <cassert>
21#include <string>
22#include <string_view>
23#include <unordered_map>
24#include <vector>
25
26namespace ROOT {
27namespace Experimental {
28namespace Internal {
29/**
30\class ROOT::Experimental::RNTupleProcessorProvenance
31\ingroup NTuple
32\brief Identifies how a processor is composed.
33
34The processor provenance is used in RNTupleProcessorEntry to identify how an (auxiliary) field in a composed processor
35can be accessed.
36*/
37// clang-format on
39private:
40 std::string fProvenance{};
41
42public:
44 RNTupleProcessorProvenance(const std::string &provenance) : fProvenance(provenance) {}
45
46 /////////////////////////////////////////////////////////////////////////////
47 /// \brief Get the full processor provenance, in the form of "x.y.z".
48 std::string Get() const { return fProvenance; }
49
50 /////////////////////////////////////////////////////////////////////////////
51 /// \brief Add a new processor to the provenance.
52 ///
53 /// \param[in] processorName Name of the processor to add.
54 ///
55 /// \return The updated provenance.
56 RNTupleProcessorProvenance Evolve(const std::string &processorName) const
57 {
58 if (fProvenance.empty())
59 return RNTupleProcessorProvenance(processorName);
60
61 return RNTupleProcessorProvenance(fProvenance + "." + processorName);
62 }
63
64 /////////////////////////////////////////////////////////////////////////////
65 /// \brief Check whether the provenance subsumes the provenance in `other`.
66 ///
67 /// \param[in] other The other provenance
68 bool Contains(const RNTupleProcessorProvenance &other) const
69 {
70 return fProvenance.rfind(other.fProvenance) != std::string::npos;
71 }
72
73 /////////////////////////////////////////////////////////////////////////////
74 /// \brief Check whether the provided field name contains this provenance.
75 ///
76 /// \param[in] fieldName Field name to check.
77 bool IsPresentInFieldName(std::string_view fieldName) const
78 {
79 return !fProvenance.empty() && fieldName.find(fProvenance) == 0;
80 }
81
82 bool Empty() const { return fProvenance.empty(); }
83};
84
85// clang-format off
86/**
87\class ROOT::Experimental::Internal::RNTupleProcessorEntry
88\ingroup NTuple
89\brief Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing values.
90*/
91// clang-format on
93public:
94 // We don't use RFieldTokens here, because it (semantically) does not make sense for the entry to be fixed to the
95 // schema ID of a particular model.
96 using FieldIndex_t = std::uint64_t;
97
98private:
100 std::unique_ptr<ROOT::RFieldBase> fField;
105
106 RProcessorValue(std::unique_ptr<ROOT::RFieldBase> field, std::string_view qualifiedFieldName,
108 : fField(std::move(field)),
109 fQualifiedFieldName(qualifiedFieldName),
110 fValue(std::move(value)),
111 fIsValid(isValid),
112 fProcessorProvenance(std::move(provenance))
113 {
114 }
115 };
116
117 std::vector<RProcessorValue> fProcessorValues;
118 // Maps from the field name to all type alternatives for that field that have been added to the entry.
119 std::unordered_map<std::string, std::vector<FieldIndex_t>> fFieldName2Index;
120
121public:
122 /////////////////////////////////////////////////////////////////////////////
123 /// \brief Clear all fields from the entry.
124 void Clear()
125 {
126 fProcessorValues.clear();
127 fFieldName2Index.clear();
128 }
129
130 /////////////////////////////////////////////////////////////////////////////
131 /// \brief Reset the specified fields to a proto field, disconnected from any physical storage.
132 ///
133 /// \param[in] fieldIdx Fields to reset.
134 void ResetFields(const std::unordered_set<FieldIndex_t> &fieldIdxs)
135 {
136 for (auto fieldIdx : fieldIdxs) {
137 auto &value = fProcessorValues[fieldIdx];
138 UpdateField(fieldIdx, value.fField->Clone(value.fField->GetFieldName()));
139 }
140 }
141
142 /////////////////////////////////////////////////////////////////////////////
143 /// \brief Set the validity of a field, i.e. whether it is possible to read its value in the current entry.
144 ///
145 /// \param[in] fieldIdx The index of the field in the entry.
146 /// \param[in] isValid The new validity of the field.
147 void SetFieldValidity(FieldIndex_t fieldIdx, bool isValid)
148 {
149 assert(fieldIdx < fProcessorValues.size());
150 fProcessorValues[fieldIdx].fIsValid = isValid;
151 }
152
153 /////////////////////////////////////////////////////////////////////////////
154 /// \brief Check whether a field is valid for reading.
155 ///
156 /// \param[in] fieldIdx The index of the field in the entry.
157 bool IsValidField(FieldIndex_t fieldIdx) const
158 {
159 assert(fieldIdx < fProcessorValues.size());
160 return fProcessorValues[fieldIdx].fIsValid;
161 }
162
163 /////////////////////////////////////////////////////////////////////////////
164 /// \brief Find the name of a field from its field index.
165 ///
166 /// \param[in] fieldIdx The index of the field in the entry.
167 ///
168 /// \warning This function has linear complexity, only use it for more helpful error messages!
169 const std::string &FindFieldName(FieldIndex_t fieldIdx) const;
170
171 /////////////////////////////////////////////////////////////////////////////
172 /// \brief Find the field index of the provided field in the entry.
173 ///
174 /// \param[in] canonicalFieldName The name of the field in the entry, including its processor name prefixes and
175 /// parent field names, if applicable.
176 /// \param[in] typeName Type of the field, if relevant. If no type name is provided, the first field corresponding to
177 /// the provided name is returned.
178 ///
179 /// \return A `std::optional` containing the field index if it was found.
180 std::optional<FieldIndex_t>
181 FindFieldIndex(std::string_view canonicalFieldName, std::string_view typeName = "") const;
182
183 /////////////////////////////////////////////////////////////////////////////
184 /// \brief Add a new field to the entry.
185 ///
186 /// \param[in] qualifiedFieldName Name of the field to add, including its parent field if applicable.
187 /// \param[in] field Reference to the field to add, used to to create its corresponding RValue.
188 /// \param[in] valuePtr Pointer to an object corresponding to the field's type to bind to its value. If this is a
189 /// `nullptr`, a pointer will be created.
190 /// \param[in] provenance Processor provenance of the field.
191 ///
192 /// \return The field index of the newly added field.
193 FieldIndex_t AddField(const std::string &qualifiedFieldName, std::unique_ptr<ROOT::RFieldBase> field, void *valuePtr,
194 const RNTupleProcessorProvenance &provenance);
195
196 /////////////////////////////////////////////////////////////////////////////
197 /// \brief Update a field in the entry, preserving the value pointer.
198 ///
199 /// \param[in] fieldIdx Index of the field to update.
200 /// \param[in] field The new field to use in the entry.
201 void UpdateField(FieldIndex_t fieldIdx, std::unique_ptr<ROOT::RFieldBase> field);
202
203 /////////////////////////////////////////////////////////////////////////////
204 /// \brief Get a field by its index.
205 ///
206 /// \param[in] fieldIdx Index of the field.
207 ///
208 /// \return A constref to the field.
209 const ROOT::RFieldBase &GetField(FieldIndex_t fieldIdx) const;
210
211 /////////////////////////////////////////////////////////////////////////////
212 /// \brief Bind a new value pointer to a field in the entry.
213 ///
214 /// \param[in] fieldIdx The index of the field in the entry.
215 /// \param[in] valuePtr Pointer to the value to bind to the field.
216 void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr);
217
218 /////////////////////////////////////////////////////////////////////////////
219 /// \brief Bind a new value pointer to a field in the entry.
220 ///
221 /// \param[in] fieldIdx The index of the field in the entry.
222 /// \param[in] valuePtr Pointer to the value to bind to the field.
223 void Bind(FieldIndex_t fieldIdx, std::shared_ptr<void> valuePtr);
224
225 /////////////////////////////////////////////////////////////////////////////
226 /// \brief Read the field value corresponding to the given field index for the provided entry index.
227 ///
228 /// \param[in] fieldIdx The index of the field in the entry.
229 /// \param[in] entryIdx The entry number to read.
230 void ReadValue(FieldIndex_t fieldIdx, ROOT::NTupleSize_t entryIdx);
231
233 {
234 assert(fieldIdx < fProcessorValues.size());
235 return fProcessorValues[fieldIdx].fValue;
236 }
237
238 /////////////////////////////////////////////////////////////////////////////
239 /// \brief Get the processor provenance of a field in the entry.
240 ///
241 /// \param[in] fieldIdx The index of the field in the entry.
243 {
244 assert(fieldIdx < fProcessorValues.size());
245 return fProcessorValues[fieldIdx].fProcessorProvenance;
246 }
247
248 /////////////////////////////////////////////////////////////////////////////
249 /// \brief Get the name of a field in the entry, including its parent fields.
250 ///
251 /// \param[in] fieldIdx The index of the field in the entry.
252 std::string GetQualifiedFieldName(FieldIndex_t fieldIdx) const
253 {
254 assert(fieldIdx < fProcessorValues.size());
255 return fProcessorValues[fieldIdx].fQualifiedFieldName;
256 }
257
258 /////////////////////////////////////////////////////////////////////////////
259 /// \brief Get all field indices of this entry.
260 std::unordered_set<FieldIndex_t> GetFieldIndices() const;
261};
262} // namespace Internal
263} // namespace Experimental
264} // namespace ROOT
265
266#endif // ROOT_RNTupleProcessorEntry
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...
std::unordered_set< FieldIndex_t > GetFieldIndices() const
Get all field indices of this entry.
void Bind(FieldIndex_t fieldIdx, std::shared_ptr< void > valuePtr)
Bind a new value pointer to a field in the entry.
void ResetFields(const std::unordered_set< FieldIndex_t > &fieldIdxs)
Reset the specified fields to a proto field, disconnected from any physical storage.
std::optional< FieldIndex_t > FindFieldIndex(std::string_view canonicalFieldName, std::string_view typeName="") const
Find the field index of the provided field in the entry.
std::unordered_map< std::string, std::vector< FieldIndex_t > > fFieldName2Index
void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr)
Bind a new value pointer to a field in the entry.
std::string GetQualifiedFieldName(FieldIndex_t fieldIdx) const
Get the name of a field in the entry, including its parent fields.
const ROOT::RFieldBase::RValue & GetValue(FieldIndex_t fieldIdx) const
const ROOT::RFieldBase & GetField(FieldIndex_t fieldIdx) const
Get a field by its index.
bool IsValidField(FieldIndex_t fieldIdx) const
Check whether a field is valid for reading.
void UpdateField(FieldIndex_t fieldIdx, std::unique_ptr< ROOT::RFieldBase > field)
Update a field in the entry, preserving the value pointer.
const std::string & FindFieldName(FieldIndex_t fieldIdx) const
Find the name of a field from its field index.
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.
FieldIndex_t AddField(const std::string &qualifiedFieldName, std::unique_ptr< ROOT::RFieldBase > field, void *valuePtr, const RNTupleProcessorProvenance &provenance)
Add a new field to the entry.
const RNTupleProcessorProvenance & GetFieldProvenance(FieldIndex_t fieldIdx) const
Get the processor provenance of a field in the entry.
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.
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.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RProcessorValue(std::unique_ptr< ROOT::RFieldBase > field, std::string_view qualifiedFieldName, ROOT::RFieldBase::RValue &&value, bool isValid, RNTupleProcessorProvenance provenance)