57#include <unordered_map>
61const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
64 {
"Double_t",
"double"},
65 {
"string",
"std::string"},
67 {
"byte",
"std::byte"},
69 {
"int8_t",
"std::int8_t"},
70 {
"UChar_t",
"unsigned char"},
71 {
"uint8_t",
"std::uint8_t"},
74 {
"int16_t",
"std::int16_t"},
75 {
"UShort_t",
"unsigned short"},
76 {
"uint16_t",
"std::uint16_t"},
79 {
"int32_t",
"std::int32_t"},
80 {
"UInt_t",
"unsigned int"},
81 {
"unsigned",
"unsigned int"},
82 {
"uint32_t",
"std::uint32_t"},
87 {
"ULong_t",
"unsigned long"},
89 {
"Long64_t",
"long long"},
90 {
"int64_t",
"std::int64_t"},
91 {
"ULong64_t",
"unsigned long long"},
92 {
"uint64_t",
"std::uint64_t"}};
96std::vector<std::string> TokenizeTypeList(std::string templateType)
98 std::vector<std::string>
result;
99 if (templateType.empty())
102 const char *eol = templateType.data() + templateType.length();
103 const char *typeBegin = templateType.data();
104 const char *typeCursor = templateType.data();
105 unsigned int nestingLevel = 0;
106 while (typeCursor != eol) {
107 switch (*typeCursor) {
108 case '<': ++nestingLevel;
break;
109 case '>': --nestingLevel;
break;
111 if (nestingLevel == 0) {
112 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
113 typeBegin = typeCursor + 1;
119 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
128std::tuple<std::string, std::vector<size_t>> ParseArrayType(std::string_view typeName)
130 std::vector<size_t> sizeVec;
133 while (typeName.back() ==
']') {
134 auto posRBrace = typeName.size() - 1;
135 auto posLBrace = typeName.find_last_of(
'[', posRBrace);
136 if (posLBrace == std::string_view::npos)
140 if (std::from_chars(typeName.data() + posLBrace + 1, typeName.data() + posRBrace,
size).ec != std::errc{})
142 sizeVec.insert(sizeVec.begin(),
size);
143 typeName.remove_suffix(typeName.size() - posLBrace);
145 return std::make_tuple(std::string{typeName}, sizeVec);
150std::string GetCanonicalTypeName(
const std::string &typeName)
153 if (typeName.substr(0, 5) ==
"std::" || typeName.substr(0, 25) ==
"ROOT::RNTupleCardinality<")
163std::string GetNormalizedTypeName(
const std::string &typeName)
167 if (
auto it = typeTranslationMap.find(normalizedType); it != typeTranslationMap.end())
168 normalizedType = it->second;
170 if (normalizedType.substr(0, 7) ==
"vector<")
171 normalizedType =
"std::" + normalizedType;
172 if (normalizedType.substr(0, 6) ==
"array<")
173 normalizedType =
"std::" + normalizedType;
174 if (normalizedType.substr(0, 8) ==
"variant<")
175 normalizedType =
"std::" + normalizedType;
176 if (normalizedType.substr(0, 5) ==
"pair<")
177 normalizedType =
"std::" + normalizedType;
178 if (normalizedType.substr(0, 6) ==
"tuple<")
179 normalizedType =
"std::" + normalizedType;
180 if (normalizedType.substr(0, 7) ==
"bitset<")
181 normalizedType =
"std::" + normalizedType;
182 if (normalizedType.substr(0, 11) ==
"unique_ptr<")
183 normalizedType =
"std::" + normalizedType;
184 if (normalizedType.substr(0, 4) ==
"set<")
185 normalizedType =
"std::" + normalizedType;
186 if (normalizedType.substr(0, 14) ==
"unordered_set<")
187 normalizedType =
"std::" + normalizedType;
188 if (normalizedType.substr(0, 9) ==
"multiset<")
189 normalizedType =
"std::" + normalizedType;
190 if (normalizedType.substr(0, 19) ==
"unordered_multiset<")
191 normalizedType =
"std::" + normalizedType;
192 if (normalizedType.substr(0, 4) ==
"map<")
193 normalizedType =
"std::" + normalizedType;
194 if (normalizedType.substr(0, 14) ==
"unordered_map<")
195 normalizedType =
"std::" + normalizedType;
196 if (normalizedType.substr(0, 9) ==
"multimap<")
197 normalizedType =
"std::" + normalizedType;
198 if (normalizedType.substr(0, 19) ==
"unordered_multimap<")
199 normalizedType =
"std::" + normalizedType;
200 if (normalizedType.substr(0, 7) ==
"atomic<")
201 normalizedType =
"std::" + normalizedType;
203 if (normalizedType.substr(0, 11) ==
"ROOT::RVec<")
204 normalizedType =
"ROOT::VecOps::RVec<" + normalizedType.substr(11);
206 return normalizedType;
210class CreateContextGuard;
212 friend class CreateContextGuard;
214 std::vector<std::string> fClassesOnStack;
217 bool fContinueOnError =
false;
220 CreateContext() =
default;
221 bool GetContinueOnError()
const {
return fContinueOnError; }
225class CreateContextGuard {
226 CreateContext &fCreateContext;
227 std::size_t fNOriginalClassesOnStack;
228 bool fOriginalContinueOnError;
231 CreateContextGuard(CreateContext &ctx)
232 : fCreateContext(ctx),
233 fNOriginalClassesOnStack(ctx.fClassesOnStack.
size()),
234 fOriginalContinueOnError(ctx.fContinueOnError)
237 ~CreateContextGuard()
239 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
240 fCreateContext.fContinueOnError = fOriginalContinueOnError;
243 void AddClassToStack(
const std::string &cl)
245 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
246 fCreateContext.fClassesOnStack.end()) {
249 fCreateContext.fClassesOnStack.emplace_back(cl);
252 void SetContinueOnError(
bool value) { fCreateContext.fContinueOnError =
value; }
257std::tuple<void **, std::int32_t *, std::int32_t *> GetRVecDataMembers(
void *rvecPtr)
259 void **begin =
reinterpret_cast<void **
>(rvecPtr);
261 std::int32_t *
size =
reinterpret_cast<std::int32_t *
>(begin + 1);
264 std::int32_t *capacity =
size + 1;
266 return {begin,
size, capacity};
269std::tuple<const void *const *, const std::int32_t *, const std::int32_t *> GetRVecDataMembers(
const void *rvecPtr)
271 return {GetRVecDataMembers(
const_cast<void *
>(rvecPtr))};
274std::size_t EvalRVecValueSize(std::size_t alignOfT, std::size_t sizeOfT, std::size_t alignOfRVecT)
288 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
291 const auto inlineStorageSz = [&] {
292#ifdef R__HAS_HARDWARE_INTERFERENCE_SIZE
294 constexpr unsigned cacheLineSize = std::hardware_destructive_interference_size;
296 constexpr unsigned cacheLineSize = 64u;
298 const unsigned elementsPerCacheLine = (cacheLineSize - dataMemberSz) / sizeOfT;
299 constexpr unsigned maxInlineByteSize = 1024;
300 const unsigned nElements =
301 elementsPerCacheLine >= 8 ? elementsPerCacheLine : (sizeOfT * 8 > maxInlineByteSize ? 0 : 8);
302 return nElements * sizeOfT;
307 auto paddingMiddle = dataMemberSz % alignOfT;
308 if (paddingMiddle != 0)
309 paddingMiddle = alignOfT - paddingMiddle;
312 auto paddingEnd = (dataMemberSz + paddingMiddle + inlineStorageSz) % alignOfRVecT;
314 paddingEnd = alignOfRVecT - paddingEnd;
316 return dataMemberSz + inlineStorageSz + paddingMiddle + paddingEnd;
319std::size_t EvalRVecAlignment(std::size_t alignOfSubField)
323 return std::max({
alignof(
void *),
alignof(std::int32_t), alignOfSubField});
326void DestroyRVecWithChecks(std::size_t alignOfT,
void **beginPtr,
char *begin, std::int32_t *capacityPtr)
330 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
331 auto paddingMiddle = dataMemberSz % alignOfT;
332 if (paddingMiddle != 0)
333 paddingMiddle = alignOfT - paddingMiddle;
334 const bool isSmall = (
reinterpret_cast<void *
>(begin) == (beginPtr + dataMemberSz + paddingMiddle));
336 const bool owns = (*capacityPtr != -1);
337 if (!isSmall && owns)
342enum class ERNTupleSerializationMode { kForceNativeMode, kForceStreamerMode,
kUnset };
344ERNTupleSerializationMode GetRNTupleSerializationMode(
TClass *cl)
347 if (!am || !am->HasKey(
"rntuple.streamerMode"))
348 return ERNTupleSerializationMode::kUnset;
350 std::string
value = am->GetPropertyAsString(
"rntuple.streamerMode");
352 if (
value ==
"TRUE") {
353 return ERNTupleSerializationMode::kForceStreamerMode;
354 }
else if (
value ==
"FALSE") {
355 return ERNTupleSerializationMode::kForceNativeMode;
358 << am->GetPropertyAsString(
"rntuple.streamerMode");
359 return ERNTupleSerializationMode::kUnset;
364constexpr std::size_t GetVariantTagSize()
367 std::variant<char> t;
368 constexpr auto sizeOfT =
sizeof(t);
370 static_assert(sizeOfT == 2 || sizeOfT == 8,
"unsupported std::variant layout");
371 return sizeOfT == 2 ? 1 : 4;
374template <std::
size_t VariantSizeT>
376 using ValueType_t =
typename std::conditional_t<VariantSizeT == 1, std::uint8_t,
377 typename std::conditional_t<VariantSizeT == 4, std::uint32_t, void>>;
386 RCallbackStreamerInfo fCallbackStreamerInfo;
390 :
TBufferFile(
mode, bufsiz), fCallbackStreamerInfo(callbackStreamerInfo)
427 : fSerializationTypes(serializationTypes), fDeserializationTypes(serializationTypes)
429 fDeserializationTypes.insert(fDeserializationTypes.end(), deserializationExtraTypes.begin(),
430 deserializationExtraTypes.end());
445 : fField(other.fField),
447 fCapacity(other.fCapacity),
449 fIsAdopted(other.fIsAdopted),
450 fNValidValues(other.fNValidValues),
451 fFirstIndex(other.fFirstIndex)
453 std::swap(
fDeleter, other.fDeleter);
454 std::swap(
fValues, other.fValues);
460 std::swap(fField, other.fField);
461 std::swap(fDeleter, other.fDeleter);
462 std::swap(fValues, other.fValues);
464 std::swap(fCapacity, other.fCapacity);
465 std::swap(
fSize, other.fSize);
466 std::swap(fIsAdopted, other.fIsAdopted);
467 std::swap(fMaskAvail, other.fMaskAvail);
468 std::swap(fNValidValues, other.fNValidValues);
469 std::swap(fFirstIndex, other.fFirstIndex);
485 for (std::size_t i = 0; i < fCapacity; ++i) {
486 fDeleter->operator()(GetValuePtrAt(i),
true );
490 operator delete(fValues);
495 if (fCapacity <
size) {
497 throw RException(
R__FAIL(
"invalid attempt to bulk read beyond the adopted buffer"));
503 for (std::size_t i = 0; i <
size; ++i) {
504 fField->ConstructValue(GetValuePtrAt(i));
508 fMaskAvail = std::make_unique<bool[]>(
size);
512 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
515 fFirstIndex = firstIndex;
522 for (std::size_t i = 0; i <
fSize; ++i)
523 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
530 fCapacity = capacity;
533 fMaskAvail = std::make_unique<bool[]>(capacity);
548std::unique_ptr<void, typename ROOT::Experimental::RFieldBase::RCreateObjectDeleter<void>::deleter>
549ROOT::Experimental::RFieldBase::CreateObject<void>()
const
552 return std::unique_ptr<void, RCreateObjectDeleter<void>::deleter>(
CreateObjectRawPtr(), gDeleter);
558 bool isSimple, std::size_t nRepetitions)
573 std::string
result = GetFieldName();
574 auto parent = GetParent();
575 while (parent && !parent->GetFieldName().empty()) {
577 parent = parent->GetParent();
585 auto typeAlias = GetNormalizedTypeName(typeName);
586 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
590std::vector<ROOT::Experimental::RFieldBase::RCheckResult>
593 auto typeAlias = GetNormalizedTypeName(typeName);
594 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
599 std::vector<RCheckResult>
result;
600 for (
const auto &
f : fieldZero) {
606 RCheckResult{invalidField->GetQualifiedFieldName(), invalidField->GetTypeName(), invalidField->GetError()});
613 const std::string &typeAlias,
bool continueOnError)
615 thread_local CreateContext createContext;
616 CreateContextGuard createContextGuard(createContext);
618 createContextGuard.SetContinueOnError(
true);
620 auto fnFail = [&fieldName, &canonicalType](
const std::string &errMsg) ->
RResult<std::unique_ptr<RFieldBase>> {
621 if (createContext.GetContinueOnError()) {
622 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, errMsg));
628 if (canonicalType.empty())
629 return R__FORWARD_RESULT(fnFail(
"no type name specified for field '" + fieldName +
"'"));
631 std::unique_ptr<ROOT::Experimental::RFieldBase>
result;
636 if (
auto [arrayBaseType, arraySizes] = ParseArrayType(canonicalType); !arraySizes.empty()) {
637 std::unique_ptr<RFieldBase> arrayField = Create(
"_0", arrayBaseType).Unwrap();
638 for (
int i = arraySizes.size() - 1; i >= 0; --i) {
640 std::make_unique<RArrayField>((i == 0) ? fieldName :
"_0", std::move(arrayField), arraySizes[i]);
645 if (canonicalType ==
"bool") {
646 result = std::make_unique<RField<bool>>(fieldName);
647 }
else if (canonicalType ==
"char") {
648 result = std::make_unique<RField<char>>(fieldName);
649 }
else if (canonicalType ==
"signed char") {
650 result = std::make_unique<RField<signed char>>(fieldName);
651 }
else if (canonicalType ==
"unsigned char") {
652 result = std::make_unique<RField<unsigned char>>(fieldName);
653 }
else if (canonicalType ==
"short") {
654 result = std::make_unique<RField<short>>(fieldName);
655 }
else if (canonicalType ==
"unsigned short") {
656 result = std::make_unique<RField<unsigned short>>(fieldName);
657 }
else if (canonicalType ==
"int") {
658 result = std::make_unique<RField<int>>(fieldName);
659 }
else if (canonicalType ==
"unsigned int") {
660 result = std::make_unique<RField<unsigned int>>(fieldName);
661 }
else if (canonicalType ==
"long") {
662 result = std::make_unique<RField<long>>(fieldName);
663 }
else if (canonicalType ==
"unsigned long") {
664 result = std::make_unique<RField<unsigned long>>(fieldName);
665 }
else if (canonicalType ==
"long long") {
666 result = std::make_unique<RField<long long>>(fieldName);
667 }
else if (canonicalType ==
"unsigned long long") {
668 result = std::make_unique<RField<unsigned long long>>(fieldName);
669 }
else if (canonicalType ==
"std::byte") {
670 result = std::make_unique<RField<std::byte>>(fieldName);
671 }
else if (canonicalType ==
"std::int8_t") {
672 result = std::make_unique<RField<std::int8_t>>(fieldName);
673 }
else if (canonicalType ==
"std::uint8_t") {
674 result = std::make_unique<RField<std::uint8_t>>(fieldName);
675 }
else if (canonicalType ==
"std::int16_t") {
676 result = std::make_unique<RField<std::int16_t>>(fieldName);
677 }
else if (canonicalType ==
"std::uint16_t") {
678 result = std::make_unique<RField<std::uint16_t>>(fieldName);
679 }
else if (canonicalType ==
"std::int32_t") {
680 result = std::make_unique<RField<std::int32_t>>(fieldName);
681 }
else if (canonicalType ==
"std::uint32_t") {
682 result = std::make_unique<RField<std::uint32_t>>(fieldName);
683 }
else if (canonicalType ==
"std::int64_t") {
684 result = std::make_unique<RField<std::int64_t>>(fieldName);
685 }
else if (canonicalType ==
"std::uint64_t") {
686 result = std::make_unique<RField<std::uint64_t>>(fieldName);
687 }
else if (canonicalType ==
"float") {
688 result = std::make_unique<RField<float>>(fieldName);
689 }
else if (canonicalType ==
"double") {
690 result = std::make_unique<RField<double>>(fieldName);
691 }
else if (canonicalType ==
"Double32_t") {
692 result = std::make_unique<RField<double>>(fieldName);
696 }
else if (canonicalType ==
"std::string") {
697 result = std::make_unique<RField<std::string>>(fieldName);
698 }
else if (canonicalType ==
"TObject") {
699 result = std::make_unique<RField<TObject>>(fieldName);
700 }
else if (canonicalType ==
"std::vector<bool>") {
701 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
702 }
else if (canonicalType.substr(0, 12) ==
"std::vector<") {
703 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
704 auto itemField = Create(
"_0", itemTypeName);
705 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
706 }
else if (canonicalType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
707 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
708 auto itemField = Create(
"_0", itemTypeName);
709 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
710 }
else if (canonicalType.substr(0, 11) ==
"std::array<") {
711 auto arrayDef = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
712 if (arrayDef.size() != 2) {
713 return R__FORWARD_RESULT(fnFail(
"the template list for std::array must have exactly two elements"));
715 auto arrayLength = std::stoi(arrayDef[1]);
716 auto itemField = Create(
"_0", arrayDef[0]);
717 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
718 }
else if (canonicalType.substr(0, 13) ==
"std::variant<") {
719 auto innerTypes = TokenizeTypeList(canonicalType.substr(13, canonicalType.length() - 14));
720 std::vector<std::unique_ptr<RFieldBase>> items;
721 items.reserve(innerTypes.size());
722 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
723 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
725 result = std::make_unique<RVariantField>(fieldName, std::move(items));
726 }
else if (canonicalType.substr(0, 10) ==
"std::pair<") {
727 auto innerTypes = TokenizeTypeList(canonicalType.substr(10, canonicalType.length() - 11));
728 if (innerTypes.size() != 2) {
729 return R__FORWARD_RESULT(fnFail(
"the type list for std::pair must have exactly two elements"));
731 std::array<std::unique_ptr<RFieldBase>, 2> items{Create(
"_0", innerTypes[0]).Unwrap(),
732 Create(
"_1", innerTypes[1]).Unwrap()};
733 result = std::make_unique<RPairField>(fieldName, std::move(items));
734 }
else if (canonicalType.substr(0, 11) ==
"std::tuple<") {
735 auto innerTypes = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
736 std::vector<std::unique_ptr<RFieldBase>> items;
737 items.reserve(innerTypes.size());
738 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
739 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
741 result = std::make_unique<RTupleField>(fieldName, std::move(items));
742 }
else if (canonicalType.substr(0, 12) ==
"std::bitset<") {
743 auto size = std::stoull(canonicalType.substr(12, canonicalType.length() - 13));
744 result = std::make_unique<RBitsetField>(fieldName,
size);
745 }
else if (canonicalType.substr(0, 16) ==
"std::unique_ptr<") {
746 std::string itemTypeName = canonicalType.substr(16, canonicalType.length() - 17);
747 auto itemField = Create(
"_0", itemTypeName).Unwrap();
748 auto normalizedInnerTypeName = itemField->GetTypeName();
749 result = std::make_unique<RUniquePtrField>(fieldName,
"std::unique_ptr<" + normalizedInnerTypeName +
">",
750 std::move(itemField));
751 }
else if (canonicalType.substr(0, 14) ==
"std::optional<") {
752 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
753 auto itemField = Create(
"_0", itemTypeName).Unwrap();
754 auto normalizedInnerTypeName = itemField->GetTypeName();
755 result = std::make_unique<ROptionalField>(fieldName,
"std::optional<" + normalizedInnerTypeName +
">",
756 std::move(itemField));
757 }
else if (canonicalType.substr(0, 9) ==
"std::set<") {
758 std::string itemTypeName = canonicalType.substr(9, canonicalType.length() - 10);
759 auto itemField = Create(
"_0", itemTypeName).Unwrap();
760 auto normalizedInnerTypeName = itemField->GetTypeName();
762 std::make_unique<RSetField>(fieldName,
"std::set<" + normalizedInnerTypeName +
">", std::move(itemField));
763 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_set<") {
764 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
765 auto itemField = Create(
"_0", itemTypeName).Unwrap();
766 auto normalizedInnerTypeName = itemField->GetTypeName();
767 result = std::make_unique<RSetField>(fieldName,
"std::unordered_set<" + normalizedInnerTypeName +
">",
768 std::move(itemField));
769 }
else if (canonicalType.substr(0, 14) ==
"std::multiset<") {
770 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
771 auto itemField = Create(
"_0", itemTypeName).Unwrap();
772 auto normalizedInnerTypeName = itemField->GetTypeName();
773 result = std::make_unique<RSetField>(fieldName,
"std::multiset<" + normalizedInnerTypeName +
">",
774 std::move(itemField));
775 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multiset<") {
776 std::string itemTypeName = canonicalType.substr(24, canonicalType.length() - 25);
777 auto itemField = Create(
"_0", itemTypeName).Unwrap();
778 auto normalizedInnerTypeName = itemField->GetTypeName();
779 result = std::make_unique<RSetField>(fieldName,
"std::unordered_multiset<" + normalizedInnerTypeName +
">",
780 std::move(itemField));
781 }
else if (canonicalType.substr(0, 9) ==
"std::map<") {
782 auto innerTypes = TokenizeTypeList(canonicalType.substr(9, canonicalType.length() - 10));
783 if (innerTypes.size() != 2) {
784 return R__FORWARD_RESULT(fnFail(
"the type list for std::map must have exactly two elements"));
787 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
791 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
792 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
794 result = std::make_unique<RMapField>(fieldName,
"std::map<" + keyTypeName +
"," + valueTypeName +
">",
795 std::move(itemField));
796 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_map<") {
797 auto innerTypes = TokenizeTypeList(canonicalType.substr(19, canonicalType.length() - 20));
798 if (innerTypes.size() != 2)
799 return R__FORWARD_RESULT(fnFail(
"the type list for std::unordered_map must have exactly two elements"));
801 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
805 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
806 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
808 result = std::make_unique<RMapField>(
809 fieldName,
"std::unordered_map<" + keyTypeName +
"," + valueTypeName +
">", std::move(itemField));
810 }
else if (canonicalType.substr(0, 14) ==
"std::multimap<") {
811 auto innerTypes = TokenizeTypeList(canonicalType.substr(14, canonicalType.length() - 15));
812 if (innerTypes.size() != 2)
813 return R__FORWARD_RESULT(fnFail(
"the type list for std::multimap must have exactly two elements"));
815 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
819 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
820 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
822 result = std::make_unique<RMapField>(fieldName,
"std::multimap<" + keyTypeName +
"," + valueTypeName +
">",
823 std::move(itemField));
824 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multimap<") {
825 auto innerTypes = TokenizeTypeList(canonicalType.substr(24, canonicalType.length() - 25));
826 if (innerTypes.size() != 2)
828 fnFail(
"the type list for std::unordered_multimap must have exactly two elements"));
830 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
834 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
835 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
837 result = std::make_unique<RMapField>(
838 fieldName,
"std::unordered_multimap<" + keyTypeName +
"," + valueTypeName +
">", std::move(itemField));
839 }
else if (canonicalType.substr(0, 12) ==
"std::atomic<") {
840 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
841 auto itemField = Create(
"_0", itemTypeName).Unwrap();
842 auto normalizedInnerTypeName = itemField->GetTypeName();
843 result = std::make_unique<RAtomicField>(fieldName,
"std::atomic<" + normalizedInnerTypeName +
">",
844 std::move(itemField));
845 }
else if (canonicalType.substr(0, 25) ==
"ROOT::RNTupleCardinality<") {
846 auto innerTypes = TokenizeTypeList(canonicalType.substr(25, canonicalType.length() - 26));
847 if (innerTypes.size() != 1)
848 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
849 if (innerTypes[0] ==
"std::uint32_t") {
850 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
851 }
else if (innerTypes[0] ==
"std::uint64_t") {
852 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
854 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
861 result = std::make_unique<REnumField>(fieldName, canonicalType);
868 createContextGuard.AddClassToStack(canonicalType);
870 result = std::make_unique<RProxiedCollectionField>(fieldName, canonicalType);
872 if (GetRNTupleSerializationMode(cl) == ERNTupleSerializationMode::kForceStreamerMode) {
873 result = std::make_unique<RStreamerField>(fieldName, canonicalType);
875 result = std::make_unique<RClassField>(fieldName, canonicalType);
881 auto error =
e.GetError();
882 if (createContext.GetContinueOnError()) {
883 return std::unique_ptr<RFieldBase>(
884 std::make_unique<RInvalidField>(fieldName, canonicalType, error.GetReport()));
891 if (typeAlias != canonicalType)
892 result->fTypeAlias = typeAlias;
902 return representations;
907 auto clone = CloneImpl(newName);
908 clone->fTypeAlias = fTypeAlias;
909 clone->fOnDiskId = fOnDiskId;
910 clone->fDescription = fDescription;
912 clone->fColumnRepresentatives = fColumnRepresentatives;
918 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
929 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(clusterIndex), to);
934 const auto valueSize = GetValueSize();
935 std::size_t nRead = 0;
936 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
945 Read(bulkSpec.
fFirstIndex + i,
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + i * valueSize);
954 void *where =
operator new(GetValueSize());
956 ConstructValue(where);
962 void *obj = CreateObjectRawPtr();
966std::vector<ROOT::Experimental::RFieldBase::RValue>
969 return std::vector<RValue>();
976 if (fState != EState::kUnconnected)
977 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
978 child->fParent =
this;
979 fSubFields.emplace_back(std::move(
child));
985 std::size_t
result = globalIndex;
986 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
987 auto parent =
f->GetParent();
988 if (parent && (parent->GetStructure() ==
kCollection || parent->GetStructure() ==
kVariant))
990 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
997 std::vector<RFieldBase *>
result;
998 result.reserve(fSubFields.size());
999 for (
const auto &
f : fSubFields) {
1007 std::vector<const RFieldBase *>
result;
1008 result.reserve(fSubFields.size());
1009 for (
const auto &
f : fSubFields) {
1017 if (!fAvailableColumns.empty()) {
1018 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1019 for (
auto &column : fAvailableColumns) {
1020 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1029 if (!fAvailableColumns.empty()) {
1030 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1031 for (
auto &column : fAvailableColumns) {
1032 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1035 column->CommitSuppressed();
1039 CommitClusterImpl();
1044 if (fState != EState::kUnconnected)
1045 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
1046 fDescription = std::string(description);
1051 if (fState != EState::kUnconnected)
1060 if (~fTraits & kTraitMappable)
1061 return AppendImpl(from);
1063 fPrincipalColumn->Append(from);
1064 return fPrincipalColumn->GetElement()->GetPackedSize();
1074 return RValue(
this, objPtr);
1083 return RBulkSpec::kAllSet;
1086 return ReadBulkImpl(bulkSpec);
1122 if (fColumnRepresentatives.empty()) {
1123 return {GetColumnRepresentations().GetSerializationDefault()};
1127 result.reserve(fColumnRepresentatives.size());
1128 for (
const auto &
r : fColumnRepresentatives) {
1137 if (fState != EState::kUnconnected)
1138 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
1139 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
1140 fColumnRepresentatives.clear();
1141 fColumnRepresentatives.reserve(representatives.size());
1142 for (
const auto &
r : representatives) {
1143 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(),
r);
1144 if (itRepresentative == std::end(validTypes))
1146 fColumnRepresentatives.emplace_back(*itRepresentative);
1152 std::uint16_t representationIndex)
const
1157 throw RException(
R__FAIL(
"No on-disk field information for `" + GetQualifiedFieldName() +
"`"));
1161 if (
c.GetRepresentationIndex() == representationIndex)
1162 onDiskTypes.emplace_back(
c.GetType());
1164 if (onDiskTypes.empty()) {
1165 if (representationIndex == 0) {
1166 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
1171 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1172 if (t == onDiskTypes)
1176 std::string columnTypeNames;
1177 for (
const auto &t : onDiskTypes) {
1178 if (!columnTypeNames.empty())
1179 columnTypeNames +=
", ";
1182 throw RException(
R__FAIL(
"On-disk column types {" + columnTypeNames +
"} for field `" + GetQualifiedFieldName() +
1183 "` cannot be matched to its in-memory type `" + GetTypeName() +
"` " +
1184 "(representation index: " + std::to_string(representationIndex) +
")"));
1189 fReadCallbacks.push_back(func);
1191 return fReadCallbacks.size() - 1;
1196 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
1197 fIsSimple = (fTraits & kTraitMappable) && fReadCallbacks.empty();
1202 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
1204 for (
auto &colType : rep) {
1219 SetColumnRepresentatives({rep});
1222 if (fTypeAlias ==
"Double32_t")
1229 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page sink"));
1230 if (fState != EState::kUnconnected)
1231 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
1236 for (
auto &column : fAvailableColumns) {
1240 auto firstElementIndex = (column->GetIndex() == 0) ? EntryToColumnElementIndex(firstEntry) : 0;
1241 column->ConnectPageSink(fOnDiskId, pageSink, firstElementIndex);
1244 if (HasExtraTypeInfo()) {
1249 fState = EState::kConnectedToSink;
1255 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
1256 if (fState != EState::kUnconnected)
1257 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
1259 if (!fColumnRepresentatives.empty())
1260 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
1261 if (!fDescription.empty())
1262 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
1264 for (
auto &
f : fSubFields) {
1268 f->ConnectPageSource(pageSource);
1274 GenerateColumns(desc);
1275 if (fColumnRepresentatives.empty()) {
1277 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1279 fColumnRepresentatives = {t};
1284 R__ASSERT(!fColumnRepresentatives.empty());
1288 if (fieldDesc.GetTypeChecksum().has_value())
1289 fOnDiskTypeChecksum = *fieldDesc.GetTypeChecksum();
1292 for (
auto &column : fAvailableColumns)
1293 column->ConnectPageSource(fOnDiskId, pageSource);
1294 OnConnectPageSource();
1296 fState = EState::kConnectedToSource;
1306std::unique_ptr<ROOT::Experimental::RFieldBase>
1309 auto result = std::make_unique<RFieldZero>();
1310 for (
auto &
f : fSubFields)
1311 result->Attach(
f->Clone(
f->GetFieldName()));
1328 return representations;
1333 GenerateColumnsImpl<ClusterSize_t>(desc);
1375 return representations;
1391 return representations;
1396 visitor.VisitByteField(*
this);
1421 return representations;
1426 visitor.VisitInt8Field(*
this);
1451 return representations;
1456 visitor.VisitUInt8Field(*
this);
1481 return representations;
1502 return representations;
1525 return representations;
1535 fTypeAlias =
"Double32_t";
1560 return representations;
1565 visitor.VisitInt16Field(*
this);
1590 return representations;
1595 visitor.VisitUInt16Field(*
this);
1620 return representations;
1625 visitor.VisitInt32Field(*
this);
1650 return representations;
1655 visitor.VisitUInt32Field(*
this);
1680 return representations;
1685 visitor.VisitUInt64Field(*
this);
1710 return representations;
1715 visitor.VisitInt64Field(*
this);
1728 return representations;
1733 GenerateColumnsImpl<ClusterSize_t, char>();
1738 GenerateColumnsImpl<ClusterSize_t, char>(desc);
1743 auto typedValue =
static_cast<const std::string *
>(from);
1744 auto length = typedValue->length();
1745 fAuxiliaryColumn->AppendV(typedValue->data(),
length);
1747 fPrincipalColumn->Append(&fIndex);
1748 return length + fPrincipalColumn->GetElement()->GetPackedSize();
1753 auto typedValue =
static_cast<std::string *
>(to);
1754 RClusterIndex collectionStart;
1756 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
1758 typedValue->clear();
1760 typedValue->resize(nChars);
1761 fAuxiliaryColumn->ReadV(collectionStart, nChars,
const_cast<char *
>(typedValue->data()));
1767 visitor.VisitStringField(*
this);
1775 fSubFieldsInfo(source.fSubFieldsInfo),
1776 fMaxAlignment(source.fMaxAlignment)
1794 throw RException(
R__FAIL(
"RField: no I/O support for type " + std::string(className)));
1800 if (className ==
"TObject") {
1805 R__FAIL(std::string(className) +
" has an associated collection proxy; use RProxiedCollectionField instead"));
1810 GetRNTupleSerializationMode(
fClass) != ERNTupleSerializationMode::kForceNativeMode) {
1811 throw RException(
R__FAIL(std::string(className) +
" cannot be stored natively in RNTuple"));
1813 if (GetRNTupleSerializationMode(
fClass) == ERNTupleSerializationMode::kForceStreamerMode) {
1815 R__FAIL(std::string(className) +
" has streamer mode enforced, not supported as native RNTuple class"));
1825 if (baseClass->GetDelta() < 0) {
1826 throw RException(
R__FAIL(std::string(
"virtual inheritance is not supported: ") + std::string(className) +
1827 " virtually inherits from " + baseClass->GetName()));
1829 TClass *
c = baseClass->GetClassPointer();
1832 fTraits &= subField->GetTraits();
1841 if (!dataMember->IsPersistent()) {
1847 std::string typeName{GetNormalizedTypeName(dataMember->GetTrueTypeName())};
1848 std::string typeAlias{GetNormalizedTypeName(dataMember->GetFullTypeName())};
1851 if (dataMember->Property() &
kIsArray) {
1852 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim)
1853 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
1856 std::unique_ptr<RFieldBase> subField;
1859 fTraits &= subField->GetTraits();
1867 fMaxAlignment = std::max(fMaxAlignment,
child->GetAlignment());
1868 fSubFieldsInfo.push_back(info);
1875 for (
const auto rule : rules) {
1880 auto func = rule->GetReadFunctionPointer();
1882 fReadCallbacks.emplace_back([func, classp](
void *
target) {
1886 func(
static_cast<char *
>(
target), &oldObj);
1887 oldObj.fClass =
nullptr;
1892std::unique_ptr<ROOT::Experimental::RFieldBase>
1895 return std::unique_ptr<RClassField>(
new RClassField(newName, *
this));
1900 std::size_t nbytes = 0;
1901 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1902 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fSubFieldsInfo[i].fOffset);
1909 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1910 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1916 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1917 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1925 const auto ruleset =
fClass->GetSchemaRules();
1929 if (rule->GetTarget() ==
nullptr)
1932 const auto dataMember = klass->GetDataMember(
target->GetString());
1933 if (!dataMember || dataMember->IsPersistent()) {
1935 << dataMember->GetName();
1942 auto rules = ruleset->FindRules(
fClass->GetName(),
static_cast<Int_t>(GetOnDiskTypeVersion()),
1943 static_cast<UInt_t>(GetOnDiskTypeChecksum()));
1944 rules.erase(std::remove_if(rules.begin(), rules.end(), referencesNonTransientMembers), rules.end());
1945 AddReadCallbacksFromIORules(rules,
fClass);
1955 fClass->Destructor(objPtr,
true );
1956 RDeleter::operator()(objPtr, dtorOnly);
1959std::vector<ROOT::Experimental::RFieldBase::RValue>
1962 std::vector<RValue>
result;
1963 auto basePtr =
value.GetPtr<
unsigned char>().get();
1964 result.reserve(fSubFields.size());
1965 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1967 fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fSubFieldsInfo[i].fOffset)));
1974 return fClass->GetClassSize();
1979 return fClass->GetClassVersion();
1984 return fClass->GetCheckSum();
1997 return dataMember->GetOffset();
2020std::unique_ptr<ROOT::Experimental::RFieldBase>
2023 return std::unique_ptr<RField<TObject>>(
new RField<TObject>(newName, *
this));
2030 auto *obj =
static_cast<const TObject *
>(from);
2035 std::size_t nbytes = 0;
2036 nbytes += CallAppendOn(*fSubFields[0],
reinterpret_cast<const unsigned char *
>(from) + GetOffsetUniqueID());
2038 UInt_t bits = *
reinterpret_cast<const UInt_t *
>(
reinterpret_cast<const unsigned char *
>(from) + GetOffsetBits());
2040 nbytes += CallAppendOn(*fSubFields[1], &bits);
2049 auto *obj =
static_cast<TObject *
>(to);
2054 CallReadOn(*fSubFields[0], globalIndex,
static_cast<unsigned char *
>(to) + GetOffsetUniqueID());
2058 CallReadOn(*fSubFields[1], globalIndex, &bits);
2060 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetBits()) = bits;
2065 if (GetTypeVersion() != 1) {
2066 throw RException(
R__FAIL(
"unsupported on-disk version of TObject: " + std::to_string(GetTypeVersion())));
2085std::vector<ROOT::Experimental::RFieldBase::RValue>
2088 std::vector<RValue>
result;
2089 auto basePtr =
value.GetPtr<
unsigned char>().get();
2091 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetUniqueID())));
2093 fSubFields[1]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetBits())));
2115 std::string_view typeAlias)
2128 throw RException(
R__FAIL(
"RStreamerField: no I/O support for type " + std::string(className)));
2138std::unique_ptr<ROOT::Experimental::RFieldBase>
2141 return std::unique_ptr<RStreamerField>(
new RStreamerField(newName, GetTypeName(), GetTypeAlias()));
2148 fClass->Streamer(
const_cast<void *
>(from), buffer);
2150 auto nbytes = buffer.Length();
2151 fAuxiliaryColumn->AppendV(buffer.Buffer(), buffer.Length());
2153 fPrincipalColumn->Append(&fIndex);
2154 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2161 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nbytes);
2164 fAuxiliaryColumn->ReadV(collectionStart, nbytes, buffer.
Buffer());
2165 fClass->Streamer(to, buffer);
2176 return representations;
2181 GenerateColumnsImpl<ClusterSize_t, std::byte>();
2186 GenerateColumnsImpl<ClusterSize_t, std::byte>(desc);
2196 fClass->Destructor(objPtr,
true );
2197 RDeleter::operator()(objPtr, dtorOnly);
2212 return std::min(
alignof(std::max_align_t), GetValueSize());
2217 return fClass->GetClassSize();
2222 return fClass->GetClassVersion();
2227 return fClass->GetCheckSum();
2238 :
REnumField(fieldName, enumName,
TEnum::GetEnum(std::string(enumName).c_str()))
2245 if (enump ==
nullptr) {
2246 throw RException(
R__FAIL(
"RField: no I/O support for enum type " + std::string(enumName)));
2264 default:
throw RException(
R__FAIL(
"Unsupported underlying integral type for enum type " + std::string(enumName)));
2271 std::unique_ptr<RFieldBase> intField)
2274 Attach(std::move(intField));
2278std::unique_ptr<ROOT::Experimental::RFieldBase>
2281 auto newIntField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2282 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
2285std::vector<ROOT::Experimental::RFieldBase::RValue>
2288 std::vector<RValue>
result;
2289 result.emplace_back(fSubFields[0]->BindValue(
value.GetPtr<
void>()));
2309 (ifuncs.
fNext !=
nullptr));
2314 std::string_view typeName,
TClass *classp)
2317 if (classp ==
nullptr)
2318 throw RException(
R__FAIL(
"RField: no I/O support for collection proxy type " + std::string(typeName)));
2320 throw RException(
R__FAIL(std::string(typeName) +
" has no associated collection proxy"));
2325 if (
fProxy->HasPointers())
2326 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
2327 if (!
fProxy->GetCollectionClass()->HasDictionary()) {
2329 GetNormalizedTypeName(
fProxy->GetCollectionClass()->GetName())));
2337 std::string_view typeName,
2338 std::unique_ptr<RFieldBase> itemField)
2342 Attach(std::move(itemField));
2346 std::string_view typeName)
2351 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
2353 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField;
2355 if (
auto valueClass =
fProxy->GetValueClass()) {
2359 switch (
fProxy->GetType()) {
2361 case EDataType::kUChar_t: itemField = std::make_unique<RField<std::uint8_t>>(
"_0");
break;
2362 case EDataType::kShort_t: itemField = std::make_unique<RField<std::int16_t>>(
"_0");
break;
2364 case EDataType::kInt_t: itemField = std::make_unique<RField<std::int32_t>>(
"_0");
break;
2365 case EDataType::kUInt_t: itemField = std::make_unique<RField<std::uint32_t>>(
"_0");
break;
2378 Attach(std::move(itemField));
2381std::unique_ptr<ROOT::Experimental::RFieldBase>
2384 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2385 return std::unique_ptr<RProxiedCollectionField>(
2391 std::size_t nbytes = 0;
2395 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2396 nbytes += CallAppendOn(*fSubFields[0], ptr);
2401 fPrincipalColumn->Append(&fNWritten);
2402 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2409 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2417 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
2418 CallReadOn(*fSubFields[0], collectionStart + (i++), elementPtr);
2421 fProxy->Commit(obj);
2430 return representations;
2435 GenerateColumnsImpl<ClusterSize_t>();
2440 GenerateColumnsImpl<ClusterSize_t>(desc);
2448std::unique_ptr<ROOT::Experimental::RFieldBase::RDeleter>
2452 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
2453 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubFields[0]), itemSize);
2455 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
2463 fItemDeleter->operator()(ptr,
true );
2466 fProxy->Destructor(objPtr,
true );
2467 RDeleter::operator()(objPtr, dtorOnly);
2470std::vector<ROOT::Experimental::RFieldBase::RValue>
2473 std::vector<RValue>
result;
2474 auto valueRawPtr =
value.GetPtr<
void>().get();
2477 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2478 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
2492 fMaxAlignment(source.fMaxAlignment),
2494 fOffsets(source.fOffsets)
2497 Attach(
f->Clone(
f->GetFieldName()));
2506void ROOT::Experimental::RRecordField::RRecordField::AttachItemFields(
2507 std::vector<std::unique_ptr<RFieldBase>> itemFields)
2509 fTraits |= kTraitTrivialType;
2510 for (
auto &item : itemFields) {
2511 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
2512 fSize += GetItemPadding(
fSize, item->GetAlignment()) + item->GetValueSize();
2513 fTraits &= item->GetTraits();
2514 Attach(std::move(item));
2518 fSize += GetItemPadding(
fSize, fMaxAlignment);
2522 std::vector<std::unique_ptr<RFieldBase>> itemFields)
2526 fOffsets.reserve(itemFields.size());
2527 for (
auto &item : itemFields) {
2531 fSize += item->GetValueSize();
2542 if (itemAlignment > 1) {
2543 auto remainder = baseOffset % itemAlignment;
2545 return itemAlignment - remainder;
2550std::unique_ptr<ROOT::Experimental::RFieldBase>
2553 return std::unique_ptr<RRecordField>(
new RRecordField(newName, *
this));
2558 std::size_t nbytes = 0;
2559 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2560 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
2567 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2568 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2574 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2575 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2581 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2582 CallConstructValueOn(*fSubFields[i],
static_cast<unsigned char *
>(where) + fOffsets[i]);
2588 for (
unsigned i = 0; i < fItemDeleters.size(); ++i) {
2589 fItemDeleters[i]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fOffsets[i],
true );
2591 RDeleter::operator()(objPtr, dtorOnly);
2596 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2597 itemDeleters.reserve(fOffsets.size());
2598 for (
const auto &
f : fSubFields) {
2599 itemDeleters.emplace_back(GetDeleterOf(*
f));
2601 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
2604std::vector<ROOT::Experimental::RFieldBase::RValue>
2607 auto basePtr =
value.GetPtr<
unsigned char>().get();
2608 std::vector<RValue>
result;
2609 result.reserve(fSubFields.size());
2610 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2611 result.emplace_back(fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fOffsets[i])));
2625 :
ROOT::Experimental::
RFieldBase(fieldName, isUntyped ?
"" :
"std::vector<" + itemField->GetTypeName() +
">",
2627 fItemSize(itemField->GetValueSize()),
2632 Attach(std::move(itemField));
2640std::unique_ptr<ROOT::Experimental::RVectorField>
2643 return std::unique_ptr<ROOT::Experimental::RVectorField>(
new RVectorField(fieldName, std::move(itemField),
true));
2646std::unique_ptr<ROOT::Experimental::RFieldBase>
2649 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2650 return std::unique_ptr<ROOT::Experimental::RVectorField>(
2651 new RVectorField(newName, std::move(newItemField), GetTypeName().empty()));
2656 auto typedValue =
static_cast<const std::vector<char> *
>(from);
2657 R__ASSERT((typedValue->size() % fItemSize) == 0);
2658 std::size_t nbytes = 0;
2659 auto count = typedValue->size() / fItemSize;
2661 if (fSubFields[0]->IsSimple() && count) {
2662 GetPrincipalColumnOf(*fSubFields[0])->AppendV(typedValue->data(), count);
2663 nbytes += count * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2665 for (
unsigned i = 0; i < count; ++i) {
2666 nbytes += CallAppendOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2671 fPrincipalColumn->Append(&fNWritten);
2672 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2677 auto typedValue =
static_cast<std::vector<char> *
>(to);
2681 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2683 if (fSubFields[0]->IsSimple()) {
2684 typedValue->resize(nItems * fItemSize);
2686 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, typedValue->data());
2691 const auto oldNItems = typedValue->size() / fItemSize;
2692 const bool canRealloc = oldNItems < nItems;
2693 bool allDeallocated =
false;
2695 allDeallocated = canRealloc;
2696 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
2697 fItemDeleter->operator()(typedValue->data() + (i * fItemSize),
true );
2700 typedValue->resize(nItems * fItemSize);
2701 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)) {
2702 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
2703 CallConstructValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2707 for (std::size_t i = 0; i < nItems; ++i) {
2708 CallReadOn(*fSubFields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
2718 return representations;
2723 GenerateColumnsImpl<ClusterSize_t>();
2728 GenerateColumnsImpl<ClusterSize_t>(desc);
2733 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
2735 R__ASSERT((vecPtr->size() % fItemSize) == 0);
2736 auto nItems = vecPtr->size() / fItemSize;
2737 for (std::size_t i = 0; i < nItems; ++i) {
2738 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize),
true );
2741 std::destroy_at(vecPtr);
2742 RDeleter::operator()(objPtr, dtorOnly);
2748 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubFields[0]));
2749 return std::make_unique<RVectorDeleter>();
2752std::vector<ROOT::Experimental::RFieldBase::RValue>
2755 auto vec =
value.GetPtr<std::vector<char>>();
2757 auto nItems =
vec->size() / fItemSize;
2758 std::vector<RValue>
result;
2760 for (
unsigned i = 0; i < nItems; ++i) {
2762 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(),
vec->data() + (i * fItemSize))));
2775 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
2777 fItemSize(itemField->GetValueSize()),
2782 Attach(std::move(itemField));
2786std::unique_ptr<ROOT::Experimental::RFieldBase>
2789 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2790 return std::make_unique<RRVecField>(newName, std::move(newItemField));
2795 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(from);
2797 std::size_t nbytes = 0;
2798 if (fSubFields[0]->IsSimple() && *sizePtr) {
2799 GetPrincipalColumnOf(*fSubFields[0])->AppendV(*beginPtr, *sizePtr);
2800 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2802 auto begin =
reinterpret_cast<const char *
>(*beginPtr);
2803 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2804 nbytes += CallAppendOn(*fSubFields[0], begin + i * fItemSize);
2808 fNWritten += *sizePtr;
2809 fPrincipalColumn->Append(&fNWritten);
2810 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2818 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(to);
2823 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2824 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2825 const std::size_t oldSize = *sizePtr;
2829 const bool owns = (*capacityPtr != -1);
2830 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
2831 const bool needsDestruct = owns && fItemDeleter;
2834 if (needsDestruct) {
2835 for (std::size_t i = nItems; i < oldSize; ++i) {
2836 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2841 if (std::int32_t(nItems) > *capacityPtr) {
2844 if (needsDestruct) {
2845 for (std::size_t i = 0u; i < oldSize; ++i) {
2846 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2857 *beginPtr =
malloc(nItems * fItemSize);
2859 begin =
reinterpret_cast<char *
>(*beginPtr);
2860 *capacityPtr = nItems;
2863 if (needsConstruct) {
2864 for (std::size_t i = 0u; i < oldSize; ++i)
2865 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2871 if (needsConstruct) {
2872 for (std::size_t i = oldSize; i < nItems; ++i)
2873 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2876 if (fSubFields[0]->IsSimple() && nItems) {
2877 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, begin);
2882 for (std::size_t i = 0; i < nItems; ++i) {
2883 CallReadOn(*fSubFields[0], collectionStart + i, begin + (i * fItemSize));
2889 if (!fSubFields[0]->IsSimple())
2895 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
2896 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fSubFields[0]->GetValueSize();
2898 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
2899 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
2900 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(bulkSpec.
fValues);
2906 this->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
2907 *beginPtr = itemValueArray;
2908 *sizePtr = collectionSize;
2914 auto lastOffset = firstItemIndex.
GetIndex() + collectionSize;
2916 std::size_t nValues = 1;
2917 std::size_t nItems = collectionSize;
2918 while (nRemainingValues > 0) {
2921 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
2922 for (std::size_t i = 0; i < nBatch; ++i) {
2923 const auto size = offsets[i] - lastOffset;
2924 std::tie(beginPtr, sizePtr, capacityPtr) =
2925 GetRVecDataMembers(
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
2926 *beginPtr = itemValueArray + nItems * itemValueSize;
2931 lastOffset = offsets[i];
2933 nRemainingValues -= nBatch;
2937 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
2939 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
2941 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
2942 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
2943 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
2948 GetPrincipalColumnOf(*fSubFields[0])->ReadV(firstItemIndex, nItems, itemValueArray - delta);
2949 return RBulkSpec::kAllSet;
2958 return representations;
2963 GenerateColumnsImpl<ClusterSize_t>();
2968 GenerateColumnsImpl<ClusterSize_t>(desc);
2975 void **beginPtr =
new (where)(
void *)(
nullptr);
2976 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2977 new (sizePtr + 1) std::int32_t(-1);
2982 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(objPtr);
2984 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2986 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2987 fItemDeleter->operator()(begin + i * fItemSize,
true );
2991 DestroyRVecWithChecks(fItemAlignment, beginPtr, begin, capacityPtr);
2992 RDeleter::operator()(objPtr, dtorOnly);
2998 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubFields[0]));
2999 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment());
3002std::vector<ROOT::Experimental::RFieldBase::RValue>
3005 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(
value.GetPtr<
void>().get());
3007 std::vector<RValue>
result;
3008 char *begin =
reinterpret_cast<char *
>(*beginPtr);
3009 result.reserve(*sizePtr);
3010 for (std::int32_t i = 0; i < *sizePtr; ++i) {
3011 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), begin + i * fItemSize)));
3023 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
3041 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
3042 auto count = typedValue->size();
3043 for (
unsigned i = 0; i < count; ++i) {
3044 bool bval = (*typedValue)[i];
3045 CallAppendOn(*fSubFields[0], &bval);
3048 fPrincipalColumn->Append(&fNWritten);
3049 return count + fPrincipalColumn->GetElement()->GetPackedSize();
3054 auto typedValue =
static_cast<std::vector<bool> *
>(to);
3057 RClusterIndex collectionStart;
3058 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
3060 typedValue->resize(nItems);
3061 for (
unsigned i = 0; i < nItems; ++i) {
3063 CallReadOn(*fSubFields[0], collectionStart + i, &bval);
3064 (*typedValue)[i] = bval;
3071 static RColumnRepresentations representations(
3074 return representations;
3079 GenerateColumnsImpl<ClusterSize_t>();
3084 GenerateColumnsImpl<ClusterSize_t>(desc);
3087std::vector<ROOT::Experimental::RFieldBase::RValue>
3090 const auto &typedValue =
value.GetRef<std::vector<bool>>();
3091 auto count = typedValue.size();
3092 std::vector<RValue>
result;
3094 for (
unsigned i = 0; i < count; ++i) {
3096 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
3098 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
3105 visitor.VisitVectorBoolField(*
this);
3111 std::size_t arrayLength)
3113 "std::array<" + itemField->GetTypeName() +
"," + std::to_string(arrayLength) +
">",
3115 fItemSize(itemField->GetValueSize()),
3116 fArrayLength(arrayLength)
3118 fTraits |= itemField->GetTraits() & ~kTraitMappable;
3119 Attach(std::move(itemField));
3122std::unique_ptr<ROOT::Experimental::RFieldBase>
3125 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3126 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
3131 std::size_t nbytes = 0;
3132 auto arrayPtr =
static_cast<const unsigned char *
>(from);
3133 for (
unsigned i = 0; i < fArrayLength; ++i) {
3134 nbytes += CallAppendOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3141 auto arrayPtr =
static_cast<unsigned char *
>(to);
3142 for (
unsigned i = 0; i < fArrayLength; ++i) {
3143 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
3149 auto arrayPtr =
static_cast<unsigned char *
>(to);
3150 for (
unsigned i = 0; i < fArrayLength; ++i) {
3152 arrayPtr + (i * fItemSize));
3158 if (fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)
3161 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
3162 for (
unsigned i = 0; i < fArrayLength; ++i) {
3163 CallConstructValueOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3170 for (
unsigned i = 0; i < fArrayLength; ++i) {
3171 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
3174 RDeleter::operator()(objPtr, dtorOnly);
3179 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible))
3180 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetDeleterOf(*fSubFields[0]));
3181 return std::make_unique<RDeleter>();
3184std::vector<ROOT::Experimental::RFieldBase::RValue>
3187 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3188 std::vector<RValue>
result;
3189 result.reserve(fArrayLength);
3190 for (
unsigned i = 0; i < fArrayLength; ++i) {
3192 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3206 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField,
3207 std::size_t arrayLength)
3208 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
3210 fItemSize(itemField->GetValueSize()),
3211 fArrayLength(arrayLength)
3213 Attach(std::move(itemField));
3219std::unique_ptr<ROOT::Experimental::RFieldBase>
3222 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3223 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
3229 void **beginPtr =
new (where)(
void *)(
nullptr);
3230 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
3231 std::int32_t *capacityPtr =
new (sizePtr + 1) std::int32_t(0);
3235 char *begin =
reinterpret_cast<char *
>(*beginPtr);
3238 if (*sizePtr == std::int32_t(fArrayLength))
3244 const bool owns = (*capacityPtr != -1);
3245 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
3246 const bool needsDestruct = owns && fItemDeleter;
3250 if (needsDestruct) {
3251 for (std::int32_t i = 0; i < *sizePtr; ++i) {
3252 fItemDeleter->operator()(begin + (i * fItemSize),
true );
3262 *beginPtr =
malloc(fArrayLength * fItemSize);
3265 begin =
reinterpret_cast<char *
>(*beginPtr);
3267 *sizePtr = fArrayLength;
3268 *capacityPtr = fArrayLength;
3271 if (needsConstruct) {
3272 for (std::size_t i = 0; i < fArrayLength; ++i)
3273 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
3280 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize,
3281 GetDeleterOf(*fSubFields[0]));
3283 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment());
3289 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3290 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3292 if (fSubFields[0]->IsSimple()) {
3293 GetPrincipalColumnOf(*fSubFields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, rvecBeginPtr);
3298 for (std::size_t i = 0; i < fArrayLength; ++i) {
3299 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, rvecBeginPtr + (i * fItemSize));
3305 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3306 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3309 const auto &clusterIndexIndex = clusterIndex.
GetIndex();
3311 if (fSubFields[0]->IsSimple()) {
3312 GetPrincipalColumnOf(*fSubFields[0])
3313 ->ReadV(
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength), fArrayLength, rvecBeginPtr);
3318 for (std::size_t i = 0; i < fArrayLength; ++i) {
3319 CallReadOn(*fSubFields[0],
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength + i),
3320 rvecBeginPtr + (i * fItemSize));
3326 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
3329std::vector<ROOT::Experimental::RFieldBase::RValue>
3332 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3333 std::vector<ROOT::Experimental::RFieldBase::RValue>
result;
3334 result.reserve(fArrayLength);
3335 for (
unsigned i = 0; i < fArrayLength; ++i) {
3337 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3364 return representations;
3369 GenerateColumnsImpl<bool>();
3374 GenerateColumnsImpl<bool>(desc);
3379 const auto *asULongArray =
static_cast<const Word_t *
>(from);
3382 for (std::size_t word = 0; word < (fN + kBitsPerWord - 1) / kBitsPerWord; ++word) {
3383 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < fN); ++
mask, ++i) {
3384 elementValue = (asULongArray[word] & (
static_cast<Word_t>(1) <<
mask)) != 0;
3385 fPrincipalColumn->Append(&elementValue);
3393 auto *asULongArray =
static_cast<Word_t *
>(to);
3395 for (std::size_t i = 0; i < fN; ++i) {
3396 fPrincipalColumn->Read(globalIndex * fN + i, &elementValue);
3398 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
3399 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
3405 auto *asULongArray =
static_cast<Word_t *
>(to);
3407 for (std::size_t i = 0; i < fN; ++i) {
3411 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
3412 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
3426 for (
size_t i = 0; i < itemFields.size(); ++i) {
3427 result += itemFields[i]->GetTypeName() +
",";
3436 fMaxItemSize(source.fMaxItemSize),
3437 fMaxAlignment(source.fMaxAlignment),
3438 fTagOffset(source.fTagOffset),
3439 fVariantOffset(source.fVariantOffset),
3440 fNWritten(source.fNWritten.
size(), 0)
3443 Attach(
f->Clone(
f->GetFieldName()));
3448 std::vector<std::unique_ptr<RFieldBase>> itemFields)
3449 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields) +
">",
3455 auto nFields = itemFields.size();
3460 for (
unsigned int i = 0; i < nFields; ++i) {
3463 fTraits &= itemFields[i]->GetTraits();
3464 Attach(std::move(itemFields[i]));
3475 const auto tagSize = GetVariantTagSize();
3476 const auto padding = tagSize - (
fMaxItemSize % tagSize);
3480std::unique_ptr<ROOT::Experimental::RFieldBase>
3483 return std::unique_ptr<RVariantField>(
new RVariantField(newName, *
this));
3488 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3489 auto tag = *
reinterpret_cast<const TagType_t *
>(
reinterpret_cast<const unsigned char *
>(variantPtr) + tagOffset);
3490 return (tag == TagType_t(-1)) ? 0 : tag + 1;
3495 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3496 auto tagPtr =
reinterpret_cast<TagType_t *
>(
reinterpret_cast<unsigned char *
>(variantPtr) + tagOffset);
3497 *tagPtr = (tag == 0) ? TagType_t(-1) :
static_cast<TagType_t
>(tag - 1);
3502 auto tag = GetTag(from, fTagOffset);
3503 std::size_t nbytes = 0;
3506 nbytes += CallAppendOn(*fSubFields[tag - 1],
reinterpret_cast<const unsigned char *
>(from) + fVariantOffset);
3507 index = fNWritten[tag - 1]++;
3510 fPrincipalColumn->Append(&varSwitch);
3518 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
3525 void *varPtr =
reinterpret_cast<unsigned char *
>(to) + fVariantOffset;
3526 CallConstructValueOn(*fSubFields[tag - 1], varPtr);
3527 CallReadOn(*fSubFields[tag - 1], variantIndex, varPtr);
3529 SetTag(to, fTagOffset, tag);
3536 return representations;
3541 GenerateColumnsImpl<RColumnSwitch>();
3546 GenerateColumnsImpl<RColumnSwitch>(desc);
3551 memset(where, 0, GetValueSize());
3552 CallConstructValueOn(*fSubFields[0],
reinterpret_cast<unsigned char *
>(where) + fVariantOffset);
3553 SetTag(where, fTagOffset, 1);
3558 auto tag = GetTag(objPtr, fTagOffset);
3560 fItemDeleters[tag - 1]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fVariantOffset,
true );
3562 RDeleter::operator()(objPtr, dtorOnly);
3567 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
3568 itemDeleters.reserve(fSubFields.size());
3569 for (
const auto &
f : fSubFields) {
3570 itemDeleters.emplace_back(GetDeleterOf(*
f));
3572 return std::make_unique<RVariantDeleter>(fTagOffset, fVariantOffset, std::move(itemDeleters));
3577 return std::max(fMaxAlignment,
alignof(RVariantTag<GetVariantTagSize()>::ValueType_t));
3583 const auto actualSize = fTagOffset + GetVariantTagSize();
3585 return actualSize + ((padding ==
alignment) ? 0 : padding);
3590 std::fill(fNWritten.begin(), fNWritten.end(), 0);
3596 std::unique_ptr<RFieldBase> itemField)
3604 std::unique_ptr<RFieldBase> itemField)
3607 if (!
dynamic_cast<RPairField *
>(itemField.get()))
3610 auto *itemClass =
fProxy->GetValueClass();
3613 Attach(std::move(itemField));
3619 std::unique_ptr<RFieldBase> itemField)
3622 Attach(std::move(itemField));
3631 return representations;
3636 GenerateColumnsImpl<ClusterSize_t>();
3641 GenerateColumnsImpl<ClusterSize_t>(desc);
3646 fPrincipalColumn->Append(&fNWritten);
3652 auto nbytesItem = CallAppendOn(*fSubFields[0], from);
3654 fPrincipalColumn->Append(&fNWritten);
3662 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
3663 return (collectionSize == 0) ?
RClusterIndex() : collectionStart;
3674 std::unique_ptr<RFieldBase> itemField)
3675 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3679std::unique_ptr<ROOT::Experimental::RFieldBase>
3682 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3683 return std::make_unique<RUniquePtrField>(newName, GetTypeName(), std::move(newItemField));
3688 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
3690 return AppendValue(typedValue->get());
3692 return AppendNull();
3698 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
3699 bool isValidValue =
static_cast<bool>(*ptr);
3701 auto itemIndex = GetItemIndex(globalIndex);
3704 void *valuePtr =
nullptr;
3706 valuePtr = ptr->get();
3708 if (isValidValue && !isValidItem) {
3710 fItemDeleter->operator()(valuePtr,
false );
3717 if (!isValidValue) {
3718 valuePtr = CallCreateObjectRawPtrOn(*fSubFields[0]);
3719 ptr->reset(
reinterpret_cast<char *
>(valuePtr));
3722 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3727 auto typedPtr =
static_cast<std::unique_ptr<char> *
>(objPtr);
3729 fItemDeleter->operator()(typedPtr->get(),
false );
3730 typedPtr->release();
3732 RDeleter::operator()(objPtr, dtorOnly);
3737 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubFields[0]));
3740std::vector<ROOT::Experimental::RFieldBase::RValue>
3743 std::vector<RValue>
result;
3744 const auto &ptr =
value.GetRef<std::unique_ptr<char>>();
3746 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr.get())));
3754 std::unique_ptr<RFieldBase> itemField)
3755 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3763 void *
value = optionalPtr;
3765 reinterpret_cast<bool *
>(
reinterpret_cast<unsigned char *
>(optionalPtr) + fSubFields[0]->GetValueSize());
3766 return {
value, engagement};
3769std::pair<const void *, const bool *>
3772 return GetValueAndEngagementPtrs(
const_cast<void *
>(optionalPtr));
3775std::unique_ptr<ROOT::Experimental::RFieldBase>
3778 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3779 return std::make_unique<ROptionalField>(newName, GetTypeName(), std::move(newItemField));
3784 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(from);
3785 if (*engagementPtr) {
3786 return AppendValue(valuePtr);
3788 return AppendNull();
3794 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(to);
3795 auto itemIndex = GetItemIndex(globalIndex);
3797 *engagementPtr =
false;
3799 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3800 *engagementPtr =
true;
3806 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(where);
3807 CallConstructValueOn(*fSubFields[0], valuePtr);
3808 *engagementPtr =
false;
3813 fItemDeleter->operator()(objPtr,
true );
3814 RDeleter::operator()(objPtr, dtorOnly);
3819 return std::make_unique<ROptionalDeleter>(GetDeleterOf(*fSubFields[0]));
3822std::vector<ROOT::Experimental::RFieldBase::RValue>
3825 std::vector<RValue>
result;
3826 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(
value.GetPtr<
void>().get());
3827 if (*engagementPtr) {
3828 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), valuePtr)));
3837 const auto actualSize = fSubFields[0]->GetValueSize() +
sizeof(
bool);
3840 auto remainder = actualSize %
alignment;
3844 return actualSize + padding;
3849 return fSubFields[0]->GetAlignment();
3855ROOT::Experimental::RPairField::RPairField::GetTypeList(
const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3857 return itemFields[0]->GetTypeName() +
"," + itemFields[1]->GetTypeName();
3861 std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
3862 const std::array<std::size_t, 2> &offsets)
3863 :
ROOT::Experimental::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields) +
">")
3871 std::array<std::unique_ptr<RFieldBase>, 2> itemFields)
3872 :
ROOT::Experimental::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields) +
">")
3882 auto firstElem =
c->GetRealData(
"first");
3885 fOffsets.push_back(firstElem->GetThisOffset());
3887 auto secondElem =
c->GetRealData(
"second");
3890 fOffsets.push_back(secondElem->GetThisOffset());
3896ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3899 if (itemFields.empty())
3900 throw RException(
R__FAIL(
"the type list for std::tuple must have at least one element"));
3901 for (
size_t i = 0; i < itemFields.size(); ++i) {
3902 result += itemFields[i]->GetTypeName() +
",";
3909 std::vector<std::unique_ptr<RFieldBase>> itemFields,
3910 const std::vector<std::size_t> &offsets)
3911 :
ROOT::Experimental::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields) +
">")
3918 std::vector<std::unique_ptr<RFieldBase>> itemFields)
3919 :
ROOT::Experimental::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields) +
">")
3933 for (
unsigned i = 0; i <
fSubFields.size(); ++i) {
3934 std::string memberName(
"_" + std::to_string(i));
3935 auto member =
c->GetRealData(memberName.c_str());
3938 fOffsets.push_back(member->GetThisOffset());
3945 std::unique_ptr<RFieldBase> itemField)
3952 Attach(std::move(itemField));
3955std::unique_ptr<ROOT::Experimental::RFieldBase>
3958 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3959 return std::make_unique<RAtomicField>(newName, GetTypeName(), std::move(newItemField));
3962std::vector<ROOT::Experimental::RFieldBase::RValue>
3965 std::vector<RValue>
result;
3966 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 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 VisitStreamerField(const RStreamerField &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 const char * GetColumnTypeName(EColumnType type)
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.
void ConstructValue(void *where) const final
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 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
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
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
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 ...
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
void operator()(void *objPtr, bool dtorOnly) final
The field for a class with dictionary.
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
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.
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 ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
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, const RClassField &source)
Used by CloneImpl.
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.
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
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.
RFieldBase * fParent
Sub fields point to their mother field.
void FlushColumns()
Flushes data from active columns.
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias, bool continueOnError=false)
Factory method to resurrect a field from the stored on-disk type information.
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
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)
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 final
Called by Clone(), which additionally copies the on-disk ID.
Classes with dictionaries that can be inspected by TClass.
RField(std::string_view name)
Used in RFieldBase::Check() to record field creation failures.
RMapField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
The on-storage meta-data of an ntuple.
RColumnDescriptorIterable GetColumnIterable() const
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) 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.
Template specializations for C++ std::pair.
RPairField(std::string_view fieldName, std::array< std::unique_ptr< RFieldBase >, 2 > itemFields, const std::array< std::size_t, 2 > &offsets)
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.
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
std::size_t AppendImpl(const void *from) final
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 final
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
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....
std::unique_ptr< RDeleter > GetDeleter() const final
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void operator()(void *objPtr, bool dtorOnly) final
std::unique_ptr< RDeleter > fItemDeleter
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
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
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 GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
size_t GetAlignment() const final
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 ...
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::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void operator()(void *objPtr, bool dtorOnly) final
The field for an untyped record.
std::size_t fMaxAlignment
std::vector< std::size_t > fOffsets
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadInClusterImpl(RClusterIndex clusterIndex, void *to) final
RRecordField(std::string_view name, const RRecordField &source)
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::unique_ptr< RDeleter > GetDeleter() const final
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 final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void AttachItemFields(std::vector< std::unique_ptr< RFieldBase > > itemFields)
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)
void operator()(void *objPtr, bool dtorOnly) final
The field for a class using ROOT standard streaming.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
RStreamerField(std::string_view fieldName, std::string_view className, TClass *classp)
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
RExtraTypeInfoDescriptor GetExtraTypeInfo() const final
RTupleField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, const std::vector< std::size_t > &offsets)
void operator()(void *objPtr, bool dtorOnly) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
std::unique_ptr< RDeleter > GetDeleter() const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::variant.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
static void SetTag(void *variantPtr, std::size_t tagOffset, std::uint8_t tag)
static std::string GetTypeList(const std::vector< std::unique_ptr< RFieldBase > > &itemFields)
std::vector< ClusterSize_t::ValueType > fNWritten
size_t fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void CommitClusterImpl() final
static constexpr std::size_t kMaxVariants
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
static std::uint8_t GetTag(const void *variantPtr, std::size_t tagOffset)
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
RVariantField(std::string_view name, const RVariantField &source)
size_t fVariantOffset
In the std::variant memory layout, the actual union of types may start at an offset > 0.
std::unique_ptr< RDeleter > GetDeleter() const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::vector.
static std::unique_ptr< RVectorField > CreateUntyped(std::string_view fieldName, 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.
std::unique_ptr< RDeleter > fItemDeleter
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponsing to the field type ...
std::unique_ptr< RDeleter > GetDeleter() const final
RVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, bool isUntyped)
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
void TagStreamerInfo(TVirtualStreamerInfo *info) override
Mark the classindex of the current file as using this TStreamerInfo.
TClass instances represent classes, structs and namespaces in the ROOT type system.
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Int_t Size() const
Return size of object of this class.
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Version_t GetClassVersion() const
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
All ROOT classes may have RTTI (run time type identification) support added.
Longptr_t GetOffset() const
Get offset from "this".
TDictAttributeMap * GetAttributeMap() const
The TEnum class implements the enum type.
EDataType GetUnderlyingType() const
Get the underlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Mother of all ROOT objects.
@ kIsOnHeap
object is on heap
@ kNotDeleted
object has not been deleted
@ kIsReferenced
if object is referenced by a TRef or TRefArray
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
@ kNeedDelete
The collection contains directly or indirectly (via other collection) some pointers that need explici...
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
Return a pointer to a function that can advance an iterator (see Next_t).
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual TVirtualCollectionProxy * Generate() const =0
Returns a clean object of the actual class that derives from TVirtualCollectionProxy.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Return a pointer to a function that can create an iterator pair, where each iterator points to the be...
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Abstract Interface class describing Streamer information for one class.
virtual Int_t GetNumber() const =0
RResult< void > EnsureValidNameForRNTuple(std::string_view name, std::string_view where)
Check whether a given string is a valid name according to the RNTuple specification.
auto MakeAliasedSharedPtr(T *rawPtr)
void CallConnectPageSinkOnField(RFieldBase &, RPageSink &, NTupleSize_t firstEntry=0)
void CallFlushColumnsOnField(RFieldBase &)
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
void CallCommitClusterOnField(RFieldBase &)
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RClusterSize ClusterSize_t
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr ClusterSize_t kInvalidClusterIndex(std::uint64_t(-1))
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
constexpr DescriptorId_t kInvalidDescriptorId
void(off) SmallVectorTemplateBase< T
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=nullptr)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
std::size_t fCount
Size of the bulk range.
RClusterIndex fFirstIndex
Start of the bulk range.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
Used in the return value of the Check() method.
std::default_delete< T > deleter
TVirtualCollectionProxy::Next_t fNext
TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators
TVirtualCollectionProxy::CreateIterators_t fCreateIterators