#include "cString.h"

#define min(a, b)  (((a) < (b)) ? (a) : (b)) 
/////////////////////////////////////////////////////////////////////
cString::cString(){
	String = NULL;
	Length = 0;
	Allocate = false;
}

cString::cString(long nSize){
	Length = nSize - 1;
	String = new char[Length + 1];
	String[Length] = '\0';
	Allocate = true;
}

cString::cString(char *nString){
	Length = strlen(nString);
	String = new char [Length + 1];
	String[Length] = '\0';
	Allocate = true;
	Copy(nString);
}

cString::cString(cString &A){
	Length = A.GetLength();
	String = new char [Length + 1];
	String[Length] = '\0';
	Allocate = true;
	Copy(A);
}

cString::~cString(){
	Destroy();
}
//////////////////////////////////////////////////////////////////////////
void cString::Create(long nSize){
	Destroy();
	Length = nSize - 1;
	String = new char[Length + 1];
	String[Length] = '\0';
	Allocate = true;
}
void cString::Create(char *nString){
	Destroy();
	Length = strlen(nString);
	String = new char [Length + 1];
	String[Length] = '\0';
	Allocate = true;
	Copy(nString);
}
void cString::Create(cString &A){
	Destroy();
	Length = A.GetLength();
	String = new char [Length + 1];
	String[Length] = '\0';
	Allocate = true;
	Copy(A);
}

void cString::Destroy(){
	if(Allocate){
		delete [] String;
	}
	String = NULL;
	Length = 0;
}

///////////////////////////////////////////
char *cString::Get(){
	return String;
}

/////////////////////////////// String as an Array
long cString::GetLength(){
	return Length;
}
char cString::Get(long i){
	return String[i];
}
void cString::Set(long i, int c){
	String[i] = c;
}

//////////////////////////////// Block Operation
void cString::Copy(char *nString){
	strncpy(String, nString, Length + 1);
}
void cString::Copy(cString &A){
	strncpy(String, A.String, min(Length + 1, A.Length + 1));
}
void cString::CopyAt(char *nString, int p, int n){
	strncpy(String + p, nString, n);
}
void cString::CopyAt(cString &A, int p, int n){
	strncpy(String + p, A.String, n);
}
/////////////////////////////// Expression
void cString::operator=(char *nString){
	Create(nString);
}
void cString::operator=(cString &A){
	Create(A);
}
cString cString::operator+(cString &A){
	cString t;
	t.Create(Length + A.Length + 1);
	t.Copy(*this);
	t.CopyAt(A, Length, A.Length);
	return t;
}
cString cString::operator+(char *A){
	long len = strlen(A);
	cString t;
	t.Create(Length + len + 1);
	t.Copy(*this);
	t.CopyAt(A, Length, len);
	return t;
}
cString operator+(char *s, cString &A){
	long len = strlen(s);
	cString t;
	t.Create(A.Length + len + 1);
	t.Copy(s);
	t.CopyAt(A, len, A.Length);
	return t;
}

void cString::operator+=(char *a){
	long len = strlen(a);
	cString t;

	t = *this;
	Create(Length + len + 1);
	Copy(t);
	CopyAt(a, t.Length, len);
}

void cString::operator+=(cString &A){
	cString t;

	t = *this;
	Create(Length + A.Length + 1);
	Copy(t);
	CopyAt(A, t.Length, A.Length);
}
/////////////////////////////////////// Extraction
cString cString::Middle(long p, long n){
	cString t(n + 1);
	strncpy(t.String, String + p, n);
    t.String[n] = '\0';
	return t;

}
cString cString::Left(long n){
	cString t(n + 1);
	strncpy(t.String, String, n);
	t.String[n] = '\0';
	return t;
}
cString cString::Right(long n){
	cString t(n + 1);
	strncpy(t.String, String + Length - n, n);
	t.String[n] = '\0';
	return t;
}

//////////////////////////////// Comparison
int cString::Compare(char *nString, bool Case){
	long len = strlen(nString);
	if(Length < len) return -1;
	if(Length > len) return 1;
	return strncmp(String, nString, Length);
//	return strncmpi(String, nString, Length);

}
int cString::Compare(cString &A, bool Case){
	return Compare(A.String, Case);
}
bool cString::operator==(char *nString){
	if(Compare(nString) == 0) return true;
	return false;
}
bool cString::operator==(cString &A){
	if(Compare(A) == 0) return true;
	return false;
}
////////////////////////////////////// Conversion
void cString::ToLower(){
	strlwr(String);
}
void cString::ToUpper(){
	strupr(String);
}
//////////////////////////////////// Searching
long cString::Find(int c, long p){
	char *ptr;
	ptr = strchr(String + p, c);
	if(ptr) return ptr - String;
	return -1;
}

long cString::Find(char *s, long p){
	char *ptr;
	ptr = strstr(String + p, s);
	if(ptr) return ptr - String;
	return -1;
}

long cString::Find(cString &A, long p){
	char *ptr;

	ptr = strstr(String + p, A.String);
	if(ptr) return ptr - String;
	return -1;
}
