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