Logo ROOT  
Reference Guide
RNTupleModel.cxx
Go to the documentation of this file.
1/// \file RNTupleModel.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
18#include <ROOT/RNTupleModel.hxx>
19#include <ROOT/RNTuple.hxx>
20#include <ROOT/StringUtils.hxx>
21
22#include <atomic>
23#include <cstdlib>
24#include <memory>
25#include <utility>
26
27
29{
31 if (!nameValid) {
32 nameValid.Throw();
33 }
34 auto fieldNameStr = std::string(fieldName);
35 if (fFieldNames.insert(fieldNameStr).second == false) {
36 throw RException(R__FAIL("field name '" + fieldNameStr + "' already exists in NTuple model"));
37 }
38}
39
41{
42 if (IsFrozen())
43 throw RException(R__FAIL("invalid attempt to modify frozen model"));
44}
45
47{
48 if (!fDefaultEntry)
49 throw RException(R__FAIL("invalid attempt to use default entry of bare model"));
50}
51
53 : fFieldZero(std::make_unique<RFieldZero>())
54{}
55
56std::unique_ptr<ROOT::Experimental::RNTupleModel> ROOT::Experimental::RNTupleModel::Create()
57{
58 auto model = CreateBare();
59 model->fDefaultEntry = std::unique_ptr<REntry>(new REntry());
60 return model;
61}
62
63std::unique_ptr<ROOT::Experimental::RNTupleModel> ROOT::Experimental::RNTupleModel::Clone() const
64{
65 auto cloneModel = std::unique_ptr<RNTupleModel>(new RNTupleModel());
66 auto cloneFieldZero = fFieldZero->Clone("");
67 cloneModel->fModelId = fModelId;
68 cloneModel->fFieldZero = std::unique_ptr<RFieldZero>(static_cast<RFieldZero *>(cloneFieldZero.release()));
69 cloneModel->fFieldNames = fFieldNames;
70 cloneModel->fDescription = fDescription;
71 if (fDefaultEntry) {
72 cloneModel->fDefaultEntry = std::unique_ptr<REntry>(new REntry(fModelId));
73 for (const auto &f : cloneModel->fFieldZero->GetSubFields()) {
74 cloneModel->fDefaultEntry->AddValue(f->GenerateValue());
75 }
76 }
77 return cloneModel;
78}
79
80
81void ROOT::Experimental::RNTupleModel::AddField(std::unique_ptr<Detail::RFieldBase> field)
82{
83 EnsureNotFrozen();
84 if (!field)
85 throw RException(R__FAIL("null field"));
86 EnsureValidFieldName(field->GetName());
87
88 if (fDefaultEntry)
89 fDefaultEntry->AddValue(field->GenerateValue());
90 fFieldZero->Attach(std::move(field));
91}
92
93
94std::shared_ptr<ROOT::Experimental::RCollectionNTupleWriter> ROOT::Experimental::RNTupleModel::MakeCollection(
95 std::string_view fieldName, std::unique_ptr<RNTupleModel> collectionModel)
96{
97 EnsureNotFrozen();
98 EnsureValidFieldName(fieldName);
99 if (!collectionModel) {
100 throw RException(R__FAIL("null collectionModel"));
101 }
102 auto collectionNTuple = std::make_shared<RCollectionNTupleWriter>(std::move(collectionModel->fDefaultEntry));
103 auto field = std::make_unique<RCollectionField>(fieldName, collectionNTuple, std::move(collectionModel));
104 if (fDefaultEntry)
105 fDefaultEntry->CaptureValue(field->CaptureValue(collectionNTuple->GetOffsetPtr()));
106 fFieldZero->Attach(std::move(field));
107 return collectionNTuple;
108}
109
112{
113 if (fieldName.empty())
114 return nullptr;
115
116 auto *field = static_cast<ROOT::Experimental::Detail::RFieldBase *>(fFieldZero.get());
117 for (auto subfieldName : ROOT::Split(fieldName, ".")) {
118 const auto subfields = field->GetSubFields();
119 auto it =
120 std::find_if(subfields.begin(), subfields.end(), [&](const auto *f) { return f->GetName() == subfieldName; });
121 if (it != subfields.end()) {
122 field = *it;
123 } else {
124 field = nullptr;
125 break;
126 }
127 }
128
129 return field;
130}
131
133{
134 if (!IsFrozen())
135 throw RException(R__FAIL("invalid attempt to get default entry of unfrozen model"));
136 EnsureNotBare();
137 return fDefaultEntry.get();
138}
139
140std::unique_ptr<ROOT::Experimental::REntry> ROOT::Experimental::RNTupleModel::CreateEntry() const
141{
142 if (!IsFrozen())
143 throw RException(R__FAIL("invalid attempt to create entry of unfrozen model"));
144
145 auto entry = std::unique_ptr<REntry>(new REntry(fModelId));
146 for (const auto &f : fFieldZero->GetSubFields()) {
147 entry->AddValue(f->GenerateValue());
148 }
149 return entry;
150}
151
152std::unique_ptr<ROOT::Experimental::REntry> ROOT::Experimental::RNTupleModel::CreateBareEntry() const
153{
154 if (!IsFrozen())
155 throw RException(R__FAIL("invalid attempt to create entry of unfrozen model"));
156
157 auto entry = std::unique_ptr<REntry>(new REntry(fModelId));
158 for (const auto &f : fFieldZero->GetSubFields()) {
159 entry->CaptureValue(f->CaptureValue(nullptr));
160 }
161 return entry;
162}
163
165{
166 if (IsFrozen())
167 return;
168
169 static std::atomic<std::uint64_t> gLastModelId = 0;
170 fModelId = ++gLastModelId;
171 if (fDefaultEntry)
172 fDefaultEntry->fModelId = fModelId;
173}
174
176{
177 EnsureNotFrozen();
178 fDescription = std::string(description);
179}
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition: RError.hxx:291
#define f(i)
Definition: RSha256.hxx:104
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition: RField.cxx:262
std::vector< RFieldBase * > GetSubFields() const
Definition: RField.cxx:321
void Throw()
Throws an RException with fError.
Definition: RError.cxx:69
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
Definition: REntry.hxx:43
Base class for all ROOT issued exceptions.
Definition: RError.hxx:114
The container field for an ntuple model, which itself has no physical representation.
Definition: RField.hxx:270
The RNTupleModel encapulates the schema of an ntuple.
std::unordered_set< std::string > fFieldNames
Keeps track of which field names are taken.
void EnsureValidFieldName(std::string_view fieldName)
Checks that user-provided field names are valid in the context of this NTuple model.
void EnsureNotBare() const
Throws an RException if fDefaultEntry is nullptr.
std::unique_ptr< RNTupleModel > Clone() const
void EnsureNotFrozen() const
Throws an RException if fFrozen is true.
std::unique_ptr< REntry > CreateBareEntry() const
In a bare entry, all values point to nullptr.
std::unique_ptr< REntry > CreateEntry() const
static std::unique_ptr< RNTupleModel > Create()
void SetDescription(std::string_view description)
std::shared_ptr< RCollectionNTupleWriter > MakeCollection(std::string_view fieldName, std::unique_ptr< RNTupleModel > collectionModel)
Ingests a model for a sub collection and attaches it to the current model.
const Detail::RFieldBase * GetField(std::string_view fieldName) const
void AddField(std::unique_ptr< Detail::RFieldBase > field)
Adds a field whose type is not known at compile time.
RResult<void> has no data member and no Inspect() method but instead a Success() factory method.
Definition: RError.hxx:257
basic_string_view< char > string_view
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
Definition: StringUtils.cxx:23