Logo ROOT  
Reference Guide
TBuffer.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id: 6da0b5b613bbcfaa3a5cd4074e7b2be2448dfb31 $
2// Author: Fons Rademakers 04/05/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TBuffer
13\ingroup Base
14
15Buffer base class used for serializing objects.
16*/
17
18#include "TBuffer.h"
19#include "TClass.h"
20#include "TProcessID.h"
21
22constexpr Int_t kExtraSpace = 8; // extra space at end of buffer (used for free block count)
23constexpr Int_t kMaxBufferSize = 0x7FFFFFFE; // largest possible size.
24
25
27
28/// Default streamer implementation used by ClassDefInline to avoid
29/// requirement to include TBuffer.h
30void ROOT::Internal::DefaultStreamer(TBuffer &R__b, const TClass *cl, void *objpointer)
31{
32 if (R__b.IsReading())
33 R__b.ReadClassBuffer(cl, objpointer);
34 else
35 R__b.WriteClassBuffer(cl, objpointer);
36}
37
38////////////////////////////////////////////////////////////////////////////////
39/// The user has provided memory than we don't own, thus we can not extent it
40/// either.
41
42static char *R__NoReAllocChar(char *, size_t, size_t)
43{
44 return 0;
45}
46
47////////////////////////////////////////////////////////////////////////////////
48/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
49/// TBuffer::kWrite. By default the I/O buffer has a size of
50/// TBuffer::kInitialSize (1024) bytes.
51
53{
55 fMode = mode;
56 fVersion = 0;
57 fParent = 0;
58
60
61 fBuffer = new char[fBufSize+kExtraSpace];
62
65
66 SetReAllocFunc( 0 );
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
71/// TBuffer::kWrite.
72
74{
75 if (bufsiz < 0)
76 Fatal("TBuffer","Request to create a buffer with a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", bufsiz, kMaxBufferSize);
77 if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
78 fBufSize = bufsiz;
79 fMode = mode;
80 fVersion = 0;
81 fParent = 0;
82
84
85 fBuffer = new char[fBufSize+kExtraSpace];
86
89
90 SetReAllocFunc( 0 );
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Create an I/O buffer object. Mode should be either TBuffer::kRead or
95/// TBuffer::kWrite. By default the I/O buffer has a size of
96/// TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
97/// to TBuffer via the buf argument. By default this buffer will be adopted
98/// unless adopt is false.
99///
100/// If the new buffer is _not_ adopted and no memory allocation routine
101/// is provided, a Fatal error will be issued if the Buffer attempts to
102/// expand.
103
104TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
105{
106 if (bufsiz < 0)
107 Fatal("TBuffer","Request to create a buffer with a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", bufsiz, kMaxBufferSize);
108 fBufSize = bufsiz;
109 fMode = mode;
110 fVersion = 0;
111 fParent = 0;
112
114
115 if (buf) {
116 fBuffer = (char *)buf;
117 if ( (fMode&kWrite)!=0 ) {
119 }
120 if (!adopt) ResetBit(kIsOwner);
121 } else {
122 if (fBufSize < kMinimalSize) {
124 }
126 }
129
130 SetReAllocFunc( reallocfunc );
131
132 if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
134 }
135}
136
137////////////////////////////////////////////////////////////////////////////////
138/// Delete an I/O buffer object.
139
141{
142 if (TestBit(kIsOwner)) {
143 //printf("Deleting fBuffer=%lx\n", fBuffer);
144 delete [] fBuffer;
145 }
146 fBuffer = 0;
147 fParent = 0;
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Automatically calculate a new size and expand the buffer to fit at least size_needed.
152/// The goals is to minimize the number of memory allocation and the memory allocation
153/// which avoiding too much memory wastage.
154///
155/// If the size_needed is larger than the current size, the policy
156/// is to expand to double the current size or the size_needed which ever is largest.
157
158void TBuffer::AutoExpand(Int_t size_needed)
159{
160 if (size_needed < 0) {
161 Fatal("AutoExpand","Request to expand to a negative size, likely due to an integer overflow: 0x%x for a max of 0x%x.", size_needed, kMaxBufferSize);
162 }
163 if (size_needed > fBufSize) {
164 Long64_t doubling = 2LLU * fBufSize;
165 if (doubling > kMaxBufferSize)
166 doubling = kMaxBufferSize;
167 if (size_needed > doubling) {
168 Expand(size_needed);
169 } else {
170 Expand(doubling);
171 }
172 }
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
177/// new buffer is expected to have the same size as the previous buffer.
178/// The current buffer position is reset to the start of the buffer.
179/// If the TBuffer owned the previous buffer, it will be deleted prior
180/// to accepting the new buffer. By default the new buffer will be
181/// adopted unless adopt is false.
182///
183/// If the new buffer is _not_ adopted and no memory allocation routine
184/// is provided, a Fatal error will be issued if the Buffer attempts to
185/// expand.
186
187void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
188{
189 if (fBuffer && TestBit(kIsOwner))
190 delete [] fBuffer;
191
192 if (adopt)
194 else
196
197 fBuffer = (char *)buf;
199 if (newsiz > 0) {
200 if ( (fMode&kWrite)!=0 ) {
201 fBufSize = newsiz - kExtraSpace;
202 } else {
203 fBufSize = newsiz;
204 }
205 }
207
208 SetReAllocFunc( reallocfunc );
209
210 if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
212 }
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Expand (or shrink) the I/O buffer to newsize bytes.
217/// If copy is true (the default), the existing content of the
218/// buffer is preserved, otherwise the buffer is returned zero-ed out.
219///
220/// In order to avoid losing data, if the current length is greater than
221/// the requested size, we only shrink down to the current length.
222
223void TBuffer::Expand(Int_t newsize, Bool_t copy)
224{
225 Int_t l = Length();
226 if ( (l > newsize) && copy ) {
227 newsize = l;
228 }
229 const Int_t extraspace = (fMode&kWrite)!=0 ? kExtraSpace : 0;
230
231 if ( ((Long64_t)newsize+extraspace) > kMaxBufferSize) {
232 if (l < kMaxBufferSize) {
233 newsize = kMaxBufferSize - extraspace;
234 } else {
235 Fatal("Expand","Requested size (%d) is too large (max is %d).", newsize, kMaxBufferSize);
236 }
237 }
238 if ( (fMode&kWrite)!=0 ) {
240 copy ? fBufSize+kExtraSpace : 0);
241 } else {
242 fBuffer = fReAllocFunc(fBuffer, newsize,
243 copy ? fBufSize : 0);
244 }
245 if (fBuffer == 0) {
247 Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
248 } else if (fReAllocFunc == R__NoReAllocChar) {
249 Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
250 } else {
251 Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", (Long_t)fReAllocFunc);
252 }
253 }
254 fBufSize = newsize;
255 fBufCur = fBuffer + l;
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Return pointer to parent of this buffer.
261
263{
264 return fParent;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Set parent owning this buffer.
269
271{
272 fParent = parent;
273}
274////////////////////////////////////////////////////////////////////////////////
275/// Return the reallocation method currently used.
276
278{
279 return fReAllocFunc;
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// Set which memory reallocation method to use. If reallocafunc is null,
284/// reset it to the default value (TStorage::ReAlloc)
285
287{
288 if (reallocfunc) {
289 fReAllocFunc = reallocfunc;
290 } else {
291 if (TestBit(kIsOwner)) {
293 } else {
295 }
296 }
297}
298
299////////////////////////////////////////////////////////////////////////////////
300/// Set buffer in read mode.
301
303{
304 if ( (fMode&kWrite)!=0 ) {
305 // We had reserved space for the free block count,
306 // release it,
308 }
309 fMode = kRead;
310}
311
312////////////////////////////////////////////////////////////////////////////////
313/// Set buffer in write mode.
314
316{
317 if ( (fMode&kWrite)==0 ) {
318 // We had not yet reserved space for the free block count,
319 // reserve it now.
321 }
322 fMode = kWrite;
323}
324
325////////////////////////////////////////////////////////////////////////////////
326/// Forward to TROOT::GetClass().
327
328TClass *TBuffer::GetClass(const std::type_info &typeinfo)
329{
330 return TClass::GetClass(typeinfo);
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Forward to TROOT::GetClass().
335
336TClass *TBuffer::GetClass(const char *className)
337{
338 return TClass::GetClass(className);
339}
340
341////////////////////////////////////////////////////////////////////////////////
342/// Return the current Process-ID.
343
345{
346 if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
347 return 0;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Always return 0 (current processID).
352
354{
355 return 0;
356}
357
358////////////////////////////////////////////////////////////////////////////////
359/// Push a new data cache area onto the list of area to be used for
360/// temporarily store 'missing' data members.
361
363{
364 fCacheStack.push_back(obj);
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// Return the 'current' data cache area from the list of area to be used for
369/// temporarily store 'missing' data members.
370
372{
373 if (fCacheStack.empty()) return 0;
374 return fCacheStack.back();
375}
376
377////////////////////////////////////////////////////////////////////////////////
378/// Pop and Return the 'current' data cache area from the list of area to be used for
379/// temporarily store 'missing' data members.
380
382{
384 fCacheStack.pop_back();
385 return val;
386}
387
388////////////////////////////////////////////////////////////////////////////////
389/// Byte-swap N primitive-elements in the buffer.
390/// Bulk API relies on this function.
391
393{
394 char *input_buf = GetCurrent();
395 if ((type == EDataType::kShort_t) || (type == EDataType::kUShort_t)) {
396#ifdef R__BYTESWAP
397 Short_t *buf __attribute__((aligned(8))) = reinterpret_cast<Short_t*>(input_buf);
398 for (int idx=0; idx<n; idx++) {
399 Short_t tmp = *reinterpret_cast<Short_t*>(buf + idx); // Makes a copy of the values; frombuf can't handle aliasing.
400 char *tmp_ptr = reinterpret_cast<char *>(&tmp);
401 frombuf(tmp_ptr, buf + idx);
402 }
403#endif
404 } else if ((type == EDataType::kFloat_t) || (type == EDataType::kInt_t) || (type == EDataType::kUInt_t)) {
405#ifdef R__BYTESWAP
406 Float_t *buf __attribute__((aligned(8))) = reinterpret_cast<Float_t*>(input_buf);
407 for (int idx=0; idx<n; idx++) {
408 Float_t tmp = *reinterpret_cast<Float_t*>(buf + idx); // Makes a copy of the values; frombuf can't handle aliasing.
409 char *tmp_ptr = reinterpret_cast<char *>(&tmp);
410 frombuf(tmp_ptr, buf + idx);
411 }
412#endif
413 } else if ((type == EDataType::kDouble_t) || (type == EDataType::kLong64_t) || (type == EDataType::kULong64_t)) {
414#ifdef R__BYTESWAP
415 Double_t *buf __attribute__((aligned(8))) = reinterpret_cast<Double_t*>(input_buf);
416 for (int idx=0; idx<n; idx++) {
417 Double_t tmp = *reinterpret_cast<Double_t*>(buf + idx); // Makes a copy of the values; frombuf can't handle aliasing.
418 char *tmp_ptr = reinterpret_cast<char*>(&tmp);
419 frombuf(tmp_ptr, buf + idx);
420 }
421#endif
422 } else {
423 return false;
424 }
425
426 return true;
427}
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:280
int Int_t
Definition: CPyCppyy.h:43
unsigned int UInt_t
Definition: CPyCppyy.h:44
long Long_t
Definition: CPyCppyy.h:50
unsigned short UShort_t
Definition: RtypesCore.h:38
bool Bool_t
Definition: RtypesCore.h:61
short Short_t
Definition: RtypesCore.h:37
double Double_t
Definition: RtypesCore.h:57
float Float_t
Definition: RtypesCore.h:55
#define ClassImp(name)
Definition: Rtypes.h:361
constexpr Int_t kExtraSpace
Definition: TBuffer.cxx:22
constexpr Int_t kMaxBufferSize
Definition: TBuffer.cxx:23
static char * R__NoReAllocChar(char *, size_t, size_t)
The user has provided memory than we don't own, thus we can not extent it either.
Definition: TBuffer.cxx:42
EDataType
Definition: TDataType.h:28
@ kFloat_t
Definition: TDataType.h:31
@ kULong64_t
Definition: TDataType.h:32
@ kInt_t
Definition: TDataType.h:30
@ kShort_t
Definition: TDataType.h:29
@ kLong64_t
Definition: TDataType.h:32
@ kUShort_t
Definition: TDataType.h:29
@ kDouble_t
Definition: TDataType.h:31
@ kUInt_t
Definition: TDataType.h:30
char *(* ReAllocCharFun_t)(char *, size_t, size_t)
Definition: TStorage.h:30
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
char * GetCurrent() const
Definition: TBuffer.h:96
TBuffer()
Definition: TBuffer.h:58
void SetWriteMode()
Set buffer in write mode.
Definition: TBuffer.cxx:315
void SetReAllocFunc(ReAllocCharFun_t reallocfunc=0)
Set which memory reallocation method to use.
Definition: TBuffer.cxx:286
Bool_t ByteSwapBuffer(Long64_t n, EDataType type)
Byte-swap N primitive-elements in the buffer.
Definition: TBuffer.cxx:392
CacheList_t fCacheStack
Realloc function to be used when extending the buffer.
Definition: TBuffer.h:55
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:344
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:353
Int_t fBufSize
Definition: TBuffer.h:49
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:270
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:262
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:223
@ kIsOwner
Definition: TBuffer.h:74
virtual void PushDataCache(TVirtualArray *)
Push a new data cache area onto the list of area to be used for temporarily store 'missing' data memb...
Definition: TBuffer.cxx:362
virtual TVirtualArray * PopDataCache()
Pop and Return the 'current' data cache area from the list of area to be used for temporarily store '...
Definition: TBuffer.cxx:381
@ kWrite
Definition: TBuffer.h:72
@ kRead
Definition: TBuffer.h:72
char * fBufMax
Definition: TBuffer.h:52
char * fBufCur
Definition: TBuffer.h:51
void AutoExpand(Int_t size_needed)
Automatically calculate a new size and expand the buffer to fit at least size_needed.
Definition: TBuffer.cxx:158
void SetBuffer(void *buf, UInt_t bufsiz=0, Bool_t adopt=kTRUE, ReAllocCharFun_t reallocfunc=0)
Sets a new buffer in an existing TBuffer object.
Definition: TBuffer.cxx:187
virtual TVirtualArray * PeekDataCache() const
Return the 'current' data cache area from the list of area to be used for temporarily store 'missing'...
Definition: TBuffer.cxx:371
@ kMinimalSize
Definition: TBuffer.h:77
@ kInitialSize
Definition: TBuffer.h:77
virtual ~TBuffer()
Delete an I/O buffer object.
Definition: TBuffer.cxx:140
static TClass * GetClass(const std::type_info &typeinfo)
Forward to TROOT::GetClass().
Definition: TBuffer.cxx:328
Bool_t IsReading() const
Definition: TBuffer.h:85
Bool_t fMode
Definition: TBuffer.h:47
ReAllocCharFun_t GetReAllocFunc() const
Return the reallocation method currently used.
Definition: TBuffer.cxx:277
ReAllocCharFun_t fReAllocFunc
Definition: TBuffer.h:54
char * fBuffer
Definition: TBuffer.h:50
TObject * fParent
Definition: TBuffer.h:53
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:302
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Int_t fVersion
Definition: TBuffer.h:48
Int_t Length() const
Definition: TBuffer.h:99
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2937
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:919
void ResetBit(UInt_t f)
Definition: TObject.h:186
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:341
static char * ReAllocChar(char *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:265
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:27
long long Long64_t
Definition: cpp_cppyy.h:13
const Int_t n
Definition: legend1.C:16
void DefaultStreamer(TBuffer &R__b, const TClass *cl, void *objpointer)
Default streamer implementation used by ClassDefInline to avoid requirement to include TBuffer....
Definition: TBuffer.cxx:30
auto * l
Definition: textangle.C:4