// $Source: /usr/local/SimSoft/SoftShop/Basics/Structur/DynArray.h,v $
// $Revision: 1.20 $
// $Author: baum $
// $Date: 2001/11/29 15:52:23 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-20 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: DynArray.h,v $
// Revision 1.20  2001/11/29 15:52:23  baum
// -In Kalender.cpp und Kalender.h Handsteuerung eingebaut
//

#if !defined _DynArray_h
#define _DynArray_h 1

#if defined(_MSC_VER)
#pragma warning(disable:4251)
#endif  // _MSC_VER

#include <string.h>

#if defined __GNUG__ || defined __hpux
#  pragma interface
#endif

//==================================================================
//		Klassen-Header
//		fuer class DynArray<T>
//==================================================================

//##ModelId=3FBCBCC7008C
template <class T>
class DynArray
  {
  public:
    // Konstruktor
	//##ModelId=3FBCBCC7009D
    DynArray (unsigned size = 10);

    // Copyconstructor
	//##ModelId=3FBCBCC7009F
    DynArray (const DynArray<T>&);

    // destructor
	//##ModelId=3FBCBCC700A1
    ~DynArray ();

    // assignment operators
	//##ModelId=3FBCBCC700AB
    DynArray<T>& operator = (const DynArray<T>&);

    // append a new Val at the end of Array
	//##ModelId=3FBCBCC700AD
    T& append (const T&);

    // append a new Object 'what' after 'where'
	//##ModelId=3FBCBCC700BB
    T& append (const T& what, const T& where);

    // append another DynArray
	//##ModelId=3FBCBCC700BE
    DynArray<T>& append (const DynArray<T>&);

    // prepend a new Object at first Position of Array
	//##ModelId=3FBCBCC700C0
    T& prepend (const T&);

    // prepend a new Object 'what' before 'where'
	//##ModelId=3FBCBCC700CC
    T& prepend (const T& what, const T& where);

    // prepend an other DynArray
	//##ModelId=3FBCBCC700CF
    DynArray<T>& prepend (const DynArray<T>&);

    // remove First or Last Object
	//##ModelId=3FBCBCC700DB
    T* removeFirst ();
	//##ModelId=3FBCBCC700DC
    T* removeLast ();

    // be careful, 'remove' may invalidate the Iterator
    // remove indicated Obj
	//##ModelId=3FBCBCC700DD
    T* remove (const T&);

    // remove all Objects
	//##ModelId=3FBCBCC700EB
    void removeAll ();

    // getting current Object under Cursor
	//##ModelId=3FBCBCC700EC
    T* operator () () const;

    // find Object and set Cursor
	//##ModelId=3FBCBCC700EE
    T* find (const T&) const;

    // increment & decrement operator
	//##ModelId=3FBCBCC700FC
    T* operator ++ () const;        // Prefix-Notation  (++x)
	//##ModelId=3FBCBCC700FE
    T* operator ++ (int) const;     // Postfix-Notation (x++)
	//##ModelId=3FBCBCC7010A
    T* operator -- () const;        // Prefix-Notation  (--x)
	//##ModelId=3FBCBCC7010C
    T* operator -- (int) const;     // Postfix-Notation (x--)

    // getting first Object and set Cursor
	//##ModelId=3FBCBCC7011A
    T* First () const;

    // getting last Object and set Cursor
	//##ModelId=3FBCBCC7011C
    T* Last () const;

    // getting next Object after current and set Cursor
	//##ModelId=3FBCBCC70128
    T* Next () const;

    // getting previous Object before current and set Cursor
	//##ModelId=3FBCBCC7012A
    T* Prev () const;

    // proof if there are some Objects in the Array
	//##ModelId=3FBCBCC7012C
    bool isEmpty () const;

    // returns the Count of Items
	//##ModelId=3FBCBCC70138
    unsigned Count () const;

  private:
    // data members
	//##ModelId=3FBCBCC7013B
    unsigned ObjSize;
	//##ModelId=3FBCBCC70149
    unsigned ObjEnd;
	//##ModelId=3FBCBCC7014E
    mutable unsigned ObjCursor;
	//##ModelId=3FBCBCC70157
    T** ObjVal;

	//##ModelId=3FBCBCC70158
    void grow (unsigned);

};	// class DynArray

//==================================================================
//		Inline-Quellcode
//		fuer class DynArray<T>
//==================================================================

//##ModelId=3FBCBCC7009D
template <class T>
inline DynArray<T>::DynArray (unsigned size /* = 10 */)
  : ObjSize (size ? size : 1), ObjEnd (0), ObjCursor (0),
    ObjVal (new T* [ObjSize]) {
}

//##ModelId=3FBCBCC7009F
template <class T>
DynArray<T>::DynArray (const DynArray<T>& d)
  : ObjSize (d.ObjSize), ObjEnd (d.ObjEnd), ObjCursor (d.ObjCursor),
    ObjVal (new T* [ObjSize]) {
  for (register unsigned i = 0; i < ObjEnd; i++)  ObjVal [i] = d.ObjVal [i];
}

//##ModelId=3FBCBCC700A1
template <class T>
inline DynArray<T>::~DynArray () {
  delete[] ObjVal;
}

// assignment operators
//##ModelId=3FBCBCC700AB
template <class T>
DynArray<T>& DynArray<T>::operator = (const DynArray<T>& d) {
  delete[] ObjVal;
  ObjSize = d.ObjSize;
  ObjEnd = d.ObjEnd;
  ObjCursor = d.ObjCursor; 
  ObjVal = new T* [ObjSize];
  for (register unsigned i = 0; i < ObjEnd; i++)  ObjVal [i] = d.ObjVal [i];
  return *this;
}

// append a new Val at the end of Array
//##ModelId=3FBCBCC700AD
template <class T>
inline T& DynArray<T>::append (const T& what) {
  if (ObjEnd >= ObjSize)  grow (ObjSize + 1);
  return *(ObjVal [ObjEnd++] = (T*) &what);
}

// append a new Object 'what' after 'where'
//##ModelId=3FBCBCC700BB
template <class T>
T& DynArray<T>::append (const T& what, const T& where) {
  register unsigned i;
  for (i = 0; i < ObjEnd; i++)
    if (ObjVal [i] == &where) break;
  if (i == ObjEnd)  return append (what);
  else {
    if (ObjEnd >= ObjSize)  grow (ObjSize + 1);
    i++;
    memmove (&ObjVal [i + 1], &ObjVal [i], sizeof (T*) * ((ObjEnd++) - i));
    ObjVal [i] = (T*) &what;
    if (ObjCursor >= i)  ObjCursor++;
    return *ObjVal [i];
  }
}

// append an other DynArray
//##ModelId=3FBCBCC700BE
template <class T>
DynArray<T>& DynArray<T>::append (const DynArray<T>& d) {
  if (d.ObjEnd) {
    if ((ObjEnd + d.ObjEnd) >= ObjSize)  grow (ObjSize + d.ObjEnd);
    for (register unsigned i = 0; i < d.ObjEnd; i++)
      ObjVal [i + ObjEnd] = d.ObjVal [i];
    ObjEnd += d.ObjEnd;
  }
  return *((DynArray<T>*) &d);
}

// prepend a new Object at first Position of Array
//##ModelId=3FBCBCC700C0
template <class T>
inline T& DynArray<T>::prepend (const T& what) {
  if (!ObjEnd)  return append (what);
  else {
    if (ObjEnd >= ObjSize)  grow (ObjSize + 1);
    memmove (&ObjVal [1], ObjVal, sizeof (T*) * ObjEnd++);
    ObjVal [0] = (T*) &what;
    ObjCursor++;
    return *ObjVal [0];
  }
}

// prepend a new Object 'what' before 'where'
//##ModelId=3FBCBCC700CC
template <class T>
T& DynArray<T>::prepend (const T& what, const T& where) {
  register unsigned i;
  for (i = 0; i < ObjEnd; i++)
    if (ObjVal [i] == &where) break;
  if (i == ObjEnd)  return append (what);
  else {
    if (ObjEnd >= ObjSize)  grow (ObjSize + 1);
    memmove (&ObjVal [i + 1], &ObjVal [i], sizeof (T*) * ((ObjEnd++) - i));
    ObjVal [i] = (T*) &what;
    if (ObjCursor >= i)  ObjCursor++;
    return *ObjVal [i];
  }
}

// prepend an other DynArray
//##ModelId=3FBCBCC700CF
template <class T>
inline DynArray<T>& DynArray<T>::prepend (const DynArray<T>& d) {
  if (d.ObjEnd) {
    if ((ObjEnd + d.ObjEnd) >= ObjSize)  grow (ObjSize + d.ObjEnd);
    memmove (&ObjVal [d.ObjEnd], ObjVal, sizeof (T*) * ObjEnd);
    memcpy (ObjVal, d.ObjVal, sizeof (T*) * d.ObjEnd);
    ObjEnd += d.ObjEnd;
    ObjCursor += d.ObjEnd;
  }
  return *((DynArray<T>*) &d);
}

// remove First or Last Object
//##ModelId=3FBCBCC700DB
template <class T>
inline T* DynArray<T>::removeFirst () {
  if (ObjEnd) {
    T* t = ObjVal [0];
    memmove (ObjVal, &ObjVal [1], sizeof (T*) * (--ObjEnd));
    if (ObjCursor)  ObjCursor--;
    else  ObjCursor = ObjEnd;
    return t;
  }
  return NULL;
}

//##ModelId=3FBCBCC700DC
template <class T>
inline T* DynArray<T>::removeLast () {
  return (ObjEnd) ? ObjVal [--ObjEnd] : (T*) NULL;
}

//##ModelId=3FBCBCC700DD
template <class T>
T* DynArray<T>::remove (const T& what) {
  register unsigned i;
  for (i = 0; i < ObjEnd; i++)
    if (ObjVal [i] == &what)  break;
  if (i == ObjEnd) return NULL;
  else {
    T* t = ObjVal [i];
    memmove (&ObjVal [i], &ObjVal [i + 1], sizeof (T*) * ((--ObjEnd) - i));
    if (ObjCursor == i)  ObjCursor = ObjEnd;
    else
      if (ObjCursor > i)  ObjCursor--;
    return t;
  }
}

//##ModelId=3FBCBCC700EB
template <class T>
void DynArray<T>::removeAll () {
  for (register unsigned i = 0; i < ObjEnd; ObjVal [i++] = NULL);
  ObjEnd = ObjCursor = 0;
}

// getting current Object under Cursor
//##ModelId=3FBCBCC700EC
template <class T>
inline T* DynArray<T>::operator () () const {
  return (ObjCursor < ObjEnd) ? ObjVal [ObjCursor] : (T*) NULL;
}

//##ModelId=3FBCBCC700FC
template <class T>
inline T* DynArray<T>::operator ++ () const {
  return (++ObjCursor < ObjEnd) ? ObjVal [ObjCursor] : (T*) NULL;
}

//##ModelId=3FBCBCC700FE
template <class T>
inline T* DynArray<T>::operator ++ (int) const {
  return (ObjCursor < ObjEnd) ? ObjVal [ObjCursor++] : (T*) NULL;
}

//##ModelId=3FBCBCC7010A
template <class T>
inline T* DynArray<T>::operator -- () const {
  if (!ObjCursor)  ObjCursor = ObjEnd;
  return (ObjCursor < ObjEnd) ? ObjVal [--ObjCursor] : (T*) NULL;
}

//##ModelId=3FBCBCC7010C
template <class T>
inline T* DynArray<T>::operator -- (int) const {
  if (!ObjCursor)  {
    ObjCursor = ObjEnd;
    return ObjVal [0];
  }
  return (ObjCursor < ObjEnd) ? ObjVal [ObjCursor--] : (T*) NULL;
}

// getting first Object and set Cursor
//##ModelId=3FBCBCC7011A
template <class T>
inline T* DynArray<T>::First () const {
  return (ObjEnd) ? ObjVal [ObjCursor = 0] : (T*) NULL;
}

// getting last Object and set Cursor
//##ModelId=3FBCBCC7011C
template <class T>
inline T* DynArray<T>::Last () const {
  return (ObjEnd) ? ObjVal [ObjCursor = (ObjEnd - 1)] : (T*) NULL;
}

// getting next Object and set Cursor
//##ModelId=3FBCBCC70128
template <class T>
inline T* DynArray<T>::Next () const {
  return (++ObjCursor < ObjEnd) ? ObjVal [ObjCursor] : (T*) NULL;
}

// getting previous Object and set Cursor
//##ModelId=3FBCBCC7012A
template <class T>
inline T* DynArray<T>::Prev () const {
  if (!ObjCursor)  ObjCursor = ObjEnd;
  return (ObjCursor < ObjEnd) ? ObjVal [--ObjCursor] : (T*) NULL;
}

// find Object and set Cursor
//##ModelId=3FBCBCC700EE
template <class T>
T* DynArray<T>::find (const T& what) const {
  for (register unsigned i = 0; i < ObjEnd; i++)
    if (ObjVal [i] == &what)  return ObjVal [ObjCursor = i];
  return NULL;
}

//##ModelId=3FBCBCC70138
template <class T>
inline unsigned DynArray<T>::Count () const {
  return ObjEnd;
}

//##ModelId=3FBCBCC7012C
template <class T>
inline bool DynArray<T>::isEmpty () const {
  return !ObjEnd;
}

//##ModelId=3FBCBCC70158
template <class T>
inline void DynArray<T>::grow (unsigned newSize) {
  T** newVal = new T* [newSize];
  memcpy (newVal, ObjVal, sizeof (T*) * ObjEnd);
  delete[] ObjVal;
  ObjVal = newVal;
  ObjSize = newSize;
}

#endif	// !defined _DynArray_h
