Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RField.cxx
Go to the documentation of this file.
1/// \file RField.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include <ROOT/RColumn.hxx>
15#include <ROOT/REntry.hxx>
16#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
19#include <ROOT/RLogger.hxx>
20#include <ROOT/RNTupleModel.hxx>
22#include <ROOT/RNTupleTypes.hxx>
23#include <TClassEdit.h>
24
25#include <algorithm>
26#include <cstdint>
27#include <cstdlib>
28#include <exception>
29#include <functional>
30#include <iostream>
31#include <memory>
32#include <string_view>
33#include <type_traits>
34#include <unordered_set>
35
37{
38 fieldZero.fAllowFieldSubstitutions = val;
39}
40
41void ROOT::RFieldZero::Attach(std::unique_ptr<RFieldBase> child)
42{
43 const std::string childName = child->GetFieldName();
44 if (fSubfieldNames.count(childName) > 0)
45 throw RException(R__FAIL("duplicate field name: " + childName));
46 RFieldBase::Attach(std::move(child), "");
48}
49
54
55std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldZero::CloneImpl(std::string_view /*newName*/) const
56{
57 auto result = std::make_unique<RFieldZero>();
58 for (auto &f : fSubfields) {
59 result->Attach(f->Clone(f->GetFieldName()));
60 result->fSubfieldNames.insert(f->GetFieldName());
61 }
62 return result;
63}
64
65std::vector<std::unique_ptr<ROOT::RFieldBase>> ROOT::RFieldZero::ReleaseSubfields()
66{
67 std::vector<std::unique_ptr<ROOT::RFieldBase>> result;
68 std::swap(fSubfields, result);
69 for (auto &f : result)
70 f->fParent = nullptr;
71 return result;
72}
73
75{
76 visitor.VisitFieldZero(*this);
77}
78
79//------------------------------------------------------------------------------
80
90
95
97{
98 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError();
99
100 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
101 if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) {
102 if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) {
103 throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() +
104 " expects an on-disk leaf field of the same type\n" +
105 Internal::GetTypeTraceReport(*this, desc)));
106 }
107 } else if (fieldDesc.GetStructure() == ENTupleStructure::kCollection) {
108 if (!fieldDesc.IsSoACollection() && fieldDesc.GetTypeVersion() != 0) {
109 throw RException(R__FAIL("invalid on-disk type version for RCardinalityField " + GetQualifiedFieldName() +
110 "\n" + Internal::GetTypeTraceReport(*this, desc)));
111 }
112 } else {
113 throw RException(R__FAIL("invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName() +
114 "\n" + Internal::GetTypeTraceReport(*this, desc)));
115 }
116}
117
119{
120 visitor.VisitCardinalityField(*this);
121}
122
127
132
133//------------------------------------------------------------------------------
134
135template <typename T>
137{
138 EnsureMatchingOnDiskField(desc, kDiffTypeName);
139
140 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
142 SetOnDiskId(desc.FindFieldId("_0", GetOnDiskId()));
143 return;
144 }
145
146 static const std::string gIntegralTypeNames[] = {"bool", "char", "std::int8_t", "std::uint8_t",
147 "std::int16_t", "std::uint16_t", "std::int32_t", "std::uint32_t",
148 "std::int64_t", "std::uint64_t"};
149 if (std::find(std::begin(gIntegralTypeNames), std::end(gIntegralTypeNames), fieldDesc.GetTypeName()) ==
150 std::end(gIntegralTypeNames)) {
151 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
152 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
153 }
154}
155
156template <typename T>
158{
159 EnsureMatchingOnDiskField(desc, kDiffTypeName);
160
161 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
162 if (!(fieldDesc.GetTypeName() == "float" || fieldDesc.GetTypeName() == "double")) {
163 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
164 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
165 }
166}
167
168//------------------------------------------------------------------------------
169
170template class ROOT::RSimpleField<char>;
171
191
193{
194 visitor.VisitCharField(*this);
195}
196
197//------------------------------------------------------------------------------
198
199template class ROOT::RSimpleField<std::byte>;
200
202{
203 static RColumnRepresentations representations({{ENTupleColumnType::kByte}}, {});
204 return representations;
205}
206
208{
209 visitor.VisitByteField(*this);
210}
211
212//------------------------------------------------------------------------------
213
214template class ROOT::RSimpleField<int8_t>;
215
217{
218 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
233 return representations;
234}
235
237{
238 visitor.VisitInt8Field(*this);
239}
240
241//------------------------------------------------------------------------------
242
243template class ROOT::RSimpleField<uint8_t>;
244
246{
247 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
262 return representations;
263}
264
266{
267 visitor.VisitUInt8Field(*this);
268}
269
270//------------------------------------------------------------------------------
271
272template class ROOT::RSimpleField<bool>;
273
293
295{
296 visitor.VisitBoolField(*this);
297}
298
299//------------------------------------------------------------------------------
300
301template class ROOT::RSimpleField<float>;
302
313
315{
316 visitor.VisitFloatField(*this);
317}
318
319//------------------------------------------------------------------------------
320
321template class ROOT::RSimpleField<double>;
322
335
337{
338 visitor.VisitDoubleField(*this);
339}
340
342{
343 fTypeAlias = "Double32_t";
344}
345
346//------------------------------------------------------------------------------
347
348template class ROOT::RSimpleField<int16_t>;
349
351{
367 return representations;
368}
369
371{
372 visitor.VisitInt16Field(*this);
373}
374
375//------------------------------------------------------------------------------
376
377template class ROOT::RSimpleField<uint16_t>;
378
380{
396 return representations;
397}
398
400{
401 visitor.VisitUInt16Field(*this);
402}
403
404//------------------------------------------------------------------------------
405
406template class ROOT::RSimpleField<int32_t>;
407
409{
425 return representations;
426}
427
429{
430 visitor.VisitInt32Field(*this);
431}
432
433//------------------------------------------------------------------------------
434
435template class ROOT::RSimpleField<uint32_t>;
436
438{
454 return representations;
455}
456
458{
459 visitor.VisitUInt32Field(*this);
460}
461
462//------------------------------------------------------------------------------
463
464template class ROOT::RSimpleField<uint64_t>;
465
467{
483 return representations;
484}
485
487{
488 visitor.VisitUInt64Field(*this);
489}
490
491//------------------------------------------------------------------------------
492
493template class ROOT::RSimpleField<int64_t>;
494
496{
512 return representations;
513}
514
516{
517 visitor.VisitInt64Field(*this);
518}
519
520//------------------------------------------------------------------------------
521
523{
528 {});
529 return representations;
530}
531
533{
535}
536
538{
540}
541
542std::size_t ROOT::RField<std::string>::AppendImpl(const void *from)
543{
544 auto typedValue = static_cast<const std::string *>(from);
545 auto length = typedValue->length();
546 fAuxiliaryColumn->AppendV(typedValue->data(), length);
547 fIndex += length;
548 fPrincipalColumn->Append(&fIndex);
549 return length + fPrincipalColumn->GetElement()->GetPackedSize();
550}
551
553{
554 auto typedValue = static_cast<std::string *>(to);
555 RNTupleLocalIndex collectionStart;
557 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
558 if (nChars == 0) {
559 typedValue->clear();
560 } else {
561 typedValue->resize(nChars);
562 fAuxiliaryColumn->ReadV(collectionStart, nChars, const_cast<char *>(typedValue->data()));
563 }
564}
565
567{
568 visitor.VisitStringField(*this);
569}
570
571//------------------------------------------------------------------------------
572
574 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
575 fMaxAlignment(source.fMaxAlignment),
577 fOffsets(source.fOffsets)
578{
579 for (const auto &f : source.GetConstSubfields())
580 Attach(f->Clone(f->GetFieldName()));
581 fSubfieldNames = source.fSubfieldNames;
582 fTraits = source.fTraits;
583}
584
585ROOT::RRecordField::RRecordField(std::string_view fieldName, std::string_view typeName)
586 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
587{
588}
589
590std::unique_ptr<ROOT::RFieldBase>
592 std::vector<std::unique_ptr<RFieldBase>> itemFields,
593 std::string_view emulatedFromType)
594{
595 R__ASSERT(!emulatedFromType.empty());
596 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
597}
598
599std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
600 std::unique_ptr<RFieldBase> itemField,
601 std::string_view emulatedFromType)
602{
603 R__ASSERT(!emulatedFromType.empty());
604 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
605}
606
607ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
608 std::string_view emulatedFromType)
610{
611 AttachItemFields(std::move(itemFields));
613}
614
615ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
617{
619}
620
621void ROOT::RRecordField::AddItem(std::unique_ptr<RFieldBase> item)
622{
623 fSize += GetItemPadding(fSize, item->GetAlignment());
624 if (!IsPairOrTuple()) {
625 fOffsets.emplace_back(fSize);
626 }
627 fSize += item->GetValueSize();
628 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
629 fTraits &= item->GetTraits() | (fTraits & kTraitExtensible); // may be called by AddItemToRecord()
630
631 if (IsPairOrTuple()) {
632 Attach(std::move(item), "_" + std::to_string(fSubfields.size()));
633 } else {
634 const std::string itemName = item->GetFieldName();
635 if (fSubfieldNames.count(itemName) > 0)
636 throw RException(R__FAIL("duplicate field name: " + itemName));
637 Attach(std::move(item));
638 fSubfieldNames.insert(itemName);
639 }
640}
641
643{
644 // Only supported for untyped records
645 assert(record.GetTypeName().empty());
646 record.AddItem(std::move(newItem));
647
648 // For nested record fields, we have to reattach all fields of all parents because the modification to the
649 // current field will change its size and may change its alignment and hence the layout of all parents.
650 auto parent = record.fParent;
651 while (parent && typeid(*parent) != typeid(RFieldZero)) {
652 // untyped records can only have an untyped record as parent
653 assert(dynamic_cast<RRecordField *>(parent) && parent->GetTypeName().empty());
654
655 auto precord = static_cast<RRecordField *>(parent);
656 std::vector<std::unique_ptr<ROOT::RFieldBase>> subfields;
657 std::swap(precord->fSubfields, subfields);
659 precord->fSubfieldNames.clear();
660 precord->fMaxAlignment = 1;
661 precord->fSize = 0;
662 precord->fOffsets.clear();
663 precord->AttachItemFields(std::move(subfields));
664
665 parent = precord->fParent;
666 }
667}
668
669std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
670{
671 if (itemAlignment > 1) {
672 auto remainder = baseOffset % itemAlignment;
673 if (remainder != 0)
674 return itemAlignment - remainder;
675 }
676 return 0;
677}
678
679std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
680{
681 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
682}
683
684std::size_t ROOT::RRecordField::AppendImpl(const void *from)
685{
686 std::size_t nbytes = 0;
687 for (unsigned i = 0; i < fSubfields.size(); ++i) {
688 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
689 }
690 return nbytes;
691}
692
694{
695 for (unsigned i = 0; i < fSubfields.size(); ++i) {
696 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
697 }
698}
699
701{
702 for (unsigned i = 0; i < fSubfields.size(); ++i) {
703 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
704 }
705}
706
708{
709 if (fTraits & kTraitEmulatedField) {
710 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
711 return;
712 }
713 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
714 R__ASSERT(GetTypeName().empty());
715
716 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
717
718 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
719 // and we will ignore extra on-disk fields.
720 // It remains to mark the extra in-memory fields as artificial.
721 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
722 std::unordered_set<std::string_view> onDiskSubfields;
723 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
724 onDiskSubfields.insert(subField.GetFieldName());
725 }
726 for (auto &f : fSubfields) {
727 if (onDiskSubfields.count(f->GetFieldName()) == 0)
728 CallSetArtificialOn(*f);
729 }
730}
731
733{
734 for (unsigned i = 0; i < fSubfields.size(); ++i) {
735 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
736 }
737}
738
740{
741 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
742 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
743 }
744 RDeleter::operator()(objPtr, dtorOnly);
745}
746
747std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
748{
749 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
750 itemDeleters.reserve(fOffsets.size());
751 for (const auto &f : fSubfields) {
752 itemDeleters.emplace_back(GetDeleterOf(*f));
753 }
754 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
755}
756
757std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
758{
759 auto valuePtr = value.GetPtr<void>();
760 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
761 std::vector<RValue> result;
762 result.reserve(fSubfields.size());
763 for (unsigned i = 0; i < fSubfields.size(); ++i) {
764 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
765 }
766 return result;
767}
768
770{
771 visitor.VisitRecordField(*this);
772}
773
774//------------------------------------------------------------------------------
775
776ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
777 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
778 false /* isSimple */, N),
779 fN(N)
780{
782}
783
789
794
799
800template <typename FUlong, typename FUlonglong, typename... Args>
802{
803 if (WordSize() == sizeof(unsigned long)) {
804 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
805 } else if (WordSize() == sizeof(unsigned long long)) {
806 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
807 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
808 } else {
809 R__ASSERT(false);
810 }
811}
812
813template <typename Word_t>
814static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
815{
816 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
817
818 const auto *asWordArray = static_cast<const Word_t *>(from);
819 bool elementValue;
820 std::size_t i = 0;
821 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
822 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
823 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
824 column.Append(&elementValue);
825 }
826 }
827}
828
829std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
830{
832 return fN;
833}
834
835template <typename Word_t>
836static void
838{
839 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
840
841 auto *asWordArray = static_cast<Word_t *>(to);
842 bool elementValue;
843 for (std::size_t i = 0; i < nBits; ++i) {
844 column.Read(globalIndex * nBits + i, &elementValue);
845 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
846 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
847 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
848 }
849}
850
855
856template <typename Word_t>
857static void
859{
860 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
861
862 auto *asWordArray = static_cast<Word_t *>(to);
863 bool elementValue;
864 for (std::size_t i = 0; i < nBits; ++i) {
865 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
866 &elementValue);
867 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
868 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
869 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
870 }
871}
872
877
879{
880 visitor.VisitBitsetField(*this);
881}
882
883//------------------------------------------------------------------------------
884
885ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
886 std::unique_ptr<RFieldBase> itemField)
887 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
888 false /* isSimple */)
889{
890 if (!itemField->GetTypeAlias().empty())
891 fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
892
893 Attach(std::move(itemField), "_0");
894}
895
905
911
913{
914 if (!fIsEvolvedFromInnerType)
916}
917
919{
920 fPrincipalColumn->Append(&fNWritten);
921 return sizeof(ROOT::Internal::RColumnIndex);
922}
923
924std::size_t ROOT::RNullableField::AppendValue(const void *from)
925{
926 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
927 fNWritten++;
928 fPrincipalColumn->Append(&fNWritten);
930}
931
933{
934 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
935
936 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
937 if (!success) {
938 fIsEvolvedFromInnerType = true;
939 } else {
940 success = EnsureMatchingTypePrefix(desc, prefixes);
941 fIsEvolvedFromInnerType = !success;
942 }
943
944 if (fIsEvolvedFromInnerType)
945 fSubfields[0]->SetOnDiskId(GetOnDiskId());
946}
947
955
963
965{
966 visitor.VisitNullableField(*this);
967}
968
969//------------------------------------------------------------------------------
970
971namespace {
972// Dummy class to determine the dynamic type of any polymorphic user object.
973struct PolymorphicClass {
974 virtual ~PolymorphicClass() = default;
975};
976} // namespace
977
978ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
979 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
980{
981 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
982 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
983 }
984}
985
986std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
987{
988 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
989 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
990}
991
992std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
993{
994 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
995 if (*typedValue) {
996 const void *obj = typedValue->get();
997 if (fPolymorphicTypeInfo != nullptr) {
998 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
999 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
1000 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
1001 if (t != *fPolymorphicTypeInfo) {
1002 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
1003 int err = 0;
1005 if (!err) {
1006 msg = msg + " but was passed " + demangled;
1007 free(demangled);
1008 }
1009 msg += " and upcasting of polymorphic types is not supported in RNTuple";
1010 throw RException(R__FAIL(msg));
1011 }
1012 }
1013 return AppendValue(obj);
1014 } else {
1015 return AppendNull();
1016 }
1017}
1018
1020{
1021 auto ptr = static_cast<std::unique_ptr<char> *>(to);
1022 bool isValidValue = static_cast<bool>(*ptr);
1023
1024 void *valuePtr = nullptr;
1025 if (isValidValue)
1026 valuePtr = ptr->get();
1027
1028 if (isValidValue && !hasOnDiskValue) {
1029 ptr->release();
1030 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
1031 } else if (!isValidValue && hasOnDiskValue) {
1032 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
1033 ptr->reset(reinterpret_cast<char *>(valuePtr));
1034 }
1035
1036 return valuePtr;
1037}
1038
1040{
1042 if (!fIsEvolvedFromInnerType)
1043 itemIndex = GetItemIndex(globalIndex);
1044 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1045 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1046 if (hasOnDiskValue) {
1047 if (fIsEvolvedFromInnerType) {
1048 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1049 } else {
1050 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1051 }
1052 }
1053}
1054
1056{
1058 if (!fIsEvolvedFromInnerType) {
1059 itemIndex = GetItemIndex(localIndex);
1060 } else {
1062 }
1063 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1064 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1065 if (hasOnDiskValue)
1066 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1067}
1068
1070{
1071 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1072 if (*typedPtr) {
1073 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1074 typedPtr->release();
1075 }
1076 RDeleter::operator()(objPtr, dtorOnly);
1077}
1078
1079std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1080{
1081 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1082}
1083
1084std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1085{
1086 std::vector<RValue> result;
1087 auto valuePtr = value.GetPtr<void>();
1088 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1089 if (uniquePtr) {
1090 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1091 }
1092 return result;
1093}
1094
1095//------------------------------------------------------------------------------
1096
1097ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1098 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1099{
1102}
1103
1105{
1106 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1107}
1108
1110{
1111 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1112}
1113
1114std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1115{
1116 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1117 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1118}
1119
1120std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1121{
1122 if (*GetEngagementPtr(from)) {
1123 return AppendValue(from);
1124 } else {
1125 return AppendNull();
1126 }
1127}
1128
1130{
1131 auto engagementPtr = GetEngagementPtr(to);
1132 if (hasOnDiskValue) {
1133 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1134 CallConstructValueOn(*fSubfields[0], to);
1135 *engagementPtr = true;
1136 } else {
1137 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1138 fItemDeleter->operator()(to, true /* dtorOnly */);
1139 *engagementPtr = false;
1140 }
1141}
1142
1144{
1146 if (!fIsEvolvedFromInnerType)
1147 itemIndex = GetItemIndex(globalIndex);
1148 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1149 PrepareRead(to, hasOnDiskValue);
1150 if (hasOnDiskValue) {
1151 if (fIsEvolvedFromInnerType) {
1152 CallReadOn(*fSubfields[0], globalIndex, to);
1153 } else {
1154 CallReadOn(*fSubfields[0], itemIndex, to);
1155 }
1156 }
1157}
1158
1160{
1162 if (!fIsEvolvedFromInnerType) {
1163 itemIndex = GetItemIndex(localIndex);
1164 } else {
1166 }
1167 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1168 PrepareRead(to, hasOnDiskValue);
1169 if (hasOnDiskValue)
1170 CallReadOn(*fSubfields[0], itemIndex, to);
1171}
1172
1174{
1175 *GetEngagementPtr(where) = false;
1176}
1177
1179{
1180 if (fItemDeleter) {
1181 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1182 if (*engagementPtr)
1183 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1184 }
1185 RDeleter::operator()(objPtr, dtorOnly);
1186}
1187
1188std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1189{
1190 return std::make_unique<ROptionalDeleter>(
1191 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1192 fSubfields[0]->GetValueSize());
1193}
1194
1195std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1196{
1197 std::vector<RValue> result;
1198 const auto valuePtr = value.GetPtr<void>().get();
1199 if (*GetEngagementPtr(valuePtr)) {
1200 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1201 }
1202 return result;
1203}
1204
1206{
1207 const auto alignment = GetAlignment();
1208 // real size is the sum of the value size and the engagement boolean
1209 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1210 auto padding = 0;
1211 if (alignment > 1) {
1212 auto remainder = actualSize % alignment;
1213 if (remainder != 0)
1214 padding = alignment - remainder;
1215 }
1216 return actualSize + padding;
1217}
1218
1220{
1221 return fSubfields[0]->GetAlignment();
1222}
1223
1224//------------------------------------------------------------------------------
1225
1226ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1227 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1228 false /* isSimple */)
1229{
1230 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1232 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1234
1235 if (!itemField->GetTypeAlias().empty())
1236 fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1237
1238 Attach(std::move(itemField), "_0");
1239}
1240
1241std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1242{
1243 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1244 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1245}
1246
1248{
1249 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1250 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1251 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1252 } else {
1253 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1254 }
1255}
1256
1257std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1258{
1259 std::vector<RValue> result;
1260 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1261 return result;
1262}
1263
1265{
1266 visitor.VisitAtomicField(*this);
1267}
dim_t fSize
#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:300
static void BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:837
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:858
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:814
#define f(i)
Definition RSha256.hxx:104
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
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:145
TCanvas * alignment()
Definition alignment.C:1
#define free
Definition civetweb.c:1578
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:38
void Read(const ROOT::NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:160
void Append(const void *from)
Definition RColumn.hxx:126
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1264
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1226
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1241
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:1247
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Definition RField.cxx:1257
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:776
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:873
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:790
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:851
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:829
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:784
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:878
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:801
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:118
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:81
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
Definition RField.cxx:123
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:96
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
Definition RField.cxx:128
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.hxx:370
The field for a class with dictionary.
Definition RField.hxx:138
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
The list of column representations a field can have.
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
void Attach(std::unique_ptr< RFieldBase > child, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitExtensible
Can attach new item fields even when already connected.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
std::string fTypeAlias
A typedef or using name that was used when creating the field.
std::uint32_t GetTraits() const
const std::string & GetTypeName() const
Metadata stored for every field of an RNTuple.
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:59
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
Definition RField.hxx:72
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:74
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:55
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Definition RField.cxx:65
void Attach(std::unique_ptr< RFieldBase > child)
A public version of the Attach method that allows piece-wise construction of the zero field.
Definition RField.cxx:41
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:322
The on-storage metadata of an RNTuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) const
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Template specializations for C++ std::optional and std::unique_ptr.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:932
RNTupleLocalIndex GetItemIndex(NTupleSize_t globalIndex)
Given the global index of the nullable field, returns the corresponding cluster-local index of the su...
Definition RField.cxx:948
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:885
std::size_t AppendNull()
Definition RField.cxx:918
std::size_t AppendValue(const void *from)
Definition RField.cxx:924
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:906
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:964
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:896
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1178
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Definition RField.cxx:1173
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
Definition RField.cxx:1219
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1188
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1114
const bool * GetEngagementPtr(const void *optionalPtr) const
Given a pointer to an std::optional<T> in optionalPtr, extract a pointer to the engagement boolean.
Definition RField.cxx:1109
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1143
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1120
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1159
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Definition RField.cxx:1195
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
Definition RField.cxx:1205
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1129
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1097
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:739
The field for an untyped record.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Definition RField.cxx:757
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:679
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:700
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:573
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:769
void AttachItemFields(ContainerT &&itemFields)
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:747
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:669
void AddItem(std::unique_ptr< RFieldBase > item)
Adds an additional item field.
Definition RField.cxx:621
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:693
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
Definition RField.cxx:732
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:684
void ReconcileOnDiskField(const RNTupleDescriptor &desc) override
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:707
void ReconcileIntegralField(const RNTupleDescriptor &desc)
Definition RField.cxx:136
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
Definition RField.cxx:157
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1069
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
Definition RField.cxx:1084
const std::type_info * fPolymorphicTypeInfo
If the item type is a polymorphic class (that declares or inherits at least one virtual method),...
void * PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1019
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1079
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1039
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:986
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:978
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:992
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1055
Template specializations for C++ std::vector.
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
Definition RField.cxx:36
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
Definition RField.cxx:599
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:591
std::string GetTypeTraceReport(const RFieldBase &field, const RNTupleDescriptor &desc)
Prints the hierarchy of types with their field names and field IDs for the given in-memory field and ...
void AddItemToRecord(RRecordField &record, std::unique_ptr< RFieldBase > newItem)
Definition RField.cxx:642
bool IsCustomEnumFieldDesc(const RNTupleDescriptor &desc, const RFieldDescriptor &fieldDesc)
Tells if the field describes a user-defined enum type.
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
ENTupleStructure
The fields in the RNTuple data model tree can carry different structural information about the type s...
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.