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.
268 // We trust that malloc returns a buffer with large enough alignment.
269 // This might not be the case if T in RVec<T> is over-aligned.
270 *beginPtr = static_cast<unsigned char *>(malloc(nItems * itemSize));
271 R__ASSERT(*beginPtr != nullptr);
273
274 // Placement new for elements that were already there before the resize
275 if (needsConstruct) {
276 for (std::size_t i = 0u; i < oldSize; ++i)
277 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
278 }
279 }
280 *sizePtr = nItems;
281
282 // Placement new for new elements, if any
283 if (needsConstruct) {
284 for (std::size_t i = oldSize; i < nItems; ++i)
285 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
286 }
287
288 return *beginPtr;
289}
290
292{
293 // TODO as a performance optimization, we could assign values to elements of the inline buffer:
294 // if size < inline buffer size: we save one allocation here and usage of the RVec skips a pointer indirection
295
296 // Read collection info for this entry
299 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
300
301 auto begin = ResizeRVec(to, nItems, fItemSize, fSubfields[0].get(), fItemDeleter.get());
302
303 if (fSubfields[0]->IsSimple() && nItems) {
304 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, begin);
305 return;
306 }
307
308 // Read the new values into the collection elements
309 for (std::size_t i = 0; i < nItems; ++i) {
310 CallReadOn(*fSubfields[0], collectionStart + i, begin + (i * fItemSize));
311 }
312}
313
315{
316 if (!fBulkSubfield)
318
319 if (bulkSpec.fAuxData->empty()) {
320 /// Initialize auxiliary memory: the first sizeof(size_t) bytes store the value size of the item field.
321 /// The following bytes store the item values, consecutively.
322 bulkSpec.fAuxData->resize(sizeof(std::size_t));
323 *reinterpret_cast<std::size_t *>(bulkSpec.fAuxData->data()) = fBulkNRepetition * fBulkSubfield->GetValueSize();
324 }
325 const auto itemValueSize = *reinterpret_cast<std::size_t *>(bulkSpec.fAuxData->data());
326 unsigned char *itemValueArray = bulkSpec.fAuxData->data() + sizeof(std::size_t);
328
329 // Get size of the first RVec of the bulk
332 fPrincipalColumn->GetCollectionInfo(bulkSpec.fFirstIndex, &firstItemIndex, &collectionSize);
335 *capacityPtr = -1;
336
337 // Set the size of the remaining RVecs of the bulk, going page by page through the RNTuple offset column.
338 // We optimistically assume that bulkSpec.fAuxData is already large enough to hold all the item values in the
339 // given range. If not, we'll fix up the pointers afterwards.
340 auto lastOffset = firstItemIndex.GetIndexInCluster() + collectionSize;
342 std::size_t nValues = 1;
343 std::size_t nItems = collectionSize;
344 while (nRemainingValues > 0) {
346 const auto offsets =
347 fPrincipalColumn->MapV<ROOT::Internal::RColumnIndex>(bulkSpec.fFirstIndex + nValues, nElementsUntilPageEnd);
348 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
349 for (std::size_t i = 0; i < nBatch; ++i) {
350 const auto size = offsets[i] - lastOffset;
352 reinterpret_cast<unsigned char *>(bulkSpec.fValues) + (nValues + i) * fValueSize);
354 *sizePtr = size;
355 *capacityPtr = -1;
356
357 nItems += size;
358 lastOffset = offsets[i];
359 }
361 nValues += nBatch;
362 }
363
364 bulkSpec.fAuxData->resize(sizeof(std::size_t) + nItems * itemValueSize);
365 // If the vector got reallocated, we need to fix-up the RVecs begin pointers.
366 const auto delta = itemValueArray - (bulkSpec.fAuxData->data() + sizeof(std::size_t));
367 if (delta != 0) {
368 auto beginPtrAsUChar = reinterpret_cast<unsigned char *>(bulkSpec.fValues);
369 for (std::size_t i = 0; i < bulkSpec.fCount; ++i) {
370 *reinterpret_cast<unsigned char **>(beginPtrAsUChar) -= delta;
372 }
373 }
374
375 GetPrincipalColumnOf(*fBulkSubfield)
376 ->ReadV(firstItemIndex * fBulkNRepetition, nItems * fBulkNRepetition, itemValueArray - delta);
377 return RBulkSpec::kAllSet;
378}
379
389
394
399
401{
402 if (GetOnDiskId() == kInvalidDescriptorId)
403 return nullptr;
404
405 const auto descGuard = pageSource.GetSharedDescriptorGuard();
406 const auto &fieldDesc = descGuard->GetFieldDescriptor(GetOnDiskId());
407 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
408 auto substitute = std::make_unique<RArrayAsRVecField>(
409 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
410 substitute->SetOnDiskId(GetOnDiskId());
411 return substitute;
412 }
413 return nullptr;
414}
415
417{
418 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
419}
420
422{
423 // initialize data members fBegin, fSize, fCapacity
424 // currently the inline buffer is left uninitialized
425 void **beginPtr = new (where)(void *)(nullptr);
426 std::int32_t *sizePtr = new (reinterpret_cast<void *>(beginPtr + 1)) std::int32_t(0);
427 new (sizePtr + 1) std::int32_t(-1);
428}
429
431{
433
434 if (fItemDeleter) {
435 for (std::int32_t i = 0; i < *sizePtr; ++i) {
436 fItemDeleter->operator()(*beginPtr + i * fItemSize, true /* dtorOnly */);
437 }
438 }
439
441 RDeleter::operator()(objPtr, dtorOnly);
442}
443
444std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRVecField::GetDeleter() const
445{
446 if (fItemDeleter)
447 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubfields[0]));
448 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment());
449}
450
451std::vector<ROOT::RFieldBase::RValue> ROOT::RRVecField::SplitValue(const RValue &value) const
452{
453 auto [beginPtr, sizePtr, _] = Internal::GetRVecDataMembers(value.GetPtr<void>().get());
454
455 std::vector<RValue> result;
456 result.reserve(*sizePtr);
457 for (std::int32_t i = 0; i < *sizePtr; ++i) {
458 result.emplace_back(
459 fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), *beginPtr + i * fItemSize)));
460 }
461 return result;
462}
463
465{
466 return fValueSize;
467}
468
470{
471 return Internal::EvalRVecAlignment(fSubfields[0]->GetAlignment());
472}
473
475{
476 visitor.VisitRVecField(*this);
477}
478
479//------------------------------------------------------------------------------
480
481ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
482 std::optional<std::string_view> emulatedFromType)
483 : ROOT::RFieldBase(fieldName, emulatedFromType ? *emulatedFromType : "std::vector<" + itemField->GetTypeName() + ">",
484 ROOT::ENTupleStructure::kCollection, false /* isSimple */),
485 fItemSize(itemField->GetValueSize()),
486 fNWritten(0)
487{
488 if (emulatedFromType && !emulatedFromType->empty())
490
491 if (!itemField->GetTypeAlias().empty())
492 fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
493
494 if (!(itemField->GetTraits() & kTraitTriviallyDestructible))
496 Attach(std::move(itemField), "_0");
497}
498
499ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
501{
502}
503
504std::unique_ptr<ROOT::RVectorField>
505ROOT::RVectorField::CreateUntyped(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
506{
507 return std::unique_ptr<ROOT::RVectorField>(new RVectorField(fieldName, itemField->Clone("_0"), ""));
508}
509
510std::unique_ptr<ROOT::RFieldBase> ROOT::RVectorField::CloneImpl(std::string_view newName) const
511{
512 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
513 auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
514 auto emulatedFromType = isUntyped ? std::make_optional(GetTypeName()) : std::nullopt;
515 return std::unique_ptr<ROOT::RVectorField>(new RVectorField(newName, std::move(newItemField), emulatedFromType));
516}
517
518std::size_t ROOT::RVectorField::AppendImpl(const void *from)
519{
520 auto typedValue = static_cast<const std::vector<char> *>(from);
521 // The order is important here: Profiling showed that the integer division is on the critical path. By moving the
522 // computation of count before R__ASSERT, the compiler can use the result of a single instruction (on x86) also for
523 // the modulo operation. Otherwise, it must perform the division twice because R__ASSERT expands to an external call
524 // of Fatal() in case of failure, which could have side effects that the compiler cannot analyze.
525 auto count = typedValue->size() / fItemSize;
526 R__ASSERT((typedValue->size() % fItemSize) == 0);
527 std::size_t nbytes = 0;
528
529 if (fSubfields[0]->IsSimple() && count) {
530 GetPrincipalColumnOf(*fSubfields[0])->AppendV(typedValue->data(), count);
531 nbytes += count * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
532 } else {
533 for (unsigned i = 0; i < count; ++i) {
534 nbytes += CallAppendOn(*fSubfields[0], typedValue->data() + (i * fItemSize));
535 }
536 }
537
538 fNWritten += count;
539 fPrincipalColumn->Append(&fNWritten);
540 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
541}
542
543void ROOT::RVectorField::ResizeVector(void *vec, std::size_t nItems, std::size_t itemSize, const RFieldBase &itemField,
545{
546 auto typedValue = static_cast<std::vector<char> *>(vec);
547
548 // See "semantics of reading non-trivial objects" in RNTuple's Architecture.md
549 R__ASSERT(itemSize > 0);
550 const auto oldNItems = typedValue->size() / itemSize;
551 const auto availNItems = typedValue->capacity() / itemSize;
552 const bool canRealloc = availNItems < nItems;
553 bool allDeallocated = false;
554 if (itemDeleter) {
556 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
557 itemDeleter->operator()(typedValue->data() + (i * itemSize), true /* dtorOnly */);
558 }
559 }
560 typedValue->resize(nItems * itemSize);
561 if (!(itemField.GetTraits() & kTraitTriviallyConstructible)) {
562 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
563 CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));
564 }
565 }
566}
567
569{
570 auto typedValue = static_cast<std::vector<char> *>(to);
571
574 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
575
576 if (fSubfields[0]->IsSimple()) {
577 typedValue->resize(nItems * fItemSize);
578 if (nItems)
579 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, typedValue->data());
580 return;
581 }
582
583 ResizeVector(to, nItems, fItemSize, *fSubfields[0], fItemDeleter.get());
584
585 for (std::size_t i = 0; i < nItems; ++i) {
586 CallReadOn(*fSubfields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
587 }
588}
589
599
604
609
611{
612 if (GetOnDiskId() == kInvalidDescriptorId)
613 return nullptr;
614
615 const auto descGuard = pageSource.GetSharedDescriptorGuard();
616 const auto &fieldDesc = descGuard->GetFieldDescriptor(GetOnDiskId());
617 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
618 auto substitute = std::make_unique<RArrayAsVectorField>(
619 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
620 substitute->SetOnDiskId(GetOnDiskId());
621 return substitute;
622 }
623 return nullptr;
624}
625
627{
628 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
629}
630
632{
633 auto vecPtr = static_cast<std::vector<char> *>(objPtr);
634 if (fItemDeleter) {
635 R__ASSERT(fItemSize > 0);
636 R__ASSERT((vecPtr->size() % fItemSize) == 0);
637 auto nItems = vecPtr->size() / fItemSize;
638 for (std::size_t i = 0; i < nItems; ++i) {
639 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize), true /* dtorOnly */);
640 }
641 }
642 std::destroy_at(vecPtr);
643 RDeleter::operator()(objPtr, dtorOnly);
644}
645
646std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RVectorField::GetDeleter() const
647{
648 if (fItemDeleter)
649 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubfields[0]));
650 return std::make_unique<RVectorDeleter>();
651}
652
653std::vector<ROOT::RFieldBase::RValue> ROOT::RVectorField::SplitValue(const RValue &value) const
654{
655 return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
656}
657
659{
660 return GetSizeOfVector();
661}
662
664{
665 return GetAlignOfVector();
666}
667
669{
670 visitor.VisitVectorField(*this);
671}
672
673//------------------------------------------------------------------------------
674
675ROOT::RField<std::vector<bool>>::RField(std::string_view name)
676 : ROOT::RFieldBase(name, "std::vector<bool>", ROOT::ENTupleStructure::kCollection, false /* isSimple */)
677{
678 Attach(std::make_unique<RField<bool>>("_0"));
679}
680
681std::size_t ROOT::RField<std::vector<bool>>::AppendImpl(const void *from)
682{
683 auto typedValue = static_cast<const std::vector<bool> *>(from);
684 auto count = typedValue->size();
685 for (unsigned i = 0; i < count; ++i) {
686 bool bval = (*typedValue)[i];
687 CallAppendOn(*fSubfields[0], &bval);
688 }
689 fNWritten += count;
690 fPrincipalColumn->Append(&fNWritten);
691 return count + fPrincipalColumn->GetElement()->GetPackedSize();
692}
693
695{
696 auto typedValue = static_cast<std::vector<bool> *>(to);
697
698 if (fOnDiskNRepetitions == 0) {
700 RNTupleLocalIndex collectionStart;
701 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
702 typedValue->resize(nItems);
703 for (std::size_t i = 0; i < nItems; ++i) {
704 bool bval;
705 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
706 (*typedValue)[i] = bval;
707 }
708 } else {
709 typedValue->resize(fOnDiskNRepetitions);
710 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
711 bool bval;
712 CallReadOn(*fSubfields[0], globalIndex * fOnDiskNRepetitions + i, &bval);
713 (*typedValue)[i] = bval;
714 }
715 }
716}
717
718void ROOT::RField<std::vector<bool>>::ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to)
719{
720 auto typedValue = static_cast<std::vector<bool> *>(to);
721
722 if (fOnDiskNRepetitions == 0) {
724 RNTupleLocalIndex collectionStart;
725 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &nItems);
726 typedValue->resize(nItems);
727 for (std::size_t i = 0; i < nItems; ++i) {
728 bool bval;
729 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
730 (*typedValue)[i] = bval;
731 }
732 } else {
733 typedValue->resize(fOnDiskNRepetitions);
734 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
735 bool bval;
736 CallReadOn(*fSubfields[0], localIndex * fOnDiskNRepetitions + i, &bval);
737 (*typedValue)[i] = bval;
738 }
739 }
740}
741
742const ROOT::RFieldBase::RColumnRepresentations &ROOT::RField<std::vector<bool>>::GetColumnRepresentations() const
743{
744 static RColumnRepresentations representations({{ENTupleColumnType::kSplitIndex64},
748 {{}});
749 return representations;
750}
751
752void ROOT::RField<std::vector<bool>>::GenerateColumns()
753{
754 R__ASSERT(fOnDiskNRepetitions == 0); // fOnDiskNRepetitions must only be used for reading
756}
757
758void ROOT::RField<std::vector<bool>>::GenerateColumns(const ROOT::RNTupleDescriptor &desc)
759{
760 if (fOnDiskNRepetitions == 0)
762}
763
764void ROOT::RField<std::vector<bool>>::ReconcileOnDiskField(const RNTupleDescriptor &desc)
765{
766 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
767
768 if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
769 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
770
771 if (fieldDesc.GetNRepetitions() == 0) {
772 throw RException(R__FAIL("fixed-size array --> std::vector<bool>: expected repetition count > 0\n" +
773 Internal::GetTypeTraceReport(*this, desc)));
774 }
775 if (fieldDesc.GetStructure() != ENTupleStructure::kPlain) {
776 throw RException(R__FAIL("fixed-size array --> std::vector<bool>: expected plain on-disk field\n" +
777 Internal::GetTypeTraceReport(*this, desc)));
778 }
779 fOnDiskNRepetitions = fieldDesc.GetNRepetitions();
780 } else {
781 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
782 }
783}
784
785std::vector<ROOT::RFieldBase::RValue> ROOT::RField<std::vector<bool>>::SplitValue(const RValue &value) const
786{
787 const auto &typedValue = value.GetRef<std::vector<bool>>();
788 auto count = typedValue.size();
789 std::vector<RValue> result;
790 result.reserve(count);
791 for (unsigned i = 0; i < count; ++i) {
792 if (typedValue[i]) {
793 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(new bool(true))));
794 } else {
795 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(new bool(false))));
796 }
797 }
798 return result;
799}
800
802{
803 visitor.VisitVectorBoolField(*this);
804}
805
806//------------------------------------------------------------------------------
807
808ROOT::RArrayAsRVecField::RArrayAsRVecField(std::string_view fieldName, std::unique_ptr<ROOT::RFieldBase> itemField,
809 std::size_t arrayLength)
810 : ROOT::RFieldBase(fieldName, "ROOT::VecOps::RVec<" + itemField->GetTypeName() + ">",
811 ROOT::ENTupleStructure::kCollection, false /* isSimple */),
812 fItemSize(itemField->GetValueSize()),
813 fArrayLength(arrayLength)
814{
815 if (!itemField->GetTypeAlias().empty())
816 fTypeAlias = "ROOT::VecOps::RVec<" + itemField->GetTypeAlias() + ">";
817 Attach(std::move(itemField), "_0");
818 fValueSize =
822}
823
824std::unique_ptr<ROOT::RFieldBase> ROOT::RArrayAsRVecField::CloneImpl(std::string_view newName) const
825{
826 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
827 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
828}
829
831{
832 // initialize data members fBegin, fSize, fCapacity
833 // currently the inline buffer is left uninitialized
834 void **beginPtr = new (where)(void *)(nullptr);
835 std::int32_t *sizePtr = new (static_cast<void *>(beginPtr + 1)) std::int32_t(0);
836 new (sizePtr + 1) std::int32_t(-1);
837}
838
839std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RArrayAsRVecField::GetDeleter() const
840{
841 if (fItemDeleter) {
842 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize,
843 GetDeleterOf(*fSubfields[0]));
844 }
845 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment());
846}
847
849{
850 auto begin = RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
851
852 if (fSubfields[0]->IsSimple()) {
853 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, begin);
854 return;
855 }
856
857 // Read the new values into the collection elements
858 for (std::size_t i = 0; i < fArrayLength; ++i) {
859 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, begin + (i * fItemSize));
860 }
861}
862
864{
865 auto begin = RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
866
867 if (fSubfields[0]->IsSimple()) {
868 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, begin);
869 return;
870 }
871
872 // Read the new values into the collection elements
873 for (std::size_t i = 0; i < fArrayLength; ++i) {
874 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, begin + (i * fItemSize));
875 }
876}
877
879{
880 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
881 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
882 if (fieldDesc.GetTypeName().rfind("std::array<", 0) != 0) {
883 throw RException(R__FAIL("RArrayAsRVecField " + GetQualifiedFieldName() + " expects an on-disk array field\n" +
884 Internal::GetTypeTraceReport(*this, desc)));
885 }
886}
887
889{
890 return Internal::EvalRVecAlignment(fSubfields[0]->GetAlignment());
891}
892
893std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayAsRVecField::SplitValue(const ROOT::RFieldBase::RValue &value) const
894{
895 auto arrayPtr = value.GetPtr<unsigned char>().get();
896 std::vector<ROOT::RFieldBase::RValue> result;
897 result.reserve(fArrayLength);
898 for (unsigned i = 0; i < fArrayLength; ++i) {
899 result.emplace_back(
900 fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), arrayPtr + (i * fItemSize))));
901 }
902 return result;
903}
904
906{
907 visitor.VisitArrayAsRVecField(*this);
908}
909
910//------------------------------------------------------------------------------
911
912ROOT::RArrayAsVectorField::RArrayAsVectorField(std::string_view fieldName, std::unique_ptr<ROOT::RFieldBase> itemField,
913 std::size_t arrayLength)
914 : ROOT::RFieldBase(fieldName, "std::vector<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
915 false /* isSimple */),
916 fItemSize(itemField->GetValueSize()),
917 fArrayLength(arrayLength)
918{
919 if (!itemField->GetTypeAlias().empty())
920 fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
921 Attach(std::move(itemField), "_0");
924}
925
926std::unique_ptr<ROOT::RFieldBase> ROOT::RArrayAsVectorField::CloneImpl(std::string_view newName) const
927{
928 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
929 return std::make_unique<RArrayAsVectorField>(newName, std::move(newItemField), fArrayLength);
930}
931
933{
934 throw RException(R__FAIL("RArrayAsVectorField fields must only be used for reading"));
935}
936
937std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RArrayAsVectorField::GetDeleter() const
938{
939 if (fItemDeleter)
940 return std::make_unique<RVectorField::RVectorDeleter>(fItemSize, GetDeleterOf(*fSubfields[0]));
941 return std::make_unique<RVectorField::RVectorDeleter>();
942}
943
945{
946 auto typedValue = static_cast<std::vector<char> *>(to);
947
948 if (fSubfields[0]->IsSimple()) {
949 typedValue->resize(fArrayLength * fItemSize);
950 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, typedValue->data());
951 return;
952 }
953
954 RVectorField::ResizeVector(to, fArrayLength, fItemSize, *fSubfields[0], fItemDeleter.get());
955
956 for (std::size_t i = 0; i < fArrayLength; ++i) {
957 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
958 }
959}
960
962{
963 auto typedValue = static_cast<std::vector<char> *>(to);
964
965 if (fSubfields[0]->IsSimple()) {
966 typedValue->resize(fArrayLength * fItemSize);
967 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, typedValue->data());
968 return;
969 }
970
971 RVectorField::ResizeVector(to, fArrayLength, fItemSize, *fSubfields[0], fItemDeleter.get());
972
973 for (std::size_t i = 0; i < fArrayLength; ++i) {
974 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
975 }
976}
977
979{
980 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions);
981
982 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
983 if (fieldDesc.GetTypeName().rfind("std::array<", 0) != 0) {
984 throw RException(R__FAIL("RArrayAsVectorField " + GetQualifiedFieldName() + " expects an on-disk array field\n" +
985 Internal::GetTypeTraceReport(*this, desc)));
986 }
987}
988
989std::vector<ROOT::RFieldBase::RValue> ROOT::RArrayAsVectorField::SplitValue(const ROOT::RFieldBase::RValue &value) const
990{
991 return SplitVector(value.GetPtr<void>(), *fSubfields[0]);
992}
993
995{
996 return GetSizeOfVector();
997}
998
1000{
1001 return GetAlignOfVector();
1002}
1003
1005{
1006 visitor.VisitArrayAsVectorField(*this);
1007}
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 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().