// @(#)root/io:$Id$
// Author: Rene Brun   28/12/94

/*************************************************************************
 * 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.             *
 *************************************************************************/

#include "TFree.h"
#include "TList.h"
#include "TFile.h"
#include "Bytes.h"
#include "Riostream.h"

ClassImp(TFree)

//______________________________________________________________________________
//
// Service class for TFile.
// Each file has a linked list of free segments. Each free segment
// is described by its firts and last address.
// When an object is written to a file via TObject::Write, a new Key (see TKey)
// is created. The first free segment big enough to accomodate the object
// is used.
// If the object size has a length corresponding to the size of the free segment,
// the free segment is deleted from the list of free segments.
// When an object is deleted from a file, a new TFree object is generated.
// If the deleted object is contiguous to an already deleted object, the free
// segments are merged in one single segment.
//

//______________________________________________________________________________
TFree::TFree()
{
   // TFree default constructor.

   fFirst = fLast = 0;
}

//______________________________________________________________________________
TFree::TFree(TList *lfree, Long64_t first, Long64_t last)
{
   // Constructor for a FREE segment.

   fFirst = first;
   fLast  = last;
   lfree->Add(this);
}

//______________________________________________________________________________
TFree *TFree::AddFree(TList *lfree, Long64_t first, Long64_t last)
{
// Add a new free segment to the list of free segments.
//
//  If last just precedes an existing free segment, then first becomes
//     the new starting location of the free segment.
//  if first just follows an existing free segment, then last becomes
//     the new ending location of the free segment.
//  if first just follows an existing free segment AND last just precedes
//     an existing free segment, these two segments are merged into
//     one single segment.
//

   TFree *idcur = this;
   while (idcur) {
      Long64_t curfirst = idcur->GetFirst();
      Long64_t curlast  = idcur->GetLast();
      if (curlast == first-1) {
         idcur->SetLast(last);
         TFree *idnext = (TFree*)lfree->After(idcur);
         if (idnext == 0) return idcur;
         if (idnext->GetFirst() > last+1) return idcur;
         idcur->SetLast( idnext->GetLast() );
         lfree->Remove(idnext);
         delete idnext;
         return idcur;
      }
      if (curfirst == last+1) {
         idcur->SetFirst(first);
         return idcur;
      }
      if (first < curfirst) {
         TFree * newfree = new TFree();
         newfree->SetFirst(first);
         newfree->SetLast(last);
         lfree->AddBefore(idcur, newfree);
         return newfree;
      }
      idcur = (TFree*)lfree->After(idcur);
   }
   return 0;
}

//______________________________________________________________________________
TFree::~TFree()
{
   // TFree Destructor.

}

//______________________________________________________________________________
void TFree::FillBuffer(char *&buffer)
{
   // Encode FREE structure into output buffer.

   Version_t version = TFree::Class_Version();
   if (fLast > TFile::kStartBigFile) version += 1000;
   tobuf(buffer, version);
//printf("TFree::fillBuffer, fFirst=%lld, fLast=%lld, version=%d\n",fFirst,fLast,version);
   if (version > 1000) {
      tobuf(buffer, fFirst);
      tobuf(buffer, fLast);
   } else {
      tobuf(buffer, (Int_t)fFirst);
      tobuf(buffer, (Int_t)fLast);
   }
}

//______________________________________________________________________________
TFree *TFree::GetBestFree(TList *lfree, Int_t nbytes)
{
   // Return the best free segment where to store nbytes.

   TFree *idcur = this;
   if (idcur == 0) return 0;
   TFree *idcur1 = 0;
   do {
      Long64_t nleft = Long64_t(idcur->fLast - idcur->fFirst +1);
      if (nleft == nbytes) {
         // Found an exact match
         return idcur;
      }
      if(nleft > (Long64_t)(nbytes+3)) {
         if (idcur1 == 0) {
            idcur1=idcur;
         }
      }
      idcur = (TFree*)lfree->After(idcur);
   } while (idcur !=0);

   // return first segment >nbytes
   if (idcur1) return idcur1;

   //try big file
   idcur = (TFree*)lfree->Last();
   Long64_t last = idcur->fLast+1000000000;
   idcur->SetLast(last);
   return idcur;
}

//______________________________________________________________________________
void TFree::ls(Option_t *) const
{
   // List free segment contents.

   std::cout <<"Free Segment: "<<fFirst<<"\t"<<fLast<<std::endl;
}

//______________________________________________________________________________
void TFree::ReadBuffer(char *&buffer)
{
   // Decode one FREE structure from input buffer

   Version_t version;
   frombuf(buffer, &version);
   if (version > 1000) {
      frombuf(buffer, &fFirst);
      frombuf(buffer, &fLast);
   } else {
      Int_t first,last;
      frombuf(buffer, &first);  fFirst = (Long64_t)first;
      frombuf(buffer, &last);   fLast  = (Long64_t)last;
   }
}

//______________________________________________________________________________
Int_t TFree::Sizeof() const
{
   // return number of bytes occupied by this TFree on permanent storage

   if (fLast > TFile::kStartBigFile) return 18;
   else                              return 10;
}

 TFree.cxx:1
 TFree.cxx:2
 TFree.cxx:3
 TFree.cxx:4
 TFree.cxx:5
 TFree.cxx:6
 TFree.cxx:7
 TFree.cxx:8
 TFree.cxx:9
 TFree.cxx:10
 TFree.cxx:11
 TFree.cxx:12
 TFree.cxx:13
 TFree.cxx:14
 TFree.cxx:15
 TFree.cxx:16
 TFree.cxx:17
 TFree.cxx:18
 TFree.cxx:19
 TFree.cxx:20
 TFree.cxx:21
 TFree.cxx:22
 TFree.cxx:23
 TFree.cxx:24
 TFree.cxx:25
 TFree.cxx:26
 TFree.cxx:27
 TFree.cxx:28
 TFree.cxx:29
 TFree.cxx:30
 TFree.cxx:31
 TFree.cxx:32
 TFree.cxx:33
 TFree.cxx:34
 TFree.cxx:35
 TFree.cxx:36
 TFree.cxx:37
 TFree.cxx:38
 TFree.cxx:39
 TFree.cxx:40
 TFree.cxx:41
 TFree.cxx:42
 TFree.cxx:43
 TFree.cxx:44
 TFree.cxx:45
 TFree.cxx:46
 TFree.cxx:47
 TFree.cxx:48
 TFree.cxx:49
 TFree.cxx:50
 TFree.cxx:51
 TFree.cxx:52
 TFree.cxx:53
 TFree.cxx:54
 TFree.cxx:55
 TFree.cxx:56
 TFree.cxx:57
 TFree.cxx:58
 TFree.cxx:59
 TFree.cxx:60
 TFree.cxx:61
 TFree.cxx:62
 TFree.cxx:63
 TFree.cxx:64
 TFree.cxx:65
 TFree.cxx:66
 TFree.cxx:67
 TFree.cxx:68
 TFree.cxx:69
 TFree.cxx:70
 TFree.cxx:71
 TFree.cxx:72
 TFree.cxx:73
 TFree.cxx:74
 TFree.cxx:75
 TFree.cxx:76
 TFree.cxx:77
 TFree.cxx:78
 TFree.cxx:79
 TFree.cxx:80
 TFree.cxx:81
 TFree.cxx:82
 TFree.cxx:83
 TFree.cxx:84
 TFree.cxx:85
 TFree.cxx:86
 TFree.cxx:87
 TFree.cxx:88
 TFree.cxx:89
 TFree.cxx:90
 TFree.cxx:91
 TFree.cxx:92
 TFree.cxx:93
 TFree.cxx:94
 TFree.cxx:95
 TFree.cxx:96
 TFree.cxx:97
 TFree.cxx:98
 TFree.cxx:99
 TFree.cxx:100
 TFree.cxx:101
 TFree.cxx:102
 TFree.cxx:103
 TFree.cxx:104
 TFree.cxx:105
 TFree.cxx:106
 TFree.cxx:107
 TFree.cxx:108
 TFree.cxx:109
 TFree.cxx:110
 TFree.cxx:111
 TFree.cxx:112
 TFree.cxx:113
 TFree.cxx:114
 TFree.cxx:115
 TFree.cxx:116
 TFree.cxx:117
 TFree.cxx:118
 TFree.cxx:119
 TFree.cxx:120
 TFree.cxx:121
 TFree.cxx:122
 TFree.cxx:123
 TFree.cxx:124
 TFree.cxx:125
 TFree.cxx:126
 TFree.cxx:127
 TFree.cxx:128
 TFree.cxx:129
 TFree.cxx:130
 TFree.cxx:131
 TFree.cxx:132
 TFree.cxx:133
 TFree.cxx:134
 TFree.cxx:135
 TFree.cxx:136
 TFree.cxx:137
 TFree.cxx:138
 TFree.cxx:139
 TFree.cxx:140
 TFree.cxx:141
 TFree.cxx:142
 TFree.cxx:143
 TFree.cxx:144
 TFree.cxx:145
 TFree.cxx:146
 TFree.cxx:147
 TFree.cxx:148
 TFree.cxx:149
 TFree.cxx:150
 TFree.cxx:151
 TFree.cxx:152
 TFree.cxx:153
 TFree.cxx:154
 TFree.cxx:155
 TFree.cxx:156
 TFree.cxx:157
 TFree.cxx:158
 TFree.cxx:159
 TFree.cxx:160
 TFree.cxx:161
 TFree.cxx:162
 TFree.cxx:163
 TFree.cxx:164
 TFree.cxx:165
 TFree.cxx:166
 TFree.cxx:167
 TFree.cxx:168
 TFree.cxx:169
 TFree.cxx:170
 TFree.cxx:171
 TFree.cxx:172
 TFree.cxx:173
 TFree.cxx:174
 TFree.cxx:175
 TFree.cxx:176
 TFree.cxx:177
 TFree.cxx:178
 TFree.cxx:179
 TFree.cxx:180
 TFree.cxx:181
 TFree.cxx:182
 TFree.cxx:183
 TFree.cxx:184
 TFree.cxx:185
 TFree.cxx:186
 TFree.cxx:187