* pack.c (pack_pack): generalized integer packer implemented.

(pack_unpack): generalized integer unpacker implemented.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2010-02-28 02:32:09 +00:00
parent f828d53066
commit 334244eb5d
2 changed files with 76 additions and 61 deletions

View File

@ -1,3 +1,8 @@
Sun Feb 28 11:25:16 2010 Tanaka Akira <akr@fsij.org>
* pack.c (pack_pack): generalized integer packer implemented.
(pack_unpack): generalized integer unpacker implemented.
Sun Feb 28 06:58:53 2010 Tanaka Akira <akr@fsij.org> Sun Feb 28 06:58:53 2010 Tanaka Akira <akr@fsij.org>
* pack.c (swap32): use __builtin_bswap32 on gcc 4.3.0 or later. * pack.c (swap32): use __builtin_bswap32 on gcc 4.3.0 or later.
@ -9,9 +14,9 @@ Sun Feb 28 00:38:18 2010 Tanaka Akira <akr@fsij.org>
Sat Feb 27 15:54:55 2010 Tanaka Akira <akr@fsij.org> Sat Feb 27 15:54:55 2010 Tanaka Akira <akr@fsij.org>
* pack.c: check assuption on QUAD_SIZE and SIZEOF_LONG. * pack.c: check assumption on QUAD_SIZE and SIZEOF_LONG.
* bignum.c: check assuption on SIZEOF_LONG and SIZEOF_BDIGITS. * bignum.c: check assumption on SIZEOF_LONG and SIZEOF_BDIGITS.
Sat Feb 27 03:48:18 2010 Tanaka Akira <akr@fsij.org> Sat Feb 27 03:48:18 2010 Tanaka Akira <akr@fsij.org>
@ -34,12 +39,12 @@ Fri Feb 26 21:36:51 2010 Tanaka Akira <akr@fsij.org>
(rb_quad_pack): use quad_buf_complement. don't raise for large (rb_quad_pack): use quad_buf_complement. don't raise for large
values. values.
(rb_quad_unpack): use quad_buf_complement. (rb_quad_unpack): use quad_buf_complement.
(quad_buf_complement): new function extracted frm rb_quad_pack. (quad_buf_complement): new function extracted from rb_quad_pack.
add one after bitwise negation. add one after bitwise negation.
Fri Feb 26 21:29:48 2010 Tanaka Akira <akr@fsij.org> Fri Feb 26 21:29:48 2010 Tanaka Akira <akr@fsij.org>
* configure.in (RSHIFT): add parenthesis to supress warning. * configure.in (RSHIFT): add parenthesis to suppress warning.
Fri Feb 26 20:51:47 2010 Yusuke Endoh <mame@tsg.ne.jp> Fri Feb 26 20:51:47 2010 Yusuke Endoh <mame@tsg.ne.jp>
@ -87,7 +92,7 @@ Thu Feb 25 00:43:57 2010 Koichi Sasada <ko1@atdot.net>
(getting IC directly) and is for the AOT compilation development. (getting IC directly) and is for the AOT compilation development.
* compile.c, iseq.c, insns.def: Change the approach to handling inline * compile.c, iseq.c, insns.def: Change the approach to handling inline
cahce (IC) type operand to enable the above change. cache (IC) type operand to enable the above change.
This change also affects ISeq#to_a method. The inline cache operand This change also affects ISeq#to_a method. The inline cache operand
will be dumped by fixnum, the index of inline cache, in other words, will be dumped by fixnum, the index of inline cache, in other words,
inline cache identity. inline cache identity.

122
pack.c
View File

@ -282,7 +282,9 @@ num2i32(VALUE x)
} }
#define QUAD_SIZE 8 #define QUAD_SIZE 8
#define MAX_INTEGER_PACK_SIZE 8
/* #define FORCE_BIG_PACK */ /* #define FORCE_BIG_PACK */
static const char toofew[] = "too few arguments"; static const char toofew[] = "too few arguments";
static void encodes(VALUE,const char*,long,int,int); static void encodes(VALUE,const char*,long,int,int);
@ -715,7 +717,7 @@ pack_pack(VALUE ary, VALUE fmt)
pack_integer: pack_integer:
switch (integer_size) { switch (integer_size) {
#ifdef HAVE_INT16_T #if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT16_T: case SIZEOF_INT16_T:
while (len-- > 0) { while (len-- > 0) {
int16_t v; int16_t v;
@ -728,7 +730,7 @@ pack_pack(VALUE ary, VALUE fmt)
break; break;
#endif #endif
#ifdef HAVE_INT32_T #if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT32_T: case SIZEOF_INT32_T:
while (len-- > 0) { while (len-- > 0) {
int32_t v; int32_t v;
@ -747,36 +749,43 @@ pack_pack(VALUE ary, VALUE fmt)
int64_t v; int64_t v;
from = NEXTFROM; from = NEXTFROM;
v = num2i32(from); v = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
if (bigendian_p != BIGENDIAN_P()) v = swap64(v); if (bigendian_p != BIGENDIAN_P()) v = swap64(v);
rb_str_buf_cat(res, (char *)&v, sizeof(int64_t)); rb_str_buf_cat(res, (char *)&v, sizeof(int64_t));
} }
break; break;
#else #else
# if QUAD_SIZE % SIZEOF_LONG != 0
# error unexpected QUAD_SIZE : SIZEOF_LONG ratio
# endif
case QUAD_SIZE:
while (len-- > 0) {
unsigned long tmp[QUAD_SIZE/SIZEOF_LONG];
from = NEXTFROM;
rb_big_pack(from, tmp, QUAD_SIZE/SIZEOF_LONG);
if (BIGENDIAN_P()) {
int i;
for (i = 0; i < QUAD_SIZE/SIZEOF_LONG/2; i++) {
unsigned long t = tmp[i];
tmp[i] = tmp[QUAD_SIZE/SIZEOF_LONG-i-1];
tmp[QUAD_SIZE/SIZEOF_LONG-i-1] = t;
}
}
rb_str_buf_cat(res, (char*)tmp, QUAD_SIZE);
}
break;
#endif #endif
default: default:
rb_bug("unexpected intger size for pack: %d", integer_size); if (integer_size > MAX_INTEGER_PACK_SIZE)
rb_bug("unexpected intger size for pack: %d", integer_size);
while (len-- > 0) {
unsigned long tmp[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG];
int num_longs = (integer_size+SIZEOF_LONG-1)/SIZEOF_LONG;
int i;
from = NEXTFROM;
rb_big_pack(from, tmp, num_longs);
if (bigendian_p) {
for (i = 0; i < num_longs/2; i++) {
unsigned long t = tmp[i];
tmp[i] = tmp[num_longs-1-i];
tmp[num_longs-1-i] = t;
}
}
if (bigendian_p != BIGENDIAN_P()) {
for (i = 0; i < num_longs; i++)
tmp[i] = swapl(tmp[i]);
}
rb_str_buf_cat(res,
bigendian_p ?
(char*)tmp + sizeof(long)*num_longs - integer_size :
(char*)tmp,
integer_size);
}
break;
} }
break; break;
@ -1567,7 +1576,7 @@ pack_unpack(VALUE str, VALUE fmt)
unpack_integer: unpack_integer:
switch (integer_size) { switch (integer_size) {
#ifdef HAVE_INT16_T #if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT16_T: case SIZEOF_INT16_T:
if (signed_p) { if (signed_p) {
PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t)); PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t));
@ -1594,7 +1603,7 @@ pack_unpack(VALUE str, VALUE fmt)
break; break;
#endif #endif
#ifdef HAVE_INT32_T #if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT32_T: case SIZEOF_INT32_T:
if (signed_p) { if (signed_p) {
PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t)); PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t));
@ -1646,40 +1655,41 @@ pack_unpack(VALUE str, VALUE fmt)
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
} }
break; break;
#else
# if QUAD_SIZE % SIZEOF_LONG != 0
# error unexpected QUAD_SIZE : SIZEOF_LONG ratio
# endif
case QUAD_SIZE:
if (bigendian_p != BIGENDIAN_P())
rb_bug("unexpected endian for unpack");
PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
while (len-- > 0) {
unsigned long tmp[QUAD_SIZE/SIZEOF_LONG+1];
memcpy(tmp, s, QUAD_SIZE);
if (BIGENDIAN_P()) {
int i;
for (i = 0; i < (QUAD_SIZE/SIZEOF_LONG)/2; i++) {
unsigned long t = tmp[i];
tmp[i] = tmp[(QUAD_SIZE/SIZEOF_LONG)-i-1];
tmp[(QUAD_SIZE/SIZEOF_LONG)-i-1] = t;
}
}
s += QUAD_SIZE;
if (signed_p) {
UNPACK_PUSH(rb_big_unpack(tmp, QUAD_SIZE/SIZEOF_LONG));
}
else {
tmp[QUAD_SIZE/SIZEOF_LONG] = 0;
UNPACK_PUSH(rb_big_unpack(tmp, QUAD_SIZE/SIZEOF_LONG+1));
}
}
PACK_ITEM_ADJUST();
break;
#endif #endif
default: default:
rb_bug("unexpected intger size for unpack"); if (integer_size > MAX_INTEGER_PACK_SIZE)
rb_bug("unexpected intger size for pack: %d", integer_size);
PACK_LENGTH_ADJUST_SIZE(integer_size);
while (len-- > 0) {
unsigned long tmp[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG];
int num_longs = (integer_size+SIZEOF_LONG)/SIZEOF_LONG;
int i;
if (signed_p && (signed char)s[bigendian_p ? 0 : (integer_size-1)] < 0)
memset(tmp, 0xff, sizeof(long)*num_longs);
else
memset(tmp, 0, sizeof(long)*num_longs);
if (bigendian_p)
memcpy((char*)(tmp + num_longs) - integer_size, s, integer_size);
else
memcpy(tmp, s, integer_size);
if (bigendian_p) {
for (i = 0; i < num_longs/2; i++) {
unsigned long t = tmp[i];
tmp[i] = tmp[num_longs-1-i];
tmp[num_longs-1-i] = t;
}
}
if (bigendian_p != BIGENDIAN_P()) {
for (i = 0; i < num_longs; i++)
tmp[i] = swapl(tmp[i]);
}
s += integer_size;
UNPACK_PUSH(rb_big_unpack(tmp, num_longs));
}
PACK_ITEM_ADJUST();
break;
} }
case 'f': case 'f':