/*	XGArray.cpp
 *
 *		This implements the common code that is used by the XGDynArray
 *	template and other dynamic array objects.
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XError.h>
#include <XDynArray.h>

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

// @G"Construction/Destruction"

/*	@F"XGArray::XGArray" @I
 *
 *		Construct an empty array.
 */

XGArray::XGArray()
{
	fLength = 0;
	fAlloc = 0;
}

/*	@F"XGArray::~XGArray" @I
 *
 *		Destroy this object. This does nothing; the destruction of
 *	the contents of this thing is dependant on the template declared
 *	from this thing.
 */

XGArray::~XGArray()
{
}

/************************************************************************/
/*																		*/
/*	External Interface													*/
/*																		*/
/************************************************************************/

// @G"Public Methods"

/*	@F"XGArray::Delete" @I
 *
 *		Delete one element
 */

void XGArray::Delete(long index)
{
	long j;
	
	/*
	 *	Range check
	 */
	
	Assert((index >= 0) && (index < fLength));
	
	/*
	 *	Copy elements over
	 */
	
	for (j = index+1; j < fLength; j++) {
		CopyArray(j-1,j);
	}
	fLength--;
	
	/*
	 *	Shrink allocation (if needed)
	 */
	
	j = fLength;
	if (j % 16) j += 16 - (j % 16);
	if (j != fAlloc) {
		ChangeArray(j,fLength);
		fAlloc = j;
	}
}

/*	@F"XGArray::DeleteAll" @I
 *
 *		Delete all elements
 */

void XGArray::DeleteAll(void)
{
	fLength = 0;
	fAlloc = 0;
	ChangeArray(0,0);
}

/*	@F"XGArray::SetLength" @I
 *
 *		This forces the length to be set to the particular size, clipping
 *	or adding elements to the end of the array
 */

void XGArray::SetLength(long length)
{
	long j;
	
	if (length == fLength) return;
	
	j = length;
	if (j % 16) j += 16 - (j % 16);
	if (j != fAlloc) {
		if (fLength < length) ChangeArray(j,fLength);
		else ChangeArray(j,length);
		fAlloc = j;
	}
	fLength = length;
}

/************************************************************************/
/*																		*/
/*	Hidden stuff														*/
/*																		*/
/************************************************************************/

/*	XGArray::Copy
 *
 *		Copy arrays
 */

void XGArray::Copy(const XGArray &a)
{
	long i;
	
	if (fAlloc != a.fAlloc) {
		ChangeArray(a.fAlloc,0);
		fAlloc = a.fAlloc;
	}
	fLength = a.fLength;
	for (i = 0; i < fLength; i++) {
		CopyElement(i,a.GetElement(i));
	}
}

/*	XGArray::InsertElement
 *
 *		Insert this element. It is assumed that the thing overriding
 *	the ChangeArray/CopyArray/etc stuff know the size of this
 */

void XGArray::InsertElement(long index, void *ptr)
{
	long j;
	
	/*
	 *	Range check
	 */
	
	Assert((index >= 0) && (index <= fLength));
	
	/*
	 *	Change the allocation if needed
	 */
	
	j = fLength + 1;
	if (j % 16) j += 16 - (j % 16);
	if (j != fAlloc) {
		ChangeArray(j,fLength);
		fAlloc = j;
	}
	
	/*
	 *	Insert the element
	 */
	
	for (j = fLength; j > index; j--) {
		CopyArray(j,j-1);
	}
	CopyElement(index,ptr);
	fLength++;
}

