#ifndef SDPTYPES_H
#define SDPTYPES_H

// SDPTypes Library
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This library 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 2 of the License, or (at your option) 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
// 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 library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Public API for the entire SDPTypes library
		\author Tim Shead (tshead@k-3d.com)
*/

/////////////////////////////////////////////////////////////////////////////
// Identify platform

#if defined WIN32
/// target platform is Win32
#define SDPWIN32
#else // SDPWIN32
/// Target platform is Unix
#define SDPUNIX
#endif //  !SDPWIN32

#ifdef SDPWIN32
#include <windows.h>
#endif // SDPWIN32

/////////////////////////////////////////////////////////////////////////////
// Extend std::string

#include <sstream>
#include <string>

/// Pointer to a constant string
typedef const char* const SDPCSTRING;

// Stop the unicode madness!
#if defined (_UNICODE) || defined (UNICODE)
	#error "sdpString does not support UNICODE builds!"
#endif

/// The sdpString base class
typedef std::string sdpStringBase;

/// An extended string class, derived from std::string
class sdpString :
	public sdpStringBase
{
public:
	// Constructors ...
	sdpString() :
		sdpStringBase()
	{
	}

	sdpString(SDPCSTRING String) :
		sdpStringBase(String ? String : "")
	{
	}

	sdpString(SDPCSTRING String, unsigned long Length) :
		sdpStringBase(String, Length)
	{
	}

	sdpString(const sdpString& String) :
		sdpStringBase(String)
	{
	}

	sdpString(const sdpStringBase& String) :
		sdpStringBase(String)
	{
	}

	sdpString(size_type Size, value_type Character) :
		sdpStringBase(Size, Character)
	{
	}

	sdpString(const_iterator First, const_iterator Last) :
		sdpStringBase(First, Last)
	{
	}

	// Assignment operators ...
	sdpString& sdpString::operator=(const sdpString& String)
	{
		erase();
		assign(String.c_str());
		return *this;
	};

	sdpString& sdpString::operator=(const sdpStringBase& String)
	{
		erase();
		assign(String.c_str());
		return *this;
	};

	sdpString& sdpString::operator=(SDPCSTRING String)
	{
		erase();
		if(String != 0)
			assign(String);
		return *this;
	};

	sdpString& sdpString::operator=(char Character)
	{
		erase();
		assign(1, Character);

		return *this;
	};

	// comparison (equality)
	bool sdpString::operator==(const sdpString& String) const
	{
		return compare(String.c_str()) == 0;
	}

	bool sdpString::operator==(const sdpStringBase& String) const
	{
		return compare(String.data()) == 0;
	}

	bool sdpString::operator==(SDPCSTRING String) const
	{
		return compare(String) == 0;
	}

	bool sdpString::operator==(char* String) const
	{
		return compare(String) == 0;
	}

	bool sdpString::operator==(char Character) const
	{
		return operator==(sdpStringBase(1, Character));
	}

	// comparison operators
	bool sdpString::operator!=(const sdpString& String) const
	{
	       return compare(String.c_str()) != 0;
	 }

	bool sdpString::operator!=(const sdpStringBase& String) const
	{
	       return compare(String.data()) != 0;
	}

	bool sdpString::operator!=(SDPCSTRING String) const
	{
	       return compare(String) != 0;
	}

	bool sdpString::operator!=(char* String) const
	{
	       return compare(String) != 0;
	}

	bool sdpString::operator!=(char Character) const
	{
	       return operator!=(sdpStringBase(1, Character));
	}

	bool operator < (const sdpString& String) const
	{
		return compare(String) < 0;
	}

	bool operator < (SDPCSTRING String) const
	{
		return compare(String) < 0;
	}

	// sdpString concatenation.
	const sdpString& sdpString::operator+=(const sdpString& String)
	{
		append(String);
		return *this;
	}

	const sdpString& sdpString::operator+=(const sdpStringBase& String)
	{
		append(String);
		return *this;
	}

	const sdpString& sdpString::operator+=(SDPCSTRING String)
	{
		if(String != 0)
			append(String);

		return *this;
	}

	const sdpString& sdpString::operator+=(char Character)
	{
		append(1, Character);
		return *this;
	}

	// sdpString addition functions
	friend sdpString operator+(const sdpString& String1, const sdpString& String2)
	{
		sdpString result(String1);
		return result.append(String2);
	}

	friend sdpString operator+(const sdpString& String, char Character)
	{
		sdpString result(String);
		return result.append(1, Character);
	}

	friend sdpString operator+(char Character, const sdpString& String)
	{
		sdpString result(1, Character);
		return result.append(String);
	}

	friend sdpString operator+(const sdpString& String1, SDPCSTRING String2)
	{
		sdpString result(String1);
		return result.append(String2);
	}

	friend sdpString operator+(SDPCSTRING String1, const sdpString& String2)
	{
		sdpString result(String1);
		return result.append(String2);
	}

	/// Casts to a C style string ...
	inline operator const char*() const { return c_str(); }
};

/// Converts any stream-serializeable type into an sdpString
template<class Type>
const sdpString sdpToString(const Type& Value)
{
	std::ostringstream stream;
	stream << Value;

	const sdpString result(stream.str());

	return result;
}

/// Specialization for converting bool to sdpString
inline const sdpString sdpToString(const bool Value)
{
	std::ostringstream stream;

/** \todo Update this when gcc 3.0 becomes ubiquitous
	stream << std::boolapha << Value;
*/

	stream << (Value ? "true" : "false");

	const sdpString result(stream.str());

	return result;
}

/// Converts an sdpString into any stream-serializeable type
template<class Type>
const Type sdpFromString(const sdpString Value, const Type& DefaultValue)
{
	Type result = DefaultValue;
	std::istringstream stream(Value.c_str());
	stream >> result;

	return result;
}

/// Specialization for converting sdpString to bool
inline const bool sdpFromString(const sdpString Value, const bool DefaultValue)
{
	bool result = DefaultValue;

	if(0 == Value.find("true"))
		result = true;
	else if(0 == Value.find("false"))
		result = false;

/** \todo Update this when gcc 3.0 becomes ubiquitous
	std::istringstream stream(Value.c_str());
	stream >> std::boolalpha >> result;
*/

	return result;
}

#endif // !SDPTYPES_H


