/** * @file convert.c * @brief Implements strict string-to-number conversion over strtoll/strtod. */ #include #include #include #include #include #include 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); }