/
ScryMUD/mud/
ScryMUD/mud/grrmud/Boards/
ScryMUD/mud/grrmud/Help/
ScryMUD/mud/grrmud/Pfiles/
ScryMUD/mud/grrmud/PlayerSacks/
ScryMUD/mud/grrmud/PlayerShops/
ScryMUD/mud/grrmud/help_filter/
ScryMUD/mud/hegemon/
ScryMUD/mud/hegemon/data/
ScryMUD/mud/hegemon/data/help/battle/
ScryMUD/mud/hegemon/data/help/client/
ScryMUD/mud/hegemon/data/help/communications/
ScryMUD/mud/hegemon/data/help/skills/
ScryMUD/mud/hegemon/data/help/spells/
ScryMUD/mud/include/
ScryMUD/mud/lib/
ScryMUD/mud/lib/bitfield/
ScryMUD/mud/lib/log/
ScryMUD/mud/lib/string2/
// $Id: PtrArray.cc,v 1.4.2.5 2000/01/30 02:21:53 greear Exp $
// $Revision: 1.4.2.5 $  $Author: greear $ $Date: 2000/01/30 02:21:53 $

//
//ScryMUD Server Code
//Copyright (C) 1998  Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// To contact the Author, Ben Greear:  greear@cyberhighway.net, (preferred)
//                                     greearb@agcs.com
//

// PtrArrayBase, PtrArray, LazyPtrArray

#include "PtrArray.h"

///**********************************************************************///
///*********************  PtrArrayBase  *********************************///
///**********************************************************************///

template <class T>
PtrArrayBase<T>::PtrArrayBase(int mx) {
   if (mx < 0)
      mx = 0;

   max_len = mx;
   cur_len = 0;
   ptr_list = new T*[mx + 1];

   memset(ptr_list, 0, ((mx + 1) * sizeof(T*)));

   //for (int i = 0; i<mx; i++) {
   //   ptr_list[i] = NULL;
   //}
}//constructor


template <class T>
PtrArrayBase<T>::~PtrArrayBase() {
   delete[] ptr_list;
}

// template <class T>
// PtrArrayBase<T>& PtrArrayBase<T>::operator=(const PtrArrayBase<T>& src) {
//    if (this == &src)
//       return *this;

//    ensureCapacity(src.max_len);

//    bcopy(ptr_list, src.ptr_list, (src.max_len * sizeof(T*)));
//    memcpy(ptr_list + (max_len * sizeof(T*)), 0, 
//           ((max_len - src.max_len) * sizeof(T*)));

//    cur_len = src.cur_len;

//    return *this;
// }

// Virtually does a clearAndDestroy on Self!!!!!!
template <class T>
void PtrArrayBase<T>::becomeDeepCopyOf(const PtrArrayBase<T>& src) {
   
   if (mudlog.ofLevel(DBG)) {
      mudlog << "In becomeDeepCopy, src.cur_len:  " << src.getCurLen()
             << " cur_len: " << cur_len << " max_len:  " << max_len
             << endl;
   }

   ensureCapacity(src.getCurLen());
   
   int i;
   for (i = 0; i<src.getCurLen(); i++) {
      if (ptr_list[i]) {
         if (mudlog.ofLevel(DBG)) {
            mudlog << "Deleting one, idx: " << i << endl;
         }
         delete ptr_list[i];
      }
      
      if (src.ptr_list[i]) {
         //mudlog << "Source existed for idx: " << i << endl << flush;
         ptr_list[i] = new T(*(src.ptr_list[i]));
         cur_len = i + 1;
      }
      else {
         ptr_list[i] = NULL;
      }
   }//for

   //mudlog << "Cleaning up remainder..." << endl;
   for (; i<getMaxLen(); i++) {
      if (ptr_list[i]) {
         //mudlog << "Deleting idx:  " << i << endl;
         delete ptr_list[i];
         ptr_list[i] = NULL;
      }
   }//for
}//becomeDeepCopyOf


// If it's not already in the array,
// find the first open slot and dump it in...
template <class T>
int PtrArrayBase<T>::gainData(T* val) {
   int open = -1;
   for (int i = 0; i<cur_len; i++) {
      if (ptr_list[i] == val) {
         return -1; //already in there
      }//if
      else if ((open < 0) && !ptr_list[i]) {
         open = i;
      }
   }//for

   if (open >= 0) {
      set(val, open); //take care of cur_len if needed
   }
   else {
      return appendShallowCopy(val);
   }//else

   return open;
}//gainData


// Return TRUE if val is in the array, false otherwise.
template <class T>
int PtrArrayBase<T>::haveData(const T* val) {
   for (int i = 0; i<cur_len; i++) {
      if (ptr_list[i] == val) {
         return TRUE;
      }//if
   }//for

   return FALSE;
}


// Find the first instance and remove it.
template <class T>
int PtrArrayBase<T>::loseData(const T* val) {
   for (int i = 0; i<cur_len; i++) {
      if (ptr_list[i] == val) {
         set((T*)NULL, i); //take care of cur_len if needed
         return TRUE;
      }//if
   }//for
   return FALSE;
}//loseData   


//  This copies the data from the incomming src, not just a shallow copy.
//  Does not copy NULL's over.
template <class T>
int PtrArrayBase<T>::appendDeepCopy(const PtrArrayBase<T>& src) {
   for (int i = 0; i<src.getCurLen(); i++) {
      if (src.ptr_list[i]) {
         appendDeepCopy(*(src.ptr_list[i]));
      }
   }//if
   return TRUE;
}//appendDeepCopy


//  This copies the data from the incomming src, not just a shallow copy.
//  Does not copy NULL's over.
template <class T>
int PtrArrayBase<T>::appendShallowCopy(const PtrArrayBase<T>& src) {
   int i;
   for (i = 0; i<src.getCurLen(); i++) {
      if (src.ptr_list[i]) {
         appendShallowCopy(src.ptr_list[i]);
      }
   }//if
   return TRUE;
}//appendDeepCopy


template <class T>
int PtrArrayBase<T>::appendShallowCopy(T* val) {
   ensureCapacity(cur_len + 1);

   ptr_list[cur_len] = val;
   cur_len++;

   return cur_len - 1;
}

template <class T>
int PtrArrayBase<T>::appendDeepCopy(T& val) {
   ensureCapacity(cur_len + 1);

   ptr_list[cur_len] = new T(val);
   cur_len++;

   return cur_len - 1;;
}

// does NOT delete pointers
template <class T>
void PtrArrayBase<T>::clear() {
   for (int i = 0; i<cur_len; i++) {
      ptr_list[i] = NULL;
   }
   cur_len = 0;
}//clear


template <class T>
void PtrArrayBase<T>::clearAndDestroy() {

   for (int i = 0; i<cur_len; i++) {
      delete ptr_list[i];
   }

   delete[] ptr_list;
   max_len = 10;
   cur_len = 0;
   ptr_list = new T*[max_len + 1];
   
   for (int i = 0; i <= max_len; i++) {
      ptr_list[i] = NULL;
   }
}      

// we won't allow it to grow shorter!
template <class T>
void PtrArrayBase<T>::ensureCapacity(int i) {

   //mudlog << "ensureCapacity, max_len: " << max_len
   //       << " i: " << i << endl;

   if (i < 0)
      i = 0;
   
   if (i < max_len)
      return;

   T** new_vals = new T*[i + max_len];
   
   int j;
   for (j = 0; j<cur_len; j++) {
      new_vals[j] = ptr_list[j];
   }
   max_len += i;

   for (;j<max_len; j++) {
      new_vals[j] = NULL;
   }
   
   delete[] ptr_list;
   
   ptr_list = new_vals;
}

template <class T>
int PtrArrayBase<T>::getMaxLen() const {
   return max_len;
}

template <class T>
int PtrArrayBase<T>::getCurLen() const {
   return cur_len;
}

template <class T>
T* PtrArrayBase<T>::elementAt(int i) {
   if ((i < 0) || (i >= max_len))
      return NULL;

   return ptr_list[i];
}//elementAt


template <class T>
const T* PtrArrayBase<T>::constElementAt(int i) const {
   if ((i < 0) || (i >= max_len))
      return NULL;

   return ptr_list[i];
}//constElementAt


// return TRUE if it worked..false otherwise
template <class T>
int PtrArrayBase<T>::setAndDestroy(T* val, int posn) {
   if (posn < 0)
      return FALSE;

   ensureCapacity(posn + 1);
   
   if (ptr_list[posn])
      delete ptr_list[posn];

   if (val && (posn >= cur_len)) {
      cur_len = posn + 1;
   }
   else if (!val) {
      if (posn == (cur_len - 1)) {
         int old_cur_len = cur_len;
         cur_len = 0;
         for (int i = old_cur_len - 2; i>=0; i--) {
            cur_len = i + 1;
            if (ptr_list[i]) {
               break;
            }//if
         }//for
      }//if
   }//else

   ptr_list[posn] = val;
   return TRUE;
}

template <class T>
int PtrArrayBase<T>::set(T* val, int posn) {
   if (posn < 0)
      return FALSE;

   ensureCapacity(posn + 1);
   
   if (val && (posn >= cur_len)) {
      cur_len = posn + 1;
   }
   else if (!val) {
      if (posn == (cur_len - 1)) {
         int old_cur_len = cur_len;
         cur_len = 0;
         for (int i = old_cur_len - 2; i>=0; i--) {
            cur_len = i + 1;
            if (ptr_list[i]) {
               break;
            }//if
         }//for
      }//if
   }//else

   ptr_list[posn] = val;
   return TRUE;
}


///**********************************************************************///
///*********************  LazyPtrArray  *********************************///
///**********************************************************************///


// NOTE:  if elementAt returns null, this will SEGV, be carefull!
template <class T>
T& LazyPtrArray<T>::operator[] (const int i) {
//   cout << "PtrArrayBase::[" << i << "]  max_len:  " << max_len << endl;
   return *(elementAt(i));
}
      

template <class T>
T* LazyPtrArray<T>::elementAtNoCreate(int i) {
   if ((i < 0) || (i >= max_len))
      return NULL;
   
   return ptr_list[i];
}


// NOTE:  If this value is NULL, we will create a default one
// and return that.  Funky but useful.
template <class T>
T* LazyPtrArray<T>::elementAt(int i) {
//   cout << "PtrArrayBase::elementAt, i: " << i << "  max_len:  " 
//        << max_len << endl;

   if ((i < 0) || (i >= max_len)) {
//      cout << "Returning null" << endl;
      return NULL;
   }
   
   //cout << "Checking for null..." << endl;
   if (ptr_list[i] == NULL) {
//      cout << "Creating new one..." << endl;
      ptr_list[i] = new T(i);
   }
   else {
//      cout << " offset wasn't null..." << endl;
   }

   return ptr_list[i];
}


///**********************************************************************///
///*********************  PtrArray  *************************************///
///**********************************************************************///

template <class T>
T* PtrArray<T>::operator[] (const int i) {
   return elementAt(i);
}


///**********************************************************************///
///*********************  ObjArray  *************************************///
///**********************************************************************///

/** This should never be called more than once!! */
template <class T>
int ObjArray<T>::init(int sz) {
   if (sz < 5) {
      sz = 5;
   }
   _cnt++;

   len = sz;
   array = new T[sz];
   return 0;
}//constructor

template <class T>
ObjArray<T>::ObjArray(const ObjArray<T>& src)
      : len(src.len), bf(src.bf) {
   array = new T[len];
   for (int i = 0; i<len; i++) {
      array[i] = src.array[i];
   }//for
}//copy constructor

template <class T>
ObjArray<T>& ObjArray<T>::operator=(const ObjArray<T>& src) {
   if (this != &src) {
      ensureCapacity(src.len);
      bf = src.bf;
      
      // TODO:  Skip un-used ones??
      for (int i = 0; i<len; i++) {
         array[i] = src.array[i];
      }//for
   }
   return *this;
}//operator=


template <class T>
ObjArray<T>::~ObjArray() {
   delete[] array;
   _cnt--;
}//destructor


template <class T>
void ObjArray<T>::ensureCapacity(int cap) {
   if (cap > len) {
      T* tmp = array;
      array = new T[cap + len];

      // TODO:  Skip un-used ones??
      for (int i = 0; i<len; i++) {
         array[i] = tmp[i];
      }//for
      
      delete[] tmp;
      len += cap;
   }//if
}//ensureCapacity


template <class T>
void ObjArray<T>::addElement(T& val) {
   int idx = bf.firstClear();
   ensureCapacity(idx);
   array[idx] = val;
   bf.turn_on(idx);
}//addElement

template <class T>
void ObjArray<T>::appendElement(T& val) {
   int idx = bf.lastSet();
   idx++;
   ensureCapacity(idx);
   array[idx] = val;
   bf.turn_on(idx);
}//appendElement


template <class T>
void ObjArray<T>::purge() {
   delete[] array;
   array = NULL;
   butfield.off_all();
   len = 0;
}//purge

/** Returns TRUE if the array contains the element 'val', as
 * determined by operator=
 */
template <class T>
int ObjArray<T>::contains(T& val) const {
   for (int i = getNextIdx(-1); i != -1;
        i = getNextIdx(i)) {
      if (val == elementAt(i)) {
         return TRUE;
      }
   }//for
   return FALSE;
}//contains