aboutsummaryrefslogtreecommitdiffstats
path: root/sprintf.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-14 23:13:36 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-14 23:13:36 +0000
commit230b845fa218a9c22013e752efc5d01943831159 (patch)
tree3210d5d015ffb1c67cd6ad4ccd9c1c18b945c40a /sprintf.c
parent7b09deef51d585a909c367a06ad59ff46d090e6c (diff)
downloadruby-230b845fa218a9c22013e752efc5d01943831159.tar.gz
sprintf.c: improve rational 'f' format
* sprintf.c (rb_str_format): rational 'f' format works for more values. [fix GH-717] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47588 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'sprintf.c')
-rw-r--r--sprintf.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/sprintf.c b/sprintf.c
index d2bc9f89b5..b73aabd823 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -1027,6 +1027,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
VALUE val = GETARG(), num, den;
int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
long len;
+ int i, done = 0, prefix = 0;
if (!RB_TYPE_P(val, T_RATIONAL)) {
nextvalue = val;
goto float_value;
@@ -1062,28 +1063,53 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
if (sign || (flags&FSPACE)) ++len;
if (prec > 0) ++len; /* period */
CHECK(len > width ? len : width);
- if (width > len) {
- width -= (int)len;
- if (!(flags&FMINUS)) {
- FILL(' ', width);
- width = 0;
- }
+ if (sign || (flags&FSPACE)) {
+ buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
+ prefix++;
+ done++;
}
- if (sign || (flags&FSPACE)) buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
len = RSTRING_LEN(val) + zero;
t = RSTRING_PTR(val);
- if (len > prec)
+ if (len > prec) {
memcpy(&buf[blen], t, len - prec);
- else
+ blen += len - prec;
+ done += len - prec;
+ }
+ else {
buf[blen++] = '0';
- blen += len - prec;
- if (prec > 0) buf[blen++] = '.';
- if (zero) FILL('0', zero);
+ done++;
+ }
+ if (prec > 0) {
+ buf[blen++] = '.';
+ done++;
+ }
+ if (zero) {
+ FILL('0', zero);
+ done += zero;
+ }
+ else if (prec > len) {
+ FILL('0', prec - len);
+ memcpy(&buf[blen], t, len);
+ blen += len;
+ done += prec;
+ }
else if (prec > 0) {
memcpy(&buf[blen], t + len - prec, prec);
blen += prec;
+ done += prec;
+ }
+ if ((flags & FWIDTH) && width > done) {
+ if (!(flags&FMINUS)) {
+ int shifting = (flags&FZERO) ? done - prefix : done;
+ for (i = 1; i <= shifting; i++)
+ buf[width - i] = buf[done - i];
+ blen -= shifting;
+ FILL((flags&FZERO) ? '0' : ' ', width - done);
+ blen += shifting;
+ } else {
+ FILL(' ', width - done);
+ }
}
- if (width > 0) FILL(' ', width);
RB_GC_GUARD(val);
break;
}