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