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