summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-05-29 23:41:35 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-05-30 08:15:51 +0900
commit8a4bcc58c92ff921368b3f41a5e234266a11728c (patch)
tree6977fee05e27e35285100973f5b275e72c160826
parent60aa2192a8afc7a2f58196f1667f254832ca8c25 (diff)
downloadmruby-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.h1
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c52
-rw-r--r--src/numeric.c54
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;
}