Skip to content

Commit e84102d

Browse files
committed
Removed MRB_INT64 limitation.
1 parent 858a7b3 commit e84102d

File tree

8 files changed

+123
-54
lines changed

8 files changed

+123
-54
lines changed

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ If you want to run tests, please run below command.
2121
make test
2222

2323

24-
## Limitation
25-
26-
* mrb_int should be 64bit int. define MRB_INT64 in mrbconf.h
27-
28-
2924
## Todo
3025

3126
* Test!

run_test.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
MRuby::Build.new do |conf|
1313
toolchain :gcc
14-
conf.cc.defines << %w(MRB_INT64)
1514
conf.gem File.expand_path(File.dirname(__FILE__)) do |g|
1615
# g.use_pkg_config
1716
g.download_libffi

src/cfunc.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ cfunc_mrb_state(mrb_state *mrb, mrb_value klass)
2929
void
3030
mrb_mruby_cfunc_gem_init(mrb_state* mrb)
3131
{
32-
if(sizeof(mrb_int) < 8) {
33-
fprintf(stderr, "mruby-cfunc require 64bit for mrb_int.");
34-
}
35-
3632
struct RClass *ns = mrb_define_module(mrb, "CFunc");
3733
struct cfunc_state *state = mrb_malloc(mrb, sizeof(struct cfunc_state));
3834
set_cfunc_state(mrb, ns, state);

src/cfunc_type.c

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <stdio.h>
2222
#include <inttypes.h>
2323

24+
#define DONE mrb_gc_arena_restore(mrb, ai);
2425

2526
static void
2627
cfunc_type_destructor(mrb_state *mrb, void *p)
@@ -203,7 +204,18 @@ cfunc_type_addr(mrb_state *mrb, mrb_value self)
203204

204205

205206
static
206-
mrb_int fixnum_value(mrb_state *mrb, mrb_value val)
207+
mrb_value int64_to_mrb(int64_t val)
208+
{
209+
if(val < MRB_INT_MIN || val > MRB_INT_MAX) {
210+
return mrb_float_value(val);
211+
}
212+
else {
213+
return mrb_fixnum_value(val);
214+
}
215+
}
216+
217+
static
218+
int64_t mrb_to_int64(mrb_state *mrb, mrb_value val)
207219
{
208220
switch(mrb_type(val)) {
209221
case MRB_TT_FIXNUM:
@@ -292,10 +304,10 @@ cfunc_uint64_class_get(mrb_state *mrb, mrb_value klass)
292304
struct mrb_ffi_type *mft = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(klass));
293305
uint64_t uint64 = *(uint64_t*)cfunc_pointer_ptr(pointer);
294306

295-
if(uint64 > MRB_INT_MAX) {
307+
if(uint64 > UINT32_MAX) {
296308
mrb_raise(mrb, E_TYPE_ERROR, "too big. Use low, high");
297309
}
298-
return mrb_fixnum_value(uint64);
310+
return int64_to_mrb(uint64);
299311
}
300312

301313

@@ -307,19 +319,19 @@ cfunc_uint64_get_value(mrb_state *mrb, mrb_value self)
307319
if(data->refer) {
308320
uint64 = *(uint64_t*)data->value._pointer;
309321
}
310-
if(uint64 > MRB_INT_MAX) {
322+
if(uint64 > UINT32_MAX) {
311323
mrb_raise(mrb, E_TYPE_ERROR, "too big. Use low, high");
312324
}
313325

314-
return mrb_fixnum_value(uint64);
326+
return int64_to_mrb(uint64);
315327
}
316328

317329

318330
mrb_value
319331
cfunc_uint64_get_low(mrb_state *mrb, mrb_value self)
320332
{
321333
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
322-
return mrb_fixnum_value(data->value._uint64 & 0xffffffff);
334+
return int64_to_mrb(data->value._uint64 & 0xffffffff);
323335
}
324336

325337

@@ -330,7 +342,7 @@ cfunc_uint64_set_low(mrb_state *mrb, mrb_value self)
330342
mrb_get_args(mrb, "o", &val);
331343

332344
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
333-
data->value._uint64 = (data->value._uint64 & 0xffffffff00000000) | (((uint64_t)fixnum_value(mrb, val)) & 0xffffffff);
345+
data->value._uint64 = (data->value._uint64 & 0xffffffff00000000) | (((uint64_t)mrb_to_int64(mrb, val)) & 0xffffffff);
334346
return val;
335347
}
336348

@@ -339,7 +351,7 @@ mrb_value
339351
cfunc_uint64_get_high(mrb_state *mrb, mrb_value self)
340352
{
341353
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
342-
return mrb_fixnum_value(data->value._uint64 >> 32);
354+
return int64_to_mrb(data->value._uint64 >> 32);
343355
}
344356

345357

@@ -350,7 +362,7 @@ cfunc_uint64_set_high(mrb_state *mrb, mrb_value self)
350362
mrb_get_args(mrb, "o", &val);
351363

352364
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
353-
data->value._uint64 = (data->value._uint64 & 0x00000000ffffffff) | (((uint64_t)fixnum_value(mrb, val)) << 32);
365+
data->value._uint64 = (data->value._uint64 & 0x00000000ffffffff) | (((uint64_t)mrb_to_int64(mrb, val)) << 32);
354366

355367
return val;
356368
}
@@ -366,6 +378,50 @@ cfunc_uint64_to_s(mrb_state *mrb, mrb_value self)
366378
}
367379

368380

381+
382+
383+
// sint64 specific
384+
mrb_value
385+
cfunc_sint64_class_get(mrb_state *mrb, mrb_value klass)
386+
{
387+
mrb_value pointer;
388+
mrb_get_args(mrb, "o", &pointer);
389+
390+
struct mrb_ffi_type *mft = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(klass));
391+
int64_t sint64 = *(int64_t*)cfunc_pointer_ptr(pointer);
392+
393+
if(sint64 > INT32_MAX || sint64 < INT32_MIN) {
394+
mrb_raise(mrb, E_TYPE_ERROR, "out of range. Use low, high");
395+
}
396+
return int64_to_mrb(sint64);
397+
}
398+
399+
400+
mrb_value
401+
cfunc_sint64_get_value(mrb_state *mrb, mrb_value self)
402+
{
403+
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
404+
int64_t sint64 = data->value._sint64;
405+
if(data->refer) {
406+
sint64 = *(int64_t*)data->value._pointer;
407+
}
408+
if(sint64 > INT32_MAX || sint64 < INT32_MIN) {
409+
mrb_raise(mrb, E_TYPE_ERROR, "out of range. Use low, high");
410+
}
411+
return int64_to_mrb(sint64);
412+
}
413+
414+
415+
mrb_value
416+
cfunc_int64_to_s(mrb_state *mrb, mrb_value self)
417+
{
418+
struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);
419+
char str[65];
420+
snprintf(str, sizeof(str), "%" PRId64, data->value._sint64);
421+
return mrb_str_new_cstr(mrb, str);
422+
}
423+
424+
369425
// nil specific
370426
mrb_value
371427
cfunc_nil_addr(mrb_state *mrb, mrb_value self)
@@ -475,17 +531,17 @@ cfunc_type_ffi_##name##_mrb_to_data(mrb_state *mrb, mrb_value val, struct cfunc_
475531
.data_to_mrb = &cfunc_type_ffi_##type_##_data_to_mrb \
476532
}
477533

478-
define_cfunc_type(sint8, &ffi_type_sint8, int8_t, mrb_fixnum_value, fixnum_value);
479-
define_cfunc_type(uint8, &ffi_type_uint8, uint8_t, mrb_fixnum_value, fixnum_value);
534+
define_cfunc_type(sint8, &ffi_type_sint8, int8_t, int64_to_mrb, mrb_to_int64);
535+
define_cfunc_type(uint8, &ffi_type_uint8, uint8_t, int64_to_mrb, mrb_to_int64);
480536

481-
define_cfunc_type(sint16, &ffi_type_sint16, int16_t, mrb_fixnum_value, fixnum_value);
482-
define_cfunc_type(uint16, &ffi_type_uint16, uint16_t, mrb_fixnum_value, fixnum_value);
537+
define_cfunc_type(sint16, &ffi_type_sint16, int16_t, int64_to_mrb, mrb_to_int64);
538+
define_cfunc_type(uint16, &ffi_type_uint16, uint16_t, int64_to_mrb, mrb_to_int64);
483539

484-
define_cfunc_type(sint32, &ffi_type_sint32, int32_t, mrb_fixnum_value, fixnum_value);
485-
define_cfunc_type(uint32, &ffi_type_uint32, uint32_t, mrb_fixnum_value, fixnum_value);
540+
define_cfunc_type(sint32, &ffi_type_sint32, int32_t, int64_to_mrb, mrb_to_int64);
541+
define_cfunc_type(uint32, &ffi_type_uint32, uint32_t, int64_to_mrb, mrb_to_int64);
486542

487-
define_cfunc_type(sint64, &ffi_type_sint64, int64_t, mrb_fixnum_value, fixnum_value);
488-
define_cfunc_type(uint64, &ffi_type_uint64, uint64_t, mrb_fixnum_value, fixnum_value);
543+
define_cfunc_type(sint64, &ffi_type_sint64, int64_t, int64_to_mrb, mrb_to_int64);
544+
define_cfunc_type(uint64, &ffi_type_uint64, uint64_t, int64_to_mrb, mrb_to_int64);
489545

490546
define_cfunc_type(float, &ffi_type_float, float, mrb_float_value, float_value);
491547
define_cfunc_type(double, &ffi_type_double, double, mrb_float_value, float_value);
@@ -523,6 +579,7 @@ void init_cfunc_type(mrb_state *mrb, struct RClass* module)
523579
state->type_class = type_class;
524580
set_cfunc_state(mrb, (struct RObject*)type_class, state);
525581

582+
int ai = mrb_gc_arena_save(mrb);
526583
mrb_define_class_method(mrb, type_class, "refer", cfunc_type_class_refer, ARGS_REQ(1));
527584
mrb_define_class_method(mrb, type_class, "size", cfunc_type_size, ARGS_NONE());
528585
mrb_define_class_method(mrb, type_class, "align", cfunc_type_align, ARGS_NONE());
@@ -534,6 +591,7 @@ void init_cfunc_type(mrb_state *mrb, struct RClass* module)
534591
mrb_define_method(mrb, type_class, "value=", cfunc_type_set_value, ARGS_REQ(1));
535592
mrb_define_method(mrb, type_class, "addr", cfunc_type_addr, ARGS_NONE());
536593
mrb_define_method(mrb, type_class, "to_ffi_value", cfunc_type_addr, ARGS_NONE());
594+
DONE;
537595

538596
int map_size = sizeof(types) / sizeof(struct mrb_ffi_type);
539597
int i;
@@ -542,6 +600,7 @@ void init_cfunc_type(mrb_state *mrb, struct RClass* module)
542600
mrb_value ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_class_ffi_data_type, &types[i]));
543601
mrb_obj_iv_set(mrb, (struct RObject*)new_class, mrb_intern(mrb, "@ffi_type"), ffi_type);
544602
}
603+
DONE;
545604

546605
mrb_value mod = mrb_obj_value(module);
547606
state->void_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Void")));
@@ -555,11 +614,13 @@ void init_cfunc_type(mrb_state *mrb, struct RClass* module)
555614
state->sint64_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "SInt64")));
556615
state->float_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Float")));
557616
state->double_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Double")));
617+
DONE;
558618

559619
mrb_define_class_method(mrb, mrb->nil_class, "size", cfunc_nil_size, ARGS_NONE());
560620
mrb_define_class_method(mrb, mrb->nil_class, "align", cfunc_nil_align, ARGS_NONE());
621+
DONE;
561622

562-
// sint64 specific
623+
// uint64 specific
563624
struct RClass *uint64_class = state->uint64_class;
564625
mrb_define_class_method(mrb, uint64_class, "get", cfunc_uint64_class_get, ARGS_REQ(1));
565626
mrb_define_method(mrb, uint64_class, "value", cfunc_uint64_get_value, ARGS_NONE());
@@ -568,4 +629,16 @@ void init_cfunc_type(mrb_state *mrb, struct RClass* module)
568629
mrb_define_method(mrb, uint64_class, "high", cfunc_uint64_get_high, ARGS_NONE());
569630
mrb_define_method(mrb, uint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1));
570631
mrb_define_method(mrb, uint64_class, "to_s", cfunc_uint64_to_s, ARGS_REQ(1));
632+
DONE;
633+
634+
// sint64 specific
635+
struct RClass *sint64_class = state->sint64_class;
636+
mrb_define_class_method(mrb, sint64_class, "get", cfunc_sint64_class_get, ARGS_REQ(1));
637+
mrb_define_method(mrb, sint64_class, "value", cfunc_sint64_get_value, ARGS_NONE());
638+
mrb_define_method(mrb, sint64_class, "low", cfunc_uint64_get_low, ARGS_NONE());
639+
mrb_define_method(mrb, sint64_class, "low=", cfunc_uint64_set_low, ARGS_REQ(1));
640+
mrb_define_method(mrb, sint64_class, "high", cfunc_uint64_get_high, ARGS_NONE());
641+
mrb_define_method(mrb, sint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1));
642+
mrb_define_method(mrb, sint64_class, "to_s", cfunc_int64_to_s, ARGS_REQ(1));
643+
DONE;
571644
}

test/sint32.rb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@
2424
assert_equal idx, CFunc::SInt32.refer(sint_ptr).value
2525
end
2626

27-
sint.value = (1<<31)-1
28-
assert_equal (1<<31)-1, sint.value
29-
assert_equal (1<<31)-1, CFunc::SInt32.get(sint_ptr)
27+
sint32_max = 2147483647
28+
sint32_min = -2147483647
3029

31-
CFunc::SInt32.set(sint_ptr, (1<<31))
32-
assert_not_equal (1<<31), sint.value
30+
sint.value = sint32_max
31+
assert_equal sint32_max, sint.value
32+
assert_equal sint32_max, CFunc::SInt32.get(sint_ptr)
3333

34-
sint.value = (-1<<31)
35-
assert_equal (-1<<31), sint.value
36-
assert_equal (-1<<31), CFunc::SInt32.get(sint_ptr)
34+
CFunc::SInt32.set(sint_ptr, sint32_max+1)
35+
assert_not_equal sint32_max+1, sint.value
3736

38-
CFunc::SInt32.set(sint_ptr, (-1<<31)-1)
39-
assert_not_equal (-1<<31)-1, sint.value
37+
sint.value = sint32_min
38+
assert_equal sint32_min, sint.value
39+
assert_equal sint32_min, CFunc::SInt32.get(sint_ptr)
40+
41+
CFunc::SInt32.set(sint_ptr, sint32_min-1)
42+
assert_not_equal sint32_min , sint.value
4043

4144
sint = CFunc::SInt32.new(CFunc::SInt16.new(16))
4245
assert_equal 16, sint.value

test/sint64.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
assert_equal idx, CFunc::SInt64.refer(sint_ptr).value
2727
end
2828

29-
sint.value = (0x7fffffff << 32) + 0xffffffff # 9223372036854775807 # MAX
30-
assert_equal (0x7fffffff << 32) + 0xffffffff, sint.value
31-
assert_equal (0x7fffffff << 32) + 0xffffffff, CFunc::SInt64.get(sint_ptr)
32-
33-
sint.value = -1 * ((0x7fffffff << 32) + 0xffffffff) - 1 # -9223372036854775808 # MIN
34-
assert_equal (-1) * ((0x7fffffff << 32) + 0xffffffff) - 1, sint.value
35-
assert_equal (-1) * ((0x7fffffff << 32) + 0xffffffff) - 1, CFunc::SInt64.get(sint_ptr)
29+
sint.value = 0x7fffffff
30+
assert_equal 0x7fffffff, sint.low
31+
assert_equal 0x00000000, sint.high
32+
assert_equal 0x7fffffff, CFunc::SInt64.get(sint_ptr)
33+
34+
sint.value = -1
35+
assert_equal 0xffffffff, sint.low
36+
assert_equal 0xffffffff, sint.high
37+
assert_equal -1, CFunc::SInt64.get(sint_ptr)
3638

3739
sint = CFunc::SInt64.new(CFunc::SInt16.new(16))
3840
assert_equal 16, sint.value

test/uint32.rb

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
assert_equal idx, CFunc::UInt32.refer(uint_ptr).value
2424
end
2525

26-
uint.value = 2**32-1
27-
assert_equal (2**32-1).to_i, uint.value
28-
assert_equal (2**32-1).to_i, CFunc::UInt32.get(uint_ptr)
26+
uint32_max = 4294967295
27+
uint32_min = 0
2928

30-
CFunc::UInt32.set(uint_ptr, 2**32)
31-
assert_not_equal 2**32, uint.value
29+
uint.value = uint32_max
30+
assert_equal uint32_max, uint.value
31+
assert_equal uint32_max, CFunc::UInt32.get(uint_ptr)
3232

33-
CFunc::UInt32.set(uint_ptr, -1)
34-
assert_not_equal (-1), uint.value
33+
CFunc::UInt32.set(uint_ptr, uint32_max+1)
34+
assert_not_equal uint32_max, uint.value
35+
36+
CFunc::UInt32.set(uint_ptr, uint32_min-1)
37+
assert_not_equal (uint32_min-1), uint.value
3538

3639
uint = CFunc::UInt32.new(CFunc::SInt16.new(16))
3740
assert_equal 16, uint.value

test/uint64.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
uint.value = 1
1010
assert_equal 1, uint.low
1111
assert_equal 0, uint.high
12-
assert_equal 0, uint.high
1312
assert_equal 1, uint.value
1413
assert_equal 1, uint.to_i
1514
assert_equal 1.0, uint.to_f
@@ -18,7 +17,6 @@
1817
uint.high = 1
1918
assert_equal 2, uint.low
2019
assert_equal 1, uint.high
21-
assert_equal (1<<32)+2, uint.value
2220
assert_equal "4294967298", uint.to_s
2321
uint_ptr = uint.addr
2422
assert uint_ptr.is_a?(CFunc::Pointer)

0 commit comments

Comments
 (0)