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
34std::unique_ptr<ROOT::RFieldBase> ROOT::RFieldZero::CloneImpl(std::string_view /*newName*/) const
35{
36 auto result = std::make_unique<RFieldZero>();
37 for (auto &f : fSubfields)
38 result->Attach(f->Clone(f->GetFieldName()));
39 return result;
40}
41
43{
44 visitor.VisitFieldZero(*this);
45}
46
47//------------------------------------------------------------------------------
48
58
63
65{
66 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
67 EnsureMatchingOnDiskField(fieldDesc, kDiffTypeVersion | kDiffStructure | kDiffTypeName);
68 if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) {
69 if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) {
70 throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() +
71 " expects an on-disk leaf field of the same type"));
72 }
73 } else if (fieldDesc.GetStructure() != ENTupleStructure::kCollection) {
74 throw RException(R__FAIL("invalid on-disk structural role for RCardinalityField " + GetQualifiedFieldName()));
75 }
76}
77
79{
80 visitor.VisitCardinalityField(*this);
81}
82
87
92
93//------------------------------------------------------------------------------
94
95template class ROOT::RSimpleField<char>;
96
116
118{
119 visitor.VisitCharField(*this);
120}
121
122//------------------------------------------------------------------------------
123
124template class ROOT::RSimpleField<std::byte>;
125
127{
128 static RColumnRepresentations representations({{ENTupleColumnType::kByte}}, {});
129 return representations;
130}
131
133{
134 visitor.VisitByteField(*this);
135}
136
137//------------------------------------------------------------------------------
138
139template class ROOT::RSimpleField<int8_t>;
140
142{
143 static RColumnRepresentations representations({{ENTupleColumnType::kInt8}}, {{ENTupleColumnType::kChar},
158 return representations;
159}
160
162{
163 visitor.VisitInt8Field(*this);
164}
165
166//------------------------------------------------------------------------------
167
168template class ROOT::RSimpleField<uint8_t>;
169
171{
172 static RColumnRepresentations representations({{ENTupleColumnType::kUInt8}}, {{ENTupleColumnType::kChar},
187 return representations;
188}
189
191{
192 visitor.VisitUInt8Field(*this);
193}
194
195//------------------------------------------------------------------------------
196
197template class ROOT::RSimpleField<bool>;
198
218
220{
221 visitor.VisitBoolField(*this);
222}
223
224//------------------------------------------------------------------------------
225
226template class ROOT::RSimpleField<float>;
227
238
240{
241 visitor.VisitFloatField(*this);
242}
243
244//------------------------------------------------------------------------------
245
246template class ROOT::RSimpleField<double>;
247
260
262{
263 visitor.VisitDoubleField(*this);
264}
265
267{
268 fTypeAlias = "Double32_t";
269}
270
271//------------------------------------------------------------------------------
272
273template class ROOT::RSimpleField<int16_t>;
274
276{
292 return representations;
293}
294
296{
297 visitor.VisitInt16Field(*this);
298}
299
300//------------------------------------------------------------------------------
301
302template class ROOT::RSimpleField<uint16_t>;
303
305{
321 return representations;
322}
323
325{
326 visitor.VisitUInt16Field(*this);
327}
328
329//------------------------------------------------------------------------------
330
331template class ROOT::RSimpleField<int32_t>;
332
334{
350 return representations;
351}
352
354{
355 visitor.VisitInt32Field(*this);
356}
357
358//------------------------------------------------------------------------------
359
360template class ROOT::RSimpleField<uint32_t>;
361
363{
379 return representations;
380}
381
383{
384 visitor.VisitUInt32Field(*this);
385}
386
387//------------------------------------------------------------------------------
388
389template class ROOT::RSimpleField<uint64_t>;
390
392{
408 return representations;
409}
410
412{
413 visitor.VisitUInt64Field(*this);
414}
415
416//------------------------------------------------------------------------------
417
418template class ROOT::RSimpleField<int64_t>;
419
421{
437 return representations;
438}
439
441{
442 visitor.VisitInt64Field(*this);
443}
444
445//------------------------------------------------------------------------------
446
448{
453 {});
454 return representations;
455}
456
458{
460}
461
463{
465}
466
467std::size_t ROOT::RField<std::string>::AppendImpl(const void *from)
468{
469 auto typedValue = static_cast<const std::string *>(from);
470 auto length = typedValue->length();
471 fAuxiliaryColumn->AppendV(typedValue->data(), length);
472 fIndex += length;
473 fPrincipalColumn->Append(&fIndex);
474 return length + fPrincipalColumn->GetElement()->GetPackedSize();
475}
476
478{
479 auto typedValue = static_cast<std::string *>(to);
480 RNTupleLocalIndex collectionStart;
482 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
483 if (nChars == 0) {
484 typedValue->clear();
485 } else {
486 typedValue->resize(nChars);
487 fAuxiliaryColumn->ReadV(collectionStart, nChars, const_cast<char *>(typedValue->data()));
488 }
489}
490
492{
493 visitor.VisitStringField(*this);
494}
495
496//------------------------------------------------------------------------------
497
499 : ROOT::RFieldBase(name, source.GetTypeName(), ROOT::ENTupleStructure::kRecord, false /* isSimple */),
500 fMaxAlignment(source.fMaxAlignment),
502 fOffsets(source.fOffsets)
503{
504 for (const auto &f : source.GetConstSubfields())
505 Attach(f->Clone(f->GetFieldName()));
506 fTraits = source.fTraits;
507}
508
509ROOT::RRecordField::RRecordField(std::string_view fieldName, std::string_view typeName)
510 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kRecord, false /* isSimple */)
511{
512}
513
514void ROOT::RRecordField::AttachItemFields(std::vector<std::unique_ptr<RFieldBase>> itemFields)
515{
516 fTraits |= kTraitTrivialType;
517 for (auto &item : itemFields) {
518 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
519 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
520 fTraits &= item->GetTraits();
521 Attach(std::move(item));
522 }
523 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
524 // requirements of the type with strictest alignment
525 fSize += GetItemPadding(fSize, fMaxAlignment);
526}
527
528std::unique_ptr<ROOT::RFieldBase>
530 std::vector<std::unique_ptr<RFieldBase>> itemFields,
531 std::string_view emulatedFromType)
532{
533 R__ASSERT(!emulatedFromType.empty());
534 return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
535}
536
537std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
538 std::unique_ptr<RFieldBase> itemField,
539 std::string_view emulatedFromType)
540{
541 R__ASSERT(!emulatedFromType.empty());
542 return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
543}
544
545ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
546 std::string_view emulatedFromType)
548{
550 fOffsets.reserve(itemFields.size());
551 for (auto &item : itemFields) {
552 fSize += GetItemPadding(fSize, item->GetAlignment());
553 fOffsets.push_back(fSize);
554 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
555 fSize += item->GetValueSize();
556 fTraits &= item->GetTraits();
557 Attach(std::move(item));
558 }
560 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
561 // requirements of the type with strictest alignment
563}
564
565ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
567{
568}
569
570std::size_t ROOT::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
571{
572 if (itemAlignment > 1) {
573 auto remainder = baseOffset % itemAlignment;
574 if (remainder != 0)
575 return itemAlignment - remainder;
576 }
577 return 0;
578}
579
580std::unique_ptr<ROOT::RFieldBase> ROOT::RRecordField::CloneImpl(std::string_view newName) const
581{
582 return std::unique_ptr<RRecordField>(new RRecordField(newName, *this));
583}
584
585std::size_t ROOT::RRecordField::AppendImpl(const void *from)
586{
587 std::size_t nbytes = 0;
588 for (unsigned i = 0; i < fSubfields.size(); ++i) {
589 nbytes += CallAppendOn(*fSubfields[i], static_cast<const unsigned char *>(from) + fOffsets[i]);
590 }
591 return nbytes;
592}
593
595{
596 for (unsigned i = 0; i < fSubfields.size(); ++i) {
597 CallReadOn(*fSubfields[i], globalIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
598 }
599}
600
602{
603 for (unsigned i = 0; i < fSubfields.size(); ++i) {
604 CallReadOn(*fSubfields[i], localIndex, static_cast<unsigned char *>(to) + fOffsets[i]);
605 }
606}
607
609{
610 if (fTraits & kTraitEmulatedField) {
611 // The field has been explicitly constructed following the on-disk information. No further reconcilation needed.
612 return;
613 }
614 // Note that the RPairField and RTupleField descendants have their own reconcilation logic
615 R__ASSERT(GetTypeName().empty());
616
617 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
618 EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName | kDiffTypeVersion);
619
620 // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields
621 // and we will ignore extra on-disk fields.
622 // It remains to mark the extra in-memory fields as artificial.
623 std::unordered_set<std::string_view> onDiskSubfields;
624 for (const auto &subField : desc.GetFieldIterable(fieldDesc)) {
625 onDiskSubfields.insert(subField.GetFieldName());
626 }
627 for (auto &f : fSubfields) {
628 if (onDiskSubfields.count(f->GetFieldName()) == 0)
629 CallSetArtificialOn(*f);
630 }
631}
632
634{
635 for (unsigned i = 0; i < fSubfields.size(); ++i) {
636 CallConstructValueOn(*fSubfields[i], static_cast<unsigned char *>(where) + fOffsets[i]);
637 }
638}
639
641{
642 for (unsigned i = 0; i < fItemDeleters.size(); ++i) {
643 fItemDeleters[i]->operator()(reinterpret_cast<unsigned char *>(objPtr) + fOffsets[i], true /* dtorOnly */);
644 }
645 RDeleter::operator()(objPtr, dtorOnly);
646}
647
648std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RRecordField::GetDeleter() const
649{
650 std::vector<std::unique_ptr<RDeleter>> itemDeleters;
651 itemDeleters.reserve(fOffsets.size());
652 for (const auto &f : fSubfields) {
653 itemDeleters.emplace_back(GetDeleterOf(*f));
654 }
655 return std::make_unique<RRecordDeleter>(std::move(itemDeleters), fOffsets);
656}
657
658std::vector<ROOT::RFieldBase::RValue> ROOT::RRecordField::SplitValue(const RValue &value) const
659{
660 auto valuePtr = value.GetPtr<void>();
661 auto charPtr = static_cast<unsigned char *>(valuePtr.get());
662 std::vector<RValue> result;
663 result.reserve(fSubfields.size());
664 for (unsigned i = 0; i < fSubfields.size(); ++i) {
665 result.emplace_back(fSubfields[i]->BindValue(std::shared_ptr<void>(valuePtr, charPtr + fOffsets[i])));
666 }
667 return result;
668}
669
671{
672 visitor.VisitRecordField(*this);
673}
674
675//------------------------------------------------------------------------------
676
677ROOT::RBitsetField::RBitsetField(std::string_view fieldName, std::size_t N)
678 : ROOT::RFieldBase(fieldName, "std::bitset<" + std::to_string(N) + ">", ROOT::ENTupleStructure::kPlain,
679 false /* isSimple */, N),
680 fN(N)
681{
683}
684
690
695
700
701template <typename FUlong, typename FUlonglong, typename... Args>
703{
704 if (WordSize() == sizeof(unsigned long)) {
705 fUlong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
706 } else if (WordSize() == sizeof(unsigned long long)) {
707 // NOTE: this can only happen on Windows; see the comment on the RBitsetField class.
708 fUlonglong(std::forward<Args>(args)..., fN, *fPrincipalColumn);
709 } else {
710 R__ASSERT(false);
711 }
712}
713
714template <typename Word_t>
715static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
716{
717 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
718
719 const auto *asWordArray = static_cast<const Word_t *>(from);
720 bool elementValue;
721 std::size_t i = 0;
722 for (std::size_t word = 0; word < (nBits + kBitsPerWord - 1) / kBitsPerWord; ++word) {
723 for (std::size_t mask = 0; (mask < kBitsPerWord) && (i < nBits); ++mask, ++i) {
724 elementValue = (asWordArray[word] & (static_cast<Word_t>(1) << mask)) != 0;
725 column.Append(&elementValue);
726 }
727 }
728}
729
730std::size_t ROOT::RBitsetField::AppendImpl(const void *from)
731{
733 return fN;
734}
735
736template <typename Word_t>
737static void
739{
740 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
741
742 auto *asWordArray = static_cast<Word_t *>(to);
743 bool elementValue;
744 for (std::size_t i = 0; i < nBits; ++i) {
745 column.Read(globalIndex * nBits + i, &elementValue);
746 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
747 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
748 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
749 }
750}
751
756
757template <typename Word_t>
758static void
760{
761 constexpr auto kBitsPerWord = sizeof(Word_t) * 8;
762
763 auto *asWordArray = static_cast<Word_t *>(to);
764 bool elementValue;
765 for (std::size_t i = 0; i < nBits; ++i) {
766 column.Read(ROOT::RNTupleLocalIndex(localIndex.GetClusterId(), localIndex.GetIndexInCluster() * nBits) + i,
767 &elementValue);
768 Word_t mask = static_cast<Word_t>(1) << (i % kBitsPerWord);
769 Word_t bit = static_cast<Word_t>(elementValue) << (i % kBitsPerWord);
770 asWordArray[i / kBitsPerWord] = (asWordArray[i / kBitsPerWord] & ~mask) | bit;
771 }
772}
773
778
780{
781 visitor.VisitBitsetField(*this);
782}
783
784//------------------------------------------------------------------------------
785
786ROOT::RNullableField::RNullableField(std::string_view fieldName, std::string_view typeName,
787 std::unique_ptr<RFieldBase> itemField)
788 : ROOT::RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kCollection, false /* isSimple */)
789{
790 Attach(std::move(itemField));
791}
792
802
807
812
814{
815 fPrincipalColumn->Append(&fNWritten);
816 return sizeof(ROOT::Internal::RColumnIndex);
817}
818
819std::size_t ROOT::RNullableField::AppendValue(const void *from)
820{
821 auto nbytesItem = CallAppendOn(*fSubfields[0], from);
822 fNWritten++;
823 fPrincipalColumn->Append(&fNWritten);
825}
826
828{
829 static const std::vector<std::string> prefixes = {"std::optional<", "std::unique_ptr<"};
830
831 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
832 EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName);
833 EnsureMatchingTypePrefix(fieldDesc, prefixes);
834}
835
843
845{
846 visitor.VisitNullableField(*this);
847}
848
849//------------------------------------------------------------------------------
850
851ROOT::RUniquePtrField::RUniquePtrField(std::string_view fieldName, std::string_view typeName,
852 std::unique_ptr<RFieldBase> itemField)
853 : RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
854{
855}
856
857std::unique_ptr<ROOT::RFieldBase> ROOT::RUniquePtrField::CloneImpl(std::string_view newName) const
858{
859 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
860 return std::make_unique<RUniquePtrField>(newName, GetTypeName(), std::move(newItemField));
861}
862
863std::size_t ROOT::RUniquePtrField::AppendImpl(const void *from)
864{
865 auto typedValue = static_cast<const std::unique_ptr<char> *>(from);
866 if (*typedValue) {
867 return AppendValue(typedValue->get());
868 } else {
869 return AppendNull();
870 }
871}
872
874{
875 auto ptr = static_cast<std::unique_ptr<char> *>(to);
876 bool isValidValue = static_cast<bool>(*ptr);
877
878 auto itemIndex = GetItemIndex(globalIndex);
879 bool isValidItem = itemIndex.GetIndexInCluster() != ROOT::kInvalidNTupleIndex;
880
881 void *valuePtr = nullptr;
882 if (isValidValue)
883 valuePtr = ptr->get();
884
885 if (isValidValue && !isValidItem) {
886 ptr->release();
887 fItemDeleter->operator()(valuePtr, false /* dtorOnly */);
888 return;
889 }
890
891 if (!isValidItem) // On-disk value missing; nothing else to do
892 return;
893
894 if (!isValidValue) {
895 valuePtr = CallCreateObjectRawPtrOn(*fSubfields[0]);
896 ptr->reset(reinterpret_cast<char *>(valuePtr));
897 }
898
899 CallReadOn(*fSubfields[0], itemIndex, valuePtr);
900}
901
903{
904 auto typedPtr = static_cast<std::unique_ptr<char> *>(objPtr);
905 if (*typedPtr) {
906 fItemDeleter->operator()(typedPtr->get(), false /* dtorOnly */);
907 typedPtr->release();
908 }
909 RDeleter::operator()(objPtr, dtorOnly);
910}
911
912std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::RUniquePtrField::GetDeleter() const
913{
914 return std::make_unique<RUniquePtrDeleter>(GetDeleterOf(*fSubfields[0]));
915}
916
917std::vector<ROOT::RFieldBase::RValue> ROOT::RUniquePtrField::SplitValue(const RValue &value) const
918{
919 std::vector<RValue> result;
920 auto valuePtr = value.GetPtr<void>();
921 const auto &uniquePtr = *static_cast<std::unique_ptr<char> *>(valuePtr.get());
922 if (uniquePtr) {
923 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(valuePtr, uniquePtr.get())));
924 }
925 return result;
926}
927
928//------------------------------------------------------------------------------
929
930ROOT::ROptionalField::ROptionalField(std::string_view fieldName, std::string_view typeName,
931 std::unique_ptr<RFieldBase> itemField)
932 : RNullableField(fieldName, typeName, std::move(itemField)), fItemDeleter(GetDeleterOf(*fSubfields[0]))
933{
936}
937
939{
940 return reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(optionalPtr) + fSubfields[0]->GetValueSize());
941}
942
944{
945 return GetEngagementPtr(const_cast<void *>(optionalPtr));
946}
947
948std::unique_ptr<ROOT::RFieldBase> ROOT::ROptionalField::CloneImpl(std::string_view newName) const
949{
950 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
951 return std::make_unique<ROptionalField>(newName, GetTypeName(), std::move(newItemField));
952}
953
954std::size_t ROOT::ROptionalField::AppendImpl(const void *from)
955{
956 if (*GetEngagementPtr(from)) {
957 return AppendValue(from);
958 } else {
959 return AppendNull();
960 }
961}
962
964{
965 auto engagementPtr = GetEngagementPtr(to);
966 auto itemIndex = GetItemIndex(globalIndex);
967 if (itemIndex.GetIndexInCluster() == ROOT::kInvalidNTupleIndex) {
968 if (*engagementPtr && !(fSubfields[0]->GetTraits() & kTraitTriviallyDestructible))
969 fItemDeleter->operator()(to, true /* dtorOnly */);
970 *engagementPtr = false;
971 } else {
972 if (!(*engagementPtr) && !(fSubfields[0]->GetTraits() & kTraitTriviallyConstructible))
973 CallConstructValueOn(*fSubfields[0], to);
974 CallReadOn(*fSubfields[0], itemIndex, to);
975 *engagementPtr = true;
976 }
977}
978
980{
981 *GetEngagementPtr(where) = false;
982}
983
985{
986 if (fItemDeleter) {
987 auto engagementPtr = reinterpret_cast<bool *>(reinterpret_cast<unsigned char *>(objPtr) + fEngagementPtrOffset);
988 if (*engagementPtr)
989 fItemDeleter->operator()(objPtr, true /* dtorOnly */);
990 }
991 RDeleter::operator()(objPtr, dtorOnly);
992}
993
994std::unique_ptr<ROOT::RFieldBase::RDeleter> ROOT::ROptionalField::GetDeleter() const
995{
996 return std::make_unique<ROptionalDeleter>(
997 (fSubfields[0]->GetTraits() & kTraitTriviallyDestructible) ? nullptr : GetDeleterOf(*fSubfields[0]),
998 fSubfields[0]->GetValueSize());
999}
1000
1001std::vector<ROOT::RFieldBase::RValue> ROOT::ROptionalField::SplitValue(const RValue &value) const
1002{
1003 std::vector<RValue> result;
1004 const auto valuePtr = value.GetPtr<void>().get();
1005 if (*GetEngagementPtr(valuePtr)) {
1006 result.emplace_back(fSubfields[0]->BindValue(std::shared_ptr<void>(value.GetPtr<void>(), valuePtr)));
1007 }
1008 return result;
1009}
1010
1012{
1013 const auto alignment = GetAlignment();
1014 // real size is the sum of the value size and the engagement boolean
1015 const auto actualSize = fSubfields[0]->GetValueSize() + sizeof(bool);
1016 auto padding = 0;
1017 if (alignment > 1) {
1018 auto remainder = actualSize % alignment;
1019 if (remainder != 0)
1020 padding = alignment - remainder;
1021 }
1022 return actualSize + padding;
1023}
1024
1026{
1027 return fSubfields[0]->GetAlignment();
1028}
1029
1030//------------------------------------------------------------------------------
1031
1032ROOT::RAtomicField::RAtomicField(std::string_view fieldName, std::string_view typeName,
1033 std::unique_ptr<RFieldBase> itemField)
1034 : RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kPlain, false /* isSimple */)
1035{
1036 if (itemField->GetTraits() & kTraitTriviallyConstructible)
1038 if (itemField->GetTraits() & kTraitTriviallyDestructible)
1040 Attach(std::move(itemField));
1041}
1042
1043std::unique_ptr<ROOT::RFieldBase> ROOT::RAtomicField::CloneImpl(std::string_view newName) const
1044{
1045 auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
1046 return std::make_unique<RAtomicField>(newName, GetTypeName(), std::move(newItemField));
1047}
1048
1050{
1051 static const std::vector<std::string> prefixes = {"std::atomic<"};
1052
1053 const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId());
1054 EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName);
1055 EnsureMatchingTypePrefix(fieldDesc, prefixes);
1056}
1057
1058std::vector<ROOT::RFieldBase::RValue> ROOT::RAtomicField::SplitValue(const RValue &value) const
1059{
1060 std::vector<RValue> result;
1061 result.emplace_back(fSubfields[0]->BindValue(value.GetPtr<void>()));
1062 return result;
1063}
1064
1066{
1067 visitor.VisitAtomicField(*this);
1068}
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:738
static void BitsetReadInClusterImpl(ROOT::RNTupleLocalIndex localIndex, void *to, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:759
static void BitsetAppendImpl(const void *from, size_t nBits, ROOT::Internal::RColumn &column)
Definition RField.cxx:715
#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
RAtomicField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:1032
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1065
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:1043
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: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:1058
RBitsetField(std::string_view fieldName, std::size_t N)
Definition RField.cxx:677
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:774
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:691
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:752
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:730
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:685
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:779
void SelectWordSize(FUlong &&fUlong, FUlonglong &&fUlonglong, Args &&...args)
Definition RField.cxx:702
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:78
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:49
const RField< RNTupleCardinality< std::uint32_t > > * As32Bit() const
Definition RField.cxx:83
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:64
const RField< RNTupleCardinality< std::uint64_t > > * As64Bit() const
Definition RField.cxx:88
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.hxx:340
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.
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:42
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:34
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:292
The on-storage metadata of an RNTuple.
RFieldDescriptorIterable GetFieldIterable(const RFieldDescriptor &fieldDesc) const
const RFieldDescriptor & GetFieldDescriptor(ROOT::DescriptorId_t fieldId) 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:827
std::size_t AppendNull()
Definition RField.cxx:813
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:836
RNullableField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:786
std::size_t AppendValue(const void *from)
Definition RField.cxx:819
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Definition RField.cxx:803
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:844
const RFieldBase::RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
Definition RField.cxx:793
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:984
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:979
size_t GetAlignment() const final
As a rule of thumb, the alignment is equal to the size of the type.
Definition RField.cxx:1025
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:994
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:948
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:943
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:963
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:954
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:1001
ROptionalField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:930
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:1011
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:640
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:658
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:580
void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
Definition RField.cxx:601
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:498
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:670
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:648
void AttachItemFields(std::vector< std::unique_ptr< RFieldBase > > itemFields)
Definition RField.cxx:514
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:570
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:594
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:633
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:585
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:608
void operator()(void *objPtr, bool dtorOnly) final
Definition RField.cxx:902
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:917
RUniquePtrField(std::string_view fieldName, std::string_view typeName, std::unique_ptr< RFieldBase > itemField)
Definition RField.cxx:851
std::unique_ptr< RDeleter > GetDeleter() const final
Definition RField.cxx:912
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
Definition RField.cxx:873
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:857
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
Definition RField.cxx:863
Template specializations for C++ std::vector.
std::unique_ptr< RFieldBase > CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr< RFieldBase > itemField, std::string_view emulatedFromType)
Definition RField.cxx:537
std::unique_ptr< RFieldBase > CreateEmulatedRecordField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields, std::string_view emulatedFromType)
Definition RField.cxx:529
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...