/*
	Twilight Prophecy 3D/Multimedia SDK
	A multi-platform development system for virtual reality and multimedia.

	Copyright (C) 1997-2001 by Twilight 3D Finland Oy Ltd.

	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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	Please read the file LICENSE.TXT for additional details.


	source:
		string

	revision history:
		Jun/10/2000 - Thomas Mannfred Carlsson - initial revision
		Jan/24/2001 - Jukka Liimatta - renaissance build
*/
#include <stdio.h>
#include <prcore/prcore.hpp>
using namespace prcore;



//////////////////////////////////////////////////////
// pro                                             //
////////////////////////////////////////////////////

static inline int pro_strlen(const char* text)
{
	const char* s;

	for ( s = text; *s; s++ );
	return (int)s - (int)text;
}


static inline void pro_strcpy(char* dest, const String& string, const char* s2, int length2)
{
	const char* s1 = string;
	int length1 = string.GetLength();

	int i;
	for ( i=0; i<length1; i++ )
		*dest++ = *s1++;

	for ( i=0; i<length2; i++ )
		*dest++ = *s2++;

	*dest = 0;
}


//////////////////////////////////////////////////////
// String                                          //
////////////////////////////////////////////////////

String::String()
{
	mData = new char[1];
	mData[0] = 0;
	mLength = 0;
}


String::String(const String& str)
{
	mData = new char[ str.mLength + 1 ];
	mLength = str.mLength;

	memcpy( mData, str.mData, str.mLength + 1 );
}


String::String(const char* text)
{
	if ( !text )
	{
		mData = new char[1];
		mData[0] = 0;
		mLength = 0;
		return;
	}

	int length = pro_strlen(text);

	mData = new char[ length + 1 ];
	mLength = length;

	memcpy( mData, text, length + 1 );
}


String::~String()
{
	delete[] mData;
}


String& String::operator << ( const short s )
{
	char n[8];
	sprintf(n,"%d",(int)s);
	return operator += ( (char*) n );
}


String& String::operator << ( const unsigned short s )
{
	char n[8];
	sprintf(n,"%u",(unsigned int)s);
	return operator += ( (char*) n );
}


String& String::operator << ( const int i )
{
	char n[16];
	sprintf(n,"%d",(int)i);
	return operator += ( (char*) n );
}


String& String::operator << ( const unsigned int i )
{
	char n[16];
	sprintf(n,"%u",(unsigned int)i);
	return operator += ( (char*) n );
}


String& String::operator << ( const long l )
{
	char n[16];
	sprintf(n,"%d",(int)l);
	return operator += ( (char*) n );
}


String& String::operator << ( const unsigned long l )
{
	char n[16];
	sprintf(n,"%u",(unsigned int)l);
	return operator += ( (char*) n );
}


String& String::operator << ( const float f )
{
	PrintText( "%f.3", f );
	return *this;
}


void String::operator = (const String& str)
{
	if ( mLength != str.mLength )
	{
		delete[] mData;
		mData = new char[ str.mLength + 1 ];
		mLength = str.mLength;
	}

	memcpy( mData, str.mData, str.mLength + 1 );
}


void String::operator = (const char* text)
{
	if ( !text )
		return;

	int length = pro_strlen( text );

	if ( mLength != length )
	{
		delete[] mData;
		mData = new char[ length + 1 ];
		mLength = length;
	}

	memcpy( mData, text, length + 1 );
}


String String::operator + (const String& string) const
{
	int length = mLength + string.mLength;
	char* data = new char[ length + 1 ];

	pro_strcpy(data,*this,string.mData,string.mLength);

	String s;
	s.mLength = length;
	s.mData = data;

	return s;
}


String String::operator + (const char* text) const
{
	int slen = pro_strlen(text);
	int length = mLength + slen;
	char* data = new char[ length + 1 ];

	pro_strcpy(data,*this,text,slen);

	String string;
	string.mData = data;
	string.mLength = length;

	return string;
}


String& String::operator += (const String& string)
{
	int length = mLength + string.mLength;
	char* data = new char[ length + 1 ];

	pro_strcpy(data,*this,string.mData,string.mLength);

	delete[] mData;
	mData = data;
	mLength = length;

	return *this;
}


String& String::operator += (const char* text)
{
	int slen = pro_strlen(text);
	int length = mLength + slen;
	char* data = new char[ length + 1 ];

	pro_strcpy(data,*this,text,slen);

	delete[] mData;
	mData = data;
	mLength = length;

	return *this;
}


bool String::operator == (const String& string) const
{
	if ( mLength != string.mLength )
		return false;

	const char* s1 = mData;
	const char* s2 = string.mData;
	int count = string.mLength;

	while ( count-- )
	{
		if ( *s1++ != *s2++ )
			return false;
	}
	return true;
}


bool String::operator == (const char* text) const
{
	const char* s1 = mData;

	while ( *s1 == *text++ )
	{
		if ( *s1++ == 0 )
			return true;
	}
	return false;
}


bool String::operator != (const String& string) const
{
	if ( mLength != string.mLength )
		return true;

	const char* s1 = mData;
	const char* s2 = string.mData;
	int count = string.mLength;

	while ( count-- )
	{
		if ( *s1++ == *s2++ )
			return false;
	}
	return true;
}


bool String::operator != (const char* text) const
{
	const char* s1 = mData;
	const char* s2 = text;

	while ( *s1 == *s2++ )
	{
		if ( *s1++ == 0 )
			return false;
	}
	return true;
}


void String::PrintText(const char* text, ...)
{
	assert( text == NULL );

    // WARNING: This buffer is overflowable - do not use Print() as-is
	// in a security-critical environment for blind processing of user input.
    va_list argList;
	char tBuf[256];

    va_start(argList, text) ;
    vsprintf(tBuf, text, argList);
    va_end(argList);

	operator += ( (char*) tBuf );
}
