/*	XCollection.h
 *
 *		A collection of small objects stored in one place for fast
 *	access.
 */

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

  YAAF is Copyright 1997-1999 by William Woody.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions 
  are met:

  Redistributions of source code must retain the above copyright notice, 
  this list of conditions and the following disclaimer.

  Neither the name of the copyright holder or other contributors may
  be used to promote products derived from this software without
  specific written prior permission.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  SOFTWARE.
  
  Contact:   woody@alumni.caltech.edu
  Web page:  http://www.pandawave.com/yaaf/

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

#ifndef PandaWave_XHEAP
#define PandaWave_XHEAP

#include <XConfig.h>
#include <XHandle.h>
#include <XTypes.h>

/************************************************************************/
/*																		*/
/*	Class Declaration													*/
/*																		*/
/************************************************************************/

/*$	XGCollection
 *
 *		A collection of objects stored in one location.
 *
 *		There are a number of times in my code where I want to take
 *	advantage of storing a great many number of objects refered
 *	to by a 'handle' or reference ID. It turns out that for storing
 *	a number of small objects inside of a 'black box' object, this
 *	gives me a simple mechanism that is more memory efficient than
 *	using a whole bunch of dynamically created XGHandle objects,
 *	especially on the Macintosh.
 *
 *		There are two other advantages. First, getting the data
 *	inside of an object is a simple dereference and memory copy, so
 *	it's relatively easy to get and set data. Second, the whole
 *	mess can be relased by releasing this object.
 */

class XGCollection {
	public:
								XGCollection();
		virtual					~XGCollection();
		
		/*
		 *	Allocation/deallocation
		 */
		
		uint32					New(uint32 size);
		uint32					GetSize(uint32 id);
		void					SetSize(uint32 id, uint32 size);
		void					Free(uint32 id);
		void					DeleteAll();

		uint32					GetData(uint32 id, uint32 size, void *);
		uint32					SetData(uint32 id, uint32 size, const void *);
		void					*GetDataPtr(uint32);
		
		void					Validate();
		
		XGHandle&				GetDataHandle() { return fData; }
		
	protected:
		union XGCollected {
			struct {
				long offset;
				long size;
				long next, prev;
			} used;
			struct {
				long next, prev;
			} avail;
		};
		
		XGHandle fTOC;
		XGHandle fData;
		long fUsedChain;
		long fAvailChain;
		long fWastedSpace;
		long fAllocMark;
		
		uint32 GetDataSpace( uint32 size );
		void CompactDataSpace();
};

#endif // PandaWave_XHEAP
