diff options
| author | Hiroshi Mimaki <[email protected]> | 2020-06-05 12:42:56 +0900 |
|---|---|---|
| committer | Hiroshi Mimaki <[email protected]> | 2020-06-05 12:42:56 +0900 |
| commit | 81d340e0421daf39a8208a0181d6a54e726db134 (patch) | |
| tree | 18cefdd763a716dbd27c23bfdf98ffa2135f7624 /mrbgems/mruby-sprintf | |
| parent | f9d113f7647121f8578742a2a9ac256ece365e3f (diff) | |
| parent | 4e40169ed6d200918e542aa8d8e64634794e1864 (diff) | |
| download | mruby-81d340e0421daf39a8208a0181d6a54e726db134.tar.gz mruby-81d340e0421daf39a8208a0181d6a54e726db134.zip | |
Merge master.
Diffstat (limited to 'mrbgems/mruby-sprintf')
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 88 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/test/sprintf.rb | 28 |
2 files changed, 66 insertions, 50 deletions
diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 558d57173..9a7671a24 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -5,11 +5,6 @@ */ #include <mruby.h> - -#ifdef MRB_DISABLE_STDIO -# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb' -#endif - #include <limits.h> #include <string.h> #include <mruby/string.h> @@ -521,6 +516,50 @@ mrb_f_sprintf(mrb_state *mrb, mrb_value obj) } } +static int +mrb_int2str(char *buf, size_t len, mrb_int n) +{ +#ifdef MRB_DISABLE_STDIO + char *bufend = buf + len; + char *p = bufend - 1; + + if (len < 1) return -1; + + *p -- = '\0'; + len --; + + if (n < 0) { + if (len < 1) return -1; + + *p -- = '-'; + len --; + n = -n; + } + + if (n > 0) { + for (; n > 0; len --, n /= 10) { + if (len < 1) return -1; + + *p -- = '0' + (n % 10); + } + p ++; + } + else if (len > 0) { + *p = '0'; + len --; + } + else { + return -1; + } + + memmove(buf, p, bufend - p); + + return bufend - p - 1; +#else + return snprintf(buf, len, "%" MRB_PRId, n); +#endif /* MRB_DISABLE_STDIO */ +} + mrb_value mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt) { @@ -711,7 +750,12 @@ retry: } else if (mrb_fixnum_p(val)) { mrb_int n = mrb_fixnum(val); +#ifndef MRB_UTF8_STRING + char buf[1]; + buf[0] = (char)n&0xff; + tmp = mrb_str_new(mrb, buf, 1); +#else if (n < 0x80) { char buf[1]; @@ -722,6 +766,7 @@ retry: tmp = mrb_funcall(mrb, val, "chr", 0); mrb_check_type(mrb, tmp, MRB_TT_STRING); } +#endif } else { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character"); @@ -869,7 +914,7 @@ retry: width--; } mrb_assert(base == 10); - snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v); + mrb_int2str(nbuf, sizeof(nbuf), v); s = nbuf; if (v < 0) s++; /* skip minus sign */ } @@ -877,24 +922,12 @@ retry: s = nbuf; if (v < 0) { dots = 1; + val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base); } - switch (base) { - case 2: - if (v < 0) { - val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base); - } - else { - val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base); - } - strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1); - break; - case 8: - snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v); - break; - case 16: - snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v); - break; + else { + val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base); } + strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1); if (v < 0) { char d; @@ -1008,7 +1041,7 @@ retry: mrb_value val = GETARG(); double fval; mrb_int need = 6; - char fbuf[32]; + char fbuf[64]; fval = mrb_float(mrb_Float(mrb, val)); if (!isfinite(fval)) { @@ -1049,7 +1082,6 @@ retry: break; } - fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); need = 0; if (*p != 'e' && *p != 'E') { int i; @@ -1071,7 +1103,8 @@ retry: need += 20; CHECK(need); - n = snprintf(&buf[blen], need, fbuf, fval); + fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); + n = mrb_float_to_cstr(mrb, &buf[blen], need, fbuf, fval); if (n < 0 || n >= need) { mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error"); } @@ -1113,12 +1146,13 @@ fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec) if (flags & FSPACE) *buf++ = ' '; if (flags & FWIDTH) { - n = snprintf(buf, end - buf, "%d", (int)width); + n = mrb_int2str(buf, end - buf, width); buf += n; } if (flags & FPREC) { - n = snprintf(buf, end - buf, ".%d", (int)prec); + *buf ++ = '.'; + n = mrb_int2str(buf, end - buf, prec); buf += n; } diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb index 137812ae7..0eb51f557 100644 --- a/mrbgems/mruby-sprintf/test/sprintf.rb +++ b/mrbgems/mruby-sprintf/test/sprintf.rb @@ -8,6 +8,11 @@ assert('String#%') do assert_equal 15, ("%b" % (1<<14)).size skip unless Object.const_defined?(:Float) assert_equal "1.0", "%3.1f" % 1.01 + assert_equal " 123456789.12", "% 4.2f" % 123456789.123456789 + assert_equal "123456789.12", "%-4.2f" % 123456789.123456789 + assert_equal "+123456789.12", "%+4.2f" % 123456789.123456789 + assert_equal "123456789.12", "%04.2f" % 123456789.123456789 + assert_equal "00000000123456789.12", "%020.2f" % 123456789.123456789 end assert('String#% with inf') do @@ -68,29 +73,6 @@ assert('String#% with nan') do assert_equal " NaN", "% 5f" % nan end -assert("String#% with invalid chr") do - begin - class Fixnum - alias_method :chr_, :chr if method_defined?(:chr) - - def chr - nil - end - end - - assert_raise TypeError do - "%c" % 0x80 - end - ensure - class Fixnum - if method_defined?(:chr_) - alias_method :chr, :chr_ - remove_method :chr_ - end - end - end -end - assert("String#% %b") do assert_equal("..10115", "%0b5" % -5) end |
