summaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-03-06 20:00:13 -0500
committerJakob Kaivo <jkk@ung.org>2019-03-06 20:00:13 -0500
commit7039de6a6731437647bf6f1c3b480766872ac077 (patch)
tree91b046242226997677af0e9ec64522e8a80caf68 /src/stdlib
parent813c3440d19d8bbbe8987013d9d7160454327faf (diff)
begin work on a common string-to-floating-point implementation
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/_strtod.h93
-rw-r--r--src/stdlib/strtod.c17
-rw-r--r--src/stdlib/strtof.c35
-rw-r--r--src/stdlib/strtold.c35
4 files changed, 170 insertions, 10 deletions
diff --git a/src/stdlib/_strtod.h b/src/stdlib/_strtod.h
new file mode 100644
index 00000000..05b8f318
--- /dev/null
+++ b/src/stdlib/_strtod.h
@@ -0,0 +1,93 @@
+ /* int iswide = (sizeof(*nptr) == sizeof(wchar_t)); */
+ /* void *start = (void*)nptr; */
+ (void)max; (void)min;
+ int sign = 0;
+ int overflow = 0;
+
+ /* skip leading whitespace */
+ while (isspace(*nptr)) {
+ nptr++;
+ }
+
+ /* get sign, if any */
+ if (*nptr == '+') {
+ sign = 1;
+ nptr++;
+ } else if (*nptr == '-') {
+ sign = -1;
+ nptr++;
+ }
+
+ #if defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__
+ /* check for NAN */
+ if (toupper(nptr[0]) == 'N' && toupper(nptr[2]) == 'A' && toupper(nptr[3]) == 'N') {
+ nptr += 3;
+
+ /* check for optional parenthesized n-char-sequence */
+ if (*nptr == '(') {
+ while (*nptr != ')') {
+ nptr++;
+ }
+ }
+
+ if (endptr) {
+ *endptr = (void*)(nptr + 1);
+ }
+ return nan;
+ }
+
+ /* check for INF or INFINITY */
+ if (toupper(nptr[0]) == 'I' && toupper(nptr[1]) == 'N' && toupper(nptr[2]) == 'F') {
+ if (endptr) {
+ if (toupper(nptr[3]) == 'I' && toupper(nptr[4]) == 'N' && toupper(nptr[5]) == 'I' && toupper(nptr[6]) == 'T' && toupper(nptr[7]) == 'Y') {
+ *endptr = (void*)(nptr + 8);
+ } else {
+ *endptr = (void*)(nptr + 4);
+ }
+ }
+ return inf;
+ }
+
+ /* check for hexadecimal form */
+ if (nptr[0] == '0' && toupper(nptr[1] == 'X')) {
+ return ret;
+ }
+ #endif
+
+ while (*nptr) {
+ int n = 0;
+ /* int c = iswide ? wctomb(*nptr) : *nptr; */
+
+ switch (*nptr) {
+ case '0': n = 0; break;
+ case '1': n = 1; break;
+ case '2': n = 2; break;
+ case '3': n = 3; break;
+ case '4': n = 4; break;
+ case '5': n = 5; break;
+ case '6': n = 6; break;
+ case '7': n = 7; break;
+ case '8': n = 8; break;
+ case '9': n = 9; break;
+ default: n = -1; break;
+ }
+
+ if (n < 0) {
+ if (endptr) {
+ *endptr = (void*)nptr;
+ }
+ break;
+ }
+
+ ret = (ret) + n;
+ nptr++;
+ }
+
+ if (overflow) {
+ errno = ERANGE;
+ ret = (sign < 0) ? -huge : huge;
+ } else {
+ if (sign < 0) {
+ ret *= -1;
+ }
+ }
diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c
index 4420b02e..ba6c9636 100644
--- a/src/stdlib/strtod.c
+++ b/src/stdlib/strtod.c
@@ -1,18 +1,23 @@
#include <stdlib.h>
+#include "ctype.h"
#include "errno.h"
+#include "float.h"
+#include "math.h"
/** convert string to floating-point **/
double strtod(const char * restrict nptr, char ** restrict endptr)
{
- (void)nptr; (void)endptr;
- /* TODO */
+ double ret = 0.0;
+ double max = DBL_MAX;
+ double min = DBL_MIN;
+ double inf = INFINITY;
+ double nan = NAN;
+ double huge = HUGE_VAL;
- if (0) {
- errno = ERANGE; /* converted value out of range */
- }
+ #include "_strtod.h"
- return 0.0;
+ return ret;
}
/***
diff --git a/src/stdlib/strtof.c b/src/stdlib/strtof.c
index 4056d578..2c8fc115 100644
--- a/src/stdlib/strtof.c
+++ b/src/stdlib/strtof.c
@@ -1,11 +1,42 @@
#include <stdlib.h>
+#include "float.h"
+#include "errno.h"
+#include "ctype.h"
+#include "math.h"
+
+/** convert string to floating-point **/
float strtof(const char * restrict nptr, char ** restrict endptr)
{
- (void)nptr; (void)endptr;
- return 0;
+ float ret = 0.0;
+ float max = FLT_MAX;
+ float min = FLT_MIN;
+ float huge = HUGE_VALF;
+ float inf = INFINITY;
+ float nan = NAN;
+
+ #include "_strtod.h"
+
+ return ret;
}
+/***
+converts the string at ARGUMENT(nptr) to a TYPE(float).
+Leading whitespace is ignored. The first character that is not a valid character
+for a floating-point constant and any characters after it are also ignored. A
+pointer to the first invalid character is stored in ARGUMENT(endptr), unless
+ARGUMENT(endptr) is CONSTANT(NULL).
+
+The converted portion of the string may start with an optional plus or minus
+sign, followed by a nonempty series of digits, optionally containing a
+decimal-point character. This may optionally be followed by an exponent.
+***/
+
/*
+LC_CTYPE
+RETURN(ZERO, underflow or no conversion could be performed)
+RETURN(CONSTANT(HUGE_VALF), converted value too large)
+RETURN(CONSTANT(-HUGE_VALF), converted value too small)
+RETURN(VAR(a TYPE(float)), the converted value)
STDC(199901)
*/
diff --git a/src/stdlib/strtold.c b/src/stdlib/strtold.c
index eeb0b8b0..eb19fcc0 100644
--- a/src/stdlib/strtold.c
+++ b/src/stdlib/strtold.c
@@ -1,11 +1,42 @@
#include <stdlib.h>
+#include "float.h"
+#include "ctype.h"
+#include "errno.h"
+#include "math.h"
+
+/** convert string to floating-point **/
long double strtold(const char * restrict nptr, char ** restrict endptr)
{
- (void)nptr; (void)endptr;
- return 0;
+ long double ret = 0.0;
+ long double max = LDBL_MAX;
+ long double min = LDBL_MIN;
+ long double huge = HUGE_VALL;
+ long double inf = INFINITY;
+ long double nan = NAN;
+
+ #include "_strtod.h"
+
+ return ret;
}
+/***
+converts the string at ARGUMENT(nptr) to a TYPE(double).
+Leading whitespace is ignored. The first character that is not a valid character
+for a floating-point constant and any characters after it are also ignored. A
+pointer to the first invalid character is stored in ARGUMENT(endptr), unless
+ARGUMENT(endptr) is CONSTANT(NULL).
+
+The converted portion of the string may start with an optional plus or minus
+sign, followed by a nonempty series of digits, optionally containing a
+decimal-point character. This may optionally be followed by an exponent.
+***/
+
/*
+LC_CTYPE
+RETURN(ZERO, underflow or no conversion could be performed)
+RETURN(CONSTANT(HUGE_VALL), converted value too large)
+RETURN(CONSTANT(-HUGE_VALL), converted value too small)
+RETURN(VAR(a TYPE(long double)), the converted value)
STDC(199901)
*/