//#include "Hard Disk:CS1 Book:CS1 files:CS1 Ä:Strings.h" 
#include "Strngs.h"
#include "Error.h"
#include "Boolean.h"

String::String()
: 	_elements(new char[1])
{	if(_elements == NULL) userERROR("No more memory.");
	_elements[0] = '\0';
}

String::String(const char *s)
: 	_elements(new char[::strlen(s) +1])
{	if(_elements == NULL) userERROR("No more memory.");
	::strcpy(_elements, s);
}

String::String(const String &s)
{	copy(s);
}

String::String(unsigned long i)
: 	_elements(new char[12])
{	int j = 11;
	if(_elements == NULL) userERROR("No more memory.");
	if(i == 0)
	{	_elements[0] = '0';
		_elements[1] = '\0';
	}
	else
	{	_elements[j--] = '\0';
		while(i != 0 && j >= 0)
		{	_elements[j--] = '0' + i%10;
			i /= 10;
		}
		while(j>=0) _elements[j--] = ' ';
	}
}

String:: ~String(){ free();}

String & String::operator = (const String &s)
{	if(_elements != s._elements) 
	{	free();
		copy(s);
	}
	return *this;
}

String String::operator + (char c)
{	int oldlen = ::strlen(_elements);
	char * temp = new char[oldlen + 2];
	if(temp == NULL) userERROR("No more memory.");
	::strcpy(temp, _elements);
	temp[oldlen ] = c;
	temp[oldlen + 1] = '\0';
	String t(temp);
	delete [] temp;
	return t;
}

String String::operator + (const String &s)
{	int oldlen = ::strlen(_elements);
	int slen = s.length();
	char * temp = new char[oldlen + slen + 1];
	if(temp == NULL) userERROR("No more memory.");
	::strcpy(temp, _elements);
	::strcat(temp, s._elements);
	String t(temp);
	delete [] temp;
	return t;
}

String operator + (char c, const String &s)
{	int oldlen = ::strlen(s._elements);
	char * temp = new char[oldlen + 2];
	if(temp == NULL) userERROR("No more memory.");
	temp[0] = c;
	temp[1] = '\0';
	::strcat(temp, s._elements);
	String t(temp);
	delete [] temp;
	return t;
}

int String::operator == (const String &s)const
{	int i = 0;
	while(1)
		if(_elements[i] == '\0' && s._elements[i] == '\0') return true;
		else if(_elements[i] != s._elements[i]) return false;
		else i++;
	return true;
};

int String::operator != (const String &s)const
{	return !(*this==s);
};

int String::operator < (const String &s)const
{	int i = 0;
	while(1)
		if(_elements[i] == '\0' && s._elements[i] != '\0') return true;
		else if(s._elements[i] == '\0') return false;
		else if(_elements[i] > s._elements[i]) return false;
		else if(_elements[i] < s._elements[i]) return true;
		else i++;
	return true;
};

int String::length() const
{	return ::strlen(_elements);
}

char & String::operator [] (unsigned int i)
{	if(i < ::strlen(_elements))
		return _elements[i];
	userERROR ( "Subscript out of bounds in string.");
	return _elements[0];
}

String String::sub(unsigned int start, unsigned int len)
{	int i;
	char * result = new char[len+1];
	if(result == NULL) userERROR("No more memory.");
	for(i = 0; i < len; i++)
		result[i] = (*this)[start+i]; // error if out of bounds.
	result[len] = '\0';
	String t(result);
	delete [] result;
	return t;
}

int String::search(char what, unsigned int start)
{	int result = -1;
	if(start >= length()) return result;
	while(_elements[start] != '\0')
		if(_elements[start++] == what) return start - 1;
	return result;
}

/*
String:: operator const char*() const
{	char * result = new char [::strlen(_elements) + 1];
	if(result == NULL) userERROR("No more memory.");
	::strcpy(result, _elements);
	return result;
}
*/

char * String::value() const
{	char * result = new char [::strlen(_elements) + 1];
	if(result == NULL) userERROR("No more memory.");
	::strcpy(result, _elements);
	return result;
}

String& String::strip()
{	char* front = _elements;
	char* rear  = _elements + ::strlen(_elements) - 1;
	while(*front == ' ' || *front == '	')front++;
	while(*rear == ' ' || *rear == '	')rear--;
	char * newElements = new char [rear-front + 2];
	::strncpy(newElements, front, rear-front+1);
	newElements[rear-front+1] = '\0';
	delete [] _elements;
	_elements = newElements;
	return *this;
}

void String:: copy(const String& s)
{	_elements = new char[s.length() + 1];
	if(_elements == NULL) userERROR("No more memory.");
	::strcpy(_elements, s._elements);
}

void String:: free()
{	delete [] _elements;
}

istream& operator >>(istream& in, String& s)
{	s.free();
	s._elements = new char[133];
	if(s._elements == NULL) userERROR("No more memory.");
	in.get(s._elements,133);
	return in;
}

ostream& operator <<(ostream& os, const String& s)
{	os << s._elements;
	return os;
}
	


