17std::vector<ROOT::RFieldBase::RValue> SplitVector(
const std::shared_ptr<void> &valuePtr,
ROOT::RFieldBase &itemField)
19 auto *vec =
static_cast<std::vector<char> *
>(valuePtr.get());
23 const auto nItems = vec->size() / itemSize;
24 std::vector<ROOT::RFieldBase::RValue>
result;
26 for (
unsigned i = 0; i < nItems; ++i) {
27 result.emplace_back(itemField.
BindValue(std::shared_ptr<void>(valuePtr, vec->data() + (i * itemSize))));
32std::size_t GetSizeOfVector()
34 return sizeof(std::vector<char>);
37std::size_t GetAlignOfVector()
39 return alignof(std::vector<char>);
42void ConstructVector(
void *where, std::size_t alignOfValue)
46 switch (alignOfValue) {
60 default:
throw ROOT::RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(alignOfValue)));
68 std::size_t arrayLength)
70 "std::array<" + itemField->GetTypeName() +
"," +
73 fItemSize(itemField->GetValueSize()),
74 fArrayLength(arrayLength)
76 fTraits |= itemField->GetTraits() & ~kTraitMappable;
77 if (!itemField->GetTypeAlias().empty()) {
78 fTypeAlias =
"std::array<" + itemField->GetTypeAlias() +
"," +
81 Attach(std::move(itemField),
"_0");
86 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
87 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
92 std::size_t nbytes = 0;
93 if (fSubfields[0]->IsSimple()) {
94 GetPrincipalColumnOf(*fSubfields[0])->AppendV(from, fArrayLength);
95 nbytes += fArrayLength * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
97 auto arrayPtr =
static_cast<const unsigned char *
>(from);
98 for (
unsigned i = 0; i < fArrayLength; ++i) {
99 nbytes += CallAppendOn(*fSubfields[0], arrayPtr + (i * fItemSize));
107 if (fSubfields[0]->IsSimple()) {
108 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, to);
110 auto arrayPtr =
static_cast<unsigned char *
>(to);
111 for (
unsigned i = 0; i < fArrayLength; ++i) {
112 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
119 if (fSubfields[0]->IsSimple()) {
120 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, to);
122 auto arrayPtr =
static_cast<unsigned char *
>(to);
123 for (
unsigned i = 0; i < fArrayLength; ++i) {
124 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
131 if (!fSubfields[0]->IsSimple())
134 GetPrincipalColumnOf(*fSubfields[0])
136 return RBulkSpec::kAllSet;
141 static const std::vector<std::string> prefixes = {
"std::array<"};
143 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
144 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
149 if (fSubfields[0]->GetTraits() & kTraitTriviallyConstructible)
152 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
153 for (
unsigned i = 0; i < fArrayLength; ++i) {
154 CallConstructValueOn(*fSubfields[0], arrayPtr + (i * fItemSize));
161 for (
unsigned i = 0; i < fArrayLength; ++i) {
162 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
165 RDeleter::operator()(objPtr, dtorOnly);
170 if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
171 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetAlignment(), GetDeleterOf(*fSubfields[0]));
172 return std::make_unique<RDeleter>(GetAlignment());
177 auto valuePtr =
value.GetPtr<
void>();
178 auto arrayPtr =
static_cast<unsigned char *
>(valuePtr.get());
179 std::vector<RValue>
result;
180 result.reserve(fArrayLength);
181 for (
unsigned i = 0; i < fArrayLength; ++i) {
182 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, arrayPtr + (i * fItemSize))));
195 :
ROOT::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
197 fItemSize(itemField->GetValueSize()),
200 if (itemField->GetAlignment() >
sizeof(std::max_align_t)) {
207 if (!itemField->GetTypeAlias().empty())
208 fTypeAlias =
"ROOT::VecOps::RVec<" + itemField->GetTypeAlias() +
">";
209 Attach(std::move(itemField),
"_0");
218 auto grandChildFields =
fSubfields[0]->GetMutableSubfields();
219 if (grandChildFields[0]->
IsSimple()) {
229 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
230 return std::make_unique<RRVecField>(newName, std::move(newItemField));
237 std::size_t nbytes = 0;
238 if (fSubfields[0]->IsSimple() && *sizePtr) {
239 GetPrincipalColumnOf(*fSubfields[0])->AppendV(*beginPtr, *sizePtr);
240 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
242 for (std::int32_t i = 0; i < *sizePtr; ++i) {
243 nbytes += CallAppendOn(*fSubfields[0], *beginPtr + i * fItemSize);
247 fNWritten += *sizePtr;
248 fPrincipalColumn->Append(&fNWritten);
249 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
256 if (nItems >
static_cast<std::size_t
>(std::numeric_limits<std::int32_t>::max())) {
261 const std::size_t oldSize = *sizePtr;
263 if (oldSize == nItems) {
272 const bool owns = (*capacityPtr != -1);
273 const bool needsConstruct = !(itemField->
GetTraits() & kTraitTriviallyConstructible);
274 const bool needsDestruct = owns && itemDeleter;
278 for (std::size_t i = nItems; i < oldSize; ++i) {
279 itemDeleter->operator()(*beginPtr + (i * itemSize),
true );
289 static constexpr std::int32_t kSmallThreshold = 16;
290 if ((std::int32_t(nItems) > *capacityPtr) ||
291 ((std::int32_t(nItems) > kSmallThreshold) && (std::int32_t(nItems) < *capacityPtr / 4))) {
296 for (std::size_t i = 0u; i < std::min(oldSize, nItems); ++i) {
297 itemDeleter->operator()(*beginPtr + (i * itemSize),
true );
302 std::size_t newCapacity = nItems;
303 if (*capacityPtr > 0) {
304 constexpr std::size_t maxSize =
static_cast<std::size_t
>(std::numeric_limits<std::int32_t>::max());
305 const std::size_t oldCap =
static_cast<std::size_t
>(*capacityPtr);
306 if (nItems > oldCap) {
307 const std::size_t grown = oldCap + ((oldCap < kSmallThreshold) ? oldCap : (oldCap / 2));
308 newCapacity = std::min(maxSize, std::max(nItems, grown));
310 newCapacity = oldCap / 2;
311 assert(nItems <= newCapacity);
317 *beginPtr =
static_cast<unsigned char *
>(::operator
new(newCapacity * itemSize, std::nothrow));
319 *capacityPtr =
static_cast<std::int32_t
>(newCapacity);
325 if (needsConstruct) {
326 for (std::size_t i = 0u; i < std::min(oldSize, nItems); ++i)
327 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
333 if (needsConstruct) {
334 for (std::size_t i = oldSize; i < nItems; ++i)
335 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
349 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
351 auto begin = ResizeRVec(to, nItems, fItemSize, fSubfields[0].get(), fItemDeleter.get());
353 if (fSubfields[0]->IsSimple() && nItems) {
354 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, begin);
359 for (std::size_t i = 0; i < nItems; ++i) {
360 CallReadOn(*fSubfields[0], collectionStart + i, begin + (i * fItemSize));
372 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
373 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fBulkNRepetition * fBulkSubfield->GetValueSize();
375 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
376 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
382 fPrincipalColumn->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
383 *beginPtr = itemValueArray;
384 *sizePtr = collectionSize;
392 std::size_t nValues = 1;
393 std::size_t nItems = collectionSize;
394 while (nRemainingValues > 0) {
398 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
399 for (std::size_t i = 0; i < nBatch; ++i) {
400 const auto size = offsets[i] - lastOffset;
402 reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
403 *beginPtr = itemValueArray + nItems * itemValueSize;
408 lastOffset = offsets[i];
410 nRemainingValues -= nBatch;
414 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
416 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
418 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
419 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
420 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
425 GetPrincipalColumnOf(*fBulkSubfield)
426 ->ReadV(firstItemIndex * fBulkNRepetition, nItems * fBulkNRepetition, itemValueArray - delta);
427 return RBulkSpec::kAllSet;
437 return representations;
442 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
447 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
457 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
458 auto substitute = std::make_unique<RArrayAsRVecField>(
459 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
460 substitute->SetOnDiskId(GetOnDiskId());
468 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
475 void **beginPtr =
new (where)(
void *)(
nullptr);
476 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
477 new (sizePtr + 1) std::int32_t(-1);
485 for (std::int32_t i = 0; i < *sizePtr; ++i) {
486 fItemDeleter->operator()(*beginPtr + i * fItemSize,
true );
491 RDeleter::operator()(objPtr, dtorOnly);
497 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubfields[0]));
498 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment());
505 std::vector<RValue>
result;
507 for (std::int32_t i = 0; i < *sizePtr; ++i) {
509 fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), *beginPtr + i * fItemSize)));
534 emulatedFrom ? emulatedFrom->GetTypeName() :
"std::vector<" + itemField->GetTypeName() +
">",
536 fItemSize(itemField->GetValueSize()),
541 R__FAIL(std::string(
"Unsupported vector item alignment: ") + std::to_string(itemField->GetAlignment())));
544 if (emulatedFrom && !emulatedFrom->
GetTypeName().empty()) {
552 if (!itemField->GetTypeAlias().empty())
553 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
557 Attach(std::move(itemField),
"_0");
561 :
RVectorField(fieldName, std::move(itemField), nullptr)
565std::unique_ptr<ROOT::RVectorField>
569 return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(fieldName, itemField->Clone(
"_0"), &desc));
574 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
575 auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
580 .TypeChecksum(GetTypeChecksum())
581 .TypeName(GetTypeName())
589 return std::unique_ptr<ROOT::RVectorField>(
590 new RVectorField(newName, std::move(newItemField), isUntyped ? &desc :
nullptr));
595 auto typedValue =
static_cast<const std::vector<char> *
>(from);
600 auto count = typedValue->size() / fItemSize;
601 R__ASSERT((typedValue->size() % fItemSize) == 0);
602 std::size_t nbytes = 0;
604 if (fSubfields[0]->IsSimple() && count) {
605 GetPrincipalColumnOf(*fSubfields[0])->AppendV(typedValue->data(), count);
606 nbytes += count * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
608 for (
unsigned i = 0; i < count; ++i) {
609 nbytes += CallAppendOn(*fSubfields[0], typedValue->data() + (i * fItemSize));
614 fPrincipalColumn->Append(&fNWritten);
615 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
621 auto typedValue =
static_cast<std::vector<char> *
>(vec);
624 assert(itemSize > 0);
625 const auto oldNItems = typedValue->size() / itemSize;
626 const auto availNItems = typedValue->capacity() / itemSize;
627 assert((typedValue->size() % itemSize == 0) && (typedValue->capacity() % itemSize == 0));
629 const bool canRealloc = availNItems < nItems;
630 bool allDeallocated =
false;
632 allDeallocated = canRealloc;
633 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
634 itemDeleter->operator()(typedValue->data() + (i * itemSize),
true );
640 const auto nbytes = nItems * itemSize;
642 auto fnAlignedResize = [](
auto &vecOfAlignedStorage, std::size_t targetSize) {
643 constexpr auto valueTypeSize =
sizeof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
644 constexpr auto valueTypeAlignment =
alignof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
647 static_assert(valueTypeSize == valueTypeAlignment);
648 assert(targetSize % valueTypeAlignment == 0);
649 vecOfAlignedStorage.resize(targetSize / valueTypeSize);
652 static_assert(kMaxItemAlignment == 4096);
654 switch (itemAlignment) {
655 case 1: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(vec), nbytes);
break;
656 case 2: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(vec), nbytes);
break;
657 case 4: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(vec), nbytes);
break;
658 case 8: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(vec), nbytes);
break;
659 case 16: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(vec), nbytes);
break;
660 case 32: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(vec), nbytes);
break;
661 case 64: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(vec), nbytes);
break;
662 case 128: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(vec), nbytes);
break;
663 case 256: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(vec), nbytes);
break;
664 case 512: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(vec), nbytes);
break;
665 case 1024: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(vec), nbytes);
break;
666 case 2048: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(vec), nbytes);
break;
667 case 4096: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(vec), nbytes);
break;
668 default:
throw RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(itemAlignment)));
672 if (!(itemField.
GetTraits() & kTraitTriviallyConstructible)) {
673 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
674 CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));
681 auto typedValue =
static_cast<std::vector<char> *
>(to);
685 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
687 if (fSubfields[0]->IsSimple()) {
688 typedValue->resize(nItems * fItemSize);
690 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, typedValue->data());
694 ResizeVector(to, nItems, fItemSize, *fSubfields[0], fItemDeleter.get());
696 for (std::size_t i = 0; i < nItems; ++i) {
697 CallReadOn(*fSubfields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
708 return representations;
713 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
718 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
728 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
729 auto substitute = std::make_unique<RArrayAsVectorField>(
730 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
731 substitute->SetOnDiskId(GetOnDiskId());
739 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
744 ConstructVector(where, fSubfields[0]->GetAlignment());
748 :
RDeleter(GetAlignOfVector()), fItemAlignment(itemAlignment)
753 std::unique_ptr<RDeleter> itemDeleter)
756 fItemAlignment(itemAlignment),
763 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
766 auto nItems = vecPtr->size() /
fItemSize;
767 assert((vecPtr->size() %
fItemSize) == 0);
768 for (std::size_t i = 0; i < nItems; ++i) {
775 switch (fItemAlignment) {
776 case 1: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(objPtr));
break;
777 case 2: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(objPtr));
break;
778 case 4: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(objPtr));
break;
779 case 8: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(objPtr));
break;
780 case 16: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(objPtr));
break;
781 case 32: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(objPtr));
break;
782 case 64: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(objPtr));
break;
783 case 128: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(objPtr));
break;
784 case 256: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(objPtr));
break;
785 case 512: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(objPtr));
break;
786 case 1024: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(objPtr));
break;
787 case 2048: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(objPtr));
break;
788 case 4096: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(objPtr));
break;
789 default:
throw ROOT::RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(fItemAlignment)));
793 RDeleter::operator()(objPtr, dtorOnly);
810 return GetSizeOfVector();
815 return GetAlignOfVector();
833 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
834 auto count = typedValue->size();
835 for (
unsigned i = 0; i < count; ++i) {
836 bool bval = (*typedValue)[i];
837 CallAppendOn(*fSubfields[0], &bval);
840 fPrincipalColumn->Append(&fNWritten);
841 return count + fPrincipalColumn->GetElement()->GetPackedSize();
846 auto typedValue =
static_cast<std::vector<bool> *
>(to);
848 if (fOnDiskNRepetitions == 0) {
850 RNTupleLocalIndex collectionStart;
851 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
852 typedValue->resize(nItems);
853 for (std::size_t i = 0; i < nItems; ++i) {
855 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
856 (*typedValue)[i] = bval;
859 typedValue->resize(fOnDiskNRepetitions);
860 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
862 CallReadOn(*fSubfields[0], globalIndex * fOnDiskNRepetitions + i, &bval);
863 (*typedValue)[i] = bval;
870 auto typedValue =
static_cast<std::vector<bool> *
>(to);
872 if (fOnDiskNRepetitions == 0) {
874 RNTupleLocalIndex collectionStart;
875 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &nItems);
876 typedValue->resize(nItems);
877 for (std::size_t i = 0; i < nItems; ++i) {
879 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
880 (*typedValue)[i] = bval;
883 typedValue->resize(fOnDiskNRepetitions);
884 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
886 CallReadOn(*fSubfields[0], localIndex * fOnDiskNRepetitions + i, &bval);
887 (*typedValue)[i] = bval;
899 return representations;
905 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
910 if (fOnDiskNRepetitions == 0)
911 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
916 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
918 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
919 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
921 if (fieldDesc.GetNRepetitions() == 0) {
922 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected repetition count > 0\n" +
926 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected plain on-disk field\n" +
929 fOnDiskNRepetitions = fieldDesc.GetNRepetitions();
931 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
937 const auto &typedValue =
value.GetRef<std::vector<bool>>();
938 auto count = typedValue.size();
939 std::vector<RValue>
result;
941 for (
unsigned i = 0; i < count; ++i) {
943 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
945 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
959 std::size_t arrayLength)
960 :
ROOT::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
962 fItemSize(itemField->GetValueSize()),
963 fArrayLength(arrayLength)
965 if (!itemField->GetTypeAlias().empty())
966 fTypeAlias =
"ROOT::VecOps::RVec<" + itemField->GetTypeAlias() +
">";
967 Attach(std::move(itemField),
"_0");
976 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
977 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
984 void **beginPtr =
new (where)(
void *)(
nullptr);
985 std::int32_t *sizePtr =
new (
static_cast<void *
>(beginPtr + 1)) std::int32_t(0);
986 new (sizePtr + 1) std::int32_t(-1);
992 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize,
993 GetDeleterOf(*fSubfields[0]));
995 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment());
1000 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
1002 if (fSubfields[0]->IsSimple()) {
1003 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, begin);
1008 for (std::size_t i = 0; i < fArrayLength; ++i) {
1009 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, begin + (i * fItemSize));
1015 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
1017 if (fSubfields[0]->IsSimple()) {
1018 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, begin);
1023 for (std::size_t i = 0; i < fArrayLength; ++i) {
1024 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, begin + (i * fItemSize));
1030 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
1032 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
1033 throw RException(
R__FAIL(
"RArrayAsRVecField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1045 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
1046 std::vector<ROOT::RFieldBase::RValue>
result;
1047 result.reserve(fArrayLength);
1048 for (
unsigned i = 0; i < fArrayLength; ++i) {
1050 fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
1063 std::size_t arrayLength)
1066 fItemSize(itemField->GetValueSize()),
1067 fArrayLength(arrayLength)
1069 if (!itemField->GetTypeAlias().empty())
1070 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
1071 Attach(std::move(itemField),
"_0");
1078 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1079 return std::make_unique<RArrayAsVectorField>(newName, std::move(newItemField), fArrayLength);
1084 throw RException(
R__FAIL(
"RArrayAsVectorField fields must only be used for reading"));
1089 ConstructVector(where, fSubfields[0]->GetAlignment());
1095 return std::make_unique<RVectorField::RVectorDeleter>(fItemSize, fSubfields[0]->GetAlignment(),
1096 GetDeleterOf(*fSubfields[0]));
1098 return std::make_unique<RVectorField::RVectorDeleter>(fSubfields[0]->GetAlignment());
1103 auto typedValue =
static_cast<std::vector<char> *
>(to);
1105 if (fSubfields[0]->IsSimple()) {
1106 typedValue->resize(fArrayLength * fItemSize);
1107 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, typedValue->data());
1113 for (std::size_t i = 0; i < fArrayLength; ++i) {
1114 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1120 auto typedValue =
static_cast<std::vector<char> *
>(to);
1122 if (fSubfields[0]->IsSimple()) {
1123 typedValue->resize(fArrayLength * fItemSize);
1124 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, typedValue->data());
1130 for (std::size_t i = 0; i < fArrayLength; ++i) {
1131 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1137 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions);
1140 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
1141 throw RException(
R__FAIL(
"RArrayAsVectorField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1148 return SplitVector(
value.GetPtr<
void>(), *fSubfields[0]);
1153 return GetSizeOfVector();
1158 return GetAlignOfVector();
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
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.
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
Abstract base class for classes implementing the visitor design pattern.
virtual void VisitVectorField(const ROOT::RVectorField &field)
virtual void VisitVectorBoolField(const ROOT::RField< std::vector< bool > > &field)
virtual void VisitRVecField(const ROOT::RRVecField &field)
virtual void VisitArrayAsRVecField(const ROOT::RArrayAsRVecField &field)
virtual void VisitArrayAsVectorField(const ROOT::RArrayAsVectorField &field)
virtual void VisitArrayField(const ROOT::RArrayField &field)
The in-memory representation of a 32bit or 64bit on-disk index column.
A helper class for piece-wise construction of an RFieldDescriptor.
RResult< RFieldDescriptor > MoveDescriptor()
Attempt to make a field descriptor.
RFieldDescriptorBuilder & Structure(const ROOT::ENTupleStructure &structure)
RFieldDescriptorBuilder & TypeVersion(std::uint32_t typeVersion)
Abstract interface to read data from an ntuple.
RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
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
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
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.
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.
virtual size_t GetValueSize() const =0
What sizeof(T) for this type returns.
void Attach(std::unique_ptr< RFieldBase > child, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
virtual size_t GetAlignment() const =0
What alignof(T) for this type returns.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
@ 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.
@ kTraitSoACollection
The field represents a collection in SoA layout.
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.
std::uint32_t GetTraits() const
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
Metadata stored for every field of an RNTuple.
bool IsSoACollection() const
std::optional< std::uint32_t > GetTypeChecksum() const
std::uint32_t GetTypeVersion() const
const std::string & GetTypeName() const
Classes with dictionaries that can be inspected by TClass.
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...
ROOT::NTupleSize_t GetIndexInCluster() const
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 fBulkNRepetition
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
RVectorDeleter(std::size_t itemAlignment)
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)
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.
RVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, const ROOT::RFieldDescriptor *emulatedFrom)
Creates a possibly-untyped VectorField.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
std::uint32_t fEmulatedTypeChecksum
std::unique_ptr< RDeleter > fItemDeleter
static constexpr std::size_t kMaxItemAlignment
Maximum alignment of the vector's value type.
std::unique_ptr< RDeleter > GetDeleter() const final
std::uint32_t fEmulatedTypeVersion
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...
Storage type whose alignment matches AlignT bytes.
Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().
RNTupleLocalIndex fFirstIndex
Start of the bulk range.
void * fValues
The destination area, which has to be an array of valid objects of the correct type large enough to h...
std::size_t fCount
Size of the bulk range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulkValues class.