#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#include "cstring.h"
//#include "csource.h"

cString::cString (): 
		cShared (),
		StringLen(0) {
}

cString::cString (const cString &src): 
		cShared (src),
		StringLen(src.StringLen) {
}

cString::cString (const char *src) {
	set(src);
}

cString::cString (char src) {
	set(src);
}

cString::~cString () {
}

void cString::release(uint newsize) {
	StringLen = newsize;
	cShared::release(StringLen + 1);
	buffer()[StringLen] = 0;
}

void cString::clear() {
	cShared::clear();
	StringLen = 0;
}

void cString::set(const cString &src) {
	cShared::Set(src);
	StringLen = src.StringLen;
}

void cString::set (const char *src) {
	StringLen = strlen(src);
	allocate(StringLen + 1);

	memcpy(buffer(), src, StringLen);
	buffer()[StringLen] = 0;
}

void cString::set (char src) {
	StringLen = 1;
	allocate(StringLen + 1);

	buffer()[0] = src;
	buffer()[1] = 0;
}

void cString::append(const cString &src) {
	allocate(StringLen + src.StringLen + 1, true);

	memcpy(buffer() + StringLen, src.buffer(), src.StringLen);
	StringLen += src.StringLen;
	buffer()[StringLen] = 0;
}

void cString::append(const char *src) {
	uint len = strlen(src);
	allocate(StringLen + len + 1, true);

	memcpy(buffer() + StringLen, src, len);
	StringLen += len;
	buffer()[StringLen] = 0;
}

void cString::append(char src) {
	allocate(StringLen + 2, true);

	buffer()[StringLen] = src;
	++StringLen;
	buffer()[StringLen] = 0;
}

void cString::prepend(const cString &src) {
	allocate(StringLen + src.StringLen + 1, true);

	memmove(buffer() + src.StringLen, buffer(), StringLen);
	memcpy(buffer(), src.buffer(), src.StringLen);
	StringLen += src.StringLen;
	buffer()[StringLen] = 0;
}

void cString::prepend(const char *src) {
	uint len = strlen(src);
	allocate(StringLen + len + 1, true);

	memmove(buffer() + len, buffer(), StringLen);
	memcpy(buffer(), src, len);
	StringLen += len;
	buffer()[StringLen] = 0;
}

void cString::prepend(char src) {
	allocate(StringLen + 2, true);

	memmove(buffer() + 1, buffer(), StringLen);
	buffer()[0] = src;
	buffer()[++StringLen] = 0;
}

cString cString::left(uint count) const {
	if (count > StringLen)
		count = StringLen;

	cString ret;
	ret.allocate(count + 1);
	memcpy(ret.buffer(), buffer(), count);
	ret.buffer()[count] = 0;
	ret.StringLen = count;
	return ret;
}

cString cString::right(uint count) const {
	if (count > StringLen)
		count = StringLen;

	cString ret;
	ret.allocate(count + 1);
	memcpy(ret.buffer(), buffer() + StringLen - count, count);
	ret.buffer()[count] = 0;
	ret.StringLen = count;
	return ret;
}

cString cString::mid(int idx, uint count /* = -1 */) const {
	if (idx < 0)
		idx = StringLen + idx;

	if (((int)count == -1) || (count > StringLen - idx))
		count = StringLen - idx;

	cString ret;
	ret.allocate(count + 1);
	memcpy(ret.buffer(), buffer() + idx, count);
	ret.buffer()[count] = 0;
	ret.StringLen = count;
	return ret;
}

int cString::Find (const cString &String, uint Offset) const {
	if (Offset >= StringLen)
		return -1;

	char *pos = strstr(buffer() + Offset, String.buffer());
	if (pos) return (pos - buffer());
	else     return -1;
}

int cString::Find (const char *String, uint Offset) const {
	if (Offset >= StringLen)
		return -1;

	char *pos = strstr(buffer() + Offset, String);
	if (pos) return (pos - buffer());
	else     return -1;
}

int cString::Find (char Character, uint Offset) const {
	if (Offset >= StringLen)
		return -1;

	char *pos = strchr(buffer() + Offset, Character);
	if (pos) return (pos - buffer());
	else     return -1;
}

void cString::format (const char *fmt, ...) {
	int n, size = 128;
	va_list ap;

	char *buf = buffer(size);

	while (1) {
		va_start(ap, fmt);
		n = vsnprintf(buf, size, fmt, ap);
		va_end(ap);

		if ((n > -1) && (n < size))
			break;

		if (n > -1)
			size = n + 1;
		else
			size *= 2;

		buf = buffer(size);
	}
	release(n);
}

void cString::format(const cString &fmt, ...) {
	int n, size = 128;
	va_list ap;

	char *buf = buffer(size);

	while (1) {
		va_start(ap, &fmt);
		n = vsnprintf(buf, size, fmt, ap);
		va_end(ap);

		if ((n > -1) && (n < size))
			break;

		if (n > -1)
			size = n + 1;
		else
			size *= 2;

		buf = buffer(size);
	}
	release(n);
}

		
