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
41void ROOT::RFieldZero::Attach(std::unique_ptr<RFieldBase> child)
42{
43 const std::string childName = child->GetFieldName();
44 if (fSubfieldNames.count(childName) > 0)
45 throw RException(R__FAIL("duplicate field name: " + childName));
46 RFieldBase::Attach(std::move(child), "");
48}
49
54
55std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldZero::CloneImpl(std::string_view /*newName*/) const
56{
57 auto result = std::make_unique<RFieldZero>();
58 for (auto &f : fSubfields) {
59 result->Attach(f->Clone(f->GetFieldName()));
60 result->fSubfieldNames.insert(f->GetFieldName());
61 }
62 return result;
63}
64
65std::vector<std::unique_ptr<ROOT::RFieldBase>> ROOT::RFieldZero::ReleaseSubfields()
66{
67 std::vector<std::unique_ptr<ROOT::RFieldBase>> result;
68 std::swap(fSubfields, result);
69 for (auto &f : result)
70 f->fParent = nullptr;
71 return result;
72}
73
75{
76 visitor.VisitFieldZero(*this);
77}
78
79//------------------------------------------------------------------------------
80
90
95
97{
98 EnsureMatchingOnDiskField(desc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError();
99
100 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
101 if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) {
102 if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) {
103 throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() +
104 " expects an on-disk leaf field of the same type\n" +
105 Internal::GetTypeTraceReport(*this, desc)));
106 }
107 } else if (fieldDesc.GetStructure() == ENTupleStructure::kCollection) {
108 if (!fieldDesc.IsSoACollection() && fieldDesc.GetTypeVersion() != 0) {
109 throw RException(R__FAIL("invalid on-disk type version for RCardinalityField " + GetQualifiedFieldName() +
110 "\n" + Internal::GetTypeTraceReport(*this, desc)));
111 }
112 } else {
113 throw RException(R__FAIL("invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName() +
114 "\n" + Internal::GetTypeTraceReport(*this, desc)));
115 }
116}
117
119{
120 visitor.VisitCardinalityField(*this);
121}
122
127
132
133//------------------------------------------------------------------------------
134
135template <typename T>
137{
138 EnsureMatchingOnDiskField(desc, kDiffTypeName);
139
140 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
142 SetOnDiskId(desc.FindFieldId("_0", GetOnDiskId()));
143 return;
144 }
145
146 static const std::string gIntegralTypeNames[] = {"bool", "char", "std::int8_t", "std::uint8_t",
147 "std::int16_t", "std::uint16_t", "std::int32_t", "std::uint32_t",
148 "std::int64_t", "std::uint64_t"};
149 if (std::find(std::begin(gIntegralTypeNames), std::end(gIntegralTypeNames), fieldDesc.GetTypeName()) ==
150 std::end(gIntegralTypeNames)) {
151 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
152 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
153 }
154}
155
156template <typename T>
158{
159 EnsureMatchingOnDiskField(desc, kDiffTypeName);
160
161 const RFieldDescriptor &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
162 if (!(fieldDesc.GetTypeName() == "float" || fieldDesc.GetTypeName() == "double")) {
163 throw RException(R__FAIL("unexpected on-disk type name '" + fieldDesc.GetTypeName() + "' for field of type '" +
164 GetTypeName() + "'\n" + Internal::GetTypeTraceReport(*this, desc)));
165 }
166}
167
168//------------------------------------------------------------------------------
169
170template class ROOT::RSimpleField<char>;
171
191
193{
194 visitor.VisitCharField(*this);
195}
196
197//------------------------------------------------------------------------------
198
199template class ROOT::RSimpleField<std::byte>;
200
202{
203 static RColumnRepresentations representations({{ENTupleColumnType::kByte}}, {});
204 return representations;
205}
206
208{
209 visitor.VisitByteField(*this);
210}
211
212//------------------------------------------------------------------------------
213
214template class ROOT::RSimpleField<int8_t>;
215
217{
218 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
233 return representations;
234}
235
237{
238 visitor.VisitInt8Field(*this);
239}
240
241//------------------------------------------------------------------------------
242
243template class ROOT::RSimpleField<uint8_t>;
244
246{
247 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
262 return representations;
263}
264
266{
267 visitor.VisitUInt8Field(*this);
268}
269
270//------------------------------------------------------------------------------
271
272template class ROOT::RSimpleField<bool>;
273
293
295{
296 visitor.VisitBoolField(*this);
297}
298
299//------------------------------------------------------------------------------
300
301template class ROOT::RSimpleField<float>;
302
313
315{
316 visitor.VisitFloatField(*this);
317}
318
319//------------------------------------------------------------------------------
320
321template class ROOT::RSimpleField<double>;
322
335
337{
338 visitor.VisitDoubleField(*this);
339}
340
342{
343 fTypeAlias = "Double32_t";
344}
345
346//------------------------------------------------------------------------------
347
348template class ROOT::RSimpleField<int16_t>;
349
351{
367 return representations;
368}
369
371{
372 visitor.VisitInt16Field(*this);
373}
374
375//------------------------------------------------------------------------------
376
377template class ROOT::RSimpleField<uint16_t>;
378
380{
396 return representations;
397}
398
400{
401 visitor.VisitUInt16Field(*this);
402}
403
404//------------------------------------------------------------------------------
405
406template class ROOT::RSimpleField<int32_t>;
407
409{
425 return representations;
426}
427
429{
430 visitor.VisitInt32Field(*this);
431}
432
433//------------------------------------------------------------------------------
434
435template class ROOT::RSimpleField<uint32_t>;
436
438{
454 return representations;
455}
456
458{
459 visitor.VisitUInt32Field(*this);
460}
461
462//------------------------------------------------------------------------------
463
464template class ROOT::RSimpleField<uint64_t>;
465
467{
483 return representations;
484}
485
487{
488 visitor.VisitUInt64Field(*this);
489}
490
491//------------------------------------------------------------------------------
492
493template class ROOT::RSimpleField<int64_t>;
494
496{
512 return representations;
513}
514
516{
517 visitor.VisitInt64Field(*this);
518}
519
520//------------------------------------------------------------------------------
521
523{
528 {});
529 return representations;
530}
531
533{
535}
536
538{
540}
541
542std::size_t ROOT::RField<std::string>::AppendImpl(const void *from)
543{
544 auto typedValue = static_cast<const std::string *>(from);
545 auto length = typedValue->length();
546 fAuxiliaryColumn->AppendV(typedValue->data(), length);
547 fIndex += length;
548 fPrincipalColumn->Append(&fIndex);
549 return length + fPrincipalColumn->GetElement()->GetPackedSize();
550}
551
553{
554 auto typedValue = static_cast<std::string *>(to);
555 RNTupleLocalIndex collectionStart;
557 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
558 if (nChars == 0) {
559 typedValue->clear();
560 } else {
561 typedValue->resize(nChars);
562 fAuxiliaryColumn->ReadV(collectionStart, nChars, const_cast<char *>(typedValue->data()));
563 }
564}
565
567{
568 visitor.VisitStringField(*this);
569}
570
571//------------------------------------------------------------------------------
572
574 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
575 fMaxAlignment(source.fMaxAlignment),
577 fOffsets(source.fOffsets)
578{
579 for (const auto &f : source.GetConstSubfields())
580 Attach(f->Clone(f->GetFieldName()));
581 fSubfieldNames = source.fSubfieldNames;
582 fTraits = source.fTraits;
583}
584
585ROOT::RRecordField::RRecordField(std::string_view fieldName, std::string_view typeName)
586 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
587{
588}
589
590std::unique_ptr<ROOT::RFieldBase>
592 std::vector<std::unique_ptr<RFieldBase>> itemFields,
593 std::string_view emulatedFromType)
594{
595 R__ASSERT(!emulatedFromType.empty());
596 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
597}
598
599std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
600 std::unique_ptr<RFieldBase> itemField,
601 std::string_view emulatedFromType)
602{
603 R__ASSERT(!emulatedFromType.empty());
604 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
605}
606
607ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
608 std::string_view emulatedFromType)
610{
611 AttachItemFields(std::move(itemFields));
613}
614
615ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
617{
619}
620
621void ROOT::RRecordField::AddItem(std::unique_ptr<RFieldBase> item)
622{
623 fSize += GetItemPadding(fSize, item->GetAlignment());
624 if (!IsPairOrTuple()) {
625 fOffsets.emplace_back(fSize);
626 }
627 fSize += item->GetValueSize();
628 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
629 fTraits &= item->GetTraits() | (fTraits & kTraitExtensible); // may be called by AddItemToRecord()
630
631 if (IsPairOrTuple()) {
632 Attach(std::move(item), "_" + std::to_string(fSubfields.size()));
633 } else {
634 const std::string itemName = item->GetFieldName();
635 if (fSubfieldNames.count(itemName) > 0)
636 throw RException(R__FAIL("duplicate field name: " + itemName));
637 Attach(std::move(item));
638 fSubfieldNames.insert(itemName);
639 }
640}
641
643{
644 // Only supported for untyped records
645 assert(record.GetTypeName().empty());
646 record.AddItem(std::move(newItem));
647}
648
649std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
650{
651 if (itemAlignment > 1) {
652 auto remainder = baseOffset % itemAlignment;
653 if (remainder != 0)
654 return itemAlignment - remainder;
655 }
656 return 0;
657}
658
659std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
660{
661 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
662}
663
664std::size_t ROOT::RRecordField::AppendImpl(const void *from)
665{
666 std::size_t nbytes = 0;
667 for (unsigned i = 0; i < fSubfields.size(); ++i) {
668 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
669 }
670 return nbytes;
671}
672
674{
675 for (unsigned i = 0; i < fSubfields.size(); ++i) {
676 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
677 }
678}
679
681{
682 for (unsigned i = 0; i < fSubfields.size(); ++i) {
683 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
684 }
685}
686
688{
689 if (fTraits & kTraitEmulatedField) {
690 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
691 return;
692 }
693 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
694 R__ASSERT(GetTypeName().empty());
695
696 EnsureMatchingOnDiskField(desc, kDiffTypeName | kDiffTypeVersion).ThrowOnError();
697
698 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
699 // and we will ignore extra on-disk fields.
700 // It remains to mark the extra in-memory fields as artificial.
701 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
702 std::unordered_set<std::string_view> onDiskSubfields;
703 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
704 onDiskSubfields.insert(subField.GetFieldName());
705 }
706 for (auto &f : fSubfields) {
707 if (onDiskSubfields.count(f->GetFieldName()) == 0)
708 CallSetArtificialOn(*f);
709 }
710}
711
713{
714 for (unsigned i = 0; i < fSubfields.size(); ++i) {
715 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
716 }
717}
718
720{
721 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
722 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
723 }
724 RDeleter::operator()(objPtr, dtorOnly);
725}
726
727std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
728{
729 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
730 itemDeleters.reserve(fOffsets.size());
731 for (const auto &f : fSubfields) {
732 itemDeleters.emplace_back(GetDeleterOf(*f));
733 }
734 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
735}
736
737std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
738{
739 auto valuePtr = value.GetPtr<void>();
740 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
741 std::vector<RValue> result;
742 result.reserve(fSubfields.size());
743 for (unsigned i = 0; i < fSubfields.size(); ++i) {
744 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
745 }
746 return result;
747}
748
750{
751 visitor.VisitRecordField(*this);
752}
753
754//------------------------------------------------------------------------------
755
756ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
757 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
758 false /* isSimple */, N),
759 fN(N)
760{
762}
763
769
774
779
780template <typename FUlong, typename FUlonglong, typename... Args>
782{
783 if (WordSize() == sizeof(unsigned long)) {
784 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
785 } else if (WordSize() == sizeof(unsigned long long)) {
786 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
787 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
788 } else {
789 R__ASSERT(false);
790 }
791}
792
793template <typename Word_t>
794static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
795{
796 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
797
798 const auto *asWordArray = static_cast<const Word_t *>(from);
799 bool elementValue;
800 std::size_t i = 0;
801 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
802 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
803 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
804 column.Append(&elementValue);
805 }
806 }
807}
808
809std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
810{
812 return fN;
813}
814
815template <typename Word_t>
816static void
818{
819 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
820
821 auto *asWordArray = static_cast<Word_t *>(to);
822 bool elementValue;
823 for (std::size_t i = 0; i < nBits; ++i) {
824 column.Read(globalIndex * nBits + i, &elementValue);
825 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
826 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
827 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
828 }
829}
830
835
836template <typename Word_t>
837static void
839{
840 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
841
842 auto *asWordArray = static_cast<Word_t *>(to);
843 bool elementValue;
844 for (std::size_t i = 0; i < nBits; ++i) {
845 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
846 &elementValue);
847 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
848 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
849 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
850 }
851}
852
857
859{
860 visitor.VisitBitsetField(*this);
861}
862
863//------------------------------------------------------------------------------
864
865ROOT::RNullableField::RNullableField(std::string_view fieldName, const std::string &typePrefix,
866 std::unique_ptr<RFieldBase> itemField)
867 : ROOT::RFieldBase(fieldName, typePrefix + "<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kCollection,
868 false /* isSimple */)
869{
870 if (!itemField->GetTypeAlias().empty())
871 fTypeAlias = typePrefix + "<" + itemField->GetTypeAlias() + ">";
872
873 Attach(std::move(itemField), "_0");
874}
875
885
891
893{
894 if (!fIsEvolvedFromInnerType)
896}
897
899{
900 fPrincipalColumn->Append(&fNWritten);
901 return sizeof(ROOT::Internal::RColumnIndex);
902}
903
904std::size_t ROOT::RNullableField::AppendValue(const void *from)
905{
906 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
907 fNWritten++;
908 fPrincipalColumn->Append(&fNWritten);
910}
911
913{
914 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
915
916 auto success = EnsureMatchingOnDiskField(desc, kDiffTypeName);
917 if (!success) {
918 fIsEvolvedFromInnerType = true;
919 } else {
920 success = EnsureMatchingTypePrefix(desc, prefixes);
921 fIsEvolvedFromInnerType = !success;
922 }
923
924 if (fIsEvolvedFromInnerType)
925 fSubfields[0]->SetOnDiskId(GetOnDiskId());
926}
927
935
943
945{
946 visitor.VisitNullableField(*this);
947}
948
949//------------------------------------------------------------------------------
950
951namespace {
952// Dummy class to determine the dynamic type of any polymorphic user object.
953struct PolymorphicClass {
954 virtual ~PolymorphicClass() = default;
955};
956} // namespace
957
958ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
959 : RNullableField(fieldName, "std::unique_ptr", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
960{
961 if (const auto *classField = dynamic_cast<const ROOT::RClassField *>(fSubfields[0].get())) {
962 fPolymorphicTypeInfo = classField->GetPolymorphicTypeInfo();
963 }
964}
965
966std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
967{
968 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
969 return std::make_unique<RUniquePtrField>(newName, std::move(newItemField));
970}
971
972std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
973{
974 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
975 if (*typedValue) {
976 const void *obj = typedValue->get();
977 if (fPolymorphicTypeInfo != nullptr) {
978 // This cast allows getting the dynamic type of polymorphic objects. A similar strategy is employed by
979 // TIsAProxy. If one of them needs updating because of changes in C++, also check the other one.
980 const std::type_info &t = typeid(*static_cast<const PolymorphicClass *>(obj));
981 if (t != *fPolymorphicTypeInfo) {
982 std::string msg = "invalid dynamic type of object, expected " + fSubfields[0]->GetTypeName();
983 int err = 0;
985 if (!err) {
986 msg = msg + " but was passed " + demangled;
988 }
989 msg += " and upcasting of polymorphic types is not supported in RNTuple";
990 throw RException(R__FAIL(msg));
991 }
992 }
993 return AppendValue(obj);
994 } else {
995 return AppendNull();
996 }
997}
998
1000{
1001 auto ptr = static_cast<std::unique_ptr<char> *>(to);
1002 bool isValidValue = static_cast<bool>(*ptr);
1003
1004 void *valuePtr = nullptr;
1005 if (isValidValue)
1006 valuePtr = ptr->get();
1007
1008 if (isValidValue && !hasOnDiskValue) {
1009 ptr->release();
1010 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
1011 } else if (!isValidValue && hasOnDiskValue) {
1012 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
1013 ptr->reset(reinterpret_cast<char *>(valuePtr));
1014 }
1015
1016 return valuePtr;
1017}
1018
1020{
1022 if (!fIsEvolvedFromInnerType)
1023 itemIndex = GetItemIndex(globalIndex);
1024 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1025 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1026 if (hasOnDiskValue) {
1027 if (fIsEvolvedFromInnerType) {
1028 CallReadOn(*fSubfields[0], globalIndex, valuePtr);
1029 } else {
1030 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1031 }
1032 }
1033}
1034
1036{
1038 if (!fIsEvolvedFromInnerType) {
1039 itemIndex = GetItemIndex(localIndex);
1040 } else {
1042 }
1043 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1044 auto valuePtr = PrepareRead(to, hasOnDiskValue);
1045 if (hasOnDiskValue)
1046 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
1047}
1048
1050{
1051 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
1052 if (*typedPtr) {
1053 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
1054 typedPtr->release();
1055 }
1056 RDeleter::operator()(objPtr, dtorOnly);
1057}
1058
1059std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
1060{
1061 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
1062}
1063
1064std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
1065{
1066 std::vector<RValue> result;
1067 auto valuePtr = value.GetPtr<void>();
1068 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
1069 if (uniquePtr) {
1070 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
1071 }
1072 return result;
1073}
1074
1075//------------------------------------------------------------------------------
1076
1077ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1078 : RNullableField(fieldName, "std::optional", std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
1079{
1082}
1083
1085{
1086 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
1087}
1088
1090{
1091 return GetEngagementPtr(const_cast<void *>(optionalPtr));
1092}
1093
1094std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
1095{
1096 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1097 return std::make_unique<ROptionalField>(newName, std::move(newItemField));
1098}
1099
1100std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
1101{
1102 if (*GetEngagementPtr(from)) {
1103 return AppendValue(from);
1104 } else {
1105 return AppendNull();
1106 }
1107}
1108
1110{
1111 auto engagementPtr = GetEngagementPtr(to);
1112 if (hasOnDiskValue) {
1113 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
1114 CallConstructValueOn(*fSubfields[0], to);
1115 *engagementPtr = true;
1116 } else {
1117 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
1118 fItemDeleter->operator()(to, true /* dtorOnly */);
1119 *engagementPtr = false;
1120 }
1121}
1122
1124{
1126 if (!fIsEvolvedFromInnerType)
1127 itemIndex = GetItemIndex(globalIndex);
1128 const bool hasOnDiskValue = fIsEvolvedFromInnerType || itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1129 PrepareRead(to, hasOnDiskValue);
1130 if (hasOnDiskValue) {
1131 if (fIsEvolvedFromInnerType) {
1132 CallReadOn(*fSubfields[0], globalIndex, to);
1133 } else {
1134 CallReadOn(*fSubfields[0], itemIndex, to);
1135 }
1136 }
1137}
1138
1140{
1142 if (!fIsEvolvedFromInnerType) {
1143 itemIndex = GetItemIndex(localIndex);
1144 } else {
1146 }
1147 const bool hasOnDiskValue = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
1148 PrepareRead(to, hasOnDiskValue);
1149 if (hasOnDiskValue)
1150 CallReadOn(*fSubfields[0], itemIndex, to);
1151}
1152
1154{
1155 *GetEngagementPtr(where) = false;
1156}
1157
1159{
1160 if (fItemDeleter) {
1161 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
1162 if (*engagementPtr)
1163 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
1164 }
1165 RDeleter::operator()(objPtr, dtorOnly);
1166}
1167
1168std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
1169{
1170 return std::make_unique<ROptionalDeleter>(
1171 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
1172 fSubfields[0]->GetValueSize());
1173}
1174
1175std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1176{
1177 std::vector<RValue> result;
1178 const auto valuePtr = value.GetPtr<void>().get();
1179 if (*GetEngagementPtr(valuePtr)) {
1180 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1181 }
1182 return result;
1183}
1184
1186{
1187 const auto alignment = GetAlignment();
1188 // real size is the sum of the value size and the engagement boolean
1189 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1190 auto padding = 0;
1191 if (alignment > 1) {
1192 auto remainder = actualSize % alignment;
1193 if (remainder != 0)
1194 padding = alignment - remainder;
1195 }
1196 return actualSize + padding;
1197}
1198
1200{
1201 return fSubfields[0]->GetAlignment();
1202}
1203
1204//------------------------------------------------------------------------------
1205
1206ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
1207 : RFieldBase(fieldName, "std::atomic<" + itemField->GetTypeName() + ">", ROOT::ENTupleStructure::kPlain,
1208 false /* isSimple */)
1209{
1210 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1212 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1214
1215 if (!itemField->GetTypeAlias().empty())
1216 fTypeAlias = "std::atomic<" + itemField->GetTypeAlias() + ">";
1217
1218 Attach(std::move(itemField), "_0");
1219}
1220
1221std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1222{
1223 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1224 return std::make_unique<RAtomicField>(newName, std::move(newItemField));
1225}
1226
1228{
1229 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1230 if (fieldDesc.GetTypeName().rfind("std::atomic<", 0) == 0) {
1231 EnsureMatchingOnDiskField(desc, kDiffTypeName).ThrowOnError();
1232 } else {
1233 fSubfields[0]->SetOnDiskId(GetOnDiskId());
1234 }
1235}
1236
1237std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1238{
1239 std::vector<RValue> result;
1240 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1241 return result;
1242}
1243
1245{
1246 visitor.VisitAtomicField(*this);
1247}
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:817
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:838
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:794
#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 char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:145
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:1244
RAtomicField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1206
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1221
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:1227
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:1237
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:756
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:853
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:770
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:831
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:809
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:764
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:858
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:781
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:118
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:81
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
Definition RField.cxx:123
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:96
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
Definition RField.cxx:128
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.hxx:371
The field for a class with dictionary.
Definition RField.hxx:138
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, std::string_view expectedChildName="")
Add a new subfield to the list of nested fields.
std::vector< std::unique_ptr< RFieldBase > > fSubfields
Collections and classes own subfields.
virtual const RColumnRepresentations & GetColumnRepresentations() const
Implementations in derived classes should return a static RColumnRepresentations object.
@ kTraitEmulatedField
This field is a user defined type that was missing dictionaries and was reconstructed from the on-dis...
@ kTraitTriviallyDestructible
The type is cleaned up just by freeing its memory. I.e. the destructor performs a no-op.
@ kTraitExtensible
Can attach new item fields even when already connected.
@ kTraitTriviallyConstructible
No constructor needs to be called, i.e.
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
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
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
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
Definition RField.hxx:72
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:74
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:55
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Definition RField.cxx:65
void Attach(std::unique_ptr< RFieldBase > child)
A public version of the Attach method that allows piece-wise construction of the zero field.
Definition RField.cxx:41
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:323
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:912
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:928
RNullableField(std::string_view fieldName, const std::string &typePrefix, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:865
std::size_t AppendNull()
Definition RField.cxx:898
std::size_t AppendValue(const void *from)
Definition RField.cxx:904
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:886
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:944
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:876
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1158
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:1153
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1199
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1168
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1094
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:1089
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1123
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:1100
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1139
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:1175
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1185
void PrepareRead(void *to, bool hasOnDiskValue)
Definition RField.cxx:1109
ROptionalField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1077
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:719
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:737
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:659
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:680
std::unordered_set< std::string > fSubfieldNames
Efficient detection of duplicate field names.
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:573
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:749
void AttachItemFields(ContainerT &&itemFields)
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:727
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:649
void AddItem(std::unique_ptr< RFieldBase > item)
Adds an additional item field.
Definition RField.cxx:621
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:673
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:712
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:664
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:687
void ReconcileIntegralField(const RNTupleDescriptor &desc)
Definition RField.cxx:136
void ReconcileFloatingPointField(const RNTupleDescriptor &desc)
Definition RField.cxx:157
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:1049
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:1064
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:999
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:1059
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:1019
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:966
RUniquePtrField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:958
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:972
void ReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:1035
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:599
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:591
std::string GetTypeTraceReport(const RFieldBase &field, const RNTupleDescriptor &desc)
Prints the hierarchy of types with their field names and field IDs for the given in-memory field and ...
void AddItemToRecord(RRecordField &record, std::unique_ptr< RFieldBase > newItem)
Definition RField.cxx:642
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.