66 lines
1.9 KiB
C
66 lines
1.9 KiB
C
|
|
/**
|
||
|
|
* @file convert.c
|
||
|
|
* @brief Implements strict string-to-number conversion over strtoll/strtod.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <errno.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include <akerror.h>
|
||
|
|
|
||
|
|
#include <akbasic/convert.h>
|
||
|
|
#include <akbasic/error.h>
|
||
|
|
|
||
|
|
akerr_ErrorContext *akbasic_str_to_int64(const char *str, int base, int64_t *dest)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
char *endptr = NULL;
|
||
|
|
long long result = 0;
|
||
|
|
|
||
|
|
FAIL_ZERO_RETURN(errctx, (str != NULL), AKERR_NULLPOINTER,
|
||
|
|
"NULL string in integer conversion");
|
||
|
|
FAIL_ZERO_RETURN(errctx, (dest != NULL), AKERR_NULLPOINTER,
|
||
|
|
"NULL destination in integer conversion");
|
||
|
|
|
||
|
|
errno = 0;
|
||
|
|
result = strtoll(str, &endptr, base);
|
||
|
|
|
||
|
|
/* No digits consumed at all. */
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (endptr == str), AKBASIC_ERR_VALUE,
|
||
|
|
"INTEGER CONVERSION ON '%s'", str);
|
||
|
|
/* Trailing junk. The whole lexeme must be the number. */
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (*endptr != '\0'), AKBASIC_ERR_VALUE,
|
||
|
|
"INTEGER CONVERSION ON '%s'", str);
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (errno == ERANGE), ERANGE,
|
||
|
|
"Integer literal '%s' is out of range", str);
|
||
|
|
|
||
|
|
*dest = (int64_t)result;
|
||
|
|
SUCCEED_RETURN(errctx);
|
||
|
|
}
|
||
|
|
|
||
|
|
akerr_ErrorContext *akbasic_str_to_double(const char *str, double *dest)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
char *endptr = NULL;
|
||
|
|
double result = 0.0;
|
||
|
|
|
||
|
|
FAIL_ZERO_RETURN(errctx, (str != NULL), AKERR_NULLPOINTER,
|
||
|
|
"NULL string in float conversion");
|
||
|
|
FAIL_ZERO_RETURN(errctx, (dest != NULL), AKERR_NULLPOINTER,
|
||
|
|
"NULL destination in float conversion");
|
||
|
|
|
||
|
|
errno = 0;
|
||
|
|
result = strtod(str, &endptr);
|
||
|
|
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (endptr == str), AKBASIC_ERR_VALUE,
|
||
|
|
"FLOAT CONVERSION ON '%s'", str);
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (*endptr != '\0'), AKBASIC_ERR_VALUE,
|
||
|
|
"FLOAT CONVERSION ON '%s'", str);
|
||
|
|
FAIL_NONZERO_RETURN(errctx, (errno == ERANGE), ERANGE,
|
||
|
|
"Float literal '%s' is out of range", str);
|
||
|
|
|
||
|
|
*dest = result;
|
||
|
|
SUCCEED_RETURN(errctx);
|
||
|
|
}
|