34#include <unordered_set>
57 auto result = std::make_unique<RFieldZero>();
58 for (
auto &
f : fSubfields) {
59 result->Attach(
f->Clone(
f->GetFieldName()));
60 result->fSubfieldNames.insert(
f->GetFieldName());
67 std::vector<std::unique_ptr<ROOT::RFieldBase>>
result;
68 std::swap(fSubfields,
result);
98 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError();
102 if (
fieldDesc.GetTypeName().rfind(
"ROOT::RNTupleCardinality<", 0) != 0) {
104 " expects an on-disk leaf field of the same type\n" +
109 throw RException(
R__FAIL(
"invalid on-disk type version for RCardinalityField " + GetQualifiedFieldName() +
113 throw RException(
R__FAIL(
"invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName() +
120 visitor.VisitCardinalityField(*
this);
138 EnsureMatchingOnDiskField(desc, kDiffTypeName);
142 SetOnDiskId(desc.
FindFieldId(
"_0", GetOnDiskId()));
146 static const std::string
gIntegralTypeNames[] = {
"bool",
"char",
"std::int8_t",
"std::uint8_t",
147 "std::int16_t",
"std::uint16_t",
"std::int32_t",
"std::uint32_t",
148 "std::int64_t",
"std::uint64_t"};
159 EnsureMatchingOnDiskField(desc, kDiffTypeName);
267 visitor.VisitUInt8Field(*
this);
316 visitor.VisitFloatField(*
this);
338 visitor.VisitDoubleField(*
this);
343 fTypeAlias =
"Double32_t";
372 visitor.VisitInt16Field(*
this);
401 visitor.VisitUInt16Field(*
this);
430 visitor.VisitInt32Field(*
this);
459 visitor.VisitUInt32Field(*
this);
488 visitor.VisitUInt64Field(*
this);
517 visitor.VisitInt64Field(*
this);
544 auto typedValue =
static_cast<const std::string *
>(from);
548 fPrincipalColumn->Append(&fIndex);
549 return length + fPrincipalColumn->GetElement()->GetPackedSize();
554 auto typedValue =
static_cast<std::string *
>(to);
568 visitor.VisitStringField(*
this);
575 fMaxAlignment(
source.fMaxAlignment),
579 for (
const auto &
f :
source.GetConstSubfields())
580 Attach(
f->Clone(
f->GetFieldName()));
590std::unique_ptr<ROOT::RFieldBase>
592 std::vector<std::unique_ptr<RFieldBase>>
itemFields,
624 if (!IsPairOrTuple()) {
625 fOffsets.emplace_back(
fSize);
628 fMaxAlignment = std::max(fMaxAlignment,
item->GetAlignment());
629 fTraits &=
item->GetTraits() | (fTraits & kTraitExtensible);
631 if (IsPairOrTuple()) {
632 Attach(std::move(
item),
"_" + std::to_string(fSubfields.size()));
635 if (fSubfieldNames.count(
itemName) > 0)
637 Attach(std::move(
item));
667 for (
unsigned i = 0; i < fSubfields.size(); ++i) {
668 nbytes += CallAppendOn(*fSubfields[i],
static_cast<const unsigned char *
>(from) + fOffsets[i]);
675 for (
unsigned i = 0; i < fSubfields.size(); ++i) {
676 CallReadOn(*fSubfields[i],
globalIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
682 for (
unsigned i = 0; i < fSubfields.size(); ++i) {
683 CallReadOn(*fSubfields[i],
localIndex,
static_cast<unsigned char *
>(to) + fOffsets[i]);
689 if (fTraits & kTraitEmulatedField) {
696 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
706 for (
auto &
f : fSubfields) {
708 CallSetArtificialOn(*
f);
714 for (
unsigned i = 0; i < fSubfields.size(); ++i) {
715 CallConstructValueOn(*fSubfields[i],
static_cast<unsigned char *
>(
where) + fOffsets[i]);
721 for (
unsigned i = 0; i < fItemDeleters.size(); ++i) {
722 fItemDeleters[i]->operator()(
reinterpret_cast<unsigned char *
>(
objPtr) + fOffsets[i],
true );
731 for (
const auto &
f : fSubfields) {
734 return std::make_unique<RRecordDeleter>(std::move(
itemDeleters), fOffsets);
741 std::vector<RValue>
result;
742 result.reserve(fSubfields.size());
743 for (
unsigned i = 0; i < fSubfields.size(); ++i) {
744 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(
valuePtr,
charPtr + fOffsets[i])));
751 visitor.VisitRecordField(*
this);
783 if (WordSize() ==
sizeof(
unsigned long)) {
784 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
785 }
else if (WordSize() ==
sizeof(
unsigned long long)) {
787 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
793template <
typename Word_t>
796 constexpr auto kBitsPerWord =
sizeof(Word_t) * 8;
798 const auto *
asWordArray =
static_cast<const Word_t *
>(from);
801 for (std::size_t
word = 0;
word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++
word) {
802 for (std::size_t
mask = 0; (
mask < kBitsPerWord) && (i < nBits); ++
mask, ++i) {
815template <
typename Word_t>
819 constexpr auto kBitsPerWord =
sizeof(Word_t) * 8;
823 for (std::size_t i = 0; i < nBits; ++i) {
825 Word_t
mask =
static_cast<Word_t
>(1) << (i % kBitsPerWord);
836template <
typename Word_t>
840 constexpr auto kBitsPerWord =
sizeof(Word_t) * 8;
844 for (std::size_t i = 0; i < nBits; ++i) {
847 Word_t
mask =
static_cast<Word_t
>(1) << (i % kBitsPerWord);
860 visitor.VisitBitsetField(*
this);
894 if (!fIsEvolvedFromInnerType)
900 fPrincipalColumn->Append(&fNWritten);
906 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
908 fPrincipalColumn->Append(&fNWritten);
914 static const std::vector<std::string>
prefixes = {
"std::optional<",
"std::unique_ptr<"};
916 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
918 fIsEvolvedFromInnerType =
true;
921 fIsEvolvedFromInnerType = !
success;
924 if (fIsEvolvedFromInnerType)
925 fSubfields[0]->SetOnDiskId(GetOnDiskId());
946 visitor.VisitNullableField(*
this);
953struct PolymorphicClass {
968 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
974 auto typedValue =
static_cast<const std::unique_ptr<char> *
>(from);
977 if (fPolymorphicTypeInfo !=
nullptr) {
980 const std::type_info &t =
typeid(*
static_cast<const PolymorphicClass *
>(obj));
981 if (t != *fPolymorphicTypeInfo) {
982 std::string
msg =
"invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
989 msg +=
" and upcasting of polymorphic types is not supported in RNTuple";
993 return AppendValue(obj);
1001 auto ptr =
static_cast<std::unique_ptr<char> *
>(to);
1010 fItemDeleter->operator()(
valuePtr,
false );
1012 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
1013 ptr->reset(
reinterpret_cast<char *
>(
valuePtr));
1022 if (!fIsEvolvedFromInnerType)
1027 if (fIsEvolvedFromInnerType) {
1038 if (!fIsEvolvedFromInnerType) {
1053 fItemDeleter->operator()(
typedPtr->get(),
false );
1061 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1066 std::vector<RValue>
result;
1086 return reinterpret_cast<bool *
>(
reinterpret_cast<unsigned char *
>(
optionalPtr) + fSubfields[0]->GetValueSize());
1091 return GetEngagementPtr(
const_cast<void *
>(
optionalPtr));
1096 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1102 if (*GetEngagementPtr(from)) {
1103 return AppendValue(from);
1105 return AppendNull();
1113 if (!(*
engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1114 CallConstructValueOn(*fSubfields[0], to);
1117 if (*
engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1118 fItemDeleter->operator()(to,
true );
1126 if (!fIsEvolvedFromInnerType)
1131 if (fIsEvolvedFromInnerType) {
1134 CallReadOn(*fSubfields[0],
itemIndex, to);
1142 if (!fIsEvolvedFromInnerType) {
1150 CallReadOn(*fSubfields[0],
itemIndex, to);
1155 *GetEngagementPtr(
where) =
false;
1161 auto engagementPtr =
reinterpret_cast<bool *
>(
reinterpret_cast<unsigned char *
>(
objPtr) + fEngagementPtrOffset);
1163 fItemDeleter->operator()(
objPtr,
true );
1170 return std::make_unique<ROptionalDeleter>(
1171 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ?
nullptr : GetDeleterOf(*fSubfields[0]),
1172 fSubfields[0]->GetValueSize());
1177 std::vector<RValue>
result;
1180 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(
value.GetPtr<
void>(),
valuePtr)));
1189 const auto actualSize = fSubfields[0]->GetValueSize() +
sizeof(
bool);
1201 return fSubfields[0]->GetAlignment();
1223 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1230 if (
fieldDesc.GetTypeName().rfind(
"std::atomic<", 0) == 0) {
1231 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1233 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1239 std::vector<RValue>
result;
1240 result.emplace_back(fSubfields[0]->BindValue(
value.GetPtr<
void>()));
1246 visitor.VisitAtomicField(*
this);
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
static void BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t 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 Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize 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
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
void Read(const ROOT::NTupleSize_t globalIndex, void *to)
void Append(const void *from)
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
RBitsetField(std::string_view fieldName, std::size_t N)
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
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.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
The field for a class with dictionary.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Base class for all ROOT issued exceptions.
The list of column representations a field can have.
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.
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.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
@ 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.
@ kTraitExtensible
Can attach new item fields even when already connected.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
std::uint32_t GetTraits() const
Metadata stored for every field of an RNTuple.
The container field for an ntuple model, which itself has no physical representation.
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
void Attach(std::unique_ptr< RFieldBase > child)
A public version of the Attach method that allows piece-wise construction of the zero field.
Classes with dictionaries that can be inspected by TClass.
The on-storage metadata of an RNTuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
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::optional and std::unique_ptr.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
RNTupleLocalIndex GetItemIndex(NTupleSize_t globalIndex)
Given the global index of the nullable field, returns the corresponding cluster-local index of the su...
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
std::size_t AppendValue(const void *from)
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
void operator()(void *objPtr, bool dtorOnly) final
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
std::unique_ptr< RDeleter > GetDeleter() const final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
const bool * GetEngagementPtr(const void *optionalPtr) const
Given a pointer to an std::optional<T> in optionalPtr, extract a pointer to the engagement boolean.
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.
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
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 GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
void PrepareRead(void *to, bool hasOnDiskValue)
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
void operator()(void *objPtr, bool dtorOnly) final
The field for an untyped record.
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< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
RRecordField(std::string_view name, const RRecordField &source)
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
void AttachItemFields(ContainerT &&itemFields)
std::unique_ptr< RDeleter > GetDeleter() const final
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
void AddItem(std::unique_ptr< RFieldBase > item)
Adds an additional item field.
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...
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) override
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
void ReconcileIntegralField(const RNTupleDescriptor &desc)
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
void operator()(void *objPtr, bool dtorOnly) final
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 * fPolymorphicTypeInfo
If the item type is a polymorphic class (that declares or inherits at least one virtual method),...
void * PrepareRead(void *to, bool hasOnDiskValue)
std::unique_ptr< RDeleter > GetDeleter() const final
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Template specializations for C++ std::vector.
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
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 ...
void AddItemToRecord(RRecordField &record, std::unique_ptr< RFieldBase > newItem)
bool IsCustomEnumFieldDesc(const RNTupleDescriptor &desc, const RFieldDescriptor &fieldDesc)
Tells if the field describes a user-defined enum type.
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
ENTupleStructure
The fields in the RNTuple data model tree can carry different structural information about the type s...
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.