diff options
| -rw-r--r-- | include/mruby/numeric.h | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 83 | ||||
| -rw-r--r-- | src/fmt_fp.c | 79 |
3 files changed, 47 insertions, 117 deletions
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 8f8635189..4e3e8976a 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -171,8 +171,6 @@ int mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec /* obsolete functions; will be removed */ #define mrb_flo_to_fixnum(mrb, val) mrb_float_to_integer(mrb, val) #define mrb_to_flo(mrb, x) mrb_as_float(mrb, x) -/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */ -int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f); #endif /* MRB_NO_FLOAT */ diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index de8dbc513..2e6cec803 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -21,9 +21,6 @@ #define EXTENDSIGN(n, l) (((~0U << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0U << (n))) mrb_value mrb_str_format(mrb_state *, mrb_int, const mrb_value *, mrb_value); -#ifndef MRB_NO_FLOAT -static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int); -#endif static char* remove_sign_bits(char *str, int base) @@ -133,7 +130,52 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) #define FPREC 64 #define FPREC0 128 -#define CHECK(l) do {\ +#ifndef MRB_NO_FLOAT +static int +fmt_float(char *buf, size_t buf_size, char fmt, int flags, mrb_int width, mrb_int prec, mrb_float f) +{ + char sign = '\0'; + int left_align = 0; + int zero_pad = 0; + + if (flags & FSHARP) fmt |= 0x80; + if (flags & FPLUS) sign = '+'; + if (flags & FMINUS) left_align = 1; + if (flags & FZERO) zero_pad = 1; + if (flags & FSPACE) sign = ' '; + + int len = mrb_format_float(f, buf, buf_size, fmt, prec, sign); + + // buf[0] < '0' returns true if the first character is space, + or - + // buf[1] < '9' matches a digit, and doesn't match when we get back +nan or +inf + if (buf[0] < '0' && buf[1] <= '9' && zero_pad) { + buf++; + width--; + len--; + } + if (*buf < '0' || *buf >= '9') { + // For inf or nan, we don't want to zero pad. + zero_pad = 0; + } + if (len >= width) { + return len; + } + buf[width] = '\0'; + if (left_align) { + memset(&buf[len], ' ', width - len); + return width; + } + memmove(&buf[width - len], buf, len); + if (zero_pad) { + memset(buf, '0', width - len); + } else { + memset(buf, ' ', width - len); + } + return width; +} +#endif + +#define CHECK(l) do { \ while ((l) >= bsiz - blen) {\ if (bsiz > MRB_INT_MAX/2) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \ bsiz*=2;\ @@ -1052,7 +1094,6 @@ retry: mrb_value val = GETARG(); double fval; mrb_int need = 6; - char fbuf[64]; fval = mrb_as_float(mrb, val); if (!isfinite(fval)) { @@ -1114,8 +1155,7 @@ retry: need += 20; CHECK(need); - fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); - n = mrb_float_to_cstr(mrb, &buf[blen], need, fbuf, fval); + n = fmt_float(&buf[blen], need, *p, flags, width, prec, fval); if (n < 0 || n >= need) { mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error"); } @@ -1142,35 +1182,6 @@ retry: return result; } -#ifndef MRB_NO_FLOAT -static void -fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec) -{ - char *end = buf + size; - int n; - - *buf++ = '%'; - if (flags & FSHARP) *buf++ = '#'; - if (flags & FPLUS) *buf++ = '+'; - if (flags & FMINUS) *buf++ = '-'; - if (flags & FZERO) *buf++ = '0'; - if (flags & FSPACE) *buf++ = ' '; - - if (flags & FWIDTH) { - n = mrb_int2str(buf, end - buf, width); - buf += n; - } - - if (flags & FPREC) { - *buf ++ = '.'; - n = mrb_int2str(buf, end - buf, prec); - buf += n; - } - - *buf++ = c; - *buf = '\0'; -} -#endif void mrb_mruby_sprintf_gem_init(mrb_state *mrb) diff --git a/src/fmt_fp.c b/src/fmt_fp.c index 50abe3747..bfc0c82a6 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -365,85 +365,6 @@ mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, ch } -int -mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t buf_size, const char *fmt, mrb_float f) -{ - const char *s = fmt; - char sign = '\0'; - int alt_form = 0; - int left_align = 0; - int zero_pad = 0; - int width = -1; - int prec = 6; - - s++; // skip % - - while (*s) { - if (*s == '-') { - left_align = 1; - } else if (*s == '+') { - sign = '+'; - } else if (*s == ' ') { - sign = ' '; - } else if (*s == '0') { - zero_pad = 1; - } else if (*s == '#') { - alt_form = 1; - } else { - break; - } - s++; - } - if (ISDIGIT(*s)) { - char *endptr; - width = strtoul(s, &endptr, 10); - s = endptr; - } - if (*s == '.') { - s++; - if (ISDIGIT(*s)) { - char *endptr; - prec = strtoul(s, &endptr, 10); - s = endptr; - } - else { - prec = 0; - } - } - char c = *s; - if (alt_form) { - c |= 0x80; - } - int len = mrb_format_float(f, buf, buf_size, c, prec, sign); - - // buf[0] < '0' returns true if the first character is space, + or - - // buf[1] < '9' matches a digit, and doesn't match when we get back +nan or +inf - if (buf[0] < '0' && buf[1] <= '9' && zero_pad) { - buf++; - width--; - len--; - } - if (*buf < '0' || *buf >= '9') { - // For inf or nan, we don't want to zero pad. - zero_pad = 0; - } - if (len >= width) { - return len; - } - buf[width] = '\0'; - if (left_align) { - memset(&buf[len], ' ', width - len); - return width; - } - memmove(&buf[width - len], buf, len); - if (zero_pad) { - memset(buf, '0', width - len); - } else { - memset(buf, ' ', width - len); - } - return width; -} - MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value flo) { |
