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