/*
template CSimpleVector

	by: Shawn A. Van Ness
	rev: 2000.08.14

The CSimpleVector<> template requires T to have a meaningful default-ctor, 
copy-ctor, and assignment-operator. The Find method requires T to have a 
meaningful operator==.

///todo: nail down exact requirements (ie: verify the above statement)

Usage:

   ATLX::CSimpleVector<CMyClass> vec1;
   ATLX::CSimpleVector<float,float> vec2; 

In the above examples, vec1 will pass arguments by reference, but vec2 will 
use "float" (not "float&") as its argument type.
*/

#pragma once 

namespace ATLX {

template<class T, class A=T&>
class CSimpleVector
{
   struct CInPlaceNewWrapper
   {
      T t;

   CInPlaceNewWrapper(const T& _t) : t(_t)
      { }
   void* operator new(size_t n, void* p) 
      { return p; }
   };

   T* m_pT;
   int m_nSize,m_nAllocSize;

public:

// Initializers

CSimpleVector()
   { m_pT = 0;
     m_nSize = m_nAllocSize = 0; }

CSimpleVector(const CSimpleVector<T,A>& src)
   { m_pT = 0;
     m_nSize = m_nAllocSize = 0;
     (*this) = src; }

CSimpleVector& operator=(const CSimpleVector<T,A>& src)
   {
   RemoveAll(); 
   Append(src);
   return (*this);
   }

~CSimpleVector()
   { RemoveAll();
     free(m_pT); }

// Accessors

int GetSize() const
   { return m_nSize; }

bool IsEmpty() const
   { return (m_nSize==0); }

T& operator[](int i) const
   { ATLASSERT(i >= 0 && i < m_nSize); 
     return (m_pT[i]); }

void CopyTo(T* pt) const
   { ::CopyMemory(pt,m_pT,m_nSize*sizeof(T)); }

int Find(A a) const
   {
   for(int i = 0; i < m_nSize; i++)
      if (m_pT[i] == a) // requires meaningful T::operator==
         return i;
   return -1;
   }

// Operations

void Reserve(int i)
   {
   ATLASSERT(i >= 0);
   if (i > 0)
      {
      // Expand the allocation
      if (i < m_nSize) i = m_nSize;
      m_pT = (T*)realloc(m_pT,i*sizeof(T));
      m_nAllocSize = i;
      }
   else // i == 0
      {
      // Trim the fat, if any
      if (m_nSize == 0)
         { free(m_pT); m_pT = 0; }
      else if (m_nSize < m_nAllocSize)
         { m_pT = (T*)realloc(m_pT,m_nSize*sizeof(T)); }
      m_nAllocSize = m_nSize;
      }
   }

void Push(A a)
   {
   if (m_nSize == m_nAllocSize)
      Reserve((m_nAllocSize==0)?(4):(m_nAllocSize*2)); // first alloc == 4*sizeof(T)

   m_nSize++;
   new(m_pT+m_nSize-1) CInPlaceNewWrapper(a);
   }

T Pop()
   {
   ATLASSERT(m_nSize != 0);
   T t = m_pT[m_nSize-1];

   m_pT[m_nSize-1].~T();
   m_nSize--;

   return t;
   }

void Append(const CSimpleVector<T,A>& src)
   {
   for(int i = 0; i < src.GetSize(); i++)
      Push(src[i]);
   }

void RemoveAll()
   {
   for(int i = 0; i < m_nSize; i++)
      m_pT[i].~T();
   m_nSize = 0;
   }

void Swap(int x, int y)
   {
   ATLASSERT(x >= 0 && x < m_nSize);
   ATLASSERT(y >= 0 && y < m_nSize);

   T* pt = (T*)malloc(sizeof(T));

   ::CopyMemory(pt,&m_pT[x],sizeof(T));
   ::CopyMemory(&m_pT[x],&m_pT[y],sizeof(T));
   ::CopyMemory(&m_pT[y],pt,sizeof(T));

   free(pt);
   }

void Sort()
   {
   // Non-destructive swap-sort (as deterined by T::operator<)
   bool bDone = false;
   while (!bDone)
      {
      bDone = true;
      for (int i=0; i < (m_nSize-1); i++)
         {
         if (m_pT[i+1] < m_pT[i]) 
            {
            Swap(i,i+1);
            bDone = false;
            }
         }
      }
   }

};

} // namespace




w e b c p p
web c plus plus