pjs/include/garray.h

258 строки
7.3 KiB
C++

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
//
// Warning: This is a C++ file.
//
//
// This implements cross platform Growable arrays of Pointers.
//
#ifndef _GARRAY_H_
#define _GARRAY_H_
//
// On Unix (well at least Solaris) we are having troubles with
// templates, so hey, we won't use them...djw.
//
// On Mac we are having troubles as well, so add me to the list.
// Now, why even have templates?...jar
//
#if ! ( defined(XP_WIN16) || defined(XP_UNIX) || defined(XP_MAC) )
#define TEMPLATE_SUPPORT 1
#endif
#include "prtypes.h"
class CXP_GrowableArray {
protected:
void **m_pData;
int m_iSize;
int m_iAllocSize;
int NewSize( int iMinSize){
int iNewSize = MAX( m_iAllocSize,16) ;
while( iNewSize < iMinSize ){
iNewSize = iNewSize+iNewSize;
}
return iNewSize;
}
//
// this is the routine that does the actual work. Should be in
// its own file.
//
void GuaranteeSize(int iSize){
if(m_iAllocSize <= iSize){
int iNewSize = NewSize( iSize );
if( m_iAllocSize ){
void ** pNewData = new void*[iNewSize];
XP_BCOPY( m_pData, pNewData, m_iAllocSize * sizeof(void*) );
delete [] m_pData;
m_pData = pNewData;
}
else{
m_pData = new void*[iNewSize];
}
m_iAllocSize = iNewSize;
}
}
public:
CXP_GrowableArray(int iStartSize=0): m_pData(0),m_iSize(0),m_iAllocSize(0){
if( iStartSize ){
GuaranteeSize( iStartSize );
}
};
~CXP_GrowableArray(){ delete [] m_pData; }
int Size(){ return m_iSize; }
void SetSize( int iSize ){
GuaranteeSize( iSize );
m_iSize = iSize;
}
void* operator[](int nIndex) const { return m_pData[nIndex]; }
void*& operator[](int nIndex){ return m_pData[nIndex]; }
int Add(void* newElement){
GuaranteeSize(m_iSize+1);
m_pData[m_iSize] = newElement;
/* Return index to last item in list */
return m_iSize++;
}
int Insert(void* newElement, int nIndex){
intn iLowerLimit;
GuaranteeSize(m_iSize+1);
if( nIndex < 0 )
nIndex = 0;
if( nIndex < m_iSize )
{
iLowerLimit = PR_MAX(1, nIndex);
/* Shuffle pointers at and above insert index up */
for( int i = m_iSize; i >= iLowerLimit; i-- )
{
m_pData[i] = m_pData[i-1];
}
/* Overwrite pointer at designated location */
m_pData[nIndex] = newElement;
} else {
/* nIndex is too large - just add at end */
m_pData[m_iSize] = newElement;
}
/* Return index to last item in list */
return m_iSize++;
}
int Delete( int nIndex ){
if( nIndex < m_iSize )
{
/* Shuffle remaining pointers down */
for( int i = nIndex; i < m_iSize-1; i++ )
{
m_pData[i] = m_pData[i+1];
}
m_iSize--;
}
/* Return index to last item in list */
return (m_iSize-1);
}
int Delete( void* element ){
for( int i = 0; i < m_iSize; i++ )
{
if( m_pData[i] == element )
{
return Delete(i);
}
}
return (m_iSize-1);
}
int Find( void* element ){
for( int i = 0; i < m_iSize; i++ )
{
if( m_pData[i] == element )
{
return i;
}
}
return -1;
}
void Empty(){
m_iSize = 0;
}
};
class CXP_PtrStack : public CXP_GrowableArray{
public:
int m_iTop;
CXP_PtrStack(): m_iTop(-1){}
Bool IsEmpty(){ return m_iTop == -1; }
void Push( void* t ){
if( ++m_iTop >= Size() ) {
Add( t );
}
else {
(*this)[m_iTop] = t;
}
}
void* Top(){ return (*this)[m_iTop]; }
void* Pop(){ return (*this)[m_iTop--];}
void Reset(){ m_iTop = -1; }
int StackSize() { return m_iTop + 1; }
};
#ifdef TEMPLATE_SUPPORT
template<class PTRTYPE>
class TXP_GrowableArray: public CXP_GrowableArray {
public:
PTRTYPE operator[](int nIndex) const { return (PTRTYPE)(int32)m_pData[nIndex]; }
PTRTYPE& operator[](int nIndex){ return *(PTRTYPE*)&m_pData[nIndex]; }
int Add(PTRTYPE newElement){ return CXP_GrowableArray::Add( (void*) newElement ); }
};
#define Declare_GrowableArray(NAME,PTRTYPE) \
typedef TXP_GrowableArray<PTRTYPE> TXP_GrowableArray_##NAME;
#else
#define Declare_GrowableArray(NAME,PTRTYPE) \
class TXP_GrowableArray_##NAME: public CXP_GrowableArray { \
public: \
PTRTYPE operator[](int nIndex) const { return (PTRTYPE)(int32)m_pData[nIndex]; }\
PTRTYPE& operator[](int nIndex){ return *(PTRTYPE*)&m_pData[nIndex]; } \
int Add(PTRTYPE newElement){ return CXP_GrowableArray::Add( (void*) newElement ); } \
}; \
#endif
//
// PtrStack Imlementation
//
#ifdef TEMPLATE_SUPPORT
template<class PTRTYPE>
class TXP_PtrStack : public TXP_GrowableArray<PTRTYPE> {
public:
int m_iTop;
TXP_PtrStack(): m_iTop(-1){}
Bool IsEmpty(){ return m_iTop == -1; }
void Push( PTRTYPE t ){
if( ++m_iTop >= Size() ) {
Add( t );
}
else {
(*this)[m_iTop] = t;
}
}
PTRTYPE Top(){ return (*this)[m_iTop]; }
PTRTYPE Pop(){ return (*this)[m_iTop--];}
void Reset(){ m_iTop = -1; }
int StackSize(){ return m_iTop + 1; }
};
#define Declare_PtrStack(NAME,PTRTYPE) \
typedef TXP_PtrStack<PTRTYPE> TXP_PtrStack_##NAME;
#else // No template support
#define Declare_PtrStack(NAME, PTRTYPE) \
class TXP_PtrStack_##NAME : public CXP_PtrStack { \
public: \
void Push( PTRTYPE t ){ CXP_PtrStack::Push((void*)(int32)t); } \
PTRTYPE Top(){ return (PTRTYPE)(int32)CXP_PtrStack::Top(); } \
PTRTYPE Pop(){ return (PTRTYPE)(int32)CXP_PtrStack::Pop(); } \
PTRTYPE operator[](int nIndex) const { return (PTRTYPE)(int32)m_pData[nIndex]; }\
PTRTYPE& operator[](int nIndex){ return *(PTRTYPE*)&m_pData[nIndex]; } \
int Add(PTRTYPE newElement){ return CXP_GrowableArray::Add( (void*)(int32)newElement ); } \
}; \
#endif
#endif