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