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