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
94
96{
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{
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{
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
206void ROOT::RField<std::byte>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
207{
208 visitor.VisitByteField(*this);
209}
210
211//------------------------------------------------------------------------------
212
213template class ROOT::RSimpleField<int8_t>;
214
215const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::int8_t>::GetColumnRepresentations() const
216{
217 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
232 return representations;
233}
234
235void ROOT::RIntegralField<std::int8_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
236{
237 visitor.VisitInt8Field(*this);
238}
239
240//------------------------------------------------------------------------------
241
242template class ROOT::RSimpleField<uint8_t>;
243
244const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::uint8_t>::GetColumnRepresentations() const
245{
246 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
261 return representations;
262}
263
264void ROOT::RIntegralField<std::uint8_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
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
369void ROOT::RIntegralField<std::int16_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
370{
371 visitor.VisitInt16Field(*this);
372}
373
374//------------------------------------------------------------------------------
375
376template class ROOT::RSimpleField<uint16_t>;
377
378const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::uint16_t>::GetColumnRepresentations() const
379{
380 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt16}, {ENTupleColumnType::kUInt16}},
395 return representations;
396}
397
398void ROOT::RIntegralField<std::uint16_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
399{
400 visitor.VisitUInt16Field(*this);
401}
402
403//------------------------------------------------------------------------------
404
405template class ROOT::RSimpleField<int32_t>;
406
407const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::int32_t>::GetColumnRepresentations() const
408{
409 static RColumnRepresentations representations({{ENTupleColumnType::kSplitInt32}, {ENTupleColumnType::kInt32}},
424 return representations;
425}
426
427void ROOT::RIntegralField<std::int32_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
428{
429 visitor.VisitInt32Field(*this);
430}
431
432//------------------------------------------------------------------------------
433
434template class ROOT::RSimpleField<uint32_t>;
435
436const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::uint32_t>::GetColumnRepresentations() const
437{
438 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt32}, {ENTupleColumnType::kUInt32}},
453 return representations;
454}
455
456void ROOT::RIntegralField<std::uint32_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
457{
458 visitor.VisitUInt32Field(*this);
459}
460
461//------------------------------------------------------------------------------
462
463template class ROOT::RSimpleField<uint64_t>;
464
465const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::uint64_t>::GetColumnRepresentations() const
466{
467 static RColumnRepresentations representations({{ENTupleColumnType::kSplitUInt64}, {ENTupleColumnType::kUInt64}},
482 return representations;
483}
484
485void ROOT::RIntegralField<std::uint64_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
486{
487 visitor.VisitUInt64Field(*this);
488}
489
490//------------------------------------------------------------------------------
491
492template class ROOT::RSimpleField<int64_t>;
493
494const ROOT::RFieldBase::RColumnRepresentations &ROOT::RIntegralField<std::int64_t>::GetColumnRepresentations() const
495{
496 static RColumnRepresentations representations({{ENTupleColumnType::kSplitInt64}, {ENTupleColumnType::kInt64}},
511 return representations;
512}
513
514void ROOT::RIntegralField<std::int64_t>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
515{
516 visitor.VisitInt64Field(*this);
517}
518
519//------------------------------------------------------------------------------
520
521const ROOT::RFieldBase::RColumnRepresentations &ROOT::RField<std::string>::GetColumnRepresentations() const
522{
523 static RColumnRepresentations representations({{ENTupleColumnType::kSplitIndex64, ENTupleColumnType::kChar},
527 {});
528 return representations;
529}
530
532{
533 GenerateColumnsImpl<ROOT::Internal::RColumnIndex, char>();
534}
535
536void ROOT::RField<std::string>::GenerateColumns(const ROOT::RNTupleDescriptor &desc)
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
565void ROOT::RField<std::string>::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
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 */),
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 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)
608 : ROOT::RFieldBase(fieldName, emulatedFromType, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
609{
610 AttachItemFields(std::move(itemFields));
611 fTraits |= !emulatedFromType.empty() * kTraitEmulatedField;
612}
613
614ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
615 : ROOT::RRecordField(fieldName, std::move(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
641void ROOT::Internal::AddItemToRecord(RRecordField &record, std::unique_ptr<RFieldBase> newItem)
642{
643 // Only supported for untyped records
644 assert(record.GetTypeName().empty());
645 record.AddItem(std::move(newItem));
646}
647
648std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
649{
650 if (itemAlignment > 1) {
651 auto remainder = baseOffset % itemAlignment;
652 if (remainder != 0)
653 return itemAlignment - remainder;
654 }
655 return 0;
656}
657
658std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
659{
660 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
661}
662
663std::size_t ROOT::RRecordField::AppendImpl(const void *from)
664{
665 std::size_t nbytes = 0;
666 for (unsigned i = 0; i < fSubfields.size(); ++i) {
667 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
668 }
669 return nbytes;
670}
671
673{
674 for (unsigned i = 0; i < fSubfields.size(); ++i) {
675 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
676 }
677}
678
680{
681 for (unsigned i = 0; i < fSubfields.size(); ++i) {
682 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
683 }
684}
685
687{
689 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
690 return;
691 }
692 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
693 R__ASSERT(GetTypeName().empty());
694
696
697 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
698 // and we will ignore extra on-disk fields.
699 // It remains to mark the extra in-memory fields as artificial.
700 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
701 std::unordered_set<std::string_view> onDiskSubfields;
702 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
703 onDiskSubfields.insert(subField.GetFieldName());
704 }
705 for (auto &f : fSubfields) {
706 if (onDiskSubfields.count(f->GetFieldName()) == 0)
708 }
709}
710
712{
713 for (unsigned i = 0; i < fSubfields.size(); ++i) {
714 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
715 }
716}
717
718void ROOT::RRecordField::RRecordDeleter::operator()(void *objPtr, bool dtorOnly)
719{
720 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
721 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
722 }
723 RDeleter::operator()(objPtr, dtorOnly);
724}
725
726std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
727{
728 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
729 itemDeleters.reserve(fOffsets.size());
730 for (const auto &f : fSubfields) {
731 itemDeleters.emplace_back(GetDeleterOf(*f));
732 }
733 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
734}
735
736std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
737{
738 auto valuePtr = value.GetPtr<void>();
739 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
740 std::vector<RValue> result;
741 result.reserve(fSubfields.size());
742 for (unsigned i = 0; i < fSubfields.size(); ++i) {
743 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
744 }
745 return result;
746}
747
749{
750 visitor.VisitRecordField(*this);
751}
752
753//------------------------------------------------------------------------------
754
755ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
756 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
757 false /* isSimple */, N),
758 fN(N)
759{
761}
762
764{
765 static RColumnRepresentations representations({{ENTupleColumnType::kBit}}, {});
766 return representations;
767}
768
773
778
779template <typename FUlong, typename FUlonglong, typename... Args>
780void ROOT::RBitsetField::SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
781{
782 if (WordSize() == sizeof(unsigned long)) {
783 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
784 } else if (WordSize() == sizeof(unsigned long long)) {
785 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
786 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
787 } else {
788 R__ASSERT(false);
789 }
790}
791
792template <typename Word_t>
793static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
794{
795 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
796
797 const auto *asWordArray = static_cast<const Word_t *>(from);
798 bool elementValue;
799 std::size_t i = 0;
800 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
801 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
802 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
803 column.Append(&elementValue);
804 }
805 }
806}
807
813
814template <typename Word_t>
815static void
816BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
817{
818 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
819
820 auto *asWordArray = static_cast<Word_t *>(to);
821 bool elementValue;
822 for (std::size_t i = 0; i < nBits; ++i) {
823 column.Read(globalIndex * nBits + i, &elementValue);
824 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
825 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
826 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
827 }
828}
829
834
835template <typename Word_t>
836static void
838{
839 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
840
841 auto *asWordArray = static_cast<Word_t *>(to);
842 bool elementValue;
843 for (std::size_t i = 0; i < nBits; ++i) {
844 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
845 &elementValue);
846 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
847 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
848 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
849 }
850}
851
856
858{
859 visitor.VisitBitsetField(*this);
860}
861
862//------------------------------------------------------------------------------
863
864ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
865 std::unique_ptr<RFieldBase> itemField)
866 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
867 false /* isSimple */)
868{
869 if (!itemField->GetTypeAlias().empty())
870 fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
871
872 Attach(std::move(itemField), "_0");
873}
874
884
890
896
898{
899 fPrincipalColumn->Append(&fNWritten);
900 return sizeof(ROOT::Internal::RColumnIndex);
901}
902
903std::size_t ROOT::RNullableField::AppendValue(const void *from)
904{
905 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
906 fNWritten++;
907 fPrincipalColumn->Append(&fNWritten);
908 return sizeof(ROOT::Internal::RColumnIndex) + nbytesItem;
909}
910
912{
913 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
914
915 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
916 if (!success) {
918 } else {
919 success = EnsureMatchingTypePrefix(desc, prefixes);
920 fIsEvolvedFromInnerType = !success;
921 }
922
924 fSubfields[0]->SetOnDiskId(GetOnDiskId());
925}
926
928{
929 RNTupleLocalIndex collectionStart;
930 ROOT::NTupleSize_t collectionSize;
931 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &collectionSize);
932 return (collectionSize == 0) ? RNTupleLocalIndex() : collectionStart;
933}
934
936{
937 RNTupleLocalIndex collectionStart;
938 ROOT::NTupleSize_t collectionSize;
939 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &collectionSize);
940 return (collectionSize == 0) ? RNTupleLocalIndex() : collectionStart;
941}
942
947
948//------------------------------------------------------------------------------
949
950namespace {
951// Dummy class to determine the dynamic type of any polymorphic user object.
952struct PolymorphicClass {
953 virtual ~PolymorphicClass() = default;
954};
955} // namespace
956
957ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
958 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
959{
960 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
961 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
962 }
963}
964
965std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
966{
967 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
968 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
969}
970
971std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
972{
973 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
974 if (*typedValue) {
975 const void *obj = typedValue->get();
976 if (fPolymorphicTypeInfo != nullptr) {
977 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
978 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
979 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
980 if (t != *fPolymorphicTypeInfo) {
981 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
982 int err = 0;
983 char *demangled = TClassEdit::DemangleTypeIdName(t, err);
984 if (!err) {
985 msg = msg + " but was passed " + demangled;
986 free(demangled);
987 }
988 msg += " and upcasting of polymorphic types is not supported in RNTuple";
989 throw RException(R__FAIL(msg));
990 }
991 }
992 return AppendValue(obj);
993 } else {
994 return AppendNull();
995 }
996}
997
998void *ROOT::RUniquePtrField::PrepareRead(void *to, bool hasOnDiskValue)
999{
1000 auto ptr = static_cast<std::unique_ptr<char> *>(to);
1001 bool isValidValue = static_cast<bool>(*ptr);
1002
1003 void *valuePtr = nullptr;
1004 if (isValidValue)
1005 valuePtr = ptr->get();
1006
1007 if (isValidValue && !hasOnDiskValue) {
1008 ptr->release();
1009 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
1010 } else if (!isValidValue && hasOnDiskValue) {
1011 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
1012 ptr->reset(reinterpret_cast<char *>(valuePtr));
1013 }
1014
1015 return valuePtr;
1016}
1017
1019{
1020 RNTupleLocalIndex itemIndex;
1022 itemIndex = GetItemIndex(globalIndex);
1023 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1024 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1025 if (hasOnDiskValue) {
1027 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1028 } else {
1029 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1030 }
1031 }
1032}
1033
1035{
1036 RNTupleLocalIndex itemIndex;
1038 itemIndex = GetItemIndex(localIndex);
1039 } else {
1040 itemIndex = localIndex;
1041 }
1042 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1043 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1044 if (hasOnDiskValue)
1045 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1046}
1047
1049{
1050 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1051 if (*typedPtr) {
1052 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1053 typedPtr->release();
1054 }
1055 RDeleter::operator()(objPtr, dtorOnly);
1056}
1057
1058std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1059{
1060 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1061}
1062
1063std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1064{
1065 std::vector<RValue> result;
1066 auto valuePtr = value.GetPtr<void>();
1067 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1068 if (uniquePtr) {
1069 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1070 }
1071 return result;
1072}
1073
1074//------------------------------------------------------------------------------
1075
1076ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1077 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1078{
1081}
1082
1083bool *ROOT::ROptionalField::GetEngagementPtr(void *optionalPtr) const
1084{
1085 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1086}
1087
1088const bool *ROOT::ROptionalField::GetEngagementPtr(const void *optionalPtr) const
1089{
1090 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1091}
1092
1093std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1094{
1095 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1096 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1097}
1098
1099std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1100{
1101 if (*GetEngagementPtr(from)) {
1102 return AppendValue(from);
1103 } else {
1104 return AppendNull();
1105 }
1106}
1107
1108void ROOT::ROptionalField::PrepareRead(void *to, bool hasOnDiskValue)
1109{
1110 auto engagementPtr = GetEngagementPtr(to);
1111 if (hasOnDiskValue) {
1112 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1114 *engagementPtr = true;
1115 } else {
1116 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1117 fItemDeleter->operator()(to, true /* dtorOnly */);
1118 *engagementPtr = false;
1119 }
1120}
1121
1123{
1124 RNTupleLocalIndex itemIndex;
1126 itemIndex = GetItemIndex(globalIndex);
1127 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1128 PrepareRead(to, hasOnDiskValue);
1129 if (hasOnDiskValue) {
1131 CallReadOn(*fSubfields[0], globalIndex, to);
1132 } else {
1133 CallReadOn(*fSubfields[0], itemIndex, to);
1134 }
1135 }
1136}
1137
1139{
1140 RNTupleLocalIndex itemIndex;
1142 itemIndex = GetItemIndex(localIndex);
1143 } else {
1144 itemIndex = localIndex;
1145 }
1146 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1147 PrepareRead(to, hasOnDiskValue);
1148 if (hasOnDiskValue)
1149 CallReadOn(*fSubfields[0], itemIndex, to);
1150}
1151
1153{
1154 *GetEngagementPtr(where) = false;
1155}
1156
1158{
1159 if (fItemDeleter) {
1160 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1161 if (*engagementPtr)
1162 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1163 }
1164 RDeleter::operator()(objPtr, dtorOnly);
1165}
1166
1167std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1168{
1169 return std::make_unique<ROptionalDeleter>(
1171 fSubfields[0]->GetValueSize());
1172}
1173
1174std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1175{
1176 std::vector<RValue> result;
1177 const auto valuePtr = value.GetPtr<void>().get();
1178 if (*GetEngagementPtr(valuePtr)) {
1179 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1180 }
1181 return result;
1182}
1183
1185{
1186 const auto alignment = GetAlignment();
1187 // real size is the sum of the value size and the engagement boolean
1188 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1189 auto padding = 0;
1190 if (alignment > 1) {
1191 auto remainder = actualSize % alignment;
1192 if (remainder != 0)
1193 padding = alignment - remainder;
1194 }
1195 return actualSize + padding;
1196}
1197
1199{
1200 return fSubfields[0]->GetAlignment();
1201}
1202
1203//------------------------------------------------------------------------------
1204
1205ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1206 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1207 false /* isSimple */)
1208{
1209 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1211 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1213
1214 if (!itemField->GetTypeAlias().empty())
1215 fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1216
1217 Attach(std::move(itemField), "_0");
1218}
1219
1220std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1221{
1222 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1223 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1224}
1225
1227{
1228 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1229 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1230 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1231 } else {
1232 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1233 }
1234}
1235
1236std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1237{
1238 std::vector<RValue> result;
1239 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1240 return result;
1241}
1242
1244{
1245 visitor.VisitAtomicField(*this);
1246}
#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:816
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:837
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:793
#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:125
#define N
char name[80]
Definition TGX11.cxx:148
Double_t err
@ kCollection
Definition TStructNode.h:21
TCanvas * alignment()
Definition alignment.C:1
#define free
Definition civetweb.c:1578
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 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:1243
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1205
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1220
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:1226
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:1236
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:755
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:852
size_t WordSize() const
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:769
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:830
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:808
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:763
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:857
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:780
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.
std::shared_ptr< T > GetPtr() const
void Attach(std::unique_ptr< RFieldBase > child, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
ROOT::Internal::RColumn * fPrincipalColumn
All fields that have columns have a distinct main column.
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
void SetOnDiskId(ROOT::DescriptorId_t id)
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitExtensible
Can attach new item fields even when already connected.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
static std::unique_ptr< RDeleter > GetDeleterOf(const RFieldBase &other)
static void CallSetArtificialOn(RFieldBase &other)
Allow parents to mark their childs as artificial fields (used in class and record fields).
std::string GetQualifiedFieldName() const
Returns the field name and parent field names separated by dots (grandparent.parent....
const std::string & GetFieldName() const
RResult< void > EnsureMatchingOnDiskField(const RNTupleDescriptor &desc, std::uint32_t ignoreBits=0) const
Compares the field to the corresponding on-disk field information in the provided descriptor.
static std::size_t CallAppendOn(RFieldBase &other, const void *from)
Allow derived classes to call Append() and Read() on other (sub)fields.
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
RFieldBase(std::string_view name, std::string_view type, ROOT::ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
static void * CallCreateObjectRawPtrOn(RFieldBase &other)
std::uint32_t GetTraits() const
const std::string & GetTypeName() const
void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
Helpers for generating columns.
RValue BindValue(std::shared_ptr< void > objPtr)
Creates a value from a memory location with an already constructed object.
static void CallReadOn(RFieldBase &other, RNTupleLocalIndex localIndex, void *to)
ROOT::DescriptorId_t GetOnDiskId() const
static void CallConstructValueOn(const RFieldBase &other, void *where)
Allow derived classes to call ConstructValue(void *) and GetDeleter() on other (sub)fields.
RResult< void > EnsureMatchingTypePrefix(const RNTupleDescriptor &desc, const std::vector< std::string > &prefixes) const
Many fields accept a range of type prefixes for schema evolution, e.g.
@ kDiffStructure
The in-memory field and the on-disk field differ in their structural roles.
@ kDiffTypeName
The in-memory field and the on-disk field have different type names.
@ kDiffTypeVersion
The in-memory field and the on-disk field differ in the type version.
Metadata stored for every field of an RNTuple.
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: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...
ROOT::NTupleSize_t GetIndexInCluster() const
ROOT::DescriptorId_t GetClusterId() const
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:911
ROOT::Internal::RColumnIndex fNWritten
The number of written non-null items in this cluster.
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:927
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:864
std::size_t AppendNull()
Definition RField.cxx:897
std::size_t AppendValue(const void *from)
Definition RField.cxx:903
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:885
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:943
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:875
std::unique_ptr< RDeleter > fItemDeleter
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1157
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:1152
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1198
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1167
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1093
std::unique_ptr< RDeleter > fItemDeleter
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:1088
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1122
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1099
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1138
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:1174
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1184
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1108
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1076
std::vector< std::size_t > fOffsets
std::vector< std::unique_ptr< RDeleter > > fItemDeleters
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:718
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:736
std::size_t fMaxAlignment
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:658
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:679
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:748
void AttachItemFields(ContainerT &&itemFields)
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:726
bool IsPairOrTuple() const
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:648
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:672
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:711
std::vector< std::size_t > fOffsets
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:663
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:686
void ReconcileIntegralField(const RNTupleDescriptor &desc)
Definition RField.cxx:135
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
Definition RField.cxx:156
std::unique_ptr< RDeleter > fItemDeleter
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1048
std::unique_ptr< RDeleter > fItemDeleter
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:1063
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:998
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1058
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1018
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:965
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:957
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:971
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1034
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
if(pos!=-1) leafTypeName.Remove(pos)
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.
BVH_ALWAYS_INLINE T length(const Vec< T, N > &v)
Definition vec.h:122