Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RFieldBase.hxx
Go to the documentation of this file.
1/// \file ROOT/RFieldBase.hxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-09
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#ifndef ROOT_RFieldBase
15#define ROOT_RFieldBase
16
17#include <ROOT/RColumn.hxx>
19#include <ROOT/RNTupleRange.hxx>
20#include <ROOT/RNTupleUtil.hxx>
21
22#include <cstddef>
23#include <functional>
24#include <iterator>
25#include <memory>
26#include <new>
27#include <string>
28#include <string_view>
29#include <vector>
30
31namespace ROOT {
32
33class RFieldBase;
34class RClassField;
35
36namespace Detail {
37class RFieldVisitor;
38} // namespace Detail
39
40namespace Experimental {
41
42class RNTupleJoinProcessor;
43
44namespace Detail {
45class RRawPtrWriteEntry;
46} // namespace Detail
47
48} // namespace Experimental
49
50namespace Internal {
51
52class RPageSink;
53class RPageSource;
54struct RFieldCallbackInjector;
55struct RFieldRepresentationModifier;
56
57// TODO(jblomer): find a better way to not have these methods in the RFieldBase public API
58void CallFlushColumnsOnField(RFieldBase &);
59void CallCommitClusterOnField(RFieldBase &);
63CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options,
65
66} // namespace Internal
67
68// clang-format off
69/**
70\class ROOT::RFieldBase
71\ingroup NTuple
72\brief A field translates read and write calls from/to underlying columns to/from tree values
73
74A field is a serializable C++ type or a container for a collection of subfields. The RFieldBase and its
75type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
76mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
77The field knows based on its type and the field name the type(s) and name(s) of the columns.
78
79Note: the class hierarchy starting at RFieldBase is not meant to be extended by user-provided child classes.
80This is and can only be partially enforced through C++.
81*/
82// clang-format on
84 friend class ROOT::RClassField; // to mark members as artificial
85 friend class ROOT::Experimental::RNTupleJoinProcessor; // needs ConstructValue
86 friend class ROOT::Experimental::Detail::RRawPtrWriteEntry; // to call Append()
87 friend struct ROOT::Internal::RFieldCallbackInjector; // used for unit tests
88 friend struct ROOT::Internal::RFieldRepresentationModifier; // used for unit tests
94 Internal::CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName,
95 const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc,
97
98 using ReadCallback_t = std::function<void(void *)>;
99
100protected:
101 /// A functor to release the memory acquired by CreateValue() (memory and constructor).
102 /// This implementation works for types with a trivial destructor. More complex fields implement a derived deleter.
103 /// The deleter is operational without the field object and thus can be used to destruct/release a value after
104 /// the field has been destructed.
105 class RDeleter {
106 public:
107 virtual ~RDeleter() = default;
108 virtual void operator()(void *objPtr, bool dtorOnly)
109 {
110 if (!dtorOnly)
111 operator delete(objPtr);
112 }
113 };
114
115 /// A deleter for templated RFieldBase descendents where the value type is known.
116 template <typename T>
117 class RTypedDeleter : public RDeleter {
118 public:
119 void operator()(void *objPtr, bool dtorOnly) final
120 {
121 std::destroy_at(static_cast<T *>(objPtr));
123 }
124 };
125
126 // We cannot directly use RFieldBase::RDeleter as a shared pointer deleter due to splicing. We use this
127 // wrapper class to store a polymorphic pointer to the actual deleter.
129 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
130 void operator()(void *objPtr) { fDeleter->operator()(objPtr, false /* dtorOnly*/); }
131 explicit RSharedPtrDeleter(std::unique_ptr<RFieldBase::RDeleter> deleter) : fDeleter(std::move(deleter)) {}
132 };
133
134public:
135 static constexpr std::uint32_t kInvalidTypeVersion = -1U;
136 enum {
137 /// No constructor needs to be called, i.e. any bit pattern in the allocated memory represents a valid type
138 /// A trivially constructible field has a no-op ConstructValue() implementation
140 /// The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
142 /// A field of a fundamental type that can be directly mapped via RField<T>::Map(), i.e. maps as-is to a single
143 /// column
145 /// The TClass checksum is set and valid
147 /// This field is an instance of RInvalidField and can be safely `static_cast` to it
149 /// This field is a user defined type that was missing dictionaries and was reconstructed from the on-disk
150 /// information
152
153 /// Shorthand for types that are both trivially constructible and destructible
155 };
156
157 using ColumnRepresentation_t = std::vector<ROOT::ENTupleColumnType>;
158
159 /// During its lifetime, a field undergoes the following possible state transitions:
160 ///
161 /// [*] --> Unconnected --> ConnectedToSink ----
162 /// | | |
163 /// | --> ConnectedToSource ---> [*]
164 /// | |
165 /// -------------------------------
166 enum class EState {
170 };
171
172 // clang-format off
173 /**
174 \class ROOT::RFieldBase::RColumnRepresentations
175 \ingroup NTuple
176 \brief The list of column representations a field can have.
177
178 Some fields have multiple possible column representations, e.g. with or without split encoding.
179 All column representations supported for writing also need to be supported for reading. In addition,
180 fields can support extra column representations for reading only, e.g. a 64bit integer reading from a
181 32bit column.
182 The defined column representations must be supported by corresponding column packing/unpacking implementations,
183 i.e. for the example above, the unpacking of 32bit ints to 64bit pages must be implemented in RColumnElement.hxx
184 */
185 // clang-format on
187 public:
188 /// A list of column representations
189 using Selection_t = std::vector<ColumnRepresentation_t>;
190
193
194 /// The first column list from `fSerializationTypes` is the default for writing.
198
199 private:
201 /// The union of the serialization types and the deserialization extra types passed during construction.
202 /// Duplicates the serialization types list but the benefit is that GetDeserializationTypes() does not need to
203 /// compile the list.
205 }; // class RColumnRepresentations
206
207 class RValue;
208 class RBulk;
209
210private:
211 /// The field name relative to its parent field
212 std::string fName;
213 /// The C++ type captured by this field
214 std::string fType;
215 /// The role of this field in the data model structure
217 /// For fixed sized arrays, the array length
218 std::size_t fNRepetitions;
219 /// A field qualifies as simple if it is mappable (which implies it has a single principal column),
220 /// and it is not an artificial field and has no post-read callback
222 /// A field that is not backed on disk but computed, e.g. a default-constructed missing field or
223 /// a field whose data is created by I/O customization rules. Subfields of artificial fields are
224 /// artificial, too.
225 bool fIsArtificial = false;
226 /// When the columns are connected to a page source or page sink, the field represents a field id in the
227 /// corresponding RNTuple descriptor. This on-disk ID is set in RPageSink::Create() for writing and by
228 /// RFieldDescriptor::CreateField() when recreating a field / model from the stored descriptor.
230 /// Free text set by the user
231 std::string fDescription;
232 /// Changed by ConnectTo[Sink,Source], reset by Clone()
234
236 {
237 for (const auto &func : fReadCallbacks)
238 func(target);
239 }
240
241 /// Translate an entry index to a column element index of the principal column and vice versa. These functions
242 /// take into account the role and number of repetitions on each level of the field hierarchy as follows:
243 /// - Top level fields: element index == entry index
244 /// - Record fields propagate their principal column index to the principal columns of direct descendant fields
245 /// - Collection and variant fields set the principal column index of their children to 0
246 ///
247 /// The column element index also depends on the number of repetitions of each field in the hierarchy, e.g., given a
248 /// field with type `std::array<std::array<float, 4>, 2>`, this function returns 8 for the innermost field.
250
251 /// Flushes data from active columns
252 void FlushColumns();
253 /// Flushes data from active columns to disk and calls CommitClusterImpl()
254 void CommitCluster();
255 /// Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
256 /// can be read or written. In order to find the field in the page storage, the field's on-disk ID has to be set.
257 /// \param firstEntry The global index of the first entry with on-disk data for the connected field
259 /// Connects the field and its subfield tree to the given page source. Once connected, data can be read.
260 /// Only unconnected fields may be connected, i.e. the method is not idempotent. The field ID has to be set prior to
261 /// calling this function. For subfields, a field ID may or may not be set. If the field ID is unset, it will be
262 /// determined using the page source descriptor, based on the parent field ID and the subfield name.
264
266 {
267 fIsSimple = false;
268 fIsArtificial = true;
269 for (auto &field : fSubfields) {
270 field->SetArtificial();
271 }
272 }
273
274protected:
275 struct RBulkSpec;
276
277 /// Collections and classes own subfields
278 std::vector<std::unique_ptr<RFieldBase>> fSubfields;
279 /// Subfields point to their mother field
281 /// All fields that have columns have a distinct main column. E.g., for simple fields (`float`, `int`, ...), the
282 /// principal column corresponds to the field type. For collection fields except fixed-sized arrays,
283 /// the main column is the offset field. Class fields have no column of their own.
284 /// When reading, points to any column of the column team of the active representation. Usually, this is just
285 /// the first column.
286 /// When writing, points to the first column index of the currently active (not suppressed) column representation.
288 /// Some fields have a second column in its column representation. In this case, `fAuxiliaryColumn` points into
289 /// `fAvailableColumns` to the column that immediately follows the column `fPrincipalColumn` points to.
291 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
292 /// Contains all columns of all representations in order of representation and column index.
293 std::vector<std::unique_ptr<ROOT::Internal::RColumn>> fAvailableColumns;
294 /// Properties of the type that allow for optimizations of collections of that type
295 std::uint32_t fTraits = 0;
296 /// A typedef or using name that was used when creating the field
297 std::string fTypeAlias;
298 /// List of functions to be called after reading a value
299 std::vector<ReadCallback_t> fReadCallbacks;
300 /// C++ type version cached from the descriptor after a call to ConnectPageSource()
302 /// TClass checksum cached from the descriptor after a call to ConnectPageSource(). Only set
303 /// for classes with dictionaries.
304 std::uint32_t fOnDiskTypeChecksum = 0;
305 /// Pointers into the static vector returned by RColumnRepresentations::GetSerializationTypes() when
306 /// SetColumnRepresentatives() is called. Otherwise (if empty) GetColumnRepresentatives() returns a vector
307 /// with a single element, the default representation. Always empty for artificial fields.
308 std::vector<std::reference_wrapper<const ColumnRepresentation_t>> fColumnRepresentatives;
309
310 /// Factory method for the field's type. The caller owns the returned pointer
311 void *CreateObjectRawPtr() const;
312
313 /// Helpers for generating columns. We use the fact that most fields have the same C++/memory types
314 /// for all their column representations.
315 /// Where possible, we call the helpers not from the header to reduce compilation time.
316 template <std::uint32_t ColumnIndexT, typename HeadT, typename... TailTs>
318 {
320 auto &column = fAvailableColumns.emplace_back(
321 ROOT::Internal::RColumn::Create<HeadT>(representation[ColumnIndexT], ColumnIndexT, representationIndex));
322
323 // Initially, the first two columns become the active column representation
325 fPrincipalColumn = column.get();
326 } else if (representationIndex == 0 && !fAuxiliaryColumn) {
327 fAuxiliaryColumn = column.get();
328 } else {
329 // We currently have no fields with more than 2 columns in its column representation
331 }
332
333 if constexpr (sizeof...(TailTs))
335 }
336
337 /// For writing, use the currently set column representative
338 template <typename... ColumnCppTs>
340 {
341 if (fColumnRepresentatives.empty()) {
342 fAvailableColumns.reserve(sizeof...(ColumnCppTs));
343 GenerateColumnsImpl<0, ColumnCppTs...>(GetColumnRepresentations().GetSerializationDefault(), 0);
344 } else {
345 const auto N = fColumnRepresentatives.size();
346 fAvailableColumns.reserve(N * sizeof...(ColumnCppTs));
347 for (unsigned i = 0; i < N; ++i) {
349 }
350 }
351 }
352
353 /// For reading, use the on-disk column list
354 template <typename... ColumnCppTs>
356 {
357 std::uint16_t representationIndex = 0;
358 do {
360 if (onDiskTypes.empty())
361 break;
364 if (representationIndex > 0) {
365 for (std::size_t i = 0; i < sizeof...(ColumnCppTs); ++i) {
366 fAvailableColumns[i]->MergeTeams(
367 *fAvailableColumns[representationIndex * sizeof...(ColumnCppTs) + i].get());
368 }
369 }
371 } while (true);
372 }
373
374 /// Implementations in derived classes should return a static RColumnRepresentations object. The default
375 /// implementation does not attach any columns to the field.
376 virtual const RColumnRepresentations &GetColumnRepresentations() const;
377 /// Implementations in derived classes should create the backing columns corresponding to the field type for
378 /// writing. The default implementation does not attach any columns to the field.
379 virtual void GenerateColumns() {}
380 /// Implementations in derived classes should create the backing columns corresponding to the field type for reading.
381 /// The default implementation does not attach any columns to the field. The method should check, using the page
382 /// source and `fOnDiskId`, if the column types match and throw if they don't.
383 virtual void GenerateColumns(const ROOT::RNTupleDescriptor & /*desc*/) {}
384 /// Returns the on-disk column types found in the provided descriptor for `fOnDiskId` and the given
385 /// representation index. If there are no columns for the given representation index, return an empty
386 /// ColumnRepresentation_t list. Otherwise, the returned reference points into the static array returned by
387 /// GetColumnRepresentations().
388 /// Throws an exception if the types on disk don't match any of the deserialization types from
389 /// GetColumnRepresentations().
392 /// When connecting a field to a page sink, the field's default column representation is subject
393 /// to adjustment according to the write options. E.g., if compression is turned off, encoded columns
394 /// are changed to their unencoded counterparts.
396
397 /// Called by Clone(), which additionally copies the on-disk ID
398 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
399
400 /// Constructs value in a given location of size at least GetValueSize(). Called by the base class' CreateValue().
401 virtual void ConstructValue(void *where) const = 0;
402 virtual std::unique_ptr<RDeleter> GetDeleter() const { return std::make_unique<RDeleter>(); }
403 /// Allow derived classes to call ConstructValue(void *) and GetDeleter() on other (sub)fields.
404 static void CallConstructValueOn(const RFieldBase &other, void *where) { other.ConstructValue(where); }
405 static std::unique_ptr<RDeleter> GetDeleterOf(const RFieldBase &other) { return other.GetDeleter(); }
406
407 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
408 /// column type exists.
409 virtual std::size_t AppendImpl(const void *from);
410 virtual void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to);
411 virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to);
412
413 /// Write the given value into columns. The value object has to be of the same type as the field.
414 /// Returns the number of uncompressed bytes written.
415 std::size_t Append(const void *from);
416
417 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
418 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
419 /// to a single column and has no read callback.
421 {
422 if (fIsSimple)
423 return (void)fPrincipalColumn->Read(globalIndex, to);
424
425 if (!fIsArtificial) {
428 else
430 }
431 if (R__unlikely(!fReadCallbacks.empty()))
433 }
434
435 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
436 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
437 /// to a single column and has no read callback.
439 {
440 if (fIsSimple)
441 return (void)fPrincipalColumn->Read(localIndex, to);
442
443 if (!fIsArtificial) {
446 else
448 }
449 if (R__unlikely(!fReadCallbacks.empty()))
451 }
452
453 /// General implementation of bulk read. Loop over the required range and read values that are required
454 /// and not already present. Derived classes may implement more optimized versions of this method.
455 /// See ReadBulk() for the return value.
456 virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec);
457
458 /// Returns the number of newly available values, that is the number of bools in `bulkSpec.fMaskAvail` that
459 /// flipped from false to true. As a special return value, `kAllSet` can be used if all values are read
460 /// independent from the masks.
461 std::size_t ReadBulk(const RBulkSpec &bulkSpec);
462
463 /// Allow derived classes to call Append() and Read() on other (sub)fields.
464 static std::size_t CallAppendOn(RFieldBase &other, const void *from) { return other.Append(from); }
467 static void *CallCreateObjectRawPtrOn(RFieldBase &other) { return other.CreateObjectRawPtr(); }
468
469 /// Fields may need direct access to the principal column of their subfields, e.g. in RRVecField::ReadBulk()
470 static ROOT::Internal::RColumn *GetPrincipalColumnOf(const RFieldBase &other) { return other.fPrincipalColumn; }
471
472 /// Set a user-defined function to be called after reading a value, giving a chance to inspect and/or modify the
473 /// value object.
474 /// Returns an index that can be used to remove the callback.
475 size_t AddReadCallback(ReadCallback_t func);
476 void RemoveReadCallback(size_t idx);
477
478 // Perform housekeeping tasks for global to cluster-local index translation
479 virtual void CommitClusterImpl() {}
480 // The field can indicate that it needs to register extra type information in the on-disk schema.
481 // In this case, a callback from the page sink to the field will be registered on connect, so that the
482 // extra type information can be collected when the dataset gets committed.
483 virtual bool HasExtraTypeInfo() const { return false; }
484 // The page sink's callback when the data set gets committed will call this method to get the field's extra
485 // type information. This has to happen at the end of writing because the type information may change depending
486 // on the data that's written, e.g. for polymorphic types in the streamer field.
488
489 /// Add a new subfield to the list of nested fields
490 void Attach(std::unique_ptr<RFieldBase> child);
491
492 /// Called by ConnectPageSource() before connecting; derived classes may override this as appropriate
494
495 /// Called by ConnectPageSource() once connected; derived classes may override this as appropriate
496 virtual void AfterConnectPageSource() {}
497
498 /// Factory method to resurrect a field from the stored on-disk type information. This overload takes an already
499 /// normalized type name and type alias.
500 /// `desc` and `fieldId` must be passed if `options.fEmulateUnknownTypes` is true, otherwise they can be left blank.
502 Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options,
504
505public:
506 template <bool IsConstT>
507 class RSchemaIteratorTemplate;
510
511 // This is used in CreateObject() and is specialized for void
512 template <typename T>
514 using deleter = std::default_delete<T>;
515 };
516
517 /// Used in the return value of the Check() method
519 std::string fFieldName; ///< Qualified field name causing the error
520 std::string fTypeName; ///< Type name corresponding to the (sub)field
521 std::string fErrMsg; ///< Cause of the failure, e.g. unsupported type
522 };
523
524 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
525 /// If `isSimple` is `true`, the trait `kTraitMappable` is automatically set on construction. However, the
526 /// field might be demoted to non-simple if a post-read callback is set.
527 RFieldBase(std::string_view name, std::string_view type, ROOT::ENTupleStructure structure, bool isSimple,
528 std::size_t nRepetitions = 0);
529 RFieldBase(const RFieldBase &) = delete;
530 RFieldBase(RFieldBase &&) = default;
531 RFieldBase &operator=(const RFieldBase &) = delete;
533 virtual ~RFieldBase() = default;
534
535 /// Copies the field and its subfields using a possibly new name and a new, unconnected set of columns
536 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
537
538 /// Factory method to create a field from a certain type given as string.
539 /// Note that the provided type name must be a valid C++ type name. Template arguments of templated types
540 /// must be type names or integers (e.g., no expressions).
542 Create(const std::string &fieldName, const std::string &typeName);
543
544 /// Checks if the given type is supported by RNTuple. In case of success, the result vector is empty.
545 /// Otherwise there is an error record for each failing subfield (subtype).
546 static std::vector<RCheckResult> Check(const std::string &fieldName, const std::string &typeName);
547
548 /// Generates an object of the field type and allocates new initialized memory according to the type.
549 /// Implemented at the end of this header because the implementation is using RField<T>::TypeName()
550 /// The returned object can be released with `delete`, i.e. it is valid to call:
551 /// ~~~{.cpp}
552 /// auto ptr = field->CreateObject();
553 /// delete ptr.release();
554 /// ~~~
555 ///
556 /// Note that CreateObject<void>() is supported. The returned `unique_ptr` has a custom deleter that reports an error
557 /// if it is called. The intended use of the returned `unique_ptr<void>` is to call `release()`. In this way, the
558 /// transfer of pointer ownership is explicit.
559 template <typename T>
560 std::unique_ptr<T, typename RCreateObjectDeleter<T>::deleter> CreateObject() const;
561 /// Generates an object of the field's type, wraps it in a shared pointer and returns it as an RValue connected to
562 /// the field.
564 /// Creates a new, initially empty bulk.
565 /// RBulk::ReadBulk() will construct the array of values. The memory of the value array is managed by the RBulk
566 /// class.
568 /// Creates a value from a memory location with an already constructed object
569 RValue BindValue(std::shared_ptr<void> objPtr);
570 /// Creates the list of direct child values given an existing value for this field. E.g. a single value for the
571 /// correct `std::variant` or all the elements of a collection. The default implementation assumes no subvalues
572 /// and returns an empty vector.
573 virtual std::vector<RValue> SplitValue(const RValue &value) const;
574 /// The number of bytes taken by a value of the appropriate type
575 virtual size_t GetValueSize() const = 0;
576 /// As a rule of thumb, the alignment is equal to the size of the type. There are, however, various exceptions
577 /// to this rule depending on OS and CPU architecture. So enforce the alignment to be explicitly spelled out.
578 virtual size_t GetAlignment() const = 0;
579 std::uint32_t GetTraits() const { return fTraits; }
580 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
581
582 const std::string &GetFieldName() const { return fName; }
583 /// Returns the field name and parent field names separated by dots (`grandparent.parent.child`)
584 std::string GetQualifiedFieldName() const;
585 const std::string &GetTypeName() const { return fType; }
586 const std::string &GetTypeAlias() const { return fTypeAlias; }
588 std::size_t GetNRepetitions() const { return fNRepetitions; }
589 const RFieldBase *GetParent() const { return fParent; }
590 std::vector<RFieldBase *> GetMutableSubfields();
591 std::vector<const RFieldBase *> GetConstSubfields() const;
592 bool IsSimple() const { return fIsSimple; }
593 bool IsArtificial() const { return fIsArtificial; }
594 /// Get the field's description
595 const std::string &GetDescription() const { return fDescription; }
596 void SetDescription(std::string_view description);
597 EState GetState() const { return fState; }
598
601
602 /// Returns the `fColumnRepresentative` pointee or, if unset (always the case for artificial fields), the field's
603 /// default representative
605 /// Fixes a column representative. This can only be done _before_ connecting the field to a page sink.
606 /// Otherwise, or if the provided representation is not in the list of GetColumnRepresentations(),
607 /// an exception is thrown
609 /// Whether or not an explicit column representative was set
611
612 /// Indicates an evolution of the mapping scheme from C++ type to columns
613 virtual std::uint32_t GetFieldVersion() const { return 0; }
614 /// Indicates an evolution of the C++ type itself
615 virtual std::uint32_t GetTypeVersion() const { return 0; }
616 /// Return the current TClass reported checksum of this class. Only valid if `kTraitTypeChecksum` is set.
617 virtual std::uint32_t GetTypeChecksum() const { return 0; }
618 /// Return the C++ type version stored in the field descriptor; only valid after a call to ConnectPageSource()
619 std::uint32_t GetOnDiskTypeVersion() const { return fOnDiskTypeVersion; }
620 /// Return checksum stored in the field descriptor; only valid after a call to ConnectPageSource(),
621 /// if the field stored a type checksum
622 std::uint32_t GetOnDiskTypeChecksum() const { return fOnDiskTypeChecksum; }
623
630
632}; // class RFieldBase
633
634/// Iterates over the subtree of fields in depth-first search order
635template <bool IsConstT>
637private:
638 struct Position {
639 using FieldPtr_t = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
640 Position() : fFieldPtr(nullptr), fIdxInParent(-1) {}
644 };
645 /// The stack of nodes visited when walking down the tree of fields
646 std::vector<Position> fStack;
647
648public:
650 using iterator_category = std::forward_iterator_tag;
651 using difference_type = std::ptrdiff_t;
652 using value_type = std::conditional_t<IsConstT, const RFieldBase, RFieldBase>;
653 using pointer = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
654 using reference = std::conditional_t<IsConstT, const RFieldBase &, RFieldBase &>;
655
659 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
660 /// in depth-first search order
661 void Advance()
662 {
663 auto itr = fStack.rbegin();
664 if (!itr->fFieldPtr->fSubfields.empty()) {
665 fStack.emplace_back(Position(itr->fFieldPtr->fSubfields[0].get(), 0));
666 return;
667 }
668
669 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
670 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubfields.size()) {
671 if (fStack.size() == 1) {
672 itr->fFieldPtr = itr->fFieldPtr->fParent;
673 itr->fIdxInParent = -1;
674 return;
675 }
676 fStack.pop_back();
677 itr = fStack.rbegin();
678 nextIdxInParent = ++(itr->fIdxInParent);
679 }
680 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubfields[nextIdxInParent].get();
681 }
682
683 iterator operator++(int) /* postfix */
684 {
685 auto r = *this;
686 Advance();
687 return r;
688 }
689 iterator &operator++() /* prefix */
690 {
691 Advance();
692 return *this;
693 }
694 reference operator*() const { return *fStack.back().fFieldPtr; }
695 pointer operator->() const { return fStack.back().fFieldPtr; }
696 bool operator==(const iterator &rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
697 bool operator!=(const iterator &rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
698};
699
700/// Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
701/// Fields can create RValue objects through RFieldBase::CreateValue(), RFieldBase::BindValue()) or
702/// RFieldBase::SplitValue().
704 friend class RFieldBase;
705
706private:
707 RFieldBase *fField = nullptr; ///< The field that created the RValue
708 /// Set by Bind() or by RFieldBase::CreateValue(), RFieldBase::SplitValue() or RFieldBase::BindValue()
709 std::shared_ptr<void> fObjPtr;
710 RValue(RFieldBase *field, std::shared_ptr<void> objPtr) : fField(field), fObjPtr(objPtr) {}
711
712public:
713 RValue(const RValue &) = default;
714 RValue &operator=(const RValue &) = default;
715 RValue(RValue &&other) = default;
717 ~RValue() = default;
718
719 std::size_t Append() { return fField->Append(fObjPtr.get()); }
722 void Bind(std::shared_ptr<void> objPtr) { fObjPtr = objPtr; }
723 void BindRawPtr(void *rawPtr);
724 /// Replace the current object pointer by a pointer to a new object constructed by the field
725 void EmplaceNew() { fObjPtr = fField->CreateValue().GetPtr<void>(); }
726
727 template <typename T>
728 std::shared_ptr<T> GetPtr() const
729 {
730 return std::static_pointer_cast<T>(fObjPtr);
731 }
732
733 template <typename T>
734 const T &GetRef() const
735 {
736 return *static_cast<T *>(fObjPtr.get());
737 }
738
739 const RFieldBase &GetField() const { return *fField; }
740};
741
742/// Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().
743// See the RBulk class documentation for more information.
745 /// Possible return value of ReadBulk() and ReadBulkImpl(), which indicates that the full bulk range was read
746 /// independently of the provided masks.
747 static const std::size_t kAllSet = std::size_t(-1);
748
749 RNTupleLocalIndex fFirstIndex; ///< Start of the bulk range
750 std::size_t fCount = 0; ///< Size of the bulk range
751 /// A bool array of size fCount, indicating the required values in the requested range
752 const bool *fMaskReq = nullptr;
753 bool *fMaskAvail = nullptr; ///< A bool array of size `fCount`, indicating the valid values in fValues
754 /// The destination area, which has to be an array of valid objects of the correct type large enough to hold the bulk
755 /// range.
756 void *fValues = nullptr;
757 /// Reference to memory owned by the RBulk class. The field implementing BulkReadImpl() may use `fAuxData` as memory
758 /// that stays persistent between calls.
759 std::vector<unsigned char> *fAuxData = nullptr;
760};
761
762// clang-format off
763/**
764\class ROOT::RFieldBase::RBulk
765\ingroup NTuple
766\brief Points to an array of objects with RNTuple I/O support, used for bulk reading.
767
768Similar to RValue, but manages an array of consecutive values. Bulks have to come from the same cluster.
769Bulk I/O works with two bit masks: the mask of all the available entries in the current bulk and the mask
770of the required entries in a bulk read. The idea is that a single bulk may serve multiple read operations
771on the same range, where in each read operation a different subset of values is required.
772The memory of the value array is managed by the RBulk class.
773*/
774// clang-format on
776private:
777 friend class RFieldBase;
778
779 RFieldBase *fField = nullptr; ///< The field that created the array of values
780 std::unique_ptr<RFieldBase::RDeleter> fDeleter; /// Cached deleter of fField
781 void *fValues = nullptr; ///< Pointer to the start of the array
782 std::size_t fValueSize = 0; ///< Cached copy of RFieldBase::GetValueSize()
783 std::size_t fCapacity = 0; ///< The size of the array memory block in number of values
784 std::size_t fSize = 0; ///< The number of available values in the array (provided their mask is set)
785 bool fIsAdopted = false; ///< True if the user provides the memory buffer for fValues
786 std::unique_ptr<bool[]> fMaskAvail; ///< Masks invalid values in the array
787 std::size_t fNValidValues = 0; ///< The sum of non-zero elements in the fMask
788 RNTupleLocalIndex fFirstIndex; ///< Index of the first value of the array
789 /// Reading arrays of complex values may require additional memory, for instance for the elements of
790 /// arrays of vectors. A pointer to the `fAuxData` array is passed to the field's BulkRead method.
791 /// The RBulk class does not modify the array in-between calls to the field's BulkRead method.
792 std::vector<unsigned char> fAuxData;
793
794 void ReleaseValues();
795 /// Sets a new range for the bulk. If there is enough capacity, the `fValues` array will be reused.
796 /// Otherwise a new array is allocated. After reset, fMaskAvail is false for all values.
797 void Reset(RNTupleLocalIndex firstIndex, std::size_t size);
798 void CountValidValues();
799
801 {
802 if (firstIndex.GetClusterId() != fFirstIndex.GetClusterId())
803 return false;
804 return (firstIndex.GetIndexInCluster() >= fFirstIndex.GetIndexInCluster()) &&
805 ((firstIndex.GetIndexInCluster() + size) <= (fFirstIndex.GetIndexInCluster() + fSize));
806 }
807
808 void *GetValuePtrAt(std::size_t idx) const { return reinterpret_cast<unsigned char *>(fValues) + idx * fValueSize; }
809
813
814public:
815 ~RBulk();
816 RBulk(const RBulk &) = delete;
817 RBulk &operator=(const RBulk &) = delete;
818 RBulk(RBulk &&other);
820
821 // Sets `fValues` and `fSize`/`fCapacity` to the given values. The capacity is specified in number of values.
822 // Once a buffer is adopted, an attempt to read more values then available throws an exception.
823 void AdoptBuffer(void *buf, std::size_t capacity);
824
825 /// Reads `size` values from the associated field, starting from `firstIndex`. Note that the index is given
826 /// relative to a certain cluster. The return value points to the array of read objects.
827 /// The `maskReq` parameter is a bool array of at least `size` elements. Only objects for which the mask is
828 /// true are guaranteed to be read in the returned value array. A `nullptr` means to read all elements.
829 void *ReadBulk(RNTupleLocalIndex firstIndex, const bool *maskReq, std::size_t size)
830 {
833
834 // We may read a subrange of the currently available range
835 auto offset = firstIndex.GetIndexInCluster() - fFirstIndex.GetIndexInCluster();
836
837 if (fNValidValues == fSize)
838 return GetValuePtrAt(offset);
839
841 bulkSpec.fFirstIndex = firstIndex;
842 bulkSpec.fCount = size;
843 bulkSpec.fMaskReq = maskReq;
844 bulkSpec.fMaskAvail = &fMaskAvail[offset];
845 bulkSpec.fValues = GetValuePtrAt(offset);
846 bulkSpec.fAuxData = &fAuxData;
847 auto nRead = fField->ReadBulk(bulkSpec);
848 if (nRead == RBulkSpec::kAllSet) {
849 if ((offset == 0) && (size == fSize)) {
851 } else {
853 }
854 } else {
856 }
857 return GetValuePtrAt(offset);
858 }
859
860 /// Overload to read all elements in the given cluster range.
861 void *ReadBulk(ROOT::RNTupleLocalRange range) { return ReadBulk(*range.begin(), nullptr, range.size()); }
862};
863
864namespace Internal {
865// At some point, RFieldBase::OnClusterCommit() may allow for a user-defined callback to change the
866// column representation. For now, we inject this for testing and internal use only.
869 {
870 R__ASSERT(newRepresentationIdx < field.fColumnRepresentatives.size());
871 const auto N = field.fColumnRepresentatives[0].get().size();
872 R__ASSERT(N >= 1 && N <= 2);
873 R__ASSERT(field.fPrincipalColumn);
874 field.fPrincipalColumn = field.fAvailableColumns[newRepresentationIdx * N].get();
875 if (field.fAuxiliaryColumn) {
876 R__ASSERT(N == 2);
877 field.fAuxiliaryColumn = field.fAvailableColumns[newRepresentationIdx * N + 1].get();
878 }
879 }
880};
881} // namespace Internal
882} // namespace ROOT
883
884#endif
#define R__unlikely(expr)
Definition RConfig.hxx:602
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
Abstract base class for classes implementing the visitor design pattern.
A container of const raw pointers, corresponding to a row in the data set.
Processor specialization for horizontally combined (joined) RNTuples.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:38
void Read(const ROOT::NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:160
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
The field for a class with dictionary.
Definition RField.hxx:111
Field specific extra type information from the header / extenstion header.
Points to an array of objects with RNTuple I/O support, used for bulk reading.
std::size_t fValueSize
Cached copy of RFieldBase::GetValueSize()
RBulk(const RBulk &)=delete
std::size_t fNValidValues
The sum of non-zero elements in the fMask.
void * GetValuePtrAt(std::size_t idx) const
bool ContainsRange(RNTupleLocalIndex firstIndex, std::size_t size) const
void * ReadBulk(RNTupleLocalIndex firstIndex, const bool *maskReq, std::size_t size)
Reads size values from the associated field, starting from firstIndex.
RBulk(RFieldBase *field)
RNTupleLocalIndex fFirstIndex
Index of the first value of the array.
void * ReadBulk(ROOT::RNTupleLocalRange range)
Overload to read all elements in the given cluster range.
std::size_t fCapacity
The size of the array memory block in number of values.
void Reset(RNTupleLocalIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
std::vector< unsigned char > fAuxData
Reading arrays of complex values may require additional memory, for instance for the elements of arra...
bool fIsAdopted
True if the user provides the memory buffer for fValues.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
RFieldBase * fField
The field that created the array of values.
RBulk & operator=(const RBulk &)=delete
void * fValues
Cached deleter of fField.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
void AdoptBuffer(void *buf, std::size_t capacity)
std::size_t fSize
The number of available values in the array (provided their mask is set)
The list of column representations a field can have.
const Selection_t & GetSerializationTypes() const
const Selection_t & GetDeserializationTypes() const
const ColumnRepresentation_t & GetSerializationDefault() const
The first column list from fSerializationTypes is the default for writing.
std::vector< ColumnRepresentation_t > Selection_t
A list of column representations.
Selection_t fDeserializationTypes
The union of the serialization types and the deserialization extra types passed during construction.
A functor to release the memory acquired by CreateValue() (memory and constructor).
virtual void operator()(void *objPtr, bool dtorOnly)
virtual ~RDeleter()=default
Iterates over the subtree of fields in depth-first search order.
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
bool operator==(const iterator &rh) const
std::conditional_t< IsConstT, const RFieldBase &, RFieldBase & > reference
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > pointer
std::conditional_t< IsConstT, const RFieldBase, RFieldBase > value_type
std::forward_iterator_tag iterator_category
void Advance()
Given that the iterator points to a valid field which is not the end iterator, go to the next field i...
bool operator!=(const iterator &rh) const
RSchemaIteratorTemplate(pointer val, int idxInParent)
A deleter for templated RFieldBase descendents where the value type is known.
void operator()(void *objPtr, bool dtorOnly) final
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
std::shared_ptr< void > fObjPtr
Set by Bind() or by RFieldBase::CreateValue(), RFieldBase::SplitValue() or RFieldBase::BindValue()
void Read(ROOT::NTupleSize_t globalIndex)
void EmplaceNew()
Replace the current object pointer by a pointer to a new object constructed by the field.
void Bind(std::shared_ptr< void > objPtr)
void Read(RNTupleLocalIndex localIndex)
const RFieldBase & GetField() const
RValue(const RValue &)=default
RValue(RValue &&other)=default
std::shared_ptr< T > GetPtr() const
RFieldBase * fField
The field that created the RValue.
RValue(RFieldBase *field, std::shared_ptr< void > objPtr)
RValue & operator=(const RValue &)=default
RValue & operator=(RValue &&other)=default
void BindRawPtr(void *rawPtr)
const T & GetRef() const
A field translates read and write calls from/to underlying columns to/from tree values.
ROOT::DescriptorId_t fOnDiskId
When the columns are connected to a page source or page sink, the field represents a field id in the ...
ROOT::ENTupleStructure GetStructure() const
virtual size_t GetValueSize() const =0
The number of bytes taken by a value of the appropriate type.
static constexpr std::uint32_t kInvalidTypeVersion
RSchemaIterator end()
void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives)
Fixes a column representative.
void InvokeReadCallbacks(void *target)
ROOT::Internal::RColumn * fPrincipalColumn
All fields that have columns have a distinct main column.
virtual size_t GetAlignment() const =0
As a rule of thumb, the alignment is equal to the size of the type.
virtual std::unique_ptr< RDeleter > GetDeleter() const
ROOT::NTupleSize_t EntryToColumnElementIndex(ROOT::NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and vice versa.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
virtual void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
void FlushColumns()
Flushes data from active columns.
virtual void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to)
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
std::uint32_t GetOnDiskTypeVersion() const
Return the C++ type version stored in the field descriptor; only valid after a call to ConnectPageSou...
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
RBulk CreateBulk()
Creates a new, initially empty bulk.
EState
During its lifetime, a field undergoes the following possible state transitions:
bool fIsSimple
A field qualifies as simple if it is mappable (which implies it has a single principal column),...
RConstSchemaIterator cbegin() const
std::unique_ptr< T, typename RCreateObjectDeleter< T >::deleter > CreateObject() const
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.hxx:500
RFieldBase & operator=(const RFieldBase &)=delete
virtual void AfterConnectPageSource()
Called by ConnectPageSource() once connected; derived classes may override this as appropriate.
virtual void GenerateColumns(const ROOT::RNTupleDescriptor &)
Implementations in derived classes should create the backing columns corresponding to the field type ...
void AutoAdjustColumnTypes(const ROOT::RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
virtual void ConstructValue(void *where) const =0
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::vector< const RFieldBase * > GetConstSubfields() const
void SetOnDiskId(ROOT::DescriptorId_t id)
void RemoveReadCallback(size_t idx)
void GenerateColumnsImpl(const ROOT::RNTupleDescriptor &desc)
For reading, use the on-disk column list.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
void Read(RNTupleLocalIndex localIndex, void *to)
Populate a single value with data from the field.
const RFieldBase * GetParent() const
std::vector< RFieldBase * > GetMutableSubfields()
std::string fDescription
Free text set by the user.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
static ROOT::Internal::RColumn * GetPrincipalColumnOf(const RFieldBase &other)
Fields may need direct access to the principal column of their subfields, e.g. in RRVecField::ReadBul...
static std::vector< RCheckResult > Check(const std::string &fieldName, const std::string &typeName)
Checks if the given type is supported by RNTuple.
RSchemaIterator begin()
ROOT::Internal::RColumn * fAuxiliaryColumn
Some fields have a second column in its column representation.
size_t AddReadCallback(ReadCallback_t func)
Set a user-defined function to be called after reading a value, giving a chance to inspect and/or mod...
RConstSchemaIterator cend() const
std::size_t fNRepetitions
For fixed sized arrays, the array length.
std::function< void(void *)> ReadCallback_t
virtual void BeforeConnectPageSource(ROOT::Internal::RPageSource &)
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate.
std::size_t Append(const void *from)
Write the given value into columns.
RValue CreateValue()
Generates an object of the field's type, wraps it in a shared pointer and returns it as an RValue con...
RSchemaIteratorTemplate< false > RSchemaIterator
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const ROOT::RNTupleDescriptor &desc, std::uint16_t representationIndex) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given represe...
RFieldBase(RFieldBase &&)=default
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given an existing value for this field.
virtual std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const =0
Called by Clone(), which additionally copies the on-disk ID.
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots (grandparent.parent....
const std::string & GetFieldName() const
void ConnectPageSink(ROOT::Internal::RPageSink &pageSink, ROOT::NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
std::vector< ROOT::ENTupleColumnType > ColumnRepresentation_t
std::vector< ReadCallback_t > fReadCallbacks
List of functions to be called after reading a value.
RFieldBase & operator=(RFieldBase &&)=default
const std::string & GetTypeAlias() const
static void CallReadOn(RFieldBase &other, ROOT::NTupleSize_t globalIndex, void *to)
virtual ~RFieldBase()=default
static std::size_t CallAppendOn(RFieldBase &other, const void *from)
Allow derived classes to call Append() and Read() on other (sub)fields.
virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to)
virtual void CommitClusterImpl()
std::vector< std::reference_wrapper< const ColumnRepresentation_t > > fColumnRepresentatives
Pointers into the static vector returned by RColumnRepresentations::GetSerializationTypes() when SetC...
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
friend struct ROOT::Internal::RFieldCallbackInjector
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
RFieldBase * fParent
Subfields point to their mother field.
std::vector< std::unique_ptr< ROOT::Internal::RColumn > > fAvailableColumns
The columns are connected either to a sink or to a source (not to both); they are owned by the field.
RFieldBase(std::string_view name, std::string_view type, ROOT::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.
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
@ kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
@ kTraitInvalidField
This field is an instance of RInvalidField and can be safely static_cast to it.
@ kTraitTypeChecksum
The TClass checksum is set and valid.
EState fState
Changed by ConnectTo[Sink,Source], reset by Clone()
static void * CallCreateObjectRawPtrOn(RFieldBase &other)
bool IsArtificial() const
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
const std::string & GetDescription() const
Get the field's description.
bool HasReadCallbacks() const
std::string fTypeAlias
A typedef or using name that was used when creating the field.
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
std::string fType
The C++ type captured by this field.
RColumnRepresentations::Selection_t GetColumnRepresentatives() const
Returns the fColumnRepresentative pointee or, if unset (always the case for artificial fields),...
RSchemaIteratorTemplate< true > RConstSchemaIterator
virtual std::uint32_t GetTypeChecksum() const
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
bool IsSimple() const
std::uint32_t GetTraits() const
std::size_t GetNRepetitions() const
std::uint32_t fOnDiskTypeChecksum
TClass checksum cached from the descriptor after a call to ConnectPageSource().
const std::string & GetTypeName() const
ROOT::ENTupleStructure fStructure
The role of this field in the data model structure.
void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
Helpers for generating columns.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
void SetDescription(std::string_view description)
static void CallReadOn(RFieldBase &other, RNTupleLocalIndex localIndex, void *to)
ROOT::DescriptorId_t GetOnDiskId() const
std::uint32_t fOnDiskTypeVersion
C++ type version cached from the descriptor after a call to ConnectPageSource()
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its subfields using a possibly new name and a new, unconnected set of columns.
std::string fName
The field name relative to its parent field.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl()
void ConnectPageSource(ROOT::Internal::RPageSource &pageSource)
Connects the field and its subfield tree to the given page source.
static void CallConstructValueOn(const RFieldBase &other, void *where)
Allow derived classes to call ConstructValue(void *) and GetDeleter() on other (sub)fields.
EState GetState() const
void GenerateColumnsImpl()
For writing, use the currently set column representative.
virtual ROOT::RExtraTypeInfoDescriptor GetExtraTypeInfo() const
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
void Read(ROOT::NTupleSize_t globalIndex, void *to)
Populate a single value with data from the field.
std::uint32_t GetOnDiskTypeChecksum() const
Return checksum stored in the field descriptor; only valid after a call to ConnectPageSource(),...
RFieldBase(const RFieldBase &)=delete
virtual bool HasExtraTypeInfo() const
bool fIsArtificial
A field that is not backed on disk but computed, e.g.
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
bool HasDefaultColumnRepresentative() const
Whether or not an explicit column representative was set.
The on-storage metadata of an RNTuple.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
ROOT::NTupleSize_t GetIndexInCluster() const
ROOT::DescriptorId_t GetClusterId() const
Used to loop over entries of collections in a single cluster.
Common user-tunable settings for storing RNTuples.
const_iterator begin() const
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:197
void CallCommitClusterOnField(RFieldBase &)
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
ROOT::RResult< std::unique_ptr< ROOT::RFieldBase > > CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
void CallFlushColumnsOnField(RFieldBase &)
void CallConnectPageSinkOnField(RFieldBase &, ROOT::Internal::RPageSink &, ROOT::NTupleSize_t firstEntry=0)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
static void SetPrimaryColumnRepresentation(RFieldBase &field, std::uint16_t newRepresentationIdx)
Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().
static const std::size_t kAllSet
Possible return value of ReadBulk() and ReadBulkImpl(), which indicates that the full bulk range was ...
RNTupleLocalIndex fFirstIndex
Start of the bulk range.
void * fValues
The destination area, which has to be an array of valid objects of the correct type large enough to h...
std::size_t fCount
Size of the bulk range.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
Used in the return value of the Check() method.
std::string fFieldName
Qualified field name causing the error.
std::string fTypeName
Type name corresponding to the (sub)field.
std::string fErrMsg
Cause of the failure, e.g. unsupported type.
Position(FieldPtr_t fieldPtr, int idxInParent)
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > FieldPtr_t
RSharedPtrDeleter(std::unique_ptr< RFieldBase::RDeleter > deleter)
std::unique_ptr< RFieldBase::RDeleter > fDeleter