#include "TExMap.h"
#include "TError.h"
#include "TMathBase.h"
#include <string.h>
ClassImp(TExMap)
TExMap::TExMap(Int_t mapSize)
{
   
   
   if (mapSize < 4) mapSize = 5;
   switch (mapSize) {
      
      case   5: fSize = 5; break;
      case 503: fSize = 503; break;
      default:
         fSize  = (Int_t)TMath::NextPrime(mapSize);
   }
   fTable = new Assoc_t [fSize];
   memset(fTable,0,sizeof(Assoc_t)*fSize);
   fTally = 0;
}
TExMap::TExMap(const TExMap &map) : TObject(map)
{
   
   fSize  = map.fSize;
   fTally = map.fTally;
   fTable = new Assoc_t [fSize];
   memcpy(fTable, map.fTable, fSize*sizeof(Assoc_t));
}
TExMap& TExMap::operator=(const TExMap &map)
{
   
   if (this != &map) {
      TObject::operator=(map);
      fSize  = map.fSize;
      fTally = map.fTally;
      fTable = new Assoc_t [fSize];
      memcpy(fTable, map.fTable, fSize*sizeof(Assoc_t));
   }
   return *this;
}
TExMap::~TExMap()
{
   
   delete [] fTable; fTable = 0;
}
void TExMap::Add(ULong_t hash, Long_t key, Long_t value)
{
   
   if (!fTable) return;
   Int_t slot = FindElement(hash, key);
   if (!fTable[slot].InUse()) {
      fTable[slot].SetHash(hash);
      fTable[slot].fKey = key;
      fTable[slot].fValue = value;
      fTally++;
      if (HighWaterMark())
         Expand(2 * fSize);
   } else
      Error("Add", "key %ld is not unique", key);
}
void TExMap::AddAt(UInt_t slot, ULong_t hash, Long_t key, Long_t value)
{
   
   
   
   
   
   
   
   
   
   if (!fTable) return;
   if (!fTable[slot].InUse()) {
      fTable[slot].SetHash(hash);
      fTable[slot].fKey = key;
      fTable[slot].fValue = value;
      fTally++;
      if (HighWaterMark())
         Expand(2 * fSize);
   } else {
      Add(hash,key,value);
   }
}
Long_t &TExMap::operator()(ULong_t hash, Long_t key)
{
   
   
   
   
   static Long_t err;
   if (!fTable) {
      Error("operator()", "fTable==0, should never happen");
      return err;
   }
   Int_t slot = FindElement(hash, key);
   if (!fTable[slot].InUse()) {
      fTable[slot].SetHash(hash);
      fTable[slot].fKey = key;
      fTable[slot].fValue = 0;
      fTally++;
      if (HighWaterMark()) {
         Expand(2 * fSize);
         slot = FindElement(hash, key);
      }
   }
   return fTable[slot].fValue;
}
void TExMap::Delete(Option_t *)
{
   
   memset(fTable,0,sizeof(Assoc_t)*fSize);
   fTally = 0;
}
Long_t TExMap::GetValue(ULong_t hash, Long_t key)
{
   
   
   if (!fTable) return 0;
   hash |= 0x1;
   Int_t slot = Int_t(hash % fSize);
   Int_t firstSlot = slot;
   do {
      if (!fTable[slot].InUse()) return 0;
      if (key == fTable[slot].fKey) return fTable[slot].fValue;
      if (++slot == fSize) slot = 0;
   } while (firstSlot != slot);
   Error("GetValue", "table full");
   return 0;
}
Long_t TExMap::GetValue(ULong_t hash, Long_t key, UInt_t &slot)
{
   
   
   
   
   if (!fTable) { slot = 0; return 0; }
   hash |= 0x1;
   slot = Int_t(hash % fSize);
   UInt_t firstSlot = slot;
   do {
      if (!fTable[slot].InUse()) return 0;
      if (key == fTable[slot].fKey) return fTable[slot].fValue;
      if (++slot == (UInt_t)fSize) slot = 0;
   } while (firstSlot != slot);
   Error("GetValue", "table full");
   return 0;
}
void TExMap::Remove(ULong_t hash, Long_t key)
{
   
   if (!fTable)
      return;
   Int_t i = FindElement(hash, key);
   if (!fTable[i].InUse()) {
      Error("Remove", "key %ld not found at %d", key, i);
      return;
   }
   fTable[i].Clear();
   FixCollisions(i);
   fTally--;
}
Int_t TExMap::FindElement(ULong_t hash, Long_t key)
{
   
   
   if (!fTable) return 0;
   hash |= 0x1;
   Int_t slot = Int_t(hash % fSize);
   Int_t firstSlot = slot;
   do {
      if (!fTable[slot].InUse()) return slot;
      if (key == fTable[slot].fKey) return slot;
      if (++slot == fSize) slot = 0;
   } while (firstSlot != slot);
   Error("FindElement", "table full");
   return 0;
}
void TExMap::FixCollisions(Int_t index)
{
   
   Int_t oldIndex, nextIndex;
   Assoc_t nextObject;
   for (oldIndex = index+1; ;oldIndex++) {
      if (oldIndex >= fSize)
         oldIndex = 0;
      nextObject = fTable[oldIndex];
      if (!nextObject.InUse())
         break;
      nextIndex = FindElement(nextObject.GetHash(), nextObject.fKey);
      if (nextIndex != oldIndex) {
         fTable[nextIndex] = nextObject;
         fTable[oldIndex].Clear();
      }
   }
}
void TExMap::Expand(Int_t newSize)
{
   
   Int_t i;
   Assoc_t *oldTable = fTable;
   Int_t oldsize = fSize;
   newSize = (Int_t)TMath::NextPrime(newSize);
   fTable  = new Assoc_t [newSize];
   for (i = newSize; --i >= 0;) {
      fTable[i].Clear();
   }
   fSize = newSize;
   for (i = 0; i < oldsize; i++)
      if (oldTable[i].InUse()) {
         Int_t slot = FindElement(oldTable[i].GetHash(), oldTable[i].fKey);
         if (!fTable[slot].InUse())
            fTable[slot] = oldTable[i];
         else
            Error("Expand", "slot %d not empty (should never happen)", slot);
      }
   delete [] oldTable;
}
void TExMap::Streamer(TBuffer &b)
{
   
   Int_t i;
   UInt_t R__s, R__c;
   if (b.IsReading()) {
      b.ReadVersion(&R__s, &R__c);
      TObject::Streamer(b);
      Int_t n;
      b >> n;
      ULong_t hash;
      Long_t key,value;
      for (i = 0; i < n; i++) {
         b >> hash;
         b >> key;
         b >> value;
         Add(hash,key,value);
      }
      b.CheckByteCount(R__s, R__c,TExMap::IsA());
   } else {
      R__c = b.WriteVersion(TExMap::IsA(), kTRUE);
      TObject::Streamer(b);
      b << fTally;
      for (i=0;i<fSize;i++) {
         if (!fTable[i].InUse()) continue;
         b << fTable[i].GetHash();
         b << fTable[i].fKey;
         b << fTable[i].fValue;
      }
      b.SetByteCount(R__c, kTRUE);
   }
}
ClassImp(TExMapIter)
TExMapIter::TExMapIter(const TExMap *map) : fMap(map), fCursor(0)
{
   
}
TExMapIter &TExMapIter::operator=(const TExMapIter &rhs)
{
   
   if (this != &rhs) {
      fMap    = rhs.fMap;
      fCursor = rhs.fCursor;
   }
   return *this;
}
Bool_t TExMapIter::Next(ULong_t &hash, Long_t &key, Long_t &value)
{
   
   while (fCursor < fMap->fSize && !fMap->fTable[fCursor].InUse())
      fCursor++;
   if (fCursor == fMap->fSize)
      return kFALSE;
   hash  = fMap->fTable[fCursor].GetHash();
   key   = fMap->fTable[fCursor].fKey;
   value = fMap->fTable[fCursor].fValue;
   fCursor++;
   return kTRUE;
}
Bool_t TExMapIter::Next(Long_t &key, Long_t &value)
{
   
   ULong_t hash;
   return Next(hash, key, value);
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.