51#include <unordered_set>
59TClass *EnsureValidClass(std::string_view className)
73 " cannot be constructed from a class that's not at least Interpreted"));
84 "use RProxiedCollectionField instead"));
95 R__FAIL(field.
GetTypeName() +
" has streamer mode enforced, not supported as native RNTuple class"));
105 if (realMember->GetStreamer()) {
107 " with a custom streamer; not supported natively in RNTuple"));
112TEnum *EnsureValidEnum(std::string_view enumName)
121void EnsureValidAlignment(std::size_t
alignment)
130std::string GetTypeList(std::span<std::unique_ptr<ROOT::RFieldBase>> itemFields,
bool useTypeAliases)
133 for (
size_t i = 0; i < itemFields.size(); ++i) {
134 if (useTypeAliases && !itemFields[i]->GetTypeAlias().empty()) {
135 result += itemFields[i]->GetTypeAlias();
137 result += itemFields[i]->GetTypeName();
150 std::string typePrefix;
166 if (
const auto pairField =
dynamic_cast<const ROOT::RPairField *
>(innerField)) {
167 std::string typePrefix;
175 const auto &items = pairField->GetConstSubfields();
176 std::string
type = typePrefix;
177 for (
int i : {0, 1}) {
178 if (useTypeAliases && !items[i]->GetTypeAlias().empty()) {
179 type += items[i]->GetTypeAlias();
181 type += items[i]->GetTypeName();
203 auto idSourceMember = desc.
FindFieldId(memberName, classFieldId);
205 return idSourceMember;
208 const auto &subFieldName = subFieldDesc.GetFieldName();
209 if (subFieldName.length() > 2 && subFieldName[0] ==
':' && subFieldName[1] ==
'_') {
210 idSourceMember = LookupMember(desc, memberName, subFieldDesc.GetId());
212 return idSourceMember;
222 if (classVersion != GetTypeVersion() || className != GetTypeName()) {
223 fStagingClass =
TClass::GetClass((className + std::string(
"@@") + std::to_string(classVersion)).c_str());
224 if (!fStagingClass) {
232 R__ASSERT(
static_cast<unsigned int>(fStagingClass->GetClassVersion()) == classVersion);
239 std::size_t stagingAreaSize = 0;
240 for (
const auto rule : rules) {
242 auto [itr, isNew] = fStagingItems.emplace(source->GetName(),
RStagingItem());
249 const auto memberFieldId = LookupMember(desc, source->
GetName(), classFieldDesc.
GetId());
251 throw RException(
R__FAIL(std::string(
"cannot find on disk rule source member ") + GetTypeName() +
"." +
255 auto memberType = source->GetTypeForDeclaration() + source->GetDimensions();
256 auto memberField = Create(
"" , std::string(memberType)).Unwrap();
257 memberField->SetOnDiskId(memberFieldId);
258 auto fieldZero = std::make_unique<RFieldZero>();
260 fieldZero->Attach(std::move(memberField));
261 stagingItem.
fField = std::move(fieldZero);
263 stagingItem.
fOffset = fStagingClass->GetDataMemberOffset(source->GetName());
267 stagingAreaSize = std::max(stagingAreaSize, stagingItem.
fOffset + stagingItem.
fField->begin()->GetValueSize());
271 if (stagingAreaSize) {
272 R__ASSERT(
static_cast<Int_t>(stagingAreaSize) <= fStagingClass->Size());
274 fStagingArea = std::make_unique<unsigned char[]>(stagingAreaSize);
276 for (
const auto &[
_, si] : fStagingItems) {
277 const auto &memberField = *si.fField->cbegin();
278 if (!(memberField.GetTraits() & kTraitTriviallyConstructible)) {
279 CallConstructValueOn(memberField, fStagingArea.get() + si.fOffset);
289 const auto ruleset =
fClass->GetSchemaRules();
296 rules = ruleset->FindRules(
fClass->GetName(),
fClass->GetClassVersion(),
fClass->GetCheckSum());
299 std::string normalizedName;
306 rules = ruleset->FindRules(normalizedName, fieldDesc->
GetTypeVersion());
312 std::unordered_map<std::string, std::string> sourceNameAndType;
313 std::size_t nskip = 0;
314 for (
auto itr = rules.begin(); itr != rules.end() - nskip;) {
315 const auto rule = *itr;
320 <<
"ignoring I/O customization rule with unsupported type: " << rule->GetRuleType();
321 itr = rules.erase(itr);
325 bool hasConflictingSourceMembers =
false;
327 auto memberType = source->GetTypeForDeclaration() + source->GetDimensions();
328 auto [itrSrc, isNew] = sourceNameAndType.emplace(source->GetName(), memberType);
329 if (!isNew && (itrSrc->second != memberType)) {
331 <<
"ignoring I/O customization rule due to conflicting source member type: " << itrSrc->second <<
" vs. "
332 << memberType <<
" for member " << source->GetName();
333 hasConflictingSourceMembers =
true;
337 if (hasConflictingSourceMembers) {
338 itr = rules.erase(itr);
343 if (rule->GetTarget() ==
nullptr) {
345 if (itr != rules.end() - nskip)
346 std::iter_swap(itr++, rules.end() - nskip);
359 if (func ==
nullptr) {
363 fReadCallbacks.emplace_back(
364 [func, subObjectOffset, stagingClass = fStagingClass, stagingArea = fStagingArea.get()](
void *
target) {
365 TVirtualObject onfileObj{nullptr};
366 onfileObj.fClass = stagingClass;
367 onfileObj.fObject = stagingArea;
368 func(
static_cast<char *
>(
target) + subObjectOffset, &onfileObj);
369 onfileObj.fObject =
nullptr;
377 fSubfieldsInfo(source.fSubfieldsInfo)
386 :
RClassField(fieldName, EnsureValidClass(className))
393 EnsureValidUserClass(
fClass, *
this,
"RClassField");
404 std::string renormalizedAlias;
412 if (baseClass->GetDelta() < 0) {
414 " virtually inherits from " + baseClass->GetName()));
416 TClass *
c = baseClass->GetClassPointer();
419 fTraits &= subField->GetTraits();
428 if (!dataMember->IsPersistent()) {
437 std::string typeName{dataMember->GetTrueTypeName()};
440 if (dataMember->Property() &
kIsArray) {
441 for (
int dim = 0,
n = dataMember->GetArrayDim(); dim <
n; ++dim) {
442 typeName +=
"[" + std::to_string(dataMember->GetMaxIndex(dim)) +
"]";
448 fTraits &= subField->GetTraits();
457 for (
const auto &[
_, si] : fStagingItems) {
458 if (!(si.fField->GetTraits() & kTraitTriviallyDestructible)) {
459 auto deleter = GetDeleterOf(*si.fField);
460 deleter->operator()(fStagingArea.get() + si.fOffset,
true );
468 fSubfieldsInfo.push_back(info);
474 return std::unique_ptr<RClassField>(
new RClassField(newName, *
this));
479 std::size_t nbytes = 0;
480 for (
unsigned i = 0; i < fSubfields.size(); i++) {
481 nbytes += CallAppendOn(*fSubfields[i],
static_cast<const unsigned char *
>(from) + fSubfieldsInfo[i].fOffset);
488 for (
const auto &[
_, si] : fStagingItems) {
489 CallReadOn(*si.fField, globalIndex, fStagingArea.get() + si.fOffset);
491 for (
unsigned i = 0; i < fSubfields.size(); i++) {
492 CallReadOn(*fSubfields[i], globalIndex,
static_cast<unsigned char *
>(to) + fSubfieldsInfo[i].fOffset);
498 for (
const auto &[
_, si] : fStagingItems) {
499 CallReadOn(*si.fField, localIndex, fStagingArea.get() + si.fOffset);
501 for (
unsigned i = 0; i < fSubfields.size(); i++) {
502 CallReadOn(*fSubfields[i], localIndex,
static_cast<unsigned char *
>(to) + fSubfieldsInfo[i].fOffset);
508 std::vector<const TSchemaRule *> rules;
511 std::unordered_set<std::string> regularSubfields;
514 int nOnDiskBaseClasses = 0;
518 rules = FindRules(
nullptr);
520 SetStagingClass(GetTypeName(), GetTypeVersion());
529 auto substitute = std::make_unique<RStreamerField>(GetFieldName(), GetTypeName());
530 substitute->SetOnDiskId(GetOnDiskId());
534 for (
auto linkId : fieldDesc.GetLinkIds()) {
536 regularSubfields.insert(subFieldDesc.GetFieldName());
537 if (!subFieldDesc.GetFieldName().empty() && subFieldDesc.GetFieldName()[0] ==
':')
538 nOnDiskBaseClasses++;
541 rules = FindRules(&fieldDesc);
550 if (GetTypeName() != descTypeName) {
551 throw RException(
R__FAIL(
"incompatible type name for field " + GetFieldName() +
": " + GetTypeName() +
552 " vs. " + descTypeName));
556 const bool hasSources = std::any_of(rules.begin(), rules.end(), [](
const auto &
r) {
557 return r->GetSource() && (r->GetSource()->GetEntries() > 0);
566 std::uint32_t assignedVersionForOnDiskLayout = fieldDesc.GetTypeVersion();
568 if (fieldDesc.GetTypeVersion() != GetTypeVersion() || *fieldDesc.GetTypeChecksum() !=
fClass->GetCheckSum() ||
569 fieldDesc.GetTypeName() != GetTypeName()) {
572 auto onDiskStreamerInfo = oldCl->FindStreamerInfo(*fieldDesc.GetTypeChecksum());
574 assignedVersionForOnDiskLayout = onDiskStreamerInfo->GetClassVersion();
576 SetStagingClass(fieldDesc.GetTypeName(), assignedVersionForOnDiskLayout);
577 PrepareStagingArea(rules, desc, fieldDesc);
578 for (
auto &[
_, si] : fStagingItems) {
585 for (
const auto rule : rules) {
586 if (!rule->GetTarget())
590 regularSubfields.erase(std::string(
target->GetString()));
595 for (
const auto rule : rules) {
596 AddReadCallbacksFromIORule(rule);
600 int nInMemoryBaseClasses = 0;
601 for (
auto &field : fSubfields) {
603 if (regularSubfields.count(fieldName) == 0) {
604 CallSetArtificialOn(*field);
606 if (!fieldName.empty() && fieldName[0] ==
':')
607 nInMemoryBaseClasses++;
610 if (nInMemoryBaseClasses != 0 && nOnDiskBaseClasses != 0 && nInMemoryBaseClasses != nOnDiskBaseClasses) {
612 R__FAIL(std::string(
"incompatible number of base classes for field ") + GetFieldName() +
": " + GetTypeName() +
613 ", " + std::to_string(nInMemoryBaseClasses) +
614 " base classes in memory "
616 std::to_string(nOnDiskBaseClasses) +
" base classes on-disk\n" +
625 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffTypeName).ThrowOnError();
638 RDeleter::operator()(objPtr, dtorOnly);
643 std::vector<RValue>
result;
644 auto valuePtr =
value.GetPtr<
void>();
645 auto charPtr =
static_cast<unsigned char *
>(valuePtr.get());
647 for (
unsigned i = 0; i <
fSubfields.size(); i++) {
662 EnsureValidAlignment(align);
694 fSoAMemberOffsets(source.fSoAMemberOffsets)
706 :
RSoAField(fieldName, EnsureValidClass(className))
711 const RSoAField &nestedSoA, std::size_t offsetInParent,
712 const std::function<
RFieldBase *(
const std::string &)> &fnRecordFieldFinder)
733 const auto lenPrefix = nestedSoA.
GetFieldName().length() + strlen(
"._0.");
735 for (std::size_t i = 0; i < nNestedRecordMemberFields; ++i) {
736 const auto fieldNameForMatching =
739 fRecordMemberFields.emplace_back(fnRecordFieldFinder(fieldNameForMatching));
753 std::vector<RFieldBase *> realRecordMemberFields;
755 std::unordered_map<std::string, std::size_t> recordFieldNameToIdx;
758 unsigned int nDirectRecordSubfields = 0;
759 unsigned int nDirectRecordBases = 0;
761 for (
auto itr = fSubfields[0]->begin(), iEnd = fSubfields[0]->end(); itr != iEnd; ++itr) {
762 if (itr->GetParent() == fSubfields[0].get()) {
763 if (itr->GetFieldName()[0] ==
':') {
764 nDirectRecordBases++;
766 nDirectRecordSubfields++;
771 auto qualifiedName = itr->GetFieldName();
772 auto parent = itr->GetParent();
773 while (parent != fSubfields[0].get()) {
774 qualifiedName = parent->GetFieldName() +
"." + qualifiedName;
775 parent = parent->GetParent();
777 recordFieldNameToIdx[qualifiedName] = realRecordMemberFields.size();
779 realRecordMemberFields.emplace_back(&(*itr));
783 const auto *soaBases =
fClass->GetListOfBases();
784 if (soaBases->GetSize() !=
static_cast<Int_t>(nDirectRecordBases)) {
785 throw RException(
R__FAIL(std::string(
"number of base classes don't match between SoA class ") + GetFieldName() +
786 " and its underlying record type"));
788 unsigned int baseIdx = 0;
790 if (base->GetDelta() < 0) {
791 throw RException(
R__FAIL(std::string(
"virtual inheritance is not supported: ") + GetTypeName() +
792 " virtually inherits from " + base->GetName()));
794 TClass *cl = base->GetClassPointer();
796 const auto baseFieldName = std::string(
":_") + std::to_string(baseIdx);
801 auto recordBaseField = realRecordMemberFields[recordFieldNameToIdx[baseFieldName]];
802 if (underlyingBaseTypeName != recordBaseField->GetTypeName()) {
803 throw RException(
R__FAIL(std::string(
"inheritance of SoA class ") + GetFieldName() +
804 " does not match its underlying record type"));
807 std::unique_ptr<RSoAField> soaBaseField;
809 soaBaseField = std::make_unique<RSoAField>(baseFieldName, cl->
GetName());
812 GetFieldName() +
" (" +
e.what() +
")"));
815 GraftNestedMemberFields(*soaBaseField, base->GetDelta(), [&](
const std::string &
name) {
816 return realRecordMemberFields[recordFieldNameToIdx[name]];
819 for (
const RRule &
r : soaBaseField->fRules) {
820 fRules.emplace_back(
r);
821 fRules.back().fOffset += base->GetDelta();
827 unsigned int nMembers = 0;
832 if ((dataMember->Property() &
kIsStatic) || !dataMember->IsPersistent())
835 if (dataMember->Property() &
kIsArray) {
836 throw RException(
R__FAIL(std::string(
"unsupported array type in SoA class: ") + dataMember->GetName()));
839 const std::string typeName{dataMember->GetTrueTypeName()};
842 auto itr = recordFieldNameToIdx.find(dmField->GetFieldName());
843 if (itr == recordFieldNameToIdx.end()) {
844 throw RException(
R__FAIL(std::string(
"unexpected SoA member: ") + dmField->GetFieldName()));
846 auto underlyingField = realRecordMemberFields[itr->second];
847 assert(dmField->GetFieldName() == underlyingField->GetFieldName());
849 if (
auto soaField =
dynamic_cast<RSoAField *
>(dmField.get())) {
851 throw RException(
R__FAIL(std::string(
"nested SoA field ") + soaField->GetQualifiedFieldName() +
" [" +
852 soaField->GetTypeName() +
"] does not match underlying type " +
853 underlyingField->GetTypeName()));
856 GraftNestedMemberFields(*soaField, dataMember->GetOffset(), [&](
const std::string &
name) {
857 return realRecordMemberFields[recordFieldNameToIdx[name]];
860 for (
const RRule &
r : soaField->fRules) {
861 fRules.emplace_back(
r);
862 fRules.back().fOffset += dataMember->GetOffset();
864 }
else if (
auto vecField =
dynamic_cast<RRVecField *
>(dmField.get())) {
865 if (vecField->begin()->GetTypeName() != underlyingField->GetTypeName() ||
866 vecField->begin()->GetTypeAlias() != underlyingField->GetTypeAlias()) {
867 const std::string leftType =
868 vecField->begin()->GetTypeName() +
869 (vecField->begin()->GetTypeAlias().empty() ?
"" :
" [" + vecField->begin()->GetTypeAlias() +
"]");
870 const std::string rightType =
871 underlyingField->GetTypeName() +
872 (underlyingField->GetTypeAlias().empty() ?
"" :
" [" + underlyingField->GetTypeAlias() +
"]");
873 throw RException(
R__FAIL(std::string(
"SoA member type mismatch: ") + vecField->GetFieldName() +
" (" +
874 leftType +
" vs. " + rightType +
")"));
877 fRecordMemberFields.emplace_back(underlyingField);
878 fRecordMemberDeleters.emplace_back(GetDeleterOf(*underlyingField));
879 fSoAMemberOffsets.emplace_back(dataMember->GetOffset());
881 throw RException(
R__FAIL(
"invalid field type in SoA class: " + dmField->GetTypeName()));
886 if (nDirectRecordSubfields != nMembers) {
890 auto schemaRules = FindRules(
nullptr);
891 for (
const auto &
r : schemaRules)
892 fRules.emplace_back(
RRule{
r, 0});
898 static std::once_flag once;
899 std::call_once(once, []() {
903 EnsureValidUserClass(
fClass, *
this,
"RSoAField");
905 if (recordTypeName.empty()) {
907 " is not marked with the rntupleSoARecord "
908 "dictionary option; cannot create corresponding RSoAField."));
911 Attach(std::make_unique<ROOT::RClassField>(
"_0", recordTypeName));
919 throw RException(
R__FAIL(std::string(
"version mismatch between SoA type and underlying record type: ") +
921 std::to_string(
fSubfields[0]->GetTypeVersion())));
926 std::string renormalizedAlias;
936 return std::unique_ptr<RSoAField>(
new RSoAField(newName, *
this));
946 return representations;
951 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
956 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
961 const std::size_t nSoAMembers = fSoAMemberOffsets.size();
964 for (std::size_t i = 0; i < nSoAMembers; ++i) {
965 const void *rvecPtr =
static_cast<const unsigned char *
>(from) + fSoAMemberOffsets[i];
967 assert(*sizePtr >= 0);
971 if (
static_cast<std::size_t
>(*sizePtr) !=
N) {
972 const auto f = fRecordMemberFields[i];
973 throw RException(
R__FAIL(
"SoA length mismatch for " +
f->GetFieldName() +
": " + std::to_string(*sizePtr) +
974 " vs. " + std::to_string(
N) +
" (expected)"));
979 std::size_t nbytes = 0;
981 for (std::size_t i = 0; i < nSoAMembers; ++i) {
982 const void *rvecPtr =
static_cast<const unsigned char *
>(from) + fSoAMemberOffsets[i];
984 RFieldBase *memberField = fRecordMemberFields[i];
986 GetPrincipalColumnOf(*memberField)->AppendV(*beginPtr,
N);
987 nbytes +=
N * GetPrincipalColumnOf(*memberField)->GetElement()->GetPackedSize();
989 for (std::size_t j = 0; j <
N; ++j) {
990 nbytes += CallAppendOn(*memberField, *beginPtr + j * memberField->
GetValueSize());
997 fPrincipalColumn->Append(&fNWritten);
998 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1006 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &
N);
1008 const auto nSoAMembers = fSoAMemberOffsets.size();
1009 for (std::size_t i = 0; i < nSoAMembers; ++i) {
1010 RFieldBase *memberField = fRecordMemberFields[i];
1012 void *rvecPtr =
static_cast<unsigned char *
>(to) + fSoAMemberOffsets[i];
1019 GetPrincipalColumnOf(*memberField)->ReadV(collectionStart,
N, begin);
1027 if (memberField->
GetTraits() & kTraitTriviallyConstructible) {
1028 std::memset(begin, 0,
N * memberSize);
1031 for (std::size_t j = 0; j <
N; ++j) {
1032 CallReadOn(*memberField, collectionStart + j, begin + (j * memberSize));
1039std::unique_ptr<ROOT::RFieldBase>
1049 const bool hasSources = std::any_of(fRules.begin(), fRules.end(), [](
const auto &
r) {
1050 return r.fRule->GetSource() && (r.fRule->GetSource()->GetEntries() > 0);
1052 const bool hasTargets =
1053 std::any_of(fRules.begin(), fRules.end(), [](
const auto &
r) { return r.fRule->GetTarget(); });
1056 throw RException(
R__FAIL(
"I/O customization rules with sources are currently unsupported for SoA fields (" +
1057 GetTypeName() +
")"));
1061 throw RException(
R__FAIL(
"I/O customization rules with targets are currently unsupported for SoA fields (" +
1062 GetTypeName() +
")"));
1065 for (
const auto &
r : fRules) {
1066 AddReadCallbacksFromIORule(
r.fRule,
r.fOffset);
1074 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1088 fSoAClass->Destructor(objPtr,
true );
1089 RDeleter::operator()(objPtr, dtorOnly);
1098 fSplitFields = std::make_unique<std::vector<std::unique_ptr<ROOT::RFieldBase>>>();
1099 fSplitOffsets = std::make_unique<std::vector<std::size_t>>();
1101 unsigned int baseIdx = 0;
1103 TClass *cl = base->GetClassPointer();
1111 if ((dataMember->Property() &
kIsStatic) || !dataMember->IsPersistent())
1114 const std::string typeName{dataMember->GetTrueTypeName()};
1126 auto valuePtr =
value.GetPtr<
void>();
1127 auto soaPtr =
static_cast<unsigned char *
>(valuePtr.get());
1128 std::vector<RValue> values;
1129 values.reserve(nSplitFields);
1130 for (std::size_t i = 0; i < nSplitFields; ++i) {
1154 EnsureValidAlignment(align);
1176 std::string_view emulatedFromType,
1177 std::string_view underlyingIntType)
1179 return std::unique_ptr<RFieldBase>(
new REnumField(fieldName, emulatedFromType, underlyingIntType));
1183 :
REnumField(fieldName, EnsureValidEnum(enumName))
1215 std::unique_ptr<RFieldBase> intField)
1218 Attach(std::move(intField));
1223 std::string_view underlyingIntType)
1226 auto intField =
Create(
"_0", std::string(underlyingIntType)).Unwrap();
1227 Attach(std::move(intField));
1233 auto newIntField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1234 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
1240 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1245 std::vector<RValue>
result;
1246 result.emplace_back(fSubfields[0]->BindValue(
value.GetPtr<
void>()));
1258 :
ROOT::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields, false ) +
">")
1260 const std::string typeAlias =
"std::pair<" + GetTypeList(itemFields,
true ) +
">";
1278 auto firstElem =
c->GetRealData(
"first");
1281 fOffsets.push_back(firstElem->GetThisOffset());
1283 auto secondElem =
c->GetRealData(
"second");
1286 fOffsets.push_back(secondElem->GetThisOffset());
1291 std::array<std::unique_ptr<RFieldBase>, 2> itemClones = {fSubfields[0]->Clone(fSubfields[0]->GetFieldName()),
1292 fSubfields[1]->Clone(fSubfields[1]->GetFieldName())};
1293 return std::unique_ptr<RPairField>(
new RPairField(newName, std::move(itemClones)));
1298 static const std::vector<std::string> prefixes = {
"std::pair<",
"std::tuple<"};
1300 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1301 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
1304 const auto nOnDiskSubfields = fieldDesc.
GetLinkIds().size();
1305 if (nOnDiskSubfields != 2) {
1307 std::to_string(nOnDiskSubfields) +
"\n" +
1323 (ifuncs.
fNext !=
nullptr));
1335 static const std::vector<std::string> supportedStdTypes = {
1336 "std::set<",
"std::unordered_set<",
"std::multiset<",
"std::unordered_multiset<",
1337 "std::map<",
"std::unordered_map<",
"std::multimap<",
"std::unordered_multimap<"};
1338 bool isSupported =
false;
1339 for (
const auto &tn : supportedStdTypes) {
1349 std::string renormalizedAlias;
1356 if (
fProxy->HasPointers())
1357 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
1368 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
1370 std::unique_ptr<ROOT::RFieldBase> itemField;
1372 if (
auto valueClass =
fProxy->GetValueClass()) {
1376 switch (
fProxy->GetType()) {
1381 case EDataType::kInt_t: itemField = std::make_unique<RField<Int_t>>(
"_0");
break;
1395 Attach(std::move(itemField));
1402 clone->fItemSize = fItemSize;
1403 clone->Attach(fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1409 std::size_t nbytes = 0;
1413 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1414 nbytes += CallAppendOn(*fSubfields[0], ptr);
1419 fPrincipalColumn->Append(&fNWritten);
1420 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1427 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1435 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
1436 CallReadOn(*fSubfields[0], collectionStart + (i++), elementPtr);
1439 fProxy->Commit(obj);
1449 return representations;
1454 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
1459 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
1464 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1475 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
1476 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubfields[0]), itemSize);
1478 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
1482 std::shared_ptr<TVirtualCollectionProxy> proxy)
1483 :
RDeleter(proxy->GetCollectionClass()->GetClassAlignment()), fProxy(std::move(proxy))
1488 std::shared_ptr<TVirtualCollectionProxy> proxy, std::unique_ptr<RDeleter> itemDeleter,
size_t itemSize)
1489 :
RDeleter(proxy->GetCollectionClass()->GetClassAlignment()),
1490 fProxy(std::move(proxy)),
1491 fItemDeleter(std::move(itemDeleter)),
1502 fItemDeleter->operator()(ptr,
true );
1505 fProxy->Destructor(objPtr,
true );
1506 RDeleter::operator()(objPtr, dtorOnly);
1511 std::vector<RValue>
result;
1512 auto valueRawPtr =
value.GetPtr<
void>().get();
1528 const auto align =
fProxy->GetCollectionClass()->GetClassAlignment();
1529 EnsureValidAlignment(align);
1542 EnsureValidClass(BuildMapTypeName(mapType, itemField.get(), false ))),
1545 if (!itemField->GetTypeAlias().empty())
1546 fTypeAlias = BuildMapTypeName(mapType, itemField.get(),
true );
1548 auto *itemClass =
fProxy->GetValueClass();
1551 Attach(std::move(itemField),
"_0");
1556 return std::make_unique<RMapField>(newName, fMapType, fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1561 static const std::vector<std::string> prefixesRegular = {
"std::map<",
"std::unordered_map<"};
1563 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1566 case EMapType::kMap:
1567 case EMapType::kUnorderedMap: EnsureMatchingTypePrefix(desc, prefixesRegular).ThrowOnError();
break;
1578 EnsureValidClass(BuildSetTypeName(setType, *itemField, false ))),
1581 if (!itemField->GetTypeAlias().empty())
1582 fTypeAlias = BuildSetTypeName(setType, *itemField,
true );
1586 Attach(std::move(itemField),
"_0");
1591 return std::make_unique<RSetField>(newName, fSetType, fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1596 static const std::vector<std::string> prefixesRegular = {
"std::set<",
"std::unordered_set<",
"std::map<",
1597 "std::unordered_map<"};
1599 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1602 case ESetType::kSet:
1603 case ESetType::kUnorderedSet: EnsureMatchingTypePrefix(desc, prefixesRegular).ThrowOnError();
break;
1620 RCallbackStreamerInfo fCallbackStreamerInfo;
1624 :
TBufferFile(
mode, bufsize), fCallbackStreamerInfo(std::move(callbackStreamerInfo))
1648 std::string renormalizedAlias;
1672 fClass->Streamer(
const_cast<void *
>(from), buffer);
1674 auto nbytes = buffer.Length();
1675 fAuxiliaryColumn->AppendV(buffer.Buffer(), buffer.Length());
1677 fPrincipalColumn->Append(&fIndex);
1678 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1685 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nbytes);
1688 fAuxiliaryColumn->ReadV(collectionStart, nbytes, buffer.
Buffer());
1689 fClass->Streamer(to, buffer);
1699 return representations;
1704 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, std::byte>();
1709 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, std::byte>(desc);
1720 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1736 RDeleter::operator()(objPtr, dtorOnly);
1752 EnsureValidAlignment(align);
1781 return dataMember->GetOffset();
1806 return std::unique_ptr<RField<TObject>>(
new RField<TObject>(newName, *
this));
1813 auto *obj =
static_cast<const TObject *
>(from);
1818 std::size_t nbytes = 0;
1819 nbytes += CallAppendOn(*fSubfields[0],
reinterpret_cast<const unsigned char *
>(from) + GetOffsetUniqueID());
1821 UInt_t bits = *
reinterpret_cast<const UInt_t *
>(
reinterpret_cast<const unsigned char *
>(from) + GetOffsetBits());
1823 nbytes += CallAppendOn(*fSubfields[1], &bits);
1832 auto *obj =
static_cast<TObject *
>(to);
1837 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetUniqueID()) = uniqueID;
1841 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetBits()) = bits;
1847 CallReadOn(*fSubfields[0], globalIndex, &uniqueID);
1848 CallReadOn(*fSubfields[1], globalIndex, &bits);
1849 ReadTObject(to, uniqueID, bits);
1855 CallReadOn(*fSubfields[0], localIndex, &uniqueID);
1856 CallReadOn(*fSubfields[1], localIndex, &bits);
1857 ReadTObject(to, uniqueID, bits);
1877 std::vector<RValue>
result;
1880 auto charPtr =
static_cast<unsigned char *
>(ptr.get());
1881 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(ptr, charPtr + GetOffsetUniqueID())));
1882 result.emplace_back(fSubfields[1]->BindValue(std::shared_ptr<void>(ptr, charPtr + GetOffsetBits())));
1904 :
ROOT::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields, false ) +
">")
1906 const std::string typeAlias =
"std::tuple<" + GetTypeList(itemFields,
true ) +
">";
1922 for (
unsigned i = 0; i <
fSubfields.size(); ++i) {
1923 std::string memberName(
"_" + std::to_string(i));
1924 auto member =
c->GetRealData(memberName.c_str());
1927 fOffsets.push_back(member->GetThisOffset());
1933 std::vector<std::unique_ptr<RFieldBase>> itemClones;
1934 itemClones.reserve(fSubfields.size());
1935 for (
const auto &
f : fSubfields) {
1936 itemClones.emplace_back(
f->Clone(
f->GetFieldName()));
1938 return std::unique_ptr<RTupleField>(
new RTupleField(newName, std::move(itemClones)));
1943 static const std::vector<std::string> prefixes = {
"std::pair<",
"std::tuple<"};
1945 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1946 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
1949 const auto nOnDiskSubfields = fieldDesc.
GetLinkIds().size();
1950 const auto nSubfields = fSubfields.size();
1951 if (nOnDiskSubfields != nSubfields) {
1953 std::to_string(nOnDiskSubfields) +
" vs. " + std::to_string(nSubfields) +
"\n" +
1963constexpr std::size_t GetVariantTagSize()
1966 std::variant<char> t;
1967 constexpr auto sizeOfT =
sizeof(t);
1969 static_assert(sizeOfT == 2 || sizeOfT == 8,
"unsupported std::variant layout");
1970 return sizeOfT == 2 ? 1 : 4;
1973template <std::
size_t VariantSizeT>
1975 using ValueType_t =
typename std::conditional_t<VariantSizeT == 1, std::uint8_t,
1976 typename std::conditional_t<VariantSizeT == 4, std::uint32_t, void>>;
1983 fMaxItemSize(source.fMaxItemSize),
1984 fMaxAlignment(source.fMaxAlignment),
1985 fTagOffset(source.fTagOffset),
1986 fVariantOffset(source.fVariantOffset),
1987 fNWritten(source.fNWritten.
size(), 0)
1990 Attach(
f->Clone(
f->GetFieldName()));
1995 :
ROOT::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields, false ) +
">",
2001 const std::string typeAlias =
"std::variant<" + GetTypeList(itemFields,
true ) +
">";
2005 auto nFields = itemFields.size();
2010 for (
unsigned int i = 0; i < nFields; ++i) {
2013 fTraits &= itemFields[i]->GetTraits();
2014 Attach(std::move(itemFields[i]),
"_" + std::to_string(i));
2025 const auto tagSize = GetVariantTagSize();
2026 const auto padding = tagSize - (
fMaxItemSize % tagSize);
2032 return std::unique_ptr<RVariantField>(
new RVariantField(newName, *
this));
2037 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
2038 auto tag = *
reinterpret_cast<const TagType_t *
>(
reinterpret_cast<const unsigned char *
>(variantPtr) + tagOffset);
2039 return (tag == TagType_t(-1)) ? 0 : tag + 1;
2044 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
2045 auto tagPtr =
reinterpret_cast<TagType_t *
>(
reinterpret_cast<unsigned char *
>(variantPtr) + tagOffset);
2046 *tagPtr = (tag == 0) ? TagType_t(-1) :
static_cast<TagType_t
>(tag - 1);
2051 auto tag = GetTag(from, fTagOffset);
2052 std::size_t nbytes = 0;
2055 nbytes += CallAppendOn(*fSubfields[tag - 1],
reinterpret_cast<const unsigned char *
>(from) + fVariantOffset);
2056 index = fNWritten[tag - 1]++;
2059 fPrincipalColumn->Append(&varSwitch);
2067 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
2074 void *varPtr =
reinterpret_cast<unsigned char *
>(to) + fVariantOffset;
2075 CallConstructValueOn(*fSubfields[tag - 1], varPtr);
2076 CallReadOn(*fSubfields[tag - 1], variantIndex, varPtr);
2078 SetTag(to, fTagOffset, tag);
2084 return representations;
2089 GenerateColumnsImpl<ROOT::Internal::RColumnSwitch>();
2094 GenerateColumnsImpl<ROOT::Internal::RColumnSwitch>(desc);
2099 static const std::vector<std::string> prefixes = {
"std::variant<"};
2101 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
2102 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
2105 if (fSubfields.size() != fieldDesc.GetLinkIds().size()) {
2106 throw RException(
R__FAIL(
"number of variants on-disk do not match for " + GetQualifiedFieldName() +
"\n" +
2113 memset(where, 0, GetValueSize());
2114 CallConstructValueOn(*fSubfields[0],
reinterpret_cast<unsigned char *
>(where) + fVariantOffset);
2115 SetTag(where, fTagOffset, 1);
2120 auto tag = GetTag(objPtr, fTagOffset);
2122 fItemDeleters[tag - 1]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fVariantOffset,
true );
2124 RDeleter::operator()(objPtr, dtorOnly);
2129 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2130 itemDeleters.reserve(fSubfields.size());
2131 for (
const auto &
f : fSubfields) {
2132 itemDeleters.emplace_back(GetDeleterOf(*
f));
2134 return std::make_unique<RVariantDeleter>(fTagOffset, fVariantOffset, GetAlignment(), std::move(itemDeleters));
2139 return std::max(fMaxAlignment,
alignof(RVariantTag<GetVariantTagSize()>::ValueType_t));
2145 const auto actualSize = fTagOffset + GetVariantTagSize();
2147 return actualSize + ((padding ==
alignment) ? 0 : padding);
2152 std::fill(fNWritten.begin(), fNWritten.end(), 0);
interop::TCppScope_t fClass
#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 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 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 ROOT::RProxiedCollectionField &field)
virtual void VisitTObjectField(const ROOT::RField< TObject > &field)
virtual void VisitStreamerField(const ROOT::RStreamerField &field)
virtual void VisitEnumField(const ROOT::REnumField &field)
virtual void VisitSoAField(const ROOT::Experimental::RSoAField &field)
virtual void VisitClassField(const ROOT::RClassField &field)
void operator()(void *objPtr, bool dtorOnly) final
The SoA field provides I/O for an in-memory SoA layout linked to an on-disk collection of the underly...
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(ROOT::NTupleSize_t globalIndex, void *to) final
std::vector< std::size_t > fSoAMemberOffsets
The offset of the RVec members in the SoA type in the same order as fRecordMemberFields.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
const std::type_info * GetPolymorphicTypeInfo() const
For polymorphic classes (that declare or inherit at least one virtual method), return the expected dy...
size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::vector< std::unique_ptr< RDeleter > > fRecordMemberDeleters
void GraftNestedMemberFields(const RSoAField &nestedSoA, std::size_t offsetInParent, const std::function< RFieldBase *(const std::string &)> &fnRecordFieldFinder)
For a nested SoA struct (either as a member of as a base class), use their fRecordMemberFields in thi...
void CollectRecordMemberFields()
Called during construction, picks up the (nested) member fields of the underlying record type(s) and ...
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
size_t GetAlignment() const final
What alignof(T) for this type returns.
std::unique_ptr< std::vector< std::size_t > > fSplitOffsets
std::vector< RFieldBase * > fRecordMemberFields
Direct access to the member fields of the underlying record.
RSoAField(std::string_view fieldName, const RSoAField &source)
Used by CloneImpl.
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
std::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
std::unique_ptr< std::vector< std::unique_ptr< ROOT::RFieldBase > > > fSplitFields
For reading and writing, the RVecs of the SoA class do not have a dedicated field.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
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 corresponding to the field type ...
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::unique_ptr< std::mutex > fLockSplitFields
protects the fSplitFields member.
void ReconstructSplitFields() const
Holds the index and the tag of a kSwitch column.
static std::string SerializeStreamerInfos(const StreamerInfoMap_t &infos)
const ROOT::RNTupleDescriptor & GetConstRef() const
Abstract interface to read data from an ntuple.
void RegisterStreamerInfos()
Builds the streamer info records from the descriptor's extra type info section.
RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
void operator()(void *objPtr, bool dtorOnly) final
RClassDeleter(TClass *cl)
The field for a class with dictionary.
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::vector< RSubfieldInfo > fSubfieldsInfo
Additional information kept for each entry in fSubfields
void Attach(std::unique_ptr< RFieldBase > child, RSubfieldInfo info)
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
void ReadGlobalImpl(ROOT::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...
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
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.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
const std::type_info * GetPolymorphicTypeInfo() const
For polymorphic classes (that declare or inherit at least one virtual method), return the expected dy...
std::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
The field for an unscoped or scoped enum with dictionary.
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 an existing value for this field.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
REnumField(std::string_view fieldName, TEnum *enump)
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Base class for all ROOT issued exceptions.
The list of column representations a field can have.
A functor to release the memory acquired by CreateValue() (memory and constructor).
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.
virtual size_t GetValueSize() const =0
What sizeof(T) for this type returns.
void Attach(std::unique_ptr< RFieldBase > child, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
std::vector< const RFieldBase * > GetConstSubfields() const
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
@ kTraitSoACollection
The field represents a collection in SoA layout.
@ kTraitTypeChecksum
The TClass checksum is set and valid.
const std::string & GetFieldName() const
const std::string & GetTypeAlias() const
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
bool IsArtificial() const
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
std::uint32_t GetTraits() const
const std::string & GetTypeName() const
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
Metadata stored for every field of an RNTuple.
ROOT::DescriptorId_t GetId() const
const std::vector< ROOT::DescriptorId_t > & GetLinkIds() const
std::optional< std::uint32_t > GetTypeChecksum() const
std::uint32_t GetTypeVersion() const
const std::string & GetTypeName() const
The container field for an ntuple model, which itself has no physical representation.
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Classes with dictionaries that can be inspected by TClass.
RField(std::string_view name)
RMapField(std::string_view fieldName, EMapType mapType, std::unique_ptr< RFieldBase > itemField)
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
The on-storage metadata of an RNTuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
const std::string & GetName() const
std::string GetTypeNameForComparison(const RFieldDescriptor &fieldDesc) const
Adjust the type name of the passed RFieldDescriptor for comparison with another renormalized type nam...
ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) const
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Template specializations for C++ std::pair.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
RPairField(std::string_view fieldName, std::array< std::unique_ptr< RFieldBase >, 2 > itemFields)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Allows for iterating over the elements of a proxied collection.
static RIteratorFuncs GetIteratorFuncs(TVirtualCollectionProxy *proxy, bool readFromDisk)
std::shared_ptr< TVirtualCollectionProxy > fProxy
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
RProxiedCollectionDeleter(std::shared_ptr< TVirtualCollectionProxy > proxy)
void operator()(void *objPtr, bool dtorOnly) final
The field for a class representing a collection of elements via TVirtualCollectionProxy.
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
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 ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
RProxiedCollectionField(std::string_view fieldName, TClass *classp)
Constructor used when the value type of the collection is not known in advance, i....
RCollectionIterableOnce::RIteratorFuncs fIFuncsWrite
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
RCollectionIterableOnce::RIteratorFuncs fIFuncsRead
Two sets of functions to operate on iterators, to be used depending on the access type.
std::shared_ptr< TVirtualCollectionProxy > fProxy
The collection proxy is needed by the deleters and thus defined as a shared pointer.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::unique_ptr< RDeleter > GetDeleter() const final
void ReconcileOnDiskField(const RNTupleDescriptor &desc) override
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Template specializations for ROOT's RVec.
static unsigned char * ResizeRVec(void *rvec, std::size_t nItems, std::size_t itemSize, const RFieldBase *itemField, RDeleter *itemDeleter)
The field for an untyped record.
void AttachItemFields(ContainerT &&itemFields)
std::vector< std::size_t > fOffsets
Base class for fields that are subject to I/O customization rules. Used by the class field and the So...
std::vector< const TSchemaRule * > FindRules(const ROOT::RFieldDescriptor *fieldDesc) const
Given the on-disk information from the page source, find all the I/O customization rules that apply t...
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
ROOT::DescriptorId_t LookupMember(const ROOT::RNTupleDescriptor &desc, std::string_view memberName, ROOT::DescriptorId_t classFieldId) const
Returns the id of member 'name' in the class field given by 'fieldId', or kInvalidDescriptorId if no ...
RRuleField(std::string_view name, std::string_view type, TClass *classp, ROOT::ENTupleStructure structure)
void PrepareStagingArea(const std::vector< const TSchemaRule * > &rules, const ROOT::RNTupleDescriptor &desc, const ROOT::RFieldDescriptor &classFieldId)
If there are rules with inputs (source members), create the staging area according to the TClass inst...
void AddReadCallbacksFromIORule(const TSchemaRule *rule, std::size_t subObjectOffset=0)
Register post-read callback corresponding to a ROOT I/O customization rules.
TClass * fClass
Set by derived class to the TClass instance representing the current in-memory layout.
void SetStagingClass(const std::string &className, unsigned int classVersion)
Sets fStagingClass according to the given name and version.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
RSetField(std::string_view fieldName, ESetType setType, std::unique_ptr< RFieldBase > itemField)
void operator()(void *objPtr, bool dtorOnly) final
RStreamerFieldDeleter(TClass *cl)
The field for a class using ROOT standard streaming.
ROOT::RExtraTypeInfoDescriptor GetExtraTypeInfo() const final
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fStreamerInfos
streamer info records seen during writing
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
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 > BeforeConnectPageSource(ROOT::Internal::RPageSource &source) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
std::unique_ptr< 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 AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
RStreamerField(std::string_view fieldName, TClass *classp)
size_t GetAlignment() const final
What alignof(T) for this type returns.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
size_t GetValueSize() const final
What sizeof(T) for this type returns.
Template specializations for C++ std::tuple.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
RTupleField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void operator()(void *objPtr, bool dtorOnly) final
Template specializations for C++ std::variant.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
static constexpr std::size_t kMaxVariants
std::vector< ROOT::Internal::RColumnIndex::ValueType > fNWritten
static std::uint8_t GetTag(const void *variantPtr, std::size_t tagOffset)
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
size_t fVariantOffset
In the std::variant memory layout, the actual union of types may start at an offset > 0.
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::unique_ptr< RDeleter > GetDeleter() const final
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
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 fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
RVariantField(std::string_view name, const RVariantField &source)
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
static void SetTag(void *variantPtr, std::size_t tagOffset, std::uint8_t tag)
void CommitClusterImpl() final
ReadFuncPtr_t GetReadFunctionPointer() const
Get the pointer to the function to be run for the rule (if it is a read rule).
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
TClass instances represent classes, structs and namespaces in the ROOT type system.
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
size_t GetClassAlignment() const
Return the alignment requirement (in bytes) for objects of this class.
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
const std::type_info * GetTypeInfo() const
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
TList * GetListOfRealData() const
Int_t Size() const
Return size of object of this class.
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Int_t GetClassSize() const
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Version_t GetClassVersion() const
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
All ROOT classes may have RTTI (run time type identification) support added.
The TEnum class implements the enum type.
EDataType GetUnderlyingType() const
Get the underlying integer type of the enum: enum E { kOne }; // ==> int enum F: long; // ==> long Re...
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
const char * GetName() const override
Returns name of object.
Mother of all ROOT objects.
@ kIsOnHeap
object is on heap
@ kNotDeleted
object has not been deleted
@ kIsReferenced
if object is referenced by a TRef or TRefArray
The TRealData class manages the effective list of all data members for a given class.
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...
Abstract Interface class describing Streamer information for one class.
virtual TVirtualStreamerInfo * GenerateInfoForPair(const std::string &pairclassname, bool silent, size_t hint_pair_offset, size_t hint_pair_size)=0
Generate the TClass and TStreamerInfo for the requested pair.
virtual Int_t GetNumber() const =0
static TVirtualStreamerInfo * Factory()
Static function returning a pointer to a new TVirtualStreamerInfo object.
virtual TClass * GetClass() const =0
TRangeCast< T, false > TRangeStaticCast
TRangeStaticCast is an adapter class that allows the typed iteration through a TCollection.
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
std::tuple< unsigned char **, std::int32_t *, std::int32_t * > GetRVecDataMembers(void *rvecPtr)
Retrieve the addresses of the data members of a generic RVec from a pointer to the beginning of the R...
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
std::string GetRNTupleSoARecord(const TClass *cl)
Checks if the "rntuple.SoARecord" class attribute is set in the dictionary.
bool NeedsMetaNameAsAlias(const std::string &metaNormalizedName, std::string &renormalizedAlias, bool isArgInTemplatedUserClass=false)
Checks if the meta normalized name is different from the RNTuple normalized name in a way that would ...
std::string GetTypeTraceReport(const RFieldBase &field, const RNTupleDescriptor &desc)
Prints the hierarchy of types with their field names and field IDs for the given in-memory field and ...
std::unique_ptr< RFieldBase > CreateEmulatedEnumField(std::string_view fieldName, std::string_view emulatedFromType, std::string_view underlyingIntType)
ERNTupleSerializationMode GetRNTupleSerializationMode(const TClass *cl)
std::string GetRenormalizedTypeName(const std::string &metaNormalizedName)
Given a type name normalized by ROOT meta, renormalize it for RNTuple. E.g., insert std::prefix.
constexpr bool IsValidAlignment(std::size_t align) noexcept
Return true if align is a valid C++ alignment value: strictly positive and a power of two.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId
ENTupleStructure
The fields in the RNTuple data model tree can carry different structural information about the type s...
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
TVirtualCollectionProxy::Next_t fNext
TVirtualCollectionProxy::CreateIterators_t fCreateIterators
TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators
std::unique_ptr< RFieldBase > fField
The field used to read the on-disk data.
std::size_t fOffset
offset in fStagingArea