/*	XHandle.h
 *
 *		Most OS systems I support have the concept of a handle,
 *	a block of resizable memory
 */

/*  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
 */

#ifndef PandaWave_XHANDLE
#define PandaWave_XHANDLE

#include <XConfig.h>

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

/*	@C"XGHandle"
 *	@H"XHandle.h"
 *	@I
 *
 *		This is the wrapper to a block of movable memory.
 */

class XGHandle {
	public:
								XGHandle(unsigned long size = 0, 
										 unsigned short pagesize = 0);
		virtual					~XGHandle();
		
		/*
		 *	Memory access
		 */
		
		void					*operator *() const;
		
		/*
		 *	Memory size
		 */
		
		//  @G"Memory size"
		
		/*	@F"XGHandle::GetSize"
		 *	@I
		 *		Returns the size of this handle.
		 */
		
		unsigned long			GetSize() const
									{
										return fSize;
									}
		void					SetSize(unsigned long);
		
		/*
		 *	Memory manipulation utilities
		 */
		
		void					Append(unsigned long len,
									   void *ptr = 0);
		void					Insert(unsigned long off,
									   unsigned long len,
									   void *ptr = 0);
		void					Delete(unsigned long off,
									   unsigned long len);
									   
		/*
		 *	Memory extraction routines
		 */
		
		//  @G"Memory extraction"
		
		/*	@F"XGHandle::GetChar"
		 *	@I
		 *		Gets the character at the specified byte offset.
		 */
		
		char					GetChar(unsigned long off) const
									{
										return *((char *)**this + off);
									}
		short					GetShort(unsigned long) const;
		long					GetLong(unsigned long) const;
		void					GetMemory(unsigned long, unsigned long, void *) const;
		
		/*	@F"XGHandle::SetChar"
		 *	@I
		 *		Sets the character at the specified byte offset to
		 *	the byte provided
		 */
		
		void					SetChar(unsigned long off, char c)
									{
										*((char *)**this + off) = c;
									}
		void					SetShort(unsigned long,short);
		void					SetLong(unsigned long,long);
		void					SetMemory(unsigned long, unsigned long, const void *);

		/*
		 *	Lock/unlock semantics (prefered: use the XGHandleLock object)
		 */
				
		void					Lock();
		void					Unlock();

	private:
		unsigned short			fPageSize;
		unsigned short			fLock;
		unsigned long			fSize;
		unsigned long			fAlloc;
		
#if OPT_MACOS
		Handle					fData;
#endif

#if OPT_XWIN || OPT_WINOS
		void					*fData;
#endif
};

/*	@C"XGHandleLock"
 *	@H"XHandle.h"
 *	@I
 *
 *		This is an inline stack class which locks the handle. This is
 *	so that handles will be unlocked when I'm done or when an exception
 *	is thrown
 */

class XGHandleLock {
	public:
		//	@G"Construction/Destruction"

		/*	@F"XGHandleLock::XGHandleLock"
		 *	@I
		 *		This stores a pointer to the specified handle, and
		 *	locks the handle using the XGHandle::Lock() method.
		 */
		
								XGHandleLock(XGHandle &ptr)
									{
										fPtr = &ptr;
										fPtr->Lock();
									}
		
		/*	@F"XGHandleLock::~XGHandleLock"
		 *	@I
		 *		This unlocks the stored handle, and is invoked
		 *	when the stack unwinds, if this is a stack-based object
		 */
		
								~XGHandleLock()
									{
										fPtr->Unlock();
									}
	private:
		XGHandle				*fPtr;
};

/************************************************************************/
/*																		*/
/*	Complex Data Types													*/
/*																		*/
/************************************************************************/

/*	@C"XGStringList"
 *	@D"XGHandle"
 *	@H"XHandle.h"
 *	@I
 *
 *		This manages a list of strings, used by various pieces of the
 *	YAAF code. Not only does this store a string list, but this also
 *	provides a mechanism for storing "extra" bytes. These extra bytes,
 *	no more than a few dozen fixed bytes per string, provide a way
 *	to store extra data, such as an index or a pointer to another
 *	object.
 */

class XGStringList : private XGHandle {
	public:
								XGStringList(short extraData = 0);
		virtual					~XGStringList();
		
		/*
		 *	String list interface
		 */
		
		// @G"String List Interface"
		
		/*	@F"XGStringList::GetNumStrings" @I
		 *
		 *		Returns the number of strings that are stored in
		 *	this XGStringList object
		 */
		
		short					GetNumStrings() const
									{
										return fNumber;
									}
		
		void					GetString(long,char *) const;
		void					SetString(long,const char *);
		void					GetExtra(long, void *) const;
		void					SetExtra(long, const void *);
		void					Insert(long,const char *str = 0);
		
		/*	@F"XGStringList::Append" @I
		 *
		 *		Appends the specified string to the end of this
		 *	string list.
		 */
		
		void					Append(const char *str = 0)
									{
										Insert(fNumber,str);
									}
		void					Delete(long);
		void					DeleteAll();
		
	private:
		short					fNumber;
		short					fExtra;
};


#endif // PandaWave_XHANDLE
