File indexing completed on 2025-11-03 10:02:58
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