File indexing completed on 2025-10-18 09:24:18
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/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
0031 class RNTupleReader;
0032
0033 namespace Internal {
0034
0035
0036
0037
0038
0039
0040 ROOT::RNTupleGlobalRange GetFieldRange(const ROOT::RFieldBase &field, const ROOT::Internal::RPageSource &pageSource);
0041
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 template <typename T>
0082 class RNTupleViewBase {
0083 protected:
0084 std::unique_ptr<ROOT::RFieldBase> fField;
0085 ROOT::RNTupleGlobalRange fFieldRange;
0086 ROOT::RFieldBase::RValue fValue;
0087
0088 static std::unique_ptr<ROOT::RFieldBase>
0089 CreateField(ROOT::DescriptorId_t fieldId, Internal::RPageSource &pageSource, std::string_view typeName = "")
0090 {
0091 std::unique_ptr<ROOT::RFieldBase> field;
0092 {
0093 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
0094 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0095 if constexpr (std::is_void_v<T>) {
0096 if (typeName.empty())
0097 field = fieldDesc.CreateField(desc);
0098 else
0099 field = ROOT::RFieldBase::Create(fieldDesc.GetFieldName(), std::string(typeName)).Unwrap();
0100 } else {
0101 field = std::make_unique<ROOT::RField<T>>(fieldDesc.GetFieldName());
0102 }
0103 }
0104 field->SetOnDiskId(fieldId);
0105 ROOT::Internal::CallConnectPageSourceOnField(*field, pageSource);
0106 return field;
0107 }
0108
0109 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0110 : fField(std::move(field)), fFieldRange(range), fValue(fField->CreateValue())
0111 {
0112 }
0113
0114 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
0115 : fField(std::move(field)), fFieldRange(range), fValue(fField->BindValue(objPtr))
0116 {
0117 }
0118
0119 RNTupleViewBase(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, T *rawPtr)
0120 : fField(std::move(field)),
0121 fFieldRange(range),
0122 fValue(fField->BindValue(ROOT::Internal::MakeAliasedSharedPtr(rawPtr)))
0123 {
0124 }
0125
0126 public:
0127 RNTupleViewBase(const RNTupleViewBase &other) = delete;
0128 RNTupleViewBase(RNTupleViewBase &&other) = default;
0129 RNTupleViewBase &operator=(const RNTupleViewBase &other) = delete;
0130 RNTupleViewBase &operator=(RNTupleViewBase &&other) = default;
0131 ~RNTupleViewBase() = default;
0132
0133 const ROOT::RFieldBase &GetField() const { return *fField; }
0134 ROOT::RFieldBase::RBulkValues CreateBulk() { return fField->CreateBulk(); }
0135
0136 const ROOT::RFieldBase::RValue &GetValue() const { return fValue; }
0137
0138
0139
0140
0141
0142 ROOT::RNTupleGlobalRange GetFieldRange() const
0143 {
0144 if (!fFieldRange.IsValid()) {
0145 throw RException(R__FAIL("field iteration over empty fields is unsupported: " + fField->GetFieldName()));
0146 }
0147 return fFieldRange;
0148 }
0149
0150 void Bind(std::shared_ptr<T> objPtr) { fValue.Bind(objPtr); }
0151 void BindRawPtr(T *rawPtr) { fValue.BindRawPtr(rawPtr); }
0152 void EmplaceNew() { fValue.EmplaceNew(); }
0153 };
0154
0155
0156
0157
0158
0159
0160
0161
0162 template <typename T>
0163 class RNTupleView : public RNTupleViewBase<T> {
0164 friend class ROOT::RNTupleReader;
0165 friend class RNTupleCollectionView;
0166
0167 protected:
0168 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0169 : RNTupleViewBase<T>(std::move(field), range)
0170 {
0171 }
0172
0173 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
0174 : RNTupleViewBase<T>(std::move(field), range, objPtr)
0175 {
0176 }
0177
0178 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, T *rawPtr)
0179 : RNTupleViewBase<T>(std::move(field), range, rawPtr)
0180 {
0181 }
0182
0183 public:
0184 RNTupleView(const RNTupleView &other) = delete;
0185 RNTupleView(RNTupleView &&other) = default;
0186 RNTupleView &operator=(const RNTupleView &other) = delete;
0187 RNTupleView &operator=(RNTupleView &&other) = default;
0188 ~RNTupleView() = default;
0189
0190
0191 const T &operator()(ROOT::NTupleSize_t globalIndex)
0192 {
0193 RNTupleViewBase<T>::fValue.Read(globalIndex);
0194 return RNTupleViewBase<T>::fValue.template GetRef<T>();
0195 }
0196
0197
0198
0199 const T &operator()(RNTupleLocalIndex localIndex)
0200 {
0201 RNTupleViewBase<T>::fValue.Read(localIndex);
0202 return RNTupleViewBase<T>::fValue.template GetRef<T>();
0203 }
0204 };
0205
0206
0207
0208
0209
0210
0211
0212
0213 template <>
0214 class RNTupleView<void> final : public RNTupleViewBase<void> {
0215 friend class ROOT::RNTupleReader;
0216 friend class RNTupleCollectionView;
0217
0218 protected:
0219 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range)
0220 : RNTupleViewBase<void>(std::move(field), range)
0221 {
0222 }
0223
0224 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, std::shared_ptr<void> objPtr)
0225 : RNTupleViewBase<void>(std::move(field), range, objPtr)
0226 {
0227 }
0228
0229 RNTupleView(std::unique_ptr<ROOT::RFieldBase> field, ROOT::RNTupleGlobalRange range, void *rawPtr)
0230 : RNTupleViewBase<void>(std::move(field), range, rawPtr)
0231 {
0232 }
0233
0234 public:
0235 RNTupleView(const RNTupleView &other) = delete;
0236 RNTupleView(RNTupleView &&other) = default;
0237 RNTupleView &operator=(const RNTupleView &other) = delete;
0238 RNTupleView &operator=(RNTupleView &&other) = default;
0239 ~RNTupleView() = default;
0240
0241
0242 void operator()(ROOT::NTupleSize_t globalIndex) { fValue.Read(globalIndex); }
0243
0244 void operator()(RNTupleLocalIndex localIndex) { fValue.Read(localIndex); }
0245 };
0246
0247
0248
0249
0250
0251
0252
0253
0254 template <typename T>
0255 class RNTupleDirectAccessView {
0256 friend class ROOT::RNTupleReader;
0257 friend class RNTupleCollectionView;
0258
0259 protected:
0260 ROOT::RField<T> fField;
0261 ROOT::RNTupleGlobalRange fFieldRange;
0262
0263 static ROOT::RField<T> CreateField(ROOT::DescriptorId_t fieldId, ROOT::Internal::RPageSource &pageSource)
0264 {
0265 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
0266 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0267 if (fieldDesc.GetTypeName() != ROOT::RField<T>::TypeName()) {
0268 throw RException(R__FAIL("type mismatch for field " + fieldDesc.GetFieldName() + ": " +
0269 fieldDesc.GetTypeName() + " vs. " + ROOT::RField<T>::TypeName()));
0270 }
0271 ROOT::RField<T> field(fieldDesc.GetFieldName());
0272 field.SetOnDiskId(fieldId);
0273 ROOT::Internal::CallConnectPageSourceOnField(field, pageSource);
0274 return field;
0275 }
0276
0277 RNTupleDirectAccessView(ROOT::RField<T> field, ROOT::RNTupleGlobalRange range)
0278 : fField(std::move(field)), fFieldRange(range)
0279 {
0280 }
0281
0282 public:
0283 RNTupleDirectAccessView(const RNTupleDirectAccessView &other) = delete;
0284 RNTupleDirectAccessView(RNTupleDirectAccessView &&other) = default;
0285 RNTupleDirectAccessView &operator=(const RNTupleDirectAccessView &other) = delete;
0286 RNTupleDirectAccessView &operator=(RNTupleDirectAccessView &&other) = default;
0287 ~RNTupleDirectAccessView() = default;
0288
0289 const ROOT::RFieldBase &GetField() const { return fField; }
0290
0291 ROOT::RNTupleGlobalRange GetFieldRange() const { return fFieldRange; }
0292
0293
0294 const T &operator()(ROOT::NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
0295
0296 const T &operator()(RNTupleLocalIndex localIndex) { return *fField.Map(localIndex); }
0297 };
0298
0299
0300
0301
0302
0303
0304
0305
0306 class RNTupleCollectionView {
0307 friend class ROOT::RNTupleReader;
0308
0309 private:
0310 ROOT::Internal::RPageSource *fSource;
0311 ROOT::RField<RNTupleCardinality<std::uint64_t>> fField;
0312 ROOT::RFieldBase::RValue fValue;
0313
0314 RNTupleCollectionView(ROOT::DescriptorId_t fieldId, const std::string &fieldName,
0315 ROOT::Internal::RPageSource *source)
0316 : fSource(source), fField(fieldName), fValue(fField.CreateValue())
0317 {
0318 fField.SetOnDiskId(fieldId);
0319 ROOT::Internal::CallConnectPageSourceOnField(fField, *source);
0320 }
0321
0322 static RNTupleCollectionView Create(ROOT::DescriptorId_t fieldId, ROOT::Internal::RPageSource *source)
0323 {
0324 std::string fieldName;
0325 {
0326 const auto &desc = source->GetSharedDescriptorGuard().GetRef();
0327 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
0328 if (fieldDesc.GetStructure() != ROOT::ENTupleStructure::kCollection) {
0329 throw RException(
0330 R__FAIL("invalid attemt to create collection view on non-collection field " + fieldDesc.GetFieldName()));
0331 }
0332 fieldName = fieldDesc.GetFieldName();
0333 }
0334 return RNTupleCollectionView(fieldId, fieldName, source);
0335 }
0336
0337 ROOT::DescriptorId_t GetFieldId(std::string_view fieldName)
0338 {
0339 auto descGuard = fSource->GetSharedDescriptorGuard();
0340 auto fieldId = descGuard->FindFieldId(fieldName, fField.GetOnDiskId());
0341 if (fieldId == ROOT::kInvalidDescriptorId) {
0342 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in collection '" +
0343 descGuard->GetQualifiedFieldName(fField.GetOnDiskId()) + "'"));
0344 }
0345 return fieldId;
0346 }
0347
0348 public:
0349 RNTupleCollectionView(const RNTupleCollectionView &other) = delete;
0350 RNTupleCollectionView(RNTupleCollectionView &&other) = default;
0351 RNTupleCollectionView &operator=(const RNTupleCollectionView &other) = delete;
0352 RNTupleCollectionView &operator=(RNTupleCollectionView &&other) = default;
0353 ~RNTupleCollectionView() = default;
0354
0355 ROOT::RNTupleLocalRange GetCollectionRange(ROOT::NTupleSize_t globalIndex)
0356 {
0357 ROOT::NTupleSize_t size;
0358 RNTupleLocalIndex collectionStart;
0359 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
0360 return ROOT::RNTupleLocalRange(collectionStart.GetClusterId(), collectionStart.GetIndexInCluster(),
0361 collectionStart.GetIndexInCluster() + size);
0362 }
0363
0364 ROOT::RNTupleLocalRange GetCollectionRange(RNTupleLocalIndex localIndex)
0365 {
0366 ROOT::NTupleSize_t size;
0367 RNTupleLocalIndex collectionStart;
0368 fField.GetCollectionInfo(localIndex, &collectionStart, &size);
0369 return ROOT::RNTupleLocalRange(collectionStart.GetClusterId(), collectionStart.GetIndexInCluster(),
0370 collectionStart.GetIndexInCluster() + size);
0371 }
0372
0373
0374
0375
0376
0377
0378 template <typename T>
0379 RNTupleView<T> GetView(std::string_view fieldName)
0380 {
0381 auto field = RNTupleView<T>::CreateField(GetFieldId(fieldName), *fSource);
0382 auto range = Internal::GetFieldRange(*field, *fSource);
0383 return RNTupleView<T>(std::move(field), range);
0384 }
0385
0386
0387
0388
0389
0390
0391
0392 template <typename T>
0393 RNTupleDirectAccessView<T> GetDirectAccessView(std::string_view fieldName)
0394 {
0395 auto field = RNTupleDirectAccessView<T>::CreateField(GetFieldId(fieldName), *fSource);
0396 auto range = Internal::GetFieldRange(field, *fSource);
0397 return RNTupleDirectAccessView<T>(std::move(field), range);
0398 }
0399
0400
0401
0402
0403
0404
0405
0406
0407 RNTupleCollectionView GetCollectionView(std::string_view fieldName)
0408 {
0409 return RNTupleCollectionView::Create(GetFieldId(fieldName), fSource);
0410 }
0411
0412
0413 std::uint64_t operator()(ROOT::NTupleSize_t globalIndex)
0414 {
0415 fValue.Read(globalIndex);
0416 return fValue.GetRef<std::uint64_t>();
0417 }
0418
0419
0420 std::uint64_t operator()(RNTupleLocalIndex localIndex)
0421 {
0422 fValue.Read(localIndex);
0423 return fValue.GetRef<std::uint64_t>();
0424 }
0425 };
0426
0427 }
0428
0429 #endif