Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldBase.hxx
Go to the documentation of this file.
1/// \file ROOT/RFieldBase.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_RFieldBase
17#define ROOT7_RFieldBase
18
19#include <ROOT/RColumn.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 {
32namespace Experimental {
33
34class RCollectionField;
35class RFieldBase;
36
37namespace Internal {
38struct RFieldCallbackInjector;
39struct RFieldRepresentationModifier;
40class RPageSink;
41class RPageSource;
42// TODO(jblomer): find a better way to not have these three methods in the RFieldBase public API
43void CallCommitClusterOnField(RFieldBase &);
44void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry = 0);
45void CallConnectPageSourceOnField(RFieldBase &, RPageSource &);
46} // namespace Internal
47
48namespace Detail {
49class RFieldVisitor;
50} // namespace Detail
51
52// clang-format off
53/**
54\class ROOT::Experimental::RFieldBase
55\ingroup NTuple
56\brief A field translates read and write calls from/to underlying columns to/from tree values
57
58A field is a serializable C++ type or a container for a collection of sub fields. The RFieldBase and its
59type-safe descendants provide the object to column mapper. They map C++ objects to primitive columns. The
60mapping is trivial for simple types such as 'double'. Complex types resolve to multiple primitive columns.
61The field knows based on its type and the field name the type(s) and name(s) of the columns.
62
63Note: the class hierarchy starting at RFieldBase is not meant to be extended by user-provided child classes.
64This is and can only be partially enforced through C++.
65*/
66// clang-format on
68 friend class ROOT::Experimental::RCollectionField; // to move the fields from the collection model
69 friend struct ROOT::Experimental::Internal::RFieldCallbackInjector; // used for unit tests
74 using ReadCallback_t = std::function<void(void *)>;
75
76protected:
77 /// A functor to release the memory acquired by CreateValue (memory and constructor).
78 /// This implementation works for types with a trivial destructor. More complex fields implement a derived deleter.
79 /// The deleter is operational without the field object and thus can be used to destruct/release a value after
80 /// the field has been destructed.
81 class RDeleter {
82 public:
83 virtual ~RDeleter() = default;
84 virtual void operator()(void *objPtr, bool dtorOnly)
85 {
86 if (!dtorOnly)
87 operator delete(objPtr);
88 }
89 };
90
91 /// A deleter for templated RFieldBase descendents where the value type is known.
92 template <typename T>
93 class RTypedDeleter : public RDeleter {
94 public:
95 void operator()(void *objPtr, bool dtorOnly) final
96 {
97 std::destroy_at(static_cast<T *>(objPtr));
98 RDeleter::operator()(objPtr, dtorOnly);
99 }
100 };
101
102 // We cannot directly use RFieldBase::RDeleter as a shared pointer deleter due to splicing. We use this
103 // wrapper class to store a polymorphic pointer to the actual deleter.
105 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
106 void operator()(void *objPtr) { fDeleter->operator()(objPtr, false /* dtorOnly*/); }
107 explicit RSharedPtrDeleter(std::unique_ptr<RFieldBase::RDeleter> deleter) : fDeleter(std::move(deleter)) {}
108 };
109
110public:
111 static constexpr std::uint32_t kInvalidTypeVersion = -1U;
112 /// No constructor needs to be called, i.e. any bit pattern in the allocated memory represents a valid type
113 /// A trivially constructible field has a no-op ConstructValue() implementation
114 static constexpr int kTraitTriviallyConstructible = 0x01;
115 /// The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
116 static constexpr int kTraitTriviallyDestructible = 0x02;
117 /// A field of a fundamental type that can be directly mapped via `RField<T>::Map()`, i.e. maps as-is to a single
118 /// column
119 static constexpr int kTraitMappable = 0x04;
120 /// The TClass checksum is set and valid
121 static constexpr int kTraitTypeChecksum = 0x08;
122 /// Shorthand for types that are both trivially constructible and destructible
124
125 using ColumnRepresentation_t = std::vector<EColumnType>;
126
127 /// During its lifetime, a field undergoes the following possible state transitions:
128 ///
129 /// [*] --> Unconnected --> ConnectedToSink ----
130 /// | | |
131 /// | --> ConnectedToSource ---> [*]
132 /// | |
133 /// -------------------------------
135
136 /// Some fields have multiple possible column representations, e.g. with or without split encoding.
137 /// All column representations supported for writing also need to be supported for reading. In addition,
138 /// fields can support extra column representations for reading only, e.g. a 64bit integer reading from a
139 /// 32bit column.
140 /// The defined column representations must be supported by corresponding column packing/unpacking implementations,
141 /// i.e. for the example above, the unpacking of 32bit ints to 64bit pages must be implemented in RColumnElement.hxx
143 public:
144 /// A list of column representations
145 using Selection_t = std::vector<ColumnRepresentation_t>;
146
148 RColumnRepresentations(const Selection_t &serializationTypes, const Selection_t &deserializationExtraTypes);
149
150 /// The first column list from fSerializationTypes is the default for writing.
154
155 private:
157 /// The union of the serialization types and the deserialization extra types. Duplicates the serialization types
158 /// list but the benenfit is that GetDeserializationTypes does not need to compile the list.
160 }; // class RColumnRepresentations
161
162 /// Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
163 /// Only fields can create RValue objects through generation, binding or splitting.
164 class RValue {
165 friend class RFieldBase;
166
167 private:
168 RFieldBase *fField = nullptr; ///< The field that created the RValue
169 std::shared_ptr<void> fObjPtr; ///< Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
170
171 RValue(RFieldBase *field, std::shared_ptr<void> objPtr) : fField(field), fObjPtr(objPtr) {}
172
173 public:
174 RValue(const RValue &) = default;
175 RValue &operator=(const RValue &) = default;
176 RValue(RValue &&other) = default;
177 RValue &operator=(RValue &&other) = default;
178 ~RValue() = default;
179
180 std::size_t Append() { return fField->Append(fObjPtr.get()); }
181 void Read(NTupleSize_t globalIndex) { fField->Read(globalIndex, fObjPtr.get()); }
182 void Read(RClusterIndex clusterIndex) { fField->Read(clusterIndex, fObjPtr.get()); }
183 void Bind(std::shared_ptr<void> objPtr) { fObjPtr = objPtr; }
184 void BindRawPtr(void *rawPtr);
185 /// Replace the current object pointer by a pointer to a new object constructed by the field
186 void EmplaceNew() { fObjPtr = fField->CreateValue().GetPtr<void>(); }
187
188 template <typename T>
189 std::shared_ptr<T> GetPtr() const
190 {
191 return std::static_pointer_cast<T>(fObjPtr);
192 }
193
194 template <typename T>
195 const T &GetRef() const
196 {
197 return *static_cast<T *>(fObjPtr.get());
198 }
199
200 const RFieldBase &GetField() const { return *fField; }
201 }; // class RValue
202
203 /// Similar to RValue but manages an array of consecutive values. Bulks have to come from the same cluster.
204 /// Bulk I/O works with two bit masks: the mask of all the available entries in the current bulk and the mask
205 /// of the required entries in a bulk read. The idea is that a single bulk may serve multiple read operations
206 /// on the same range, where in each read operation a different subset of values is required.
207 /// The memory of the value array is managed by the RBulk class.
208 class RBulk {
209 private:
210 friend class RFieldBase;
211
212 RFieldBase *fField = nullptr; ///< The field that created the array of values
213 std::unique_ptr<RFieldBase::RDeleter> fDeleter; /// Cached deleter of fField
214 void *fValues = nullptr; ///< Pointer to the start of the array
215 std::size_t fValueSize = 0; ///< Cached copy of fField->GetValueSize()
216 std::size_t fCapacity = 0; ///< The size of the array memory block in number of values
217 std::size_t fSize = 0; ///< The number of available values in the array (provided their mask is set)
218 bool fIsAdopted = false; ///< True if the user provides the memory buffer for fValues
219 std::unique_ptr<bool[]> fMaskAvail; ///< Masks invalid values in the array
220 std::size_t fNValidValues = 0; ///< The sum of non-zero elements in the fMask
221 RClusterIndex fFirstIndex; ///< Index of the first value of the array
222 /// Reading arrays of complex values may require additional memory, for instance for the elements of
223 /// arrays of vectors. A pointer to the fAuxData array is passed to the field's BulkRead method.
224 /// The RBulk class does not modify the array in-between calls to the field's BulkRead method.
225 std::vector<unsigned char> fAuxData;
226
227 void ReleaseValues();
228 /// Sets a new range for the bulk. If there is enough capacity, the fValues array will be reused.
229 /// Otherwise a new array is allocated. After reset, fMaskAvail is false for all values.
230 void Reset(RClusterIndex firstIndex, std::size_t size);
231 void CountValidValues();
232
233 bool ContainsRange(RClusterIndex firstIndex, std::size_t size) const
234 {
235 if (firstIndex.GetClusterId() != fFirstIndex.GetClusterId())
236 return false;
237 return (firstIndex.GetIndex() >= fFirstIndex.GetIndex()) &&
238 ((firstIndex.GetIndex() + size) <= (fFirstIndex.GetIndex() + fSize));
239 }
240
241 void *GetValuePtrAt(std::size_t idx) const
242 {
243 return reinterpret_cast<unsigned char *>(fValues) + idx * fValueSize;
244 }
245
246 explicit RBulk(RFieldBase *field)
247 : fField(field), fDeleter(field->GetDeleter()), fValueSize(field->GetValueSize())
248 {
249 }
250
251 public:
252 ~RBulk();
253 RBulk(const RBulk &) = delete;
254 RBulk &operator=(const RBulk &) = delete;
255 RBulk(RBulk &&other);
256 RBulk &operator=(RBulk &&other);
257
258 // Sets fValues and fSize/fCapacity to the given values. The capacity is specified in number of values.
259 // Once a buffer is adopted, an attempt to read more values then available throws an exception.
260 void AdoptBuffer(void *buf, std::size_t capacity);
261
262 /// Reads 'size' values from the associated field, starting from 'firstIndex'. Note that the index is given
263 /// relative to a certain cluster. The return value points to the array of read objects.
264 /// The 'maskReq' parameter is a bool array of at least 'size' elements. Only objects for which the mask is
265 /// true are guaranteed to be read in the returned value array.
266 void *ReadBulk(RClusterIndex firstIndex, const bool *maskReq, std::size_t size)
267 {
268 if (!ContainsRange(firstIndex, size))
269 Reset(firstIndex, size);
270
271 // We may read a sub range of the currently available range
272 auto offset = firstIndex.GetIndex() - fFirstIndex.GetIndex();
273
274 if (fNValidValues == fSize)
275 return GetValuePtrAt(offset);
276
277 RBulkSpec bulkSpec;
278 bulkSpec.fFirstIndex = firstIndex;
279 bulkSpec.fCount = size;
280 bulkSpec.fMaskReq = maskReq;
281 bulkSpec.fMaskAvail = &fMaskAvail[offset];
282 bulkSpec.fValues = GetValuePtrAt(offset);
283 bulkSpec.fAuxData = &fAuxData;
284 auto nRead = fField->ReadBulk(bulkSpec);
285 if (nRead == RBulkSpec::kAllSet) {
286 if ((offset == 0) && (size == fSize)) {
288 } else {
290 }
291 } else {
292 fNValidValues += nRead;
293 }
294 return GetValuePtrAt(offset);
295 }
296 }; // class RBulk
297
298private:
299 /// The field name relative to its parent field
300 std::string fName;
301 /// The C++ type captured by this field
302 std::string fType;
303 /// The role of this field in the data model structure
305 /// For fixed sized arrays, the array length
306 std::size_t fNRepetitions;
307 /// A field qualifies as simple if it is both mappable and has no post-read callback
309 /// When the columns are connected to a page source or page sink, the field represents a field id in the
310 /// corresponding RNTuple descriptor. This on-disk ID is set in RPageSink::Create() for writing and by
311 /// RFieldDescriptor::CreateField() when recreating a field / model from the stored descriptor.
313 /// Free text set by the user
314 std::string fDescription;
315 /// Changed by ConnectTo[Sink,Source], reset by Clone()
317
319 {
320 for (const auto &func : fReadCallbacks)
321 func(target);
322 }
323
324 /// Translate an entry index to a column element index of the principal column and viceversa. These functions
325 /// take into account the role and number of repetitions on each level of the field hierarchy as follows:
326 /// - Top level fields: element index == entry index
327 /// - Record fields propagate their principal column index to the principal columns of direct descendant fields
328 /// - Collection and variant fields set the principal column index of their childs to 0
329 ///
330 /// The column element index also depends on the number of repetitions of each field in the hierarchy, e.g., given a
331 /// field with type `std::array<std::array<float, 4>, 2>`, this function returns 8 for the inner-most field.
333
334 /// Flushes data from active columns to disk and calls CommitClusterImpl
335 void CommitCluster();
336 /// Fields and their columns live in the void until connected to a physical page storage. Only once connected, data
337 /// 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.
338 /// \param firstEntry The global index of the first entry with on-disk data for the connected field
339 void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry = 0);
340 /// Connects the field and its sub field tree to the given page source. Once connected, data can be read.
341 /// Only unconnected fields may be connected, i.e. the method is not idempotent. The field ID has to be set prior to
342 /// calling this function. For sub fields, a field ID may or may not be set. If the field ID is unset, it will be
343 /// determined using the page source descriptor, based on the parent field ID and the sub field name.
345
346 /// Factory method for the field's type. The caller owns the returned pointer
347 void *CreateObjectRawPtr() const;
348
349protected:
350 /// Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information
351 struct RBulkSpec {
352 /// As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read
353 /// independent of the provided masks.
354 static const std::size_t kAllSet = std::size_t(-1);
355
356 RClusterIndex fFirstIndex; ///< Start of the bulk range
357 std::size_t fCount = 0; ///< Size of the bulk range
358 /// A bool array of size fCount, indicating the required values in the requested range
359 const bool *fMaskReq = nullptr;
360 bool *fMaskAvail = nullptr; ///< A bool array of size fCount, indicating the valid values in fValues
361 /// The destination area, which has to be a big enough array of valid objects of the correct type
362 void *fValues = nullptr;
363 /// Reference to memory owned by the RBulk class. The field implementing BulkReadImpl may use fAuxData
364 /// as memory that stays persistent between calls.
365 std::vector<unsigned char> *fAuxData = nullptr;
366 };
367
368 /// Collections and classes own sub fields
369 std::vector<std::unique_ptr<RFieldBase>> fSubFields;
370 /// Sub fields point to their mother field
372 /// All fields that have columns have a distinct main column. E.g., for simple fields (float, int, ...), the
373 /// principal column corresponds to the field type. For collection fields except fixed-sized arrays,
374 /// the main column is the offset field. Class fields have no column of their own.
375 /// When reading, points to any column of the column team of the active representation. Usually, this is just
376 /// the first column, except for the nullable field.
377 /// When writing, points to the first column index of the currently active (not suppressed) column representation.
379 /// Some fields have a second column in its column representation. In this case, fAuxiliaryColumn points into
380 /// fAvailableColumns to the column that immediately follows the column fPrincipalColumn points to.
382 /// The columns are connected either to a sink or to a source (not to both); they are owned by the field.
383 /// Contains all columns of all representations in order of representation and column index.
384 std::vector<std::unique_ptr<Internal::RColumn>> fAvailableColumns;
385 /// Properties of the type that allow for optimizations of collections of that type
386 int fTraits = 0;
387 /// A typedef or using name that was used when creating the field
388 std::string fTypeAlias;
389 /// List of functions to be called after reading a value
390 std::vector<ReadCallback_t> fReadCallbacks;
391 /// C++ type version cached from the descriptor after a call to `ConnectPageSource()`
393 /// TClass checksum cached from the descriptor after a call to `ConnectPageSource()`. Only set
394 /// for classes with dictionaries.
395 std::uint32_t fOnDiskTypeChecksum = 0;
396 /// Pointers into the static vector GetColumnRepresentations().GetSerializationTypes() when
397 /// SetColumnRepresentatives is called. Otherwise (if empty) GetColumnRepresentatives() returns a vector
398 /// with a single element, the default representation.
399 std::vector<std::reference_wrapper<const ColumnRepresentation_t>> fColumnRepresentatives;
400
401 /// Helpers for generating columns. We use the fact that most fields have the same C++/memory types
402 /// for all their column representations.
403 /// Where possible, we call the helpers not from the header to reduce compilation time.
404 template <std::uint32_t ColumnIndexT, typename HeadT, typename... TailTs>
405 void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
406 {
407 assert(ColumnIndexT < representation.size());
408 fAvailableColumns.emplace_back(
409 Internal::RColumn::Create<HeadT>(representation[ColumnIndexT], ColumnIndexT, representationIndex));
410
411 // Initially, the first two columns become the active column representation
412 if (representationIndex == 0 && !fPrincipalColumn) {
413 fPrincipalColumn = fAvailableColumns.back().get();
414 } else if (representationIndex == 0 && !fAuxiliaryColumn) {
415 fAuxiliaryColumn = fAvailableColumns.back().get();
416 } else {
417 // We currently have no fields with more than 2 columns in its column representation
418 R__ASSERT(representationIndex > 0);
419 }
420
421 if constexpr (sizeof...(TailTs))
422 GenerateColumnsImpl<ColumnIndexT + 1, TailTs...>(representation, representationIndex);
423 }
424
425 /// For writing, use the currently set column representative
426 template <typename... ColumnCppTs>
428 {
429 if (fColumnRepresentatives.empty()) {
430 fAvailableColumns.reserve(sizeof...(ColumnCppTs));
432 } else {
433 const auto N = fColumnRepresentatives.size();
434 fAvailableColumns.reserve(N * sizeof...(ColumnCppTs));
435 for (unsigned i = 0; i < N; ++i) {
436 GenerateColumnsImpl<0, ColumnCppTs...>(fColumnRepresentatives[i].get(), i);
437 }
438 }
439 }
440
441 /// For reading, use the on-disk column list
442 template <typename... ColumnCppTs>
444 {
445 std::uint16_t representationIndex = 0;
446 do {
447 const auto &onDiskTypes = EnsureCompatibleColumnTypes(desc, representationIndex);
448 if (onDiskTypes.empty())
449 break;
450 GenerateColumnsImpl<0, ColumnCppTs...>(onDiskTypes, representationIndex);
451 fColumnRepresentatives.emplace_back(onDiskTypes);
452 if (representationIndex > 0) {
453 for (std::size_t i = 0; i < sizeof...(ColumnCppTs); ++i) {
454 fAvailableColumns[i]->MergeTeams(
455 *fAvailableColumns[representationIndex * sizeof...(ColumnCppTs) + i].get());
456 }
457 }
458 representationIndex++;
459 } while (true);
460 }
461
462 /// Implementations in derived classes should return a static RColumnRepresentations object. The default
463 /// implementation does not attach any columns to the field.
464 virtual const RColumnRepresentations &GetColumnRepresentations() const;
465 /// Implementations in derived classes should create the backing columns corresponsing to the field type for
466 /// writing. The default implementation does not attach any columns to the field.
467 virtual void GenerateColumns() {}
468 /// Implementations in derived classes should create the backing columns corresponsing to the field type for reading.
469 /// The default implementation does not attach any columns to the field. The method should check, using the page
470 /// source and fOnDiskId, if the column types match and throw if they don't.
471 virtual void GenerateColumns(const RNTupleDescriptor & /*desc*/) {}
472 /// Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given
473 /// representation index. If there are no columns for the given representation index, return an empty
474 /// ColumnRepresentation_t list. Otherwise, the returned reference points into the static array returned by
475 /// GetColumnRepresentations().
476 /// Throws an exception if the types on disk don't match any of the deserialization types from
477 /// GetColumnRepresentations().
479 EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc, std::uint16_t representationIndex) const;
480 /// When connecting a field to a page sink, the field's default column representation is subject
481 /// to adjustment according to the write options. E.g., if compression is turned off, encoded columns
482 /// are changed to their unencoded counterparts.
483 void AutoAdjustColumnTypes(const RNTupleWriteOptions &options);
484
485 /// Called by Clone(), which additionally copies the on-disk ID
486 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
487
488 /// Constructs value in a given location of size at least GetValueSize(). Called by the base class' CreateValue().
489 virtual void ConstructValue(void *where) const = 0;
490 virtual std::unique_ptr<RDeleter> GetDeleter() const { return std::make_unique<RDeleter>(); }
491 /// Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
492 static void CallConstructValueOn(const RFieldBase &other, void *where) { other.ConstructValue(where); }
493 static std::unique_ptr<RDeleter> GetDeleterOf(const RFieldBase &other) { return other.GetDeleter(); }
494
495 /// Operations on values of complex types, e.g. ones that involve multiple columns or for which no direct
496 /// column type exists.
497 virtual std::size_t AppendImpl(const void *from);
498 virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to);
499 virtual void ReadInClusterImpl(RClusterIndex clusterIndex, void *to)
500 {
502 }
503
504 /// Write the given value into columns. The value object has to be of the same type as the field.
505 /// Returns the number of uncompressed bytes written.
506 std::size_t Append(const void *from)
507 {
508 if (~fTraits & kTraitMappable)
509 return AppendImpl(from);
510
513 }
514
515 /// Populate a single value with data from the field. The memory location pointed to by to needs to be of the
516 /// fitting type. The fast path is conditioned by the field qualifying as simple, i.e. maps as-is
517 /// to a single column and has no read callback.
518 void Read(NTupleSize_t globalIndex, void *to)
519 {
520 if (fIsSimple)
521 return (void)fPrincipalColumn->Read(globalIndex, to);
522
524 fPrincipalColumn->Read(globalIndex, to);
525 else
526 ReadGlobalImpl(globalIndex, to);
527 if (R__unlikely(!fReadCallbacks.empty()))
529 }
530
531 void Read(RClusterIndex clusterIndex, void *to)
532 {
533 if (fIsSimple)
534 return (void)fPrincipalColumn->Read(clusterIndex, to);
535
537 fPrincipalColumn->Read(clusterIndex, to);
538 else
539 ReadInClusterImpl(clusterIndex, to);
540 if (R__unlikely(!fReadCallbacks.empty()))
542 }
543
544 /// General implementation of bulk read. Loop over the required range and read values that are required
545 /// and not already present. Derived classes may implement more optimized versions of this method.
546 /// See ReadBulk() for the return value.
547 virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec);
548
549 /// Returns the number of newly available values, that is the number of bools in bulkSpec.fMaskAvail that
550 /// flipped from false to true. As a special return value, kAllSet can be used if all values are read
551 /// independent from the masks.
552 std::size_t ReadBulk(const RBulkSpec &bulkSpec)
553 {
554 if (fIsSimple) {
555 /// For simple types, ignore the mask and memcopy the values into the destination
556 fPrincipalColumn->ReadV(bulkSpec.fFirstIndex, bulkSpec.fCount, bulkSpec.fValues);
557 std::fill(bulkSpec.fMaskAvail, bulkSpec.fMaskAvail + bulkSpec.fCount, true);
558 return RBulkSpec::kAllSet;
559 }
560
561 return ReadBulkImpl(bulkSpec);
562 }
563
564 /// Allow derived classes to call Append and Read on other (sub) fields.
565 static std::size_t CallAppendOn(RFieldBase &other, const void *from) { return other.Append(from); }
566 static void CallReadOn(RFieldBase &other, RClusterIndex clusterIndex, void *to) { other.Read(clusterIndex, to); }
567 static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to) { other.Read(globalIndex, to); }
568
569 /// Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBulk
571
572 /// Set a user-defined function to be called after reading a value, giving a chance to inspect and/or modify the
573 /// value object.
574 /// Returns an index that can be used to remove the callback.
575 size_t AddReadCallback(ReadCallback_t func);
576 void RemoveReadCallback(size_t idx);
577
578 // Perform housekeeping tasks for global to cluster-local index translation
579 virtual void CommitClusterImpl() {}
580 // The field can indicate that it needs to register extra type information in the on-disk schema.
581 // In this case, a callback from the page sink to the field will be registered on connect, so that the
582 // extra type information can be collected when the dataset gets committed.
583 virtual bool HasExtraTypeInfo() const { return false; }
584 // The page sink's callback when the data set gets committed will call this method to get the field's extra
585 // type information. This has to happen at the end of writing because the type information may change depending
586 // on the data that's written, e.g. for polymorphic types in the unsplit field.
588
589 /// Add a new subfield to the list of nested fields
590 void Attach(std::unique_ptr<RFieldBase> child);
591
592 /// Called by `ConnectPageSource()` once connected; derived classes may override this as appropriate
593 virtual void OnConnectPageSource() {}
594
595 /// Factory method to resurrect a field from the stored on-disk type information. This overload takes an already
596 /// normalized type name and type alias
597 /// TODO(jalopezg): this overload may eventually be removed leaving only the `RFieldBase::Create()` that takes a
598 /// single type name
599 static RResult<std::unique_ptr<RFieldBase>> Create(const std::string &fieldName, const std::string &canonicalType,
600 const std::string &typeAlias, bool fContinueOnError = false);
601
602public:
603 /// Iterates over the sub tree of fields in depth-first search order
604 template <bool IsConstT>
606 private:
607 struct Position {
608 using FieldPtr_t = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
609 Position() : fFieldPtr(nullptr), fIdxInParent(-1) {}
610 Position(FieldPtr_t fieldPtr, int idxInParent) : fFieldPtr(fieldPtr), fIdxInParent(idxInParent) {}
613 };
614 /// The stack of nodes visited when walking down the tree of fields
615 std::vector<Position> fStack;
616
617 public:
619 using iterator_category = std::forward_iterator_tag;
620 using difference_type = std::ptrdiff_t;
621 using value_type = std::conditional_t<IsConstT, const RFieldBase, RFieldBase>;
622 using pointer = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
623 using reference = std::conditional_t<IsConstT, const RFieldBase &, RFieldBase &>;
624
626 RSchemaIteratorTemplate(pointer val, int idxInParent) { fStack.emplace_back(Position(val, idxInParent)); }
628 /// Given that the iterator points to a valid field which is not the end iterator, go to the next field
629 /// in depth-first search order
630 void Advance()
631 {
632 auto itr = fStack.rbegin();
633 if (!itr->fFieldPtr->fSubFields.empty()) {
634 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
635 return;
636 }
637
638 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
639 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
640 if (fStack.size() == 1) {
641 itr->fFieldPtr = itr->fFieldPtr->fParent;
642 itr->fIdxInParent = -1;
643 return;
644 }
645 fStack.pop_back();
646 itr = fStack.rbegin();
647 nextIdxInParent = ++(itr->fIdxInParent);
648 }
649 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
650 }
651
652 iterator operator++(int) /* postfix */
653 {
654 auto r = *this;
655 Advance();
656 return r;
657 }
658 iterator &operator++() /* prefix */
659 {
660 Advance();
661 return *this;
662 }
663 reference operator*() const { return *fStack.back().fFieldPtr; }
664 pointer operator->() const { return fStack.back().fFieldPtr; }
665 bool operator==(const iterator &rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
666 bool operator!=(const iterator &rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
667 };
670
671 // This is used in CreateObject and is specialized for void
672 template <typename T>
674 using deleter = std::default_delete<T>;
675 };
676
677 /// Used in the return value of the Check() method
679 std::string fFieldName; ///< Qualified field name causing the error
680 std::string fTypeName; ///< Type name corresponding to the (sub) field
681 std::string fErrMsg; ///< Cause of the failure, e.g. unsupported type
682 };
683
684 /// The constructor creates the underlying column objects and connects them to either a sink or a source.
685 /// If `isSimple` is `true`, the trait `kTraitMappable` is automatically set on construction. However, the
686 /// field might be demoted to non-simple if a post-read callback is set.
687 RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple,
688 std::size_t nRepetitions = 0);
689 RFieldBase(const RFieldBase &) = delete;
690 RFieldBase(RFieldBase &&) = default;
691 RFieldBase &operator=(const RFieldBase &) = delete;
693 virtual ~RFieldBase() = default;
694
695 /// Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns
696 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
697
698 /// Factory method to resurrect a field from the stored on-disk type information
699 static RResult<std::unique_ptr<RFieldBase>> Create(const std::string &fieldName, const std::string &typeName);
700 /// Checks if the given type is supported by RNTuple. In case of success, the result vector is empty.
701 /// Otherwise there is an error record for each failing sub field (sub type).
702 static std::vector<RCheckResult> Check(const std::string &fieldName, const std::string &typeName);
703 /// Check whether a given string is a valid field name
704 static RResult<void> EnsureValidFieldName(std::string_view fieldName);
705
706 /// Generates an object of the field type and allocates new initialized memory according to the type.
707 /// Implemented at the end of this header because the implementation is using RField<T>::TypeName()
708 /// The returned object can be released with `delete`, i.e. it is valid to call
709 /// auto ptr = field->CreateObject();
710 /// delete ptr.release();
711 ///
712 /// Note that CreateObject<void> is supported. The returned unique_ptr has a custom deleter that reports an error
713 /// if it is called. The intended use of the returned unique_ptr<void> is to call `release()`. In this way, the
714 /// transfer of pointer ownership is explicit.
715 template <typename T>
716 std::unique_ptr<T, typename RCreateObjectDeleter<T>::deleter> CreateObject() const;
717 /// Generates an object of the field type and wraps the created object in a shared pointer and returns it an RValue
718 /// connected to the field.
720 /// The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values
721 RBulk CreateBulk() { return RBulk(this); }
722 /// Creates a value from a memory location with an already constructed object
723 RValue BindValue(std::shared_ptr<void> objPtr) { return RValue(this, objPtr); }
724 /// Creates the list of direct child values given a value for this field. E.g. a single value for the
725 /// correct variant or all the elements of a collection. The default implementation assumes no sub values
726 /// and returns an empty vector.
727 virtual std::vector<RValue> SplitValue(const RValue &value) const;
728 /// The number of bytes taken by a value of the appropriate type
729 virtual size_t GetValueSize() const = 0;
730 /// As a rule of thumb, the alignment is equal to the size of the type. There are, however, various exceptions
731 /// to this rule depending on OS and CPU architecture. So enforce the alignment to be explicitly spelled out.
732 virtual size_t GetAlignment() const = 0;
733 int GetTraits() const { return fTraits; }
734 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
735
736 const std::string &GetFieldName() const { return fName; }
737 /// Returns the field name and parent field names separated by dots ("grandparent.parent.child")
738 std::string GetQualifiedFieldName() const;
739 const std::string &GetTypeName() const { return fType; }
740 const std::string &GetTypeAlias() const { return fTypeAlias; }
742 std::size_t GetNRepetitions() const { return fNRepetitions; }
744 const RFieldBase *GetParent() const { return fParent; }
745 std::vector<RFieldBase *> GetSubFields();
746 std::vector<const RFieldBase *> GetSubFields() const;
747 bool IsSimple() const { return fIsSimple; }
748 /// Get the field's description
749 const std::string &GetDescription() const { return fDescription; }
750 void SetDescription(std::string_view description);
751 EState GetState() const { return fState; }
752
755
756 /// Returns the fColumnRepresentative pointee or, if unset, the field's default representative
758 /// Fixes a column representative. This can only be done _before_ connecting the field to a page sink.
759 /// Otherwise, or if the provided representation is not in the list of GetColumnRepresentations,
760 /// an exception is thrown
762 /// Whether or not an explicit column representative was set
764
765 /// Indicates an evolution of the mapping scheme from C++ type to columns
766 virtual std::uint32_t GetFieldVersion() const { return 0; }
767 /// Indicates an evolution of the C++ type itself
768 virtual std::uint32_t GetTypeVersion() const { return 0; }
769 /// Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
770 virtual std::uint32_t GetTypeChecksum() const { return 0; }
771 /// Return the C++ type version stored in the field descriptor; only valid after a call to `ConnectPageSource()`
772 std::uint32_t GetOnDiskTypeVersion() const { return fOnDiskTypeVersion; }
773 /// Return checksum stored in the field descriptor; only valid after a call to `ConnectPageSource()`,
774 /// if the field stored a type checksum
775 std::uint32_t GetOnDiskTypeChecksum() const { return fOnDiskTypeChecksum; }
776
778 {
779 return fSubFields.empty() ? RSchemaIterator(this, -1) : RSchemaIterator(fSubFields[0].get(), 0);
780 }
781 RSchemaIterator end() { return RSchemaIterator(this, -1); }
783 {
784 return fSubFields.empty() ? RConstSchemaIterator(this, -1) : RConstSchemaIterator(fSubFields[0].get(), 0);
785 }
786 RConstSchemaIterator cend() const { return RConstSchemaIterator(this, -1); }
787
788 virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const;
789}; // class RFieldBase
790
791namespace Internal {
792// At some point, RFieldBase::OnClusterCommit() may allow for a user-defined callback to change the
793// column representation. For now, we inject this for testing and internal use only.
795 static void SetPrimaryColumnRepresentation(RFieldBase &field, std::uint16_t newRepresentationIdx)
796 {
797 R__ASSERT(newRepresentationIdx < field.fColumnRepresentatives.size());
798 const auto N = field.fColumnRepresentatives[0].get().size();
799 R__ASSERT(N >= 1 && N <= 2);
801 field.fPrincipalColumn = field.fAvailableColumns[newRepresentationIdx * N].get();
802 if (field.fAuxiliaryColumn) {
803 R__ASSERT(N == 2);
804 field.fAuxiliaryColumn = field.fAvailableColumns[newRepresentationIdx * N + 1].get();
805 }
806 }
807};
808} // namespace Internal
809
810} // namespace Experimental
811} // namespace ROOT
812
813#endif
#define R__unlikely(expr)
Definition RConfig.hxx:586
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#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.
std::size_t GetPackedSize(std::size_t nElements=1U) const
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:42
NTupleSize_t GetGlobalIndex(RClusterIndex clusterIndex)
Definition RColumn.hxx:283
RColumnElementBase * GetElement() const
Definition RColumn.hxx:353
void Append(const void *from)
Definition RColumn.hxx:140
void ReadV(const NTupleSize_t globalIndex, const ClusterSize_t::ValueType count, void *to)
Definition RColumn.hxx:207
void Read(const NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:185
NTupleSize_t GetNElements() const
Definition RColumn.hxx:352
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
The collection field is only used for writing; when reading, untyped collections are projected to an ...
Definition RField.hxx:273
Field specific extra type information from the header / extenstion header.
Similar to RValue but manages an array of consecutive values.
bool fIsAdopted
True if the user provides the memory buffer for fValues.
void * ReadBulk(RClusterIndex firstIndex, const bool *maskReq, std::size_t size)
Reads 'size' values from the associated field, starting from 'firstIndex'.
RFieldBase * fField
The field that created the array of values.
std::vector< unsigned char > fAuxData
Reading arrays of complex values may require additional memory, for instance for the elements of arra...
bool ContainsRange(RClusterIndex firstIndex, std::size_t size) const
std::size_t fCapacity
The size of the array memory block in number of values.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
std::size_t fValueSize
Cached copy of fField->GetValueSize()
void AdoptBuffer(void *buf, std::size_t capacity)
Definition RField.cxx:529
void * GetValuePtrAt(std::size_t idx) const
RBulk & operator=(const RBulk &)=delete
void Reset(RClusterIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
Definition RField.cxx:496
std::size_t fNValidValues
The sum of non-zero elements in the fMask.
RClusterIndex fFirstIndex
Index of the first value of the array.
std::size_t fSize
The number of available values in the array (provided their mask is set)
void * fValues
Cached deleter of fField.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
Some fields have multiple possible column representations, e.g.
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.
const ColumnRepresentation_t & GetSerializationDefault() const
The first column list from fSerializationTypes is the default for writing.
A functor to release the memory acquired by CreateValue (memory and constructor).
virtual void operator()(void *objPtr, bool dtorOnly)
Iterates over the sub tree of fields in depth-first search order.
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > pointer
std::vector< Position > fStack
The stack of nodes visited when walking down the tree of fields.
void Advance()
Given that the iterator points to a valid field which is not the end iterator, go to the next field i...
std::conditional_t< IsConstT, const RFieldBase, RFieldBase > value_type
std::conditional_t< IsConstT, const RFieldBase &, RFieldBase & > reference
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.
RValue & operator=(RValue &&other)=default
void Read(NTupleSize_t globalIndex)
RFieldBase * fField
The field that created the RValue.
RValue & operator=(const RValue &)=default
const RFieldBase & GetField() const
void EmplaceNew()
Replace the current object pointer by a pointer to a new object constructed by the field.
std::shared_ptr< void > fObjPtr
Set by Bind() or by RFieldBase::CreateValue(), SplitValue() or BindValue()
std::shared_ptr< T > GetPtr() const
void Read(RClusterIndex clusterIndex)
void Bind(std::shared_ptr< void > objPtr)
RValue(RFieldBase *field, std::shared_ptr< void > objPtr)
A field translates read and write calls from/to underlying columns to/from tree values.
static constexpr std::uint32_t kInvalidTypeVersion
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
const std::string & GetTypeAlias() const
const RFieldBase * GetParent() const
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponsing to the field type ...
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition RField.cxx:933
bool HasDefaultColumnRepresentative() const
Whether or not an explicit column representative was set.
std::uint32_t fOnDiskTypeVersion
C++ type version cached from the descriptor after a call to ConnectPageSource()
std::uint32_t GetOnDiskTypeChecksum() const
Return checksum stored in the field descriptor; only valid after a call to ConnectPageSource(),...
void AutoAdjustColumnTypes(const RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
Definition RField.cxx:1085
RFieldBase & operator=(RFieldBase &&)=default
void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives)
Fixes a column representative.
Definition RField.cxx:1020
ENTupleStructure fStructure
The role of this field in the data model structure.
std::vector< RFieldBase * > GetSubFields()
Definition RField.cxx:956
static std::vector< RCheckResult > Check(const std::string &fieldName, const std::string &typeName)
Checks if the given type is supported by RNTuple.
Definition RField.cxx:593
virtual void GenerateColumns(const RNTupleDescriptor &)
Implementations in derived classes should create the backing columns corresponsing to the field type ...
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
virtual bool HasExtraTypeInfo() const
std::function< void(void *)> ReadCallback_t
EState fState
Changed by ConnectTo[Sink,Source], reset by Clone()
static constexpr int kTraitTriviallyConstructible
No constructor needs to be called, i.e.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
const std::string & GetDescription() const
Get the field's description.
const std::string & GetFieldName() const
RConstSchemaIterator cbegin() const
RSchemaIteratorTemplate< false > RSchemaIterator
ENTupleStructure GetStructure() const
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
const std::string & GetTypeName() const
RFieldBase(RFieldBase &&)=default
virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const
Definition RField.cxx:1193
std::string fDescription
Free text set by the user.
static Internal::RColumn * GetPrincipalColumnOf(const RFieldBase &other)
Fields may need direct access to the principal column of their sub fields, e.g. in RRVecField::ReadBu...
friend struct ROOT::Experimental::Internal::RFieldCallbackInjector
std::size_t fNRepetitions
For fixed sized arrays, the array length.
RFieldBase & operator=(const RFieldBase &)=delete
RFieldBase * fParent
Sub fields point to their mother field.
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:504
static std::size_t CallAppendOn(RFieldBase &other, const void *from)
Allow derived classes to call Append and Read on other (sub) fields.
int fTraits
Properties of the type that allow for optimizations of collections of that type.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
Internal::RColumn * fAuxiliaryColumn
Some fields have a second column in its column representation.
void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
Definition RField.cxx:1120
DescriptorId_t fOnDiskId
When the columns are connected to a page source or page sink, the field represents a field id in the ...
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
Definition RField.cxx:882
static constexpr int kTraitTypeChecksum
The TClass checksum is set and valid.
RConstSchemaIterator cend() const
void Read(NTupleSize_t globalIndex, void *to)
Populate a single value with data from the field.
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
virtual RExtraTypeInfoDescriptor GetExtraTypeInfo() const
std::vector< std::reference_wrapper< const ColumnRepresentation_t > > fColumnRepresentatives
Pointers into the static vector GetColumnRepresentations().GetSerializationTypes() when SetColumnRepr...
std::uint32_t GetOnDiskTypeVersion() const
Return the C++ type version stored in the field descriptor; only valid after a call to ConnectPageSou...
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots ("grandparent.parent....
Definition RField.cxx:573
virtual std::uint32_t GetTypeVersion() const
Indicates an evolution of the C++ type itself.
std::vector< EColumnType > ColumnRepresentation_t
void GenerateColumnsImpl(const RNTupleDescriptor &desc)
For reading, use the on-disk column list.
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
Definition RField.cxx:893
void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
Helpers for generating columns.
virtual std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const =0
Called by Clone(), which additionally copies the on-disk ID.
std::size_t Append(const void *from)
Write the given value into columns.
RFieldBase(const RFieldBase &)=delete
void RemoveReadCallback(size_t idx)
Definition RField.cxx:1079
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
Definition RField.cxx:913
virtual std::uint32_t GetTypeChecksum() const
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl.
Definition RField.cxx:976
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc, std::uint16_t representationIndex) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given represe...
Definition RField.cxx:1037
void ConnectPageSource(Internal::RPageSource &pageSource)
Connects the field and its sub field tree to the given page source.
Definition RField.cxx:1146
RValue CreateValue()
Generates an object of the field type and wraps the created object in a shared pointer and returns it...
Definition RField.cxx:921
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns.
Definition RField.cxx:871
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
virtual std::unique_ptr< RDeleter > GetDeleter() const
virtual void ReadInClusterImpl(RClusterIndex clusterIndex, void *to)
static void CallReadOn(RFieldBase &other, RClusterIndex clusterIndex, void *to)
virtual std::uint32_t GetFieldVersion() const
Indicates an evolution of the mapping scheme from C++ type to columns.
virtual void ConstructValue(void *where) const =0
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, bool fContinueOnError=false)
Factory method to resurrect a field from the stored on-disk type information.
Definition RField.cxx:614
RSchemaIteratorTemplate< true > RConstSchemaIterator
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...
Definition RField.cxx:1072
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given a value for this field.
Definition RField.cxx:928
std::vector< std::unique_ptr< Internal::RColumn > > fAvailableColumns
The columns are connected either to a sink or to a source (not to both); they are owned by the field.
void SetOnDiskId(DescriptorId_t id)
Definition RField.cxx:998
std::size_t GetNRepetitions() const
RColumnRepresentations::Selection_t GetColumnRepresentatives() const
Returns the fColumnRepresentative pointee or, if unset, the field's default representative.
Definition RField.cxx:1006
virtual ~RFieldBase()=default
std::string fName
The field name relative to its parent field.
virtual size_t GetAlignment() const =0
As a rule of thumb, the alignment is equal to the size of the type.
RBulk CreateBulk()
The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values.
void InvokeReadCallbacks(void *target)
std::uint32_t fOnDiskTypeChecksum
TClass checksum cached from the descriptor after a call to ConnectPageSource().
virtual void OnConnectPageSource()
Called by ConnectPageSource() once connected; derived classes may override this as appropriate.
static void CallReadOn(RFieldBase &other, NTupleSize_t globalIndex, void *to)
void Read(RClusterIndex clusterIndex, void *to)
static void CallConstructValueOn(const RFieldBase &other, void *where)
Allow derived classes to call ConstructValue(void *) and GetDeleter on other (sub) fields.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
std::string fType
The C++ type captured by this field.
Internal::RColumn * fPrincipalColumn
All fields that have columns have a distinct main column.
DescriptorId_t GetOnDiskId() const
virtual size_t GetValueSize() const =0
The number of bytes taken by a value of the appropriate type.
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
EState
During its lifetime, a field undergoes the following possible state transitions:
std::vector< ReadCallback_t > fReadCallbacks
List of functions to be called after reading a value.
void SetDescription(std::string_view description)
Definition RField.cxx:991
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition RField.cxx:854
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
Definition RField.cxx:944
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
Definition RField.cxx:888
NTupleSize_t GetNElements() const
void GenerateColumnsImpl()
For writing, use the currently set column representative.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:865
The on-storage meta-data of an ntuple.
Common user-tunable settings for storing ntuples.
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:194
void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry=0)
Definition RField.cxx:407
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
Definition RField.cxx:412
void CallCommitClusterOnField(RFieldBase &)
Definition RField.cxx:403
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static void SetPrimaryColumnRepresentation(RFieldBase &field, std::uint16_t newRepresentationIdx)
Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information.
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
std::size_t fCount
Size of the bulk range.
RClusterIndex fFirstIndex
Start of the bulk range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
static const std::size_t kAllSet
As a return value of ReadBulk and ReadBulkImpl(), indicates that the full bulk range was read indepen...
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.
std::conditional_t< IsConstT, const RFieldBase *, RFieldBase * > FieldPtr_t
RSharedPtrDeleter(std::unique_ptr< RFieldBase::RDeleter > deleter)
std::unique_ptr< RFieldBase::RDeleter > fDeleter