File indexing completed on 2025-09-17 09:14:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RField
0015 #define ROOT_RField
0016
0017 #include <ROOT/RError.hxx>
0018 #include <ROOT/RFieldBase.hxx>
0019 #include <ROOT/RFieldUtils.hxx>
0020 #include <ROOT/RNTupleSerialize.hxx>
0021 #include <ROOT/RNTupleUtil.hxx>
0022 #include <ROOT/RSpan.hxx>
0023 #include <string_view>
0024 #include <ROOT/TypeTraits.hxx>
0025
0026 #include <TGenericClassInfo.h>
0027
0028 #include <algorithm>
0029 #include <array>
0030 #include <cstddef>
0031 #include <iostream>
0032 #include <memory>
0033 #include <string>
0034 #include <type_traits>
0035 #include <typeinfo>
0036 #include <vector>
0037
0038 class TClass;
0039 class TEnum;
0040 class TObject;
0041 class TVirtualStreamerInfo;
0042
0043 namespace ROOT {
0044
0045 class TSchemaRule;
0046 class RNTupleCollectionView;
0047
0048 namespace Detail {
0049 class RFieldVisitor;
0050 }
0051
0052
0053
0054 class RFieldZero final : public RFieldBase {
0055 protected:
0056 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0057 void ConstructValue(void *) const final {}
0058
0059 public:
0060 RFieldZero() : RFieldBase("", "", ROOT::ENTupleStructure::kRecord, false ) {}
0061
0062 using RFieldBase::Attach;
0063 size_t GetValueSize() const final { return 0; }
0064 size_t GetAlignment() const final { return 0; }
0065
0066 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0067 };
0068
0069
0070
0071
0072 class RInvalidField final : public RFieldBase {
0073 public:
0074 enum class RCategory {
0075
0076 kGeneric,
0077
0078 kTypeError,
0079
0080 kUnknownType,
0081
0082 kUnknownStructure
0083 };
0084
0085 private:
0086 std::string fError;
0087 RCategory fCategory;
0088
0089 protected:
0090 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final
0091 {
0092 return std::make_unique<RInvalidField>(newName, GetTypeName(), fError, fCategory);
0093 }
0094 void ConstructValue(void *) const final {}
0095
0096 public:
0097 RInvalidField(std::string_view name, std::string_view type, std::string_view error, RCategory category)
0098 : RFieldBase(name, type, ROOT::ENTupleStructure::kLeaf, false ), fError(error), fCategory(category)
0099 {
0100 fTraits |= kTraitInvalidField;
0101 }
0102
0103 const std::string &GetError() const { return fError; }
0104 RCategory GetCategory() const { return fCategory; }
0105
0106 size_t GetValueSize() const final { return 0; }
0107 size_t GetAlignment() const final { return 0; }
0108 };
0109
0110
0111 class RClassField : public RFieldBase {
0112 private:
0113 enum ESubFieldRole {
0114 kBaseClass,
0115 kDataMember,
0116 };
0117 struct RSubFieldInfo {
0118 ESubFieldRole fRole;
0119 std::size_t fOffset;
0120 };
0121
0122 struct RStagingItem {
0123
0124
0125 std::unique_ptr<RFieldBase> fField;
0126 std::size_t fOffset;
0127 };
0128
0129 static constexpr const char *kPrefixInherited{":"};
0130
0131 class RClassDeleter : public RDeleter {
0132 private:
0133 TClass *fClass;
0134
0135 public:
0136 explicit RClassDeleter(TClass *cl) : fClass(cl) {}
0137 void operator()(void *objPtr, bool dtorOnly) final;
0138 };
0139
0140 TClass *fClass;
0141
0142 std::vector<RSubFieldInfo> fSubfieldsInfo;
0143 std::size_t fMaxAlignment = 1;
0144
0145
0146
0147 std::unique_ptr<unsigned char[]> fStagingArea;
0148
0149
0150
0151
0152 TClass *fStagingClass = nullptr;
0153 std::unordered_map<std::string, RStagingItem> fStagingItems;
0154
0155 private:
0156 RClassField(std::string_view fieldName, const RClassField &source);
0157 RClassField(std::string_view fieldName, TClass *classp);
0158 void Attach(std::unique_ptr<RFieldBase> child, RSubFieldInfo info);
0159
0160
0161
0162 ROOT::DescriptorId_t
0163 LookupMember(const ROOT::RNTupleDescriptor &desc, std::string_view memberName, ROOT::DescriptorId_t classFieldId);
0164
0165 void SetStagingClass(const std::string &className, unsigned int classVersion);
0166
0167
0168 void PrepareStagingArea(const std::vector<const TSchemaRule *> &rules, const ROOT::RNTupleDescriptor &desc,
0169 const ROOT::RFieldDescriptor &classFieldId);
0170
0171 void AddReadCallbacksFromIORule(const TSchemaRule *rule);
0172
0173
0174
0175
0176 std::vector<const TSchemaRule *> FindRules(const ROOT::RFieldDescriptor *fieldDesc);
0177
0178 protected:
0179 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0180
0181 void ConstructValue(void *where) const final;
0182 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RClassDeleter>(fClass); }
0183
0184 std::size_t AppendImpl(const void *from) final;
0185 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0186 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0187 void BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
0188
0189 public:
0190 RClassField(std::string_view fieldName, std::string_view className);
0191 RClassField(RClassField &&other) = default;
0192 RClassField &operator=(RClassField &&other) = default;
0193 ~RClassField() override;
0194
0195 std::vector<RValue> SplitValue(const RValue &value) const final;
0196 size_t GetValueSize() const final;
0197 size_t GetAlignment() const final { return fMaxAlignment; }
0198 std::uint32_t GetTypeVersion() const final;
0199 std::uint32_t GetTypeChecksum() const final;
0200 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0201 };
0202
0203
0204 class RStreamerField final : public RFieldBase {
0205 private:
0206 class RStreamerFieldDeleter : public RDeleter {
0207 private:
0208 TClass *fClass;
0209
0210 public:
0211 explicit RStreamerFieldDeleter(TClass *cl) : fClass(cl) {}
0212 void operator()(void *objPtr, bool dtorOnly) final;
0213 };
0214
0215 TClass *fClass = nullptr;
0216 ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fStreamerInfos;
0217 ROOT::Internal::RColumnIndex fIndex;
0218
0219 private:
0220 RStreamerField(std::string_view fieldName, TClass *classp);
0221
0222 protected:
0223 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0224
0225 const RColumnRepresentations &GetColumnRepresentations() const final;
0226 void GenerateColumns() final;
0227 void GenerateColumns(const ROOT::RNTupleDescriptor &) final;
0228
0229 void ConstructValue(void *where) const final;
0230 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RStreamerFieldDeleter>(fClass); }
0231
0232 std::size_t AppendImpl(const void *from) final;
0233 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0234
0235 void CommitClusterImpl() final { fIndex = 0; }
0236
0237 bool HasExtraTypeInfo() const final { return true; }
0238
0239 ROOT::RExtraTypeInfoDescriptor GetExtraTypeInfo() const final;
0240
0241 void BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
0242
0243 public:
0244 RStreamerField(std::string_view fieldName, std::string_view className, std::string_view typeAlias = "");
0245 RStreamerField(RStreamerField &&other) = default;
0246 RStreamerField &operator=(RStreamerField &&other) = default;
0247 ~RStreamerField() final = default;
0248
0249 size_t GetValueSize() const final;
0250 size_t GetAlignment() const final;
0251 std::uint32_t GetTypeVersion() const final;
0252 std::uint32_t GetTypeChecksum() const final;
0253 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0254 };
0255
0256
0257 class REnumField : public RFieldBase {
0258 private:
0259 REnumField(std::string_view fieldName, TEnum *enump);
0260 REnumField(std::string_view fieldName, std::string_view enumName, std::unique_ptr<RFieldBase> intField);
0261
0262 protected:
0263 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0264
0265 void ConstructValue(void *where) const final { CallConstructValueOn(*fSubfields[0], where); }
0266
0267 std::size_t AppendImpl(const void *from) final { return CallAppendOn(*fSubfields[0], from); }
0268 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final { CallReadOn(*fSubfields[0], globalIndex, to); }
0269 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final { CallReadOn(*fSubfields[0], localIndex, to); }
0270
0271 public:
0272 REnumField(std::string_view fieldName, std::string_view enumName);
0273 REnumField(REnumField &&other) = default;
0274 REnumField &operator=(REnumField &&other) = default;
0275 ~REnumField() override = default;
0276
0277 std::vector<RValue> SplitValue(const RValue &value) const final;
0278 size_t GetValueSize() const final { return fSubfields[0]->GetValueSize(); }
0279 size_t GetAlignment() const final { return fSubfields[0]->GetAlignment(); }
0280 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0281 };
0282
0283
0284 template <typename T, typename = void>
0285 class RField final : public RClassField {
0286 public:
0287 static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); }
0288 RField(std::string_view name) : RClassField(name, TypeName())
0289 {
0290 static_assert(std::is_class_v<T>, "no I/O support for this basic C++ type");
0291 }
0292 RField(RField &&other) = default;
0293 RField &operator=(RField &&other) = default;
0294 ~RField() final = default;
0295 };
0296
0297 template <typename T>
0298 class RField<T, typename std::enable_if<std::is_enum_v<T>>::type> final : public REnumField {
0299 public:
0300 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
0301 RField(std::string_view name) : REnumField(name, TypeName()) {}
0302 RField(RField &&other) = default;
0303 RField &operator=(RField &&other) = default;
0304 ~RField() final = default;
0305 };
0306
0307
0308
0309
0310
0311
0312 class RCardinalityField : public RFieldBase {
0313 friend class ROOT::RNTupleCollectionView;
0314
0315 private:
0316 void GetCollectionInfo(ROOT::NTupleSize_t globalIndex, RNTupleLocalIndex *collectionStart, ROOT::NTupleSize_t *size)
0317 {
0318 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
0319 }
0320 void GetCollectionInfo(RNTupleLocalIndex localIndex, RNTupleLocalIndex *collectionStart, ROOT::NTupleSize_t *size)
0321 {
0322 fPrincipalColumn->GetCollectionInfo(localIndex, collectionStart, size);
0323 }
0324
0325 protected:
0326 RCardinalityField(std::string_view fieldName, std::string_view typeName)
0327 : RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kLeaf, false )
0328 {
0329 }
0330
0331 const RColumnRepresentations &GetColumnRepresentations() const final;
0332
0333 void GenerateColumns() final { throw RException(R__FAIL("Cardinality fields must only be used for reading")); }
0334 void GenerateColumns(const ROOT::RNTupleDescriptor &) final;
0335
0336 public:
0337 RCardinalityField(RCardinalityField &&other) = default;
0338 RCardinalityField &operator=(RCardinalityField &&other) = default;
0339 ~RCardinalityField() override = default;
0340
0341 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0342
0343 const RField<RNTupleCardinality<std::uint32_t>> *As32Bit() const;
0344 const RField<RNTupleCardinality<std::uint64_t>> *As64Bit() const;
0345 };
0346
0347 template <typename T>
0348 class RSimpleField : public RFieldBase {
0349 protected:
0350 void GenerateColumns() override { GenerateColumnsImpl<T>(); }
0351 void GenerateColumns(const ROOT::RNTupleDescriptor &desc) override { GenerateColumnsImpl<T>(desc); }
0352
0353 void ConstructValue(void *where) const final { new (where) T{0}; }
0354
0355 public:
0356 RSimpleField(std::string_view name, std::string_view type)
0357 : RFieldBase(name, type, ROOT::ENTupleStructure::kLeaf, true )
0358 {
0359 fTraits |= kTraitTrivialType;
0360 }
0361 RSimpleField(RSimpleField &&other) = default;
0362 RSimpleField &operator=(RSimpleField &&other) = default;
0363 ~RSimpleField() override = default;
0364
0365 T *Map(ROOT::NTupleSize_t globalIndex) { return fPrincipalColumn->Map<T>(globalIndex); }
0366 T *Map(RNTupleLocalIndex localIndex) { return fPrincipalColumn->Map<T>(localIndex); }
0367 T *MapV(ROOT::NTupleSize_t globalIndex, ROOT::NTupleSize_t &nItems)
0368 {
0369 return fPrincipalColumn->MapV<T>(globalIndex, nItems);
0370 }
0371 T *MapV(RNTupleLocalIndex localIndex, ROOT::NTupleSize_t &nItems)
0372 {
0373 return fPrincipalColumn->MapV<T>(localIndex, nItems);
0374 }
0375
0376 size_t GetValueSize() const final { return sizeof(T); }
0377 size_t GetAlignment() const final { return alignof(T); }
0378 };
0379
0380
0381
0382
0383
0384 }
0385
0386 #include "RField/RFieldFundamental.hxx"
0387 #include "RField/RFieldProxiedCollection.hxx"
0388 #include "RField/RFieldRecord.hxx"
0389 #include "RField/RFieldSequenceContainer.hxx"
0390 #include "RField/RFieldSTLMisc.hxx"
0391
0392 namespace ROOT {
0393
0394 template <typename SizeT>
0395 class RField<RNTupleCardinality<SizeT>> final : public RCardinalityField {
0396 protected:
0397 std::unique_ptr<ROOT::RFieldBase> CloneImpl(std::string_view newName) const final
0398 {
0399 return std::make_unique<RField<RNTupleCardinality<SizeT>>>(newName);
0400 }
0401 void ConstructValue(void *where) const final { new (where) RNTupleCardinality<SizeT>(0); }
0402
0403
0404 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
0405 {
0406 RNTupleLocalIndex collectionStart;
0407 ROOT::NTupleSize_t size;
0408 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &size);
0409 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
0410 }
0411
0412
0413 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
0414 {
0415 RNTupleLocalIndex collectionStart;
0416 ROOT::NTupleSize_t size;
0417 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &size);
0418 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
0419 }
0420
0421 std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
0422 {
0423 RNTupleLocalIndex collectionStart;
0424 ROOT::NTupleSize_t collectionSize;
0425 fPrincipalColumn->GetCollectionInfo(bulkSpec.fFirstIndex, &collectionStart, &collectionSize);
0426
0427 auto typedValues = static_cast<RNTupleCardinality<SizeT> *>(bulkSpec.fValues);
0428 typedValues[0] = collectionSize;
0429
0430 auto lastOffset = collectionStart.GetIndexInCluster() + collectionSize;
0431 ROOT::NTupleSize_t nRemainingEntries = bulkSpec.fCount - 1;
0432 std::size_t nEntries = 1;
0433 while (nRemainingEntries > 0) {
0434 ROOT::NTupleSize_t nItemsUntilPageEnd;
0435 auto offsets =
0436 fPrincipalColumn->MapV<ROOT::Internal::RColumnIndex>(bulkSpec.fFirstIndex + nEntries, nItemsUntilPageEnd);
0437 std::size_t nBatch = std::min(nRemainingEntries, nItemsUntilPageEnd);
0438 for (std::size_t i = 0; i < nBatch; ++i) {
0439 typedValues[nEntries + i] = offsets[i] - lastOffset;
0440 lastOffset = offsets[i];
0441 }
0442 nRemainingEntries -= nBatch;
0443 nEntries += nBatch;
0444 }
0445 return RBulkSpec::kAllSet;
0446 }
0447
0448 public:
0449 static std::string TypeName() { return "ROOT::RNTupleCardinality<" + RField<SizeT>::TypeName() + ">"; }
0450 explicit RField(std::string_view name) : RCardinalityField(name, TypeName()) {}
0451 RField(RField &&other) = default;
0452 RField &operator=(RField &&other) = default;
0453 ~RField() final = default;
0454
0455 size_t GetValueSize() const final { return sizeof(RNTupleCardinality<SizeT>); }
0456 size_t GetAlignment() const final { return alignof(RNTupleCardinality<SizeT>); }
0457 };
0458
0459
0460 template <>
0461 class RField<TObject> final : public RFieldBase {
0462 static std::size_t GetOffsetOfMember(const char *name);
0463 static std::size_t GetOffsetUniqueID() { return GetOffsetOfMember("fUniqueID"); }
0464 static std::size_t GetOffsetBits() { return GetOffsetOfMember("fBits"); }
0465
0466 private:
0467 RField(std::string_view fieldName, const RField<TObject> &source);
0468
0469 protected:
0470 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0471
0472 void ConstructValue(void *where) const final;
0473 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<TObject>>(); }
0474
0475 std::size_t AppendImpl(const void *from) final;
0476 void ReadTObject(void *to, UInt_t uniqueID, UInt_t bits);
0477 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0478 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0479
0480 void AfterConnectPageSource() final;
0481
0482 public:
0483 static std::string TypeName() { return "TObject"; }
0484
0485 RField(std::string_view fieldName);
0486 RField(RField &&other) = default;
0487 RField &operator=(RField &&other) = default;
0488 ~RField() final = default;
0489
0490 std::vector<RValue> SplitValue(const RValue &value) const final;
0491 size_t GetValueSize() const final;
0492 size_t GetAlignment() const final;
0493 std::uint32_t GetTypeVersion() const final;
0494 std::uint32_t GetTypeChecksum() const final;
0495 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0496 };
0497
0498
0499
0500
0501 template <typename T>
0502 std::unique_ptr<T, typename RFieldBase::RCreateObjectDeleter<T>::deleter> RFieldBase::CreateObject() const
0503 {
0504 if (GetTypeName() != RField<T>::TypeName()) {
0505 throw RException(
0506 R__FAIL("type mismatch for field " + GetFieldName() + ": " + GetTypeName() + " vs. " + RField<T>::TypeName()));
0507 }
0508 return std::unique_ptr<T>(static_cast<T *>(CreateObjectRawPtr()));
0509 }
0510
0511 template <>
0512 struct RFieldBase::RCreateObjectDeleter<void> {
0513 using deleter = RCreateObjectDeleter<void>;
0514 void operator()(void *);
0515 };
0516
0517 template <>
0518 std::unique_ptr<void, typename RFieldBase::RCreateObjectDeleter<void>::deleter>
0519 ROOT::RFieldBase::CreateObject<void>() const;
0520
0521 }
0522
0523 #endif