Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:22:27

0001 /// \file ROOT/REntry.hxx
0002 /// \ingroup NTuple ROOT7
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-07-19
0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0006 /// is welcome!
0007 
0008 /*************************************************************************
0009  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0010  * All rights reserved.                                                  *
0011  *                                                                       *
0012  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0013  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0014  *************************************************************************/
0015 
0016 #ifndef ROOT7_REntry
0017 #define ROOT7_REntry
0018 
0019 #include <ROOT/RError.hxx>
0020 #include <ROOT/RField.hxx>
0021 #include <string_view>
0022 
0023 #include <TError.h>
0024 
0025 #include <algorithm>
0026 #include <iterator>
0027 #include <memory>
0028 #include <type_traits>
0029 #include <utility>
0030 #include <vector>
0031 
0032 namespace ROOT {
0033 namespace Experimental {
0034 
0035 // clang-format off
0036 /**
0037 \class ROOT::Experimental::REntry
0038 \ingroup NTuple
0039 \brief The REntry is a collection of values in an ntuple corresponding to a complete row in the data set
0040 
0041 The entry provides a memory-managed binder for a set of values. Through shared pointers, the memory locations
0042 that are associated to values are managed.
0043 */
0044 // clang-format on
0045 class REntry {
0046    friend class RNTupleCollectionWriter;
0047    friend class RNTupleModel;
0048    friend class RNTupleReader;
0049    friend class RNTupleFillContext;
0050 
0051 public:
0052    /// The field token identifies a top-level field in this entry. It can be used for fast indexing in REntry's
0053    /// methods, e.g. BindValue. The field token can also be created by the model.
0054    class RFieldToken {
0055       friend class REntry;
0056       friend class RNTupleModel;
0057 
0058       std::size_t fIndex;     ///< the index in fValues that belongs to the top-level field
0059       std::uint64_t fModelId; ///< Safety check to prevent tokens from other models being used
0060       RFieldToken(std::size_t index, std::uint64_t modelId) : fIndex(index), fModelId(modelId) {}
0061    };
0062 
0063 private:
0064    /// The entry must be linked to a specific model (or one if its clones), identified by a model ID
0065    std::uint64_t fModelId = 0;
0066    /// Corresponds to the top-level fields of the linked model
0067    std::vector<RFieldBase::RValue> fValues;
0068 
0069    // Creation of entries is done by the RNTupleModel class
0070 
0071    REntry() = default;
0072    explicit REntry(std::uint64_t modelId) : fModelId(modelId) {}
0073 
0074    void AddValue(RFieldBase::RValue &&value) { fValues.emplace_back(std::move(value)); }
0075 
0076    /// While building the entry, adds a new value to the list and return the value's shared pointer
0077    template <typename T, typename... ArgsT>
0078    std::shared_ptr<T> AddValue(RField<T> &field, ArgsT &&...args)
0079    {
0080       auto ptr = std::make_shared<T>(std::forward<ArgsT>(args)...);
0081       fValues.emplace_back(field.BindValue(ptr));
0082       return ptr;
0083    }
0084 
0085    void Read(NTupleSize_t index)
0086    {
0087       for (auto &v : fValues) {
0088          v.Read(index);
0089       }
0090    }
0091 
0092    std::size_t Append()
0093    {
0094       std::size_t bytesWritten = 0;
0095       for (auto &v : fValues) {
0096          bytesWritten += v.Append();
0097       }
0098       return bytesWritten;
0099    }
0100 
0101    void EnsureMatchingModel(RFieldToken token) const
0102    {
0103       if (fModelId != token.fModelId) {
0104          throw RException(R__FAIL("invalid token for this entry, "
0105                                   "make sure to use a token from the same model as this entry."));
0106       }
0107    }
0108 
0109    template <typename T>
0110    void EnsureMatchingType(RFieldToken token [[maybe_unused]]) const
0111    {
0112       if constexpr (!std::is_void_v<T>) {
0113          const auto &v = fValues[token.fIndex];
0114          if (v.GetField().GetTypeName() != RField<T>::TypeName()) {
0115             throw RException(R__FAIL("type mismatch for field " + v.GetField().GetFieldName() + ": " +
0116                                      v.GetField().GetTypeName() + " vs. " + RField<T>::TypeName()));
0117          }
0118       }
0119    }
0120 
0121 public:
0122    using ConstIterator_t = decltype(fValues)::const_iterator;
0123 
0124    REntry(const REntry &other) = delete;
0125    REntry &operator=(const REntry &other) = delete;
0126    REntry(REntry &&other) = default;
0127    REntry &operator=(REntry &&other) = default;
0128    ~REntry() = default;
0129 
0130    /// The ordinal of the top-level field fieldName; can be used in other methods to address the corresponding value
0131    RFieldToken GetToken(std::string_view fieldName) const
0132    {
0133       auto it = std::find_if(fValues.begin(), fValues.end(),
0134          [&fieldName] (const RFieldBase::RValue &value) { return value.GetField().GetFieldName() == fieldName; });
0135 
0136       if ( it == fValues.end() ) {
0137          throw RException(R__FAIL("invalid field name: " + std::string(fieldName)));
0138       }
0139       return RFieldToken(std::distance(fValues.begin(), it), fModelId);
0140    }
0141 
0142    void EmplaceNewValue(RFieldToken token)
0143    {
0144       EnsureMatchingModel(token);
0145       fValues[token.fIndex].EmplaceNew();
0146    }
0147 
0148    void EmplaceNewValue(std::string_view fieldName) { EmplaceNewValue(GetToken(fieldName)); }
0149 
0150    template <typename T>
0151    void BindValue(RFieldToken token, std::shared_ptr<T> objPtr)
0152    {
0153       EnsureMatchingModel(token);
0154       EnsureMatchingType<T>(token);
0155       fValues[token.fIndex].Bind(objPtr);
0156    }
0157 
0158    template <typename T>
0159    void BindValue(std::string_view fieldName, std::shared_ptr<T> objPtr)
0160    {
0161       BindValue<T>(GetToken(fieldName), objPtr);
0162    }
0163 
0164    template <typename T>
0165    void BindRawPtr(RFieldToken token, T *rawPtr)
0166    {
0167       EnsureMatchingModel(token);
0168       EnsureMatchingType<T>(token);
0169       fValues[token.fIndex].BindRawPtr(rawPtr);
0170    }
0171 
0172    template <typename T>
0173    void BindRawPtr(std::string_view fieldName, T *rawPtr)
0174    {
0175       BindRawPtr<void>(GetToken(fieldName), rawPtr);
0176    }
0177 
0178    template <typename T>
0179    std::shared_ptr<T> GetPtr(RFieldToken token) const
0180    {
0181       EnsureMatchingModel(token);
0182       EnsureMatchingType<T>(token);
0183       return std::static_pointer_cast<T>(fValues[token.fIndex].GetPtr<void>());
0184    }
0185 
0186    template <typename T>
0187    std::shared_ptr<T> GetPtr(std::string_view fieldName) const
0188    {
0189       return GetPtr<T>(GetToken(fieldName));
0190    }
0191 
0192    std::uint64_t GetModelId() const { return fModelId; }
0193 
0194    ConstIterator_t begin() const { return fValues.cbegin(); }
0195    ConstIterator_t end() const { return fValues.cend(); }
0196 };
0197 
0198 } // namespace Experimental
0199 } // namespace ROOT
0200 
0201 #endif