/////////////////////////////////////////////////////////////////////////////
// File:        conversion.cpp
// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
//
//  This program 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.
//
//  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////

#include "spcore/conversion.h"

#include <locale.h>
#include <stdio.h>

namespace spcore {

/**
	Converts a string to a float value in a locale independent fashion
*/

static char g_decimal_point= 0;

// Assume that 100 is wide enough to hold a decimal number
#define MAX_NUMBER_SIZE 100

static inline 
int CopySubsts (const char* orig, char* dst)
{
	if (!g_decimal_point) g_decimal_point = *(localeconv()->decimal_point);

	// Copy & substs. Also manages buggy strings
	int i= 0;
	for (; i< MAX_NUMBER_SIZE; ++i) {
		if (orig[i]== 0) {
			dst[i]= 0;
			break;
		}
		if (orig[i]== '.') 	dst[i]= g_decimal_point;
		else if (orig[i]== ',') {
			// Use comma as separator
			dst[i]= 0;
			break;
		}
		else dst[i]= orig[i];
	}

	return i;
}


/**
	Converts a string into a float

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION
bool StrToFloat (const char* str, float* val)
{
	char dst[MAX_NUMBER_SIZE];
	
	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
		// Error, too long
		return false;

	return (sscanf(dst, "%g", val)== 1);
}

/**
	Converts a string into a double

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION
bool StrToDouble (const char* str, double* val)
{
	char dst[MAX_NUMBER_SIZE];
	
	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
		// Error, too long
		return false;

	return (sscanf(dst, "%lg", val)== 1);
}

/**
	Converts a string into a long double

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION
bool StrToLongDouble (const char* str, long double* val)
{
	char dst[MAX_NUMBER_SIZE];
	
	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
		// Error, too long
		return false;

	return (sscanf(dst, "%Lg", val)== 1);
}

/**
	Converts a string into a int

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION
bool StrToInt (const char* str, int* val)
{
	return (sscanf(str, "%d", val)== 1);
}

/**
	Converts a string into an unsigned int

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION 
bool StrToUint (const char* str, unsigned int* val)
{
	return (sscanf(str, "%u", val)== 1);
}

/**
	Converts a string into a long

	\return true is conversion successful, or false otherwise
*/
SPEXPORT_FUNCTION
bool StrToLongInt (const char* str, long* val)
{
	return (sscanf(str, "%ld", val)== 1);
}

} // namespace spcore
