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)));
532 std::optional<std::string_view> emulatedFromType)
533 :
ROOT::
RFieldBase(fieldName, emulatedFromType ? *emulatedFromType :
"std::vector<" + itemField->GetTypeName() +
">",
535 fItemSize(itemField->GetValueSize()),
540 R__FAIL(std::string(
"Unsupported vector item alignment: ") + std::to_string(itemField->GetAlignment())));
543 if (emulatedFromType && !emulatedFromType->empty())
546 if (!itemField->GetTypeAlias().empty())
547 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
551 Attach(std::move(itemField),
"_0");
559std::unique_ptr<ROOT::RVectorField>
562 return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(fieldName, itemField->Clone(
"_0"),
""));
567 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
568 auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
569 auto emulatedFromType = isUntyped ? std::make_optional(GetTypeName()) : std::nullopt;
570 return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(newName, std::move(newItemField), emulatedFromType));
575 auto typedValue =
static_cast<const std::vector<char> *
>(from);
580 auto count = typedValue->size() / fItemSize;
581 R__ASSERT((typedValue->size() % fItemSize) == 0);
582 std::size_t nbytes = 0;
584 if (fSubfields[0]->IsSimple() && count) {
585 GetPrincipalColumnOf(*fSubfields[0])->AppendV(typedValue->data(), count);
586 nbytes += count * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
588 for (
unsigned i = 0; i < count; ++i) {
589 nbytes += CallAppendOn(*fSubfields[0], typedValue->data() + (i * fItemSize));
594 fPrincipalColumn->Append(&fNWritten);
595 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
601 auto typedValue =
static_cast<std::vector<char> *
>(vec);
604 assert(itemSize > 0);
605 const auto oldNItems = typedValue->size() / itemSize;
606 const auto availNItems = typedValue->capacity() / itemSize;
607 assert((typedValue->size() % itemSize == 0) && (typedValue->capacity() % itemSize == 0));
609 const bool canRealloc = availNItems < nItems;
610 bool allDeallocated =
false;
612 allDeallocated = canRealloc;
613 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
614 itemDeleter->operator()(typedValue->data() + (i * itemSize),
true );
620 const auto nbytes = nItems * itemSize;
622 auto fnAlignedResize = [](
auto &vecOfAlignedStorage, std::size_t targetSize) {
623 constexpr auto valueTypeSize =
sizeof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
624 constexpr auto valueTypeAlignment =
alignof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
627 static_assert(valueTypeSize == valueTypeAlignment);
628 assert(targetSize % valueTypeAlignment == 0);
629 vecOfAlignedStorage.resize(targetSize / valueTypeSize);
632 static_assert(kMaxItemAlignment == 4096);
634 switch (itemAlignment) {
635 case 1: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(vec), nbytes);
break;
636 case 2: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(vec), nbytes);
break;
637 case 4: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(vec), nbytes);
break;
638 case 8: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(vec), nbytes);
break;
639 case 16: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(vec), nbytes);
break;
640 case 32: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(vec), nbytes);
break;
641 case 64: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(vec), nbytes);
break;
642 case 128: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(vec), nbytes);
break;
643 case 256: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(vec), nbytes);
break;
644 case 512: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(vec), nbytes);
break;
645 case 1024: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(vec), nbytes);
break;
646 case 2048: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(vec), nbytes);
break;
647 case 4096: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(vec), nbytes);
break;
648 default:
throw RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(itemAlignment)));
652 if (!(itemField.
GetTraits() & kTraitTriviallyConstructible)) {
653 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
654 CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));
661 auto typedValue =
static_cast<std::vector<char> *
>(to);
665 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
667 if (fSubfields[0]->IsSimple()) {
668 typedValue->resize(nItems * fItemSize);
670 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, typedValue->data());
674 ResizeVector(to, nItems, fItemSize, *fSubfields[0], fItemDeleter.get());
676 for (std::size_t i = 0; i < nItems; ++i) {
677 CallReadOn(*fSubfields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
688 return representations;
693 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
698 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
708 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
709 auto substitute = std::make_unique<RArrayAsVectorField>(
710 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
711 substitute->SetOnDiskId(GetOnDiskId());
719 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
724 ConstructVector(where, fSubfields[0]->GetAlignment());
728 :
RDeleter(GetAlignOfVector()), fItemAlignment(itemAlignment)
733 std::unique_ptr<RDeleter> itemDeleter)
736 fItemAlignment(itemAlignment),
743 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
746 auto nItems = vecPtr->size() /
fItemSize;
747 assert((vecPtr->size() %
fItemSize) == 0);
748 for (std::size_t i = 0; i < nItems; ++i) {
755 switch (fItemAlignment) {
756 case 1: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(objPtr));
break;
757 case 2: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(objPtr));
break;
758 case 4: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(objPtr));
break;
759 case 8: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(objPtr));
break;
760 case 16: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(objPtr));
break;
761 case 32: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(objPtr));
break;
762 case 64: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(objPtr));
break;
763 case 128: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(objPtr));
break;
764 case 256: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(objPtr));
break;
765 case 512: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(objPtr));
break;
766 case 1024: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(objPtr));
break;
767 case 2048: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(objPtr));
break;
768 case 4096: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(objPtr));
break;
769 default:
throw ROOT::RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(fItemAlignment)));
773 RDeleter::operator()(objPtr, dtorOnly);
790 return GetSizeOfVector();
795 return GetAlignOfVector();
813 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
814 auto count = typedValue->size();
815 for (
unsigned i = 0; i < count; ++i) {
816 bool bval = (*typedValue)[i];
817 CallAppendOn(*fSubfields[0], &bval);
820 fPrincipalColumn->Append(&fNWritten);
821 return count + fPrincipalColumn->GetElement()->GetPackedSize();
826 auto typedValue =
static_cast<std::vector<bool> *
>(to);
828 if (fOnDiskNRepetitions == 0) {
830 RNTupleLocalIndex collectionStart;
831 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
832 typedValue->resize(nItems);
833 for (std::size_t i = 0; i < nItems; ++i) {
835 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
836 (*typedValue)[i] = bval;
839 typedValue->resize(fOnDiskNRepetitions);
840 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
842 CallReadOn(*fSubfields[0], globalIndex * fOnDiskNRepetitions + i, &bval);
843 (*typedValue)[i] = bval;
850 auto typedValue =
static_cast<std::vector<bool> *
>(to);
852 if (fOnDiskNRepetitions == 0) {
854 RNTupleLocalIndex collectionStart;
855 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &nItems);
856 typedValue->resize(nItems);
857 for (std::size_t i = 0; i < nItems; ++i) {
859 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
860 (*typedValue)[i] = bval;
863 typedValue->resize(fOnDiskNRepetitions);
864 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
866 CallReadOn(*fSubfields[0], localIndex * fOnDiskNRepetitions + i, &bval);
867 (*typedValue)[i] = bval;
879 return representations;
885 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
890 if (fOnDiskNRepetitions == 0)
891 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
896 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
898 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
899 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
901 if (fieldDesc.GetNRepetitions() == 0) {
902 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected repetition count > 0\n" +
906 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected plain on-disk field\n" +
909 fOnDiskNRepetitions = fieldDesc.GetNRepetitions();
911 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
917 const auto &typedValue =
value.GetRef<std::vector<bool>>();
918 auto count = typedValue.size();
919 std::vector<RValue>
result;
921 for (
unsigned i = 0; i < count; ++i) {
923 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
925 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
939 std::size_t arrayLength)
940 :
ROOT::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
942 fItemSize(itemField->GetValueSize()),
943 fArrayLength(arrayLength)
945 if (!itemField->GetTypeAlias().empty())
946 fTypeAlias =
"ROOT::VecOps::RVec<" + itemField->GetTypeAlias() +
">";
947 Attach(std::move(itemField),
"_0");
956 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
957 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
964 void **beginPtr =
new (where)(
void *)(
nullptr);
965 std::int32_t *sizePtr =
new (
static_cast<void *
>(beginPtr + 1)) std::int32_t(0);
966 new (sizePtr + 1) std::int32_t(-1);
972 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize,
973 GetDeleterOf(*fSubfields[0]));
975 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment());
980 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
982 if (fSubfields[0]->IsSimple()) {
983 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, begin);
988 for (std::size_t i = 0; i < fArrayLength; ++i) {
989 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, begin + (i * fItemSize));
995 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
997 if (fSubfields[0]->IsSimple()) {
998 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, begin);
1003 for (std::size_t i = 0; i < fArrayLength; ++i) {
1004 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, begin + (i * fItemSize));
1010 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
1012 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
1013 throw RException(
R__FAIL(
"RArrayAsRVecField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1025 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
1026 std::vector<ROOT::RFieldBase::RValue>
result;
1027 result.reserve(fArrayLength);
1028 for (
unsigned i = 0; i < fArrayLength; ++i) {
1030 fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
1043 std::size_t arrayLength)
1046 fItemSize(itemField->GetValueSize()),
1047 fArrayLength(arrayLength)
1049 if (!itemField->GetTypeAlias().empty())
1050 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
1051 Attach(std::move(itemField),
"_0");
1058 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1059 return std::make_unique<RArrayAsVectorField>(newName, std::move(newItemField), fArrayLength);
1064 throw RException(
R__FAIL(
"RArrayAsVectorField fields must only be used for reading"));
1069 ConstructVector(where, fSubfields[0]->GetAlignment());
1075 return std::make_unique<RVectorField::RVectorDeleter>(fItemSize, fSubfields[0]->GetAlignment(),
1076 GetDeleterOf(*fSubfields[0]));
1078 return std::make_unique<RVectorField::RVectorDeleter>(fSubfields[0]->GetAlignment());
1083 auto typedValue =
static_cast<std::vector<char> *
>(to);
1085 if (fSubfields[0]->IsSimple()) {
1086 typedValue->resize(fArrayLength * fItemSize);
1087 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, typedValue->data());
1093 for (std::size_t i = 0; i < fArrayLength; ++i) {
1094 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1100 auto typedValue =
static_cast<std::vector<char> *
>(to);
1102 if (fSubfields[0]->IsSimple()) {
1103 typedValue->resize(fArrayLength * fItemSize);
1104 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, typedValue->data());
1110 for (std::size_t i = 0; i < fArrayLength; ++i) {
1111 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1117 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions);
1120 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
1121 throw RException(
R__FAIL(
"RArrayAsVectorField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1128 return SplitVector(
value.GetPtr<
void>(), *fSubfields[0]);
1133 return GetSizeOfVector();
1138 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.
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.
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.
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)
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.
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::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
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.