18std::vector<ROOT::RFieldBase::RValue> SplitVector(
const std::shared_ptr<void> &valuePtr,
ROOT::RFieldBase &itemField)
20 auto *vec =
static_cast<std::vector<char> *
>(valuePtr.get());
24 const auto nItems = vec->size() / itemSize;
25 std::vector<ROOT::RFieldBase::RValue>
result;
27 for (
unsigned i = 0; i < nItems; ++i) {
28 result.emplace_back(itemField.
BindValue(std::shared_ptr<void>(valuePtr, vec->data() + (i * itemSize))));
33std::size_t GetSizeOfVector()
35 return sizeof(std::vector<char>);
38std::size_t GetAlignOfVector()
40 return alignof(std::vector<char>);
43void ConstructVector(
void *where, std::size_t alignOfValue)
47 switch (alignOfValue) {
61 default:
throw ROOT::RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(alignOfValue)));
69 std::size_t arrayLength)
71 "std::array<" + itemField->GetTypeName() +
"," +
74 fItemSize(itemField->GetValueSize()),
75 fArrayLength(arrayLength)
77 fTraits |= itemField->GetTraits() & ~kTraitMappable;
78 if (!itemField->GetTypeAlias().empty()) {
79 fTypeAlias =
"std::array<" + itemField->GetTypeAlias() +
"," +
82 Attach(std::move(itemField),
"_0");
87 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
88 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
93 std::size_t nbytes = 0;
94 if (fSubfields[0]->IsSimple()) {
95 GetPrincipalColumnOf(*fSubfields[0])->AppendV(from, fArrayLength);
96 nbytes += fArrayLength * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
98 auto arrayPtr =
static_cast<const unsigned char *
>(from);
99 for (
unsigned i = 0; i < fArrayLength; ++i) {
100 nbytes += CallAppendOn(*fSubfields[0], arrayPtr + (i * fItemSize));
108 if (fSubfields[0]->IsSimple()) {
109 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, to);
111 auto arrayPtr =
static_cast<unsigned char *
>(to);
112 for (
unsigned i = 0; i < fArrayLength; ++i) {
113 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
120 if (fSubfields[0]->IsSimple()) {
121 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, to);
123 auto arrayPtr =
static_cast<unsigned char *
>(to);
124 for (
unsigned i = 0; i < fArrayLength; ++i) {
125 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
132 if (!fSubfields[0]->IsSimple())
135 GetPrincipalColumnOf(*fSubfields[0])
137 return RBulkSpec::kAllSet;
142 static const std::vector<std::string> prefixes = {
"std::array<"};
144 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
145 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
150 if (fSubfields[0]->GetTraits() & kTraitTriviallyConstructible)
153 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
154 for (
unsigned i = 0; i < fArrayLength; ++i) {
155 CallConstructValueOn(*fSubfields[0], arrayPtr + (i * fItemSize));
162 for (
unsigned i = 0; i < fArrayLength; ++i) {
163 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
166 RDeleter::operator()(objPtr, dtorOnly);
171 if (!(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
172 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetAlignment(), GetDeleterOf(*fSubfields[0]));
173 return std::make_unique<RDeleter>(GetAlignment());
178 auto valuePtr =
value.GetPtr<
void>();
179 auto arrayPtr =
static_cast<unsigned char *
>(valuePtr.get());
180 std::vector<RValue>
result;
181 result.reserve(fArrayLength);
182 for (
unsigned i = 0; i < fArrayLength; ++i) {
183 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, arrayPtr + (i * fItemSize))));
196 :
ROOT::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
198 fItemSize(itemField->GetValueSize()),
201 if (itemField->GetAlignment() >
sizeof(std::max_align_t)) {
208 if (!itemField->GetTypeAlias().empty())
209 fTypeAlias =
"ROOT::VecOps::RVec<" + itemField->GetTypeAlias() +
">";
210 Attach(std::move(itemField),
"_0");
219 auto grandChildFields =
fSubfields[0]->GetMutableSubfields();
220 if (grandChildFields[0]->
IsSimple()) {
230 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
231 return std::make_unique<RRVecField>(newName, std::move(newItemField));
238 std::size_t nbytes = 0;
239 if (fSubfields[0]->IsSimple() && *sizePtr) {
240 GetPrincipalColumnOf(*fSubfields[0])->AppendV(*beginPtr, *sizePtr);
241 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
243 for (std::int32_t i = 0; i < *sizePtr; ++i) {
244 nbytes += CallAppendOn(*fSubfields[0], *beginPtr + i * fItemSize);
248 fNWritten += *sizePtr;
249 fPrincipalColumn->Append(&fNWritten);
250 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
257 if (nItems >
static_cast<std::size_t
>(std::numeric_limits<std::int32_t>::max())) {
262 const std::size_t oldSize = *sizePtr;
264 if (oldSize == nItems) {
273 const bool owns = (*capacityPtr != -1);
274 const bool needsConstruct = !(itemField->
GetTraits() & kTraitTriviallyConstructible);
275 const bool needsDestruct = owns && itemDeleter;
279 for (std::size_t i = nItems; i < oldSize; ++i) {
280 itemDeleter->operator()(*beginPtr + (i * itemSize),
true );
285 if (std::int32_t(nItems) > *capacityPtr) {
289 for (std::size_t i = 0u; i < oldSize; ++i) {
290 itemDeleter->operator()(*beginPtr + (i * itemSize),
true );
298 *beginPtr =
static_cast<unsigned char *
>(malloc(nItems * itemSize));
300 *capacityPtr = nItems;
303 if (needsConstruct) {
304 for (std::size_t i = 0u; i < oldSize; ++i)
305 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
311 if (needsConstruct) {
312 for (std::size_t i = oldSize; i < nItems; ++i)
313 CallConstructValueOn(*itemField, *beginPtr + (i * itemSize));
327 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
329 auto begin = ResizeRVec(to, nItems, fItemSize, fSubfields[0].get(), fItemDeleter.get());
331 if (fSubfields[0]->IsSimple() && nItems) {
332 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, begin);
337 for (std::size_t i = 0; i < nItems; ++i) {
338 CallReadOn(*fSubfields[0], collectionStart + i, begin + (i * fItemSize));
350 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
351 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fBulkNRepetition * fBulkSubfield->GetValueSize();
353 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
354 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
360 fPrincipalColumn->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
361 *beginPtr = itemValueArray;
362 *sizePtr = collectionSize;
370 std::size_t nValues = 1;
371 std::size_t nItems = collectionSize;
372 while (nRemainingValues > 0) {
376 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
377 for (std::size_t i = 0; i < nBatch; ++i) {
378 const auto size = offsets[i] - lastOffset;
380 reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
381 *beginPtr = itemValueArray + nItems * itemValueSize;
386 lastOffset = offsets[i];
388 nRemainingValues -= nBatch;
392 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
394 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
396 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
397 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
398 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
403 GetPrincipalColumnOf(*fBulkSubfield)
404 ->ReadV(firstItemIndex * fBulkNRepetition, nItems * fBulkNRepetition, itemValueArray - delta);
405 return RBulkSpec::kAllSet;
415 return representations;
420 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
425 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
435 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
436 auto substitute = std::make_unique<RArrayAsRVecField>(
437 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
438 substitute->SetOnDiskId(GetOnDiskId());
446 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
453 void **beginPtr =
new (where)(
void *)(
nullptr);
454 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
455 new (sizePtr + 1) std::int32_t(-1);
463 for (std::int32_t i = 0; i < *sizePtr; ++i) {
464 fItemDeleter->operator()(*beginPtr + i * fItemSize,
true );
469 RDeleter::operator()(objPtr, dtorOnly);
475 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubfields[0]));
476 return std::make_unique<RRVecDeleter>(fSubfields[0]->GetAlignment());
483 std::vector<RValue>
result;
485 for (std::int32_t i = 0; i < *sizePtr; ++i) {
487 fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), *beginPtr + i * fItemSize)));
510 std::optional<std::string_view> emulatedFromType)
511 :
ROOT::
RFieldBase(fieldName, emulatedFromType ? *emulatedFromType :
"std::vector<" + itemField->GetTypeName() +
">",
513 fItemSize(itemField->GetValueSize()),
518 R__FAIL(std::string(
"Unsupported vector item alignment: ") + std::to_string(itemField->GetAlignment())));
521 if (emulatedFromType && !emulatedFromType->empty())
524 if (!itemField->GetTypeAlias().empty())
525 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
529 Attach(std::move(itemField),
"_0");
537std::unique_ptr<ROOT::RVectorField>
540 return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(fieldName, itemField->Clone(
"_0"),
""));
545 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
546 auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
547 auto emulatedFromType = isUntyped ? std::make_optional(GetTypeName()) : std::nullopt;
548 return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(newName, std::move(newItemField), emulatedFromType));
553 auto typedValue =
static_cast<const std::vector<char> *
>(from);
558 auto count = typedValue->size() / fItemSize;
559 R__ASSERT((typedValue->size() % fItemSize) == 0);
560 std::size_t nbytes = 0;
562 if (fSubfields[0]->IsSimple() && count) {
563 GetPrincipalColumnOf(*fSubfields[0])->AppendV(typedValue->data(), count);
564 nbytes += count * GetPrincipalColumnOf(*fSubfields[0])->GetElement()->GetPackedSize();
566 for (
unsigned i = 0; i < count; ++i) {
567 nbytes += CallAppendOn(*fSubfields[0], typedValue->data() + (i * fItemSize));
572 fPrincipalColumn->Append(&fNWritten);
573 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
579 auto typedValue =
static_cast<std::vector<char> *
>(vec);
582 assert(itemSize > 0);
583 const auto oldNItems = typedValue->size() / itemSize;
584 const auto availNItems = typedValue->capacity() / itemSize;
585 assert((typedValue->size() % itemSize == 0) && (typedValue->capacity() % itemSize == 0));
587 const bool canRealloc = availNItems < nItems;
588 bool allDeallocated =
false;
590 allDeallocated = canRealloc;
591 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
592 itemDeleter->operator()(typedValue->data() + (i * itemSize),
true );
598 const auto nbytes = nItems * itemSize;
600 auto fnAlignedResize = [](
auto &vecOfAlignedStorage, std::size_t targetSize) {
601 constexpr auto valueTypeSize =
sizeof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
602 constexpr auto valueTypeAlignment =
alignof(
typename std::decay_t<
decltype(vecOfAlignedStorage)>::value_type);
605 static_assert(valueTypeSize == valueTypeAlignment);
606 assert(targetSize % valueTypeAlignment == 0);
607 vecOfAlignedStorage.resize(targetSize / valueTypeSize);
610 static_assert(kMaxItemAlignment == 4096);
612 switch (itemAlignment) {
613 case 1: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(vec), nbytes);
break;
614 case 2: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(vec), nbytes);
break;
615 case 4: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(vec), nbytes);
break;
616 case 8: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(vec), nbytes);
break;
617 case 16: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(vec), nbytes);
break;
618 case 32: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(vec), nbytes);
break;
619 case 64: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(vec), nbytes);
break;
620 case 128: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(vec), nbytes);
break;
621 case 256: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(vec), nbytes);
break;
622 case 512: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(vec), nbytes);
break;
623 case 1024: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(vec), nbytes);
break;
624 case 2048: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(vec), nbytes);
break;
625 case 4096: fnAlignedResize(*
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(vec), nbytes);
break;
626 default:
throw RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(itemAlignment)));
630 if (!(itemField.
GetTraits() & kTraitTriviallyConstructible)) {
631 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
632 CallConstructValueOn(itemField, typedValue->data() + (i * itemSize));
639 auto typedValue =
static_cast<std::vector<char> *
>(to);
643 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
645 if (fSubfields[0]->IsSimple()) {
646 typedValue->resize(nItems * fItemSize);
648 GetPrincipalColumnOf(*fSubfields[0])->ReadV(collectionStart, nItems, typedValue->data());
652 ResizeVector(to, nItems, fItemSize, *fSubfields[0], fItemDeleter.get());
654 for (std::size_t i = 0; i < nItems; ++i) {
655 CallReadOn(*fSubfields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
666 return representations;
671 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
676 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
686 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
687 auto substitute = std::make_unique<RArrayAsVectorField>(
688 GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
689 substitute->SetOnDiskId(GetOnDiskId());
697 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
702 ConstructVector(where, fSubfields[0]->GetAlignment());
706 :
RDeleter(GetAlignOfVector()), fItemAlignment(itemAlignment)
711 std::unique_ptr<RDeleter> itemDeleter)
714 fItemAlignment(itemAlignment),
721 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
724 auto nItems = vecPtr->size() /
fItemSize;
725 assert((vecPtr->size() %
fItemSize) == 0);
726 for (std::size_t i = 0; i < nItems; ++i) {
733 switch (fItemAlignment) {
734 case 1: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 1>
> *>(objPtr));
break;
735 case 2: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 2>
> *>(objPtr));
break;
736 case 4: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 4>
> *>(objPtr));
break;
737 case 8: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 8>
> *>(objPtr));
break;
738 case 16: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 16>
> *>(objPtr));
break;
739 case 32: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 32>
> *>(objPtr));
break;
740 case 64: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 64>
> *>(objPtr));
break;
741 case 128: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 128>
> *>(objPtr));
break;
742 case 256: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 256>
> *>(objPtr));
break;
743 case 512: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage< 512>
> *>(objPtr));
break;
744 case 1024: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<1024>
> *>(objPtr));
break;
745 case 2048: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<2048>
> *>(objPtr));
break;
746 case 4096: std::destroy_at(
static_cast<std::vector<Internal::RAlignedStorage<4096>
> *>(objPtr));
break;
747 default:
throw ROOT::RException(
R__FAIL(std::string(
"Unsupported alignment: ") + std::to_string(fItemAlignment)));
751 RDeleter::operator()(objPtr, dtorOnly);
768 return GetSizeOfVector();
773 return GetAlignOfVector();
791 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
792 auto count = typedValue->size();
793 for (
unsigned i = 0; i < count; ++i) {
794 bool bval = (*typedValue)[i];
795 CallAppendOn(*fSubfields[0], &bval);
798 fPrincipalColumn->Append(&fNWritten);
799 return count + fPrincipalColumn->GetElement()->GetPackedSize();
804 auto typedValue =
static_cast<std::vector<bool> *
>(to);
806 if (fOnDiskNRepetitions == 0) {
808 RNTupleLocalIndex collectionStart;
809 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
810 typedValue->resize(nItems);
811 for (std::size_t i = 0; i < nItems; ++i) {
813 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
814 (*typedValue)[i] = bval;
817 typedValue->resize(fOnDiskNRepetitions);
818 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
820 CallReadOn(*fSubfields[0], globalIndex * fOnDiskNRepetitions + i, &bval);
821 (*typedValue)[i] = bval;
828 auto typedValue =
static_cast<std::vector<bool> *
>(to);
830 if (fOnDiskNRepetitions == 0) {
832 RNTupleLocalIndex collectionStart;
833 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &nItems);
834 typedValue->resize(nItems);
835 for (std::size_t i = 0; i < nItems; ++i) {
837 CallReadOn(*fSubfields[0], collectionStart + i, &bval);
838 (*typedValue)[i] = bval;
841 typedValue->resize(fOnDiskNRepetitions);
842 for (std::size_t i = 0; i < fOnDiskNRepetitions; ++i) {
844 CallReadOn(*fSubfields[0], localIndex * fOnDiskNRepetitions + i, &bval);
845 (*typedValue)[i] = bval;
857 return representations;
863 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
868 if (fOnDiskNRepetitions == 0)
869 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
874 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
876 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) == 0) {
877 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
879 if (fieldDesc.GetNRepetitions() == 0) {
880 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected repetition count > 0\n" +
884 throw RException(
R__FAIL(
"fixed-size array --> std::vector<bool>: expected plain on-disk field\n" +
887 fOnDiskNRepetitions = fieldDesc.GetNRepetitions();
889 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
895 const auto &typedValue =
value.GetRef<std::vector<bool>>();
896 auto count = typedValue.size();
897 std::vector<RValue>
result;
899 for (
unsigned i = 0; i < count; ++i) {
901 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
903 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
917 std::size_t arrayLength)
918 :
ROOT::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
920 fItemSize(itemField->GetValueSize()),
921 fArrayLength(arrayLength)
923 if (!itemField->GetTypeAlias().empty())
924 fTypeAlias =
"ROOT::VecOps::RVec<" + itemField->GetTypeAlias() +
">";
925 Attach(std::move(itemField),
"_0");
934 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
935 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
942 void **beginPtr =
new (where)(
void *)(
nullptr);
943 std::int32_t *sizePtr =
new (
static_cast<void *
>(beginPtr + 1)) std::int32_t(0);
944 new (sizePtr + 1) std::int32_t(-1);
950 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment(), fItemSize,
951 GetDeleterOf(*fSubfields[0]));
953 return std::make_unique<RRVecField::RRVecDeleter>(fSubfields[0]->GetAlignment());
958 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
960 if (fSubfields[0]->IsSimple()) {
961 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, begin);
966 for (std::size_t i = 0; i < fArrayLength; ++i) {
967 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, begin + (i * fItemSize));
973 auto begin =
RRVecField::ResizeRVec(to, fArrayLength, fItemSize, fSubfields[0].get(), fItemDeleter.get());
975 if (fSubfields[0]->IsSimple()) {
976 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, begin);
981 for (std::size_t i = 0; i < fArrayLength; ++i) {
982 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, begin + (i * fItemSize));
988 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions).ThrowOnError();
990 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
991 throw RException(
R__FAIL(
"RArrayAsRVecField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1003 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
1004 std::vector<ROOT::RFieldBase::RValue>
result;
1005 result.reserve(fArrayLength);
1006 for (
unsigned i = 0; i < fArrayLength; ++i) {
1008 fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
1021 std::size_t arrayLength)
1024 fItemSize(itemField->GetValueSize()),
1025 fArrayLength(arrayLength)
1027 if (!itemField->GetTypeAlias().empty())
1028 fTypeAlias =
"std::vector<" + itemField->GetTypeAlias() +
">";
1029 Attach(std::move(itemField),
"_0");
1036 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1037 return std::make_unique<RArrayAsVectorField>(newName, std::move(newItemField), fArrayLength);
1042 throw RException(
R__FAIL(
"RArrayAsVectorField fields must only be used for reading"));
1047 ConstructVector(where, fSubfields[0]->GetAlignment());
1053 return std::make_unique<RVectorField::RVectorDeleter>(fItemSize, fSubfields[0]->GetAlignment(),
1054 GetDeleterOf(*fSubfields[0]));
1056 return std::make_unique<RVectorField::RVectorDeleter>(fSubfields[0]->GetAlignment());
1061 auto typedValue =
static_cast<std::vector<char> *
>(to);
1063 if (fSubfields[0]->IsSimple()) {
1064 typedValue->resize(fArrayLength * fItemSize);
1065 GetPrincipalColumnOf(*fSubfields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, typedValue->data());
1071 for (std::size_t i = 0; i < fArrayLength; ++i) {
1072 CallReadOn(*fSubfields[0], globalIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1078 auto typedValue =
static_cast<std::vector<char> *
>(to);
1080 if (fSubfields[0]->IsSimple()) {
1081 typedValue->resize(fArrayLength * fItemSize);
1082 GetPrincipalColumnOf(*fSubfields[0])->ReadV(localIndex * fArrayLength, fArrayLength, typedValue->data());
1088 for (std::size_t i = 0; i < fArrayLength; ++i) {
1089 CallReadOn(*fSubfields[0], localIndex * fArrayLength + i, typedValue->data() + (i * fItemSize));
1095 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffStructure | kDiffNRepetitions);
1098 if (fieldDesc.GetTypeName().rfind(
"std::array<", 0) != 0) {
1099 throw RException(
R__FAIL(
"RArrayAsVectorField " + GetQualifiedFieldName() +
" expects an on-disk array field\n" +
1106 return SplitVector(
value.GetPtr<
void>(), *fSubfields[0]);
1111 return GetSizeOfVector();
1116 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.