Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldBase.cxx
Go to the documentation of this file.
1/// \file RFieldBase.cxx
2/// \ingroup NTuple
3/// \author Jonas Hahnfeld <jonas.hahnfeld@cern.ch>
4/// \date 2024-11-19
5
6#include <ROOT/RError.hxx>
7#include <ROOT/RField.hxx>
8#include <ROOT/RFieldBase.hxx>
10#include <ROOT/RFieldUtils.hxx>
11
12#include <TClass.h>
13#include <TClassEdit.h>
14#include <TEnum.h>
15
16#include <string>
17#include <vector>
18
19namespace {
20
21/// Used as a thread local context storage for Create(); steers the behavior of the Create() call stack
22class CreateContextGuard;
23class CreateContext {
24 friend class CreateContextGuard;
25 /// All classes that were defined by Create() calls higher up in the stack. Finds cyclic type definitions.
26 std::vector<std::string> fClassesOnStack;
27 /// If set to true, Create() will create an RInvalidField on error instead of throwing an exception.
28 /// This is used in RFieldBase::Check() to identify unsupported sub fields.
29 bool fContinueOnError = false;
30
31public:
32 CreateContext() = default;
33 bool GetContinueOnError() const { return fContinueOnError; }
34};
35
36/// RAII for modifications of CreateContext
37class CreateContextGuard {
38 CreateContext &fCreateContext;
39 std::size_t fNOriginalClassesOnStack;
40 bool fOriginalContinueOnError;
41
42public:
43 CreateContextGuard(CreateContext &ctx)
44 : fCreateContext(ctx),
45 fNOriginalClassesOnStack(ctx.fClassesOnStack.size()),
46 fOriginalContinueOnError(ctx.fContinueOnError)
47 {
48 }
50 {
51 fCreateContext.fClassesOnStack.resize(fNOriginalClassesOnStack);
52 fCreateContext.fContinueOnError = fOriginalContinueOnError;
53 }
54
55 void AddClassToStack(const std::string &cl)
56 {
57 if (std::find(fCreateContext.fClassesOnStack.begin(), fCreateContext.fClassesOnStack.end(), cl) !=
58 fCreateContext.fClassesOnStack.end()) {
59 throw ROOT::RException(R__FAIL("cyclic class definition: " + cl));
60 }
61 fCreateContext.fClassesOnStack.emplace_back(cl);
62 }
63
64 void SetContinueOnError(bool value) { fCreateContext.fContinueOnError = value; }
65};
66
67} // anonymous namespace
68
86
88ROOT::Internal::CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName,
89 const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc,
91{
92 return RFieldBase::Create(fieldName, typeName, options, desc, fieldId);
93}
94
95//------------------------------------------------------------------------------
96
98{
99 // A single representations with an empty set of columns
102}
103
111
112//------------------------------------------------------------------------------
113
115{
116 // Set fObjPtr to an aliased shared_ptr of the input raw pointer. Note that
117 // fObjPtr will be non-empty but have use count zero.
119}
120
121//------------------------------------------------------------------------------
122
124 : fField(other.fField),
126 fCapacity(other.fCapacity),
128 fIsAdopted(other.fIsAdopted),
129 fNValidValues(other.fNValidValues),
130 fFirstIndex(other.fFirstIndex)
131{
132 std::swap(fDeleter, other.fDeleter);
133 std::swap(fValues, other.fValues);
134 std::swap(fMaskAvail, other.fMaskAvail);
135}
136
138{
139 std::swap(fField, other.fField);
140 std::swap(fDeleter, other.fDeleter);
141 std::swap(fValues, other.fValues);
142 std::swap(fValueSize, other.fValueSize);
143 std::swap(fCapacity, other.fCapacity);
144 std::swap(fSize, other.fSize);
145 std::swap(fIsAdopted, other.fIsAdopted);
146 std::swap(fMaskAvail, other.fMaskAvail);
147 std::swap(fNValidValues, other.fNValidValues);
148 std::swap(fFirstIndex, other.fFirstIndex);
149 return *this;
150}
151
153{
154 if (fValues)
155 ReleaseValues();
156}
157
159{
160 if (fIsAdopted)
161 return;
162
163 if (!(fField->GetTraits() & RFieldBase::kTraitTriviallyDestructible)) {
164 for (std::size_t i = 0; i < fCapacity; ++i) {
165 fDeleter->operator()(GetValuePtrAt(i), true /* dtorOnly */);
166 }
167 }
168
169 operator delete(fValues);
170}
171
173{
174 if (fCapacity < size) {
175 if (fIsAdopted) {
176 throw RException(R__FAIL("invalid attempt to bulk read beyond the adopted buffer"));
177 }
178 ReleaseValues();
179 fValues = operator new(size * fValueSize);
180
181 if (!(fField->GetTraits() & RFieldBase::kTraitTriviallyConstructible)) {
182 for (std::size_t i = 0; i < size; ++i) {
183 fField->ConstructValue(GetValuePtrAt(i));
184 }
185 }
186
187 fMaskAvail = std::make_unique<bool[]>(size);
188 fCapacity = size;
189 }
190
191 std::fill(fMaskAvail.get(), fMaskAvail.get() + size, false);
192 fNValidValues = 0;
193
194 fFirstIndex = firstIndex;
195 fSize = size;
196}
197
199{
200 fNValidValues = 0;
201 for (std::size_t i = 0; i < fSize; ++i)
202 fNValidValues += static_cast<std::size_t>(fMaskAvail[i]);
203}
204
205void ROOT::RFieldBase::RBulkValues::AdoptBuffer(void *buf, std::size_t capacity)
206{
207 ReleaseValues();
208 fValues = buf;
209 fCapacity = capacity;
210 fSize = capacity;
211
212 fMaskAvail = std::make_unique<bool[]>(capacity);
213
214 fFirstIndex = RNTupleLocalIndex();
215
216 fIsAdopted = true;
217}
218
219//------------------------------------------------------------------------------
220
222{
223 R__LOG_WARNING(ROOT::Internal::NTupleLog()) << "possibly leaking object from RField<T>::CreateObject<void>";
224}
225
226template <>
227std::unique_ptr<void, typename ROOT::RFieldBase::RCreateObjectDeleter<void>::deleter>
228ROOT::RFieldBase::CreateObject<void>() const
229{
231 return std::unique_ptr<void, RCreateObjectDeleter<void>::deleter>(CreateObjectRawPtr(), gDeleter);
232}
233
234//------------------------------------------------------------------------------
235
236ROOT::RFieldBase::RFieldBase(std::string_view name, std::string_view type, ROOT::ENTupleStructure structure,
237 bool isSimple, std::size_t nRepetitions)
238 : fName(name),
239 fType(type),
240 fStructure(structure),
243 fParent(nullptr),
244 fPrincipalColumn(nullptr),
246{
248}
249
251{
252 std::string result = GetFieldName();
253 auto parent = GetParent();
254 while (parent && !parent->GetFieldName().empty()) {
255 result = parent->GetFieldName() + "." + result;
256 parent = parent->GetParent();
257 }
258 return result;
259}
260
262ROOT::RFieldBase::Create(const std::string &fieldName, const std::string &typeName)
263{
264 return R__FORWARD_RESULT(
266}
267
268std::vector<ROOT::RFieldBase::RCheckResult>
269ROOT::RFieldBase::Check(const std::string &fieldName, const std::string &typeName)
270{
273 cfOpts.SetReturnInvalidOnError(true);
274 cfOpts.SetEmulateUnknownTypes(false);
275 fieldZero.Attach(RFieldBase::Create(fieldName, typeName, cfOpts, nullptr, kInvalidDescriptorId).Unwrap());
276
277 std::vector<RCheckResult> result;
278 for (const auto &f : fieldZero) {
279 const bool isInvalidField = f.GetTraits() & RFieldBase::kTraitInvalidField;
280 if (!isInvalidField)
281 continue;
282
283 const auto &invalidField = static_cast<const RInvalidField &>(f);
284 result.emplace_back(
285 RCheckResult{invalidField.GetQualifiedFieldName(), invalidField.GetTypeName(), invalidField.GetError()});
286 }
287 return result;
288}
289
291ROOT::RFieldBase::Create(const std::string &fieldName, const std::string &typeName,
292 const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc,
294{
298
300
301 thread_local CreateContext createContext;
302 CreateContextGuard createContextGuard(createContext);
303 if (options.GetReturnInvalidOnError())
304 createContextGuard.SetContinueOnError(true);
305
306 auto fnFail = [&fieldName,
307 &resolvedType](const std::string &errMsg,
309 RInvalidField::RCategory::kTypeError) -> RResult<std::unique_ptr<RFieldBase>> {
310 if (createContext.GetContinueOnError()) {
311 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, resolvedType, errMsg, cat));
312 } else {
313 return R__FAIL(errMsg);
314 }
315 };
316
317 if (resolvedType.empty())
318 return R__FORWARD_RESULT(fnFail("no type name specified for field '" + fieldName + "'"));
319
320 std::unique_ptr<ROOT::RFieldBase> result;
321
322 const auto maybeGetChildId = [desc, fieldId](int childId) {
323 if (desc) {
324 const auto &fieldDesc = desc->GetFieldDescriptor(fieldId);
325 return fieldDesc.GetLinkIds().at(childId);
326 } else {
328 }
329 };
330
331 // try-catch block to intercept any exception that may be thrown by Unwrap() so that this
332 // function never throws but returns RResult::Error instead.
333 try {
335 std::unique_ptr<RFieldBase> arrayField = Create("_0", arrayBaseType, options, desc, fieldId).Unwrap();
336 for (int i = arraySizes.size() - 1; i >= 0; --i) {
337 arrayField =
338 std::make_unique<RArrayField>((i == 0) ? fieldName : "_0", std::move(arrayField), arraySizes[i]);
339 }
340 return arrayField;
341 }
342
343 if (resolvedType == "bool") {
344 result = std::make_unique<RField<bool>>(fieldName);
345 } else if (resolvedType == "char") {
346 result = std::make_unique<RField<char>>(fieldName);
347 } else if (resolvedType == "std::byte") {
348 result = std::make_unique<RField<std::byte>>(fieldName);
349 } else if (resolvedType == "std::int8_t") {
350 result = std::make_unique<RField<std::int8_t>>(fieldName);
351 } else if (resolvedType == "std::uint8_t") {
352 result = std::make_unique<RField<std::uint8_t>>(fieldName);
353 } else if (resolvedType == "std::int16_t") {
354 result = std::make_unique<RField<std::int16_t>>(fieldName);
355 } else if (resolvedType == "std::uint16_t") {
356 result = std::make_unique<RField<std::uint16_t>>(fieldName);
357 } else if (resolvedType == "std::int32_t") {
358 result = std::make_unique<RField<std::int32_t>>(fieldName);
359 } else if (resolvedType == "std::uint32_t") {
360 result = std::make_unique<RField<std::uint32_t>>(fieldName);
361 } else if (resolvedType == "std::int64_t") {
362 result = std::make_unique<RField<std::int64_t>>(fieldName);
363 } else if (resolvedType == "std::uint64_t") {
364 result = std::make_unique<RField<std::uint64_t>>(fieldName);
365 } else if (resolvedType == "float") {
366 result = std::make_unique<RField<float>>(fieldName);
367 } else if (resolvedType == "double") {
368 result = std::make_unique<RField<double>>(fieldName);
369 } else if (resolvedType == "Double32_t") {
370 result = std::make_unique<RField<double>>(fieldName);
371 static_cast<RField<double> *>(result.get())->SetDouble32();
372 // Prevent the type alias from being reset by returning early
373 return result;
374 } else if (resolvedType == "std::string") {
375 result = std::make_unique<RField<std::string>>(fieldName);
376 } else if (resolvedType == "TObject") {
377 result = std::make_unique<RField<TObject>>(fieldName);
378 } else if (resolvedType == "std::vector<bool>") {
379 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
380 } else if (resolvedType.substr(0, 12) == "std::vector<") {
381 std::string itemTypeName = resolvedType.substr(12, resolvedType.length() - 13);
382 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0));
383 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
384 } else if (resolvedType.substr(0, 19) == "ROOT::VecOps::RVec<") {
385 std::string itemTypeName = resolvedType.substr(19, resolvedType.length() - 20);
386 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0));
387 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
388 } else if (resolvedType.substr(0, 11) == "std::array<") {
389 auto arrayDef = TokenizeTypeList(resolvedType.substr(11, resolvedType.length() - 12));
390 if (arrayDef.size() != 2) {
391 return R__FORWARD_RESULT(fnFail("the template list for std::array must have exactly two elements"));
392 }
394 auto itemField = Create("_0", arrayDef[0], options, desc, maybeGetChildId(0));
395 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
396 } else if (resolvedType.substr(0, 13) == "std::variant<") {
397 auto innerTypes = TokenizeTypeList(resolvedType.substr(13, resolvedType.length() - 14));
398 std::vector<std::unique_ptr<RFieldBase>> items;
399 items.reserve(innerTypes.size());
400 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
401 items.emplace_back(
402 Create("_" + std::to_string(i), innerTypes[i], options, desc, maybeGetChildId(i)).Unwrap());
403 }
404 result = std::make_unique<RVariantField>(fieldName, std::move(items));
405 } else if (resolvedType.substr(0, 10) == "std::pair<") {
406 auto innerTypes = TokenizeTypeList(resolvedType.substr(10, resolvedType.length() - 11));
407 if (innerTypes.size() != 2) {
408 return R__FORWARD_RESULT(fnFail("the type list for std::pair must have exactly two elements"));
409 }
410 std::array<std::unique_ptr<RFieldBase>, 2> items{
411 Create("_0", innerTypes[0], options, desc, maybeGetChildId(0)).Unwrap(),
412 Create("_1", innerTypes[1], options, desc, maybeGetChildId(1)).Unwrap()};
413 result = std::make_unique<RPairField>(fieldName, std::move(items));
414 } else if (resolvedType.substr(0, 11) == "std::tuple<") {
415 auto innerTypes = TokenizeTypeList(resolvedType.substr(11, resolvedType.length() - 12));
416 std::vector<std::unique_ptr<RFieldBase>> items;
417 items.reserve(innerTypes.size());
418 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
419 items.emplace_back(
420 Create("_" + std::to_string(i), innerTypes[i], options, desc, maybeGetChildId(i)).Unwrap());
421 }
422 result = std::make_unique<RTupleField>(fieldName, std::move(items));
423 } else if (resolvedType.substr(0, 12) == "std::bitset<") {
424 auto size = ParseUIntTypeToken(resolvedType.substr(12, resolvedType.length() - 13));
425 result = std::make_unique<RBitsetField>(fieldName, size);
426 } else if (resolvedType.substr(0, 16) == "std::unique_ptr<") {
427 std::string itemTypeName = resolvedType.substr(16, resolvedType.length() - 17);
428 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
429 auto normalizedInnerTypeName = itemField->GetTypeName();
430 result = std::make_unique<RUniquePtrField>(fieldName, "std::unique_ptr<" + normalizedInnerTypeName + ">",
431 std::move(itemField));
432 } else if (resolvedType.substr(0, 14) == "std::optional<") {
433 std::string itemTypeName = resolvedType.substr(14, resolvedType.length() - 15);
434 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
435 auto normalizedInnerTypeName = itemField->GetTypeName();
436 result = std::make_unique<ROptionalField>(fieldName, "std::optional<" + normalizedInnerTypeName + ">",
437 std::move(itemField));
438 } else if (resolvedType.substr(0, 9) == "std::set<") {
439 std::string itemTypeName = resolvedType.substr(9, resolvedType.length() - 10);
440 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
441 auto normalizedInnerTypeName = itemField->GetTypeName();
442 result =
443 std::make_unique<RSetField>(fieldName, "std::set<" + normalizedInnerTypeName + ">", std::move(itemField));
444 } else if (resolvedType.substr(0, 19) == "std::unordered_set<") {
445 std::string itemTypeName = resolvedType.substr(19, resolvedType.length() - 20);
446 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
447 auto normalizedInnerTypeName = itemField->GetTypeName();
448 result = std::make_unique<RSetField>(fieldName, "std::unordered_set<" + normalizedInnerTypeName + ">",
449 std::move(itemField));
450 } else if (resolvedType.substr(0, 14) == "std::multiset<") {
451 std::string itemTypeName = resolvedType.substr(14, resolvedType.length() - 15);
452 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
453 auto normalizedInnerTypeName = itemField->GetTypeName();
454 result = std::make_unique<RSetField>(fieldName, "std::multiset<" + normalizedInnerTypeName + ">",
455 std::move(itemField));
456 } else if (resolvedType.substr(0, 24) == "std::unordered_multiset<") {
457 std::string itemTypeName = resolvedType.substr(24, resolvedType.length() - 25);
458 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
459 auto normalizedInnerTypeName = itemField->GetTypeName();
460 result = std::make_unique<RSetField>(fieldName, "std::unordered_multiset<" + normalizedInnerTypeName + ">",
461 std::move(itemField));
462 } else if (resolvedType.substr(0, 9) == "std::map<") {
463 auto innerTypes = TokenizeTypeList(resolvedType.substr(9, resolvedType.length() - 10));
464 if (innerTypes.size() != 2) {
465 return R__FORWARD_RESULT(fnFail("the type list for std::map must have exactly two elements"));
466 }
467
468 auto itemField =
469 Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0))
470 .Unwrap();
471
472 // We use the type names of subfields of the newly created item fields to create the map's type name to
473 // ensure the inner type names are properly normalized.
474 auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName();
475 auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName();
476
477 result = std::make_unique<RMapField>(fieldName, "std::map<" + keyTypeName + "," + valueTypeName + ">",
478 std::move(itemField));
479 } else if (resolvedType.substr(0, 19) == "std::unordered_map<") {
480 auto innerTypes = TokenizeTypeList(resolvedType.substr(19, resolvedType.length() - 20));
481 if (innerTypes.size() != 2)
482 return R__FORWARD_RESULT(fnFail("the type list for std::unordered_map must have exactly two elements"));
483
484 auto itemField =
485 Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0))
486 .Unwrap();
488 // We use the type names of subfields of the newly created item fields to create the map's type name to
489 // ensure the inner type names are properly normalized.
490 auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName();
491 auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName();
492
493 result = std::make_unique<RMapField>(
494 fieldName, "std::unordered_map<" + keyTypeName + "," + valueTypeName + ">", std::move(itemField));
495 } else if (resolvedType.substr(0, 14) == "std::multimap<") {
496 auto innerTypes = TokenizeTypeList(resolvedType.substr(14, resolvedType.length() - 15));
497 if (innerTypes.size() != 2)
498 return R__FORWARD_RESULT(fnFail("the type list for std::multimap must have exactly two elements"));
499
500 auto itemField =
501 Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0))
502 .Unwrap();
503
504 // We use the type names of subfields of the newly created item fields to create the map's type name to
505 // ensure the inner type names are properly normalized.
506 auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName();
507 auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName();
508
509 result = std::make_unique<RMapField>(fieldName, "std::multimap<" + keyTypeName + "," + valueTypeName + ">",
510 std::move(itemField));
511 } else if (resolvedType.substr(0, 24) == "std::unordered_multimap<") {
512 auto innerTypes = TokenizeTypeList(resolvedType.substr(24, resolvedType.length() - 25));
513 if (innerTypes.size() != 2)
514 return R__FORWARD_RESULT(
515 fnFail("the type list for std::unordered_multimap must have exactly two elements"));
516
517 auto itemField =
518 Create("_0", "std::pair<" + innerTypes[0] + "," + innerTypes[1] + ">", options, desc, maybeGetChildId(0))
519 .Unwrap();
520
521 // We use the type names of subfields of the newly created item fields to create the map's type name to
522 // ensure the inner type names are properly normalized.
523 auto keyTypeName = itemField->GetConstSubfields()[0]->GetTypeName();
524 auto valueTypeName = itemField->GetConstSubfields()[1]->GetTypeName();
525
526 result = std::make_unique<RMapField>(
527 fieldName, "std::unordered_multimap<" + keyTypeName + "," + valueTypeName + ">", std::move(itemField));
528 } else if (resolvedType.substr(0, 12) == "std::atomic<") {
529 std::string itemTypeName = resolvedType.substr(12, resolvedType.length() - 13);
530 auto itemField = Create("_0", itemTypeName, options, desc, maybeGetChildId(0)).Unwrap();
531 auto normalizedInnerTypeName = itemField->GetTypeName();
532 result = std::make_unique<RAtomicField>(fieldName, "std::atomic<" + normalizedInnerTypeName + ">",
533 std::move(itemField));
534 } else if (resolvedType.substr(0, 25) == "ROOT::RNTupleCardinality<") {
535 auto innerTypes = TokenizeTypeList(resolvedType.substr(25, resolvedType.length() - 26));
536 if (innerTypes.size() != 1)
537 return R__FORWARD_RESULT(fnFail("invalid cardinality template: " + resolvedType));
539 if (canonicalInnerType == "std::uint32_t") {
540 result = std::make_unique<RField<RNTupleCardinality<std::uint32_t>>>(fieldName);
541 } else if (canonicalInnerType == "std::uint64_t") {
542 result = std::make_unique<RField<RNTupleCardinality<std::uint64_t>>>(fieldName);
543 } else {
544 return R__FORWARD_RESULT(fnFail("invalid cardinality template: " + resolvedType));
545 }
546 }
547
548 if (!result) {
549 auto e = TEnum::GetEnum(resolvedType.c_str());
550 if (e != nullptr) {
551 result = std::make_unique<REnumField>(fieldName, typeName);
552 }
553 }
554
555 if (!result) {
556 auto cl = TClass::GetClass(typeName.c_str());
557 // NOTE: if the class is not at least "Interpreted" we currently don't try to construct
558 // the RClassField, as in that case we'd need to fetch the information from the StreamerInfo
559 // rather than from TClass. This might be desirable in the future, but for now in this
560 // situation we rely on field emulation instead.
561 if (cl != nullptr && cl->GetState() >= TClass::kInterpreted) {
562 createContextGuard.AddClassToStack(resolvedType);
563 if (cl->GetCollectionProxy()) {
564 result = std::make_unique<RProxiedCollectionField>(fieldName, typeName);
565 } else {
568 result = std::make_unique<RStreamerField>(fieldName, typeName);
569 } else {
570 result = std::make_unique<RClassField>(fieldName, typeName);
571 }
572 }
573 } else if (options.GetEmulateUnknownTypes()) {
574 assert(desc);
575 const auto &fieldDesc = desc->GetFieldDescriptor(fieldId);
576
577 std::vector<std::unique_ptr<RFieldBase>> memberFields;
578 memberFields.reserve(fieldDesc.GetLinkIds().size());
579 for (auto id : fieldDesc.GetLinkIds()) {
580 const auto &memberDesc = desc->GetFieldDescriptor(id);
581 auto field = Create(memberDesc.GetFieldName(), memberDesc.GetTypeName(), options, desc, id).Unwrap();
582 memberFields.emplace_back(std::move(field));
583 }
584 R__ASSERT(typeName == fieldDesc.GetTypeName());
585 auto recordField =
587 recordField->fTypeAlias = fieldDesc.GetTypeAlias();
588 return recordField;
589 }
590 }
591 } catch (RException &e) {
592 auto error = e.GetError();
593 if (createContext.GetContinueOnError()) {
594 return std::unique_ptr<RFieldBase>(std::make_unique<RInvalidField>(fieldName, typeName, error.GetReport(),
596 } else {
597 return error;
598 }
599 } catch (std::logic_error &e) {
600 // Integer parsing error
601 if (createContext.GetContinueOnError()) {
602 return std::unique_ptr<RFieldBase>(
603 std::make_unique<RInvalidField>(fieldName, typeName, e.what(), RInvalidField::RCategory::kGeneric));
604 } else {
605 return R__FAIL(e.what());
606 }
607 }
608
609 if (result) {
611 if (normOrigType != result->GetTypeName()) {
612 result->fTypeAlias = normOrigType;
613 }
614 return result;
615 }
616 return R__FORWARD_RESULT(fnFail("unknown type: " + typeName, RInvalidField::RCategory::kUnknownType));
617}
618
624
625std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldBase::Clone(std::string_view newName) const
626{
627 auto clone = CloneImpl(newName);
628 clone->fTypeAlias = fTypeAlias;
629 clone->fOnDiskId = fOnDiskId;
630 clone->fDescription = fDescription;
631 // We can just copy the references because fColumnRepresentatives point into a static structure
632 clone->fColumnRepresentatives = fColumnRepresentatives;
633 return clone;
634}
635
636std::size_t ROOT::RFieldBase::AppendImpl(const void * /* from */)
637{
638 R__ASSERT(false && "A non-simple RField must implement its own AppendImpl");
639 return 0;
640}
641
643{
644 R__ASSERT(false);
645}
646
648{
649 ReadGlobalImpl(fPrincipalColumn->GetGlobalIndex(localIndex), to);
650}
651
653{
654 const auto valueSize = GetValueSize();
655 std::size_t nRead = 0;
656 for (std::size_t i = 0; i < bulkSpec.fCount; ++i) {
657 // Value not needed
658 if (bulkSpec.fMaskReq && !bulkSpec.fMaskReq[i])
659 continue;
660
661 // Value already present
662 if (bulkSpec.fMaskAvail[i])
663 continue;
664
665 Read(bulkSpec.fFirstIndex + i, reinterpret_cast<unsigned char *>(bulkSpec.fValues) + i * valueSize);
666 bulkSpec.fMaskAvail[i] = true;
667 nRead++;
668 }
669 return nRead;
670}
671
673{
674 void *where = operator new(GetValueSize());
675 R__ASSERT(where != nullptr);
676 ConstructValue(where);
677 return where;
678}
679
681{
682 void *obj = CreateObjectRawPtr();
683 return RValue(this, std::shared_ptr<void>(obj, RSharedPtrDeleter(GetDeleter())));
684}
685
686std::vector<ROOT::RFieldBase::RValue> ROOT::RFieldBase::SplitValue(const RValue & /*value*/) const
687{
688 return std::vector<RValue>();
689}
690
691void ROOT::RFieldBase::Attach(std::unique_ptr<ROOT::RFieldBase> child)
692{
693 // Note that during a model update, new fields will be attached to the zero field. The zero field, however,
694 // does not change its inital state because only its sub fields get connected by RPageSink::UpdateSchema.
695 if (fState != EState::kUnconnected)
696 throw RException(R__FAIL("invalid attempt to attach subfield to already connected field"));
697 child->fParent = this;
698 fSubfields.emplace_back(std::move(child));
699}
700
702{
703 std::size_t result = globalIndex;
704 for (auto f = this; f != nullptr; f = f->GetParent()) {
705 auto parent = f->GetParent();
706 if (parent && (parent->GetStructure() == ROOT::ENTupleStructure::kCollection ||
707 parent->GetStructure() == ROOT::ENTupleStructure::kVariant)) {
708 return 0U;
709 }
710 result *= std::max(f->GetNRepetitions(), std::size_t{1U});
711 }
712 return result;
713}
714
715std::vector<ROOT::RFieldBase *> ROOT::RFieldBase::GetMutableSubfields()
716{
717 std::vector<RFieldBase *> result;
718 result.reserve(fSubfields.size());
719 for (const auto &f : fSubfields) {
720 result.emplace_back(f.get());
721 }
722 return result;
723}
724
725std::vector<const ROOT::RFieldBase *> ROOT::RFieldBase::GetConstSubfields() const
726{
727 std::vector<const RFieldBase *> result;
728 result.reserve(fSubfields.size());
729 for (const auto &f : fSubfields) {
730 result.emplace_back(f.get());
731 }
732 return result;
733}
734
736{
737 if (!fAvailableColumns.empty()) {
738 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
739 for (auto &column : fAvailableColumns) {
740 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
741 column->Flush();
742 }
743 }
744 }
745}
746
748{
749 if (!fAvailableColumns.empty()) {
750 const auto activeRepresentationIndex = fPrincipalColumn->GetRepresentationIndex();
751 for (auto &column : fAvailableColumns) {
752 if (column->GetRepresentationIndex() == activeRepresentationIndex) {
753 column->Flush();
754 } else {
755 column->CommitSuppressed();
756 }
757 }
758 }
759 CommitClusterImpl();
760}
761
763{
764 if (fState != EState::kUnconnected)
765 throw RException(R__FAIL("cannot set field description once field is connected"));
766 fDescription = std::string(description);
767}
768
770{
771 if (fState != EState::kUnconnected)
772 throw RException(R__FAIL("cannot set field ID once field is connected"));
773 fOnDiskId = id;
774}
775
776/// Write the given value into columns. The value object has to be of the same type as the field.
777/// Returns the number of uncompressed bytes written.
778std::size_t ROOT::RFieldBase::Append(const void *from)
779{
780 if (~fTraits & kTraitMappable)
781 return AppendImpl(from);
782
783 fPrincipalColumn->Append(from);
784 return fPrincipalColumn->GetElement()->GetPackedSize();
785}
786
791
793{
794 return RValue(this, objPtr);
795}
796
798{
799 if (fIsSimple) {
800 /// For simple types, ignore the mask and memcopy the values into the destination
801 fPrincipalColumn->ReadV(bulkSpec.fFirstIndex, bulkSpec.fCount, bulkSpec.fValues);
802 std::fill(bulkSpec.fMaskAvail, bulkSpec.fMaskAvail + bulkSpec.fCount, true);
803 return RBulkSpec::kAllSet;
804 }
805
806 return ReadBulkImpl(bulkSpec);
807}
808
810{
811 return fSubfields.empty() ? RSchemaIterator(this, -1) : RSchemaIterator(fSubfields[0].get(), 0);
812}
813
818
820{
821 return fSubfields.empty() ? RConstSchemaIterator(this, -1) : RConstSchemaIterator(fSubfields[0].get(), 0);
822}
823
828
830{
831 return fSubfields.empty() ? RConstSchemaIterator(this, -1) : RConstSchemaIterator(fSubfields[0].get(), 0);
832}
833
838
840{
841 if (fColumnRepresentatives.empty()) {
842 return {GetColumnRepresentations().GetSerializationDefault()};
843 }
844
846 result.reserve(fColumnRepresentatives.size());
847 for (const auto &r : fColumnRepresentatives) {
848 result.emplace_back(r.get());
849 }
850 return result;
851}
852
854{
855 if (fState != EState::kUnconnected)
856 throw RException(R__FAIL("cannot set column representative once field is connected"));
857 const auto &validTypes = GetColumnRepresentations().GetSerializationTypes();
858 fColumnRepresentatives.clear();
859 fColumnRepresentatives.reserve(representatives.size());
860 for (const auto &r : representatives) {
861 auto itRepresentative = std::find(validTypes.begin(), validTypes.end(), r);
862 if (itRepresentative == std::end(validTypes))
863 throw RException(R__FAIL("invalid column representative"));
864
865 // don't add a duplicate representation
866 if (std::find_if(fColumnRepresentatives.begin(), fColumnRepresentatives.end(),
867 [&r](const auto &rep) { return r == rep.get(); }) == fColumnRepresentatives.end())
868 fColumnRepresentatives.emplace_back(*itRepresentative);
869 }
870}
871
874 std::uint16_t representationIndex) const
875{
876 static const ColumnRepresentation_t kEmpty;
877
878 if (fOnDiskId == ROOT::kInvalidDescriptorId)
879 throw RException(R__FAIL("No on-disk field information for `" + GetQualifiedFieldName() + "`"));
880
882 for (const auto &c : desc.GetColumnIterable(fOnDiskId)) {
883 if (c.GetRepresentationIndex() == representationIndex)
884 onDiskTypes.emplace_back(c.GetType());
885 }
886 if (onDiskTypes.empty()) {
887 if (representationIndex == 0) {
888 throw RException(R__FAIL("No on-disk column information for field `" + GetQualifiedFieldName() + "`"));
889 }
890 return kEmpty;
891 }
892
893 for (const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
894 if (t == onDiskTypes)
895 return t;
896 }
897
898 std::string columnTypeNames;
899 for (const auto &t : onDiskTypes) {
900 if (!columnTypeNames.empty())
901 columnTypeNames += ", ";
903 }
904 throw RException(R__FAIL("On-disk column types {" + columnTypeNames + "} for field `" + GetQualifiedFieldName() +
905 "` cannot be matched to its in-memory type `" + GetTypeName() + "` " +
906 "(representation index: " + std::to_string(representationIndex) + ")"));
907}
908
910{
911 fReadCallbacks.push_back(func);
912 fIsSimple = false;
913 return fReadCallbacks.size() - 1;
914}
915
917{
918 fReadCallbacks.erase(fReadCallbacks.begin() + idx);
919 fIsSimple = (fTraits & kTraitMappable) && !fIsArtificial && fReadCallbacks.empty();
920}
921
947
949{
950 if (dynamic_cast<ROOT::RFieldZero *>(this))
951 throw RException(R__FAIL("invalid attempt to connect zero field to page sink"));
952 if (fState != EState::kUnconnected)
953 throw RException(R__FAIL("invalid attempt to connect an already connected field to a page sink"));
954
955 AutoAdjustColumnTypes(pageSink.GetWriteOptions());
956
957 GenerateColumns();
958 for (auto &column : fAvailableColumns) {
959 // Only the first column of every representation can be a deferred column. In all column representations,
960 // larger column indexes are data columns of collections (string, streamer) and thus
961 // they have no elements on late model extension
962 auto firstElementIndex = (column->GetIndex() == 0) ? EntryToColumnElementIndex(firstEntry) : 0;
963 column->ConnectPageSink(fOnDiskId, pageSink, firstElementIndex);
964 }
965
966 if (HasExtraTypeInfo()) {
967 pageSink.RegisterOnCommitDatasetCallback(
968 [this](ROOT::Internal::RPageSink &sink) { sink.UpdateExtraTypeInfo(GetExtraTypeInfo()); });
969 }
970
971 fState = EState::kConnectedToSink;
972}
973
975{
976 if (dynamic_cast<ROOT::RFieldZero *>(this))
977 throw RException(R__FAIL("invalid attempt to connect zero field to page source"));
978 if (fState != EState::kUnconnected)
979 throw RException(R__FAIL("invalid attempt to connect an already connected field to a page source"));
980
981 if (!fColumnRepresentatives.empty())
982 throw RException(R__FAIL("fixed column representative only valid when connecting to a page sink"));
983 if (!fDescription.empty())
984 throw RException(R__FAIL("setting description only valid when connecting to a page sink"));
985
986 BeforeConnectPageSource(pageSource);
987
988 for (auto &f : fSubfields) {
989 if (f->GetOnDiskId() == ROOT::kInvalidDescriptorId) {
990 f->SetOnDiskId(pageSource.GetSharedDescriptorGuard()->FindFieldId(f->GetFieldName(), GetOnDiskId()));
991 }
992 f->ConnectPageSource(pageSource);
993 }
994
995 // Do not generate columns nor set fColumnRepresentatives for artificial fields.
996 if (!fIsArtificial) {
997 const auto descriptorGuard = pageSource.GetSharedDescriptorGuard();
998 const ROOT::RNTupleDescriptor &desc = descriptorGuard.GetRef();
999 GenerateColumns(desc);
1000 if (fColumnRepresentatives.empty()) {
1001 // If we didn't get columns from the descriptor, ensure that we actually expect a field without columns
1002 for (const auto &t : GetColumnRepresentations().GetDeserializationTypes()) {
1003 if (t.empty()) {
1004 fColumnRepresentatives = {t};
1005 break;
1006 }
1007 }
1008 }
1009 R__ASSERT(!fColumnRepresentatives.empty());
1010 if (fOnDiskId != ROOT::kInvalidDescriptorId) {
1011 const auto &fieldDesc = desc.GetFieldDescriptor(fOnDiskId);
1012 fOnDiskTypeVersion = fieldDesc.GetTypeVersion();
1013 if (fieldDesc.GetTypeChecksum().has_value())
1014 fOnDiskTypeChecksum = *fieldDesc.GetTypeChecksum();
1015 }
1016 }
1017 for (auto &column : fAvailableColumns)
1018 column->ConnectPageSource(fOnDiskId, pageSource);
1019
1020 AfterConnectPageSource();
1021
1022 fState = EState::kConnectedToSource;
1023}
1024
1026{
1027 visitor.VisitField(*this);
1028}
size_t fValueSize
dim_t fSize
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
Definition RError.hxx:301
#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:299
#define R__LOG_WARNING(...)
Definition RLogger.hxx:358
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define e(i)
Definition RSha256.hxx:103
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.
Definition TError.h:125
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
char name[80]
Definition TGX11.cxx:110
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.
Definition RError.hxx:79
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.
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.
RSchemaIterator end()
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.
RSchemaIterator begin()
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.
@ 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.
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.
Definition RField.hxx:54
Used in RFieldBase::Check() to record field creation failures.
Definition RField.hxx:72
@ 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...
Definition RError.hxx:197
@ kInterpreted
Definition TClass.h:129
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.
Definition TClass.cxx:3074
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:182
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 &)
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
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)
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)
Definition RField.cxx:513
std::string GetNormalizedUnresolvedTypeName(const std::string &origName)
Applies all RNTuple type normalization rules except typedef resolution.
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....
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 ntuple model tree can carry different structural information about the type system.
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
Input parameter to RFieldBase::ReadBulk() and RFieldBase::ReadBulkImpl().
Used in the return value of the Check() method.