Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RField.cxx
Go to the documentation of this file.
1/// \file RField.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include <ROOT/RColumn.hxx>
15#include <ROOT/REntry.hxx>
16#include <ROOT/RError.hxx>
17#include <ROOT/RField.hxx>
19#include <ROOT/RLogger.hxx>
20#include <ROOT/RNTupleModel.hxx>
22#include <ROOT/RNTupleTypes.hxx>
23#include <TClassEdit.h>
24
25#include <algorithm>
26#include <cstdint>
27#include <cstdlib>
28#include <exception>
29#include <functional>
30#include <iostream>
31#include <memory>
32#include <string_view>
33#include <type_traits>
34#include <unordered_set>
35
37{
38 fieldZero.fAllowFieldSubstitutions = val;
39}
40
41std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldZero::CloneImpl(std::string_view /*newName*/) const
42{
43 auto result = std::make_unique<RFieldZero>();
44 for (auto &f : fSubfields)
45 result->Attach(f->Clone(f->GetFieldName()));
46 return result;
47}
48
49std::vector<std::unique_ptr<ROOT::RFieldBase>> ROOT::RFieldZero::ReleaseSubfields()
50{
51 std::vector<std::unique_ptr<ROOT::RFieldBase>> result;
52 std::swap(fSubfields, result);
53 for (auto &f : result)
54 f->fParent = nullptr;
55 return result;
56}
57
59{
60 visitor.VisitFieldZero(*this);
61}
62
63//------------------------------------------------------------------------------
64
74
79
81{
82 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError();
83
84 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
85 if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) {
86 if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) {
87 throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() +
88 " expects an on-disk leaf field of the same type\n" +
89 Internal::GetTypeTraceReport(*this, desc)));
90 }
91 } else if (fieldDesc.GetStructure() != ENTupleStructure::kCollection) {
92 throw RException(R__FAIL("invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName() +
93 "\n" + Internal::GetTypeTraceReport(*this, desc)));
94 }
95}
96
98{
99 visitor.VisitCardinalityField(*this);
100}
101
106
111
112//------------------------------------------------------------------------------
113
114template <typename T>
116{
117 EnsureMatchingOnDiskField(desc, kDiffTypeName);
118
119 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
121 SetOnDiskId(desc.FindFieldId("_0", GetOnDiskId()));
122 return;
123 }
124
125 static const std::string gIntegralTypeNames[] = {"bool", "char", "std::int8_t", "std::uint8_t",
126 "std::int16_t", "std::uint16_t", "std::int32_t", "std::uint32_t",
127 "std::int64_t", "std::uint64_t"};
128 if (std::find(std::begin(gIntegralTypeNames), std::end(gIntegralTypeNames), fieldDesc.GetTypeName()) ==
129 std::end(gIntegralTypeNames)) {
130 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
131 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
132 }
133}
134
135template <typename T>
137{
138 EnsureMatchingOnDiskField(desc, kDiffTypeName);
139
140 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
141 if (!(fieldDesc.GetTypeName() == "float" || fieldDesc.GetTypeName() == "double")) {
142 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
143 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
144 }
145}
146
147//------------------------------------------------------------------------------
148
149template class ROOT::RSimpleField<char>;
150
170
172{
173 visitor.VisitCharField(*this);
174}
175
176//------------------------------------------------------------------------------
177
178template class ROOT::RSimpleField<std::byte>;
179
181{
182 static RColumnRepresentations representations({{ENTupleColumnType::kByte}}, {});
183 return representations;
184}
185
187{
188 visitor.VisitByteField(*this);
189}
190
191//------------------------------------------------------------------------------
192
193template class ROOT::RSimpleField<int8_t>;
194
196{
197 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
212 return representations;
213}
214
216{
217 visitor.VisitInt8Field(*this);
218}
219
220//------------------------------------------------------------------------------
221
222template class ROOT::RSimpleField<uint8_t>;
223
225{
226 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
241 return representations;
242}
243
245{
246 visitor.VisitUInt8Field(*this);
247}
248
249//------------------------------------------------------------------------------
250
251template class ROOT::RSimpleField<bool>;
252
272
274{
275 visitor.VisitBoolField(*this);
276}
277
278//------------------------------------------------------------------------------
279
280template class ROOT::RSimpleField<float>;
281
292
294{
295 visitor.VisitFloatField(*this);
296}
297
298//------------------------------------------------------------------------------
299
300template class ROOT::RSimpleField<double>;
301
314
316{
317 visitor.VisitDoubleField(*this);
318}
319
321{
322 fTypeAlias = "Double32_t";
323}
324
325//------------------------------------------------------------------------------
326
327template class ROOT::RSimpleField<int16_t>;
328
330{
346 return representations;
347}
348
350{
351 visitor.VisitInt16Field(*this);
352}
353
354//------------------------------------------------------------------------------
355
356template class ROOT::RSimpleField<uint16_t>;
357
359{
375 return representations;
376}
377
379{
380 visitor.VisitUInt16Field(*this);
381}
382
383//------------------------------------------------------------------------------
384
388{
404 return representations;
405}
406
408{
409 visitor.VisitInt32Field(*this);
410}
411
412//------------------------------------------------------------------------------
413
414template class ROOT::RSimpleField<uint32_t>;
415
417{
433 return representations;
434}
435
437{
438 visitor.VisitUInt32Field(*this);
439}
440
441//------------------------------------------------------------------------------
442
443template class ROOT::RSimpleField<uint64_t>;
444
446{
462 return representations;
463}
464
466{
467 visitor.VisitUInt64Field(*this);
468}
469
470//------------------------------------------------------------------------------
471
472template class ROOT::RSimpleField<int64_t>;
473
475{
491 return representations;
492}
493
495{
496 visitor.VisitInt64Field(*this);
497}
498
499//------------------------------------------------------------------------------
500
502{
507 {});
508 return representations;
509}
510
512{
514}
515
517{
519}
520
521std::size_t ROOT::RField<std::string>::AppendImpl(const void *from)
522{
523 auto typedValue = static_cast<const std::string *>(from);
524 auto length = typedValue->length();
525 fAuxiliaryColumn->AppendV(typedValue->data(), length);
526 fIndex += length;
527 fPrincipalColumn->Append(&fIndex);
528 return length + fPrincipalColumn->GetElement()->GetPackedSize();
529}
530
532{
533 auto typedValue = static_cast<std::string *>(to);
534 RNTupleLocalIndex collectionStart;
536 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
537 if (nChars == 0) {
538 typedValue->clear();
539 } else {
540 typedValue->resize(nChars);
541 fAuxiliaryColumn->ReadV(collectionStart, nChars, const_cast<char *>(typedValue->data()));
542 }
543}
544
546{
547 visitor.VisitStringField(*this);
548}
549
550//------------------------------------------------------------------------------
551
553 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
554 fMaxAlignment(source.fMaxAlignment),
556 fOffsets(source.fOffsets)
557{
558 for (const auto &f : source.GetConstSubfields())
559 Attach(f->Clone(f->GetFieldName()));
560 fTraits = source.fTraits;
561}
562
563ROOT::RRecordField::RRecordField(std::string_view fieldName, std::string_view typeName)
564 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
565{
566}
567
568void ROOT::RRecordField::AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields)
569{
570 fTraits |= kTraitTrivialType;
571 for (auto &item : itemFields) {
572 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
573 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
574 fTraits &= item->GetTraits();
575 Attach(std::move(item));
576 }
577 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
578 // requirements of the type with strictest alignment
579 fSize += GetItemPadding(fSize, fMaxAlignment);
580}
581
582std::unique_ptr<ROOT::RFieldBase>
584 std::vector<std::unique_ptr<RFieldBase>> itemFields,
585 std::string_view emulatedFromType)
586{
587 R__ASSERT(!emulatedFromType.empty());
588 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
589}
590
591std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
592 std::unique_ptr<RFieldBase> itemField,
593 std::string_view emulatedFromType)
594{
595 R__ASSERT(!emulatedFromType.empty());
596 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
597}
598
599ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
600 std::string_view emulatedFromType)
602{
604 fOffsets.reserve(itemFields.size());
605 for (auto &item : itemFields) {
606 fSize += GetItemPadding(fSize, item->GetAlignment());
607 fOffsets.push_back(fSize);
608 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
609 fSize += item->GetValueSize();
610 fTraits &= item->GetTraits();
611 Attach(std::move(item));
612 }
614 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
615 // requirements of the type with strictest alignment
617}
618
619ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
621{
622}
623
624std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
625{
626 if (itemAlignment > 1) {
627 auto remainder = baseOffset % itemAlignment;
628 if (remainder != 0)
629 return itemAlignment - remainder;
630 }
631 return 0;
632}
633
634std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
635{
636 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
637}
638
639std::size_t ROOT::RRecordField::AppendImpl(const void *from)
640{
641 std::size_t nbytes = 0;
642 for (unsigned i = 0; i < fSubfields.size(); ++i) {
643 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
644 }
645 return nbytes;
646}
647
649{
650 for (unsigned i = 0; i < fSubfields.size(); ++i) {
651 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
652 }
653}
654
656{
657 for (unsigned i = 0; i < fSubfields.size(); ++i) {
658 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
659 }
660}
661
663{
664 if (fTraits & kTraitEmulatedField) {
665 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
666 return;
667 }
668 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
669 R__ASSERT(GetTypeName().empty());
670
671 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
672
673 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
674 // and we will ignore extra on-disk fields.
675 // It remains to mark the extra in-memory fields as artificial.
676 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
677 std::unordered_set<std::string_view> onDiskSubfields;
678 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
679 onDiskSubfields.insert(subField.GetFieldName());
680 }
681 for (auto &f : fSubfields) {
682 if (onDiskSubfields.count(f->GetFieldName()) == 0)
683 CallSetArtificialOn(*f);
684 }
685}
686
688{
689 for (unsigned i = 0; i < fSubfields.size(); ++i) {
690 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
691 }
692}
693
695{
696 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
697 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
698 }
699 RDeleter::operator()(objPtr, dtorOnly);
700}
701
702std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
703{
704 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
705 itemDeleters.reserve(fOffsets.size());
706 for (const auto &f : fSubfields) {
707 itemDeleters.emplace_back(GetDeleterOf(*f));
708 }
709 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
710}
711
712std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
713{
714 auto valuePtr = value.GetPtr<void>();
715 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
716 std::vector<RValue> result;
717 result.reserve(fSubfields.size());
718 for (unsigned i = 0; i < fSubfields.size(); ++i) {
719 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
720 }
721 return result;
722}
723
725{
726 visitor.VisitRecordField(*this);
727}
728
729//------------------------------------------------------------------------------
730
731ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
732 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
733 false /* isSimple */, N),
734 fN(N)
735{
737}
738
744
749
754
755template <typename FUlong, typename FUlonglong, typename... Args>
757{
758 if (WordSize() == sizeof(unsigned long)) {
759 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
760 } else if (WordSize() == sizeof(unsigned long long)) {
761 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
762 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
763 } else {
764 R__ASSERT(false);
765 }
766}
767
768template <typename Word_t>
769static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
770{
771 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
772
773 const auto *asWordArray = static_cast<const Word_t *>(from);
774 bool elementValue;
775 std::size_t i = 0;
776 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
777 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
778 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
779 column.Append(&elementValue);
780 }
781 }
782}
783
784std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
785{
787 return fN;
788}
789
790template <typename Word_t>
791static void
793{
794 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
795
796 auto *asWordArray = static_cast<Word_t *>(to);
797 bool elementValue;
798 for (std::size_t i = 0; i < nBits; ++i) {
799 column.Read(globalIndex * nBits + i, &elementValue);
800 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
801 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
802 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
803 }
804}
805
810
811template <typename Word_t>
812static void
814{
815 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
816
817 auto *asWordArray = static_cast<Word_t *>(to);
818 bool elementValue;
819 for (std::size_t i = 0; i < nBits; ++i) {
820 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
821 &elementValue);
822 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
823 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
824 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
825 }
826}
827
832
834{
835 visitor.VisitBitsetField(*this);
836}
837
838//------------------------------------------------------------------------------
839
840ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
841 std::unique_ptr<RFieldBase> itemField)
842 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
843 false /* isSimple */)
844{
845 if (!itemField->GetTypeAlias().empty())
846 fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
847
848 Attach(std::move(itemField));
849}
850
860
866
868{
869 if (!fIsEvolvedFromInnerType)
871}
872
874{
875 fPrincipalColumn->Append(&fNWritten);
876 return sizeof(ROOT::Internal::RColumnIndex);
877}
878
879std::size_t ROOT::RNullableField::AppendValue(const void *from)
880{
881 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
882 fNWritten++;
883 fPrincipalColumn->Append(&fNWritten);
885}
886
888{
889 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
890
891 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
892 if (!success) {
893 fIsEvolvedFromInnerType = true;
894 } else {
895 success = EnsureMatchingTypePrefix(desc, prefixes);
896 fIsEvolvedFromInnerType = !success;
897 }
898
899 if (fIsEvolvedFromInnerType)
900 fSubfields[0]->SetOnDiskId(GetOnDiskId());
901}
902
910
918
920{
921 visitor.VisitNullableField(*this);
922}
923
924//------------------------------------------------------------------------------
925
926namespace {
927// Dummy class to determine the dynamic type of any polymorphic user object.
928struct PolymorphicClass {
929 virtual ~PolymorphicClass() = default;
930};
931} // namespace
932
933ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
934 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
935{
936 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
937 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
938 }
939}
940
941std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
942{
943 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
944 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
945}
946
947std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
948{
949 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
950 if (*typedValue) {
951 const void *obj = typedValue->get();
952 if (fPolymorphicTypeInfo != nullptr) {
953 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
954 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
955 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
956 if (t != *fPolymorphicTypeInfo) {
957 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
958 int err = 0;
960 if (!err) {
961 msg = msg + " but was passed " + demangled;
963 }
964 msg += " and upcasting of polymorphic types is not supported in RNTuple";
965 throw RException(R__FAIL(msg));
966 }
967 }
968 return AppendValue(obj);
969 } else {
970 return AppendNull();
971 }
972}
973
975{
976 auto ptr = static_cast<std::unique_ptr<char> *>(to);
977 bool isValidValue = static_cast<bool>(*ptr);
978
979 void *valuePtr = nullptr;
980 if (isValidValue)
981 valuePtr = ptr->get();
982
984 ptr->release();
985 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
986 } else if (!isValidValue && hasOnDiskValue) {
987 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
988 ptr->reset(reinterpret_cast<char *>(valuePtr));
989 }
990
991 return valuePtr;
992}
993
995{
997 if (!fIsEvolvedFromInnerType)
998 itemIndex = GetItemIndex(globalIndex);
999 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1000 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1001 if (hasOnDiskValue) {
1002 if (fIsEvolvedFromInnerType) {
1003 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1004 } else {
1005 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1006 }
1007 }
1008}
1009
1011{
1013 if (!fIsEvolvedFromInnerType) {
1014 itemIndex = GetItemIndex(localIndex);
1015 } else {
1017 }
1018 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1019 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1020 if (hasOnDiskValue)
1021 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1022}
1023
1025{
1026 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1027 if (*typedPtr) {
1028 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1029 typedPtr->release();
1030 }
1031 RDeleter::operator()(objPtr, dtorOnly);
1032}
1033
1034std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1035{
1036 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1037}
1038
1039std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1040{
1041 std::vector<RValue> result;
1042 auto valuePtr = value.GetPtr<void>();
1043 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1044 if (uniquePtr) {
1045 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1046 }
1047 return result;
1048}
1049
1050//------------------------------------------------------------------------------
1051
1052ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1053 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1054{
1057}
1058
1060{
1061 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1062}
1063
1065{
1066 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1067}
1068
1069std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1070{
1071 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1072 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1073}
1074
1075std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1076{
1077 if (*GetEngagementPtr(from)) {
1078 return AppendValue(from);
1079 } else {
1080 return AppendNull();
1081 }
1082}
1083
1085{
1086 auto engagementPtr = GetEngagementPtr(to);
1087 if (hasOnDiskValue) {
1088 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1089 CallConstructValueOn(*fSubfields[0], to);
1090 *engagementPtr = true;
1091 } else {
1092 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1093 fItemDeleter->operator()(to, true /* dtorOnly */);
1094 *engagementPtr = false;
1095 }
1096}
1097
1099{
1101 if (!fIsEvolvedFromInnerType)
1102 itemIndex = GetItemIndex(globalIndex);
1103 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1104 PrepareRead(to, hasOnDiskValue);
1105 if (hasOnDiskValue) {
1106 if (fIsEvolvedFromInnerType) {
1107 CallReadOn(*fSubfields[0], globalIndex, to);
1108 } else {
1109 CallReadOn(*fSubfields[0], itemIndex, to);
1110 }
1111 }
1112}
1113
1115{
1117 if (!fIsEvolvedFromInnerType) {
1118 itemIndex = GetItemIndex(localIndex);
1119 } else {
1121 }
1122 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1123 PrepareRead(to, hasOnDiskValue);
1124 if (hasOnDiskValue)
1125 CallReadOn(*fSubfields[0], itemIndex, to);
1126}
1127
1129{
1130 *GetEngagementPtr(where) = false;
1131}
1132
1134{
1135 if (fItemDeleter) {
1136 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1137 if (*engagementPtr)
1138 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1139 }
1140 RDeleter::operator()(objPtr, dtorOnly);
1141}
1142
1143std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1144{
1145 return std::make_unique<ROptionalDeleter>(
1146 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1147 fSubfields[0]->GetValueSize());
1148}
1149
1150std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1151{
1152 std::vector<RValue> result;
1153 const auto valuePtr = value.GetPtr<void>().get();
1154 if (*GetEngagementPtr(valuePtr)) {
1155 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1156 }
1157 return result;
1158}
1159
1161{
1162 const auto alignment = GetAlignment();
1163 // real size is the sum of the value size and the engagement boolean
1164 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1165 auto padding = 0;
1166 if (alignment > 1) {
1167 auto remainder = actualSize % alignment;
1168 if (remainder != 0)
1169 padding = alignment - remainder;
1170 }
1171 return actualSize + padding;
1172}
1173
1175{
1176 return fSubfields[0]->GetAlignment();
1177}
1178
1179//------------------------------------------------------------------------------
1180
1181ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1182 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1183 false /* isSimple */)
1184{
1185 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1187 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1189
1190 if (!itemField->GetTypeAlias().empty())
1191 fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1192
1193 Attach(std::move(itemField));
1194}
1195
1196std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1197{
1198 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1199 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1200}
1201
1203{
1204 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1205 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1206 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1207 } else {
1208 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1209 }
1210}
1211
1212std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1213{
1214 std::vector<RValue> result;
1215 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1216 return result;
1217}
1218
1220{
1221 visitor.VisitAtomicField(*this);
1222}
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:792
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:813
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:769
#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
#define free
Definition civetweb.c:1578
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
A column is a storage-backed array of a simple, fixed-size type, from which pages can be mapped into ...
Definition RColumn.hxx:38
void Read(const ROOT::NTupleSize_t globalIndex, void *to)
Definition RColumn.hxx:160
void Append(const void *from)
Definition RColumn.hxx:126
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1219
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1181
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1196
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:1202
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:1212
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:731
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:828
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:745
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:806
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:784
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:739
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:833
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:756
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:97
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:65
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
Definition RField.cxx:102
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:80
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
Definition RField.cxx:107
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.hxx:367
The field for a class with dictionary.
Definition RField.hxx:134
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::string fTypeAlias
A typedef or using name that was used when creating the field.
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:58
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:41
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Definition RField.cxx:49
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:319
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:887
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:903
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:840
std::size_t AppendNull()
Definition RField.cxx:873
std::size_t AppendValue(const void *from)
Definition RField.cxx:879
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:861
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:919
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:851
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1133
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:1128
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1174
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1143
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1069
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:1064
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1098
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1075
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1114
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:1150
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1160
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1084
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1052
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:694
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:712
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:634
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:655
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:552
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:724
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:702
void AttachItemFields(std::vector< std::unique_ptr< RFieldBase > > itemFields)
Definition RField.cxx:568
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:624
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:648
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:687
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:639
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:662
void ReconcileIntegralField(const RNTupleDescriptor &desc)
Definition RField.cxx:115
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
Definition RField.cxx:136
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1024
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:1039
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:974
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1034
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:994
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:941
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:933
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:947
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1010
Template specializations for C++ std::vector.
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
Definition RField.cxx:36
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
Definition RField.cxx:591
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:583
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 ...
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.