Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldSequenceContainer.cxx
Go to the documentation of this file.
1/// \file RFieldSequenceContainer.cxx
2/// \ingroup NTuple
3/// \author Jonas Hahnfeld <jonas.hahnfeld@cern.ch>
4/// \date 2024-11-19
5
6#include <ROOT/RField.hxx>
7#include <ROOT/RFieldBase.hxx>
10
11#include <cstdlib> // for malloc, free
12#include <limits>
13#include <memory>
14#include <new> // hardware_destructive_interference_size
15
16namespace {
17
18std::vector<ROOT::RFieldBase::RValue> SplitVector(std::shared_ptr<void> valuePtr, ROOT::RFieldBase &itemField)
19{
20 auto *vec = static_cast<std::vector<char> *>(valuePtr.get());
21 const auto itemSize = itemField.GetValueSize();
23 R__ASSERT((vec->size() % itemSize) == 0);
24 const auto nItems = vec->size() / itemSize;
25 std::vector<ROOT::RFieldBase::RValue> result;
26 result.reserve(nItems);
27 for (unsigned i = 0; i < nItems; ++i) {
28 result.emplace_back(itemField.BindValue(std::shared_ptr<void>(valuePtr, vec->data() + (i * itemSize))));
29 }
30 return result;
31}
32
33std::size_t GetSizeOfVector()
34{
35 return sizeof(std::vector<char>);
36}
37
38std::size_t GetAlignOfVector()
39{
40 return alignof(std::vector<char>);
41}
42
43} // anonymous namespace
44
45ROOT::RArrayField::RArrayField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
46 std::size_t arrayLength)
48 "std::array<" + itemField->GetTypeName() + "," +
49 Internal::GetNormalizedInteger(static_cast<unsigned long long>(arrayLength)) + ">",
50 ROOT::ENTupleStructure::kPlain, false /* isSimple */, arrayLength),
51 fItemSize(itemField->GetValueSize()),
52 fArrayLength(arrayLength)
53{
54 fTraits |= itemField->GetTraits() & ~kTraitMappable;
55 if (!itemField->GetTypeAlias().empty()) {
56 fTypeAlias = "std::array<" + itemField->GetTypeAlias() + "," +
57 Internal::GetNormalizedInteger(static_cast<unsigned long long>(arrayLength)) + ">";
58 }
59 Attach(std::move(itemField), "_0");
60}
61
62std::unique_ptr<ROOT::RFieldBase> ROOT::RArrayField::CloneImpl(std::string_view newName) const
63{
64 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
65 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
66}
67
68std::size_t ROOT::RArrayField::AppendImpl(const void *from)
69{
70 std::size_t nbytes = 0;
71 if (fSubfields[0]->IsSimple()) {
72 GetPrincipalColumnOf(*fSubfields[0])->AppendV(from, fArrayLength);
73 nbytes += fArrayLength * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
74 } else {
75 auto arrayPtr = static_cast<const unsigned char *>(from);
76 for (unsigned i = 0; i < fArrayLength; ++i) {
77 nbytes += CallAppendOn(*fSubfields[0], arrayPtr + (i * fItemSize));
78 }
79 }
80 return nbytes;
81}
82
84{
85 if (fSubfields[0]->IsSimple()) {
86 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, to);
87 } else {
88 auto arrayPtr = static_cast<unsigned char *>(to);
89 for (unsigned i = 0; i < fArrayLength; ++i) {
90 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
91 }
92 }
93}
94
96{
97 if (fSubfields[0]->IsSimple()) {
98 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, to);
99 } else {
100 auto arrayPtr = static_cast<unsigned char *>(to);
101 for (unsigned i = 0; i < fArrayLength; ++i) {
102 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
103 }
104 }
105}
106
108{
109 if (!fSubfields[0]->IsSimple())
111
112 GetPrincipalColumnOf(*fSubfields[0])
113 ->ReadV(bulkSpec.fFirstIndex * fArrayLength, bulkSpec.fCount * fArrayLength, bulkSpec.fValues);
114 return RBulkSpec::kAllSet;
115}
116
118{
119 static const std::vector<std::string> prefixes = {"std::array<"};
120
121 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
122 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
123}
124
126{
127 if (fSubfields[0]->GetTraits() & kTraitTriviallyConstructible)
128 return;
129
130 auto arrayPtr = reinterpret_cast<unsigned char *>(where);
131 for (unsigned i = 0; i < fArrayLength; ++i) {
132 CallConstructValueOn(*fSubfields[0], arrayPtr + (i * fItemSize));
133 }
134}
135
137{
138 if (fItemDeleter) {
139 for (unsigned i = 0; i < fArrayLength; ++i) {
140 fItemDeleter->operator()(reinterpret_cast<unsigned char *>(objPtr) + i * fItemSize, true /* dtorOnly */);
141 }
142 }
143 RDeleter::operator()(objPtr, dtorOnly);
144}
145
146std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RArrayField::GetDeleter() const
147{
148 if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
149 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetDeleterOf(*fSubfields[0]));
150 return std::make_unique<RDeleter>();
151}
152
153std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayField::SplitValue(const RValue &value) const
154{
155 auto valuePtr = value.GetPtr<void>();
156 auto arrayPtr = static_cast<unsigned char *>(valuePtr.get());
157 std::vector<RValue> result;
158 result.reserve(fArrayLength);
159 for (unsigned i = 0; i < fArrayLength; ++i) {
160 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, arrayPtr + (i * fItemSize))));
161 }
162 return result;
163}
164
166{
167 visitor.VisitArrayField(*this);
168}
169
170//------------------------------------------------------------------------------
171
172ROOT::RRVecField::RRVecField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
173 : ROOT::RFieldBase(fieldName, "ROOT::VecOps::RVec<" + itemField->GetTypeName() + ">",
174 ROOT::ENTupleStructure::kCollection, false /* isSimple */),
175 fItemSize(itemField->GetValueSize()),
176 fNWritten(0)
177{
178 if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
180 if (!itemField->GetTypeAlias().empty())
181 fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
182 Attach(std::move(itemField), "_0");
183 fValueSize =
185
186 // Determine if we can optimimize bulk reading
187 if (fSubfields[0]->IsSimple()) {
188 fBulkSubfield = fSubfields[0].get();
189 } else {
190 if (auto f = dynamic_cast<RArrayField *>(fSubfields[0].get())) {
191 auto grandChildFields = fSubfields[0]->GetMutableSubfields();
192 if (grandChildFields[0]->IsSimple()) {
194 fBulkNRepetition = f->GetLength();
195 }
196 }
197 }
198}
199
200std::unique_ptr<ROOT::RFieldBase> ROOT::RRVecField::CloneImpl(std::string_view newName) const
201{
202 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
203 return std::make_unique<RRVecField>(newName, std::move(newItemField));
204}
205
206std::size_t ROOT::RRVecField::AppendImpl(const void *from)
207{
209
210 std::size_t nbytes = 0;
211 if (fSubfields[0]->IsSimple() && *sizePtr) {
212 GetPrincipalColumnOf(*fSubfields[0])->AppendV(*beginPtr, *sizePtr);
213 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
214 } else {
215 for (std::int32_t i = 0; i < *sizePtr; ++i) {
216 nbytes += CallAppendOn(*fSubfields[0], *beginPtr + i * fItemSize);
217 }
218 }
219
220 fNWritten += *sizePtr;
221 fPrincipalColumn->Append(&fNWritten);
222 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
223}
224
225unsigned char *ROOT::RRVecField::ResizeRVec(void *rvec, std::size_t nItems, std::size_t itemSize,
227
228{
229 if (nItems > static_cast<std::size_t>(std::numeric_limits<std::int32_t>::max())) {
230 throw RException(R__FAIL("RVec too large: " + std::to_string(nItems)));
231 }
232
234 const std::size_t oldSize = *sizePtr;
235
236 if (oldSize == nItems) {
237 // If neither shrink nor grow is necessary, do nothing.
238 // Note that this case preserves a memory adopting RVec as such. All real resizes in either direction
239 // transform a memory adopting RVec into an owning RVec.
240 return *beginPtr;
241 }
242
243 // See "semantics of reading non-trivial objects" in RNTuple's Architecture.md for details
244 // on the element construction/destrution.
245 const bool owns = (*capacityPtr != -1);
246 const bool needsConstruct = !(itemField->GetTraits() & kTraitTriviallyConstructible);
247 const bool needsDestruct = owns && itemDeleter;
248
249 // Destroy excess elements, if any
250 if (needsDestruct) {
251 for (std::size_t i = nItems; i < oldSize; ++i) {
252 itemDeleter->operator()(*beginPtr + (i * itemSize), true /* dtorOnly */);
253 }
254 }
255
256 // Resize RVec (capacity and size)
257 if (std::int32_t(nItems) > *capacityPtr) { // must reallocate
258 // Destroy old elements: useless work for trivial types, but in case the element type's constructor
259 // allocates memory we need to release it here to avoid memleaks (e.g. if this is an RVec<RVec<int>>)
260 if (needsDestruct) {
261 for (std::size_t i = 0u; i < oldSize; ++i) {
262 itemDeleter->operator()(*beginPtr + (i * itemSize), true /* dtorOnly */);
263 }
264 }
265
266 // TODO Increment capacity by a factor rather than just enough to fit the elements.
267 if (owns) {
268 // *beginPtr points to the array of item values (allocated in an earlier call by the following malloc())
269 free(*beginPtr);
270 }
271 // We trust that malloc returns a buffer with large enough alignment.
272 // This might not be the case if T in RVec<T> is over-aligned.
273 *beginPtr = static_cast<unsigned char *>(malloc(nItems * itemSize));
274 R__ASSERT(*beginPtr != nullptr);
276
277 // Placement new for elements that were already there before the resize
278 if (needsConstruct) {
279 for (std::size_t i = 0u; i < oldSize; ++i)
280 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
281 }
282 }
283 *sizePtr = nItems;
284
285 // Placement new for new elements, if any
286 if (needsConstruct) {
287 for (std::size_t i = oldSize; i < nItems; ++i)
288 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
289 }
290
291 return *beginPtr;
292}
293
295{
296 // TODO as a performance optimization, we could assign values to elements of the inline buffer:
297 // if size < inline buffer size: we save one allocation here and usage of the RVec skips a pointer indirection
298
299 // Read collection info for this entry
302 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
303
304 auto begin = ResizeRVec(to, nItems, fItemSize, fSubfields[0].get(), fItemDeleter.get());
305
306 if (fSubfields[0]->IsSimple() && nItems) {
307 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, begin);
308 return;
309 }
310
311 // Read the new values into the collection elements
312 for (std::size_t i = 0; i < nItems; ++i) {
313 CallReadOn(*fSubfields[0], collectionStart + i, begin + (i * fItemSize));
314 }
315}
316
318{
319 if (!fBulkSubfield)
321
322 if (bulkSpec.fAuxData->empty()) {
323 /// Initialize auxiliary memory: the first sizeof(size_t) bytes store the value size of the item field.
324 /// The following bytes store the item values, consecutively.
325 bulkSpec.fAuxData->resize(sizeof(std::size_t));
326 *reinterpret_cast<std::size_t *>(bulkSpec.fAuxData->data()) = fBulkNRepetition * fBulkSubfield->GetValueSize();
327 }
328 const auto itemValueSize = *reinterpret_cast<std::size_t *>(bulkSpec.fAuxData->data());
329 unsigned char *itemValueArray = bulkSpec.fAuxData->data() + sizeof(std::size_t);
331
332 // Get size of the first RVec of the bulk
335 fPrincipalColumn->GetCollectionInfo(bulkSpec.fFirstIndex, &firstItemIndex, &collectionSize);
338 *capacityPtr = -1;
339
340 // Set the size of the remaining RVecs of the bulk, going page by page through the RNTuple offset column.
341 // We optimistically assume that bulkSpec.fAuxData is already large enough to hold all the item values in the
342 // given range. If not, we'll fix up the pointers afterwards.
343 auto lastOffset = firstItemIndex.GetIndexInCluster() + collectionSize;
345 std::size_t nValues = 1;
346 std::size_t nItems = collectionSize;
347 while (nRemainingValues > 0) {
349 const auto offsets =
350 fPrincipalColumn->MapV<ROOT::Internal::RColumnIndex>(bulkSpec.fFirstIndex + nValues, nElementsUntilPageEnd);
351 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
352 for (std::size_t i = 0; i < nBatch; ++i) {
353 const auto size = offsets[i] - lastOffset;
355 reinterpret_cast<unsigned char *>(bulkSpec.fValues) + (nValues + i) * fValueSize);
357 *sizePtr = size;
358 *capacityPtr = -1;
359
360 nItems += size;
361 lastOffset = offsets[i];
362 }
364 nValues += nBatch;
365 }
366
367 bulkSpec.fAuxData->resize(sizeof(std::size_t) + nItems * itemValueSize);
368 // If the vector got reallocated, we need to fix-up the RVecs begin pointers.
369 const auto delta = itemValueArray - (bulkSpec.fAuxData->data() + sizeof(std::size_t));
370 if (delta != 0) {
371 auto beginPtrAsUChar = reinterpret_cast<unsigned char *>(bulkSpec.fValues);
372 for (std::size_t i = 0; i < bulkSpec.fCount; ++i) {
373 *reinterpret_cast<unsigned char **>(beginPtrAsUChar) -= delta;
375 }
376 }
377
378 GetPrincipalColumnOf(*fBulkSubfield)
379 ->ReadV(firstItemIndex * fBulkNRepetition, nItems * fBulkNRepetition, itemValueArray - delta);
380 return RBulkSpec::kAllSet;
381}
382
392
397
402
404{
405 if (GetOnDiskId() == kInvalidDescriptorId)
406 return nullptr;
407
408 const auto descGuard = pageSource.GetSharedDescriptorGuard();
409 const auto &fieldDesc = descGuard->GetFieldDescriptor(GetOnDiskId());
410 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
411 auto substitute = std::make_unique<RArrayAsRVecField>(
412 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
413 substitute->SetOnDiskId(GetOnDiskId());
414 return substitute;
415 }
416 return nullptr;
417}
418
420{
421 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
422}
423
425{
426 // initialize data members fBegin, fSize, fCapacity
427 // currently the inline buffer is left uninitialized
428 void **beginPtr = new (where)(void *)(nullptr);
429 std::int32_t *sizePtr = new (reinterpret_cast<void *>(beginPtr + 1)) std::int32_t(0);
430 new (sizePtr + 1) std::int32_t(-1);
431}
432
434{
436
437 if (fItemDeleter) {
438 for (std::int32_t i = 0; i < *sizePtr; ++i) {
439 fItemDeleter->operator()(*beginPtr + i * fItemSize, true /* dtorOnly */);
440 }
441 }
442
444 RDeleter::operator()(objPtr, dtorOnly);
445}
446
447std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRVecField::GetDeleter() const
448{
449 if (fItemDeleter)
450 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubfields[0]));
451 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment());
452}
453
454std::vector<ROOT::RFieldBase::RValue> ROOT::RRVecField::SplitValue(const RValue &value) const
455{
456 auto [beginPtr, sizePtr, _] = Internal::GetRVecDataMembers(value.GetPtr<void>().get());
457
458 std::vector<RValue> result;
459 result.reserve(*sizePtr);
460 for (std::int32_t i = 0; i < *sizePtr; ++i) {
461 result.emplace_back(
462 fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), *beginPtr + i * fItemSize)));
463 }
464 return result;
465}
466
468{
469 return fValueSize;
470}
471
473{
474 return Internal::EvalRVecAlignment(fSubfields[0]->GetAlignment());
475}
476
478{
479 visitor.VisitRVecField(*this);
480}
481
482//------------------------------------------------------------------------------
483
484ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
485 std::optional<std::string_view> emulatedFromType)
486 : ROOT::RFieldBase(fieldName, emulatedFromType ? *emulatedFromType : "std::vector<" + itemField->GetTypeName() + ">",
487 ROOT::ENTupleStructure::kCollection, false /* isSimple */),
488 fItemSize(itemField->GetValueSize()),
489 fNWritten(0)
490{
491 if (emulatedFromType && !emulatedFromType->empty())
493
494 if (!itemField->GetTypeAlias().empty())
495 fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
496
497 if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
499 Attach(std::move(itemField), "_0");
500}
501
502ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
504{
505}
506
507std::unique_ptr<ROOT::RVectorField>
508ROOT::RVectorField::CreateUntyped(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
509{
510 return std::unique_ptr<ROOT::RVectorField>(new RVectorField(fieldName, itemField->Clone("_0"), ""));
511}
512
513std::unique_ptr<ROOT::RFieldBase> ROOT::RVectorField::CloneImpl(std::string_view newName) const
514{
515 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
516 auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
517 auto emulatedFromType = isUntyped ? std::make_optional(GetTypeName()) : std::nullopt;
518 return std::unique_ptr<ROOT::RVectorField>(new RVectorField(newName, std::move(newItemField), emulatedFromType));
519}
520
521std::size_t ROOT::RVectorField::AppendImpl(const void *from)
522{
523 auto typedValue = static_cast<const std::vector<char> *>(from);
524 // The order is important here: Profiling showed that the integer division is on the critical path. By moving the
525 // computation of count before R__ASSERT, the compiler can use the result of a single instruction (on x86) also for
526 // the modulo operation. Otherwise, it must perform the division twice because R__ASSERT expands to an external call
527 // of Fatal() in case of failure, which could have side effects that the compiler cannot analyze.
528 auto count = typedValue->size() / fItemSize;
529 R__ASSERT((typedValue->size() % fItemSize) == 0);
530 std::size_t nbytes = 0;
531
532 if (fSubfields[0]->IsSimple() && count) {
533 GetPrincipalColumnOf(*fSubfields[0])->AppendV(typedValue->data(), count);
534 nbytes += count * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
535 } else {
536 for (unsigned i = 0; i < count; ++i) {
537 nbytes += CallAppendOn(*fSubfields[0], typedValue->data() + (i * fItemSize));
538 }
539 }
540
541 fNWritten += count;
542 fPrincipalColumn->Append(&fNWritten);
543 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
544}
545
546void ROOT::RVectorField::ResizeVector(void *vec, std::size_t nItems, std::size_t itemSize, const RFieldBase &itemField,
548{
549 auto typedValue = static_cast<std::vector<char> *>(vec);
550
551 // See "semantics of reading non-trivial objects" in RNTuple's Architecture.md
552 R__ASSERT(itemSize > 0);
553 const auto oldNItems = typedValue->size() / itemSize;
554 const auto availNItems = typedValue->capacity() / itemSize;
555 const bool canRealloc = availNItems < nItems;
556 bool allDeallocated = false;
557 if (itemDeleter) {
559 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
560 itemDeleter->operator()(typedValue->data() + (i * itemSize), true /* dtorOnly */);
561 }
562 }
563 typedValue->resize(nItems * itemSize);
564 if (!(itemField.GetTraits() & kTraitTriviallyConstructible)) {
565 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
566 CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));
567 }
568 }
569}
570
572{
573 auto typedValue = static_cast<std::vector<char> *>(to);
574
577 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
578
579 if (fSubfields[0]->IsSimple()) {
580 typedValue->resize(nItems * fItemSize);
581 if (nItems)
582 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, typedValue->data());
583 return;
584 }
585
586 ResizeVector(to, nItems, fItemSize, *fSubfields[0], fItemDeleter.get());
587
588 for (std::size_t i = 0; i < nItems; ++i) {
589 CallReadOn(*fSubfields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
590 }
591}
592
602
607
612
614{
615 if (GetOnDiskId() == kInvalidDescriptorId)
616 return nullptr;
617
618 const auto descGuard = pageSource.GetSharedDescriptorGuard();
619 const auto &fieldDesc = descGuard->GetFieldDescriptor(GetOnDiskId());
620 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
621 auto substitute = std::make_unique<RArrayAsVectorField>(
622 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
623 substitute->SetOnDiskId(GetOnDiskId());
624 return substitute;
625 }
626 return nullptr;
627}
628
630{
631 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
632}
633
635{
636 auto vecPtr = static_cast<std::vector<char> *>(objPtr);
637 if (fItemDeleter) {
638 R__ASSERT(fItemSize > 0);
639 R__ASSERT((vecPtr->size() % fItemSize) == 0);
640 auto nItems = vecPtr->size() / fItemSize;
641 for (std::size_t i = 0; i < nItems; ++i) {
642 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize), true /* dtorOnly */);
643 }
644 }
645 std::destroy_at(vecPtr);
646 RDeleter::operator()(objPtr, dtorOnly);
647}
648
649std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RVectorField::GetDeleter() const
650{
651 if (fItemDeleter)
652 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubfields[0]));
653 return std::make_unique<RVectorDeleter>();
654}
655
656std::vector<ROOT::RFieldBase::RValue> ROOT::RVectorField::SplitValue(const RValue &value) const
657{
658 return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
659}
660
662{
663 return GetSizeOfVector();
664}
665
667{
668 return GetAlignOfVector();
669}
670
672{
673 visitor.VisitVectorField(*this);
674}
675
676//------------------------------------------------------------------------------
677
678ROOT::RField<std::vector<bool>>::RField(std::string_view name)
679 : ROOT::RFieldBase(name, "std::vector<bool>", ROOT::ENTupleStructure::kCollection, false /* isSimple */)
680{
681 Attach(std::make_unique<RField<bool>>("_0"));
682}
683
684std::size_t ROOT::RField<std::vector<bool>>::AppendImpl(const void *from)
685{
686 auto typedValue = static_cast<const std::vector<bool> *>(from);
687 auto count = typedValue->size();
688 for (unsigned i = 0; i < count; ++i) {
689 bool bval = (*typedValue)[i];
690 CallAppendOn(*fSubfields[0], &bval);
691 }
692 fNWritten += count;
693 fPrincipalColumn->Append(&fNWritten);
694 return count + fPrincipalColumn->GetElement()->GetPackedSize();
695}
696
698{
699 auto typedValue = static_cast<std::vector<bool> *>(to);
700
701 if (fOnDiskNRepetitions == 0) {
703 RNTupleLocalIndex collectionStart;
704 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
705 typedValue->resize(nItems);
706 for (std::size_t i = 0; i < nItems; ++i) {
707 bool bval;
708 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
709 (*typedValue)[i] = bval;
710 }
711 } else {
712 typedValue->resize(fOnDiskNRepetitions);
713 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
714 bool bval;
715 CallReadOn(*fSubfields[0], globalIndex * fOnDiskNRepetitions + i, &bval);
716 (*typedValue)[i] = bval;
717 }
718 }
719}
720
721void ROOT::RField<std::vector<bool>>::ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to)
722{
723 auto typedValue = static_cast<std::vector<bool> *>(to);
724
725 if (fOnDiskNRepetitions == 0) {
727 RNTupleLocalIndex collectionStart;
728 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &nItems);
729 typedValue->resize(nItems);
730 for (std::size_t i = 0; i < nItems; ++i) {
731 bool bval;
732 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
733 (*typedValue)[i] = bval;
734 }
735 } else {
736 typedValue->resize(fOnDiskNRepetitions);
737 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
738 bool bval;
739 CallReadOn(*fSubfields[0], localIndex * fOnDiskNRepetitions + i, &bval);
740 (*typedValue)[i] = bval;
741 }
742 }
743}
744
745const ROOT::RFieldBase::RColumnRepresentations &ROOT::RField<std::vector<bool>>::GetColumnRepresentations() const
746{
747 static RColumnRepresentations representations({{ENTupleColumnType::kSplitIndex64},
751 {{}});
752 return representations;
753}
754
755void ROOT::RField<std::vector<bool>>::GenerateColumns()
756{
757 R__ASSERT(fOnDiskNRepetitions == 0); // fOnDiskNRepetitions must only be used for reading
759}
760
761void ROOT::RField<std::vector<bool>>::GenerateColumns(const ROOT::RNTupleDescriptor &desc)
762{
763 if (fOnDiskNRepetitions == 0)
765}
766
767void ROOT::RField<std::vector<bool>>::ReconcileOnDiskField(const RNTupleDescriptor &desc)
768{
769 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
770
771 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
772 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
773
774 if (fieldDesc.GetNRepetitions() == 0) {
775 throw RException(R__FAIL("fixed-size array --> std::vector<bool>: expected repetition count > 0\n" +
776 Internal::GetTypeTraceReport(*this, desc)));
777 }
778 if (fieldDesc.GetStructure() != ENTupleStructure::kPlain) {
779 throw RException(R__FAIL("fixed-size array --> std::vector<bool>: expected plain on-disk field\n" +
780 Internal::GetTypeTraceReport(*this, desc)));
781 }
782 fOnDiskNRepetitions = fieldDesc.GetNRepetitions();
783 } else {
784 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
785 }
786}
787
788std::vector<ROOT::RFieldBase::RValue> ROOT::RField<std::vector<bool>>::SplitValue(const RValue &value) const
789{
790 const auto &typedValue = value.GetRef<std::vector<bool>>();
791 auto count = typedValue.size();
792 std::vector<RValue> result;
793 result.reserve(count);
794 for (unsigned i = 0; i < count; ++i) {
795 if (typedValue[i]) {
796 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(new bool(true))));
797 } else {
798 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(new bool(false))));
799 }
800 }
801 return result;
802}
803
805{
806 visitor.VisitVectorBoolField(*this);
807}
808
809//------------------------------------------------------------------------------
810
811ROOT::RArrayAsRVecField::RArrayAsRVecField(std::string_view fieldName, std::unique_ptr<ROOT::RFieldBase> itemField,
812 std::size_t arrayLength)
813 : ROOT::RFieldBase(fieldName, "ROOT::VecOps::RVec<" + itemField->GetTypeName() + ">",
814 ROOT::ENTupleStructure::kCollection, false /* isSimple */),
815 fItemSize(itemField->GetValueSize()),
816 fArrayLength(arrayLength)
817{
818 if (!itemField->GetTypeAlias().empty())
819 fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
820 Attach(std::move(itemField), "_0");
821 fValueSize =
825}
826
827std::unique_ptr<ROOT::RFieldBase> ROOT::RArrayAsRVecField::CloneImpl(std::string_view newName) const
828{
829 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
830 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
831}
832
834{
835 // initialize data members fBegin, fSize, fCapacity
836 // currently the inline buffer is left uninitialized
837 void **beginPtr = new (where)(void *)(nullptr);
838 std::int32_t *sizePtr = new (static_cast<void *>(beginPtr + 1)) std::int32_t(0);
839 new (sizePtr + 1) std::int32_t(-1);
840}
841
842std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RArrayAsRVecField::GetDeleter() const
843{
844 if (fItemDeleter) {
845 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize,
846 GetDeleterOf(*fSubfields[0]));
847 }
848 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment());
849}
850
852{
853 auto begin = RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
854
855 if (fSubfields[0]->IsSimple()) {
856 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, begin);
857 return;
858 }
859
860 // Read the new values into the collection elements
861 for (std::size_t i = 0; i < fArrayLength; ++i) {
862 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, begin + (i * fItemSize));
863 }
864}
865
867{
868 auto begin = RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
869
870 if (fSubfields[0]->IsSimple()) {
871 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, begin);
872 return;
873 }
874
875 // Read the new values into the collection elements
876 for (std::size_t i = 0; i < fArrayLength; ++i) {
877 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, begin + (i * fItemSize));
878 }
879}
880
882{
883 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
884 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
885 if (fieldDesc.GetTypeName().rfind("std::array<", 0) != 0) {
886 throw RException(R__FAIL("RArrayAsRVecField " + GetQualifiedFieldName() + " expects an on-disk array field\n" +
887 Internal::GetTypeTraceReport(*this, desc)));
888 }
889}
890
892{
893 return Internal::EvalRVecAlignment(fSubfields[0]->GetAlignment());
894}
895
896std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayAsRVecField::SplitValue(const ROOT::RFieldBase::RValue &value) const
897{
898 auto arrayPtr = value.GetPtr<unsigned char>().get();
899 std::vector<ROOT::RFieldBase::RValue> result;
900 result.reserve(fArrayLength);
901 for (unsigned i = 0; i < fArrayLength; ++i) {
902 result.emplace_back(
903 fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), arrayPtr + (i * fItemSize))));
904 }
905 return result;
906}
907
909{
910 visitor.VisitArrayAsRVecField(*this);
911}
912
913//------------------------------------------------------------------------------
914
915ROOT::RArrayAsVectorField::RArrayAsVectorField(std::string_view fieldName, std::unique_ptr<ROOT::RFieldBase> itemField,
916 std::size_t arrayLength)
917 : ROOT::RFieldBase(fieldName, "std::vector<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
918 false /* isSimple */),
919 fItemSize(itemField->GetValueSize()),
920 fArrayLength(arrayLength)
921{
922 if (!itemField->GetTypeAlias().empty())
923 fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
924 Attach(std::move(itemField), "_0");
927}
928
929std::unique_ptr<ROOT::RFieldBase> ROOT::RArrayAsVectorField::CloneImpl(std::string_view newName) const
930{
931 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
932 return std::make_unique<RArrayAsVectorField>(newName, std::move(newItemField), fArrayLength);
933}
934
936{
937 throw RException(R__FAIL("RArrayAsVectorField fields must only be used for reading"));
938}
939
940std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RArrayAsVectorField::GetDeleter() const
941{
942 if (fItemDeleter)
943 return std::make_unique<RVectorField::RVectorDeleter>(fItemSize, GetDeleterOf(*fSubfields[0]));
944 return std::make_unique<RVectorField::RVectorDeleter>();
945}
946
948{
949 auto typedValue = static_cast<std::vector<char> *>(to);
950
951 if (fSubfields[0]->IsSimple()) {
952 typedValue->resize(fArrayLength * fItemSize);
953 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, typedValue->data());
954 return;
955 }
956
957 RVectorField::ResizeVector(to, fArrayLength, fItemSize, *fSubfields[0], fItemDeleter.get());
958
959 for (std::size_t i = 0; i < fArrayLength; ++i) {
960 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
961 }
962}
963
965{
966 auto typedValue = static_cast<std::vector<char> *>(to);
967
968 if (fSubfields[0]->IsSimple()) {
969 typedValue->resize(fArrayLength * fItemSize);
970 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, typedValue->data());
971 return;
972 }
973
974 RVectorField::ResizeVector(to, fArrayLength, fItemSize, *fSubfields[0], fItemDeleter.get());
975
976 for (std::size_t i = 0; i < fArrayLength; ++i) {
977 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
978 }
979}
980
982{
983 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions);
984
985 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
986 if (fieldDesc.GetTypeName().rfind("std::array<", 0) != 0) {
987 throw RException(R__FAIL("RArrayAsVectorField " + GetQualifiedFieldName() + " expects an on-disk array field\n" +
988 Internal::GetTypeTraceReport(*this, desc)));
989 }
990}
991
992std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayAsVectorField::SplitValue(const ROOT::RFieldBase::RValue &value) const
993{
994 return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
995}
996
998{
999 return GetSizeOfVector();
1000}
1001
1003{
1004 return GetAlignOfVector();
1005}
1006
1008{
1009 visitor.VisitArrayAsVectorField(*this);
1010}
size_t fValueSize
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:300
#define f(i)
Definition RSha256.hxx:104
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
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 result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:145
#define _(A, B)
Definition cfortran.h:108
#define free
Definition civetweb.c:1578
#define malloc
Definition civetweb.c:1575
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
Abstract interface to read data from an ntuple.
std::unique_ptr< RDeleter > fItemDeleter
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
RArrayAsRVecField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::size_t arrayLength)
Constructor of the field.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
std::unique_ptr< RDeleter > GetDeleter() const final
Returns an RRVecField::RRVecDeleter.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
The size of a value of this field, i.e. an RVec.
std::vector< RFieldBase::RValue > SplitValue(const RFieldBase::RValue &value) const final
Creates the list of direct child values given an existing value for this field.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
std::size_t fValueSize
The length of the arrays in this field.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::unique_ptr< RDeleter > GetDeleter() const final
Returns an RVectorField::RVectorDeleter.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
std::unique_ptr< RDeleter > fItemDeleter
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
RArrayAsVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::size_t arrayLength)
The itemField argument represents the inner item of the on-disk array, i.e.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
std::vector< RFieldBase::RValue > SplitValue(const RFieldBase::RValue &value) const final
Creates the list of direct child values given an existing value for this field.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
The length of the arrays in this field.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::array and C-style arrays.
std::unique_ptr< RDeleter > GetDeleter() const final
RArrayField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::size_t arrayLength)
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
General implementation of bulk read.
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
The list of column representations a field can have.
A functor to release the memory acquired by CreateValue() (memory and constructor).
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
void Attach(std::unique_ptr< RFieldBase > child, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
bool IsSimple() const
std::uint32_t GetTraits() const
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:322
The on-storage metadata of an RNTuple.
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
void operator()(void *objPtr, bool dtorOnly) final
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
size_t GetAlignment() const final
What alignof(T) for this type returns.
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
General implementation of bulk read.
RRVecField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
static unsigned char * ResizeRVec(void *rvec, std::size_t nItems, std::size_t itemSize, const RFieldBase *itemField, RDeleter *itemDeleter)
std::unique_ptr< RDeleter > fItemDeleter
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
RFieldBase * fBulkSubfield
May be a direct PoD subfield or a sub-subfield of a fixed-size array of PoD.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::unique_ptr< RDeleter > GetDeleter() const final
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::vector.
static std::unique_ptr< RVectorField > CreateUntyped(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
static void ResizeVector(void *vec, std::size_t nItems, std::size_t itemSize, const RFieldBase &itemField, RDeleter *itemDeleter)
RVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::optional< std::string_view > emulatedFromType)
Creates a possibly-untyped VectorField.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
std::unique_ptr< RDeleter > fItemDeleter
std::unique_ptr< RDeleter > GetDeleter() const final
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
std::tuple< unsigned char **, std::int32_t *, std::int32_t * > GetRVecDataMembers(void *rvecPtr)
Retrieve the addresses of the data members of a generic RVec from a pointer to the beginning of the R...
void DestroyRVecWithChecks(std::size_t alignOfT, unsigned char **beginPtr, std::int32_t *capacityPtr)
std::string GetNormalizedInteger(const std::string &intTemplateArg)
Appends 'll' or 'ull' to the where necessary and strips the suffix if not needed.
std::string GetTypeTraceReport(const RFieldBase &field, const RNTupleDescriptor &desc)
Prints the hierarchy of types with their field names and field IDs for the given in-memory field and ...
std::size_t EvalRVecAlignment(std::size_t alignOfSubfield)
std::size_t EvalRVecValueSize(std::size_t alignOfT, std::size_t sizeOfT, std::size_t alignOfRVecT)
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 RNTuple data model tree can carry different structural information about the type s...
Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().