Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RField.hxx
Go to the documentation of this file.
1/// \file ROOT/RField.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-09
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RField
17#define ROOT7_RField
18
19#include <ROOT/RColumn.hxx>
20#include <ROOT/RError.hxx>
22#include <ROOT/RNTupleUtil.hxx>
23#include <ROOT/RSpan.hxx>
24#include <string_view>
25#include <ROOT/RVec.hxx>
26#include <ROOT/TypeTraits.hxx>
27
28#include <TGenericClassInfo.h>
30
31#include <algorithm>
32#include <array>
33#include <atomic>
34#include <bitset>
35#include <cstddef>
36#include <functional>
37#include <iostream>
38#include <iterator>
39#include <map>
40#include <memory>
41#include <new>
42#include <set>
43#include <string>
44#include <type_traits>
45#include <typeinfo>
46#include <variant>
47#include <vector>
48#include <utility>
49
50class TClass;
51class TEnum;
52
53namespace ROOT {
54
55class TSchemaRule;
56class RFieldBase;
57
58namespace Experimental {
59
60class RCollectionField;
61class RNTupleCollectionWriter;
62class REntry;
63
64namespace Internal {
65struct RFieldCallbackInjector;
66class RPageSink;
67class RPageSource;
68// TODO(jblomer): find a better way to not have these three methods in the RFieldBase public API
69void CallCommitClusterOnField(RFieldBase &);
70void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry = 0);
71void CallConnectPageSourceOnField(RFieldBase &, RPageSource &);
72} // namespace Internal
73
74namespace Detail {
75class RFieldVisitor;
76} // namespace Detail
77
78// clang-format off
79/**
80\class ROOT::Experimental::RFieldBase
81\ingroup NTuple
82\brief A field translates read and write calls from/to underlying columns to/from tree values
83
84A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
85type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
86mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
87The field knows based on its type and the field name the type(s) and name(s) of the columns.
88
89Note: the class hierarchy starting at RFieldBase is not meant to be extended by user-provided child classes.
90This is and can only be partially enforced through C++.
91*/
92// clang-format on
94 friend class ROOT::Experimental::RCollectionField; // to move the fields from the collection model
95 friend struct ROOT::Experimental::Internal::RFieldCallbackInjector; // used for unit tests
99 using ReadCallback_t = std::function<void(void *)>;
100
101protected:
102 /// A functor to release the memory acquired by CreateValue (memory and constructor).
103 /// This implementation works for types with a trivial destructor. More complex fields implement a derived deleter.
104 /// The deleter is operational without the field object and thus can be used to destruct/release a value after
105 /// the field has been destructed.
106 class RDeleter {
107 public:
108 virtual ~RDeleter() = default;
109 virtual void operator()(void *objPtr, bool dtorOnly)
110 {
111 if (!dtorOnly)
112 operator delete(objPtr);
113 }
114 };
115
116 /// A deleter for templated RFieldBase descendents where the value type is known.
117 template <typename T>
118 class RTypedDeleter : public RDeleter {
119 public:
120 void operator()(void *objPtr, bool dtorOnly) final
121 {
122 std::destroy_at(static_cast<T *>(objPtr));
123 RDeleter::operator()(objPtr, dtorOnly);
124 }
125 };
126
127 // We cannot directly use RFieldBase::RDeleter as a shared pointer deleter due to splicing. We use this
128 // wrapper class to store a polymorphic pointer to the actual deleter.
130 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
131 void operator()(void *objPtr) { fDeleter->operator()(objPtr, false /* dtorOnly*/); }
132 explicit RSharedPtrDeleter(std::unique_ptr<RFieldBase::RDeleter> deleter) : fDeleter(std::move(deleter)) {}
133 };
134
135public:
136 static constexpr std::uint32_t kInvalidTypeVersion = -1U;
137 /// No constructor needs to be called, i.e. any bit pattern in the allocated memory represents a valid type
138 /// A trivially constructible field has a no-op ConstructValue() implementation
139 static constexpr int kTraitTriviallyConstructible = 0x01;
140 /// The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
141 static constexpr int kTraitTriviallyDestructible = 0x02;
142 /// A field of a fundamental type that can be directly mapped via `RField<T>::Map()`, i.e. maps as-is to a single
143 /// column
144 static constexpr int kTraitMappable = 0x04;
145 /// Shorthand for types that are both trivially constructible and destructible
147
148 using ColumnRepresentation_t = std::vector<EColumnType>;
149
150 /// During its lifetime, a field undergoes the following possible state transitions:
151 ///
152 /// [*] --> Unconnected --> ConnectedToSink ----
153 /// | | |
154 /// | --> ConnectedToSource ---> [*]
155 /// | |
156 /// -------------------------------
158
159 /// Some fields have multiple possible column representations, e.g. with or without split encoding.
160 /// All column representations supported for writing also need to be supported for reading. In addition,
161 /// fields can support extra column representations for reading only, e.g. a 64bit integer reading from a
162 /// 32bit column.
163 /// The defined column representations must be supported by corresponding column packing/unpacking implementations,
164 /// i.e. for the example above, the unpacking of 32bit ints to 64bit pages must be implemented in RColumnElement.hxx
166 public:
167 using TypesList_t = std::vector<ColumnRepresentation_t>;
169 RColumnRepresentations(const TypesList_t &serializationTypes, const TypesList_t &deserializationExtraTypes);
170
171 /// The first column list from fSerializationTypes is the default for writing.
175
176 private:
178 /// The union of the serialization types and the deserialization extra types. Duplicates the serialization types
179 /// list but the benenfit is that GetDeserializationTypes does not need to compile the list.
181 }; // class RColumnRepresentations
182
183 /// Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
184 /// Only fields can create RValue objects through generation, binding or splitting.
185 class RValue {
186 friend class RFieldBase;
187
188 private:
189 RFieldBase *fField = nullptr; ///< The field that created the RValue
190 std::shared_ptr<void> fObjPtr; ///< Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
191
192 RValue(RFieldBase *field, std::shared_ptr<void> objPtr) : fField(field), fObjPtr(objPtr) {}
193
194 public:
195 RValue(const RValue &) = default;
196 RValue &operator=(const RValue &) = default;
197 RValue(RValue &&other) = default;
198 RValue &operator=(RValue &&other) = default;
199 ~RValue() = default;
200
201 std::size_t Append() { return fField->Append(fObjPtr.get()); }
202 void Read(NTupleSize_t globalIndex) { fField->Read(globalIndex, fObjPtr.get()); }
203 void Read(RClusterIndex clusterIndex) { fField->Read(clusterIndex, fObjPtr.get()); }
204 void Bind(std::shared_ptr<void> objPtr) { fObjPtr = objPtr; }
205 void BindRawPtr(void *rawPtr);
206 /// Replace the current object pointer by a pointer to a new object constructed by the field
207 void EmplaceNew() { fObjPtr = fField->CreateValue().GetPtr<void>(); }
208
209 template <typename T>
210 std::shared_ptr<T> GetPtr() const
211 {
212 return std::static_pointer_cast<T>(fObjPtr);
213 }
214
215 template <typename T>
216 const T &GetRef() const
217 {
218 return *static_cast<T *>(fObjPtr.get());
219 }
220
221 const RFieldBase &GetField() const { return *fField; }
222 }; // class RValue
223
224 /// Similar to RValue but manages an array of consecutive values. Bulks have to come from the same cluster.
225 /// Bulk I/O works with two bit masks: the mask of all the available entries in the current bulk and the mask
226 /// of the required entries in a bulk read. The idea is that a single bulk may serve multiple read operations
227 /// on the same range, where in each read operation a different subset of values is required.
228 /// The memory of the value array is managed by the RBulk class.
229 class RBulk {
230 private:
231 friend class RFieldBase;
232
233 RFieldBase *fField = nullptr; ///< The field that created the array of values
234 std::unique_ptr<RFieldBase::RDeleter> fDeleter; /// Cached deleter of fField
235 void *fValues = nullptr; ///< Pointer to the start of the array
236 std::size_t fValueSize = 0; ///< Cached copy of fField->GetValueSize()
237 std::size_t fCapacity = 0; ///< The size of the array memory block in number of values
238 std::size_t fSize = 0; ///< The number of available values in the array (provided their mask is set)
239 bool fIsAdopted = false; ///< True if the user provides the memory buffer for fValues
240 std::unique_ptr<bool[]> fMaskAvail; ///< Masks invalid values in the array
241 std::size_t fNValidValues = 0; ///< The sum of non-zero elements in the fMask
242 RClusterIndex fFirstIndex; ///< Index of the first value of the array
243 /// Reading arrays of complex values may require additional memory, for instance for the elements of
244 /// arrays of vectors. A pointer to the fAuxData array is passed to the field's BulkRead method.
245 /// The RBulk class does not modify the array in-between calls to the field's BulkRead method.
246 std::vector<unsigned char> fAuxData;
247
248 void ReleaseValues();
249 /// Sets a new range for the bulk. If there is enough capacity, the fValues array will be reused.
250 /// Otherwise a new array is allocated. After reset, fMaskAvail is false for all values.
251 void Reset(RClusterIndex firstIndex, std::size_t size);
252 void CountValidValues();
253
254 bool ContainsRange(RClusterIndex firstIndex, std::size_t size) const
255 {
256 if (firstIndex.GetClusterId() != fFirstIndex.GetClusterId())
257 return false;
258 return (firstIndex.GetIndex() >= fFirstIndex.GetIndex()) &&
259 ((firstIndex.GetIndex() + size) <= (fFirstIndex.GetIndex() + fSize));
260 }
261
262 void *GetValuePtrAt(std::size_t idx) const
263 {
264 return reinterpret_cast<unsigned char *>(fValues) + idx * fValueSize;
265 }
266
267 explicit RBulk(RFieldBase *field)
268 : fField(field), fDeleter(field->GetDeleter()), fValueSize(field->GetValueSize())
269 {
270 }
271
272 public:
273 ~RBulk();
274 RBulk(const RBulk &) = delete;
275 RBulk &operator=(const RBulk &) = delete;
276 RBulk(RBulk &&other);
277 RBulk &operator=(RBulk &&other);
278
279 // Sets fValues and fSize/fCapacity to the given values. The capacity is specified in number of values.
280 // Once a buffer is adopted, an attempt to read more values then available throws an exception.
281 void AdoptBuffer(void *buf, std::size_t capacity);
282
283 /// Reads 'size' values from the associated field, starting from 'firstIndex'. Note that the index is given
284 /// relative to a certain cluster. The return value points to the array of read objects.
285 /// The 'maskReq' parameter is a bool array of at least 'size' elements. Only objects for which the mask is
286 /// true are guaranteed to be read in the returned value array.
287 void *ReadBulk(RClusterIndex firstIndex, const bool *maskReq, std::size_t size)
288 {
289 if (!ContainsRange(firstIndex, size))
290 Reset(firstIndex, size);
291
292 // We may read a sub range of the currently available range
293 auto offset = firstIndex.GetIndex() - fFirstIndex.GetIndex();
294
295 if (fNValidValues == fSize)
296 return GetValuePtrAt(offset);
297
298 RBulkSpec bulkSpec;
299 bulkSpec.fFirstIndex = firstIndex;
300 bulkSpec.fCount = size;
301 bulkSpec.fMaskReq = maskReq;
302 bulkSpec.fMaskAvail = &fMaskAvail[offset];
303 bulkSpec.fValues = GetValuePtrAt(offset);
304 bulkSpec.fAuxData = &fAuxData;
305 auto nRead = fField->ReadBulk(bulkSpec);
306 if (nRead == RBulkSpec::kAllSet) {
307 if ((offset == 0) && (size == fSize)) {
309 } else {
311 }
312 } else {
313 fNValidValues += nRead;
314 }
315 return GetValuePtrAt(offset);
316 }
317 }; // class RBulk
318
319private:
320 /// The field name relative to its parent field
321 std::string fName;
322 /// The C++ type captured by this field
323 std::string fType;
324 /// The role of this field in the data model structure
326 /// For fixed sized arrays, the array length
327 std::size_t fNRepetitions;
328 /// A field qualifies as simple if it is both mappable and has no post-read callback
330 /// When the columns are connected to a page source or page sink, the field represents a field id in the
331 /// corresponding RNTuple descriptor. This on-disk ID is set in RPageSink::Create() for writing and by
332 /// RFieldDescriptor::CreateField() when recreating a field / model from the stored descriptor.
334 /// Free text set by the user
335 std::string fDescription;
336 /// Changed by ConnectTo[Sink,Source], reset by Clone()
338
340 {
341 for (const auto &func : fReadCallbacks)
342 func(target);
343 }
344
345 /// Translate an entry index to a column element index of the principal column and viceversa. These functions
346 /// take into account the role and number of repetitions on each level of the field hierarchy as follows:
347 /// - Top level fields: element index == entry index
348 /// - Record fields propagate their principal column index to the principal columns of direct descendant fields
349 /// - Collection and variant fields set the principal column index of their childs to 0
350 ///
351 /// The column element index also depends on the number of repetitions of each field in the hierarchy, e.g., given a
352 /// field with type `std::array<std::array<float, 4>, 2>`, this function returns 8 for the inner-most field.
354
355 /// Flushes data from active columns to disk and calls CommitClusterImpl
356 void CommitCluster();
357 /// Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
358 /// can be read or written. In order to find the field in the page storage, the field's on-disk ID has to be set.
359 /// \param firstEntry The global index of the first entry with on-disk data for the connected field
360 void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry = 0);
361 /// Connects the field and its sub field tree to the given page source. Once connected, data can be read.
362 /// Only unconnected fields may be connected, i.e. the method is not idempotent. The field ID has to be set prior to
363 /// calling this function. For sub fields, a field ID may or may not be set. If the field ID is unset, it will be
364 /// determined using the page source descriptor, based on the parent field ID and the sub field name.
366
367 /// Factory method for the field's type. The caller owns the returned pointer
368 void *CreateObjectRawPtr() const;
369
370protected:
371 /// Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information
372 struct RBulkSpec {
373 /// As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read
374 /// independent of the provided masks.
375 static const std::size_t kAllSet = std::size_t(-1);
376
377 RClusterIndex fFirstIndex; ///< Start of the bulk range
378 std::size_t fCount = 0; ///< Size of the bulk range
379 /// A bool array of size fCount, indicating the required values in the requested range
380 const bool *fMaskReq = nullptr;
381 bool *fMaskAvail = nullptr; ///< A bool array of size fCount, indicating the valid values in fValues
382 /// The destination area, which has to be a big enough array of valid objects of the correct type
383 void *fValues = nullptr;
384 /// Reference to memory owned by the RBulk class. The field implementing BulkReadImpl may use fAuxData
385 /// as memory that stays persistent between calls.
386 std::vector<unsigned char> *fAuxData = nullptr;
387 };
388
389 /// Collections and classes own sub fields
390 std::vector<std::unique_ptr<RFieldBase>> fSubFields;
391 /// Sub fields point to their mother field
393 /// Points into fColumns. All fields that have columns have a distinct main column. For simple fields
394 /// (float, int, ...), the principal column corresponds to the field type. For collection fields expect std::array,
395 /// the main column is the offset field. Class fields have no column of their own.
397 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
398 std::vector<std::unique_ptr<Internal::RColumn>> fColumns;
399 /// Properties of the type that allow for optimizations of collections of that type
400 int fTraits = 0;
401 /// A typedef or using name that was used when creating the field
402 std::string fTypeAlias;
403 /// List of functions to be called after reading a value
404 std::vector<ReadCallback_t> fReadCallbacks;
405 /// C++ type version cached from the descriptor after a call to `ConnectPageSource()`
407 /// Points into the static vector GetColumnRepresentations().GetSerializationTypes() when SetColumnRepresentative
408 /// is called. Otherwise GetColumnRepresentative returns the default representation.
410
411 /// Implementations in derived classes should return a static RColumnRepresentations object. The default
412 /// implementation does not attach any columns to the field.
414 /// Creates the backing columns corresponsing to the field type for writing
415 virtual void GenerateColumnsImpl() = 0;
416 /// Creates the backing columns corresponsing to the field type for reading.
417 /// The method should to check, using the page source and fOnDiskId, if the column types match
418 /// and throw if they don't.
419 virtual void GenerateColumnsImpl(const RNTupleDescriptor &desc) = 0;
420 /// Returns the on-disk column types found in the provided descriptor for fOnDiskId. Throws an exception if the types
421 /// don't match any of the deserialization types from GetColumnRepresentations().
423 /// When connecting a field to a page sink, the field's default column representation is subject
424 /// to adjustment according to the write options. E.g., if compression is turned off, encoded columns
425 /// are changed to their unencoded counterparts.
426 void AutoAdjustColumnTypes(const RNTupleWriteOptions &options);
427
428 /// Called by Clone(), which additionally copies the on-disk ID
429 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
430
431 /// Constructs value in a given location of size at least GetValueSize(). Called by the base class' CreateValue().
432 virtual void ConstructValue(void *where) const = 0;
433 virtual std::unique_ptr<RDeleter> GetDeleter() const { return std::make_unique<RDeleter>(); }
434 /// Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
435 static void CallConstructValueOn(const RFieldBase &other, void *where) { other.ConstructValue(where); }
436 static std::unique_ptr<RDeleter> GetDeleterOf(const RFieldBase &other) { return other.GetDeleter(); }
437
438 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
439 /// column type exists.
440 virtual std::size_t AppendImpl(const void *from);
441 virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to);
442 virtual void ReadInClusterImpl(RClusterIndex clusterIndex, void *to)
443 {
445 }
446
447 /// Write the given value into columns. The value object has to be of the same type as the field.
448 /// Returns the number of uncompressed bytes written.
449 std::size_t Append(const void *from)
450 {
451 if (~fTraits & kTraitMappable)
452 return AppendImpl(from);
453
456 }
457
458 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
459 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
460 /// to a single column and has no read callback.
461 void Read(NTupleSize_t globalIndex, void *to)
462 {
463 if (fIsSimple)
464 return (void)fPrincipalColumn->Read(globalIndex, to);
465
467 fPrincipalColumn->Read(globalIndex, to);
468 else
469 ReadGlobalImpl(globalIndex, to);
470 if (R__unlikely(!fReadCallbacks.empty()))
472 }
473
474 void Read(RClusterIndex clusterIndex, void *to)
475 {
476 if (fIsSimple)
477 return (void)fPrincipalColumn->Read(clusterIndex, to);
478
480 fPrincipalColumn->Read(clusterIndex, to);
481 else
482 ReadInClusterImpl(clusterIndex, to);
483 if (R__unlikely(!fReadCallbacks.empty()))
485 }
486
487 /// General implementation of bulk read. Loop over the required range and read values that are required
488 /// and not already present. Derived classes may implement more optimized versions of this method.
489 /// See ReadBulk() for the return value.
490 virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec);
491
492 /// Returns the number of newly available values, that is the number of bools in bulkSpec.fMaskAvail that
493 /// flipped from false to true. As a special return value, kAllSet can be used if all values are read
494 /// independent from the masks.
495 std::size_t ReadBulk(const RBulkSpec &bulkSpec)
496 {
497 if (fIsSimple) {
498 /// For simple types, ignore the mask and memcopy the values into the destination
499 fPrincipalColumn->ReadV(bulkSpec.fFirstIndex, bulkSpec.fCount, bulkSpec.fValues);
500 std::fill(bulkSpec.fMaskAvail, bulkSpec.fMaskAvail + bulkSpec.fCount, true);
501 return RBulkSpec::kAllSet;
502 }
503
504 return ReadBulkImpl(bulkSpec);
505 }
506
507 /// Allow derived classes to call Append and Read on other (sub) fields.
508 static std::size_t CallAppendOn(RFieldBase &other, const void *from) { return other.Append(from); }
509 static void CallReadOn(RFieldBase &other, RClusterIndex clusterIndex, void *to) { other.Read(clusterIndex, to); }
510 static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to) { other.Read(globalIndex, to); }
511
512 /// Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBulk
514
515 /// Set a user-defined function to be called after reading a value, giving a chance to inspect and/or modify the
516 /// value object.
517 /// Returns an index that can be used to remove the callback.
518 size_t AddReadCallback(ReadCallback_t func);
519 void RemoveReadCallback(size_t idx);
520
521 // Perform housekeeping tasks for global to cluster-local index translation
522 virtual void CommitClusterImpl() {}
523
524 /// Add a new subfield to the list of nested fields
525 void Attach(std::unique_ptr<RFieldBase> child);
526
527 /// Called by `ConnectPageSource()` only once connected; derived classes may override this
528 /// as appropriate
529 virtual void OnConnectPageSource() {}
530
531 /// Factory method to resurrect a field from the stored on-disk type information. This overload takes an already
532 /// normalized type name and type alias
533 /// TODO(jalopezg): this overload may eventually be removed leaving only the `RFieldBase::Create()` that takes a
534 /// single type name
536 Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias);
537
538public:
539 /// Iterates over the sub tree of fields in depth-first search order
540 template <bool IsConstT>
542 private:
543 struct Position {
544 using FieldPtr_t = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
545 Position() : fFieldPtr(nullptr), fIdxInParent(-1) { }
546 Position(FieldPtr_t fieldPtr, int idxInParent) : fFieldPtr(fieldPtr), fIdxInParent(idxInParent) {}
549 };
550 /// The stack of nodes visited when walking down the tree of fields
551 std::vector<Position> fStack;
552 public:
554 using iterator_category = std::forward_iterator_tag;
555 using difference_type = std::ptrdiff_t;
556 using value_type = std::conditional_t<IsConstT, const RFieldBase, RFieldBase>;
557 using pointer = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
558 using reference = std::conditional_t<IsConstT, const RFieldBase &, RFieldBase &>;
559
561 RSchemaIteratorTemplate(pointer val, int idxInParent) { fStack.emplace_back(Position(val, idxInParent)); }
563 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
564 /// in depth-first search order
565 void Advance()
566 {
567 auto itr = fStack.rbegin();
568 if (!itr->fFieldPtr->fSubFields.empty()) {
569 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
570 return;
571 }
572
573 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
574 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
575 if (fStack.size() == 1) {
576 itr->fFieldPtr = itr->fFieldPtr->fParent;
577 itr->fIdxInParent = -1;
578 return;
579 }
580 fStack.pop_back();
581 itr = fStack.rbegin();
582 nextIdxInParent = ++(itr->fIdxInParent);
583 }
584 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
585 }
586
587 iterator operator++(int) /* postfix */ { auto r = *this; Advance(); return r; }
588 iterator& operator++() /* prefix */ { Advance(); return *this; }
589 reference operator* () const { return *fStack.back().fFieldPtr; }
590 pointer operator->() const { return fStack.back().fFieldPtr; }
591 bool operator==(const iterator& rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
592 bool operator!=(const iterator& rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
593 };
596
597 // This is used in CreateObject and is specialized for void
598 template <typename T>
600 using deleter = std::default_delete<T>;
601 };
602
603 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
604 /// If `isSimple` is `true`, the trait `kTraitMappable` is automatically set on construction. However, the
605 /// field might be demoted to non-simple if a post-read callback is set.
606 RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple,
607 std::size_t nRepetitions = 0);
608 RFieldBase(const RFieldBase&) = delete;
609 RFieldBase(RFieldBase&&) = default;
612 virtual ~RFieldBase() = default;
613
614 /// Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns
615 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
616
617 /// Factory method to resurrect a field from the stored on-disk type information
619 Create(const std::string &fieldName, const std::string &typeName);
620 /// Check whether a given string is a valid field name
621 static RResult<void> EnsureValidFieldName(std::string_view fieldName);
622
623 /// Generates an object of the field type and allocates new initialized memory according to the type.
624 /// Implemented at the end of this header because the implementation is using RField<T>::TypeName()
625 /// The returned object can be released with `delete`, i.e. it is valid to call
626 /// auto ptr = field->CreateObject();
627 /// delete ptr.release();
628 ///
629 /// Note that CreateObject<void> is supported. The returned unique_ptr has a custom deleter that reports an error
630 /// if it is called. The intended use of the returned unique_ptr<void> is to call `release()`. In this way, the
631 /// transfer of pointer ownership is explicit.
632 template <typename T>
633 std::unique_ptr<T, typename RCreateObjectDeleter<T>::deleter> CreateObject() const;
634 /// Generates an object of the field type and wraps the created object in a shared pointer and returns it an RValue
635 /// connected to the field.
637 /// The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values
638 RBulk CreateBulk() { return RBulk(this); }
639 /// Creates a value from a memory location with an already constructed object
640 RValue BindValue(std::shared_ptr<void> objPtr) { return RValue(this, objPtr); }
641 /// Creates the list of direct child values given a value for this field. E.g. a single value for the
642 /// correct variant or all the elements of a collection. The default implementation assumes no sub values
643 /// and returns an empty vector.
644 virtual std::vector<RValue> SplitValue(const RValue &value) const;
645 /// The number of bytes taken by a value of the appropriate type
646 virtual size_t GetValueSize() const = 0;
647 /// As a rule of thumb, the alignment is equal to the size of the type. There are, however, various exceptions
648 /// to this rule depending on OS and CPU architecture. So enforce the alignment to be explicitly spelled out.
649 virtual size_t GetAlignment() const = 0;
650 int GetTraits() const { return fTraits; }
651 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
652
653 std::string GetFieldName() const { return fName; }
654 /// Returns the field name and parent field names separated by dots ("grandparent.parent.child")
655 std::string GetQualifiedFieldName() const;
656 std::string GetTypeName() const { return fType; }
657 std::string GetTypeAlias() const { return fTypeAlias; }
659 std::size_t GetNRepetitions() const { return fNRepetitions; }
661 const RFieldBase *GetParent() const { return fParent; }
662 std::vector<RFieldBase *> GetSubFields();
663 std::vector<const RFieldBase *> GetSubFields() const;
664 bool IsSimple() const { return fIsSimple; }
665 /// Get the field's description
666 std::string GetDescription() const { return fDescription; }
667 void SetDescription(std::string_view description);
668 EState GetState() const { return fState; }
669
672
673 /// Returns the fColumnRepresentative pointee or, if unset, the field's default representative
675 /// Fixes a column representative. This can only be done _before_ connecting the field to a page sink.
676 /// Otherwise, or if the provided representation is not in the list of GetColumnRepresentations,
677 /// an exception is thrown
678 void SetColumnRepresentative(const ColumnRepresentation_t &representative);
679 /// Whether or not an explicit column representative was set
680 bool HasDefaultColumnRepresentative() const { return fColumnRepresentative == nullptr; }
681
682 /// Indicates an evolution of the mapping scheme from C++ type to columns
683 virtual std::uint32_t GetFieldVersion() const { return 0; }
684 /// Indicates an evolution of the C++ type itself
685 virtual std::uint32_t GetTypeVersion() const { return 0; }
686 /// Return the C++ type version stored in the field descriptor; only valid after a call to `ConnectPageSource()`
687 std::uint32_t GetOnDiskTypeVersion() const { return fOnDiskTypeVersion; }
688
690 {
691 return fSubFields.empty() ? RSchemaIterator(this, -1) : RSchemaIterator(fSubFields[0].get(), 0);
692 }
693 RSchemaIterator end() { return RSchemaIterator(this, -1); }
695 {
696 return fSubFields.empty() ? RConstSchemaIterator(this, -1) : RConstSchemaIterator(fSubFields[0].get(), 0);
697 }
698 RConstSchemaIterator cend() const { return RConstSchemaIterator(this, -1); }
699
700 virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const;
701}; // class RFieldBase
702
703/// The container field for an ntuple model, which itself has no physical representation.
704/// Therefore, the zero field must not be connected to a page source or sink.
705class RFieldZero final : public RFieldBase {
706protected:
707 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
708 void GenerateColumnsImpl() final {}
710 void ConstructValue(void *) const final {}
711
712public:
713 RFieldZero() : RFieldBase("", "", ENTupleStructure::kRecord, false /* isSimple */) {}
714
715 using RFieldBase::Attach;
716 size_t GetValueSize() const final { return 0; }
717 size_t GetAlignment() const final { return 0; }
718
719 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
720};
721
722/// The field for a class with dictionary
723class RClassField : public RFieldBase {
724private:
728 };
731 std::size_t fOffset;
732 };
733 /// Prefix used in the subfield names generated for base classes
734 static constexpr const char *kPrefixInherited{":"};
735
736 class RClassDeleter : public RDeleter {
737 private:
739
740 public:
741 explicit RClassDeleter(TClass *cl) : fClass(cl) {}
742 void operator()(void *objPtr, bool dtorOnly) final;
743 };
744
746 /// Additional information kept for each entry in `fSubFields`
747 std::vector<RSubFieldInfo> fSubFieldsInfo;
748 std::size_t fMaxAlignment = 1;
749
750private:
751 RClassField(std::string_view fieldName, std::string_view className, TClass *classp);
752 void Attach(std::unique_ptr<RFieldBase> child, RSubFieldInfo info);
753 /// Register post-read callbacks corresponding to a list of ROOT I/O customization rules. `classp` is used to
754 /// fill the `TVirtualObject` instance passed to the user function.
755 void AddReadCallbacksFromIORules(const std::span<const TSchemaRule *> rules, TClass *classp = nullptr);
756
757protected:
758 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
759 void GenerateColumnsImpl() final {}
761
762 void ConstructValue(void *where) const override;
763 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RClassDeleter>(fClass); }
764
765 std::size_t AppendImpl(const void *from) final;
766 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
767 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final;
768 void OnConnectPageSource() final;
769
770public:
771 RClassField(std::string_view fieldName, std::string_view className);
772 RClassField(RClassField&& other) = default;
773 RClassField& operator =(RClassField&& other) = default;
774 ~RClassField() override = default;
775
776 std::vector<RValue> SplitValue(const RValue &value) const final;
777 size_t GetValueSize() const override;
778 size_t GetAlignment() const final { return fMaxAlignment; }
779 std::uint32_t GetTypeVersion() const final;
780 void AcceptVisitor(Detail::RFieldVisitor &visitor) const override;
781};
782
783/// The field for an unscoped or scoped enum with dictionary
784class REnumField : public RFieldBase {
785private:
786 REnumField(std::string_view fieldName, std::string_view enumName, TEnum *enump);
787 REnumField(std::string_view fieldName, std::string_view enumName, std::unique_ptr<RFieldBase> intField);
788
789protected:
790 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
791 void GenerateColumnsImpl() final {}
792 void GenerateColumnsImpl(const RNTupleDescriptor & /* desc */) final {}
793
794 void ConstructValue(void *where) const final { CallConstructValueOn(*fSubFields[0], where); }
795
796 std::size_t AppendImpl(const void *from) final { return CallAppendOn(*fSubFields[0], from); }
797 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final { CallReadOn(*fSubFields[0], globalIndex, to); }
798 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final { CallReadOn(*fSubFields[0], clusterIndex, to); }
799
800public:
801 REnumField(std::string_view fieldName, std::string_view enumName);
802 REnumField(REnumField &&other) = default;
803 REnumField &operator=(REnumField &&other) = default;
804 ~REnumField() override = default;
805
806 std::vector<RValue> SplitValue(const RValue &value) const final;
807 size_t GetValueSize() const final { return fSubFields[0]->GetValueSize(); }
808 size_t GetAlignment() const final { return fSubFields[0]->GetAlignment(); }
809 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
810};
811
812/// The field for a class representing a collection of elements via `TVirtualCollectionProxy`.
813/// Objects of such type behave as collections that can be accessed through the corresponding member functions in
814/// `TVirtualCollectionProxy`. For STL collections, these proxies are provided. Custom classes need to implement the
815/// corresponding member functions in `TVirtualCollectionProxy`. At a bare minimum, the user is required to provide an
816/// implementation for the following functions in `TVirtualCollectionProxy`: `HasPointers()`, `GetProperties()`,
817/// `GetValueClass()`, `GetType()`, `PushProxy()`, `PopProxy()`, `GetFunctionCreateIterators()`, `GetFunctionNext()`,
818/// and `GetFunctionDeleteTwoIterators()`.
819///
820/// The collection proxy for a given class can be set via `TClass::CopyCollectionProxy()`.
822protected:
823 /// Allows for iterating over the elements of a proxied collection. RCollectionIterableOnce avoids an additional
824 /// iterator copy (see `TVirtualCollectionProxy::GetFunctionCopyIterator`) and thus can only be iterated once.
826 public:
831 };
832 static RIteratorFuncs GetIteratorFuncs(TVirtualCollectionProxy *proxy, bool readFromDisk);
833
834 private:
835 class RIterator {
837 void *fIterator = nullptr;
838 void *fElementPtr = nullptr;
839
840 void Advance()
841 {
842 auto fnNext_Contig = [&]() {
843 // Array-backed collections (e.g. kSTLvector) directly use the pointer-to-iterator-data as a
844 // pointer-to-element, thus saving an indirection level (see documentation for TVirtualCollectionProxy)
845 auto &iter = reinterpret_cast<unsigned char *&>(fIterator), p = iter;
846 iter += fOwner.fStride;
847 return p;
848 };
849 fElementPtr = fOwner.fStride ? fnNext_Contig() : fOwner.fIFuncs.fNext(fIterator, fOwner.fEnd);
850 }
851
852 public:
853 using iterator_category = std::forward_iterator_tag;
855 using difference_type = std::ptrdiff_t;
856 using pointer = void *;
857
858 RIterator(const RCollectionIterableOnce &owner) : fOwner(owner) {}
859 RIterator(const RCollectionIterableOnce &owner, void *iter) : fOwner(owner), fIterator(iter) { Advance(); }
861 {
862 Advance();
863 return *this;
864 }
865 pointer operator*() const { return fElementPtr; }
866 bool operator!=(const iterator &rh) const { return fElementPtr != rh.fElementPtr; }
867 bool operator==(const iterator &rh) const { return fElementPtr == rh.fElementPtr; }
868 };
869
871 const std::size_t fStride;
872 unsigned char fBeginSmallBuf[TVirtualCollectionProxy::fgIteratorArenaSize];
874 void *fBegin = &fBeginSmallBuf;
875 void *fEnd = &fEndSmallBuf;
876 public:
877 /// Construct a `RCollectionIterableOnce` that iterates over `collection`. If elements are guaranteed to be
878 /// contiguous in memory (e.g. a vector), `stride` can be provided for faster iteration, i.e. the address of each
879 /// element is known given the base pointer.
880 RCollectionIterableOnce(void *collection, const RIteratorFuncs &ifuncs, TVirtualCollectionProxy *proxy,
881 std::size_t stride = 0U)
882 : fIFuncs(ifuncs), fStride(stride)
883 {
884 fIFuncs.fCreateIterators(collection, &fBegin, &fEnd, proxy);
885 }
887
888 RIterator begin() { return RIterator(*this, fBegin); }
889 RIterator end() { return fStride ? RIterator(*this, fEnd) : RIterator(*this); }
890 }; // class RCollectionIterableOnce
891
893 private:
894 std::shared_ptr<TVirtualCollectionProxy> fProxy;
895 std::unique_ptr<RDeleter> fItemDeleter;
896 std::size_t fItemSize = 0;
898
899 public:
900 explicit RProxiedCollectionDeleter(std::shared_ptr<TVirtualCollectionProxy> proxy) : fProxy(proxy) {}
901 RProxiedCollectionDeleter(std::shared_ptr<TVirtualCollectionProxy> proxy, std::unique_ptr<RDeleter> itemDeleter,
902 size_t itemSize)
903 : fProxy(proxy), fItemDeleter(std::move(itemDeleter)), fItemSize(itemSize)
904 {
905 fIFuncsWrite = RCollectionIterableOnce::GetIteratorFuncs(fProxy.get(), false /* readFromDisk */);
906 }
907 void operator()(void *objPtr, bool dtorOnly) final;
908 };
909
910 /// The collection proxy is needed by the deleters and thus defined as a shared pointer
911 std::shared_ptr<TVirtualCollectionProxy> fProxy;
914 /// Two sets of functions to operate on iterators, to be used depending on the access type. The direction preserves
915 /// the meaning from TVirtualCollectionProxy, i.e. read from disk / write to disk, respectively
918 std::size_t fItemSize;
920
921 /// Constructor used when the value type of the collection is not known in advance, i.e. in the case of custom
922 /// collections.
923 RProxiedCollectionField(std::string_view fieldName, std::string_view typeName, TClass *classp);
924 /// Constructor used when the value type of the collection is known in advance, e.g. in `RSetField`.
925 RProxiedCollectionField(std::string_view fieldName, std::string_view typeName,
926 std::unique_ptr<RFieldBase> itemField);
927
928protected:
929 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
930 const RColumnRepresentations &GetColumnRepresentations() const final;
931 void GenerateColumnsImpl() final;
932 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
933
934 void ConstructValue(void *where) const override;
935 std::unique_ptr<RDeleter> GetDeleter() const override;
936
937 std::size_t AppendImpl(const void *from) override;
938 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) override;
939
940 void CommitClusterImpl() final { fNWritten = 0; }
941
942public:
943 RProxiedCollectionField(std::string_view fieldName, std::string_view typeName);
946 ~RProxiedCollectionField() override = default;
947
948 std::vector<RValue> SplitValue(const RValue &value) const override;
949 size_t GetValueSize() const override { return fProxy->Sizeof(); }
950 size_t GetAlignment() const override { return alignof(std::max_align_t); }
951 void AcceptVisitor(Detail::RFieldVisitor &visitor) const override;
952 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
953 {
954 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
955 }
956 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
957 {
958 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
959 }
960};
961
962/// The field for an untyped record. The subfields are stored consequitively in a memory block, i.e.
963/// the memory layout is identical to one that a C++ struct would have
964class RRecordField : public RFieldBase {
965private:
966 class RRecordDeleter : public RDeleter {
967 private:
968 std::vector<std::unique_ptr<RDeleter>> fItemDeleters;
969 std::vector<std::size_t> fOffsets;
970
971 public:
972 RRecordDeleter(std::vector<std::unique_ptr<RDeleter>> &itemDeleters, const std::vector<std::size_t> &offsets)
973 : fItemDeleters(std::move(itemDeleters)), fOffsets(offsets)
974 {
975 }
976 void operator()(void *objPtr, bool dtorOnly) final;
977 };
978
979protected:
980 std::size_t fMaxAlignment = 1;
981 std::size_t fSize = 0;
982 std::vector<std::size_t> fOffsets;
983
984 std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const;
985
986 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
987
988 void GenerateColumnsImpl() final {}
990
991 void ConstructValue(void *where) const override;
992 std::unique_ptr<RDeleter> GetDeleter() const override;
993
994 std::size_t AppendImpl(const void *from) final;
995 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
996 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final;
997
998 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
999 const std::vector<std::size_t> &offsets, std::string_view typeName = "");
1000
1001 template <std::size_t N>
1002 RRecordField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, N> &&itemFields,
1003 const std::array<std::size_t, N> &offsets, std::string_view typeName = "")
1004 : ROOT::Experimental::RFieldBase(fieldName, typeName, ENTupleStructure::kRecord, false /* isSimple */)
1005 {
1006 fTraits |= kTraitTrivialType;
1007 for (unsigned i = 0; i < N; ++i) {
1008 fOffsets.push_back(offsets[i]);
1009 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
1010 fSize += GetItemPadding(fSize, itemFields[i]->GetAlignment()) + itemFields[i]->GetValueSize();
1011 fTraits &= itemFields[i]->GetTraits();
1012 Attach(std::move(itemFields[i]));
1013 }
1014 }
1015public:
1016 /// Construct a RRecordField based on a vector of child fields. The ownership of the child fields is transferred
1017 /// to the RRecordField instance.
1018 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> &&itemFields);
1019 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> &itemFields);
1020 RRecordField(RRecordField&& other) = default;
1022 ~RRecordField() override = default;
1023
1024 std::vector<RValue> SplitValue(const RValue &value) const final;
1025 size_t GetValueSize() const final { return fSize; }
1026 size_t GetAlignment() const final { return fMaxAlignment; }
1027 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1028};
1029
1030/// The generic field for a (nested) std::vector<Type> except for std::vector<bool>
1031class RVectorField : public RFieldBase {
1032private:
1033 class RVectorDeleter : public RDeleter {
1034 private:
1035 std::size_t fItemSize = 0;
1036 std::unique_ptr<RDeleter> fItemDeleter;
1037
1038 public:
1039 RVectorDeleter() = default;
1040 RVectorDeleter(std::size_t itemSize, std::unique_ptr<RDeleter> itemDeleter)
1041 : fItemSize(itemSize), fItemDeleter(std::move(itemDeleter))
1042 {
1043 }
1044 void operator()(void *objPtr, bool dtorOnly) final;
1045 };
1046
1047 std::size_t fItemSize;
1049 std::unique_ptr<RDeleter> fItemDeleter;
1050
1051protected:
1052 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1053
1054 const RColumnRepresentations &GetColumnRepresentations() const final;
1055 void GenerateColumnsImpl() final;
1056 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1057
1058 void ConstructValue(void *where) const override { new (where) std::vector<char>(); }
1059 std::unique_ptr<RDeleter> GetDeleter() const final;
1060
1061 std::size_t AppendImpl(const void *from) final;
1062 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1063
1064 void CommitClusterImpl() final { fNWritten = 0; }
1065
1066public:
1067 RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
1068 RVectorField(RVectorField&& other) = default;
1070 ~RVectorField() override = default;
1071
1072 std::vector<RValue> SplitValue(const RValue &value) const final;
1073 size_t GetValueSize() const override { return sizeof(std::vector<char>); }
1074 size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
1075 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1076 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const {
1077 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
1078 }
1079 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
1080 {
1081 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
1082 }
1083};
1084
1085/// The type-erased field for a RVec<Type>
1086class RRVecField : public RFieldBase {
1087public:
1088 /// the RRVecDeleter is also used by RArrayAsRVecField and therefore declared public
1089 class RRVecDeleter : public RDeleter {
1090 private:
1091 std::size_t fItemAlignment;
1092 std::size_t fItemSize = 0;
1093 std::unique_ptr<RDeleter> fItemDeleter;
1094
1095 public:
1096 explicit RRVecDeleter(std::size_t itemAlignment) : fItemAlignment(itemAlignment) {}
1097 RRVecDeleter(std::size_t itemAlignment, std::size_t itemSize, std::unique_ptr<RDeleter> itemDeleter)
1098 : fItemAlignment(itemAlignment), fItemSize(itemSize), fItemDeleter(std::move(itemDeleter))
1099 {
1100 }
1101 void operator()(void *objPtr, bool dtorOnly) final;
1102 };
1103
1104 std::unique_ptr<RDeleter> fItemDeleter;
1105
1106protected:
1107 std::size_t fItemSize;
1109 std::size_t fValueSize;
1110
1111 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
1112 const RColumnRepresentations &GetColumnRepresentations() const final;
1113 void GenerateColumnsImpl() final;
1114 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1115
1116 void ConstructValue(void *where) const override;
1117 std::unique_ptr<RDeleter> GetDeleter() const override;
1118
1119 std::size_t AppendImpl(const void *from) override;
1120 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) override;
1121 std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final;
1122
1123 void CommitClusterImpl() final { fNWritten = 0; }
1124
1125public:
1126 RRVecField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField);
1127 RRVecField(RRVecField &&) = default;
1129 RRVecField(const RRVecField &) = delete;
1131 ~RRVecField() override = default;
1132
1133 std::vector<RValue> SplitValue(const RValue &value) const final;
1134 size_t GetValueSize() const override;
1135 size_t GetAlignment() const override;
1136 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1137 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
1138 {
1139 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
1140 }
1141 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
1142 {
1143 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
1144 }
1145};
1146
1147/// The generic field for fixed size arrays, which do not need an offset column
1148class RArrayField : public RFieldBase {
1149private:
1150 class RArrayDeleter : public RDeleter {
1151 private:
1152 std::size_t fItemSize = 0;
1153 std::size_t fArrayLength = 0;
1154 std::unique_ptr<RDeleter> fItemDeleter;
1155
1156 public:
1157 RArrayDeleter(std::size_t itemSize, std::size_t arrayLength, std::unique_ptr<RDeleter> itemDeleter)
1158 : fItemSize(itemSize), fArrayLength(arrayLength), fItemDeleter(std::move(itemDeleter))
1159 {
1160 }
1161 void operator()(void *objPtr, bool dtorOnly) final;
1162 };
1163
1164 std::size_t fItemSize;
1165 std::size_t fArrayLength;
1166
1167protected:
1168 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1169
1170 void GenerateColumnsImpl() final {}
1172
1173 void ConstructValue(void *where) const override;
1174 std::unique_ptr<RDeleter> GetDeleter() const final;
1175
1176 std::size_t AppendImpl(const void *from) final;
1177 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1178 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final;
1179
1180public:
1181 RArrayField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, std::size_t arrayLength);
1182 RArrayField(RArrayField &&other) = default;
1183 RArrayField& operator =(RArrayField &&other) = default;
1184 ~RArrayField() override = default;
1185
1186 std::vector<RValue> SplitValue(const RValue &value) const final;
1187 size_t GetLength() const { return fArrayLength; }
1188 size_t GetValueSize() const final { return fItemSize * fArrayLength; }
1189 size_t GetAlignment() const final { return fSubFields[0]->GetAlignment(); }
1190 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1191};
1192
1193/**
1194\class ROOT::Experimental::RArrayAsRVecField
1195\brief A field for fixed-size arrays that are represented as RVecs in memory.
1196\ingroup ntuple
1197This class is used only for reading. In particular, it helps exposing
1198arbitrarily-nested std::array on-disk fields as RVecs for usage in RDataFrame.
1199*/
1200class RArrayAsRVecField final : public RFieldBase {
1201private:
1202 std::unique_ptr<RDeleter> fItemDeleter; /// Sub field deleter or nullptr for simple fields
1203 std::size_t fItemSize; /// The size of a child field's item
1204 std::size_t fArrayLength; /// The length of the arrays in this field
1205 std::size_t fValueSize; /// The size of a value of this field, i.e. an RVec
1206
1207protected:
1208 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1209
1210 void GenerateColumnsImpl() final { R__ASSERT(false && "RArrayAsRVec fields must only be used for reading"); }
1212
1213 void ConstructValue(void *where) const final;
1214 /// Returns an RRVecField::RRVecDeleter
1215 std::unique_ptr<RDeleter> GetDeleter() const final;
1216
1217 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1218 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final;
1219
1220public:
1221 /**
1222 Constructor of the field. the \p itemField argument represents the inner
1223 item of the on-disk array, i.e. for an `std::array<float>` it is the `float`
1224 field and not the `std::array` itself.
1225 */
1226 RArrayAsRVecField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, std::size_t arrayLength);
1227 RArrayAsRVecField(const RArrayAsRVecField &other) = delete;
1228 RArrayAsRVecField &operator=(const RArrayAsRVecField &other) = delete;
1230 RArrayAsRVecField &operator=(RArrayAsRVecField &&other) = default;
1231 ~RArrayAsRVecField() final = default;
1232
1233 std::size_t GetValueSize() const final { return fValueSize; }
1234 std::size_t GetAlignment() const final;
1235
1236 std::vector<RFieldBase::RValue> SplitValue(const RFieldBase::RValue &value) const final;
1237 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1238};
1239
1240/// The generic field an std::bitset<N>. All compilers we care about store the bits in an array of unsigned long.
1241/// TODO(jblomer): reading and writing efficiency should be improved; currently it is one bit at a time
1242/// with an array of bools on the page level.
1243class RBitsetField : public RFieldBase {
1244 using Word_t = unsigned long;
1245 static constexpr std::size_t kWordSize = sizeof(Word_t);
1246 static constexpr std::size_t kBitsPerWord = kWordSize * 8;
1247
1248protected:
1249 std::size_t fN;
1250
1251protected:
1252 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1253 {
1254 return std::make_unique<RBitsetField>(newName, fN);
1255 }
1256 const RColumnRepresentations &GetColumnRepresentations() const final;
1257 void GenerateColumnsImpl() final;
1258 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1259 void ConstructValue(void *where) const final { memset(where, 0, GetValueSize()); }
1260 std::size_t AppendImpl(const void *from) final;
1261 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1262
1263public:
1264 RBitsetField(std::string_view fieldName, std::size_t N);
1265 RBitsetField(RBitsetField &&other) = default;
1267 ~RBitsetField() override = default;
1268
1269 size_t GetValueSize() const final { return kWordSize * ((fN + kBitsPerWord - 1) / kBitsPerWord); }
1270 size_t GetAlignment() const final { return alignof(Word_t); }
1271 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1272
1273 /// Get the number of bits in the bitset, i.e. the N in std::bitset<N>
1274 std::size_t GetN() const { return fN; }
1275};
1276
1277/// The generic field for std::variant types
1279private:
1280 class RVariantDeleter : public RDeleter {
1281 private:
1282 std::size_t fTagOffset;
1283 std::vector<std::unique_ptr<RDeleter>> fItemDeleters;
1284
1285 public:
1286 RVariantDeleter(std::size_t tagOffset, std::vector<std::unique_ptr<RDeleter>> &itemDeleters)
1287 : fTagOffset(tagOffset), fItemDeleters(std::move(itemDeleters))
1288 {
1289 }
1290 void operator()(void *objPtr, bool dtorOnly) final;
1291 };
1292
1293 size_t fMaxItemSize = 0;
1294 size_t fMaxAlignment = 1;
1295 /// In the std::variant memory layout, at which byte number is the index stored
1296 size_t fTagOffset = 0;
1297 std::vector<ClusterSize_t::ValueType> fNWritten;
1298
1299 static std::string GetTypeList(const std::vector<RFieldBase *> &itemFields);
1300 /// Extracts the index from an std::variant and transforms it into the 1-based index used for the switch column
1301 static std::uint32_t GetTag(const void *variantPtr, std::size_t tagOffset);
1302 static void SetTag(void *variantPtr, std::size_t tagOffset, std::uint32_t tag);
1303
1304protected:
1305 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1306
1307 const RColumnRepresentations &GetColumnRepresentations() const final;
1308 void GenerateColumnsImpl() final;
1309 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1310
1311 void ConstructValue(void *where) const override;
1312 std::unique_ptr<RDeleter> GetDeleter() const final;
1313
1314 std::size_t AppendImpl(const void *from) final;
1315 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1316
1317 void CommitClusterImpl() final;
1318
1319public:
1320 // TODO(jblomer): use std::span in signature
1321 RVariantField(std::string_view fieldName, const std::vector<RFieldBase *> &itemFields);
1322 RVariantField(RVariantField &&other) = default;
1323 RVariantField& operator =(RVariantField &&other) = default;
1324 ~RVariantField() override = default;
1325
1326 size_t GetValueSize() const final;
1327 size_t GetAlignment() const final { return fMaxAlignment; }
1328};
1329
1330/// The generic field for a std::set<Type> and std::unordered_set<Type>
1332protected:
1333 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1334
1335public:
1336 RSetField(std::string_view fieldName, std::string_view typeName, std::unique_ptr<RFieldBase> itemField);
1337 RSetField(RSetField &&other) = default;
1338 RSetField &operator=(RSetField &&other) = default;
1339 ~RSetField() override = default;
1340
1341 size_t GetAlignment() const override { return std::alignment_of<std::set<std::max_align_t>>(); }
1342};
1343
1344/// The generic field for a std::map<KeyType, ValueType> and std::unordered_map<KeyType, ValueType>
1346private:
1348
1349protected:
1350 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1351
1352 std::size_t AppendImpl(const void *from) final;
1353 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1354
1355public:
1356 RMapField(std::string_view fieldName, std::string_view typeName, std::unique_ptr<RFieldBase> itemField);
1357 RMapField(RMapField &&other) = default;
1358 RMapField &operator=(RMapField &&other) = default;
1359 ~RMapField() override = default;
1360
1361 std::vector<RValue> SplitValue(const RValue &value) const final;
1362
1363 size_t GetAlignment() const override { return std::alignment_of<std::map<std::max_align_t, std::max_align_t>>(); }
1364};
1365
1366/// The field for values that may or may not be present in an entry. Parent class for unique pointer field and
1367/// optional field. A nullable field cannot be instantiated itself but only its descendants.
1368/// The RNullableField takes care of the on-disk representation. Child classes are responsible for the in-memory
1369/// representation. The on-disk representation can be "dense" or "sparse". Dense nullable fields have a bitmask
1370/// (true: item available, false: item missing) and serialize a default-constructed item for missing items.
1371/// Sparse nullable fields use a (Split)Index[64|32] column to point to the available items.
1372/// By default, items whose size is smaller or equal to 4 bytes (size of (Split)Index32 column element) are stored
1373/// densely.
1375 /// For a dense nullable field, used to write a default-constructed item for missing ones.
1376 std::unique_ptr<RValue> fDefaultItemValue;
1377 /// For a sparse nullable field, the number of written non-null items in this cluster
1378 ClusterSize_t fNWritten{0};
1379
1380protected:
1381 const RFieldBase::RColumnRepresentations &GetColumnRepresentations() const final;
1382 void GenerateColumnsImpl() final;
1383 void GenerateColumnsImpl(const RNTupleDescriptor &) final;
1384
1385 std::size_t AppendNull();
1386 std::size_t AppendValue(const void *from);
1387 void CommitClusterImpl() final { fNWritten = 0; }
1388
1389 /// Given the index of the nullable field, returns the corresponding global index of the subfield or,
1390 /// if it is null, returns kInvalidClusterIndex
1391 RClusterIndex GetItemIndex(NTupleSize_t globalIndex);
1392
1393 RNullableField(std::string_view fieldName, std::string_view typeName, std::unique_ptr<RFieldBase> itemField);
1394
1395public:
1396 RNullableField(RNullableField &&other) = default;
1398 ~RNullableField() override = default;
1399
1400 bool IsDense() const { return GetColumnRepresentative()[0] == EColumnType::kBit; }
1401 bool IsSparse() const { return !IsDense(); }
1402 void SetDense() { SetColumnRepresentative({EColumnType::kBit}); }
1403 void SetSparse() { SetColumnRepresentative({EColumnType::kSplitIndex32}); }
1404
1405 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1406};
1407
1410 private:
1411 std::unique_ptr<RDeleter> fItemDeleter;
1412
1413 public:
1414 explicit RUniquePtrDeleter(std::unique_ptr<RDeleter> itemDeleter) : fItemDeleter(std::move(itemDeleter)) {}
1415 void operator()(void *objPtr, bool dtorOnly) final;
1416 };
1417
1418 std::unique_ptr<RDeleter> fItemDeleter;
1419
1420protected:
1421 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1422
1423 void ConstructValue(void *where) const final { new (where) std::unique_ptr<char>(); }
1424 std::unique_ptr<RDeleter> GetDeleter() const final;
1425
1426 std::size_t AppendImpl(const void *from) final;
1427 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1428
1429public:
1430 RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr<RFieldBase> itemField);
1432 RUniquePtrField &operator=(RUniquePtrField &&other) = default;
1433 ~RUniquePtrField() override = default;
1434
1435 std::vector<RValue> SplitValue(const RValue &value) const final;
1436 size_t GetValueSize() const final { return sizeof(std::unique_ptr<char>); }
1437 size_t GetAlignment() const final { return alignof(std::unique_ptr<char>); }
1438};
1439
1440class RAtomicField : public RFieldBase {
1441protected:
1442 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1443 void GenerateColumnsImpl() final {}
1445
1446 void ConstructValue(void *where) const final { CallConstructValueOn(*fSubFields[0], where); }
1447 std::unique_ptr<RDeleter> GetDeleter() const final { return GetDeleterOf(*fSubFields[0]); }
1448
1449 std::size_t AppendImpl(const void *from) final { return CallAppendOn(*fSubFields[0], from); }
1450 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final { CallReadOn(*fSubFields[0], globalIndex, to); }
1451 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final { CallReadOn(*fSubFields[0], clusterIndex, to); }
1452
1453public:
1454 RAtomicField(std::string_view fieldName, std::string_view typeName, std::unique_ptr<RFieldBase> itemField);
1455 RAtomicField(RAtomicField &&other) = default;
1457 ~RAtomicField() override = default;
1458
1459 std::vector<RValue> SplitValue(const RValue &value) const final;
1460
1461 size_t GetValueSize() const final { return fSubFields[0]->GetValueSize(); }
1462 size_t GetAlignment() const final { return fSubFields[0]->GetAlignment(); }
1463
1464 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1465};
1466
1467/// Classes with dictionaries that can be inspected by TClass
1468template <typename T, typename = void>
1469class RField final : public RClassField {
1470protected:
1471 void ConstructValue(void *where) const final
1472 {
1473 if constexpr (std::is_default_constructible_v<T>) {
1474 new (where) T();
1475 } else {
1476 // If there is no default constructor, try with the IO constructor
1477 new (where) T(static_cast<TRootIOCtor *>(nullptr));
1478 }
1479 }
1480
1481public:
1482 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
1483 RField(std::string_view name) : RClassField(name, TypeName()) {
1484 static_assert(std::is_class_v<T>, "no I/O support for this basic C++ type");
1485 }
1486 RField(RField &&other) = default;
1487 RField &operator=(RField &&other) = default;
1488 ~RField() override = default;
1489};
1490
1491template <typename T>
1492class RField<T, typename std::enable_if<std::is_enum_v<T>>::type> : public REnumField {
1493public:
1494 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
1495 RField(std::string_view name) : REnumField(name, TypeName()) {}
1496 RField(RField &&other) = default;
1497 RField &operator=(RField &&other) = default;
1498 ~RField() override = default;
1499};
1500
1501template <typename T, typename = void>
1502struct HasCollectionProxyMemberType : std::false_type {
1503};
1504template <typename T>
1506 T, typename std::enable_if<std::is_same<typename T::IsCollectionProxy, std::true_type>::value>::type>
1507 : std::true_type {
1508};
1509
1510/// The point here is that we can only tell at run time if a class has an associated collection proxy.
1511/// For compile time, in the first iteration of this PR we had an extra template argument that acted as a "tag" to
1512/// differentiate the RField specialization for classes with an associated collection proxy (inherits
1513/// `RProxiedCollectionField`) from the RField primary template definition (`RClassField`-derived), as in:
1514/// ```
1515/// auto field = std::make_unique<RField<MyClass>>("klass");
1516/// // vs
1517/// auto otherField = std::make_unique<RField<MyClass, ROOT::Experimental::TagIsCollectionProxy>>("klass");
1518/// ```
1519///
1520/// That is convenient only for non-nested types, i.e. it doesn't work with, e.g. `RField<std::vector<MyClass>,
1521/// ROOT::Experimental::TagIsCollectionProxy>`, as the tag is not forwarded to the instantiation of the inner RField
1522/// (that for the value type of the vector). The following two possible solutions were considered:
1523/// - A wrapper type (much like `ntuple/v7/inc/ROOT/RNTupleUtil.hxx:49`), that helps to differentiate both cases.
1524/// There we would have:
1525/// ```
1526/// auto field = std::make_unique<RField<RProxiedCollection<MyClass>>>("klass"); // Using collection proxy
1527/// ```
1528/// - A helper `IsCollectionProxy<T>` type, that can be used in a similar way to those in the `<type_traits>` header.
1529/// We found this more convenient and is the implemented thing below. Here, classes can be marked as a
1530/// collection proxy with either of the following two forms (whichever is more convenient for the user):
1531/// ```
1532/// template <>
1533/// struct IsCollectionProxy<MyClass> : std::true_type {};
1534/// ```
1535/// or by adding a member type to the class as follows:
1536/// ```
1537/// class MyClass {
1538/// public:
1539/// using IsCollectionProxy = std::true_type;
1540/// };
1541/// ```
1542///
1543/// Of course, there is another possible solution which is to have a single `RClassField` that implements both
1544/// the regular-class and the collection-proxy behaviors, and always chooses appropriately at run time.
1545/// We found that less clean and probably has more overhead, as most probably it involves an additional branch + call
1546/// in each of the member functions.
1547template <typename T, typename = void>
1549};
1550
1551/// Classes behaving as a collection of elements that can be queried via the `TVirtualCollectionProxy` interface
1552/// The use of a collection proxy for a particular class can be enabled via:
1553/// ```
1554/// namespace ROOT::Experimental {
1555/// template <> struct IsCollectionProxy<Classname> : std::true_type {};
1556/// }
1557/// ```
1558/// Alternatively, this can be achieved by adding a member type to the class definition as follows:
1559/// ```
1560/// class Classname {
1561/// public:
1562/// using IsCollectionProxy = std::true_type;
1563/// };
1564/// ```
1565template <typename T>
1566class RField<T, typename std::enable_if<IsCollectionProxy<T>::value>::type> final : public RProxiedCollectionField {
1567protected:
1568 void ConstructValue(void *where) const final { new (where) T(); }
1569
1570public:
1571 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
1572 RField(std::string_view name) : RProxiedCollectionField(name, TypeName())
1573 {
1574 static_assert(std::is_class<T>::value, "collection proxy unsupported for fundamental types");
1575 }
1576 RField(RField&& other) = default;
1577 RField& operator =(RField&& other) = default;
1578 ~RField() override = default;
1579};
1580
1581/// The collection field is only used for writing; when reading, untyped collections are projected to an std::vector
1583private:
1584 /// Save the link to the collection ntuple in order to reset the offset counter when committing the cluster
1585 std::shared_ptr<RNTupleCollectionWriter> fCollectionWriter;
1586
1587protected:
1588 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
1589 const RColumnRepresentations &GetColumnRepresentations() const final;
1590 void GenerateColumnsImpl() final;
1591 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1592 void ConstructValue(void *) const final {}
1593
1594 std::size_t AppendImpl(const void *from) final;
1595 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
1596
1597 void CommitClusterImpl() final;
1598
1599public:
1600 static std::string TypeName() { return ""; }
1601 RCollectionField(std::string_view name, std::shared_ptr<RNTupleCollectionWriter> collectionWriter,
1602 std::unique_ptr<RFieldZero> collectionParent);
1605 ~RCollectionField() override = default;
1606
1607 size_t GetValueSize() const final { return sizeof(ClusterSize_t); }
1608 size_t GetAlignment() const final { return alignof(ClusterSize_t); }
1609};
1610
1611/// The generic field for `std::pair<T1, T2>` types
1612class RPairField : public RRecordField {
1613private:
1614 class RPairDeleter : public RDeleter {
1615 private:
1617
1618 public:
1619 explicit RPairDeleter(TClass *cl) : fClass(cl) {}
1620 void operator()(void *objPtr, bool dtorOnly) final;
1621 };
1622
1623 TClass *fClass = nullptr;
1624 static std::string GetTypeList(const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);
1625
1626protected:
1627 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
1628
1629 void ConstructValue(void *where) const override;
1630 std::unique_ptr<RDeleter> GetDeleter() const override { return std::make_unique<RPairDeleter>(fClass); }
1631
1632 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> &&itemFields,
1633 const std::array<std::size_t, 2> &offsets);
1634
1635public:
1636 RPairField(std::string_view fieldName, std::array<std::unique_ptr<RFieldBase>, 2> &itemFields);
1637 RPairField(RPairField &&other) = default;
1638 RPairField &operator=(RPairField &&other) = default;
1639 ~RPairField() override = default;
1640};
1641
1642/// The generic field for `std::tuple<Ts...>` types
1644private:
1645 class RTupleDeleter : public RDeleter {
1646 private:
1648
1649 public:
1650 explicit RTupleDeleter(TClass *cl) : fClass(cl) {}
1651 void operator()(void *objPtr, bool dtorOnly) final;
1652 };
1653
1654 TClass *fClass = nullptr;
1655 static std::string GetTypeList(const std::vector<std::unique_ptr<RFieldBase>> &itemFields);
1656
1657protected:
1658 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const override;
1659
1660 void ConstructValue(void *where) const override;
1661 std::unique_ptr<RDeleter> GetDeleter() const override { return std::make_unique<RTupleDeleter>(fClass); }
1662
1663 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
1664 const std::vector<std::size_t> &offsets);
1665
1666public:
1667 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> &itemFields);
1668 RTupleField(RTupleField &&other) = default;
1669 RTupleField &operator=(RTupleField &&other) = default;
1670 ~RTupleField() override = default;
1671};
1672
1673/// An artificial field that transforms an RNTuple column that contains the offset of collections into
1674/// collection sizes. It is only used for reading, e.g. as projected field or as an artificial field that provides the
1675/// "number of" RDF columns for collections (e.g. `R_rdf_sizeof_jets` for a collection named `jets`).
1676/// It is used in the templated RField<RNTupleCardinality<SizeT>> form, which represents the collection sizes either
1677/// as 32bit unsigned int (std::uint32_t) or as 64bit unsigned int (std::uint64_t).
1679protected:
1680 RCardinalityField(std::string_view fieldName, std::string_view typeName)
1681 : RFieldBase(fieldName, typeName, ENTupleStructure::kLeaf, false /* isSimple */)
1682 {
1683 }
1684
1685 const RColumnRepresentations &GetColumnRepresentations() const final;
1686 // Field is only used for reading
1687 void GenerateColumnsImpl() final { throw RException(R__FAIL("Cardinality fields must only be used for reading")); }
1688 void GenerateColumnsImpl(const RNTupleDescriptor &) final;
1689
1690public:
1693 ~RCardinalityField() override = default;
1694
1695 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1696
1697 const RField<RNTupleCardinality<std::uint32_t>> *As32Bit() const;
1698 const RField<RNTupleCardinality<std::uint64_t>> *As64Bit() const;
1699};
1700
1701////////////////////////////////////////////////////////////////////////////////
1702/// Template specializations for concrete C++ types
1703////////////////////////////////////////////////////////////////////////////////
1704
1705template <>
1706class RField<void> : public RFieldBase {
1707public:
1708 static std::string TypeName() { return "void"; }
1709 // RField<void> should never be constructed.
1710 RField() = delete;
1711 RField(const RField &) = delete;
1712 RField &operator=(const RField &) = delete;
1713};
1714
1715template <>
1716class RField<ClusterSize_t> final : public RFieldBase {
1717protected:
1718 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1719 {
1720 return std::make_unique<RField>(newName);
1721 }
1722
1724 void GenerateColumnsImpl() final;
1725 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1726 void ConstructValue(void *where) const final { new (where) ClusterSize_t(0); }
1727
1728public:
1729 static std::string TypeName() { return "ROOT::Experimental::ClusterSize_t"; }
1730 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1731 {
1732 fTraits |= kTraitTrivialType;
1733 }
1734 RField(RField&& other) = default;
1735 RField& operator =(RField&& other) = default;
1736 ~RField() override = default;
1737
1739 return fPrincipalColumn->Map<ClusterSize_t>(globalIndex);
1740 }
1741 ClusterSize_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<ClusterSize_t>(clusterIndex); }
1743 return fPrincipalColumn->MapV<ClusterSize_t>(globalIndex, nItems);
1744 }
1746 {
1747 return fPrincipalColumn->MapV<ClusterSize_t>(clusterIndex, nItems);
1748 }
1749
1750 size_t GetValueSize() const final { return sizeof(ClusterSize_t); }
1751 size_t GetAlignment() const final { return alignof(ClusterSize_t); }
1752
1753 /// Special help for offset fields
1754 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) {
1755 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
1756 }
1757 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
1758 {
1759 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
1760 }
1761 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1762};
1763
1764template <typename SizeT>
1765class RField<RNTupleCardinality<SizeT>> final : public RCardinalityField {
1766protected:
1767 std::unique_ptr<ROOT::Experimental::RFieldBase> CloneImpl(std::string_view newName) const final
1768 {
1769 return std::make_unique<RField<RNTupleCardinality<SizeT>>>(newName);
1770 }
1771 void ConstructValue(void *where) const final { new (where) RNTupleCardinality<SizeT>(0); }
1772
1773public:
1774 static std::string TypeName() { return "ROOT::Experimental::RNTupleCardinality<" + RField<SizeT>::TypeName() + ">"; }
1775 explicit RField(std::string_view name) : RCardinalityField(name, TypeName()) {}
1776 RField(RField &&other) = default;
1777 RField &operator=(RField &&other) = default;
1778 ~RField() override = default;
1779
1780 size_t GetValueSize() const final { return sizeof(RNTupleCardinality<SizeT>); }
1781 size_t GetAlignment() const final { return alignof(RNTupleCardinality<SizeT>); }
1782
1783 /// Get the number of elements of the collection identified by globalIndex
1784 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
1785 {
1786 RClusterIndex collectionStart;
1788 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &size);
1789 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
1790 }
1791
1792 /// Get the number of elements of the collection identified by clusterIndex
1793 void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
1794 {
1795 RClusterIndex collectionStart;
1797 fPrincipalColumn->GetCollectionInfo(clusterIndex, &collectionStart, &size);
1798 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
1799 }
1800
1801 std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
1802 {
1803 RClusterIndex collectionStart;
1804 ClusterSize_t collectionSize;
1805 fPrincipalColumn->GetCollectionInfo(bulkSpec.fFirstIndex, &collectionStart, &collectionSize);
1806
1807 auto typedValues = static_cast<RNTupleCardinality<SizeT> *>(bulkSpec.fValues);
1808 typedValues[0] = collectionSize;
1809
1810 auto lastOffset = collectionStart.GetIndex() + collectionSize;
1811 ClusterSize_t::ValueType nRemainingEntries = bulkSpec.fCount - 1;
1812 std::size_t nEntries = 1;
1813 while (nRemainingEntries > 0) {
1814 NTupleSize_t nItemsUntilPageEnd;
1815 auto offsets = fPrincipalColumn->MapV<ClusterSize_t>(bulkSpec.fFirstIndex + nEntries, nItemsUntilPageEnd);
1816 std::size_t nBatch = std::min(nRemainingEntries, nItemsUntilPageEnd);
1817 for (std::size_t i = 0; i < nBatch; ++i) {
1818 typedValues[nEntries + i] = offsets[i] - lastOffset;
1819 lastOffset = offsets[i];
1820 }
1821 nRemainingEntries -= nBatch;
1822 nEntries += nBatch;
1823 }
1824 return RBulkSpec::kAllSet;
1825 }
1826};
1827
1828template <>
1829class RField<bool> final : public RFieldBase {
1830protected:
1831 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1832 {
1833 return std::make_unique<RField>(newName);
1834 }
1835
1836 const RColumnRepresentations &GetColumnRepresentations() const final;
1837 void GenerateColumnsImpl() final;
1838 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1839 void ConstructValue(void *where) const final { new (where) bool(false); }
1840
1841public:
1842 static std::string TypeName() { return "bool"; }
1843 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1844 {
1845 fTraits |= kTraitTrivialType;
1846 }
1847 RField(RField&& other) = default;
1848 RField& operator =(RField&& other) = default;
1849 ~RField() override = default;
1850
1851 bool *Map(NTupleSize_t globalIndex) {
1852 return fPrincipalColumn->Map<bool>(globalIndex);
1853 }
1854 bool *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<bool>(clusterIndex); }
1855 bool *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1856 return fPrincipalColumn->MapV<bool>(globalIndex, nItems);
1857 }
1858 bool *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
1859 {
1860 return fPrincipalColumn->MapV<bool>(clusterIndex, nItems);
1861 }
1862
1863 size_t GetValueSize() const final { return sizeof(bool); }
1864 size_t GetAlignment() const final { return alignof(bool); }
1865 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1866};
1867
1868template <>
1869class RField<float> final : public RFieldBase {
1870protected:
1871 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1872 {
1873 return std::make_unique<RField>(newName);
1874 }
1875
1876 const RColumnRepresentations &GetColumnRepresentations() const final;
1877 void GenerateColumnsImpl() final;
1878 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1879 void ConstructValue(void *where) const final { new (where) float(0.0); }
1880
1881public:
1882 static std::string TypeName() { return "float"; }
1883 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1884 {
1885 fTraits |= kTraitTrivialType;
1886 }
1887 RField(RField&& other) = default;
1888 RField& operator =(RField&& other) = default;
1889 ~RField() override = default;
1890
1891 float *Map(NTupleSize_t globalIndex) {
1892 return fPrincipalColumn->Map<float>(globalIndex);
1893 }
1894 float *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<float>(clusterIndex); }
1895 float *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1896 return fPrincipalColumn->MapV<float>(globalIndex, nItems);
1897 }
1898 float *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
1899 {
1900 return fPrincipalColumn->MapV<float>(clusterIndex, nItems);
1901 }
1902
1903 size_t GetValueSize() const final { return sizeof(float); }
1904 size_t GetAlignment() const final { return alignof(float); }
1905 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1906
1907 void SetHalfPrecision();
1908};
1909
1910template <>
1911class RField<double> final : public RFieldBase {
1912protected:
1913 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1914 {
1915 return std::make_unique<RField>(newName);
1916 }
1917
1918 const RColumnRepresentations &GetColumnRepresentations() const final;
1919 void GenerateColumnsImpl() final;
1920 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1921 void ConstructValue(void *where) const final { new (where) double(0.0); }
1922
1923public:
1924 static std::string TypeName() { return "double"; }
1925 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1926 {
1927 fTraits |= kTraitTrivialType;
1928 }
1929 RField(RField&& other) = default;
1930 RField& operator =(RField&& other) = default;
1931 ~RField() override = default;
1932
1933 double *Map(NTupleSize_t globalIndex) {
1934 return fPrincipalColumn->Map<double>(globalIndex);
1935 }
1936 double *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<double>(clusterIndex); }
1937 double *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1938 return fPrincipalColumn->MapV<double>(globalIndex, nItems);
1939 }
1940 double *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
1941 {
1942 return fPrincipalColumn->MapV<double>(clusterIndex, nItems);
1943 }
1944
1945 size_t GetValueSize() const final { return sizeof(double); }
1946 size_t GetAlignment() const final { return alignof(double); }
1947 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1948
1949 // Set the column representation to 32 bit floating point and the type alias to Double32_t
1950 void SetDouble32();
1951};
1952
1953template <>
1954class RField<std::byte> final : public RFieldBase {
1955protected:
1956 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1957 {
1958 return std::make_unique<RField>(newName);
1959 }
1960
1961 const RColumnRepresentations &GetColumnRepresentations() const final;
1962 void GenerateColumnsImpl() final;
1963 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1964 void ConstructValue(void *where) const final { new (where) std::byte{0}; }
1965
1966public:
1967 static std::string TypeName() { return "std::byte"; }
1968 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1969 {
1970 fTraits |= kTraitTrivialType;
1971 }
1972 RField(RField &&other) = default;
1973 RField &operator=(RField &&other) = default;
1974 ~RField() override = default;
1975
1976 std::byte *Map(NTupleSize_t globalIndex) { return fPrincipalColumn->Map<std::byte>(globalIndex); }
1977 std::byte *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::byte>(clusterIndex); }
1978 std::byte *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
1979 {
1980 return fPrincipalColumn->MapV<std::byte>(globalIndex, nItems);
1981 }
1982 std::byte *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
1983 {
1984 return fPrincipalColumn->MapV<std::byte>(clusterIndex, nItems);
1985 }
1986
1987 size_t GetValueSize() const final { return sizeof(std::byte); }
1988 size_t GetAlignment() const final { return alignof(std::byte); }
1989 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1990};
1991
1992template <>
1993class RField<char> final : public RFieldBase {
1994protected:
1995 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
1996 {
1997 return std::make_unique<RField>(newName);
1998 }
1999
2000 const RColumnRepresentations &GetColumnRepresentations() const final;
2001 void GenerateColumnsImpl() final;
2002 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2003 void ConstructValue(void *where) const final { new (where) char(0); }
2004
2005public:
2006 static std::string TypeName() { return "char"; }
2007 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2008 {
2009 fTraits |= kTraitTrivialType;
2010 }
2011 RField(RField&& other) = default;
2012 RField& operator =(RField&& other) = default;
2013 ~RField() override = default;
2014
2015 char *Map(NTupleSize_t globalIndex) {
2016 return fPrincipalColumn->Map<char>(globalIndex);
2017 }
2018 char *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<char>(clusterIndex); }
2019 char *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2020 return fPrincipalColumn->MapV<char>(globalIndex, nItems);
2021 }
2022 char *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2023 {
2024 return fPrincipalColumn->MapV<char>(clusterIndex, nItems);
2025 }
2026
2027 size_t GetValueSize() const final { return sizeof(char); }
2028 size_t GetAlignment() const final { return alignof(char); }
2029 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2030};
2031
2032template <>
2033class RField<std::int8_t> final : public RFieldBase {
2034protected:
2035 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2036 {
2037 return std::make_unique<RField>(newName);
2038 }
2039
2040 const RColumnRepresentations &GetColumnRepresentations() const final;
2041 void GenerateColumnsImpl() final;
2042 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2043 void ConstructValue(void *where) const final { new (where) int8_t(0); }
2044
2045public:
2046 static std::string TypeName() { return "std::int8_t"; }
2047 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2048 {
2049 fTraits |= kTraitTrivialType;
2050 }
2051 RField(RField&& other) = default;
2052 RField& operator =(RField&& other) = default;
2053 ~RField() override = default;
2054
2055 std::int8_t *Map(NTupleSize_t globalIndex) {
2056 return fPrincipalColumn->Map<std::int8_t>(globalIndex);
2057 }
2058 std::int8_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::int8_t>(clusterIndex); }
2059 std::int8_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2060 return fPrincipalColumn->MapV<std::int8_t>(globalIndex, nItems);
2061 }
2062 std::int8_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2063 {
2064 return fPrincipalColumn->MapV<std::int8_t>(clusterIndex, nItems);
2065 }
2066
2067 size_t GetValueSize() const final { return sizeof(std::int8_t); }
2068 size_t GetAlignment() const final { return alignof(std::int8_t); }
2069 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2070};
2071
2072template <>
2073class RField<std::uint8_t> final : public RFieldBase {
2074protected:
2075 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2076 {
2077 return std::make_unique<RField>(newName);
2078 }
2079
2080 const RColumnRepresentations &GetColumnRepresentations() const final;
2081 void GenerateColumnsImpl() final;
2082 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2083 void ConstructValue(void *where) const final { new (where) uint8_t(0); }
2084
2085public:
2086 static std::string TypeName() { return "std::uint8_t"; }
2087 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2088 {
2089 fTraits |= kTraitTrivialType;
2090 }
2091 RField(RField&& other) = default;
2092 RField& operator =(RField&& other) = default;
2093 ~RField() override = default;
2094
2095 std::uint8_t *Map(NTupleSize_t globalIndex) {
2096 return fPrincipalColumn->Map<std::uint8_t>(globalIndex);
2097 }
2098 std::uint8_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::uint8_t>(clusterIndex); }
2099 std::uint8_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2100 return fPrincipalColumn->MapV<std::uint8_t>(globalIndex, nItems);
2101 }
2102 std::uint8_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2103 {
2104 return fPrincipalColumn->MapV<std::uint8_t>(clusterIndex, nItems);
2105 }
2106
2107 size_t GetValueSize() const final { return sizeof(std::uint8_t); }
2108 size_t GetAlignment() const final { return alignof(std::uint8_t); }
2109 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2110};
2111
2112template <>
2113class RField<std::int16_t> final : public RFieldBase {
2114protected:
2115 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2116 {
2117 return std::make_unique<RField>(newName);
2118 }
2119
2120 const RColumnRepresentations &GetColumnRepresentations() const final;
2121 void GenerateColumnsImpl() final;
2122 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2123 void ConstructValue(void *where) const final { new (where) int16_t(0); }
2124
2125public:
2126 static std::string TypeName() { return "std::int16_t"; }
2127 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2128 {
2129 fTraits |= kTraitTrivialType;
2130 }
2131 RField(RField&& other) = default;
2132 RField& operator =(RField&& other) = default;
2133 ~RField() override = default;
2134
2135 std::int16_t *Map(NTupleSize_t globalIndex) {
2136 return fPrincipalColumn->Map<std::int16_t>(globalIndex);
2137 }
2138 std::int16_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::int16_t>(clusterIndex); }
2139 std::int16_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2140 return fPrincipalColumn->MapV<std::int16_t>(globalIndex, nItems);
2141 }
2142 std::int16_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2143 {
2144 return fPrincipalColumn->MapV<std::int16_t>(clusterIndex, nItems);
2145 }
2146
2147 size_t GetValueSize() const final { return sizeof(std::int16_t); }
2148 size_t GetAlignment() const final { return alignof(std::int16_t); }
2149 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2150};
2151
2152template <>
2153class RField<std::uint16_t> final : public RFieldBase {
2154protected:
2155 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2156 {
2157 return std::make_unique<RField>(newName);
2158 }
2159
2160 const RColumnRepresentations &GetColumnRepresentations() const final;
2161 void GenerateColumnsImpl() final;
2162 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2163 void ConstructValue(void *where) const final { new (where) int16_t(0); }
2164
2165public:
2166 static std::string TypeName() { return "std::uint16_t"; }
2167 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2168 {
2169 fTraits |= kTraitTrivialType;
2170 }
2171 RField(RField&& other) = default;
2172 RField& operator =(RField&& other) = default;
2173 ~RField() override = default;
2174
2175 std::uint16_t *Map(NTupleSize_t globalIndex) {
2176 return fPrincipalColumn->Map<std::uint16_t>(globalIndex);
2177 }
2178 std::uint16_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::uint16_t>(clusterIndex); }
2179 std::uint16_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2180 return fPrincipalColumn->MapV<std::uint16_t>(globalIndex, nItems);
2181 }
2182 std::uint16_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2183 {
2184 return fPrincipalColumn->MapV<std::uint16_t>(clusterIndex, nItems);
2185 }
2186
2187 size_t GetValueSize() const final { return sizeof(std::uint16_t); }
2188 size_t GetAlignment() const final { return alignof(std::uint16_t); }
2189 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2190};
2191
2192template <>
2193class RField<std::int32_t> final : public RFieldBase {
2194protected:
2195 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2196 {
2197 return std::make_unique<RField>(newName);
2198 }
2199
2200 const RColumnRepresentations &GetColumnRepresentations() const final;
2201 void GenerateColumnsImpl() final;
2202 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2203 void ConstructValue(void *where) const final { new (where) int32_t(0); }
2204
2205public:
2206 static std::string TypeName() { return "std::int32_t"; }
2207 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2208 {
2209 fTraits |= kTraitTrivialType;
2210 }
2211 RField(RField&& other) = default;
2212 RField& operator =(RField&& other) = default;
2213 ~RField() override = default;
2214
2215 std::int32_t *Map(NTupleSize_t globalIndex) {
2216 return fPrincipalColumn->Map<std::int32_t>(globalIndex);
2217 }
2218 std::int32_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::int32_t>(clusterIndex); }
2219 std::int32_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2220 return fPrincipalColumn->MapV<std::int32_t>(globalIndex, nItems);
2221 }
2222 std::int32_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2223 {
2224 return fPrincipalColumn->MapV<std::int32_t>(clusterIndex, nItems);
2225 }
2226
2227 size_t GetValueSize() const final { return sizeof(std::int32_t); }
2228 size_t GetAlignment() const final { return alignof(std::int32_t); }
2229 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2230};
2231
2232template <>
2233class RField<std::uint32_t> final : public RFieldBase {
2234protected:
2235 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2236 {
2237 return std::make_unique<RField>(newName);
2238 }
2239
2240 const RColumnRepresentations &GetColumnRepresentations() const final;
2241 void GenerateColumnsImpl() final;
2242 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2243 void ConstructValue(void *where) const final { new (where) uint32_t(0); }
2244
2245public:
2246 static std::string TypeName() { return "std::uint32_t"; }
2247 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2248 {
2249 fTraits |= kTraitTrivialType;
2250 }
2251 RField(RField&& other) = default;
2252 RField& operator =(RField&& other) = default;
2253 ~RField() override = default;
2254
2255 std::uint32_t *Map(NTupleSize_t globalIndex) {
2256 return fPrincipalColumn->Map<std::uint32_t>(globalIndex);
2257 }
2258 std::uint32_t *Map(const RClusterIndex clusterIndex) {
2259 return fPrincipalColumn->Map<std::uint32_t>(clusterIndex);
2260 }
2261 std::uint32_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2262 return fPrincipalColumn->MapV<std::uint32_t>(globalIndex, nItems);
2263 }
2264 std::uint32_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2265 {
2266 return fPrincipalColumn->MapV<std::uint32_t>(clusterIndex, nItems);
2267 }
2268
2269 size_t GetValueSize() const final { return sizeof(std::uint32_t); }
2270 size_t GetAlignment() const final { return alignof(std::uint32_t); }
2271 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2272};
2273
2274template <>
2275class RField<std::uint64_t> final : public RFieldBase {
2276protected:
2277 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2278 {
2279 return std::make_unique<RField>(newName);
2280 }
2281
2282 const RColumnRepresentations &GetColumnRepresentations() const final;
2283 void GenerateColumnsImpl() final;
2284 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2285 void ConstructValue(void *where) const final { new (where) uint64_t(0); }
2286
2287public:
2288 static std::string TypeName() { return "std::uint64_t"; }
2289 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2290 {
2291 fTraits |= kTraitTrivialType;
2292 }
2293 RField(RField&& other) = default;
2294 RField& operator =(RField&& other) = default;
2295 ~RField() override = default;
2296
2297 std::uint64_t *Map(NTupleSize_t globalIndex) {
2298 return fPrincipalColumn->Map<std::uint64_t>(globalIndex);
2299 }
2300 std::uint64_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::uint64_t>(clusterIndex); }
2301 std::uint64_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2302 return fPrincipalColumn->MapV<std::uint64_t>(globalIndex, nItems);
2303 }
2304 std::uint64_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2305 {
2306 return fPrincipalColumn->MapV<std::uint64_t>(clusterIndex, nItems);
2307 }
2308
2309 size_t GetValueSize() const final { return sizeof(std::uint64_t); }
2310 size_t GetAlignment() const final { return alignof(std::uint64_t); }
2311 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2312};
2313
2314template <>
2315class RField<std::int64_t> final : public RFieldBase {
2316protected:
2317 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2318 {
2319 return std::make_unique<RField>(newName);
2320 }
2321
2322 const RColumnRepresentations &GetColumnRepresentations() const final;
2323 void GenerateColumnsImpl() final;
2324 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2325 void ConstructValue(void *where) const final { new (where) int64_t(0); }
2326
2327public:
2328 static std::string TypeName() { return "std::int64_t"; }
2329 explicit RField(std::string_view name) : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
2330 {
2331 fTraits |= kTraitTrivialType;
2332 }
2333 RField(RField&& other) = default;
2334 RField& operator =(RField&& other) = default;
2335 ~RField() override = default;
2336
2337 std::int64_t *Map(NTupleSize_t globalIndex) {
2338 return fPrincipalColumn->Map<std::int64_t>(globalIndex);
2339 }
2340 std::int64_t *Map(RClusterIndex clusterIndex) { return fPrincipalColumn->Map<std::int64_t>(clusterIndex); }
2341 std::int64_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
2342 return fPrincipalColumn->MapV<std::int64_t>(globalIndex, nItems);
2343 }
2344 std::int64_t *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
2345 {
2346 return fPrincipalColumn->MapV<std::int64_t>(clusterIndex, nItems);
2347 }
2348
2349 size_t GetValueSize() const final { return sizeof(std::int64_t); }
2350 size_t GetAlignment() const final { return alignof(std::int64_t); }
2351 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2352};
2353
2354template <>
2355class RField<std::string> final : public RFieldBase {
2356private:
2357 ClusterSize_t fIndex;
2358
2359 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2360 {
2361 return std::make_unique<RField>(newName);
2362 }
2363
2364 const RColumnRepresentations &GetColumnRepresentations() const final;
2365 void GenerateColumnsImpl() final;
2366 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2367
2368 void ConstructValue(void *where) const final { new (where) std::string(); }
2369 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<std::string>>(); }
2370
2371 std::size_t AppendImpl(const void *from) final;
2372 void ReadGlobalImpl(ROOT::Experimental::NTupleSize_t globalIndex, void *to) final;
2373
2374 void CommitClusterImpl() final { fIndex = 0; }
2375
2376public:
2377 static std::string TypeName() { return "std::string"; }
2378 explicit RField(std::string_view name)
2379 : RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, false /* isSimple */), fIndex(0)
2380 {
2381 }
2382 RField(RField&& other) = default;
2383 RField& operator =(RField&& other) = default;
2384 ~RField() override = default;
2385
2386 size_t GetValueSize() const final { return sizeof(std::string); }
2387 size_t GetAlignment() const final { return std::alignment_of<std::string>(); }
2388 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2389};
2390
2391template <typename ItemT, std::size_t N>
2392class RField<std::array<ItemT, N>> : public RArrayField {
2393 using ContainerT = typename std::array<ItemT, N>;
2394
2395protected:
2396 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2397
2398public:
2399 static std::string TypeName() {
2400 return "std::array<" + RField<ItemT>::TypeName() + "," + std::to_string(N) + ">";
2401 }
2402 explicit RField(std::string_view name) : RArrayField(name, std::make_unique<RField<ItemT>>("_0"), N)
2403 {}
2404 RField(RField&& other) = default;
2405 RField& operator =(RField&& other) = default;
2406 ~RField() override = default;
2407};
2408
2409template <typename ItemT, std::size_t N>
2410class RField<ItemT[N]> final : public RField<std::array<ItemT, N>> {
2411public:
2412 explicit RField(std::string_view name) : RField<std::array<ItemT, N>>(name) {}
2413 RField(RField &&other) = default;
2414 RField &operator=(RField &&other) = default;
2415 ~RField() override = default;
2416};
2417
2418template <typename ItemT>
2419class RField<std::set<ItemT>> : public RSetField {
2420 using ContainerT = typename std::set<ItemT>;
2421
2422protected:
2423 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2424 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2425
2426public:
2427 static std::string TypeName() { return "std::set<" + RField<ItemT>::TypeName() + ">"; }
2428
2429 explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique<RField<ItemT>>("_0")) {}
2430 RField(RField &&other) = default;
2431 RField &operator=(RField &&other) = default;
2432 ~RField() override = default;
2433
2434 size_t GetValueSize() const final { return sizeof(ContainerT); }
2435 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
2436};
2437
2438template <typename ItemT>
2439class RField<std::unordered_set<ItemT>> final : public RSetField {
2440 using ContainerT = typename std::unordered_set<ItemT>;
2441
2442protected:
2443 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2444 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2445
2446public:
2447 static std::string TypeName() { return "std::unordered_set<" + RField<ItemT>::TypeName() + ">"; }
2448
2449 explicit RField(std::string_view name) : RSetField(name, TypeName(), std::make_unique<RField<ItemT>>("_0")) {}
2450 RField(RField &&other) = default;
2451 RField &operator=(RField &&other) = default;
2452 ~RField() override = default;
2453
2454 size_t GetValueSize() const final { return sizeof(ContainerT); }
2455 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
2456};
2457
2458template <typename KeyT, typename ValueT>
2459class RField<std::map<KeyT, ValueT>> final : public RMapField {
2460 using ContainerT = typename std::map<KeyT, ValueT>;
2461
2462protected:
2463 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2464 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2465
2466public:
2467 static std::string TypeName()
2468 {
2469 return "std::map<" + RField<KeyT>::TypeName() + "," + RField<ValueT>::TypeName() + ">";
2470 }
2471
2472 explicit RField(std::string_view name)
2473 : RMapField(name, TypeName(), std::make_unique<RField<std::pair<KeyT, ValueT>>>("_0"))
2474 {
2475 }
2476 RField(RField &&other) = default;
2477 RField &operator=(RField &&other) = default;
2478 ~RField() override = default;
2479
2480 size_t GetValueSize() const final { return sizeof(ContainerT); }
2481 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
2482};
2483
2484template <typename KeyT, typename ValueT>
2485class RField<std::unordered_map<KeyT, ValueT>> final : public RMapField {
2486 using ContainerT = typename std::unordered_map<KeyT, ValueT>;
2487
2488protected:
2489 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2490 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2491
2492public:
2493 static std::string TypeName()
2494 {
2495 return "std::unordered_map<" + RField<KeyT>::TypeName() + "," + RField<ValueT>::TypeName() + ">";
2496 }
2497
2498 explicit RField(std::string_view name)
2499 : RMapField(name, TypeName(), std::make_unique<RField<std::pair<KeyT, ValueT>>>("_0"))
2500 {
2501 }
2502 RField(RField &&other) = default;
2503 RField &operator=(RField &&other) = default;
2504 ~RField() override = default;
2505
2506 size_t GetValueSize() const final { return sizeof(ContainerT); }
2507 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
2508};
2509
2510template <typename... ItemTs>
2511class RField<std::variant<ItemTs...>> final : public RVariantField {
2512 using ContainerT = typename std::variant<ItemTs...>;
2513private:
2514 template <typename HeadT, typename... TailTs>
2515 static std::string BuildItemTypes()
2516 {
2517 std::string result = RField<HeadT>::TypeName();
2518 if constexpr(sizeof...(TailTs) > 0)
2519 result += "," + BuildItemTypes<TailTs...>();
2520 return result;
2521 }
2522
2523 template <typename HeadT, typename... TailTs>
2524 static std::vector<RFieldBase *> BuildItemFields(unsigned int index = 0)
2525 {
2526 std::vector<RFieldBase *> result;
2527 result.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
2528 if constexpr(sizeof...(TailTs) > 0) {
2529 auto tailFields = BuildItemFields<TailTs...>(index + 1);
2530 result.insert(result.end(), tailFields.begin(), tailFields.end());
2531 }
2532 return result;
2533 }
2534
2535protected:
2536 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2537
2538public:
2539 static std::string TypeName() { return "std::variant<" + BuildItemTypes<ItemTs...>() + ">"; }
2540 explicit RField(std::string_view name) : RVariantField(name, BuildItemFields<ItemTs...>()) {}
2541 RField(RField&& other) = default;
2542 RField& operator =(RField&& other) = default;
2543 ~RField() override = default;
2544};
2545
2546template <typename ItemT>
2547class RField<std::vector<ItemT>> final : public RVectorField {
2548 using ContainerT = typename std::vector<ItemT>;
2549
2550protected:
2551 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2552
2553public:
2554 static std::string TypeName() { return "std::vector<" + RField<ItemT>::TypeName() + ">"; }
2555 explicit RField(std::string_view name)
2556 : RVectorField(name, std::make_unique<RField<ItemT>>("_0"))
2557 {}
2558 RField(RField&& other) = default;
2559 RField& operator =(RField&& other) = default;
2560 ~RField() override = default;
2561
2562 size_t GetValueSize() const final { return sizeof(ContainerT); }
2563};
2564
2565// std::vector<bool> is a template specialization and needs special treatment
2566template <>
2567class RField<std::vector<bool>> final : public RFieldBase {
2568private:
2569 ClusterSize_t fNWritten{0};
2570
2571protected:
2572 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2573 {
2574 return std::make_unique<RField>(newName);
2575 }
2576
2577 const RColumnRepresentations &GetColumnRepresentations() const final;
2578 void GenerateColumnsImpl() final;
2579 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
2580
2581 void ConstructValue(void *where) const final { new (where) std::vector<bool>(); }
2582 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<std::vector<bool>>>(); }
2583
2584 std::size_t AppendImpl(const void *from) final;
2585 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final;
2586
2587 void CommitClusterImpl() final { fNWritten = 0; }
2588
2589public:
2590 static std::string TypeName() { return "std::vector<bool>"; }
2591 explicit RField(std::string_view name);
2592 RField(RField&& other) = default;
2593 RField& operator =(RField&& other) = default;
2594 ~RField() override = default;
2595
2596 std::vector<RValue> SplitValue(const RValue &value) const final;
2597
2598 size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
2599 size_t GetAlignment() const final { return std::alignment_of<std::vector<bool>>(); }
2600 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
2601 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const {
2602 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
2603 }
2604 void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
2605 {
2606 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
2607 }
2608};
2609
2610template <typename ItemT>
2611class RField<ROOT::VecOps::RVec<ItemT>> final : public RRVecField {
2613protected:
2614 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2615 {
2616 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2617 return std::make_unique<RField<ROOT::VecOps::RVec<ItemT>>>(newName, std::move(newItemField));
2618 }
2619
2620 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2621 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2622
2623 std::size_t AppendImpl(const void *from) final
2624 {
2625 auto typedValue = static_cast<const ContainerT *>(from);
2626 auto nbytes = 0;
2627 auto count = typedValue->size();
2628 for (unsigned i = 0; i < count; ++i) {
2629 nbytes += CallAppendOn(*fSubFields[0], &typedValue->data()[i]);
2630 }
2631 this->fNWritten += count;
2632 fColumns[0]->Append(&this->fNWritten);
2633 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
2634 }
2635 void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
2636 {
2637 auto typedValue = static_cast<ContainerT *>(to);
2638 ClusterSize_t nItems;
2639 RClusterIndex collectionStart;
2640 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2641 typedValue->resize(nItems);
2642 for (unsigned i = 0; i < nItems; ++i) {
2643 CallReadOn(*fSubFields[0], collectionStart + i, &typedValue->data()[i]);
2644 }
2645 }
2646
2647public:
2648 RField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
2649 : RRVecField(fieldName, std::move(itemField))
2650 {
2651 }
2652
2653 explicit RField(std::string_view name)
2654 : RField(name, std::make_unique<RField<ItemT>>("_0"))
2655 {
2656 }
2657 RField(RField&& other) = default;
2658 RField& operator =(RField&& other) = default;
2659 ~RField() override = default;
2660
2661 static std::string TypeName() { return "ROOT::VecOps::RVec<" + RField<ItemT>::TypeName() + ">"; }
2662
2663 size_t GetValueSize() const final { return sizeof(ContainerT); }
2664 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
2665};
2666
2667template <typename T1, typename T2>
2668class RField<std::pair<T1, T2>> final : public RPairField {
2669 using ContainerT = typename std::pair<T1,T2>;
2670private:
2671 template <typename Ty1, typename Ty2>
2672 static std::array<std::unique_ptr<RFieldBase>, 2> BuildItemFields()
2673 {
2674 return {std::make_unique<RField<Ty1>>("_0"), std::make_unique<RField<Ty2>>("_1")};
2675 }
2676
2677 static std::array<std::size_t, 2> BuildItemOffsets()
2678 {
2679 auto pair = ContainerT();
2680 auto offsetFirst = reinterpret_cast<std::uintptr_t>(&(pair.first)) - reinterpret_cast<std::uintptr_t>(&pair);
2681 auto offsetSecond = reinterpret_cast<std::uintptr_t>(&(pair.second)) - reinterpret_cast<std::uintptr_t>(&pair);
2682 return {offsetFirst, offsetSecond};
2683 }
2684
2685protected:
2686 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2687 {
2688 std::array<std::unique_ptr<RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetFieldName()),
2689 fSubFields[1]->Clone(fSubFields[1]->GetFieldName())};
2690 return std::make_unique<RField<std::pair<T1, T2>>>(newName, std::move(items));
2691 }
2692
2693 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2694 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2695
2696public:
2697 static std::string TypeName() {
2698 return "std::pair<" + RField<T1>::TypeName() + "," + RField<T2>::TypeName() + ">";
2699 }
2700 explicit RField(std::string_view name, std::array<std::unique_ptr<RFieldBase>, 2> &&itemFields)
2701 : RPairField(name, std::move(itemFields), BuildItemOffsets())
2702 {
2703 fMaxAlignment = std::max(alignof(T1), alignof(T2));
2704 fSize = sizeof(ContainerT);
2705 }
2706 explicit RField(std::string_view name) : RField(name, BuildItemFields<T1, T2>()) {}
2707 RField(RField&& other) = default;
2708 RField& operator =(RField&& other) = default;
2709 ~RField() override = default;
2710};
2711
2712template <typename... ItemTs>
2713class RField<std::tuple<ItemTs...>> final : public RTupleField {
2714 using ContainerT = typename std::tuple<ItemTs...>;
2715private:
2716 template <typename HeadT, typename... TailTs>
2717 static std::string BuildItemTypes()
2718 {
2719 std::string result = RField<HeadT>::TypeName();
2720 if constexpr (sizeof...(TailTs) > 0)
2721 result += "," + BuildItemTypes<TailTs...>();
2722 return result;
2723 }
2724
2725 template <typename HeadT, typename... TailTs>
2726 static void _BuildItemFields(std::vector<std::unique_ptr<RFieldBase>> &itemFields, unsigned int index = 0)
2727 {
2728 itemFields.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
2729 if constexpr (sizeof...(TailTs) > 0)
2730 _BuildItemFields<TailTs...>(itemFields, index + 1);
2731 }
2732 template <typename... Ts>
2733 static std::vector<std::unique_ptr<RFieldBase>> BuildItemFields()
2734 {
2735 std::vector<std::unique_ptr<RFieldBase>> result;
2736 _BuildItemFields<Ts...>(result);
2737 return result;
2738 }
2739
2740 template <unsigned Index, typename HeadT, typename... TailTs>
2741 static void _BuildItemOffsets(std::vector<std::size_t> &offsets, const ContainerT &tuple)
2742 {
2743 auto offset =
2744 reinterpret_cast<std::uintptr_t>(&std::get<Index>(tuple)) - reinterpret_cast<std::uintptr_t>(&tuple);
2745 offsets.emplace_back(offset);
2746 if constexpr (sizeof...(TailTs) > 0)
2747 _BuildItemOffsets<Index + 1, TailTs...>(offsets, tuple);
2748 }
2749 template <typename... Ts>
2750 static std::vector<std::size_t> BuildItemOffsets()
2751 {
2752 std::vector<std::size_t> result;
2753 _BuildItemOffsets<0, Ts...>(result, ContainerT());
2754 return result;
2755 }
2756
2757protected:
2758 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
2759 {
2760 std::vector<std::unique_ptr<RFieldBase>> items;
2761 for (auto &item : fSubFields)
2762 items.push_back(item->Clone(item->GetFieldName()));
2763 return std::make_unique<RField<std::tuple<ItemTs...>>>(newName, std::move(items));
2764 }
2765
2766 void ConstructValue(void *where) const final { new (where) ContainerT(); }
2767 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<ContainerT>>(); }
2768
2769public:
2770 static std::string TypeName() { return "std::tuple<" + BuildItemTypes<ItemTs...>() + ">"; }
2771 explicit RField(std::string_view name, std::vector<std::unique_ptr<RFieldBase>> &&itemFields)
2772 : RTupleField(name, std::move(itemFields), BuildItemOffsets<ItemTs...>())
2773 {
2774 fMaxAlignment = std::max({alignof(ItemTs)...});
2775 fSize = sizeof(ContainerT);
2776 }
2777 explicit RField(std::string_view name) : RField(name, BuildItemFields<ItemTs...>()) {}
2778 RField(RField &&other) = default;
2779 RField &operator=(RField &&other) = default;
2780 ~RField() override = default;
2781};
2782
2783template <std::size_t N>
2784class RField<std::bitset<N>> final : public RBitsetField {
2785public:
2786 static std::string TypeName() { return "std::bitset<" + std::to_string(N) + ">"; }
2787 explicit RField(std::string_view name) : RBitsetField(name, N) {}
2788 RField(RField &&other) = default;
2789 RField &operator=(RField &&other) = default;
2790 ~RField() override = default;
2791};
2792
2793template <typename ItemT>
2794class RField<std::unique_ptr<ItemT>> final : public RUniquePtrField {
2795public:
2796 static std::string TypeName() { return "std::unique_ptr<" + RField<ItemT>::TypeName() + ">"; }
2797 explicit RField(std::string_view name) : RUniquePtrField(name, TypeName(), std::make_unique<RField<ItemT>>("_0")) {}
2798 RField(RField &&other) = default;
2799 RField &operator=(RField &&other) = default;
2800 ~RField() override = default;
2801};
2802
2803template <typename ItemT>
2804class RField<std::atomic<ItemT>> final : public RAtomicField {
2805public:
2806 static std::string TypeName() { return "std::atomic<" + RField<ItemT>::TypeName() + ">"; }
2807 explicit RField(std::string_view name) : RAtomicField(name, TypeName(), std::make_unique<RField<ItemT>>("_0")) {}
2808 RField(RField &&other) = default;
2809 RField &operator=(RField &&other) = default;
2810 ~RField() override = default;
2811};
2812
2813// Has to be implemented after the definition of all RField<T> types
2814// The void type is specialized in RField.cxx
2815
2816template <typename T>
2817std::unique_ptr<T, typename RFieldBase::RCreateObjectDeleter<T>::deleter> RFieldBase::CreateObject() const
2818{
2819 if (GetTypeName() != RField<T>::TypeName()) {
2820 throw RException(
2821 R__FAIL("type mismatch for field " + GetFieldName() + ": " + GetTypeName() + " vs. " + RField<T>::TypeName()));
2822 }
2823 return std::unique_ptr<T>(static_cast<T *>(CreateObjectRawPtr()));
2824}
2825
2826template <>
2829 void operator()(void *);
2830};
2831
2832template <>
2833std::unique_ptr<void, typename RFieldBase::RCreateObjectDeleter<void>::deleter>
2834ROOT::Experimental::RFieldBase::CreateObject<void>() const;
2835
2836} // namespace Experimental
2837} // namespace ROOT
2838
2839#endif
size_t fValueSize
Cppyy::TCppType_t fClass
dim_t fSize
#define R__unlikely(expr)
Definition RConfig.hxx:603
#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:290
ROOT::Experimental::RField< T > RField
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Definition TError.h:118
#define N
winID h TVirtualViewer3D TVirtualGLPainter p
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 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 Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
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 r
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 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 child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
TRObject operator()(const T1 &t1) const
Binding & operator=(OUT(*fun)(void))
Abstract base class for classes implementing the visitor design pattern.
std::size_t GetPackedSize(std::size_t nElements=1U) const
NTupleSize_t GetGlobalIndex(RClusterIndex clusterIndex)
Definition RColumn.hxx:265
RColumnElementBase * GetElement() const
Definition RColumn.hxx:325
void Append(const void *from)
Definition RColumn.hxx:122
void ReadV(const NTupleSize_t globalIndex, const ClusterSize_t::ValueType count, void *to)
Definition RColumn.hxx:189
void Read(const NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:167
NTupleSize_t GetNElements() const
Definition RColumn.hxx:324
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
A field for fixed-size arrays that are represented as RVecs in memory.
Definition RField.hxx:1200
std::size_t fArrayLength
The size of a child field's item.
Definition RField.hxx:1204
std::size_t fValueSize
The length of the arrays in this field.
Definition RField.hxx:1205
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:1211
std::size_t fItemSize
Sub field deleter or nullptr for simple fields.
Definition RField.hxx:1203
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1202
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:1210
RArrayDeleter(std::size_t itemSize, std::size_t arrayLength, std::unique_ptr< RDeleter > itemDeleter)
Definition RField.hxx:1157
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1154
The generic field for fixed size arrays, which do not need an offset column.
Definition RField.hxx:1148
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:1171
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:1170
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1188
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1189
~RAtomicField() override=default
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
Definition RField.hxx:1451
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.hxx:1447
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.hxx:1446
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
Definition RField.hxx:1450
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:1443
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:1444
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.hxx:1449
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1462
RAtomicField & operator=(RAtomicField &&other)=default
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1461
RAtomicField(RAtomicField &&other)=default
The generic field an std::bitset<N>.
Definition RField.hxx:1243
std::size_t GetN() const
Get the number of bits in the bitset, i.e. the N in std::bitset<N>
Definition RField.hxx:1274
RBitsetField(RBitsetField &&other)=default
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1270
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1252
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1269
~RBitsetField() override=default
RBitsetField & operator=(RBitsetField &&other)=default
An artificial field that transforms an RNTuple column that contains the offset of collections into co...
Definition RField.hxx:1678
RCardinalityField & operator=(RCardinalityField &&other)=default
RCardinalityField(RCardinalityField &&other)=default
RCardinalityField(std::string_view fieldName, std::string_view typeName)
Definition RField.hxx:1680
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1654
The field for a class with dictionary.
Definition RField.hxx:723
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
Definition RField.cxx:1616
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
Definition RField.hxx:734
void Attach(std::unique_ptr< RFieldBase > child, RSubFieldInfo info)
Definition RField.cxx:1565
void OnConnectPageSource() final
Called by ConnectPageSource() only once connected; derived classes may override this as appropriate.
Definition RField.cxx:1623
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1673
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Definition RField.cxx:1649
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1600
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1609
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1593
void AddReadCallbacksFromIORules(const std::span< const TSchemaRule * > rules, TClass *classp=nullptr)
Register post-read callbacks corresponding to a list of ROOT I/O customization rules.
Definition RField.cxx:1572
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition RField.cxx:1683
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:778
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
Definition RField.cxx:1678
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:760
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:759
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1661
std::vector< RSubFieldInfo > fSubFieldsInfo
Additional information kept for each entry in fSubFields
Definition RField.hxx:747
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.hxx:763
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
The collection field is only used for writing; when reading, untyped collections are projected to an ...
Definition RField.hxx:1582
std::shared_ptr< RNTupleCollectionWriter > fCollectionWriter
Save the link to the collection ntuple in order to reset the offset counter when committing the clust...
Definition RField.hxx:1585
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1608
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1607
RCollectionField(RCollectionField &&other)=default
The field for an unscoped or scoped enum with dictionary.
Definition RField.hxx:784
~REnumField() override=default
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:807
REnumField & operator=(REnumField &&other)=default
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:792
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
Definition RField.hxx:798
REnumField(REnumField &&other)=default
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:808
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:791
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.hxx:796
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
Definition RField.hxx:797
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.hxx:794
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
Similar to RValue but manages an array of consecutive values.
Definition RField.hxx:229
bool fIsAdopted
True if the user provides the memory buffer for fValues.
Definition RField.hxx:239
void * ReadBulk(RClusterIndex firstIndex, const bool *maskReq, std::size_t size)
Reads 'size' values from the associated field, starting from 'firstIndex'.
Definition RField.hxx:287
RFieldBase * fField
The field that created the array of values.
Definition RField.hxx:233
std::vector< unsigned char > fAuxData
Reading arrays of complex values may require additional memory, for instance for the elements of arra...
Definition RField.hxx:246
bool ContainsRange(RClusterIndex firstIndex, std::size_t size) const
Definition RField.hxx:254
std::size_t fCapacity
The size of the array memory block in number of values.
Definition RField.hxx:237
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
Definition RField.hxx:240
std::size_t fValueSize
Cached copy of fField->GetValueSize()
Definition RField.hxx:236
void AdoptBuffer(void *buf, std::size_t capacity)
Definition RField.cxx:464
void * GetValuePtrAt(std::size_t idx) const
Definition RField.hxx:262
RBulk & operator=(const RBulk &)=delete
void Reset(RClusterIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
Definition RField.cxx:431
std::size_t fNValidValues
The sum of non-zero elements in the fMask.
Definition RField.hxx:241
RClusterIndex fFirstIndex
Index of the first value of the array.
Definition RField.hxx:242
std::size_t fSize
The number of available values in the array (provided their mask is set)
Definition RField.hxx:238
void * fValues
Cached deleter of fField.
Definition RField.hxx:235
std::unique_ptr< RFieldBase::RDeleter > fDeleter
Definition RField.hxx:234
Some fields have multiple possible column representations, e.g.
Definition RField.hxx:165
std::vector< ColumnRepresentation_t > TypesList_t
Definition RField.hxx:167
TypesList_t fDeserializationTypes
The union of the serialization types and the deserialization extra types.
Definition RField.hxx:180
const TypesList_t & GetDeserializationTypes() const
Definition RField.hxx:174
const ColumnRepresentation_t & GetSerializationDefault() const
The first column list from fSerializationTypes is the default for writing.
Definition RField.hxx:172
A functor to release the memory acquired by CreateValue (memory and constructor).
Definition RField.hxx:106
virtual void operator()(void *objPtr, bool dtorOnly)
Definition RField.hxx:109
Iterates over the sub tree of fields in depth-first search order.
Definition RField.hxx:541
RSchemaIteratorTemplate(pointer val, int idxInParent)
Definition RField.hxx:561
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > pointer
Definition RField.hxx:557
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
Definition RField.hxx:551
void Advance()
Given that the iterator points to a valid field which is not the end iterator, go to the next field i...
Definition RField.hxx:565
std::conditional_t< IsConstT, const RFieldBase, RFieldBase > value_type
Definition RField.hxx:556
std::conditional_t< IsConstT, const RFieldBase &, RFieldBase & > reference
Definition RField.hxx:558
A deleter for templated RFieldBase descendents where the value type is known.
Definition RField.hxx:118
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.hxx:120
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
Definition RField.hxx:185
RValue & operator=(RValue &&other)=default
void Read(NTupleSize_t globalIndex)
Definition RField.hxx:202
RFieldBase * fField
The field that created the RValue.
Definition RField.hxx:189
RValue & operator=(const RValue &)=default
const RFieldBase & GetField() const
Definition RField.hxx:221
void EmplaceNew()
Replace the current object pointer by a pointer to a new object constructed by the field.
Definition RField.hxx:207
std::shared_ptr< void > fObjPtr
Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
Definition RField.hxx:190
std::shared_ptr< T > GetPtr() const
Definition RField.hxx:210
void Read(RClusterIndex clusterIndex)
Definition RField.hxx:203
void Bind(std::shared_ptr< void > objPtr)
Definition RField.hxx:204
RValue(RFieldBase *field, std::shared_ptr< void > objPtr)
Definition RField.hxx:192
A field translates read and write calls from/to underlying columns to/from tree values.
Definition RField.hxx:93
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type for writing.
static constexpr std::uint32_t kInvalidTypeVersion
Definition RField.hxx:136
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
Definition RField.hxx:141
const RFieldBase * GetParent() const
Definition RField.hxx:661
std::string GetFieldName() const
Definition RField.hxx:653
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition RField.cxx:790
bool HasDefaultColumnRepresentative() const
Whether or not an explicit column representative was set.
Definition RField.hxx:680
std::uint32_t fOnDiskTypeVersion
C++ type version cached from the descriptor after a call to ConnectPageSource()
Definition RField.hxx:406
void AutoAdjustColumnTypes(const RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
Definition RField.cxx:912
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId.
Definition RField.cxx:875
ENTupleStructure fStructure
The role of this field in the data model structure.
Definition RField.hxx:325
std::vector< RFieldBase * > GetSubFields()
Definition RField.cxx:813
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
Definition RField.hxx:144
std::function< void(void *)> ReadCallback_t
Definition RField.hxx:99
EState fState
Changed by ConnectTo[Sink,Source], reset by Clone()
Definition RField.hxx:337
static constexpr int kTraitTriviallyConstructible
No constructor needs to be called, i.e.
Definition RField.hxx:139
RSchemaIterator begin()
Definition RField.hxx:689
std::string fTypeAlias
A typedef or using name that was used when creating the field.
Definition RField.hxx:402
std::vector< std::unique_ptr< Internal::RColumn > > fColumns
The columns are connected either to a sink or to a source (not to both); they are owned by the field.
Definition RField.hxx:398
RConstSchemaIterator cbegin() const
Definition RField.hxx:694
RSchemaIteratorTemplate< false > RSchemaIterator
Definition RField.hxx:594
ENTupleStructure GetStructure() const
Definition RField.hxx:658
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:640
RFieldBase(RFieldBase &&)=default
std::string GetTypeName() const
Definition RField.hxx:656
virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const
Definition RField.cxx:1011
std::string fDescription
Free text set by the user.
Definition RField.hxx:335
static Internal::RColumn * GetPrincipalColumnOf(const RFieldBase &other)
Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBu...
Definition RField.hxx:513
friend struct ROOT::Experimental::Internal::RFieldCallbackInjector
Definition RField.hxx:95
std::size_t fNRepetitions
For fixed sized arrays, the array length.
Definition RField.hxx:327
RFieldBase & operator=(const RFieldBase &)=delete
RFieldBase * fParent
Sub fields point to their mother field.
Definition RField.hxx:392
std::unique_ptr< T, typename RCreateObjectDeleter< T >::deleter > CreateObject() const
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.hxx:2817
static std::size_t CallAppendOn(RFieldBase &other, const void *from)
Allow derived classes to call Append and Read on other (sub) fields.
Definition RField.hxx:508
int fTraits
Properties of the type that allow for optimizations of collections of that type.
Definition RField.hxx:400
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
Definition RField.hxx:436
void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
Definition RField.cxx:947
DescriptorId_t fOnDiskId
When the columns are connected to a page source or page sink, the field represents a field id in the ...
Definition RField.hxx:333
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
Definition RField.cxx:739
virtual void GenerateColumnsImpl(const RNTupleDescriptor &desc)=0
Creates the backing columns corresponsing to the field type for reading.
RConstSchemaIterator cend() const
Definition RField.hxx:698
const ColumnRepresentation_t * fColumnRepresentative
Points into the static vector GetColumnRepresentations().GetSerializationTypes() when SetColumnRepres...
Definition RField.hxx:409
void Read(NTupleSize_t globalIndex, void *to)
Populate a single value with data from the field.
Definition RField.hxx:461
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
Definition RField.hxx:329
std::uint32_t GetOnDiskTypeVersion() const
Return the C++ type version stored in the field descriptor; only valid after a call to ConnectPageSou...
Definition RField.hxx:687
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots ("grandparent.parent....
Definition RField.cxx:508
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition RField.hxx:685
std::vector< EColumnType > ColumnRepresentation_t
Definition RField.hxx:148
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
Definition RField.cxx:750
virtual std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const =0
Called by Clone(), which additionally copies the on-disk ID.
std::size_t Append(const void *from)
Write the given value into columns.
Definition RField.hxx:449
RFieldBase(const RFieldBase &)=delete
void RemoveReadCallback(size_t idx)
Definition RField.cxx:906
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
Definition RField.cxx:770
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl.
Definition RField.cxx:833
void ConnectPageSource(Internal::RPageSource &pageSource)
Connects the field and its sub field tree to the given page source.
Definition RField.cxx:967
RValue CreateValue()
Generates an object of the field type and wraps the created object in a shared pointer and returns it...
Definition RField.cxx:778
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns.
Definition RField.cxx:728
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
Definition RField.hxx:495
virtual std::unique_ptr< RDeleter > GetDeleter() const
Definition RField.hxx:433
virtual void ReadInClusterImpl(RClusterIndex clusterIndex, void *to)
Definition RField.hxx:442
static void CallReadOn(RFieldBase &other, RClusterIndex clusterIndex, void *to)
Definition RField.hxx:509
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition RField.hxx:683
virtual void ConstructValue(void *where) const =0
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
RSchemaIteratorTemplate< true > RConstSchemaIterator
Definition RField.hxx:595
std::string GetDescription() const
Get the field's description.
Definition RField.hxx:666
size_t AddReadCallback(ReadCallback_t func)
Set a user-defined function to be called after reading a value, giving a chance to inspect and/or mod...
Definition RField.cxx:899
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given a value for this field.
Definition RField.cxx:785
void SetOnDiskId(DescriptorId_t id)
Definition RField.cxx:848
std::size_t GetNRepetitions() const
Definition RField.hxx:659
virtual ~RFieldBase()=default
std::string fName
The field name relative to its parent field.
Definition RField.hxx:321
virtual size_t GetAlignment() const =0
As a rule of thumb, the alignment is equal to the size of the type.
RBulk CreateBulk()
The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values.
Definition RField.hxx:638
void InvokeReadCallbacks(void *target)
Definition RField.hxx:339
virtual void OnConnectPageSource()
Called by ConnectPageSource() only once connected; derived classes may override this as appropriate.
Definition RField.hxx:529
static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to)
Definition RField.hxx:510
void Read(RClusterIndex clusterIndex, void *to)
Definition RField.hxx:474
void SetColumnRepresentative(const ColumnRepresentation_t &representative)
Fixes a column representative.
Definition RField.cxx:863
static void CallConstructValueOn(const RFieldBase &other, void *where)
Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
Definition RField.hxx:435
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition RField.hxx:390
std::string fType
The C++ type captured by this field.
Definition RField.hxx:323
Internal::RColumn * fPrincipalColumn
Points into fColumns.
Definition RField.hxx:396
DescriptorId_t GetOnDiskId() const
Definition RField.hxx:670
virtual size_t GetValueSize() const =0
The number of bytes taken by a value of the appropriate type.
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
Definition RField.hxx:146
const ColumnRepresentation_t & GetColumnRepresentative() const
Returns the fColumnRepresentative pointee or, if unset, the field's default representative.
Definition RField.cxx:856
std::string GetTypeAlias() const
Definition RField.hxx:657
EState
During its lifetime, a field undergoes the following possible state transitions:
Definition RField.hxx:157
std::vector< ReadCallback_t > fReadCallbacks
List of functions to be called after reading a value.
Definition RField.hxx:404
void SetDescription(std::string_view description)
Definition RField.cxx:841
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition RField.cxx:711
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
Definition RField.cxx:801
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
Definition RField.cxx:745
NTupleSize_t GetNElements() const
Definition RField.hxx:660
virtual void CommitClusterImpl()
Definition RField.hxx:522
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias)
Factory method to resurrect a field from the stored on-disk type information.
Definition RField.cxx:528
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:722
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:705
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1028
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:717
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:716
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1019
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:708
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:709
void ConstructValue(void *) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Definition RField.hxx:710
ClusterSize_t * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1742
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1718
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1750
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
ClusterSize_t * Map(NTupleSize_t globalIndex)
Definition RField.hxx:1738
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition RField.hxx:1754
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1751
ClusterSize_t * Map(RClusterIndex clusterIndex)
Definition RField.hxx:1741
void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Definition RField.hxx:1757
ClusterSize_t * MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1745
RField & operator=(RField &&other)=default
RField(RField &&other)=default
RField(std::string_view name)
Definition RField.hxx:2412
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
General implementation of bulk read.
Definition RField.hxx:1801
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.hxx:1771
std::unique_ptr< ROOT::Experimental::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1767
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
Get the number of elements of the collection identified by clusterIndex.
Definition RField.hxx:1793
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
Get the number of elements of the collection identified by globalIndex.
Definition RField.hxx:1784
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1780
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1781
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:2663
typename ROOT::VecOps::RVec< ItemT > ContainerT
Definition RField.hxx:2612
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.hxx:2623
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
Definition RField.hxx:2635
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:2614
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.hxx:2621
RField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.hxx:2648
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:2664
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.hxx:2620
bool * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1855
RField(std::string_view name)
Definition RField.hxx:1843
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1863
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1831
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1864
bool * MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1858
bool * Map(RClusterIndex clusterIndex)
Definition RField.hxx:1854
static std::string TypeName()
Definition RField.hxx:1842
RField(RField &&other)=default
bool * Map(NTupleSize_t globalIndex)
Definition RField.hxx:1851
char * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:2019
RField(std::string_view name)
Definition RField.hxx:2007
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:2028
char * Map(RClusterIndex clusterIndex)
Definition RField.hxx:2018
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:2027
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1995
char * Map(NTupleSize_t globalIndex)
Definition RField.hxx:2015
RField(RField &&other)=default
char * MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:2022
static std::string TypeName()
Definition RField.hxx:2006
double * Map(RClusterIndex clusterIndex)
Definition RField.hxx:1936
double * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1937
RField(std::string_view name)
Definition RField.hxx:1925
double * MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1940
double * Map(NTupleSize_t globalIndex)
Definition RField.hxx:1933
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1946
RField(RField &&other)=default
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1945
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1913
static std::string TypeName()
Definition RField.hxx:1882
RField(RField &&other)=default
float * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1895
RField(std::string_view name)
Definition RField.hxx:1883
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1903
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1904
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.hxx:1871
float * MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1898
float * Map(NTupleSize_t globalIndex)
Definition RField.hxx:1891
float * Map(RClusterIndex clusterIndex)
Definition RField.hxx:1894
RField(const RField &)=delete
static std::string TypeName()
Definition RField.hxx:1708
RField & operator=(const RField &)=delete
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:1469
RField(std::string_view name)
Definition RField.hxx:1483
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.hxx:1471
RField & operator=(RField &&other)=default
RField(RField &&other)=default
static std::string TypeName()
Definition RField.hxx:1482
~RField() override=default
The generic field for a std::map<KeyType, ValueType> and std::unordered_map<KeyType,...
Definition RField.hxx:1345
size_t GetAlignment() const override
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1363
RMapField(RMapField &&other)=default
~RMapField() override=default
RMapField & operator=(RMapField &&other)=default
The on-storage meta-data of an ntuple.
Common user-tunable settings for storing ntuples.
The field for values that may or may not be present in an entry.
Definition RField.hxx:1374
RNullableField & operator=(RNullableField &&other)=default
~RNullableField() override=default
RNullableField(RNullableField &&other)=default
std::unique_ptr< RValue > fDefaultItemValue
For a dense nullable field, used to write a default-constructed item for missing ones.
Definition RField.hxx:1376
The generic field for std::pair<T1, T2> types.
Definition RField.hxx:1612
~RPairField() override=default
static std::string GetTypeList(const std::array< std::unique_ptr< RFieldBase >, 2 > &itemFields)
RPairField(RPairField &&other)=default
std::unique_ptr< RDeleter > GetDeleter() const override
Definition RField.hxx:1630
RPairField & operator=(RPairField &&other)=default
RIterator(const RCollectionIterableOnce &owner, void *iter)
Definition RField.hxx:859
Allows for iterating over the elements of a proxied collection.
Definition RField.hxx:825
RCollectionIterableOnce(void *collection, const RIteratorFuncs &ifuncs, TVirtualCollectionProxy *proxy, std::size_t stride=0U)
Construct a RCollectionIterableOnce that iterates over collection.
Definition RField.hxx:880
RProxiedCollectionDeleter(std::shared_ptr< TVirtualCollectionProxy > proxy, std::unique_ptr< RDeleter > itemDeleter, size_t itemSize)
Definition RField.hxx:901
RProxiedCollectionDeleter(std::shared_ptr< TVirtualCollectionProxy > proxy)
Definition RField.hxx:900
The field for a class representing a collection of elements via TVirtualCollectionProxy.
Definition RField.hxx:821
void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:956
std::shared_ptr< TVirtualCollectionProxy > fProxy
The collection proxy is needed by the deleters and thus defined as a shared pointer.
Definition RField.hxx:911
RCollectionIterableOnce::RIteratorFuncs fIFuncsRead
Two sets of functions to operate on iterators, to be used depending on the access type.
Definition RField.hxx:916
RProxiedCollectionField(RProxiedCollectionField &&other)=default
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:952
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
Definition RField.hxx:917
size_t GetAlignment() const override
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:950
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:949
RProxiedCollectionField & operator=(RProxiedCollectionField &&other)=default
the RRVecDeleter is also used by RArrayAsRVecField and therefore declared public
Definition RField.hxx:1089
RRVecDeleter(std::size_t itemAlignment)
Definition RField.hxx:1096
RRVecDeleter(std::size_t itemAlignment, std::size_t itemSize, std::unique_ptr< RDeleter > itemDeleter)
Definition RField.hxx:1097
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1093
The type-erased field for a RVec<Type>
Definition RField.hxx:1086
void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:1141
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1104
RRVecField(RRVecField &&)=default
~RRVecField() override=default
RRVecField(const RRVecField &)=delete
RRVecField & operator=(RRVecField &&)=default
RRVecField & operator=(RRVecField &)=delete
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:1137
std::vector< std::unique_ptr< RDeleter > > fItemDeleters
Definition RField.hxx:968
RRecordDeleter(std::vector< std::unique_ptr< RDeleter > > &itemDeleters, const std::vector< std::size_t > &offsets)
Definition RField.hxx:972
The field for an untyped record.
Definition RField.hxx:964
RRecordField(std::string_view fieldName, std::array< std::unique_ptr< RFieldBase >, N > &&itemFields, const std::array< std::size_t, N > &offsets, std::string_view typeName="")
Definition RField.hxx:1002
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1025
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1026
std::vector< std::size_t > fOffsets
Definition RField.hxx:982
RRecordField(RRecordField &&other)=default
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:989
~RRecordField() override=default
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:988
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition RError.hxx:194
The generic field for a std::set<Type> and std::unordered_set<Type>
Definition RField.hxx:1331
RSetField(RSetField &&other)=default
RSetField & operator=(RSetField &&other)=default
size_t GetAlignment() const override
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1341
~RSetField() override=default
The generic field for std::tuple<Ts...> types.
Definition RField.hxx:1643
std::unique_ptr< RDeleter > GetDeleter() const override
Definition RField.hxx:1661
RTupleField & operator=(RTupleField &&other)=default
static std::string GetTypeList(const std::vector< std::unique_ptr< RFieldBase > > &itemFields)
~RTupleField() override=default
RTupleField(RTupleField &&other)=default
RUniquePtrDeleter(std::unique_ptr< RDeleter > itemDeleter)
Definition RField.hxx:1414
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.hxx:1423
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1418
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1437
std::vector< std::unique_ptr< RDeleter > > fItemDeleters
Definition RField.hxx:1283
RVariantDeleter(std::size_t tagOffset, std::vector< std::unique_ptr< RDeleter > > &itemDeleters)
Definition RField.hxx:1286
The generic field for std::variant types.
Definition RField.hxx:1278
std::vector< ClusterSize_t::ValueType > fNWritten
Definition RField.hxx:1297
RVectorDeleter(std::size_t itemSize, std::unique_ptr< RDeleter > itemDeleter)
Definition RField.hxx:1040
The generic field for a (nested) std::vector<Type> except for std::vector<bool>
Definition RField.hxx:1031
~RVectorField() override=default
std::unique_ptr< RDeleter > fItemDeleter
Definition RField.hxx:1049
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1073
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:1076
void GetCollectionInfo(RClusterIndex clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:1079
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.hxx:1074
RVectorField(RVectorField &&other)=default
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1492
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
The TEnum class implements the enum type.
Definition TEnum.h:33
Defines a common interface to inspect/change the contents of an object that represents a collection.
void(* CreateIterators_t)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy)
*begin_arena and *end_arena should contain the location of a memory arena of size fgIteratorArenaSize...
void *(* Next_t)(void *iter, const void *end)
iter and end should be pointers to an iterator to be incremented and an iterator that points to the e...
void(* DeleteTwoIterators_t)(void *begin, void *end)
static const Int_t fgIteratorArenaSize
The size of a small buffer that can be allocated on the stack to store iterator-specific information.
RooCmdArg Index(RooCategory &icat)
auto Map(Args &&... args)
Create new collection applying a callable to the elements of the input collection.
Definition RVec.hxx:2113
#define T2
Definition md5.inl:147
#define T1
Definition md5.inl:146
void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry=0)
Definition RField.cxx:342
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
Definition RField.cxx:347
void CallCommitClusterOnField(RFieldBase &)
Definition RField.cxx:338
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RClusterSize ClusterSize_t
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
std::string GetDemangledTypeName(const std::type_info &t)
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
The point here is that we can only tell at run time if a class has an associated collection proxy.
Definition RField.hxx:1548
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.
Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information.
Definition RField.hxx:372
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
Definition RField.hxx:383
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
Definition RField.hxx:380
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
Definition RField.hxx:381
std::size_t fCount
Size of the bulk range.
Definition RField.hxx:378
RClusterIndex fFirstIndex
Start of the bulk range.
Definition RField.hxx:377
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
Definition RField.hxx:386
static const std::size_t kAllSet
As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read indepen...
Definition RField.hxx:375
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > FieldPtr_t
Definition RField.hxx:544
RSharedPtrDeleter(std::unique_ptr< RFieldBase::RDeleter > deleter)
Definition RField.hxx:132
std::unique_ptr< RFieldBase::RDeleter > fDeleter
Definition RField.hxx:130
Helper types to present an offset column as array of collection sizes.
unsigned char byte
Definition gifdecode.c:10