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