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

#ifndef USTR_H
#define USTR_H

#include "uconfig.h"

#ifdef __GNUC__
#	define EGCS_CONST const
#else
#	define EGCS_CONST
#endif

#include <string.h>

/*!
 * \class UPStr ustr.h
 * \brief up to 255 characters pascal and C string.
 */

class UEXPORT UPStr
{
public :
	inline UPStr() : str(0L) {}
	inline UPStr(const char *newstr)
	{
		str = 0L;
		*this = newstr;
	}
	inline UPStr(const unsigned char *newstr)
	{
		str = 0L;
		*this = newstr;
	}
	inline UPStr(const UPStr & newstr)
	{
		str = 0L;
		*this = newstr;
	}
	virtual ~UPStr() {flush();}

	inline bool empty(void) const {return str == 0L || str[0] == '\0';}
	inline unsigned int length(void) const {return str == 0L ? 0 : (unsigned char)str[0];}

	//! set to a new C String (0L is OK)
	const char *operator=(const char *newstr);
	//! set to a new P String (0L is OK)
	const unsigned char *operator=(const unsigned char *newstr);
	//! set according to another UPStr
	const UPStr & operator=(const UPStr & newstr);
	//! set from a buffer
	const UPStr & set(const char *buf, unsigned int len);

	//! as a C string
	inline operator const char *() const {return str == 0L ? "" : str + 1;}
	//! as a C string
	inline operator char *() EGCS_CONST {return str == 0L ? 0L : str + 1;}
	//! as a C string
	inline const char *c_str() const {return str == 0L ? "" : str + 1;}

	//! as a P string
	inline operator const unsigned char *() const
		{return str == 0L ? (unsigned char *)"" : (unsigned char *)str;}
	//! as a P string
	inline operator unsigned char *() EGCS_CONST
		{return str == 0L ? (unsigned char *)"" : (unsigned char *)str;}
	//! as a P string
	inline const unsigned char *p_str() const
		{return str == 0L ? (unsigned char *)"" : (unsigned char *)str;}

	//! concatenate
	UPStr & operator<<(const char *addToStr);
	//! concatenate
	UPStr & operator<<(char addToStr);
	//! concatenate
	UPStr & operator<<(int addToStr);

	inline bool endsWith(char c) const {return str == 0L ? false : str[str[0]] == c;}
	
	//! replace a character
	const UPStr & replace(char which, char bywhich);
	
protected :
	void flush(void);

	//! the String 
	char *str;
};

/*!
 * \class UStr ustr.h
 * \brief C string class.
 */

class UEXPORT UStr
{
public :
	inline UStr() : str(0L) {}
	inline UStr(const char *newstr)
	{
		str = 0L;
		*this = newstr;
	}
	inline UStr(const unsigned char *newstr)
	{
		str = 0L;
		set((const char *)newstr + 1, newstr[0]);
	}
	inline UStr(const UStr & newstr)
	{
		str = 0L;
		*this = newstr;
	}
	virtual ~UStr() {flush();}

	inline bool empty(void) const {return str == 0L || str[0] == '\0';}
	inline unsigned int length(void) const {return str == 0L ? 0 : strlen(str);}

	//! set from a C String (0L is OK)
	const char *operator=(const char *newstr);
	//! set from a P String (0L is OK)
	const char *operator=(const unsigned char *newstr);
	//! set according to another UStr
	const UStr & operator=(const UStr & newstr);
	//! set from a buffer
	const UStr & set(const char *buf, unsigned int len);

	//! compare, provided to compile with STL
	bool operator<(const UStr & str) const;
	//! compare, provided to compile with STL
	bool operator>(const UStr & str) const;
	//! compare, provided to compile with STL
	bool operator==(const UStr & str) const;
	//! compare, provided to compile with STL
	bool operator==(const char *str) const;
	//! compare, provided to compile with STL
	bool operator!=(const UStr & str) const;
	//! compare, provided to compile with STL
	bool operator!=(const char *str) const;

#if (defined(__MWERKS__) && __MWERKS__ < 0x2400) || defined(__GNUC__)
	inline char operator[](int index) const { return str[index]; }
	inline char & operator[](int index) { return str[index]; }
#endif /* TARGET_OS_MAC */

	//! as a C string
	inline operator const char *() const { return str == 0L ? "" : str; }
	//! as a C string
	inline operator char *() EGCS_CONST { return str == 0L ? (char*)"" : str; }
	//! as a C string
	inline const char *c_str() const { return str == 0L ? "" : str; }

	//! concatenate
	UStr & operator<<(const char *addToStr);
	//! concatenate
	UStr & operator<<(char addToStr);
	//! concatenate
	UStr & operator<<(int addToStr);
	//! concatenate
	UStr & operator+=(int addToStr);
	//! concatenate
	UStr & operator+=(char *addToStr);
	//! concatenate
	UStr & operator+=(const char *addToStr);
	//! concatenate
	UStr & operator+=(const UStr & addToStr);

	//! compare
	inline int compare(const char *thestr) const { return strcmp(*this, thestr); }

	inline bool endsWith(char c) const {return !length() ? false : str[length()-1] == c;}
	
	//! replace a character
	const UStr & replace(char which, char bywhich);
		
	//! find a string
	const int find(const char *thestr) const;
	const int rfind(const char *thestr) const;
	
	//! find a character
	const int find(char thechar) const;
	const int rfind(char thechar) const;
		
	//! get substring	
	char* substr(int idx, int len) const;
	//! get substring in an UStr; returns input reference for convenience
	UStr& substr(int idx, int len, UStr& subStr) const;
		
protected :
	void flush(void);
	//! the String
	char *str;
};

#endif /* USTR_H */
