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>
21#include <ROOT/RField.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>
30#include <TError.h>
31
32#include <algorithm>
33#include <array>
34#include <iostream>
35#include <iterator>
36#include <memory>
37#include <string>
38#include <type_traits>
39#include <typeinfo>
40#if __cplusplus >= 201703L
41#include <variant>
42#endif
43#include <vector>
44#include <utility>
45
46class TClass;
47
48namespace ROOT {
49namespace Experimental {
50
51class RCollectionNTuple;
52class REntry;
53class RFieldCollection;
54class RNTupleModel;
55
56namespace Detail {
57
58class RFieldFuse;
59class RNTupleVisitor;
60class RPageStorage;
61
62// clang-format off
63/**
64\class ROOT::Experimental::RFieldBase
65\ingroup NTuple
66\brief A field translates read and write calls from/to underlying columns to/from tree values
67
68A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
69type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
70mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
71The field knows based on its type and the field name the type(s) and name(s) of the columns.
72*/
73// clang-format on
75 friend class ROOT::Experimental::Detail::RFieldFuse; // to connect the columns to a page storage
76 friend class ROOT::Experimental::RFieldCollection; // to change the field names when collections are attached
77private:
78 /// The field name relative to its parent field
79 std::string fName;
80 /// The C++ type captured by this field
81 std::string fType;
82 /// The role of this field in the data model structure
84 /// For fixed sized arrays, the array length
85 std::size_t fNRepetitions;
86 /// A field on a trivial type that maps as-is to a single column
88 /// Describes where the field is located inside the ntuple.
89 struct RLevelInfo {
90 private:
91 /// Tells how deep the field is in the ntuple. Rootfield has fLevel 0, direct subfield of Rootfield has fLevel 1, etc.
92 int fLevel = 1;
93 /// First subfield of parentfield has fOrder 1, the next fOrder 2, etc. Value set by RFieldBase::fOrder
94 int fOrder = 1;
95 /// The field itself is also included in this number.
97 public:
98 RLevelInfo() = default;
99 RLevelInfo(const RFieldBase *field) : RLevelInfo() {
100 fLevel = GetLevel(field);
101 fOrder = GetOrder(field);
103 }
104 int GetNumSiblings(const RFieldBase *field = nullptr) const {
105 if (field && field->GetParent())
106 return static_cast<int>(field->GetParent()->fSubFields.size());
107 return fNumSiblingFields;
108 }
109 int GetLevel(const RFieldBase *field = nullptr) const {
110 if(!field)
111 return fLevel;
112 int level{0};
113 const RFieldBase *parentPtr{field->GetParent()};
114 while (parentPtr) {
115 parentPtr = parentPtr->GetParent();
116 ++level;
117 }
118 return level;
119 }
120 int GetOrder(const RFieldBase *field = nullptr) const {
121 if(field)
122 return field->fOrder;
123 return fOrder;
124 }
125 };
126 /// First subfield of parentfield has fOrder 1, the next fOrder 2, etc. Value set by RFieldBase::Attach()
127 int fOrder = 1;
128protected:
129 /// Collections and classes own sub fields
130 std::vector<std::unique_ptr<RFieldBase>> fSubFields;
131 /// Sub fields point to their mother field
133 /// Points into fColumns. All fields that have columns have a distinct main column. For simple fields
134 /// (float, int, ...), the principal column corresponds to the field type. For collection fields expect std::array,
135 /// the main column is the offset field. Class fields have no column of their own.
137 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
138 std::vector<std::unique_ptr<RColumn>> fColumns;
139
140 /// Creates the backing columns corresponsing to the field type and name
141 virtual void DoGenerateColumns() = 0;
142
143 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
144 /// column type exists.
145 virtual void DoAppend(const RFieldValue &value);
146 virtual void DoReadGlobal(NTupleSize_t globalIndex, RFieldValue *value);
147 virtual void DoReadInCluster(const RClusterIndex &clusterIndex, RFieldValue *value) {
148 DoReadGlobal(fPrincipalColumn->GetGlobalIndex(clusterIndex), value);
149 }
150
151public:
152 /// Iterates over the sub fields in depth-first search order
153 class RIterator : public std::iterator<std::forward_iterator_tag, Detail::RFieldBase> {
154 private:
156 struct Position {
157 Position() : fFieldPtr(nullptr), fIdxInParent(-1) { }
158 Position(pointer fieldPtr, int idxInParent) : fFieldPtr(fieldPtr), fIdxInParent(idxInParent) { }
159 pointer fFieldPtr;
161 };
162 /// The stack of nodes visited when walking down the tree of fields
163 std::vector<Position> fStack;
164 public:
165 RIterator() { fStack.emplace_back(Position()); }
166 RIterator(pointer val, int idxInParent) { fStack.emplace_back(Position(val, idxInParent)); }
168 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
169 /// in depth-first search order
170 void Advance();
171
172 iterator operator++(int) /* postfix */ { auto r = *this; Advance(); return r; }
173 iterator& operator++() /* prefix */ { Advance(); return *this; }
174 reference operator* () const { return *fStack.back().fFieldPtr; }
175 pointer operator->() const { return fStack.back().fFieldPtr; }
176 bool operator==(const iterator& rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
177 bool operator!=(const iterator& rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
178 };
179
180 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
182 std::size_t nRepetitions = 0);
183 RFieldBase(const RFieldBase&) = delete;
184 RFieldBase(RFieldBase&&) = default;
187 virtual ~RFieldBase();
188
189 ///// Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns
190 virtual RFieldBase *Clone(std::string_view newName) = 0;
191
192 /// Factory method to resurrect a field from the stored on-disk type information
193 static RFieldBase *Create(const std::string &fieldName, const std::string &typeName);
194
195 /// Generates a tree value of the field type and allocates new initialized memory according to the type.
197 /// Generates a tree value in a given location of size at least GetValueSize(). Assumes that where has been
198 /// allocated by malloc().
199 virtual RFieldValue GenerateValue(void *where) = 0;
200 /// Releases the resources acquired during GenerateValue (memory and constructor)
201 /// This implementation works for simple types but needs to be overwritten for complex ones
202 virtual void DestroyValue(const RFieldValue &value, bool dtorOnly = false);
203 /// Creates a value from a memory location with an already constructed object
204 virtual RFieldValue CaptureValue(void *where) = 0;
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
210 /// Write the given value into columns. The value object has to be of the same type as the field.
211 void Append(const RFieldValue& value) {
212 if (!fIsSimple) {
213 DoAppend(value);
214 return;
215 }
216 //printf("Appending simple value for %lu %s\n", *(unsigned long *)(value.GetRawPtr()), fName.c_str());
218 }
219
220 /// Populate a single value with data from the tree, which needs to be of the fitting type.
221 /// Reading copies data into the memory wrapped by the ntuple value.
222 void Read(NTupleSize_t globalIndex, RFieldValue *value) {
223 if (!fIsSimple) {
224 DoReadGlobal(globalIndex, value);
225 return;
226 }
227 fPrincipalColumn->Read(globalIndex, &value->fMappedElement);
228 }
229
230 void Read(const RClusterIndex &clusterIndex, RFieldValue *value) {
231 if (!fIsSimple) {
232 DoReadInCluster(clusterIndex, value);
233 return;
234 }
235 fPrincipalColumn->Read(clusterIndex, &value->fMappedElement);
236 }
237
238 /// Ensure that all received items are written from page buffers to the storage.
239 void Flush() const;
240 /// Perform housekeeping tasks for global to cluster-local index translation
241 virtual void CommitCluster() {}
242
243 void Attach(std::unique_ptr<Detail::RFieldBase> child);
244
245 std::string GetName() const { return fName; }
246 std::string GetType() const { return fType; }
248 std::size_t GetNRepetitions() const { return fNRepetitions; }
249 const RFieldBase* GetParent() const { return fParent; }
250 bool IsSimple() const { return fIsSimple; }
251
252 /// Indicates an evolution of the mapping scheme from C++ type to columns
253 virtual RNTupleVersion GetFieldVersion() const { return RNTupleVersion(); }
254 /// Indicates an evolution of the C++ type itself
255 virtual RNTupleVersion GetTypeVersion() const { return RNTupleVersion(); }
256
257 RIterator begin();
258 RIterator end();
259
260 /// Used for the visitor design pattern, see for example RNTupleReader::Print()
261 virtual void TraverseVisitor(RNTupleVisitor &visitor, int level = 0) const;
262 virtual void AcceptVisitor(RNTupleVisitor &visitor, int level) const;
263
265 return RLevelInfo(this);
266 }
267 void SetOrder(int o) { fOrder = o; }
268};
269
270// clang-format off
271/**
272\class ROOT::Experimental::RFieldFuse
273\ingroup NTuple
274\brief A friend of RFieldBase responsible for connecting a field's columns to the physical page storage
275
276Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
277can be read or written.
278*/
279// clang-format on
281public:
282 static void Connect(DescriptorId_t fieldId, RPageStorage &pageStorage, RFieldBase &field);
283};
284
285} // namespace Detail
286
287
288
289/// The container field for an ntuple model, which itself has no physical representation
291public:
292 RFieldRoot() : Detail::RFieldBase("", "", ENTupleStructure::kRecord, false /* isSimple */) { SetOrder(-1); }
294
295 void DoGenerateColumns() final {}
299 size_t GetValueSize() const final { return 0; }
300
301 /// Generates managed values for the top-level sub fields
303 void AcceptVisitor(Detail::RNTupleVisitor &visitor, int level) const final;
304};
305
306/// The field for a class with dictionary
308private:
310 std::size_t fMaxAlignment = 1;
311
312protected:
313 void DoAppend(const Detail::RFieldValue& value) final;
314 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
315 void DoReadInCluster(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final;
316public:
317 RFieldClass(std::string_view fieldName, std::string_view className);
318 RFieldClass(RFieldClass&& other) = default;
319 RFieldClass& operator =(RFieldClass&& other) = default;
320 ~RFieldClass() = default;
321 RFieldBase* Clone(std::string_view newName) final;
322
323 void DoGenerateColumns() final;
324 using Detail::RFieldBase::GenerateValue;
325 Detail::RFieldValue GenerateValue(void* where) override;
326 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
327 Detail::RFieldValue CaptureValue(void *where) final;
328 size_t GetValueSize() const override;
329 size_t GetAlignment() const final { return fMaxAlignment; }
330};
331
332/// The generic field for a (nested) std::vector<Type> except for std::vector<bool>
334private:
335 std::size_t fItemSize;
337
338protected:
339 void DoAppend(const Detail::RFieldValue& value) final;
340 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
341
342public:
343 RFieldVector(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField);
344 RFieldVector(RFieldVector&& other) = default;
346 ~RFieldVector() = default;
347 RFieldBase* Clone(std::string_view newName) final;
348
349 void DoGenerateColumns() final;
350 using Detail::RFieldBase::GenerateValue;
351 Detail::RFieldValue GenerateValue(void* where) override;
352 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
353 Detail::RFieldValue CaptureValue(void *where) override;
354 size_t GetValueSize() const override { return sizeof(std::vector<char>); }
355 size_t GetAlignment() const final { return std::alignment_of<std::vector<char>>(); }
356 void CommitCluster() final;
357};
358
359
360/// The generic field for fixed size arrays, which do not need an offset column
361class RFieldArray : public Detail::RFieldBase {
362private:
363 std::size_t fItemSize;
364 std::size_t fArrayLength;
365
366protected:
367 void DoAppend(const Detail::RFieldValue& value) final;
368 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
369 void DoReadInCluster(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final;
370
371public:
372 RFieldArray(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength);
373 RFieldArray(RFieldArray &&other) = default;
374 RFieldArray& operator =(RFieldArray &&other) = default;
375 ~RFieldArray() = default;
376 RFieldBase *Clone(std::string_view newName) final;
377
378 void DoGenerateColumns() final;
379 using Detail::RFieldBase::GenerateValue;
380 Detail::RFieldValue GenerateValue(void *where) override;
381 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final;
382 Detail::RFieldValue CaptureValue(void *where) final;
383 size_t GetValueSize() const final { return fItemSize * fArrayLength; }
384 size_t GetAlignment() const final { return fSubFields[0]->GetAlignment(); }
385};
386
387#if __cplusplus >= 201703L
388/// The generic field for std::variant types
389class RFieldVariant : public Detail::RFieldBase {
390private:
391 size_t fMaxItemSize = 0;
392 size_t fMaxAlignment = 1;
393 /// In the std::variant memory layout, at which byte number is the index stored
394 size_t fTagOffset = 0;
395 std::vector<ClusterSize_t::ValueType> fNWritten;
396
397 static std::string GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields);
398 /// Extracts the index from an std::variant and transforms it into the 1-based index used for the switch column
399 std::uint32_t GetTag(void *variantPtr) const;
400 void SetTag(void *variantPtr, std::uint32_t tag) const;
401
402protected:
403 void DoAppend(const Detail::RFieldValue& value) final;
404 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
405
406public:
407 // TODO(jblomer): use std::span in signature
408 RFieldVariant(std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields);
409 RFieldVariant(RFieldVariant &&other) = default;
410 RFieldVariant& operator =(RFieldVariant &&other) = default;
411 ~RFieldVariant() = default;
412 RFieldBase *Clone(std::string_view newName) final;
413
414 void DoGenerateColumns() final;
415 using Detail::RFieldBase::GenerateValue;
416 Detail::RFieldValue GenerateValue(void *where) override;
417 void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly = false) final;
418 Detail::RFieldValue CaptureValue(void *where) final;
419 size_t GetValueSize() const final;
420 size_t GetAlignment() const final { return fMaxAlignment; }
421 void CommitCluster() final;
422};
423#endif
424
425
426/// Classes with dictionaries that can be inspected by TClass
427template <typename T, typename=void>
428class RField : public RFieldClass {
429public:
430 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
432 static_assert(std::is_class<T>::value, "no I/O support for this basic C++ type");
433 }
434 RField(RField&& other) = default;
435 RField& operator =(RField&& other) = default;
436 ~RField() = default;
437
439 template <typename... ArgsT>
441 {
442 return Detail::RFieldValue(this, static_cast<T*>(where), std::forward<ArgsT>(args)...);
443 }
445};
446
447
449private:
450 /// Save the link to the collection ntuple in order to reset the offset counter when committing the cluster
451 std::shared_ptr<RCollectionNTuple> fCollectionNTuple;
452public:
453 static std::string TypeName() { return ":RFieldCollection:"; }
455 std::shared_ptr<RCollectionNTuple> collectionNTuple,
456 std::unique_ptr<RNTupleModel> collectionModel);
459 ~RFieldCollection() = default;
460 RFieldBase* Clone(std::string_view newName) final;
461
462 void DoGenerateColumns() final;
463
464 using Detail::RFieldBase::GenerateValue;
465 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final {
466 return Detail::RFieldValue(
468 this, static_cast<ClusterSize_t*>(where));
469 }
471 return Detail::RFieldValue(true /* captureFlag */,
473 }
474 size_t GetValueSize() const final { return 0; }
475 void CommitCluster() final;
476};
477
478
479/// Template specializations for concrete C++ types
480
481
482template <>
483class RField<ClusterSize_t> : public Detail::RFieldBase {
484public:
485 static std::string TypeName() { return "ROOT::Experimental::ClusterSize_t"; }
487 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
488 RField(RField&& other) = default;
489 RField& operator =(RField&& other) = default;
490 ~RField() = default;
491 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
492
493 void DoGenerateColumns() final;
494
497 }
498 ClusterSize_t *Map(const RClusterIndex &clusterIndex) {
500 }
501
503 template <typename... ArgsT>
505 {
506 return Detail::RFieldValue(
508 this, static_cast<ClusterSize_t*>(where), std::forward<ArgsT>(args)...);
509 }
512 return Detail::RFieldValue(true /* captureFlag */,
514 }
515 size_t GetValueSize() const final { return sizeof(ClusterSize_t); }
516
517 /// Special help for offset fields
518 void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) {
519 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
520 }
521 void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) {
522 fPrincipalColumn->GetCollectionInfo(clusterIndex, collectionStart, size);
523 }
524};
525
526
527template <>
528class RField<bool> : public Detail::RFieldBase {
529public:
530 static std::string TypeName() { return "bool"; }
532 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
533 RField(RField&& other) = default;
534 RField& operator =(RField&& other) = default;
535 ~RField() = default;
536 RFieldBase *Clone(std::string_view newName) final { return new RField(newName); }
537
538 void DoGenerateColumns() final;
539
540 bool *Map(NTupleSize_t globalIndex) {
541 return fPrincipalColumn->Map<bool, EColumnType::kBit>(globalIndex);
542 }
543 bool *Map(const RClusterIndex &clusterIndex) {
544 return fPrincipalColumn->Map<bool, EColumnType::kBit>(clusterIndex);
545 }
546
548 template <typename... ArgsT>
550 {
551 return Detail::RFieldValue(
552 Detail::RColumnElement<bool, EColumnType::kBit>(static_cast<bool*>(where)),
553 this, static_cast<bool*>(where), std::forward<ArgsT>(args)...);
554 }
555 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, false); }
557 return Detail::RFieldValue(true /* captureFlag */,
558 Detail::RColumnElement<bool, EColumnType::kBit>(static_cast<bool*>(where)), this, where);
559 }
560 size_t GetValueSize() const final { return sizeof(bool); }
561};
562
563template <>
564class RField<float> : public Detail::RFieldBase {
565public:
566 static std::string TypeName() { return "float"; }
568 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
569 RField(RField&& other) = default;
570 RField& operator =(RField&& other) = default;
571 ~RField() = default;
572 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
573
574 void DoGenerateColumns() final;
575
576 float *Map(NTupleSize_t globalIndex) {
577 return fPrincipalColumn->Map<float, EColumnType::kReal32>(globalIndex);
578 }
579 float *Map(const RClusterIndex &clusterIndex) {
580 return fPrincipalColumn->Map<float, EColumnType::kReal32>(clusterIndex);
581 }
582
584 template <typename... ArgsT>
586 {
587 return Detail::RFieldValue(
588 Detail::RColumnElement<float, EColumnType::kReal32>(static_cast<float*>(where)),
589 this, static_cast<float*>(where), std::forward<ArgsT>(args)...);
590 }
591 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0.0); }
593 return Detail::RFieldValue(true /* captureFlag */,
594 Detail::RColumnElement<float, EColumnType::kReal32>(static_cast<float*>(where)), this, where);
595 }
596 size_t GetValueSize() const final { return sizeof(float); }
597};
598
599
600template <>
601class RField<double> : public Detail::RFieldBase {
602public:
603 static std::string TypeName() { return "double"; }
605 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
606 RField(RField&& other) = default;
607 RField& operator =(RField&& other) = default;
608 ~RField() = default;
609 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
610
611 void DoGenerateColumns() final;
612
613 double *Map(NTupleSize_t globalIndex) {
614 return fPrincipalColumn->Map<double, EColumnType::kReal64>(globalIndex);
615 }
616 double *Map(const RClusterIndex &clusterIndex) {
617 return fPrincipalColumn->Map<double, EColumnType::kReal64>(clusterIndex);
618 }
619
621 template <typename... ArgsT>
623 {
624 return Detail::RFieldValue(
625 Detail::RColumnElement<double, EColumnType::kReal64>(static_cast<double*>(where)),
626 this, static_cast<double*>(where), std::forward<ArgsT>(args)...);
627 }
628 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0.0); }
630 return Detail::RFieldValue(true /* captureFlag */,
631 Detail::RColumnElement<double, EColumnType::kReal64>(static_cast<double*>(where)), this, where);
632 }
633 size_t GetValueSize() const final { return sizeof(double); }
634};
635
636template <>
637class RField<std::uint8_t> : public Detail::RFieldBase {
638public:
639 static std::string TypeName() { return "std::uint8_t"; }
640 explicit RField(std::string_view name)
641 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
642 RField(RField&& other) = default;
643 RField& operator =(RField&& other) = default;
644 ~RField() = default;
645 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
646
647 void DoGenerateColumns() final;
648
649 std::uint8_t *Map(NTupleSize_t globalIndex) {
650 return fPrincipalColumn->Map<std::uint8_t, EColumnType::kByte>(globalIndex);
651 }
652 std::uint8_t *Map(const RClusterIndex &clusterIndex) {
653 return fPrincipalColumn->Map<std::uint8_t, EColumnType::kByte>(clusterIndex);
654 }
655
657 template <typename... ArgsT>
658 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
659 {
660 return Detail::RFieldValue(
661 Detail::RColumnElement<std::uint8_t, EColumnType::kByte>(static_cast<std::uint8_t*>(where)),
662 this, static_cast<std::uint8_t*>(where), std::forward<ArgsT>(args)...);
663 }
664 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final { return GenerateValue(where, 0); }
665 Detail::RFieldValue CaptureValue(void *where) final {
666 return Detail::RFieldValue(true /* captureFlag */,
667 Detail::RColumnElement<std::uint8_t, EColumnType::kByte>(static_cast<std::uint8_t*>(where)), this, where);
668 }
669 size_t GetValueSize() const final { return sizeof(std::uint8_t); }
670};
671
672template <>
673class RField<std::int32_t> : public Detail::RFieldBase {
674public:
675 static std::string TypeName() { return "std::int32_t"; }
676 explicit RField(std::string_view name)
677 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
678 RField(RField&& other) = default;
679 RField& operator =(RField&& other) = default;
680 ~RField() = default;
681 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
682
683 void DoGenerateColumns() final;
684
685 std::int32_t *Map(NTupleSize_t globalIndex) {
686 return fPrincipalColumn->Map<std::int32_t, EColumnType::kInt32>(globalIndex);
687 }
688 std::int32_t *Map(const RClusterIndex &clusterIndex) {
689 return fPrincipalColumn->Map<std::int32_t, EColumnType::kInt32>(clusterIndex);
690 }
691
693 template <typename... ArgsT>
694 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
695 {
696 return Detail::RFieldValue(
697 Detail::RColumnElement<std::int32_t, EColumnType::kInt32>(static_cast<std::int32_t*>(where)),
698 this, static_cast<std::int32_t*>(where), std::forward<ArgsT>(args)...);
699 }
700 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
701 Detail::RFieldValue CaptureValue(void *where) final {
702 return Detail::RFieldValue(true /* captureFlag */,
703 Detail::RColumnElement<std::int32_t, EColumnType::kInt32>(static_cast<std::int32_t*>(where)), this, where);
704 }
705 size_t GetValueSize() const final { return sizeof(std::int32_t); }
706};
707
708template <>
709class RField<std::uint32_t> : public Detail::RFieldBase {
710public:
711 static std::string TypeName() { return "std::uint32_t"; }
712 explicit RField(std::string_view name)
713 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
714 RField(RField&& other) = default;
715 RField& operator =(RField&& other) = default;
716 ~RField() = default;
717 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
718
719 void DoGenerateColumns() final;
720
721 std::uint32_t *Map(NTupleSize_t globalIndex) {
722 return fPrincipalColumn->Map<std::uint32_t, EColumnType::kInt32>(globalIndex);
723 }
724 std::uint32_t *Map(const RClusterIndex clusterIndex) {
725 return fPrincipalColumn->Map<std::uint32_t, EColumnType::kInt32>(clusterIndex);
726 }
727
729 template <typename... ArgsT>
730 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
731 {
732 return Detail::RFieldValue(
733 Detail::RColumnElement<std::uint32_t, EColumnType::kInt32>(static_cast<std::uint32_t*>(where)),
734 this, static_cast<std::uint32_t*>(where), std::forward<ArgsT>(args)...);
735 }
736 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
737 Detail::RFieldValue CaptureValue(void *where) final {
738 return Detail::RFieldValue(true /* captureFlag */,
739 Detail::RColumnElement<std::uint32_t, EColumnType::kInt32>(static_cast<std::uint32_t*>(where)), this, where);
740 }
741 size_t GetValueSize() const final { return sizeof(std::uint32_t); }
742};
743
744template <>
745class RField<std::uint64_t> : public Detail::RFieldBase {
746public:
747 static std::string TypeName() { return "std::uint64_t"; }
748 explicit RField(std::string_view name)
749 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, true /* isSimple */) {}
750 RField(RField&& other) = default;
751 RField& operator =(RField&& other) = default;
752 ~RField() = default;
753 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
754
755 void DoGenerateColumns() final;
756
757 std::uint64_t *Map(NTupleSize_t globalIndex) {
758 return fPrincipalColumn->Map<std::uint64_t, EColumnType::kInt64>(globalIndex);
759 }
760 std::uint64_t *Map(const RClusterIndex &clusterIndex) {
761 return fPrincipalColumn->Map<std::uint64_t, EColumnType::kInt64>(clusterIndex);
762 }
763
765 template <typename... ArgsT>
766 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
767 {
768 return Detail::RFieldValue(
769 Detail::RColumnElement<std::uint64_t, EColumnType::kInt64>(static_cast<std::uint64_t*>(where)),
770 this, static_cast<std::uint64_t*>(where), std::forward<ArgsT>(args)...);
771 }
772 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
773 Detail::RFieldValue CaptureValue(void *where) final {
774 return Detail::RFieldValue(true /* captureFlag */,
775 Detail::RColumnElement<std::uint64_t, EColumnType::kInt64>(static_cast<std::uint64_t*>(where)), this, where);
776 }
777 size_t GetValueSize() const final { return sizeof(std::uint64_t); }
778};
779
780
781template <>
782class RField<std::string> : public Detail::RFieldBase {
783private:
784 ClusterSize_t fIndex;
785 Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex> fElemIndex;
786
787 void DoAppend(const ROOT::Experimental::Detail::RFieldValue& value) final;
790
791public:
792 static std::string TypeName() { return "std::string"; }
793 explicit RField(std::string_view name)
794 : Detail::RFieldBase(name, TypeName(), ENTupleStructure::kLeaf, false /* isSimple */)
795 , fIndex(0), fElemIndex(&fIndex) {}
796 RField(RField&& other) = default;
797 RField& operator =(RField&& other) = default;
798 ~RField() = default;
799 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
800
801 void DoGenerateColumns() final;
802
803 using Detail::RFieldBase::GenerateValue;
804 template <typename... ArgsT>
805 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
806 {
807 return Detail::RFieldValue(this, static_cast<std::string*>(where), std::forward<ArgsT>(args)...);
808 }
809 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, ""); }
810 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) {
811 auto str = value.Get<std::string>();
812 str->~basic_string(); // TODO(jblomer) C++17 std::destroy_at
813 if (!dtorOnly)
814 free(str);
815 }
816 Detail::RFieldValue CaptureValue(void *where) {
817 return Detail::RFieldValue(true /* captureFlag */, this, where);
818 }
819 size_t GetValueSize() const final { return sizeof(std::string); }
820 size_t GetAlignment() const final { return std::alignment_of<std::string>(); }
821 void CommitCluster() final;
822};
823
824
825template <typename ItemT, std::size_t N>
826class RField<std::array<ItemT, N>> : public RFieldArray {
827 using ContainerT = typename std::array<ItemT, N>;
828public:
829 static std::string TypeName() {
830 return "std::array<" + RField<ItemT>::TypeName() + "," + std::to_string(N) + ">";
831 }
832 explicit RField(std::string_view name)
833 : RFieldArray(name, std::make_unique<RField<ItemT>>(RField<ItemT>::TypeName()), N)
834 {}
835 RField(RField&& other) = default;
836 RField& operator =(RField&& other) = default;
837 ~RField() = default;
838
840 template <typename... ArgsT>
841 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
842 {
843 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
844 }
846 return GenerateValue(where, ContainerT());
847 }
848};
849
850
851#if __cplusplus >= 201703L
852template <typename... ItemTs>
853class RField<std::variant<ItemTs...>> : public RFieldVariant {
854 using ContainerT = typename std::variant<ItemTs...>;
855private:
856 template <typename HeadT, typename... TailTs>
857 static std::string BuildItemTypes()
858 {
859 std::string result = RField<HeadT>::TypeName();
860 if constexpr(sizeof...(TailTs) > 0)
861 result += "," + BuildItemTypes<TailTs...>();
862 return result;
863 }
864
865 template <typename HeadT, typename... TailTs>
866 static std::vector<Detail::RFieldBase *> BuildItemFields(unsigned int index = 0)
867 {
868 std::vector<Detail::RFieldBase *> result;
869 result.emplace_back(new RField<HeadT>("variant" + std::to_string(index)));
870 if constexpr(sizeof...(TailTs) > 0) {
871 auto tailFields = BuildItemFields<TailTs...>(index + 1);
872 result.insert(result.end(), tailFields.begin(), tailFields.end());
873 }
874 return result;
875 }
876
877public:
878 static std::string TypeName() { return "std::variant<" + BuildItemTypes<ItemTs...>() + ">"; }
879 explicit RField(std::string_view name) : RFieldVariant(name, BuildItemFields<ItemTs...>()) {}
880 RField(RField&& other) = default;
881 RField& operator =(RField&& other) = default;
882 ~RField() = default;
883
885 template <typename... ArgsT>
886 ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT&&... args)
887 {
888 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
889 }
891 return GenerateValue(where, ContainerT());
892 }
893};
894#endif
895
896template <typename ItemT>
897class RField<std::vector<ItemT>> : public RFieldVector {
898 using ContainerT = typename std::vector<ItemT>;
899public:
900 static std::string TypeName() { return "std::vector<" + RField<ItemT>::TypeName() + ">"; }
901 explicit RField(std::string_view name)
902 : RFieldVector(name, std::make_unique<RField<ItemT>>(RField<ItemT>::TypeName()))
903 {}
904 RField(RField&& other) = default;
905 RField& operator =(RField&& other) = default;
906 ~RField() = default;
907
909 template <typename... ArgsT>
910 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
911 {
912 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
913 }
915 return GenerateValue(where, ContainerT());
916 }
917 Detail::RFieldValue CaptureValue(void *where) final {
918 return Detail::RFieldValue(true /* captureFlag */, this, where);
919 }
920 size_t GetValueSize() const final { return sizeof(ContainerT); }
921};
922
923// std::vector<bool> is a template specialization and needs special treatment
924template <>
925class RField<std::vector<bool>> : public Detail::RFieldBase {
926private:
928
929protected:
930 void DoAppend(const Detail::RFieldValue& value) final;
931 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
932 void DoGenerateColumns() final;
933
934public:
935 static std::string TypeName() { return "std::vector<bool>"; }
936 explicit RField(std::string_view name);
937 RField(RField&& other) = default;
938 RField& operator =(RField&& other) = default;
939 ~RField() = default;
940 RFieldBase* Clone(std::string_view newName) final { return new RField(newName); }
941
943 template <typename... ArgsT>
944 ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where, ArgsT&&... args)
945 {
946 return Detail::RFieldValue(this, static_cast<std::vector<bool>*>(where), std::forward<ArgsT>(args)...);
947 }
949 return GenerateValue(where, std::vector<bool>());
950 }
951 Detail::RFieldValue CaptureValue(void *where) final {
952 return Detail::RFieldValue(true /* captureFlag */, this, where);
953 }
954 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final;
955
956 size_t GetValueSize() const final { return sizeof(std::vector<bool>); }
957 size_t GetAlignment() const final { return std::alignment_of<std::vector<bool>>(); }
958 void CommitCluster() final { fNWritten = 0; }
959};
960
961
962/**
963 * The RVec type has different layouts depending on the item type, therefore we cannot go with a generic
964 * RVec implementation as we can with std::vector
965 */
966template <typename ItemT>
969private:
970 size_t fItemSize;
972
973protected:
974 void DoAppend(const Detail::RFieldValue& value) final {
975 auto typedValue = value.Get<ContainerT>();
976 auto count = typedValue->size();
977 for (unsigned i = 0; i < count; ++i) {
978 auto itemValue = fSubFields[0]->CaptureValue(&typedValue->data()[i]);
979 fSubFields[0]->Append(itemValue);
980 }
982 fNWritten += count;
983 fColumns[0]->Append(elemIndex);
984 }
985 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final {
986 auto typedValue = value->Get<ContainerT>();
987 ClusterSize_t nItems;
988 RClusterIndex collectionStart;
989 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
990 typedValue->resize(nItems);
991 for (unsigned i = 0; i < nItems; ++i) {
992 auto itemValue = fSubFields[0]->GenerateValue(&typedValue->data()[i]);
993 fSubFields[0]->Read(collectionStart + i, &itemValue);
994 }
995 }
996
997public:
998 RField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
999 : ROOT::Experimental::Detail::RFieldBase(
1000 fieldName, "ROOT::VecOps::RVec<" + itemField->GetType() + ">", ENTupleStructure::kCollection, false)
1001 , fItemSize(itemField->GetValueSize()), fNWritten(0)
1002 {
1003 Attach(std::move(itemField));
1004 }
1006 : RField(name, std::make_unique<RField<ItemT>>(RField<ItemT>::TypeName()))
1007 {
1008 }
1009 RField(RField&& other) = default;
1010 RField& operator =(RField&& other) = default;
1011 ~RField() = default;
1013 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1014 return new RField<ROOT::VecOps::RVec<ItemT>>(newName, std::unique_ptr<Detail::RFieldBase>(newItemField));
1015 }
1016
1017 void DoGenerateColumns() final {
1018 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1019 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1020 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1021 fPrincipalColumn = fColumns[0].get();
1022 }
1023 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final {
1024 auto vec = reinterpret_cast<ContainerT*>(value.GetRawPtr());
1025 auto nItems = vec->size();
1026 for (unsigned i = 0; i < nItems; ++i) {
1027 auto itemValue = fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize));
1028 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1029 }
1030 vec->~RVec();
1031 if (!dtorOnly)
1032 free(vec);
1033 }
1034 void CommitCluster() final { fNWritten = 0; }
1035
1036 static std::string TypeName() { return "ROOT::VecOps::RVec<" + RField<ItemT>::TypeName() + ">"; }
1037
1039 template <typename... ArgsT>
1041 {
1042 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1043 }
1045 return GenerateValue(where, ContainerT());
1046 }
1048 return Detail::RFieldValue(true /* captureFlag */, this, static_cast<ContainerT*>(where));
1049 }
1050 size_t GetValueSize() const final { return sizeof(ContainerT); }
1051 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
1052};
1053
1054/**
1055 * RVec<bool> needs special treatment due to std::vector<bool> sepcialization
1056 */
1057template <>
1060private:
1062
1063protected:
1064 void DoAppend(const Detail::RFieldValue& value) final {
1065 auto typedValue = value.Get<ContainerT>();
1066 auto count = typedValue->size();
1067 for (unsigned i = 0; i < count; ++i) {
1068 bool bval = (*typedValue)[i];
1069 auto itemValue = fSubFields[0]->CaptureValue(&bval);
1070 fSubFields[0]->Append(itemValue);
1071 }
1073 fNWritten += count;
1074 fColumns[0]->Append(elemIndex);
1075 }
1076 void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final {
1077 auto typedValue = value->Get<ContainerT>();
1078 ClusterSize_t nItems;
1079 RClusterIndex collectionStart;
1080 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1081 typedValue->resize(nItems);
1082 for (unsigned i = 0; i < nItems; ++i) {
1083 bool bval = (*typedValue)[i];
1084 auto itemValue = fSubFields[0]->GenerateValue(&bval);
1085 fSubFields[0]->Read(collectionStart + i, &itemValue);
1086 (*typedValue)[i] = bval;
1087 }
1088 }
1089
1090public:
1092 : ROOT::Experimental::Detail::RFieldBase(name, "ROOT::VecOps::RVec<bool>", ENTupleStructure::kCollection, false)
1093 {
1094 Attach(std::make_unique<RField<bool>>("bool"));
1095 }
1096 RField(RField&& other) = default;
1097 RField& operator =(RField&& other) = default;
1098 ~RField() = default;
1100 return new RField<ROOT::VecOps::RVec<bool>>(newName);
1101 }
1102
1103 void DoGenerateColumns() final {
1104 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1105 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1106 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1107 fPrincipalColumn = fColumns[0].get();
1108 }
1109 void DestroyValue(const Detail::RFieldValue& value, bool dtorOnly = false) final {
1110 auto vec = reinterpret_cast<ContainerT*>(value.GetRawPtr());
1111 vec->~RVec();
1112 if (!dtorOnly)
1113 free(vec);
1114 }
1115 void CommitCluster() final { fNWritten = 0; }
1116
1117 static std::string TypeName() { return "ROOT::VecOps::RVec<bool>"; }
1118
1120 template <typename... ArgsT>
1122 {
1123 return Detail::RFieldValue(this, static_cast<ContainerT*>(where), std::forward<ArgsT>(args)...);
1124 }
1126 return GenerateValue(where, ContainerT());
1127 }
1129 return Detail::RFieldValue(true /* captureFlag */, this, static_cast<ContainerT*>(where));
1130 }
1131 size_t GetValueSize() const final { return sizeof(ContainerT); }
1132 size_t GetAlignment() const final { return std::alignment_of<ContainerT>(); }
1133};
1134
1135} // namespace Experimental
1136} // namespace ROOT
1137
1138#endif
ROOT::R::TRInterface & r
Definition: Object.C:4
#define N
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
#define free
Definition: civetweb.c:1539
void Append(const RColumnElementBase &element)
Definition: RColumn.hxx:84
CppT * Map(const NTupleSize_t globalIndex)
Definition: RColumn.hxx:161
void Read(const NTupleSize_t globalIndex, RColumnElementBase *element)
Definition: RColumn.hxx:107
NTupleSize_t GetGlobalIndex(const RClusterIndex &clusterIndex)
Definition: RColumn.hxx:180
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:196
Iterates over the sub fields in depth-first search order.
Definition: RField.hxx:153
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:244
bool operator==(const iterator &rh) const
Definition: RField.hxx:176
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
Definition: RField.hxx:163
bool operator!=(const iterator &rh) const
Definition: RField.hxx:177
RIterator(pointer val, int idxInParent)
Definition: RField.hxx:166
void Append(const RFieldValue &value)
Write the given value into columns. The value object has to be of the same type as the field.
Definition: RField.hxx:211
virtual RFieldValue CaptureValue(void *where)=0
Creates a value from a memory location with an already constructed object.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition: RField.hxx:130
RFieldBase * fParent
Sub fields point to their mother field.
Definition: RField.hxx:132
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:88
virtual void DoAppend(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition: RField.cxx:175
std::size_t GetNRepetitions() const
Definition: RField.hxx:248
virtual void DoGenerateColumns()=0
Creates the backing columns corresponsing to the field type and name.
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:193
virtual RNTupleVersion GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition: RField.hxx:255
int fOrder
First subfield of parentfield has fOrder 1, the next fOrder 2, etc. Value set by RFieldBase::Attach()
Definition: RField.hxx:127
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition: RField.cxx:207
virtual void AcceptVisitor(RNTupleVisitor &visitor, int level) const
Definition: RField.cxx:224
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:241
virtual size_t GetAlignment() const
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:208
virtual size_t GetValueSize() const =0
The number of bytes taken by a value of the appropriate type.
bool fIsSimple
A field on a trivial type that maps as-is to a single column.
Definition: RField.hxx:87
std::string fType
The C++ type captured by this field.
Definition: RField.hxx:81
std::string fName
The field name relative to its parent field.
Definition: RField.hxx:79
virtual void DoReadGlobal(NTupleSize_t globalIndex, RFieldValue *value)
Definition: RField.cxx:179
virtual RNTupleVersion GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition: RField.hxx:253
virtual void TraverseVisitor(RNTupleVisitor &visitor, int level=0) const
Used for the visitor design pattern, see for example RNTupleReader::Print()
Definition: RField.cxx:214
static 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:100
std::size_t fNRepetitions
For fixed sized arrays, the array length.
Definition: RField.hxx:85
RFieldBase(const RFieldBase &)=delete
ENTupleStructure fStructure
The role of this field in the data model structure.
Definition: RField.hxx:83
void Read(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition: RField.hxx:230
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:138
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Definition: RField.cxx:199
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:247
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:222
const RFieldBase * GetParent() const
Definition: RField.hxx:249
virtual RFieldBase * Clone(std::string_view newName)=0
RFieldValue GenerateValue()
Generates a tree value of the field type and allocates new initialized memory according to the type.
Definition: RField.cxx:186
virtual void DoReadInCluster(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition: RField.hxx:147
RColumn * fPrincipalColumn
Points into fColumns.
Definition: RField.hxx:136
static void Connect(DescriptorId_t fieldId, RPageStorage &pageStorage, RFieldBase &field)
Definition: RField.cxx:76
RColumnElementBase fMappedElement
For simple types, the mapped element drills through the layers from the C++ data representation to th...
Definition: RFieldValue.hxx:53
Abstract base class for classes implementing the visitor design pattern.
Common functionality of an ntuple storage for both reading and writing.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Definition: RNTupleUtil.hxx:83
Holds the static meta-data of a column in a tree.
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
Definition: REntry.hxx:42
The generic field for fixed size arrays, which do not need an offset column.
Definition: RField.hxx:361
RFieldArray(RFieldArray &&other)=default
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:384
A field translates read and write calls from/to underlying columns to/from tree values.
Definition: RField.hxx:60
The field for a class with dictionary.
Definition: RField.hxx:307
RFieldClass & operator=(RFieldClass &&other)=default
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.cxx:481
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:497
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:329
void DoAppend(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:449
RFieldClass(std::string_view fieldName, std::string_view className)
Definition: RField.cxx:428
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:502
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:490
RFieldBase * Clone(std::string_view newName) final
Definition: RField.cxx:444
RFieldClass(RFieldClass &&other)=default
void DoReadInCluster(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:470
void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:459
RFieldCollection(RFieldCollection &&other)=default
static std::string TypeName()
Definition: RField.hxx:453
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:474
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:470
std::shared_ptr< RCollectionNTuple > fCollectionNTuple
Save the link to the collection ntuple in order to reset the offset counter when committing the clust...
Definition: RField.hxx:451
A friend of RFieldBase responsible for connecting a field's columns to the physical page storage.
The container field for an ntuple model, which itself has no physical representation.
Definition: RField.hxx:290
RFieldBase * Clone(std::string_view newName)
Definition: RField.cxx:270
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:295
REntry * GenerateEntry()
Generates managed values for the top-level sub fields.
Definition: RField.cxx:281
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:299
void AcceptVisitor(Detail::RNTupleVisitor &visitor, int level) const final
Definition: RField.cxx:290
Detail::RFieldValue CaptureValue(void *) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:298
Detail::RFieldValue GenerateValue(void *)
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:297
Represents transient storage of simple or complex C++ values.
Definition: RFieldValue.hxx:28
The generic field for a (nested) std::vector<Type> except for std::vector<bool>
Definition: RField.hxx:333
RFieldVector & operator=(RFieldVector &&other)=default
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:355
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:354
void DoAppend(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:526
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:586
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.cxx:554
void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:539
RFieldVector(RFieldVector &&other)=default
RFieldBase * Clone(std::string_view newName) final
Definition: RField.cxx:520
RFieldVector(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.cxx:511
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:567
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:581
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:491
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Definition: RField.hxx:521
ClusterSize_t * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:498
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:511
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:515
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition: RField.hxx:518
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:504
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:510
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:1047
void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.hxx:985
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
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:1050
typename ROOT::VecOps::RVec< ItemT > ContainerT
Definition: RField.hxx:968
RField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.hxx:998
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:1051
void DoAppend(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.hxx:974
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:1017
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:1040
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:1034
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:1012
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:1023
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:1109
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:1099
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:1128
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:1121
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:1125
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:1132
void DoGenerateColumns() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:1103
void DoAppend(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.hxx:1064
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:1115
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:1131
typename ROOT::VecOps::RVec< bool > ContainerT
Definition: RField.hxx:1059
void DoReadGlobal(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.hxx:1076
RField(std::string_view name)
Definition: RField.hxx:531
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:560
static std::string TypeName()
Definition: RField.hxx:530
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:549
RField(RField &&other)=default
bool * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:543
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:536
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:556
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:555
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:629
double * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:616
RField(std::string_view name)
Definition: RField.hxx:604
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:609
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:622
RField(RField &&other)=default
static std::string TypeName()
Definition: RField.hxx:603
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:633
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:628
static std::string TypeName()
Definition: RField.hxx:566
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where) final
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:591
RField(RField &&other)=default
RField(std::string_view name)
Definition: RField.hxx:567
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:585
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:596
float * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:579
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:572
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:592
Classes with dictionaries that can be inspected by TClass.
Definition: RField.hxx:428
RField(std::string_view name)
Definition: RField.hxx:431
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:440
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:444
static std::string TypeName()
Definition: RField.hxx:430
For forward and backward compatibility, attach version information to the consitituents of the file f...
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition: RVec.hxx:274
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
basic_string_view< char > string_view
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:43
RClusterSize ClusterSize_t
Definition: RNTupleUtil.hxx:58
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
Definition: RNTupleUtil.hxx:33
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
Definition: RNTupleUtil.hxx:79
std::string GetDemangledTypeName(const std::type_info &)
Returns a string with the demangled and normalized name for the given type.
double T(double x)
Definition: ChebyshevPol.h:34
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:909
VSD Structures.
Definition: StringConv.hxx:21
Describes where the field is located inside the ntuple.
Definition: RField.hxx:89
int fLevel
Tells how deep the field is in the ntuple. Rootfield has fLevel 0, direct subfield of Rootfield has f...
Definition: RField.hxx:92
int GetLevel(const RFieldBase *field=nullptr) const
Definition: RField.hxx:109
int GetOrder(const RFieldBase *field=nullptr) const
Definition: RField.hxx:120
int fNumSiblingFields
The field itself is also included in this number.
Definition: RField.hxx:96
int fOrder
First subfield of parentfield has fOrder 1, the next fOrder 2, etc. Value set by RFieldBase::fOrder.
Definition: RField.hxx:94
int GetNumSiblings(const RFieldBase *field=nullptr) const
Definition: RField.hxx:104
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:46