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