summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-sprintf/src/sprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-sprintf/src/sprintf.c')
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c177
1 files changed, 71 insertions, 106 deletions
diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c
index 3d96573a7..7b8201736 100644
--- a/mrbgems/mruby-sprintf/src/sprintf.c
+++ b/mrbgems/mruby-sprintf/src/sprintf.c
@@ -116,7 +116,6 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
#define CHECK(l) do {\
/* int cr = ENC_CODERANGE(result);*/\
- if ((l) < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "illegal specifier"); \
while ((l) >= bsiz - blen) {\
bsiz*=2;\
if (bsiz < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \
@@ -529,7 +528,6 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
mrb_int n;
mrb_int width;
mrb_int prec;
- int flags = FNONE;
int nextarg = 1;
int posarg = 0;
mrb_value nextvalue;
@@ -565,6 +563,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
for (; p < end; p++) {
const char *t;
mrb_sym id = 0;
+ int flags = FNONE;
for (t = p; t < end && *t != '%'; t++) ;
if (t + 1 == end) ++t;
@@ -702,35 +701,39 @@ retry:
tmp = mrb_check_string_type(mrb, val);
if (!mrb_nil_p(tmp)) {
- if (mrb_fixnum(mrb_funcall(mrb, tmp, "size", 0)) != 1 ) {
+ if (RSTRING_LEN(tmp) != 1) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
}
}
else if (mrb_fixnum_p(val)) {
- tmp = mrb_funcall(mrb, val, "chr", 0);
+ mrb_int n = mrb_fixnum(val);
+
+ if (n < 0x80) {
+ char buf[1];
+
+ buf[0] = (char)n;
+ tmp = mrb_str_new(mrb, buf, 1);
+ }
+ else {
+ tmp = mrb_funcall(mrb, val, "chr", 0);
+ mrb_check_type(mrb, tmp, MRB_TT_STRING);
+ }
}
else {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
}
- mrb_check_type(mrb, tmp, MRB_TT_STRING);
c = RSTRING_PTR(tmp);
n = RSTRING_LEN(tmp);
if (!(flags & FWIDTH)) {
- CHECK(n);
- memcpy(buf+blen, c, n);
- blen += n;
+ PUSH(c, n);
}
else if ((flags & FMINUS)) {
- CHECK(n);
- memcpy(buf+blen, c, n);
- blen += n;
+ PUSH(c, n);
if (width>0) FILL(' ', width-1);
}
else {
if (width>0) FILL(' ', width-1);
- CHECK(n);
- memcpy(buf+blen, c, n);
- blen += n;
+ PUSH(c, n);
}
}
break;
@@ -768,19 +771,11 @@ retry:
if ((flags&FWIDTH) && (width > slen)) {
width -= (int)slen;
if (!(flags&FMINUS)) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
+ FILL(' ', width);
}
- CHECK(len);
- memcpy(&buf[blen], RSTRING_PTR(str), len);
- blen += len;
+ PUSH(RSTRING_PTR(str), len);
if (flags&FMINUS) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
+ FILL(' ', width);
}
break;
}
@@ -806,13 +801,6 @@ retry:
int base;
mrb_int len;
- switch (*p) {
- case 'd':
- case 'i':
- sign = 1; break;
- default:
- break;
- }
if (flags & FSHARP) {
switch (*p) {
case 'o': prefix = "0"; break;
@@ -853,21 +841,13 @@ retry:
case 'u':
case 'd':
case 'i':
+ sign = 1;
default:
base = 10; break;
}
- if (base == 2) {
- if (v < 0 && !sign) {
- val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
- dots = 1;
- }
- else {
- val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
- }
- }
if (sign) {
- if (v > 0) {
+ if (v >= 0) {
if (flags & FPLUS) {
sc = '+';
width--;
@@ -877,37 +857,33 @@ retry:
width--;
}
}
- switch (base) {
- case 2:
- strncpy(nbuf, RSTRING_PTR(val), sizeof(nbuf));
- break;
- case 8:
- snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIo, v);
- break;
- case 10:
- snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
- break;
- case 16:
- snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIx, v);
- break;
+ else {
+ sc = '-';
+ width--;
}
+ mrb_assert(base == 10);
+ snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
s = nbuf;
+ if (v < 0) s++; /* skip minus sign */
}
else {
s = nbuf;
- if (base != 10 && v < 0) {
+ if (v < 0) {
dots = 1;
}
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 10:
- snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRId, v);
- break;
case 16:
snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v);
break;
@@ -935,11 +911,6 @@ retry:
len = (mrb_int)size;
}
- if (dots) {
- prec -= 2;
- width -= 2;
- }
-
if (*p == 'X') {
char *pp = s;
int c;
@@ -986,10 +957,8 @@ retry:
}
if (!(flags&FMINUS) && width > 0) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
+ FILL(' ', width);
+ width = 0;
}
if (sc) PUSH(&sc, 1);
@@ -998,28 +967,25 @@ retry:
int plen = (int)strlen(prefix);
PUSH(prefix, plen);
}
- CHECK(prec - len);
- if (dots) PUSH("..", 2);
-
- if (v < 0) {
- char c = sign_bits(base, p);
- while (len < prec--) {
- buf[blen++] = c;
- }
+ if (dots) {
+ prec -= 2;
+ width -= 2;
+ PUSH("..", 2);
}
- else if ((flags & (FMINUS|FPREC)) != FMINUS) {
- char c = '0';
- while (len < prec--) {
- buf[blen++] = c;
+
+ if (prec > len) {
+ CHECK(prec - len);
+ if ((flags & (FMINUS|FPREC)) != FMINUS) {
+ char c = '0';
+ FILL(c, prec - len);
+ } else if (v < 0) {
+ char c = sign_bits(base, p);
+ FILL(c, prec - len);
}
}
-
PUSH(s, len);
if (width > 0) {
- CHECK(width);
- while (width-- > 0) {
- buf[blen++] = ' ';
- }
+ FILL(' ', width);
}
}
break;
@@ -1040,6 +1006,7 @@ retry:
if (!isfinite(fval)) {
const char *expr;
const int elen = 3;
+ char sign = '\0';
if (isnan(fval)) {
expr = "NaN";
@@ -1048,35 +1015,29 @@ retry:
expr = "Inf";
}
need = elen;
- if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
- need++;
+ if (!isnan(fval) && fval < 0.0)
+ sign = '-';
+ else if (flags & (FPLUS|FSPACE))
+ sign = (flags & FPLUS) ? '+' : ' ';
+ if (sign)
+ ++need;
if ((flags & FWIDTH) && need < width)
need = width;
- CHECK(need + 1);
- n = snprintf(&buf[blen], need + 1, "%*s", need, "");
- if (n < 0) {
- mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
+ if (need < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "width too big");
}
+ FILL(' ', need);
if (flags & FMINUS) {
- if (!isnan(fval) && fval < 0.0)
- buf[blen++] = '-';
- else if (flags & FPLUS)
- buf[blen++] = '+';
- else if (flags & FSPACE)
- blen++;
- memcpy(&buf[blen], expr, elen);
+ if (sign)
+ buf[blen - need--] = sign;
+ memcpy(&buf[blen - need], expr, elen);
}
else {
- if (!isnan(fval) && fval < 0.0)
- buf[blen + need - elen - 1] = '-';
- else if (flags & FPLUS)
- buf[blen + need - elen - 1] = '+';
- else if ((flags & FSPACE) && need > width)
- blen++;
- memcpy(&buf[blen + need - elen], expr, elen);
+ if (sign)
+ buf[blen - elen - 1] = sign;
+ memcpy(&buf[blen - elen], expr, elen);
}
- blen += strlen(&buf[blen]);
break;
}
@@ -1092,6 +1053,10 @@ retry:
if ((flags&FWIDTH) && need < width)
need = width;
need += 20;
+ if (need <= 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR,
+ (width > prec ? "width too big" : "prec too big"));
+ }
CHECK(need);
n = snprintf(&buf[blen], need, fbuf, fval);