/*- * Copyright 2005-2007 Guram Dukashvili * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //--------------------------------------------------------------------------- #ifndef _array_H #define _array_H //----------------------------------------------------------------------------- namespace ksys { //----------------------------------------------------------------------------- template class Vector; //----------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- template class Array { public: ~Array(); Array(T * ptr = NULL); Array(const T & element); Array(const Array & array); Array(const Vector & vector); Array & operator = (const Array & array); Array & operator = (const Vector & vector); Array & operator = (const T & element); #if !HAVE_INTPTR_T_AS_INT T & operator [] (int i); const T & operator [] (int i) const; T & operator [] (unsigned int i); const T & operator [] (unsigned int i) const; #endif T & operator [] (intptr_t i); const T & operator [] (intptr_t i) const; T & operator [] (uintptr_t i); const T & operator [] (uintptr_t i) const; operator T * (){ return ptr_; } operator const T * () const { return ptr_; } Array & operator << (const T & element){ return add(element); } const uintptr_t & count() const; Array & clear(); T * & ptr(); const T * & ptr() const; Array & resize(uintptr_t newSize); Array & add(const T & element); Array & insert(uintptr_t i, const T & element); intptr_t search(const T & element) const; intptr_t bSearch(const T & element) const; uintptr_t bSearch(const T & element, intptr_t & c) const; intptr_t searchCase(const T & element) const; intptr_t bSearchCase(const T & element) const; uintptr_t bSearchCase(const T & element, intptr_t & c) const; Array & remove(uintptr_t i); Array & setBit(uintptr_t n); Array & resetBit(uintptr_t n); Array & invertBit(uintptr_t n); uintptr_t bit(uintptr_t n) const; #if !HAVE_INTPTR_T_AS_INTMAX_T Array & setBit(uintmax_t n); Array & resetBit(uintmax_t n); Array & invertBit(uintmax_t n); uintptr_t bit(uintmax_t n) const; #endif Array & setBitRange(uintptr_t n, uintptr_t c); Array & resetBitRange(uintptr_t n, uintptr_t c); Array & invertBitRange(uintptr_t n, uintptr_t c); Array & replace(Array< T> & array); protected: T * ptr_; uintptr_t count_; private: }; //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::replace(Array< T> & array) { xchg(ptr_,array.ptr_); xchg(count_,array.count_); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T>::~Array() { clear(); } //----------------------------------------------------------------------------- template< class T> inline Array< T>::Array(T * ptr) : ptr_(ptr), count_(0) { } //----------------------------------------------------------------------------- template< class T> inline Array< T>::Array(const T & element) : ptr_(NULL), count_(0) { resize(1).ptr_[0] = element; } //----------------------------------------------------------------------------- template< class T> inline Array< T>::Array(const Array< T> & array) : ptr_(NULL), count_(0) { *this = array; } //----------------------------------------------------------------------------- template inline Array::Array(const Vector & vector) : ptr_(NULL), count_(0) { *this = vector; } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif Array< T> & Array::operator =(const Array< T> & array) { Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * array.count_); while( newArray.count_ < array.count_ ){ new (newArray.ptr_ + newArray.count_) T(array.ptr_[newArray.count_]); newArray.count_++; } return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif Array & Array::operator = (const Vector & vector) { Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * vector.count()); while( newArray.count_ < vector.count() ){ new (newArray.ptr_ + newArray.count_) T(vector[newArray.count_]); newArray.count_++; } return replace(newArray); } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif Array< T> & Array::operator =(const T & element) { for( intptr_t i = count_ - 1; i >= 0; i-- ) ptr_[i] = element; return *this; } //----------------------------------------------------------------------------- template< class T> inline T & Array::operator[](intptr_t i) { assert((uintptr_t) i < count_); return ptr_[i]; } //----------------------------------------------------------------------------- template< class T> inline const T & Array::operator[](intptr_t i) const { assert((uintptr_t) i < count_); return ptr_[i]; } //----------------------------------------------------------------------------- template< class T> inline T & Array::operator[](uintptr_t i) { assert(i < count_); return ptr_[i]; } //----------------------------------------------------------------------------- template inline const T & Array::operator[](uintptr_t i) const { assert(i < count_); return ptr_[i]; } //----------------------------------------------------------------------------- #if !HAVE_INTPTR_T_AS_INT //----------------------------------------------------------------------------- template inline T & Array::operator [] (int i) { assert( (uintptr_t) i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- template inline const T & Array::operator [] (int i) const { assert( (uintptr_t) i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- template inline T & Array::operator [] (unsigned int i) { assert( i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- template inline const T & Array::operator [] (unsigned int i) const { assert( i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- #endif //----------------------------------------------------------------------------- template< class T> inline const uintptr_t & Array< T>::count() const { return count_; } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif Array< T> & Array< T>::clear() { while( count_ > 0 ){ count_--; (ptr_ + count_)->~T(); } xfree(ptr_); ptr_ = NULL; return *this; } //----------------------------------------------------------------------------- template< class T> inline T * & Array< T>::ptr() { return ptr_; } //----------------------------------------------------------------------------- template< class T> inline const T * & Array< T>::ptr() const { return ptr_; } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif Array & Array::resize(uintptr_t newSize) { if( newSize == count_ ) return *this; Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * newSize); while( newArray.count_ < newSize ){ if( newArray.count_ < count_ ) new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_]); else new (newArray.ptr_ + newArray.count_) T; newArray.count_++; } return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif Array & Array::add(const T & element) { Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * (count_ + 1)); while( newArray.count_ < count_ ){ new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_]); newArray.count_++; } new (newArray.ptr_ + newArray.count_++) T(element); return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif Array & Array::insert(uintptr_t i,const T & element) { assert( (uintptr_t) i <= count_ ); Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * (count_ + 1)); while( newArray.count_ < i ){ new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_]); newArray.count_++; } new (newArray.ptr_ + newArray.count_++) T(element); while( newArray.count_ - 1 < count_ ){ new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_ - 1]); newArray.count_++; } return replace(newArray); } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif intptr_t Array< T>::search(const T & element) const { intptr_t i; for( i = count_ - 1; i >= 0; i-- ) if( ptr_[i] == element ) break; return i; } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif intptr_t Array< T>::bSearch(const T & element) const { intptr_t low = 0, high = count_ - 1, pos ; while( low <= high ){ pos = (low + high) / 2; if( element > ptr_[pos] ){ low = pos + 1; } else if( element < ptr_[pos] ){ high = pos - 1; } else return pos; } return -1; } //----------------------------------------------------------------------------- template< class T> #ifndef __BCPLUSPLUS__ inline #endif uintptr_t Array< T>::bSearch(const T & element, intptr_t & c) const { intptr_t low = 0, high = count_ - 1, pos = -1; c = 1; while( low <= high ){ pos = (low + high) / 2; if( element > ptr_[pos] ){ low = pos + 1; c = 1; } else if( element < ptr_[pos] ){ high = pos - 1; c = -1; } else{ c = 0; break; } } return pos; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif intptr_t Array::searchCase(const T & element) const { intptr_t i; for( i = count_ - 1; i >= 0; i-- ) if( ptr_[i].strcasecmp(element) == 0 ) break; return i; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif intptr_t Array::bSearchCase(const T & element) const { intptr_t low = 0, high = count_ - 1, pos, c; while( low <= high ){ pos = (low + high) / 2; c = element.strcasecmp(ptr_[pos]); if( c > 0 ){ low = pos + 1; } else if( c < 0 ){ high = pos - 1; } else return pos; } return -1; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif uintptr_t Array::bSearchCase(const T & element,intptr_t & c) const { intptr_t low = 0, high = count_ - 1, pos = -1; c = 1; while( low <= high ){ pos = (low + high) / 2; c = element.strcasecmp(ptr_[pos]); if( c > 0 ){ low = pos + 1; } else if( c < 0 ){ high = pos - 1; } else break; } return pos; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif Array & Array::remove(uintptr_t i) { assert(i < count_); Array newArray; newArray.ptr_ = (T *) kmalloc(sizeof(T) * (count_ - 1)); while( newArray.count_ < i ){ new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_]); newArray.count_++; } while( newArray.count_ + 1 < count_ ){ new (newArray.ptr_ + newArray.count_) T(ptr_[newArray.count_ + 1]); newArray.count_++; } return replace(newArray); } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::setBit(uintptr_t n) { assert(n < count_ * 8); setBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::resetBit(uintptr_t n) { assert(n < count_ * 8); resetBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::invertBit(uintptr_t n) { assert(n < count_ * 8); invertBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline uintptr_t Array< T>::bit(uintptr_t n) const { assert(n < count_ * 8); return bit(ptr_, n); } //----------------------------------------------------------------------------- #if !HAVE_INTPTR_T_AS_INTMAX_T //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::setBit(uintmax_t n) { assert(n < count_ * 8); setBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::resetBit(uintmax_t n) { assert(n < count_ * 8); resetBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::invertBit(uintmax_t n) { assert(n < count_ * 8); invertBit(ptr_, n); return *this; } //----------------------------------------------------------------------------- template< class T> inline uintptr_t Array< T>::bit(uintmax_t n) const { assert(n < count_ * 8); return bit(ptr_, n); } //----------------------------------------------------------------------------- #endif //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::setBitRange(uintptr_t n, uintptr_t c) { assert(n < count_ * 8 && n + c <= count_ * 8); setBitRange(ptr_, n, c); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::resetBitRange(uintptr_t n, uintptr_t c) { assert(n < count_ * 8 && n + c <= count_ * 8); resetBitRange(ptr_, n, c); return *this; } //----------------------------------------------------------------------------- template< class T> inline Array< T> & Array< T>::invertBitRange(uintptr_t n, uintptr_t c) { assert(n < count_ * 8 && n + c <= count_ * 8); invertBitRange(ptr_, n, c); return *this; } //----------------------------------------------------------------------------- template ST & operator << (ST & stream,const Array & array) { uint64_t u = array.count(); stream << u; while( u-- > 0 ) stream << array[(uintptr_t) u]; return stream; } //----------------------------------------------------------------------------- template ST & operator >> (ST & stream,Array & array) { Array t; uint64_t u; stream >> u; t.resize((uintptr_t) u); while( u > 0 ) stream >> t[(uintptr_t) --u]; array.replace(t); return stream; } //----------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- /*template class SparseArray { private: protected: T * ptr_; long count_; SparseArray(long count); SparseArray & replace(SparseArray & array); public: ~SparseArray(); SparseArray(T * ptr = NULL); SparseArray(const SparseArray & array); SparseArray & operator = (const SparseArray & array); SparseArray & operator = (const T & element); T & operator [] (long i); const T & operator [] (long i) const; const long & count() const; SparseArray & clear(); T * & ptr(); T * const & ptr() const; SparseArray & resize(long newSize); SparseArray & add(const T & element); SparseArray & insert(long i,const T & element); long search(const T & element) const; long bSearch(const T & element) const; long bSearch(const T & element,long & c) const; SparseArray & remove(long i); }; //----------------------------------------------------------------------------- template inline SparseArray & SparseArray::replace(SparseArray & array) { clear(); ptr_ = array.ptr_; count_ = array.count_; array.ptr_ = NULL; array.count_ = 0; return *this; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray::SparseArray(long count) : count_(0) { xmalloc(ptr_,sizeof(T) * count); while( count_ < count ){ new (ptr_ + count_) T; count_++; } } //----------------------------------------------------------------------------- template inline SparseArray::~SparseArray() { clear(); } //----------------------------------------------------------------------------- template inline SparseArray::SparseArray(T * ptr) : ptr_(ptr), count_(0) { } //----------------------------------------------------------------------------- template inline SparseArray::SparseArray(const SparseArray & array) : ptr_(NULL), count_(0) { *this = array; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::operator = (const SparseArray & array) { SparseArray newArray(array.count_); for( long i = array.count_ - 1; i >= 0; i-- ) newArray.ptr_[i] = array.ptr_[i]; return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::operator = (const T & element) { for( long i = count_ - 1; i >= 0; i-- ) ptr_[i] = element; return *this; } //----------------------------------------------------------------------------- template inline T & SparseArray::operator [] (long i) { assert( i >= 0 && i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- template inline const T & SparseArray::operator [] (long i) const { assert( i >= 0 && i < count_ ); return ptr_[i]; } //----------------------------------------------------------------------------- template inline const long & SparseArray::count() const { return count_; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::clear() { while( count_ > 0 ){ count_--; ptr_[count_].~T(); } xfree(ptr_); ptr_ = NULL; return *this; } //----------------------------------------------------------------------------- template inline T * & SparseArray::ptr() { return ptr_; } //----------------------------------------------------------------------------- template inline T * const & SparseArray::ptr() const { return ptr_; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::resize(long newSize) { SparseArray newArray(newSize); for( long i = (newSize > count_ ? count_ : newSize) - 1; i >= 0; i-- ) newArray.ptr_[i] = ptr_[i]; return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::add(const T & element) { SparseArray newArray(count_ + 1); for( long i = count_ - 1; i >= 0; i-- ) newArray.ptr_[i] = ptr_[i]; newArray.ptr_[count_] = element; return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::insert(long i,const T & element) { assert( i >= 0 && i <= count_ ); SparseArray newArray(count_ + 1); long j; for( j = 0; j < i; j++ ) newArray.ptr_[j] = ptr_[j]; newArray.ptr_[j] = element; while( j < count_ ){ newArray.ptr_[j + 1] = ptr_[j]; j++; } return replace(newArray); } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif long SparseArray::search(const T & element) const { long i; for( i = count_ - 1; i >= 0; i-- ) if( ptr_[i] == element ) break; return i; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif long SparseArray::bSearch(const T & element) const { long low = 0, high = count_ - 1, pos; while( low <= high ){ pos = (low + high) / 2; if( element > ptr_[pos] ){ low = pos + 1; } else if( element < ptr_[pos] ){ high = pos - 1; } else return pos; } return -1; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif long SparseArray::bSearch(const T & element,long & c) const { long low = 0, high = count_ - 1, pos = -1; c = 1; while( low <= high ){ pos = (low + high) / 2; if( element > ptr_[pos] ){ low = pos + 1; c = 1; } else if( element < ptr_[pos] ){ high = pos - 1; c = -1; } else { c = 0; break; } } return pos; } //----------------------------------------------------------------------------- template #ifndef __BCPLUSPLUS__ inline #endif SparseArray & SparseArray::remove(long i) { assert( i >= 0 && i < count_ ); SparseArray newArray(count_ - 1); long j; for( j = 0; j < i; j++ ) newArray.ptr_[j] = ptr_[j]; for( j = i + 1; j < count_; j++ ) newArray.ptr_[j - 1] = ptr_[j]; return replace(newArray); }*/ //----------------------------------------------------------------------------- } //----------------------------------------------------------------------------- #endif