In Files

  • dl/dl.c

DL::PtrData

Public Class Methods

malloc(p1, p2 = v2) click to toggle source
 
               static VALUE
rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
{
  VALUE size, sym, obj;
  int   s;
  freefunc_t f = NULL;

  switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
  case 1:
    s = NUM2INT(size);
    break;
  case 2:
    s = NUM2INT(size);
    f = rb_dlsym2csym(sym);
    break;
  default:
    rb_bug("rb_dlptr_s_malloc");
  }

  obj = rb_dlptr_malloc(s,f);

  return obj;
}
            
new(p1, p2 = v2, p3 = v3) click to toggle source
 
               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*)(DLNUM2LONG(rb_Integer(ptr)));
    break;
  case 2:
    p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
    s = DLNUM2LONG(size);
    break;
  case 3:
    p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
    s = DLNUM2LONG(size);
    f = rb_dlsym2csym(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;
}
            

Public Instance Methods

+(p1) click to toggle source
 
               VALUE
rb_dlptr_plus(VALUE self, VALUE other)
{
  void *ptr;
  long num, size;

  ptr = rb_dlptr2cptr(self);
  size = RDLPTR(self)->size;
  num = DLNUM2LONG(other);
  return rb_dlptr_new((char *)ptr + num, size - num, 0);
}
            
+@() click to toggle source
 
               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);
}
            
-(p1) click to toggle source
 
               VALUE
rb_dlptr_minus(VALUE self, VALUE other)
{
  void *ptr;
  long num, size;

  ptr = rb_dlptr2cptr(self);
  size = RDLPTR(self)->size;
  num = DLNUM2LONG(other);
  return rb_dlptr_new((char *)ptr - num, size + num, 0);
}
            
-@() click to toggle source
 
               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);
}
            
<=>(p1) click to toggle source
 
               VALUE
rb_dlptr_cmp(VALUE self, VALUE other)
{
  void *ptr1, *ptr2;
  ptr1 = rb_dlptr2cptr(self);
  ptr2 = rb_dlptr2cptr(other);
  return DLLONG2NUM((long)ptr1 - (long)ptr2);
}
            
==(p1) click to toggle source
 
               VALUE
rb_dlptr_eql(VALUE self, VALUE other)
{
  void *ptr1, *ptr2;
  ptr1 = rb_dlptr2cptr(self);
  ptr2 = rb_dlptr2cptr(other);

  return ptr1 == ptr2 ? Qtrue : Qfalse;
}
            
[](p1, p2 = v2) click to toggle source
 
               VALUE
rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
{
  VALUE key = Qnil, num = Qnil;
  ID id;
  struct ptr_data *data;
  int i;
  int offset;

  if (rb_scan_args(argc, argv, "11", &key, &num) == 1) {
    num = INT2NUM(0);
  }

  if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
    VALUE pass[1];
    pass[0] = num;
    return rb_dlptr_to_str(1, pass, rb_dlptr_plus(self, key));
  }
  rb_to_id(key);
  if (! (TYPE(key) == T_STRING || TYPE(key) == T_SYMBOL)) {
    rb_raise(rb_eTypeError, "the key must be a string or symbol");
  }

  id = rb_to_id(key);
  Data_Get_Struct(self, struct ptr_data, data);
  offset = 0;
  switch (data->ctype) {
  case DLPTR_CTYPE_STRUCT:
    for (i=0; i < data->ids_num; i++) {
      switch (data->stype[i]) {
      case 'I':
        DLALIGN(data->ptr,offset,INT_ALIGN);
        break;
      case 'L':
        DLALIGN(data->ptr,offset,LONG_ALIGN);
        break;
      case 'P':
      case 'S':
        DLALIGN(data->ptr,offset,VOIDP_ALIGN);
        break;
      case 'F':
        DLALIGN(data->ptr,offset,FLOAT_ALIGN);
        break;
      case 'D':
        DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
        break;
      case 'C':
        break;
      case 'H':
        DLALIGN(data->ptr,offset,SHORT_ALIGN);
        break;
      default:
        rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
      }
      if (data->ids[i] == id) {
        return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
      }
      switch (data->stype[i]) {
      case 'I':
        offset += sizeof(int) * data->ssize[i];
        break;
      case 'L':
        offset += sizeof(long) * data->ssize[i];
        break;
      case 'P':
      case 'S':
        offset += sizeof(void*) * data->ssize[i];
        break;
      case 'F':
        offset += sizeof(float) * data->ssize[i];
        break;
      case 'D':
        offset += sizeof(double) * data->ssize[i];
        break;
      case 'C':
        offset += sizeof(char) * data->ssize[i];
        break;
      case 'H':
        offset += sizeof(short) * data->ssize[i];
        break;
      default:
        rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
      }
    }
    break;
  case DLPTR_CTYPE_UNION:
    for (i=0; i < data->ids_num; i++) {
      if (data->ids[i] == id) {
        return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
      }
    }
    break;
  } /* end of switch */

  rb_raise(rb_eNameError, "undefined key `%s' for %s",
           rb_id2name(id), rb_class2name(CLASS_OF(self)));

  return Qnil;
}
            
[]=(p1, p2, p3 = v3) click to toggle source
 
               VALUE
rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
{
  VALUE key = Qnil, num = Qnil, val = Qnil;
  ID id;
  struct ptr_data *data;
  int i;
  int offset;
  long memsize;
  void *memimg;

  rb_secure(4);
  switch (rb_scan_args(argc, argv, "21", &key, &num, &val)) {
  case 2:
    val = num;
    num = Qnil;
    break;
  }

  if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
    void *dst, *src;
    long len;

    StringValue(val);
    Data_Get_Struct(self, struct ptr_data, data);
    dst = (void*)((long)(data->ptr) + DLNUM2LONG(key));
    src = RSTRING(val)->ptr;
    len = RSTRING(val)->len;
    if (num == Qnil) {
      memcpy(dst, src, len);
    }
    else{
      long n = NUM2INT(num);
      memcpy(dst, src, n < len ? n : len);
      if (n > len) MEMZERO((char*)dst + len, char, n - len);
    }
    return val;
  }

  id = rb_to_id(key);
  Data_Get_Struct(self, struct ptr_data, data);
  switch (data->ctype) {
  case DLPTR_CTYPE_STRUCT:
    offset = 0;
    for (i=0; i < data->ids_num; i++) {
      switch (data->stype[i]) {
      case 'I':
        DLALIGN(data->ptr,offset,INT_ALIGN);
        break;
      case 'L':
        DLALIGN(data->ptr,offset,LONG_ALIGN);
        break;
      case 'P':
      case 'S':
        DLALIGN(data->ptr,offset,VOIDP_ALIGN);
        break;
      case 'D':
        DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
        break;
      case 'F':
        DLALIGN(data->ptr,offset,FLOAT_ALIGN);
        break;
      case 'C':
        break;
      case 'H':
        DLALIGN(data->ptr,offset,SHORT_ALIGN);
        break;
      default:
        rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
      }
      if (data->ids[i] == id) {
        memimg = ary2cary(data->stype[i], val, &memsize);
        memcpy((char *)data->ptr + offset, memimg, memsize);
        dlfree(memimg);
        return val;
      }
      switch (data->stype[i]) {
      case 'I':
      case 'i':
        offset += sizeof(int) * data->ssize[i];
        break;
      case 'L':
      case 'l':
        offset += sizeof(long) * data->ssize[i];
        break;
      case 'P':
      case 'p':
      case 'S':
      case 's':
        offset += sizeof(void*) * data->ssize[i];
        break;
      case 'D':
      case 'd':
        offset += sizeof(double) * data->ssize[i];
        break;
      case 'F':
      case 'f':
        offset += sizeof(float) * data->ssize[i];
        break;
      case 'C':
      case 'c':
        offset += sizeof(char) * data->ssize[i];
        break;
      case 'H':
      case 'h':
        offset += sizeof(short) * data->ssize[i];
        break;
      default:
        rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
      }
    }
    return val;
    /* break; */
  case DLPTR_CTYPE_UNION:
    for (i=0; i < data->ids_num; i++) {
      if (data->ids[i] == id) {
        switch (data->stype[i]) {
        case 'I': case 'i':
          memsize = sizeof(int) * data->ssize[i];
          break;
        case 'L': case 'l':
          memsize = sizeof(long) * data->ssize[i];
          break;
        case 'P': case 'p':
        case 'S': case 's':
          memsize = sizeof(void*) * data->ssize[i];
          break;
        case 'F': case 'f':
          memsize = sizeof(float) * data->ssize[i];
          break;
        case 'D': case 'd':
          memsize = sizeof(double) * data->ssize[i];
          break;
        case 'C': case 'c':
          memsize = sizeof(char) * data->ssize[i];
          break;
        case 'H': case 'h':
          memsize = sizeof(short) * data->ssize[i];
          break;
        default:
          rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
        }
        memimg = ary2cary(data->stype[i], val, NULL);
        memcpy(data->ptr, memimg, memsize);
        dlfree(memimg);
      }
    }
    return val;
    /* break; */
  }

  rb_raise(rb_eNameError, "undefined key `%s' for %s",
           rb_id2name(id), rb_class2name(CLASS_OF(self)));

  return Qnil;
}
            
data_type() click to toggle source
 
               VALUE
rb_dlptr_get_data_type(VALUE self)
{
  struct ptr_data *data;

  Data_Get_Struct(self, struct ptr_data, data);
  if (data->stype)
    return rb_assoc_new(INT2FIX(data->ctype),
                        rb_tainted_str_new(data->stype, data->slen));
  else
    return rb_assoc_new(INT2FIX(data->ctype), Qnil);
}
            
define_data_type(p1, p2 = v2, *args) click to toggle source
 
               VALUE
rb_dlptr_define_data_type(int argc, VALUE argv[], VALUE self)
{
  VALUE data_type, type, rest, vid;
  struct ptr_data *data;
  int i, t, num;
  char *ctype;

  rb_scan_args(argc, argv, "11*", &data_type, &type, &rest);
  Data_Get_Struct(self, struct ptr_data, data);

  if (argc == 1 || (argc == 2 && type == Qnil)) {
    if (NUM2INT(data_type) == DLPTR_CTYPE_UNKNOWN) {
      data->ctype = DLPTR_CTYPE_UNKNOWN;
      data->slen = 0;
      data->ids_num  = 0;
      if (data->stype) {
        dlfree(data->stype);
        data->stype = NULL;
      }
      if (data->ids) {
        dlfree(data->ids);
        data->ids = NULL;
      }
      return Qnil;
    }
    else{
      rb_raise(rb_eArgError, "wrong arguments");
    }
  }

  t = NUM2INT(data_type);
  StringValue(type);
  Check_Type(rest, T_ARRAY);
  num = RARRAY(rest)->len;
  for (i=0; i<num; i++) {
    rb_to_id(rb_ary_entry(rest,i));
  }

  data->ctype = t;
  data->slen = num;
  data->ids_num  = num;
  if (data->stype) dlfree(data->stype);
  data->stype = (char*)dlmalloc(sizeof(char) * num);
  if (data->ssize) dlfree(data->ssize);
  data->ssize = (int*)dlmalloc(sizeof(int) * num);
  if (data->ids) dlfree(data->ids);
  data->ids  = (ID*)dlmalloc(sizeof(ID) * data->ids_num);

  ctype = StringValuePtr(type);
  for (i=0; i<num; i++) {
    vid = rb_ary_entry(rest,i);
    data->ids[i] = rb_to_id(vid);
    data->stype[i] = *ctype;
    ctype ++;
    if (isdigit(*ctype)) {
      char *p, *d;
      for (p=ctype; isdigit(*p); p++) ;
      d = ALLOCA_N(char, p - ctype + 1);
      strncpy(d, ctype, p - ctype);
      d[p - ctype] = '\0';
      data->ssize[i] = atoi(d);
      ctype = p;
    }
    else{
      data->ssize[i] = 1;
    }
  }

  if (*ctype) {
    rb_raise(rb_eArgError, "too few/many arguments");
  }

  if (!data->size)
    data->size = dlsizeof(RSTRING(type)->ptr);

  return Qnil;
}
            
eql?(p1) click to toggle source
 
               VALUE
rb_dlptr_eql(VALUE self, VALUE other)
{
  void *ptr1, *ptr2;
  ptr1 = rb_dlptr2cptr(self);
  ptr2 = rb_dlptr2cptr(other);

  return ptr1 == ptr2 ? Qtrue : Qfalse;
}
            
free() click to toggle source
 
               VALUE
rb_dlptr_free_get(VALUE self)
{
  struct ptr_data *pdata;

  Data_Get_Struct(self, struct ptr_data, pdata);

  return rb_dlsym_new(pdata->free,"(free)","0P");
}
            
free=(p1) click to toggle source
 
               VALUE
rb_dlptr_free_set(VALUE self, VALUE val)
{
  struct ptr_data *data;

  Data_Get_Struct(self, struct ptr_data, data);

  data->free = DLFREEFUNC(rb_dlsym2csym(val));

  return Qnil;
}
            
inspect() click to toggle source
 
               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:0x%lx ptr=0x%lx size=%ld free=0x%lx>",
           rb_class2name(CLASS_OF(self)), data, data->ptr, data->size,
           (long)data->free);
  return rb_str_new2(str);
}
            
null?() click to toggle source
 
               VALUE
rb_dlptr_null_p(VALUE self)
{
  struct ptr_data *data;

  Data_Get_Struct(self, struct ptr_data, data);
  return data->ptr ? Qfalse : Qtrue;
}
            
ptr() click to toggle source
 
               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);
}
            
ref() click to toggle source
 
               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);
}
            
size(p1 = v1) click to toggle source
 
               VALUE
rb_dlptr_size(int argc, VALUE argv[], VALUE self)
{
  VALUE size;

  if (rb_scan_args(argc, argv, "01", &size) == 0){
    return DLLONG2NUM(RDLPTR(self)->size);
  }
  else{
    RDLPTR(self)->size = DLNUM2LONG(size);
    return size;
  }
}
            
size=(p1 = v1) click to toggle source
 
               VALUE
rb_dlptr_size(int argc, VALUE argv[], VALUE self)
{
  VALUE size;

  if (rb_scan_args(argc, argv, "01", &size) == 0){
    return DLLONG2NUM(RDLPTR(self)->size);
  }
  else{
    RDLPTR(self)->size = DLNUM2LONG(size);
    return size;
  }
}
            
struct!(*args) click to toggle source
 
               VALUE
rb_dlptr_define_struct(int argc, VALUE argv[], VALUE self)
{
  VALUE *pass_argv;
  int pass_argc, i;

  pass_argc = argc + 1;
  pass_argv = ALLOCA_N(VALUE, pass_argc);
  pass_argv[0] = INT2FIX(DLPTR_CTYPE_STRUCT);
  for (i=1; i<pass_argc; i++) {
    pass_argv[i] = argv[i-1];
  }
  return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
}
            
to_a(p1, p2 = v2) click to toggle source
 
               VALUE
rb_dlptr_to_array(int argc, VALUE argv[], VALUE self)
{
  struct ptr_data *data;
  int n;
  int i;
  int t;
  VALUE ary;
  VALUE type, size;

  Data_Get_Struct(self, struct ptr_data, data);

  switch (rb_scan_args(argc, argv, "11", &type, &size)) {
  case 2:
    t = StringValuePtr(type)[0];
    n = NUM2INT(size);
    break;
  case 1:
    t = StringValuePtr(type)[0];
    switch (t) {
    case 'C':
      n = data->size;
      break;
    case 'H':
      n = data->size / sizeof(short);
      break;
    case 'I':
      n = data->size / sizeof(int);
      break;
    case 'L':
      n = data->size / sizeof(long);
      break;
    case 'F':
      n = data->size / sizeof(float);
      break;
    case 'D':
      n = data->size / sizeof(double);
      break;
    case  'P': case 'p':
      n = data->size / sizeof(void*);
      break;
    case 'S': case 's':
      for (n=0; ((void**)(data->ptr))[n]; n++) {};
      break;
    default:
        n = 0;
    }
    break;
  default:
    rb_bug("rb_dlptr_to_array");
  }

  ary = rb_ary_new();

  for (i=0; i < n; i++) {
    switch (t) {
    case 'C':
      rb_ary_push(ary, INT2NUM(((char*)(data->ptr))[i]));
      break;
    case 'H':
      rb_ary_push(ary, INT2NUM(((short*)(data->ptr))[i]));
      break;
    case 'I':
      rb_ary_push(ary, INT2NUM(((int*)(data->ptr))[i]));
      break;
    case 'L':
      rb_ary_push(ary, DLLONG2NUM(((long*)(data->ptr))[i]));
      break;
    case 'D':
      rb_ary_push(ary, rb_float_new(((double*)(data->ptr))[i]));
      break;
    case 'F':
      rb_ary_push(ary, rb_float_new(((float*)(data->ptr))[i]));
      break;
    case 'S':
      {
        char *str = ((char**)(data->ptr))[i];
        if (str) {
          rb_ary_push(ary, rb_tainted_str_new2(str));
        }
        else{
          rb_ary_push(ary, Qnil);
        }
      }
      break;
    case 's':
      {
        char *str = ((char**)(data->ptr))[i];
        if (str) {
          rb_ary_push(ary, rb_tainted_str_new2(str));
          xfree(str);
        }
        else{
          rb_ary_push(ary, Qnil);
        }
      }
      break;
    case 'P':
      rb_ary_push(ary, rb_dlptr_new(((void**)(data->ptr))[i],0,0));
      break;
    case 'p':
      rb_ary_push(ary,
                  rb_dlptr_new(((void**)(data->ptr))[i],0,dlfree));
      break;
    }
  }

  return ary;
}
            
to_i() click to toggle source
 
               VALUE
rb_dlptr_to_i(VALUE self)
{
  struct ptr_data *data;

  Data_Get_Struct(self, struct ptr_data, data);
  return DLLONG2NUM(data->ptr);
}
            
to_s(p1 = v1) click to toggle source
 
               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;
}
            
to_str(p1 = v1) click to toggle source
 
               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;
}
            
union!(*args) click to toggle source
 
               VALUE
rb_dlptr_define_union(int argc, VALUE argv[], VALUE self)
{
  VALUE *pass_argv;
  int pass_argc, i;

  pass_argc = argc + 1;
  pass_argv = ALLOCA_N(VALUE, pass_argc);
  pass_argv[0] = INT2FIX(DLPTR_CTYPE_UNION);
  for (i=1; i<pass_argc; i++) {
    pass_argv[i] = argv[i-1];
  }
  return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
}
            

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 visit Documenting-ruby.org.

blog comments powered by Disqus