Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RField.cxx
Go to the documentation of this file.
1/// \file RField.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include <ROOT/RColumn.hxx>
15#include <ROOT/REntry.hxx>
16#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
19#include <ROOT/RLogger.hxx>
20#include <ROOT/RNTupleModel.hxx>
22#include <ROOT/RNTupleTypes.hxx>
23
24#include <algorithm>
25#include <cstdint>
26#include <exception>
27#include <functional>
28#include <iostream>
29#include <memory>
30#include <string_view>
31#include <type_traits>
32#include <unordered_set>
33
35{
36 fieldZero.fAllowFieldSubstitutions = val;
37}
38
39std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldZero::CloneImpl(std::string_view /*newName*/) const
40{
41 auto result = std::make_unique<RFieldZero>();
42 for (auto &f : fSubfields)
43 result->Attach(f->Clone(f->GetFieldName()));
44 return result;
45}
46
47std::vector<std::unique_ptr<ROOT::RFieldBase>> ROOT::RFieldZero::ReleaseSubfields()
48{
49 std::vector<std::unique_ptr<ROOT::RFieldBase>> result;
50 std::swap(fSubfields, result);
51 for (auto &f : result)
52 f->fParent = nullptr;
53 return result;
54}
55
57{
58 visitor.VisitFieldZero(*this);
59}
60
61//------------------------------------------------------------------------------
62
72
77
79{
80 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError();
81
82 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
83 if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) {
84 if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) {
85 throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() +
86 " expects an on-disk leaf field of the same type\n" +
87 Internal::GetTypeTraceReport(*this, desc)));
88 }
89 } else if (fieldDesc.GetStructure() != ENTupleStructure::kCollection) {
90 throw RException(R__FAIL("invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName() +
91 "\n" + Internal::GetTypeTraceReport(*this, desc)));
92 }
93}
94
96{
97 visitor.VisitCardinalityField(*this);
98}
99
104
109
110//------------------------------------------------------------------------------
111
112template <typename T>
114{
115 EnsureMatchingOnDiskField(desc, kDiffTypeName);
116
117 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
118 if (fieldDesc.IsCustomEnum(desc)) {
119 SetOnDiskId(desc.FindFieldId("_0", GetOnDiskId()));
120 return;
121 }
122
123 static const std::string gIntegralTypeNames[] = {"bool", "char", "std::int8_t", "std::uint8_t",
124 "std::int16_t", "std::uint16_t", "std::int32_t", "std::uint32_t",
125 "std::int64_t", "std::uint64_t"};
126 if (std::find(std::begin(gIntegralTypeNames), std::end(gIntegralTypeNames), fieldDesc.GetTypeName()) ==
127 std::end(gIntegralTypeNames)) {
128 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
129 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
130 }
131}
132
133template <typename T>
135{
136 EnsureMatchingOnDiskField(desc, kDiffTypeName);
137
138 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
139 if (!(fieldDesc.GetTypeName() == "float" || fieldDesc.GetTypeName() == "double")) {
140 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
141 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
142 }
143}
144
145//------------------------------------------------------------------------------
146
147template class ROOT::RSimpleField<char>;
148
168
170{
171 visitor.VisitCharField(*this);
172}
173
174//------------------------------------------------------------------------------
175
176template class ROOT::RSimpleField<std::byte>;
177
179{
180 static RColumnRepresentations representations({{ENTupleColumnType::kByte}}, {});
181 return representations;
182}
183
185{
186 visitor.VisitByteField(*this);
187}
188
189//------------------------------------------------------------------------------
190
191template class ROOT::RSimpleField<int8_t>;
192
194{
195 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
210 return representations;
211}
212
214{
215 visitor.VisitInt8Field(*this);
216}
217
218//------------------------------------------------------------------------------
219
220template class ROOT::RSimpleField<uint8_t>;
221
223{
224 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
239 return representations;
240}
241
243{
244 visitor.VisitUInt8Field(*this);
245}
246
247//------------------------------------------------------------------------------
248
249template class ROOT::RSimpleField<bool>;
250
270
272{
273 visitor.VisitBoolField(*this);
274}
275
276//------------------------------------------------------------------------------
277
278template class ROOT::RSimpleField<float>;
279
290
292{
293 visitor.VisitFloatField(*this);
294}
295
296//------------------------------------------------------------------------------
297
298template class ROOT::RSimpleField<double>;
299
312
314{
315 visitor.VisitDoubleField(*this);
316}
317
319{
320 fTypeAlias = "Double32_t";
321}
322
323//------------------------------------------------------------------------------
324
325template class ROOT::RSimpleField<int16_t>;
326
328{
344 return representations;
345}
346
348{
349 visitor.VisitInt16Field(*this);
350}
351
352//------------------------------------------------------------------------------
353
354template class ROOT::RSimpleField<uint16_t>;
355
357{
373 return representations;
374}
375
377{
378 visitor.VisitUInt16Field(*this);
381//------------------------------------------------------------------------------
382
383template class ROOT::RSimpleField<int32_t>;
384
386{
402 return representations;
403}
404
406{
407 visitor.VisitInt32Field(*this);
408}
409
410//------------------------------------------------------------------------------
411
412template class ROOT::RSimpleField<uint32_t>;
413
415{
431 return representations;
432}
433
435{
436 visitor.VisitUInt32Field(*this);
437}
438
439//------------------------------------------------------------------------------
440
441template class ROOT::RSimpleField<uint64_t>;
442
444{
460 return representations;
461}
462
464{
465 visitor.VisitUInt64Field(*this);
466}
467
468//------------------------------------------------------------------------------
469
470template class ROOT::RSimpleField<int64_t>;
471
473{
489 return representations;
490}
491
493{
494 visitor.VisitInt64Field(*this);
495}
496
497//------------------------------------------------------------------------------
498
500{
505 {});
506 return representations;
507}
508
510{
512}
513
515{
517}
518
519std::size_t ROOT::RField<std::string>::AppendImpl(const void *from)
520{
521 auto typedValue = static_cast<const std::string *>(from);
522 auto length = typedValue->length();
523 fAuxiliaryColumn->AppendV(typedValue->data(), length);
524 fIndex += length;
525 fPrincipalColumn->Append(&fIndex);
526 return length + fPrincipalColumn->GetElement()->GetPackedSize();
527}
528
530{
531 auto typedValue = static_cast<std::string *>(to);
532 RNTupleLocalIndex collectionStart;
534 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
535 if (nChars == 0) {
536 typedValue->clear();
537 } else {
538 typedValue->resize(nChars);
539 fAuxiliaryColumn->ReadV(collectionStart, nChars, const_cast<char *>(typedValue->data()));
540 }
541}
542
544{
545 visitor.VisitStringField(*this);
546}
547
548//------------------------------------------------------------------------------
549
551 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
552 fMaxAlignment(source.fMaxAlignment),
554 fOffsets(source.fOffsets)
555{
556 for (const auto &f : source.GetConstSubfields())
557 Attach(f->Clone(f->GetFieldName()));
558 fTraits = source.fTraits;
559}
560
561ROOT::RRecordField::RRecordField(std::string_view fieldName, std::string_view typeName)
562 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
563{
564}
565
566void ROOT::RRecordField::AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields)
567{
568 fTraits |= kTraitTrivialType;
569 for (auto &item : itemFields) {
570 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
571 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
572 fTraits &= item->GetTraits();
573 Attach(std::move(item));
574 }
575 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
576 // requirements of the type with strictest alignment
577 fSize += GetItemPadding(fSize, fMaxAlignment);
578}
579
580std::unique_ptr<ROOT::RFieldBase>
582 std::vector<std::unique_ptr<RFieldBase>> itemFields,
583 std::string_view emulatedFromType)
584{
585 R__ASSERT(!emulatedFromType.empty());
586 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
587}
588
589std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
590 std::unique_ptr<RFieldBase> itemField,
591 std::string_view emulatedFromType)
592{
593 R__ASSERT(!emulatedFromType.empty());
594 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
595}
596
597ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
598 std::string_view emulatedFromType)
600{
602 fOffsets.reserve(itemFields.size());
603 for (auto &item : itemFields) {
604 fSize += GetItemPadding(fSize, item->GetAlignment());
605 fOffsets.push_back(fSize);
606 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
607 fSize += item->GetValueSize();
608 fTraits &= item->GetTraits();
609 Attach(std::move(item));
610 }
612 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
613 // requirements of the type with strictest alignment
615}
616
617ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
619{
620}
621
622std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
623{
624 if (itemAlignment > 1) {
625 auto remainder = baseOffset % itemAlignment;
626 if (remainder != 0)
627 return itemAlignment - remainder;
628 }
629 return 0;
630}
631
632std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
633{
634 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
635}
636
637std::size_t ROOT::RRecordField::AppendImpl(const void *from)
638{
639 std::size_t nbytes = 0;
640 for (unsigned i = 0; i < fSubfields.size(); ++i) {
641 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
642 }
643 return nbytes;
644}
645
647{
648 for (unsigned i = 0; i < fSubfields.size(); ++i) {
649 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
650 }
651}
652
654{
655 for (unsigned i = 0; i < fSubfields.size(); ++i) {
656 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
657 }
658}
659
661{
662 if (fTraits & kTraitEmulatedField) {
663 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
664 return;
665 }
666 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
667 R__ASSERT(GetTypeName().empty());
668
669 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
670
671 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
672 // and we will ignore extra on-disk fields.
673 // It remains to mark the extra in-memory fields as artificial.
674 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
675 std::unordered_set<std::string_view> onDiskSubfields;
676 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
677 onDiskSubfields.insert(subField.GetFieldName());
678 }
679 for (auto &f : fSubfields) {
680 if (onDiskSubfields.count(f->GetFieldName()) == 0)
681 CallSetArtificialOn(*f);
682 }
683}
684
686{
687 for (unsigned i = 0; i < fSubfields.size(); ++i) {
688 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
689 }
690}
691
693{
694 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
695 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
696 }
697 RDeleter::operator()(objPtr, dtorOnly);
698}
699
700std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
701{
702 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
703 itemDeleters.reserve(fOffsets.size());
704 for (const auto &f : fSubfields) {
705 itemDeleters.emplace_back(GetDeleterOf(*f));
706 }
707 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
708}
709
710std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
711{
712 auto valuePtr = value.GetPtr<void>();
713 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
714 std::vector<RValue> result;
715 result.reserve(fSubfields.size());
716 for (unsigned i = 0; i < fSubfields.size(); ++i) {
717 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
718 }
719 return result;
720}
721
723{
724 visitor.VisitRecordField(*this);
725}
726
727//------------------------------------------------------------------------------
728
729ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
730 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
731 false /* isSimple */, N),
732 fN(N)
733{
735}
736
742
747
752
753template <typename FUlong, typename FUlonglong, typename... Args>
755{
756 if (WordSize() == sizeof(unsigned long)) {
757 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
758 } else if (WordSize() == sizeof(unsigned long long)) {
759 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
760 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
761 } else {
762 R__ASSERT(false);
763 }
764}
765
766template <typename Word_t>
767static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
768{
769 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
770
771 const auto *asWordArray = static_cast<const Word_t *>(from);
772 bool elementValue;
773 std::size_t i = 0;
774 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
775 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
776 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
777 column.Append(&elementValue);
778 }
779 }
780}
781
782std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
783{
785 return fN;
786}
787
788template <typename Word_t>
789static void
791{
792 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
793
794 auto *asWordArray = static_cast<Word_t *>(to);
795 bool elementValue;
796 for (std::size_t i = 0; i < nBits; ++i) {
797 column.Read(globalIndex * nBits + i, &elementValue);
798 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
799 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
800 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
801 }
802}
803
808
809template <typename Word_t>
810static void
812{
813 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
814
815 auto *asWordArray = static_cast<Word_t *>(to);
816 bool elementValue;
817 for (std::size_t i = 0; i < nBits; ++i) {
818 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
819 &elementValue);
820 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
821 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
822 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
823 }
824}
825
830
832{
833 visitor.VisitBitsetField(*this);
834}
835
836//------------------------------------------------------------------------------
837
838ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
839 std::unique_ptr<RFieldBase> itemField)
840 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
841 false /* isSimple */)
842{
843 Attach(std::move(itemField));
844}
845
855
861
863{
864 if (!fIsEvolvedFromInnerType)
866}
867
869{
870 fPrincipalColumn->Append(&fNWritten);
871 return sizeof(ROOT::Internal::RColumnIndex);
872}
873
874std::size_t ROOT::RNullableField::AppendValue(const void *from)
875{
876 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
877 fNWritten++;
878 fPrincipalColumn->Append(&fNWritten);
880}
881
883{
884 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
885
886 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
887 if (!success) {
888 fIsEvolvedFromInnerType = true;
889 } else {
890 success = EnsureMatchingTypePrefix(desc, prefixes);
891 fIsEvolvedFromInnerType = !success;
892 }
893
894 if (fIsEvolvedFromInnerType)
895 fSubfields[0]->SetOnDiskId(GetOnDiskId());
896}
897
905
913
915{
916 visitor.VisitNullableField(*this);
917}
918
919//------------------------------------------------------------------------------
920
921ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
922 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
923{
924}
925
926std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
927{
928 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
929 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
930}
931
932std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
933{
934 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
935 if (*typedValue) {
936 return AppendValue(typedValue->get());
937 } else {
938 return AppendNull();
939 }
940}
941
943{
944 auto ptr = static_cast<std::unique_ptr<char> *>(to);
945 bool isValidValue = static_cast<bool>(*ptr);
946
947 void *valuePtr = nullptr;
948 if (isValidValue)
949 valuePtr = ptr->get();
950
952 ptr->release();
953 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
954 } else if (!isValidValue && hasOnDiskValue) {
955 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
956 ptr->reset(reinterpret_cast<char *>(valuePtr));
957 }
958
959 return valuePtr;
960}
961
963{
965 if (!fIsEvolvedFromInnerType)
966 itemIndex = GetItemIndex(globalIndex);
967 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
968 auto valuePtr = PrepareRead(to, hasOnDiskValue);
969 if (hasOnDiskValue) {
970 if (fIsEvolvedFromInnerType) {
971 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
972 } else {
973 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
974 }
975 }
976}
977
979{
981 if (!fIsEvolvedFromInnerType) {
982 itemIndex = GetItemIndex(localIndex);
983 } else {
985 }
986 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
987 auto valuePtr = PrepareRead(to, hasOnDiskValue);
988 if (hasOnDiskValue)
989 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
990}
991
993{
994 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
995 if (*typedPtr) {
996 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
997 typedPtr->release();
998 }
999 RDeleter::operator()(objPtr, dtorOnly);
1000}
1001
1002std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1003{
1004 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1005}
1006
1007std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1008{
1009 std::vector<RValue> result;
1010 auto valuePtr = value.GetPtr<void>();
1011 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1012 if (uniquePtr) {
1013 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1014 }
1015 return result;
1016}
1017
1018//------------------------------------------------------------------------------
1019
1020ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1021 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1022{
1025}
1026
1028{
1029 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1030}
1031
1033{
1034 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1035}
1036
1037std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1038{
1039 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1040 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1041}
1042
1043std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1044{
1045 if (*GetEngagementPtr(from)) {
1046 return AppendValue(from);
1047 } else {
1048 return AppendNull();
1049 }
1050}
1051
1053{
1054 auto engagementPtr = GetEngagementPtr(to);
1055 if (hasOnDiskValue) {
1056 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1057 CallConstructValueOn(*fSubfields[0], to);
1058 *engagementPtr = true;
1059 } else {
1060 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1061 fItemDeleter->operator()(to, true /* dtorOnly */);
1062 *engagementPtr = false;
1063 }
1064}
1065
1067{
1069 if (!fIsEvolvedFromInnerType)
1070 itemIndex = GetItemIndex(globalIndex);
1071 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1072 PrepareRead(to, hasOnDiskValue);
1073 if (hasOnDiskValue) {
1074 if (fIsEvolvedFromInnerType) {
1075 CallReadOn(*fSubfields[0], globalIndex, to);
1076 } else {
1077 CallReadOn(*fSubfields[0], itemIndex, to);
1078 }
1079 }
1080}
1081
1083{
1085 if (!fIsEvolvedFromInnerType) {
1086 itemIndex = GetItemIndex(localIndex);
1087 } else {
1089 }
1090 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1091 PrepareRead(to, hasOnDiskValue);
1092 if (hasOnDiskValue)
1093 CallReadOn(*fSubfields[0], itemIndex, to);
1094}
1095
1097{
1098 *GetEngagementPtr(where) = false;
1099}
1100
1102{
1103 if (fItemDeleter) {
1104 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1105 if (*engagementPtr)
1106 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1107 }
1108 RDeleter::operator()(objPtr, dtorOnly);
1109}
1110
1111std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1112{
1113 return std::make_unique<ROptionalDeleter>(
1114 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1115 fSubfields[0]->GetValueSize());
1116}
1117
1118std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1119{
1120 std::vector<RValue> result;
1121 const auto valuePtr = value.GetPtr<void>().get();
1122 if (*GetEngagementPtr(valuePtr)) {
1123 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1124 }
1125 return result;
1126}
1127
1129{
1130 const auto alignment = GetAlignment();
1131 // real size is the sum of the value size and the engagement boolean
1132 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1133 auto padding = 0;
1134 if (alignment > 1) {
1135 auto remainder = actualSize % alignment;
1136 if (remainder != 0)
1137 padding = alignment - remainder;
1138 }
1139 return actualSize + padding;
1140}
1141
1143{
1144 return fSubfields[0]->GetAlignment();
1145}
1146
1147//------------------------------------------------------------------------------
1148
1149ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1150 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1151 false /* isSimple */)
1152{
1153 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1155 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1157 Attach(std::move(itemField));
1158}
1159
1160std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1161{
1162 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1163 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1164}
1165
1167{
1168 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1169 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1170 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1171 } else {
1172 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1173 }
1174}
1175
1176std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1177{
1178 std::vector<RValue> result;
1179 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1180 return result;
1181}
1182
1184{
1185 visitor.VisitAtomicField(*this);
1186}
dim_t fSize
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:300
static void BitsetReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:790
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:811
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:767
#define f(i)
Definition RSha256.hxx:104
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
TCanvas * alignment()
Definition alignment.C:1
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:38
void Read(const ROOT::NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:160
void Append(const void *from)
Definition RColumn.hxx:126
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1183
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1149
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1160
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:1166
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:1176
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:729
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:826
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:743
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:804
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:782
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:737
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:831
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:754
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:95
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:63
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
Definition RField.cxx:100
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:78
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
Definition RField.cxx:105
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.hxx:361
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
The list of column representations a field can have.
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
void Attach(std::unique_ptr< RFieldBase > child)
Add a new subfield to the list of nested fields.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
std::uint32_t fTraits
Properties of the type that allow for optimizations of collections of that type.
std::uint32_t GetTraits() const
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTrivialType
Shorthand for types that are both trivially constructible and destructible.
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
Metadata stored for every field of an RNTuple.
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:59
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:56
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:39
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Definition RField.cxx:47
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:313
The on-storage metadata of an RNTuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) const
ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) const
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Template specializations for C++ std::optional and std::unique_ptr.
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
Definition RField.cxx:882
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:898
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:838
std::size_t AppendNull()
Definition RField.cxx:868
std::size_t AppendValue(const void *from)
Definition RField.cxx:874
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:856
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:914
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:846
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1101
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:1096
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1142
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1111
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1037
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:1032
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1066
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1043
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1082
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:1118
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1128
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1052
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1020
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:692
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:710
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:632
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:653
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:550
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:722
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:700
void AttachItemFields(std::vector< std::unique_ptr< RFieldBase > > itemFields)
Definition RField.cxx:566
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:622
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:646
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:685
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:637
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:660
void ReconcileIntegralField(const RNTupleDescriptor &desc)
Definition RField.cxx:113
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
Definition RField.cxx:134
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:992
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:1007
void * PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:942
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1002
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:962
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:926
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:921
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:932
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:978
Template specializations for C++ std::vector.
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
Definition RField.cxx:34
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
Definition RField.cxx:589
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:581
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 ...
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...