2005/5/9

     
 

core_vector.h

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/sys/core_vector.h,v 1.19 2005/03/14 12:14:31 kommer Exp $
#ifndef acdk_lang_sys_core_vector_h
#define acdk_lang_sys_core_vector_h

#include <string.h>
namespace acdk {
namespace lang {
namespace sys {

template <class IT> class core_vector_iterator;
template <class IT> class core_vector_reverse_iterator;

void ACDK_CORE_PUBLIC core_vector_throw_out_of_index(int size, int idx);

/**
  replacement for the std::vector class.
  access outside valid range will throw acdk::lang::RIndexOutOfBoundsException
*/

template <class T> 
class core_vector 
{
private:
  T* _begin;
  T* _end;
  int _capacity;
public:
  typedef T value_type;
  typedef T* iterator;
  typedef const T* const_iterator;
  
  core_vector()
  : _begin(0)
  , _end(0)
  , _capacity(10)
  {
    _end = _begin = _allocData(_capacity);
  }
  explicit core_vector(int initsize, const T& fillwith = T())
  : _begin(0)
  , _end(0)
  , _capacity(initsize)
  {
    if (_capacity < 10)
      _capacity = 10;
    _end = _begin = _allocData(_capacity);
    for (int i = 0; i < initsize; i++)
    {
      ::new ((void*)(_end))T(fillwith);
      ++_end;
    }
  }
  core_vector(int initsize, int initcap, const T& fillwith)
  : _begin(0)
  , _end(0)
  , _capacity(0)
  {
    if (initcap < initsize)
      initcap = initsize;
    if (initcap <= 0)
      initcap = 10;

    _end = _begin = _allocData(initcap);
    _capacity = initcap;
    
    for (int i = 0; i < initsize; i++)
    {
      ::new ((void*)(_end))T(fillwith);
      ++_end;
    }
  }
  /** 
    copy constructor
  */
  core_vector(const core_vector<T>& other)
  : _begin(0)
  , _end(0)
  , _capacity(other._capacity)
  {
    _end = _begin = _allocData(_capacity);
    _copy2end(other.begin(), other.end());
  }
  ~core_vector()
  {
    _destroy();
  }
  core_vector<T>& operator=(const core_vector<T>& other)
  {
    if (this == &other)
      return *this;
    _destroy();
    _capacity  = other._capacity;
    _end = _begin = _allocData(sizeof(T) * _capacity );
    _copy2end(other.begin(), other.end());
    return *this;
  }
  bool operator==(const core_vector<T>& other) const
  {
    if (size() != other.size())
      return false;
    const_iterator it1 = _begin;
    const_iterator end1 = _end;
    const_iterator it2 = other._begin;
    const_iterator end2 = other._end;
    for (; it1 < end1; ++it1, ++it2)
      if (*it1 != *it2)
        return false;
    return true;
  }
  bool operator!=(const core_vector<T>& other) const
  {
    return operator==(other) == false;
  }
  void assign(const_iterator b, const_iterator e)
  {
    if (_begin == b && _end == e)
      return;
    _destroy();
    _ensureCapacity(e - b);
    _begin = _end;
    _copy2end(b, e);
  }
  void insert(iterator it, const_iterator first, const_iterator last)
  {
    int inspos = it - _begin;
    _ensureCapacity(size() + last - first);
    it = _begin + inspos;
    int tsize = size();
    int diff = last - first;
   
    int mvs = _end - it;
    memmove(it + diff, it, sizeof(T) * (_end - it));
    _end += diff;
    iterator mit = _begin + inspos;
    while (first < last)
    {
      new ((void*)mit) T(*first);
      ++first;
      ++mit;
    }
  }
  void insert(int idx, const T& elem)
  {
    if (idx < 0 || idx > size())
      core_vector_throw_out_of_index(size(), idx);
    insert(begin() + idx, &elem, &elem + 1);
  }
  /**
    ensure that the size of the vector is at least
    given newize. Fills new empty elements with fillwi
    th
  */
  void ensureSize(int newsize, const T& fillwith = T())
  {
    ensureCapacity(newsize);
    for (int i = size(); i < newsize; ++i)
    {
      ::new ((void*)(_end))T(fillwith);
      ++_end;
    }
  }
  /**
    resize the array on given newsize
    if newsize > as size() new slots will be
    filled with fillwith
  */
  void resize(int newsize, const T& fillwith = T()) 
  { 
    if (newsize > size())
      ensureSize(newsize, fillwith); 
    else
    {
      erase(begin() + newsize, end());
    }
  }

  void ensureCapacity(int newcap)
  {
    if (_capacity >= newcap)
      return;
    if (newcap < _capacity * 2)
      newcap = _capacity * 2;
    if (newcap < 10) 
      newcap = 10;
    else if (newcap < (int)((float)_capacity * 2))
      newcap = (int)((float)_capacity * 2);
    _ensureCapacity(newcap);
  }
  
  /// STL compatibility
  void reserve(int newcap) { ensureCapacity(newcap); }
  void _ensureCapacity(int newcap)
  {
    if (_capacity >= newcap)
      return;
    int tsize = size();
    T* newData = _allocData(newcap);
    memcpy(newData, _begin, sizeof(T) * tsize);
    _freeData();
    _begin = newData;
    _end = _begin + tsize;
    _capacity = newcap;
  }
  
  inline T& operator[](int idx)
  {
    check_range(idx);
    return _begin[idx];
  }
  inline const T& operator[](int idx) const
  {
    check_range(idx);
    return _begin[idx];
  }
  inline T& at(int idx) 
  { 
    check_range(idx);
    return _begin[idx]; 
  }
  inline const T& at(int idx) const 
  { 
    check_range(idx);
    return _begin[idx]; 
  }

  void add(const T& el)
  {
    ensureCapacity(size() + 1);
    ::new ((void*)(_end)) T(el);
    ++_end;
  }
  void push_back(const T& el) { add(el); }
  void addLast(const T& el) { add(el); }
  void addFirst(const T& el)
  {
    insert(_begin, &el, &el + 1);
  }
  inline int size() const { return _end - _begin; }
  inline int capacity() const { return _capacity; }
  inline bool empty() const { return _begin == _end; }
  inline T& front() 
  { 
    check_range(0);
    return *_begin; 
  }
  inline const T& front() const 
  { 
    check_range(0);
    return *_begin; 
  }
  inline T& back() 
  { 
    check_range(0);
    return *(_end - 1); 
  }
  const T& back() const 
  { 
    check_range(0);
    return *(_end - 1); 
  }
  
  inline void pop_back() 
  { 
    check_range(0);
    erase(end() - 1); 
  }
  inline void pop_front() 
  { 
    check_range(0);
    erase(begin(), begin() + 1); 
  }

  // set _size  to 0, doesn't care of any constructor/destructor 
  /*
  void reset_hard(int newsize = 0)
  {
    _size = newsize;
  }*/
  inline bool hasElement(const T& el) const
  {
    return find(el) != _end; 
  }
  inline void clear() { erase(begin(), end()); }
  
  inline iterator erase(iterator it)
  {
    return erase(it, it + 1);
  }
  iterator erase(iterator it, iterator eit)
  {
    if (it < _begin || it >= _end)
      return _end;
    
    _destroy(it, eit);
    
    int diff = eit - it;
    
    while (it + diff < _end) 
    {
      memcpy(it, it + diff, sizeof(T));
      ++it;
    }
    _end -= diff;
    return eit;
  }
  inline bool deleteElement(const T& el) 
  {
    iterator it = find(el);
    if (it == _end)
      return false;
    erase(it);
    return true;
  }
  const_iterator find(const T& t) const
  {
    
    for (const_iterator it = _begin;
         it < _end;
         ++it)
    {
      if (*it == t)
        return it;
    }
    return _end;
  }
  iterator find(const T& t) 
  {
    
    for (iterator it = _begin;
         it < _end;
         ++it)
    {
      if (*it == t)
        return it;
    }
    return _end;
  }
  friend class core_vector_iterator<T>;  
  inline iterator begin() { return _begin; }
  inline iterator end() { return _end; }
  inline const_iterator begin() const { return _begin;  }
  inline const_iterator end() const { return _end; }

  friend class core_vector_reverse_iterator<T>;  
  typedef core_vector_reverse_iterator<T> reverse_iterator;
  typedef core_vector_iterator<T> const_reverse_iterator; // ## short hack
  inline reverse_iterator rbegin() { return core_vector_reverse_iterator<T>(*this, size() - 1); }
  inline reverse_iterator rend() { return core_vector_reverse_iterator<T>(*this, -1); }
  inline T* data() { return _begin; }

  void swap(iterator first, iterator second)
  {
    // make dump copy
    char buff[sizeof(T)];
    ::memcpy(buff, first, sizeof(T));
    ::memcpy((char*)first, (char*)second, sizeof(T));
    ::memcpy(second, buff, sizeof(T));
  }
  inline void check_range(int idx) const
  {
    if (idx < 0 || idx >= size())
      core_vector_throw_out_of_index(size(), idx);
  }
protected:
  
  void _destroy()
  {
    _destroy(_begin, _end);
    _freeData();
    _begin = _end = 0;
  }
  void _destroy(iterator s, iterator e)
  {
    while (s < e) 
    {
      s->~T();
      ++s;
    }
  }
  T* _allocData(int elemcount)
  {
    return static_cast<T*>(operator new(sizeof(T) * elemcount));
  }
  void _freeData()
  {
    operator delete(_begin);
  }
  void _copy2end(const_iterator oit, const_iterator eit)
  {
    for (const_iterator it = oit;
         it < eit;
         ++it)
    {
      ::new ((void*)(_end)) T(*it);
      ++_end;
    }
  }

};


template <typename T>
inline
core_vector<T> 
make_core_vector(const T& t1, const T& t2, const T& t3)
{
  core_vector<T> ret(3);
  ret[0] = t1;
  ret[1] = t2;
  ret[2] = t3;
  return ret;
}

template <typename T>
inline
core_vector<T> 
make_core_vector(const T& t1, const T& t2)
{
  core_vector<T> ret(2);
  ret[0] = t1;
  ret[1] = t2;
  return ret;
}


template <typename T>
inline
core_vector<T> 
make_core_vector(const T& t1)
{
  core_vector<T> ret(1);
  ret[0] = t1;
  return ret;
}

/**
  reverse iterator vor core_vector
*/
template <class IT>
class core_vector_reverse_iterator
  { 
    core_vector<IT>& _vec;
    int _pos;
  public:
    core_vector_reverse_iterator(core_vector<IT>& vec, int start)
    : _vec(vec),
      _pos(start)
    {
    }
    core_vector_reverse_iterator(const core_vector_reverse_iterator<IT>& other)
    : _vec(other._vec),
      _pos(other._pos)
    {
    }
    core_vector_reverse_iterator& operator=(const core_vector_reverse_iterator<IT>& other)
    {
      _vec = other._vec;
      _pos = other._pos;
      return *this;
    }
    core_vector_reverse_iterator<IT>& operator++()
    {
      if (_pos <= 0)
        return *this;
      --_pos;
      return *this;
    }
    core_vector_reverse_iterator<IT>& operator--()
    {
      if (_pos >= _vec._size)
        return *this;
      ++_pos;
      return *this;
    }
    bool operator==(const core_vector_reverse_iterator<IT>&other) const { return _pos == other._pos; }
    bool operator!=(const core_vector_reverse_iterator<IT>&other) const { return _pos != other._pos; }
    bool operator<(const core_vector_reverse_iterator<IT>&other) const { return _pos > other._pos; }
    bool operator<=(const core_vector_reverse_iterator<IT>&other) const { return _pos > other._pos; }
    bool operator>(const core_vector_reverse_iterator<IT>&other) const { return _pos < other._pos; }
    bool operator>=(const core_vector_reverse_iterator<IT>&other) const { return _pos <= other._pos; }
    IT& operator*() { return _vec[_pos]; }
    const IT& operator*() const { return _vec[_pos]; }
};


/**
  Basic stack based on core_vector
*/
template <class T>
class core_stack 
{
  typedef core_vector<T> Container;
public:
  Container _vec;
  typedef typename Container::iterator iterator;
  typedef typename Container::const_iterator const_iterator;
  inline core_stack()
  {
  }
  inline core_stack(int initsize, int initcap, const T& fillwith = T())
  : _vec(initsize, initcap, fillwith)
  {
  }
  inline void push(const T& t)
  {
    _vec.push_back(t);
  }
  inline T pop()
  {
    T ret = _vec[_vec.size() - 1];
    _vec.erase(_vec.end() - 1);
    return ret;
  }
  inline void pop_noret()
  {
    _vec.check_range(0);
    _vec.erase(_vec.end() - 1);
  }
  inline T& top() { return _vec.back(); }
  inline const T& top() const { return _vec.back(); }
  inline T& bottom() { return _vec.front(); }
  inline const T& bottom() const { return _vec.front(); }
  inline int size() const { return _vec.size(); }
  inline bool empty() const { return _vec.empty(); }
  inline int capacity() const { return _vec.capacity(); }
  inline T& peek(int fromtop = 0) { return _vec[_vec.size() - 1 - fromtop]; }
  inline const T& peek(int fromtop = 0) const { return _vec[_vec.size() - 1 - fromtop]; }
  inline T& operator[](int idx) { return _vec[idx]; }
  inline const T& operator[](int idx) const { return _vec[idx]; }
};


/**
  use core_vector stack as scope.
  all items in core_stack 
  will be erased in destructor of core_stack_scope
  are inserted since construction
*/
template <class T>
class core_stack_scope
{
  core_stack<T>& _stack;
  typedef typename core_stack<T>::iterator iterator;
  int _savedTop;
  
public:
  core_stack_scope(core_stack<T>& stack)
  : _stack(stack)
  , _savedTop(stack.size())
  
  {
  }
  ~core_stack_scope()
  {
    _stack._vec.erase(_stack._vec.begin() + _savedTop, _stack._vec.end());
  }
  void commit() { _savedTop = _stack.size(); }
  void push(const T& t) { _stack.push(t); }
  T pop() { return _stack.pop(); }
  T& top() { return _stack.top(); }
};


} // sys
} // lang
} // acdk
#endif //acdk_lang_sys_core_vector_h