/* $Id$ */

#include <cstdio>
#include <cstdarg>
#include "util.h"
#include "throw.h"
#include "intl.h"

std::string Util::Sanitize(const std::string s)
{
	std::string out;

	for (std::string::const_iterator i(s.begin()); i != s.end(); ++i)
	{
		if (*i == '"')
		{
			out += std::string("\"\"");
			continue;
		}

		if (*i >= 0x20 && *i < 0x7F)
		{
			out += std::string(1, *i);
			continue;
		}

		char buf[5];
		snprintf(buf, sizeof(buf), "\\x%02X", (unsigned char) *i);
		out += buf;
	}

	return out;
}

std::string Util::IntToStr(size_t i)
{
	char buf[8];
	snprintf(buf, sizeof(buf), "%u", (unsigned) i);
	return buf;
}

std::string Util::NextToken(std::string &s, const std::string &sep)
{
	size_t f;
	for (f = 0; f < s.size(); ++f)
		if (sep.find(s[f]) != sep.npos)
			break;

	std::string rs(s.substr(0, f));
	s.erase(0, f + 1);
	return rs;
}

unsigned char Util::FromHexOne(const char ch)
{
	if (ch >= '0' && ch <= '9')
		return ch - '0';

	if (ch >= 'A' && ch <= 'F')
		return ch - 'A' + 10;

	if (ch >= 'a' && ch <= 'f')
		return ch - 'a' + 10;

	Throw(_("Invalid hex char %02X"), ch);
}

unsigned char Util::FromHex(const std::string &s)
{
	return (FromHexOne(s[0]) << 4) | FromHexOne(s[1]);
}

std::string Util::StripDot(const std::string &s)
{
	std::string rs;
	for (std::string::const_iterator i(s.begin()); i != s.end(); ++i)
		if (*i != '.')
			rs += std::string(1, *i);
	return rs;
}

// function from http://stackoverflow.com/questions/10564491/function-to-calculate-a-crc16-checksum

unsigned short Util::Crc16(unsigned char *data, unsigned char size)
{
	unsigned char x;
	unsigned short crc = 0xFFFF;

	while (size--)
	{
		x = crc >> 8 ^ *data++;
		x ^= x >> 4;
		crc = (crc << 8) ^ ((unsigned short) (x << 12)) ^ ((unsigned short) (x <<5)) ^ ((unsigned short) x);
	}

	return crc;
}

std::string Util::Format(const char *fmt, ...)
{
	char buf[1024];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);

	return buf;
}
