/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	String.cpp
 *
 *****************************************************************************/

// SOL++2000
// 1999.09.03 Added a constructor String.
// 2000/11/11

#include <sol\String.h>
#include <sol\OutOfMemoryException.h>

#include <sol\NullPointerException.h>

 
BOOL String::copy(const char* string)
{
	BOOL rc = FALSE;
    char* temp = new char[len+1];
	if(temp) {
		strcpy(temp, string);
		if(text == string) { 
			delete [] text;
		}
		text = temp;
		rc = TRUE;
	}
	return rc;
}


String::String(const char* string)
	:len(0),
	text(NULL) 
{	 
	const char* str = "";
	if(string) {
		str = string;
	}

    len = strlen(str);
    text = NULL;
    BOOL rc = copy(str);
	if(rc == FALSE) {
		throw OutOfMemoryException("Failed to create a string");
	}
}

// 1999.09.03 Added
String::String(const String* string)
	:len(0),
	text(NULL) 
{	 
	const char* str = "";
	if(string) {
		str = string->getContents();
	}
	if (str == null) {
		str = "";
	}

    len = strlen(str);
    text = NULL;
    BOOL rc = copy(str);
	if(rc == FALSE) {
		throw OutOfMemoryException("Failed to create a string");
	}
}

String::String(const String& string)
	:len(0),
	text(NULL)
{
    len = string.getLength();
    text = NULL;
	BOOL rc = copy(string.getContents());  

	if(rc == FALSE) {
		throw OutOfMemoryException("Failed to create a string");
	}	
}


String& String::operator=(const char* string)
{ 
	const char* str = "";       
	if(string) {
		str = string;
	}

    len = strlen(str);
    BOOL rc = copy(str);
	if(rc == FALSE) {
		throw OutOfMemoryException("Failed to substitue a string");
	}
    return *this;
}


String& String::operator=(const String& string)
{        
    len = string.getLength();
    BOOL rc = copy(string.getContents());
	if(rc == FALSE) {
		throw OutOfMemoryException("Failed to substitue a string");
	}
    return *this;
}


int String::operator==(const char* string)
{
	if(string == NULL) {
		return 0;		
	}

    if(strcmp(text, string) == 0)
        return 1;
    else 
        return 0;
}


int String::operator==(String& string)
{
    if(strcmp(text, (const char*)string) == 0)
        return 1;
    else 
        return 0;
}


String& String::operator+(const char* string)
{
	if(string == NULL) {
		return *this;
	}

    len += strlen(string);
    char* temp = new char[len+1];
    strcpy(temp, text);
    strcat(temp, string);
    if(text != string) {
        delete [] text;
    }
    text = temp;
    return *this;
}


int String::compare(Object* object)
{
	String* string = (String*)object;
	char* p1 = text;
	char* p2 = "";
	if (string) {
		p2 = (char*)(*string);
	}
	return strcmp(p1, p2);
}


const char* String::find(const char* string)
{
	const char* ptr = null;
	if (text && string) {
		ptr = strstr(text, string);
	}
	return ptr;
}


int String::replace(char oc, char nc)
{
	int	n = 0;
	if (text) {
		for (int i = 0; i<len; i++) {
			if (text[i] == oc) {
				text[i] = nc;
				n++;
			}
		}
	}
	return n;
}

//<added date="2000/11/10">
String& String::operator+(char ch)
{
	char string[80];
	sprintf(string, "%c", ch);
	return String::operator+(string);
}

String& String::operator+(int num)
{
	char string[80];
	sprintf(string, "%d", num);
	return String::operator+(string);
}

String& String::operator+(float num)
{
	char string[80];
	sprintf(string, "%f", num);
	return String::operator+(string);
}

void String::trim()
{
	if (text == NULL) {
		return;
	}

	char* ptr = text;
	while (*ptr == ' ' || *ptr == '\t' || 
		*ptr == '\r' || *ptr == '\n') {
		ptr++;
	}

	/*
	if (temp == NULL) {
		return;
	}
	*/
	char* temp = ptr;
	int len = strlen(temp);
	ptr = temp + len-1;

	while (*ptr == ' ' || *ptr == '\t' || 
		*ptr == '\r' || *ptr == '\n') {
		if (ptr <= temp) {
			break;
		}
		*ptr = Zero;
		ptr--;
	}

	len = strlen(temp);
	if (temp != text) {
		memcpy(text, temp, len);
		text[len] = Zero;
		/*
		char* nstring = new char[len+1];
		strcpy(nstring, temp);
		delete [] text;
		text = nstring;
		*/
	}
}


Boolean String::startsWith(const char* string)
{
	Boolean rc = False;
	if (text != null && string != null) {
		int tlen = strlen(text);
		int slen = strlen(string);
		if (tlen >= slen) {
			int  r = strncmp(text, string, slen);	
			if (r == 0) {
				rc = True;
			}
		}
	}
	return rc;
}


Boolean String::endsWith(const char* string)
{
	Boolean rc = False;
	if (text != null && string != null) {
		int tlen = strlen(text);
		int slen = strlen(string);
		if (tlen >= slen) {
			int  r = strncmp(text+tlen-slen, 
							string, slen);	
			if (r == 0) {
				rc = True;
			}
		}
	}
	return rc;
}

const char* String::findLast(const char* string)
{
	const char* ptr = null;

	if (text && string) {
		int tlen = strlen(text);
		int slen = strlen(string);
		if (tlen < slen) {
			return ptr;
		} else {
			for(int i = tlen - slen; i>=0; i--) {
				int n= strncmp(text + i, string, slen);
				if (n == 0) {
					ptr = text + i;
					break;
				}
			}
		}	
	}
	return ptr;
}


Boolean String::equalsIgnoreCase(const char* string)
{
	Boolean rc = False;

	if (text == null && string == null) {
		return True;
	}

	if(text == null || string == null) {
		return False;		
	}

    if(strcmpi(text, string) == 0) {
       rc = True;
	}
	return rc;
}


Boolean String::equalsIgnoreCase(String& string)
{
	Boolean rc = False;
	if (text == null && ((const char*)string) == null) {
		return True;	
	}

	if (text == null || ((const char*)string) == null) {
		return False;	
	}

    if(strcmpi(text, (const char*)string) == 0) {
		rc = True;
	}
	return rc;
}


char&    String::operator[](int n) 
{
	if (text != null && n >= 0 && n <len) {
		return text[n]; 
	} else {
		throw NullPointerException("String::operator[] - Text is null");
	}
}
