/*
 *  ppui/Tools.cpp
 *
 *  Copyright 2009 Peter Barth
 *
 *  This file is part of Milkytracker.
 *
 *  Milkytracker is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Milkytracker is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Tools.h"

const char PPTools::hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

pp_uint32 PPTools::getHexNumDigits(pp_uint32 value)
{
	if (value == 0 || (signed)value < 0)
		return 1;

	pp_uint32 i = 0;
	while (value >> i*4)
		i++;

	return i;
}

void PPTools::convertToHex(char* name, pp_uint32 value, pp_uint32 numDigits)
{
	pp_uint32 i;
	for (i = 0; i < numDigits; i++)
		name[i] = hex[((value>>(numDigits-1-i)*4)&0xF)];
	
	name[i] = 0;
}

pp_uint32 PPTools::getDecNumDigits(pp_uint32 value)
{
	if (value == 0)
		return 1;

	pp_uint32 i = 0;
	pp_uint32 start = 1;
	while (value / start)
	{
		i++;
		start*=10;
	}

	return i;
}

void PPTools::convertToDec(char* name, pp_uint32 value, pp_uint32 numDigits)
{
	pp_uint32 i;
	pp_uint32 start = 1;
	for (i = 0; i < numDigits-1; i++)
		start*=10;
		
	for (i = 0; i < numDigits; i++)
	{
		name[i] = hex[(value / start)%10];
		start/=10;
	}

	name[i] = 0;
}

// you're responsible for deleting this vector
PPSimpleVector<PPString>* PPTools::extractStringList(const PPString& str)
{
	PPSimpleVector<PPString>* stringList = new PPSimpleVector<PPString>();
	
	const char* sz = str;
	
	PPString* line = new PPString();
	
	while (*sz)
	{
		if (*sz == '\n')
		{
			stringList->add(line);
			line = new PPString();
		}
		else
		{
			line->append(*sz);
		}
		sz++;
	}
	
	if (!line->length())
		delete line;
	else
		stringList->add(line);
	
	return stringList;
}

PPString PPTools::encodeByteArray(const pp_uint8* array, pp_uint32 size)
{
	char buffer[10];
	
	// Convert number of bytes
	convertToHex(buffer, size, 8);
	
	PPString str = buffer;
	
	for (pp_uint32 i = 0; i < size; i++)
	{
		convertToHex(buffer, array[i], 2);
		str.append(buffer);
	}
	
	return str;
}

pp_uint8 PPTools::getNibble(const char* str)
{
	if (*str >= '0' && *str <= '9')
		return (*str - '0');
	if (*str >= 'A' && *str <= 'F')
		return (*str - 'A' + 10);
	if (*str >= 'a' && *str <= 'f')
		return (*str - 'a' + 10);
	
	return 0;
}

pp_uint8 PPTools::getByte(const char* str)
{
	return (getNibble(str)<<4) + getNibble(str+1);
}

pp_uint16 PPTools::getWord(const char* str)
{
	return (getByte(str)<<8) + getByte(str+2);
}

pp_uint32 PPTools::getDWord(const char* str)
{
	return (getWord(str)<<16) + getWord(str+4);
}

bool PPTools::decodeByteArray(pp_uint8* array, pp_uint32 size, const PPString& str)
{
	const char* ptr = str;
	
	pp_uint32 length = getDWord(ptr);
	
	if (length != size)
		return false;
	
	ptr+=8;
	
	for (pp_uint32 i = 0; i < length; i++)
	{
		*array++ = getByte(ptr);
		ptr+=2;
	}
	
	return true;
}

pp_int32 PPTools::clamp(pp_int32 a, pp_int32 min, pp_int32 max)
{
	return (a < min ? min : (a >= max ? max-1 : a));
}

