зеркало из https://github.com/github/ruby.git
* configure.in: Invoke RUBY_REPLACE_TYPE for size_t.
Don't invoke RUBY_CHECK_PRINTF_PREFIX for size_t to avoid conflict with RUBY_REPLACE_TYPE. * internal.h (rb_absint_size): Declared. (rb_absint_size_in_word): Ditto. (rb_int_export): Ditto. * bignum.c (rb_absint_size): New function. (rb_absint_size_in_word): Ditto. (int_export_fill_dd): Ditto. (int_export_take_lowbits): Ditto. (rb_int_export): Ditto. * pack.c (pack_pack): Use rb_int_export for BER compressed integer. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
c247e62808
Коммит
9fea8758e9
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
Thu Jun 6 20:40:17 2013 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* configure.in: Invoke RUBY_REPLACE_TYPE for size_t.
|
||||
Don't invoke RUBY_CHECK_PRINTF_PREFIX for size_t to avoid conflict
|
||||
with RUBY_REPLACE_TYPE.
|
||||
|
||||
* internal.h (rb_absint_size): Declared.
|
||||
(rb_absint_size_in_word): Ditto.
|
||||
(rb_int_export): Ditto.
|
||||
|
||||
* bignum.c (rb_absint_size): New function.
|
||||
(rb_absint_size_in_word): Ditto.
|
||||
(int_export_fill_dd): Ditto.
|
||||
(int_export_take_lowbits): Ditto.
|
||||
(rb_int_export): Ditto.
|
||||
|
||||
* pack.c (pack_pack): Use rb_int_export for BER compressed integer.
|
||||
|
||||
Thu Jun 6 19:31:33 2013 Tadayoshi Funaba <tadf@dotrb.org>
|
||||
|
||||
* ext/date/date_core.c: fixed coding error [ruby-core:55337].
|
||||
|
|
321
bignum.c
321
bignum.c
|
@ -50,6 +50,8 @@ static VALUE big_three = Qnil;
|
|||
(BDIGITS(x)[0] == 0 && \
|
||||
(RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
|
||||
|
||||
static int nlz(BDIGIT x);
|
||||
|
||||
#define BIGNUM_DEBUG 0
|
||||
#if BIGNUM_DEBUG
|
||||
#define ON_DEBUG(x) do { x; } while (0)
|
||||
|
@ -449,6 +451,325 @@ rb_big_unpack(unsigned long *buf, long num_longs)
|
|||
}
|
||||
}
|
||||
|
||||
/* number of bytes of abs(val). additionaly number of leading zeros can be returned. */
|
||||
size_t
|
||||
rb_absint_size(VALUE val, int *number_of_leading_zero_bits)
|
||||
{
|
||||
BDIGIT *dp;
|
||||
BDIGIT *de;
|
||||
BDIGIT fixbuf[(sizeof(long) + SIZEOF_BDIGITS - 1) / SIZEOF_BDIGITS];
|
||||
int i;
|
||||
int num_leading_zeros;
|
||||
|
||||
val = rb_to_int(val);
|
||||
|
||||
if (FIXNUM_P(val)) {
|
||||
long v = FIX2LONG(val);
|
||||
if (v < 0) {
|
||||
v = -v;
|
||||
}
|
||||
#if SIZEOF_BDIGITS == SIZEOF_LONG
|
||||
fixbuf[0] = v;
|
||||
#else
|
||||
for (i = 0; i < (int)(sizeof(fixbuf)/sizeof(*fixbuf)); i++) {
|
||||
fixbuf[i] = v & ((1L << (SIZEOF_BDIGITS * CHAR_BIT)) - 1);
|
||||
v >>= SIZEOF_BDIGITS * CHAR_BIT;
|
||||
}
|
||||
#endif
|
||||
dp = fixbuf;
|
||||
de = fixbuf + sizeof(fixbuf)/sizeof(*fixbuf);
|
||||
}
|
||||
else {
|
||||
dp = BDIGITS(val);
|
||||
de = dp + RBIGNUM_LEN(val);
|
||||
}
|
||||
while (dp < de && de[-1] == 0)
|
||||
de--;
|
||||
if (dp == de) {
|
||||
if (number_of_leading_zero_bits)
|
||||
*number_of_leading_zero_bits = 0;
|
||||
return 0;
|
||||
}
|
||||
num_leading_zeros = nlz(de[-1]);
|
||||
if (number_of_leading_zero_bits)
|
||||
*number_of_leading_zero_bits = num_leading_zeros % CHAR_BIT;
|
||||
return (de - dp) * SIZEOF_BDIGITS - num_leading_zeros / CHAR_BIT;
|
||||
}
|
||||
|
||||
size_t
|
||||
rb_absint_size_in_word(VALUE val, size_t word_numbits_arg, size_t *number_of_leading_zero_bits)
|
||||
{
|
||||
size_t numbytes;
|
||||
size_t numwords;
|
||||
int zerobits_in_byte;
|
||||
VALUE val_numbits, word_numbits;
|
||||
VALUE div_mod, div, mod;
|
||||
|
||||
numbytes = rb_absint_size(val, &zerobits_in_byte);
|
||||
|
||||
/*
|
||||
* val_numbits = numbytes * CHAR_BIT - zerobits_in_byte
|
||||
* div, mod = val_numbits.divmod(word_numbits)
|
||||
* numwords = mod == 0 ? div : div + 1
|
||||
* number_of_leading_zero_bits_in_word = mod == 0 ? 0 : word_numbits - mod
|
||||
*/
|
||||
val_numbits = SIZET2NUM(numbytes);
|
||||
val_numbits = rb_funcall(val_numbits, '*', 1, LONG2FIX(CHAR_BIT));
|
||||
if (zerobits_in_byte)
|
||||
val_numbits = rb_funcall(val_numbits, '-', 1, LONG2FIX(zerobits_in_byte));
|
||||
word_numbits = SIZET2NUM(word_numbits_arg);
|
||||
div_mod = rb_funcall(val_numbits, rb_intern("divmod"), 1, word_numbits);
|
||||
div = RARRAY_AREF(div_mod, 0);
|
||||
mod = RARRAY_AREF(div_mod, 1);
|
||||
if (mod == LONG2FIX(0)) {
|
||||
numwords = NUM2SIZE(div);
|
||||
if (number_of_leading_zero_bits)
|
||||
*number_of_leading_zero_bits = 0;
|
||||
}
|
||||
else {
|
||||
numwords = NUM2SIZE(rb_funcall(div, '+', 1, LONG2FIX(1)));
|
||||
if (number_of_leading_zero_bits)
|
||||
*number_of_leading_zero_bits = word_numbits_arg - NUM2SIZE(mod);
|
||||
}
|
||||
return numwords;
|
||||
}
|
||||
|
||||
static inline void
|
||||
int_export_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
|
||||
{
|
||||
if (*dpp < *dep && SIZEOF_BDIGITS * CHAR_BIT <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
|
||||
*ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
|
||||
*numbits_in_dd_p += SIZEOF_BDIGITS * CHAR_BIT;
|
||||
}
|
||||
else if (*dpp == *dep) {
|
||||
/* higher bits are infinity zeros */
|
||||
*numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline BDIGIT_DBL
|
||||
int_export_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
|
||||
{
|
||||
BDIGIT_DBL ret;
|
||||
ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
|
||||
*ddp >>= n;
|
||||
*numbits_in_dd_p -= n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Export an integer into a buffer.
|
||||
*
|
||||
* [val] Fixnum, Bignum or another object which has to_int.
|
||||
* [signp] signedness is returned in *signp if it is not NULL.
|
||||
* 0 for zero.
|
||||
* -1 for negative without overflow. 1 for positive without overflow.
|
||||
* -2 for negative overflow. 2 for positive overflow.
|
||||
* [buf] buffer to export abs(val). allocated by xmalloc if it is NULL.
|
||||
* [countp] the size of given buffer as number of words (only meaningful when buf is not NULL).
|
||||
* *countp is overwritten as the number of allocated words when buf is NULL and allocated.
|
||||
* [wordorder] order of words: 1 for most significant word first. -1 for least significant word first.
|
||||
* [wordsize] the size of word as number of bytes.
|
||||
* [endian] order of bytes in a word: 1 for most significant byte first. -1 for least significant byte first. 0 for native endian.
|
||||
* [nails] number of padding bits in a word. Most significant nails bits of each word are filled by zero.
|
||||
*
|
||||
* This function returns buf or the allocated buffer if buf is NULL.
|
||||
*
|
||||
*/
|
||||
void *
|
||||
rb_int_export(VALUE val, int *signp, void *bufarg, size_t *countp, int wordorder, size_t wordsize, int endian, size_t nails)
|
||||
{
|
||||
int sign;
|
||||
BDIGIT *dp;
|
||||
BDIGIT *de;
|
||||
BDIGIT fixbuf[(sizeof(long) + SIZEOF_BDIGITS - 1) / SIZEOF_BDIGITS];
|
||||
int i;
|
||||
unsigned char *buf = bufarg;
|
||||
unsigned char *bufend;
|
||||
size_t wordcount;
|
||||
|
||||
val = rb_to_int(val);
|
||||
|
||||
if (wordorder != 1 && wordorder != -1)
|
||||
rb_raise(rb_eArgError, "unexpected wordorder: %d", wordorder);
|
||||
if (endian != 1 && endian != -1 && endian != 0)
|
||||
rb_raise(rb_eArgError, "unexpected endian: %d", endian);
|
||||
if (wordsize == 0)
|
||||
rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
|
||||
if (SSIZE_MAX < wordsize)
|
||||
rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
|
||||
if (buf && SIZE_MAX / wordsize < *countp)
|
||||
rb_raise(rb_eArgError, "too big count * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", *countp, wordsize);
|
||||
if (wordsize <= nails / CHAR_BIT)
|
||||
rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails);
|
||||
|
||||
if (endian == 0) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
endian = 1;
|
||||
#else
|
||||
endian = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (FIXNUM_P(val)) {
|
||||
long v = FIX2LONG(val);
|
||||
if (v < 0) {
|
||||
sign = -1;
|
||||
v = -v;
|
||||
}
|
||||
else {
|
||||
sign = 1;
|
||||
}
|
||||
#if SIZEOF_BDIGITS == SIZEOF_LONG
|
||||
fixbuf[0] = v;
|
||||
#else
|
||||
for (i = 0; i < (int)(sizeof(fixbuf)/sizeof(*fixbuf)); i++) {
|
||||
fixbuf[i] = v & ((1L << (SIZEOF_BDIGITS * CHAR_BIT)) - 1);
|
||||
v >>= SIZEOF_BDIGITS * CHAR_BIT;
|
||||
}
|
||||
#endif
|
||||
dp = fixbuf;
|
||||
de = fixbuf + sizeof(fixbuf)/sizeof(*fixbuf);
|
||||
}
|
||||
else {
|
||||
sign = RBIGNUM_POSITIVE_P(val) ? 1 : -1;
|
||||
dp = BDIGITS(val);
|
||||
de = dp + RBIGNUM_LEN(val);
|
||||
}
|
||||
while (dp < de && de[-1] == 0)
|
||||
de--;
|
||||
if (dp == de) {
|
||||
sign = 0;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
wordcount = *countp;
|
||||
bufend = buf + wordcount * wordsize;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* val_numbits = (de - dp) * SIZEOF_BDIGITS * CHAR_BIT - nlz(de[-1])
|
||||
* word_numbits = wordsize * CHAR_BIT - nails
|
||||
* wordcount = (val_numbits + word_numbits - 1) / word_numbits
|
||||
*/
|
||||
VALUE val_numbits, word_numbits, wordcountv;
|
||||
val_numbits = SIZET2NUM((de - dp) * SIZEOF_BDIGITS);
|
||||
val_numbits = rb_funcall(val_numbits, '*', 1, LONG2FIX(CHAR_BIT));
|
||||
if (dp != de)
|
||||
val_numbits = rb_funcall(val_numbits, '-', 1, LONG2FIX(nlz(de[-1])));
|
||||
word_numbits = SIZET2NUM(wordsize);
|
||||
word_numbits = rb_funcall(word_numbits, '*', 1, LONG2FIX(CHAR_BIT));
|
||||
if (nails != 0)
|
||||
word_numbits = rb_funcall(word_numbits, '-', 1, SIZET2NUM(nails));
|
||||
wordcountv = rb_funcall(val_numbits, '+', 1, word_numbits);
|
||||
wordcountv = rb_funcall(wordcountv, '-', 1, LONG2FIX(1));
|
||||
wordcountv = rb_funcall(wordcountv, rb_intern("div"), 1, word_numbits);
|
||||
wordcount = NUM2SIZE(wordcountv);
|
||||
buf = xmalloc(wordcount * wordsize);
|
||||
bufend = buf + wordcount * wordsize;
|
||||
}
|
||||
|
||||
if (buf == bufend) {
|
||||
sign *= 2; /* overflow if non-zero*/
|
||||
}
|
||||
else if (dp == de) {
|
||||
memset(buf, '\0', bufend - buf);
|
||||
}
|
||||
else if (dp < de && buf < bufend) {
|
||||
int word_num_partialbits;
|
||||
size_t word_num_fullbytes;
|
||||
size_t word_num_nailbytes;
|
||||
|
||||
ssize_t word_step;
|
||||
size_t byte_start;
|
||||
int byte_step;
|
||||
|
||||
unsigned char *bytep, *wordp, *last_wordp;
|
||||
size_t index_in_word;
|
||||
BDIGIT_DBL dd;
|
||||
int numbits_in_dd;
|
||||
|
||||
word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
|
||||
if (word_num_partialbits == CHAR_BIT)
|
||||
word_num_partialbits = 0;
|
||||
word_num_fullbytes = wordsize - (nails / CHAR_BIT);
|
||||
if (word_num_partialbits != 0) {
|
||||
word_num_fullbytes--;
|
||||
word_num_nailbytes = wordsize - word_num_fullbytes - 1;
|
||||
}
|
||||
else {
|
||||
word_num_nailbytes = wordsize - word_num_fullbytes;
|
||||
}
|
||||
|
||||
if (wordorder == 1) {
|
||||
word_step = -(ssize_t)wordsize;
|
||||
wordp = buf + wordsize*(wordcount-1);
|
||||
last_wordp = buf;
|
||||
}
|
||||
else {
|
||||
word_step = wordsize;
|
||||
wordp = buf;
|
||||
last_wordp = buf + wordsize*(wordcount-1);
|
||||
}
|
||||
|
||||
if (endian == 1) {
|
||||
byte_step = -1;
|
||||
byte_start = wordsize-1;
|
||||
}
|
||||
else {
|
||||
byte_step = 1;
|
||||
byte_start = 0;
|
||||
}
|
||||
|
||||
dd = 0;
|
||||
numbits_in_dd = 0;
|
||||
|
||||
#define FILL_DD \
|
||||
int_export_fill_dd(&dp, &de, &dd, &numbits_in_dd)
|
||||
#define TAKE_LOWBITS(n) \
|
||||
int_export_take_lowbits(n, &dd, &numbits_in_dd)
|
||||
|
||||
while (1) {
|
||||
index_in_word = 0;
|
||||
bytep = wordp + byte_start;
|
||||
while (index_in_word < word_num_fullbytes) {
|
||||
FILL_DD;
|
||||
*bytep = TAKE_LOWBITS(CHAR_BIT);
|
||||
bytep += byte_step;
|
||||
index_in_word++;
|
||||
}
|
||||
if (word_num_partialbits) {
|
||||
FILL_DD;
|
||||
*bytep = TAKE_LOWBITS(word_num_partialbits);
|
||||
bytep += byte_step;
|
||||
index_in_word++;
|
||||
}
|
||||
while (wordsize - word_num_nailbytes <= index_in_word && index_in_word < wordsize) {
|
||||
*bytep = 0;
|
||||
bytep += byte_step;
|
||||
index_in_word++;
|
||||
}
|
||||
|
||||
if (wordp == last_wordp)
|
||||
break;
|
||||
|
||||
wordp += word_step;
|
||||
}
|
||||
if (dp != de || dd)
|
||||
sign *= 2; /* overflow */
|
||||
}
|
||||
|
||||
if (signp)
|
||||
*signp = sign;
|
||||
|
||||
if (!bufarg)
|
||||
*countp = wordcount;
|
||||
|
||||
return buf;
|
||||
#undef FILL_DD
|
||||
#undef TAKE_LOWBITS
|
||||
}
|
||||
|
||||
#define QUAD_SIZE 8
|
||||
|
||||
#if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
|
||||
|
|
|
@ -1234,6 +1234,7 @@ RUBY_REPLACE_TYPE(gid_t, int, GIDT)
|
|||
RUBY_REPLACE_TYPE(time_t, [], TIMET, [@%:@include <time.h>])
|
||||
RUBY_REPLACE_TYPE(dev_t, [int long "long long"], DEVT)
|
||||
RUBY_REPLACE_TYPE(mode_t, ["unsigned int" long], MODET, [@%:@include <sys/stat.h>])
|
||||
RUBY_REPLACE_TYPE(size_t, ["unsigned int" "unsigned long" "unsigned long long"], SIZE)
|
||||
RUBY_REPLACE_TYPE(rlim_t, [int long "long long"], RLIM, [
|
||||
@%:@ifdef HAVE_SYS_TYPES_H
|
||||
@%:@include <sys/types.h>
|
||||
|
@ -1482,7 +1483,6 @@ fi
|
|||
AC_TYPE_SIZE_T
|
||||
RUBY_CHECK_SIZEOF(size_t, [int long void*], [], [@%:@include <sys/types.h>])
|
||||
RUBY_CHECK_SIZEOF(ptrdiff_t, size_t, [], [@%:@include <stddef.h>])
|
||||
RUBY_CHECK_PRINTF_PREFIX(size_t, z)
|
||||
RUBY_CHECK_PRINTF_PREFIX(ptrdiff_t, t)
|
||||
AC_STRUCT_ST_BLKSIZE
|
||||
AC_STRUCT_ST_BLOCKS
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#include "ruby.h"
|
||||
#include "internal.h"
|
||||
|
||||
static VALUE
|
||||
rb_int_export_m(VALUE val, VALUE buf, VALUE wordorder, VALUE wordsize_arg, VALUE endian, VALUE nails)
|
||||
{
|
||||
int sign;
|
||||
size_t count;
|
||||
void *ret;
|
||||
size_t wordsize = NUM2SIZE(wordsize_arg);
|
||||
|
||||
if (!NIL_P(buf)) {
|
||||
StringValue(buf);
|
||||
rb_str_modify(buf);
|
||||
count = RSTRING_LEN(buf) / wordsize;
|
||||
}
|
||||
|
||||
ret = rb_int_export(val,
|
||||
&sign, NIL_P(buf) ? NULL : RSTRING_PTR(buf), &count,
|
||||
NUM2INT(wordorder), wordsize, NUM2INT(endian), NUM2INT(nails));
|
||||
|
||||
return rb_ary_new_from_args(3, INT2NUM(sign), ret ? rb_str_new(ret, wordsize * count) : Qnil, SIZE2NUM(count));
|
||||
}
|
||||
|
||||
void
|
||||
Init_export(VALUE klass)
|
||||
{
|
||||
rb_define_method(rb_cInteger, "test_export", rb_int_export_m, 5);
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
|
||||
$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
|
||||
inits = $srcs.map {|s| File.basename(s, ".*")}
|
||||
inits.delete("init")
|
||||
|
|
|
@ -99,6 +99,8 @@ VALUE rb_big_fdiv(VALUE x, VALUE y);
|
|||
VALUE rb_big_uminus(VALUE x);
|
||||
VALUE rb_integer_float_cmp(VALUE x, VALUE y);
|
||||
VALUE rb_integer_float_eq(VALUE x, VALUE y);
|
||||
size_t rb_absint_size(VALUE val, int *number_of_leading_zero_bits);
|
||||
size_t rb_absint_size_in_word(VALUE val, size_t word_numbits, size_t *number_of_leading_zero_bits);
|
||||
|
||||
/* class.c */
|
||||
VALUE rb_obj_methods(int argc, VALUE *argv, VALUE obj);
|
||||
|
@ -423,6 +425,9 @@ const char *rb_objspace_data_type_name(VALUE obj);
|
|||
/* Temporary. This API will be removed (renamed). */
|
||||
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
|
||||
|
||||
/* bignum.c */
|
||||
void *rb_int_export(VALUE val, int *signp, void *bufarg, size_t *countp, int wordorder, size_t wordsize, int endian, size_t nails);
|
||||
|
||||
/* io.c */
|
||||
void rb_maygvl_fd_fix_cloexec(int fd);
|
||||
|
||||
|
|
61
pack.c
61
pack.c
|
@ -1011,50 +1011,35 @@ pack_pack(VALUE ary, VALUE fmt)
|
|||
|
||||
case 'w': /* BER compressed integer */
|
||||
while (len-- > 0) {
|
||||
unsigned long ul;
|
||||
VALUE buf = rb_str_new(0, 0);
|
||||
char c, *bufs, *bufe;
|
||||
size_t numbytes;
|
||||
int sign;
|
||||
size_t count;
|
||||
char *cp;
|
||||
|
||||
from = NEXTFROM;
|
||||
if (RB_TYPE_P(from, T_BIGNUM)) {
|
||||
VALUE big128 = rb_uint2big(128);
|
||||
while (RB_TYPE_P(from, T_BIGNUM)) {
|
||||
from = rb_big_divmod(from, big128);
|
||||
c = castchar(NUM2INT(RARRAY_AREF(from, 1)) | 0x80); /* mod */
|
||||
rb_str_buf_cat(buf, &c, sizeof(char));
|
||||
from = RARRAY_AREF(from, 0); /* div */
|
||||
}
|
||||
}
|
||||
from = rb_to_int(from);
|
||||
numbytes = rb_absint_size_in_word(from, 7, NULL);
|
||||
if (numbytes == 0)
|
||||
numbytes = 1;
|
||||
buf = rb_str_new(NULL, numbytes);
|
||||
|
||||
{
|
||||
long l = NUM2LONG(from);
|
||||
if (l < 0) {
|
||||
rb_raise(rb_eArgError, "can't compress negative numbers");
|
||||
}
|
||||
ul = l;
|
||||
}
|
||||
count = RSTRING_LEN(buf);
|
||||
rb_int_export(from, &sign, RSTRING_PTR(buf), &count, 1, 1, 1, 1);
|
||||
|
||||
while (ul) {
|
||||
c = castchar((ul & 0x7f) | 0x80);
|
||||
rb_str_buf_cat(buf, &c, sizeof(char));
|
||||
ul >>= 7;
|
||||
}
|
||||
if (sign < 0)
|
||||
rb_raise(rb_eArgError, "can't compress negative numbers");
|
||||
if (sign == 2)
|
||||
rb_bug("buffer size problem?");
|
||||
|
||||
if (RSTRING_LEN(buf)) {
|
||||
bufs = RSTRING_PTR(buf);
|
||||
bufe = bufs + RSTRING_LEN(buf) - 1;
|
||||
*bufs &= 0x7f; /* clear continue bit */
|
||||
while (bufs < bufe) { /* reverse */
|
||||
c = *bufs;
|
||||
*bufs++ = *bufe;
|
||||
*bufe-- = c;
|
||||
}
|
||||
rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
|
||||
}
|
||||
else {
|
||||
c = 0;
|
||||
rb_str_buf_cat(res, &c, sizeof(char));
|
||||
}
|
||||
cp = RSTRING_PTR(buf);
|
||||
while (1 < numbytes) {
|
||||
*cp |= 0x80;
|
||||
cp++;
|
||||
numbytes--;
|
||||
}
|
||||
|
||||
rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# coding: ASCII-8BIT
|
||||
|
||||
require 'test/unit'
|
||||
require "-test-/bignum"
|
||||
|
||||
class TestBignum < Test::Unit::TestCase
|
||||
class TestExport < Test::Unit::TestCase
|
||||
def test_export_zero
|
||||
assert_equal([0, "", 0], 0.test_export(nil, 1, 1, 1, 0))
|
||||
end
|
||||
|
||||
def test_argument_check
|
||||
assert_raise(ArgumentError) { 0.test_export(nil, 0, 1, 1, 0) }
|
||||
assert_raise(ArgumentError) { 0.test_export(nil, 1, 1, 2, 0) }
|
||||
assert_raise(ArgumentError) { 0.test_export(nil, 1, 0, 1, 0) }
|
||||
assert_raise(ArgumentError) { 0.test_export(nil, 1, 1, 1, 8) }
|
||||
|
||||
# assume sizeof(ssize_t) == sizeof(intptr_t)
|
||||
assert_raise(ArgumentError) { 0.test_export(nil, 1, 1 << ([""].pack("p").length * 8 - 1), 1, 0) }
|
||||
end
|
||||
|
||||
def test_export_wordsize
|
||||
assert_equal([1, "\x01", 1], 1.test_export(nil, 1, 1, 1, 0))
|
||||
assert_equal([1, "\x00\x01", 1], 1.test_export(nil, 1, 2, 1, 0))
|
||||
assert_equal([1, "\x00\x00\x01", 1], 1.test_export(nil, 1, 3, 1, 0))
|
||||
assert_equal([1, "\x01", 1], 1.test_export(nil, 1, 1, -1, 0))
|
||||
assert_equal([1, "\x01\x00", 1], 1.test_export(nil, 1, 2, -1, 0))
|
||||
assert_equal([1, "\x01\x00\x00", 1], 1.test_export(nil, 1, 3, -1, 0))
|
||||
end
|
||||
|
||||
def test_export_fixed_buffer
|
||||
assert_equal([0, "\x00\x00", 2], 0.test_export("xx", 1, 1, 1, 0))
|
||||
assert_equal([1, "\x00\x01", 2], 0x01.test_export("xx", 1, 1, 1, 0))
|
||||
assert_equal([1, "\x02\x01", 2], 0x0201.test_export("xx", 1, 1, 1, 0))
|
||||
assert_equal([2, "\x02\x01", 2], 0x030201.test_export("xx", 1, 1, 1, 0))
|
||||
assert_equal([2, "\x02\x01", 2], 0x04030201.test_export("xx", 1, 1, 1, 0))
|
||||
assert_equal([0, "\x00\x00", 2], 0.test_export("xx", -1, 1, 1, 0))
|
||||
assert_equal([1, "\x01\x00", 2], 0x01.test_export("xx", -1, 1, 1, 0))
|
||||
assert_equal([1, "\x01\x02", 2], 0x0201.test_export("xx", -1, 1, 1, 0))
|
||||
assert_equal([2, "\x01\x02", 2], 0x030201.test_export("xx", -1, 1, 1, 0))
|
||||
assert_equal([2, "\x01\x02", 2], 0x04030201.test_export("xx", -1, 1, 1, 0))
|
||||
end
|
||||
|
||||
def test_export_wordorder_and_endian
|
||||
assert_equal([1, "\x12\x34\x56\x78", 2], 0x12345678.test_export(nil, 1, 2, 1, 0))
|
||||
assert_equal([1, "\x34\x12\x78\x56", 2], 0x12345678.test_export(nil, 1, 2, -1, 0))
|
||||
assert_equal([1, "\x56\x78\x12\x34", 2], 0x12345678.test_export(nil, -1, 2, 1, 0))
|
||||
assert_equal([1, "\x78\x56\x34\x12", 2], 0x12345678.test_export(nil, -1, 2, -1, 0))
|
||||
end
|
||||
|
||||
def test_export_native_endian
|
||||
assert_equal([1, [0x1234].pack("S!"), 1], 0x1234.test_export(nil, 1, 2, 0, 0))
|
||||
end
|
||||
|
||||
def test_export_nail
|
||||
assert_equal([1, "\x01\x00\x00\x00\x01\x01", 6], 0b100011.test_export(nil, 1, 1, 1, 7))
|
||||
assert_equal([1, "\x01\x02\x03\x04\x05\x06\x07\x08", 8], 0x12345678.test_export(nil, 1, 1, 1, 4))
|
||||
assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78", 4], 0x12345678.test_export(nil, 1, 2, 1, 8))
|
||||
end
|
||||
|
||||
def test_export_sign
|
||||
assert_equal([-1, "\x01", 1], (-1).test_export(nil, 1, 1, 1, 0))
|
||||
assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10", 8], (-0x8070605040302010).test_export(nil, 1, 1, 1, 0))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Загрузка…
Ссылка в новой задаче