/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#include <stdlib.h>
#include <blc_stdlib.h>

/** @addtogroup stdlib */
/** @{ */

/**
*	Convert a string to a double.
*
*	The function is identical in semantics to the strtode() function
*	except that it does not provide a feedback on overlow conditions.
*
*	@param	nptr	Pointer to the string to convert.
*	@param	eptr	Pointer to a location to store the address of the
*					first character that was not converted. NULL is allowed.
*
*	@return			The numeric result of the conversion, if it was successful,
*					the largest or smallest fload if there was an overflow
*					and 0, if there was a conversion error.
*/

double strtod( const char *nptr, char **eptr )
{
	return( strtode( nptr, eptr, (void *) 0 ) );
}

/**
*	Convert a string to double precision float number.
*
*	The function processes the string pointed by the \p nptr parameter.
*	Initial whitespace is skipped, then a possible '+' or '-' signum is
*	processed. Following that, if the string starts with 0x or 0X followed
*	by at least one hexadecimal digit, then a hexadecimal float conversion
*	takes place. The format of the hexadecimal float number is a sequence
*	if integer hexadecimal digits, an optional '.' followed by optional
*	hexadecimal fractional digits, followed by an optional 'p' or 'P'
*	exponent separator followed by an optional '+' or '-' exponent signum,
*	followed by a sequence of decimal digits. The hexadecimal integer and
*	fractinal digits are converted to a float point number in radix 16 and
*	the exponent is interpreted as a power of 2. Note that the integer
*	part of the mantissa can not be empty (it can be 0, but at least one
*	hexadecimal digit must be present before the radix point or the exponent).
*	If the number does not start with 0x, then a decimal conversion is
*	attempted. If the signum is followed by a sequence of decimal digits,
*	then it is the integer part of the mantissa. It can optionally followed
*	by a '.' optionally followed by more decimal digits, that form the
*	fractional part of the mantissa. The integer and fractional parts can't
*	both be empty. If the number start with the decimal radix point, then
*	the integer part of the mantissa is implicitely assumed to be 0.
*	The mantissa is possibly followed by 'e' or 'E', followed by an
*	optional '+' or '-', followed by a sequence of decimal digits.
*	The 'E' and the characters following it are the decimal exponent.
*	If the optional signum of the mantissa is followed by a case insensitive
*	string of NAN, then the conversion result is a NaN (which is unsigned).
*	If the string starts with INF, then the result will be a signed infinity.
*	In that case, the input is further consumed up until the word INFINITY
*	is found in full or the first character that doesn't match the word is
*	found.
*
*	If the \p eptr argument is not NULL, then a pointer to the first character
*	that was rejected will be stored at the location it points to. If there
*	was no conversion, then the original pointer to the string will be
*	stored.
*
*	If the conversion results in an overflow, then the returned value is
*	the largest (absolute value) number representable in an IEEE-754 double
*	is returned; in case of underflow the smallest such number is returned.
*
*	@param	nptr	Pointer to the string to convert.
*	@param	eptr	Pointer to a location to store the address of the
*					first character that was not converted. NULL is allowed.
*	@param	optr	Pointer to void (*)(void) function that will be called
*					if there was an uder- or overflow. NULL is allowed.
*					This facility can be used to implement errno in a
*					system dependent manner.
*
*	@return			The numeric result of the conversion, if it was successful,
*					and 0, if there was a conversion error.
*	@note
*			This function is not a standard library function.
*			Furthermore, the standard declares that in string representation
*			either INF or INFINITY is to signal infinity. This implementation
*			accepts any leading substring of INFINITY that is at least 3
*			characters long (i.e. INF or INFI or INFINIT are all accepted).
*/

double strtode( const char *nptr, char **eptr, void (*optr)( void ) )
{
BLC_S2F	stat;
int		retv;
char	*this = (char *) nptr;

	_blc_StrToFlt( &stat );

	while ( ! ( retv = (*stat.func)( &stat, *this++ ) ) );

	if ( retv < 0 ) {

		if ( eptr ) *eptr = (char *) nptr;
		return( 0.0 );
	}
	else {

		if ( eptr ) *eptr = this - retv;
		if ( stat.flag < 0 && optr ) (*optr)();
		return( stat.data.numb );
	}
}

/** @} */

