// $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