fmt_fp.c: remove fmt argument from mrb_float_to_str().

With major refactoring to prepare removing `snprintf(3) calls.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2021-05-20 10:54:35 +09:00
parent beaf365dd4
commit fa29bb3bb4
2 changed files with 31 additions and 64 deletions
+30 -26
View File
@@ -1,5 +1,12 @@
#include <mruby.h>
#if !defined(MRB_NO_FLOAT)
#include <string.h>
#ifndef MRB_NO_FLOAT
#ifdef MRB_USE_FLOAT32
#define FLO_TO_STR_PREC 7
#else
#define FLO_TO_STR_PREC 15
#endif
#if defined(MRB_NO_STDIO) || defined(_WIN32) || defined(_WIN64)
/*
@@ -410,21 +417,6 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
}
}
mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
struct fmt_args f;
mrb_value str = mrb_str_new_capa(mrb, 24);
f.mrb = mrb;
f.output = strcat_value;
f.opaque = (void*)&str;
if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
}
return str;
}
int
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
{
@@ -445,19 +437,31 @@ mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_fl
#else /* MRB_NO_STDIO || _WIN32 || _WIN64 */
#include <stdio.h>
mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
char buf[25];
snprintf(buf, sizeof(buf), fmt, mrb_float(flo));
return mrb_str_new_cstr(mrb, buf);
}
MRB_API int
int
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
{
return snprintf(buf, len, fmt, fval);
}
#endif /* MRB_NO_STDIO || _WIN32 || _WIN64 */
MRB_API mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo)
{
char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
char buf[25];
mrb_float_to_cstr(mrb, buf, sizeof(buf), fmt, mrb_float(flo));
for (char *p = buf; *p; p++) {
if (*p == '.') goto exit;
if (*p == 'e') {
memmove(p+2, p, strlen(p)+1);
memcpy(p, ".0", 2);
goto exit;
}
}
strcat(buf, ".0");
exit:
return mrb_str_new_cstr(mrb, buf);
}
#endif
+1 -38
View File
@@ -25,9 +25,7 @@
#define floor(f) floorf(f)
#define ceil(f) ceilf(f)
#define fmod(x,y) fmodf(x,y)
#define FLO_TO_STR_PREC 8
#else
#define FLO_TO_STR_PREC 16
#endif
#endif
@@ -303,49 +301,14 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
if (isinf(f)) {
str = f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
: mrb_str_new_lit(mrb, "Infinity");
goto exit;
}
else if (isnan(f)) {
str = mrb_str_new_lit(mrb, "NaN");
goto exit;
}
else {
char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
mrb_int len;
char *begp, *p, *endp;
str = mrb_float_to_str(mrb, flt, fmt);
insert_dot_zero:
begp = RSTRING_PTR(str);
len = RSTRING_LEN(str);
for (p = begp, endp = p + len; p < endp; ++p) {
if (*p == '.') {
goto exit;
}
else if (*p == 'e') {
ptrdiff_t e_pos = p - begp;
mrb_str_cat(mrb, str, ".0", 2);
p = RSTRING_PTR(str) + e_pos;
memmove(p + 2, p, len - e_pos);
memcpy(p, ".0", 2);
goto exit;
}
}
if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
--fmt[sizeof(fmt) - 3]; /* %.16g(%.8g) -> %.15g(%.7g) */
str = mrb_float_to_str(mrb, flt, fmt);
goto insert_dot_zero;
}
else {
mrb_str_cat(mrb, str, ".0", 2);
}
goto exit;
str = mrb_float_to_str(mrb, flt);
}
exit:
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}