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)
572 std::string
result = GetFieldName();
573 auto parent = GetParent();
574 while (parent && !parent->GetFieldName().empty()) {
576 parent = parent->GetParent();
584 auto typeAlias = GetNormalizedTypeName(typeName);
585 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
589std::vector<ROOT::Experimental::RFieldBase::RCheckResult>
592 auto typeAlias = GetNormalizedTypeName(typeName);
593 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
598 std::vector<RCheckResult>
result;
599 for (
const auto &
f : fieldZero) {
605 RCheckResult{invalidField->GetQualifiedFieldName(), invalidField->GetTypeName(), invalidField->GetError()});
612 const std::string &typeAlias,
bool continueOnError)
614 thread_local CreateContext createContext;
615 CreateContextGuard createContextGuard(createContext);
617 createContextGuard.SetContinueOnError(
true);
619 auto fnFail = [&fieldName, &canonicalType](
const std::string &errMsg) ->
RResult<std::unique_ptr<RFieldBase>> {
620 if (createContext.GetContinueOnError()) {
621 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, canonicalType, errMsg));
627 if (canonicalType.empty())
628 return R__FORWARD_RESULT(fnFail(
"no type name specified for field '" + fieldName +
"'"));
630 std::unique_ptr<ROOT::Experimental::RFieldBase>
result;
635 if (
auto [arrayBaseType, arraySizes] = ParseArrayType(canonicalType); !arraySizes.empty()) {
636 std::unique_ptr<RFieldBase> arrayField = Create(
"_0", arrayBaseType).Unwrap();
637 for (
int i = arraySizes.size() - 1; i >= 0; --i) {
639 std::make_unique<RArrayField>((i == 0) ? fieldName :
"_0", std::move(arrayField), arraySizes[i]);
644 if (canonicalType ==
"bool") {
645 result = std::make_unique<RField<bool>>(fieldName);
646 }
else if (canonicalType ==
"char") {
647 result = std::make_unique<RField<char>>(fieldName);
648 }
else if (canonicalType ==
"signed char") {
649 result = std::make_unique<RField<signed char>>(fieldName);
650 }
else if (canonicalType ==
"unsigned char") {
651 result = std::make_unique<RField<unsigned char>>(fieldName);
652 }
else if (canonicalType ==
"short") {
653 result = std::make_unique<RField<short>>(fieldName);
654 }
else if (canonicalType ==
"unsigned short") {
655 result = std::make_unique<RField<unsigned short>>(fieldName);
656 }
else if (canonicalType ==
"int") {
657 result = std::make_unique<RField<int>>(fieldName);
658 }
else if (canonicalType ==
"unsigned int") {
659 result = std::make_unique<RField<unsigned int>>(fieldName);
660 }
else if (canonicalType ==
"long") {
661 result = std::make_unique<RField<long>>(fieldName);
662 }
else if (canonicalType ==
"unsigned long") {
663 result = std::make_unique<RField<unsigned long>>(fieldName);
664 }
else if (canonicalType ==
"long long") {
665 result = std::make_unique<RField<long long>>(fieldName);
666 }
else if (canonicalType ==
"unsigned long long") {
667 result = std::make_unique<RField<unsigned long long>>(fieldName);
668 }
else if (canonicalType ==
"std::byte") {
669 result = std::make_unique<RField<std::byte>>(fieldName);
670 }
else if (canonicalType ==
"std::int8_t") {
671 result = std::make_unique<RField<std::int8_t>>(fieldName);
672 }
else if (canonicalType ==
"std::uint8_t") {
673 result = std::make_unique<RField<std::uint8_t>>(fieldName);
674 }
else if (canonicalType ==
"std::int16_t") {
675 result = std::make_unique<RField<std::int16_t>>(fieldName);
676 }
else if (canonicalType ==
"std::uint16_t") {
677 result = std::make_unique<RField<std::uint16_t>>(fieldName);
678 }
else if (canonicalType ==
"std::int32_t") {
679 result = std::make_unique<RField<std::int32_t>>(fieldName);
680 }
else if (canonicalType ==
"std::uint32_t") {
681 result = std::make_unique<RField<std::uint32_t>>(fieldName);
682 }
else if (canonicalType ==
"std::int64_t") {
683 result = std::make_unique<RField<std::int64_t>>(fieldName);
684 }
else if (canonicalType ==
"std::uint64_t") {
685 result = std::make_unique<RField<std::uint64_t>>(fieldName);
686 }
else if (canonicalType ==
"float") {
687 result = std::make_unique<RField<float>>(fieldName);
688 }
else if (canonicalType ==
"double") {
689 result = std::make_unique<RField<double>>(fieldName);
690 }
else if (canonicalType ==
"Double32_t") {
691 result = std::make_unique<RField<double>>(fieldName);
695 }
else if (canonicalType ==
"std::string") {
696 result = std::make_unique<RField<std::string>>(fieldName);
697 }
else if (canonicalType ==
"TObject") {
698 result = std::make_unique<RField<TObject>>(fieldName);
699 }
else if (canonicalType ==
"std::vector<bool>") {
700 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
701 }
else if (canonicalType.substr(0, 12) ==
"std::vector<") {
702 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
703 auto itemField = Create(
"_0", itemTypeName);
704 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
705 }
else if (canonicalType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
706 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
707 auto itemField = Create(
"_0", itemTypeName);
708 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
709 }
else if (canonicalType.substr(0, 11) ==
"std::array<") {
710 auto arrayDef = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
711 if (arrayDef.size() != 2) {
712 return R__FORWARD_RESULT(fnFail(
"the template list for std::array must have exactly two elements"));
714 auto arrayLength = std::stoi(arrayDef[1]);
715 auto itemField = Create(
"_0", arrayDef[0]);
716 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
717 }
else if (canonicalType.substr(0, 13) ==
"std::variant<") {
718 auto innerTypes = TokenizeTypeList(canonicalType.substr(13, canonicalType.length() - 14));
719 std::vector<std::unique_ptr<RFieldBase>> items;
720 items.reserve(innerTypes.size());
721 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
722 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
724 result = std::make_unique<RVariantField>(fieldName, std::move(items));
725 }
else if (canonicalType.substr(0, 10) ==
"std::pair<") {
726 auto innerTypes = TokenizeTypeList(canonicalType.substr(10, canonicalType.length() - 11));
727 if (innerTypes.size() != 2) {
728 return R__FORWARD_RESULT(fnFail(
"the type list for std::pair must have exactly two elements"));
730 std::array<std::unique_ptr<RFieldBase>, 2> items{Create(
"_0", innerTypes[0]).Unwrap(),
731 Create(
"_1", innerTypes[1]).Unwrap()};
732 result = std::make_unique<RPairField>(fieldName, std::move(items));
733 }
else if (canonicalType.substr(0, 11) ==
"std::tuple<") {
734 auto innerTypes = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
735 std::vector<std::unique_ptr<RFieldBase>> items;
736 items.reserve(innerTypes.size());
737 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
738 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
740 result = std::make_unique<RTupleField>(fieldName, std::move(items));
741 }
else if (canonicalType.substr(0, 12) ==
"std::bitset<") {
742 auto size = std::stoull(canonicalType.substr(12, canonicalType.length() - 13));
743 result = std::make_unique<RBitsetField>(fieldName,
size);
744 }
else if (canonicalType.substr(0, 16) ==
"std::unique_ptr<") {
745 std::string itemTypeName = canonicalType.substr(16, canonicalType.length() - 17);
746 auto itemField = Create(
"_0", itemTypeName).Unwrap();
747 auto normalizedInnerTypeName = itemField->GetTypeName();
748 result = std::make_unique<RUniquePtrField>(fieldName,
"std::unique_ptr<" + normalizedInnerTypeName +
">",
749 std::move(itemField));
750 }
else if (canonicalType.substr(0, 14) ==
"std::optional<") {
751 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
752 auto itemField = Create(
"_0", itemTypeName).Unwrap();
753 auto normalizedInnerTypeName = itemField->GetTypeName();
754 result = std::make_unique<ROptionalField>(fieldName,
"std::optional<" + normalizedInnerTypeName +
">",
755 std::move(itemField));
756 }
else if (canonicalType.substr(0, 9) ==
"std::set<") {
757 std::string itemTypeName = canonicalType.substr(9, canonicalType.length() - 10);
758 auto itemField = Create(
"_0", itemTypeName).Unwrap();
759 auto normalizedInnerTypeName = itemField->GetTypeName();
761 std::make_unique<RSetField>(fieldName,
"std::set<" + normalizedInnerTypeName +
">", std::move(itemField));
762 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_set<") {
763 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
764 auto itemField = Create(
"_0", itemTypeName).Unwrap();
765 auto normalizedInnerTypeName = itemField->GetTypeName();
766 result = std::make_unique<RSetField>(fieldName,
"std::unordered_set<" + normalizedInnerTypeName +
">",
767 std::move(itemField));
768 }
else if (canonicalType.substr(0, 14) ==
"std::multiset<") {
769 std::string itemTypeName = canonicalType.substr(14, canonicalType.length() - 15);
770 auto itemField = Create(
"_0", itemTypeName).Unwrap();
771 auto normalizedInnerTypeName = itemField->GetTypeName();
772 result = std::make_unique<RSetField>(fieldName,
"std::multiset<" + normalizedInnerTypeName +
">",
773 std::move(itemField));
774 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multiset<") {
775 std::string itemTypeName = canonicalType.substr(24, canonicalType.length() - 25);
776 auto itemField = Create(
"_0", itemTypeName).Unwrap();
777 auto normalizedInnerTypeName = itemField->GetTypeName();
778 result = std::make_unique<RSetField>(fieldName,
"std::unordered_multiset<" + normalizedInnerTypeName +
">",
779 std::move(itemField));
780 }
else if (canonicalType.substr(0, 9) ==
"std::map<") {
781 auto innerTypes = TokenizeTypeList(canonicalType.substr(9, canonicalType.length() - 10));
782 if (innerTypes.size() != 2) {
783 return R__FORWARD_RESULT(fnFail(
"the type list for std::map must have exactly two elements"));
786 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
790 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
791 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
793 result = std::make_unique<RMapField>(fieldName,
"std::map<" + keyTypeName +
"," + valueTypeName +
">",
794 std::move(itemField));
795 }
else if (canonicalType.substr(0, 19) ==
"std::unordered_map<") {
796 auto innerTypes = TokenizeTypeList(canonicalType.substr(19, canonicalType.length() - 20));
797 if (innerTypes.size() != 2)
798 return R__FORWARD_RESULT(fnFail(
"the type list for std::unordered_map must have exactly two elements"));
800 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
804 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
805 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
807 result = std::make_unique<RMapField>(
808 fieldName,
"std::unordered_map<" + keyTypeName +
"," + valueTypeName +
">", std::move(itemField));
809 }
else if (canonicalType.substr(0, 14) ==
"std::multimap<") {
810 auto innerTypes = TokenizeTypeList(canonicalType.substr(14, canonicalType.length() - 15));
811 if (innerTypes.size() != 2)
812 return R__FORWARD_RESULT(fnFail(
"the type list for std::multimap must have exactly two elements"));
814 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
818 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
819 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
821 result = std::make_unique<RMapField>(fieldName,
"std::multimap<" + keyTypeName +
"," + valueTypeName +
">",
822 std::move(itemField));
823 }
else if (canonicalType.substr(0, 24) ==
"std::unordered_multimap<") {
824 auto innerTypes = TokenizeTypeList(canonicalType.substr(24, canonicalType.length() - 25));
825 if (innerTypes.size() != 2)
827 fnFail(
"the type list for std::unordered_multimap must have exactly two elements"));
829 auto itemField = Create(
"_0",
"std::pair<" + innerTypes[0] +
"," + innerTypes[1] +
">").Unwrap();
833 auto keyTypeName = itemField->GetSubFields()[0]->GetTypeName();
834 auto valueTypeName = itemField->GetSubFields()[1]->GetTypeName();
836 result = std::make_unique<RMapField>(
837 fieldName,
"std::unordered_multimap<" + keyTypeName +
"," + valueTypeName +
">", std::move(itemField));
838 }
else if (canonicalType.substr(0, 12) ==
"std::atomic<") {
839 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
840 auto itemField = Create(
"_0", itemTypeName).Unwrap();
841 auto normalizedInnerTypeName = itemField->GetTypeName();
842 result = std::make_unique<RAtomicField>(fieldName,
"std::atomic<" + normalizedInnerTypeName +
">",
843 std::move(itemField));
844 }
else if (canonicalType.substr(0, 25) ==
"ROOT::RNTupleCardinality<") {
845 auto innerTypes = TokenizeTypeList(canonicalType.substr(25, canonicalType.length() - 26));
846 if (innerTypes.size() != 1)
847 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
848 if (innerTypes[0] ==
"std::uint32_t") {
849 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
850 }
else if (innerTypes[0] ==
"std::uint64_t") {
851 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
853 return R__FORWARD_RESULT(fnFail(
"invalid cardinality template: " + canonicalType));
860 result = std::make_unique<REnumField>(fieldName, canonicalType);
867 createContextGuard.AddClassToStack(canonicalType);
869 result = std::make_unique<RProxiedCollectionField>(fieldName, canonicalType);
871 if (GetRNTupleSerializationMode(cl) == ERNTupleSerializationMode::kForceStreamerMode) {
872 result = std::make_unique<RStreamerField>(fieldName, canonicalType);
874 result = std::make_unique<RClassField>(fieldName, canonicalType);
880 auto error =
e.GetError();
881 if (createContext.GetContinueOnError()) {
882 return std::unique_ptr<RFieldBase>(
883 std::make_unique<RInvalidField>(fieldName, canonicalType, error.GetReport()));
890 if (typeAlias != canonicalType)
891 result->fTypeAlias = typeAlias;
899 if (fieldName.empty()) {
900 return R__FAIL(
"name cannot be empty string \"\"");
901 }
else if (fieldName.find(
'.') != std::string::npos) {
902 return R__FAIL(
"name '" + std::string(fieldName) +
"' cannot contain dot characters '.'");
911 return representations;
916 auto clone = CloneImpl(newName);
917 clone->fTypeAlias = fTypeAlias;
918 clone->fOnDiskId = fOnDiskId;
919 clone->fDescription = fDescription;
921 clone->fColumnRepresentatives = fColumnRepresentatives;
927 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
938 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(clusterIndex), to);
943 const auto valueSize = GetValueSize();
944 std::size_t nRead = 0;
945 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
954 Read(bulkSpec.
fFirstIndex + i,
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + i * valueSize);
963 void *where =
operator new(GetValueSize());
965 ConstructValue(where);
971 void *obj = CreateObjectRawPtr();
975std::vector<ROOT::Experimental::RFieldBase::RValue>
978 return std::vector<RValue>();
985 if (fState != EState::kUnconnected)
986 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
987 child->fParent =
this;
988 fSubFields.emplace_back(std::move(
child));
994 std::size_t
result = globalIndex;
995 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
996 auto parent =
f->GetParent();
997 if (parent && (parent->GetStructure() ==
kCollection || parent->GetStructure() ==
kVariant))
999 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
1006 std::vector<RFieldBase *>
result;
1007 result.reserve(fSubFields.size());
1008 for (
const auto &
f : fSubFields) {
1016 std::vector<const RFieldBase *>
result;
1017 result.reserve(fSubFields.size());
1018 for (
const auto &
f : fSubFields) {
1026 if (!fAvailableColumns.empty()) {
1027 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1028 for (
auto &column : fAvailableColumns) {
1029 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1038 if (!fAvailableColumns.empty()) {
1039 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
1040 for (
auto &column : fAvailableColumns) {
1041 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
1044 column->CommitSuppressed();
1048 CommitClusterImpl();
1053 if (fState != EState::kUnconnected)
1054 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
1055 fDescription = std::string(description);
1060 if (fState != EState::kUnconnected)
1069 if (~fTraits & kTraitMappable)
1070 return AppendImpl(from);
1072 fPrincipalColumn->Append(from);
1073 return fPrincipalColumn->GetElement()->GetPackedSize();
1083 return RValue(
this, objPtr);
1092 return RBulkSpec::kAllSet;
1095 return ReadBulkImpl(bulkSpec);
1131 if (fColumnRepresentatives.empty()) {
1132 return {GetColumnRepresentations().GetSerializationDefault()};
1136 result.reserve(fColumnRepresentatives.size());
1137 for (
const auto &
r : fColumnRepresentatives) {
1146 if (fState != EState::kUnconnected)
1147 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
1148 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
1149 fColumnRepresentatives.clear();
1150 fColumnRepresentatives.reserve(representatives.size());
1151 for (
const auto &
r : representatives) {
1152 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(),
r);
1153 if (itRepresentative == std::end(validTypes))
1155 fColumnRepresentatives.emplace_back(*itRepresentative);
1161 std::uint16_t representationIndex)
const
1166 throw RException(
R__FAIL(
"No on-disk field information for `" + GetQualifiedFieldName() +
"`"));
1170 if (
c.GetRepresentationIndex() == representationIndex)
1171 onDiskTypes.emplace_back(
c.GetType());
1173 if (onDiskTypes.empty()) {
1174 if (representationIndex == 0) {
1175 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
1180 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1181 if (t == onDiskTypes)
1185 std::string columnTypeNames;
1186 for (
const auto &t : onDiskTypes) {
1187 if (!columnTypeNames.empty())
1188 columnTypeNames +=
", ";
1191 throw RException(
R__FAIL(
"On-disk column types {" + columnTypeNames +
"} for field `" + GetQualifiedFieldName() +
1192 "` cannot be matched to its in-memory type `" + GetTypeName() +
"` " +
1193 "(representation index: " + std::to_string(representationIndex) +
")"));
1198 fReadCallbacks.push_back(func);
1200 return fReadCallbacks.size() - 1;
1205 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
1206 fIsSimple = (fTraits & kTraitMappable) && fReadCallbacks.empty();
1211 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
1213 for (
auto &colType : rep) {
1228 SetColumnRepresentatives({rep});
1231 if (fTypeAlias ==
"Double32_t")
1238 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page sink"));
1239 if (fState != EState::kUnconnected)
1240 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
1245 for (
auto &column : fAvailableColumns) {
1249 auto firstElementIndex = (column->GetIndex() == 0) ? EntryToColumnElementIndex(firstEntry) : 0;
1250 column->ConnectPageSink(fOnDiskId, pageSink, firstElementIndex);
1253 if (HasExtraTypeInfo()) {
1258 fState = EState::kConnectedToSink;
1264 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
1265 if (fState != EState::kUnconnected)
1266 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
1268 if (!fColumnRepresentatives.empty())
1269 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
1270 if (!fDescription.empty())
1271 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
1273 for (
auto &
f : fSubFields) {
1277 f->ConnectPageSource(pageSource);
1283 GenerateColumns(desc);
1284 if (fColumnRepresentatives.empty()) {
1286 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1288 fColumnRepresentatives = {t};
1293 R__ASSERT(!fColumnRepresentatives.empty());
1297 if (fieldDesc.GetTypeChecksum().has_value())
1298 fOnDiskTypeChecksum = *fieldDesc.GetTypeChecksum();
1301 for (
auto &column : fAvailableColumns)
1302 column->ConnectPageSource(fOnDiskId, pageSource);
1303 OnConnectPageSource();
1305 fState = EState::kConnectedToSource;
1315std::unique_ptr<ROOT::Experimental::RFieldBase>
1318 auto result = std::make_unique<RFieldZero>();
1319 for (
auto &
f : fSubFields)
1320 result->Attach(
f->Clone(
f->GetFieldName()));
1337 return representations;
1342 GenerateColumnsImpl<ClusterSize_t>(desc);
1384 return representations;
1400 return representations;
1405 visitor.VisitByteField(*
this);
1430 return representations;
1435 visitor.VisitInt8Field(*
this);
1460 return representations;
1465 visitor.VisitUInt8Field(*
this);
1490 return representations;
1511 return representations;
1534 return representations;
1544 fTypeAlias =
"Double32_t";
1569 return representations;
1574 visitor.VisitInt16Field(*
this);
1599 return representations;
1604 visitor.VisitUInt16Field(*
this);
1629 return representations;
1634 visitor.VisitInt32Field(*
this);
1659 return representations;
1664 visitor.VisitUInt32Field(*
this);
1689 return representations;
1694 visitor.VisitUInt64Field(*
this);
1719 return representations;
1724 visitor.VisitInt64Field(*
this);
1737 return representations;
1742 GenerateColumnsImpl<ClusterSize_t, char>();
1747 GenerateColumnsImpl<ClusterSize_t, char>(desc);
1752 auto typedValue =
static_cast<const std::string *
>(from);
1753 auto length = typedValue->length();
1754 fAuxiliaryColumn->AppendV(typedValue->data(),
length);
1756 fPrincipalColumn->Append(&fIndex);
1757 return length + fPrincipalColumn->GetElement()->GetPackedSize();
1762 auto typedValue =
static_cast<std::string *
>(to);
1763 RClusterIndex collectionStart;
1765 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
1767 typedValue->clear();
1769 typedValue->resize(nChars);
1770 fAuxiliaryColumn->ReadV(collectionStart, nChars,
const_cast<char *
>(typedValue->data()));
1776 visitor.VisitStringField(*
this);
1784 fSubFieldsInfo(source.fSubFieldsInfo),
1785 fMaxAlignment(source.fMaxAlignment)
1803 throw RException(
R__FAIL(
"RField: no I/O support for type " + std::string(className)));
1809 if (className ==
"TObject") {
1814 R__FAIL(std::string(className) +
" has an associated collection proxy; use RProxiedCollectionField instead"));
1819 GetRNTupleSerializationMode(
fClass) != ERNTupleSerializationMode::kForceNativeMode) {
1820 throw RException(
R__FAIL(std::string(className) +
" cannot be stored natively in RNTuple"));
1822 if (GetRNTupleSerializationMode(
fClass) == ERNTupleSerializationMode::kForceStreamerMode) {
1824 R__FAIL(std::string(className) +
" has streamer mode enforced, not supported as native RNTuple class"));
1834 if (baseClass->GetDelta() < 0) {
1835 throw RException(
R__FAIL(std::string(
"virtual inheritance is not supported: ") + std::string(className) +
1836 " virtually inherits from " + baseClass->GetName()));
1838 TClass *
c = baseClass->GetClassPointer();
1841 fTraits &= subField->GetTraits();
1850 if (!dataMember->IsPersistent()) {
1856 std::string typeName{GetNormalizedTypeName(dataMember->GetTrueTypeName())};
1857 std::string typeAlias{GetNormalizedTypeName(dataMember->GetFullTypeName())};
1860 if (dataMember->Property() &
kIsArray) {
1861 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim)
1862 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
1865 std::unique_ptr<RFieldBase> subField;
1868 fTraits &= subField->GetTraits();
1876 fMaxAlignment = std::max(fMaxAlignment,
child->GetAlignment());
1877 fSubFieldsInfo.push_back(info);
1884 for (
const auto rule : rules) {
1889 auto func = rule->GetReadFunctionPointer();
1891 fReadCallbacks.emplace_back([func, classp](
void *
target) {
1895 func(
static_cast<char *
>(
target), &oldObj);
1896 oldObj.fClass =
nullptr;
1901std::unique_ptr<ROOT::Experimental::RFieldBase>
1904 return std::unique_ptr<RClassField>(
new RClassField(newName, *
this));
1909 std::size_t nbytes = 0;
1910 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1911 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fSubFieldsInfo[i].fOffset);
1918 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1919 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1925 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1926 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1934 const auto ruleset =
fClass->GetSchemaRules();
1938 if (rule->GetTarget() ==
nullptr)
1941 const auto dataMember = klass->GetDataMember(
target->GetString());
1942 if (!dataMember || dataMember->IsPersistent()) {
1944 << dataMember->GetName();
1951 auto rules = ruleset->FindRules(
fClass->GetName(),
static_cast<Int_t>(GetOnDiskTypeVersion()),
1952 static_cast<UInt_t>(GetOnDiskTypeChecksum()));
1953 rules.erase(std::remove_if(rules.begin(), rules.end(), referencesNonTransientMembers), rules.end());
1954 AddReadCallbacksFromIORules(rules,
fClass);
1964 fClass->Destructor(objPtr,
true );
1965 RDeleter::operator()(objPtr, dtorOnly);
1968std::vector<ROOT::Experimental::RFieldBase::RValue>
1971 std::vector<RValue>
result;
1972 auto basePtr =
value.GetPtr<
unsigned char>().get();
1973 result.reserve(fSubFields.size());
1974 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1976 fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fSubFieldsInfo[i].fOffset)));
1983 return fClass->GetClassSize();
1988 return fClass->GetClassVersion();
1993 return fClass->GetCheckSum();
2006 return dataMember->GetOffset();
2029std::unique_ptr<ROOT::Experimental::RFieldBase>
2032 return std::unique_ptr<RField<TObject>>(
new RField<TObject>(newName, *
this));
2039 auto *obj =
static_cast<const TObject *
>(from);
2044 std::size_t nbytes = 0;
2045 nbytes += CallAppendOn(*fSubFields[0],
reinterpret_cast<const unsigned char *
>(from) + GetOffsetUniqueID());
2047 UInt_t bits = *
reinterpret_cast<const UInt_t *
>(
reinterpret_cast<const unsigned char *
>(from) + GetOffsetBits());
2049 nbytes += CallAppendOn(*fSubFields[1], &bits);
2058 auto *obj =
static_cast<TObject *
>(to);
2063 CallReadOn(*fSubFields[0], globalIndex,
static_cast<unsigned char *
>(to) + GetOffsetUniqueID());
2067 CallReadOn(*fSubFields[1], globalIndex, &bits);
2069 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetBits()) = bits;
2074 if (GetTypeVersion() != 1) {
2075 throw RException(
R__FAIL(
"unsupported on-disk version of TObject: " + std::to_string(GetTypeVersion())));
2094std::vector<ROOT::Experimental::RFieldBase::RValue>
2097 std::vector<RValue>
result;
2098 auto basePtr =
value.GetPtr<
unsigned char>().get();
2100 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetUniqueID())));
2102 fSubFields[1]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + GetOffsetBits())));
2124 std::string_view typeAlias)
2137 throw RException(
R__FAIL(
"RStreamerField: no I/O support for type " + std::string(className)));
2147std::unique_ptr<ROOT::Experimental::RFieldBase>
2150 return std::unique_ptr<RStreamerField>(
new RStreamerField(newName, GetTypeName(), GetTypeAlias()));
2157 fClass->Streamer(
const_cast<void *
>(from), buffer);
2159 auto nbytes = buffer.Length();
2160 fAuxiliaryColumn->AppendV(buffer.Buffer(), buffer.Length());
2162 fPrincipalColumn->Append(&fIndex);
2163 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2170 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nbytes);
2173 fAuxiliaryColumn->ReadV(collectionStart, nbytes, buffer.
Buffer());
2174 fClass->Streamer(to, buffer);
2185 return representations;
2190 GenerateColumnsImpl<ClusterSize_t, std::byte>();
2195 GenerateColumnsImpl<ClusterSize_t, std::byte>(desc);
2205 fClass->Destructor(objPtr,
true );
2206 RDeleter::operator()(objPtr, dtorOnly);
2221 return std::min(
alignof(std::max_align_t), GetValueSize());
2226 return fClass->GetClassSize();
2231 return fClass->GetClassVersion();
2236 return fClass->GetCheckSum();
2247 :
REnumField(fieldName, enumName,
TEnum::GetEnum(std::string(enumName).c_str()))
2254 if (enump ==
nullptr) {
2255 throw RException(
R__FAIL(
"RField: no I/O support for enum type " + std::string(enumName)));
2273 default:
throw RException(
R__FAIL(
"Unsupported underlying integral type for enum type " + std::string(enumName)));
2280 std::unique_ptr<RFieldBase> intField)
2283 Attach(std::move(intField));
2287std::unique_ptr<ROOT::Experimental::RFieldBase>
2290 auto newIntField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2291 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
2294std::vector<ROOT::Experimental::RFieldBase::RValue>
2297 std::vector<RValue>
result;
2298 result.emplace_back(fSubFields[0]->BindValue(
value.GetPtr<
void>()));
2318 (ifuncs.
fNext !=
nullptr));
2323 std::string_view typeName,
TClass *classp)
2326 if (classp ==
nullptr)
2327 throw RException(
R__FAIL(
"RField: no I/O support for collection proxy type " + std::string(typeName)));
2329 throw RException(
R__FAIL(std::string(typeName) +
" has no associated collection proxy"));
2334 if (
fProxy->HasPointers())
2335 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
2336 if (!
fProxy->GetCollectionClass()->HasDictionary()) {
2338 GetNormalizedTypeName(
fProxy->GetCollectionClass()->GetName())));
2346 std::string_view typeName,
2347 std::unique_ptr<RFieldBase> itemField)
2351 Attach(std::move(itemField));
2355 std::string_view typeName)
2360 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
2362 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField;
2364 if (
auto valueClass =
fProxy->GetValueClass()) {
2368 switch (
fProxy->GetType()) {
2370 case EDataType::kUChar_t: itemField = std::make_unique<RField<std::uint8_t>>(
"_0");
break;
2371 case EDataType::kShort_t: itemField = std::make_unique<RField<std::int16_t>>(
"_0");
break;
2373 case EDataType::kInt_t: itemField = std::make_unique<RField<std::int32_t>>(
"_0");
break;
2374 case EDataType::kUInt_t: itemField = std::make_unique<RField<std::uint32_t>>(
"_0");
break;
2387 Attach(std::move(itemField));
2390std::unique_ptr<ROOT::Experimental::RFieldBase>
2393 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2394 return std::unique_ptr<RProxiedCollectionField>(
2400 std::size_t nbytes = 0;
2404 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2405 nbytes += CallAppendOn(*fSubFields[0], ptr);
2410 fPrincipalColumn->Append(&fNWritten);
2411 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2418 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2426 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
2427 CallReadOn(*fSubFields[0], collectionStart + (i++), elementPtr);
2430 fProxy->Commit(obj);
2439 return representations;
2444 GenerateColumnsImpl<ClusterSize_t>();
2449 GenerateColumnsImpl<ClusterSize_t>(desc);
2457std::unique_ptr<ROOT::Experimental::RFieldBase::RDeleter>
2461 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
2462 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubFields[0]), itemSize);
2464 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
2472 fItemDeleter->operator()(ptr,
true );
2475 fProxy->Destructor(objPtr,
true );
2476 RDeleter::operator()(objPtr, dtorOnly);
2479std::vector<ROOT::Experimental::RFieldBase::RValue>
2482 std::vector<RValue>
result;
2483 auto valueRawPtr =
value.GetPtr<
void>().get();
2486 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
2487 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr)));
2501 fMaxAlignment(source.fMaxAlignment),
2503 fOffsets(source.fOffsets)
2506 Attach(
f->Clone(
f->GetFieldName()));
2515void ROOT::Experimental::RRecordField::RRecordField::AttachItemFields(
2516 std::vector<std::unique_ptr<RFieldBase>> itemFields)
2518 fTraits |= kTraitTrivialType;
2519 for (
auto &item : itemFields) {
2520 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
2521 fSize += GetItemPadding(
fSize, item->GetAlignment()) + item->GetValueSize();
2522 fTraits &= item->GetTraits();
2523 Attach(std::move(item));
2527 fSize += GetItemPadding(
fSize, fMaxAlignment);
2531 std::vector<std::unique_ptr<RFieldBase>> itemFields)
2535 fOffsets.reserve(itemFields.size());
2536 for (
auto &item : itemFields) {
2540 fSize += item->GetValueSize();
2551 if (itemAlignment > 1) {
2552 auto remainder = baseOffset % itemAlignment;
2554 return itemAlignment - remainder;
2559std::unique_ptr<ROOT::Experimental::RFieldBase>
2562 return std::unique_ptr<RRecordField>(
new RRecordField(newName, *
this));
2567 std::size_t nbytes = 0;
2568 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2569 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
2576 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2577 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2583 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2584 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
2590 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2591 CallConstructValueOn(*fSubFields[i],
static_cast<unsigned char *
>(where) + fOffsets[i]);
2597 for (
unsigned i = 0; i < fItemDeleters.size(); ++i) {
2598 fItemDeleters[i]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fOffsets[i],
true );
2600 RDeleter::operator()(objPtr, dtorOnly);
2605 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2606 itemDeleters.reserve(fOffsets.size());
2607 for (
const auto &
f : fSubFields) {
2608 itemDeleters.emplace_back(GetDeleterOf(*
f));
2610 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
2613std::vector<ROOT::Experimental::RFieldBase::RValue>
2616 auto basePtr =
value.GetPtr<
unsigned char>().get();
2617 std::vector<RValue>
result;
2618 result.reserve(fSubFields.size());
2619 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2620 result.emplace_back(fSubFields[i]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), basePtr + fOffsets[i])));
2634 :
ROOT::Experimental::
RFieldBase(fieldName, isUntyped ?
"" :
"std::vector<" + itemField->GetTypeName() +
">",
2636 fItemSize(itemField->GetValueSize()),
2641 Attach(std::move(itemField));
2649std::unique_ptr<ROOT::Experimental::RVectorField>
2652 return std::unique_ptr<ROOT::Experimental::RVectorField>(
new RVectorField(fieldName, std::move(itemField),
true));
2655std::unique_ptr<ROOT::Experimental::RFieldBase>
2658 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2659 return std::unique_ptr<ROOT::Experimental::RVectorField>(
2660 new RVectorField(newName, std::move(newItemField), GetTypeName().empty()));
2665 auto typedValue =
static_cast<const std::vector<char> *
>(from);
2666 R__ASSERT((typedValue->size() % fItemSize) == 0);
2667 std::size_t nbytes = 0;
2668 auto count = typedValue->size() / fItemSize;
2670 if (fSubFields[0]->IsSimple() && count) {
2671 GetPrincipalColumnOf(*fSubFields[0])->AppendV(typedValue->data(), count);
2672 nbytes += count * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2674 for (
unsigned i = 0; i < count; ++i) {
2675 nbytes += CallAppendOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2680 fPrincipalColumn->Append(&fNWritten);
2681 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2686 auto typedValue =
static_cast<std::vector<char> *
>(to);
2690 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2692 if (fSubFields[0]->IsSimple()) {
2693 typedValue->resize(nItems * fItemSize);
2695 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, typedValue->data());
2700 const auto oldNItems = typedValue->size() / fItemSize;
2701 const bool canRealloc = oldNItems < nItems;
2702 bool allDeallocated =
false;
2704 allDeallocated = canRealloc;
2705 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
2706 fItemDeleter->operator()(typedValue->data() + (i * fItemSize),
true );
2709 typedValue->resize(nItems * fItemSize);
2710 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)) {
2711 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
2712 CallConstructValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
2716 for (std::size_t i = 0; i < nItems; ++i) {
2717 CallReadOn(*fSubFields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
2727 return representations;
2732 GenerateColumnsImpl<ClusterSize_t>();
2737 GenerateColumnsImpl<ClusterSize_t>(desc);
2742 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
2744 R__ASSERT((vecPtr->size() % fItemSize) == 0);
2745 auto nItems = vecPtr->size() / fItemSize;
2746 for (std::size_t i = 0; i < nItems; ++i) {
2747 fItemDeleter->operator()(vecPtr->data() + (i * fItemSize),
true );
2750 std::destroy_at(vecPtr);
2751 RDeleter::operator()(objPtr, dtorOnly);
2757 return std::make_unique<RVectorDeleter>(fItemSize, GetDeleterOf(*fSubFields[0]));
2758 return std::make_unique<RVectorDeleter>();
2761std::vector<ROOT::Experimental::RFieldBase::RValue>
2764 auto vec =
value.GetPtr<std::vector<char>>();
2766 auto nItems =
vec->size() / fItemSize;
2767 std::vector<RValue>
result;
2769 for (
unsigned i = 0; i < nItems; ++i) {
2771 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(),
vec->data() + (i * fItemSize))));
2784 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
2786 fItemSize(itemField->GetValueSize()),
2791 Attach(std::move(itemField));
2795std::unique_ptr<ROOT::Experimental::RFieldBase>
2798 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
2799 return std::make_unique<RRVecField>(newName, std::move(newItemField));
2804 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(from);
2806 std::size_t nbytes = 0;
2807 if (fSubFields[0]->IsSimple() && *sizePtr) {
2808 GetPrincipalColumnOf(*fSubFields[0])->AppendV(*beginPtr, *sizePtr);
2809 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
2811 auto begin =
reinterpret_cast<const char *
>(*beginPtr);
2812 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2813 nbytes += CallAppendOn(*fSubFields[0], begin + i * fItemSize);
2817 fNWritten += *sizePtr;
2818 fPrincipalColumn->Append(&fNWritten);
2819 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
2827 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(to);
2832 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2833 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2834 const std::size_t oldSize = *sizePtr;
2838 const bool owns = (*capacityPtr != -1);
2839 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
2840 const bool needsDestruct = owns && fItemDeleter;
2843 if (needsDestruct) {
2844 for (std::size_t i = nItems; i < oldSize; ++i) {
2845 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2850 if (std::int32_t(nItems) > *capacityPtr) {
2853 if (needsDestruct) {
2854 for (std::size_t i = 0u; i < oldSize; ++i) {
2855 fItemDeleter->operator()(begin + (i * fItemSize),
true );
2866 *beginPtr =
malloc(nItems * fItemSize);
2868 begin =
reinterpret_cast<char *
>(*beginPtr);
2869 *capacityPtr = nItems;
2872 if (needsConstruct) {
2873 for (std::size_t i = 0u; i < oldSize; ++i)
2874 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2880 if (needsConstruct) {
2881 for (std::size_t i = oldSize; i < nItems; ++i)
2882 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
2885 if (fSubFields[0]->IsSimple() && nItems) {
2886 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, begin);
2891 for (std::size_t i = 0; i < nItems; ++i) {
2892 CallReadOn(*fSubFields[0], collectionStart + i, begin + (i * fItemSize));
2898 if (!fSubFields[0]->IsSimple())
2904 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
2905 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fSubFields[0]->GetValueSize();
2907 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
2908 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
2909 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(bulkSpec.
fValues);
2915 this->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
2916 *beginPtr = itemValueArray;
2917 *sizePtr = collectionSize;
2923 auto lastOffset = firstItemIndex.
GetIndex() + collectionSize;
2925 std::size_t nValues = 1;
2926 std::size_t nItems = collectionSize;
2927 while (nRemainingValues > 0) {
2930 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
2931 for (std::size_t i = 0; i < nBatch; ++i) {
2932 const auto size = offsets[i] - lastOffset;
2933 std::tie(beginPtr, sizePtr, capacityPtr) =
2934 GetRVecDataMembers(
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
2935 *beginPtr = itemValueArray + nItems * itemValueSize;
2940 lastOffset = offsets[i];
2942 nRemainingValues -= nBatch;
2946 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
2948 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
2950 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
2951 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
2952 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
2957 GetPrincipalColumnOf(*fSubFields[0])->ReadV(firstItemIndex, nItems, itemValueArray - delta);
2958 return RBulkSpec::kAllSet;
2967 return representations;
2972 GenerateColumnsImpl<ClusterSize_t>();
2977 GenerateColumnsImpl<ClusterSize_t>(desc);
2984 void **beginPtr =
new (where)(
void *)(
nullptr);
2985 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2986 new (sizePtr + 1) std::int32_t(-1);
2991 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(objPtr);
2993 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2995 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2996 fItemDeleter->operator()(begin + i * fItemSize,
true );
3000 DestroyRVecWithChecks(fItemAlignment, beginPtr, begin, capacityPtr);
3001 RDeleter::operator()(objPtr, dtorOnly);
3007 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize, GetDeleterOf(*fSubFields[0]));
3008 return std::make_unique<RRVecDeleter>(fSubFields[0]->GetAlignment());
3011std::vector<ROOT::Experimental::RFieldBase::RValue>
3014 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(
value.GetPtr<
void>().get());
3016 std::vector<RValue>
result;
3017 char *begin =
reinterpret_cast<char *
>(*beginPtr);
3018 result.reserve(*sizePtr);
3019 for (std::int32_t i = 0; i < *sizePtr; ++i) {
3020 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), begin + i * fItemSize)));
3032 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
3050 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
3051 auto count = typedValue->size();
3052 for (
unsigned i = 0; i < count; ++i) {
3053 bool bval = (*typedValue)[i];
3054 CallAppendOn(*fSubFields[0], &bval);
3057 fPrincipalColumn->Append(&fNWritten);
3058 return count + fPrincipalColumn->GetElement()->GetPackedSize();
3063 auto typedValue =
static_cast<std::vector<bool> *
>(to);
3066 RClusterIndex collectionStart;
3067 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
3069 typedValue->resize(nItems);
3070 for (
unsigned i = 0; i < nItems; ++i) {
3072 CallReadOn(*fSubFields[0], collectionStart + i, &bval);
3073 (*typedValue)[i] = bval;
3080 static RColumnRepresentations representations(
3083 return representations;
3088 GenerateColumnsImpl<ClusterSize_t>();
3093 GenerateColumnsImpl<ClusterSize_t>(desc);
3096std::vector<ROOT::Experimental::RFieldBase::RValue>
3099 const auto &typedValue =
value.GetRef<std::vector<bool>>();
3100 auto count = typedValue.size();
3101 std::vector<RValue>
result;
3103 for (
unsigned i = 0; i < count; ++i) {
3105 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
true))));
3107 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<bool>(
new bool(
false))));
3114 visitor.VisitVectorBoolField(*
this);
3120 std::size_t arrayLength)
3122 "std::array<" + itemField->GetTypeName() +
"," + std::to_string(arrayLength) +
">",
3124 fItemSize(itemField->GetValueSize()),
3125 fArrayLength(arrayLength)
3127 fTraits |= itemField->GetTraits() & ~kTraitMappable;
3128 Attach(std::move(itemField));
3131std::unique_ptr<ROOT::Experimental::RFieldBase>
3134 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3135 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
3140 std::size_t nbytes = 0;
3141 auto arrayPtr =
static_cast<const unsigned char *
>(from);
3142 for (
unsigned i = 0; i < fArrayLength; ++i) {
3143 nbytes += CallAppendOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3150 auto arrayPtr =
static_cast<unsigned char *
>(to);
3151 for (
unsigned i = 0; i < fArrayLength; ++i) {
3152 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
3158 auto arrayPtr =
static_cast<unsigned char *
>(to);
3159 for (
unsigned i = 0; i < fArrayLength; ++i) {
3161 arrayPtr + (i * fItemSize));
3167 if (fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)
3170 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
3171 for (
unsigned i = 0; i < fArrayLength; ++i) {
3172 CallConstructValueOn(*fSubFields[0], arrayPtr + (i * fItemSize));
3179 for (
unsigned i = 0; i < fArrayLength; ++i) {
3180 fItemDeleter->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + i * fItemSize,
true );
3183 RDeleter::operator()(objPtr, dtorOnly);
3188 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible))
3189 return std::make_unique<RArrayDeleter>(fItemSize, fArrayLength, GetDeleterOf(*fSubFields[0]));
3190 return std::make_unique<RDeleter>();
3193std::vector<ROOT::Experimental::RFieldBase::RValue>
3196 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3197 std::vector<RValue>
result;
3198 result.reserve(fArrayLength);
3199 for (
unsigned i = 0; i < fArrayLength; ++i) {
3201 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3215 std::unique_ptr<ROOT::Experimental::RFieldBase> itemField,
3216 std::size_t arrayLength)
3217 :
ROOT::Experimental::
RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetTypeName() +
">",
3219 fItemSize(itemField->GetValueSize()),
3220 fArrayLength(arrayLength)
3222 Attach(std::move(itemField));
3228std::unique_ptr<ROOT::Experimental::RFieldBase>
3231 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3232 return std::make_unique<RArrayAsRVecField>(newName, std::move(newItemField), fArrayLength);
3238 void **beginPtr =
new (where)(
void *)(
nullptr);
3239 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
3240 std::int32_t *capacityPtr =
new (sizePtr + 1) std::int32_t(0);
3244 char *begin =
reinterpret_cast<char *
>(*beginPtr);
3247 if (*sizePtr == std::int32_t(fArrayLength))
3253 const bool owns = (*capacityPtr != -1);
3254 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
3255 const bool needsDestruct = owns && fItemDeleter;
3259 if (needsDestruct) {
3260 for (std::int32_t i = 0; i < *sizePtr; ++i) {
3261 fItemDeleter->operator()(begin + (i * fItemSize),
true );
3271 *beginPtr =
malloc(fArrayLength * fItemSize);
3274 begin =
reinterpret_cast<char *
>(*beginPtr);
3276 *sizePtr = fArrayLength;
3277 *capacityPtr = fArrayLength;
3280 if (needsConstruct) {
3281 for (std::size_t i = 0; i < fArrayLength; ++i)
3282 CallConstructValueOn(*fSubFields[0], begin + (i * fItemSize));
3289 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment(), fItemSize,
3290 GetDeleterOf(*fSubFields[0]));
3292 return std::make_unique<RRVecField::RRVecDeleter>(fSubFields[0]->GetAlignment());
3298 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3299 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3301 if (fSubFields[0]->IsSimple()) {
3302 GetPrincipalColumnOf(*fSubFields[0])->ReadV(globalIndex * fArrayLength, fArrayLength, rvecBeginPtr);
3307 for (std::size_t i = 0; i < fArrayLength; ++i) {
3308 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, rvecBeginPtr + (i * fItemSize));
3314 auto [beginPtr,
_, __] = GetRVecDataMembers(to);
3315 auto rvecBeginPtr =
reinterpret_cast<char *
>(*beginPtr);
3318 const auto &clusterIndexIndex = clusterIndex.
GetIndex();
3320 if (fSubFields[0]->IsSimple()) {
3321 GetPrincipalColumnOf(*fSubFields[0])
3322 ->ReadV(
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength), fArrayLength, rvecBeginPtr);
3327 for (std::size_t i = 0; i < fArrayLength; ++i) {
3328 CallReadOn(*fSubFields[0],
RClusterIndex(clusterId, clusterIndexIndex * fArrayLength + i),
3329 rvecBeginPtr + (i * fItemSize));
3335 return EvalRVecAlignment(fSubFields[0]->GetAlignment());
3338std::vector<ROOT::Experimental::RFieldBase::RValue>
3341 auto arrayPtr =
value.GetPtr<
unsigned char>().get();
3342 std::vector<ROOT::Experimental::RFieldBase::RValue>
result;
3343 result.reserve(fArrayLength);
3344 for (
unsigned i = 0; i < fArrayLength; ++i) {
3346 fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), arrayPtr + (i * fItemSize))));
3373 return representations;
3378 GenerateColumnsImpl<bool>();
3383 GenerateColumnsImpl<bool>(desc);
3388 const auto *asULongArray =
static_cast<const Word_t *
>(from);
3391 for (std::size_t word = 0; word < (fN + kBitsPerWord - 1) / kBitsPerWord; ++word) {
3392 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < fN); ++
mask, ++i) {
3393 elementValue = (asULongArray[word] & (
static_cast<Word_t>(1) <<
mask)) != 0;
3394 fPrincipalColumn->Append(&elementValue);
3402 auto *asULongArray =
static_cast<Word_t *
>(to);
3404 for (std::size_t i = 0; i < fN; ++i) {
3405 fPrincipalColumn->Read(globalIndex * fN + i, &elementValue);
3407 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
3408 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
3414 auto *asULongArray =
static_cast<Word_t *
>(to);
3416 for (std::size_t i = 0; i < fN; ++i) {
3420 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
3421 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
3435 for (
size_t i = 0; i < itemFields.size(); ++i) {
3436 result += itemFields[i]->GetTypeName() +
",";
3445 fMaxItemSize(source.fMaxItemSize),
3446 fMaxAlignment(source.fMaxAlignment),
3447 fTagOffset(source.fTagOffset),
3448 fVariantOffset(source.fVariantOffset),
3449 fNWritten(source.fNWritten.
size(), 0)
3452 Attach(
f->Clone(
f->GetFieldName()));
3457 std::vector<std::unique_ptr<RFieldBase>> itemFields)
3458 :
ROOT::Experimental::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields) +
">",
3464 auto nFields = itemFields.size();
3469 for (
unsigned int i = 0; i < nFields; ++i) {
3472 fTraits &= itemFields[i]->GetTraits();
3473 Attach(std::move(itemFields[i]));
3484 const auto tagSize = GetVariantTagSize();
3485 const auto padding = tagSize - (
fMaxItemSize % tagSize);
3489std::unique_ptr<ROOT::Experimental::RFieldBase>
3492 return std::unique_ptr<RVariantField>(
new RVariantField(newName, *
this));
3497 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3498 auto tag = *
reinterpret_cast<const TagType_t *
>(
reinterpret_cast<const unsigned char *
>(variantPtr) + tagOffset);
3499 return (tag == TagType_t(-1)) ? 0 : tag + 1;
3504 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
3505 auto tagPtr =
reinterpret_cast<TagType_t *
>(
reinterpret_cast<unsigned char *
>(variantPtr) + tagOffset);
3506 *tagPtr = (tag == 0) ? TagType_t(-1) :
static_cast<TagType_t
>(tag - 1);
3511 auto tag = GetTag(from, fTagOffset);
3512 std::size_t nbytes = 0;
3515 nbytes += CallAppendOn(*fSubFields[tag - 1],
reinterpret_cast<const unsigned char *
>(from) + fVariantOffset);
3516 index = fNWritten[tag - 1]++;
3519 fPrincipalColumn->Append(&varSwitch);
3527 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
3534 void *varPtr =
reinterpret_cast<unsigned char *
>(to) + fVariantOffset;
3535 CallConstructValueOn(*fSubFields[tag - 1], varPtr);
3536 CallReadOn(*fSubFields[tag - 1], variantIndex, varPtr);
3538 SetTag(to, fTagOffset, tag);
3545 return representations;
3550 GenerateColumnsImpl<RColumnSwitch>();
3555 GenerateColumnsImpl<RColumnSwitch>(desc);
3560 memset(where, 0, GetValueSize());
3561 CallConstructValueOn(*fSubFields[0],
reinterpret_cast<unsigned char *
>(where) + fVariantOffset);
3562 SetTag(where, fTagOffset, 1);
3567 auto tag = GetTag(objPtr, fTagOffset);
3569 fItemDeleters[tag - 1]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fVariantOffset,
true );
3571 RDeleter::operator()(objPtr, dtorOnly);
3576 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
3577 itemDeleters.reserve(fSubFields.size());
3578 for (
const auto &
f : fSubFields) {
3579 itemDeleters.emplace_back(GetDeleterOf(*
f));
3581 return std::make_unique<RVariantDeleter>(fTagOffset, fVariantOffset, std::move(itemDeleters));
3586 return std::max(fMaxAlignment,
alignof(RVariantTag<GetVariantTagSize()>::ValueType_t));
3592 const auto actualSize = fTagOffset + GetVariantTagSize();
3594 return actualSize + ((padding ==
alignment) ? 0 : padding);
3599 std::fill(fNWritten.begin(), fNWritten.end(), 0);
3605 std::unique_ptr<RFieldBase> itemField)
3613 std::unique_ptr<RFieldBase> itemField)
3616 if (!
dynamic_cast<RPairField *
>(itemField.get()))
3619 auto *itemClass =
fProxy->GetValueClass();
3622 Attach(std::move(itemField));
3628 std::unique_ptr<RFieldBase> itemField)
3631 Attach(std::move(itemField));
3640 return representations;
3645 GenerateColumnsImpl<ClusterSize_t>();
3650 GenerateColumnsImpl<ClusterSize_t>(desc);
3655 fPrincipalColumn->Append(&fNWritten);
3661 auto nbytesItem = CallAppendOn(*fSubFields[0], from);
3663 fPrincipalColumn->Append(&fNWritten);
3671 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
3672 return (collectionSize == 0) ?
RClusterIndex() : collectionStart;
3683 std::unique_ptr<RFieldBase> itemField)
3684 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3688std::unique_ptr<ROOT::Experimental::RFieldBase>
3691 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetFieldName());
3692 return std::make_unique<RUniquePtrField>(newName, GetTypeName(), std::move(newItemField));
3697 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
3699 return AppendValue(typedValue->get());
3701 return AppendNull();
3707 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
3708 bool isValidValue =
static_cast<bool>(*ptr);
3710 auto itemIndex = GetItemIndex(globalIndex);
3713 void *valuePtr =
nullptr;
3715 valuePtr = ptr->get();
3717 if (isValidValue && !isValidItem) {
3719 fItemDeleter->operator()(valuePtr,
false );
3726 if (!isValidValue) {
3727 valuePtr = CallCreateObjectRawPtrOn(*fSubFields[0]);
3728 ptr->reset(
reinterpret_cast<char *
>(valuePtr));
3731 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3736 auto typedPtr =
static_cast<std::unique_ptr<char> *
>(objPtr);
3738 fItemDeleter->operator()(typedPtr->get(),
false );
3739 typedPtr->release();
3741 RDeleter::operator()(objPtr, dtorOnly);
3746 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubFields[0]));
3749std::vector<ROOT::Experimental::RFieldBase::RValue>
3752 std::vector<RValue>
result;
3753 const auto &ptr =
value.GetRef<std::unique_ptr<char>>();
3755 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), ptr.get())));
3763 std::unique_ptr<RFieldBase> itemField)
3764 :
RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubFields[0]))
3772 void *
value = optionalPtr;
3774 reinterpret_cast<bool *
>(
reinterpret_cast<unsigned char *
>(optionalPtr) + fSubFields[0]->GetValueSize());
3775 return {
value, engagement};
3778std::pair<const void *, const bool *>
3781 return GetValueAndEngagementPtrs(
const_cast<void *
>(optionalPtr));
3784std::unique_ptr<ROOT::Experimental::RFieldBase>
3787 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3788 return std::make_unique<ROptionalField>(newName, GetTypeName(), std::move(newItemField));
3793 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(from);
3794 if (*engagementPtr) {
3795 return AppendValue(valuePtr);
3797 return AppendNull();
3803 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(to);
3804 auto itemIndex = GetItemIndex(globalIndex);
3806 *engagementPtr =
false;
3808 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
3809 *engagementPtr =
true;
3815 auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(where);
3816 CallConstructValueOn(*fSubFields[0], valuePtr);
3817 *engagementPtr =
false;
3822 fItemDeleter->operator()(objPtr,
true );
3823 RDeleter::operator()(objPtr, dtorOnly);
3828 return std::make_unique<ROptionalDeleter>(GetDeleterOf(*fSubFields[0]));
3831std::vector<ROOT::Experimental::RFieldBase::RValue>
3834 std::vector<RValue>
result;
3835 const auto [valuePtr, engagementPtr] = GetValueAndEngagementPtrs(
value.GetPtr<
void>().get());
3836 if (*engagementPtr) {
3837 result.emplace_back(fSubFields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(), valuePtr)));
3846 const auto actualSize = fSubFields[0]->GetValueSize() +
sizeof(
bool);
3849 auto remainder = actualSize %
alignment;
3853 return actualSize + padding;
3858 return fSubFields[0]->GetAlignment();
3864ROOT::Experimental::RPairField::RPairField::GetTypeList(
const std::array<std::unique_ptr<RFieldBase>, 2> &itemFields)
3866 return itemFields[0]->GetTypeName() +
"," + itemFields[1]->GetTypeName();
3870 std::array<std::unique_ptr<RFieldBase>, 2> itemFields,
3871 const std::array<std::size_t, 2> &offsets)
3872 :
ROOT::Experimental::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields) +
">")
3880 std::array<std::unique_ptr<RFieldBase>, 2> itemFields)
3881 :
ROOT::Experimental::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields) +
">")
3891 auto firstElem =
c->GetRealData(
"first");
3894 fOffsets.push_back(firstElem->GetThisOffset());
3896 auto secondElem =
c->GetRealData(
"second");
3899 fOffsets.push_back(secondElem->GetThisOffset());
3905ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
const std::vector<std::unique_ptr<RFieldBase>> &itemFields)
3908 if (itemFields.empty())
3909 throw RException(
R__FAIL(
"the type list for std::tuple must have at least one element"));
3910 for (
size_t i = 0; i < itemFields.size(); ++i) {
3911 result += itemFields[i]->GetTypeName() +
",";
3918 std::vector<std::unique_ptr<RFieldBase>> itemFields,
3919 const std::vector<std::size_t> &offsets)
3920 :
ROOT::Experimental::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields) +
">")
3927 std::vector<std::unique_ptr<RFieldBase>> itemFields)
3928 :
ROOT::Experimental::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields) +
">")
3942 for (
unsigned i = 0; i <
fSubFields.size(); ++i) {
3943 std::string memberName(
"_" + std::to_string(i));
3944 auto member =
c->GetRealData(memberName.c_str());
3947 fOffsets.push_back(member->GetThisOffset());
3954 std::unique_ptr<RFieldBase> itemField)
3961 Attach(std::move(itemField));
3964std::unique_ptr<ROOT::Experimental::RFieldBase>
3967 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetFieldName());
3968 return std::make_unique<RAtomicField>(newName, GetTypeName(), std::move(newItemField));
3971std::vector<ROOT::Experimental::RFieldBase::RValue>
3974 std::vector<RValue>
result;
3975 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 * GetTypeName(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)
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
std::uint32_t GetTypeVersion() const
The container field for an ntuple model, which itself has no physical representation.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const 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.