File indexing completed on 2025-01-18 10:10:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef ROOT7_RNTupleView
0017 #define ROOT7_RNTupleView
0018
0019 #include <ROOT/RField.hxx>
0020 #include <ROOT/RNTupleUtil.hxx>
0021 #include <string_view>
0022
0023 #include <iterator>
0024 #include <memory>
0025 #include <type_traits>
0026 #include <utility>
0027 #include <unordered_map>
0028
0029 namespace ROOT {
0030 namespace Experimental {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 class RNTupleGlobalRange {
0041 private:
0042 const NTupleSize_t fStart;
0043 const NTupleSize_t fEnd;
0044 public:
0045 class RIterator {
0046 private:
0047 NTupleSize_t fIndex = kInvalidNTupleIndex;
0048 public:
0049 using iterator = RIterator;
0050 using iterator_category = std::forward_iterator_tag;
0051 using value_type = NTupleSize_t;
0052 using difference_type = NTupleSize_t;
0053 using pointer = NTupleSize_t*;
0054 using reference = NTupleSize_t&;
0055
0056 RIterator() = default;
0057 explicit RIterator(NTupleSize_t index) : fIndex(index) {}
0058 ~RIterator() = default;
0059
0060 iterator operator++(int) { auto r = *this; fIndex++; return r; }
0061 iterator& operator++() { ++fIndex; return *this; }
0062 reference operator* () { return fIndex; }
0063 pointer operator->() { return &fIndex; }
0064 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
0065 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
0066 };
0067
0068 RNTupleGlobalRange(NTupleSize_t start, NTupleSize_t end) : fStart(start), fEnd(end) {}
0069 RIterator begin() { return RIterator(fStart); }
0070 RIterator end() { return RIterator(fEnd); }
0071 };
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 class RNTupleClusterRange {
0082 private:
0083 const DescriptorId_t fClusterId;
0084 const ClusterSize_t::ValueType fStart;
0085 const ClusterSize_t::ValueType fEnd;
0086 public:
0087 class RIterator {
0088 private:
0089 RClusterIndex fIndex;
0090 public:
0091 using iterator = RIterator;
0092 using iterator_category = std::forward_iterator_tag;
0093 using value_type = RClusterIndex;
0094 using difference_type = RClusterIndex;
0095 using pointer = RClusterIndex*;
0096 using reference = RClusterIndex&;
0097
0098 RIterator() = default;
0099 explicit RIterator(RClusterIndex index) : fIndex(index) {}
0100 ~RIterator() = default;
0101
0102 iterator operator++(int) { auto r = *this; fIndex++; return r; }
0103 iterator& operator++() { fIndex++; return *this; }
0104 reference operator* () { return fIndex; }
0105 pointer operator->() { return &fIndex; }
0106 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
0107 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
0108 };
0109
0110 RNTupleClusterRange(DescriptorId_t clusterId, ClusterSize_t::ValueType start, ClusterSize_t::ValueType end)
0111 : fClusterId(clusterId), fStart(start), fEnd(end) {}
0112 RIterator begin() { return RIterator(RClusterIndex(fClusterId, fStart)); }
0113 RIterator end() { return RIterator(RClusterIndex(fClusterId, fEnd)); }
0114 };
0115
0116
0117 namespace Internal {
0118
0119 template <typename FieldT, typename SFINAE = void>
0120 inline constexpr bool isMappable = false;
0121
0122 template <typename FieldT>
0123 inline constexpr bool isMappable<FieldT, std::void_t<decltype(std::declval<FieldT>().Map(NTupleSize_t{}))>> = true;
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 template <typename T, bool UserProvidedAddress>
0144 class RNTupleView {
0145 friend class RNTupleReader;
0146 friend class RNTupleCollectionView;
0147
0148 using FieldT = RField<T>;
0149
0150 private:
0151
0152 FieldT fField;
0153
0154 RFieldBase::RValue fValue;
0155
0156 void SetupField(DescriptorId_t fieldId, Internal::RPageSource *pageSource)
0157 {
0158 fField.SetOnDiskId(fieldId);
0159 Internal::CallConnectPageSourceOnField(fField, *pageSource);
0160 if constexpr (!UserProvidedAddress) {
0161 if ((fField.GetTraits() & RFieldBase::kTraitMappable) && fField.HasReadCallbacks())
0162 throw RException(R__FAIL("view disallowed on field with mappable type and read callback"));
0163 }
0164 }
0165
0166 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource)
0167 : fField(pageSource->GetSharedDescriptorGuard()->GetFieldDescriptor(fieldId).GetFieldName()),
0168 fValue(fField.CreateValue())
0169 {
0170 SetupField(fieldId, pageSource);
0171 }
0172
0173 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource, std::shared_ptr<T> objPtr)
0174 : fField(pageSource->GetSharedDescriptorGuard()->GetFieldDescriptor(fieldId).GetFieldName()),
0175 fValue(fField.BindValue(objPtr))
0176 {
0177 SetupField(fieldId, pageSource);
0178 }
0179
0180 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource, T *rawPtr)
0181 : fField(pageSource->GetSharedDescriptorGuard()->GetFieldDescriptor(fieldId).GetFieldName()),
0182 fValue(fField.BindValue(Internal::MakeAliasedSharedPtr(rawPtr)))
0183 {
0184 SetupField(fieldId, pageSource);
0185 }
0186
0187 public:
0188 RNTupleView(const RNTupleView& other) = delete;
0189 RNTupleView(RNTupleView&& other) = default;
0190 RNTupleView& operator=(const RNTupleView& other) = delete;
0191 RNTupleView& operator=(RNTupleView&& other) = default;
0192 ~RNTupleView() = default;
0193
0194 const FieldT &GetField() const { return fField; }
0195 RNTupleGlobalRange GetFieldRange() const { return RNTupleGlobalRange(0, fField.GetNElements()); }
0196
0197 const T &operator()(NTupleSize_t globalIndex)
0198 {
0199 if constexpr (Internal::isMappable<FieldT> && !UserProvidedAddress) {
0200 return *fField.Map(globalIndex);
0201 } else {
0202 fValue.Read(globalIndex);
0203 return fValue.GetRef<T>();
0204 }
0205 }
0206
0207 const T &operator()(RClusterIndex clusterIndex)
0208 {
0209 if constexpr (Internal::isMappable<FieldT> && !UserProvidedAddress) {
0210 return *fField.Map(clusterIndex);
0211 } else {
0212 fValue.Read(clusterIndex);
0213 return fValue.GetRef<T>();
0214 }
0215 }
0216
0217
0218 template <typename C = T, std::enable_if_t<Internal::isMappable<FieldT>, C*> = nullptr>
0219 const C *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
0220 {
0221 return fField.MapV(globalIndex, nItems);
0222 }
0223
0224
0225 template <typename C = T, std::enable_if_t<Internal::isMappable<FieldT>, C *> = nullptr>
0226 const C *MapV(RClusterIndex clusterIndex, NTupleSize_t &nItems)
0227 {
0228 return fField.MapV(clusterIndex, nItems);
0229 }
0230
0231 void Bind(std::shared_ptr<T> objPtr)
0232 {
0233 static_assert(
0234 UserProvidedAddress,
0235 "Only views which were created with an external memory location at construction time can be bound to a "
0236 "different memory location afterwards. Call the RNTupleReader::GetView overload with a shared_ptr.");
0237 fValue.Bind(objPtr);
0238 }
0239
0240 void BindRawPtr(T *rawPtr)
0241 {
0242 static_assert(
0243 UserProvidedAddress,
0244 "Only views which were created with an external memory location at construction time can be bound to a "
0245 "different memory location afterwards. Call the RNTupleReader::GetView overload with a shared_ptr.");
0246 fValue.BindRawPtr(rawPtr);
0247 }
0248
0249 void EmplaceNew()
0250 {
0251
0252
0253
0254
0255 static_assert(!(Internal::isMappable<FieldT> && !UserProvidedAddress),
0256 "Cannot emplace a new value into a view of a mappable type, unless an external memory location is "
0257 "provided at construction time.");
0258 fValue.EmplaceNew();
0259 }
0260 };
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 template <bool UserProvidedAddress>
0273 class RNTupleView<void, UserProvidedAddress> {
0274 friend class RNTupleReader;
0275 friend class RNTupleCollectionView;
0276
0277 private:
0278 std::unique_ptr<RFieldBase> fField;
0279 RFieldBase::RValue fValue;
0280
0281 static std::unique_ptr<RFieldBase> CreateField(DescriptorId_t fieldId, const RNTupleDescriptor &desc)
0282 {
0283 return desc.GetFieldDescriptor(fieldId).CreateField(desc);
0284 }
0285
0286 void SetupField(DescriptorId_t fieldId, Internal::RPageSource *pageSource)
0287 {
0288 fField->SetOnDiskId(fieldId);
0289 Internal::CallConnectPageSourceOnField(*fField, *pageSource);
0290 }
0291
0292 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource)
0293 : fField(CreateField(fieldId, pageSource->GetSharedDescriptorGuard().GetRef())), fValue(fField->CreateValue())
0294 {
0295 SetupField(fieldId, pageSource);
0296 }
0297
0298 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource, std::shared_ptr<void> objPtr)
0299 : fField(CreateField(fieldId, pageSource->GetSharedDescriptorGuard().GetRef())), fValue(fField->BindValue(objPtr))
0300 {
0301 SetupField(fieldId, pageSource);
0302 }
0303
0304 RNTupleView(DescriptorId_t fieldId, Internal::RPageSource *pageSource, void *rawPtr)
0305 : fField(CreateField(fieldId, pageSource->GetSharedDescriptorGuard().GetRef())),
0306 fValue(fField->BindValue(Internal::MakeAliasedSharedPtr(rawPtr)))
0307 {
0308 SetupField(fieldId, pageSource);
0309 }
0310
0311 public:
0312 RNTupleView(const RNTupleView &other) = delete;
0313 RNTupleView(RNTupleView &&other) = default;
0314 RNTupleView &operator=(const RNTupleView &other) = delete;
0315 RNTupleView &operator=(RNTupleView &&other) = default;
0316 ~RNTupleView() = default;
0317
0318 const RFieldBase &GetField() const { return *fField; }
0319 const RFieldBase::RValue &GetValue() const { return fValue; }
0320 RNTupleGlobalRange GetFieldRange() const { return RNTupleGlobalRange(0, fField->GetNElements()); }
0321
0322 void operator()(NTupleSize_t globalIndex) { fValue.Read(globalIndex); }
0323 void operator()(RClusterIndex clusterIndex) { fValue.Read(clusterIndex); }
0324
0325 void Bind(std::shared_ptr<void> objPtr)
0326 {
0327 static_assert(
0328 UserProvidedAddress,
0329 "Only views which were created with an external memory location at construction time can be bound to a "
0330 "different memory location afterwards. Call the RNTupleReader::GetView overload with a shared_ptr.");
0331 fValue.Bind(objPtr);
0332 }
0333
0334 void BindRawPtr(void *rawPtr)
0335 {
0336 static_assert(
0337 UserProvidedAddress,
0338 "Only views which were created with an external memory location at construction time can be bound to a "
0339 "different memory location afterwards. Call the RNTupleReader::GetView overload with a shared_ptr.");
0340 fValue.BindRawPtr(rawPtr);
0341 }
0342
0343 void EmplaceNew() { fValue.EmplaceNew(); }
0344 };
0345
0346
0347
0348
0349
0350
0351
0352
0353 class RNTupleCollectionView : public RNTupleView<ClusterSize_t, false> {
0354 friend class RNTupleReader;
0355
0356 private:
0357 Internal::RPageSource *fSource;
0358 DescriptorId_t fCollectionFieldId;
0359
0360 RNTupleCollectionView(DescriptorId_t fieldId, Internal::RPageSource *source)
0361 : RNTupleView<ClusterSize_t, false>(fieldId, source), fSource(source), fCollectionFieldId(fieldId)
0362 {}
0363
0364 public:
0365 RNTupleCollectionView(const RNTupleCollectionView &other) = delete;
0366 RNTupleCollectionView(RNTupleCollectionView &&other) = default;
0367 RNTupleCollectionView &operator=(const RNTupleCollectionView &other) = delete;
0368 RNTupleCollectionView &operator=(RNTupleCollectionView &&other) = default;
0369 ~RNTupleCollectionView() = default;
0370
0371 RNTupleClusterRange GetCollectionRange(NTupleSize_t globalIndex) {
0372 ClusterSize_t size;
0373 RClusterIndex collectionStart;
0374 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
0375 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
0376 collectionStart.GetIndex() + size);
0377 }
0378 RNTupleClusterRange GetCollectionRange(RClusterIndex clusterIndex)
0379 {
0380 ClusterSize_t size;
0381 RClusterIndex collectionStart;
0382 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
0383 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
0384 collectionStart.GetIndex() + size);
0385 }
0386
0387
0388 template <typename T>
0389 RNTupleView<T, false> GetView(std::string_view fieldName)
0390 {
0391 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName, fCollectionFieldId);
0392 if (fieldId == kInvalidDescriptorId) {
0393 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" +
0394 fSource->GetSharedDescriptorGuard()->GetName() + "'"));
0395 }
0396 return RNTupleView<T, false>(fieldId, fSource);
0397 }
0398
0399 RNTupleCollectionView GetCollectionView(std::string_view fieldName)
0400 {
0401 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName, fCollectionFieldId);
0402 if (fieldId == kInvalidDescriptorId) {
0403 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" +
0404 fSource->GetSharedDescriptorGuard()->GetName() + "'"));
0405 }
0406 return RNTupleCollectionView(fieldId, fSource);
0407 }
0408
0409 ClusterSize_t operator()(NTupleSize_t globalIndex) {
0410 ClusterSize_t size;
0411 RClusterIndex collectionStart;
0412 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
0413 return size;
0414 }
0415 ClusterSize_t operator()(RClusterIndex clusterIndex)
0416 {
0417 ClusterSize_t size;
0418 RClusterIndex collectionStart;
0419 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
0420 return size;
0421 }
0422 };
0423
0424 }
0425 }
0426
0427 #endif