51#include <unordered_map>
55static const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
58 {
"Double_t",
"double"},
59 {
"string",
"std::string"},
62 {
"int8_t",
"std::int8_t"},
63 {
"signed char",
"char"},
64 {
"UChar_t",
"std::uint8_t"},
65 {
"unsigned char",
"std::uint8_t"},
66 {
"uint8_t",
"std::uint8_t"},
68 {
"Short_t",
"std::int16_t"},
69 {
"int16_t",
"std::int16_t"},
70 {
"short",
"std::int16_t"},
71 {
"UShort_t",
"std::uint16_t"},
72 {
"unsigned short",
"std::uint16_t"},
73 {
"uint16_t",
"std::uint16_t"},
75 {
"Int_t",
"std::int32_t"},
76 {
"int32_t",
"std::int32_t"},
77 {
"int",
"std::int32_t"},
78 {
"UInt_t",
"std::uint32_t"},
79 {
"unsigned",
"std::uint32_t"},
80 {
"unsigned int",
"std::uint32_t"},
81 {
"uint32_t",
"std::uint32_t"},
83 {
"Long_t",
"std::int64_t"},
84 {
"Long64_t",
"std::int64_t"},
85 {
"int64_t",
"std::int64_t"},
86 {
"long",
"std::int64_t"},
87 {
"ULong64_t",
"std::uint64_t"},
88 {
"unsigned long",
"std::uint64_t"},
89 {
"uint64_t",
"std::uint64_t"}
94std::vector<std::string> TokenizeTypeList(std::string templateType) {
95 std::vector<std::string>
result;
96 if (templateType.empty())
99 const char *eol = templateType.data() + templateType.length();
100 const char *typeBegin = templateType.data();
101 const char *typeCursor = templateType.data();
102 unsigned int nestingLevel = 0;
103 while (typeCursor != eol) {
104 switch (*typeCursor) {
112 if (nestingLevel == 0) {
113 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
114 typeBegin = typeCursor + 1;
120 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
129std::tuple<std::string, std::vector<size_t>> ParseArrayType(std::string_view typeName)
131 std::vector<size_t> sizeVec;
134 while (typeName.back() ==
']') {
135 auto posRBrace = typeName.size() - 1;
136 auto posLBrace = typeName.find_last_of(
"[", posRBrace);
137 if (posLBrace == std::string_view::npos)
141 if (std::from_chars(typeName.data() + posLBrace + 1, typeName.data() + posRBrace,
size).ec != std::errc{})
143 sizeVec.insert(sizeVec.begin(),
size);
144 typeName.remove_suffix(typeName.size() - posLBrace);
146 return std::make_tuple(std::string{typeName}, sizeVec);
151std::string GetCanonicalTypeName(
const std::string &typeName)
154 if (typeName ==
"ROOT::Experimental::ClusterSize_t" || typeName.substr(0, 5) ==
"std::" ||
155 typeName.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<")
165std::string GetNormalizedTypeName(
const std::string &typeName)
169 if (
auto it = typeTranslationMap.find(normalizedType); it != typeTranslationMap.end())
170 normalizedType = it->second;
172 if (normalizedType.substr(0, 7) ==
"vector<")
173 normalizedType =
"std::" + normalizedType;
174 if (normalizedType.substr(0, 6) ==
"array<")
175 normalizedType =
"std::" + normalizedType;
176 if (normalizedType.substr(0, 8) ==
"variant<")
177 normalizedType =
"std::" + normalizedType;
178 if (normalizedType.substr(0, 5) ==
"pair<")
179 normalizedType =
"std::" + normalizedType;
180 if (normalizedType.substr(0, 6) ==
"tuple<")
181 normalizedType =
"std::" + normalizedType;
182 if (normalizedType.substr(0, 7) ==
"bitset<")
183 normalizedType =
"std::" + normalizedType;
184 if (normalizedType.substr(0, 11) ==
"unique_ptr<")
185 normalizedType =
"std::" + normalizedType;
186 if (normalizedType.substr(0, 4) ==
"set<")
187 normalizedType =
"std::" + normalizedType;
189 return normalizedType;
194std::tuple<void **, std::int32_t *, std::int32_t *> GetRVecDataMembers(
void *rvecPtr)
196 void **begin =
reinterpret_cast<void **
>(rvecPtr);
198 std::int32_t *
size =
reinterpret_cast<std::int32_t *
>(begin + 1);
201 std::int32_t *capacity =
size + 1;
203 return {begin,
size, capacity};
206std::tuple<const void *const *, const std::int32_t *, const std::int32_t *> GetRVecDataMembers(
const void *rvecPtr)
208 return {GetRVecDataMembers(
const_cast<void *
>(rvecPtr))};
216 auto iFrom = from.
cbegin();
217 auto iTo = to.
begin();
218 for (; iFrom != from.
cend(); ++iFrom, ++iTo) {
219 iTo->SetOnDiskId(iFrom->GetOnDiskId());
236 : fSerializationTypes(serializationTypes), fDeserializationTypes(serializationTypes)
239 deserializationExtraTypes.begin(), deserializationExtraTypes.end());
245 : fField(other.fField),
247 fCapacity(other.fCapacity),
249 fNValidValues(other.fNValidValues),
250 fFirstIndex(other.fFirstIndex)
252 std::swap(
fValues, other.fValues);
258 std::swap(fField, other.fField);
259 std::swap(fValues, other.fValues);
261 std::swap(fCapacity, other.fCapacity);
262 std::swap(
fSize, other.fSize);
263 std::swap(fMaskAvail, other.fMaskAvail);
264 std::swap(fNValidValues, other.fNValidValues);
265 std::swap(fFirstIndex, other.fFirstIndex);
282 for (std::size_t i = 0; i < fCapacity; ++i) {
283 fField->DestroyValue(GetValuePtrAt(i),
true );
290 if (fCapacity <
size) {
295 for (std::size_t i = 0; i <
size; ++i) {
296 fField->GenerateValue(GetValuePtrAt(i));
300 fMaskAvail = std::make_unique<bool[]>(
size);
304 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
307 fFirstIndex = firstIndex;
314 for (std::size_t i = 0; i <
fSize; ++i)
315 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
333 std::string
result = GetName();
335 while (parent && !parent->
GetName().empty()) {
345 auto typeAlias = GetNormalizedTypeName(typeName);
346 auto canonicalType = GetNormalizedTypeName(GetCanonicalTypeName(typeAlias));
352 const std::string &typeAlias)
354 if (canonicalType.empty())
355 return R__FAIL(
"no type name specified for Field " + fieldName);
357 if (
auto [arrayBaseType, arraySize] = ParseArrayType(canonicalType); !arraySize.empty()) {
359 if (arraySize.size() > 1)
360 return R__FAIL(
"multi-dimensional array type not supported " + canonicalType);
361 auto itemField = Create(
"_0", arrayBaseType).Unwrap();
362 return {std::make_unique<RArrayField>(fieldName, std::move(itemField), arraySize[0])};
365 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
result;
367 if (canonicalType ==
"ROOT::Experimental::ClusterSize_t") {
368 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
369 }
else if (canonicalType ==
"bool") {
370 result = std::make_unique<RField<bool>>(fieldName);
371 }
else if (canonicalType ==
"char") {
372 result = std::make_unique<RField<char>>(fieldName);
373 }
else if (canonicalType ==
"std::int8_t") {
374 result = std::make_unique<RField<std::int8_t>>(fieldName);
375 }
else if (canonicalType ==
"std::uint8_t") {
376 result = std::make_unique<RField<std::uint8_t>>(fieldName);
377 }
else if (canonicalType ==
"std::int16_t") {
378 result = std::make_unique<RField<std::int16_t>>(fieldName);
379 }
else if (canonicalType ==
"std::uint16_t") {
380 result = std::make_unique<RField<std::uint16_t>>(fieldName);
381 }
else if (canonicalType ==
"std::int32_t") {
382 result = std::make_unique<RField<std::int32_t>>(fieldName);
383 }
else if (canonicalType ==
"std::uint32_t") {
384 result = std::make_unique<RField<std::uint32_t>>(fieldName);
385 }
else if (canonicalType ==
"std::int64_t") {
386 result = std::make_unique<RField<std::int64_t>>(fieldName);
387 }
else if (canonicalType ==
"std::uint64_t") {
388 result = std::make_unique<RField<std::uint64_t>>(fieldName);
389 }
else if (canonicalType ==
"float") {
390 result = std::make_unique<RField<float>>(fieldName);
391 }
else if (canonicalType ==
"double") {
392 result = std::make_unique<RField<double>>(fieldName);
393 }
else if (canonicalType ==
"Double32_t") {
394 result = std::make_unique<RField<double>>(fieldName);
398 }
else if (canonicalType ==
"std::string") {
399 result = std::make_unique<RField<std::string>>(fieldName);
400 }
else if (canonicalType ==
"std::vector<bool>") {
401 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
402 }
else if (canonicalType.substr(0, 12) ==
"std::vector<") {
403 std::string itemTypeName = canonicalType.substr(12, canonicalType.length() - 13);
404 auto itemField = Create(
"_0", itemTypeName);
405 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
406 }
else if (canonicalType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
407 std::string itemTypeName = canonicalType.substr(19, canonicalType.length() - 20);
408 auto itemField = Create(
"_0", itemTypeName);
409 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
410 }
else if (canonicalType.substr(0, 11) ==
"std::array<") {
411 auto arrayDef = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
413 auto arrayLength = std::stoi(arrayDef[1]);
414 auto itemField = Create(
"_0", arrayDef[0]);
415 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
416 }
else if (canonicalType.substr(0, 13) ==
"std::variant<") {
417 auto innerTypes = TokenizeTypeList(canonicalType.substr(13, canonicalType.length() - 14));
418 std::vector<RFieldBase *> items;
419 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
420 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap().release());
422 result = std::make_unique<RVariantField>(fieldName, items);
423 }
else if (canonicalType.substr(0, 10) ==
"std::pair<") {
424 auto innerTypes = TokenizeTypeList(canonicalType.substr(10, canonicalType.length() - 11));
425 if (innerTypes.size() != 2)
426 return R__FAIL(
"the type list for std::pair must have exactly two elements");
427 std::array<std::unique_ptr<RFieldBase>, 2> items{Create(
"_0", innerTypes[0]).Unwrap(),
428 Create(
"_1", innerTypes[1]).Unwrap()};
429 result = std::make_unique<RPairField>(fieldName, items);
430 }
else if (canonicalType.substr(0, 11) ==
"std::tuple<") {
431 auto innerTypes = TokenizeTypeList(canonicalType.substr(11, canonicalType.length() - 12));
432 std::vector<std::unique_ptr<RFieldBase>> items;
433 for (
unsigned int i = 0; i < innerTypes.size(); ++i) {
434 items.emplace_back(Create(
"_" + std::to_string(i), innerTypes[i]).Unwrap());
436 result = std::make_unique<RTupleField>(fieldName, items);
437 }
else if (canonicalType.substr(0, 12) ==
"std::bitset<") {
438 auto size = std::stoull(canonicalType.substr(12, canonicalType.length() - 13));
439 result = std::make_unique<RBitsetField>(fieldName,
size);
440 }
else if (canonicalType.substr(0, 16) ==
"std::unique_ptr<") {
441 std::string itemTypeName = canonicalType.substr(16, canonicalType.length() - 17);
442 auto itemField = Create(
"_0", itemTypeName).Unwrap();
443 auto normalizedInnerTypeName = itemField->GetType();
444 result = std::make_unique<RUniquePtrField>(fieldName,
"std::unique_ptr<" + normalizedInnerTypeName +
">",
445 std::move(itemField));
446 }
else if (canonicalType.substr(0, 9) ==
"std::set<") {
447 std::string itemTypeName = canonicalType.substr(9, canonicalType.length() - 10);
448 auto itemField = Create(
"_0", itemTypeName).Unwrap();
449 auto normalizedInnerTypeName = itemField->GetType();
451 std::make_unique<RSetField>(fieldName,
"std::set<" + normalizedInnerTypeName +
">", std::move(itemField));
452 }
else if (canonicalType ==
":Collection:") {
454 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
455 }
else if (canonicalType.substr(0, 39) ==
"ROOT::Experimental::RNTupleCardinality<") {
456 auto innerTypes = TokenizeTypeList(canonicalType.substr(39, canonicalType.length() - 40));
457 if (innerTypes.size() != 1)
458 return R__FAIL(std::string(
"Field ") + fieldName +
" has invalid cardinality template: " + canonicalType);
459 if (innerTypes[0] ==
"std::uint32_t") {
460 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
461 }
else if (innerTypes[0] ==
"std::uint64_t") {
462 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
464 return R__FAIL(std::string(
"Field ") + fieldName +
" has invalid cardinality template: " + canonicalType);
471 result = std::make_unique<REnumField>(fieldName, canonicalType);
478 if (cl->GetCollectionProxy())
479 result = std::make_unique<RProxiedCollectionField>(fieldName, canonicalType);
481 result = std::make_unique<RClassField>(fieldName, canonicalType);
486 if (typeAlias != canonicalType)
487 result->fTypeAlias = typeAlias;
490 return R__FAIL(std::string(
"Field ") + fieldName +
" has unknown type " + canonicalType);
496 if (fieldName ==
"") {
497 return R__FAIL(
"name cannot be empty string \"\"");
498 }
else if (fieldName.find(
".") != std::string::npos) {
499 return R__FAIL(
"name '" + std::string(fieldName) +
"' cannot contain dot characters '.'");
508 return representations;
511std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
514 auto clone = CloneImpl(newName);
515 clone->fTypeAlias = fTypeAlias;
516 clone->fOnDiskId = fOnDiskId;
517 clone->fDescription = fDescription;
519 clone->fColumnRepresentative = fColumnRepresentative;
525 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
536 const auto valueSize = GetValueSize();
537 std::size_t nRead = 0;
538 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
547 Read(bulkSpec.
fFirstIndex + i,
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + i * valueSize);
556 void *where =
malloc(GetValueSize());
558 GenerateValue(where);
559 return RValue(
this, where,
true );
568std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
571 return std::vector<RValue>();
575 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
child)
579 if (fState != EState::kUnconnected)
580 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
581 child->fParent =
this;
582 fSubFields.emplace_back(std::move(
child));
588 std::size_t
result = globalIndex;
589 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
590 auto parent =
f->GetParent();
591 if (parent && (parent->GetStructure() ==
kCollection || parent->GetStructure() ==
kVariant))
593 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
600 std::vector<RFieldBase *>
result;
601 for (
const auto &
f : fSubFields) {
609 for (
auto& column : fColumns) {
617 if (fState != EState::kUnconnected)
618 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
619 fDescription = std::string(description);
624 if (fState != EState::kUnconnected)
632 if (fColumnRepresentative)
633 return *fColumnRepresentative;
634 return GetColumnRepresentations().GetSerializationDefault();
639 if (fState != EState::kUnconnected)
640 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
641 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
642 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(), representative);
643 if (itRepresentative == std::end(validTypes))
645 fColumnRepresentative = &(*itRepresentative);
652 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
656 onDiskTypes.emplace_back(
c.GetModel().GetType());
658 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
659 if (t == onDiskTypes)
663 std::string columnTypeNames;
664 for (
const auto &t : onDiskTypes) {
665 if (!columnTypeNames.empty())
666 columnTypeNames +=
", ";
669 throw RException(
R__FAIL(
"On-disk column types `" + columnTypeNames +
"` for field `" + GetQualifiedFieldName() +
670 "` cannot be matched."));
675 fReadCallbacks.push_back(func);
677 return fReadCallbacks.size() - 1;
682 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
683 fIsSimple = (fTraits & kTraitMappable) && fReadCallbacks.empty();
688 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
690 for (
auto &colType : rep) {
702 SetColumnRepresentative(rep);
707 for (
auto &colType : rep) {
714 SetColumnRepresentative(rep);
717 if (fTypeAlias ==
"Double32_t")
725 if (fState != EState::kUnconnected)
726 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
730 GenerateColumnsImpl();
731 if (!fColumns.empty())
732 fPrincipalColumn = fColumns[0].get();
733 for (
auto &column : fColumns) {
734 auto firstElementIndex = (column.get() == fPrincipalColumn) ? EntryToColumnElementIndex(firstEntry) : 0;
735 column->Connect(fOnDiskId, &pageSink, firstElementIndex);
738 fState = EState::kConnectedToSink;
745 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
746 if (fState != EState::kUnconnected)
747 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
749 if (fColumnRepresentative)
750 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
751 if (!fDescription.empty())
752 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
757 GenerateColumnsImpl(desc);
759 for (
const auto &
c : fColumns) {
760 onDiskColumnTypes.emplace_back(
c->GetModel().GetType());
762 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
763 if (t == onDiskColumnTypes)
764 fColumnRepresentative = &t;
770 if (!fColumns.empty())
771 fPrincipalColumn = fColumns[0].get();
772 for (
auto& column : fColumns)
773 column->Connect(fOnDiskId, &pageSource);
774 OnConnectPageSource();
776 fState = EState::kConnectedToSource;
787std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
790 auto result = std::make_unique<RFieldZero>();
791 for (
auto &
f : fSubFields)
792 result->Attach(
f->Clone(
f->GetName()));
808 static RColumnRepresentations representations(
811 return representations;
816 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
821 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
822 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
827 visitor.VisitClusterSizeField(*
this);
838 return representations;
843 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
844 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
870 return representations;
875 fColumns.emplace_back(Detail::RColumn::Create<char>(
RColumnModel(GetColumnRepresentative()[0]), 0));
880 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
881 fColumns.emplace_back(Detail::RColumn::Create<char>(
RColumnModel(onDiskTypes[0]), 0));
895 return representations;
900 fColumns.emplace_back(Detail::RColumn::Create<std::int8_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
905 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
906 fColumns.emplace_back(Detail::RColumn::Create<std::int8_t>(RColumnModel(onDiskTypes[0]), 0));
911 visitor.VisitInt8Field(*
this);
920 return representations;
925 fColumns.emplace_back(Detail::RColumn::Create<std::uint8_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
930 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
931 fColumns.emplace_back(Detail::RColumn::Create<std::uint8_t>(RColumnModel(onDiskTypes[0]), 0));
936 visitor.VisitUInt8Field(*
this);
945 return representations;
950 fColumns.emplace_back(Detail::RColumn::Create<bool>(
RColumnModel(GetColumnRepresentative()[0]), 0));
955 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
956 fColumns.emplace_back(Detail::RColumn::Create<bool>(
RColumnModel(onDiskTypes[0]), 0));
970 return representations;
975 fColumns.emplace_back(Detail::RColumn::Create<float>(
RColumnModel(GetColumnRepresentative()[0]), 0));
980 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
981 fColumns.emplace_back(Detail::RColumn::Create<float>(
RColumnModel(onDiskTypes[0]), 0));
997 return representations;
1002 fColumns.emplace_back(Detail::RColumn::Create<double>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1007 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1008 fColumns.emplace_back(Detail::RColumn::Create<double>(
RColumnModel(onDiskTypes[0]), 0));
1018 fTypeAlias =
"Double32_t";
1028 return representations;
1033 fColumns.emplace_back(Detail::RColumn::Create<std::int16_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1038 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1039 fColumns.emplace_back(Detail::RColumn::Create<std::int16_t>(RColumnModel(onDiskTypes[0]), 0));
1044 visitor.VisitInt16Field(*
this);
1054 return representations;
1059 fColumns.emplace_back(Detail::RColumn::Create<std::uint16_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1064 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1065 fColumns.emplace_back(Detail::RColumn::Create<std::uint16_t>(RColumnModel(onDiskTypes[0]), 0));
1070 visitor.VisitUInt16Field(*
this);
1080 return representations;
1085 fColumns.emplace_back(Detail::RColumn::Create<std::int32_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1090 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1091 fColumns.emplace_back(Detail::RColumn::Create<std::int32_t>(RColumnModel(onDiskTypes[0]), 0));
1096 visitor.VisitIntField(*
this);
1106 return representations;
1111 fColumns.emplace_back(Detail::RColumn::Create<std::uint32_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1116 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1117 fColumns.emplace_back(Detail::RColumn::Create<std::uint32_t>(RColumnModel(onDiskTypes[0]), 0));
1122 visitor.VisitUInt32Field(*
this);
1132 return representations;
1137 fColumns.emplace_back(Detail::RColumn::Create<std::uint64_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1142 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1143 fColumns.emplace_back(Detail::RColumn::Create<std::uint64_t>(RColumnModel(onDiskTypes[0]), 0));
1148 visitor.VisitUInt64Field(*
this);
1163 return representations;
1168 fColumns.emplace_back(Detail::RColumn::Create<std::int64_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1173 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1174 fColumns.emplace_back(Detail::RColumn::Create<std::int64_t>(RColumnModel(onDiskTypes[0]), 0));
1179 visitor.VisitInt64Field(*
this);
1192 return representations;
1197 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
1198 fColumns.emplace_back(Detail::RColumn::Create<char>(RColumnModel(GetColumnRepresentative()[1]), 1));
1203 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1204 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
1205 fColumns.emplace_back(Detail::RColumn::Create<char>(RColumnModel(onDiskTypes[1]), 1));
1210 std::destroy_at(
static_cast<std::string *
>(objPtr));
1216 auto typedValue =
static_cast<const std::string *
>(from);
1217 auto length = typedValue->length();
1218 fColumns[1]->AppendV(typedValue->data(),
length);
1220 fColumns[0]->Append(&fIndex);
1221 return length + fColumns[0]->GetElement()->GetPackedSize();
1226 auto typedValue =
static_cast<std::string *
>(to);
1227 RClusterIndex collectionStart;
1229 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
1231 typedValue->clear();
1233 typedValue->resize(nChars);
1234 fColumns[1]->ReadV(collectionStart, nChars,
const_cast<char *
>(typedValue->data()));
1240 visitor.VisitStringField(*
this);
1256 throw RException(
R__FAIL(
"RField: no I/O support for type " + std::string(className)));
1264 R__FAIL(std::string(className) +
" has an associated collection proxy; use RProxiedCollectionField instead"));
1274 TClass *
c = baseClass->GetClassPointer();
1276 c->GetName()).Unwrap();
1277 fTraits &= subField->GetTraits();
1278 Attach(std::move(subField),
1287 if (!dataMember->IsPersistent()) {
1293 std::string typeName{GetNormalizedTypeName(dataMember->GetTrueTypeName())};
1294 std::string typeAlias{GetNormalizedTypeName(dataMember->GetFullTypeName())};
1296 if (dataMember->Property() &
kIsArray) {
1297 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim)
1298 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
1301 fTraits &= subField->GetTraits();
1302 Attach(std::move(subField),
1309 fMaxAlignment = std::max(fMaxAlignment,
child->GetAlignment());
1310 fSubFieldsInfo.push_back(info);
1311 RFieldBase::Attach(std::move(
child));
1317 for (
const auto rule : rules) {
1322 auto func = rule->GetReadFunctionPointer();
1324 fReadCallbacks.emplace_back([func, classp](
void *
target) {
1328 func(
static_cast<char *
>(
target), &oldObj);
1329 oldObj.fClass =
nullptr;
1334std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1338 SyncFieldIDs(*
this, *
result);
1344 std::size_t nbytes = 0;
1345 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1346 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fSubFieldsInfo[i].fOffset);
1353 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1354 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1360 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1361 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fSubFieldsInfo[i].fOffset);
1369 const auto ruleset =
fClass->GetSchemaRules();
1373 if (rule->GetTarget() ==
nullptr)
1376 const auto dataMember = klass->GetDataMember(
target->GetString());
1377 if (!dataMember || dataMember->IsPersistent()) {
1379 << dataMember->GetName();
1386 auto rules = ruleset->FindRules(
fClass->GetName(),
static_cast<Int_t>(GetOnDiskTypeVersion()));
1387 rules.erase(std::remove_if(rules.begin(), rules.end(), referencesNonTransientMembers), rules.end());
1388 AddReadCallbacksFromIORules(rules,
fClass);
1398 fClass->Destructor(objPtr,
true );
1402std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
1405 std::vector<RValue>
result;
1406 for (
unsigned i = 0; i < fSubFields.size(); i++) {
1407 result.emplace_back(fSubFields[i]->BindValue(
value.Get<
unsigned char>() + fSubFieldsInfo[i].fOffset));
1415 return fClass->GetClassSize();
1420 return fClass->GetClassVersion();
1431 :
REnumField(fieldName, enumName,
TEnum::GetEnum(std::string(enumName).c_str()))
1438 if (enump ==
nullptr) {
1439 throw RException(
R__FAIL(
"RField: no I/O support for enum type " + std::string(enumName)));
1457 default:
throw RException(
R__FAIL(
"Unsupported underlying integral type for enum type " + std::string(enumName)));
1464 std::unique_ptr<RFieldBase> intField)
1467 Attach(std::move(intField));
1471std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1474 auto newIntField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1475 return std::unique_ptr<REnumField>(
new REnumField(newName, GetType(), std::move(newIntField)));
1478std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
1481 std::vector<RValue>
result;
1482 result.emplace_back(fSubFields[0]->BindValue(
value.GetRawPtr()));
1502 (ifuncs.
fNext !=
nullptr));
1507 std::string_view typeName,
TClass *classp)
1510 if (classp ==
nullptr)
1511 throw RException(
R__FAIL(
"RField: no I/O support for collection proxy type " + std::string(typeName)));
1513 throw RException(
R__FAIL(std::string(typeName) +
" has no associated collection proxy"));
1518 if (
fProxy->HasPointers())
1519 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
1520 if (!
fProxy->GetCollectionClass()->HasDictionary()) {
1522 GetNormalizedTypeName(
fProxy->GetCollectionClass()->GetName())));
1530 std::string_view typeName,
1531 std::unique_ptr<Detail::RFieldBase> itemField)
1535 Attach(std::move(itemField));
1539 std::string_view typeName)
1545 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
1547 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> itemField;
1549 if (
auto valueClass =
fProxy->GetValueClass()) {
1551 itemField = RFieldBase::Create(
"_0", valueClass->GetName()).Unwrap();
1553 switch (
fProxy->GetType()) {
1555 case EDataType::kUChar_t: itemField = std::make_unique<RField<std::uint8_t>>(
"_0");
break;
1556 case EDataType::kShort_t: itemField = std::make_unique<RField<std::int16_t>>(
"_0");
break;
1558 case EDataType::kInt_t: itemField = std::make_unique<RField<std::int32_t>>(
"_0");
break;
1559 case EDataType::kUInt_t: itemField = std::make_unique<RField<std::uint32_t>>(
"_0");
break;
1562 itemField = std::make_unique<RField<std::int64_t>>(
"_0");
1566 itemField = std::make_unique<RField<std::uint64_t>>(
"_0");
1577 Attach(std::move(itemField));
1580std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1583 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1584 return std::unique_ptr<RProxiedCollectionField>(
1590 std::size_t nbytes = 0;
1594 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1595 nbytes += CallAppendOn(*fSubFields[0], ptr);
1600 fColumns[0]->Append(&fNWritten);
1601 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
1608 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1616 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
1617 CallReadOn(*fSubFields[0], collectionStart + (i++), elementPtr);
1620 fProxy->Commit(obj);
1629 return representations;
1634 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1639 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1640 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
1653 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1654 CallDestroyValueOn(*fSubFields[0], ptr,
true );
1657 fProxy->Destructor(objPtr,
true );
1661std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
1664 std::vector<RValue>
result;
1667 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1668 result.emplace_back(fSubFields[0]->BindValue(ptr));
1681 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
1682 const std::vector<std::size_t> &offsets, std::string_view typeName)
1687 for (
auto &item : itemFields) {
1696 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields)
1700 for (
auto &item : itemFields) {
1704 fSize += item->GetValueSize();
1714 std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
1721 if (itemAlignment > 1) {
1722 auto remainder = baseOffset % itemAlignment;
1724 return itemAlignment - remainder;
1729std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1732 std::vector<std::unique_ptr<Detail::RFieldBase>> cloneItems;
1733 for (
auto &item : fSubFields)
1734 cloneItems.emplace_back(item->Clone(item->GetName()));
1735 return std::unique_ptr<RRecordField>(
new RRecordField(newName, std::move(cloneItems), fOffsets, GetType()));
1740 std::size_t nbytes = 0;
1741 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1742 nbytes += CallAppendOn(*fSubFields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
1749 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1750 CallReadOn(*fSubFields[i], globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
1756 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1757 CallReadOn(*fSubFields[i], clusterIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
1763 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1764 CallGenerateValueOn(*fSubFields[i],
static_cast<unsigned char *
>(where) + fOffsets[i]);
1770 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1771 CallDestroyValueOn(*fSubFields[i],
static_cast<unsigned char *
>(objPtr) + fOffsets[i],
true );
1776std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
1779 std::vector<RValue>
result;
1780 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
1781 result.emplace_back(fSubFields[i]->BindValue(
value.Get<
unsigned char>() + fOffsets[i]));
1796 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
1797 :
ROOT::Experimental::Detail::RFieldBase(
1799 , fItemSize(itemField->GetValueSize()), fNWritten(0)
1801 Attach(std::move(itemField));
1804std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1807 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1808 return std::make_unique<RVectorField>(newName, std::move(newItemField));
1813 auto typedValue =
static_cast<const std::vector<char> *
>(from);
1814 R__ASSERT((typedValue->size() % fItemSize) == 0);
1815 std::size_t nbytes = 0;
1816 auto count = typedValue->size() / fItemSize;
1818 if (fSubFields[0]->IsSimple() && count) {
1819 GetPrincipalColumnOf(*fSubFields[0])->AppendV(typedValue->data(), count);
1820 nbytes += count * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
1822 for (
unsigned i = 0; i < count; ++i) {
1823 nbytes += CallAppendOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
1828 fColumns[0]->Append(&fNWritten);
1829 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
1834 auto typedValue =
static_cast<std::vector<char> *
>(to);
1838 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1840 if (fSubFields[0]->IsSimple()) {
1841 typedValue->resize(nItems * fItemSize);
1843 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, typedValue->data());
1848 const auto oldNItems = typedValue->size() / fItemSize;
1849 const bool canRealloc = oldNItems < nItems;
1850 bool allDeallocated =
false;
1851 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible)) {
1852 allDeallocated = canRealloc;
1853 for (std::size_t i = allDeallocated ? 0 : nItems; i < oldNItems; ++i) {
1854 CallDestroyValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize),
true );
1857 typedValue->resize(nItems * fItemSize);
1858 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)) {
1859 for (std::size_t i = allDeallocated ? 0 : oldNItems; i < nItems; ++i) {
1860 CallGenerateValueOn(*fSubFields[0], typedValue->data() + (i * fItemSize));
1864 for (std::size_t i = 0; i < nItems; ++i) {
1865 CallReadOn(*fSubFields[0], collectionStart + i, typedValue->data() + (i * fItemSize));
1875 return representations;
1880 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
1885 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
1886 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
1891 auto vecPtr =
static_cast<std::vector<char> *
>(objPtr);
1892 R__ASSERT((vecPtr->size() % fItemSize) == 0);
1893 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible)) {
1894 auto nItems = vecPtr->size() / fItemSize;
1895 for (
unsigned i = 0; i < nItems; ++i) {
1896 CallDestroyValueOn(*fSubFields[0], vecPtr->data() + (i * fItemSize),
true );
1899 std::destroy_at(vecPtr);
1904std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
1907 auto vec =
value.Get<std::vector<char>>();
1909 auto nItems =
vec->size() / fItemSize;
1910 std::vector<RValue>
result;
1911 for (
unsigned i = 0; i < nItems; ++i) {
1912 result.emplace_back(fSubFields[0]->BindValue(
vec->data() + (i * fItemSize)));
1926 :
ROOT::Experimental::Detail::RFieldBase(fieldName,
"ROOT::VecOps::RVec<" + itemField->GetType() +
">",
1928 fItemSize(itemField->GetValueSize()), fNWritten(0)
1930 Attach(std::move(itemField));
1934std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1937 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1938 return std::make_unique<RRVecField>(newName, std::move(newItemField));
1943 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(from);
1945 std::size_t nbytes = 0;
1946 if (fSubFields[0]->IsSimple() && *sizePtr) {
1947 GetPrincipalColumnOf(*fSubFields[0])->AppendV(*beginPtr, *sizePtr);
1948 nbytes += *sizePtr * GetPrincipalColumnOf(*fSubFields[0])->GetElement()->GetPackedSize();
1950 auto begin =
reinterpret_cast<const char *
>(*beginPtr);
1951 for (std::int32_t i = 0; i < *sizePtr; ++i) {
1952 nbytes += CallAppendOn(*fSubFields[0], begin + i * fItemSize);
1956 fNWritten += *sizePtr;
1957 fColumns[0]->Append(&fNWritten);
1958 return nbytes + fColumns[0]->GetElement()->GetPackedSize();
1966 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(to);
1971 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1972 char *begin =
reinterpret_cast<char *
>(*beginPtr);
1973 const std::size_t oldSize = *sizePtr;
1977 const bool owns = (*capacityPtr != -1);
1978 const bool needsConstruct = !(fSubFields[0]->GetTraits() & kTraitTriviallyConstructible);
1979 const bool needsDestruct = owns && !(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible);
1982 if (needsDestruct) {
1983 for (std::size_t i = nItems; i < oldSize; ++i) {
1984 CallDestroyValueOn(*fSubFields[0], begin + (i * fItemSize),
true );
1989 if (std::int32_t(nItems) > *capacityPtr) {
1992 if (needsDestruct) {
1993 for (std::size_t i = 0u; i < oldSize; ++i) {
1994 CallDestroyValueOn(*fSubFields[0], begin + (i * fItemSize),
true );
2005 *beginPtr =
malloc(nItems * fItemSize);
2007 begin =
reinterpret_cast<char *
>(*beginPtr);
2008 *capacityPtr = nItems;
2011 if (needsConstruct) {
2012 for (std::size_t i = 0u; i < oldSize; ++i)
2013 CallGenerateValueOn(*fSubFields[0], begin + (i * fItemSize));
2019 if (needsConstruct) {
2020 for (std::size_t i = oldSize; i < nItems; ++i)
2021 CallGenerateValueOn(*fSubFields[0], begin + (i * fItemSize));
2024 if (fSubFields[0]->IsSimple() && nItems) {
2025 GetPrincipalColumnOf(*fSubFields[0])->ReadV(collectionStart, nItems, begin);
2030 for (std::size_t i = 0; i < nItems; ++i) {
2031 CallReadOn(*fSubFields[0], collectionStart + i, begin + (i * fItemSize));
2037 if (!fSubFields[0]->IsSimple())
2038 return RFieldBase::ReadBulkImpl(bulkSpec);
2043 bulkSpec.
fAuxData->resize(
sizeof(std::size_t));
2044 *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data()) = fSubFields[0]->GetValueSize();
2046 const auto itemValueSize = *
reinterpret_cast<std::size_t *
>(bulkSpec.
fAuxData->data());
2047 unsigned char *itemValueArray = bulkSpec.
fAuxData->data() +
sizeof(std::size_t);
2048 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(bulkSpec.
fValues);
2054 this->GetCollectionInfo(bulkSpec.
fFirstIndex, &firstItemIndex, &collectionSize);
2055 *beginPtr = itemValueArray;
2056 *sizePtr = collectionSize;
2061 auto lastOffset = firstItemIndex.
GetIndex() + collectionSize;
2063 std::size_t nValues = 1;
2064 std::size_t nItems = collectionSize;
2065 while (nRemainingValues > 0) {
2068 const std::size_t nBatch = std::min(nRemainingValues, nElementsUntilPageEnd);
2069 for (std::size_t i = 0; i < nBatch; ++i) {
2070 const auto size = offsets[i] - lastOffset;
2071 std::tie(beginPtr, sizePtr,
_) = GetRVecDataMembers(
2072 reinterpret_cast<unsigned char *
>(bulkSpec.
fValues) + (nValues + i) *
fValueSize);
2073 *beginPtr = itemValueArray + nItems * itemValueSize;
2077 lastOffset = offsets[i];
2079 nRemainingValues -= nBatch;
2083 bulkSpec.
fAuxData->resize(
sizeof(std::size_t) + nItems * itemValueSize);
2085 const auto delta = itemValueArray - (bulkSpec.
fAuxData->data() +
sizeof(std::size_t));
2087 auto beginPtrAsUChar =
reinterpret_cast<unsigned char *
>(bulkSpec.
fValues);
2088 for (std::size_t i = 0; i < bulkSpec.
fCount; ++i) {
2089 *
reinterpret_cast<unsigned char **
>(beginPtrAsUChar) -= delta;
2094 GetPrincipalColumnOf(*fSubFields[0])->ReadV(firstItemIndex, nItems, itemValueArray - delta);
2095 return RBulkSpec::kAllSet;
2104 return representations;
2109 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2114 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2115 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
2122 void **beginPtr =
new (where)(
void *)(
nullptr);
2123 std::int32_t *sizePtr =
new (
reinterpret_cast<void *
>(beginPtr + 1)) std::int32_t(0);
2124 new (sizePtr + 1) std::int32_t(-1);
2129 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(objPtr);
2131 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2132 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible)) {
2133 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2134 CallDestroyValueOn(*fSubFields[0], begin + i * fItemSize,
true );
2140 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
2141 const auto alignOfT = fSubFields[0]->GetAlignment();
2142 auto paddingMiddle = dataMemberSz % alignOfT;
2143 if (paddingMiddle != 0)
2144 paddingMiddle = alignOfT - paddingMiddle;
2145 const bool isSmall = (
reinterpret_cast<void *
>(begin) == (beginPtr + dataMemberSz + paddingMiddle));
2147 const bool owns = (*capacityPtr != -1);
2148 if (!isSmall && owns)
2155std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
2158 auto [beginPtr, sizePtr,
_] = GetRVecDataMembers(
value.GetRawPtr());
2160 std::vector<RValue>
result;
2161 char *begin =
reinterpret_cast<char *
>(*beginPtr);
2162 for (std::int32_t i = 0; i < *sizePtr; ++i) {
2163 result.emplace_back(fSubFields[0]->BindValue(begin + i * fItemSize));
2182 constexpr auto dataMemberSz =
sizeof(
void *) + 2 *
sizeof(std::int32_t);
2183 const auto alignOfT = fSubFields[0]->GetAlignment();
2184 const auto sizeOfT = fSubFields[0]->GetValueSize();
2187 const auto inlineStorageSz = [&] {
2188#ifdef R__HAS_HARDWARE_INTERFERENCE_SIZE
2190 constexpr unsigned cacheLineSize = std::hardware_destructive_interference_size;
2192 constexpr unsigned cacheLineSize = 64u;
2194 const unsigned elementsPerCacheLine = (cacheLineSize - dataMemberSz) / sizeOfT;
2195 constexpr unsigned maxInlineByteSize = 1024;
2196 const unsigned nElements =
2197 elementsPerCacheLine >= 8 ? elementsPerCacheLine : (sizeOfT * 8 > maxInlineByteSize ? 0 : 8);
2198 return nElements * sizeOfT;
2203 auto paddingMiddle = dataMemberSz % alignOfT;
2204 if (paddingMiddle != 0)
2205 paddingMiddle = alignOfT - paddingMiddle;
2208 const auto alignOfRVecT = GetAlignment();
2209 auto paddingEnd = (dataMemberSz + paddingMiddle + inlineStorageSz) % alignOfRVecT;
2210 if (paddingEnd != 0)
2211 paddingEnd = alignOfRVecT - paddingEnd;
2213 return dataMemberSz + inlineStorageSz + paddingMiddle + paddingEnd;
2225 return std::max({
alignof(
void *),
alignof(std::int32_t), fSubFields[0]->GetAlignment()});
2244 auto typedValue =
static_cast<const std::vector<bool> *
>(from);
2245 auto count = typedValue->size();
2246 for (
unsigned i = 0; i < count; ++i) {
2247 bool bval = (*typedValue)[i];
2248 CallAppendOn(*fSubFields[0], &bval);
2251 fColumns[0]->Append(&fNWritten);
2252 return count + fColumns[0]->GetElement()->GetPackedSize();
2257 auto typedValue =
static_cast<std::vector<bool> *
>(to);
2260 RClusterIndex collectionStart;
2261 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
2263 typedValue->resize(nItems);
2264 for (
unsigned i = 0; i < nItems; ++i) {
2266 CallReadOn(*fSubFields[0], collectionStart + i, &bval);
2267 (*typedValue)[i] = bval;
2274 static RColumnRepresentations representations(
2277 return representations;
2282 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(GetColumnRepresentative()[0]), 0));
2287 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2288 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(RColumnModel(onDiskTypes[0]), 0));
2291std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
2294 const static bool trueValue =
true;
2295 const static bool falseValue =
false;
2297 auto typedValue =
value.Get<std::vector<bool>>();
2298 auto count = typedValue->size();
2299 std::vector<RValue>
result;
2300 for (
unsigned i = 0; i < count; ++i) {
2301 if ((*typedValue)[i])
2302 result.emplace_back(fSubFields[0]->BindValue(
const_cast<bool *
>(&trueValue)));
2304 result.emplace_back(fSubFields[0]->BindValue(
const_cast<bool *
>(&falseValue)));
2311 std::destroy_at(
static_cast<std::vector<bool> *
>(objPtr));
2317 visitor.VisitVectorBoolField(*
this);
2325 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength)
2326 :
ROOT::Experimental::Detail::RFieldBase(
2327 fieldName,
"std::array<" + itemField->GetType() +
"," + std::to_string(arrayLength) +
">",
2329 , fItemSize(itemField->GetValueSize()), fArrayLength(arrayLength)
2331 fTraits |= itemField->GetTraits() & ~kTraitMappable;
2332 Attach(std::move(itemField));
2335std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2338 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
2339 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
2344 std::size_t nbytes = 0;
2345 auto arrayPtr =
static_cast<const unsigned char *
>(from);
2346 for (
unsigned i = 0; i < fArrayLength; ++i) {
2347 nbytes += CallAppendOn(*fSubFields[0], arrayPtr + (i * fItemSize));
2354 auto arrayPtr =
static_cast<unsigned char *
>(to);
2355 for (
unsigned i = 0; i < fArrayLength; ++i) {
2356 CallReadOn(*fSubFields[0], globalIndex * fArrayLength + i, arrayPtr + (i * fItemSize));
2362 auto arrayPtr =
static_cast<unsigned char *
>(to);
2363 for (
unsigned i = 0; i < fArrayLength; ++i) {
2365 arrayPtr + (i * fItemSize));
2371 if (fSubFields[0]->GetTraits() & kTraitTriviallyConstructible)
2374 auto arrayPtr =
reinterpret_cast<unsigned char *
>(where);
2375 for (
unsigned i = 0; i < fArrayLength; ++i) {
2376 CallGenerateValueOn(*fSubFields[0], arrayPtr + (i * fItemSize));
2382 auto arrayPtr =
static_cast<unsigned char *
>(objPtr);
2383 if (!(fSubFields[0]->GetTraits() & kTraitTriviallyDestructible)) {
2384 for (
unsigned i = 0; i < fArrayLength; ++i) {
2385 CallDestroyValueOn(*fSubFields[0], arrayPtr + (i * fItemSize),
true );
2391std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
2394 auto arrayPtr =
value.Get<
unsigned char>();
2395 std::vector<RValue>
result;
2396 for (
unsigned i = 0; i < fArrayLength; ++i) {
2397 result.emplace_back(fSubFields[0]->BindValue(arrayPtr + (i * fItemSize)));
2410 :
ROOT::Experimental::Detail::RFieldBase(fieldName,
"std::bitset<" + std::to_string(
N) +
">",
2421 return representations;
2426 fColumns.emplace_back(Detail::RColumn::Create<bool>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2431 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2432 fColumns.emplace_back(Detail::RColumn::Create<bool>(
RColumnModel(onDiskTypes[0]), 0));
2437 const auto *asULongArray =
static_cast<const Word_t *
>(from);
2440 for (std::size_t word = 0; word < (fN + kBitsPerWord - 1) / kBitsPerWord; ++word) {
2441 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < fN); ++
mask, ++i) {
2442 elementValue = (asULongArray[word] & (
static_cast<Word_t>(1) <<
mask)) != 0;
2443 fColumns[0]->Append(&elementValue);
2451 auto *asULongArray =
static_cast<Word_t *
>(to);
2453 for (std::size_t i = 0; i < fN; ++i) {
2454 fColumns[0]->Read(globalIndex * fN + i, &elementValue);
2456 Word_t bit =
static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
2457 asULongArray[i / kBitsPerWord] = (asULongArray[i / kBitsPerWord] & ~mask) | bit;
2471 for (
size_t i = 0; i < itemFields.size(); ++i) {
2472 result += itemFields[i]->GetType() +
",";
2480 std::string_view fieldName,
const std::vector<Detail::RFieldBase *> &itemFields)
2481 :
ROOT::Experimental::Detail::RFieldBase(fieldName,
2487 auto nFields = itemFields.size();
2490 for (
unsigned int i = 0; i < nFields; ++i) {
2493 fTraits &= itemFields[i]->GetTraits();
2494 Attach(std::unique_ptr<Detail::RFieldBase>(itemFields[i]));
2499std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2502 auto nFields = fSubFields.size();
2503 std::vector<Detail::RFieldBase *> itemFields;
2504 for (
unsigned i = 0; i < nFields; ++i) {
2506 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetName()).release());
2508 return std::make_unique<RVariantField>(newName, itemFields);
2513 auto index = *(
reinterpret_cast<const char *
>(variantPtr) + fTagOffset);
2519 auto index =
reinterpret_cast<char *
>(variantPtr) + fTagOffset;
2520 *
index =
static_cast<char>(tag - 1);
2525 auto tag = GetTag(from);
2526 std::size_t nbytes = 0;
2529 nbytes += CallAppendOn(*fSubFields[tag - 1], from);
2530 index = fNWritten[tag - 1]++;
2533 fColumns[0]->Append(&varSwitch);
2541 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
2547 CallGenerateValueOn(*fSubFields[tag - 1], to);
2548 CallReadOn(*fSubFields[tag - 1], variantIndex, to);
2557 return representations;
2562 fColumns.emplace_back(Detail::RColumn::Create<RColumnSwitch>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2567 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2568 fColumns.emplace_back(Detail::RColumn::Create<RColumnSwitch>(
RColumnModel(onDiskTypes[0]), 0));
2573 memset(where, 0, GetValueSize());
2574 CallGenerateValueOn(*fSubFields[0], where);
2580 auto tag = GetTag(objPtr);
2582 CallDestroyValueOn(*fSubFields[tag - 1], objPtr,
true );
2589 return fMaxItemSize + fMaxAlignment;
2594 std::fill(fNWritten.begin(), fNWritten.end(), 0);
2600 std::unique_ptr<Detail::RFieldBase> itemField)
2605std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2608 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetName());
2609 return std::unique_ptr<RSetField>(
new RSetField(newName, GetType(), std::move(newItemField)));
2615 std::unique_ptr<Detail::RFieldBase> itemField)
2618 Attach(std::move(itemField));
2627 return representations;
2632 if (HasDefaultColumnRepresentative()) {
2633 if (fSubFields[0]->GetValueSize() < 4) {
2638 fDefaultItemValue = std::make_unique<RValue>(fSubFields[0]->GenerateValue());
2641 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2647 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2651 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
2659 fPrincipalColumn->Append(&
mask);
2660 return 1 + CallAppendOn(*fSubFields[0], fDefaultItemValue->GetRawPtr());
2662 fPrincipalColumn->Append(&fNWritten);
2669 auto nbytesItem = CallAppendOn(*fSubFields[0], from);
2672 fPrincipalColumn->Append(&
mask);
2673 return 1 + nbytesItem;
2676 fPrincipalColumn->Append(&fNWritten);
2685 const bool isValidItem = *fPrincipalColumn->Map<
bool>(globalIndex);
2686 return isValidItem ? fPrincipalColumn->GetClusterIndex(globalIndex) : nullIndex;
2690 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
2691 return (collectionSize == 0) ? nullIndex : collectionStart;
2703 std::unique_ptr<Detail::RFieldBase> itemField)
2708std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2711 auto newItemField = fSubFields[0]->
Clone(fSubFields[0]->GetName());
2712 return std::make_unique<RUniquePtrField>(newName, GetType(), std::move(newItemField));
2717 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
2719 return AppendValue(typedValue->get());
2721 return AppendNull();
2727 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
2728 bool isValidValue =
static_cast<bool>(*ptr);
2730 auto itemIndex = GetItemIndex(globalIndex);
2733 void *valuePtr =
nullptr;
2735 valuePtr = ptr->get();
2737 if (isValidValue && !isValidItem) {
2739 CallDestroyValueOn(*fSubFields[0], valuePtr,
false );
2746 if (!isValidValue) {
2747 valuePtr =
malloc(fSubFields[0]->GetValueSize());
2748 CallGenerateValueOn(*fSubFields[0], valuePtr);
2749 ptr->reset(
reinterpret_cast<char *
>(valuePtr));
2752 CallReadOn(*fSubFields[0], itemIndex, valuePtr);
2757 auto typedPtr =
static_cast<std::unique_ptr<char> *
>(objPtr);
2759 CallDestroyValueOn(*fSubFields[0], typedPtr->get(),
false );
2760 typedPtr->release();
2765std::vector<ROOT::Experimental::Detail::RFieldBase::RValue>
2768 std::vector<RValue>
result;
2769 auto ptr =
value.Get<std::unique_ptr<char>>();
2771 result.emplace_back(fSubFields[0]->BindValue(ptr->get()));
2778std::string ROOT::Experimental::RPairField::RPairField::GetTypeList(
2779 const std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields)
2781 return itemFields[0]->GetType() +
"," + itemFields[1]->GetType();
2785 std::array<std::unique_ptr<Detail::RFieldBase>, 2> &&itemFields,
2786 const std::array<std::size_t, 2> &offsets)
2787 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
2788 "std::pair<" + GetTypeList(itemFields) +
">")
2793 std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields)
2795 "std::pair<" + GetTypeList(itemFields) +
">")
2802 fOffsets[0] =
fClass->GetDataMember(
"first")->GetOffset();
2803 fOffsets[1] =
fClass->GetDataMember(
"second")->GetOffset();
2806std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2809 std::array<std::unique_ptr<Detail::RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetName()),
2810 fSubFields[1]->Clone(fSubFields[1]->GetName())};
2812 std::unique_ptr<RPairField>
result(
new RPairField(newName, std::move(items), {fOffsets[0], fOffsets[1]}));
2824 fClass->Destructor(objPtr,
true );
2830std::string ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
2831 const std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
2834 if (itemFields.empty())
2835 throw RException(
R__FAIL(
"the type list for std::tuple must have at least one element"));
2836 for (
size_t i = 0; i < itemFields.size(); ++i) {
2837 result += itemFields[i]->GetType() +
",";
2844 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
2845 const std::vector<std::size_t> &offsets)
2846 :
ROOT::Experimental::
RRecordField(fieldName, std::move(itemFields), offsets,
2847 "std::tuple<" + GetTypeList(itemFields) +
">")
2852 std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
2854 "std::tuple<" + GetTypeList(itemFields) +
">")
2866 for (
unsigned i = 0; i < fSubFields.size(); ++i) {
2867 std::string memberName(
"_" + std::to_string(i));
2868 auto member =
fClass->GetRealData(memberName.c_str());
2871 fOffsets.push_back(member->GetThisOffset());
2875std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2878 std::vector<std::unique_ptr<Detail::RFieldBase>> items;
2879 for (
const auto &item : fSubFields)
2880 items.push_back(item->Clone(item->GetName()));
2882 std::unique_ptr<RTupleField>
result(
new RTupleField(newName, std::move(items), fOffsets));
2894 fClass->Destructor(objPtr,
true );
2901 std::string_view
name,
2902 std::shared_ptr<RCollectionNTupleWriter> collectionNTuple,
2903 std::unique_ptr<RNTupleModel> collectionModel)
2905 , fCollectionNTuple(collectionNTuple)
2907 for (
unsigned i = 0; i < collectionModel->GetFieldZero()->
fSubFields.size(); ++i) {
2908 auto& subField = collectionModel->GetFieldZero()->fSubFields[i];
2909 Attach(std::move(subField));
2920 return representations;
2925 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(GetColumnRepresentative()[0]), 0));
2930 auto onDiskTypes = EnsureCompatibleColumnTypes(desc);
2931 fColumns.emplace_back(Detail::RColumn::Create<ClusterSize_t>(
RColumnModel(onDiskTypes[0]), 0));
2935std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
2939 for (
auto&
f : fSubFields) {
2948 *fCollectionNTuple->GetOffsetPtr() = 0;
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
#define R__LOG_WARNING(...)
TObject * clone(const char *newname) const override
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
static std::string GetTypeName(EColumnType type)
Similar to RValue but manages an array of consecutive values.
void * fValues
Pointer to the start of the array.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
void Reset(const RClusterIndex &firstIndex, std::size_t size)
Sets a new range for the bulk.
RBulk & operator=(const RBulk &)=delete
Some fields have multiple possible column representations, e.g.
TypesList_t fSerializationTypes
TypesList_t fDeserializationTypes
The union of the serialization types and the deserialization extra types.
std::vector< ColumnRepresentation_t > TypesList_t
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
RFieldBase * GetParent() const
void SetOnDiskId(DescriptorId_t id)
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type for writing.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
RConstSchemaIterator cend() const
RFieldBase * fParent
Sub fields point to their mother field.
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &canonicalType, const std::string &typeAlias)
Factory method to resurrect a field from the stored on-disk type information.
std::string GetName() const
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.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl.
int fTraits
Properties of the type that allow for optimizations of collections of that type.
static constexpr int kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
friend class ROOT::Experimental::RCollectionField
void RemoveReadCallback(size_t idx)
RValue GenerateValue()
Generates an object of the field type and allocates new initialized memory according to the type.
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, void *to)
void SetDescription(std::string_view description)
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
bool fIsSimple
A field qualifies as simple if it is both mappable and has no post-read callback.
std::string fType
The C++ type captured by this field.
std::function< void(void *)> ReadCallback_t
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given a value for this field.
std::string fName
The field name relative to its parent field.
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...
void ConnectPageSource(RPageSource &pageSource)
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
virtual void DestroyValue(void *objPtr, bool dtorOnly=false) const
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
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 fNRepetitions
For fixed sized arrays, the array length.
virtual void AcceptVisitor(RFieldVisitor &visitor) const
ENTupleStructure fStructure
The role of this field in the data model structure.
void AutoAdjustColumnTypes(const RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots ("grandparent.parent....
const ColumnRepresentation_t & GetColumnRepresentative() const
Returns the fColumnRepresentative pointee or, if unset, the field's default representative.
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
std::vector< RFieldBase * > GetSubFields() const
void SetColumnRepresentative(const ColumnRepresentation_t &representative)
Fixes a column representative.
void ConnectPageSink(RPageSink &pageSink, NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
RConstSchemaIterator cbegin() const
static constexpr int kTraitTriviallyConstructible
No constructor needs to be called, i.e.
static constexpr int kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. DestroyValue() is a no-op.
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const RNTupleDescriptor &desc) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId.
NTupleSize_t EntryToColumnElementIndex(NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and viceversa.
std::vector< EColumnType > ColumnRepresentation_t
RColumn * fPrincipalColumn
Points into fColumns.
Abstract base class for classes implementing the visitor design pattern.
virtual void VisitProxiedCollectionField(const RProxiedCollectionField &field)
virtual void VisitBoolField(const RField< bool > &field)
virtual void VisitBitsetField(const RBitsetField &field)
virtual void VisitNullableField(const RNullableField &field)
virtual void VisitFieldZero(const RFieldZero &field)
virtual void VisitRVecField(const RRVecField &field)
virtual void VisitCardinalityField(const RCardinalityField &field)
virtual void VisitEnumField(const REnumField &field)
virtual void VisitField(const Detail::RFieldBase &field)=0
virtual void VisitDoubleField(const RField< double > &field)
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)
Abstract interface to write data into an ntuple.
const RNTupleWriteOptions & GetWriteOptions() const
Returns the sink's write options.
Abstract interface to read data from an ntuple.
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
void DestroyValue(void *objPtr, bool dtorOnly=false) const final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
void ReadInClusterImpl(const RClusterIndex &clusterIndex, void *to) final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
RArrayField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
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::unique_ptr< Detail::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.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
RBitsetField(std::string_view fieldName, std::size_t N)
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
The field for a class with dictionary.
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
void OnConnectPageSource() final
Called by ConnectPageSource() only once connected; derived classes may override this as appropriate.
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
void Attach(std::unique_ptr< Detail::RFieldBase > child, RSubFieldInfo info)
void DestroyValue(void *objPtr, bool dtorOnly=false) const final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void AddReadCallbacksFromIORules(const std::span< const TSchemaRule * > rules, TClass *classp=nullptr)
Register post-read callbacks corresponding to a list of ROOT I/O customization rules.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void ReadInClusterImpl(const RClusterIndex &clusterIndex, void *to) final
RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
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
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void CommitClusterImpl() final
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Holds the static meta-data of an RNTuple column.
Holds the index and the tag of a kSwitch column.
The field for an unscoped or scoped enum with dictionary.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::unique_ptr< Detail::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.
REnumField(std::string_view fieldName, std::string_view enumName, TEnum *enump)
Base class for all ROOT issued exceptions.
std::uint32_t GetTypeVersion() const
The container field for an ntuple model, which itself has no physical representation.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Classes with dictionaries that can be inspected by TClass.
The on-storage meta-data of an ntuple.
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
RColumnDescriptorIterable GetColumnIterable() const
static std::unique_ptr< RNTupleModel > Create()
Common user-tunable settings for storing ntuples.
int GetCompression() const
bool GetHasSmallClusters() const
The field for values that may or may not be present in an entry.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
const Detail::RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
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< Detail::RFieldBase > itemField)
std::size_t AppendValue(const void *from)
The generic field for std::pair<T1, T2> types.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void DestroyValue(void *objPtr, bool dtorOnly=false) const override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
RPairField(std::string_view fieldName, std::array< std::unique_ptr< Detail::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)
The field for a class representing a collection of elements via TVirtualCollectionProxy.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
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
std::unique_ptr< TVirtualCollectionProxy > fProxy
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< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void DestroyValue(void *objPtr, bool dtorOnly=false) const override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
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 EvalValueSize() const
Evaluate the constant returned by GetValueSize.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
RRVecField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
void DestroyValue(void *objPtr, bool dtorOnly=false) const override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
size_t GetAlignment() const override
As a rule of thumb, the alignment is equal to the size of the type.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
General implementation of bulk read.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
std::size_t AppendImpl(const void *from) override
Operations on values of complex types, e.g.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) override
The field for an untyped record.
std::size_t fMaxAlignment
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
std::vector< std::size_t > fOffsets
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void ReadInClusterImpl(const RClusterIndex &clusterIndex, void *to) final
RRecordField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets, std::string_view typeName="")
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
void DestroyValue(void *objPtr, bool dtorOnly=false) const override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
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
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
The generic field for a std::set<Type>
RSetField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< Detail::RFieldBase > itemField)
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
The generic field for std::tuple<Ts...> types.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void DestroyValue(void *objPtr, bool dtorOnly=false) const override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
RTupleField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets)
RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< Detail::RFieldBase > itemField)
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::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void DestroyValue(void *objPtr, bool dtorOnly=false) const final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
void DestroyValue(void *objPtr, bool dtorOnly=false) const final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::vector< ClusterSize_t::ValueType > fNWritten
size_t fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
void SetTag(void *variantPtr, std::uint32_t tag) const
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void CommitClusterImpl() final
static std::string GetTypeList(const std::vector< Detail::RFieldBase * > &itemFields)
std::uint32_t GetTag(const void *variantPtr) const
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
RVariantField(std::string_view fieldName, const std::vector< Detail::RFieldBase * > &itemFields)
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given a value for this field.
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
void ReadGlobalImpl(NTupleSize_t globalIndex, void *to) final
void DestroyValue(void *objPtr, bool dtorOnly=false) const final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
RVectorField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
TClass instances represent classes, structs and namespaces in the ROOT type system.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
The TEnum class implements the enum type.
EDataType GetUnderlyingType() const
Get the underlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
@ kNeedDelete
The collection contains directly or indirectly (via other collection) some pointers that need explici...
virtual Next_t GetFunctionNext(Bool_t read=kTRUE)=0
Return a pointer to a function that can advance an iterator (see Next_t).
virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read=kTRUE)=0
virtual TVirtualCollectionProxy * Generate() const =0
Returns a clean object of the actual class that derives from TVirtualCollectionProxy.
virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read=kTRUE)=0
Return a pointer to a function that can create an iterator pair, where each iterator points to the be...
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RClusterSize ClusterSize_t
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr ClusterSize_t kInvalidClusterIndex(std::uint64_t(-1))
constexpr DescriptorId_t kInvalidDescriptorId
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=nullptr)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
Input parameter to ReadBulk() and ReadBulkImpl(). See RBulk class for more information.
bool * fMaskAvail
A bool array of size fCount, indicating the valid values in fValues.
std::vector< unsigned char > * fAuxData
Reference to memory owned by the RBulk class.
const bool * fMaskReq
A bool array of size fCount, indicating the required values in the requested range.
void * fValues
The destination area, which has to be a big enough array of valid objects of the correct type.
RClusterIndex fFirstIndex
Start of the bulk range.
std::size_t fCount
Size of the bulk range.
Wrap the integer in a struct in order to avoid template specialization clash with std::uint32_t.
TVirtualCollectionProxy::Next_t fNext
TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators
TVirtualCollectionProxy::CreateIterators_t fCreateIterators