#pragma once
#pragma push_macro("new")
#pragma push_macro("delete")
#undef new
#undef delete

//:Ignore
#define MxArray_GROWTH_THRESHOLD 0x10000

template <class T> class McArrayMemCopyReallocator
{
public:
	static void reallocateArray(T* pCopy, const T * pSource, int nCount)
	{
		if (nCount > 0) 
		{
			memcpy(pCopy, pSource, nCount * sizeof(T));
		}
	}
};

MXGEDLL void* _MxAlloc_(size_t size);
MXGEDLL void _MxFree_(void* pFree);
//:End Ignore

// -------------------------------------------------------------------------
// Summary:
// 		控件中的数组类型
// -------------------------------------------------------------------------
template <class T, class R = McArrayMemCopyReallocator<T> > class McArray
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McArray(int initPhysicalLength = 0, int initGrowLength = 8);
	McArray(const McArray<T,R>&);
	// -------------------------------------------------------------------------
	// Summary:
	// 		析构函数
	// -------------------------------------------------------------------------
	~McArray();

	// -------------------------------------------------------------------------
	// Summary:
	// 		等号重载
	// -------------------------------------------------------------------------
	McArray<T,R>&         operator =  (const McArray<T,R>&);

	// -------------------------------------------------------------------------
	// Summary:
	// 		等号重载
	// -------------------------------------------------------------------------
	bool                operator == (const McArray<T,R>&);


	// -------------------------------------------------------------------------
	// Summary:
	// 		[]成员运算符
	// -------------------------------------------------------------------------
	T&                  operator [] (int);

	// -------------------------------------------------------------------------
	// Summary:
	// 		[]成员运算符
	// -------------------------------------------------------------------------
	const T             operator [] (int) const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		返回指定位置处的值
	// -------------------------------------------------------------------------
	T                   at          (int index) const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		设置指定位置的值
	// -------------------------------------------------------------------------
	McArray<T,R>&         setAt       (int index, const T& value);

	// -------------------------------------------------------------------------
	// Summary:
	// 		把数组中所有元素都设置成指定的值
	// -------------------------------------------------------------------------
	McArray<T,R>&         setAll      (const T& value);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组第一个元素
	// -------------------------------------------------------------------------
	T&                  first       ();
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组第一个元素
	// -------------------------------------------------------------------------
	const T             first       () const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组最后一个元素
	// -------------------------------------------------------------------------
	T&                  last        ();
	const T             last        () const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		向数组中增加一个值
	// -------------------------------------------------------------------------
	int                 append      (const T& value);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向数组中增加一个数组
	// -------------------------------------------------------------------------
	McArray<T,R>&         append      (const McArray<T,R>& array);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向数组指定位置插入一个值
	// -------------------------------------------------------------------------
	McArray<T,R>&         insertAt    (int index, const T& value);

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除指定位置的值
	// -------------------------------------------------------------------------
	McArray<T,R>&         removeAt    (int index);

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除指定值对象
	// -------------------------------------------------------------------------
	bool                remove      (const T& value, int start = 0);

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除第一个对象
	// -------------------------------------------------------------------------
	McArray<T,R>&         removeFirst ();

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除最后一个对象
	// -------------------------------------------------------------------------
	McArray<T,R>&         removeLast  ();

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除startIndex到endIndex间的元素
	// -------------------------------------------------------------------------
	McArray<T,R>&         removeSubArray (int startIndex, int endIndex);


	// -------------------------------------------------------------------------
	// Summary:
	// 		数组中是否有指定值的元素
	// -------------------------------------------------------------------------
	bool                contains    (const T& value, int start = 0) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		在数组中搜索指定值元素，foundAt是找到后所在的位置
	// -------------------------------------------------------------------------
	bool                find        (const T& value, int& foundAt,
		int start = 0) const;
	int                 find        (const T& value) const;
	int                 findFrom    (const T& value, int start) const;
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组长度
	// -------------------------------------------------------------------------
	int                 length      () const;

	int                 size() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		数组是否为空
	// -------------------------------------------------------------------------
	bool                isEmpty     () const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组长度
	// -------------------------------------------------------------------------
	int                 logicalLength() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置数组长度
	// -------------------------------------------------------------------------
	McArray<T, R>&         setLogicalLength(int);

	void resize(int iSize) {
		this->setLogicalLength(iSize);
	}
	
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组物理内存长度
	// -------------------------------------------------------------------------
	int                 physicalLength() const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置数组物理内存长度
	// -------------------------------------------------------------------------
	McArray<T,R>&         setPhysicalLength(int);

//:Ignore

	int                 growLength  () const;
	McArray<T,R>&         setGrowLength(int);
//:End Ignore

	// -------------------------------------------------------------------------
	// Summary:
	// 		数组中的元素反向
	// -------------------------------------------------------------------------
	McArray<T,R>&         reverse     ();

	// -------------------------------------------------------------------------
	// Summary:
	// 		交换数组中两个元素
	// -------------------------------------------------------------------------
	McArray<T,R>&         swap        (int i1, int i2);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回数组中元素的内存指针
	// -------------------------------------------------------------------------
	const T*            asArrayPtr  () const;
	T*                  asArrayPtr  ();

	// -------------------------------------------------------------------------
	// Summary:
	// 		清理所有的方法
	// -------------------------------------------------------------------------
	void removeAll() {
		setLogicalLength(0);
	}

	void clear() {
		setLogicalLength(0);
	}
//:Ignore

protected:
	T*                  mpArray;
	int                 mPhysicalLen;
	int                 mLogicalLen;
	int                 mGrowLen;

	bool                isValid     (int) const;
//:End Ignore
};


template <class T, class R> inline bool
McArray<T,R>::contains(const T& value, int start) const
{ int dummy; return find(value, dummy, start); }

template <class T, class R> int
	McArray<T,R>::find(const T& value) const
{
	return this->findFrom(value, 0);   // search from the beginning
}

template <class T, class R> int
	McArray<T,R>::findFrom(const T& value, int start) const
{
	for (int i = start; i < this->mLogicalLen; i++) {
		if (mpArray[i] == value)
			return i;
	}
	return -1;
}


template <class T, class R> inline int
McArray<T,R>::length() const
{ return mLogicalLen; }


template <class T, class R> inline int
McArray<T, R>::size() const
{
	return mLogicalLen;
}

template <class T, class R> inline bool
McArray<T,R>::isEmpty() const
{ return mLogicalLen == 0; }

template <class T, class R> inline int
McArray<T,R>::logicalLength() const
{ return mLogicalLen; }

template <class T, class R> inline int
McArray<T,R>::physicalLength() const
{ return mPhysicalLen; }

template <class T, class R> inline int
McArray<T,R>::growLength() const
{ return mGrowLen; }

template <class T, class R> inline const T*
McArray<T,R>::asArrayPtr() const
{ return mpArray; }

template <class T, class R> inline T*
McArray<T,R>::asArrayPtr()
{ return mpArray; }

template <class T, class R> inline bool
McArray<T,R>::isValid(int i) const
{ return i >= 0 && i < mLogicalLen; }

template <class T, class R> inline T&
McArray<T,R>::operator [] (int i)
{ MXASSERT(isValid(i)); return mpArray[i]; }

template <class T, class R> inline const T
McArray<T,R>::operator [] (int i) const
{
	MXASSERT(isValid(i)); return mpArray[i];
}

template <class T, class R> inline T
McArray<T,R>::at(int i) const
{
	MXASSERT(isValid(i)); return mpArray[i];
}

template <class T, class R> inline McArray<T,R>&
McArray<T,R>::setAt(int i, const T& value)
{
	MXASSERT(isValid(i)); mpArray[i] = value; return *this;
}

template <class T, class R> inline T&
McArray<T,R>::first()
{
	MXASSERT(!isEmpty()); return mpArray[0];
}

template <class T, class R> inline const T
McArray<T,R>::first() const
{
	MXASSERT(!isEmpty()); return mpArray[0];
}

template <class T, class R> inline T&
McArray<T,R>::last()
{
	MXASSERT(!isEmpty()); return mpArray[mLogicalLen - 1];
}

template <class T, class R> inline const T
McArray<T,R>::last() const
{
	MXASSERT(!isEmpty()); return mpArray[mLogicalLen - 1];
}

template <class T, class R> inline int
McArray<T,R>::append(const T& value)
{ insertAt(mLogicalLen, value); return mLogicalLen-1; }

template <class T, class R> inline McArray<T,R>&
McArray<T,R>::removeFirst()
{
	MXASSERT(!isEmpty()); return removeAt(0);
}

template <class T, class R> inline McArray<T,R>&
McArray<T,R>::removeLast()
{
	MXASSERT(!isEmpty()); mLogicalLen--; return *this;
}

template <class T, class R> inline McArray<T,R>&
McArray<T,R>::setGrowLength(int glen)
{
	MXASSERT(glen > 0); mGrowLen = glen; return *this;
}


#define MxlowMemBail() MXASSERT(false)

template < class T, class R >
McArray< T, R > ::McArray(int physicalLength, int growLength)
: mpArray(NULL),
mPhysicalLen(physicalLength),
mLogicalLen(0),
mGrowLen(growLength)
{
	MXASSERT(mGrowLen > 0);
	MXASSERT(mPhysicalLen >= 0);
	if (mPhysicalLen > 0) {

		//mpArray = (::operator new  T[mPhysicalLen]);
		mpArray = static_cast<T *>(_MxAlloc_(sizeof(T) * mPhysicalLen));

		if (mpArray == NULL) {
			mPhysicalLen = 0;
			MxlowMemBail();
		}
		else {
			T *pNewBuf = mpArray;
			for (int i = 0; i < mPhysicalLen; i++, pNewBuf++)
				::new(pNewBuf) T;
		}
	}
}


template <class T, class R>
McArray<T,R>::McArray(const McArray<T,R>& src)
: mpArray(NULL),
mPhysicalLen(src.mPhysicalLen),
mLogicalLen(src.mLogicalLen),
mGrowLen(src.mGrowLen)
{
	if (mPhysicalLen > 0) {

		//mpArray = (::operator new T[mPhysicalLen]);
		mpArray = static_cast<T *>(_MxAlloc_(sizeof(T) * mPhysicalLen));
		if (mpArray == NULL) {
			MxlowMemBail();
			mPhysicalLen = 0;
			mLogicalLen = 0;
		}
		else {
			T *pNewBuf = mpArray;
			for (int i = 0; i < mPhysicalLen; i++, pNewBuf++)
				::new(pNewBuf) T;
		}
	}

	R::reallocateArray(mpArray, src.mpArray, mLogicalLen);
}

template <class T, class R>
McArray<T,R>::~McArray()
{
	if (mpArray != NULL)

		for (size_t i = 0; i < mPhysicalLen; i++)
			(mpArray + i)->~T();

	_MxFree_(static_cast<void *>(mpArray));
		//::operator delete[] mpArray;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::operator = (const McArray<T,R>& src)
{
	if (this != &src) {
		if (mPhysicalLen < src.mLogicalLen) {
			if (mpArray != NULL) {

				for (size_t i = 0; i < mPhysicalLen; i++)
					(mpArray + i)->~T();


				_MxFree_(static_cast<void *>(mpArray));
				//::operator delete[] mpArray;
			}
			mPhysicalLen = src.mLogicalLen;
			

			//mpArray = (::operator new  T[mPhysicalLen]);
			mpArray = static_cast<T *>(_MxAlloc_(sizeof(T) * mPhysicalLen));

			if (mpArray == NULL) { 
				MxlowMemBail();
				mPhysicalLen = 0;
				mLogicalLen = 0;
				return *this;
			}
			else {
				T *pNewBuf = mpArray;
				for (int i = 0; i < mPhysicalLen; i++, pNewBuf++)
					::new(pNewBuf) T;
			}
		}
		mLogicalLen = src.mLogicalLen;
		R::reallocateArray(mpArray, src.mpArray, mLogicalLen);
	}
	return *this;
}



template <class T, class R> bool
McArray<T,R>::operator == (const McArray<T,R>& cpr)
{
	if (mLogicalLen == cpr.mLogicalLen) {
		for ( int i = 0; i < mLogicalLen; i++)
			if (mpArray[i] != cpr.mpArray[i])
				return false;
		return true;
	}
	return false;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::setAll(const T& value)
{
	for ( int i = 0; i < mLogicalLen; i++) {
		mpArray[i] = value;
	}
	return *this;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::append(const McArray<T,R>& otherArray)
{
	int otherLen = otherArray.length();
	if (otherLen == 0) {
		return *this;
	}
	int newLen = mLogicalLen + otherLen;
	if (newLen > mPhysicalLen) {
		setPhysicalLength(newLen);
	}

	R::reallocateArray(mpArray + mLogicalLen, otherArray.mpArray, otherLen);

	mLogicalLen = newLen;
	return *this;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::insertAt(int index, const T& value)
{
	T  tmp(value);
	MXASSERT(index >= 0 && index <= mLogicalLen);

	if (mLogicalLen >= mPhysicalLen) {
		int growth = (mLogicalLen * sizeof(T)) < MxArray_GROWTH_THRESHOLD ?
mLogicalLen : MxArray_GROWTH_THRESHOLD / sizeof(T);
		setPhysicalLength(mLogicalLen + mxmax(growth, mGrowLen));
	}

	if (index != mLogicalLen) {
		 T* p = mpArray + mLogicalLen;
		 T* pStop = mpArray + index;
		do {
			*p = *(p-1);
		} while (--p != pStop);
	}
	mpArray[index] = tmp;
	mLogicalLen++;
	return *this;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::removeAt(int index)
{
	MXASSERT(isValid(index));

	if (index < mLogicalLen - 1) {
		 T* p = mpArray + index;
		 T* pStop = mpArray + mLogicalLen - 1;
		do {
			*p = *(p+1);
		} while (++p != pStop);
	}
	mLogicalLen--;
	return *this;
}

template <class T, class R> McArray<T,R>&
McArray<T,R>::removeSubArray(int startIndex, int endIndex)
{
	MXASSERT(isValid(startIndex));
	MXASSERT(startIndex <= endIndex);

	if ( endIndex >= mLogicalLen - 1) {
		mLogicalLen = startIndex;
		return *this;
	}


	if (startIndex < mLogicalLen - 1) {
		 T* p = mpArray + startIndex;
		 T* q = mpArray + endIndex + 1;
		 T* pStop = mpArray + mLogicalLen;
		for (; q < pStop; p++, q++ ) {
			*p = *q;
		}
	}
	mLogicalLen -= endIndex - startIndex + 1;
	return *this;
}


template <class T, class R> bool
McArray<T,R>::find(const T& value, int& index, int start) const
{
	for ( int i = start; i < mLogicalLen; i++) {
		if (mpArray[i] == value) {
			index = i;
			return true;
		}
	}
	return false;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::setLogicalLength(int n)
{
	MXASSERT(n >= 0);
	if (n > mPhysicalLen) {

		int growth = (mPhysicalLen * sizeof(T)) < MxArray_GROWTH_THRESHOLD ?
mPhysicalLen : MxArray_GROWTH_THRESHOLD / sizeof(T);

		int minSize = mPhysicalLen + mxmax(growth, mGrowLen);
		if ( n > minSize)
			minSize = n;
		setPhysicalLength(minSize);
	}
	mLogicalLen = n;
	return *this;
}

template <class T, class R> McArray<T,R>&
McArray<T,R>::setPhysicalLength(int n)
{
	MXASSERT(n >= 0);
	if (n == mPhysicalLen) return *this;
	T* pOldArray = mpArray;
	const size_t nOldLen = mPhysicalLen;

	if (n == 0) { 
		mpArray = NULL;
		mPhysicalLen = 0;


	} else {

		//mpArray = (::operator new  T[n]);
		mpArray = static_cast<T *>(_MxAlloc_(sizeof(T) * n));

		if (mpArray == NULL) {
			MxlowMemBail();
			mPhysicalLen = 0;
		} else {

			T *pNewBuf = mpArray;
			for (int i = 0; i < n; i++, pNewBuf++)
				::new(pNewBuf) T;

			R::reallocateArray(mpArray, pOldArray, ((n < mLogicalLen) ? n : mLogicalLen));
			mPhysicalLen = n;
		}
	}

	if (pOldArray != NULL) { 

		for (size_t i = 0; i < nOldLen; i++)
			(pOldArray + i)->~T();

		_MxFree_(static_cast<void *>(pOldArray));
		//::operator delete[] pOldArray;
	}
	if (mPhysicalLen < mLogicalLen) {
		mLogicalLen = mPhysicalLen;
	}
	return *this;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::reverse()
{
	T tmp;
	for ( int i = 0; i < mLogicalLen/2; i++) {
		tmp = mpArray[i];
		mpArray[i] = mpArray[mLogicalLen - 1 - i];
		mpArray[mLogicalLen - 1 - i] = tmp;
	}
	return *this;
}


template <class T, class R> McArray<T,R>&
McArray<T,R>::swap(int i1, int i2)
{
	MXASSERT(isValid(i1));
	MXASSERT(isValid(i2));

	if (i1 == i2) return *this;

	T tmp = mpArray[i1];
	mpArray[i1] = mpArray[i2];
	mpArray[i2] = tmp;
	return *this;
}


template <class T, class R> bool
McArray<T,R>::remove(const T& value, int start)
{
	int i = 0;
	if (find(value, i, start)) {
		removeAt(i);
		return true;
	} else {
		return false;
	}
}

//:End Ignore

// -------------------------------------------------------------------------
// Summary:
// 		Double数组
// -------------------------------------------------------------------------
typedef McArray<double> McGeDoubleArray;

typedef McArray<float> McGeFloatArray;

// -------------------------------------------------------------------------
// Summary:
// 		int数组
// -------------------------------------------------------------------------
typedef McArray<int>    McGeIntArray;

// -------------------------------------------------------------------------
// Summary:
// 		int数组
// -------------------------------------------------------------------------
typedef McArray<int>	McDbIntArray;

// -------------------------------------------------------------------------
// Summary:
// 		指针数组
// -------------------------------------------------------------------------
typedef McArray<void*>  McGeVoidPointerArray;

// -------------------------------------------------------------------------
// Summary:
// 		指针数组
// -------------------------------------------------------------------------
typedef McArray<void*>  McDbVoidPtrArray;

#pragma pop_macro("new")
#pragma pop_macro("delete")