
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef _WINDOWS
#include <strings.h>
#endif
#include "jlstring.h"

JLString::JLString() {

	_str = NULL;
	_len = 0;
	_referenced = 0;
}

JLString::JLString(const JLString &s) {

	_str = NULL;
	_len = 0;
	SetString(s._str);
}

JLString::JLString(const char *c) {

	_len = 0;
	_str = NULL;
	SetString(c);
}

JLString::JLString(int argc_num, char **argv) {

	_str = argv[argc_num];
	_len = strlen(_str);
	_referenced = 1;
}

JLString::~JLString() {

	if (_str && !_referenced)
		delete _str;
}

char JLString::operator[](int i) const {

	if (i >= _len) {
		cerr << "Error in JLString::operator[]: subscript too large!"
			 << endl;
		exit(-1);
	}

	return _str[i];
}

JLString& JLString::SetString(const char *c) {

	if (_str && !_referenced)
		delete _str;

	if (c) {
		_len = strlen(c);
		_str = new char[_len + 1];
		strcpy(_str, c);
	}
	else {
		_len = 0;
		_str = NULL;
	}

	_referenced = 0;

	return *this;
}

int JLString::operator==(const JLString &s) const {

	if (_len != s._len)
		return 0;

	return !(strcmp(_str, s._str));
}

int JLString::operator!=(const JLString &s) const {

	if (_len != s._len)
		return 1;

	return (strcmp(_str, s._str) ? 1 : 0);
}

int JLString::operator==(const char *c) const {

	if (_len != int(strlen(c)))
		return 0;

	return !(strcmp(_str, c));
}

int JLString::operator!=(const char *c) const {

	if (_len != int(strlen(c)))
		return 1;

	return (strcmp(_str, c) ? 1 : 0);
}

int JLString::operator<(const JLString &s) const {

#ifndef _WINDOWS
	return ((strcasecmp(_str, s._str)) < 0);
#else
	return ((strcmp(_str, s._str)) < 0);
#endif
}

int JLString::operator>(const JLString &s) const {

#ifndef _WINDOWS
	return ((strcasecmp(_str, s._str)) > 0);
#else
	return ((strcmp(_str, s._str)) > 0);
#endif
}

JLString& JLString::operator+=(const char c) {


	if (!_str) {
		_str = new char[2];
		_str[0] = c;
		_str[1] = '\0';
		_len = 1;
		return *this;
	}

	char *tmp = new char[_len + 1 + 1];

	strcpy(tmp, _str);
	tmp[_len] = c;
	tmp[_len+1] = '\0';

	if (_str && !_referenced)
		delete _str;

	_str = tmp;
	_len++;

	return *this;
}

JLString& JLString::operator+=(const char *c) {

	if (!c)
		return *this;

	if (!_str)
		return SetString(c);

	char *tmp = new char[_len + strlen(c) + 1];

	strcpy(tmp, _str);
	strcpy(tmp + _len, c);

	SetString(tmp);

	return *this;
}

JLString& JLString::operator+=(const JLString &s) {

	if (s._str)
		*this += (s._str);

	return *this;
}

JLString JLString::operator+(const JLString &s2) {

	JLString s1(*this);
	s1 += s2;

	return s1;
}

JLString operator+(const char *c, JLString &s) {

	JLString tmp(c);
	tmp += s;

	return tmp;
}

JLString operator+(int i, JLString &s) {

	char *tmp = new char[s._len + 50];

	sprintf(tmp, "%d%s", i, s._str);
	JLString result(tmp);

	delete tmp;

	return result;
}

JLString operator+(JLString &s, int i) {

	char *tmp = new char[s._len + 50];

	sprintf(tmp, "%s%d", s._str, i);
	JLString result(tmp);

	delete tmp;

	return result;
}


JLString JLString::SubString(int begin, int end) const {

	JLString tmp;

	if ((begin < 0) || (begin > (int) _len) || (end > (int) _len) ||
		(end < 0) || (begin > end))
			return tmp;

	tmp._len = end-begin;
	tmp._str = new char[tmp._len + 1];

	for (int i=begin; i<end; i++)
		tmp._str[i-begin] = _str[i];

	tmp._str[tmp._len] = '\0';

	return tmp;
}

int JLString::IsAlpha() {

	for (int i=0; i<_len; i++)
		if (!isalpha(_str[i])) return 0;

	return 1;
}

int JLString::IsInt() {

	int start = 0;

	if (_str[0] == '-')
		start = 1;

	for (int i=start; i<_len; i++)
		if (!isdigit(_str[i])) return 0;

	return 1;
}

int JLString::IsFloat() {

	int decimal = 0;
	int start = 0;

	if (_str[0] == '-')
		start = 1;

	for (int i=start; i<_len; i++)
		if (_str[i] == '.') {
			if (decimal) return 0;
			decimal = 1;
		}
		else if (!isdigit(_str[i]))
			return 0;

	return 1;
}

int JLString::TryToEat(char c) {

	if ((_len < 1) || (_str[0] != c))
		return 0;

	*this = SubString(1, _len);

	return 1;
}

void JLString::EatUpTo(char c) {

	int ok = 0;

	while ((_len > 0) && (!ok)) {
		ok = (_str[0] == c);
		*this = SubString(1, _len);
	}
}

ostream& operator<<(ostream &co, const JLString &s) {

	if (s._str)
		co << s._str;

	return co;
}

istream& operator>>(istream &ci, JLString &s) {

	char buff[100], c;
	int bufflen = 0, ok = 1, beginning = 1;

	s = "";

	while (ok) {
		if (bufflen == 99) {
			buff[99] = 0;
			s += buff;
			bufflen = 0;
		}

		if (beginning)
			do
				ci.get(c);
			while (isspace(c) && !ci.eof());
		else
			ci.get(c);

		beginning = 0;

		buff[bufflen] = c;

		if (buff[bufflen] < ' ')
			ok = 0;
		else
			bufflen++;

		if (ci.eof())
			ok = 0;
	}

	if (bufflen) {
		buff[bufflen] = 0;
		s += buff;
		bufflen = 0;
	}

	return ci;
}
