/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.

** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- January 1997
 */

/*
 * CPStr.h --- simple Pascal-C string
 */

#ifndef CPSTR_H
#define CPSTR_H

#include <string.h>
#include <stdlib.h>

#include "Persistent.h"

#include "ustr.h"
#include <exception>
#define CPStr UPStr
#define CStr UStr

#if TARGET_RT_MAC_CFM
	extern "C" int stricmp(const char *str1, const char *str2);
	extern "C" int strnicmp(const char *str1, const char *str2, unsigned long size);
#elif TARGET_RT_MAC_MACHO
#	define stricmp strcasecmp
#	define strnicmp strncasecmp
#endif

// the persistent version
class PCPStr : public CPStr, public CPersistent
{
	UDECLARE_DYNAMIC(PCPStr)
public:
	PCPStr(const char *uniqueName, const char *defValue = 0L, kClassPersistent pclass = kNoClass) : CPStr(),
		CPersistent(uniqueName, pclass)
	{
		if(defValue != 0L)
			*(CPStr *)this = defValue;
	}
	virtual ~PCPStr()
	{
	}

	virtual unsigned int SizeOf(void) const
	{
		return str != 0L ? length() + 1 : 1;
	}
	
	virtual const void *GetData(void) const
	{
		const void *res = (const char *)(*(CPStr *)this);
		return res == 0L ? "" : res;
	}
	
	virtual void SetData(const void *ptr, unsigned int size)
	{
		if(strlen((const char *)ptr) == (size - 1))
			*(CPStr *)this = (const char *)ptr;
	}

	inline operator const unsigned char *() const
		{ return *(CPStr *)this; }
	inline operator unsigned char *() EGCS_CONST
		{ return *(CPStr *)this; }
		// as a P string

	inline operator const char *() const { return *(CPStr *)this; }
	inline operator char *() EGCS_CONST { return *(CPStr *)this; }
		// as a C string

	inline const char *operator=(const char *newstr)
		{ return ((CPStr *)this)->operator=(newstr); }
		// set from a C String (0L is OK)
	inline const unsigned char *operator=(const unsigned char *newstr)
		{ return ((CPStr *)this)->operator=(newstr); }
		// set from a P String (0L is OK)
};

class PCStr : public CStr, public CPersistent
{
	UDECLARE_DYNAMIC(PCStr)
public:
	PCStr(const char *uniqueName, const char *defValue = 0L, kClassPersistent pclass = kNoClass) : CStr(),
		CPersistent(uniqueName, pclass)
	{
		if(defValue != 0L)
			*(CStr *)this = defValue;
	}
	virtual ~PCStr()
	{
	}

	virtual unsigned int SizeOf(void) const
	{
		return str != 0L ? length() + 1 : 0;
	}
	
	virtual const void *GetData(void) const
	{
		const void *res = (const char *)(*(CStr *)this);
		return res == 0L ? "" : res;
	}
	
	virtual void SetData(const void *ptr, unsigned int size)
	{
		if(strlen((const char *)ptr) == (size - 1))
			*(CStr *)this = (const char *)ptr;
	}

	inline operator const char *() const { return *(CStr *)this; }
	inline operator char *() EGCS_CONST { return *(CStr *)this; }
		// as a C string

	inline const char *operator=(const char *newstr)
	{
		TouchTimeStamp();
		return ((CStr *)this)->operator=(newstr);
	}
		// set from a C String (0L is OK)
	inline const char *operator=(const unsigned char *newstr)
	{
		TouchTimeStamp();
		return ((CStr *)this)->operator=(newstr);
	}
		// set from a P String (0L is OK)
};

// class to use when fed-up with realloc, malloc...
template <class T>
class CStaticAllocT
{
public:
	CStaticAllocT()
	{
		buf = 0L;
		numbuf = 0;
	}

	~CStaticAllocT()
	{
		if(buf != 0L)
			free(buf);
	}

	void AdjustSize(size_t size)
	{
		if(numbuf < size)
		{
			if(buf == 0L)
				buf = (T *)malloc(size * sizeof(T));
			else
				buf = (T *)realloc(buf, size * sizeof(T));
			if(buf == 0L)
				throw std::bad_alloc();
			numbuf = size;
		}
	}

	inline operator T *(void) const /* egcs const */ { return buf; }
	inline operator const T *(void) const { return buf; }
#ifdef __GNUC__
	inline const T & operator[](int i) const { return buf[i]; }
	inline T & operator[](int i) { return buf[i]; }
#endif

	inline size_t size() const { return numbuf; }
protected:
	T *buf;
	size_t numbuf;
};

#endif /* CPSTR_H */
