// @(#)root/base:$Id: 6da0b5b613bbcfaa3a5cd4074e7b2be2448dfb31 $
// Author: Fons Rademakers   04/05/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBuffer                                                              //
//                                                                      //
// Buffer base class used for serializing objects.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBuffer.h"
#include "TClass.h"
#include "TProcessID.h"

const Int_t  kExtraSpace        = 8;   // extra space at end of buffer (used for free block count)

ClassImp(TBuffer)

//______________________________________________________________________________
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.
   return 0;
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes.

   fBufSize      = kInitialSize;
   fMode         = mode;
   fVersion      = 0;
   fParent       = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite.

   if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
   // to TBuffer via the buf argument. By default this buffer will be adopted
   // unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   if (buf) {
      fBuffer = (char *)buf;
      if ( (fMode&kWrite)!=0 ) {
         fBufSize -= kExtraSpace;
      }
      if (!adopt) ResetBit(kIsOwner);
   } else {
      if (fBufSize < kMinimalSize) {
         fBufSize = kMinimalSize;
      }
      fBuffer = new char[fBufSize+kExtraSpace];
   }
   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
TBuffer::~TBuffer()
{
   // Delete an I/O buffer object.

   if (TestBit(kIsOwner)) {
      //printf("Deleting fBuffer=%lx\n", fBuffer);
      delete [] fBuffer;
   }
   fBuffer = 0;
   fParent = 0;
}


//______________________________________________________________________________
void TBuffer::AutoExpand(Int_t size_needed)
{
   // Automatically calculate a new size and expand the buffer to fit at least size_needed.
   // The goals is to minimize the number of memory allocation and the memory allocation
   // which avoiding too much memory wastage.
   // If the size_needed is larger than the current size, the policy
   // is to expand to double the current size or the size_needed which ever is largest.

   if (size_needed > fBufSize) {
      if (size_needed > 2*fBufSize) {
         Expand(size_needed);
      } else {
         Expand(2*fBufSize);
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
   // new buffer is expected to have the same size as the previous buffer.
   // The current buffer position is reset to the start of the buffer.
   // If the TBuffer owned the previous buffer, it will be deleted prior
   // to accepting the new buffer. By default the new buffer will be
   // adopted unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   if (fBuffer && TestBit(kIsOwner))
      delete [] fBuffer;

   if (adopt)
      SetBit(kIsOwner);
   else
      ResetBit(kIsOwner);

   fBuffer = (char *)buf;
   fBufCur = fBuffer;
   if (newsiz > 0) {
      if ( (fMode&kWrite)!=0 ) {
         fBufSize = newsiz - kExtraSpace;
      } else {
         fBufSize = newsiz;
      }
   }
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
void TBuffer::Expand(Int_t newsize, Bool_t copy)
{
   // Expand (or shrink) the I/O buffer to newsize bytes.
   // If copy is true (the default), the existing content of the
   // buffer is preserved, otherwise the buffer is returned zero-ed out.
   //
   // In order to avoid losing data, if the current length is greater than
   // the requested size, we only shrink down to the current length.

   Int_t l  = Length();
   if ( l > newsize ) {
      newsize = l;
   }
   if ( (fMode&kWrite)!=0 ) {
      fBuffer  = fReAllocFunc(fBuffer, newsize+kExtraSpace,
                              copy ? fBufSize+kExtraSpace : 0);
   } else {
      fBuffer  = fReAllocFunc(fBuffer, newsize,
                              copy ? fBufSize : 0);
   }
   if (fBuffer == 0) {
      if (fReAllocFunc == TStorage::ReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
      } if (fReAllocFunc == R__NoReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
      } else {
         Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", (Long_t)fReAllocFunc);
      }
   }
   fBufSize = newsize;
   fBufCur  = fBuffer + l;
   fBufMax  = fBuffer + fBufSize;
}

//______________________________________________________________________________
TObject *TBuffer::GetParent() const
{
   // Return pointer to parent of this buffer.

   return fParent;
}

//______________________________________________________________________________
void TBuffer::SetParent(TObject *parent)
{
   // Set parent owning this buffer.

   fParent = parent;
}
//______________________________________________________________________________
ReAllocCharFun_t TBuffer::GetReAllocFunc() const
{
   // Return the reallocation method currently used.
   return fReAllocFunc;
}

//______________________________________________________________________________
void  TBuffer::SetReAllocFunc(ReAllocCharFun_t reallocfunc )
{
   // Set which memory reallocation method to use.  If reallocafunc is null,
   // reset it to the defaul value (TStorage::ReAlloc)

   if (reallocfunc) {
      fReAllocFunc = reallocfunc;
   } else {
      if (TestBit(kIsOwner)) {
         fReAllocFunc = TStorage::ReAllocChar;
      } else {
         fReAllocFunc = R__NoReAllocChar;
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetReadMode()
{
   // Set buffer in read mode.

   if ( (fMode&kWrite)!=0 ) {
      // We had reserved space for the free block count,
      // release it,
      fBufSize += kExtraSpace;
   }
   fMode = kRead;
}

//______________________________________________________________________________
void TBuffer::SetWriteMode()
{
   // Set buffer in write mode.

   if ( (fMode&kWrite)==0 ) {
      // We had not yet reserved space for the free block count,
      // reserve it now.
      fBufSize -= kExtraSpace;
   }
   fMode = kWrite;
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const type_info &typeinfo)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(typeinfo);
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const char *className)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(className);
}

//______________________________________________________________________________
TProcessID *TBuffer::ReadProcessID(UShort_t pidf)
{
   // Return the current PRocessID.

   if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
   return 0;
}

//______________________________________________________________________________
UShort_t TBuffer::WriteProcessID(TProcessID *)
{
   // Always return 0 (current processID).

   return 0;
}

//______________________________________________________________________________
void TBuffer::PushDataCache(TVirtualArray *obj)
{
   // Push a new data cache area onto the list of area to be used for
   // temporarily store 'missing' data members.

   fCacheStack.push_back(obj);
}

//______________________________________________________________________________
TVirtualArray *TBuffer::PeekDataCache() const
{
   // Return the 'current' data cache area from the list of area to be used for
   // temporarily store 'missing' data members.

   if (fCacheStack.empty()) return 0;
   return fCacheStack.back();
}

//______________________________________________________________________________
TVirtualArray *TBuffer::PopDataCache()
{
   // Pop and Return the 'current' data cache area from the list of area to be used for
   // temporarily store 'missing' data members.

   TVirtualArray *val = PeekDataCache();
   fCacheStack.pop_back();
   return val;
}

 TBuffer.cxx:1
 TBuffer.cxx:2
 TBuffer.cxx:3
 TBuffer.cxx:4
 TBuffer.cxx:5
 TBuffer.cxx:6
 TBuffer.cxx:7
 TBuffer.cxx:8
 TBuffer.cxx:9
 TBuffer.cxx:10
 TBuffer.cxx:11
 TBuffer.cxx:12
 TBuffer.cxx:13
 TBuffer.cxx:14
 TBuffer.cxx:15
 TBuffer.cxx:16
 TBuffer.cxx:17
 TBuffer.cxx:18
 TBuffer.cxx:19
 TBuffer.cxx:20
 TBuffer.cxx:21
 TBuffer.cxx:22
 TBuffer.cxx:23
 TBuffer.cxx:24
 TBuffer.cxx:25
 TBuffer.cxx:26
 TBuffer.cxx:27
 TBuffer.cxx:28
 TBuffer.cxx:29
 TBuffer.cxx:30
 TBuffer.cxx:31
 TBuffer.cxx:32
 TBuffer.cxx:33
 TBuffer.cxx:34
 TBuffer.cxx:35
 TBuffer.cxx:36
 TBuffer.cxx:37
 TBuffer.cxx:38
 TBuffer.cxx:39
 TBuffer.cxx:40
 TBuffer.cxx:41
 TBuffer.cxx:42
 TBuffer.cxx:43
 TBuffer.cxx:44
 TBuffer.cxx:45
 TBuffer.cxx:46
 TBuffer.cxx:47
 TBuffer.cxx:48
 TBuffer.cxx:49
 TBuffer.cxx:50
 TBuffer.cxx:51
 TBuffer.cxx:52
 TBuffer.cxx:53
 TBuffer.cxx:54
 TBuffer.cxx:55
 TBuffer.cxx:56
 TBuffer.cxx:57
 TBuffer.cxx:58
 TBuffer.cxx:59
 TBuffer.cxx:60
 TBuffer.cxx:61
 TBuffer.cxx:62
 TBuffer.cxx:63
 TBuffer.cxx:64
 TBuffer.cxx:65
 TBuffer.cxx:66
 TBuffer.cxx:67
 TBuffer.cxx:68
 TBuffer.cxx:69
 TBuffer.cxx:70
 TBuffer.cxx:71
 TBuffer.cxx:72
 TBuffer.cxx:73
 TBuffer.cxx:74
 TBuffer.cxx:75
 TBuffer.cxx:76
 TBuffer.cxx:77
 TBuffer.cxx:78
 TBuffer.cxx:79
 TBuffer.cxx:80
 TBuffer.cxx:81
 TBuffer.cxx:82
 TBuffer.cxx:83
 TBuffer.cxx:84
 TBuffer.cxx:85
 TBuffer.cxx:86
 TBuffer.cxx:87
 TBuffer.cxx:88
 TBuffer.cxx:89
 TBuffer.cxx:90
 TBuffer.cxx:91
 TBuffer.cxx:92
 TBuffer.cxx:93
 TBuffer.cxx:94
 TBuffer.cxx:95
 TBuffer.cxx:96
 TBuffer.cxx:97
 TBuffer.cxx:98
 TBuffer.cxx:99
 TBuffer.cxx:100
 TBuffer.cxx:101
 TBuffer.cxx:102
 TBuffer.cxx:103
 TBuffer.cxx:104
 TBuffer.cxx:105
 TBuffer.cxx:106
 TBuffer.cxx:107
 TBuffer.cxx:108
 TBuffer.cxx:109
 TBuffer.cxx:110
 TBuffer.cxx:111
 TBuffer.cxx:112
 TBuffer.cxx:113
 TBuffer.cxx:114
 TBuffer.cxx:115
 TBuffer.cxx:116
 TBuffer.cxx:117
 TBuffer.cxx:118
 TBuffer.cxx:119
 TBuffer.cxx:120
 TBuffer.cxx:121
 TBuffer.cxx:122
 TBuffer.cxx:123
 TBuffer.cxx:124
 TBuffer.cxx:125
 TBuffer.cxx:126
 TBuffer.cxx:127
 TBuffer.cxx:128
 TBuffer.cxx:129
 TBuffer.cxx:130
 TBuffer.cxx:131
 TBuffer.cxx:132
 TBuffer.cxx:133
 TBuffer.cxx:134
 TBuffer.cxx:135
 TBuffer.cxx:136
 TBuffer.cxx:137
 TBuffer.cxx:138
 TBuffer.cxx:139
 TBuffer.cxx:140
 TBuffer.cxx:141
 TBuffer.cxx:142
 TBuffer.cxx:143
 TBuffer.cxx:144
 TBuffer.cxx:145
 TBuffer.cxx:146
 TBuffer.cxx:147
 TBuffer.cxx:148
 TBuffer.cxx:149
 TBuffer.cxx:150
 TBuffer.cxx:151
 TBuffer.cxx:152
 TBuffer.cxx:153
 TBuffer.cxx:154
 TBuffer.cxx:155
 TBuffer.cxx:156
 TBuffer.cxx:157
 TBuffer.cxx:158
 TBuffer.cxx:159
 TBuffer.cxx:160
 TBuffer.cxx:161
 TBuffer.cxx:162
 TBuffer.cxx:163
 TBuffer.cxx:164
 TBuffer.cxx:165
 TBuffer.cxx:166
 TBuffer.cxx:167
 TBuffer.cxx:168
 TBuffer.cxx:169
 TBuffer.cxx:170
 TBuffer.cxx:171
 TBuffer.cxx:172
 TBuffer.cxx:173
 TBuffer.cxx:174
 TBuffer.cxx:175
 TBuffer.cxx:176
 TBuffer.cxx:177
 TBuffer.cxx:178
 TBuffer.cxx:179
 TBuffer.cxx:180
 TBuffer.cxx:181
 TBuffer.cxx:182
 TBuffer.cxx:183
 TBuffer.cxx:184
 TBuffer.cxx:185
 TBuffer.cxx:186
 TBuffer.cxx:187
 TBuffer.cxx:188
 TBuffer.cxx:189
 TBuffer.cxx:190
 TBuffer.cxx:191
 TBuffer.cxx:192
 TBuffer.cxx:193
 TBuffer.cxx:194
 TBuffer.cxx:195
 TBuffer.cxx:196
 TBuffer.cxx:197
 TBuffer.cxx:198
 TBuffer.cxx:199
 TBuffer.cxx:200
 TBuffer.cxx:201
 TBuffer.cxx:202
 TBuffer.cxx:203
 TBuffer.cxx:204
 TBuffer.cxx:205
 TBuffer.cxx:206
 TBuffer.cxx:207
 TBuffer.cxx:208
 TBuffer.cxx:209
 TBuffer.cxx:210
 TBuffer.cxx:211
 TBuffer.cxx:212
 TBuffer.cxx:213
 TBuffer.cxx:214
 TBuffer.cxx:215
 TBuffer.cxx:216
 TBuffer.cxx:217
 TBuffer.cxx:218
 TBuffer.cxx:219
 TBuffer.cxx:220
 TBuffer.cxx:221
 TBuffer.cxx:222
 TBuffer.cxx:223
 TBuffer.cxx:224
 TBuffer.cxx:225
 TBuffer.cxx:226
 TBuffer.cxx:227
 TBuffer.cxx:228
 TBuffer.cxx:229
 TBuffer.cxx:230
 TBuffer.cxx:231
 TBuffer.cxx:232
 TBuffer.cxx:233
 TBuffer.cxx:234
 TBuffer.cxx:235
 TBuffer.cxx:236
 TBuffer.cxx:237
 TBuffer.cxx:238
 TBuffer.cxx:239
 TBuffer.cxx:240
 TBuffer.cxx:241
 TBuffer.cxx:242
 TBuffer.cxx:243
 TBuffer.cxx:244
 TBuffer.cxx:245
 TBuffer.cxx:246
 TBuffer.cxx:247
 TBuffer.cxx:248
 TBuffer.cxx:249
 TBuffer.cxx:250
 TBuffer.cxx:251
 TBuffer.cxx:252
 TBuffer.cxx:253
 TBuffer.cxx:254
 TBuffer.cxx:255
 TBuffer.cxx:256
 TBuffer.cxx:257
 TBuffer.cxx:258
 TBuffer.cxx:259
 TBuffer.cxx:260
 TBuffer.cxx:261
 TBuffer.cxx:262
 TBuffer.cxx:263
 TBuffer.cxx:264
 TBuffer.cxx:265
 TBuffer.cxx:266
 TBuffer.cxx:267
 TBuffer.cxx:268
 TBuffer.cxx:269
 TBuffer.cxx:270
 TBuffer.cxx:271
 TBuffer.cxx:272
 TBuffer.cxx:273
 TBuffer.cxx:274
 TBuffer.cxx:275
 TBuffer.cxx:276
 TBuffer.cxx:277
 TBuffer.cxx:278
 TBuffer.cxx:279
 TBuffer.cxx:280
 TBuffer.cxx:281
 TBuffer.cxx:282
 TBuffer.cxx:283
 TBuffer.cxx:284
 TBuffer.cxx:285
 TBuffer.cxx:286
 TBuffer.cxx:287
 TBuffer.cxx:288
 TBuffer.cxx:289
 TBuffer.cxx:290
 TBuffer.cxx:291
 TBuffer.cxx:292
 TBuffer.cxx:293
 TBuffer.cxx:294
 TBuffer.cxx:295
 TBuffer.cxx:296
 TBuffer.cxx:297
 TBuffer.cxx:298
 TBuffer.cxx:299
 TBuffer.cxx:300
 TBuffer.cxx:301
 TBuffer.cxx:302
 TBuffer.cxx:303
 TBuffer.cxx:304
 TBuffer.cxx:305
 TBuffer.cxx:306
 TBuffer.cxx:307
 TBuffer.cxx:308
 TBuffer.cxx:309
 TBuffer.cxx:310
 TBuffer.cxx:311
 TBuffer.cxx:312
 TBuffer.cxx:313
 TBuffer.cxx:314
 TBuffer.cxx:315
 TBuffer.cxx:316
 TBuffer.cxx:317
 TBuffer.cxx:318
 TBuffer.cxx:319
 TBuffer.cxx:320
 TBuffer.cxx:321
 TBuffer.cxx:322
 TBuffer.cxx:323
 TBuffer.cxx:324
 TBuffer.cxx:325
 TBuffer.cxx:326
 TBuffer.cxx:327
 TBuffer.cxx:328
 TBuffer.cxx:329
 TBuffer.cxx:330
 TBuffer.cxx:331
 TBuffer.cxx:332
 TBuffer.cxx:333
 TBuffer.cxx:334
 TBuffer.cxx:335
 TBuffer.cxx:336
 TBuffer.cxx:337
 TBuffer.cxx:338
 TBuffer.cxx:339
 TBuffer.cxx:340
 TBuffer.cxx:341
 TBuffer.cxx:342
 TBuffer.cxx:343
 TBuffer.cxx:344
 TBuffer.cxx:345
 TBuffer.cxx:346
 TBuffer.cxx:347
 TBuffer.cxx:348
 TBuffer.cxx:349
 TBuffer.cxx:350
 TBuffer.cxx:351
 TBuffer.cxx:352
 TBuffer.cxx:353
 TBuffer.cxx:354