Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/ROOT/REntry.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /// \file ROOT/REntry.hxx
0002 /// \ingroup NTuple
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-07-19
0005 
0006 /*************************************************************************
0007  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0008  * All rights reserved.                                                  *
0009  *                                                                       *
0010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0012  *************************************************************************/
0013 
0014 #ifndef ROOT_REntry
0015 #define ROOT_REntry
0016 
0017 #include <ROOT/RError.hxx>
0018 #include <ROOT/RField.hxx>
0019 #include <ROOT/RFieldToken.hxx>
0020 #include <string_view>
0021 
0022 #include <TError.h>
0023 
0024 #include <algorithm>
0025 #include <iterator>
0026 #include <memory>
0027 #include <type_traits>
0028 #include <utility>
0029 #include <vector>
0030 #include <unordered_map>
0031 
0032 namespace ROOT {
0033 
0034 class RNTupleFillContext;
0035 class RNTupleReader;
0036 
0037 // clang-format off
0038 /**
0039 \class ROOT::REntry
0040 \ingroup NTuple
0041 \brief The REntry is a collection of values in an RNTuple corresponding to a complete row in the data set.
0042 
0043 The entry provides a memory-managed binder for a set of values read from fields in an RNTuple. The memory locations that are associated
0044 with values are managed through shared pointers.
0045 */
0046 // clang-format on
0047 class REntry {
0048    friend class RNTupleFillContext;
0049    friend class RNTupleModel;
0050    friend class RNTupleReader;
0051 
0052 private:
0053    /// The entry must be linked to a specific model, identified by a model ID
0054    std::uint64_t fModelId = 0;
0055    /// The entry and its tokens are also linked to a specific schema, identified by a schema ID
0056    std::uint64_t fSchemaId = 0;
0057    /// Corresponds to the fields of the linked model
0058    std::vector<ROOT::RFieldBase::RValue> fValues;
0059    /// For fast lookup of token IDs given a (sub)field name present in the entry
0060    std::unordered_map<std::string, std::size_t> fFieldName2Token;
0061    /// To ensure that the entry is standalone, a copy of all field types
0062    std::vector<std::string> fFieldTypes;
0063 
0064    /// Creation of entries can be done by the RNTupleModel, the RNTupleReader, or the RNTupleWriter.
0065    REntry() = default;
0066    explicit REntry(std::uint64_t modelId, std::uint64_t schemaId) : fModelId(modelId), fSchemaId(schemaId) {}
0067 
0068    void AddValue(ROOT::RFieldBase::RValue &&value)
0069    {
0070       fFieldName2Token[value.GetField().GetQualifiedFieldName()] = fValues.size();
0071       fFieldTypes.push_back(value.GetField().GetTypeName());
0072       fValues.emplace_back(std::move(value));
0073    }
0074 
0075    /// While building the entry, adds a new value for the field and returns the value's shared pointer
0076    template <typename T>
0077    std::shared_ptr<T> AddValue(ROOT::RField<T> &field)
0078    {
0079       fFieldName2Token[field.GetQualifiedFieldName()] = fValues.size();
0080       fFieldTypes.push_back(field.GetTypeName());
0081       auto value = field.CreateValue();
0082       fValues.emplace_back(value);
0083       // We know that the created RValue has the right type, skip the unnecessary check.
0084       return std::static_pointer_cast<T>(value.template GetPtr<void>());
0085    }
0086 
0087    void Read(ROOT::NTupleSize_t index)
0088    {
0089       for (auto &v : fValues) {
0090          v.Read(index);
0091       }
0092    }
0093 
0094    std::size_t Append()
0095    {
0096       std::size_t bytesWritten = 0;
0097       for (auto &v : fValues) {
0098          bytesWritten += v.Append();
0099       }
0100       return bytesWritten;
0101    }
0102 
0103    void EnsureMatchingModel(ROOT::RFieldToken token) const
0104    {
0105       if (fSchemaId != token.fSchemaId) {
0106          throw RException(R__FAIL("invalid token for this entry, "
0107                                   "make sure to use a token from a model with the same schema as this entry."));
0108       }
0109    }
0110 
0111    /// This function has linear complexity, only use it for more helpful error messages!
0112    const std::string &FindFieldName(ROOT::RFieldToken token) const
0113    {
0114       for (const auto &[fieldName, index] : fFieldName2Token) {
0115          if (index == token.fIndex) {
0116             return fieldName;
0117          }
0118       }
0119       // Should never happen, but avoid compiler warning about "returning reference to local temporary object".
0120       static const std::string empty = "";
0121       return empty;
0122    }
0123 
0124    template <typename T>
0125    void EnsureMatchingType(ROOT::RFieldToken token [[maybe_unused]]) const
0126    {
0127       if constexpr (!std::is_void_v<T>) {
0128          if (!Internal::IsMatchingFieldType<T>(fFieldTypes[token.fIndex])) {
0129             throw RException(R__FAIL("type mismatch for field " + FindFieldName(token) + ": " +
0130                                      fFieldTypes[token.fIndex] + " vs. " + ROOT::RField<T>::TypeName()));
0131          }
0132       }
0133    }
0134 
0135 public:
0136    using ConstIterator_t = decltype(fValues)::const_iterator;
0137 
0138    REntry(const REntry &other) = delete;
0139    REntry &operator=(const REntry &other) = delete;
0140    REntry(REntry &&other) = default;
0141    REntry &operator=(REntry &&other) = default;
0142    ~REntry() = default;
0143 
0144    /// The ordinal of the (sub)field fieldName; can be used in other methods to address the corresponding value
0145    ROOT::RFieldToken GetToken(std::string_view fieldName) const
0146    {
0147       auto it = fFieldName2Token.find(std::string(fieldName));
0148       if (it == fFieldName2Token.end()) {
0149          throw RException(R__FAIL("invalid field name: " + std::string(fieldName)));
0150       }
0151       return ROOT::RFieldToken(it->second, fSchemaId);
0152    }
0153 
0154    /// Create a new value for the field referenced by `token`.
0155    void EmplaceNewValue(ROOT::RFieldToken token)
0156    {
0157       EnsureMatchingModel(token);
0158       fValues[token.fIndex].EmplaceNew();
0159    }
0160 
0161    /// Create a new value for the field referenced by its name.
0162    void EmplaceNewValue(std::string_view fieldName) { EmplaceNewValue(GetToken(fieldName)); }
0163 
0164    /// Bind the value for the field, referenced by `token`, to `objPtr`.
0165    ///
0166    /// \sa BindValue(std::string_view, std::shared_ptr<T>)
0167    template <typename T>
0168    void BindValue(ROOT::RFieldToken token, std::shared_ptr<T> objPtr)
0169    {
0170       EnsureMatchingModel(token);
0171       EnsureMatchingType<T>(token);
0172       fValues[token.fIndex].Bind(objPtr);
0173    }
0174 
0175    /// Bind the value for the field, referenced by its name, to `objPtr`.
0176    ///
0177    /// Ownership is shared with the caller and the object will be kept alive until it is replaced (by a call to
0178    /// EmplaceNewValue, BindValue, or BindRawPtr) or the entry is destructed.
0179    ///
0180    /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to match the field and
0181    /// object types.
0182    template <typename T>
0183    void BindValue(std::string_view fieldName, std::shared_ptr<T> objPtr)
0184    {
0185       BindValue<T>(GetToken(fieldName), objPtr);
0186    }
0187 
0188    /// Bind the value for the field, referenced by `token`, to `rawPtr`.
0189    ///
0190    /// \sa BindRawPtr(std::string_view, T *)
0191    template <typename T>
0192    void BindRawPtr(ROOT::RFieldToken token, T *rawPtr)
0193    {
0194       EnsureMatchingModel(token);
0195       EnsureMatchingType<T>(token);
0196       fValues[token.fIndex].BindRawPtr(rawPtr);
0197    }
0198 
0199    /// Bind the value for the field, referenced by its name, to `rawPtr`.
0200    ///
0201    /// The caller retains ownership of the object and must ensure it is kept alive when reading or writing using the
0202    /// entry.
0203    ///
0204    /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to match the field and
0205    /// object types.
0206    template <typename T>
0207    void BindRawPtr(std::string_view fieldName, T *rawPtr)
0208    {
0209       BindRawPtr<void>(GetToken(fieldName), rawPtr);
0210    }
0211 
0212    /// Get the (typed) pointer to the value for the field referenced by `token`.
0213    ///
0214    /// \sa GetPtr(std::string_view)
0215    template <typename T>
0216    std::shared_ptr<T> GetPtr(ROOT::RFieldToken token) const
0217    {
0218       EnsureMatchingModel(token);
0219       EnsureMatchingType<T>(token);
0220       return std::static_pointer_cast<T>(fValues[token.fIndex].GetPtr<void>());
0221    }
0222 
0223    /// Get the (typed) pointer to the value for the field referenced by `token`.
0224    ///
0225    /// Ownership is shared and the caller can continue to use the object after the entry is destructed.
0226    ///
0227    /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to use the returned pointer
0228    /// according to the field type.
0229    template <typename T>
0230    std::shared_ptr<T> GetPtr(std::string_view fieldName) const
0231    {
0232       return GetPtr<T>(GetToken(fieldName));
0233    }
0234 
0235    const std::string &GetTypeName(ROOT::RFieldToken token) const
0236    {
0237       EnsureMatchingModel(token);
0238       return fFieldTypes[token.fIndex];
0239    }
0240 
0241    const std::string &GetTypeName(std::string_view fieldName) const { return GetTypeName(GetToken(fieldName)); }
0242 
0243    std::uint64_t GetModelId() const { return fModelId; }
0244    std::uint64_t GetSchemaId() const { return fSchemaId; }
0245 
0246    ConstIterator_t begin() const { return fValues.cbegin(); }
0247    ConstIterator_t end() const { return fValues.cend(); }
0248 };
0249 
0250 } // namespace ROOT
0251 
0252 #endif