/****************************************************************************************

		Accumulator.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		8/3/98		Greg		Fixed TMCPtrArray conversion (T* to T)

*****************************************************************************************/

#ifndef __ACCUMULATOR__
#define __ACCUMULATOR__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCArray.h"
#include "MCPtrArray.h"

OBSOLETE;
/// Never used => Deprecated ?
///
template <class T> class TMCAccumulator : public TMCObject
{
public:
						TMCAccumulator();
						~TMCAccumulator();

	void				Accumulate(const T& element);
	TMCArray<T>*		MakeArray();

	static void 		StaticAccumulate(void *element,void *priv);

protected:
	int8*				fCurElement;
	TMCPtrArray<void>*	fCArrays;
	int32				fNbrElemInCurArray;
	int32				fNbrElement;
	int32				fMaxNbrElement;
	int16				fAlignedSize;
};

enum {kNbrElemInCurArray=0x400};

template <class T> TMCAccumulator<T>::TMCAccumulator()
{
	int32 elementsize=sizeof(T);
	fAlignedSize = (elementsize <= 4) ? elementsize : (elementsize + 3) & (~0x3);
	fNbrElement = 0;
	fCurElement = nil;
	fNbrElemInCurArray = kNbrElemInCurArray;
	fCArrays = new TMCPtrArray<void>;
	fMaxNbrElement = 0;
}

template <class T> TMCAccumulator<T>::~TMCAccumulator()
{
	TMCPtrArray<void>::iterator iter(*fCArrays);
	for (void* cur = iter.First(); iter.More(); cur = iter.Next())
	{
		MCfree(cur);
	}
	delete fCArrays;
}

template <class T> void TMCAccumulator<T>::StaticAccumulate(void* element, void* priv)
{
	((TMCAccumulator *)priv)->Accumulate(&(T*)*element);
}

template <class T> void TMCAccumulator<T>::Accumulate(const T& element)
{
	if (fNbrElement >= fMaxNbrElement)
	{
		void* newCArray = MCmalloc(fNbrElemInCurArray * fAlignedSize);
		fCArrays->AddElem(newCArray);
		fCurElement = (int8 *)newCArray;
		fMaxNbrElement += fNbrElemInCurArray;
		fNbrElemInCurArray <<= 1;
	}
	MCmemcpy(fCurElement, &element, sizeof(T));
	fCurElement += fAlignedSize;
	fNbrElement++;
}

template <class T> TMCArray<T>* TMCAccumulator<T>::MakeArray()
{
	TMCArray<T>* res = new TMCArray<T>(fNbrElement,false);

	TMCArray<T>::iterator begin=res->Begin();
	int8* curOut = (int8 *)&(*begin);
	int32 nbrcopied = 0;
	int32 nbrElemInCurArray = kNbrElemInCurArray;

	TMCPtrArray<void>::iterator iter=fCArrays->Begin();
	for (void* cur = iter.First(); iter.More(); cur = iter.Next())
	{
		int32 nbrToCopy = fNbrElement - nbrcopied;
		if (nbrToCopy > nbrElemInCurArray)
		{
			nbrToCopy = nbrElemInCurArray;
		}
		int32 bytesToCopy = nbrToCopy * sizeof(T);
		MCmemcpy(curOut, cur, bytesToCopy);
		curOut += bytesToCopy;
		nbrcopied += nbrToCopy;
		nbrElemInCurArray <<= 1;
	}

	return res;
}

#endif