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