mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-11 23:07:36 +02:00
Do not automatically convert floats to ints
This commit is contained in:
parent
16c1f8c885
commit
655b56e390
1 changed files with 65 additions and 6 deletions
71
runtime.c
71
runtime.c
|
@ -13,6 +13,8 @@
|
|||
#include "cyclone/types.h"
|
||||
#include "cyclone/runtime.h"
|
||||
#include "cyclone/ck_ht_hash.h"
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
//#include <signal.h> // TODO: only used for debugging!
|
||||
|
||||
//int JAE_DEBUG = 0;
|
||||
|
@ -1349,21 +1351,78 @@ object Cyc_string2number2_(void *data, object cont, int argc, object str, ...)
|
|||
Cyc_string2number_(data, cont, str);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
STR2INT_SUCCESS,
|
||||
STR2INT_OVERFLOW,
|
||||
STR2INT_UNDERFLOW,
|
||||
STR2INT_INCONVERTIBLE
|
||||
} str2int_errno;
|
||||
|
||||
/*
|
||||
Convert string s to int out.
|
||||
|
||||
@param[out] out The converted int. Cannot be NULL.
|
||||
|
||||
@param[in] s Input string to be converted.
|
||||
|
||||
The format is the same as strtol,
|
||||
except that the following are inconvertible:
|
||||
|
||||
- empty string
|
||||
- leading whitespace
|
||||
- any trailing characters that are not part of the number
|
||||
|
||||
Cannot be NULL.
|
||||
|
||||
@param[in] base Base to interpret string in. Same range as strtol (2 to 36).
|
||||
|
||||
@return Indicates if the operation succeeded, or why it failed.
|
||||
*/
|
||||
str2int_errno str2int(int *out, char *s, int base)
|
||||
{
|
||||
char *end;
|
||||
if (s[0] == '\0' || isspace((unsigned char) s[0]))
|
||||
return STR2INT_INCONVERTIBLE;
|
||||
errno = 0;
|
||||
long l = strtol(s, &end, base);
|
||||
/* Both checks are needed because INT_MAX == LONG_MAX is possible. */
|
||||
if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
|
||||
return STR2INT_OVERFLOW;
|
||||
if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
|
||||
return STR2INT_UNDERFLOW;
|
||||
if (*end != '\0')
|
||||
return STR2INT_INCONVERTIBLE;
|
||||
*out = l;
|
||||
return STR2INT_SUCCESS;
|
||||
}
|
||||
|
||||
int str2double(double *out, char *s)
|
||||
{
|
||||
*out = strtold(s, NULL);
|
||||
// TODO: error checking, EG: HUGE_VALL
|
||||
return 0;
|
||||
}
|
||||
|
||||
object Cyc_string2number_(void *data, object cont, object str)
|
||||
{
|
||||
int result;
|
||||
int result, rv;
|
||||
long l;
|
||||
double n;
|
||||
char *s, *end;
|
||||
Cyc_check_obj(data, string_tag, str);
|
||||
Cyc_check_str(data, str);
|
||||
if (type_of(str) == string_tag && ((string_type *) str)->str) {
|
||||
n = atof(((string_type *) str)->str);
|
||||
s = ((string_type *) str)->str;
|
||||
|
||||
if (ceilf(n) == n) {
|
||||
result = (int)n;
|
||||
rv = str2int(&result, s, 10);
|
||||
if (rv == STR2INT_SUCCESS) {
|
||||
return_closcall1(data, cont, obj_int2obj(result));
|
||||
} else {
|
||||
make_double(result, n);
|
||||
return_closcall1(data, cont, &result);
|
||||
str2double(&n, s);
|
||||
{
|
||||
make_double(result, n);
|
||||
return_closcall1(data, cont, &result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: not good enough because we do pointer comparisons to #f
|
||||
|
|
Loading…
Add table
Reference in a new issue