numeric.c: introduce `mrb_int_to_cstr()` to dump `mrb_int`.

* refactor `mrb_integer_to_str()`
* refactor `mrb_str_format()`
parent 60aa2192
......@@ -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);
......
......@@ -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;
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment