23class CreateContextGuard;
25 friend class CreateContextGuard;
27 std::vector<std::string> fClassesOnStack;
30 bool fContinueOnError =
false;
33 CreateContext() =
default;
38class CreateContextGuard {
39 CreateContext &fCreateContext;
40 std::size_t fNOriginalClassesOnStack;
41 bool fOriginalContinueOnError;
44 CreateContextGuard(CreateContext &ctx)
45 : fCreateContext(ctx),
46 fNOriginalClassesOnStack(ctx.fClassesOnStack.
size()),
47 fOriginalContinueOnError(ctx.fContinueOnError)
52 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
53 fCreateContext.fContinueOnError = fOriginalContinueOnError;
58 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
59 fCreateContext.fClassesOnStack.end()) {
62 fCreateContext.fClassesOnStack.emplace_back(cl);
76 field.CommitCluster();
125 : fField(
other.fField),
127 fCapacity(
other.fCapacity),
129 fIsAdopted(
other.fIsAdopted),
130 fNValidValues(
other.fNValidValues),
131 fFirstIndex(
other.fFirstIndex)
140 std::swap(fField,
other.fField);
141 std::swap(fDeleter,
other.fDeleter);
142 std::swap(fValues,
other.fValues);
144 std::swap(fCapacity,
other.fCapacity);
146 std::swap(fIsAdopted,
other.fIsAdopted);
147 std::swap(fMaskAvail,
other.fMaskAvail);
148 std::swap(fNValidValues,
other.fNValidValues);
149 std::swap(fFirstIndex,
other.fFirstIndex);
165 for (std::size_t i = 0; i < fCapacity; ++i) {
166 fDeleter->operator()(GetValuePtrAt(i),
true );
170 operator delete(fValues);
175 if (fCapacity <
size) {
177 throw RException(
R__FAIL(
"invalid attempt to bulk read beyond the adopted buffer"));
183 for (std::size_t i = 0; i <
size; ++i) {
184 fField->ConstructValue(GetValuePtrAt(i));
188 fMaskAvail = std::make_unique<bool[]>(
size);
192 std::fill(fMaskAvail.get(), fMaskAvail.get() +
size,
false);
202 for (std::size_t i = 0; i <
fSize; ++i)
203 fNValidValues +=
static_cast<std::size_t
>(fMaskAvail[i]);
210 fCapacity = capacity;
213 fMaskAvail = std::make_unique<bool[]>(capacity);
228std::unique_ptr<void, typename ROOT::RFieldBase::RCreateObjectDeleter<void>::deleter>
229ROOT::RFieldBase::CreateObject<void>()
const
253 std::string
result = GetFieldName();
254 auto parent = GetParent();
255 while (parent && !parent->GetFieldName().empty()) {
257 parent = parent->GetParent();
269std::vector<ROOT::RFieldBase::RCheckResult>
274 cfOpts.SetReturnInvalidOnError(
true);
275 cfOpts.SetEmulateUnknownTypes(
false);
278 std::vector<RCheckResult>
result;
320 std::unique_ptr<ROOT::RFieldBase>
result;
371 }
else if (
resolvedType.substr(0, 12) ==
"std::vector<") {
375 }
else if (
resolvedType.substr(0, 19) ==
"ROOT::VecOps::RVec<") {
379 }
else if (
resolvedType.substr(0, 11) ==
"std::array<") {
387 }
else if (
resolvedType.substr(0, 13) ==
"std::variant<") {
389 std::vector<std::unique_ptr<RFieldBase>>
items;
391 for (
unsigned int i = 0; i <
innerTypes.size(); ++i) {
396 }
else if (
resolvedType.substr(0, 10) ==
"std::pair<") {
401 std::array<std::unique_ptr<RFieldBase>, 2>
items{
405 }
else if (
resolvedType.substr(0, 11) ==
"std::tuple<") {
407 std::vector<std::unique_ptr<RFieldBase>>
items;
409 for (
unsigned int i = 0; i <
innerTypes.size(); ++i) {
414 }
else if (
resolvedType.substr(0, 12) ==
"std::bitset<") {
417 }
else if (
resolvedType.substr(0, 16) ==
"std::unique_ptr<") {
423 }
else if (
resolvedType.substr(0, 14) ==
"std::optional<") {
435 }
else if (
resolvedType.substr(0, 19) ==
"std::unordered_set<") {
441 }
else if (
resolvedType.substr(0, 14) ==
"std::multiset<") {
447 }
else if (
resolvedType.substr(0, 24) ==
"std::unordered_multiset<") {
470 }
else if (
resolvedType.substr(0, 19) ==
"std::unordered_map<") {
484 result = std::make_unique<RMapField>(
486 }
else if (
resolvedType.substr(0, 14) ==
"std::multimap<") {
502 }
else if (
resolvedType.substr(0, 24) ==
"std::unordered_multimap<") {
506 fnFail(
"the type list for std::unordered_multimap must have exactly two elements"));
517 result = std::make_unique<RMapField>(
519 }
else if (
resolvedType.substr(0, 12) ==
"std::atomic<") {
525 }
else if (
resolvedType.substr(0, 25) ==
"ROOT::RNTupleCardinality<") {
531 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(
fieldName);
533 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(
fieldName);
551 if (cl->GetCollectionProxy()) {
552 result = std::make_unique<RProxiedCollectionField>(
fieldName, typeName);
602 }
catch (
const RException &
e) {
603 auto error =
e.GetError();
605 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(
fieldName, typeName, error.GetReport(),
610 }
catch (
const std::logic_error &
e) {
613 return std::unique_ptr<RFieldBase>(
638 auto clone = CloneImpl(
newName);
639 clone->fTypeAlias = fTypeAlias;
640 clone->fOnDiskId = fOnDiskId;
641 clone->fDescription = fDescription;
643 clone->fColumnRepresentatives = fColumnRepresentatives;
649 R__ASSERT(
false &&
"A non-simple RField must implement its own AppendImpl");
660 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(
localIndex), to);
666 std::size_t
nRead = 0;
667 for (std::size_t i = 0; i <
bulkSpec.fCount; ++i) {
685 void *
where =
operator new(GetValueSize());
687 ConstructValue(
where);
693 void *obj = CreateObjectRawPtr();
699 return std::vector<RValue>();
706 if (fState != EState::kUnconnected)
707 throw RException(
R__FAIL(
"invalid attempt to attach subfield to already connected field"));
708 child->fParent =
this;
709 fSubfields.emplace_back(std::move(
child));
715 for (
auto f =
this;
f !=
nullptr;
f =
f->GetParent()) {
716 auto parent =
f->GetParent();
721 result *= std::max(
f->GetNRepetitions(), std::size_t{1U});
728 std::vector<RFieldBase *>
result;
729 result.reserve(fSubfields.size());
730 for (
const auto &
f : fSubfields) {
738 std::vector<const RFieldBase *>
result;
739 result.reserve(fSubfields.size());
740 for (
const auto &
f : fSubfields) {
748 if (!fAvailableColumns.empty()) {
750 for (
auto &column : fAvailableColumns) {
760 if (!fAvailableColumns.empty()) {
762 for (
auto &column : fAvailableColumns) {
766 column->CommitSuppressed();
775 if (fState != EState::kUnconnected)
776 throw RException(
R__FAIL(
"cannot set field description once field is connected"));
782 if (fState != EState::kUnconnected)
791 if (~fTraits & kTraitMappable)
792 return AppendImpl(from);
794 fPrincipalColumn->Append(from);
795 return fPrincipalColumn->GetElement()->GetPackedSize();
814 return RBulkSpec::kAllSet;
852 if (fColumnRepresentatives.empty()) {
853 return {GetColumnRepresentations().GetSerializationDefault()};
857 result.reserve(fColumnRepresentatives.size());
858 for (
const auto &
r : fColumnRepresentatives) {
866 if (fState != EState::kUnconnected)
867 throw RException(
R__FAIL(
"cannot set column representative once field is connected"));
868 const auto &
validTypes = GetColumnRepresentations().GetSerializationTypes();
869 fColumnRepresentatives.clear();
877 if (std::find_if(fColumnRepresentatives.begin(), fColumnRepresentatives.end(),
878 [&
r](
const auto &
rep) { return r == rep.get(); }) == fColumnRepresentatives.end())
890 throw RException(
R__FAIL(
"No on-disk field information for `" + GetQualifiedFieldName() +
"`"));
899 throw RException(
R__FAIL(
"No on-disk column information for field `" + GetQualifiedFieldName() +
"`"));
904 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
916 "` cannot be matched to its in-memory type `" + GetTypeName() +
"` " +
922 fReadCallbacks.push_back(func);
924 return fReadCallbacks.size() - 1;
929 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
930 fIsSimple = (fTraits & kTraitMappable) && !fIsArtificial && fReadCallbacks.empty();
935 if ((options.
GetCompression() == 0) && HasDefaultColumnRepresentative()) {
952 SetColumnRepresentatives({
rep});
955 if (fTypeAlias ==
"Double32_t")
963 if (fState != EState::kUnconnected)
964 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page sink"));
966 AutoAdjustColumnTypes(
pageSink.GetWriteOptions());
969 for (
auto &column : fAvailableColumns) {
977 if (HasExtraTypeInfo()) {
978 pageSink.RegisterOnCommitDatasetCallback(
982 fState = EState::kConnectedToSink;
988 throw RException(
R__FAIL(
"invalid attempt to connect zero field to page source"));
989 if (fState != EState::kUnconnected)
990 throw RException(
R__FAIL(
"invalid attempt to connect an already connected field to a page source"));
992 if (!fColumnRepresentatives.empty())
993 throw RException(
R__FAIL(
"fixed column representative only valid when connecting to a page sink"));
994 if (!fDescription.empty())
995 throw RException(
R__FAIL(
"setting description only valid when connecting to a page sink"));
999 for (
auto &
f : fSubfields) {
1001 f->SetOnDiskId(
pageSource.GetSharedDescriptorGuard()->FindFieldId(
f->GetFieldName(), GetOnDiskId()));
1007 if (!fIsArtificial) {
1010 GenerateColumns(desc);
1011 if (fColumnRepresentatives.empty()) {
1013 for (
const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1015 fColumnRepresentatives = {t};
1020 R__ASSERT(!fColumnRepresentatives.empty());
1023 fOnDiskTypeVersion =
fieldDesc.GetTypeVersion();
1024 if (
fieldDesc.GetTypeChecksum().has_value())
1025 fOnDiskTypeChecksum = *
fieldDesc.GetTypeChecksum();
1028 for (
auto &column : fAvailableColumns)
1029 column->ConnectPageSource(fOnDiskId,
pageSource);
1031 AfterConnectPageSource();
1033 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.
static const char * GetColumnTypeName(ROOT::ENTupleColumnType type)
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
Base class for all ROOT issued exceptions.
Points to an array of objects with RNTuple I/O support, used for bulk reading.
std::unique_ptr< bool[]> fMaskAvail
Masks invalid values in the array.
std::unique_ptr< RFieldBase::RDeleter > fDeleter
void Reset(RNTupleLocalIndex firstIndex, std::size_t size)
Sets a new range for the bulk.
void * fValues
Cached deleter of fField.
RBulkValues & operator=(const RBulkValues &)=delete
RBulkValues(RFieldBase *field)
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.
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....
RBulkValues CreateBulk()
Creates a new, initially empty bulk.
void ConnectPageSink(ROOT::Internal::RPageSink &pageSink, ROOT::NTupleSize_t firstEntry=0)
Fields and their columns live in the void until connected to a physical page storage.
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
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.
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),...
@ 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.
ROOT::ENTupleStructure fStructure
The role of this field in the data model structure.
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 ConnectPageSource(ROOT::Internal::RPageSource &pageSource)
Connects the field and its subfield tree to the given page source.
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::vector< std::string > TokenizeTypeList(std::string_view templateType, std::size_t maxArgs=0)
Used in RFieldBase::Create() in order to get the comma-separated list of template types E....
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
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 &)
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
unsigned long long ParseUIntTypeToken(const std::string &uintToken)
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
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)
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::string GetNormalizedUnresolvedTypeName(const std::string &origName)
Applies all RNTuple type normalization rules except typedef resolution.
void CallConnectPageSinkOnField(RFieldBase &, ROOT::Internal::RPageSink &, ROOT::NTupleSize_t firstEntry=0)
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...
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