1 #include "class/string.hpp"
3 #include "capi/capi.hpp"
6 using namespace rubinius
;
7 using namespace rubinius::capi
;
10 /* This is a really wacky MRI API, which is actually marked internal
11 * despite being used in external code. The existing Fixnum#size and
12 * Bignum#size methods are sufficient for the 3-4 places it's used in MRI's
13 * code itself, where the 2nd argument isn't even used.
15 * We provide a "good enough" implementation.
17 size_t rb_absint_size(VALUE value
, int* nlz_bits
) {
18 NativeMethodEnvironment
* env
= NativeMethodEnvironment::get();
21 if(RB_TYPE_P(value
, T_FIXNUM
)) {
23 size
= FIXNUM_MAX_WIDTH
;
25 size
= FIXNUM_MIN_WIDTH
;
27 } else if(RB_TYPE_P(value
, T_BIGNUM
)) {
28 Bignum
* big
= MemoryHandle::object
<Bignum
>(value
);
29 size
= big
->size(env
->state())->to_native();
33 if(nlz_bits
) *nlz_bits
= 0;
38 int rb_integer_pack(VALUE value
, void *words
, size_t numwords
, size_t wordsize
,
39 size_t nails
, int flags
)
42 rb_raise(rb_eNotImpError
, "non-zero bit padding is unsupported");
45 if(((flags
& INTEGER_PACK_MSWORD_FIRST
) != 0 &&
46 (flags
& INTEGER_PACK_LSBYTE_FIRST
) != 0) ||
47 ((flags
& INTEGER_PACK_LSWORD_FIRST
) != 0 &&
48 (flags
& INTEGER_PACK_MSBYTE_FIRST
) != 0)) {
49 rb_raise(rb_eNotImpError
, "mixed byte and word ordering is unsupported");
52 value
= rb_to_int(value
);
54 size_t numbytes
= numwords
* wordsize
;
55 memset(words
, 0, numbytes
);
57 NativeMethodEnvironment
* env
= NativeMethodEnvironment::get();
59 if(Fixnum
* f
= MemoryHandle::try_as
<Fixnum
>(value
)) {
60 intptr_t v
= f
->to_native();
64 if((numbytes
>= FIXNUM_MIN_WIDTH
/ 8) &&
65 ((flags
& INTEGER_PACK_NATIVE_BYTE_ORDER
) ||
66 #ifdef RBX_LITTLE_ENDIAN
67 ((flags
& INTEGER_PACK_LSWORD_FIRST
) &&
68 (flags
& INTEGER_PACK_LSBYTE_FIRST
))
70 ((flags
& INTEGER_PACK_MSWORD_FIRST
) &&
71 (flags
& INTEGER_PACK_MSBYTE_FIRST
))
75 memcpy(words
, &v
, numbytes
);
76 return v
< 0 ? -1 : 1;
80 String
* bytes
= String::create_pinned(env
->state(), Fixnum::from(numbytes
));
81 memset(bytes
->byte_address(), 0, numbytes
);
83 VALUE result
= rb_funcall(rb_mCAPI
, rb_intern("rb_integer_pack"), 6,
84 value
, MemoryHandle::value(bytes
), INT2FIX(numwords
), INT2FIX(wordsize
),
85 INT2FIX(nails
), INT2FIX(flags
));
87 memcpy(words
, bytes
->byte_address(), numbytes
);
89 return FIX2INT(result
);