// file: $isip/class/search/HistoryPool/cpol_05.cc
// version: $Id: hpol_05.cc 9000 2003-01-23 20:00:34Z alphonso $
//

// isip include files
//
#include "HistoryPool.h"

// method: assign
//
// arguments:
//  const HistoryPool& copy_node: (input) node to copy
//
// return: logical error status
//
// assign HistoryPool from the copy
//
boolean HistoryPool::assign(const HistoryPool& copy_node_a) {

  // clear the contents
  //
  clear();
  
  // set the allocation mode
  //
  return pool_d.assign(copy_node_a.pool_d);
}

// method: clear
//
// arguments:
//  Integral::CMODE cmode: (input) clear mode
//
// return: logical error status
//
// clear the contents of the HistoryPool
//
boolean HistoryPool::clear(Integral::CMODE cmode_a) {

  // declare local variables
  //
  Vector<History> keys;
  History* ptr = (History*)NULL;
  
  // free the allocated history objects
  //
  pool_d.keys(keys);
  for (long i=0; i < keys.length(); i++) {
    pool_d.remove(keys(i), ptr);
    delete ptr;
    ptr = (History*)NULL;
  }

  // clear the pool
  //
  pool_d.clear(cmode_a);

  // set the allocation mode
  //
  pool_d.setAllocationMode(DstrBase::USER);

  // set the context pool capacity
  //
  pool_d.setCapacity(DEF_CAPACITY);
  
  // exit gracefully
  //
  return true;
}

// method: eq
//
// arguments:
//  const HistoryPool& compare_node: (input) HistoryPool to compare
//
// return: true if the HistoryPools are equivalent, else false
//
// compare two HistoryPools. they are equivalent if they have equivalent history
// objects
//
boolean HistoryPool::eq(const HistoryPool& compare_node_a) const {

  // compare the address
  //
  return (pool_d.eq(compare_node_a.pool_d));
}

// method: initAndAllocate
//
// arguments: none
//
// return: logical error status
//
// method creates a new history object and inserts it in the existing pool
//
History* HistoryPool::initAndAllocate() {

  // declare local variables
  //
  History* ptr = (History*)NULL;  
  History* new_obj = (History*)NULL;

  // allocate memory for the new object
  //
  new_obj = new History();

  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (History*)NULL) {

    delete new_obj;
    new_obj = ptr;
  }

  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }
  
  // return the object
  //
  return new_obj;
}

// method: popAndAllocate
//
// arguments:
//   History* obj: (input) input object
//   Context*& val: (output) context popped from the history stack
//
// return: logical error status
//
// method creates a new history object and inserts it in the existing pool
//
History* HistoryPool::popAndAllocate(History* obj_a, Context*& val_a) {

  // declare local variables
  //
  History* ptr = (History*)NULL;  
  History* new_obj = (History*)NULL;

  // make sure that the inout object is not empty
  //
  if (obj_a->isEmpty()) {
    Error::handle(name(), L"popAndAllocate", Error::ARG, __FILE__, __LINE__);
    return (History*)NULL;
  }
  
  // allocate memory for the new object
  //
  new_obj = new History(*obj_a);

  // pop the item from the stack
  //
  val_a = new_obj->pop();
    
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (History*)NULL) {

    delete new_obj;
    new_obj = ptr;
  }

  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }
  
  // return the object
  //
  return new_obj;
}

// method: pushAndAllocate
//
// arguments:
//   History* obj: (input) input object
//   Context* val: (output) context pushed on the history stack
//
// return: logical error status
//
// method creates a new history object and inserts it in the existing pool
//
History* HistoryPool::pushAndAllocate(History* obj_a, Context* val_a) {

  // declare local variables
  //
  History* ptr = (History*)NULL;  
  History* new_obj = (History*)NULL;

  // allocate memory for the new object
  //
  new_obj = new History(*obj_a);

  // push the item onto the stack
  //
  new_obj->push(val_a);
    
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (History*)NULL) {

    delete new_obj;
    new_obj = ptr;
  }

  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }
  
  // return the object
  //
  return new_obj;
}
