#ifndef FILE_NGS_ARRAY #define FILE_NGS_ARRAY /**************************************************************************/ /* File: array.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ /** Exception thrown by array range check. Only thrown when compiled with RANGE_CHECK */ class ArrayRangeException : public Exception { public: ArrayRangeException () : Exception("ArrayRangeException\n") { ; } }; /** A simple array container. Array represented by size and data-pointer. No memory allocation and deallocation, must be provided by user. Helper functions for printing. Optional range check by macro RANGE_CHECK */ template class FlatArray { protected: /// the size int size; /// the data T * data; public: /// provide size and memory FlatArray (int asize, T * adata) : size(asize), data(adata) { ; } /// memory from local heap FlatArray(int asize, LocalHeap & lh) : size(asize), data(static_cast (lh.Alloc(asize*sizeof(T)))) { ; } /// the size int Size() const { return size; } /// access array. range check by macro CHECK_RANGE T & operator[] (int i) { #ifdef CHECK_RANGE if (i < 0 || i >= size) throw RangeException ("FlatArray::operator[]", i, 0, size-1); #endif return data[i]; } /// Access array. range check by macro CHECK_RANGE const T & operator[] (int i) const { #ifdef CHECK_RANGE if (i < 0 || i >= size) throw RangeException ("FlatArray::operator[]", i, 0, size-1); #endif return data[i]; } /// access last element. check by macro CHECK_RANGE T & Last () { #ifdef CHECK_RANGE if (!size) throw Exception ("Array should not be empty"); #endif return data[size-1]; } /// access last element. check by macro CHECK_RANGE const T & Last () const { #ifdef CHECK_RANGE if (!size) throw Exception ("Array should not be empty"); #endif return data[size-1]; } /// takes sub-array starting from position pos FlatArray Part (int pos) { return FlatArray (size-pos, data+pos); } /// takes subsize elements starting from position pos FlatArray Part (int pos, int subsize) { return FlatArray (subsize, data+pos); } /// Fill array with value val FlatArray & operator= (const T & val) { for (int i = 0; i < size; i++) data[i] = val; return *this; } /// copies pointers FlatArray & operator= (const FlatArray & a2) { size = a2.size; data = a2.data; return *this; } }; /// print array template ostream & operator<< (ostream & s, const FlatArray & a) { for (int i = 0; i < a.Size(); i++) s << i << ": " << a[i] << "\n"; return s; } template inline bool operator== (const FlatArray & a1, const FlatArray & a2) { if (a1.Size () != a2.Size()) return 0; for (int i = 0; i < a1.Size(); i++) if (a1[i] != a2[i]) return 0; return 1; } /** Dynamic array container. ARRAY is an automatically increasing array container. The allocated memory doubles on overflow. Either the container takes care of memory allocation and deallocation, or the user provides one block of data. */ template class ARRAY : public FlatArray { protected: /// physical size of array int allocsize; /// memory is responsibility of container bool ownmem; public: /// Generate array of logical and physical size asize explicit ARRAY(int asize = 0) : FlatArray (asize, asize ? new T[asize] : 0) { allocsize = asize; ownmem = 1; } /// Generate array in user data ARRAY(int asize, T* adata) : FlatArray (asize, adata) { allocsize = asize; ownmem = 0; } /// array copy explicit ARRAY (const ARRAY & a2) : FlatArray (a2.Size(), a2.Size() ? new T[a2.Size()] : 0) { allocsize = this->size; ownmem = 1; for (int i = 0; i < this->size; i++) (*this)[i] = a2[i]; } /// if responsible, deletes memory ~ARRAY() { if (ownmem) delete [] this->data; } /// Change logical size. If necessary, do reallocation. Keeps contents. void SetSize(int nsize) { if (nsize > allocsize) ReSize (nsize); this->size = nsize; } /// Change physical size. Keeps logical size. Keeps contents. void SetAllocSize (int nallocsize) { if (nallocsize > allocsize) ReSize (nallocsize); } /// Add element at end of array. reallocation if necessary. int Append (const T & el) { if (this->size == allocsize) ReSize (this->size+1); this->data[this->size] = el; this->size++; return this->size; } /// Delete element i. Move last element to position i. void DeleteElement (int i) { #ifdef CHECK_RANGE RangeCheck (i); #endif this->data[i] = this->data[this->size-1]; this->size--; } /// Delete last element. void DeleteLast () { #ifdef CHECK_RANGE // CheckNonEmpty(); #endif this->size--; } /// Deallocate memory void DeleteAll () { if (ownmem) delete [] this->data; this->data = 0; this->size = allocsize = 0; } /// Fill array with val ARRAY & operator= (const T & val) { FlatArray::operator= (val); return *this; } /// array copy ARRAY & operator= (const ARRAY & a2) { SetSize (a2.Size()); for (int i = 0; i < this->size; i++) (*this)[i] = a2[i]; return *this; } private: /// resize array, at least to size minsize. copy contents void ReSize (int minsize) { int nsize = 2 * allocsize; if (nsize < minsize) nsize = minsize; if (this->data) { T * p = new T[nsize]; int mins = (nsize < this->size) ? nsize : this->size; memcpy (p, this->data, mins * sizeof(T)); if (ownmem) delete [] this->data; ownmem = 1; this->data = p; } else { this->data = new T[nsize]; ownmem = 1; } allocsize = nsize; } }; template class ArrayMem : public ARRAY { // T mem[S]; // should be best, but calles trivial default constructor // char mem[S*sizeof(T)]; // avoids calling the array default-constructor (icc) double mem[(S*sizeof(T)+7) / 8]; // alignment (on ia64 machines) public: /// Generate array of logical and physical size asize explicit ArrayMem(int asize = 0) : ARRAY (S, static_cast (static_cast(&mem[0]))) { this->SetSize (asize); } explicit ArrayMem(const ARRAY & a2) : ARRAY (S, (T*)mem) { ARRAY::operator= (a2); } explicit ArrayMem(const ArrayMem & a2) : ARRAY (S, (T*)mem) { ARRAY::operator= (a2); } }; #endif