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/RFieldValue.hxx>
23#include <ROOT/RNTupleUtil.hxx>
24#include <ROOT/RSpan.hxx>
25#include <ROOT/RStringView.hxx>
26#include <ROOT/RVec.hxx>
27#include <ROOT/TypeTraits.hxx>
28
29#include <TGenericClassInfo.h>
31
32#include <algorithm>
33#include <array>
34#include <cstddef>
35#include <functional>
36#include <iostream>
37#include <iterator>
38#include <memory>
39#include <string>
40#include <type_traits>
41#include <typeinfo>
42#include <variant>
43#include <vector>
44#include <utility>
45
46class TClass;
47
48namespace ROOT {
49namespace Experimental {
50
51class RCollectionField;
52class RCollectionNTupleWriter;
53class REntry;
54class RNTupleModel;
55
56namespace Internal {
57struct RFieldCallbackInjector;
58} // namespace Internal
59
60namespace Detail {
61
62class RFieldVisitor;
63class RPageStorage;
64
65// clang-format off
66/**
67\class ROOT::Experimental::RFieldBase
68\ingroup NTuple
69\brief A field translates read and write calls from/to underlying columns to/from tree values
70
71A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
72type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
73mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
74The field knows based on its type and the field name the type(s) and name(s) of the columns.
75*/
76// clang-format on
78 friend class ROOT::Experimental::RCollectionField; // to move the fields from the collection model
79 friend struct ROOT::Experimental::Internal::RFieldCallbackInjector; // used for unit tests
80 using ReadCallback_t = std::function<void(RFieldValue &)>;
81
82public:
83 /// No constructor needs to be called, i.e. any bit pattern in the allocated memory represents a valid type
84 /// A trivially constructible field has a no-op GenerateValue() implementation
85 static constexpr int kTraitTriviallyConstructible = 0x01;
86 /// The type is cleaned up just by freeing its memory. I.e. DestroyValue() is a no-op.
87 static constexpr int kTraitTriviallyDestructible = 0x02;
88 /// A field of a fundamental type that can be directly mapped via `RField<T>::Map()`, i.e. maps as-is to a single
89 /// column
90 static constexpr int kTraitMappable = 0x04;
91 /// Shorthand for types that are both trivially constructible and destructible
93
94private:
95 /// The field name relative to its parent field
96 std::string fName;
97 /// The C++ type captured by this field
98 std::string fType;
99 /// The role of this field in the data model structure
101 /// For fixed sized arrays, the array length
102 std::size_t fNRepetitions;
103 /// A field qualifies as simple if it is both mappable and has no post-read callback
105 /// When the columns are connected to a page source or page sink, the field represents a field id in the
106 /// corresponding RNTuple descriptor. This on-disk ID is set in RPageSink::Create() for writing and by
107 /// RFieldDescriptor::CreateField() when recreating a field / model from the stored descriptor.
109 /// Free text set by the user
110 std::string fDescription;
111
112protected:
113 /// Collections and classes own sub fields
114 std::vector<std::unique_ptr<RFieldBase>> fSubFields;
115 /// Sub fields point to their mother field
117 /// Points into fColumns. All fields that have columns have a distinct main column. For simple fields
118 /// (float, int, ...), the principal column corresponds to the field type. For collection fields expect std::array,
119 /// the main column is the offset field. Class fields have no column of their own.
121 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
122 std::vector<std::unique_ptr<RColumn>> fColumns;
123 /// Properties of the type that allow for optimizations of collections of that type
124 int fTraits = 0;
125 /// List of functions to be called after reading a value
126 std::vector<ReadCallback_t> fReadCallbacks;
127
128 /// Creates the backing columns corresponsing to the field type for writing
129 virtual void GenerateColumnsImpl() = 0;
130 /// Creates the backing columns corresponsing to the field type for reading.
131 /// The method should to check, using the page source and fOnDiskId, if the column types match
132 /// and throw if they don't.
133 virtual void GenerateColumnsImpl(const RNTupleDescriptor &desc) = 0;
134
135 /// Called by Clone(), which additionally copies the on-disk ID
136 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
137
138 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
139 /// column type exists.
140 virtual std::size_t AppendImpl(const RFieldValue &value);
141 virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value);
142 virtual void ReadInClusterImpl(const RClusterIndex &clusterIndex, RFieldValue *value) {
144 }
145
146 /// Throws an exception if the column given by fOnDiskId and the columnIndex in the provided descriptor
147 /// is not of one of the requested types.
148 ROOT::Experimental::EColumnType EnsureColumnType(const std::vector<EColumnType> &requestedTypes,
149 unsigned int columnIndex, const RNTupleDescriptor &desc);
150
151 /// Set a user-defined function to be called after reading a value, giving a chance to inspect and/or modify the
152 /// value object.
153 /// Returns an index that can be used to remove the callback.
154 size_t AddReadCallback(ReadCallback_t func);
155 void RemoveReadCallback(size_t idx);
156
157private:
159 {
160 for (const auto &func : fReadCallbacks)
161 func(value);
162 }
163
164public:
165 /// Iterates over the sub tree of fields in depth-first search order
167 private:
168 struct Position {
169 Position() : fFieldPtr(nullptr), fIdxInParent(-1) { }
170 Position(RFieldBase *fieldPtr, int idxInParent) : fFieldPtr(fieldPtr), fIdxInParent(idxInParent) { }
173 };
174 /// The stack of nodes visited when walking down the tree of fields
175 std::vector<Position> fStack;
176 public:
178 using iterator_category = std::forward_iterator_tag;
180 using difference_type = std::ptrdiff_t;
183
184 RSchemaIterator() { fStack.emplace_back(Position()); }
185 RSchemaIterator(pointer val, int idxInParent) { fStack.emplace_back(Position(val, idxInParent)); }
187 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
188 /// in depth-first search order
189 void Advance();
190
191 iterator operator++(int) /* postfix */ { auto r = *this; Advance(); return r; }
192 iterator& operator++() /* prefix */ { Advance(); return *this; }
193 reference operator* () const { return *fStack.back().fFieldPtr; }
194 pointer operator->() const { return fStack.back().fFieldPtr; }
195 bool operator==(const iterator& rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
196 bool operator!=(const iterator& rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
197 };
198
199 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
200 /// If `isSimple` is `true`, the trait `kTraitMappable` is automatically set on construction. However, the
201 /// field might be demoted to non-simple if a post-read callback is set.
202 RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple,
203 std::size_t nRepetitions = 0);
204 RFieldBase(const RFieldBase&) = delete;
205 RFieldBase(RFieldBase&&) = default;
208 virtual ~RFieldBase();
209
210 /// Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns
211 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
212
213 /// Factory method to resurrect a field from the stored on-disk type information
214 static RResult<std::unique_ptr<RFieldBase>> Create(const std::string &fieldName, const std::string &typeName);
215 /// Check whether a given string is a valid field name
216 static RResult<void> EnsureValidFieldName(std::string_view fieldName);
217
218 /// Generates an object of the field type and allocates new initialized memory according to the type.
220 /// Generates a tree value in a given location of size at least GetValueSize(). Assumes that where has been
221 /// allocated by malloc().
222 virtual RFieldValue GenerateValue(void *where) = 0;
223 /// Releases the resources acquired during GenerateValue (memory and constructor)
224 /// This implementation works for simple types but needs to be overwritten for complex ones
225 virtual void DestroyValue(const RFieldValue &value, bool dtorOnly = false);
226 /// Creates a value from a memory location with an already constructed object
227 virtual RFieldValue CaptureValue(void *where) = 0;
228 /// Creates the list of direct child values given a value for this field. E.g. a single value for the
229 /// correct variant or all the elements of a collection. The default implementation assumes no sub values
230 /// and returns an empty vector.
231 virtual std::vector<RFieldValue> SplitValue(const RFieldValue &value) const;
232 /// The number of bytes taken by a value of the appropriate type
233 virtual size_t GetValueSize() const = 0;
234 /// For many types, the alignment requirement is equal to the size; otherwise override.
235 virtual size_t GetAlignment() const { return GetValueSize(); }
236 int GetTraits() const { return fTraits; }
237 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
238
239 /// Write the given value into columns. The value object has to be of the same type as the field.
240 /// Returns the number of uncompressed bytes written.
241 std::size_t Append(const RFieldValue& value) {
242 if (~fTraits & kTraitMappable)
243 return AppendImpl(value);
244
245 fPrincipalColumn->Append(value.fMappedElement);
246 return value.fMappedElement.GetSize();
247 }
248
249 /// Populate a single value with data from the tree, which needs to be of the fitting type.
250 /// Reading copies data into the memory wrapped by the ntuple value.
251 /// The fast path is conditioned by the field qualifying as simple, i.e. maps as-is to a single column and has no
252 /// read callback.
253 void Read(NTupleSize_t globalIndex, RFieldValue *value) {
254 if (fIsSimple)
255 return (void)fPrincipalColumn->Read(globalIndex, &value->fMappedElement);
256
258 fPrincipalColumn->Read(globalIndex, &value->fMappedElement);
259 else
260 ReadGlobalImpl(globalIndex, value);
261 if (R__unlikely(!fReadCallbacks.empty()))
263 }
264
265 void Read(const RClusterIndex &clusterIndex, RFieldValue *value) {
266 if (fIsSimple)
267 return (void)fPrincipalColumn->Read(clusterIndex, &value->fMappedElement);
268
270 fPrincipalColumn->Read(clusterIndex, &value->fMappedElement);
271 else
272 ReadInClusterImpl(clusterIndex, value);
273 if (R__unlikely(!fReadCallbacks.empty()))
275 }
276
277 /// Ensure that all received items are written from page buffers to the storage.
278 void Flush() const;
279 /// Perform housekeeping tasks for global to cluster-local index translation
280 virtual void CommitCluster() {}
281
282 /// Add a new subfield to the list of nested fields
283 void Attach(std::unique_ptr<Detail::RFieldBase> child);
284
285 std::string GetName() const { return fName; }
286 std::string GetType() const { return fType; }
288 std::size_t GetNRepetitions() const { return fNRepetitions; }
290 RFieldBase *GetParent() const { return fParent; }
291 std::vector<RFieldBase *> GetSubFields() const;
292 bool IsSimple() const { return fIsSimple; }
293 /// Get the field's description
294 std::string GetDescription() const { return fDescription; }
295 void SetDescription(std::string_view description) { fDescription = std::string(description); }
296
299
300 /// Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
301 /// 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.
302 void ConnectPageSink(RPageSink &pageSink);
303 void ConnectPageSource(RPageSource &pageSource);
304
305 /// Indicates an evolution of the mapping scheme from C++ type to columns
306 virtual std::uint32_t GetFieldVersion() const { return 0; }
307 /// Indicates an evolution of the C++ type itself
308 virtual std::uint32_t GetTypeVersion() const { return 0; }
309
310 RSchemaIterator begin();
311 RSchemaIterator end();
312
313 virtual void AcceptVisitor(RFieldVisitor &visitor) const;
314};
315
316} // namespace Detail
317
318
319
320/// The container field for an ntuple model, which itself has no physical representation
322protected:
323 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const override;
324
325public:
326 RFieldZero() : Detail::RFieldBase("", "", ENTupleStructure::kRecord, false /* isSimple */) { }
327
328 void GenerateColumnsImpl() final {}
333 size_t GetValueSize() const final { return 0; }
334
335 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
336};
337
338/// The field for a class with dictionary
340private:
344 };
347 std::size_t fOffset;
348 };
349 /// Prefix used in the subfield names generated for base classes
350 static constexpr const char *kPrefixInherited{":"};
351
353 /// Additional information kept for each entry in `fSubFields`
354 std::vector<RSubFieldInfo> fSubFieldsInfo;
355 std::size_t fMaxAlignment = 1;
356
357private:
358 RClassField(std::string_view fieldName, std::string_view className, TClass *classp);
359 void Attach(std::unique_ptr<Detail::RFieldBase> child, RSubFieldInfo info);
360
361protected:
362 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
363 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
364 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
365 void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final;
366
367public:
368 RClassField(std::string_view fieldName, std::string_view className);
369 RClassField(RClassField&& other) = default;
370 RClassField& operator =(RClassField&& other) = default;
371 ~RClassField() override = default;
372
373 void GenerateColumnsImpl() final;
374 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
375 using Detail::RFieldBase::GenerateValue;
376 Detail::RFieldValue GenerateValue(void* where) override;
377 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
378 Detail::RFieldValue CaptureValue(void *where) final;
379 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
380 size_t GetValueSize() const override;
381 size_t GetAlignment() const final { return fMaxAlignment; }
382 void AcceptVisitor(Detail::RFieldVisitor &visitor) const override;
383};
384
385/// The field for a class representing a collection of elements via `TVirtualCollectionProxy`.
386/// Objects of such type behave as collections that can be accessed through the corresponding member functions in
387/// `TVirtualCollectionProxy`. At a bare minimum, the user is required to provide an implementation for the following
388/// functions in `TVirtualCollectionProxy`: `HasPointers()`, `GetProperties()`, `GetValueClass()`, `GetType()`,
389/// `Sizeof()`, `PushProxy()`, `PopProxy()`, `At()`, `Clear()`, and `Insert()`.
390///
391/// The collection proxy for a given class can be set via `TClass::CopyCollectionProxy()`.
393private:
394 /// Chunk size in bytes used in `ReadGlobalImp()`. Items held in the same chunk will be inserted in
395 /// a single `TVirtualCollectionProxy::Insert()` call.
396 static constexpr const std::size_t kReadChunkSize = 64 * 1024;
397 std::unique_ptr<TVirtualCollectionProxy> fProxy;
398 std::size_t fItemSize;
400
401 RCollectionClassField(std::string_view fieldName, std::string_view className, TClass *classp);
402
403protected:
404 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
405 std::size_t AppendImpl(const Detail::RFieldValue &value) final;
406 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
407
408public:
409 RCollectionClassField(std::string_view fieldName, std::string_view className);
412 ~RCollectionClassField() override = default;
413
414 void GenerateColumnsImpl() final;
415 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
416 using Detail::RFieldBase::GenerateValue;
417 Detail::RFieldValue GenerateValue(void *where) override;
418 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final;
419 Detail::RFieldValue CaptureValue(void *where) override;
420 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
421 size_t GetValueSize() const override { return fProxy->Sizeof(); }
422 size_t GetAlignment() const final { return alignof(std::max_align_t); }
423 void CommitCluster() final;
424 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
425 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
426 {
427 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
428 }
429 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
430 {
431 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
432 }
433};
434
435/// The field for an untyped record. The subfields are stored consequitively in a memory block, i.e.
436/// the memory layout is identical to one that a C++ struct would have
438protected:
439 std::size_t fMaxAlignment = 1;
440 std::size_t fSize = 0;
441 std::vector<std::size_t> fOffsets;
442
443 std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const;
444
445 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const override;
446 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
447 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
448 void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final;
449
450 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
451 const std::vector<std::size_t> &offsets, std::string_view typeName = "");
452
453 template <std::size_t N>
454 RRecordField(std::string_view fieldName, std::array<std::unique_ptr<Detail::RFieldBase>, N> &&itemFields,
455 const std::array<std::size_t, N> &offsets, std::string_view typeName = "")
456 : ROOT::Experimental::Detail::RFieldBase(fieldName, typeName, ENTupleStructure::kRecord, false /* isSimple */)
457 {
459 for (unsigned i = 0; i < N; ++i) {
460 fOffsets.push_back(offsets[i]);
461 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
462 fSize += GetItemPadding(fSize, itemFields[i]->GetAlignment()) + itemFields[i]->GetValueSize();
463 fTraits &= itemFields[i]->GetTraits();
464 Attach(std::move(itemFields[i]));
465 }
466 }
467public:
468 /// Construct a RRecordField based on a vector of child fields. The ownership of the child fields is transferred
469 /// to the RRecordField instance.
470 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields);
471 RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields);
472 RRecordField(RRecordField&& other) = default;
474 ~RRecordField() override = default;
475
476 void GenerateColumnsImpl() final {}
479 Detail::RFieldValue GenerateValue(void* where) override;
480 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) override;
481 Detail::RFieldValue CaptureValue(void *where) final;
482 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
483 size_t GetValueSize() const final { return fSize; }
484 size_t GetAlignment() const final { return fMaxAlignment; }
485 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
486};
487
488/// The generic field for a (nested) std::vector<Type> except for std::vector<bool>
490private:
491 std::size_t fItemSize;
493
494protected:
495 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
496 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
497 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
498
499public:
500 RVectorField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField);
501 RVectorField(RVectorField&& other) = default;
503 ~RVectorField() override = default;
504
505 void GenerateColumnsImpl() final;
506 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
507 using Detail::RFieldBase::GenerateValue;
508 Detail::RFieldValue GenerateValue(void* where) override;
509 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
510 Detail::RFieldValue CaptureValue(void *where) override;
511 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
512 size_t GetValueSize() const override { return sizeof(std::vector<char>); }
513 size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
514 void CommitCluster() final;
515 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
516 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const {
517 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
518 }
519 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const {
520 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
521 }
522};
523
524/// The type-erased field for a RVec<Type>
526private:
527 /// Evaluate the constant returned by GetValueSize.
528 // (we separate evaluation from the getter to avoid repeating the computation).
529 std::size_t EvalValueSize() const;
530
531protected:
532 std::size_t fItemSize;
534 std::size_t fValueSize;
535
536 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const override;
537 std::size_t AppendImpl(const Detail::RFieldValue &value) override;
538 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) override;
539
540public:
541 RRVecField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField);
542 RRVecField(RRVecField &&) = default;
544 RRVecField(const RRVecField &) = delete;
546 ~RRVecField() override = default;
547
548 void GenerateColumnsImpl() final;
549 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
550 using Detail::RFieldBase::GenerateValue;
551 Detail::RFieldValue GenerateValue(void *where) override;
552 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) override;
553 Detail::RFieldValue CaptureValue(void *where) override;
554 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
555 size_t GetValueSize() const override;
556 size_t GetAlignment() const override;
557 void CommitCluster() final;
558 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
559 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
560 {
561 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
562 }
563 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
564 {
565 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
566 }
567};
568
569/// The generic field for fixed size arrays, which do not need an offset column
571private:
572 std::size_t fItemSize;
573 std::size_t fArrayLength;
574
575protected:
576 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
577 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
578 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
579 void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final;
580
581public:
582 RArrayField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength);
583 RArrayField(RArrayField &&other) = default;
584 RArrayField& operator =(RArrayField &&other) = default;
585 ~RArrayField() override = default;
586
587 void GenerateColumnsImpl() final;
588 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
589 using Detail::RFieldBase::GenerateValue;
590 Detail::RFieldValue GenerateValue(void *where) override;
591 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final;
592 Detail::RFieldValue CaptureValue(void *where) final;
593 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
594 size_t GetLength() const { return fArrayLength; }
595 size_t GetValueSize() const final { return fItemSize * fArrayLength; }
596 size_t GetAlignment() const final { return fSubFields[0]->GetAlignment(); }
597 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
598};
599
600/// The generic field for std::variant types
602private:
603 size_t fMaxItemSize = 0;
604 size_t fMaxAlignment = 1;
605 /// In the std::variant memory layout, at which byte number is the index stored
606 size_t fTagOffset = 0;
607 std::vector<ClusterSize_t::ValueType> fNWritten;
608
609 static std::string GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields);
610 /// Extracts the index from an std::variant and transforms it into the 1-based index used for the switch column
611 std::uint32_t GetTag(void *variantPtr) const;
612 void SetTag(void *variantPtr, std::uint32_t tag) const;
613
614protected:
615 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
616 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
617 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
618
619public:
620 // TODO(jblomer): use std::span in signature
621 RVariantField(std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields);
622 RVariantField(RVariantField &&other) = default;
624 ~RVariantField() override = default;
625
626 void GenerateColumnsImpl() final;
627 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
628 using Detail::RFieldBase::GenerateValue;
629 Detail::RFieldValue GenerateValue(void *where) override;
630 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final;
631 Detail::RFieldValue CaptureValue(void *where) final;
632 size_t GetValueSize() const final;
633 size_t GetAlignment() const final { return fMaxAlignment; }
634 void CommitCluster() final;
635};
636
637
638/// Classes with dictionaries that can be inspected by TClass
639template <typename T, typename=void>
640class RField : public RClassField {
641public:
642 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
643 RField(std::string_view name) : RClassField(name, TypeName()) {
644 static_assert(std::is_class<T>::value, "no I/O support for this basic C++ type");
645 }
646 RField(RField &&other) = default;
647 RField &operator=(RField &&other) = default;
648 ~RField() override = default;
649
651 template <typename... ArgsT>
653 {
654 return Detail::RFieldValue(this, static_cast<T *>(where), std::forward<ArgsT>(args)...);
655 }
656 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final { return GenerateValue(where, T()); }
657};
658
659template <typename T, typename = void>
660struct HasCollectionProxyMemberType : std::false_type {
661};
662template <typename T>
664 T, typename std::enable_if<std::is_same<typename T::IsCollectionProxy, std::true_type>::value>::type>
665 : std::true_type {
666};
667
668/// The point here is that we can only tell at run time if a class has an associated collection proxy.
669/// For compile time, in the first iteration of this PR we had an extra template argument that acted as a "tag" to
670/// differentiate the RField specialization for classes with an associated collection proxy (inherits
671/// `RCollectionClassField`) from the RField primary template definition (`RClassField`-derived), as in:
672/// ```
673/// auto field = std::make_unique<RField<MyClass>>("klass");
674/// // vs
675/// auto otherField = std::make_unique<RField<MyClass, ROOT::Experimental::TagIsCollectionProxy>>("klass");
676/// ```
677///
678/// That is convenient only for non-nested types, i.e. it doesn't work with, e.g. `RField<std::vector<MyClass>,
679/// ROOT::Experimental::TagIsCollectionProxy>`, as the tag is not forwarded to the instantiation of the inner RField
680/// (that for the value type of the vector). The following two possible solutions were considered:
681/// - A wrapper type (much like `ntuple/v7/inc/ROOT/RNTupleUtil.hxx:49`), that helps to differentiate both cases.
682/// There we would have:
683/// ```
684/// auto field = std::make_unique<RField<RProxiedCollection<MyClass>>>("klass"); // Using collection proxy
685/// ```
686/// - A helper `IsCollectionProxy<T>` type, that can be used in a similar way to those in the `<type_traits>` header.
687/// We found this more convenient and is the implemented thing below. Here, classes can be marked as a
688/// collection proxy with either of the following two forms (whichever is more convenient for the user):
689/// ```
690/// template <>
691/// struct IsCollectionProxy<MyClass> : std::true_type {};
692/// ```
693/// or by adding a member type to the class as follows:
694/// ```
695/// class MyClass {
696/// public:
697/// using IsCollectionProxy = std::true_type;
698/// };
699/// ```
700///
701/// Of course, there is another possible solution which is to have a single `RClassField` that implements both
702/// the regular-class and the collection-proxy behaviors, and always chooses appropriately at run time.
703/// We found that less clean and probably has more overhead, as most probably it involves an additional branch + call
704/// in each of the member functions.
705template <typename T, typename = void>
707};
708
709/// Classes behaving as a collection of elements that can be queried via the `TVirtualCollectionProxy` interface
710/// The use of a collection proxy for a particular class can be enabled via:
711/// ```
712/// namespace ROOT::Experimental {
713/// template <> struct IsCollectionProxy<Classname> : std::true_type {};
714/// }
715/// ```
716/// Alternatively, this can be achieved by adding a member type to the class definition as follows:
717/// ```
718/// class Classname {
719/// public:
720/// using IsCollectionProxy = std::true_type;
721/// };
722/// ```
723template <typename T>
724class RField<T, typename std::enable_if<IsCollectionProxy<T>::value>::type> : public RCollectionClassField {
725public:
726 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
727 RField(std::string_view name) : RCollectionClassField(name, TypeName())
728 {
729 static_assert(std::is_class<T>::value, "collection proxy unsupported for fundamental types");
730 }
731 RField(RField&& other) = default;
732 RField& operator =(RField&& other) = default;
733 ~RField() override = default;
734
735 using Detail::RFieldBase::GenerateValue;
736 template <typename... ArgsT>
737 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
738 {
739 return Detail::RFieldValue(this, static_cast<T*>(where), std::forward<ArgsT>(args)...);
740 }
741 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, T()); }
742};
743
744/// The collection field is only used for writing; when reading, untyped collections are projected to an std::vector
746private:
747 /// Save the link to the collection ntuple in order to reset the offset counter when committing the cluster
748 std::shared_ptr<RCollectionNTupleWriter> fCollectionNTuple;
749protected:
750 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final;
751public:
752 static std::string TypeName() { return ""; }
753 RCollectionField(std::string_view name,
754 std::shared_ptr<RCollectionNTupleWriter> collectionNTuple,
755 std::unique_ptr<RNTupleModel> collectionModel);
758 ~RCollectionField() override = default;
759
760 void GenerateColumnsImpl() final;
761 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
762
763 using Detail::RFieldBase::GenerateValue;
764 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final {
765 return Detail::RFieldValue(
767 this, static_cast<ClusterSize_t*>(where));
768 }
770 return Detail::RFieldValue(true /* captureFlag */,
771 Detail::RColumnElement<ClusterSize_t>(static_cast<ClusterSize_t*>(where)), this, where);
772 }
773 size_t GetValueSize() const final { return sizeof(ClusterSize_t); }
774 void CommitCluster() final;
775};
776
777/// The generic field for `std::pair<T1, T2>` types
778class RPairField : public RRecordField {
779private:
780 TClass *fClass = nullptr;
781 static std::string GetTypeList(const std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields);
782
783protected:
784 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const override;
785
786 RPairField(std::string_view fieldName, std::array<std::unique_ptr<Detail::RFieldBase>, 2> &&itemFields,
787 const std::array<std::size_t, 2> &offsets);
788
789public:
790 RPairField(std::string_view fieldName, std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields);
791 RPairField(RPairField &&other) = default;
792 RPairField &operator=(RPairField &&other) = default;
793 ~RPairField() override = default;
794
796 Detail::RFieldValue GenerateValue(void *where) override;
797 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) override;
798};
799
800/// The generic field for `std::tuple<Ts...>` types
801class RTupleField : public RRecordField {
802private:
803 TClass *fClass = nullptr;
804 static std::string GetTypeList(const std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields);
805
806protected:
807 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const override;
808
809 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
810 const std::vector<std::size_t> &offsets);
811
812public:
813 RTupleField(std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields);
814 RTupleField(RTupleField &&other) = default;
815 RTupleField &operator=(RTupleField &&other) = default;
816 ~RTupleField() override = default;
817
818 using Detail::RFieldBase::GenerateValue;
819 Detail::RFieldValue GenerateValue(void *where) override;
820 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) override;
821};
822
823/// Template specializations for concrete C++ types
824
825
826template <>
828protected:
829 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
830 return std::make_unique<RField>(newName);
831 }
832
833public:
834 static std::string TypeName() { return "ROOT::Experimental::ClusterSize_t"; }
835 explicit RField(std::string_view name)
836 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
837 {
838 fTraits |= kTraitTrivialType;
839 }
840 RField(RField&& other) = default;
841 RField& operator =(RField&& other) = default;
842 ~RField() override = default;
843
845 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
846
847 ClusterSize_t *Map(NTupleSize_t globalIndex) {
848 return fPrincipalColumn->Map<ClusterSize_t>(globalIndex);
849 }
850 ClusterSize_t *Map(const RClusterIndex &clusterIndex) {
851 return fPrincipalColumn->Map<ClusterSize_t>(clusterIndex);
852 }
854 return fPrincipalColumn->MapV<ClusterSize_t>(globalIndex, nItems);
855 }
856 ClusterSize_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
857 return fPrincipalColumn->MapV<ClusterSize_t>(clusterIndex, nItems);
858 }
859
860 using Detail::RFieldBase::GenerateValue;
861 template <typename... ArgsT>
863 {
864 return Detail::RFieldValue(
866 this, static_cast<ClusterSize_t*>(where), std::forward<ArgsT>(args)...);
867 }
870 return Detail::RFieldValue(true /* captureFlag */,
871 Detail::RColumnElement<ClusterSize_t>(static_cast<ClusterSize_t*>(where)), this, where);
872 }
873 size_t GetValueSize() const final { return sizeof(ClusterSize_t); }
874
875 /// Special help for offset fields
876 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) {
877 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
878 }
879 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) {
880 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
881 }
882 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
883};
884
885
886template <>
888protected:
889 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
890 return std::make_unique<RField>(newName);
891 }
892
893public:
894 static std::string TypeName() { return "bool"; }
895 explicit RField(std::string_view name)
896 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
897 {
898 fTraits |= kTraitTrivialType;
899 }
900 RField(RField&& other) = default;
901 RField& operator =(RField&& other) = default;
902 ~RField() override = default;
903
904 void GenerateColumnsImpl() final;
905 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
906
907 bool *Map(NTupleSize_t globalIndex) {
908 return fPrincipalColumn->Map<bool>(globalIndex);
909 }
910 bool *Map(const RClusterIndex &clusterIndex) {
911 return fPrincipalColumn->Map<bool>(clusterIndex);
912 }
913 bool *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
914 return fPrincipalColumn->MapV<bool>(globalIndex, nItems);
915 }
916 bool *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
917 return fPrincipalColumn->MapV<bool>(clusterIndex, nItems);
918 }
919
920 using Detail::RFieldBase::GenerateValue;
921 template <typename... ArgsT>
923 {
924 return Detail::RFieldValue(
925 Detail::RColumnElement<bool>(static_cast<bool*>(where)),
926 this, static_cast<bool*>(where), std::forward<ArgsT>(args)...);
927 }
928 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, false); }
930 return Detail::RFieldValue(true /* captureFlag */,
931 Detail::RColumnElement<bool>(static_cast<bool*>(where)), this, where);
932 }
933 size_t GetValueSize() const final { return sizeof(bool); }
934 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
935};
936
937template <>
938class RField<float> : public Detail::RFieldBase {
939protected:
940 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
941 return std::make_unique<RField>(newName);
942 }
943
944public:
945 static std::string TypeName() { return "float"; }
946 explicit RField(std::string_view name)
947 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
948 {
949 fTraits |= kTraitTrivialType;
950 }
951 RField(RField&& other) = default;
952 RField& operator =(RField&& other) = default;
953 ~RField() override = default;
954
955 void GenerateColumnsImpl() final;
956 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
957
958 float *Map(NTupleSize_t globalIndex) {
959 return fPrincipalColumn->Map<float>(globalIndex);
960 }
961 float *Map(const RClusterIndex &clusterIndex) {
962 return fPrincipalColumn->Map<float>(clusterIndex);
963 }
964 float *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
965 return fPrincipalColumn->MapV<float>(globalIndex, nItems);
966 }
967 float *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
968 return fPrincipalColumn->MapV<float>(clusterIndex, nItems);
969 }
970
971 using Detail::RFieldBase::GenerateValue;
972 template <typename... ArgsT>
974 {
975 return Detail::RFieldValue(
976 Detail::RColumnElement<float>(static_cast<float*>(where)),
977 this, static_cast<float*>(where), std::forward<ArgsT>(args)...);
978 }
979 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0.0); }
981 return Detail::RFieldValue(true /* captureFlag */,
982 Detail::RColumnElement<float>(static_cast<float*>(where)), this, where);
983 }
984 size_t GetValueSize() const final { return sizeof(float); }
985 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
986};
987
988
989template <>
991protected:
992 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
993 return std::make_unique<RField>(newName);
994 }
995
996public:
997 static std::string TypeName() { return "double"; }
998 explicit RField(std::string_view name)
999 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1000 {
1001 fTraits |= kTraitTrivialType;
1002 }
1003 RField(RField&& other) = default;
1004 RField& operator =(RField&& other) = default;
1005 ~RField() override = default;
1006
1007 void GenerateColumnsImpl() final;
1008 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1009
1010 double *Map(NTupleSize_t globalIndex) {
1011 return fPrincipalColumn->Map<double>(globalIndex);
1012 }
1013 double *Map(const RClusterIndex &clusterIndex) {
1014 return fPrincipalColumn->Map<double>(clusterIndex);
1015 }
1016 double *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1017 return fPrincipalColumn->MapV<double>(globalIndex, nItems);
1018 }
1019 double *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1020 return fPrincipalColumn->MapV<double>(clusterIndex, nItems);
1021 }
1022
1023 using Detail::RFieldBase::GenerateValue;
1024 template <typename... ArgsT>
1026 {
1027 return Detail::RFieldValue(
1028 Detail::RColumnElement<double>(static_cast<double*>(where)),
1029 this, static_cast<double*>(where), std::forward<ArgsT>(args)...);
1030 }
1033 return Detail::RFieldValue(true /* captureFlag */,
1034 Detail::RColumnElement<double>(static_cast<double*>(where)), this, where);
1035 }
1036 size_t GetValueSize() const final { return sizeof(double); }
1037 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1038};
1039
1040template <>
1041class RField<char> : public Detail::RFieldBase {
1042protected:
1043 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1044 return std::make_unique<RField>(newName);
1045 }
1046
1047public:
1048 static std::string TypeName() { return "char"; }
1049 explicit RField(std::string_view name)
1050 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1051 {
1052 fTraits |= kTraitTrivialType;
1053 }
1054 RField(RField&& other) = default;
1055 RField& operator =(RField&& other) = default;
1056 ~RField() override = default;
1057
1058 void GenerateColumnsImpl() final;
1059 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1060
1061 char *Map(NTupleSize_t globalIndex) {
1062 return fPrincipalColumn->Map<char>(globalIndex);
1063 }
1064 char *Map(const RClusterIndex &clusterIndex) {
1065 return fPrincipalColumn->Map<char>(clusterIndex);
1066 }
1067 char *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1068 return fPrincipalColumn->MapV<char>(globalIndex, nItems);
1069 }
1070 char *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1071 return fPrincipalColumn->MapV<char>(clusterIndex, nItems);
1072 }
1073
1074 using Detail::RFieldBase::GenerateValue;
1075 template <typename... ArgsT>
1077 {
1078 return Detail::RFieldValue(
1079 Detail::RColumnElement<char>(static_cast<char*>(where)),
1080 this, static_cast<char*>(where), std::forward<ArgsT>(args)...);
1081 }
1084 return Detail::RFieldValue(true /* captureFlag */,
1085 Detail::RColumnElement<char>(static_cast<char*>(where)), this, where);
1086 }
1087 size_t GetValueSize() const final { return sizeof(char); }
1088 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1089};
1090
1091template <>
1092class RField<std::int8_t> : public Detail::RFieldBase {
1093protected:
1094 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1095 return std::make_unique<RField>(newName);
1096 }
1097
1098public:
1099 static std::string TypeName() { return "std::int8_t"; }
1100 explicit RField(std::string_view name)
1101 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1102 {
1103 fTraits |= kTraitTrivialType;
1104 }
1105 RField(RField&& other) = default;
1106 RField& operator =(RField&& other) = default;
1107 ~RField() override = default;
1108
1109 void GenerateColumnsImpl() final;
1110 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1111
1112 std::int8_t *Map(NTupleSize_t globalIndex) {
1113 return fPrincipalColumn->Map<std::int8_t>(globalIndex);
1114 }
1115 std::int8_t *Map(const RClusterIndex &clusterIndex) {
1116 return fPrincipalColumn->Map<std::int8_t>(clusterIndex);
1117 }
1118 std::int8_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1119 return fPrincipalColumn->MapV<std::int8_t>(globalIndex, nItems);
1120 }
1121 std::int8_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1122 return fPrincipalColumn->MapV<std::int8_t>(clusterIndex, nItems);
1123 }
1124
1125 using Detail::RFieldBase::GenerateValue;
1126 template <typename... ArgsT>
1127 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
1128 {
1129 return Detail::RFieldValue(
1130 Detail::RColumnElement<std::int8_t>(static_cast<std::int8_t*>(where)),
1131 this, static_cast<std::int8_t*>(where), std::forward<ArgsT>(args)...);
1132 }
1133 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final { return GenerateValue(where, 0); }
1134 Detail::RFieldValue CaptureValue(void *where) final {
1135 return Detail::RFieldValue(true /* captureFlag */,
1136 Detail::RColumnElement<std::int8_t>(static_cast<std::int8_t*>(where)), this, where);
1137 }
1138 size_t GetValueSize() const final { return sizeof(std::int8_t); }
1139 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1140};
1141
1142template <>
1143class RField<std::uint8_t> : public Detail::RFieldBase {
1144protected:
1145 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1146 return std::make_unique<RField>(newName);
1147 }
1148
1149public:
1150 static std::string TypeName() { return "std::uint8_t"; }
1151 explicit RField(std::string_view name)
1152 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1153 {
1154 fTraits |= kTraitTrivialType;
1155 }
1156 RField(RField&& other) = default;
1157 RField& operator =(RField&& other) = default;
1158 ~RField() override = default;
1159
1160 void GenerateColumnsImpl() final;
1161 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1162
1163 std::uint8_t *Map(NTupleSize_t globalIndex) {
1164 return fPrincipalColumn->Map<std::uint8_t>(globalIndex);
1165 }
1166 std::uint8_t *Map(const RClusterIndex &clusterIndex) {
1167 return fPrincipalColumn->Map<std::uint8_t>(clusterIndex);
1168 }
1169 std::uint8_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1170 return fPrincipalColumn->MapV<std::uint8_t>(globalIndex, nItems);
1171 }
1172 std::uint8_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1173 return fPrincipalColumn->MapV<std::uint8_t>(clusterIndex, nItems);
1174 }
1175
1176 using Detail::RFieldBase::GenerateValue;
1177 template <typename... ArgsT>
1178 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
1179 {
1180 return Detail::RFieldValue(
1181 Detail::RColumnElement<std::uint8_t>(static_cast<std::uint8_t*>(where)),
1182 this, static_cast<std::uint8_t*>(where), std::forward<ArgsT>(args)...);
1183 }
1184 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final { return GenerateValue(where, 0); }
1185 Detail::RFieldValue CaptureValue(void *where) final {
1186 return Detail::RFieldValue(true /* captureFlag */,
1187 Detail::RColumnElement<std::uint8_t>(static_cast<std::uint8_t*>(where)), this, where);
1188 }
1189 size_t GetValueSize() const final { return sizeof(std::uint8_t); }
1190 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1191};
1192
1193template <>
1194class RField<std::int16_t> : public Detail::RFieldBase {
1195protected:
1196 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1197 return std::make_unique<RField>(newName);
1198 }
1199
1200public:
1201 static std::string TypeName() { return "std::int16_t"; }
1202 explicit RField(std::string_view name)
1203 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1204 {
1205 fTraits |= kTraitTrivialType;
1206 }
1207 RField(RField&& other) = default;
1208 RField& operator =(RField&& other) = default;
1209 ~RField() override = default;
1210
1211 void GenerateColumnsImpl() final;
1212 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1213
1214 std::int16_t *Map(NTupleSize_t globalIndex) {
1215 return fPrincipalColumn->Map<std::int16_t>(globalIndex);
1216 }
1217 std::int16_t *Map(const RClusterIndex &clusterIndex) {
1218 return fPrincipalColumn->Map<std::int16_t>(clusterIndex);
1219 }
1220 std::int16_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1221 return fPrincipalColumn->MapV<std::int16_t>(globalIndex, nItems);
1222 }
1223 std::int16_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1224 return fPrincipalColumn->MapV<std::int16_t>(clusterIndex, nItems);
1225 }
1226
1227 using Detail::RFieldBase::GenerateValue;
1228 template <typename... ArgsT>
1229 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1230 {
1231 return Detail::RFieldValue(
1232 Detail::RColumnElement<std::int16_t>(static_cast<std::int16_t*>(where)),
1233 this, static_cast<std::int16_t*>(where), std::forward<ArgsT>(args)...);
1234 }
1235 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1236 Detail::RFieldValue CaptureValue(void *where) final {
1237 return Detail::RFieldValue(true /* captureFlag */,
1238 Detail::RColumnElement<std::int16_t>(static_cast<std::int16_t*>(where)), this, where);
1239 }
1240 size_t GetValueSize() const final { return sizeof(std::int16_t); }
1241 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1242};
1243
1244template <>
1245class RField<std::uint16_t> : public Detail::RFieldBase {
1246protected:
1247 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1248 return std::make_unique<RField>(newName);
1249 }
1250
1251public:
1252 static std::string TypeName() { return "std::uint16_t"; }
1253 explicit RField(std::string_view name)
1254 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1255 {
1256 fTraits |= kTraitTrivialType;
1257 }
1258 RField(RField&& other) = default;
1259 RField& operator =(RField&& other) = default;
1260 ~RField() override = default;
1261
1262 void GenerateColumnsImpl() final;
1263 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1264
1265 std::uint16_t *Map(NTupleSize_t globalIndex) {
1266 return fPrincipalColumn->Map<std::uint16_t>(globalIndex);
1267 }
1268 std::uint16_t *Map(const RClusterIndex &clusterIndex) {
1269 return fPrincipalColumn->Map<std::uint16_t>(clusterIndex);
1270 }
1271 std::uint16_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1272 return fPrincipalColumn->MapV<std::uint16_t>(globalIndex, nItems);
1273 }
1274 std::uint16_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1275 return fPrincipalColumn->MapV<std::uint16_t>(clusterIndex, nItems);
1276 }
1277
1278 using Detail::RFieldBase::GenerateValue;
1279 template <typename... ArgsT>
1280 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1281 {
1282 return Detail::RFieldValue(
1283 Detail::RColumnElement<std::uint16_t>(static_cast<std::uint16_t*>(where)),
1284 this, static_cast<std::uint16_t*>(where), std::forward<ArgsT>(args)...);
1285 }
1286 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1287 Detail::RFieldValue CaptureValue(void *where) final {
1288 return Detail::RFieldValue(true /* captureFlag */,
1289 Detail::RColumnElement<std::uint16_t>(static_cast<std::uint16_t*>(where)), this, where);
1290 }
1291 size_t GetValueSize() const final { return sizeof(std::uint16_t); }
1292 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1293};
1294
1295template <>
1296class RField<std::int32_t> : public Detail::RFieldBase {
1297protected:
1298 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1299 return std::make_unique<RField>(newName);
1300 }
1301
1302public:
1303 static std::string TypeName() { return "std::int32_t"; }
1304 explicit RField(std::string_view name)
1305 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1306 {
1307 fTraits |= kTraitTrivialType;
1308 }
1309 RField(RField&& other) = default;
1310 RField& operator =(RField&& other) = default;
1311 ~RField() override = default;
1312
1313 void GenerateColumnsImpl() final;
1314 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1315
1316 std::int32_t *Map(NTupleSize_t globalIndex) {
1317 return fPrincipalColumn->Map<std::int32_t>(globalIndex);
1318 }
1319 std::int32_t *Map(const RClusterIndex &clusterIndex) {
1320 return fPrincipalColumn->Map<std::int32_t>(clusterIndex);
1321 }
1322 std::int32_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1323 return fPrincipalColumn->MapV<std::int32_t>(globalIndex, nItems);
1324 }
1325 std::int32_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1326 return fPrincipalColumn->MapV<std::int32_t>(clusterIndex, nItems);
1327 }
1328
1329 using Detail::RFieldBase::GenerateValue;
1330 template <typename... ArgsT>
1331 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1332 {
1333 return Detail::RFieldValue(
1334 Detail::RColumnElement<std::int32_t>(static_cast<std::int32_t*>(where)),
1335 this, static_cast<std::int32_t*>(where), std::forward<ArgsT>(args)...);
1336 }
1337 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1338 Detail::RFieldValue CaptureValue(void *where) final {
1339 return Detail::RFieldValue(true /* captureFlag */,
1340 Detail::RColumnElement<std::int32_t>(static_cast<std::int32_t*>(where)), this, where);
1341 }
1342 size_t GetValueSize() const final { return sizeof(std::int32_t); }
1343 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1344};
1345
1346template <>
1347class RField<std::uint32_t> : public Detail::RFieldBase {
1348protected:
1349 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1350 return std::make_unique<RField>(newName);
1351 }
1352
1353public:
1354 static std::string TypeName() { return "std::uint32_t"; }
1355 explicit RField(std::string_view name)
1356 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1357 {
1358 fTraits |= kTraitTrivialType;
1359 }
1360 RField(RField&& other) = default;
1361 RField& operator =(RField&& other) = default;
1362 ~RField() override = default;
1363
1364 void GenerateColumnsImpl() final;
1365 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1366
1367 std::uint32_t *Map(NTupleSize_t globalIndex) {
1368 return fPrincipalColumn->Map<std::uint32_t>(globalIndex);
1369 }
1370 std::uint32_t *Map(const RClusterIndex clusterIndex) {
1371 return fPrincipalColumn->Map<std::uint32_t>(clusterIndex);
1372 }
1373 std::uint32_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1374 return fPrincipalColumn->MapV<std::uint32_t>(globalIndex, nItems);
1375 }
1376 std::uint32_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1377 return fPrincipalColumn->MapV<std::uint32_t>(clusterIndex, nItems);
1378 }
1379
1380 using Detail::RFieldBase::GenerateValue;
1381 template <typename... ArgsT>
1382 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1383 {
1384 return Detail::RFieldValue(
1385 Detail::RColumnElement<std::uint32_t>(static_cast<std::uint32_t*>(where)),
1386 this, static_cast<std::uint32_t*>(where), std::forward<ArgsT>(args)...);
1387 }
1388 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1389 Detail::RFieldValue CaptureValue(void *where) final {
1390 return Detail::RFieldValue(true /* captureFlag */,
1391 Detail::RColumnElement<std::uint32_t>(static_cast<std::uint32_t*>(where)), this, where);
1392 }
1393 size_t GetValueSize() const final { return sizeof(std::uint32_t); }
1394 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1395};
1396
1397template <>
1398class RField<std::uint64_t> : public Detail::RFieldBase {
1399protected:
1400 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1401 return std::make_unique<RField>(newName);
1402 }
1403
1404public:
1405 static std::string TypeName() { return "std::uint64_t"; }
1406 explicit RField(std::string_view name)
1407 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1408 {
1409 fTraits |= kTraitTrivialType;
1410 }
1411 RField(RField&& other) = default;
1412 RField& operator =(RField&& other) = default;
1413 ~RField() override = default;
1414
1415 void GenerateColumnsImpl() final;
1416 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1417
1418 std::uint64_t *Map(NTupleSize_t globalIndex) {
1419 return fPrincipalColumn->Map<std::uint64_t>(globalIndex);
1420 }
1421 std::uint64_t *Map(const RClusterIndex &clusterIndex) {
1422 return fPrincipalColumn->Map<std::uint64_t>(clusterIndex);
1423 }
1424 std::uint64_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1425 return fPrincipalColumn->MapV<std::uint64_t>(globalIndex, nItems);
1426 }
1427 std::uint64_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1428 return fPrincipalColumn->MapV<std::uint64_t>(clusterIndex, nItems);
1429 }
1430
1431 using Detail::RFieldBase::GenerateValue;
1432 template <typename... ArgsT>
1433 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1434 {
1435 return Detail::RFieldValue(
1436 Detail::RColumnElement<std::uint64_t>(static_cast<std::uint64_t*>(where)),
1437 this, static_cast<std::uint64_t*>(where), std::forward<ArgsT>(args)...);
1438 }
1439 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1440 Detail::RFieldValue CaptureValue(void *where) final {
1441 return Detail::RFieldValue(true /* captureFlag */,
1442 Detail::RColumnElement<std::uint64_t>(static_cast<std::uint64_t*>(where)), this, where);
1443 }
1444 size_t GetValueSize() const final { return sizeof(std::uint64_t); }
1445 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1446};
1447
1448template <>
1449class RField<std::int64_t> : public Detail::RFieldBase {
1450protected:
1451 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1452 return std::make_unique<RField>(newName);
1453 }
1454
1455public:
1456 static std::string TypeName() { return "std::int64_t"; }
1457 explicit RField(std::string_view name)
1458 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */)
1459 {
1460 fTraits |= kTraitTrivialType;
1461 }
1462 RField(RField&& other) = default;
1463 RField& operator =(RField&& other) = default;
1464 ~RField() override = default;
1465
1466 void GenerateColumnsImpl() final;
1467 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1468
1469 std::int64_t *Map(NTupleSize_t globalIndex) {
1470 return fPrincipalColumn->Map<std::int64_t>(globalIndex);
1471 }
1472 std::int64_t *Map(const RClusterIndex &clusterIndex) {
1473 return fPrincipalColumn->Map<std::int64_t>(clusterIndex);
1474 }
1475 std::int64_t *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
1476 return fPrincipalColumn->MapV<std::int64_t>(globalIndex, nItems);
1477 }
1478 std::int64_t *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
1479 return fPrincipalColumn->MapV<std::int64_t>(clusterIndex, nItems);
1480 }
1481
1482 using Detail::RFieldBase::GenerateValue;
1483 template <typename... ArgsT>
1484 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1485 {
1486 return Detail::RFieldValue(
1487 Detail::RColumnElement<std::int64_t>(static_cast<std::int64_t*>(where)),
1488 this, static_cast<std::int64_t*>(where), std::forward<ArgsT>(args)...);
1489 }
1490 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
1491 Detail::RFieldValue CaptureValue(void *where) final {
1492 return Detail::RFieldValue(true /* captureFlag */,
1493 Detail::RColumnElement<std::int64_t>(static_cast<std::int64_t*>(where)), this, where);
1494 }
1495 size_t GetValueSize() const final { return sizeof(std::int64_t); }
1496 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1497};
1498
1499template <>
1500class RField<std::string> : public Detail::RFieldBase {
1501private:
1502 ClusterSize_t fIndex;
1503 Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex> fElemIndex;
1504
1505 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1506 return std::make_unique<RField>(newName);
1507 }
1508 std::size_t AppendImpl(const ROOT::Experimental::Detail::RFieldValue& value) final;
1509 void ReadGlobalImpl(ROOT::Experimental::NTupleSize_t globalIndex,
1511
1512public:
1513 static std::string TypeName() { return "std::string"; }
1514 explicit RField(std::string_view name)
1515 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, false /* isSimple */), fIndex(0),
1516 fElemIndex(&fIndex)
1517 {
1518 }
1519 RField(RField&& other) = default;
1520 RField& operator =(RField&& other) = default;
1521 ~RField() override = default;
1522
1523 void GenerateColumnsImpl() final;
1524 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1525
1526 using Detail::RFieldBase::GenerateValue;
1527 template <typename... ArgsT>
1528 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1529 {
1530 return Detail::RFieldValue(this, static_cast<std::string*>(where), std::forward<ArgsT>(args)...);
1531 }
1532 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, ""); }
1533 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) override {
1534 auto str = value.Get<std::string>();
1535 str->~basic_string(); // TODO(jblomer) C++17 std::destroy_at
1536 if (!dtorOnly)
1537 free(str);
1538 }
1539 Detail::RFieldValue CaptureValue(void *where) override {
1540 return Detail::RFieldValue(true /* captureFlag */, this, where);
1541 }
1542 size_t GetValueSize() const final { return sizeof(std::string); }
1543 size_t GetAlignment() const final { return std::alignment_of<std::string>(); }
1544 void CommitCluster() final;
1545 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1546};
1547
1548
1549template <typename ItemT, std::size_t N>
1550class RField<std::array<ItemT, N>> : public RArrayField {
1551 using ContainerT = typename std::array<ItemT, N>;
1552public:
1553 static std::string TypeName() {
1554 return "std::array<" + RField<ItemT>::TypeName() + "," + std::to_string(N) + ">";
1555 }
1556 explicit RField(std::string_view name)
1557 : RArrayField(name, std::make_unique<RField<ItemT>>(RField<ItemT>::TypeName()), N)
1558 {}
1559 RField(RField&& other) = default;
1560 RField& operator =(RField&& other) = default;
1561 ~RField() override = default;
1562
1563 using Detail::RFieldBase::GenerateValue;
1564 template <typename... ArgsT>
1565 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
1566 {
1567 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1568 }
1569 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final {
1570 return GenerateValue(where, ContainerT());
1571 }
1572};
1573
1574template <typename ItemT, std::size_t N>
1575class RField<ItemT[N]> : public RField<std::array<ItemT, N>> {
1576public:
1577 explicit RField(std::string_view name) : RField<std::array<ItemT, N>>(name) {}
1578 RField(RField &&other) = default;
1579 RField &operator=(RField &&other) = default;
1580 ~RField() override = default;
1581};
1582
1583template <typename... ItemTs>
1584class RField<std::variant<ItemTs...>> : public RVariantField {
1585 using ContainerT = typename std::variant<ItemTs...>;
1586private:
1587 template <typename HeadT, typename... TailTs>
1588 static std::string BuildItemTypes()
1589 {
1590 std::string result = RField<HeadT>::TypeName();
1591 if constexpr(sizeof...(TailTs) > 0)
1592 result += "," + BuildItemTypes<TailTs...>();
1593 return result;
1594 }
1595
1596 template <typename HeadT, typename... TailTs>
1597 static std::vector<Detail::RFieldBase *> BuildItemFields(unsigned int index = 0)
1598 {
1599 std::vector<Detail::RFieldBase *> result;
1600 result.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
1601 if constexpr(sizeof...(TailTs) > 0) {
1602 auto tailFields = BuildItemFields<TailTs...>(index + 1);
1603 result.insert(result.end(), tailFields.begin(), tailFields.end());
1604 }
1605 return result;
1606 }
1607
1608public:
1609 static std::string TypeName() { return "std::variant<" + BuildItemTypes<ItemTs...>() + ">"; }
1610 explicit RField(std::string_view name) : RVariantField(name, BuildItemFields<ItemTs...>()) {}
1611 RField(RField&& other) = default;
1612 RField& operator =(RField&& other) = default;
1613 ~RField() override = default;
1614
1615 using Detail::RFieldBase::GenerateValue;
1616 template <typename... ArgsT>
1617 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
1618 {
1619 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1620 }
1621 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final {
1622 return GenerateValue(where, ContainerT());
1623 }
1624};
1625
1626template <typename ItemT>
1627class RField<std::vector<ItemT>> : public RVectorField {
1628 using ContainerT = typename std::vector<ItemT>;
1629public:
1630 static std::string TypeName() { return "std::vector<" + RField<ItemT>::TypeName() + ">"; }
1631 explicit RField(std::string_view name)
1632 : RVectorField(name, std::make_unique<RField<ItemT>>("_0"))
1633 {}
1634 RField(RField&& other) = default;
1635 RField& operator =(RField&& other) = default;
1636 ~RField() override = default;
1637
1638 using Detail::RFieldBase::GenerateValue;
1639 template <typename... ArgsT>
1640 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1641 {
1642 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1643 }
1644 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final {
1645 return GenerateValue(where, ContainerT());
1646 }
1647 Detail::RFieldValue CaptureValue(void *where) final {
1648 return Detail::RFieldValue(true /* captureFlag */, this, where);
1649 }
1650 size_t GetValueSize() const final { return sizeof(ContainerT); }
1651};
1652
1653// std::vector<bool> is a template specialization and needs special treatment
1654template <>
1655class RField<std::vector<bool>> : public Detail::RFieldBase {
1656private:
1657 ClusterSize_t fNWritten{0};
1658
1659protected:
1660 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1661 return std::make_unique<RField>(newName);
1662 }
1663 std::size_t AppendImpl(const Detail::RFieldValue& value) final;
1664 void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
1665 void GenerateColumnsImpl() final;
1666 void GenerateColumnsImpl(const RNTupleDescriptor &desc) final;
1667
1668public:
1669 static std::string TypeName() { return "std::vector<bool>"; }
1670 explicit RField(std::string_view name);
1671 RField(RField&& other) = default;
1672 RField& operator =(RField&& other) = default;
1673 ~RField() override = default;
1674
1675 using Detail::RFieldBase::GenerateValue;
1676 template <typename... ArgsT>
1677 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
1678 {
1679 return Detail::RFieldValue(this, static_cast<std::vector<bool>*>(where), std::forward<ArgsT>(args)...);
1680 }
1681 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final {
1682 return GenerateValue(where, std::vector<bool>());
1683 }
1684 Detail::RFieldValue CaptureValue(void *where) final {
1685 return Detail::RFieldValue(true /* captureFlag */, this, where);
1686 }
1687 std::vector<Detail::RFieldValue> SplitValue(const Detail::RFieldValue &value) const final;
1688 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
1689
1690 size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
1691 size_t GetAlignment() const final { return std::alignment_of<std::vector<bool>>(); }
1692 void CommitCluster() final { fNWritten = 0; }
1693 void AcceptVisitor(Detail::RFieldVisitor &visitor) const final;
1694 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const {
1695 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
1696 }
1697 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
1698 {
1699 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
1700 }
1701};
1702
1703template <typename ItemT>
1704class RField<ROOT::VecOps::RVec<ItemT>> : public RRVecField {
1706protected:
1707 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final {
1708 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1709 return std::make_unique<RField<ROOT::VecOps::RVec<ItemT>>>(newName, std::move(newItemField));
1710 }
1711 std::size_t AppendImpl(const Detail::RFieldValue& value) final {
1712 auto typedValue = value.Get<ContainerT>();
1713 auto nbytes = 0;
1714 auto count = typedValue->size();
1715 for (unsigned i = 0; i < count; ++i) {
1716 auto itemValue = fSubFields[0]->CaptureValue(&typedValue->data()[i]);
1717 nbytes += fSubFields[0]->Append(itemValue);
1718 }
1720 this->fNWritten += count;
1721 fColumns[0]->Append(elemIndex);
1722 return nbytes + sizeof(elemIndex);
1723 }
1725 auto typedValue = value->Get<ContainerT>();
1726 ClusterSize_t nItems;
1727 RClusterIndex collectionStart;
1728 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1729 typedValue->resize(nItems);
1730 for (unsigned i = 0; i < nItems; ++i) {
1731 auto itemValue = fSubFields[0]->CaptureValue(&typedValue->data()[i]);
1732 fSubFields[0]->Read(collectionStart + i, &itemValue);
1733 }
1734 }
1735
1736public:
1737 RField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
1738 : RRVecField(fieldName, std::move(itemField))
1739 {
1740 }
1741
1742 explicit RField(std::string_view name)
1743 : RField(name, std::make_unique<RField<ItemT>>("_0"))
1744 {
1745 }
1746 RField(RField&& other) = default;
1747 RField& operator =(RField&& other) = default;
1748 ~RField() override = default;
1749
1750 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final {
1751 auto vec = reinterpret_cast<ContainerT*>(value.GetRawPtr());
1752 vec->~RVec();
1753 if (!dtorOnly)
1754 free(vec);
1755 }
1756
1757 static std::string TypeName() { return "ROOT::VecOps::RVec<" + RField<ItemT>::TypeName() + ">"; }
1758
1759 using Detail::RFieldBase::GenerateValue;
1760 template <typename... ArgsT>
1762 {
1763 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1764 }
1766 return GenerateValue(where, ContainerT());
1767 }
1769 return Detail::RFieldValue(true /* captureFlag */, this, static_cast<ContainerT*>(where));
1770 }
1771 size_t GetValueSize() const final { return sizeof(ContainerT); }
1772 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
1773};
1774
1775template <typename T1, typename T2>
1776class RField<std::pair<T1, T2>> : public RPairField {
1777 using ContainerT = typename std::pair<T1,T2>;
1778private:
1779 template <typename Ty1, typename Ty2>
1780 static std::array<std::unique_ptr<Detail::RFieldBase>, 2> BuildItemFields()
1781 {
1782 return {std::make_unique<RField<Ty1>>("_0"), std::make_unique<RField<Ty2>>("_1")};
1783 }
1784
1785protected:
1786 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final
1787 {
1788 std::array<std::unique_ptr<Detail::RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetName()),
1789 fSubFields[1]->Clone(fSubFields[1]->GetName())};
1790 return std::make_unique<RField<std::pair<T1, T2>>>(newName, std::move(items));
1791 }
1792
1793public:
1794 static std::string TypeName() {
1795 return "std::pair<" + RField<T1>::TypeName() + "," + RField<T2>::TypeName() + ">";
1796 }
1797 explicit RField(std::string_view name, std::array<std::unique_ptr<Detail::RFieldBase>, 2> &&itemFields)
1798 : RPairField(name, std::move(itemFields), {offsetof(ContainerT, first), offsetof(ContainerT, second)})
1799 {
1800 fMaxAlignment = std::max(alignof(T1), alignof(T2));
1801 fSize = sizeof(ContainerT);
1802 }
1803 explicit RField(std::string_view name) : RField(name, BuildItemFields<T1, T2>()) {}
1804 RField(RField&& other) = default;
1805 RField& operator =(RField&& other) = default;
1806 ~RField() override = default;
1807
1808 using Detail::RFieldBase::GenerateValue;
1809 template <typename... ArgsT>
1810 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
1811 {
1812 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1813 }
1814 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final {
1815 return GenerateValue(where, ContainerT());
1816 }
1817 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final
1818 {
1819 reinterpret_cast<ContainerT *>(value.GetRawPtr())->~pair();
1820 if (!dtorOnly)
1821 free(reinterpret_cast<ContainerT *>(value.GetRawPtr()));
1822 }
1823};
1824
1825template <typename... ItemTs>
1826class RField<std::tuple<ItemTs...>> : public RTupleField {
1827 using ContainerT = typename std::tuple<ItemTs...>;
1828private:
1829 template <typename HeadT, typename... TailTs>
1830 static std::string BuildItemTypes()
1831 {
1832 std::string result = RField<HeadT>::TypeName();
1833 if constexpr (sizeof...(TailTs) > 0)
1834 result += "," + BuildItemTypes<TailTs...>();
1835 return result;
1836 }
1837
1838 template <typename HeadT, typename... TailTs>
1839 static void _BuildItemFields(std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields, unsigned int index = 0)
1840 {
1841 itemFields.emplace_back(new RField<HeadT>("_" + std::to_string(index)));
1842 if constexpr (sizeof...(TailTs) > 0)
1843 _BuildItemFields<TailTs...>(itemFields, index + 1);
1844 }
1845 template <typename... Ts>
1846 static std::vector<std::unique_ptr<Detail::RFieldBase>> BuildItemFields()
1847 {
1848 std::vector<std::unique_ptr<Detail::RFieldBase>> result;
1849 _BuildItemFields<Ts...>(result);
1850 return result;
1851 }
1852
1853 template <unsigned Index, typename HeadT, typename... TailTs>
1854 static void _BuildItemOffsets(std::vector<std::size_t> &offsets, const ContainerT &tuple)
1855 {
1856 auto offset =
1857 reinterpret_cast<std::uintptr_t>(&std::get<Index>(tuple)) - reinterpret_cast<std::uintptr_t>(&tuple);
1858 offsets.emplace_back(offset);
1859 if constexpr (sizeof...(TailTs) > 0)
1860 _BuildItemOffsets<Index + 1, TailTs...>(offsets, tuple);
1861 }
1862 template <typename... Ts>
1863 static std::vector<std::size_t> BuildItemOffsets()
1864 {
1865 std::vector<std::size_t> result;
1866 _BuildItemOffsets<0, Ts...>(result, ContainerT());
1867 return result;
1868 }
1869
1870protected:
1871 std::unique_ptr<Detail::RFieldBase> CloneImpl(std::string_view newName) const final
1872 {
1873 std::vector<std::unique_ptr<Detail::RFieldBase>> items;
1874 for (auto &item : fSubFields)
1875 items.push_back(item->Clone(item->GetName()));
1876 return std::make_unique<RField<std::tuple<ItemTs...>>>(newName, std::move(items));
1877 }
1878
1879public:
1880 static std::string TypeName() { return "std::tuple<" + BuildItemTypes<ItemTs...>() + ">"; }
1881 explicit RField(std::string_view name, std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields)
1882 : RTupleField(name, std::move(itemFields), BuildItemOffsets<ItemTs...>())
1883 {
1884 fMaxAlignment = std::max({alignof(ItemTs)...});
1885 fSize = sizeof(ContainerT);
1886 }
1887 explicit RField(std::string_view name) : RField(name, BuildItemFields<ItemTs...>()) {}
1888 RField(RField &&other) = default;
1889 RField &operator=(RField &&other) = default;
1890 ~RField() override = default;
1891
1892 using Detail::RFieldBase::GenerateValue;
1893 template <typename... ArgsT>
1894 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&...args)
1895 {
1896 return Detail::RFieldValue(this, static_cast<ContainerT *>(where), std::forward<ArgsT>(args)...);
1897 }
1898 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
1899 {
1900 return GenerateValue(where, ContainerT());
1901 }
1902 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final
1903 {
1904 reinterpret_cast<ContainerT *>(value.GetRawPtr())->~tuple();
1905 if (!dtorOnly)
1906 free(reinterpret_cast<ContainerT *>(value.GetRawPtr()));
1907 }
1908};
1909
1910} // namespace Experimental
1911} // namespace ROOT
1912
1913#endif
size_t fSize
Cppyy::TCppType_t fClass
#define R__unlikely(expr)
Definition RConfig.hxx:601
ROOT::Experimental::RField< T > RField
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define N
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 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 id
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))
#define free
Definition civetweb.c:1539
Pairs of C++ type and column type, like float and EColumnType::kReal32.
void Append(const RColumnElementBase &element)
Definition RColumn.hxx:116
void Read(const NTupleSize_t globalIndex, RColumnElementBase *element)
Definition RColumn.hxx:157
NTupleSize_t GetGlobalIndex(const RClusterIndex &clusterIndex)
Definition RColumn.hxx:248
NTupleSize_t GetNElements() const
Definition RColumn.hxx:307
void GetCollectionInfo(const NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *collectionSize)
For offset columns only, look at the two adjacent values that define a collection's coordinates.
Definition RColumn.hxx:264
Iterates over the sub tree of fields in depth-first search order.
Definition RField.hxx:166
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.cxx:467
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
Definition RField.hxx:175
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition RField.hxx:306
virtual RFieldValue CaptureValue(void *where)=0
Creates a value from a memory location with an already constructed object.
std::string GetDescription() const
Get the field's description.
Definition RField.hxx:294
void SetOnDiskId(DescriptorId_t id)
Definition RField.hxx:298
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.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition RField.hxx:114
RFieldBase * fParent
Sub fields point to their mother field.
Definition RField.hxx:116
std::size_t GetNRepetitions() const
Definition RField.hxx:288
std::string fDescription
Free text set by the user.
Definition RField.hxx:110
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition RField.hxx:308
int fTraits
Properties of the type that allow for optimizations of collections of that type.
Definition RField.hxx:124
friend struct ROOT::Experimental::Internal::RFieldCallbackInjector
Definition RField.hxx:79
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:337
DescriptorId_t GetOnDiskId() const
Definition RField.hxx:297
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
Definition RField.hxx:92
friend class ROOT::Experimental::RCollectionField
Definition RField.hxx:78
void ConnectPageSink(RPageSink &pageSink)
Fields and their columns live in the void until connected to a physical page storage.
Definition RField.cxx:420
ROOT::Experimental::EColumnType EnsureColumnType(const std::vector< EColumnType > &requestedTypes, unsigned int columnIndex, const RNTupleDescriptor &desc)
Throws an exception if the column given by fOnDiskId and the columnIndex in the provided descriptor i...
Definition RField.cxx:375
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition RField.cxx:367
virtual void ReadInClusterImpl(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition RField.hxx:142
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.hxx:280
virtual size_t GetAlignment() const
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:235
virtual std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const =0
Called by Clone(), which additionally copies the on-disk ID.
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.hxx:295
virtual std::vector< RFieldValue > SplitValue(const RFieldValue &value) const
Creates the list of direct child values given a value for this field.
Definition RField.cxx:344
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition RField.cxx:298
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
Definition RField.hxx:104
std::string fType
The C++ type captured by this field.
Definition RField.hxx:98
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName)
Factory method to resurrect a field from the stored on-disk type information.
Definition RField.cxx:193
std::string fName
The field name relative to its parent field.
Definition RField.hxx:96
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:407
NTupleSize_t GetNElements() const
Definition RField.hxx:289
void ConnectPageSource(RPageSource &pageSource)
Definition RField.cxx:431
std::size_t Append(const RFieldValue &value)
Write the given value into columns.
Definition RField.hxx:241
virtual std::size_t AppendImpl(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition RField.cxx:317
std::function< void(RFieldValue &)> ReadCallback_t
Definition RField.hxx:80
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:309
std::size_t fNRepetitions
For fixed sized arrays, the array length.
Definition RField.hxx:102
RFieldBase(const RFieldBase &)=delete
virtual void AcceptVisitor(RFieldVisitor &visitor) const
Definition RField.cxx:445
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:108
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value)
Definition RField.cxx:323
ENTupleStructure fStructure
The role of this field in the data model structure.
Definition RField.hxx:100
void Read(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition RField.hxx:265
void InvokeReadCallbacks(RFieldValue &value)
Definition RField.hxx:158
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:122
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
Definition RField.hxx:90
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition RField.cxx:349
std::vector< RFieldBase * > GetSubFields() const
Definition RField.cxx:357
virtual RFieldValue GenerateValue(void *where)=0
Generates a tree value in a given location of size at least GetValueSize().
RFieldBase & operator=(const RFieldBase &)=delete
ENTupleStructure GetStructure() const
Definition RField.hxx:287
void Read(NTupleSize_t globalIndex, RFieldValue *value)
Populate a single value with data from the tree, which needs to be of the fitting type.
Definition RField.hxx:253
static constexpr int kTraitTriviallyConstructible
No constructor needs to be called, i.e.
Definition RField.hxx:85
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. DestroyValue() is a no-op.
Definition RField.hxx:87
RFieldValue GenerateValue()
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.cxx:330
std::vector< ReadCallback_t > fReadCallbacks
List of functions to be called after reading a value.
Definition RField.hxx:126
RColumn * fPrincipalColumn
Points into fColumns.
Definition RField.hxx:120
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 available trivial, native content types of a column.
The generic field for fixed size arrays, which do not need an offset column.
Definition RField.hxx:570
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1834
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1828
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1785
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1776
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1845
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1795
RArrayField & operator=(RArrayField &&other)=default
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:595
RArrayField(RArrayField &&other)=default
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1815
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:596
~RArrayField() override=default
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1766
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:1760
The field for a class with dictionary.
Definition RField.hxx:339
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:958
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
Definition RField.hxx:350
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:976
void Attach(std::unique_ptr< Detail::RFieldBase > child, RSubFieldInfo info)
Definition RField.cxx:900
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:965
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:908
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:913
RClassField & operator=(RClassField &&other)=default
~RClassField() override=default
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition RField.cxx:981
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:381
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:930
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:938
std::vector< RSubFieldInfo > fSubFieldsInfo
Additional information kept for each entry in fSubFields
Definition RField.hxx:354
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:922
RClassField(RClassField &&other)=default
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:951
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
The field for a class representing a collection of elements via TVirtualCollectionProxy.
Definition RField.hxx:392
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:425
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1113
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1134
std::unique_ptr< TVirtualCollectionProxy > fProxy
Definition RField.hxx:397
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:1041
RCollectionClassField & operator=(RCollectionClassField &&other)=default
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1062
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1128
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1047
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:422
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1150
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:429
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:421
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1095
RCollectionClassField(RCollectionClassField &&other)=default
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1145
static constexpr const std::size_t kReadChunkSize
Chunk size in bytes used in ReadGlobalImp().
Definition RField.hxx:396
The collection field is only used for writing; when reading, untyped collections are projected to an ...
Definition RField.hxx:745
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:769
static std::string TypeName()
Definition RField.hxx:752
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:748
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:773
RCollectionField(RCollectionField &&other)=default
A field translates read and write calls from/to underlying columns to/from tree values.
Represents transient storage of simple or complex C++ values.
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:321
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:503
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:494
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:333
Detail::RFieldValue GenerateValue(void *) override
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:331
Detail::RFieldValue CaptureValue(void *) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:332
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:328
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:329
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Definition RField.hxx:879
ClusterSize_t * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:853
ClusterSize_t * Map(const RClusterIndex &clusterIndex)
Definition RField.hxx:850
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:869
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:873
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
ClusterSize_t * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:856
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition RField.hxx:876
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:862
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:868
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:829
RField & operator=(RField &&other)=default
RField(RField &&other)=default
RField(std::string_view name)
Definition RField.hxx:1577
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:1768
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:1765
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.hxx:1724
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1771
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.hxx:1711
typename ROOT::VecOps::RVec< ItemT > ContainerT
Definition RField.hxx:1705
RField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition RField.hxx:1737
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:1707
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:1772
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:1761
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.hxx:1750
bool * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:913
RField(std::string_view name)
Definition RField.hxx:895
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:933
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:889
bool * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:916
static std::string TypeName()
Definition RField.hxx:894
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:922
RField(RField &&other)=default
bool * Map(const RClusterIndex &clusterIndex)
Definition RField.hxx:910
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:929
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:928
char * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1067
RField(std::string_view name)
Definition RField.hxx:1049
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1087
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:1082
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:1043
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:1076
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:1083
RField(RField &&other)=default
char * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1070
static std::string TypeName()
Definition RField.hxx:1048
char * Map(const RClusterIndex &clusterIndex)
Definition RField.hxx:1064
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:1032
double * Map(const RClusterIndex &clusterIndex)
Definition RField.hxx:1013
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:992
double * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:1016
double * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:1019
RField(std::string_view name)
Definition RField.hxx:998
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:1025
RField(RField &&other)=default
static std::string TypeName()
Definition RField.hxx:997
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:1036
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:1031
static std::string TypeName()
Definition RField.hxx:945
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:979
RField(RField &&other)=default
float * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
Definition RField.hxx:964
float * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Definition RField.hxx:967
RField(std::string_view name)
Definition RField.hxx:946
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition RField.hxx:973
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:984
float * Map(const RClusterIndex &clusterIndex)
Definition RField.hxx:961
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.hxx:980
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:940
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:640
RField(std::string_view name)
Definition RField.hxx:643
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&...args)
Definition RField.hxx:652
RField & operator=(RField &&other)=default
RField(RField &&other)=default
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition RField.hxx:656
static std::string TypeName()
Definition RField.hxx:642
~RField() override=default
The on-storage meta-data of an ntuple.
The generic field for std::pair<T1, T2> types.
Definition RField.hxx:778
~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
The type-erased field for a RVec<Type>
Definition RField.hxx:525
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1570
std::size_t EvalValueSize() const
Evaluate the constant returned by GetValueSize.
Definition RField.cxx:1589
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1541
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1649
RRVecField(RRVecField &&)=default
~RRVecField() override=default
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:563
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) override
Definition RField.cxx:1449
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1654
size_t GetAlignment() const override
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.cxx:1642
RRVecField(const RRVecField &)=delete
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:1426
RRVecField & operator=(RRVecField &&)=default
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1637
std::size_t AppendImpl(const Detail::RFieldValue &value) override
Operations on values of complex types, e.g.
Definition RField.cxx:1432
RRVecField & operator=(RRVecField &)=delete
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1576
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:559
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1517
The field for an untyped record.
Definition RField.hxx:437
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:1207
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:483
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:484
std::vector< std::size_t > fOffsets
Definition RField.hxx:441
RRecordField(RRecordField &&other)=default
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1215
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:454
void GenerateColumnsImpl(const RNTupleDescriptor &) final
Creates the backing columns corresponsing to the field type for reading.
Definition RField.hxx:477
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:1196
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1224
~RRecordField() override=default
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1259
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1266
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1248
RRecordField & operator=(RRecordField &&other)=default
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1232
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.hxx:476
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1276
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 std::tuple<Ts...> types.
Definition RField.hxx:801
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
The generic field for std::variant types.
Definition RField.hxx:601
~RVariantField() override=default
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1907
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1973
RVariantField & operator=(RVariantField &&other)=default
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1956
std::vector< ClusterSize_t::ValueType > fNWritten
Definition RField.hxx:607
size_t fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
Definition RField.hxx:606
void SetTag(void *variantPtr, std::uint32_t tag) const
Definition RField.cxx:1901
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1935
std::uint32_t GetTag(void *variantPtr) const
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
Definition RField.cxx:1895
static std::string GetTypeList(const std::vector< Detail::RFieldBase * > &itemFields)
Definition RField.cxx:1852
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1923
RVariantField(RVariantField &&other)=default
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:633
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1968
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:1884
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1978
The generic field for a (nested) std::vector<Type> except for std::vector<bool>
Definition RField.hxx:489
~RVectorField() override=default
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1385
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1403
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:1294
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1408
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:512
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition RField.cxx:1391
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:519
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1315
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition RField.hxx:516
RVectorField & operator=(RVectorField &&other)=default
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1351
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:513
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:1369
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1300
RVectorField(RVectorField &&other)=default
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1480
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
RooCmdArg Index(RooCategory &icat)
auto Map(Args &&... args)
Create new collection applying a callable to the elements of the input collection.
Definition RVec.hxx:2098
#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)
double T(double x)
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Definition first.py:1
The point here is that we can only tell at run time if a class has an associated collection proxy.
Definition RField.hxx:706
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...