diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-05-29 23:41:35 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-05-30 08:15:51 +0900 |
| commit | 8a4bcc58c92ff921368b3f41a5e234266a11728c (patch) | |
| tree | 6977fee05e27e35285100973f5b275e72c160826 | |
| parent | 60aa2192a8afc7a2f58196f1667f254832ca8c25 (diff) | |
| download | mruby-8a4bcc58c92ff921368b3f41a5e234266a11728c.tar.gz mruby-8a4bcc58c92ff921368b3f41a5e234266a11728c.zip | |
numeric.c: introduce `mrb_int_to_cstr()` to dump `mrb_int`.
* refactor `mrb_integer_to_str()`
* refactor `mrb_str_format()`
| -rw-r--r-- | include/mruby/numeric.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 52 | ||||
| -rw-r--r-- | src/numeric.c | 54 |
3 files changed, 39 insertions, 68 deletions
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 4e3e8976a..52e335ade 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -35,6 +35,7 @@ MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y); MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y); MRB_API mrb_value mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base); +MRB_API char *mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base); /* internal function(s) */ mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y); diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 2e6cec803..1bb150f51 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -585,50 +585,6 @@ mrb_f_sprintf(mrb_state *mrb, mrb_value obj) } } -static int -mrb_int2str(char *buf, size_t len, mrb_int n) -{ -#ifdef MRB_NO_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_NO_STDIO */ -} - mrb_value mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt) { @@ -983,13 +939,10 @@ retry: sc = '-'; width--; } - mrb_assert(base == 10); - mrb_int2str(nbuf, sizeof(nbuf)-1, v); - s = nbuf; + s = mrb_int_to_cstr(nbuf, sizeof(nbuf), v, base); if (v < 0) s++; /* skip minus sign */ } else { - s = nbuf; if (v < 0) { dots = 1; val = mrb_fix2binstr(mrb, mrb_int_value(mrb, v), base); @@ -997,7 +950,8 @@ retry: else { val = mrb_integer_to_str(mrb, mrb_int_value(mrb, v), base); } - strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-2); + strncpy(nbuf+1, RSTRING_PTR(val), sizeof(nbuf)-2); + s = nbuf+1; } { size_t size; diff --git a/src/numeric.c b/src/numeric.c index fe9995bd4..a344440f4 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1507,35 +1507,51 @@ int_sub(mrb_state *mrb, mrb_value self) return int_minus(mrb, self, other); } - -MRB_API mrb_value -mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base) +MRB_API char* +mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base) { - char buf[MRB_INT_BIT+1]; - char *b = buf + sizeof buf; - mrb_int val = mrb_integer(x); - mrb_value str; + char *bufend = buf + len; + char *b = bufend-1; - if (base < 2 || 36 < base) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base); - } + if (base < 2 || 36 < base) return NULL; + if (len < 2) return NULL; - if (val == 0) { - *--b = '0'; + if (n == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return buf; } - else if (val < 0) { + + *b-- = '\0'; + if (n < 0) { do { - *--b = mrb_digitmap[-(val % base)]; - } while (val /= base); - *--b = '-'; + if (b-- == buf) return NULL; + *b = mrb_digitmap[-(n % base)]; + } while (n /= base); + if (b-- == buf) return NULL; + *b = '-'; } else { do { - *--b = mrb_digitmap[(int)(val % base)]; - } while (val /= base); + if (b-- == buf) return NULL; + *b = mrb_digitmap[(int)(n % base)]; + } while (n /= base); } + return b; +} + +MRB_API mrb_value +mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base) +{ + char buf[MRB_INT_BIT+1]; + mrb_int val = mrb_integer(x); - str = mrb_str_new(mrb, b, buf + sizeof(buf) - b); + if (base < 2 || 36 < base) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base); + } + const char *p = mrb_int_to_cstr(buf, sizeof(buf), val, base); + mrb_assert(p != NULL); + mrb_value str = mrb_str_new_cstr(mrb, p); RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); return str; } |
