File indexing completed on 2026-11-03 10:40:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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 namespace Experimental {
0038 class RNTupleAttrSetReader;
0039
0040 namespace Internal {
0041 struct RNTupleAttrEntry;
0042 }
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 class REntry {
0056 friend class RNTupleFillContext;
0057 friend class RNTupleModel;
0058 friend class RNTupleReader;
0059 friend class Experimental::RNTupleAttrSetReader;
0060 friend struct Experimental::Internal::RNTupleAttrEntry;
0061
0062 private:
0063
0064 std::uint64_t fModelId = 0;
0065
0066 std::uint64_t fSchemaId = 0;
0067
0068 std::vector<ROOT::RFieldBase::RValue> fValues;
0069
0070 std::unordered_map<std::string, std::size_t> fFieldName2Token;
0071
0072 std::vector<std::string> fFieldTypes;
0073
0074
0075 REntry() = default;
0076 explicit REntry(std::uint64_t modelId, std::uint64_t schemaId) : fModelId(modelId), fSchemaId(schemaId) {}
0077
0078 void AddValue(ROOT::RFieldBase::RValue &&value)
0079 {
0080 fFieldName2Token[value.GetField().GetQualifiedFieldName()] = fValues.size();
0081 fFieldTypes.push_back(value.GetField().GetTypeName());
0082 fValues.emplace_back(std::move(value));
0083 }
0084
0085
0086 template <typename T>
0087 std::shared_ptr<T> AddValue(ROOT::RField<T> &field)
0088 {
0089 fFieldName2Token[field.GetQualifiedFieldName()] = fValues.size();
0090 fFieldTypes.push_back(field.GetTypeName());
0091 auto value = field.CreateValue();
0092 fValues.emplace_back(value);
0093
0094 return std::static_pointer_cast<T>(value.template GetPtr<void>());
0095 }
0096
0097 void Read(ROOT::NTupleSize_t index)
0098 {
0099 for (auto &v : fValues) {
0100 v.Read(index);
0101 }
0102 }
0103
0104 std::size_t Append()
0105 {
0106 std::size_t bytesWritten = 0;
0107 for (auto &v : fValues) {
0108 bytesWritten += v.Append();
0109 }
0110 return bytesWritten;
0111 }
0112
0113 void EnsureMatchingModel(ROOT::RFieldToken token) const
0114 {
0115 if (fSchemaId != token.fSchemaId) {
0116 throw RException(R__FAIL("invalid token for this entry, "
0117 "make sure to use a token from a model with the same schema as this entry."));
0118 }
0119 }
0120
0121
0122 const std::string &FindFieldName(ROOT::RFieldToken token) const
0123 {
0124 for (const auto &[fieldName, index] : fFieldName2Token) {
0125 if (index == token.fIndex) {
0126 return fieldName;
0127 }
0128 }
0129
0130 static const std::string empty = "";
0131 return empty;
0132 }
0133
0134 template <typename T>
0135 void EnsureMatchingType(ROOT::RFieldToken token [[maybe_unused]]) const
0136 {
0137 if constexpr (!std::is_void_v<T>) {
0138 if (!Internal::IsMatchingFieldType<T>(fFieldTypes[token.fIndex])) {
0139 throw RException(R__FAIL("type mismatch for field " + FindFieldName(token) + ": " +
0140 fFieldTypes[token.fIndex] + " vs. " + ROOT::RField<T>::TypeName()));
0141 }
0142 }
0143 }
0144
0145 public:
0146 using ConstIterator_t = decltype(fValues)::const_iterator;
0147
0148 REntry(const REntry &other) = delete;
0149 REntry &operator=(const REntry &other) = delete;
0150 REntry(REntry &&other) = default;
0151 REntry &operator=(REntry &&other) = default;
0152 ~REntry() = default;
0153
0154
0155 ROOT::RFieldToken GetToken(std::string_view fieldName) const
0156 {
0157 auto it = fFieldName2Token.find(std::string(fieldName));
0158 if (it == fFieldName2Token.end()) {
0159 throw RException(R__FAIL("invalid field name: " + std::string(fieldName)));
0160 }
0161 return ROOT::RFieldToken(it->second, fSchemaId);
0162 }
0163
0164
0165 void EmplaceNewValue(ROOT::RFieldToken token)
0166 {
0167 EnsureMatchingModel(token);
0168 fValues[token.fIndex].EmplaceNew();
0169 }
0170
0171
0172 void EmplaceNewValue(std::string_view fieldName) { EmplaceNewValue(GetToken(fieldName)); }
0173
0174
0175
0176
0177 template <typename T>
0178 void BindValue(ROOT::RFieldToken token, std::shared_ptr<T> objPtr)
0179 {
0180 EnsureMatchingModel(token);
0181 EnsureMatchingType<T>(token);
0182 fValues[token.fIndex].Bind(objPtr);
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192 template <typename T>
0193 void BindValue(std::string_view fieldName, std::shared_ptr<T> objPtr)
0194 {
0195 BindValue<T>(GetToken(fieldName), objPtr);
0196 }
0197
0198
0199
0200
0201 template <typename T>
0202 void BindRawPtr(ROOT::RFieldToken token, T *rawPtr)
0203 {
0204 EnsureMatchingModel(token);
0205 EnsureMatchingType<T>(token);
0206 fValues[token.fIndex].BindRawPtr(rawPtr);
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216 template <typename T>
0217 void BindRawPtr(std::string_view fieldName, T *rawPtr)
0218 {
0219 BindRawPtr<T>(GetToken(fieldName), rawPtr);
0220 }
0221
0222
0223
0224
0225 template <typename T>
0226 std::shared_ptr<T> GetPtr(ROOT::RFieldToken token) const
0227 {
0228 EnsureMatchingModel(token);
0229 EnsureMatchingType<T>(token);
0230 return std::static_pointer_cast<T>(fValues[token.fIndex].GetPtr<void>());
0231 }
0232
0233
0234
0235
0236
0237
0238
0239 template <typename T>
0240 std::shared_ptr<T> GetPtr(std::string_view fieldName) const
0241 {
0242 return GetPtr<T>(GetToken(fieldName));
0243 }
0244
0245 const std::string &GetTypeName(ROOT::RFieldToken token) const
0246 {
0247 EnsureMatchingModel(token);
0248 return fFieldTypes[token.fIndex];
0249 }
0250
0251 const std::string &GetTypeName(std::string_view fieldName) const { return GetTypeName(GetToken(fieldName)); }
0252
0253 bool HasField(std::string_view fieldName) const { return fFieldName2Token.count(std::string(fieldName)) > 0; }
0254
0255 std::uint64_t GetModelId() const { return fModelId; }
0256 std::uint64_t GetSchemaId() const { return fSchemaId; }
0257
0258 ConstIterator_t begin() const { return fValues.cbegin(); }
0259 ConstIterator_t end() const { return fValues.cend(); }
0260 };
0261
0262 }
0263
0264 #endif