VALUE
rb_dlptr_s_to_ptr(VALUE self, VALUE val)
{
VALUE ptr;
if (rb_obj_is_kind_of(val, rb_cIO) == Qtrue){
rb_io_t *fptr;
FILE *fp;
GetOpenFile(val, fptr);
fp = rb_io_stdio_file(fptr);
ptr = rb_dlptr_new(fp, 0, NULL);
}
else if (rb_obj_is_kind_of(val, rb_cString) == Qtrue){
char *str = StringValuePtr(val);
ptr = rb_dlptr_new(str, RSTRING_LEN(val), NULL);
}
else if (rb_respond_to(val, id_to_ptr)){
VALUE vptr = rb_funcall(val, id_to_ptr, 0);
if (rb_obj_is_kind_of(vptr, rb_cDLCPtr)){
ptr = vptr;
}
else{
rb_raise(rb_eDLError, "to_ptr should return a CPtr object");
}
}
else{
ptr = rb_dlptr_new(NUM2PTR(rb_Integer(val)), 0, NULL);
}
OBJ_INFECT(ptr, val);
return ptr;
}
static VALUE
rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
{
VALUE size, sym, obj;
int s;
freefunc_t f;
switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
case 1:
s = NUM2LONG(size);
f = NULL;
break;
case 2:
s = NUM2LONG(size);
f = get_freefunc(sym);
break;
default:
rb_bug("rb_dlptr_s_malloc");
}
obj = rb_dlptr_malloc(s,f);
return obj;
}
static VALUE
rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
{
VALUE ptr, sym, size;
struct ptr_data *data;
void *p = NULL;
freefunc_t f = NULL;
long s = 0;
switch (rb_scan_args(argc, argv, "12", &ptr, &size, &sym)) {
case 1:
p = (void*)(NUM2PTR(rb_Integer(ptr)));
break;
case 2:
p = (void*)(NUM2PTR(rb_Integer(ptr)));
s = NUM2LONG(size);
break;
case 3:
p = (void*)(NUM2PTR(rb_Integer(ptr)));
s = NUM2LONG(size);
f = get_freefunc(sym);
break;
default:
rb_bug("rb_dlptr_initialize");
}
if (p) {
Data_Get_Struct(self, struct ptr_data, data);
if (data->ptr && data->free) {
/* Free previous memory. Use of inappropriate initialize may cause SEGV. */
(*(data->free))(data->ptr);
}
data->ptr = p;
data->size = s;
data->free = f;
}
return Qnil;
}
VALUE
rb_dlptr_s_to_ptr(VALUE self, VALUE val)
{
VALUE ptr;
if (rb_obj_is_kind_of(val, rb_cIO) == Qtrue){
rb_io_t *fptr;
FILE *fp;
GetOpenFile(val, fptr);
fp = rb_io_stdio_file(fptr);
ptr = rb_dlptr_new(fp, 0, NULL);
}
else if (rb_obj_is_kind_of(val, rb_cString) == Qtrue){
char *str = StringValuePtr(val);
ptr = rb_dlptr_new(str, RSTRING_LEN(val), NULL);
}
else if (rb_respond_to(val, id_to_ptr)){
VALUE vptr = rb_funcall(val, id_to_ptr, 0);
if (rb_obj_is_kind_of(vptr, rb_cDLCPtr)){
ptr = vptr;
}
else{
rb_raise(rb_eDLError, "to_ptr should return a CPtr object");
}
}
else{
ptr = rb_dlptr_new(NUM2PTR(rb_Integer(val)), 0, NULL);
}
OBJ_INFECT(ptr, val);
return ptr;
}
VALUE
rb_dlptr_plus(VALUE self, VALUE other)
{
void *ptr;
long num, size;
ptr = rb_dlptr2cptr(self);
size = RPTR_DATA(self)->size;
num = NUM2LONG(other);
return rb_dlptr_new((char *)ptr + num, size - num, 0);
}
VALUE
rb_dlptr_ptr(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return rb_dlptr_new(*((void**)(data->ptr)),0,0);
}
VALUE
rb_dlptr_minus(VALUE self, VALUE other)
{
void *ptr;
long num, size;
ptr = rb_dlptr2cptr(self);
size = RPTR_DATA(self)->size;
num = NUM2LONG(other);
return rb_dlptr_new((char *)ptr - num, size + num, 0);
}
VALUE
rb_dlptr_ref(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return rb_dlptr_new(&(data->ptr),0,0);
}
VALUE
rb_dlptr_cmp(VALUE self, VALUE other)
{
void *ptr1, *ptr2;
SIGNED_VALUE diff;
ptr1 = rb_dlptr2cptr(self);
ptr2 = rb_dlptr2cptr(other);
diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
if (!diff) return INT2FIX(0);
return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
}
VALUE
rb_dlptr_eql(VALUE self, VALUE other)
{
void *ptr1, *ptr2;
ptr1 = rb_dlptr2cptr(self);
ptr2 = rb_dlptr2cptr(other);
return ptr1 == ptr2 ? Qtrue : Qfalse;
}
VALUE
rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
{
VALUE arg0, arg1;
VALUE retval = Qnil;
size_t offset, len;
switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
case 1:
offset = NUM2ULONG(arg0);
retval = INT2NUM(*((char*)RPTR_DATA(self)->ptr + offset));
break;
case 2:
offset = NUM2ULONG(arg0);
len = NUM2ULONG(arg1);
retval = rb_tainted_str_new((char *)RPTR_DATA(self)->ptr + offset, len);
break;
default:
rb_bug("rb_dlptr_aref()");
}
return retval;
}
VALUE
rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
{
VALUE arg0, arg1, arg2;
VALUE retval = Qnil;
size_t offset, len;
void *mem;
switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
case 2:
offset = NUM2ULONG(arg0);
((char*)RPTR_DATA(self)->ptr)[offset] = NUM2UINT(arg1);
retval = arg1;
break;
case 3:
offset = NUM2ULONG(arg0);
len = NUM2ULONG(arg1);
if( TYPE(arg2) == T_STRING ){
mem = StringValuePtr(arg2);
}
else if( rb_obj_is_kind_of(arg2, rb_cDLCPtr) ){
mem = rb_dlptr2cptr(arg2);
}
else{
mem = NUM2PTR(arg2);
}
memcpy((char *)RPTR_DATA(self)->ptr + offset, mem, len);
retval = arg2;
break;
default:
rb_bug("rb_dlptr_aset()");
}
return retval;
}
VALUE
rb_dlptr_eql(VALUE self, VALUE other)
{
void *ptr1, *ptr2;
ptr1 = rb_dlptr2cptr(self);
ptr2 = rb_dlptr2cptr(other);
return ptr1 == ptr2 ? Qtrue : Qfalse;
}
VALUE
rb_dlptr_free_get(VALUE self)
{
struct ptr_data *pdata;
Data_Get_Struct(self, struct ptr_data, pdata);
return rb_dlcfunc_new(pdata->free, DLTYPE_VOID, "free<anonymous>", CFUNC_CDECL);
}
VALUE
rb_dlptr_free_set(VALUE self, VALUE val)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
data->free = get_freefunc(val);
return Qnil;
}
VALUE
rb_dlptr_inspect(VALUE self)
{
struct ptr_data *data;
char str[1024];
Data_Get_Struct(self, struct ptr_data, data);
snprintf(str, 1023, "#<%s:%p ptr=%p size=%ld free=%p>",
rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
return rb_str_new2(str);
}
VALUE
rb_dlptr_null_p(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return data->ptr ? Qfalse : Qtrue;
}
VALUE
rb_dlptr_ptr(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return rb_dlptr_new(*((void**)(data->ptr)),0,0);
}
VALUE
rb_dlptr_ref(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return rb_dlptr_new(&(data->ptr),0,0);
}
VALUE
rb_dlptr_size(int argc, VALUE argv[], VALUE self)
{
VALUE size;
if (rb_scan_args(argc, argv, "01", &size) == 0){
return LONG2NUM(RPTR_DATA(self)->size);
}
else{
RPTR_DATA(self)->size = NUM2LONG(size);
return size;
}
}
VALUE
rb_dlptr_size(int argc, VALUE argv[], VALUE self)
{
VALUE size;
if (rb_scan_args(argc, argv, "01", &size) == 0){
return LONG2NUM(RPTR_DATA(self)->size);
}
else{
RPTR_DATA(self)->size = NUM2LONG(size);
return size;
}
}
VALUE
rb_dlptr_to_i(VALUE self)
{
struct ptr_data *data;
Data_Get_Struct(self, struct ptr_data, data);
return PTR2NUM(data->ptr);
}
VALUE
rb_dlptr_to_s(int argc, VALUE argv[], VALUE self)
{
struct ptr_data *data;
VALUE arg1, val;
int len;
Data_Get_Struct(self, struct ptr_data, data);
switch (rb_scan_args(argc, argv, "01", &arg1)) {
case 0:
val = rb_tainted_str_new2((char*)(data->ptr));
break;
case 1:
len = NUM2INT(arg1);
val = rb_tainted_str_new((char*)(data->ptr), len);
break;
default:
rb_bug("rb_dlptr_to_s");
}
return val;
}
VALUE
rb_dlptr_to_str(int argc, VALUE argv[], VALUE self)
{
struct ptr_data *data;
VALUE arg1, val;
int len;
Data_Get_Struct(self, struct ptr_data, data);
switch (rb_scan_args(argc, argv, "01", &arg1)) {
case 0:
val = rb_tainted_str_new((char*)(data->ptr),data->size);
break;
case 1:
len = NUM2INT(arg1);
val = rb_tainted_str_new((char*)(data->ptr), len);
break;
default:
rb_bug("rb_dlptr_to_str");
}
return val;
}
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please see Improve the docs, or visit Documenting-ruby.org.