Warning, file /include/root/ROOT/RFieldBase.hxx was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RFieldBase
0015 #define ROOT_RFieldBase
0016
0017 #include <ROOT/RColumn.hxx>
0018 #include <ROOT/RCreateFieldOptions.hxx>
0019 #include <ROOT/RError.hxx>
0020 #include <ROOT/RFieldUtils.hxx>
0021 #include <ROOT/RNTupleRange.hxx>
0022 #include <ROOT/RNTupleTypes.hxx>
0023
0024 #include <atomic>
0025 #include <cstddef>
0026 #include <functional>
0027 #include <iterator>
0028 #include <memory>
0029 #include <new>
0030 #include <string>
0031 #include <string_view>
0032 #include <typeinfo>
0033 #include <type_traits>
0034 #include <vector>
0035
0036 namespace ROOT {
0037
0038 class REntry;
0039 class RFieldBase;
0040 class RClassField;
0041
0042 namespace Detail {
0043 class RFieldVisitor;
0044 }
0045
0046 namespace Experimental {
0047
0048 namespace Detail {
0049 class RRawPtrWriteEntry;
0050 }
0051
0052 }
0053
0054 namespace Internal {
0055
0056 class RPageSink;
0057 class RPageSource;
0058 struct RFieldCallbackInjector;
0059 struct RFieldRepresentationModifier;
0060
0061
0062 void CallFlushColumnsOnField(RFieldBase &);
0063 void CallCommitClusterOnField(RFieldBase &);
0064 void CallConnectPageSinkOnField(RFieldBase &, ROOT::Internal::RPageSink &, ROOT::NTupleSize_t firstEntry = 0);
0065 void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &);
0066 ROOT::RResult<std::unique_ptr<ROOT::RFieldBase>>
0067 CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options,
0068 const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId);
0069
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 class RFieldBase {
0088 friend class RFieldZero;
0089 friend class ROOT::Experimental::Detail::RRawPtrWriteEntry;
0090 friend struct ROOT::Internal::RFieldCallbackInjector;
0091 friend struct ROOT::Internal::RFieldRepresentationModifier;
0092 friend void Internal::CallFlushColumnsOnField(RFieldBase &);
0093 friend void Internal::CallCommitClusterOnField(RFieldBase &);
0094 friend void Internal::CallConnectPageSinkOnField(RFieldBase &, ROOT::Internal::RPageSink &, ROOT::NTupleSize_t);
0095 friend void Internal::CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &);
0096 friend ROOT::RResult<std::unique_ptr<ROOT::RFieldBase>>
0097 Internal::CallFieldBaseCreate(const std::string &fieldName, const std::string &typeName,
0098 const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc,
0099 ROOT::DescriptorId_t fieldId);
0100
0101 using ReadCallback_t = std::function<void(void *)>;
0102
0103 protected:
0104
0105
0106
0107
0108 class RDeleter {
0109 public:
0110 virtual ~RDeleter() = default;
0111 virtual void operator()(void *objPtr, bool dtorOnly)
0112 {
0113 if (!dtorOnly)
0114 operator delete(objPtr);
0115 }
0116 };
0117
0118
0119 template <typename T>
0120 class RTypedDeleter : public RDeleter {
0121 public:
0122 void operator()(void *objPtr, bool dtorOnly) final
0123 {
0124 std::destroy_at(static_cast<T *>(objPtr));
0125 RDeleter::operator()(objPtr, dtorOnly);
0126 }
0127 };
0128
0129
0130
0131 struct RSharedPtrDeleter {
0132 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
0133 void operator()(void *objPtr) { fDeleter->operator()(objPtr, false ); }
0134 explicit RSharedPtrDeleter(std::unique_ptr<RFieldBase::RDeleter> deleter) : fDeleter(std::move(deleter)) {}
0135 };
0136
0137 public:
0138 static constexpr std::uint32_t kInvalidTypeVersion = -1U;
0139 enum {
0140
0141
0142 kTraitTriviallyConstructible = 0x01,
0143
0144 kTraitTriviallyDestructible = 0x02,
0145
0146
0147 kTraitMappable = 0x04,
0148
0149 kTraitTypeChecksum = 0x08,
0150
0151 kTraitInvalidField = 0x10,
0152
0153
0154 kTraitEmulatedField = 0x20,
0155
0156
0157 kTraitTrivialType = kTraitTriviallyConstructible | kTraitTriviallyDestructible
0158 };
0159
0160 using ColumnRepresentation_t = std::vector<ROOT::ENTupleColumnType>;
0161
0162
0163
0164
0165
0166
0167
0168
0169 enum class EState {
0170 kUnconnected,
0171 kConnectedToSink,
0172 kConnectedToSource
0173 };
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 class RColumnRepresentations {
0190 public:
0191
0192 using Selection_t = std::vector<ColumnRepresentation_t>;
0193
0194 RColumnRepresentations();
0195 RColumnRepresentations(const Selection_t &serializationTypes, const Selection_t &deserializationExtraTypes);
0196
0197
0198 const ColumnRepresentation_t &GetSerializationDefault() const { return fSerializationTypes[0]; }
0199 const Selection_t &GetSerializationTypes() const { return fSerializationTypes; }
0200 const Selection_t &GetDeserializationTypes() const { return fDeserializationTypes; }
0201
0202 private:
0203 Selection_t fSerializationTypes;
0204
0205
0206
0207 Selection_t fDeserializationTypes;
0208 };
0209
0210 class RValue;
0211 class RBulkValues;
0212
0213 private:
0214
0215 std::string fName;
0216
0217 std::string fType;
0218
0219 ROOT::ENTupleStructure fStructure;
0220
0221 std::size_t fNRepetitions;
0222
0223
0224 bool fIsSimple;
0225
0226
0227
0228 bool fIsArtificial = false;
0229
0230
0231
0232 ROOT::DescriptorId_t fOnDiskId = ROOT::kInvalidDescriptorId;
0233
0234 std::string fDescription;
0235
0236 EState fState = EState::kUnconnected;
0237
0238 void InvokeReadCallbacks(void *target)
0239 {
0240 for (const auto &func : fReadCallbacks)
0241 func(target);
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 ROOT::NTupleSize_t EntryToColumnElementIndex(ROOT::NTupleSize_t globalIndex) const;
0253
0254
0255 void FlushColumns();
0256
0257 void CommitCluster();
0258
0259
0260
0261 void ConnectPageSink(ROOT::Internal::RPageSink &pageSink, ROOT::NTupleSize_t firstEntry = 0);
0262
0263
0264
0265
0266 void ConnectPageSource(ROOT::Internal::RPageSource &pageSource);
0267
0268 void SetArtificial()
0269 {
0270 fIsSimple = false;
0271 fIsArtificial = true;
0272 for (auto &field : fSubfields) {
0273 field->SetArtificial();
0274 }
0275 }
0276
0277 protected:
0278 struct RBulkSpec;
0279
0280
0281 enum {
0282
0283 kDiffFieldVersion = 0x01,
0284
0285 kDiffTypeVersion = 0x02,
0286
0287 kDiffStructure = 0x04,
0288
0289 kDiffTypeName = 0x08,
0290
0291 kDiffNRepetitions = 0x10
0292 };
0293
0294
0295 std::vector<std::unique_ptr<RFieldBase>> fSubfields;
0296
0297 RFieldBase *fParent;
0298
0299
0300
0301
0302
0303
0304 ROOT::Internal::RColumn *fPrincipalColumn = nullptr;
0305
0306
0307 ROOT::Internal::RColumn *fAuxiliaryColumn = nullptr;
0308
0309
0310 std::vector<std::unique_ptr<ROOT::Internal::RColumn>> fAvailableColumns;
0311
0312 std::uint32_t fTraits = 0;
0313
0314 std::string fTypeAlias;
0315
0316 std::vector<ReadCallback_t> fReadCallbacks;
0317
0318 std::uint32_t fOnDiskTypeVersion = kInvalidTypeVersion;
0319
0320
0321 std::uint32_t fOnDiskTypeChecksum = 0;
0322
0323
0324
0325 std::vector<std::reference_wrapper<const ColumnRepresentation_t>> fColumnRepresentatives;
0326
0327
0328 void *CreateObjectRawPtr() const;
0329
0330
0331
0332
0333 template <std::uint32_t ColumnIndexT, typename HeadT, typename... TailTs>
0334 void GenerateColumnsImpl(const ColumnRepresentation_t &representation, std::uint16_t representationIndex)
0335 {
0336 assert(ColumnIndexT < representation.size());
0337 auto &column = fAvailableColumns.emplace_back(
0338 ROOT::Internal::RColumn::Create<HeadT>(representation[ColumnIndexT], ColumnIndexT, representationIndex));
0339
0340
0341 if (representationIndex == 0 && !fPrincipalColumn) {
0342 fPrincipalColumn = column.get();
0343 } else if (representationIndex == 0 && !fAuxiliaryColumn) {
0344 fAuxiliaryColumn = column.get();
0345 } else {
0346
0347 R__ASSERT(representationIndex > 0);
0348 }
0349
0350 if constexpr (sizeof...(TailTs))
0351 GenerateColumnsImpl<ColumnIndexT + 1, TailTs...>(representation, representationIndex);
0352 }
0353
0354
0355 template <typename... ColumnCppTs>
0356 void GenerateColumnsImpl()
0357 {
0358 if (fColumnRepresentatives.empty()) {
0359 fAvailableColumns.reserve(sizeof...(ColumnCppTs));
0360 GenerateColumnsImpl<0, ColumnCppTs...>(GetColumnRepresentations().GetSerializationDefault(), 0);
0361 } else {
0362 const auto N = fColumnRepresentatives.size();
0363 fAvailableColumns.reserve(N * sizeof...(ColumnCppTs));
0364 for (unsigned i = 0; i < N; ++i) {
0365 GenerateColumnsImpl<0, ColumnCppTs...>(fColumnRepresentatives[i].get(), i);
0366 }
0367 }
0368 }
0369
0370
0371 template <typename... ColumnCppTs>
0372 void GenerateColumnsImpl(const ROOT::RNTupleDescriptor &desc)
0373 {
0374 std::uint16_t representationIndex = 0;
0375 do {
0376 const auto &onDiskTypes = EnsureCompatibleColumnTypes(desc, representationIndex);
0377 if (onDiskTypes.empty())
0378 break;
0379 GenerateColumnsImpl<0, ColumnCppTs...>(onDiskTypes, representationIndex);
0380 fColumnRepresentatives.emplace_back(onDiskTypes);
0381 if (representationIndex > 0) {
0382 for (std::size_t i = 0; i < sizeof...(ColumnCppTs); ++i) {
0383 fAvailableColumns[i]->MergeTeams(
0384 *fAvailableColumns[representationIndex * sizeof...(ColumnCppTs) + i].get());
0385 }
0386 }
0387 representationIndex++;
0388 } while (true);
0389 }
0390
0391
0392
0393 virtual const RColumnRepresentations &GetColumnRepresentations() const;
0394
0395
0396 virtual void GenerateColumns() {}
0397
0398
0399
0400 virtual void GenerateColumns(const ROOT::RNTupleDescriptor & ) {}
0401
0402
0403
0404
0405
0406
0407 const ColumnRepresentation_t &
0408 EnsureCompatibleColumnTypes(const ROOT::RNTupleDescriptor &desc, std::uint16_t representationIndex) const;
0409
0410
0411
0412 void AutoAdjustColumnTypes(const ROOT::RNTupleWriteOptions &options);
0413
0414
0415 virtual std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const = 0;
0416
0417
0418 virtual void ConstructValue(void *where) const = 0;
0419 virtual std::unique_ptr<RDeleter> GetDeleter() const { return std::make_unique<RDeleter>(); }
0420
0421 static void CallConstructValueOn(const RFieldBase &other, void *where) { other.ConstructValue(where); }
0422 static std::unique_ptr<RDeleter> GetDeleterOf(const RFieldBase &other) { return other.GetDeleter(); }
0423
0424
0425 static void CallSetArtificialOn(RFieldBase &other) { other.SetArtificial(); }
0426
0427 static void SetTypeAliasOf(RFieldBase &other, const std::string &alias) { other.fTypeAlias = alias; }
0428
0429
0430
0431 virtual std::size_t AppendImpl(const void *from);
0432 virtual void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to);
0433 virtual void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to);
0434
0435
0436
0437 std::size_t Append(const void *from);
0438
0439
0440
0441
0442 void Read(ROOT::NTupleSize_t globalIndex, void *to)
0443 {
0444 if (fIsSimple)
0445 return (void)fPrincipalColumn->Read(globalIndex, to);
0446
0447 if (!fIsArtificial) {
0448 if (fTraits & kTraitMappable)
0449 fPrincipalColumn->Read(globalIndex, to);
0450 else
0451 ReadGlobalImpl(globalIndex, to);
0452 }
0453 if (R__unlikely(!fReadCallbacks.empty()))
0454 InvokeReadCallbacks(to);
0455 }
0456
0457
0458
0459
0460 void Read(RNTupleLocalIndex localIndex, void *to)
0461 {
0462 if (fIsSimple)
0463 return (void)fPrincipalColumn->Read(localIndex, to);
0464
0465 if (!fIsArtificial) {
0466 if (fTraits & kTraitMappable)
0467 fPrincipalColumn->Read(localIndex, to);
0468 else
0469 ReadInClusterImpl(localIndex, to);
0470 }
0471 if (R__unlikely(!fReadCallbacks.empty()))
0472 InvokeReadCallbacks(to);
0473 }
0474
0475
0476
0477
0478 virtual std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec);
0479
0480
0481
0482
0483 std::size_t ReadBulk(const RBulkSpec &bulkSpec);
0484
0485
0486 static std::size_t CallAppendOn(RFieldBase &other, const void *from) { return other.Append(from); }
0487 static void CallReadOn(RFieldBase &other, RNTupleLocalIndex localIndex, void *to) { other.Read(localIndex, to); }
0488 static void CallReadOn(RFieldBase &other, ROOT::NTupleSize_t globalIndex, void *to) { other.Read(globalIndex, to); }
0489 static void *CallCreateObjectRawPtrOn(RFieldBase &other) { return other.CreateObjectRawPtr(); }
0490
0491
0492 static ROOT::Internal::RColumn *GetPrincipalColumnOf(const RFieldBase &other) { return other.fPrincipalColumn; }
0493
0494
0495
0496
0497 size_t AddReadCallback(ReadCallback_t func);
0498 void RemoveReadCallback(size_t idx);
0499
0500
0501 virtual void CommitClusterImpl() {}
0502
0503
0504
0505 virtual bool HasExtraTypeInfo() const { return false; }
0506
0507
0508
0509 virtual ROOT::RExtraTypeInfoDescriptor GetExtraTypeInfo() const { return ROOT::RExtraTypeInfoDescriptor(); }
0510
0511
0512 void Attach(std::unique_ptr<RFieldBase> child);
0513
0514
0515
0516
0517
0518
0519
0520 virtual std::unique_ptr<RFieldBase> BeforeConnectPageSource(ROOT::Internal::RPageSource & )
0521 {
0522 return nullptr;
0523 }
0524
0525
0526
0527
0528 virtual void ReconcileOnDiskField(const RNTupleDescriptor &desc);
0529
0530
0531
0532 std::uint32_t CompareOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits) const;
0533
0534
0535
0536 RResult<void> EnsureMatchingOnDiskField(const RNTupleDescriptor &desc, std::uint32_t ignoreBits = 0) const;
0537
0538
0539 RResult<void>
0540 EnsureMatchingTypePrefix(const RNTupleDescriptor &desc, const std::vector<std::string> &prefixes) const;
0541
0542
0543
0544
0545 static RResult<std::unique_ptr<RFieldBase>>
0546 Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options,
0547 const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId);
0548
0549 public:
0550 template <bool IsConstT>
0551 class RSchemaIteratorTemplate;
0552 using RSchemaIterator = RSchemaIteratorTemplate<false>;
0553 using RConstSchemaIterator = RSchemaIteratorTemplate<true>;
0554
0555
0556 template <typename T>
0557 struct RCreateObjectDeleter {
0558 using deleter = std::default_delete<T>;
0559 };
0560
0561
0562 struct RCheckResult {
0563 std::string fFieldName;
0564 std::string fTypeName;
0565 std::string fErrMsg;
0566 };
0567
0568
0569
0570
0571 RFieldBase(std::string_view name, std::string_view type, ROOT::ENTupleStructure structure, bool isSimple,
0572 std::size_t nRepetitions = 0);
0573 RFieldBase(const RFieldBase &) = delete;
0574 RFieldBase(RFieldBase &&) = default;
0575 RFieldBase &operator=(const RFieldBase &) = delete;
0576 RFieldBase &operator=(RFieldBase &&) = default;
0577 virtual ~RFieldBase() = default;
0578
0579
0580 std::unique_ptr<RFieldBase> Clone(std::string_view newName) const;
0581
0582
0583
0584
0585 static RResult<std::unique_ptr<RFieldBase>>
0586 Create(const std::string &fieldName, const std::string &typeName);
0587
0588
0589
0590 static std::vector<RCheckResult> Check(const std::string &fieldName, const std::string &typeName);
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603 template <typename T>
0604 std::unique_ptr<T, typename RCreateObjectDeleter<T>::deleter> CreateObject() const;
0605
0606
0607 RValue CreateValue();
0608
0609
0610
0611 RBulkValues CreateBulk();
0612
0613 RValue BindValue(std::shared_ptr<void> objPtr);
0614
0615
0616
0617 virtual std::vector<RValue> SplitValue(const RValue &value) const;
0618
0619 virtual size_t GetValueSize() const = 0;
0620
0621
0622 virtual size_t GetAlignment() const = 0;
0623 std::uint32_t GetTraits() const { return fTraits; }
0624 bool HasReadCallbacks() const { return !fReadCallbacks.empty(); }
0625
0626 const std::string &GetFieldName() const { return fName; }
0627
0628 std::string GetQualifiedFieldName() const;
0629 const std::string &GetTypeName() const { return fType; }
0630 const std::string &GetTypeAlias() const { return fTypeAlias; }
0631 ROOT::ENTupleStructure GetStructure() const { return fStructure; }
0632 std::size_t GetNRepetitions() const { return fNRepetitions; }
0633 const RFieldBase *GetParent() const { return fParent; }
0634 std::vector<RFieldBase *> GetMutableSubfields();
0635 std::vector<const RFieldBase *> GetConstSubfields() const;
0636 bool IsSimple() const { return fIsSimple; }
0637 bool IsArtificial() const { return fIsArtificial; }
0638
0639 const std::string &GetDescription() const { return fDescription; }
0640 void SetDescription(std::string_view description);
0641 EState GetState() const { return fState; }
0642
0643 ROOT::DescriptorId_t GetOnDiskId() const { return fOnDiskId; }
0644 void SetOnDiskId(ROOT::DescriptorId_t id);
0645
0646
0647
0648 RColumnRepresentations::Selection_t GetColumnRepresentatives() const;
0649
0650
0651
0652 void SetColumnRepresentatives(const RColumnRepresentations::Selection_t &representatives);
0653
0654 bool HasDefaultColumnRepresentative() const { return fColumnRepresentatives.empty(); }
0655
0656
0657 virtual std::uint32_t GetFieldVersion() const { return 0; }
0658
0659 virtual std::uint32_t GetTypeVersion() const { return 0; }
0660
0661 virtual std::uint32_t GetTypeChecksum() const { return 0; }
0662
0663 std::uint32_t GetOnDiskTypeVersion() const { return fOnDiskTypeVersion; }
0664
0665
0666 std::uint32_t GetOnDiskTypeChecksum() const { return fOnDiskTypeChecksum; }
0667
0668 RSchemaIterator begin();
0669 RSchemaIterator end();
0670 RConstSchemaIterator begin() const;
0671 RConstSchemaIterator end() const;
0672 RConstSchemaIterator cbegin() const;
0673 RConstSchemaIterator cend() const;
0674
0675 virtual void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const;
0676 };
0677
0678
0679 template <bool IsConstT>
0680 class RFieldBase::RSchemaIteratorTemplate {
0681 private:
0682 struct Position {
0683 using FieldPtr_t = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
0684 Position() : fFieldPtr(nullptr), fIdxInParent(-1) {}
0685 Position(FieldPtr_t fieldPtr, int idxInParent) : fFieldPtr(fieldPtr), fIdxInParent(idxInParent) {}
0686 FieldPtr_t fFieldPtr;
0687 int fIdxInParent;
0688 };
0689
0690 std::vector<Position> fStack;
0691
0692 public:
0693 using iterator = RSchemaIteratorTemplate<IsConstT>;
0694 using iterator_category = std::forward_iterator_tag;
0695 using difference_type = std::ptrdiff_t;
0696 using value_type = std::conditional_t<IsConstT, const RFieldBase, RFieldBase>;
0697 using pointer = std::conditional_t<IsConstT, const RFieldBase *, RFieldBase *>;
0698 using reference = std::conditional_t<IsConstT, const RFieldBase &, RFieldBase &>;
0699
0700 RSchemaIteratorTemplate() { fStack.emplace_back(Position()); }
0701 RSchemaIteratorTemplate(pointer val, int idxInParent) { fStack.emplace_back(Position(val, idxInParent)); }
0702 ~RSchemaIteratorTemplate() {}
0703
0704
0705 void Advance()
0706 {
0707 auto itr = fStack.rbegin();
0708 if (!itr->fFieldPtr->fSubfields.empty()) {
0709 fStack.emplace_back(Position(itr->fFieldPtr->fSubfields[0].get(), 0));
0710 return;
0711 }
0712
0713 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
0714 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubfields.size()) {
0715 if (fStack.size() == 1) {
0716 itr->fFieldPtr = itr->fFieldPtr->fParent;
0717 itr->fIdxInParent = -1;
0718 return;
0719 }
0720 fStack.pop_back();
0721 itr = fStack.rbegin();
0722 nextIdxInParent = ++(itr->fIdxInParent);
0723 }
0724 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubfields[nextIdxInParent].get();
0725 }
0726
0727 iterator operator++(int)
0728 {
0729 auto r = *this;
0730 Advance();
0731 return r;
0732 }
0733 iterator &operator++()
0734 {
0735 Advance();
0736 return *this;
0737 }
0738 reference operator*() const { return *fStack.back().fFieldPtr; }
0739 pointer operator->() const { return fStack.back().fFieldPtr; }
0740 bool operator==(const iterator &rh) const { return fStack.back().fFieldPtr == rh.fStack.back().fFieldPtr; }
0741 bool operator!=(const iterator &rh) const { return fStack.back().fFieldPtr != rh.fStack.back().fFieldPtr; }
0742 };
0743
0744
0745
0746
0747 class RFieldBase::RValue final {
0748 friend class RFieldBase;
0749 friend class ROOT::REntry;
0750
0751 private:
0752 RFieldBase *fField = nullptr;
0753
0754 std::shared_ptr<void> fObjPtr;
0755 mutable std::atomic<const std::type_info *> fTypeInfo = nullptr;
0756
0757 RValue(RFieldBase *field, std::shared_ptr<void> objPtr) : fField(field), fObjPtr(objPtr) {}
0758
0759 public:
0760 RValue(const RValue &other) : fField(other.fField), fObjPtr(other.fObjPtr) {}
0761 RValue &operator=(const RValue &other)
0762 {
0763 fField = other.fField;
0764 fObjPtr = other.fObjPtr;
0765
0766 fTypeInfo = nullptr;
0767 return *this;
0768 }
0769 RValue(RValue &&other) : fField(other.fField), fObjPtr(other.fObjPtr) {}
0770 RValue &operator=(RValue &&other)
0771 {
0772 fField = other.fField;
0773 fObjPtr = other.fObjPtr;
0774
0775 fTypeInfo = nullptr;
0776 return *this;
0777 }
0778 ~RValue() = default;
0779
0780 private:
0781 template <typename T>
0782 void EnsureMatchingType() const
0783 {
0784 if constexpr (!std::is_void_v<T>) {
0785 const std::type_info &ti = typeid(T);
0786
0787
0788 auto *cachedTypeInfo = fTypeInfo.load();
0789 if (cachedTypeInfo != nullptr && *cachedTypeInfo == ti) {
0790 return;
0791 }
0792 std::string renormalizedTypeName = Internal::GetRenormalizedTypeName(ti);
0793 if (Internal::IsMatchingFieldType(fField->GetTypeName(), renormalizedTypeName, ti)) {
0794 fTypeInfo.store(&ti);
0795 return;
0796 }
0797 throw RException(R__FAIL("type mismatch for field \"" + fField->GetFieldName() + "\": expected " +
0798 fField->GetTypeName() + ", got " + renormalizedTypeName));
0799 }
0800 }
0801
0802 std::size_t Append() { return fField->Append(fObjPtr.get()); }
0803
0804 public:
0805 void Read(ROOT::NTupleSize_t globalIndex) { fField->Read(globalIndex, fObjPtr.get()); }
0806 void Read(RNTupleLocalIndex localIndex) { fField->Read(localIndex, fObjPtr.get()); }
0807
0808 void Bind(std::shared_ptr<void> objPtr) { fObjPtr = objPtr; }
0809 void BindRawPtr(void *rawPtr);
0810
0811 void EmplaceNew() { fObjPtr = fField->CreateValue().GetPtr<void>(); }
0812
0813 template <typename T>
0814 std::shared_ptr<T> GetPtr() const
0815 {
0816 EnsureMatchingType<T>();
0817 return std::static_pointer_cast<T>(fObjPtr);
0818 }
0819
0820 template <typename T>
0821 const T &GetRef() const
0822 {
0823 EnsureMatchingType<T>();
0824 return *static_cast<T *>(fObjPtr.get());
0825 }
0826
0827 const RFieldBase &GetField() const { return *fField; }
0828 };
0829
0830
0831
0832 struct RFieldBase::RBulkSpec {
0833
0834
0835 static const std::size_t kAllSet = std::size_t(-1);
0836
0837 RNTupleLocalIndex fFirstIndex;
0838 std::size_t fCount = 0;
0839
0840 const bool *fMaskReq = nullptr;
0841 bool *fMaskAvail = nullptr;
0842
0843
0844 void *fValues = nullptr;
0845
0846
0847 std::vector<unsigned char> *fAuxData = nullptr;
0848 };
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863 class RFieldBase::RBulkValues final {
0864 private:
0865 friend class RFieldBase;
0866
0867 RFieldBase *fField = nullptr;
0868 std::unique_ptr<RFieldBase::RDeleter> fDeleter;
0869 void *fValues = nullptr;
0870 std::size_t fValueSize = 0;
0871 std::size_t fCapacity = 0;
0872 std::size_t fSize = 0;
0873 bool fIsAdopted = false;
0874 std::unique_ptr<bool[]> fMaskAvail;
0875 std::size_t fNValidValues = 0;
0876 RNTupleLocalIndex fFirstIndex;
0877
0878
0879
0880 std::vector<unsigned char> fAuxData;
0881
0882 void ReleaseValues();
0883
0884
0885 void Reset(RNTupleLocalIndex firstIndex, std::size_t size);
0886
0887 bool ContainsRange(RNTupleLocalIndex firstIndex, std::size_t size) const
0888 {
0889 if (firstIndex.GetClusterId() != fFirstIndex.GetClusterId())
0890 return false;
0891 return (firstIndex.GetIndexInCluster() >= fFirstIndex.GetIndexInCluster()) &&
0892 ((firstIndex.GetIndexInCluster() + size) <= (fFirstIndex.GetIndexInCluster() + fSize));
0893 }
0894
0895 void *GetValuePtrAt(std::size_t idx) const { return reinterpret_cast<unsigned char *>(fValues) + idx * fValueSize; }
0896
0897 explicit RBulkValues(RFieldBase *field)
0898 : fField(field), fDeleter(field->GetDeleter()), fValueSize(field->GetValueSize())
0899 {
0900 }
0901
0902 public:
0903 ~RBulkValues();
0904 RBulkValues(const RBulkValues &) = delete;
0905 RBulkValues &operator=(const RBulkValues &) = delete;
0906 RBulkValues(RBulkValues &&other);
0907 RBulkValues &operator=(RBulkValues &&other);
0908
0909
0910
0911 void AdoptBuffer(void *buf, std::size_t capacity);
0912
0913
0914
0915
0916
0917 void *ReadBulk(RNTupleLocalIndex firstIndex, const bool *maskReq, std::size_t size)
0918 {
0919 if (!ContainsRange(firstIndex, size))
0920 Reset(firstIndex, size);
0921
0922
0923 auto offset = firstIndex.GetIndexInCluster() - fFirstIndex.GetIndexInCluster();
0924
0925 if (fNValidValues == fSize)
0926 return GetValuePtrAt(offset);
0927
0928 RBulkSpec bulkSpec;
0929 bulkSpec.fFirstIndex = firstIndex;
0930 bulkSpec.fCount = size;
0931 bulkSpec.fMaskReq = maskReq;
0932 bulkSpec.fMaskAvail = &fMaskAvail[offset];
0933 bulkSpec.fValues = GetValuePtrAt(offset);
0934 bulkSpec.fAuxData = &fAuxData;
0935 auto nRead = fField->ReadBulk(bulkSpec);
0936 if (nRead == RBulkSpec::kAllSet) {
0937
0938
0939
0940
0941
0942
0943 R__ASSERT((offset == 0) && (size == fSize));
0944 fNValidValues = fSize;
0945 } else {
0946 fNValidValues += nRead;
0947 }
0948 return GetValuePtrAt(offset);
0949 }
0950
0951
0952 void *ReadBulk(ROOT::RNTupleLocalRange range) { return ReadBulk(*range.begin(), nullptr, range.size()); }
0953 };
0954
0955 namespace Internal {
0956
0957
0958 struct RFieldRepresentationModifier {
0959 static void SetPrimaryColumnRepresentation(RFieldBase &field, std::uint16_t newRepresentationIdx)
0960 {
0961 R__ASSERT(newRepresentationIdx < field.fColumnRepresentatives.size());
0962 const auto N = field.fColumnRepresentatives[0].get().size();
0963 R__ASSERT(N >= 1 && N <= 2);
0964 R__ASSERT(field.fPrincipalColumn);
0965 field.fPrincipalColumn = field.fAvailableColumns[newRepresentationIdx * N].get();
0966 if (field.fAuxiliaryColumn) {
0967 R__ASSERT(N == 2);
0968 field.fAuxiliaryColumn = field.fAvailableColumns[newRepresentationIdx * N + 1].get();
0969 }
0970 }
0971 };
0972 }
0973 }
0974
0975 #endif