#ifndef TOOLBOX_STRING_H
#define TOOLBOX_STRING_H

#include "tools.h"
#include "cshared.h"

class cSource;

// hide VDR's new cString class...
typedef cString cStringVDR;
#define cString cStringMPC


class cString: public cShared {
	private:
		uint StringLen;

	public:
		cString ();
		cString (const cString &src);
		cString (const char *src);
		cString (char src);
		virtual ~cString ();

		void clear ();
		void set   (const cString &src);
		void set   (const char *src);
		void set   (char src);

		void release (uint newsize);

		cString &operator= (const cString &src) { set(src); return *this; }
		cString &operator= (const char *src) 	{ set(src); return *this; }
		cString &operator= (char src)			{ set(src); return *this; }

		void append (const cString &src);
		void append (const char *src);
		void append (char src);

		friend cString operator+ (const cString &a, const cString &b);
		friend cString operator+ (const cString &a, const char *b);
		friend cString operator+ (const char *a, const cString &b);
		friend cString operator+ (const cString &a, char b);
		friend cString operator+ (char a, const cString &b);

		friend cString &operator+= (cString &a, const cString &b);
		friend cString &operator+= (cString &a, const char *b);
		friend cString &operator+= (cString &a, char b);

		void prepend (const cString &src);
		void prepend (const char *src);
		void prepend (char src);

		char at (uint i) const;
		char operator[] (int i) const { return at((uint)i); }

		char &at (uint i);
		char &operator[] (int i) { return at(i); }

		cString left  (uint count) const;
		cString right (uint count) const;
		cString mid   (int idx, uint count = (uint)-1) const;

		int Find (const cString &String, uint Offset = 0) const;
		int Find (const char *String, uint Offset = 0) const;
		int Find (char Character, uint Offset = 0) const;
		
		void format (const char *fmt, ...)
#if defined(_CC_GNU)
			__attribute__ ((format (printf, 2, 3)))
#endif
			;
		void format (const cString &fmt, ...)
#if defined(_CC_GNU)
			__attribute__ ((format (printf, 2, 3)))
#endif
			;

		uint length () const { return StringLen; }
		bool isNull () const { return buffer() == 0; }

		friend bool operator== (const cString &str1, const cString &str2);
		friend bool operator== (const cString &str1, const char *str2);
		friend bool operator== (const char *str1, const cString &str2);

		friend bool operator!= (const cString &str1, const cString &str2);
		friend bool operator!= (const cString &str1, const char *str2);
		friend bool operator!= (const char *str1, const cString &str2);

		friend bool operator< (const cString &str1, const cString &str2);
		friend bool operator< (const cString &str1, const char *str2);
		friend bool operator< (const char *str1, const cString &str2);
		
		friend bool operator> (const cString &str1, const cString &str2);
		friend bool operator> (const cString &str1, const char *str2);
		friend bool operator> (const char *str1, const cString &str2);
		
		friend bool operator<= (const cString &str1, const cString &str2);
		friend bool operator<= (const cString &str1, const char *str2);
		friend bool operator<= (const char *str1, const cString &str2);
		
		friend bool operator>= (const cString &str1, const cString &str2);
		friend bool operator>= (const cString &str1, const char *str2);
		friend bool operator>= (const char *str1, const cString &str2);
};

inline char cString::at(uint idx) const {
	ASSERT(idx >= StringLen);
	return buffer() ? buffer()[idx] : 0;
}

inline char &cString::at(uint idx) {
	static char null = 0;
	ASSERT(idx >= StringLen);
	if (buffer()) {
		exclusive();
		return buffer()[idx];
	} else
		return (null = 0);
}

inline cString operator+ (const cString &a, const cString &b) {
	cString ret(a);
	ret.append(b);
	return ret;
}

inline cString operator+ (const cString &a, const char *b) {
	cString ret(a);
	ret.append(b);
	return ret;
}

inline cString operator+ (const char *a, const cString &b) {
	cString ret(a);
	ret.append(b);
	return ret;
}

inline cString operator+ (const cString &a, char b) {
	cString ret(a);
	ret.append(b);
	return ret;
}

inline cString operator+ (char a, const cString &b) {
	cString ret(a);
	ret.append(b);
	return ret;
}

inline cString &operator+= (cString &a, const cString &b) {
	a.append(b);
	return a;
}

inline cString &operator+= (cString &a, const char *b) {
	a.append(b);
	return a;
}

inline cString &operator+= (cString &a, char b) {
	a.append(b);
	return a;
}

inline bool operator== (const cString &str1, const cString &str2) {
	if (str1.length() != str2.length())
		return false;
	return memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length()) == 0;
}

inline bool operator== (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	if (str1.length() != len)
		return false;
	return memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len) == 0;
}

inline bool operator== (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	if (len != str2.length())
		return false;
	return memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length()) == 0;
}

inline bool operator!= (const cString &str1, const cString &str2) {
	if (str1.length() != str2.length())
		return true;
	return memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length()) != 0;
}

inline bool operator!= (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	if (str1.length() != len)
		return true;
	return memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len) != 0;
}

inline bool operator!= (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	if (len != str2.length())
		return true;
	return memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length()) != 0;
}

inline bool operator< (const cString &str1, const cString &str2) {
	int ret = memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length());
	if ((ret < 0) || ((ret == 0) && (str1.length() < str2.length())))
		return true;
	return false;
}

inline bool operator< (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	int ret = memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len);
	if ((ret < 0) || ((ret == 0) && (str1.length() < len)))
		return true;
	return false;
}

inline bool operator< (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	int ret = memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length());
	if ((ret < 0) || ((ret == 0) && (len < str2.length())))
		return true;
	return false;
}

inline bool operator> (const cString &str1, const cString &str2) {
	int ret = memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length());
	if ((ret > 0) || ((ret == 0) && (str1.length() < str2.length())))
		return true;
	return false;
}

inline bool operator> (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	int ret = memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len);
	if ((ret > 0) || ((ret == 0) && (str1.length() < len)))
		return true;
	return false;
}

inline bool operator> (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	int ret = memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length());
	if ((ret > 0) || ((ret == 0) && (len < str2.length())))
		return true;
	return false;
}

inline bool operator<= (const cString &str1, const cString &str2) {
	int ret = memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length());
	if ((ret < 0) || ((ret == 0) && (str1.length() <= str2.length())))
		return true;
	return false;
}

inline bool operator<= (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	int ret = memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len);
	if ((ret < 0) || ((ret == 0) && (str1.length() <= len)))
		return true;
	return false;
}

inline bool operator<= (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	int ret = memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length());
	if ((ret < 0) || ((ret == 0) && (len <= str2.length())))
		return true;
	return false;
}

inline bool operator>= (const cString &str1, const cString &str2) {
	int ret = memcmp(str1.buffer(), str2.buffer(), str1.length() < str2.length() ? str1.length() : str2.length());
	if ((ret > 0) || ((ret == 0) && (str1.length() >= str2.length())))
		return true;
	return false;
}

inline bool operator>= (const cString &str1, const char *str2) {
	uint len = strlen(str2);
	int ret = memcmp(str1.buffer(), str2, str1.length() < len ? str1.length() : len);
	if ((ret > 0) || ((ret == 0) && (str1.length() >= len)))
		return true;
	return false;
}

inline bool operator>= (const char *str1, const cString &str2) {
	uint len = strlen(str1);
	int ret = memcmp(str1, str2.buffer(), len < str2.length() ? len : str2.length());
	if ((ret > 0) || ((ret == 0) && (len >= str2.length())))
		return true;
	return false;
}
		
#endif // TOOLBOX_STRING_H
