52#include <unordered_map>
56const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
59 {
"Double_t",
"double"},
60 {
"string",
"std::string"},
62 {
"byte",
"std::byte"},
64 {
"int8_t",
"std::int8_t"},
65 {
"signed char",
"char"},
66 {
"UChar_t",
"std::uint8_t"},
67 {
"unsigned char",
"std::uint8_t"},
68 {
"uint8_t",
"std::uint8_t"},
70 {
"Short_t",
"std::int16_t"},
71 {
"int16_t",
"std::int16_t"},
72 {
"short",
"std::int16_t"},
73 {
"UShort_t",
"std::uint16_t"},
74 {
"unsigned short",
"std::uint16_t"},
75 {
"uint16_t",
"std::uint16_t"},
77 {
"Int_t",
"std::int32_t"},
78 {
"int32_t",
"std::int32_t"},
79 {
"int",
"std::int32_t"},
80 {
"UInt_t",
"std::uint32_t"},
81 {
"unsigned",
"std::uint32_t"},
82 {
"unsigned int",
"std::uint32_t"},
83 {
"uint32_t",
"std::uint32_t"},
86 {
"Long_t",
"std::int64_t"},
87 {
"Long64_t",
"std::int64_t"},
88 {
"int64_t",
"std::int64_t"},
89 {
"long",
"std::int64_t"},
90 {
"ULong_t",
"std::uint64_t"},
91 {
"ULong64_t",
"std::uint64_t"},
92 {
"unsigned long",
"std::uint64_t"},
93 {
"uint64_t",
"std::uint64_t"}
98std::vector<std::string> TokenizeTypeList(std::string templateType) {
99 std::vector<std::string>
result;
100 if (templateType.empty())
103 const char *eol = templateType.data() + templateType.length();
104 const char *typeBegin = templateType.data();
105 const char *typeCursor = templateType.data();
106 unsigned int nestingLevel = 0;
107 while (typeCursor != eol) {
108 switch (*typeCursor) {
116 if (nestingLevel == 0) {
117 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
118 typeBegin = typeCursor + 1;
124 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
133std::tuple<std::string, std::vector<size_t>> ParseArrayType(std::string_view typeName)
135 std::vector<size_t> sizeVec;
138 while (typeName.back() ==
']') {
139 auto posRBrace = typeName.size() - 1;
140 auto posLBrace = typeName.find_last_of(
'[', posRBrace);
141 if (posLBrace == std::string_view::npos)
145 if (std::from_chars(typeName.data() + posLBrace + 1, typeName.data() + posRBrace,
size).ec != std::errc{})
147 sizeVec.insert(sizeVec.begin(),
size);
148 typeName.remove_suffix(typeName.size() - posLBrace);
150 return std::make_tuple(std::string{typeName}, sizeVec);
155std::string GetCanonicalTypeName(
const std::string &typeName)
158 if (typeName ==
"ROOT::Experimental::ClusterSize_t" || typeName.substr(0, 5) ==
"std::" ||
159 typeName.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<")
170std::string GetNormalizedTypeName(
const std::string &typeName)
174 if (
auto it = typeTranslationMap.find(normalizedType); it != typeTranslationMap.end())
175 normalizedType = it->second;
177 if (normalizedType.substr(0, 7) ==
"vector<")
178 normalizedType =
"std::" + normalizedType;
179 if (normalizedType.substr(0, 6) ==
"array<")
180 normalizedType =
"std::" + normalizedType;
181 if (normalizedType.substr(0, 8) ==
"variant<")
182 normalizedType =
"std::" + normalizedType;
183 if (normalizedType.substr(0, 5) ==
"pair<")
184 normalizedType =
"std::" + normalizedType;
185 if (normalizedType.substr(0, 6) ==
"tuple<")
186 normalizedType =
"std::" + normalizedType;
187 if (normalizedType.substr(0, 7) ==
"bitset<")
188 normalizedType =
"std::" + normalizedType;
189 if (normalizedType.substr(0, 11) ==
"unique_ptr<")
190 normalizedType =
"std::" + normalizedType;
191 if (normalizedType.substr(0, 4) ==
"set<")
192 normalizedType =
"std::" + normalizedType;
193 if (normalizedType.substr(0, 14) ==
"unordered_set<")
194 normalizedType =
"std::" + normalizedType;
195 if (normalizedType.substr(0, 4) ==
"map<")
196 normalizedType =
"std::" + normalizedType;
197 if (normalizedType.substr(0, 14) ==
"unordered_map<")
198 normalizedType =
"std::" + normalizedType;
199 if (normalizedType.substr(0, 7) ==
"atomic<")
200 normalizedType =
"std::" + normalizedType;
202 if (normalizedType.substr(0, 11) ==
"ROOT::RVec<")
203 normalizedType =
"ROOT::VecOps::RVec<" + normalizedType.substr(11);
205 return normalizedType;
209class CreateContextGuard;
211 friend class CreateContextGuard;
213 std::vector<std::string> fClassesOnStack;
216 bool fContinueOnError =
false;
219 CreateContext() =
default;
220 bool GetContinueOnError()
const {
return fContinueOnError; }
224class CreateContextGuard {
225 CreateContext &fCreateContext;
226 std::size_t fNOriginalClassesOnStack;
227 bool fOriginalContinueOnError;
230 CreateContextGuard(CreateContext &ctx)
231 : fCreateContext(ctx),
232 fNOriginalClassesOnStack(ctx.fClassesOnStack.
size()),
233 fOriginalContinueOnError(ctx.fContinueOnError)
236 ~CreateContextGuard()
238 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
239 fCreateContext.fContinueOnError = fOriginalContinueOnError;
242 void AddClassToStack(
const std::string &cl)
244 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
245 fCreateContext.fClassesOnStack.end()) {
248 fCreateContext.fClassesOnStack.emplace_back(cl);
251 void SetContinueOnError(
bool value) { fCreateContext.fContinueOnError =
value; }
256std::tuple<void **, std::int32_t *, std::int32_t *> GetRVecDataMembers(
void *rvecPtr)
258 void **begin =
reinterpret_cast<void **
>(rvecPtr);
260 std::int32_t *
size =
reinterpret_cast<std::int32_t *
>(begin + 1);
263 std::int32_t *capacity =
size + 1;
265 return {begin,
size, capacity};
268std::tuple<const void *const *, const std::int32_t *, const std::int32_t *> GetRVecDataMembers(
const void *rvecPtr)
270 return {GetRVecDataMembers(
const_cast<void *
>(rvecPtr))};
278 auto iFrom = from.
cbegin();
279 auto iTo = to.
begin();
280 for (; iFrom != from.
cend(); ++iFrom, ++iTo) {
281 iTo->SetOnDiskId(iFrom->GetOnDiskId());
285std::size_t EvalRVecValueSize(std::size_t alignOfT, std::size_t sizeOfT, std::size_t alignOfRVecT)
299 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
302 const auto inlineStorageSz = [&] {
303#ifdef R__HAS_HARDWARE_INTERFERENCE_SIZE
305 constexpr unsigned cacheLineSize = std::hardware_destructive_interference_size;
307 constexpr unsigned cacheLineSize = 64u;
309 const unsigned elementsPerCacheLine = (cacheLineSize - dataMemberSz) / sizeOfT;
310 constexpr unsigned maxInlineByteSize = 1024;
311 const unsigned nElements =
312 elementsPerCacheLine >= 8 ? elementsPerCacheLine : (sizeOfT * 8 > maxInlineByteSize ? 0 : 8);
313 return nElements * sizeOfT;
318 auto paddingMiddle = dataMemberSz % alignOfT;
319 if (paddingMiddle != 0)
320 paddingMiddle = alignOfT - paddingMiddle;
323 auto paddingEnd = (dataMemberSz + paddingMiddle + inlineStorageSz) % alignOfRVecT;
325 paddingEnd = alignOfRVecT - paddingEnd;
327 return dataMemberSz + inlineStorageSz + paddingMiddle + paddingEnd;
330std::size_t EvalRVecAlignment(std::size_t alignOfSubField)
334 return std::max({
alignof(
void *),
alignof(std::int32_t), alignOfSubField});
337void DestroyRVecWithChecks(std::size_t alignOfT,
void **beginPtr,
char *begin, std::int32_t *capacityPtr)
341 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
342 auto paddingMiddle = dataMemberSz % alignOfT;
343 if (paddingMiddle != 0)
344 paddingMiddle = alignOfT - paddingMiddle;
345 const bool isSmall = (
reinterpret_cast<void *
>(begin) == (beginPtr + dataMemberSz + paddingMiddle));
347 const bool owns = (*capacityPtr != -1);
348 if (!isSmall && owns)
379 : fSerializationTypes(serializationTypes), fDeserializationTypes(serializationTypes)
382 deserializationExtraTypes.begin(), deserializationExtraTypes.end());
397 : fField(other.fField),
399 fCapacity(other.fCapacity),
401 fIsAdopted(other.fIsAdopted),
402 fNValidValues(other.fNValidValues),
403 fFirstIndex(other.fFirstIndex)
405 std::swap(
fDeleter, other.fDeleter);
406 std::swap(
fValues, other.fValues);
412 std::swap(fField, other.fField);
413 std::swap(fDeleter, other.fDeleter);
414 std::swap(fValues, other.fValues);
416 std::swap(fCapacity, other.fCapacity);
417 std::swap(
fSize, other.fSize);
418 std::swap(fIsAdopted, other.fIsAdopted);
419 std::swap(fMaskAvail, other.fMaskAvail);
420 std::swap(fNValidValues, other.fNValidValues);
421 std::swap(fFirstIndex, other.fFirstIndex);
441 for (std::size_t i = 0; i < fCapacity; ++i) {
442 fDeleter->operator()(GetValuePtrAt(i),
true );
449 if (fCapacity <
size) {
451 throw RException(
R__FAIL(
"invalid attempt to bulk read beyond the adopted buffer"));
457 for (std::size_t i = 0; i <
size; ++i) {
458 fField->ConstructValue(GetValuePtrAt(i));
462 fMaskAvail = std::make_unique<bool[]>(
size);
466 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
469 fFirstIndex = firstIndex;
476 for (std::size_t i = 0; i <
fSize; ++i)
477 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
484 fCapacity = capacity;
487 fMaskAvail = std::make_unique<bool[]>(capacity);
502std::unique_ptr<void, typename ROOT::Experimental::RFieldBase::RCreateObjectDeleter<void>::deleter>
503ROOT::Experimental::RFieldBase::CreateObject<void>()
const
506 return std::unique_ptr<void, RCreateObjectDeleter<void>::deleter>(
CreateObjectRawPtr(), gDeleter);
512 bool isSimple, std::size_t nRepetitions)
527 auto parent = GetParent();
528 while (parent && !parent->GetFieldName().empty()) {
530 parent = parent->GetParent();
538 auto typeAlias = GetNormalizedTypeName(typeName);
539 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
543std::vector<ROOT::Experimental::RFieldBase::RCheckResult>
546 auto typeAlias = GetNormalizedTypeName(typeName);
547 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
552 std::vector<RCheckResult>
result;
553 for (
const auto &
f : fieldZero) {
559 RCheckResult{invalidField->GetQualifiedFieldName(), invalidField->GetTypeName(), invalidField->GetError()});
566 const std::string &typeAlias,
bool continueOnError)
568 thread_local CreateContext createContext;
569 CreateContextGuard createContextGuard(createContext);
571 createContextGuard.SetContinueOnError(
true);
573 auto fnFail = [&fieldName, &canonicalType](
const std::string &errMsg) ->
RResult<std::unique_ptr<RFieldBase>> {
574 if (createContext.GetContinueOnError()) {
575 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, errMsg));
581 if (canonicalType.empty())
582 return R__FORWARD_RESULT(fnFail(
"no type name specified for field '" + fieldName +
"'"));
584 if (
auto [arrayBaseType, arraySizes] = ParseArrayType(canonicalType); !arraySizes.empty()) {
585 std::unique_ptr<RFieldBase> arrayField = Create(
"_0", arrayBaseType).Unwrap();
586 for (
int i = arraySizes.size() - 1; i >= 0; --i) {
587 arrayField = std::make_unique<RArrayField>((i == 0) ? fieldName :
"_0", std::move(arrayField), arraySizes[i]);
592 std::unique_ptr<ROOT::Experimental::RFieldBase>
result;
594 if (canonicalType ==
"ROOT::Experimental::ClusterSize_t") {
595 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
596 }
else if (canonicalType ==
"bool") {
597 result = std::make_unique<RField<bool>>(fieldName);
598 }
else if (canonicalType ==
"char") {
599 result = std::make_unique<RField<char>>(fieldName);
600 }
else if (canonicalType ==
"std::byte") {
601 result = std::make_unique<RField<std::byte>>(fieldName);
602 }
else if (canonicalType ==
"std::int8_t") {
603 result = std::make_unique<RField<std::int8_t>>(fieldName);
604 }
else if (canonicalType ==
"std::uint8_t") {
605 result = std::make_unique<RField<std::uint8_t>>(fieldName);
606 }
else if (canonicalType ==
"std::int16_t") {
607 result = std::make_unique<RField<std::int16_t>>(fieldName);
608 }
else if (canonicalType ==
"std::uint16_t") {
609 result = std::make_unique<RField<std::uint16_t>>(fieldName);
610 }
else if (canonicalType ==
"std::int32_t") {
611 result = std::make_unique<RField<std::int32_t>>(fieldName);
612 }
else if (canonicalType ==
"std::uint32_t") {
613 result = std::make_unique<RField<std::uint32_t>>(fieldName);
614 }
else if (canonicalType ==
"std::int64_t") {
615 result = std::make_unique<RField<std::int64_t>>(fieldName);
616 }
else if (canonicalType ==
"std::uint64_t") {
617 result = std::make_unique<RField<std::uint64_t>>(fieldName);
618 }
else if (canonicalType ==
"float") {
619 result = std::make_unique<RField<float>>(fieldName);
620 }
else if (canonicalType ==
"double") {
621 result = std::make_unique<RField<double>>(fieldName);
622 }
else if (canonicalType ==
"Double32_t") {
623 result = std::make_unique<RField<double>>(fieldName);
627 }
else if (canonicalType ==
"std::string") {
628 result = std::make_unique<RField<std::string>>(fieldName);
629 }
else if (canonicalType ==
"std::vector<bool>") {
630 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
631 }
else if (canonicalType.substr(0, 12) ==
"std::vector<") {
632 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
633 auto itemField = Create(
"_0", itemTypeName);
634 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
635 }
else if (canonicalType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
636 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
637 auto itemField = Create(
"_0", itemTypeName);
638 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
639 }
else if (canonicalType.substr(0, 11) ==
"std::array<") {
640 auto arrayDef = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
641 if (arrayDef.size() != 2) {
642 return R__FORWARD_RESULT(fnFail(
"the template list for std::array must have exactly two elements"));
644 auto arrayLength = std::stoi(arrayDef[1]);
645 auto itemField = Create(
"_0", arrayDef[0]);
646 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
647 }
else if (canonicalType.substr(0, 13) ==
"std::variant<") {
648 auto innerTypes = TokenizeTypeList(canonicalType.substr(13, canonicalType.length() - 14));
649 std::vector<RFieldBase *> items;
650 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
651 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap().release());
653 result = std::make_unique<RVariantField>(fieldName, items);
654 }
else if (canonicalType.substr(0, 10) ==
"std::pair<") {
655 auto innerTypes = TokenizeTypeList(canonicalType.substr(10, canonicalType.length() - 11));
656 if (innerTypes.size() != 2) {
657 return R__FORWARD_RESULT(fnFail(
"the type list for std::pair must have exactly two elements"));
659 std::array<std::unique_ptr<RFieldBase>, 2> items{Create(
"_0", innerTypes[0]).Unwrap(),
660 Create(
"_1", innerTypes[1]).Unwrap()};
661 result = std::make_unique<RPairField>(fieldName, items);
662 }
else if (canonicalType.substr(0, 11) ==
"std::tuple<") {
663 auto innerTypes = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
664 std::vector<std::unique_ptr<RFieldBase>> items;
665 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
666 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
668 result = std::make_unique<RTupleField>(fieldName, items);
669 }
else if (canonicalType.substr(0, 12) ==
"std::bitset<") {
670 auto size = std::stoull(canonicalType.substr(12, canonicalType.length() - 13));
671 result = std::make_unique<RBitsetField>(fieldName,
size);
672 }
else if (canonicalType.substr(0, 16) ==
"std::unique_ptr<") {
673 std::string itemTypeName = canonicalType.substr(16, canonicalType.length() - 17);
674 auto itemField = Create(
"_0", itemTypeName).Unwrap();
675 auto normalizedInnerTypeName = itemField->GetTypeName();
676 result = std::make_unique<RUniquePtrField>(fieldName,
"std::unique_ptr<" + normalizedInnerTypeName +
">",
677 std::move(itemField));
678 }
else if (canonicalType.substr(0, 9) ==
"std::set<") {
679 std::string itemTypeName = canonicalType.substr(9, canonicalType.length() - 10);
680 auto itemField = Create(
"_0", itemTypeName).Unwrap();
681 auto normalizedInnerTypeName = itemField->GetTypeName();
683 std::make_unique<RSetField>(fieldName,
"std::set<" + normalizedInnerTypeName +
">", std::move(itemField));
684 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_set<") {
685 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
686 auto itemField = Create(
"_0", itemTypeName).Unwrap();
687 auto normalizedInnerTypeName = itemField->GetTypeName();
688 result = std::make_unique<RSetField>(fieldName,
"std::unordered_set<" + normalizedInnerTypeName +
">",
689 std::move(itemField));
690 }
else if (canonicalType.substr(0, 9) ==
"std::map<") {
691 auto innerTypes = TokenizeTypeList(canonicalType.substr(9, canonicalType.length() - 10));
692 if (innerTypes.size() != 2) {
693 return R__FORWARD_RESULT(fnFail(
"the type list for std::map must have exactly two elements"));
696 auto normalizedKeyTypeName = GetNormalizedTypeName(innerTypes[0]);
697 auto normalizedValueTypeName = GetNormalizedTypeName(innerTypes[1]);
700 Create(
"_0",
"std::pair<" + normalizedKeyTypeName +
"," + normalizedValueTypeName +
">").Unwrap();
701 result = std::make_unique<RMapField>(
702 fieldName,
"std::map<" + normalizedKeyTypeName +
"," + normalizedValueTypeName +
">", std::move(itemField));
703 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_map<") {
704 auto innerTypes = TokenizeTypeList(canonicalType.substr(19, canonicalType.length() - 20));
705 if (innerTypes.size() != 2)
706 return R__FORWARD_RESULT(fnFail(
"the type list for std::unordered_map must have exactly two elements"));
708 auto normalizedKeyTypeName = GetNormalizedTypeName(innerTypes[0]);
709 auto normalizedValueTypeName = GetNormalizedTypeName(innerTypes[1]);
712 Create(
"_0",
"std::pair<" + normalizedKeyTypeName +
"," + normalizedValueTypeName +
">").Unwrap();
713 result = std::make_unique<RMapField>(
714 fieldName,
"std::unordered_map<" + normalizedKeyTypeName +
"," + normalizedValueTypeName +
">",
715 std::move(itemField));
716 }
else if (canonicalType.substr(0, 12) ==
"std::atomic<") {
717 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
718 auto itemField = Create(
"_0", itemTypeName).Unwrap();
719 auto normalizedInnerTypeName = itemField->GetTypeName();
720 result = std::make_unique<RAtomicField>(fieldName,
"std::atomic<" + normalizedInnerTypeName +
">",
721 std::move(itemField));
722 }
else if (canonicalType.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<") {
723 auto innerTypes = TokenizeTypeList(canonicalType.substr(39, canonicalType.length() - 40));
724 if (innerTypes.size() != 1)
725 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
726 if (innerTypes[0] ==
"std::uint32_t") {
727 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
728 }
else if (innerTypes[0] ==
"std::uint64_t") {
729 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
731 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
739 result = std::make_unique<REnumField>(fieldName, canonicalType);
746 createContextGuard.AddClassToStack(canonicalType);
747 if (cl->GetCollectionProxy()) {
748 result = std::make_unique<RProxiedCollectionField>(fieldName, canonicalType);
750 result = std::make_unique<RClassField>(fieldName, canonicalType);
755 auto error =
e.GetError();
756 if (createContext.GetContinueOnError()) {
757 std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, error.GetReport()));
764 if (typeAlias != canonicalType)
765 result->fTypeAlias = typeAlias;
773 if (fieldName.empty()) {
774 return R__FAIL(
"name cannot be empty string \"\"");
775 }
else if (fieldName.find(
'.') != std::string::npos) {
776 return R__FAIL(
"name '" + std::string(fieldName) +
"' cannot contain dot characters '.'");
785 return representations;
790 auto clone = CloneImpl(newName);
791 clone->fTypeAlias = fTypeAlias;
792 clone->fOnDiskId = fOnDiskId;
793 clone->fDescription = fDescription;
795 clone->fColumnRepresentative = fColumnRepresentative;
801 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
812 const auto valueSize = GetValueSize();
813 std::size_t nRead = 0;
814 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
823 Read(bulkSpec.
fFirstIndex + i,
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + i * valueSize);
832 void *where =
operator new(GetValueSize());
834 ConstructValue(where);
840 void *obj = CreateObjectRawPtr();
844std::vector<ROOT::Experimental::RFieldBase::RValue>
847 return std::vector<RValue>();
854 if (fState != EState::kUnconnected)
855 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
856 child->fParent =
this;
857 fSubFields.emplace_back(std::move(
child));
863 std::size_t
result = globalIndex;
864 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
865 auto parent =
f->GetParent();
866 if (parent && (parent->GetStructure() ==
kCollection || parent->GetStructure() ==
kVariant))
868 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
875 std::vector<RFieldBase *>
result;
876 result.reserve(fSubFields.size());
877 for (
const auto &
f : fSubFields) {
885 std::vector<const RFieldBase *>
result;
886 result.reserve(fSubFields.size());
887 for (
const auto &
f : fSubFields) {
895 for (
auto& column : fColumns) {
903 if (fState != EState::kUnconnected)
904 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
905 fDescription = std::string(description);
910 if (fState != EState::kUnconnected)
918 if (fColumnRepresentative)
919 return *fColumnRepresentative;
920 return GetColumnRepresentations().GetSerializationDefault();
925 if (fState != EState::kUnconnected)
926 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
927 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
928 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(), representative);
929 if (itRepresentative == std::end(validTypes))
931 fColumnRepresentative = &(*itRepresentative);
938 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
942 onDiskTypes.emplace_back(
c.GetModel().GetType());
944 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
945 if (t == onDiskTypes)
949 std::string columnTypeNames;
950 for (
const auto &t : onDiskTypes) {
951 if (!columnTypeNames.empty())
952 columnTypeNames +=
", ";
955 throw RException(
R__FAIL(
"On-disk column types `" + columnTypeNames +
"` for field `" + GetQualifiedFieldName() +
956 "` cannot be matched."));
961 fReadCallbacks.push_back(func);
963 return fReadCallbacks.size() - 1;
968 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
969 fIsSimple = (fTraits & kTraitMappable) && fReadCallbacks.empty();
974 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
976 for (
auto &colType : rep) {
988 SetColumnRepresentative(rep);
993 for (
auto &colType : rep) {
1000 SetColumnRepresentative(rep);
1003 if (fTypeAlias ==
"Double32_t")
1010 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page sink"));
1011 if (fState != EState::kUnconnected)
1012 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
1016 GenerateColumnsImpl();
1017 if (!fColumns.empty())
1018 fPrincipalColumn = fColumns[0].get();
1019 for (
auto &column : fColumns) {
1020 auto firstElementIndex = (column.get() == fPrincipalColumn) ? EntryToColumnElementIndex(firstEntry) : 0;
1021 column->ConnectPageSink(fOnDiskId, pageSink, firstElementIndex);
1024 fState = EState::kConnectedToSink;
1030 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
1031 if (fState != EState::kUnconnected)
1032 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
1034 if (fColumnRepresentative)
1035 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
1036 if (!fDescription.empty())
1037 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
1039 for (
auto &
f : fSubFields) {
1043 f->ConnectPageSource(pageSource);
1049 GenerateColumnsImpl(desc);
1051 for (
const auto &
c : fColumns) {
1052 onDiskColumnTypes.emplace_back(
c->GetModel().GetType());
1054 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1055 if (t == onDiskColumnTypes)
1056 fColumnRepresentative = &t;
1062 if (!fColumns.empty())
1063 fPrincipalColumn = fColumns[0].get();
1064 for (
auto& column : fColumns)
1065 column->ConnectPageSource(fOnDiskId, pageSource);
1066 OnConnectPageSource();
1068 fState = EState::kConnectedToSource;
1078std::unique_ptr<ROOT::Experimental::RFieldBase>
1081 auto result = std::make_unique<RFieldZero>();
1082 for (
auto &
f : fSubFields)
1083 result->Attach(
f->Clone(
f->GetFieldName()));
1099 static RColumnRepresentations representations(
1102 return representations;
1107 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1112 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1113 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
1118 visitor.VisitClusterSizeField(*
this);
1129 return representations;
1134 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1135 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
1161 return representations;
1166 fColumns.emplace_back(Internal::RColumn::Create<char>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1171 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1172 fColumns.emplace_back(Internal::RColumn::Create<char>(
RColumnModel(onDiskTypes[0]), 0));
1186 return representations;
1191 fColumns.emplace_back(Internal::RColumn::Create<char>(RColumnModel(GetColumnRepresentative()[0]), 0));
1196 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1197 fColumns.emplace_back(Internal::RColumn::Create<char>(RColumnModel(onDiskTypes[0]), 0));
1202 visitor.VisitByteField(*
this);
1211 return representations;
1216 fColumns.emplace_back(Internal::RColumn::Create<std::int8_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1221 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1222 fColumns.emplace_back(Internal::RColumn::Create<std::int8_t>(RColumnModel(onDiskTypes[0]), 0));
1227 visitor.VisitInt8Field(*
this);
1236 return representations;
1241 fColumns.emplace_back(Internal::RColumn::Create<std::uint8_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1246 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1247 fColumns.emplace_back(Internal::RColumn::Create<std::uint8_t>(RColumnModel(onDiskTypes[0]), 0));
1252 visitor.VisitUInt8Field(*
this);
1261 return representations;
1266 fColumns.emplace_back(Internal::RColumn::Create<bool>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1271 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1272 fColumns.emplace_back(Internal::RColumn::Create<bool>(
RColumnModel(onDiskTypes[0]), 0));
1287 return representations;
1292 fColumns.emplace_back(Internal::RColumn::Create<float>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1297 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1298 fColumns.emplace_back(Internal::RColumn::Create<float>(
RColumnModel(onDiskTypes[0]), 0));
1318 return representations;
1323 fColumns.emplace_back(Internal::RColumn::Create<double>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1328 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1329 fColumns.emplace_back(Internal::RColumn::Create<double>(
RColumnModel(onDiskTypes[0]), 0));
1339 fTypeAlias =
"Double32_t";
1349 return representations;
1354 fColumns.emplace_back(Internal::RColumn::Create<std::int16_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1359 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1360 fColumns.emplace_back(Internal::RColumn::Create<std::int16_t>(RColumnModel(onDiskTypes[0]), 0));
1365 visitor.VisitInt16Field(*
this);
1375 return representations;
1380 fColumns.emplace_back(Internal::RColumn::Create<std::uint16_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1385 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1386 fColumns.emplace_back(Internal::RColumn::Create<std::uint16_t>(RColumnModel(onDiskTypes[0]), 0));
1391 visitor.VisitUInt16Field(*
this);
1401 return representations;
1406 fColumns.emplace_back(Internal::RColumn::Create<std::int32_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1411 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1412 fColumns.emplace_back(Internal::RColumn::Create<std::int32_t>(RColumnModel(onDiskTypes[0]), 0));
1417 visitor.VisitIntField(*
this);
1427 return representations;
1432 fColumns.emplace_back(Internal::RColumn::Create<std::uint32_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1437 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1438 fColumns.emplace_back(Internal::RColumn::Create<std::uint32_t>(RColumnModel(onDiskTypes[0]), 0));
1443 visitor.VisitUInt32Field(*
this);
1453 return representations;
1458 fColumns.emplace_back(Internal::RColumn::Create<std::uint64_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1463 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1464 fColumns.emplace_back(Internal::RColumn::Create<std::uint64_t>(RColumnModel(onDiskTypes[0]), 0));
1469 visitor.VisitUInt64Field(*
this);
1484 return representations;
1489 fColumns.emplace_back(Internal::RColumn::Create<std::int64_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1494 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1495 fColumns.emplace_back(Internal::RColumn::Create<std::int64_t>(RColumnModel(onDiskTypes[0]), 0));
1500 visitor.VisitInt64Field(*
this);
1513 return representations;
1518 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1519 fColumns.emplace_back(Internal::RColumn::Create<char>(RColumnModel(GetColumnRepresentative()[1]), 1));
1524 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1525 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
1526 fColumns.emplace_back(Internal::RColumn::Create<char>(RColumnModel(onDiskTypes[1]), 1));
1531 auto typedValue =
static_cast<const std::string *
>(from);
1532 auto length = typedValue->length();
1533 fColumns[1]->AppendV(typedValue->data(),
length);
1535 fColumns[0]->Append(&fIndex);
1536 return length + fColumns[0]->GetElement()->GetPackedSize();
1541 auto typedValue =
static_cast<std::string *
>(to);
1542 RClusterIndex collectionStart;
1544 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
1546 typedValue->clear();
1548 typedValue->resize(nChars);
1549 fColumns[1]->ReadV(collectionStart, nChars,
const_cast<char *
>(typedValue->data()));
1555 visitor.VisitStringField(*
this);
1570 throw RException(
R__FAIL(
"RField: no I/O support for type " + std::string(className)));
1578 R__FAIL(std::string(className) +
" has an associated collection proxy; use RProxiedCollectionField instead"));
1592 if (baseClass->GetDelta() < 0) {
1593 throw RException(
R__FAIL(std::string(
"virtual inheritance is not supported: ") + std::string(className) +
1594 " virtually inherits from " + baseClass->GetName()));
1596 TClass *
c = baseClass->GetClassPointer();
1599 fTraits &= subField->GetTraits();
1600 Attach(std::move(subField),
1609 if (!dataMember->IsPersistent()) {
1615 std::string typeName{GetNormalizedTypeName(dataMember->GetTrueTypeName())};
1616 std::string typeAlias{GetNormalizedTypeName(dataMember->GetFullTypeName())};
1618 if (dataMember->Property() &
kIsArray) {
1619 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim)
1620 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
1622 auto subField =
RFieldBase::Create(dataMember->GetName(), typeName, typeAlias).Unwrap();
1623 fTraits &= subField->GetTraits();
1624 Attach(std::move(subField),
1631 fMaxAlignment = std::max(fMaxAlignment,
child->GetAlignment());
1632 fSubFieldsInfo.push_back(info);
1639 for (
const auto rule : rules) {
1644 auto func = rule->GetReadFunctionPointer();
1646 fReadCallbacks.emplace_back([func, classp](
void *
target) {
1650 func(
static_cast<char *
>(
target), &oldObj);
1651 oldObj.fClass =
nullptr;
1656std::unique_ptr<ROOT::Experimental::RFieldBase>
1660 SyncFieldIDs(*
this, *
result);
1666 std::size_t nbytes = 0;
1667 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1668 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fSubFieldsInfo[i].fOffset);
1675 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1676 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1682 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1683 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1691 const auto ruleset =
fClass->GetSchemaRules();
1695 if (rule->GetTarget() ==
nullptr)
1698 const auto dataMember = klass->GetDataMember(
target->GetString());
1699 if (!dataMember || dataMember->IsPersistent()) {
1701 << dataMember->GetName();
1708 auto rules = ruleset->FindRules(
fClass->GetName(),
static_cast<Int_t>(GetOnDiskTypeVersion()));
1709 rules.erase(std::remove_if(rules.begin(), rules.end(), referencesNonTransientMembers), rules.end());
1710 AddReadCallbacksFromIORules(rules,
fClass);
1720 fClass->Destructor(objPtr,
true );
1721 RDeleter::operator()(objPtr, dtorOnly);
1724std::vector<ROOT::Experimental::RFieldBase::RValue>
1727 std::vector<RValue>
result;
1728 auto basePtr =
value.GetPtr<
unsigned char>().get();
1729 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1731 fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fSubFieldsInfo[i].fOffset)));
1739 return fClass->GetClassSize();
1744 return fClass->GetClassVersion();
1755 :
REnumField(fieldName, enumName,
TEnum::GetEnum(std::string(enumName).c_str()))
1762 if (enump ==
nullptr) {
1763 throw RException(
R__FAIL(
"RField: no I/O support for enum type " + std::string(enumName)));
1781 default:
throw RException(
R__FAIL(
"Unsupported underlying integral type for enum type " + std::string(enumName)));
1788 std::unique_ptr<RFieldBase> intField)
1791 Attach(std::move(intField));
1795std::unique_ptr<ROOT::Experimental::RFieldBase>
1798 auto newIntField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
1799 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
1802std::vector<ROOT::Experimental::RFieldBase::RValue>
1805 std::vector<RValue>
result;
1806 result.emplace_back(fSubFields[0]->BindValue(
value.GetPtr<
void>()));
1826 (ifuncs.
fNext !=
nullptr));
1831 std::string_view typeName,
TClass *classp)
1834 if (classp ==
nullptr)
1835 throw RException(
R__FAIL(
"RField: no I/O support for collection proxy type " + std::string(typeName)));
1837 throw RException(
R__FAIL(std::string(typeName) +
" has no associated collection proxy"));
1842 if (
fProxy->HasPointers())
1843 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
1844 if (!
fProxy->GetCollectionClass()->HasDictionary()) {
1846 GetNormalizedTypeName(
fProxy->GetCollectionClass()->GetName())));
1854 std::string_view typeName,
1855 std::unique_ptr<RFieldBase> itemField)
1859 Attach(std::move(itemField));
1863 std::string_view typeName)
1868 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
1870 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField;
1872 if (
auto valueClass =
fProxy->GetValueClass()) {
1876 switch (
fProxy->GetType()) {
1878 case EDataType::kUChar_t: itemField = std::make_unique<RField<std::uint8_t>>(
"_0");
break;
1879 case EDataType::kShort_t: itemField = std::make_unique<RField<std::int16_t>>(
"_0");
break;
1881 case EDataType::kInt_t: itemField = std::make_unique<RField<std::int32_t>>(
"_0");
break;
1882 case EDataType::kUInt_t: itemField = std::make_unique<RField<std::uint32_t>>(
"_0");
break;
1885 itemField = std::make_unique<RField<std::int64_t>>(
"_0");
1889 itemField = std::make_unique<RField<std::uint64_t>>(
"_0");
1900 Attach(std::move(itemField));
1903std::unique_ptr<ROOT::Experimental::RFieldBase>
1906 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
1907 return std::unique_ptr<RProxiedCollectionField>(
1913 std::size_t nbytes = 0;
1917 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1918 nbytes += CallAppendOn(*fSubFields[0], ptr);
1923 fColumns[0]->Append(&fNWritten);
1924 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
1931 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1939 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
1940 CallReadOn(*fSubFields[0], collectionStart + (i++), elementPtr);
1943 fProxy->Commit(obj);
1952 return representations;
1957 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1962 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1963 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
1971std::unique_ptr<ROOT::Experimental::RFieldBase::RDeleter>
1975 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
1976 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubFields[0]), itemSize);
1978 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
1986 fItemDeleter->operator()(ptr,
true );
1989 fProxy->Destructor(objPtr,
true );
1990 RDeleter::operator()(objPtr, dtorOnly);
1993std::vector<ROOT::Experimental::RFieldBase::RValue>
1996 std::vector<RValue>
result;
1997 auto valueRawPtr =
value.GetPtr<
void>().get();
2000 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2001 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
2014 std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
2015 const std::vector<std::size_t> &offsets, std::string_view typeName)
2020 for (
auto &item : itemFields) {
2029 std::vector<std::unique_ptr<RFieldBase>> &&itemFields)
2033 for (
auto &item : itemFields) {
2037 fSize += item->GetValueSize();
2047 std::vector<std::unique_ptr<RFieldBase>> &itemFields)
2054 if (itemAlignment > 1) {
2055 auto remainder = baseOffset % itemAlignment;
2057 return itemAlignment - remainder;
2062std::unique_ptr<ROOT::Experimental::RFieldBase>
2065 std::vector<std::unique_ptr<RFieldBase>> cloneItems;
2066 cloneItems.reserve(fSubFields.size());
2067 for (
auto &item : fSubFields)
2068 cloneItems.emplace_back(item->Clone(item->GetFieldName()));
2069 return std::unique_ptr<RRecordField>(
new RRecordField(newName, std::move(cloneItems), fOffsets, GetTypeName()));
2074 std::size_t nbytes = 0;
2075 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2076 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
2083 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2084 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2090 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2091 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2097 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2098 CallConstructValueOn(*fSubFields[i],
static_cast<unsigned char *
>(where) + fOffsets[i]);
2104 for (
unsigned i = 0; i < fItemDeleters.size(); ++i) {
2105 fItemDeleters[i]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fOffsets[i],
true );
2107 RDeleter::operator()(objPtr, dtorOnly);
2112 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2113 itemDeleters.reserve(fOffsets.size());
2114 for (
const auto &
f : fSubFields) {
2115 itemDeleters.emplace_back(GetDeleterOf(*
f));
2117 return std::make_unique<RRecordDeleter>(itemDeleters, fOffsets);
2120std::vector<ROOT::Experimental::RFieldBase::RValue>
2123 auto basePtr =
value.GetPtr<
unsigned char>().get();
2124 std::vector<RValue>
result;
2125 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2126 result.emplace_back(fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fOffsets[i])));
2140 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::vector<" + itemField->GetTypeName() +
">",
2142 fItemSize(itemField->GetValueSize()),
2147 Attach(std::move(itemField));
2150std::unique_ptr<ROOT::Experimental::RFieldBase>
2153 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2154 return std::make_unique<RVectorField>(newName, std::move(newItemField));
2159 auto typedValue =
static_cast<const std::vector<char> *
>(from);
2160 R__ASSERT((typedValue->size() % fItemSize) == 0);
2161 std::size_t nbytes = 0;
2162 auto count = typedValue->size() / fItemSize;
2164 if (fSubFields[0]->IsSimple() && count) {
2165 GetPrincipalColumnOf(*fSubFields[0])->AppendV(typedValue->data(), count);
2166 nbytes += count * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2168 for (
unsigned i = 0; i < count; ++i) {
2169 nbytes += CallAppendOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2174 fColumns[0]->Append(&fNWritten);
2175 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
2180 auto typedValue =
static_cast<std::vector<char> *
>(to);
2184 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2186 if (fSubFields[0]->IsSimple()) {
2187 typedValue->resize(nItems * fItemSize);
2189 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, typedValue->data());
2194 const auto oldNItems = typedValue->size() / fItemSize;
2195 const bool canRealloc = oldNItems < nItems;
2196 bool allDeallocated =
false;
2198 allDeallocated = canRealloc;
2199 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
2200 fItemDeleter->operator()(typedValue->data() + (i * fItemSize),
true );
2203 typedValue->resize(nItems * fItemSize);
2204 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)) {
2205 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
2206 CallConstructValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2210 for (std::size_t i = 0; i < nItems; ++i) {
2211 CallReadOn(*fSubFields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
2221 return representations;
2226 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2231 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2232 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
2237 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
2239 R__ASSERT((vecPtr->size() % fItemSize) == 0);
2240 auto nItems = vecPtr->size() / fItemSize;
2241 for (std::size_t i = 0; i < nItems; ++i) {
2242 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize),
true );
2245 std::destroy_at(vecPtr);
2246 RDeleter::operator()(objPtr, dtorOnly);
2252 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubFields[0]));
2253 return std::make_unique<RVectorDeleter>();
2256std::vector<ROOT::Experimental::RFieldBase::RValue>
2259 auto vec =
value.GetPtr<std::vector<char>>();
2261 auto nItems =
vec->size() / fItemSize;
2262 std::vector<RValue>
result;
2263 for (
unsigned i = 0; i < nItems; ++i) {
2265 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(),
vec->data() + (i * fItemSize))));
2279 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
2281 fItemSize(itemField->GetValueSize()),
2286 Attach(std::move(itemField));
2290std::unique_ptr<ROOT::Experimental::RFieldBase>
2293 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2294 return std::make_unique<RRVecField>(newName, std::move(newItemField));
2299 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(from);
2301 std::size_t nbytes = 0;
2302 if (fSubFields[0]->IsSimple() && *sizePtr) {
2303 GetPrincipalColumnOf(*fSubFields[0])->AppendV(*beginPtr, *sizePtr);
2304 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2306 auto begin =
reinterpret_cast<const char *
>(*beginPtr);
2307 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2308 nbytes += CallAppendOn(*fSubFields[0], begin + i * fItemSize);
2312 fNWritten += *sizePtr;
2313 fColumns[0]->Append(&fNWritten);
2314 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
2322 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(to);
2327 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2328 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2329 const std::size_t oldSize = *sizePtr;
2333 const bool owns = (*capacityPtr != -1);
2334 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
2335 const bool needsDestruct = owns && fItemDeleter;
2338 if (needsDestruct) {
2339 for (std::size_t i = nItems; i < oldSize; ++i) {
2340 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2345 if (std::int32_t(nItems) > *capacityPtr) {
2348 if (needsDestruct) {
2349 for (std::size_t i = 0u; i < oldSize; ++i) {
2350 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2361 *beginPtr =
malloc(nItems * fItemSize);
2363 begin =
reinterpret_cast<char *
>(*beginPtr);
2364 *capacityPtr = nItems;
2367 if (needsConstruct) {
2368 for (std::size_t i = 0u; i < oldSize; ++i)
2369 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2375 if (needsConstruct) {
2376 for (std::size_t i = oldSize; i < nItems; ++i)
2377 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2380 if (fSubFields[0]->IsSimple() && nItems) {
2381 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, begin);
2386 for (std::size_t i = 0; i < nItems; ++i) {
2387 CallReadOn(*fSubFields[0], collectionStart + i, begin + (i * fItemSize));
2393 if (!fSubFields[0]->IsSimple())
2399 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
2400 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fSubFields[0]->GetValueSize();
2402 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
2403 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
2404 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(bulkSpec.
fValues);
2410 this->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
2411 *beginPtr = itemValueArray;
2412 *sizePtr = collectionSize;
2418 auto lastOffset = firstItemIndex.
GetIndex() + collectionSize;
2420 std::size_t nValues = 1;
2421 std::size_t nItems = collectionSize;
2422 while (nRemainingValues > 0) {
2425 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
2426 for (std::size_t i = 0; i < nBatch; ++i) {
2427 const auto size = offsets[i] - lastOffset;
2428 std::tie(beginPtr, sizePtr, capacityPtr) =
2429 GetRVecDataMembers(
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
2430 *beginPtr = itemValueArray + nItems * itemValueSize;
2435 lastOffset = offsets[i];
2437 nRemainingValues -= nBatch;
2441 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
2443 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
2445 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
2446 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
2447 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
2452 GetPrincipalColumnOf(*fSubFields[0])->ReadV(firstItemIndex, nItems, itemValueArray - delta);
2453 return RBulkSpec::kAllSet;
2462 return representations;
2467 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2472 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2473 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
2480 void **beginPtr =
new (where)(
void *)(
nullptr);
2481 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2482 new (sizePtr + 1) std::int32_t(-1);
2487 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(objPtr);
2489 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2491 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2492 fItemDeleter->operator()(begin + i * fItemSize,
true );
2496 DestroyRVecWithChecks(fItemAlignment, beginPtr, begin, capacityPtr);
2497 RDeleter::operator()(objPtr, dtorOnly);
2503 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubFields[0]));
2504 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment());
2507std::vector<ROOT::Experimental::RFieldBase::RValue>
2510 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(
value.GetPtr<
void>().get());
2512 std::vector<RValue>
result;
2513 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2514 result.reserve(*sizePtr);
2515 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2516 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), begin + i * fItemSize)));
2528 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
2546 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
2547 auto count = typedValue->size();
2548 for (
unsigned i = 0; i < count; ++i) {
2549 bool bval = (*typedValue)[i];
2550 CallAppendOn(*fSubFields[0], &bval);
2553 fColumns[0]->Append(&fNWritten);
2554 return count + fColumns[0]->GetElement()->GetPackedSize();
2559 auto typedValue =
static_cast<std::vector<bool> *
>(to);
2562 RClusterIndex collectionStart;
2563 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2565 typedValue->resize(nItems);
2566 for (
unsigned i = 0; i < nItems; ++i) {
2568 CallReadOn(*fSubFields[0], collectionStart + i, &bval);
2569 (*typedValue)[i] = bval;
2576 static RColumnRepresentations representations(
2579 return representations;
2584 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
2589 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2590 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
2593std::vector<ROOT::Experimental::RFieldBase::RValue>
2596 const auto &typedValue =
value.GetRef<std::vector<bool>>();
2597 auto count = typedValue.size();
2598 std::vector<RValue>
result;
2599 for (
unsigned i = 0; i < count; ++i) {
2601 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
2603 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
2610 visitor.VisitVectorBoolField(*
this);
2617 std::size_t arrayLength)
2619 "std::array<" + itemField->GetTypeName() +
"," + std::to_string(arrayLength) +
">",
2621 fItemSize(itemField->GetValueSize()),
2622 fArrayLength(arrayLength)
2624 fTraits |= itemField->GetTraits() & ~kTraitMappable;
2625 Attach(std::move(itemField));
2628std::unique_ptr<ROOT::Experimental::RFieldBase>
2631 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2632 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
2637 std::size_t nbytes = 0;
2638 auto arrayPtr =
static_cast<const unsigned char *
>(from);
2639 for (
unsigned i = 0; i < fArrayLength; ++i) {
2640 nbytes += CallAppendOn(*fSubFields[0], arrayPtr + (i * fItemSize));
2647 auto arrayPtr =
static_cast<unsigned char *
>(to);
2648 for (
unsigned i = 0; i < fArrayLength; ++i) {
2649 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
2655 auto arrayPtr =
static_cast<unsigned char *
>(to);
2656 for (
unsigned i = 0; i < fArrayLength; ++i) {
2658 arrayPtr + (i * fItemSize));
2664 if (fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)
2667 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
2668 for (
unsigned i = 0; i < fArrayLength; ++i) {
2669 CallConstructValueOn(*fSubFields[0], arrayPtr + (i * fItemSize));
2676 for (
unsigned i = 0; i < fArrayLength; ++i) {
2677 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
2680 RDeleter::operator()(objPtr, dtorOnly);
2685 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible))
2686 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetDeleterOf(*fSubFields[0]));
2687 return std::make_unique<RDeleter>();
2690std::vector<ROOT::Experimental::RFieldBase::RValue>
2693 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
2694 std::vector<RValue>
result;
2695 for (
unsigned i = 0; i < fArrayLength; ++i) {
2697 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
2711 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField,
2712 std::size_t arrayLength)
2713 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
2715 fItemSize(itemField->GetValueSize()),
2716 fArrayLength(arrayLength)
2718 Attach(std::move(itemField));
2724std::unique_ptr<ROOT::Experimental::RFieldBase>
2727 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2728 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
2734 void **beginPtr =
new (where)(
void *)(
nullptr);
2735 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2736 std::int32_t *capacityPtr =
new (sizePtr + 1) std::int32_t(0);
2740 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2743 if (*sizePtr == std::int32_t(fArrayLength))
2749 const bool owns = (*capacityPtr != -1);
2750 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
2751 const bool needsDestruct = owns && fItemDeleter;
2755 if (needsDestruct) {
2756 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2757 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2767 *beginPtr =
malloc(fArrayLength * fItemSize);
2770 begin =
reinterpret_cast<char *
>(*beginPtr);
2772 *sizePtr = fArrayLength;
2773 *capacityPtr = fArrayLength;
2776 if (needsConstruct) {
2777 for (std::size_t i = 0; i < fArrayLength; ++i)
2778 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2785 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize,
2786 GetDeleterOf(*fSubFields[0]));
2788 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment());
2794 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
2795 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
2797 if (fSubFields[0]->IsSimple()) {
2798 GetPrincipalColumnOf(*fSubFields[0])->ReadV(globalIndex*fArrayLength, fArrayLength, rvecBeginPtr);
2803 for (std::size_t i = 0; i < fArrayLength; ++i) {
2804 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, rvecBeginPtr + (i * fItemSize));
2810 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
2811 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
2814 const auto &clusterIndexIndex = clusterIndex.
GetIndex();
2816 if (fSubFields[0]->IsSimple()) {
2817 GetPrincipalColumnOf(*fSubFields[0])
2818 ->ReadV(
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength), fArrayLength, rvecBeginPtr);
2823 for (std::size_t i = 0; i < fArrayLength; ++i) {
2824 CallReadOn(*fSubFields[0],
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength + i),
2825 rvecBeginPtr + (i * fItemSize));
2831 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
2834std::vector<ROOT::Experimental::RFieldBase::RValue>
2837 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
2838 std::vector<ROOT::Experimental::RFieldBase::RValue>
result;
2839 for (
unsigned i = 0; i < fArrayLength; ++i) {
2841 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
2868 return representations;
2873 fColumns.emplace_back(Internal::RColumn::Create<bool>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2878 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2879 fColumns.emplace_back(Internal::RColumn::Create<bool>(
RColumnModel(onDiskTypes[0]), 0));
2884 const auto *asULongArray =
static_cast<const Word_t *
>(from);
2887 for (std::size_t word = 0; word < (fN + kBitsPerWord - 1) / kBitsPerWord; ++word) {
2888 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < fN); ++
mask, ++i) {
2889 elementValue = (asULongArray[word] & (
static_cast<Word_t>(1) <<
mask)) != 0;
2890 fColumns[0]->Append(&elementValue);
2898 auto *asULongArray =
static_cast<Word_t *
>(to);
2900 for (std::size_t i = 0; i < fN; ++i) {
2901 fColumns[0]->Read(globalIndex * fN + i, &elementValue);
2903 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
2904 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
2918 for (
size_t i = 0; i < itemFields.size(); ++i) {
2919 result += itemFields[i]->GetTypeName() +
",";
2927 const std::vector<RFieldBase *> &itemFields)
2928 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields) +
">",
2934 auto nFields = itemFields.size();
2937 for (
unsigned int i = 0; i < nFields; ++i) {
2940 fTraits &= itemFields[i]->GetTraits();
2941 Attach(std::unique_ptr<RFieldBase>(itemFields[i]));
2946std::unique_ptr<ROOT::Experimental::RFieldBase>
2949 auto nFields = fSubFields.size();
2950 std::vector<RFieldBase *> itemFields;
2951 for (
unsigned i = 0; i < nFields; ++i) {
2953 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetFieldName()).release());
2955 return std::make_unique<RVariantField>(newName, itemFields);
2960 auto index = *(
reinterpret_cast<const char *
>(variantPtr) + tagOffset);
2966 auto index =
reinterpret_cast<char *
>(variantPtr) + tagOffset;
2967 *
index =
static_cast<char>(tag - 1);
2972 auto tag = GetTag(from, fTagOffset);
2973 std::size_t nbytes = 0;
2976 nbytes += CallAppendOn(*fSubFields[tag - 1], from);
2977 index = fNWritten[tag - 1]++;
2980 fColumns[0]->Append(&varSwitch);
2988 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
2994 CallConstructValueOn(*fSubFields[tag - 1], to);
2995 CallReadOn(*fSubFields[tag - 1], variantIndex, to);
2997 SetTag(to, fTagOffset, tag);
3004 return representations;
3009 fColumns.emplace_back(Internal::RColumn::Create<RColumnSwitch>(
RColumnModel(GetColumnRepresentative()[0]), 0));
3014 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
3015 fColumns.emplace_back(Internal::RColumn::Create<RColumnSwitch>(
RColumnModel(onDiskTypes[0]), 0));
3020 memset(where, 0, GetValueSize());
3021 CallConstructValueOn(*fSubFields[0], where);
3022 SetTag(where, fTagOffset, 1);
3027 auto tag = GetTag(objPtr, fTagOffset);
3029 fItemDeleters[tag - 1]->operator()(objPtr,
true );
3031 RDeleter::operator()(objPtr, dtorOnly);
3036 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
3037 itemDeleters.reserve(fSubFields.size());
3038 for (
const auto &
f : fSubFields) {
3039 itemDeleters.emplace_back(GetDeleterOf(*
f));
3041 return std::make_unique<RVariantDeleter>(fTagOffset, itemDeleters);
3046 return fMaxItemSize + fMaxAlignment;
3051 std::fill(fNWritten.begin(), fNWritten.end(), 0);
3057 std::unique_ptr<RFieldBase> itemField)
3064 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3065 return std::make_unique<RSetField>(newName, GetTypeName(), std::move(newItemField));
3071 std::unique_ptr<RFieldBase> itemField)
3074 if (!
dynamic_cast<RPairField *
>(itemField.get()))
3080 Attach(std::move(itemField));
3085 std::size_t nbytes = 0;
3089 nbytes += CallAppendOn(*fSubFields[0], ptr);
3093 fColumns[0]->Append(&fNWritten);
3094 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
3101 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
3109 CallReadOn(*fSubFields[0], collectionStart + i, ptr);
3114 fProxy->Commit(obj);
3119 std::vector<RValue>
result;
3120 auto valueRawPtr =
value.GetPtr<
void>().get();
3123 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
3130 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3131 return std::unique_ptr<RMapField>(
new RMapField(newName, GetTypeName(), std::move(newItemField)));
3137 std::unique_ptr<RFieldBase> itemField)
3140 Attach(std::move(itemField));
3149 return representations;
3154 if (HasDefaultColumnRepresentative()) {
3155 if (fSubFields[0]->GetValueSize() < 4) {
3160 fDefaultItemValue = std::make_unique<RValue>(fSubFields[0]->CreateValue());
3163 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
3169 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
3173 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
3181 fPrincipalColumn->Append(&
mask);
3182 return 1 + CallAppendOn(*fSubFields[0], fDefaultItemValue->GetPtr<
void>().get());
3184 fPrincipalColumn->Append(&fNWritten);
3191 auto nbytesItem = CallAppendOn(*fSubFields[0], from);
3194 fPrincipalColumn->Append(&
mask);
3195 return 1 + nbytesItem;
3198 fPrincipalColumn->Append(&fNWritten);
3207 const bool isValidItem = *fPrincipalColumn->Map<
bool>(globalIndex);
3208 return isValidItem ? fPrincipalColumn->GetClusterIndex(globalIndex) : nullIndex;
3212 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
3213 return (collectionSize == 0) ? nullIndex : collectionStart;
3225 std::unique_ptr<RFieldBase> itemField)
3226 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3230std::unique_ptr<ROOT::Experimental::RFieldBase>
3233 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3234 return std::make_unique<RUniquePtrField>(newName, GetTypeName(), std::move(newItemField));
3239 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
3241 return AppendValue(typedValue->get());
3243 return AppendNull();
3249 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
3250 bool isValidValue =
static_cast<bool>(*ptr);
3252 auto itemIndex = GetItemIndex(globalIndex);
3255 void *valuePtr =
nullptr;
3257 valuePtr = ptr->get();
3259 if (isValidValue && !isValidItem) {
3261 fItemDeleter->operator()(valuePtr,
false );
3268 if (!isValidValue) {
3269 valuePtr =
malloc(fSubFields[0]->GetValueSize());
3270 CallConstructValueOn(*fSubFields[0], valuePtr);
3271 ptr->reset(
reinterpret_cast<char *
>(valuePtr));
3274 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3279 auto typedPtr =
static_cast<std::unique_ptr<char> *
>(objPtr);
3281 fItemDeleter->operator()(typedPtr->get(),
false );
3282 typedPtr->release();
3284 RDeleter::operator()(objPtr, dtorOnly);
3289 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubFields[0]));
3292std::vector<ROOT::Experimental::RFieldBase::RValue>
3295 std::vector<RValue>
result;
3296 const auto &ptr =
value.GetRef<std::unique_ptr<char>>();
3298 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr.get())));
3306ROOT::Experimental::RPairField::RPairField::GetTypeList(
const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3308 return itemFields[0]->GetTypeName() +
"," + itemFields[1]->GetTypeName();
3312 std::array<std::unique_ptr<RFieldBase>, 2> &&itemFields,
3313 const std::array<std::size_t, 2> &offsets)
3314 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
3315 "std::pair<" + GetTypeList(itemFields) +
">")
3320 std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3322 "std::pair<" + GetTypeList(itemFields) +
">")
3330 auto firstElem =
fClass->GetRealData(
"first");
3333 fOffsets[0] = firstElem->GetThisOffset();
3335 auto secondElem =
fClass->GetRealData(
"second");
3338 fOffsets[1] = secondElem->GetThisOffset();
3341std::unique_ptr<ROOT::Experimental::RFieldBase>
3344 std::array<std::unique_ptr<RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetFieldName()),
3345 fSubFields[1]->Clone(fSubFields[1]->GetFieldName())};
3347 std::unique_ptr<RPairField>
result(
new RPairField(newName, std::move(items), {fOffsets[0], fOffsets[1]}));
3359 fClass->Destructor(objPtr,
true );
3360 RDeleter::operator()(objPtr, dtorOnly);
3366ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3369 if (itemFields.empty())
3370 throw RException(
R__FAIL(
"the type list for std::tuple must have at least one element"));
3371 for (
size_t i = 0; i < itemFields.size(); ++i) {
3372 result += itemFields[i]->GetTypeName() +
",";
3379 std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
3380 const std::vector<std::size_t> &offsets)
3381 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
3382 "std::tuple<" + GetTypeList(itemFields) +
">")
3387 std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3389 "std::tuple<" + GetTypeList(itemFields) +
">")
3401 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
3402 std::string memberName(
"_" + std::to_string(i));
3403 auto member =
fClass->GetRealData(memberName.c_str());
3406 fOffsets.push_back(member->GetThisOffset());
3410std::unique_ptr<ROOT::Experimental::RFieldBase>
3413 std::vector<std::unique_ptr<RFieldBase>> items;
3414 items.reserve(fSubFields.size());
3415 for (
const auto &item : fSubFields)
3416 items.push_back(item->Clone(item->GetFieldName()));
3418 std::unique_ptr<RTupleField>
result(
new RTupleField(newName, std::move(items), fOffsets));
3430 fClass->Destructor(objPtr,
true );
3431 RDeleter::operator()(objPtr, dtorOnly);
3437 std::shared_ptr<RNTupleCollectionWriter> collectionWriter,
3438 std::unique_ptr<RFieldZero> collectionParent)
3441 const std::size_t
N = collectionParent->
fSubFields.size();
3442 for (std::size_t i = 0; i <
N; ++i) {
3443 Attach(std::move(collectionParent->fSubFields[i]));
3453 return representations;
3458 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
3463 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
3464 fColumns.emplace_back(Internal::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
3467std::unique_ptr<ROOT::Experimental::RFieldBase>
3470 auto parent = std::make_unique<RFieldZero>();
3471 for (
auto&
f : fSubFields) {
3472 parent->Attach(
f->Clone(
f->GetFieldName()));
3474 return std::make_unique<RCollectionField>(newName, fCollectionWriter, std::move(parent));
3481 std::size_t bytesWritten = fCollectionWriter->fBytesWritten;
3482 fCollectionWriter->fBytesWritten = 0;
3484 fColumns[0]->Append(from);
3485 return bytesWritten + fColumns[0]->GetElement()->GetPackedSize();
3490 R__ASSERT(
false &&
"should never read an RCollectionField");
3495 *fCollectionWriter->GetOffsetPtr() = 0;
3501 std::unique_ptr<RFieldBase> itemField)
3508 Attach(std::move(itemField));
3511std::unique_ptr<ROOT::Experimental::RFieldBase>
3514 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3515 return std::make_unique<RAtomicField>(newName, GetTypeName(), std::move(newItemField));
3518std::vector<ROOT::Experimental::RFieldBase::RValue>
3521 std::vector<RValue>
result;
3522 result.emplace_back(fSubFields[0]->BindValue(
value.GetPtr<
void>()));
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
#define R__LOG_WARNING(...)
TObject * clone(const char *newname) const override
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 mask
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
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 char Point_t Rectangle_t WindowAttributes_t index
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
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 Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Abstract base class for classes implementing the visitor design pattern.
virtual void VisitProxiedCollectionField(const RProxiedCollectionField &field)
virtual void VisitBoolField(const RField< bool > &field)
virtual void VisitBitsetField(const RBitsetField &field)
virtual void VisitNullableField(const RNullableField &field)
virtual void VisitFieldZero(const RFieldZero &field)
virtual void VisitRVecField(const RRVecField &field)
virtual void VisitCardinalityField(const RCardinalityField &field)
virtual void VisitEnumField(const REnumField &field)
virtual void VisitArrayAsRVecField(const RArrayAsRVecField &field)
virtual void VisitDoubleField(const RField< double > &field)
virtual void VisitField(const RFieldBase &field)=0
virtual void VisitCharField(const RField< char > &field)
virtual void VisitArrayField(const RArrayField &field)
virtual void VisitClassField(const RClassField &field)
virtual void VisitRecordField(const RRecordField &field)
virtual void VisitVectorField(const RVectorField &field)
virtual void VisitFloatField(const RField< float > &field)
virtual void VisitAtomicField(const RAtomicField &field)
static std::string GetTypeName(EColumnType type)
Abstract interface to write data into an ntuple.
const RNTupleWriteOptions & GetWriteOptions() const
Returns the sink's write options.
Abstract interface to read data from an ntuple.
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
The size of a value of this field, i.e. an RVec.
std::size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
std::size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
std::size_t fValueSize
The length of the arrays in this field.
std::unique_ptr< RDeleter > GetDeleter() const final
Returns an RRVecField::RRVecDeleter.
RArrayAsRVecField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::size_t arrayLength)
Constructor of the field.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
std::vector< RFieldBase::RValue > SplitValue(const RFieldBase::RValue &value) const final
Creates the list of direct child values given a value for this field.
std::unique_ptr< RDeleter > fItemDeleter
void operator()(void *objPtr, bool dtorOnly) final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
std::unique_ptr< RDeleter > GetDeleter() const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
RArrayField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::size_t arrayLength)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
RAtomicField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
RBitsetField(std::string_view fieldName, std::size_t N)
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
void operator()(void *objPtr, bool dtorOnly) final
The field for a class with dictionary.
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
void Attach(std::unique_ptr< RFieldBase > child, RSubFieldInfo info)
void OnConnectPageSource() final
Called by ConnectPageSource() only once connected; derived classes may override this as appropriate.
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, 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 AddReadCallbacksFromIORules(const std::span< const TSchemaRule * > rules, TClass *classp=nullptr)
Register post-read callbacks corresponding to a list of ROOT I/O customization rules.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void CommitClusterImpl() final
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Holds the static meta-data of an RNTuple column.
Holds the index and the tag of a kSwitch column.
The field for an unscoped or scoped enum with dictionary.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
REnumField(std::string_view fieldName, std::string_view enumName, TEnum *enump)
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Base class for all ROOT issued exceptions.
Similar to RValue but manages an array of consecutive values.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
void AdoptBuffer(void *buf, std::size_t capacity)
RBulk & operator=(const RBulk &)=delete
void Reset(RClusterIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
void * fValues
Cached deleter of fField.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
Some fields have multiple possible column representations, e.g.
std::vector< ColumnRepresentation_t > TypesList_t
TypesList_t fSerializationTypes
TypesList_t fDeserializationTypes
The union of the serialization types and the deserialization extra types.
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
void BindRawPtr(void *rawPtr)
A field translates read and write calls from/to underlying columns to/from tree values.
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type for writing.
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
void AutoAdjustColumnTypes(const RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId.
ENTupleStructure fStructure
The role of this field in the data model structure.
std::vector< RFieldBase * > GetSubFields()
static std::vector< RCheckResult > Check(const std::string &fieldName, const std::string &typeName)
Checks if the given type is supported by RNTuple.
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
std::function< void(void *)> ReadCallback_t
static constexpr int kTraitTriviallyConstructible
No constructor needs to be called, i.e.
RConstSchemaIterator cbegin() const
virtual void AcceptVisitor(Detail::RFieldVisitor &visitor) const
std::size_t fNRepetitions
For fixed sized arrays, the array length.
friend class ROOT::Experimental::RCollectionField
RFieldBase * fParent
Sub fields point to their mother field.
int fTraits
Properties of the type that allow for optimizations of collections of that type.
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
void ConnectPageSink(Internal::RPageSink &pageSink, NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
RConstSchemaIterator cend() const
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots ("grandparent.parent....
std::vector< EColumnType > ColumnRepresentation_t
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
void RemoveReadCallback(size_t idx)
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl.
void ConnectPageSource(Internal::RPageSource &pageSource)
Connects the field and its sub field tree to the given page source.
RValue CreateValue()
Generates an object of the field type and wraps the created object in a shared pointer and returns it...
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns.
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, bool fContinueOnError=false)
Factory method to resurrect a field from the stored on-disk type information.
size_t AddReadCallback(ReadCallback_t func)
Set a user-defined function to be called after reading a value, giving a chance to inspect and/or mod...
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given a value for this field.
void SetOnDiskId(DescriptorId_t id)
std::string fName
The field name relative to its parent field.
void SetColumnRepresentative(const ColumnRepresentation_t &representative)
Fixes a column representative.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
std::string fType
The C++ type captured by this field.
Internal::RColumn * fPrincipalColumn
Points into fColumns.
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
const ColumnRepresentation_t & GetColumnRepresentative() const
Returns the fColumnRepresentative pointee or, if unset, the field's default representative.
void SetDescription(std::string_view description)
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
std::uint32_t GetTypeVersion() const
The container field for an ntuple model, which itself has no physical representation.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Classes with dictionaries that can be inspected by TClass.
Used in RFieldBase::Check() to record field creation failures.
The generic field for a std::map<KeyType, ValueType> and std::unordered_map<KeyType,...
RMapField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
The on-storage meta-data of an ntuple.
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
RColumnDescriptorIterable GetColumnIterable() const
Common user-tunable settings for storing ntuples.
int GetCompression() const
bool GetHasSmallClusters() const
The field for values that may or may not be present in an entry.
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
RClusterIndex GetItemIndex(NTupleSize_t globalIndex)
Given the index of the nullable field, returns the corresponding global index of the subfield or,...
RNullableField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::size_t AppendValue(const void *from)
void operator()(void *objPtr, bool dtorOnly) final
The generic field for std::pair<T1, T2> types.
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
RPairField(std::string_view fieldName, std::array< std::unique_ptr< RFieldBase >, 2 > &&itemFields, const std::array< std::size_t, 2 > &offsets)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Allows for iterating over the elements of a proxied collection.
static RIteratorFuncs GetIteratorFuncs(TVirtualCollectionProxy *proxy, bool readFromDisk)
void operator()(void *objPtr, bool dtorOnly) final
The field for a class representing a collection of elements via TVirtualCollectionProxy.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::size_t AppendImpl(const void *from) override
Operations on values of complex types, e.g.
std::shared_ptr< TVirtualCollectionProxy > fProxy
The collection proxy is needed by the deleters and thus defined as a shared pointer.
RCollectionIterableOnce::RIteratorFuncs fIFuncsRead
Two sets of functions to operate on iterators, to be used depending on the access type.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
std::unique_ptr< RDeleter > GetDeleter() const override
RProxiedCollectionField(std::string_view fieldName, std::string_view typeName, TClass *classp)
Constructor used when the value type of the collection is not known in advance, i....
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::vector< RValue > SplitValue(const RValue &value) const override
Creates the list of direct child values given a value for this field.
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) override
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
void operator()(void *objPtr, bool dtorOnly) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
std::unique_ptr< RDeleter > fItemDeleter
std::unique_ptr< RDeleter > GetDeleter() const override
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
size_t GetAlignment() const override
As a rule of thumb, the alignment is equal to the size of the type.
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
RRVecField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
General implementation of bulk read.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::size_t AppendImpl(const void *from) override
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) override
void operator()(void *objPtr, bool dtorOnly) final
The field for an untyped record.
std::size_t fMaxAlignment
RRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets, std::string_view typeName="")
std::vector< std::size_t > fOffsets
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
std::unique_ptr< RDeleter > GetDeleter() const override
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
RSetField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void operator()(void *objPtr, bool dtorOnly) final
The generic field for std::tuple<Ts...> types.
RTupleField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void operator()(void *objPtr, bool dtorOnly) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::unique_ptr< RDeleter > GetDeleter() const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void operator()(void *objPtr, bool dtorOnly) final
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
static void SetTag(void *variantPtr, std::size_t tagOffset, std::uint32_t tag)
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void ConstructValue(void *where) const override
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
static std::string GetTypeList(const std::vector< RFieldBase * > &itemFields)
std::vector< ClusterSize_t::ValueType > fNWritten
size_t fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void CommitClusterImpl() final
std::unique_ptr< RDeleter > GetDeleter() const final
static std::uint32_t GetTag(const void *variantPtr, std::size_t tagOffset)
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
RVariantField(std::string_view fieldName, const std::vector< RFieldBase * > &itemFields)
void operator()(void *objPtr, bool dtorOnly) final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::unique_ptr< RDeleter > fItemDeleter
std::unique_ptr< RDeleter > GetDeleter() const final
RVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
TClass instances represent classes, structs and namespaces in the ROOT type system.
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Int_t Size() const
Return size of object of this class.
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Int_t GetClassSize() const
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
The TEnum class implements the enum type.
EDataType GetUnderlyingType() const
Get the underlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
@ kNeedDelete
The collection contains directly or indirectly (via other collection) some pointers that need explici...
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
Return a pointer to a function that can advance an iterator (see Next_t).
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual TVirtualCollectionProxy * Generate() const =0
Returns a clean object of the actual class that derives from TVirtualCollectionProxy.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Return a pointer to a function that can create an iterator pair, where each iterator points to the be...
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
auto MakeAliasedSharedPtr(T *rawPtr)
void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry=0)
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
void CallCommitClusterOnField(RFieldBase &)
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RClusterSize ClusterSize_t
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr ClusterSize_t kInvalidClusterIndex(std::uint64_t(-1))
constexpr DescriptorId_t kInvalidDescriptorId
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=nullptr)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.
Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information.
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
std::size_t fCount
Size of the bulk range.
RClusterIndex fFirstIndex
Start of the bulk range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
Used in the return value of the Check() method.
std::default_delete< T > deleter
TVirtualCollectionProxy::Next_t fNext
TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators
TVirtualCollectionProxy::CreateIterators_t fCreateIterators