File indexing completed on 2025-12-27 11:37:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RNTupleView
0015 #define ROOT_RNTupleView
0016
0017 #include <ROOT/RError.hxx>
0018 #include <ROOT/RField.hxx>
0019 #include <ROOT/RNTupleRange.hxx>
0020 #include <ROOT/RNTupleTypes.hxx>
0021 #include <ROOT/RNTupleUtils.hxx>
0022 #include <string_view>
0023
0024 #include <iterator>
0025 #include <memory>
0026 #include <type_traits>
0027 #include <utility>
0028 #include <unordered_map>
0029
0030 namespace ROOT {
0031
0032 class RNTupleReader;
0033
0034 namespace Internal {
0035
0036
0037
0038
0039
0040
0041 ROOT::RNTupleGlobalRange GetFieldRange(const ROOT::RFieldBase &field, const ROOT::Internal::RPageSource &pageSource);
0042
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 template <typename T>
0083 class RNTupleViewBase {
0084 protected:
0085 std::unique_ptr<ROOT::RFieldBase> fField;
0086 ROOT::RNTupleGlobalRange fFieldRange;
0087 ROOT::RFieldBase::RValue fValue;
0088
0089 static std::unique_ptr<ROOT::RFieldBase>
0090 CreateField(ROOT::DescriptorId_t fieldId, Internal::RPageSource &pageSource, std::string_view typeName = "")
0091 {
0092 RFieldZero fieldZero;
0093 Internal::SetAllowFieldSubstitutions(fieldZero, true);
0094 std::unique_ptr<ROOT::RFieldBase> field;
0095 {
0096 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
0097 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0098 if constexpr (std::is_void_v<T>) {
0099 if (typeName.empty())
0100 field = fieldDesc.CreateField(desc);
0101 else
0102 field = ROOT::RFieldBase::Create(fieldDesc.GetFieldName(), std::string(typeName)).Unwrap();
0103 } else {
0104 field = std::make_unique<ROOT::RField<T>>(fieldDesc.GetFieldName());
0105 }
0106 }
0107 field->SetOnDiskId(fieldId);
0108 fieldZero.Attach(std::move(field));
0109 ROOT::Internal::CallConnectPageSourceOnField(fieldZero, pageSource);
0110 return std::move(fieldZero.ReleaseSubfields()[0]);
0111 }
0112
0113 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0114 : fField(std::move(field)), fFieldRange(range), fValue(fField->CreateValue())
0115 {
0116 }
0117
0118 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
0119 : fField(std::move(field)), fFieldRange(range), fValue(fField->BindValue(objPtr))
0120 {
0121 }
0122
0123 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, T *rawPtr)
0124 : fField(std::move(field)),
0125 fFieldRange(range),
0126 fValue(fField->BindValue(ROOT::Internal::MakeAliasedSharedPtr(rawPtr)))
0127 {
0128 }
0129
0130 public:
0131 RNTupleViewBase(const RNTupleViewBase &other) = delete;
0132 RNTupleViewBase(RNTupleViewBase &&other) = default;
0133 RNTupleViewBase &operator=(const RNTupleViewBase &other) = delete;
0134 RNTupleViewBase &operator=(RNTupleViewBase &&other) = default;
0135 ~RNTupleViewBase() = default;
0136
0137 const ROOT::RFieldBase &GetField() const { return *fField; }
0138 ROOT::RFieldBase::RBulkValues CreateBulk() { return fField->CreateBulk(); }
0139
0140 const ROOT::RFieldBase::RValue &GetValue() const { return fValue; }
0141
0142
0143
0144
0145
0146 ROOT::RNTupleGlobalRange GetFieldRange() const
0147 {
0148 if (!fFieldRange.IsValid()) {
0149 throw RException(R__FAIL("field iteration over empty fields is unsupported: " + fField->GetFieldName()));
0150 }
0151 return fFieldRange;
0152 }
0153
0154 void Bind(std::shared_ptr<T> objPtr) { fValue.Bind(objPtr); }
0155 void BindRawPtr(T *rawPtr) { fValue.BindRawPtr(rawPtr); }
0156 void EmplaceNew() { fValue.EmplaceNew(); }
0157 };
0158
0159
0160
0161
0162
0163
0164
0165
0166 template <typename T>
0167 class RNTupleView : public RNTupleViewBase<T> {
0168 friend class ROOT::RNTupleReader;
0169 friend class RNTupleCollectionView;
0170
0171 protected:
0172 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0173 : RNTupleViewBase<T>(std::move(field), range)
0174 {
0175 }
0176
0177 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
0178 : RNTupleViewBase<T>(std::move(field), range, objPtr)
0179 {
0180 }
0181
0182 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, T *rawPtr)
0183 : RNTupleViewBase<T>(std::move(field), range, rawPtr)
0184 {
0185 }
0186
0187 const T &GetValueRef() const
0188 {
0189
0190 void *ptr = RNTupleViewBase<T>::fValue.template GetPtr<void>().get();
0191 return *static_cast<T *>(ptr);
0192 }
0193
0194 public:
0195 RNTupleView(const RNTupleView &other) = delete;
0196 RNTupleView(RNTupleView &&other) = default;
0197 RNTupleView &operator=(const RNTupleView &other) = delete;
0198 RNTupleView &operator=(RNTupleView &&other) = default;
0199 ~RNTupleView() = default;
0200
0201
0202 const T &operator()(ROOT::NTupleSize_t globalIndex)
0203 {
0204 RNTupleViewBase<T>::fValue.Read(globalIndex);
0205 return GetValueRef();
0206 }
0207
0208
0209
0210 const T &operator()(RNTupleLocalIndex localIndex)
0211 {
0212 RNTupleViewBase<T>::fValue.Read(localIndex);
0213 return GetValueRef();
0214 }
0215 };
0216
0217
0218
0219
0220
0221
0222
0223
0224 template <>
0225 class RNTupleView<void> final : public RNTupleViewBase<void> {
0226 friend class ROOT::RNTupleReader;
0227 friend class RNTupleCollectionView;
0228
0229 protected:
0230 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0231 : RNTupleViewBase<void>(std::move(field), range)
0232 {
0233 }
0234
0235 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<void> objPtr)
0236 : RNTupleViewBase<void>(std::move(field), range, objPtr)
0237 {
0238 }
0239
0240 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, void *rawPtr)
0241 : RNTupleViewBase<void>(std::move(field), range, rawPtr)
0242 {
0243 }
0244
0245 public:
0246 RNTupleView(const RNTupleView &other) = delete;
0247 RNTupleView(RNTupleView &&other) = default;
0248 RNTupleView &operator=(const RNTupleView &other) = delete;
0249 RNTupleView &operator=(RNTupleView &&other) = default;
0250 ~RNTupleView() = default;
0251
0252
0253 void operator()(ROOT::NTupleSize_t globalIndex) { fValue.Read(globalIndex); }
0254
0255 void operator()(RNTupleLocalIndex localIndex) { fValue.Read(localIndex); }
0256 };
0257
0258
0259
0260
0261
0262
0263
0264
0265 template <typename T>
0266 class RNTupleDirectAccessView {
0267 friend class ROOT::RNTupleReader;
0268 friend class RNTupleCollectionView;
0269
0270 protected:
0271 ROOT::RField<T> fField;
0272 ROOT::RNTupleGlobalRange fFieldRange;
0273
0274 static ROOT::RField<T> CreateField(ROOT::DescriptorId_t fieldId, ROOT::Internal::RPageSource &pageSource)
0275 {
0276 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
0277 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0278 if (!Internal::IsMatchingFieldType<T>(fieldDesc.GetTypeName())) {
0279 throw RException(R__FAIL("type mismatch for field " + fieldDesc.GetFieldName() + ": " +
0280 fieldDesc.GetTypeName() + " vs. " + ROOT::RField<T>::TypeName()));
0281 }
0282 ROOT::RField<T> field(fieldDesc.GetFieldName());
0283 field.SetOnDiskId(fieldId);
0284 ROOT::Internal::CallConnectPageSourceOnField(field, pageSource);
0285 return field;
0286 }
0287
0288 RNTupleDirectAccessView(ROOT::RField<T> field, ROOT::RNTupleGlobalRange range)
0289 : fField(std::move(field)), fFieldRange(range)
0290 {
0291 }
0292
0293 public:
0294 RNTupleDirectAccessView(const RNTupleDirectAccessView &other) = delete;
0295 RNTupleDirectAccessView(RNTupleDirectAccessView &&other) = default;
0296 RNTupleDirectAccessView &operator=(const RNTupleDirectAccessView &other) = delete;
0297 RNTupleDirectAccessView &operator=(RNTupleDirectAccessView &&other) = default;
0298 ~RNTupleDirectAccessView() = default;
0299
0300 const ROOT::RFieldBase &GetField() const { return fField; }
0301
0302 ROOT::RNTupleGlobalRange GetFieldRange() const { return fFieldRange; }
0303
0304
0305 const T &operator()(ROOT::NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
0306
0307 const T &operator()(RNTupleLocalIndex localIndex) { return *fField.Map(localIndex); }
0308 };
0309
0310
0311
0312
0313
0314
0315
0316
0317 class RNTupleCollectionView {
0318 friend class ROOT::RNTupleReader;
0319
0320 private:
0321 ROOT::Internal::RPageSource *fSource;
0322 ROOT::RField<RNTupleCardinality<std::uint64_t>> fField;
0323 ROOT::RFieldBase::RValue fValue;
0324
0325 RNTupleCollectionView(ROOT::DescriptorId_t fieldId, const std::string &fieldName,
0326 ROOT::Internal::RPageSource *source)
0327 : fSource(source), fField(fieldName), fValue(fField.CreateValue())
0328 {
0329 fField.SetOnDiskId(fieldId);
0330 ROOT::Internal::CallConnectPageSourceOnField(fField, *source);
0331 }
0332
0333 static RNTupleCollectionView Create(ROOT::DescriptorId_t fieldId, ROOT::Internal::RPageSource *source)
0334 {
0335 std::string fieldName;
0336 {
0337 const auto &desc = source->GetSharedDescriptorGuard().GetRef();
0338 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0339 if (fieldDesc.GetStructure() != ROOT::ENTupleStructure::kCollection) {
0340 throw RException(
0341 R__FAIL("invalid attemt to create collection view on non-collection field " + fieldDesc.GetFieldName()));
0342 }
0343 fieldName = fieldDesc.GetFieldName();
0344 }
0345 return RNTupleCollectionView(fieldId, fieldName, source);
0346 }
0347
0348 ROOT::DescriptorId_t GetFieldId(std::string_view fieldName)
0349 {
0350 auto descGuard = fSource->GetSharedDescriptorGuard();
0351 auto fieldId = descGuard->FindFieldId(fieldName, fField.GetOnDiskId());
0352 if (fieldId == ROOT::kInvalidDescriptorId) {
0353 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in collection '" +
0354 descGuard->GetQualifiedFieldName(fField.GetOnDiskId()) + "'"));
0355 }
0356 return fieldId;
0357 }
0358
0359 std::uint64_t GetCardinalityValue() const
0360 {
0361
0362 void *ptr = fValue.GetPtr<void>().get();
0363 return *static_cast<RNTupleCardinality<std::uint64_t> *>(ptr);
0364 }
0365
0366 public:
0367 RNTupleCollectionView(const RNTupleCollectionView &other) = delete;
0368 RNTupleCollectionView &operator=(const RNTupleCollectionView &other) = delete;
0369 RNTupleCollectionView(RNTupleCollectionView &&other)
0370 : fSource(other.fSource), fField(std::move(other.fField)), fValue(fField.CreateValue())
0371 {
0372 }
0373 RNTupleCollectionView &operator=(RNTupleCollectionView &&other)
0374 {
0375 if (this == &other)
0376 return *this;
0377 std::swap(fSource, other.fSource);
0378 std::swap(fField, other.fField);
0379 fValue = fField.CreateValue();
0380 return *this;
0381 }
0382 ~RNTupleCollectionView() = default;
0383
0384 ROOT::RNTupleLocalRange GetCollectionRange(ROOT::NTupleSize_t globalIndex)
0385 {
0386 ROOT::NTupleSize_t size;
0387 RNTupleLocalIndex collectionStart;
0388 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
0389 return ROOT::RNTupleLocalRange(collectionStart.GetClusterId(), collectionStart.GetIndexInCluster(),
0390 collectionStart.GetIndexInCluster() + size);
0391 }
0392
0393 ROOT::RNTupleLocalRange GetCollectionRange(RNTupleLocalIndex localIndex)
0394 {
0395 ROOT::NTupleSize_t size;
0396 RNTupleLocalIndex collectionStart;
0397 fField.GetCollectionInfo(localIndex, &collectionStart, &size);
0398 return ROOT::RNTupleLocalRange(collectionStart.GetClusterId(), collectionStart.GetIndexInCluster(),
0399 collectionStart.GetIndexInCluster() + size);
0400 }
0401
0402
0403
0404
0405
0406
0407 template <typename T>
0408 RNTupleView<T> GetView(std::string_view fieldName)
0409 {
0410 auto field = RNTupleView<T>::CreateField(GetFieldId(fieldName), *fSource);
0411 auto range = Internal::GetFieldRange(*field, *fSource);
0412 return RNTupleView<T>(std::move(field), range);
0413 }
0414
0415
0416
0417
0418
0419
0420
0421 template <typename T>
0422 RNTupleDirectAccessView<T> GetDirectAccessView(std::string_view fieldName)
0423 {
0424 auto field = RNTupleDirectAccessView<T>::CreateField(GetFieldId(fieldName), *fSource);
0425 auto range = Internal::GetFieldRange(field, *fSource);
0426 return RNTupleDirectAccessView<T>(std::move(field), range);
0427 }
0428
0429
0430
0431
0432
0433
0434
0435
0436 RNTupleCollectionView GetCollectionView(std::string_view fieldName)
0437 {
0438 return RNTupleCollectionView::Create(GetFieldId(fieldName), fSource);
0439 }
0440
0441
0442 std::uint64_t operator()(ROOT::NTupleSize_t globalIndex)
0443 {
0444 fValue.Read(globalIndex);
0445 return GetCardinalityValue();
0446 }
0447
0448
0449 std::uint64_t operator()(RNTupleLocalIndex localIndex)
0450 {
0451 fValue.Read(localIndex);
0452 return GetCardinalityValue();
0453 }
0454 };
0455
0456 }
0457
0458 #endif