From 3fd6ce5b10fe6cee65c9cebe263c503ce3e5a24a Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Wed, 12 Sep 2018 11:44:34 -0400 Subject: [PATCH] Add string number functionality --- src/core/string.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/core/string.c b/src/core/string.c index 9475be4c..c963b0d5 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -107,8 +107,7 @@ const uint8_t *janet_cstring(const char *str) { #define BUFSIZE 64 static int32_t real_to_string_impl(uint8_t *buf, double x) { - /* Use 16 decimal places to ignore one ulp errors for now */ - int count = snprintf((char *) buf, BUFSIZE, "%.16gR", x); + int count = snprintf((char *) buf, BUFSIZE, "%.17gr", x); return (int32_t) count; } @@ -979,7 +978,54 @@ static int cfun_join(JanetArgs args) { out += chunklen; } JANET_RETURN_STRING(args, janet_string_end(buf)); +} +struct formatter { + const char *lead; + const char *f1; + const char *f2; +} formatters[] = { + {":g", "%g", "%.*g"}, + {":G", "%G", "%.*G"}, + {":e", "%e", "%.*e"}, + {":E", "%E", "%.*E"}, + {":f", "%f", "%.*f"}, + {":F", "%F", "%.*F"} +}; + +static int cfun_number(JanetArgs args) { + struct formatter fmter = formatters[0]; + char buf[100]; + double x; + int formatNargs = 1; + int32_t precision = 0; + JANET_MINARITY(args, 1); + JANET_MAXARITY(args, 4); + JANET_ARG_NUMBER(x, args, 0); + if (args.n >= 2) { + const uint8_t *flag; + JANET_ARG_SYMBOL(flag, args, 1); + for (int i = 0; i < 6; i++) { + struct formatter fmttest = formatters[i]; + if (!janet_cstrcmp(flag, fmttest.lead)) { + fmter = fmttest; + break; + } + } + } + + if (args.n >= 3) { + JANET_ARG_INTEGER(precision, args, 2); + formatNargs++; + } + + if (formatNargs == 1) { + snprintf(buf, sizeof(buf), fmter.f1, x); + } else if (formatNargs == 2) { + snprintf(buf, sizeof(buf), fmter.f2, precision, x); + } + + JANET_RETURN_CSTRING(args, buf); } static const JanetReg cfuns[] = { @@ -997,6 +1043,7 @@ static const JanetReg cfuns[] = { {"string.split", cfun_split}, {"string.check-set", cfun_checkset}, {"string.join", cfun_join}, + {"string.number", cfun_number}, {NULL, NULL} };