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());
120 if (fieldDesc.IsCustomEnum(desc)) {
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}
383//------------------------------------------------------------------------------
384
385template class ROOT::RSimpleField<int32_t>;
386
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 Attach(std::move(itemField));
846}
847
857
863
865{
866 if (!fIsEvolvedFromInnerType)
868}
869
871{
872 fPrincipalColumn->Append(&fNWritten);
873 return sizeof(ROOT::Internal::RColumnIndex);
874}
875
876std::size_t ROOT::RNullableField::AppendValue(const void *from)
877{
878 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
879 fNWritten++;
880 fPrincipalColumn->Append(&fNWritten);
882}
883
885{
886 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
887
888 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
889 if (!success) {
890 fIsEvolvedFromInnerType = true;
891 } else {
892 success = EnsureMatchingTypePrefix(desc, prefixes);
893 fIsEvolvedFromInnerType = !success;
894 }
895
896 if (fIsEvolvedFromInnerType)
897 fSubfields[0]->SetOnDiskId(GetOnDiskId());
898}
899
907
915
917{
918 visitor.VisitNullableField(*this);
919}
920
921//------------------------------------------------------------------------------
922
923namespace {
924// Dummy class to determine the dynamic type of any polymorphic user object.
925struct PolymorphicClass {
926 virtual ~PolymorphicClass() = default;
927};
928} // namespace
929
930ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
931 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
932{
933 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
934 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
935 }
936}
937
938std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
939{
940 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
941 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
942}
943
944std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
945{
946 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
947 if (*typedValue) {
948 const void *obj = typedValue->get();
949 if (fPolymorphicTypeInfo != nullptr) {
950 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
951 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
952 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
953 if (t != *fPolymorphicTypeInfo) {
954 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
955 int err = 0;
957 if (!err) {
958 msg = msg + " but was passed " + demangled;
960 }
961 msg += " and upcasting of polymorphic types is not supported in RNTuple";
962 throw RException(R__FAIL(msg));
963 }
964 }
965 return AppendValue(obj);
966 } else {
967 return AppendNull();
968 }
969}
970
972{
973 auto ptr = static_cast<std::unique_ptr<char> *>(to);
974 bool isValidValue = static_cast<bool>(*ptr);
975
976 void *valuePtr = nullptr;
977 if (isValidValue)
978 valuePtr = ptr->get();
979
981 ptr->release();
982 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
983 } else if (!isValidValue && hasOnDiskValue) {
984 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
985 ptr->reset(reinterpret_cast<char *>(valuePtr));
986 }
987
988 return valuePtr;
989}
990
992{
994 if (!fIsEvolvedFromInnerType)
995 itemIndex = GetItemIndex(globalIndex);
996 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
997 auto valuePtr = PrepareRead(to, hasOnDiskValue);
998 if (hasOnDiskValue) {
999 if (fIsEvolvedFromInnerType) {
1000 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1001 } else {
1002 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1003 }
1004 }
1005}
1006
1008{
1010 if (!fIsEvolvedFromInnerType) {
1011 itemIndex = GetItemIndex(localIndex);
1012 } else {
1014 }
1015 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1016 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1017 if (hasOnDiskValue)
1018 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1019}
1020
1022{
1023 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1024 if (*typedPtr) {
1025 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1026 typedPtr->release();
1027 }
1028 RDeleter::operator()(objPtr, dtorOnly);
1029}
1030
1031std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1032{
1033 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1034}
1035
1036std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1037{
1038 std::vector<RValue> result;
1039 auto valuePtr = value.GetPtr<void>();
1040 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1041 if (uniquePtr) {
1042 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1043 }
1044 return result;
1045}
1046
1047//------------------------------------------------------------------------------
1048
1049ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1050 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1051{
1054}
1055
1057{
1058 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1059}
1060
1062{
1063 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1064}
1065
1066std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1067{
1068 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1069 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1070}
1071
1072std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1073{
1074 if (*GetEngagementPtr(from)) {
1075 return AppendValue(from);
1076 } else {
1077 return AppendNull();
1078 }
1079}
1080
1082{
1083 auto engagementPtr = GetEngagementPtr(to);
1084 if (hasOnDiskValue) {
1085 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1086 CallConstructValueOn(*fSubfields[0], to);
1087 *engagementPtr = true;
1088 } else {
1089 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1090 fItemDeleter->operator()(to, true /* dtorOnly */);
1091 *engagementPtr = false;
1092 }
1093}
1094
1096{
1098 if (!fIsEvolvedFromInnerType)
1099 itemIndex = GetItemIndex(globalIndex);
1100 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1101 PrepareRead(to, hasOnDiskValue);
1102 if (hasOnDiskValue) {
1103 if (fIsEvolvedFromInnerType) {
1104 CallReadOn(*fSubfields[0], globalIndex, to);
1105 } else {
1106 CallReadOn(*fSubfields[0], itemIndex, to);
1107 }
1108 }
1109}
1110
1112{
1114 if (!fIsEvolvedFromInnerType) {
1115 itemIndex = GetItemIndex(localIndex);
1116 } else {
1118 }
1119 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1120 PrepareRead(to, hasOnDiskValue);
1121 if (hasOnDiskValue)
1122 CallReadOn(*fSubfields[0], itemIndex, to);
1123}
1124
1126{
1127 *GetEngagementPtr(where) = false;
1128}
1129
1131{
1132 if (fItemDeleter) {
1133 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1134 if (*engagementPtr)
1135 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1136 }
1137 RDeleter::operator()(objPtr, dtorOnly);
1138}
1139
1140std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1141{
1142 return std::make_unique<ROptionalDeleter>(
1143 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1144 fSubfields[0]->GetValueSize());
1145}
1146
1147std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1148{
1149 std::vector<RValue> result;
1150 const auto valuePtr = value.GetPtr<void>().get();
1151 if (*GetEngagementPtr(valuePtr)) {
1152 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1153 }
1154 return result;
1155}
1156
1158{
1159 const auto alignment = GetAlignment();
1160 // real size is the sum of the value size and the engagement boolean
1161 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1162 auto padding = 0;
1163 if (alignment > 1) {
1164 auto remainder = actualSize % alignment;
1165 if (remainder != 0)
1166 padding = alignment - remainder;
1167 }
1168 return actualSize + padding;
1169}
1170
1172{
1173 return fSubfields[0]->GetAlignment();
1174}
1175
1176//------------------------------------------------------------------------------
1177
1178ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1179 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1180 false /* isSimple */)
1181{
1182 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1184 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1186 Attach(std::move(itemField));
1187}
1188
1189std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1190{
1191 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1192 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1193}
1194
1196{
1197 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1198 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1199 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1200 } else {
1201 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1202 }
1203}
1204
1205std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1206{
1207 std::vector<RValue> result;
1208 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1209 return result;
1210}
1211
1213{
1214 visitor.VisitAtomicField(*this);
1215}
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:1212
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1178
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1189
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:1195
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:1205
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:364
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::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:316
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:884
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:900
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:870
std::size_t AppendValue(const void *from)
Definition RField.cxx:876
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:858
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:916
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:848
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1130
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:1125
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1171
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1140
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1066
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:1061
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1095
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1072
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1111
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:1147
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1157
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1081
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1049
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:1021
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:1036
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:971
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1031
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:991
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:938
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:930
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:944
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1007
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 ...
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.