/*
 * @(#)StringBuffer.cpp
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 *
 * Jörg Haeger, 22.04.2002
 */

#include <ctype.h>
#include <string.h>
#include "Error.h"
#include "Log.h"
#include "StringBuffer.h"

int StringBuffer::no = 0,
	StringBuffer::existing = 0,
	StringBuffer::existingTop = 100;

StringBuffer::StringBuffer(int size) {
	init();
	this->size = size;
	buf = new int[size];
	len = 0;
}

StringBuffer::StringBuffer(const StringBuffer &buffer) {
	init();
	size = buffer.size;
	buf = new int[size];
	len = 0;

	for (int i = 0; i < buffer.len; i++)
		append((char)buffer.buf[i]);
}

StringBuffer::StringBuffer(StringBuffer *buffer) {
	init();
	buf = buffer->buf;
	buffer->buf = NULL;

	len = buffer->len;
	size = buffer->size;

	delete buffer;
}

StringBuffer::StringBuffer(const char *str) {
	init();
	this->size = strlen(str);
	buf = new int[size];
	len = 0;

	append(str);
}

StringBuffer::~StringBuffer() {
	if (buf != NULL)
		delete[] buf;
	existing--;
}

StringBuffer &StringBuffer::operator=(StringBuffer *buffer) {
	int *oldBuf = buf;
	buf = buffer->buf;
	buffer->buf = oldBuf;

	len = buffer->len;
	size = buffer->size;

	delete buffer;
	return *this;
}

int StringBuffer::charAt(int index) const {
	if (index < 0 || index >= len)
		throw new Error("index out of bounds");

	return buf[index];
}

StringBuffer &StringBuffer::delete_(int start, int end) {
	for (int i = 0; i < len - end; i++)
		buf[start + i] = buf[end + i];

	if (end > len)
		len = start;
	else
		len -= end - start;

	return *this;
}

int StringBuffer::endsWith(const char *suffix) const {
	int offset = len - strlen(suffix);
	if (offset < 0)
		return 0;

	for (int i = offset; i < len; i++)
		if (suffix[i - offset] != buf[i])
			return 0;

	return 1;
}

int StringBuffer::equals(const char *str) const {
	int i;
	for (i = 0; i < len; i++)
		if (str[i] == 0)
			return 0;
		else if (str[i] != buf[i])
			return 0;

	return str[i] == 0;
}

int StringBuffer::equalsIgnoreCase(const char *str) const {
	int i;
	for (i = 0; i < len; i++)
		if (str[i] == 0)
			return 0;
		else if (toupper(str[i]) != toupper(buf[i]))
			return 0;

	return str[i] == 0;
}

int StringBuffer::indexOf(const char *str, int fromIndex) const {
	for (int i = fromIndex; i < len; i++)
		for (int j = i; ; j++)
			if (str[j - i] == 0)
				return i;
			else if (j == len)
				break;
			else if (buf[j] != str[j - i])
				break;

	return -1;
}

void StringBuffer::init() {
	no++;
	existing++;
	if (existing > existingTop) {
		existingTop = existing;
		log.putv("StringBuffer: no = %d existing = %d", no, existing);
	}
}

StringBuffer &StringBuffer::insert(int offset, char c) {
	if (len == size) {
		int *oldBuf = buf;
		size += 16;
		buf = new int[size];
		for (int i = 0; i < len; i++)
			buf[i] = oldBuf[i];
		delete[] oldBuf;
	}

	for (int i = len; i > offset; i--)
		buf[i] = buf[i - 1];

	buf[offset] = c;
	len++;
	return *this;
}

StringBuffer &StringBuffer::insert(int offset, int i) {
	if (i == 0)
		insert(offset, '0');
	else if (i < 0) {
		insert(offset++, '-');
		i = -i;
	}

	for (; i > 0; i /= 10)
		insert(offset, (char)('0' + i % 10));

	return *this;
}

StringBuffer &StringBuffer::insert(int offset, const char *str) {
	for (int i = 0; str[i] != 0; i++)
		insert(offset + i, str[i]);

	return *this;
}

StringBuffer &StringBuffer::insert(
		int index, const char *str, int offset, int len) {
	for (int i = 0; i < len; i++)
		insert(index + i, str[offset + i]);

	return *this;
}

int StringBuffer::startsWith(const char *prefix) const {
	for (int i = 0; i < len; i++)
		if (prefix[i] == 0)
			return 1;
		else if (prefix[i] != buf[i])
			return 0;

	return prefix[len] == 0;
}
