Logo ROOT   master
Reference Guide
RField.hxx
Go to the documentation of this file.
1 /// \file ROOT/RField.hxx
2 /// \ingroup NTuple ROOT7
3 /// \author Jakob Blomer <jblomer@cern.ch>
4 /// \date 2018-10-09
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #ifndef ROOT7_RField
17 #define ROOT7_RField
18 
19 #include <ROOT/RColumn.hxx>
20 #include <ROOT/RColumnElement.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 
46 class TClass;
47 
48 namespace ROOT {
49 namespace Experimental {
50 
51 class RCollectionNTuple;
52 class REntry;
53 class RFieldCollection;
54 class RNTupleModel;
55 
56 namespace Detail {
57 
58 class RFieldFuse;
59 class RFieldVisitor;
60 class 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 
68 A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
69 type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
70 mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
71 The field knows based on its type and the field name the type(s) and name(s) of the columns.
72 */
73 // clang-format on
74 class RFieldBase {
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 
78 private:
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
88  bool fIsSimple;
89 
90 protected:
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 
113 public:
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.
143  RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple,
144  std::size_t nRepetitions = 0);
145  RFieldBase(const RFieldBase&) = delete;
146  RFieldBase(RFieldBase&&) = default;
147  RFieldBase& operator =(const RFieldBase&) = delete;
148  RFieldBase& operator =(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 a tree value 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 
237 Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
238 can be read or written.
239 */
240 // clang-format on
241 class RFieldFuse {
242 public:
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
252 public:
253  RFieldRoot() : Detail::RFieldBase("", "", ENTupleStructure::kRecord, false /* isSimple */) { }
254  RFieldBase* Clone(std::string_view newName);
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
269 private:
271  std::size_t fMaxAlignment = 1;
272 
273 protected:
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 
278 public:
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>
298 private:
299  std::size_t fItemSize;
301 
302 protected:
303  void AppendImpl(const Detail::RFieldValue& value) final;
304  void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
305 
306 public:
307  RFieldVector(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField);
308  RFieldVector(RFieldVector&& other) = default;
309  RFieldVector& operator =(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
334 private:
335  std::size_t fItemSize;
336  std::size_t fArrayLength;
337 
338 protected:
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 
343 public:
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
364 class RFieldVariant : public Detail::RFieldBase {
365 private:
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 
377 protected:
378  void AppendImpl(const Detail::RFieldValue& value) final;
379  void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
380 
381 public:
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
402 template <typename T, typename=void>
403 class RField : public RFieldClass {
404 public:
405  static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
406  RField(std::string_view name) : RFieldClass(name, TypeName()) {
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  }
419  ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, T()); }
420 };
421 
422 
424 private:
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;
427 public:
428  static std::string TypeName() { return ":RFieldCollection:"; }
429  RFieldCollection(std::string_view name,
430  std::shared_ptr<RCollectionNTuple> collectionNTuple,
431  std::unique_ptr<RNTupleModel> collectionModel);
432  RFieldCollection(RFieldCollection&& other) = default;
433  RFieldCollection& operator =(RFieldCollection&& other) = default;
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(
442  Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex>(static_cast<ClusterSize_t*>(where)),
443  this, static_cast<ClusterSize_t*>(where));
444  }
445  Detail::RFieldValue CaptureValue(void* where) final {
446  return Detail::RFieldValue(true /* captureFlag */,
447  Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex>(static_cast<ClusterSize_t*>(where)), this, where);
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 
457 template <>
458 class RField<ClusterSize_t> : public Detail::RFieldBase {
459 public:
460  static std::string TypeName() { return "ROOT::Experimental::ClusterSize_t"; }
461  explicit RField(std::string_view name)
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 
468  void GenerateColumnsImpl() final;
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(
482  Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex>(static_cast<ClusterSize_t*>(where)),
483  this, static_cast<ClusterSize_t*>(where), std::forward<ArgsT>(args)...);
484  }
485  ROOT::Experimental::Detail::RFieldValue GenerateValue(void* where) final { return GenerateValue(where, 0); }
486  Detail::RFieldValue CaptureValue(void *where) final {
487  return Detail::RFieldValue(true /* captureFlag */,
488  Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex>(static_cast<ClusterSize_t*>(where)), this, where);
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 
503 template <>
504 class RField<bool> : public Detail::RFieldBase {
505 public:
506  static std::string TypeName() { return "bool"; }
507  explicit RField(std::string_view name)
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); }
532  Detail::RFieldValue CaptureValue(void *where) final {
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 
540 template <>
541 class RField<float> : public Detail::RFieldBase {
542 public:
543  static std::string TypeName() { return "float"; }
544  explicit RField(std::string_view name)
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); }
569  Detail::RFieldValue CaptureValue(void *where) final {
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 
578 template <>
580 public:
581  static std::string TypeName() { return "double"; }
582  explicit RField(std::string_view name)
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); }
607  Detail::RFieldValue CaptureValue(void *where) final {
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 
615 template <>
616 class RField<std::uint8_t> : public Detail::RFieldBase {
617 public:
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 
652 template <>
653 class RField<std::int32_t> : public Detail::RFieldBase {
654 public:
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 
689 template <>
690 class RField<std::uint32_t> : public Detail::RFieldBase {
691 public:
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 
726 template <>
727 class RField<std::uint64_t> : public Detail::RFieldBase {
728 public:
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 
764 template <>
765 class RField<std::string> : public Detail::RFieldBase {
766 private:
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 
774 public:
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 
809 template <typename ItemT, std::size_t N>
810 class RField<std::array<ItemT, N>> : public RFieldArray {
811  using ContainerT = typename std::array<ItemT, N>;
812 public:
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
836 template <typename... ItemTs>
837 class RField<std::variant<ItemTs...>> : public RFieldVariant {
838  using ContainerT = typename std::variant<ItemTs...>;
839 private:
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 
861 public:
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 
880 template <typename ItemT>
881 class RField<std::vector<ItemT>> : public RFieldVector {
882  using ContainerT = typename std::vector<ItemT>;
883 public:
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
908 template <>
909 class RField<std::vector<bool>> : public Detail::RFieldBase {
910 private:
911  ClusterSize_t fNWritten{0};
912 
913 protected:
914  void AppendImpl(const Detail::RFieldValue& value) final;
915  void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final;
916  void GenerateColumnsImpl() final;
917 
918 public:
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  */
958 template <typename ItemT>
959 class RField<ROOT::VecOps::RVec<ItemT>> : public Detail::RFieldBase {
961 private:
962  size_t fItemSize;
964 
965 protected:
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 
989 public:
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  }
997  explicit RField(std::string_view name)
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;
1004  RFieldBase* Clone(std::string_view newName) final {
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  }
1039  Detail::RFieldValue CaptureValue(void *where) final {
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  */
1049 template <>
1050 class RField<ROOT::VecOps::RVec<bool>> : public Detail::RFieldBase {
1052 private:
1053  ClusterSize_t fNWritten{0};
1054 
1055 protected:
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 
1082 public:
1083  RField(std::string_view name)
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;
1091  RFieldBase* Clone(std::string_view newName) final {
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  }
1120  Detail::RFieldValue CaptureValue(void *where) final {
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
The container field for an ntuple model, which itself has no physical representation.
Definition: RField.hxx:251
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:587
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:150
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
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:319
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:536
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:1107
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set ...
Definition: REntry.hxx:42
Holds the static meta-data of a column in a tree
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:479
RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source...
Definition: RField.cxx:88
RFieldArray & operator=(RFieldArray &&other)=default
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:486
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:415
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition: RField.hxx:326
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:206
Detail::RFieldValue GenerateValue(void *)
Generates a tree value in a given location of size at least GetValueSize().
Definition: RField.hxx:258
Returns the available number of logical cores.
Definition: StringConv.hxx:21
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:854
RField(std::string_view name)
Definition: RField.hxx:406
Represents transient storage of simple or complex C++ values.
Definition: RFieldValue.hxx:28
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:445
RFieldBase * Clone(std::string_view newName) final
Definition: RField.cxx:780
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
NTupleSize_t GetNElements() const
Definition: RField.hxx:215
void Read(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition: RField.hxx:195
RFieldClass & operator=(RFieldClass &&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:531
double T(double x)
Definition: ChebyshevPol.h:34
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:1113
virtual RNTupleVersion GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
Definition: RField.hxx:221
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
A field translates read and write calls from/to underlying columns to/from tree values ...
Definition: RField.hxx:60
virtual void ReadInClusterImpl(const RClusterIndex &clusterIndex, RFieldValue *value)
Definition: RField.hxx:109
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.hxx:1068
typename ROOT::VecOps::RVec< bool > ContainerT
Definition: RField.hxx:1051
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system...
Definition: RNTupleUtil.hxx:32
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:843
RFieldBase & operator=(const RFieldBase &)=delete
#define N
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
Definition: RNTupleUtil.hxx:78
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:42
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition: RField.hxx:92
The generic field for fixed size arrays, which do not need an offset column.
Definition: RField.hxx:333
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
STL namespace.
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:466
std::size_t GetNRepetitions() const
Definition: RField.hxx:214
typename ROOT::VecOps::RVec< ItemT > ContainerT
Definition: RField.hxx:960
RFieldBase * Clone(std::string_view newName) final
Definition: RField.cxx:500
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:515
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:615
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:560
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size) const
Definition: RField.hxx:323
double * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:594
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:532
virtual RFieldBase * Clone(std::string_view newName)=0
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.hxx:977
void Append(const RColumnElementBase &element)
Definition: RColumn.hxx:83
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:803
RColumnElementBase fMappedElement
For simple types, the mapped element drills through the layers from the C++ data representation to th...
Definition: RFieldValue.hxx:53
The field for a class with dictionary.
Definition: RField.hxx:268
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:449
static std::string TypeName()
Definition: RField.hxx:405
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:569
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
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:549
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:1043
const RFieldBase * GetParent() const
Definition: RField.hxx:216
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:45
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:526
RFieldArray(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
Definition: RField.cxx:770
RField(std::string_view name)
Definition: RField.hxx:544
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:1091
REntry * GenerateEntry()
Generates managed values for the top-level sub fields.
Definition: RField.cxx:291
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:794
bool fIsSimple
A field on a trivial type that maps as-is to a single column.
Definition: RField.hxx:88
RFieldBase * fParent
Sub fields point to their mother field.
Definition: RField.hxx:94
RField(std::string_view name)
Definition: RField.hxx:582
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:254
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.cxx:813
Classes with dictionaries that can be inspected by TClass.
Definition: RField.hxx:403
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:643
static RFieldBase * Create(const std::string &fieldName, const std::string &typeName)
Factory method to resurrect a field from the stored on-disk type information.
Definition: RField.cxx:100
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:200
static std::string TypeName()
Definition: RField.hxx:428
Common functionality of an ntuple storage for both reading and writing
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 "std::vector"-like collection of values implementing handy operation to analyse them ...
Definition: RVec.hxx:55
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.cxx:630
RField(std::string_view name)
Definition: RField.hxx:507
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
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:357
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
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:663
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:1009
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:1120
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:1123
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
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual void AcceptVisitor(RFieldVisitor &visitor) const
Definition: RField.cxx:232
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition: RField.cxx:224
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:193
RFieldClass(std::string_view fieldName, std::string_view className)
Definition: RField.cxx:484
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:574
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:553
ClusterSize_t * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:473
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:1026
float * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:556
ENTupleStructure fStructure
The role of this field in the data model structure.
Definition: RField.hxx:84
Detail::RFieldValue CaptureValue(void *) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:259
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.hxx:1056
RFieldValue GenerateValue()
Generates a tree value of the field type and allocates new initialized memory according to the type...
Definition: RField.cxx:186
virtual RNTupleVersion GetTypeVersion() const
Indicates an evolution of the C++ type itself.
Definition: RField.hxx:223
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:300
The generic field for a (nested) std::vector<Type> except for std::vector<bool>
Definition: RField.hxx:297
virtual RFieldValue CaptureValue(void *where)=0
Creates a value from a memory location with an already constructed object.
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:1042
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value)
Definition: RField.cxx:179
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:256
Iterates over the sub tree of fields in depth-first search order.
Definition: RField.hxx:115
RColumn * fPrincipalColumn
Points into fColumns.
Definition: RField.hxx:98
void Read(const NTupleSize_t globalIndex, RColumnElementBase *element)
Definition: RColumn.hxx:106
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
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.cxx:537
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:1039
ENTupleStructure GetStructure() const
Definition: RField.hxx:213
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:358
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&#39;s coordinates...
Definition: RColumn.hxx:196
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:786
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:490
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:675
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.hxx:607
void GetCollectionInfo(const RClusterIndex &clusterIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Definition: RField.hxx:496
virtual size_t GetAlignment() const
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:174
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition: RField.cxx:579
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
static std::string TypeName()
Definition: RField.hxx:543
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition: RField.hxx:1095
int type
Definition: TGX11.cxx:120
#define free
Definition: civetweb.c:1539
virtual void AppendImpl(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition: RField.cxx:175
std::string fType
The C++ type captured by this field.
Definition: RField.hxx:82
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:1032
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:320
std::vector< const RFieldBase * > GetSubFields() const
Definition: RField.cxx:214
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
Definition: RField.hxx:125
RClusterSize ClusterSize_t
Definition: RNTupleUtil.hxx:57
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:573
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:562
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:657
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:602
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition: RField.cxx:205
NTupleSize_t GetNElements() const
Definition: RColumn.hxx:229
RFieldBase * Clone(std::string_view newName)
Definition: RField.cxx:280
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:909
Binding & operator=(OUT(*fun)(void))
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:611
bool * Map(const RClusterIndex &clusterIndex)
Definition: RField.hxx:519
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:680
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:260
RFieldVector(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.cxx:587
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
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:1124
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:505
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:600
Abstract base class for classes implementing the visitor design pattern.
NTupleSize_t GetGlobalIndex(const RClusterIndex &clusterIndex)
Definition: RColumn.hxx:180
static std::string TypeName()
Definition: RField.hxx:581
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:292
For forward and backward compatibility, attach version information to the consitituents of the file f...
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:512
std::string GetDemangledTypeName(const std::type_info &)
Returns a string with the demangled and normalized name for the given type.
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:837
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition: RField.hxx:493
static std::string TypeName()
Definition: RField.hxx:506
std::size_t fNRepetitions
For fixed sized arrays, the array length.
Definition: RField.hxx:86
RFieldVector & operator=(RFieldVector &&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
ROOT::Experimental::Detail::RFieldValue GenerateValue(void *where, ArgsT &&... args)
Definition: RField.hxx:525
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.hxx:966
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Definition: RNTupleUtil.hxx:82
RFieldBase * Clone(std::string_view newName) final
Definition: RField.hxx:1004
RFieldBase * Clone(std::string_view newName) final
Definition: RField.cxx:596
char name[80]
Definition: TGX11.cxx:109
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:546
std::string fName
The field name relative to its parent field.
Definition: RField.hxx:80
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type and name.
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:826
static void Connect(DescriptorId_t fieldId, RPageStorage &pageStorage, RFieldBase &field)
Definition: RField.cxx:76
RField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.hxx:990