From 6e62aeb9bc0a1abf50e107a909370ef461d157f5 Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 30 Oct 2006 03:39:44 +0000 Subject: [PATCH] * sprintf.c (rb_str_format): should preserve leading zero information for negative %b and %x. [ruby-talk:221347] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ bignum.c | 36 ++++++++++++++++++++++++------------ intern.h | 1 + sprintf.c | 2 +- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index d043f155e6..f0d3089d4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Oct 30 11:15:40 2006 Yukihiro Matsumoto + + * sprintf.c (rb_str_format): should preserve leading zero + information for negative %b and %x. [ruby-talk:221347] + Sun Oct 29 19:51:31 2006 K.Kosako * regexec.c: invalid offset value was used in STATE_CHECK_BUFF_INIT(). diff --git a/bignum.c b/bignum.c index 17424b5148..f738ff0862 100644 --- a/bignum.c +++ b/bignum.c @@ -579,13 +579,13 @@ rb_str2inum(VALUE str, int base) const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; VALUE -rb_big2str(VALUE x, int base) +rb_big2str0(VALUE x, int base, int trim) { volatile VALUE t; BDIGIT *ds; long i, j, hbase; VALUE ss; - char *s, c; + char *s; if (FIXNUM_P(x)) { return rb_fix2str(x, base); @@ -621,7 +621,7 @@ rb_big2str(VALUE x, int base) rb_raise(rb_eArgError, "illegal radix %d", base); break; } - j += 2; + j++; /* space for sign */ hbase = base * base; #if SIZEOF_BDIGITS > 2 @@ -630,11 +630,11 @@ rb_big2str(VALUE x, int base) t = rb_big_clone(x); ds = BDIGITS(t); - ss = rb_str_new(0, j); + ss = rb_str_new(0, j+1); s = RSTRING_PTR(ss); s[0] = RBIGNUM(x)->sign ? '+' : '-'; - while (i && j) { + while (i && j > 1) { long k = i; BDIGIT_DBL num = 0; @@ -643,23 +643,35 @@ rb_big2str(VALUE x, int base) ds[k] = (BDIGIT)(num / hbase); num %= hbase; } - if (ds[i-1] == 0) i--; + if (trim && ds[i-1] == 0) i--; k = SIZEOF_BDIGITS; while (k--) { - c = (char)(num % base); - s[--j] = ruby_digitmap[(int)c]; + s[--j] = ruby_digitmap[num % base]; num /= base; - if (i == 0 && num == 0) break; + if (!trim && j < 1) break; + if (trim && i == 0 && num == 0) break; } } - while (s[j] == '0') j++; - i = RSTRING_LEN(ss)-(RBIGNUM(x)->sign?j:j-1); - memmove(RBIGNUM(x)->sign?s:s+1, s+j, i); + if (trim) {while (s[j] == '0') j++;} + i = RSTRING_LEN(ss) - j; + if (RBIGNUM(x)->sign) { + memmove(s, s+j, i); + i--; + } + else { + memmove(s+1, s+j, i); + } rb_str_set_len(ss, i); return ss; } +VALUE +rb_big2str(VALUE x, int base) +{ + return rb_big2str0(x, base, Qtrue); +} + /* * call-seq: * big.to_s(base=10) => string diff --git a/intern.h b/intern.h index c1461171af..b2b3339c4e 100644 --- a/intern.h +++ b/intern.h @@ -79,6 +79,7 @@ VALUE rb_str_to_inum(VALUE, int, int); VALUE rb_cstr2inum(const char*, int); VALUE rb_str2inum(VALUE, int); VALUE rb_big2str(VALUE, int); +VALUE rb_big2str0(VALUE, int, int); SIGNED_VALUE rb_big2long(VALUE); #define rb_big2int(x) rb_big2long(x) VALUE rb_big2ulong(VALUE); diff --git a/sprintf.c b/sprintf.c index 585db5b718..41661f1134 100644 --- a/sprintf.c +++ b/sprintf.c @@ -627,7 +627,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) val = rb_big_clone(val); rb_big_2comp(val); } - tmp1 = tmp = rb_big2str(val, base); + tmp1 = tmp = rb_big2str0(val, base, RBIGNUM(val)->sign); s = RSTRING_PTR(tmp); if (*s == '-') { if (base == 10) {