File indexing completed on 2026-09-14 09:23:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef ROOT_TEmulatedCollectionProxy
0012 #define ROOT_TEmulatedCollectionProxy
0013
0014 #include "TGenCollectionProxy.h"
0015 #include "ROOT/RAlignmentUtils.hxx"
0016
0017 #include <type_traits>
0018 #include <vector>
0019
0020 class TEmulatedCollectionProxy : public TGenCollectionProxy {
0021
0022
0023 friend class TCollectionProxy;
0024
0025 public:
0026
0027
0028 template <std::size_t Align>
0029 struct alignas(Align) AlignedStorage {
0030 char data[Align] = {};
0031 };
0032
0033
0034 using Cont1_t = std::vector<AlignedStorage< 1>>;
0035 using Cont2_t = std::vector<AlignedStorage< 2>>;
0036 using Cont4_t = std::vector<AlignedStorage< 4>>;
0037 using Cont8_t = std::vector<AlignedStorage< 8>>;
0038 using Cont16_t = std::vector<AlignedStorage< 16>>;
0039 using Cont32_t = std::vector<AlignedStorage< 32>>;
0040 using Cont64_t = std::vector<AlignedStorage< 64>>;
0041 using Cont128_t = std::vector<AlignedStorage< 128>>;
0042 using Cont256_t = std::vector<AlignedStorage< 256>>;
0043 using Cont512_t = std::vector<AlignedStorage< 512>>;
0044 using Cont1024_t = std::vector<AlignedStorage<1024>>;
0045 using Cont2048_t = std::vector<AlignedStorage<2048>>;
0046 using Cont4096_t = std::vector<AlignedStorage<4096>>;
0047
0048
0049
0050 using Cont_t = std::vector<char>;
0051 using PCont_t = Cont_t *;
0052
0053
0054
0055
0056
0057 template <typename F>
0058 void WithCont(void *obj, F &&fn) const
0059 {
0060 auto *vcl = GetValueClass();
0061 std::size_t align = alignof(std::max_align_t);
0062 if (!fKey && (fVal->fCase & kIsPointer)) {
0063
0064 align = alignof(void*);
0065 } else if (vcl) {
0066 assert(ROOT::Internal::IsValidAlignment(vcl->GetClassAlignment()));
0067 align = vcl->GetClassAlignment();
0068 } else {
0069 switch( int(fVal->fKind) ) {
0070 case kChar_t:
0071 case kUChar_t: align = alignof(char); break;
0072 case kShort_t:
0073 case kUShort_t: align = alignof(short); break;
0074 case kInt_t:
0075 case kUInt_t: align = alignof(int); break;
0076 case kLong_t:
0077 case kULong_t: align = alignof(long); break;
0078 case kLong64_t:
0079 case kULong64_t:align = alignof(long long); break;
0080 case kFloat16_t:
0081 case kFloat_t: align = alignof(float); break;
0082 case kDouble32_t:
0083 case kDouble_t: align = alignof(double); break;
0084 default:
0085 Fatal("TEmulatedCollectionProxy::WithCont", "Unsupported value type %d for value class %s", fVal->fKind,
0086 vcl ? vcl->GetName() : "<unknown>");
0087 }
0088 }
0089 switch (align) {
0090
0091
0092 case 4096: fn(reinterpret_cast<Cont4096_t*>(obj), std::size_t(4096)); break;
0093 case 2048: fn(reinterpret_cast<Cont2048_t*>(obj), std::size_t(2048)); break;
0094 case 1024: fn(reinterpret_cast<Cont1024_t*>(obj), std::size_t(1024)); break;
0095 case 512: fn(reinterpret_cast<Cont512_t *>(obj), std::size_t( 512)); break;
0096 case 256: fn(reinterpret_cast<Cont256_t *>(obj), std::size_t( 256)); break;
0097 case 128: fn(reinterpret_cast<Cont128_t *>(obj), std::size_t( 128)); break;
0098 case 64: fn(reinterpret_cast<Cont64_t *>(obj), std::size_t( 64)); break;
0099 case 32: fn(reinterpret_cast<Cont32_t *>(obj), std::size_t( 32)); break;
0100 case 16: fn(reinterpret_cast<Cont16_t *>(obj), std::size_t( 16)); break;
0101 case 8: fn(reinterpret_cast<Cont8_t *>(obj), std::size_t( 8)); break;
0102 case 4: fn(reinterpret_cast<Cont4_t *>(obj), std::size_t( 4)); break;
0103 case 2: fn(reinterpret_cast<Cont2_t *>(obj), std::size_t( 2)); break;
0104 case 1: fn(reinterpret_cast<Cont1_t *>(obj), std::size_t( 1)); break;
0105 default:
0106 Fatal("TEmulatedCollectionProxy::WithCont", "Unsupported alignment %zu for value class %s",
0107 align, vcl ? vcl->GetName() : "<unknown>");
0108 }
0109 }
0110 protected:
0111
0112
0113 TGenCollectionProxy* InitializeEx(Bool_t silent) override;
0114
0115
0116 void ReadItems(int nElements, TBuffer &b);
0117
0118
0119 void WriteItems(int nElements, TBuffer &b);
0120
0121
0122 void Shrink(UInt_t nCurr, UInt_t left, Bool_t force);
0123
0124
0125 void Expand(UInt_t nCurr, UInt_t left);
0126
0127 private:
0128 TEmulatedCollectionProxy &operator=(const TEmulatedCollectionProxy &);
0129
0130 public:
0131
0132 TVirtualCollectionProxy* Generate() const override;
0133
0134
0135 TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy);
0136
0137
0138 TEmulatedCollectionProxy(const char* cl_name, Bool_t silent);
0139
0140
0141 ~TEmulatedCollectionProxy() override;
0142
0143
0144 void *New() const override
0145 {
0146 void *mem = ::operator new(sizeof(Cont_t));
0147 WithCont(mem, [](auto *c, std::size_t) { new (c) std::decay_t<decltype(*c)>(); });
0148 return mem;
0149 }
0150
0151
0152 void *New(void *memory) const override
0153 {
0154 WithCont(memory, [](auto *c, std::size_t) { new (c) std::decay_t<decltype(*c)>(); });
0155 return memory;
0156 }
0157
0158
0159 TClass::ObjectPtr NewObject() const override { return {New(), nullptr}; }
0160
0161
0162 TClass::ObjectPtr NewObject(void *memory) const override { return {New(memory), nullptr}; }
0163
0164
0165 void *NewArray(Int_t nElements) const override
0166 {
0167 void *arr = ::operator new(nElements * sizeof(Cont_t));
0168 for (Int_t i = 0; i < nElements; ++i)
0169 WithCont(static_cast<char *>(arr) + i * sizeof(Cont_t),
0170 [](auto *c, std::size_t) { new (c) std::decay_t<decltype(*c)>(); });
0171 return arr;
0172 }
0173
0174
0175 void *NewArray(Int_t nElements, void *memory) const override
0176 {
0177 for (Int_t i = 0; i < nElements; ++i)
0178 WithCont(static_cast<char *>(memory) + i * sizeof(Cont_t),
0179 [](auto *c, std::size_t) { new (c) std::decay_t<decltype(*c)>(); });
0180 return memory;
0181 }
0182
0183
0184 TClass::ObjectPtr NewObjectArray(Int_t nElements) const override { return {NewArray(nElements), nullptr}; }
0185
0186
0187 TClass::ObjectPtr NewObjectArray(Int_t nElements, void *memory) const override
0188 {
0189 return {NewArray(nElements, memory), nullptr};
0190 }
0191
0192
0193 void Destructor(void* p, Bool_t dtorOnly = kFALSE) const override;
0194
0195
0196 void DeleteArray(void* p, Bool_t dtorOnly = kFALSE) const override;
0197
0198
0199 UInt_t Sizeof() const override { return sizeof(Cont_t); }
0200
0201
0202 void *At(UInt_t idx) override;
0203
0204
0205 void Clear(const char *opt = "") override;
0206
0207
0208 void Resize(UInt_t n, Bool_t force_delete) override;
0209
0210
0211 UInt_t Size() const override;
0212
0213
0214 void* Allocate(UInt_t n, Bool_t forceDelete) override;
0215
0216
0217 void Commit(void* env) override;
0218
0219
0220
0221 void Insert(const void *data, void *container, size_t size) override;
0222
0223
0224 void ReadBuffer(TBuffer &buff, void *pObj) override;
0225 void ReadBuffer(TBuffer &buff, void *pObj, const TClass *onfile) override;
0226
0227
0228 void Streamer(TBuffer &refBuffer) override;
0229
0230
0231 void Streamer(TBuffer &buff, void *pObj, int siz) override
0232 {
0233 TGenCollectionProxy::Streamer(buff,pObj,siz);
0234 }
0235
0236
0237 Bool_t IsValid() const;
0238 };
0239
0240
0241 namespace ROOT::Internal::TEmulatedProxyHelpers {
0242 inline void PrintWriteStlWithoutProxyMsg(const char *where, const char *clName, const char *BranchName)
0243 {
0244 const char *writeStlWithoutProxyMsg =
0245 "The class requested (%s) for the branch \"%s\" "
0246 "is an instance of an stl collection and does not have a compiled CollectionProxy. "
0247 "Please generate the dictionary for this collection (%s) to avoid writing corrupted data.";
0248
0249 Error(where, writeStlWithoutProxyMsg, clName, BranchName, clName);
0250 }
0251
0252 inline bool HasEmulatedProxy(TClass *cl){
0253 return cl && cl->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy *>(cl->GetCollectionProxy());
0254 }
0255 }
0256
0257
0258 #endif