summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/numeric.h2
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c83
-rw-r--r--src/fmt_fp.c79
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)
{