File indexing completed on 2025-12-09 10:18:07
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
0201 const TClass *GetClass() const { return fClass; }
0202 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0203 };
0204
0205
0206 class RStreamerField final : public RFieldBase {
0207 private:
0208 class RStreamerFieldDeleter : public RDeleter {
0209 private:
0210 TClass *fClass;
0211
0212 public:
0213 explicit RStreamerFieldDeleter(TClass *cl) : fClass(cl) {}
0214 void operator()(void *objPtr, bool dtorOnly) final;
0215 };
0216
0217 TClass *fClass = nullptr;
0218 ROOT::Internal::RNTupleSerializer::StreamerInfoMap_t fStreamerInfos;
0219 ROOT::Internal::RColumnIndex fIndex;
0220
0221 private:
0222 RStreamerField(std::string_view fieldName, TClass *classp);
0223
0224 protected:
0225 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0226
0227 const RColumnRepresentations &GetColumnRepresentations() const final;
0228 void GenerateColumns() final;
0229 void GenerateColumns(const ROOT::RNTupleDescriptor &) final;
0230
0231 void ConstructValue(void *where) const final;
0232 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RStreamerFieldDeleter>(fClass); }
0233
0234 std::size_t AppendImpl(const void *from) final;
0235 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0236
0237 void CommitClusterImpl() final { fIndex = 0; }
0238
0239 bool HasExtraTypeInfo() const final { return true; }
0240
0241 ROOT::RExtraTypeInfoDescriptor GetExtraTypeInfo() const final;
0242
0243 void BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
0244
0245 public:
0246 RStreamerField(std::string_view fieldName, std::string_view className, std::string_view typeAlias = "");
0247 RStreamerField(RStreamerField &&other) = default;
0248 RStreamerField &operator=(RStreamerField &&other) = default;
0249 ~RStreamerField() final = default;
0250
0251 size_t GetValueSize() const final;
0252 size_t GetAlignment() const final;
0253 std::uint32_t GetTypeVersion() const final;
0254 std::uint32_t GetTypeChecksum() const final;
0255 TClass *GetClass() const { return fClass; }
0256 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0257 };
0258
0259
0260 class REnumField : public RFieldBase {
0261 private:
0262 REnumField(std::string_view fieldName, TEnum *enump);
0263 REnumField(std::string_view fieldName, std::string_view enumName, std::unique_ptr<RFieldBase> intField);
0264
0265 protected:
0266 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0267
0268 void ConstructValue(void *where) const final { CallConstructValueOn(*fSubfields[0], where); }
0269
0270 std::size_t AppendImpl(const void *from) final { return CallAppendOn(*fSubfields[0], from); }
0271 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final { CallReadOn(*fSubfields[0], globalIndex, to); }
0272 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final { CallReadOn(*fSubfields[0], localIndex, to); }
0273
0274 public:
0275 REnumField(std::string_view fieldName, std::string_view enumName);
0276 REnumField(REnumField &&other) = default;
0277 REnumField &operator=(REnumField &&other) = default;
0278 ~REnumField() override = default;
0279
0280 std::vector<RValue> SplitValue(const RValue &value) const final;
0281 size_t GetValueSize() const final { return fSubfields[0]->GetValueSize(); }
0282 size_t GetAlignment() const final { return fSubfields[0]->GetAlignment(); }
0283 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0284 };
0285
0286
0287 template <typename T, typename = void>
0288 class RField final : public RClassField {
0289 public:
0290 static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); }
0291 RField(std::string_view name) : RClassField(name, Internal::GetDemangledTypeName(typeid(T)))
0292 {
0293 static_assert(std::is_class_v<T>, "no I/O support for this basic C++ type");
0294 }
0295 RField(RField &&other) = default;
0296 RField &operator=(RField &&other) = default;
0297 ~RField() final = default;
0298 };
0299
0300 template <typename T>
0301 class RField<T, typename std::enable_if<std::is_enum_v<T>>::type> final : public REnumField {
0302 public:
0303 static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
0304 RField(std::string_view name) : REnumField(name, TypeName()) {}
0305 RField(RField &&other) = default;
0306 RField &operator=(RField &&other) = default;
0307 ~RField() final = default;
0308 };
0309
0310
0311
0312
0313
0314
0315 class RCardinalityField : public RFieldBase {
0316 friend class ROOT::RNTupleCollectionView;
0317
0318 private:
0319 void GetCollectionInfo(ROOT::NTupleSize_t globalIndex, RNTupleLocalIndex *collectionStart, ROOT::NTupleSize_t *size)
0320 {
0321 fPrincipalColumn->GetCollectionInfo(globalIndex, collectionStart, size);
0322 }
0323 void GetCollectionInfo(RNTupleLocalIndex localIndex, RNTupleLocalIndex *collectionStart, ROOT::NTupleSize_t *size)
0324 {
0325 fPrincipalColumn->GetCollectionInfo(localIndex, collectionStart, size);
0326 }
0327
0328 protected:
0329 RCardinalityField(std::string_view fieldName, std::string_view typeName)
0330 : RFieldBase(fieldName, typeName, ROOT::ENTupleStructure::kLeaf, false )
0331 {
0332 }
0333
0334 const RColumnRepresentations &GetColumnRepresentations() const final;
0335
0336 void GenerateColumns() final { throw RException(R__FAIL("Cardinality fields must only be used for reading")); }
0337 void GenerateColumns(const ROOT::RNTupleDescriptor &) final;
0338
0339 public:
0340 RCardinalityField(RCardinalityField &&other) = default;
0341 RCardinalityField &operator=(RCardinalityField &&other) = default;
0342 ~RCardinalityField() override = default;
0343
0344 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0345
0346 const RField<RNTupleCardinality<std::uint32_t>> *As32Bit() const;
0347 const RField<RNTupleCardinality<std::uint64_t>> *As64Bit() const;
0348 };
0349
0350 template <typename T>
0351 class RSimpleField : public RFieldBase {
0352 protected:
0353 void GenerateColumns() override { GenerateColumnsImpl<T>(); }
0354 void GenerateColumns(const ROOT::RNTupleDescriptor &desc) override { GenerateColumnsImpl<T>(desc); }
0355
0356 void ConstructValue(void *where) const final { new (where) T{0}; }
0357
0358 public:
0359 RSimpleField(std::string_view name, std::string_view type)
0360 : RFieldBase(name, type, ROOT::ENTupleStructure::kLeaf, true )
0361 {
0362 fTraits |= kTraitTrivialType;
0363 }
0364 RSimpleField(RSimpleField &&other) = default;
0365 RSimpleField &operator=(RSimpleField &&other) = default;
0366 ~RSimpleField() override = default;
0367
0368 T *Map(ROOT::NTupleSize_t globalIndex) { return fPrincipalColumn->Map<T>(globalIndex); }
0369 T *Map(RNTupleLocalIndex localIndex) { return fPrincipalColumn->Map<T>(localIndex); }
0370 T *MapV(ROOT::NTupleSize_t globalIndex, ROOT::NTupleSize_t &nItems)
0371 {
0372 return fPrincipalColumn->MapV<T>(globalIndex, nItems);
0373 }
0374 T *MapV(RNTupleLocalIndex localIndex, ROOT::NTupleSize_t &nItems)
0375 {
0376 return fPrincipalColumn->MapV<T>(localIndex, nItems);
0377 }
0378
0379 size_t GetValueSize() const final { return sizeof(T); }
0380 size_t GetAlignment() const final { return alignof(T); }
0381 };
0382
0383
0384
0385
0386
0387 }
0388
0389 #include "RField/RFieldFundamental.hxx"
0390 #include "RField/RFieldProxiedCollection.hxx"
0391 #include "RField/RFieldRecord.hxx"
0392 #include "RField/RFieldSequenceContainer.hxx"
0393 #include "RField/RFieldSTLMisc.hxx"
0394
0395 namespace ROOT {
0396
0397 template <typename SizeT>
0398 class RField<RNTupleCardinality<SizeT>> final : public RCardinalityField {
0399 protected:
0400 std::unique_ptr<ROOT::RFieldBase> CloneImpl(std::string_view newName) const final
0401 {
0402 return std::make_unique<RField<RNTupleCardinality<SizeT>>>(newName);
0403 }
0404 void ConstructValue(void *where) const final { new (where) RNTupleCardinality<SizeT>(0); }
0405
0406
0407 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
0408 {
0409 RNTupleLocalIndex collectionStart;
0410 ROOT::NTupleSize_t size;
0411 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &size);
0412 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
0413 }
0414
0415
0416 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final
0417 {
0418 RNTupleLocalIndex collectionStart;
0419 ROOT::NTupleSize_t size;
0420 fPrincipalColumn->GetCollectionInfo(localIndex, &collectionStart, &size);
0421 *static_cast<RNTupleCardinality<SizeT> *>(to) = size;
0422 }
0423
0424 std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final
0425 {
0426 RNTupleLocalIndex collectionStart;
0427 ROOT::NTupleSize_t collectionSize;
0428 fPrincipalColumn->GetCollectionInfo(bulkSpec.fFirstIndex, &collectionStart, &collectionSize);
0429
0430 auto typedValues = static_cast<RNTupleCardinality<SizeT> *>(bulkSpec.fValues);
0431 typedValues[0] = collectionSize;
0432
0433 auto lastOffset = collectionStart.GetIndexInCluster() + collectionSize;
0434 ROOT::NTupleSize_t nRemainingEntries = bulkSpec.fCount - 1;
0435 std::size_t nEntries = 1;
0436 while (nRemainingEntries > 0) {
0437 ROOT::NTupleSize_t nItemsUntilPageEnd;
0438 auto offsets =
0439 fPrincipalColumn->MapV<ROOT::Internal::RColumnIndex>(bulkSpec.fFirstIndex + nEntries, nItemsUntilPageEnd);
0440 std::size_t nBatch = std::min(nRemainingEntries, nItemsUntilPageEnd);
0441 for (std::size_t i = 0; i < nBatch; ++i) {
0442 typedValues[nEntries + i] = offsets[i] - lastOffset;
0443 lastOffset = offsets[i];
0444 }
0445 nRemainingEntries -= nBatch;
0446 nEntries += nBatch;
0447 }
0448 return RBulkSpec::kAllSet;
0449 }
0450
0451 public:
0452 static std::string TypeName() { return "ROOT::RNTupleCardinality<" + RField<SizeT>::TypeName() + ">"; }
0453 explicit RField(std::string_view name) : RCardinalityField(name, TypeName()) {}
0454 RField(RField &&other) = default;
0455 RField &operator=(RField &&other) = default;
0456 ~RField() final = default;
0457
0458 size_t GetValueSize() const final { return sizeof(RNTupleCardinality<SizeT>); }
0459 size_t GetAlignment() const final { return alignof(RNTupleCardinality<SizeT>); }
0460 };
0461
0462
0463 template <>
0464 class RField<TObject> final : public RFieldBase {
0465 static std::size_t GetOffsetOfMember(const char *name);
0466 static std::size_t GetOffsetUniqueID() { return GetOffsetOfMember("fUniqueID"); }
0467 static std::size_t GetOffsetBits() { return GetOffsetOfMember("fBits"); }
0468
0469 private:
0470 RField(std::string_view fieldName, const RField<TObject> &source);
0471
0472 protected:
0473 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
0474
0475 void ConstructValue(void *where) const final;
0476 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RTypedDeleter<TObject>>(); }
0477
0478 std::size_t AppendImpl(const void *from) final;
0479 void ReadTObject(void *to, UInt_t uniqueID, UInt_t bits);
0480 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
0481 void ReadInClusterImpl(RNTupleLocalIndex localIndex, void *to) final;
0482
0483 void AfterConnectPageSource() final;
0484
0485 public:
0486 static std::string TypeName() { return "TObject"; }
0487
0488 RField(std::string_view fieldName);
0489 RField(RField &&other) = default;
0490 RField &operator=(RField &&other) = default;
0491 ~RField() final = default;
0492
0493 std::vector<RValue> SplitValue(const RValue &value) const final;
0494 size_t GetValueSize() const final;
0495 size_t GetAlignment() const final;
0496 std::uint32_t GetTypeVersion() const final;
0497 std::uint32_t GetTypeChecksum() const final;
0498 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
0499 };
0500
0501
0502
0503
0504 template <typename T>
0505 std::unique_ptr<T, typename RFieldBase::RCreateObjectDeleter<T>::deleter> RFieldBase::CreateObject() const
0506 {
0507 if (GetTypeName() != RField<T>::TypeName()) {
0508 throw RException(
0509 R__FAIL("type mismatch for field " + GetFieldName() + ": " + GetTypeName() + " vs. " + RField<T>::TypeName()));
0510 }
0511 return std::unique_ptr<T>(static_cast<T *>(CreateObjectRawPtr()));
0512 }
0513
0514 template <>
0515 struct RFieldBase::RCreateObjectDeleter<void> {
0516 using deleter = RCreateObjectDeleter<void>;
0517 void operator()(void *);
0518 };
0519
0520 template <>
0521 std::unique_ptr<void, typename RFieldBase::RCreateObjectDeleter<void>::deleter>
0522 ROOT::RFieldBase::CreateObject<void>() const;
0523
0524 }
0525
0526 #endif