// @(#)root/base:$Name:  $:$Id: TProcessUUID.cxx,v 1.1 2002/07/09 21:17:02 brun Exp $
// Author: Rene Brun    06/07/2002

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

//////////////////////////////////////////////////////////////////////////
// 
// TProcessUUID
//
// This class is a specialized TProcessID managing the list of UUIDs.
// In addition to TProcessID, this object has the following members:
//   - fUUIDs  : a THashlist of TUUIDs in string format (using a TObjString)
//   - fActive : a TBits table with one bit per TUUID in the table
// When a new TUUID is entered into the list fUUIDs, it is assigned
// the first free slot in the list of bits and the TUUID UUIDNumber
// is set to this slot number.
// When a TUUID is removed from the list, the corresponding bit
// is reset in fActive.
// The object corresponding to a TUUID at slot I can be found
// via fObjects->At(I).
// One can use two mechanisms to find the object corresponding to a TUUID:
//  1- the input is the TUUID.AsString. One can find the corresponding 
//     TObjString object objs in fUUIDs via THashList::FindObject(name).
//     The slot number is then objs->GetUniqueID().
//  2- The input is the UUIDNumber. The slot number is UIUIDNumber
//
// When a TRef points to an object having a TUUID, both the TRef and the
// referenced object have their bit kHasUUID set. In this case, the pointer
// TProcessID *fPID in TRef points to the unique object TProcessUUID.
// The TRef uniqueID is directly the UUIDNumber=slot number.
//
//////////////////////////////////////////////////////////////////////////

#include "TROOT.h"
#include "TProcessUUID.h"
#include "THashList.h"
#include "TBits.h"
#include "TObjString.h"
#include "TUUID.h"

ClassImp(TProcessUUID)

//______________________________________________________________________________
TProcessUUID::TProcessUUID() : TProcessID()
{
   fUUIDs   = new THashList(100,3);
   fActive  = new TBits(100);
   IncrementCount();
}

//______________________________________________________________________________
TProcessUUID::~TProcessUUID()
{
   fUUIDs->Delete();
   delete fUUIDs;  fUUIDs  = 0;
   delete fActive; fActive = 0;
}

//______________________________________________________________________________
UInt_t TProcessUUID::AddUUID(TUUID &uuid, TObject *obj)
{
   // Add uuid to the table of UUIDs
   // The TObject *obj has its uniqueID set to the UUID number
   // return entry number in the table

   
   UInt_t number;
   const char *uuids = uuid.AsString();
   TObjString *objs = (TObjString*)fUUIDs->FindObject(uuids);
   if (objs) {
      number = objs->GetUniqueID();
      uuid.SetUUIDNumber(number);
      objs->SetUniqueID(number);
      obj->SetUniqueID(number);
      obj->SetBit(kHasUUID);
      if (number >= (UInt_t)fObjects->GetSize()) fObjects->AddAtAndExpand(obj,number);
      if (fObjects->UncheckedAt(number) == 0) fObjects->AddAt(obj,number);
      return number;
   }   
   
   objs = new TObjString(uuids);
   fUUIDs->Add(objs);
   number = fActive->FirstNullBit();
   uuid.SetUUIDNumber(number);
   objs->SetUniqueID(number);
   obj->SetUniqueID(number);
   obj->SetBit(kHasUUID);
   fActive->SetBitNumber(number);
   fObjects->AddAtAndExpand(obj,number);
   return number;
}

//______________________________________________________________________________
UInt_t TProcessUUID::AddUUID(const char *uuids)
{
   // Add uuid with name uuids to the table of UUIDs
   // return entry number in the table

   
   TObjString *objs = (TObjString*)fUUIDs->FindObject(uuids);
   if (objs) return objs->GetUniqueID();
   
   UInt_t number;
   objs = new TObjString(uuids);
   fUUIDs->Add(objs);
   number = fActive->FirstNullBit();
   objs->SetUniqueID(number);
   fActive->SetBitNumber(number);
   return number;
}

//______________________________________________________________________________
TObjString *TProcessUUID::FindUUID(UInt_t number) const
{
   //Find the TObjString by slot number
   
   TIter next(fUUIDs);
   TObjString *obj;
   while ((obj = (TObjString*)next())) {
      if (obj->GetUniqueID() == number) return obj;
   }
   return 0;
}

//______________________________________________________________________________
void TProcessUUID::RemoveUUID(UInt_t number)
{
   //Remove entry number in the list of uuids
   if (number > (UInt_t)fObjects->GetSize()) return;
   TIter next(fUUIDs);
   TObjString *obj = FindUUID(number);
   if (obj) {
      fUUIDs->Remove(obj);
      delete obj;
      fActive->ResetBit(number);
      fObjects->AddAt(0,number);
      return;
   }
}   
