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