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