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), "");
46 fSubfieldNames.insert(childName);
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
91{
92 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
93}
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
121
126
131
132//------------------------------------------------------------------------------
133
134template <typename T>
136{
137 EnsureMatchingOnDiskField(desc, kDiffTypeName);
138
139 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
140 if (Internal::IsCustomEnumFieldDesc(desc, fieldDesc)) {
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
339
341{
342 fTypeAlias = "Double32_t";
343}
344
345//------------------------------------------------------------------------------
346
347template class ROOT::RSimpleField<int16_t>;
348
350{
351 static RColumnRepresentations representations({{ENTupleColumnType::kSplitInt16}, {ENTupleColumnType::kInt16}},
366 return representations;
367}
368
370{
371 visitor.VisitInt16Field(*this);
372}
373
374//------------------------------------------------------------------------------
375
376template class ROOT::RSimpleField<uint16_t>;
377
379{
380 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt16}, {ENTupleColumnType::kUInt16}},
395 return representations;
396}
397
399{
400 visitor.VisitUInt16Field(*this);
401}
402
403//------------------------------------------------------------------------------
404
405template class ROOT::RSimpleField<int32_t>;
406
424 return representations;
425}
426
428{
429 visitor.VisitInt32Field(*this);
430}
431
432//------------------------------------------------------------------------------
433
434template class ROOT::RSimpleField<uint32_t>;
435
437{
438 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt32}, {ENTupleColumnType::kUInt32}},
453 return representations;
454}
455
457{
458 visitor.VisitUInt32Field(*this);
459}
460
461//------------------------------------------------------------------------------
462
463template class ROOT::RSimpleField<uint64_t>;
464
466{
467 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt64}, {ENTupleColumnType::kUInt64}},
482 return representations;
483}
484
486{
487 visitor.VisitUInt64Field(*this);
488}
489
490//------------------------------------------------------------------------------
491
492template class ROOT::RSimpleField<int64_t>;
493
495{
496 static RColumnRepresentations representations({{ENTupleColumnType::kSplitInt64}, {ENTupleColumnType::kInt64}},
511 return representations;
512}
513
515{
516 visitor.VisitInt64Field(*this);
517}
518
519//------------------------------------------------------------------------------
520
522{
523 static RColumnRepresentations representations({{ENTupleColumnType::kSplitIndex64, ENTupleColumnType::kChar},
527 {});
528 return representations;
529}
530
532{
533 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, char>();
534}
535
537{
538 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, char>(desc);
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;
555 ROOT::NTupleSize_t nChars;
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
572ROOT::RRecordField::RRecordField(std::string_view name, const RRecordField &source)
573 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
574 fMaxAlignment(source.fMaxAlignment),
575 fSize(source.fSize),
576 fOffsets(source.fOffsets)
577{
578 for (const auto &f : source.GetConstSubfields())
579 Attach(f->Clone(f->GetFieldName()));
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 const RFieldDescriptor &emulatedFrom)
593{
594 R__ASSERT(!emulatedFrom.GetTypeName().empty());
595 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), &emulatedFrom));
596}
597
598std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
599 std::unique_ptr<RFieldBase> itemField,
600 const RFieldDescriptor &emulatedFrom)
601{
602 R__ASSERT(!emulatedFrom.GetTypeName().empty());
603 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), &emulatedFrom));
604}
605
606ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
607 const ROOT::RFieldDescriptor *emulatedFrom)
608 : ROOT::RFieldBase(fieldName, emulatedFrom ? emulatedFrom->GetTypeName() : "", ROOT::ENTupleStructure::kRecord,
609 false /* isSimple */)
610{
611 AttachItemFields(std::move(itemFields));
612 fTraits |= !!emulatedFrom * kTraitEmulatedField;
613 if (emulatedFrom) {
614 fTraits |= emulatedFrom->GetTypeChecksum().has_value() * kTraitTypeChecksum;
615 fEmulatedTypeVersion = emulatedFrom->GetTypeVersion();
616 fEmulatedTypeChecksum = emulatedFrom->GetTypeChecksum().value_or(0);
617 }
618}
619
620ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
621 : ROOT::RRecordField(fieldName, std::move(itemFields), nullptr)
622{
624}
625
626void ROOT::RRecordField::AddItem(std::unique_ptr<RFieldBase> item)
627{
628 fSize += GetItemPadding(fSize, item->GetAlignment());
629 if (!IsPairOrTuple()) {
630 fOffsets.emplace_back(fSize);
631 }
632 fSize += item->GetValueSize();
633 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
634 fTraits &= item->GetTraits() | (fTraits & kTraitExtensible); // may be called by AddItemToRecord()
635
636 if (IsPairOrTuple()) {
637 Attach(std::move(item), "_" + std::to_string(fSubfields.size()));
638 } else {
639 const std::string itemName = item->GetFieldName();
640 if (fSubfieldNames.count(itemName) > 0)
641 throw RException(R__FAIL("duplicate field name: " + itemName));
642 Attach(std::move(item));
643 fSubfieldNames.insert(itemName);
644 }
645}
646
647void ROOT::Internal::AddItemToRecord(RRecordField &record, std::unique_ptr<RFieldBase> newItem)
648{
649 // Only supported for untyped records
650 assert(record.GetTypeName().empty());
651 record.AddItem(std::move(newItem));
652
653 // For nested record fields, we have to reattach all fields of all parents because the modification to the
654 // current field will change its size and may change its alignment and hence the layout of all parents.
655 auto parent = record.fParent;
656 while (parent && typeid(*parent) != typeid(RFieldZero)) {
657 // untyped records can only have an untyped record as parent
658 assert(dynamic_cast<RRecordField *>(parent) && parent->GetTypeName().empty());
659
660 auto precord = static_cast<RRecordField *>(parent);
661 std::vector<std::unique_ptr<ROOT::RFieldBase>> subfields;
662 std::swap(precord->fSubfields, subfields);
663 precord->fTraits = ROOT::RFieldBase::kTraitExtensible;
664 precord->fSubfieldNames.clear();
665 precord->fMaxAlignment = 1;
666 precord->fSize = 0;
667 precord->fOffsets.clear();
668 precord->AttachItemFields(std::move(subfields));
669
670 parent = precord->fParent;
671 }
672}
673
674std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
675{
676 if (itemAlignment > 1) {
677 auto remainder = baseOffset % itemAlignment;
678 if (remainder != 0)
679 return itemAlignment - remainder;
680 }
681 return 0;
682}
683
684std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
685{
686 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
687}
688
689std::size_t ROOT::RRecordField::AppendImpl(const void *from)
690{
691 std::size_t nbytes = 0;
692 for (unsigned i = 0; i < fSubfields.size(); ++i) {
693 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
694 }
695 return nbytes;
696}
697
699{
700 for (unsigned i = 0; i < fSubfields.size(); ++i) {
701 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
702 }
703}
704
706{
707 for (unsigned i = 0; i < fSubfields.size(); ++i) {
708 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
709 }
710}
711
713{
714 if (fTraits & kTraitEmulatedField) {
715 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
716 return;
717 }
718 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
719 R__ASSERT(GetTypeName().empty());
720
721 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
722
723 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
724 // and we will ignore extra on-disk fields.
725 // It remains to mark the extra in-memory fields as artificial.
726 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
727 std::unordered_set<std::string_view> onDiskSubfields;
728 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
729 onDiskSubfields.insert(subField.GetFieldName());
730 }
731 for (auto &f : fSubfields) {
732 if (onDiskSubfields.count(f->GetFieldName()) == 0)
733 CallSetArtificialOn(*f);
734 }
735}
736
738{
739 for (unsigned i = 0; i < fSubfields.size(); ++i) {
740 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
741 }
742}
743
744void ROOT::RRecordField::RRecordDeleter::operator()(void *objPtr, bool dtorOnly)
745{
746 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
747 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
748 }
749 RDeleter::operator()(objPtr, dtorOnly);
750}
751
752std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
753{
754 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
755 itemDeleters.reserve(fOffsets.size());
756 for (const auto &f : fSubfields) {
757 itemDeleters.emplace_back(GetDeleterOf(*f));
758 }
759 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets, GetAlignment());
760}
761
762std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
763{
764 auto valuePtr = value.GetPtr<void>();
765 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
766 std::vector<RValue> result;
767 result.reserve(fSubfields.size());
768 for (unsigned i = 0; i < fSubfields.size(); ++i) {
769 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
770 }
771 return result;
772}
773
775{
776 visitor.VisitRecordField(*this);
777}
778
779//------------------------------------------------------------------------------
780
781ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
782 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
783 false /* isSimple */, N),
784 fN(N)
785{
787}
788
790{
791 static RColumnRepresentations representations({{ENTupleColumnType::kBit}}, {});
792 return representations;
793}
794
796{
797 GenerateColumnsImpl<bool>();
798}
799
801{
802 GenerateColumnsImpl<bool>(desc);
803}
804
805template <typename FUlong, typename FUlonglong, typename... Args>
806void ROOT::RBitsetField::SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
807{
808 if (WordSize() == sizeof(unsigned long)) {
809 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
810 } else if (WordSize() == sizeof(unsigned long long)) {
811 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
812 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
813 } else {
814 R__ASSERT(false);
815 }
816}
817
818template <typename Word_t>
819static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
820{
821 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
822 // Process bits in stack-buffered chunks using AppendV to reduce per-element call overhead.
823 constexpr std::size_t kChunkSize = 256;
824 bool buffer[kChunkSize];
825
826 const auto *asWordArray = static_cast<const Word_t *>(from);
827 std::size_t bitIdx = 0;
828 while (bitIdx < nBits) {
829 const std::size_t nBatch = std::min(kChunkSize, nBits - bitIdx);
830 for (std::size_t b = 0; b < nBatch; ++b) {
831 const std::size_t currentBit = bitIdx + b;
832 buffer[b] =
833 (asWordArray[currentBit / kBitsPerWord] & (static_cast<Word_t>(1) << (currentBit % kBitsPerWord))) != 0;
834 }
835 column.AppendV(buffer, nBatch);
836 bitIdx += nBatch;
837 }
838}
839
840std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
841{
842 SelectWordSize(BitsetAppendImpl<unsigned long>, BitsetAppendImpl<unsigned long long>, from);
843 return fN;
844}
845
846template <typename Word_t>
847static void
848BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
849{
850 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
851 // Read column values into a local buffer in chunks via ReadV, then unpack them into bitset words.
852 constexpr std::size_t kChunkSize = 256;
853 bool buffer[kChunkSize];
854
855 auto *asWordArray = static_cast<Word_t *>(to);
856 std::size_t bitIdx = 0;
857 while (bitIdx < nBits) {
858 const std::size_t nBatch = std::min(kChunkSize, nBits - bitIdx);
859 column.ReadV(globalIndex * nBits + bitIdx, nBatch, buffer);
860 for (std::size_t b = 0; b < nBatch; ++b) {
861 const std::size_t currentBit = bitIdx + b;
862 const Word_t mask = static_cast<Word_t>(1) << (currentBit % kBitsPerWord);
863 const Word_t bit = static_cast<Word_t>(buffer[b]) << (currentBit % kBitsPerWord);
864 asWordArray[currentBit / kBitsPerWord] = (asWordArray[currentBit / kBitsPerWord] & ~mask) | bit;
865 }
866 bitIdx += nBatch;
867 }
868}
869
871{
872 SelectWordSize(BitsetReadGlobalImpl<unsigned long>, BitsetReadGlobalImpl<unsigned long long>, globalIndex, to);
873}
874
875template <typename Word_t>
876static void
878{
879 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
880 constexpr std::size_t kChunkSize = 256;
881 bool buffer[kChunkSize];
882
883 auto *asWordArray = static_cast<Word_t *>(to);
884 std::size_t bitIdx = 0;
885 while (bitIdx < nBits) {
886 const std::size_t nBatch = std::min(kChunkSize, nBits - bitIdx);
887 column.ReadV(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits + bitIdx),
888 nBatch, buffer);
889 for (std::size_t b = 0; b < nBatch; ++b) {
890 const std::size_t currentBit = bitIdx + b;
891 const Word_t mask = static_cast<Word_t>(1) << (currentBit % kBitsPerWord);
892 const Word_t bit = static_cast<Word_t>(buffer[b]) << (currentBit % kBitsPerWord);
893 asWordArray[currentBit / kBitsPerWord] = (asWordArray[currentBit / kBitsPerWord] & ~mask) | bit;
894 }
895 bitIdx += nBatch;
896 }
897}
898
900{
901 SelectWordSize(BitsetReadInClusterImpl<unsigned long>, BitsetReadInClusterImpl<unsigned long long>, localIndex, to);
902}
903
905{
906 visitor.VisitBitsetField(*this);
907}
908
909//------------------------------------------------------------------------------
910
911ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
912 std::unique_ptr<RFieldBase> itemField)
913 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
914 false /* isSimple */)
915{
916 if (!itemField->GetTypeAlias().empty())
917 fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
918
919 Attach(std::move(itemField), "_0");
920}
921
931
933{
934 R__ASSERT(!fIsEvolvedFromInnerType);
935 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>();
936}
937
939{
940 if (!fIsEvolvedFromInnerType)
941 GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
942}
943
945{
946 fPrincipalColumn->Append(&fNWritten);
947 return sizeof(ROOT::Internal::RColumnIndex);
948}
949
950std::size_t ROOT::RNullableField::AppendValue(const void *from)
951{
952 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
953 fNWritten++;
954 fPrincipalColumn->Append(&fNWritten);
955 return sizeof(ROOT::Internal::RColumnIndex) + nbytesItem;
956}
957
959{
960 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
961
962 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
963 if (!success) {
964 fIsEvolvedFromInnerType = true;
965 } else {
966 success = EnsureMatchingTypePrefix(desc, prefixes);
967 fIsEvolvedFromInnerType = !success;
968 }
969
970 if (fIsEvolvedFromInnerType)
971 fSubfields[0]->SetOnDiskId(GetOnDiskId());
972}
973
975{
976 RNTupleLocalIndex collectionStart;
977 ROOT::NTupleSize_t collectionSize;
978 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
979 return (collectionSize == 0) ? RNTupleLocalIndex() : collectionStart;
980}
981
983{
984 RNTupleLocalIndex collectionStart;
985 ROOT::NTupleSize_t collectionSize;
986 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &collectionSize);
987 return (collectionSize == 0) ? RNTupleLocalIndex() : collectionStart;
988}
989
994
995//------------------------------------------------------------------------------
996
997namespace {
998// Dummy class to determine the dynamic type of any polymorphic user object.
999struct PolymorphicClass {
1000 virtual ~PolymorphicClass() = default;
1001};
1002} // namespace
1003
1004ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1005 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1006{
1007 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
1008 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
1009 }
1010}
1011
1012std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
1013{
1014 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1015 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
1016}
1017
1018std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
1019{
1020 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
1021 if (*typedValue) {
1022 const void *obj = typedValue->get();
1023 if (fPolymorphicTypeInfo != nullptr) {
1024 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
1025 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
1026 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
1027 if (t != *fPolymorphicTypeInfo) {
1028 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
1029 int err = 0;
1030 char *demangled = TClassEdit::DemangleTypeIdName(t, err);
1031 if (!err) {
1032 msg = msg + " but was passed " + demangled;
1033 free(demangled);
1034 }
1035 msg += " and upcasting of polymorphic types is not supported in RNTuple";
1036 throw RException(R__FAIL(msg));
1037 }
1038 }
1039 return AppendValue(obj);
1040 } else {
1041 return AppendNull();
1042 }
1043}
1044
1045void *ROOT::RUniquePtrField::PrepareRead(void *to, bool hasOnDiskValue)
1046{
1047 auto ptr = static_cast<std::unique_ptr<char> *>(to);
1048 bool isValidValue = static_cast<bool>(*ptr);
1049
1050 void *valuePtr = nullptr;
1051 if (isValidValue)
1052 valuePtr = ptr->get();
1053
1054 if (isValidValue && !hasOnDiskValue) {
1055 ptr->release();
1056 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
1057 valuePtr = nullptr;
1058 } else if (!isValidValue && hasOnDiskValue) {
1059 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
1060 ptr->reset(reinterpret_cast<char *>(valuePtr));
1061 }
1062
1063 return valuePtr;
1064}
1065
1067{
1068 RNTupleLocalIndex itemIndex;
1069 if (!fIsEvolvedFromInnerType)
1070 itemIndex = GetItemIndex(globalIndex);
1071 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1072 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1073 if (hasOnDiskValue) {
1074 if (fIsEvolvedFromInnerType) {
1075 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1076 } else {
1077 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1078 }
1079 }
1080}
1081
1083{
1084 RNTupleLocalIndex itemIndex;
1085 if (!fIsEvolvedFromInnerType) {
1086 itemIndex = GetItemIndex(localIndex);
1087 } else {
1088 itemIndex = localIndex;
1089 }
1090 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1091 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1092 if (hasOnDiskValue)
1093 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1094}
1095
1097{
1098 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1099 if (*typedPtr) {
1100 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1101 typedPtr->release();
1102 }
1103 RDeleter::operator()(objPtr, dtorOnly);
1104}
1105
1106std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1107{
1108 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1109}
1110
1111std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1112{
1113 std::vector<RValue> result;
1114 auto valuePtr = value.GetPtr<void>();
1115 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1116 if (uniquePtr) {
1117 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1118 }
1119 return result;
1120}
1121
1122//------------------------------------------------------------------------------
1123
1124ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1125 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1126{
1129}
1130
1131bool *ROOT::ROptionalField::GetEngagementPtr(void *optionalPtr) const
1132{
1133 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1134}
1135
1136const bool *ROOT::ROptionalField::GetEngagementPtr(const void *optionalPtr) const
1137{
1138 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1139}
1140
1141std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1142{
1143 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1144 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1145}
1146
1147std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1148{
1149 if (*GetEngagementPtr(from)) {
1150 return AppendValue(from);
1151 } else {
1152 return AppendNull();
1153 }
1154}
1155
1156void ROOT::ROptionalField::PrepareRead(void *to, bool hasOnDiskValue)
1157{
1158 auto engagementPtr = GetEngagementPtr(to);
1159 if (hasOnDiskValue) {
1160 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1161 CallConstructValueOn(*fSubfields[0], to);
1162 *engagementPtr = true;
1163 } else {
1164 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1165 fItemDeleter->operator()(to, true /* dtorOnly */);
1166 *engagementPtr = false;
1167 }
1168}
1169
1171{
1172 RNTupleLocalIndex itemIndex;
1173 if (!fIsEvolvedFromInnerType)
1174 itemIndex = GetItemIndex(globalIndex);
1175 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1176 PrepareRead(to, hasOnDiskValue);
1177 if (hasOnDiskValue) {
1178 if (fIsEvolvedFromInnerType) {
1179 CallReadOn(*fSubfields[0], globalIndex, to);
1180 } else {
1181 CallReadOn(*fSubfields[0], itemIndex, to);
1182 }
1183 }
1184}
1185
1187{
1188 RNTupleLocalIndex itemIndex;
1189 if (!fIsEvolvedFromInnerType) {
1190 itemIndex = GetItemIndex(localIndex);
1191 } else {
1192 itemIndex = localIndex;
1193 }
1194 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1195 PrepareRead(to, hasOnDiskValue);
1196 if (hasOnDiskValue)
1197 CallReadOn(*fSubfields[0], itemIndex, to);
1198}
1199
1201{
1202 *GetEngagementPtr(where) = false;
1203}
1204
1206{
1207 if (fItemDeleter) {
1208 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1209 if (*engagementPtr)
1210 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1211 }
1212 RDeleter::operator()(objPtr, dtorOnly);
1213}
1214
1215std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1216{
1217 return std::make_unique<ROptionalDeleter>(
1218 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1219 fSubfields[0]->GetValueSize(), GetAlignment());
1220}
1221
1222std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1223{
1224 std::vector<RValue> result;
1225 const auto valuePtr = value.GetPtr<void>().get();
1226 if (*GetEngagementPtr(valuePtr)) {
1227 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1228 }
1229 return result;
1230}
1231
1233{
1234 const auto alignment = GetAlignment();
1235 // real size is the sum of the value size and the engagement boolean
1236 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1237 auto padding = 0;
1238 if (alignment > 1) {
1239 auto remainder = actualSize % alignment;
1240 if (remainder != 0)
1241 padding = alignment - remainder;
1242 }
1243 return actualSize + padding;
1244}
1245
1247{
1248 return fSubfields[0]->GetAlignment();
1249}
1250
1251//------------------------------------------------------------------------------
1252
1253ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1254 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1255 false /* isSimple */)
1256{
1257 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1259 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1261
1262 if (!itemField->GetTypeAlias().empty())
1263 fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1264
1265 Attach(std::move(itemField), "_0");
1266}
1267
1268std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1269{
1270 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1271 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1272}
1273
1275{
1276 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1277 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1278 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1279 } else {
1280 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1281 }
1282}
1283
1284std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1285{
1286 std::vector<RValue> result;
1287 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1288 return result;
1289}
1290
1292{
1293 visitor.VisitAtomicField(*this);
1294}
free(fBuffer)
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:322
static void BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:848
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:877
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:819
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:139
#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:142
TCanvas * alignment()
Definition alignment.C:1
Abstract base class for classes implementing the visitor design pattern.
virtual void VisitBitsetField(const ROOT::RBitsetField &field)
virtual void VisitByteField(const ROOT::RField< std::byte > &field)
virtual void VisitInt64Field(const ROOT::RIntegralField< std::int64_t > &field)
virtual void VisitInt8Field(const ROOT::RIntegralField< std::int8_t > &field)
virtual void VisitCharField(const ROOT::RField< char > &field)
virtual void VisitDoubleField(const ROOT::RField< double > &field)
virtual void VisitUInt32Field(const ROOT::RIntegralField< std::uint32_t > &field)
virtual void VisitCardinalityField(const ROOT::RCardinalityField &field)
virtual void VisitInt32Field(const ROOT::RIntegralField< std::int32_t > &field)
virtual void VisitUInt8Field(const ROOT::RIntegralField< std::uint8_t > &field)
virtual void VisitFieldZero(const ROOT::RFieldZero &field)
virtual void VisitStringField(const ROOT::RField< std::string > &field)
virtual void VisitUInt16Field(const ROOT::RIntegralField< std::uint16_t > &field)
virtual void VisitNullableField(const ROOT::RNullableField &field)
virtual void VisitInt16Field(const ROOT::RIntegralField< std::int16_t > &field)
virtual void VisitUInt64Field(const ROOT::RIntegralField< std::uint64_t > &field)
virtual void VisitBoolField(const ROOT::RField< bool > &field)
virtual void VisitRecordField(const ROOT::RRecordField &field)
virtual void VisitAtomicField(const ROOT::RAtomicField &field)
virtual void VisitFloatField(const ROOT::RField< float > &field)
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 AppendV(const void *from, std::size_t count)
Definition RColumn.hxx:137
void ReadV(ROOT::NTupleSize_t globalIndex, ROOT::NTupleSize_t count, void *to)
Definition RColumn.hxx:180
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1291
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1253
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1268
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:1274
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:1284
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:781
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:899
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:795
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:870
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:840
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:789
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:904
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:806
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:390
The field for a class with dictionary.
Definition RField.hxx:184
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.
std::vector< const RFieldBase * > GetConstSubfields() const
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field 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.
@ kTraitTypeChecksum
The TClass checksum is set and valid.
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
RFieldBase * fParent
Subfields point to their mother field.
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.
std::optional< std::uint32_t > GetTypeChecksum() const
std::uint32_t GetTypeVersion() const
const std::string & GetTypeName() const
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
bool fAllowFieldSubstitutions
If field substitutions are allowed, upon connecting to a page source the field hierarchy will replace...
Definition RField.hxx:69
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:342
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...
ROOT::NTupleSize_t GetIndexInCluster() const
ROOT::DescriptorId_t GetClusterId() const
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:958
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:974
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:911
std::size_t AppendNull()
Definition RField.cxx:944
std::size_t AppendValue(const void *from)
Definition RField.cxx:950
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:932
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:990
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:922
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1205
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:1200
std::size_t GetAlignment() const final
What alignof(T) for this type returns.
Definition RField.cxx:1246
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1215
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1141
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:1136
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1170
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1147
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1186
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:1222
std::size_t GetValueSize() const final
What sizeof(T) for this type returns.
Definition RField.cxx:1232
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1156
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1124
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:744
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:762
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:684
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:705
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:774
void AttachItemFields(ContainerT &&itemFields)
std::uint32_t fEmulatedTypeVersion
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:752
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:674
void AddItem(std::unique_ptr< RFieldBase > item)
Adds an additional item field.
Definition RField.cxx:626
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:698
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:737
std::uint32_t fEmulatedTypeChecksum
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:689
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:712
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:1096
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:1111
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:1045
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1106
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1066
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1012
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1004
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1018
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1082
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, const RFieldDescriptor &emulatedFrom)
Definition RField.cxx:598
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, const RFieldDescriptor &emulatedFrom)
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:647
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.