24class CreateContextGuard;
26 friend class CreateContextGuard;
28 std::vector<std::string> fClassesOnStack;
31 bool fContinueOnError =
false;
34 CreateContext() =
default;
39class CreateContextGuard {
40 CreateContext &fCreateContext;
41 std::size_t fNOriginalClassesOnStack;
42 bool fOriginalContinueOnError;
45 CreateContextGuard(CreateContext &ctx)
46 : fCreateContext(ctx),
47 fNOriginalClassesOnStack(ctx.fClassesOnStack.
size()),
48 fOriginalContinueOnError(ctx.fContinueOnError)
53 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
54 fCreateContext.fContinueOnError = fOriginalContinueOnError;
59 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
60 fCreateContext.fClassesOnStack.end()) {
63 fCreateContext.fClassesOnStack.emplace_back(cl);
77 field.CommitCluster();
126 : fField(
other.fField),
128 fCapacity(
other.fCapacity),
130 fIsAdopted(
other.fIsAdopted),
131 fNValidValues(
other.fNValidValues),
132 fFirstIndex(
other.fFirstIndex)
141 std::swap(fField,
other.fField);
142 std::swap(fDeleter,
other.fDeleter);
143 std::swap(fValues,
other.fValues);
145 std::swap(fCapacity,
other.fCapacity);
147 std::swap(fIsAdopted,
other.fIsAdopted);
148 std::swap(fMaskAvail,
other.fMaskAvail);
149 std::swap(fNValidValues,
other.fNValidValues);
150 std::swap(fFirstIndex,
other.fFirstIndex);
166 for (std::size_t i = 0; i < fCapacity; ++i) {
167 fDeleter->operator()(GetValuePtrAt(i),
true );
171 operator delete(fValues);
176 if (fCapacity <
size) {
178 throw RException(
R__FAIL(
"invalid attempt to bulk read beyond the adopted buffer"));
184 for (std::size_t i = 0; i <
size; ++i) {
185 fField->ConstructValue(GetValuePtrAt(i));
189 fMaskAvail = std::make_unique<bool[]>(
size);
193 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
203 for (std::size_t i = 0; i <
fSize; ++i)
204 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
211 fCapacity = capacity;
214 fMaskAvail = std::make_unique<bool[]>(capacity);
229std::unique_ptr<void, typename ROOT::RFieldBase::RCreateObjectDeleter<void>::deleter>
230ROOT::RFieldBase::CreateObject<void>()
const
254 std::string
result = GetFieldName();
255 auto parent = GetParent();
256 while (parent && !parent->GetFieldName().empty()) {
258 parent = parent->GetParent();
270std::vector<ROOT::RFieldBase::RCheckResult>
275 cfOpts.SetReturnInvalidOnError(
true);
276 cfOpts.SetEmulateUnknownTypes(
false);
279 std::vector<RCheckResult>
result;
322 std::unique_ptr<ROOT::RFieldBase>
result;
338 for (
int i =
arraySizes.size() - 1; i >= 0; --i) {
382 }
else if (
resolvedType.substr(0, 12) ==
"std::vector<") {
386 }
else if (
resolvedType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
390 }
else if (
resolvedType.substr(0, 11) ==
"std::array<") {
398 }
else if (
resolvedType.substr(0, 13) ==
"std::variant<") {
400 std::vector<std::unique_ptr<RFieldBase>>
items;
402 for (
unsigned int i = 0; i <
innerTypes.size(); ++i) {
407 }
else if (
resolvedType.substr(0, 10) ==
"std::pair<") {
412 std::array<std::unique_ptr<RFieldBase>, 2>
items{
416 }
else if (
resolvedType.substr(0, 11) ==
"std::tuple<") {
418 std::vector<std::unique_ptr<RFieldBase>>
items;
420 for (
unsigned int i = 0; i <
innerTypes.size(); ++i) {
425 }
else if (
resolvedType.substr(0, 12) ==
"std::bitset<") {
428 }
else if (
resolvedType.substr(0, 16) ==
"std::unique_ptr<") {
434 }
else if (
resolvedType.substr(0, 14) ==
"std::optional<") {
446 }
else if (
resolvedType.substr(0, 19) ==
"std::unordered_set<") {
452 }
else if (
resolvedType.substr(0, 14) ==
"std::multiset<") {
458 }
else if (
resolvedType.substr(0, 24) ==
"std::unordered_multiset<") {
481 }
else if (
resolvedType.substr(0, 19) ==
"std::unordered_map<") {
497 }
else if (
resolvedType.substr(0, 14) ==
"std::multimap<") {
513 }
else if (
resolvedType.substr(0, 24) ==
"std::unordered_multimap<") {
517 fnFail(
"the type list for std::unordered_multimap must have exactly two elements"));
528 result = std::make_unique<RMapField>(
530 }
else if (
resolvedType.substr(0, 12) ==
"std::atomic<") {
536 }
else if (
resolvedType.substr(0, 25) ==
"ROOT::RNTupleCardinality<") {
542 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(
fieldName);
544 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(
fieldName);
565 if (cl->GetCollectionProxy()) {
566 result = std::make_unique<RProxiedCollectionField>(
fieldName, typeName);
593 }
catch (RException &
e) {
594 auto error =
e.GetError();
596 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(
fieldName, typeName, error.GetReport(),
601 }
catch (std::logic_error &
e) {
604 return std::unique_ptr<RFieldBase>(
629 auto clone = CloneImpl(
newName);
630 clone->fTypeAlias = fTypeAlias;
631 clone->fOnDiskId = fOnDiskId;
632 clone->fDescription = fDescription;
634 clone->fColumnRepresentatives = fColumnRepresentatives;
640 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
651 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(
localIndex), to);
657 std::size_t
nRead = 0;
658 for (std::size_t i = 0; i <
bulkSpec.fCount; ++i) {
676 void *
where =
operator new(GetValueSize());
678 ConstructValue(
where);
684 void *obj = CreateObjectRawPtr();
690 return std::vector<RValue>();
697 if (fState != EState::kUnconnected)
698 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
699 child->fParent =
this;
700 fSubfields.emplace_back(std::move(
child));
706 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
707 auto parent =
f->GetParent();
712 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
719 std::vector<RFieldBase *>
result;
720 result.reserve(fSubfields.size());
721 for (
const auto &
f : fSubfields) {
729 std::vector<const RFieldBase *>
result;
730 result.reserve(fSubfields.size());
731 for (
const auto &
f : fSubfields) {
739 if (!fAvailableColumns.empty()) {
741 for (
auto &column : fAvailableColumns) {
751 if (!fAvailableColumns.empty()) {
753 for (
auto &column : fAvailableColumns) {
757 column->CommitSuppressed();
766 if (fState != EState::kUnconnected)
767 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
773 if (fState != EState::kUnconnected)
782 if (~fTraits & kTraitMappable)
783 return AppendImpl(from);
785 fPrincipalColumn->Append(from);
786 return fPrincipalColumn->GetElement()->GetPackedSize();
805 return RBulkSpec::kAllSet;
843 if (fColumnRepresentatives.empty()) {
844 return {GetColumnRepresentations().GetSerializationDefault()};
848 result.reserve(fColumnRepresentatives.size());
849 for (
const auto &
r : fColumnRepresentatives) {
857 if (fState != EState::kUnconnected)
858 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
859 const auto &
validTypes = GetColumnRepresentations().GetSerializationTypes();
860 fColumnRepresentatives.clear();
868 if (std::find_if(fColumnRepresentatives.begin(), fColumnRepresentatives.end(),
869 [&
r](
const auto &
rep) { return r == rep.get(); }) == fColumnRepresentatives.end())
881 throw RException(
R__FAIL(
"No on-disk field information for `" + GetQualifiedFieldName() +
"`"));
890 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
895 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
907 "` cannot be matched to its in-memory type `" + GetTypeName() +
"` " +
913 fReadCallbacks.push_back(func);
915 return fReadCallbacks.size() - 1;
920 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
921 fIsSimple = (fTraits & kTraitMappable) && !fIsArtificial && fReadCallbacks.empty();
926 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
943 SetColumnRepresentatives({
rep});
946 if (fTypeAlias ==
"Double32_t")
954 if (fState != EState::kUnconnected)
955 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
957 AutoAdjustColumnTypes(
pageSink.GetWriteOptions());
960 for (
auto &column : fAvailableColumns) {
968 if (HasExtraTypeInfo()) {
969 pageSink.RegisterOnCommitDatasetCallback(
973 fState = EState::kConnectedToSink;
979 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
980 if (fState != EState::kUnconnected)
981 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
983 if (!fColumnRepresentatives.empty())
984 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
985 if (!fDescription.empty())
986 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
990 for (
auto &
f : fSubfields) {
992 f->SetOnDiskId(
pageSource.GetSharedDescriptorGuard()->FindFieldId(
f->GetFieldName(), GetOnDiskId()));
998 if (!fIsArtificial) {
1001 GenerateColumns(desc);
1002 if (fColumnRepresentatives.empty()) {
1004 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1006 fColumnRepresentatives = {t};
1011 R__ASSERT(!fColumnRepresentatives.empty());
1014 fOnDiskTypeVersion =
fieldDesc.GetTypeVersion();
1015 if (
fieldDesc.GetTypeChecksum().has_value())
1016 fOnDiskTypeChecksum = *
fieldDesc.GetTypeChecksum();
1019 for (
auto &column : fAvailableColumns)
1020 column->ConnectPageSource(fOnDiskId,
pageSource);
1022 AfterConnectPageSource();
1024 fState = EState::kConnectedToSource;
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
#define R__LOG_WARNING(...)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 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 id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Abstract base class for classes implementing the visitor design pattern.
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
static const char * GetColumnTypeName(ROOT::ENTupleColumnType type)
Base class for all ROOT issued exceptions.
Points to an array of objects with RNTuple I/O support, used for bulk reading.
void Reset(RNTupleLocalIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
RBulk & operator=(const RBulk &)=delete
void * fValues
Cached deleter of fField.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
void AdoptBuffer(void *buf, std::size_t capacity)
The list of column representations a field can have.
Selection_t fSerializationTypes
std::vector< ColumnRepresentation_t > Selection_t
A list of column representations.
Selection_t fDeserializationTypes
The union of the serialization types and the deserialization extra types passed during construction.
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
void BindRawPtr(void *rawPtr)
A field translates read and write calls from/to underlying columns to/from tree values.
void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives)
Fixes a column representative.
ROOT::Internal::RColumn * fPrincipalColumn
All fields that have columns have a distinct main column.
ROOT::NTupleSize_t EntryToColumnElementIndex(ROOT::NTupleSize_t globalIndex) const
Translate an entry index to a column element index of the principal column and vice versa.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
virtual void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
void FlushColumns()
Flushes data from active columns.
virtual void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to)
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
RBulk CreateBulk()
Creates a new, initially empty bulk.
bool fIsSimple
A field qualifies as simple if it is mappable (which implies it has a single principal column),...
RConstSchemaIterator cbegin() const
void AutoAdjustColumnTypes(const ROOT::RNTupleWriteOptions &options)
When connecting a field to a page sink, the field's default column representation is subject to adjus...
std::vector< const RFieldBase * > GetConstSubfields() const
void SetOnDiskId(ROOT::DescriptorId_t id)
void RemoveReadCallback(size_t idx)
std::vector< RFieldBase * > GetMutableSubfields()
static std::vector< RCheckResult > Check(const std::string &fieldName, const std::string &typeName)
Checks if the given type is supported by RNTuple.
size_t AddReadCallback(ReadCallback_t func)
Set a user-defined function to be called after reading a value, giving a chance to inspect and/or mod...
RConstSchemaIterator cend() const
std::size_t fNRepetitions
For fixed sized arrays, the array length.
std::function< void(void *)> ReadCallback_t
std::size_t Append(const void *from)
Write the given value into columns.
RValue CreateValue()
Generates an object of the field's type, wraps it in a shared pointer and returns it as an RValue con...
const ColumnRepresentation_t & EnsureCompatibleColumnTypes(const ROOT::RNTupleDescriptor &desc, std::uint16_t representationIndex) const
Returns the on-disk column types found in the provided descriptor for fOnDiskId and the given represe...
virtual std::vector< RValue > SplitValue(const RValue &value) const
Creates the list of direct child values given an existing value for this field.
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots (grandparent.parent....
std::size_t ReadBulk(const RBulkSpec &bulkSpec)
Returns the number of newly available values, that is the number of bools in bulkSpec....
std::vector< ROOT::ENTupleColumnType > ColumnRepresentation_t
void ConnectPageSource(ROOT::Experimental::Internal::RPageSource &pageSource)
Connects the field and its subfield tree to the given page source.
virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to)
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
virtual std::size_t AppendImpl(const void *from)
Operations on values of complex types, e.g.
RFieldBase * fParent
Subfields point to their mother field.
RFieldBase(std::string_view name, std::string_view type, ROOT::ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
@ 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.
@ kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
@ kTraitInvalidField
This field is an instance of RInvalidField and can be safely static_cast to it.
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 fType
The C++ type captured by this field.
RColumnRepresentations::Selection_t GetColumnRepresentatives() const
Returns the fColumnRepresentative pointee or, if unset (always the case for artificial fields),...
ROOT::ENTupleStructure fStructure
The role of this field in the data model structure.
void ConnectPageSink(ROOT::Experimental::Internal::RPageSink &pageSink, ROOT::NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
void SetDescription(std::string_view description)
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its subfields using a possibly new name and a new, unconnected set of columns.
std::string fName
The field name relative to its parent field.
void CommitCluster()
Flushes data from active columns to disk and calls CommitClusterImpl()
void * CreateObjectRawPtr() const
Factory method for the field's type. The caller owns the returned pointer.
virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec)
General implementation of bulk read.
The container field for an ntuple model, which itself has no physical representation.
Used in RFieldBase::Check() to record field creation failures.
@ kGeneric
Generic unrecoverable error.
@ kUnknownType
The type given to RFieldBase::Create was unknown.
@ kTypeError
The type given to RFieldBase::Create was invalid.
The on-storage metadata of an RNTuple.
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
RColumnDescriptorIterable GetColumnIterable() const
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Common user-tunable settings for storing RNTuples.
std::uint32_t GetCompression() const
const_iterator begin() const
const_iterator end() const
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
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.
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
std::tuple< std::string, std::vector< std::size_t > > ParseArrayType(const std::string &typeName)
Parse a type name of the form T[n][m]... and return the base type T and a vector that contains,...
RResult< void > EnsureValidNameForRNTuple(std::string_view name, std::string_view where)
Check whether a given string is a valid name according to the RNTuple specification.
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
void CallCommitClusterOnField(RFieldBase &)
unsigned long long ParseUIntTypeToken(const std::string &uintToken)
ROOT::RResult< std::unique_ptr< ROOT::RFieldBase > > CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
ERNTupleSerializationMode GetRNTupleSerializationMode(TClass *cl)
void CallConnectPageSinkOnField(RFieldBase &, ROOT::Experimental::Internal::RPageSink &, ROOT::NTupleSize_t firstEntry=0)
auto MakeAliasedSharedPtr(T *rawPtr)
std::string GetCanonicalTypePrefix(const std::string &typeName)
Applies RNTuple specific type name normalization rules (see specs) that help the string parsing in RF...
void CallFlushColumnsOnField(RFieldBase &)
std::unique_ptr< RFieldBase > CreateEmulatedField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
std::string GetNormalizedUnresolvedTypeName(const std::string &origName)
Applies all RNTuple type normalization rules except typedef resolution.
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Experimental::Internal::RPageSource &)
std::vector< std::string > TokenizeTypeList(std::string_view templateType)
Used in RFieldBase::Create() in order to get the comma-separated list of template types E....
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 ntuple model tree can carry different structural information about the type system.
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
bool GetReturnInvalidOnError() const
bool GetEmulateUnknownTypes() const
Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().
Used in the return value of the Check() method.
std::default_delete< T > deleter