/*
 * Copyright (c) 2005-2008 Darron M Broad
 * All rights reserved.
 *
 * Licensed under the terms of the GPL3 license, see file COPYING for details.
 */

#include "util.h"

/******************************************************************************
 * UTILITY CLASS
 *****************************************************************************/

/******************************************************************************
 * MATH
 *****************************************************************************/

/*
 * re-entrant rand (0..limit-1)
 *
 * man 3 rand_r:
 *	j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
 */
int
Util::rand(int limit)
{
	static unsigned int state= time(NULL);
	int r= rand_r(&state);
	int n= (int)(limit * (r / (RAND_MAX + 1.0)));

	return n;
}

/******************************************************************************
 * BIT
 *****************************************************************************/

/*
 * high byte of word
 */
unsigned char
Util::hb(unsigned short w)
{
	return (w >> 8);
}

/*
 * low byte of word
 */
unsigned char
Util::lb(unsigned short w)
{
	return (w & 0xFF);
}

/*
 * rotate byte left
 */
unsigned char
Util::rol(unsigned char x)
{
	unsigned short y = x << 1;
	return (y & 0xFE) | ( hb(y) & 0x01);
}

/******************************************************************************
 * C-STRING
 *****************************************************************************/

/*
 * strcasestr (missing in cygwin)
 */
const char *
Util::strcasestr(const char *haystack, const char *needle)
{
	unsigned int i, j;

	for(i=0; i<strlen(haystack); i++)
	{
		for(j=0; j<strlen(needle); j++)
		{
			if( tolower(haystack[i + j]) != tolower(needle[j]) )
				break;
		}
		if(j==strlen(needle))
		{
			return &haystack[i];
		}
	}
	return NULL;
}

/*
 * Trim string right
 */
char *
Util::rtrim(char *str)
{
	int l= strlen(str) - 1;

	while(l>=0 && str[l]=='\n' || str[l]==' ')
		str[l--]= '\0';

	return str;
}

/*
 * cstring to integer (base 10)
 */
int
Util::cstringToInt(const char *s)
{
	return strtol(s, NULL, 10);
}

/*
 * cstring to integer (any base)
 */
int
Util::cstringToInt(const char *s, int base)
{
	return strtol(s, NULL, base);
}

/*
 * cstring to double
 */
double
Util::cstringToDouble(const char *s)
{
	return strtod(s, NULL);
}

/*
 * readline from stdin
 */
char *
Util::readline(const char *prompt, char *&line)
{
	while(true)
	{
		line= ::readline(prompt);
		if(line == NULL)
			continue;

		if(line[0] == '\0')
		{
			free(line);
			continue;
		}

		break;
	}
	add_history(line);
	return line;
}

/******************************************************************************
 * STRING
 *****************************************************************************/

/*
 * Return prepended space to str1 if str2 is empty, else return str1 as-is
 */
string
Util::prependspace(string str1, string str2)
{
	if(str2.empty())
		return str1;
	return (string)" " + str1;
}

/*
 * integer to string (base 10)
 */
string
Util::intToString(int n)
{
	return(Util::intToString(n, 10));
}

/*
 * integer to string (any base)
 */
string
Util::intToString(int n, int base)
{
	string str="", sign="";
	char mod;

	if(n==0)
		return "0";
	if(n<0)
	{
		n= abs(n);
		sign="-";
	}
	while(n)
	{
		mod= '0' + (n % base);
		if(mod > '9')
			mod += ('A' - '9' - 1);
		str= mod + str;
		n /= base;
	}
	return sign + str;
}

/*
 * string to integer (base 10)
 */
int
Util::stringToInt(string s)
{
	return cstringToInt(s.c_str(), 10);
}

/*
 * string to integer (any base)
 */
int
Util::stringToInt(string s, int base)
{
	return cstringToInt(s.c_str(), base);
}

/*
 * string to double
 */
double
Util::stringToDouble(string s)
{
	return cstringToDouble(s.c_str());
}

