From 069d271eb5b237b2274c382c5da011b43b0fa1d9 Mon Sep 17 00:00:00 2001 From: akr Date: Fri, 26 Feb 2010 12:41:02 +0000 Subject: [PATCH] * bignum.c: fix rb_quad_pack and rb_quad_unpack for environments which don't have 8bytes integer type. This still depends on little endian. (rb_quad_pack): use quad_buf_complement. don't raise for large values. (rb_quad_unpack): use quad_buf_complement. (quad_buf_complement): new function extracted frm rb_quad_pack. add one after bitwise negation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26770 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 +++++++++++ bignum.c | 30 ++++++++++++++++++------------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f884a415f..0f0d424737 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Fri Feb 26 21:36:51 2010 Tanaka Akira + + * bignum.c: fix rb_quad_pack and rb_quad_unpack for environments + which don't have 8bytes integer type. This still depends on little + endian. + (rb_quad_pack): use quad_buf_complement. don't raise for large + values. + (rb_quad_unpack): use quad_buf_complement. + (quad_buf_complement): new function extracted frm rb_quad_pack. + add one after bitwise negation. + Fri Feb 26 21:29:48 2010 Tanaka Akira * configure.in (RSHIFT): add parenthesis to supress warning. diff --git a/bignum.c b/bignum.c index 727122849e..de1d11f954 100644 --- a/bignum.c +++ b/bignum.c @@ -376,6 +376,20 @@ rb_quad_unpack(const char *buf, int sign) #else +static int +quad_buf_complement(char *buf, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + buf[i] = ~buf[i]; + for (i = 0; i < len; i++) { + buf[i]++; + if (buf[i] != 0) + return 0; + } + return 1; +} + void rb_quad_pack(char *buf, VALUE val) { @@ -388,15 +402,11 @@ rb_quad_pack(char *buf, VALUE val) } len = RBIGNUM_LEN(val) * SIZEOF_BDIGITS; if (len > QUAD_SIZE) { - rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'"); + len = QUAD_SIZE; } memcpy(buf, (char*)BDIGITS(val), len); - if (!RBIGNUM_SIGN(val)) { - len = QUAD_SIZE; - while (len--) { - *buf = ~*buf; - buf++; - } + if (RBIGNUM_NEGATIVE_P(val)) { + quad_buf_complement(buf, QUAD_SIZE); } } @@ -409,14 +419,10 @@ rb_quad_unpack(const char *buf, int sign) memcpy((char*)BDIGITS(big), buf, QUAD_SIZE); if (sign && BNEG(buf)) { - long len = QUAD_SIZE; char *tmp = (char*)BDIGITS(big); RBIGNUM_SET_SIGN(big, 0); - while (len--) { - *tmp = ~*tmp; - tmp++; - } + quad_buf_complement(tmp, QUAD_SIZE); } return bignorm(big);