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 EnsureValidUserClass(
fClass, *
this,
"RSoAField");
900 if (recordTypeName.empty()) {
902 " is not marked with the rntupleSoARecord "
903 "dictionary option; cannot create corresponding RSoAField."));
906 Attach(std::make_unique<ROOT::RClassField>(
"_0", recordTypeName));
914 throw RException(
R__FAIL(std::string(
"version mismatch between SoA type and underlying record type: ") +
916 std::to_string(
fSubfields[0]->GetTypeVersion())));
921 std::string renormalizedAlias;
931 return std::unique_ptr<RSoAField>(
new RSoAField(newName, *
this));
941 return representations;
946 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
951 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
956 const std::size_t nSoAMembers = fSoAMemberOffsets.size();
959 for (std::size_t i = 0; i < nSoAMembers; ++i) {
960 const void *rvecPtr =
static_cast<const unsigned char *
>(from) + fSoAMemberOffsets[i];
962 assert(*sizePtr >= 0);
966 if (
static_cast<std::size_t
>(*sizePtr) !=
N) {
967 const auto f = fRecordMemberFields[i];
968 throw RException(
R__FAIL(
"SoA length mismatch for " +
f->GetFieldName() +
": " + std::to_string(*sizePtr) +
969 " vs. " + std::to_string(
N) +
" (expected)"));
974 std::size_t nbytes = 0;
976 for (std::size_t i = 0; i < nSoAMembers; ++i) {
977 const void *rvecPtr =
static_cast<const unsigned char *
>(from) + fSoAMemberOffsets[i];
979 RFieldBase *memberField = fRecordMemberFields[i];
981 GetPrincipalColumnOf(*memberField)->AppendV(*beginPtr,
N);
982 nbytes +=
N * GetPrincipalColumnOf(*memberField)->GetElement()->GetPackedSize();
984 for (std::size_t j = 0; j <
N; ++j) {
985 nbytes += CallAppendOn(*memberField, *beginPtr + j * memberField->
GetValueSize());
992 fPrincipalColumn->Append(&fNWritten);
993 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1001 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &
N);
1003 const auto nSoAMembers = fSoAMemberOffsets.size();
1004 for (std::size_t i = 0; i < nSoAMembers; ++i) {
1005 RFieldBase *memberField = fRecordMemberFields[i];
1007 void *rvecPtr =
static_cast<unsigned char *
>(to) + fSoAMemberOffsets[i];
1014 GetPrincipalColumnOf(*memberField)->ReadV(collectionStart,
N, begin);
1022 if (memberField->
GetTraits() & kTraitTriviallyConstructible) {
1023 std::memset(begin, 0,
N * memberSize);
1026 for (std::size_t j = 0; j <
N; ++j) {
1027 CallReadOn(*memberField, collectionStart + j, begin + (j * memberSize));
1043 const bool hasSources = std::any_of(fRules.begin(), fRules.end(), [](
const auto &
r) {
1044 return r.fRule->GetSource() && (r.fRule->GetSource()->GetEntries() > 0);
1046 const bool hasTargets =
1047 std::any_of(fRules.begin(), fRules.end(), [](
const auto &
r) { return r.fRule->GetTarget(); });
1050 throw RException(
R__FAIL(
"I/O customization rules with sources are currently unsupported for SoA fields (" +
1051 GetTypeName() +
")"));
1055 throw RException(
R__FAIL(
"I/O customization rules with targets are currently unsupported for SoA fields (" +
1056 GetTypeName() +
")"));
1059 for (
const auto &
r : fRules) {
1060 AddReadCallbacksFromIORule(
r.fRule,
r.fOffset);
1068 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1080 fSoAClass->Destructor(objPtr,
true );
1081 RDeleter::operator()(objPtr, dtorOnly);
1090 fSplitFields = std::make_unique<std::vector<std::unique_ptr<ROOT::RFieldBase>>>();
1091 fSplitOffsets = std::make_unique<std::vector<std::size_t>>();
1093 unsigned int baseIdx = 0;
1095 TClass *cl = base->GetClassPointer();
1103 if ((dataMember->Property() &
kIsStatic) || !dataMember->IsPersistent())
1106 const std::string typeName{dataMember->GetTrueTypeName()};
1118 auto valuePtr =
value.GetPtr<
void>();
1119 auto soaPtr =
static_cast<unsigned char *
>(valuePtr.get());
1120 std::vector<RValue> values;
1121 values.reserve(nSplitFields);
1122 for (std::size_t i = 0; i < nSplitFields; ++i) {
1146 EnsureValidAlignment(align);
1168 std::string_view emulatedFromType,
1169 std::string_view underlyingIntType)
1171 return std::unique_ptr<RFieldBase>(
new REnumField(fieldName, emulatedFromType, underlyingIntType));
1175 :
REnumField(fieldName, EnsureValidEnum(enumName))
1207 std::unique_ptr<RFieldBase> intField)
1210 Attach(std::move(intField));
1215 std::string_view underlyingIntType)
1218 auto intField =
Create(
"_0", std::string(underlyingIntType)).Unwrap();
1219 Attach(std::move(intField));
1225 auto newIntField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1226 return std::unique_ptr<REnumField>(
new REnumField(newName, GetTypeName(), std::move(newIntField)));
1232 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1237 std::vector<RValue>
result;
1238 result.emplace_back(fSubfields[0]->BindValue(
value.GetPtr<
void>()));
1250 :
ROOT::
RRecordField(fieldName,
"std::pair<" + GetTypeList(itemFields, false ) +
">")
1252 const std::string typeAlias =
"std::pair<" + GetTypeList(itemFields,
true ) +
">";
1270 auto firstElem =
c->GetRealData(
"first");
1273 fOffsets.push_back(firstElem->GetThisOffset());
1275 auto secondElem =
c->GetRealData(
"second");
1278 fOffsets.push_back(secondElem->GetThisOffset());
1283 std::array<std::unique_ptr<RFieldBase>, 2> itemClones = {fSubfields[0]->Clone(fSubfields[0]->GetFieldName()),
1284 fSubfields[1]->Clone(fSubfields[1]->GetFieldName())};
1285 return std::unique_ptr<RPairField>(
new RPairField(newName, std::move(itemClones)));
1290 static const std::vector<std::string> prefixes = {
"std::pair<",
"std::tuple<"};
1292 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1293 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
1296 const auto nOnDiskSubfields = fieldDesc.
GetLinkIds().size();
1297 if (nOnDiskSubfields != 2) {
1299 std::to_string(nOnDiskSubfields) +
"\n" +
1315 (ifuncs.
fNext !=
nullptr));
1327 static const std::vector<std::string> supportedStdTypes = {
1328 "std::set<",
"std::unordered_set<",
"std::multiset<",
"std::unordered_multiset<",
1329 "std::map<",
"std::unordered_map<",
"std::multimap<",
"std::unordered_multimap<"};
1330 bool isSupported =
false;
1331 for (
const auto &tn : supportedStdTypes) {
1341 std::string renormalizedAlias;
1348 if (
fProxy->HasPointers())
1349 throw RException(
R__FAIL(
"collection proxies whose value type is a pointer are not supported"));
1360 throw RException(
R__FAIL(
"custom associative collection proxies not supported"));
1362 std::unique_ptr<ROOT::RFieldBase> itemField;
1364 if (
auto valueClass =
fProxy->GetValueClass()) {
1368 switch (
fProxy->GetType()) {
1373 case EDataType::kInt_t: itemField = std::make_unique<RField<Int_t>>(
"_0");
break;
1387 Attach(std::move(itemField));
1394 clone->fItemSize = fItemSize;
1395 clone->Attach(fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1401 std::size_t nbytes = 0;
1405 (fCollectionType ==
kSTLvector ? fItemSize : 0U)}) {
1406 nbytes += CallAppendOn(*fSubfields[0], ptr);
1411 fPrincipalColumn->Append(&fNWritten);
1412 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1419 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1427 (fCollectionType ==
kSTLvector || obj != to ? fItemSize : 0U)}) {
1428 CallReadOn(*fSubfields[0], collectionStart + (i++), elementPtr);
1431 fProxy->Commit(obj);
1441 return representations;
1446 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
1451 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
1456 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1467 std::size_t itemSize = fCollectionType ==
kSTLvector ? fItemSize : 0U;
1468 return std::make_unique<RProxiedCollectionDeleter>(fProxy, GetDeleterOf(*fSubfields[0]), itemSize);
1470 return std::make_unique<RProxiedCollectionDeleter>(fProxy);
1474 std::shared_ptr<TVirtualCollectionProxy> proxy)
1475 :
RDeleter(proxy->GetCollectionClass()->GetClassAlignment()), fProxy(std::move(proxy))
1480 std::shared_ptr<TVirtualCollectionProxy> proxy, std::unique_ptr<RDeleter> itemDeleter,
size_t itemSize)
1481 :
RDeleter(proxy->GetCollectionClass()->GetClassAlignment()),
1482 fProxy(std::move(proxy)),
1483 fItemDeleter(std::move(itemDeleter)),
1494 fItemDeleter->operator()(ptr,
true );
1497 fProxy->Destructor(objPtr,
true );
1498 RDeleter::operator()(objPtr, dtorOnly);
1503 std::vector<RValue>
result;
1504 auto valueRawPtr =
value.GetPtr<
void>().get();
1520 const auto align =
fProxy->GetCollectionClass()->GetClassAlignment();
1521 EnsureValidAlignment(align);
1534 EnsureValidClass(BuildMapTypeName(mapType, itemField.get(), false ))),
1537 if (!itemField->GetTypeAlias().empty())
1538 fTypeAlias = BuildMapTypeName(mapType, itemField.get(),
true );
1540 auto *itemClass =
fProxy->GetValueClass();
1543 Attach(std::move(itemField),
"_0");
1548 return std::make_unique<RMapField>(newName, fMapType, fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1553 static const std::vector<std::string> prefixesRegular = {
"std::map<",
"std::unordered_map<"};
1555 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1558 case EMapType::kMap:
1559 case EMapType::kUnorderedMap: EnsureMatchingTypePrefix(desc, prefixesRegular).ThrowOnError();
break;
1570 EnsureValidClass(BuildSetTypeName(setType, *itemField, false ))),
1573 if (!itemField->GetTypeAlias().empty())
1574 fTypeAlias = BuildSetTypeName(setType, *itemField,
true );
1578 Attach(std::move(itemField),
"_0");
1583 return std::make_unique<RSetField>(newName, fSetType, fSubfields[0]->Clone(fSubfields[0]->GetFieldName()));
1588 static const std::vector<std::string> prefixesRegular = {
"std::set<",
"std::unordered_set<",
"std::map<",
1589 "std::unordered_map<"};
1591 EnsureMatchingOnDiskCollection(desc).ThrowOnError();
1594 case ESetType::kSet:
1595 case ESetType::kUnorderedSet: EnsureMatchingTypePrefix(desc, prefixesRegular).ThrowOnError();
break;
1612 RCallbackStreamerInfo fCallbackStreamerInfo;
1616 :
TBufferFile(
mode, bufsize), fCallbackStreamerInfo(std::move(callbackStreamerInfo))
1640 std::string renormalizedAlias;
1664 fClass->Streamer(
const_cast<void *
>(from), buffer);
1666 auto nbytes = buffer.Length();
1667 fAuxiliaryColumn->AppendV(buffer.Buffer(), buffer.Length());
1669 fPrincipalColumn->Append(&fIndex);
1670 return nbytes + fPrincipalColumn->GetElement()->GetPackedSize();
1677 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nbytes);
1680 fAuxiliaryColumn->ReadV(collectionStart, nbytes, buffer.
Buffer());
1681 fClass->Streamer(to, buffer);
1691 return representations;
1696 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, std::byte>();
1701 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, std::byte>(desc);
1712 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
1728 RDeleter::operator()(objPtr, dtorOnly);
1744 EnsureValidAlignment(align);
1773 return dataMember->GetOffset();
1798 return std::unique_ptr<RField<TObject>>(
new RField<TObject>(newName, *
this));
1805 auto *obj =
static_cast<const TObject *
>(from);
1810 std::size_t nbytes = 0;
1811 nbytes += CallAppendOn(*fSubfields[0],
reinterpret_cast<const unsigned char *
>(from) + GetOffsetUniqueID());
1813 UInt_t bits = *
reinterpret_cast<const UInt_t *
>(
reinterpret_cast<const unsigned char *
>(from) + GetOffsetBits());
1815 nbytes += CallAppendOn(*fSubfields[1], &bits);
1824 auto *obj =
static_cast<TObject *
>(to);
1829 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetUniqueID()) = uniqueID;
1833 *
reinterpret_cast<UInt_t *
>(
reinterpret_cast<unsigned char *
>(to) + GetOffsetBits()) = bits;
1839 CallReadOn(*fSubfields[0], globalIndex, &uniqueID);
1840 CallReadOn(*fSubfields[1], globalIndex, &bits);
1841 ReadTObject(to, uniqueID, bits);
1847 CallReadOn(*fSubfields[0], localIndex, &uniqueID);
1848 CallReadOn(*fSubfields[1], localIndex, &bits);
1849 ReadTObject(to, uniqueID, bits);
1869 std::vector<RValue>
result;
1872 auto charPtr =
static_cast<unsigned char *
>(ptr.get());
1873 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(ptr, charPtr + GetOffsetUniqueID())));
1874 result.emplace_back(fSubfields[1]->BindValue(std::shared_ptr<void>(ptr, charPtr + GetOffsetBits())));
1896 :
ROOT::
RRecordField(fieldName,
"std::tuple<" + GetTypeList(itemFields, false ) +
">")
1898 const std::string typeAlias =
"std::tuple<" + GetTypeList(itemFields,
true ) +
">";
1914 for (
unsigned i = 0; i <
fSubfields.size(); ++i) {
1915 std::string memberName(
"_" + std::to_string(i));
1916 auto member =
c->GetRealData(memberName.c_str());
1919 fOffsets.push_back(member->GetThisOffset());
1925 std::vector<std::unique_ptr<RFieldBase>> itemClones;
1926 itemClones.reserve(fSubfields.size());
1927 for (
const auto &
f : fSubfields) {
1928 itemClones.emplace_back(
f->Clone(
f->GetFieldName()));
1930 return std::unique_ptr<RTupleField>(
new RTupleField(newName, std::move(itemClones)));
1935 static const std::vector<std::string> prefixes = {
"std::pair<",
"std::tuple<"};
1937 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1938 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
1941 const auto nOnDiskSubfields = fieldDesc.
GetLinkIds().size();
1942 const auto nSubfields = fSubfields.size();
1943 if (nOnDiskSubfields != nSubfields) {
1945 std::to_string(nOnDiskSubfields) +
" vs. " + std::to_string(nSubfields) +
"\n" +
1955constexpr std::size_t GetVariantTagSize()
1958 std::variant<char> t;
1959 constexpr auto sizeOfT =
sizeof(t);
1961 static_assert(sizeOfT == 2 || sizeOfT == 8,
"unsupported std::variant layout");
1962 return sizeOfT == 2 ? 1 : 4;
1965template <std::
size_t VariantSizeT>
1967 using ValueType_t =
typename std::conditional_t<VariantSizeT == 1, std::uint8_t,
1968 typename std::conditional_t<VariantSizeT == 4, std::uint32_t, void>>;
1975 fMaxItemSize(source.fMaxItemSize),
1976 fMaxAlignment(source.fMaxAlignment),
1977 fTagOffset(source.fTagOffset),
1978 fVariantOffset(source.fVariantOffset),
1979 fNWritten(source.fNWritten.
size(), 0)
1982 Attach(
f->Clone(
f->GetFieldName()));
1987 :
ROOT::
RFieldBase(fieldName,
"std::variant<" + GetTypeList(itemFields, false ) +
">",
1993 const std::string typeAlias =
"std::variant<" + GetTypeList(itemFields,
true ) +
">";
1997 auto nFields = itemFields.size();
2002 for (
unsigned int i = 0; i < nFields; ++i) {
2005 fTraits &= itemFields[i]->GetTraits();
2006 Attach(std::move(itemFields[i]),
"_" + std::to_string(i));
2017 const auto tagSize = GetVariantTagSize();
2018 const auto padding = tagSize - (
fMaxItemSize % tagSize);
2024 return std::unique_ptr<RVariantField>(
new RVariantField(newName, *
this));
2029 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
2030 auto tag = *
reinterpret_cast<const TagType_t *
>(
reinterpret_cast<const unsigned char *
>(variantPtr) + tagOffset);
2031 return (tag == TagType_t(-1)) ? 0 : tag + 1;
2036 using TagType_t = RVariantTag<GetVariantTagSize()>::ValueType_t;
2037 auto tagPtr =
reinterpret_cast<TagType_t *
>(
reinterpret_cast<unsigned char *
>(variantPtr) + tagOffset);
2038 *tagPtr = (tag == 0) ? TagType_t(-1) :
static_cast<TagType_t
>(tag - 1);
2043 auto tag = GetTag(from, fTagOffset);
2044 std::size_t nbytes = 0;
2047 nbytes += CallAppendOn(*fSubfields[tag - 1],
reinterpret_cast<const unsigned char *
>(from) + fVariantOffset);
2048 index = fNWritten[tag - 1]++;
2051 fPrincipalColumn->Append(&varSwitch);
2059 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
2066 void *varPtr =
reinterpret_cast<unsigned char *
>(to) + fVariantOffset;
2067 CallConstructValueOn(*fSubfields[tag - 1], varPtr);
2068 CallReadOn(*fSubfields[tag - 1], variantIndex, varPtr);
2070 SetTag(to, fTagOffset, tag);
2076 return representations;
2081 GenerateColumnsImpl<ROOT::Internal::RColumnSwitch>();
2086 GenerateColumnsImpl<ROOT::Internal::RColumnSwitch>(desc);
2091 static const std::vector<std::string> prefixes = {
"std::variant<"};
2093 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
2094 EnsureMatchingTypePrefix(desc, prefixes).ThrowOnError();
2097 if (fSubfields.size() != fieldDesc.GetLinkIds().size()) {
2098 throw RException(
R__FAIL(
"number of variants on-disk do not match for " + GetQualifiedFieldName() +
"\n" +
2105 memset(where, 0, GetValueSize());
2106 CallConstructValueOn(*fSubfields[0],
reinterpret_cast<unsigned char *
>(where) + fVariantOffset);
2107 SetTag(where, fTagOffset, 1);
2112 auto tag = GetTag(objPtr, fTagOffset);
2114 fItemDeleters[tag - 1]->operator()(
reinterpret_cast<unsigned char *
>(objPtr) + fVariantOffset,
true );
2116 RDeleter::operator()(objPtr, dtorOnly);
2121 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
2122 itemDeleters.reserve(fSubfields.size());
2123 for (
const auto &
f : fSubfields) {
2124 itemDeleters.emplace_back(GetDeleterOf(*
f));
2126 return std::make_unique<RVariantDeleter>(fTagOffset, fVariantOffset, GetAlignment(), std::move(itemDeleters));
2131 return std::max(fMaxAlignment,
alignof(RVariantTag<GetVariantTagSize()>::ValueType_t));
2137 const auto actualSize = fTagOffset + GetVariantTagSize();
2139 return actualSize + ((padding ==
alignment) ? 0 : padding);
2144 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 VisitSoAField(const ROOT::RSoAField &field)
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 VisitClassField(const ROOT::RClassField &field)
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
The SoA field provides I/O for an in-memory SoA layout linked to an on-disk collection of the underly...
std::unique_ptr< std::mutex > fLockSplitFields
protects the fSplitFields member.
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
const std::type_info * GetPolymorphicTypeInfo() const
For polymorphic classes (that declare or inherit at least one virtual method), return the expected dy...
std::vector< RFieldBase * > fRecordMemberFields
Direct access to the member fields of the underlying record.
size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::vector< std::unique_ptr< RDeleter > > fRecordMemberDeleters
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
void CollectRecordMemberFields()
Called during construction, picks up the (nested) member fields of the underlying record type(s) and ...
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReconstructSplitFields() const
std::vector< std::size_t > fSoAMemberOffsets
The offset of the RVec members in the SoA type in the same order as fRecordMemberFields.
RSoAField(std::string_view fieldName, const RSoAField &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.
std::unique_ptr< std::vector< std::size_t > > fSplitOffsets
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 ...
size_t GetAlignment() const final
What alignof(T) for this type returns.
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::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.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
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 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