58#include <unordered_map>
62const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
65 {
"Double_t",
"double"},
66 {
"string",
"std::string"},
68 {
"byte",
"std::byte"},
70 {
"int8_t",
"std::int8_t"},
71 {
"UChar_t",
"unsigned char"},
72 {
"uint8_t",
"std::uint8_t"},
75 {
"int16_t",
"std::int16_t"},
76 {
"UShort_t",
"unsigned short"},
77 {
"uint16_t",
"std::uint16_t"},
80 {
"int32_t",
"std::int32_t"},
81 {
"UInt_t",
"unsigned int"},
82 {
"unsigned",
"unsigned int"},
83 {
"uint32_t",
"std::uint32_t"},
88 {
"ULong_t",
"unsigned long"},
90 {
"Long64_t",
"long long"},
91 {
"int64_t",
"std::int64_t"},
92 {
"ULong64_t",
"unsigned long long"},
93 {
"uint64_t",
"std::uint64_t"}};
97std::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) {
109 case '<': ++nestingLevel;
break;
110 case '>': --nestingLevel;
break;
112 if (nestingLevel == 0) {
113 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
114 typeBegin = typeCursor + 1;
120 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
129std::tuple<std::string, std::vector<size_t>> ParseArrayType(std::string_view typeName)
131 std::vector<size_t> sizeVec;
134 while (typeName.back() ==
']') {
135 auto posRBrace = typeName.size() - 1;
136 auto posLBrace = typeName.find_last_of(
'[', posRBrace);
137 if (posLBrace == std::string_view::npos)
141 if (std::from_chars(typeName.data() + posLBrace + 1, typeName.data() + posRBrace,
size).ec != std::errc{})
143 sizeVec.insert(sizeVec.begin(),
size);
144 typeName.remove_suffix(typeName.size() - posLBrace);
146 return std::make_tuple(std::string{typeName}, sizeVec);
151std::string GetCanonicalTypeName(
const std::string &typeName)
154 if (typeName ==
"ROOT::Experimental::ClusterSize_t" || typeName.substr(0, 5) ==
"std::" ||
155 typeName.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<")
165std::string GetNormalizedTypeName(
const std::string &typeName)
169 if (
auto it = typeTranslationMap.find(normalizedType); it != typeTranslationMap.end())
170 normalizedType = it->second;
172 if (normalizedType.substr(0, 7) ==
"vector<")
173 normalizedType =
"std::" + normalizedType;
174 if (normalizedType.substr(0, 6) ==
"array<")
175 normalizedType =
"std::" + normalizedType;
176 if (normalizedType.substr(0, 8) ==
"variant<")
177 normalizedType =
"std::" + normalizedType;
178 if (normalizedType.substr(0, 5) ==
"pair<")
179 normalizedType =
"std::" + normalizedType;
180 if (normalizedType.substr(0, 6) ==
"tuple<")
181 normalizedType =
"std::" + normalizedType;
182 if (normalizedType.substr(0, 7) ==
"bitset<")
183 normalizedType =
"std::" + normalizedType;
184 if (normalizedType.substr(0, 11) ==
"unique_ptr<")
185 normalizedType =
"std::" + normalizedType;
186 if (normalizedType.substr(0, 4) ==
"set<")
187 normalizedType =
"std::" + normalizedType;
188 if (normalizedType.substr(0, 14) ==
"unordered_set<")
189 normalizedType =
"std::" + normalizedType;
190 if (normalizedType.substr(0, 9) ==
"multiset<")
191 normalizedType =
"std::" + normalizedType;
192 if (normalizedType.substr(0, 19) ==
"unordered_multiset<")
193 normalizedType =
"std::" + normalizedType;
194 if (normalizedType.substr(0, 4) ==
"map<")
195 normalizedType =
"std::" + normalizedType;
196 if (normalizedType.substr(0, 14) ==
"unordered_map<")
197 normalizedType =
"std::" + normalizedType;
198 if (normalizedType.substr(0, 9) ==
"multimap<")
199 normalizedType =
"std::" + normalizedType;
200 if (normalizedType.substr(0, 19) ==
"unordered_multimap<")
201 normalizedType =
"std::" + normalizedType;
202 if (normalizedType.substr(0, 7) ==
"atomic<")
203 normalizedType =
"std::" + normalizedType;
205 if (normalizedType.substr(0, 11) ==
"ROOT::RVec<")
206 normalizedType =
"ROOT::VecOps::RVec<" + normalizedType.substr(11);
208 return normalizedType;
212class CreateContextGuard;
214 friend class CreateContextGuard;
216 std::vector<std::string> fClassesOnStack;
219 bool fContinueOnError =
false;
222 CreateContext() =
default;
223 bool GetContinueOnError()
const {
return fContinueOnError; }
227class CreateContextGuard {
228 CreateContext &fCreateContext;
229 std::size_t fNOriginalClassesOnStack;
230 bool fOriginalContinueOnError;
233 CreateContextGuard(CreateContext &ctx)
234 : fCreateContext(ctx),
235 fNOriginalClassesOnStack(ctx.fClassesOnStack.
size()),
236 fOriginalContinueOnError(ctx.fContinueOnError)
239 ~CreateContextGuard()
241 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
242 fCreateContext.fContinueOnError = fOriginalContinueOnError;
245 void AddClassToStack(
const std::string &cl)
247 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
248 fCreateContext.fClassesOnStack.end()) {
251 fCreateContext.fClassesOnStack.emplace_back(cl);
254 void SetContinueOnError(
bool value) { fCreateContext.fContinueOnError =
value; }
259std::tuple<void **, std::int32_t *, std::int32_t *> GetRVecDataMembers(
void *rvecPtr)
261 void **begin =
reinterpret_cast<void **
>(rvecPtr);
263 std::int32_t *
size =
reinterpret_cast<std::int32_t *
>(begin + 1);
266 std::int32_t *capacity =
size + 1;
268 return {begin,
size, capacity};
271std::tuple<const void *const *, const std::int32_t *, const std::int32_t *> GetRVecDataMembers(
const void *rvecPtr)
273 return {GetRVecDataMembers(
const_cast<void *
>(rvecPtr))};
281 auto iFrom = from.
cbegin();
282 auto iTo = to.
begin();
283 for (; iFrom != from.
cend(); ++iFrom, ++iTo) {
284 iTo->SetOnDiskId(iFrom->GetOnDiskId());
288std::size_t EvalRVecValueSize(std::size_t alignOfT, std::size_t sizeOfT, std::size_t alignOfRVecT)
302 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
305 const auto inlineStorageSz = [&] {
306#ifdef R__HAS_HARDWARE_INTERFERENCE_SIZE
308 constexpr unsigned cacheLineSize = std::hardware_destructive_interference_size;
310 constexpr unsigned cacheLineSize = 64u;
312 const unsigned elementsPerCacheLine = (cacheLineSize - dataMemberSz) / sizeOfT;
313 constexpr unsigned maxInlineByteSize = 1024;
314 const unsigned nElements =
315 elementsPerCacheLine >= 8 ? elementsPerCacheLine : (sizeOfT * 8 > maxInlineByteSize ? 0 : 8);
316 return nElements * sizeOfT;
321 auto paddingMiddle = dataMemberSz % alignOfT;
322 if (paddingMiddle != 0)
323 paddingMiddle = alignOfT - paddingMiddle;
326 auto paddingEnd = (dataMemberSz + paddingMiddle + inlineStorageSz) % alignOfRVecT;
328 paddingEnd = alignOfRVecT - paddingEnd;
330 return dataMemberSz + inlineStorageSz + paddingMiddle + paddingEnd;
333std::size_t EvalRVecAlignment(std::size_t alignOfSubField)
337 return std::max({
alignof(
void *),
alignof(std::int32_t), alignOfSubField});
340void DestroyRVecWithChecks(std::size_t alignOfT,
void **beginPtr,
char *begin, std::int32_t *capacityPtr)
344 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
345 auto paddingMiddle = dataMemberSz % alignOfT;
346 if (paddingMiddle != 0)
347 paddingMiddle = alignOfT - paddingMiddle;
348 const bool isSmall = (
reinterpret_cast<void *
>(begin) == (beginPtr + dataMemberSz + paddingMiddle));
350 const bool owns = (*capacityPtr != -1);
351 if (!isSmall && owns)
356enum class ERNTupleUnsplitSetting { kForceSplit, kForceUnsplit,
kUnset };
358ERNTupleUnsplitSetting GetRNTupleUnsplitSetting(
TClass *cl)
361 if (!am || !am->HasKey(
"rntuple.split"))
362 return ERNTupleUnsplitSetting::kUnset;
364 std::string
value = am->GetPropertyAsString(
"rntuple.split");
366 if (
value ==
"TRUE") {
367 return ERNTupleUnsplitSetting::kForceSplit;
368 }
else if (
value ==
"FALSE") {
369 return ERNTupleUnsplitSetting::kForceUnsplit;
372 <<
"invalid setting for 'rntuple.split' class attribute: " << am->GetPropertyAsString(
"rntuple.split");
373 return ERNTupleUnsplitSetting::kUnset;
378constexpr std::size_t GetVariantTagSize()
381 std::variant<char> t;
382 constexpr auto sizeOfT =
sizeof(t);
384 static_assert(sizeOfT == 2 || sizeOfT == 8,
"unsupported std::variant layout");
385 return sizeOfT == 2 ? 1 : 4;
388template <std::
size_t VariantSizeT>
390 using ValueType_t =
typename std::conditional_t<VariantSizeT == 1, std::uint8_t,
391 typename std::conditional_t<VariantSizeT == 4, std::uint32_t, void>>;
400 RCallbackStreamerInfo fCallbackStreamerInfo;
404 :
TBufferFile(
mode, bufsiz), fCallbackStreamerInfo(callbackStreamerInfo)
441 : fSerializationTypes(serializationTypes), fDeserializationTypes(serializationTypes)
444 deserializationExtraTypes.end());
459 : fField(other.fField),
461 fCapacity(other.fCapacity),
463 fIsAdopted(other.fIsAdopted),
464 fNValidValues(other.fNValidValues),
465 fFirstIndex(other.fFirstIndex)
467 std::swap(
fDeleter, other.fDeleter);
468 std::swap(
fValues, other.fValues);
474 std::swap(fField, other.fField);
475 std::swap(fDeleter, other.fDeleter);
476 std::swap(fValues, other.fValues);
478 std::swap(fCapacity, other.fCapacity);
479 std::swap(
fSize, other.fSize);
480 std::swap(fIsAdopted, other.fIsAdopted);
481 std::swap(fMaskAvail, other.fMaskAvail);
482 std::swap(fNValidValues, other.fNValidValues);
483 std::swap(fFirstIndex, other.fFirstIndex);
503 for (std::size_t i = 0; i < fCapacity; ++i) {
504 fDeleter->operator()(GetValuePtrAt(i),
true );
511 if (fCapacity <
size) {
513 throw RException(
R__FAIL(
"invalid attempt to bulk read beyond the adopted buffer"));
519 for (std::size_t i = 0; i <
size; ++i) {
520 fField->ConstructValue(GetValuePtrAt(i));
524 fMaskAvail = std::make_unique<bool[]>(
size);
528 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
531 fFirstIndex = firstIndex;
538 for (std::size_t i = 0; i <
fSize; ++i)
539 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
546 fCapacity = capacity;
549 fMaskAvail = std::make_unique<bool[]>(capacity);
564std::unique_ptr<void, typename ROOT::Experimental::RFieldBase::RCreateObjectDeleter<void>::deleter>
565ROOT::Experimental::RFieldBase::CreateObject<void>()
const
568 return std::unique_ptr<void, RCreateObjectDeleter<void>::deleter>(
CreateObjectRawPtr(), gDeleter);
574 bool isSimple, std::size_t nRepetitions)
588 std::string
result = GetFieldName();
589 auto parent = GetParent();
590 while (parent && !parent->GetFieldName().empty()) {
592 parent = parent->GetParent();
600 auto typeAlias = GetNormalizedTypeName(typeName);
601 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
605std::vector<ROOT::Experimental::RFieldBase::RCheckResult>
608 auto typeAlias = GetNormalizedTypeName(typeName);
609 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
614 std::vector<RCheckResult>
result;
615 for (
const auto &
f : fieldZero) {
621 RCheckResult{invalidField->GetQualifiedFieldName(), invalidField->GetTypeName(), invalidField->GetError()});
628 const std::string &typeAlias,
bool continueOnError)
630 thread_local CreateContext createContext;
631 CreateContextGuard createContextGuard(createContext);
633 createContextGuard.SetContinueOnError(
true);
635 auto fnFail = [&fieldName, &canonicalType](
const std::string &errMsg) ->
RResult<std::unique_ptr<RFieldBase>> {
636 if (createContext.GetContinueOnError()) {
637 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, errMsg));
643 if (canonicalType.empty())
644 return R__FORWARD_RESULT(fnFail(
"no type name specified for field '" + fieldName +
"'"));
646 if (
auto [arrayBaseType, arraySizes] = ParseArrayType(canonicalType); !arraySizes.empty()) {
647 std::unique_ptr<RFieldBase> arrayField = Create(
"_0", arrayBaseType).Unwrap();
648 for (
int i = arraySizes.size() - 1; i >= 0; --i) {
649 arrayField = std::make_unique<RArrayField>((i == 0) ? fieldName :
"_0", std::move(arrayField), arraySizes[i]);
654 std::unique_ptr<ROOT::Experimental::RFieldBase>
result;
656 if (canonicalType ==
"ROOT::Experimental::ClusterSize_t") {
657 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
658 }
else if (canonicalType ==
"bool") {
659 result = std::make_unique<RField<bool>>(fieldName);
660 }
else if (canonicalType ==
"char") {
661 result = std::make_unique<RField<char>>(fieldName);
662 }
else if (canonicalType ==
"signed char") {
663 result = std::make_unique<RField<signed char>>(fieldName);
664 }
else if (canonicalType ==
"unsigned char") {
665 result = std::make_unique<RField<unsigned char>>(fieldName);
666 }
else if (canonicalType ==
"short") {
667 result = std::make_unique<RField<short>>(fieldName);
668 }
else if (canonicalType ==
"unsigned short") {
669 result = std::make_unique<RField<unsigned short>>(fieldName);
670 }
else if (canonicalType ==
"int") {
671 result = std::make_unique<RField<int>>(fieldName);
672 }
else if (canonicalType ==
"unsigned int") {
673 result = std::make_unique<RField<unsigned int>>(fieldName);
674 }
else if (canonicalType ==
"long") {
675 result = std::make_unique<RField<long>>(fieldName);
676 }
else if (canonicalType ==
"unsigned long") {
677 result = std::make_unique<RField<unsigned long>>(fieldName);
678 }
else if (canonicalType ==
"long long") {
679 result = std::make_unique<RField<long long>>(fieldName);
680 }
else if (canonicalType ==
"unsigned long long") {
681 result = std::make_unique<RField<unsigned long long>>(fieldName);
682 }
else if (canonicalType ==
"std::byte") {
683 result = std::make_unique<RField<std::byte>>(fieldName);
684 }
else if (canonicalType ==
"std::int8_t") {
685 result = std::make_unique<RField<std::int8_t>>(fieldName);
686 }
else if (canonicalType ==
"std::uint8_t") {
687 result = std::make_unique<RField<std::uint8_t>>(fieldName);
688 }
else if (canonicalType ==
"std::int16_t") {
689 result = std::make_unique<RField<std::int16_t>>(fieldName);
690 }
else if (canonicalType ==
"std::uint16_t") {
691 result = std::make_unique<RField<std::uint16_t>>(fieldName);
692 }
else if (canonicalType ==
"std::int32_t") {
693 result = std::make_unique<RField<std::int32_t>>(fieldName);
694 }
else if (canonicalType ==
"std::uint32_t") {
695 result = std::make_unique<RField<std::uint32_t>>(fieldName);
696 }
else if (canonicalType ==
"std::int64_t") {
697 result = std::make_unique<RField<std::int64_t>>(fieldName);
698 }
else if (canonicalType ==
"std::uint64_t") {
699 result = std::make_unique<RField<std::uint64_t>>(fieldName);
700 }
else if (canonicalType ==
"float") {
701 result = std::make_unique<RField<float>>(fieldName);
702 }
else if (canonicalType ==
"double") {
703 result = std::make_unique<RField<double>>(fieldName);
704 }
else if (canonicalType ==
"Double32_t") {
705 result = std::make_unique<RField<double>>(fieldName);
709 }
else if (canonicalType ==
"std::string") {
710 result = std::make_unique<RField<std::string>>(fieldName);
711 }
else if (canonicalType ==
"TObject") {
712 result = std::make_unique<RField<TObject>>(fieldName);
713 }
else if (canonicalType ==
"std::vector<bool>") {
714 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
715 }
else if (canonicalType.substr(0, 12) ==
"std::vector<") {
716 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
717 auto itemField = Create(
"_0", itemTypeName);
718 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
719 }
else if (canonicalType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
720 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
721 auto itemField = Create(
"_0", itemTypeName);
722 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
723 }
else if (canonicalType.substr(0, 11) ==
"std::array<") {
724 auto arrayDef = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
725 if (arrayDef.size() != 2) {
726 return R__FORWARD_RESULT(fnFail(
"the template list for std::array must have exactly two elements"));
728 auto arrayLength = std::stoi(arrayDef[1]);
729 auto itemField = Create(
"_0", arrayDef[0]);
730 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
731 }
else if (canonicalType.substr(0, 13) ==
"std::variant<") {
732 auto innerTypes = TokenizeTypeList(canonicalType.substr(13, canonicalType.length() - 14));
733 std::vector<RFieldBase *> items;
734 items.reserve(innerTypes.size());
735 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
736 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap().release());
738 result = std::make_unique<RVariantField>(fieldName, items);
739 }
else if (canonicalType.substr(0, 10) ==
"std::pair<") {
740 auto innerTypes = TokenizeTypeList(canonicalType.substr(10, canonicalType.length() - 11));
741 if (innerTypes.size() != 2) {
742 return R__FORWARD_RESULT(fnFail(
"the type list for std::pair must have exactly two elements"));
744 std::array<std::unique_ptr<RFieldBase>, 2> items{Create(
"_0", innerTypes[0]).Unwrap(),
745 Create(
"_1", innerTypes[1]).Unwrap()};
746 result = std::make_unique<RPairField>(fieldName, items);
747 }
else if (canonicalType.substr(0, 11) ==
"std::tuple<") {
748 auto innerTypes = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
749 std::vector<std::unique_ptr<RFieldBase>> items;
750 items.reserve(innerTypes.size());
751 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
752 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
754 result = std::make_unique<RTupleField>(fieldName, items);
755 }
else if (canonicalType.substr(0, 12) ==
"std::bitset<") {
756 auto size = std::stoull(canonicalType.substr(12, canonicalType.length() - 13));
757 result = std::make_unique<RBitsetField>(fieldName,
size);
758 }
else if (canonicalType.substr(0, 16) ==
"std::unique_ptr<") {
759 std::string itemTypeName = canonicalType.substr(16, canonicalType.length() - 17);
760 auto itemField = Create(
"_0", itemTypeName).Unwrap();
761 auto normalizedInnerTypeName = itemField->GetTypeName();
762 result = std::make_unique<RUniquePtrField>(fieldName,
"std::unique_ptr<" + normalizedInnerTypeName +
">",
763 std::move(itemField));
764 }
else if (canonicalType.substr(0, 14) ==
"std::optional<") {
765 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
766 auto itemField = Create(
"_0", itemTypeName).Unwrap();
767 auto normalizedInnerTypeName = itemField->GetTypeName();
768 result = std::make_unique<ROptionalField>(fieldName,
"std::optional<" + normalizedInnerTypeName +
">",
769 std::move(itemField));
770 }
else if (canonicalType.substr(0, 9) ==
"std::set<") {
771 std::string itemTypeName = canonicalType.substr(9, canonicalType.length() - 10);
772 auto itemField = Create(
"_0", itemTypeName).Unwrap();
773 auto normalizedInnerTypeName = itemField->GetTypeName();
775 std::make_unique<RSetField>(fieldName,
"std::set<" + normalizedInnerTypeName +
">", std::move(itemField));
776 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_set<") {
777 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
778 auto itemField = Create(
"_0", itemTypeName).Unwrap();
779 auto normalizedInnerTypeName = itemField->GetTypeName();
780 result = std::make_unique<RSetField>(fieldName,
"std::unordered_set<" + normalizedInnerTypeName +
">",
781 std::move(itemField));
782 }
else if (canonicalType.substr(0, 14) ==
"std::multiset<") {
783 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
784 auto itemField = Create(
"_0", itemTypeName).Unwrap();
785 auto normalizedInnerTypeName = itemField->GetTypeName();
787 std::make_unique<RSetField>(fieldName,
"std::multiset<" + normalizedInnerTypeName +
">", std::move(itemField));
788 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multiset<") {
789 std::string itemTypeName = canonicalType.substr(24, canonicalType.length() - 25);
790 auto itemField = Create(
"_0", itemTypeName).Unwrap();
791 auto normalizedInnerTypeName = itemField->GetTypeName();
792 result = std::make_unique<RSetField>(fieldName,
"std::unordered_multiset<" + normalizedInnerTypeName +
">",
793 std::move(itemField));
794 }
else if (canonicalType.substr(0, 9) ==
"std::map<") {
795 auto innerTypes = TokenizeTypeList(canonicalType.substr(9, canonicalType.length() - 10));
796 if (innerTypes.size() != 2) {
797 return R__FORWARD_RESULT(fnFail(
"the type list for std::map must have exactly two elements"));
800 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
804 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
805 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
807 result = std::make_unique<RMapField>(fieldName,
"std::map<" + keyTypeName +
"," + valueTypeName +
">",
808 std::move(itemField));
809 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_map<") {
810 auto innerTypes = TokenizeTypeList(canonicalType.substr(19, canonicalType.length() - 20));
811 if (innerTypes.size() != 2)
812 return R__FORWARD_RESULT(fnFail(
"the type list for std::unordered_map must have exactly two elements"));
814 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
818 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
819 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
821 result = std::make_unique<RMapField>(fieldName,
"std::unordered_map<" + keyTypeName +
"," + valueTypeName +
">",
822 std::move(itemField));
823 }
else if (canonicalType.substr(0, 14) ==
"std::multimap<") {
824 auto innerTypes = TokenizeTypeList(canonicalType.substr(14, canonicalType.length() - 15));
825 if (innerTypes.size() != 2)
826 return R__FORWARD_RESULT(fnFail(
"the type list for std::multimap must have exactly two elements"));
828 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
832 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
833 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
835 result = std::make_unique<RMapField>(fieldName,
"std::multimap<" + keyTypeName +
"," + valueTypeName +
">",
836 std::move(itemField));
837 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multimap<") {
838 auto innerTypes = TokenizeTypeList(canonicalType.substr(24, canonicalType.length() - 25));
839 if (innerTypes.size() != 2)
840 return R__FORWARD_RESULT(fnFail(
"the type list for std::unordered_multimap must have exactly two elements"));
842 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
846 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
847 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
849 result = std::make_unique<RMapField>(
850 fieldName,
"std::unordered_multimap<" + keyTypeName +
"," + valueTypeName +
">", std::move(itemField));
851 }
else if (canonicalType.substr(0, 12) ==
"std::atomic<") {
852 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
853 auto itemField = Create(
"_0", itemTypeName).Unwrap();
854 auto normalizedInnerTypeName = itemField->GetTypeName();
855 result = std::make_unique<RAtomicField>(fieldName,
"std::atomic<" + normalizedInnerTypeName +
">",
856 std::move(itemField));
857 }
else if (canonicalType.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<") {
858 auto innerTypes = TokenizeTypeList(canonicalType.substr(39, canonicalType.length() - 40));
859 if (innerTypes.size() != 1)
860 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
861 if (innerTypes[0] ==
"std::uint32_t") {
862 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
863 }
else if (innerTypes[0] ==
"std::uint64_t") {
864 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
866 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
874 result = std::make_unique<REnumField>(fieldName, canonicalType);
881 createContextGuard.AddClassToStack(canonicalType);
883 result = std::make_unique<RProxiedCollectionField>(fieldName, canonicalType);
885 if (GetRNTupleUnsplitSetting(cl) == ERNTupleUnsplitSetting::kForceUnsplit) {
886 result = std::make_unique<RUnsplitField>(fieldName, canonicalType);
888 result = std::make_unique<RClassField>(fieldName, canonicalType);
894 auto error =
e.GetError();
895 if (createContext.GetContinueOnError()) {
896 std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, error.GetReport()));
903 if (typeAlias != canonicalType)
904 result->fTypeAlias = typeAlias;
912 if (fieldName.empty()) {
913 return R__FAIL(
"name cannot be empty string \"\"");
914 }
else if (fieldName.find(
'.') != std::string::npos) {
915 return R__FAIL(
"name '" + std::string(fieldName) +
"' cannot contain dot characters '.'");
924 return representations;
929 auto clone = CloneImpl(newName);
930 clone->fTypeAlias = fTypeAlias;
931 clone->fOnDiskId = fOnDiskId;
932 clone->fDescription = fDescription;
934 clone->fColumnRepresentatives = fColumnRepresentatives;
940 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
951 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(clusterIndex), to);
956 const auto valueSize = GetValueSize();
957 std::size_t nRead = 0;
958 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
967 Read(bulkSpec.
fFirstIndex + i,
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + i * valueSize);
976 void *where =
operator new(GetValueSize());
978 ConstructValue(where);
984 void *obj = CreateObjectRawPtr();
988std::vector<ROOT::Experimental::RFieldBase::RValue>
991 return std::vector<RValue>();
998 if (fState != EState::kUnconnected)
999 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
1000 child->fParent =
this;
1001 fSubFields.emplace_back(std::move(
child));
1007 std::size_t
result = globalIndex;
1008 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
1009 auto parent =
f->GetParent();
1010 if (parent && (parent->GetStructure() ==
kCollection || parent->GetStructure() ==
kVariant))
1012 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
1019 std::vector<RFieldBase *>
result;
1020 result.reserve(fSubFields.size());
1021 for (
const auto &
f : fSubFields) {
1029 std::vector<const RFieldBase *>
result;
1030 result.reserve(fSubFields.size());
1031 for (
const auto &
f : fSubFields) {
1039 if (!fAvailableColumns.empty()) {
1040 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1041 for (
auto &column : fAvailableColumns) {
1042 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1051 if (!fAvailableColumns.empty()) {
1052 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1053 for (
auto &column : fAvailableColumns) {
1054 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1057 column->CommitSuppressed();
1061 CommitClusterImpl();
1066 if (fState != EState::kUnconnected)
1067 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
1068 fDescription = std::string(description);
1073 if (fState != EState::kUnconnected)
1082 if (~fTraits & kTraitMappable)
1083 return AppendImpl(from);
1085 fPrincipalColumn->Append(from);
1086 return fPrincipalColumn->GetElement()->GetPackedSize();
1096 return RValue(
this, objPtr);
1105 return RBulkSpec::kAllSet;
1108 return ReadBulkImpl(bulkSpec);
1134 if (fColumnRepresentatives.empty()) {
1135 return {GetColumnRepresentations().GetSerializationDefault()};
1139 result.reserve(fColumnRepresentatives.size());
1140 for (
const auto &
r : fColumnRepresentatives) {
1149 if (fState != EState::kUnconnected)
1150 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
1151 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
1152 fColumnRepresentatives.clear();
1153 fColumnRepresentatives.reserve(representatives.size());
1154 for (
const auto &
r : representatives) {
1155 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(),
r);
1156 if (itRepresentative == std::end(validTypes))
1158 fColumnRepresentatives.emplace_back(*itRepresentative);
1164 std::uint16_t representationIndex)
const
1169 throw RException(
R__FAIL(
"No on-disk field information for `" + GetQualifiedFieldName() +
"`"));
1173 if (
c.GetRepresentationIndex() == representationIndex)
1174 onDiskTypes.emplace_back(
c.GetType());
1176 if (onDiskTypes.empty()) {
1177 if (representationIndex == 0) {
1178 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
1183 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1184 if (t == onDiskTypes)
1188 std::string columnTypeNames;
1189 for (
const auto &t : onDiskTypes) {
1190 if (!columnTypeNames.empty())
1191 columnTypeNames +=
", ";
1194 throw RException(
R__FAIL(
"On-disk column types {" + columnTypeNames +
"} for field `" + GetQualifiedFieldName() +
1195 "` cannot be matched to its in-memory type `" + GetTypeName() +
"` " +
1196 "(representation index: " + std::to_string(representationIndex) +
")"));
1201 fReadCallbacks.push_back(func);
1203 return fReadCallbacks.size() - 1;
1208 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
1209 fIsSimple = (fTraits & kTraitMappable) && fReadCallbacks.empty();
1214 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
1216 for (
auto &colType : rep) {
1228 SetColumnRepresentatives({rep});
1231 if (fTypeAlias ==
"Double32_t")
1238 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page sink"));
1239 if (fState != EState::kUnconnected)
1240 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
1245 for (
auto &column : fAvailableColumns) {
1249 auto firstElementIndex = (column->GetIndex() == 0) ? EntryToColumnElementIndex(firstEntry) : 0;
1250 column->ConnectPageSink(fOnDiskId, pageSink, firstElementIndex);
1253 if (HasExtraTypeInfo()) {
1258 fState = EState::kConnectedToSink;
1264 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
1265 if (fState != EState::kUnconnected)
1266 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
1268 if (!fColumnRepresentatives.empty())
1269 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
1270 if (!fDescription.empty())
1271 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
1273 for (
auto &
f : fSubFields) {
1277 f->ConnectPageSource(pageSource);
1283 GenerateColumns(desc);
1284 if (fColumnRepresentatives.empty()) {
1286 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1288 fColumnRepresentatives = {t};
1293 R__ASSERT(!fColumnRepresentatives.empty());
1297 if (fieldDesc.GetTypeChecksum().has_value())
1298 fOnDiskTypeChecksum = *fieldDesc.GetTypeChecksum();
1301 for (
auto &column : fAvailableColumns)
1302 column->ConnectPageSource(fOnDiskId, pageSource);
1303 OnConnectPageSource();
1305 fState = EState::kConnectedToSource;
1315std::unique_ptr<ROOT::Experimental::RFieldBase>
1318 auto result = std::make_unique<RFieldZero>();
1319 for (
auto &
f : fSubFields)
1320 result->Attach(
f->Clone(
f->GetFieldName()));
1334 static RColumnRepresentations representations(
1337 return representations;
1342 visitor.VisitClusterSizeField(*
this);
1353 return representations;
1358 GenerateColumnsImpl<ClusterSize_t>(desc);
1386 return representations;
1402 return representations;
1407 visitor.VisitByteField(*
this);
1418 return representations;
1423 visitor.VisitInt8Field(*
this);
1434 return representations;
1439 visitor.VisitUInt8Field(*
this);
1464 return representations;
1485 return representations;
1490 const auto r = GetColumnRepresentatives();
1491 const auto n =
r.size();
1492 fAvailableColumns.reserve(
n);
1493 for (std::uint16_t i = 0; i <
n; ++i) {
1494 auto &column = fAvailableColumns.emplace_back(Internal::RColumn::Create<float>(
r[i][0], 0, i));
1496 column->SetBitsOnStorage(fBitWidth);
1498 column->SetBitsOnStorage(fBitWidth);
1499 column->SetValueRange(fValueMin, fValueMax);
1502 fPrincipalColumn = fAvailableColumns[0].get();
1507 std::uint16_t representationIndex = 0;
1509 const auto &onDiskTypes = EnsureCompatibleColumnTypes(desc, representationIndex);
1510 if (onDiskTypes.empty())
1514 fAvailableColumns.emplace_back(Internal::RColumn::Create<float>(onDiskTypes[0], 0, representationIndex));
1518 column->SetBitsOnStorage(coldesc.GetBitsOnStorage());
1522 assert(coldesc.GetValueRange().has_value());
1523 const auto [valMin, valMax] = *coldesc.GetValueRange();
1524 column->SetBitsOnStorage(coldesc.GetBitsOnStorage());
1525 column->SetValueRange(valMin, valMax);
1527 fColumnRepresentatives.emplace_back(onDiskTypes);
1528 if (representationIndex > 0) {
1529 fAvailableColumns[0]->MergeTeams(*fAvailableColumns[representationIndex]);
1532 representationIndex++;
1534 fPrincipalColumn = fAvailableColumns[0].get();
1550 if (nBits < minBits || nBits > maxBits) {
1551 throw RException(
R__FAIL(
"SetTruncated() argument nBits = " + std::to_string(nBits) +
" is out of valid range [" +
1552 std::to_string(minBits) +
", " + std::to_string(maxBits) +
"])"));
1561 if (nBits < minBits || nBits > maxBits) {
1562 throw RException(
R__FAIL(
"SetQuantized() argument nBits = " + std::to_string(nBits) +
" is out of valid range [" +
1563 std::to_string(minBits) +
", " + std::to_string(maxBits) +
"])"));
1567 fValueMin = minValue;
1568 fValueMax = maxValue;
1584 return representations;
1594 fTypeAlias =
"Double32_t";
1606 return representations;
1611 visitor.VisitInt16Field(*
this);
1623 return representations;
1628 visitor.VisitUInt16Field(*
this);
1640 return representations;
1645 visitor.VisitInt32Field(*
this);
1657 return representations;
1662 visitor.VisitUInt32Field(*
this);
1674 return representations;
1679 visitor.VisitUInt64Field(*
this);
1696 return representations;
1701 visitor.VisitInt64Field(*
this);
1714 return representations;
1719 GenerateColumnsImpl<ClusterSize_t, char>();
1724 GenerateColumnsImpl<ClusterSize_t, char>(desc);
1729 auto typedValue =
static_cast<const std::string *
>(from);
1730 auto length = typedValue->length();
1731 fAuxiliaryColumn->AppendV(typedValue->data(),
length);
1733 fPrincipalColumn->Append(&fIndex);
1734 return length + fPrincipalColumn->GetElement()->GetPackedSize();
1739 auto typedValue =
static_cast<std::string *
>(to);
1740 RClusterIndex collectionStart;
1742 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
1744 typedValue->clear();
1746 typedValue->resize(nChars);
1747 fAuxiliaryColumn->ReadV(collectionStart, nChars,
const_cast<char *
>(typedValue->data()));
1753 visitor.VisitStringField(*
this);
1768 throw RException(
R__FAIL(
"RField: no I/O support for type " + std::string(className)));
1774 if (className ==
"TObject") {
1779 R__FAIL(std::string(className) +
" has an associated collection proxy; use RProxiedCollectionField instead"));
1784 GetRNTupleUnsplitSetting(
fClass) != ERNTupleUnsplitSetting::kForceSplit) {
1787 if (GetRNTupleUnsplitSetting(
fClass) == ERNTupleUnsplitSetting::kForceUnsplit) {
1789 R__FAIL(std::string(className) +
" has unsplit mode enforced, not supported as native RNTuple class"));
1799 if (baseClass->GetDelta() < 0) {
1800 throw RException(
R__FAIL(std::string(
"virtual inheritance is not supported: ") + std::string(className) +
1801 " virtually inherits from " + baseClass->GetName()));
1803 TClass *
c = baseClass->GetClassPointer();
1806 fTraits &= subField->GetTraits();
1815 if (!dataMember->IsPersistent()) {
1821 std::string typeName{GetNormalizedTypeName(dataMember->GetTrueTypeName())};
1822 std::string typeAlias{GetNormalizedTypeName(dataMember->GetFullTypeName())};
1825 if (dataMember->Property() &
kIsArray) {
1826 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim)
1827 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
1830 std::unique_ptr<RFieldBase> subField;
1833 fTraits &= subField->GetTraits();
1841 fMaxAlignment = std::max(fMaxAlignment,
child->GetAlignment());
1842 fSubFieldsInfo.push_back(info);
1849 for (
const auto rule : rules) {
1854 auto func = rule->GetReadFunctionPointer();
1856 fReadCallbacks.emplace_back([func, classp](
void *
target) {
1860 func(
static_cast<char *
>(
target), &oldObj);
1861 oldObj.fClass =
nullptr;
1866std::unique_ptr<ROOT::Experimental::RFieldBase>
1870 SyncFieldIDs(*
this, *
result);
1876 std::size_t nbytes = 0;
1877 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1878 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fSubFieldsInfo[i].fOffset);
1885 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1886 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1892 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1893 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1901 const auto ruleset =
fClass->GetSchemaRules();
1905 if (rule->GetTarget() ==
nullptr)
1908 const auto dataMember = klass->GetDataMember(
target->GetString());
1909 if (!dataMember || dataMember->IsPersistent()) {
1911 << dataMember->GetName();
1918 auto rules = ruleset->FindRules(
fClass->GetName(),
static_cast<Int_t>(GetOnDiskTypeVersion()),
1919 static_cast<UInt_t>(GetOnDiskTypeChecksum()));
1920 rules.erase(std::remove_if(rules.begin(), rules.end(), referencesNonTransientMembers), rules.end());
1921 AddReadCallbacksFromIORules(rules,
fClass);
1931 fClass->Destructor(objPtr,
true );
1932 RDeleter::operator()(objPtr, dtorOnly);
1935std::vector<ROOT::Experimental::RFieldBase::RValue>
1938 std::vector<RValue>
result;
1939 auto basePtr =
value.GetPtr<
unsigned char>().get();
1940 result.reserve(fSubFields.size());
1941 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1943 fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fSubFieldsInfo[i].fOffset)));
1950 return fClass->GetClassSize();
1955 return fClass->GetClassVersion();
1960 return fClass->GetCheckSum();
1973 return dataMember->GetOffset();
1988std::unique_ptr<ROOT::Experimental::RFieldBase>
1991 auto result = std::make_unique<RField<TObject>>(newName);
1992 SyncFieldIDs(*
this, *
result);
2000 auto *obj =
static_cast<const TObject *
>(from);
2005 std::size_t nbytes = 0;
2006 nbytes += CallAppendOn(*fSubFields[0],
reinterpret_cast<const unsigned char *
>(from) + GetOffsetUniqueID());
2008 UInt_t bits = *
reinterpret_cast<const UInt_t *
>(
reinterpret_cast<const unsigned char *
>(from) + GetOffsetBits());
2010 nbytes += CallAppendOn(*fSubFields[1], &bits);
2019 auto *obj =
static_cast<TObject *
>(to);
2024 CallReadOn(*fSubFields[0], globalIndex,
static_cast<unsigned char *
>(to) + GetOffsetUniqueID());
2028 CallReadOn(*fSubFields[1], globalIndex, &bits);
2030 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetBits()) = bits;
2035 if (GetTypeVersion() != 1) {
2036 throw RException(
R__FAIL(
"unsupported on-disk version of TObject: " + std::to_string(GetTypeVersion())));
2055std::vector<ROOT::Experimental::RFieldBase::RValue>
2058 std::vector<RValue>
result;
2059 auto basePtr =
value.GetPtr<
unsigned char>().get();
2061 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetUniqueID())));
2063 fSubFields[1]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetBits())));
2085 std::string_view typeAlias)
2097 throw RException(
R__FAIL(
"RUnsplitField: no I/O support for type " + std::string(className)));
2107std::unique_ptr<ROOT::Experimental::RFieldBase>
2110 return std::unique_ptr<RUnsplitField>(
new RUnsplitField(newName, GetTypeName(), GetTypeAlias()));
2117 fClass->Streamer(
const_cast<void *
>(from), buffer);
2119 auto nbytes = buffer.Length();
2120 fAuxiliaryColumn->AppendV(buffer.Buffer(), buffer.Length());
2122 fPrincipalColumn->Append(&fIndex);
2123 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2130 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nbytes);
2133 fAuxiliaryColumn->ReadV(collectionStart, nbytes, buffer.
Buffer());
2134 fClass->Streamer(to, buffer);
2145 return representations;
2150 GenerateColumnsImpl<ClusterSize_t, std::byte>();
2155 GenerateColumnsImpl<ClusterSize_t, std::byte>(desc);
2165 fClass->Destructor(objPtr,
true );
2166 RDeleter::operator()(objPtr, dtorOnly);
2182 return std::min(
alignof(std::max_align_t), GetValueSize());
2187 return fClass->GetClassSize();
2192 return fClass->GetClassVersion();
2197 return fClass->GetCheckSum();
2208 :
REnumField(fieldName, enumName,
TEnum::GetEnum(std::string(enumName).c_str()))
2215 if (enump ==
nullptr) {
2216 throw RException(
R__FAIL(
"RField: no I/O support for enum type " + std::string(enumName)));
2234 default:
throw RException(
R__FAIL(
"Unsupported underlying integral type for enum type " + std::string(enumName)));
2241 std::unique_ptr<RFieldBase> intField)
2244 Attach(std::move(intField));
2248std::unique_ptr<ROOT::Experimental::RFieldBase>
2251 auto newIntField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2252 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
2255std::vector<ROOT::Experimental::RFieldBase::RValue>
2258 std::vector<RValue>
result;
2259 result.emplace_back(fSubFields[0]->BindValue(
value.GetPtr<
void>()));
2279 (ifuncs.
fNext !=
nullptr));
2284 std::string_view typeName,
TClass *classp)
2287 if (classp ==
nullptr)
2288 throw RException(
R__FAIL(
"RField: no I/O support for collection proxy type " + std::string(typeName)));
2290 throw RException(
R__FAIL(std::string(typeName) +
" has no associated collection proxy"));
2295 if (
fProxy->HasPointers())
2296 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
2297 if (!
fProxy->GetCollectionClass()->HasDictionary()) {
2299 GetNormalizedTypeName(
fProxy->GetCollectionClass()->GetName())));
2307 std::string_view typeName,
2308 std::unique_ptr<RFieldBase> itemField)
2312 Attach(std::move(itemField));
2316 std::string_view typeName)
2321 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
2323 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField;
2325 if (
auto valueClass =
fProxy->GetValueClass()) {
2329 switch (
fProxy->GetType()) {
2331 case EDataType::kUChar_t: itemField = std::make_unique<RField<std::uint8_t>>(
"_0");
break;
2332 case EDataType::kShort_t: itemField = std::make_unique<RField<std::int16_t>>(
"_0");
break;
2334 case EDataType::kInt_t: itemField = std::make_unique<RField<std::int32_t>>(
"_0");
break;
2335 case EDataType::kUInt_t: itemField = std::make_unique<RField<std::uint32_t>>(
"_0");
break;
2348 Attach(std::move(itemField));
2351std::unique_ptr<ROOT::Experimental::RFieldBase>
2354 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2355 return std::unique_ptr<RProxiedCollectionField>(
2361 std::size_t nbytes = 0;
2365 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2366 nbytes += CallAppendOn(*fSubFields[0], ptr);
2371 fPrincipalColumn->Append(&fNWritten);
2372 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2379 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2387 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
2388 CallReadOn(*fSubFields[0], collectionStart + (i++), elementPtr);
2391 fProxy->Commit(obj);
2400 return representations;
2405 GenerateColumnsImpl<ClusterSize_t>();
2410 GenerateColumnsImpl<ClusterSize_t>(desc);
2418std::unique_ptr<ROOT::Experimental::RFieldBase::RDeleter>
2422 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
2423 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubFields[0]), itemSize);
2425 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
2433 fItemDeleter->operator()(ptr,
true );
2436 fProxy->Destructor(objPtr,
true );
2437 RDeleter::operator()(objPtr, dtorOnly);
2440std::vector<ROOT::Experimental::RFieldBase::RValue>
2443 std::vector<RValue>
result;
2444 auto valueRawPtr =
value.GetPtr<
void>().get();
2447 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2448 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
2461 std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
2462 const std::vector<std::size_t> &offsets, std::string_view typeName)
2467 for (
auto &item : itemFields) {
2476 std::vector<std::unique_ptr<RFieldBase>> &&itemFields)
2480 fOffsets.reserve(itemFields.size());
2481 for (
auto &item : itemFields) {
2485 fSize += item->GetValueSize();
2495 std::vector<std::unique_ptr<RFieldBase>> &itemFields)
2502 if (itemAlignment > 1) {
2503 auto remainder = baseOffset % itemAlignment;
2505 return itemAlignment - remainder;
2510std::unique_ptr<ROOT::Experimental::RFieldBase>
2513 std::vector<std::unique_ptr<RFieldBase>> cloneItems;
2514 cloneItems.reserve(fSubFields.size());
2515 for (
auto &item : fSubFields)
2516 cloneItems.emplace_back(item->Clone(item->GetFieldName()));
2517 return std::unique_ptr<RRecordField>(
new RRecordField(newName, std::move(cloneItems), fOffsets, GetTypeName()));
2522 std::size_t nbytes = 0;
2523 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2524 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
2531 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2532 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2538 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2539 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2545 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2546 CallConstructValueOn(*fSubFields[i],
static_cast<unsigned char *
>(where) + fOffsets[i]);
2552 for (
unsigned i = 0; i < fItemDeleters.size(); ++i) {
2553 fItemDeleters[i]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fOffsets[i],
true );
2555 RDeleter::operator()(objPtr, dtorOnly);
2560 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2561 itemDeleters.reserve(fOffsets.size());
2562 for (
const auto &
f : fSubFields) {
2563 itemDeleters.emplace_back(GetDeleterOf(*
f));
2565 return std::make_unique<RRecordDeleter>(itemDeleters, fOffsets);
2568std::vector<ROOT::Experimental::RFieldBase::RValue>
2571 auto basePtr =
value.GetPtr<
unsigned char>().get();
2572 std::vector<RValue>
result;
2573 result.reserve(fSubFields.size());
2574 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2575 result.emplace_back(fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fOffsets[i])));
2588 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::vector<" + itemField->GetTypeName() +
">",
2590 fItemSize(itemField->GetValueSize()),
2595 Attach(std::move(itemField));
2598std::unique_ptr<ROOT::Experimental::RFieldBase>
2601 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2602 return std::make_unique<RVectorField>(newName, std::move(newItemField));
2607 auto typedValue =
static_cast<const std::vector<char> *
>(from);
2608 R__ASSERT((typedValue->size() % fItemSize) == 0);
2609 std::size_t nbytes = 0;
2610 auto count = typedValue->size() / fItemSize;
2612 if (fSubFields[0]->IsSimple() && count) {
2613 GetPrincipalColumnOf(*fSubFields[0])->AppendV(typedValue->data(), count);
2614 nbytes += count * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2616 for (
unsigned i = 0; i < count; ++i) {
2617 nbytes += CallAppendOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2622 fPrincipalColumn->Append(&fNWritten);
2623 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2628 auto typedValue =
static_cast<std::vector<char> *
>(to);
2632 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2634 if (fSubFields[0]->IsSimple()) {
2635 typedValue->resize(nItems * fItemSize);
2637 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, typedValue->data());
2642 const auto oldNItems = typedValue->size() / fItemSize;
2643 const bool canRealloc = oldNItems < nItems;
2644 bool allDeallocated =
false;
2646 allDeallocated = canRealloc;
2647 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
2648 fItemDeleter->operator()(typedValue->data() + (i * fItemSize),
true );
2651 typedValue->resize(nItems * fItemSize);
2652 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)) {
2653 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
2654 CallConstructValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2658 for (std::size_t i = 0; i < nItems; ++i) {
2659 CallReadOn(*fSubFields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
2669 return representations;
2674 GenerateColumnsImpl<ClusterSize_t>();
2679 GenerateColumnsImpl<ClusterSize_t>(desc);
2684 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
2686 R__ASSERT((vecPtr->size() % fItemSize) == 0);
2687 auto nItems = vecPtr->size() / fItemSize;
2688 for (std::size_t i = 0; i < nItems; ++i) {
2689 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize),
true );
2692 std::destroy_at(vecPtr);
2693 RDeleter::operator()(objPtr, dtorOnly);
2699 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubFields[0]));
2700 return std::make_unique<RVectorDeleter>();
2703std::vector<ROOT::Experimental::RFieldBase::RValue>
2706 auto vec =
value.GetPtr<std::vector<char>>();
2708 auto nItems =
vec->size() / fItemSize;
2709 std::vector<RValue>
result;
2711 for (
unsigned i = 0; i < nItems; ++i) {
2713 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(),
vec->data() + (i * fItemSize))));
2726 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
2728 fItemSize(itemField->GetValueSize()),
2733 Attach(std::move(itemField));
2737std::unique_ptr<ROOT::Experimental::RFieldBase>
2740 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2741 return std::make_unique<RRVecField>(newName, std::move(newItemField));
2746 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(from);
2748 std::size_t nbytes = 0;
2749 if (fSubFields[0]->IsSimple() && *sizePtr) {
2750 GetPrincipalColumnOf(*fSubFields[0])->AppendV(*beginPtr, *sizePtr);
2751 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2753 auto begin =
reinterpret_cast<const char *
>(*beginPtr);
2754 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2755 nbytes += CallAppendOn(*fSubFields[0], begin + i * fItemSize);
2759 fNWritten += *sizePtr;
2760 fPrincipalColumn->Append(&fNWritten);
2761 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2769 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(to);
2774 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2775 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2776 const std::size_t oldSize = *sizePtr;
2780 const bool owns = (*capacityPtr != -1);
2781 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
2782 const bool needsDestruct = owns && fItemDeleter;
2785 if (needsDestruct) {
2786 for (std::size_t i = nItems; i < oldSize; ++i) {
2787 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2792 if (std::int32_t(nItems) > *capacityPtr) {
2795 if (needsDestruct) {
2796 for (std::size_t i = 0u; i < oldSize; ++i) {
2797 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2808 *beginPtr =
malloc(nItems * fItemSize);
2810 begin =
reinterpret_cast<char *
>(*beginPtr);
2811 *capacityPtr = nItems;
2814 if (needsConstruct) {
2815 for (std::size_t i = 0u; i < oldSize; ++i)
2816 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2822 if (needsConstruct) {
2823 for (std::size_t i = oldSize; i < nItems; ++i)
2824 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2827 if (fSubFields[0]->IsSimple() && nItems) {
2828 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, begin);
2833 for (std::size_t i = 0; i < nItems; ++i) {
2834 CallReadOn(*fSubFields[0], collectionStart + i, begin + (i * fItemSize));
2840 if (!fSubFields[0]->IsSimple())
2846 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
2847 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fSubFields[0]->GetValueSize();
2849 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
2850 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
2851 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(bulkSpec.
fValues);
2857 this->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
2858 *beginPtr = itemValueArray;
2859 *sizePtr = collectionSize;
2865 auto lastOffset = firstItemIndex.
GetIndex() + collectionSize;
2867 std::size_t nValues = 1;
2868 std::size_t nItems = collectionSize;
2869 while (nRemainingValues > 0) {
2872 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
2873 for (std::size_t i = 0; i < nBatch; ++i) {
2874 const auto size = offsets[i] - lastOffset;
2875 std::tie(beginPtr, sizePtr, capacityPtr) =
2876 GetRVecDataMembers(
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
2877 *beginPtr = itemValueArray + nItems * itemValueSize;
2882 lastOffset = offsets[i];
2884 nRemainingValues -= nBatch;
2888 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
2890 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
2892 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
2893 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
2894 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
2899 GetPrincipalColumnOf(*fSubFields[0])->ReadV(firstItemIndex, nItems, itemValueArray - delta);
2900 return RBulkSpec::kAllSet;
2909 return representations;
2914 GenerateColumnsImpl<ClusterSize_t>();
2919 GenerateColumnsImpl<ClusterSize_t>(desc);
2926 void **beginPtr =
new (where)(
void *)(
nullptr);
2927 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2928 new (sizePtr + 1) std::int32_t(-1);
2933 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(objPtr);
2935 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2937 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2938 fItemDeleter->operator()(begin + i * fItemSize,
true );
2942 DestroyRVecWithChecks(fItemAlignment, beginPtr, begin, capacityPtr);
2943 RDeleter::operator()(objPtr, dtorOnly);
2949 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubFields[0]));
2950 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment());
2953std::vector<ROOT::Experimental::RFieldBase::RValue>
2956 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(
value.GetPtr<
void>().get());
2958 std::vector<RValue>
result;
2959 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2960 result.reserve(*sizePtr);
2961 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2962 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), begin + i * fItemSize)));
2974 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
2992 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
2993 auto count = typedValue->size();
2994 for (
unsigned i = 0; i < count; ++i) {
2995 bool bval = (*typedValue)[i];
2996 CallAppendOn(*fSubFields[0], &bval);
2999 fPrincipalColumn->Append(&fNWritten);
3000 return count + fPrincipalColumn->GetElement()->GetPackedSize();
3005 auto typedValue =
static_cast<std::vector<bool> *
>(to);
3008 RClusterIndex collectionStart;
3009 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
3011 typedValue->resize(nItems);
3012 for (
unsigned i = 0; i < nItems; ++i) {
3014 CallReadOn(*fSubFields[0], collectionStart + i, &bval);
3015 (*typedValue)[i] = bval;
3022 static RColumnRepresentations representations(
3025 return representations;
3030 GenerateColumnsImpl<ClusterSize_t>();
3035 GenerateColumnsImpl<ClusterSize_t>(desc);
3038std::vector<ROOT::Experimental::RFieldBase::RValue>
3041 const auto &typedValue =
value.GetRef<std::vector<bool>>();
3042 auto count = typedValue.size();
3043 std::vector<RValue>
result;
3045 for (
unsigned i = 0; i < count; ++i) {
3047 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
3049 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
3056 visitor.VisitVectorBoolField(*
this);
3062 std::size_t arrayLength)
3064 "std::array<" + itemField->GetTypeName() +
"," + std::to_string(arrayLength) +
">",
3066 fItemSize(itemField->GetValueSize()),
3067 fArrayLength(arrayLength)
3069 fTraits |= itemField->GetTraits() & ~kTraitMappable;
3070 Attach(std::move(itemField));
3073std::unique_ptr<ROOT::Experimental::RFieldBase>
3076 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3077 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
3082 std::size_t nbytes = 0;
3083 auto arrayPtr =
static_cast<const unsigned char *
>(from);
3084 for (
unsigned i = 0; i < fArrayLength; ++i) {
3085 nbytes += CallAppendOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3092 auto arrayPtr =
static_cast<unsigned char *
>(to);
3093 for (
unsigned i = 0; i < fArrayLength; ++i) {
3094 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
3100 auto arrayPtr =
static_cast<unsigned char *
>(to);
3101 for (
unsigned i = 0; i < fArrayLength; ++i) {
3103 arrayPtr + (i * fItemSize));
3109 if (fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)
3112 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
3113 for (
unsigned i = 0; i < fArrayLength; ++i) {
3114 CallConstructValueOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3121 for (
unsigned i = 0; i < fArrayLength; ++i) {
3122 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
3125 RDeleter::operator()(objPtr, dtorOnly);
3130 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible))
3131 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetDeleterOf(*fSubFields[0]));
3132 return std::make_unique<RDeleter>();
3135std::vector<ROOT::Experimental::RFieldBase::RValue>
3138 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3139 std::vector<RValue>
result;
3140 result.reserve(fArrayLength);
3141 for (
unsigned i = 0; i < fArrayLength; ++i) {
3143 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3157 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField,
3158 std::size_t arrayLength)
3159 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
3161 fItemSize(itemField->GetValueSize()),
3162 fArrayLength(arrayLength)
3164 Attach(std::move(itemField));
3170std::unique_ptr<ROOT::Experimental::RFieldBase>
3173 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3174 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
3180 void **beginPtr =
new (where)(
void *)(
nullptr);
3181 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
3182 std::int32_t *capacityPtr =
new (sizePtr + 1) std::int32_t(0);
3186 char *begin =
reinterpret_cast<char *
>(*beginPtr);
3189 if (*sizePtr == std::int32_t(fArrayLength))
3195 const bool owns = (*capacityPtr != -1);
3196 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
3197 const bool needsDestruct = owns && fItemDeleter;
3201 if (needsDestruct) {
3202 for (std::int32_t i = 0; i < *sizePtr; ++i) {
3203 fItemDeleter->operator()(begin + (i * fItemSize),
true );
3213 *beginPtr =
malloc(fArrayLength * fItemSize);
3216 begin =
reinterpret_cast<char *
>(*beginPtr);
3218 *sizePtr = fArrayLength;
3219 *capacityPtr = fArrayLength;
3222 if (needsConstruct) {
3223 for (std::size_t i = 0; i < fArrayLength; ++i)
3224 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
3231 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize,
3232 GetDeleterOf(*fSubFields[0]));
3234 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment());
3240 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3241 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3243 if (fSubFields[0]->IsSimple()) {
3244 GetPrincipalColumnOf(*fSubFields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, rvecBeginPtr);
3249 for (std::size_t i = 0; i < fArrayLength; ++i) {
3250 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, rvecBeginPtr + (i * fItemSize));
3256 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3257 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3260 const auto &clusterIndexIndex = clusterIndex.
GetIndex();
3262 if (fSubFields[0]->IsSimple()) {
3263 GetPrincipalColumnOf(*fSubFields[0])
3264 ->ReadV(
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength), fArrayLength, rvecBeginPtr);
3269 for (std::size_t i = 0; i < fArrayLength; ++i) {
3270 CallReadOn(*fSubFields[0],
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength + i),
3271 rvecBeginPtr + (i * fItemSize));
3277 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
3280std::vector<ROOT::Experimental::RFieldBase::RValue>
3283 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3284 std::vector<ROOT::Experimental::RFieldBase::RValue>
result;
3285 result.reserve(fArrayLength);
3286 for (
unsigned i = 0; i < fArrayLength; ++i) {
3288 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3315 return representations;
3320 GenerateColumnsImpl<bool>();
3325 GenerateColumnsImpl<bool>(desc);
3330 const auto *asULongArray =
static_cast<const Word_t *
>(from);
3333 for (std::size_t word = 0; word < (fN + kBitsPerWord - 1) / kBitsPerWord; ++word) {
3334 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < fN); ++
mask, ++i) {
3335 elementValue = (asULongArray[word] & (
static_cast<Word_t>(1) <<
mask)) != 0;
3336 fPrincipalColumn->Append(&elementValue);
3344 auto *asULongArray =
static_cast<Word_t *
>(to);
3346 for (std::size_t i = 0; i < fN; ++i) {
3347 fPrincipalColumn->Read(globalIndex * fN + i, &elementValue);
3349 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
3350 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
3364 for (
size_t i = 0; i < itemFields.size(); ++i) {
3365 result += itemFields[i]->GetTypeName() +
",";
3373 const std::vector<RFieldBase *> &itemFields)
3374 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields) +
">",
3380 auto nFields = itemFields.size();
3385 for (
unsigned int i = 0; i < nFields; ++i) {
3388 fTraits &= itemFields[i]->GetTraits();
3389 Attach(std::unique_ptr<RFieldBase>(itemFields[i]));
3400 const auto tagSize = GetVariantTagSize();
3401 const auto padding = tagSize - (
fMaxItemSize % tagSize);
3405std::unique_ptr<ROOT::Experimental::RFieldBase>
3408 auto nFields = fSubFields.size();
3409 std::vector<RFieldBase *> itemFields;
3410 itemFields.reserve(nFields);
3411 for (
unsigned i = 0; i < nFields; ++i) {
3413 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetFieldName()).release());
3415 return std::make_unique<RVariantField>(newName, itemFields);
3420 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3421 auto tag = *
reinterpret_cast<const TagType_t *
>(
reinterpret_cast<const unsigned char *
>(variantPtr) + tagOffset);
3422 return (tag == TagType_t(-1)) ? 0 : tag + 1;
3427 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3428 auto tagPtr =
reinterpret_cast<TagType_t *
>(
reinterpret_cast<unsigned char *
>(variantPtr) + tagOffset);
3429 *tagPtr = (tag == 0) ? TagType_t(-1) :
static_cast<TagType_t
>(tag - 1);
3434 auto tag = GetTag(from, fTagOffset);
3435 std::size_t nbytes = 0;
3438 nbytes += CallAppendOn(*fSubFields[tag - 1],
reinterpret_cast<const unsigned char *
>(from) + fVariantOffset);
3439 index = fNWritten[tag - 1]++;
3442 fPrincipalColumn->Append(&varSwitch);
3450 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
3457 void *varPtr =
reinterpret_cast<unsigned char *
>(to) + fVariantOffset;
3458 CallConstructValueOn(*fSubFields[tag - 1], varPtr);
3459 CallReadOn(*fSubFields[tag - 1], variantIndex, varPtr);
3461 SetTag(to, fTagOffset, tag);
3468 return representations;
3473 GenerateColumnsImpl<RColumnSwitch>();
3478 GenerateColumnsImpl<RColumnSwitch>(desc);
3483 memset(where, 0, GetValueSize());
3484 CallConstructValueOn(*fSubFields[0],
reinterpret_cast<unsigned char *
>(where) + fVariantOffset);
3485 SetTag(where, fTagOffset, 1);
3490 auto tag = GetTag(objPtr, fTagOffset);
3492 fItemDeleters[tag - 1]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fVariantOffset,
true );
3494 RDeleter::operator()(objPtr, dtorOnly);
3499 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
3500 itemDeleters.reserve(fSubFields.size());
3501 for (
const auto &
f : fSubFields) {
3502 itemDeleters.emplace_back(GetDeleterOf(*
f));
3504 return std::make_unique<RVariantDeleter>(fTagOffset, fVariantOffset, itemDeleters);
3509 return std::max(fMaxAlignment,
alignof(RVariantTag<GetVariantTagSize()>::ValueType_t));
3515 const auto actualSize = fTagOffset + GetVariantTagSize();
3517 return actualSize + ((padding ==
alignment) ? 0 : padding);
3522 std::fill(fNWritten.begin(), fNWritten.end(), 0);
3528 std::unique_ptr<RFieldBase> itemField)
3535 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3536 return std::make_unique<RSetField>(newName, GetTypeName(), std::move(newItemField));
3542 std::unique_ptr<RFieldBase> itemField)
3545 if (!
dynamic_cast<RPairField *
>(itemField.get()))
3551 Attach(std::move(itemField));
3556 std::size_t nbytes = 0;
3560 nbytes += CallAppendOn(*fSubFields[0], ptr);
3564 fPrincipalColumn->Append(&fNWritten);
3565 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
3572 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
3580 CallReadOn(*fSubFields[0], collectionStart + i, ptr);
3585 fProxy->Commit(obj);
3590 std::vector<RValue>
result;
3591 auto valueRawPtr =
value.GetPtr<
void>().get();
3594 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
3601 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3602 return std::unique_ptr<RMapField>(
new RMapField(newName, GetTypeName(), std::move(newItemField)));
3608 std::unique_ptr<RFieldBase> itemField)
3611 Attach(std::move(itemField));
3620 return representations;
3625 GenerateColumnsImpl<ClusterSize_t>();
3630 GenerateColumnsImpl<ClusterSize_t>(desc);
3635 fPrincipalColumn->Append(&fNWritten);
3641 auto nbytesItem = CallAppendOn(*fSubFields[0], from);
3643 fPrincipalColumn->Append(&fNWritten);
3651 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
3652 return (collectionSize == 0) ?
RClusterIndex() : collectionStart;
3663 std::unique_ptr<RFieldBase> itemField)
3664 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3668std::unique_ptr<ROOT::Experimental::RFieldBase>
3671 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3672 return std::make_unique<RUniquePtrField>(newName, GetTypeName(), std::move(newItemField));
3677 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
3679 return AppendValue(typedValue->get());
3681 return AppendNull();
3687 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
3688 bool isValidValue =
static_cast<bool>(*ptr);
3690 auto itemIndex = GetItemIndex(globalIndex);
3693 void *valuePtr =
nullptr;
3695 valuePtr = ptr->get();
3697 if (isValidValue && !isValidItem) {
3699 fItemDeleter->operator()(valuePtr,
false );
3706 if (!isValidValue) {
3707 valuePtr =
malloc(fSubFields[0]->GetValueSize());
3708 CallConstructValueOn(*fSubFields[0], valuePtr);
3709 ptr->reset(
reinterpret_cast<char *
>(valuePtr));
3712 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3717 auto typedPtr =
static_cast<std::unique_ptr<char> *
>(objPtr);
3719 fItemDeleter->operator()(typedPtr->get(),
false );
3720 typedPtr->release();
3722 RDeleter::operator()(objPtr, dtorOnly);
3727 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubFields[0]));
3730std::vector<ROOT::Experimental::RFieldBase::RValue>
3733 std::vector<RValue>
result;
3734 const auto &ptr =
value.GetRef<std::unique_ptr<char>>();
3736 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr.get())));
3744 std::unique_ptr<RFieldBase> itemField)
3745 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3753 void *
value = optionalPtr;
3755 reinterpret_cast<bool *
>(
reinterpret_cast<unsigned char *
>(optionalPtr) + fSubFields[0]->GetValueSize());
3756 return {
value, engagement};
3759std::pair<const void *, const bool *>
3762 return GetValueAndEngagementPtrs(
const_cast<void *
>(optionalPtr));
3765std::unique_ptr<ROOT::Experimental::RFieldBase>
3768 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3769 return std::make_unique<ROptionalField>(newName, GetTypeName(), std::move(newItemField));
3774 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(from);
3775 if (*engagementPtr) {
3776 return AppendValue(valuePtr);
3778 return AppendNull();
3784 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(to);
3785 auto itemIndex = GetItemIndex(globalIndex);
3787 *engagementPtr =
false;
3789 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3790 *engagementPtr =
true;
3796 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(where);
3797 CallConstructValueOn(*fSubFields[0], valuePtr);
3798 *engagementPtr =
false;
3803 fItemDeleter->operator()(objPtr,
true );
3804 RDeleter::operator()(objPtr, dtorOnly);
3809 return std::make_unique<ROptionalDeleter>(GetDeleterOf(*fSubFields[0]));
3812std::vector<ROOT::Experimental::RFieldBase::RValue>
3815 std::vector<RValue>
result;
3816 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(
value.GetPtr<
void>().get());
3817 if (*engagementPtr) {
3818 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), valuePtr)));
3827 const auto actualSize = fSubFields[0]->GetValueSize() +
sizeof(
bool);
3830 auto remainder = actualSize %
alignment;
3834 return actualSize + padding;
3839 return fSubFields[0]->GetAlignment();
3845ROOT::Experimental::RPairField::RPairField::GetTypeList(
const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3847 return itemFields[0]->GetTypeName() +
"," + itemFields[1]->GetTypeName();
3851 std::array<std::unique_ptr<RFieldBase>, 2> &&itemFields,
3852 const std::array<std::size_t, 2> &offsets)
3853 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
3854 "std::pair<" + GetTypeList(itemFields) +
">")
3859 std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3861 "std::pair<" + GetTypeList(itemFields) +
">")
3869 auto firstElem =
fClass->GetRealData(
"first");
3872 fOffsets[0] = firstElem->GetThisOffset();
3874 auto secondElem =
fClass->GetRealData(
"second");
3877 fOffsets[1] = secondElem->GetThisOffset();
3880std::unique_ptr<ROOT::Experimental::RFieldBase>
3883 std::array<std::unique_ptr<RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetFieldName()),
3884 fSubFields[1]->Clone(fSubFields[1]->GetFieldName())};
3886 std::unique_ptr<RPairField>
result(
new RPairField(newName, std::move(items), {fOffsets[0], fOffsets[1]}));
3898 fClass->Destructor(objPtr,
true );
3899 RDeleter::operator()(objPtr, dtorOnly);
3905ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3908 if (itemFields.empty())
3909 throw RException(
R__FAIL(
"the type list for std::tuple must have at least one element"));
3910 for (
size_t i = 0; i < itemFields.size(); ++i) {
3911 result += itemFields[i]->GetTypeName() +
",";
3918 std::vector<std::unique_ptr<RFieldBase>> &&itemFields,
3919 const std::vector<std::size_t> &offsets)
3920 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
3921 "std::tuple<" + GetTypeList(itemFields) +
">")
3926 std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3928 "std::tuple<" + GetTypeList(itemFields) +
">")
3940 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
3941 std::string memberName(
"_" + std::to_string(i));
3942 auto member =
fClass->GetRealData(memberName.c_str());
3945 fOffsets.push_back(member->GetThisOffset());
3949std::unique_ptr<ROOT::Experimental::RFieldBase>
3952 std::vector<std::unique_ptr<RFieldBase>> items;
3953 items.reserve(fSubFields.size());
3954 for (
const auto &item : fSubFields)
3955 items.push_back(item->Clone(item->GetFieldName()));
3957 std::unique_ptr<RTupleField>
result(
new RTupleField(newName, std::move(items), fOffsets));
3969 fClass->Destructor(objPtr,
true );
3970 RDeleter::operator()(objPtr, dtorOnly);
3976 std::shared_ptr<RNTupleCollectionWriter> collectionWriter,
3977 std::unique_ptr<RFieldZero> collectionParent)
3980 const std::size_t
N = collectionParent->
fSubFields.size();
3981 for (std::size_t i = 0; i <
N; ++i) {
3982 Attach(std::move(collectionParent->fSubFields[i]));
3992 return representations;
3997 GenerateColumnsImpl<ClusterSize_t>();
4002 GenerateColumnsImpl<ClusterSize_t>(desc);
4005std::unique_ptr<ROOT::Experimental::RFieldBase>
4008 auto parent = std::make_unique<RFieldZero>();
4009 for (
auto &
f : fSubFields) {
4010 parent->Attach(
f->Clone(
f->GetFieldName()));
4012 return std::make_unique<RCollectionField>(newName, fCollectionWriter, std::move(parent));
4019 std::size_t bytesWritten = fCollectionWriter->fBytesWritten;
4020 fCollectionWriter->fBytesWritten = 0;
4022 fPrincipalColumn->Append(from);
4023 return bytesWritten + fPrincipalColumn->GetElement()->GetPackedSize();
4028 R__ASSERT(
false &&
"should never read an RCollectionField");
4033 *fCollectionWriter->GetOffsetPtr() = 0;
4039 std::unique_ptr<RFieldBase> itemField)
4046 Attach(std::move(itemField));
4049std::unique_ptr<ROOT::Experimental::RFieldBase>
4052 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
4053 return std::make_unique<RAtomicField>(newName, GetTypeName(), std::move(newItemField));
4056std::vector<ROOT::Experimental::RFieldBase::RValue>
4059 std::vector<RValue>
result;
4060 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(...)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t 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 r
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 mode
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 VisitUnsplitField(const RUnsplitField &field)
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 VisitTObjectField(const RField< TObject > &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)
static std::pair< std::uint16_t, std::uint16_t > GetValidBitRange(EColumnType type)
Most types have a fixed on-disk bit width.
static std::string SerializeStreamerInfos(const StreamerInfoMap_t &infos)
Abstract interface to write data into an ntuple.
virtual void UpdateExtraTypeInfo(const RExtraTypeInfoDescriptor &extraTypeInfo)=0
Adds an extra type information record to schema.
const RNTupleWriteOptions & GetWriteOptions() const
Returns the sink's write options.
void RegisterOnCommitDatasetCallback(Callback_t callback)
The registered callback is executed at the beginning of CommitDataset();.
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
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)
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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 GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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() 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::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
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
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
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 GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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 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 > Selection_t
A list of column representations.
Selection_t fSerializationTypes
Selection_t fDeserializationTypes
The union of the serialization types and the deserialization extra types.
Iterates over the sub tree of fields in depth-first search order.
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.
RBulk CreateBulk()
The returned bulk is initially empty; RBulk::ReadBulk will construct the array of values.
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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...
void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives)
Fixes a column representative.
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.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
const std::string & GetTypeName() 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.
void FlushColumns()
Flushes data from active columns.
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.
static constexpr int kTraitTypeChecksum
The TClass checksum is set and valid.
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
RConstSchemaIterator cend() const
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.
std::size_t Append(const void *from)
Write the given value into columns.
virtual void ReadInClusterImpl(RClusterIndex clusterIndex, void *to)
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.
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc, std::uint16_t representationIndex) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given represe...
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.
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
RConstSchemaIterator cbegin() const
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)
RColumnRepresentations::Selection_t GetColumnRepresentatives() const
Returns the fColumnRepresentative pointee or, if unset, the field's default representative.
std::string fName
The field name relative to its parent field.
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
All fields that have columns have a distinct main column.
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
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.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
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.
RField(std::string_view name)
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Used in RFieldBase::Check() to record field creation failures.
Template specializations for C++ std::[unordered_][multi]map.
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.
RColumnDescriptorIterable GetColumnIterable() const
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
Common user-tunable settings for storing ntuples.
int GetCompression() const
Template specializations for C++ std::optional and std::unique_ptr.
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::unique_ptr< RDeleter > GetDeleter() const final
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::pair< const void *, const bool * > GetValueAndEngagementPtrs(const void *optionalPtr) const
Given a pointer to an std::optional<T> in optionalPtr, extract a pointer to the value T* and a pointe...
ROptionalField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
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.
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::pair.
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 GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
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.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field 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.
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
Template specializations for C++ std::tuple.
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.
Definition