static VALUE rb_gl_buffer_read(int argc, VALUE *argv, VALUE self) { struct buffer *buf; VALUE _length, _offset; GLsizeiptr offset, length; TypedData_Get_Struct(self, struct buffer, &buffer_type, buf); rb_scan_args(argc, argv, "02", &_length, &_offset); if (buf->len == 0 && NIL_P(_length)) rb_raise(rb_eArgError, "length must be provided for unbounded buffer"); length = NUM2SIZET(_length); if (NIL_P(_offset)) { offset = 0; } else { offset = NUM2SIZET(_offset); } if (buf->len != 0 && length + offset > buf->len) rb_raise(rb_eArgError, "read to %lu past end of buffer %lu", (unsigned long)(length + offset), (unsigned long)buf->len); return rb_str_new((char *)buf->ptr + offset, length); }
static VALUE mmap_initialize(int argc, VALUE *argv, VALUE obj) { mmap_data_t *data; VALUE file, voffset, vlength; off_t offset = 0; size_t length = 0; int fd; struct stat st; void *ptr; Data_Get_Struct(obj, mmap_data_t, data); if (data->ptr) rb_raise(rb_eRuntimeError, "already mapped"); rb_scan_args(argc, argv, "12", &file, &voffset, &vlength); if (TYPE(file) != T_FILE) rb_raise(rb_eTypeError, "File object required"); if (voffset != Qnil && NUM2LL(voffset) < 0) rb_raise(rb_eRangeError, "offset out of range: %lld", NUM2LL(voffset)); if (vlength != Qnil && NUM2LL(vlength) < 0) rb_raise(rb_eRangeError, "length out of range: %lld", NUM2LL(vlength)); fd = FIX2INT(rb_funcall(file, rb_intern("fileno"), 0)); if (fstat(fd, &st) < 0) rb_sys_fail("fstat"); offset = voffset == Qnil ? 0 : NUM2SIZET(voffset); length = vlength == Qnil ? st.st_size : NUM2SIZET(vlength); if (offset + length > st.st_size) length = st.st_size - offset; if ((ptr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, offset)) == MAP_FAILED) rb_sys_fail("mmap"); data->ptr = ptr; data->size = length; return Qnil; }
static VALUE initialize(int argc, VALUE *argv, VALUE obj) { VALUE src, voffset, vsize; size_t offset, size; size_t src_offset = 0, src_size = 0; mmapscanner_t *self; int src_size_defined = 0; rb_scan_args(argc, argv, "12", &src, &voffset, &vsize); if (voffset != Qnil && NUM2LL(voffset) < 0) rb_raise(rb_eRangeError, "offset out of range: %lld", NUM2LL(voffset)); if (vsize != Qnil && NUM2LL(vsize) < 0) rb_raise(rb_eRangeError, "length out of range: %lld", NUM2LL(vsize)); offset = voffset == Qnil ? 0 : NUM2SIZET(voffset); if (rb_obj_class(src) == cMmapScanner) { mmapscanner_t *ms; Data_Get_Struct(src, mmapscanner_t, ms); src_offset = ms->offset; src_size = ms->size; src = ms->data; src_size_defined = 1; } else if (TYPE(src) == T_FILE) { int fd = FIX2INT(rb_funcall(src, rb_intern("fileno"), 0)); struct stat st; if (fstat(fd, &st) < 0) rb_sys_fail("fstat"); if (st.st_size == 0) { src = rb_str_new(NULL, 0); src_size = 0; } else { src = rb_funcall(cMmap, rb_intern("new"), 1, src); } } if (rb_obj_class(src) == cMmap) { if (!src_size_defined) { mmap_data_t *data; Data_Get_Struct(src, mmap_data_t, data); src_size = data->size; } } else if (TYPE(src) == T_STRING) { if (!src_size_defined) src_size = RSTRING_LEN(src); } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected File/String/MmapScanner/MmapScanner::Mmap)", rb_obj_classname(src)); } if (offset > src_size) rb_raise(rb_eRangeError, "length out of range: %zu > %zu", offset, src_size); size = vsize == Qnil ? src_size - offset : NUM2SIZET(vsize); if (size > src_size - offset) size = src_size - offset; Data_Get_Struct(obj, mmapscanner_t, self); self->offset = src_offset + offset; self->size = size; self->pos = 0; self->matched = 0; self->matched_pos = 0; self->data = src; return Qnil; }
/* * call-seq: * Settings[option] = value * * Sets a libgit2 library option. */ static VALUE rb_git_set_option(VALUE self, VALUE option, VALUE value) { const char *opt; Check_Type(option, T_STRING); opt = StringValueCStr(option); if (strcmp(opt, "mwindow_size") == 0) { size_t val; Check_Type(value, T_FIXNUM); val = NUM2SIZET(value); git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, val); } else if (strcmp(opt, "mwindow_mapped_limit") == 0) { size_t val; Check_Type(value, T_FIXNUM); val = NUM2SIZET(value); git_libgit2_opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, val); } else { rb_raise(rb_eArgError, "Unknown option specified"); } return Qnil; }
// read from buffer and return a ruby string // params: dest, dest_start=0, src_start=0, len=self.length // return: bytes copied VALUE ruv_buffer_copy(int argc, VALUE* argv, VALUE rb_src) { VALUE rb_dest, rb_dest_start, rb_src_start, rb_length; size_t dest_start, src_start, length; ruv_buffer_t *src, *dest; rb_scan_args(argc, argv, "13", &rb_dest, &rb_dest_start, &rb_src_start, &rb_length); if(!rb_obj_is_kind_of(rb_dest, rb_obj_class(rb_src))) { rb_raise(rb_eArgError, "Dest is not a buffer"); } Data_Get_Struct(rb_src, ruv_buffer_t, src); Data_Get_Struct(rb_dest, ruv_buffer_t, dest); if(!NIL_P(rb_dest_start)) { Check_Type(rb_dest_start, T_FIXNUM); dest_start = NUM2SIZET(rb_dest_start); } else { dest_start = 0; } if(dest_start >= dest->length) { rb_raise(rb_eArgError, "dest_start is out of bounds."); } if(!NIL_P(rb_src_start)) { Check_Type(rb_src_start, T_FIXNUM); src_start = NUM2SIZET(rb_src_start); } else { src_start = 0; } if(src_start >= src->length) { rb_raise(rb_eArgError, "src_start is out of bounds."); } if(!NIL_P(rb_length)) { Check_Type(rb_length, T_FIXNUM); length = NUM2SIZET(rb_length); } else { length = src->length - src_start; } // make sure it's not out of bound length = MIN(length, src->length - src_start); length = MIN(length, dest->length - dest_start); memcpy(dest->data + dest_start, src->data + src_start, length); return SIZET2NUM(length); }
static VALUE nst_allocate(VALUE self) { narray_t *na; char *ptr; VALUE velmsz; GetNArray(self,na); switch(NA_TYPE(na)) { case NARRAY_DATA_T: ptr = NA_DATA_PTR(na); if (na->size > 0 && ptr == NULL) { velmsz = rb_const_get(CLASS_OF(self), rb_intern("element_byte_size")); ptr = xmalloc(NUM2SIZET(velmsz) * na->size); NA_DATA_PTR(na) = ptr; } break; case NARRAY_VIEW_T: rb_funcall(NA_VIEW_DATA(na), rb_intern("allocate"), 0); break; case NARRAY_FILEMAP_T: //ptr = ((narray_filemap_t*)na)->ptr; // to be implemented default: rb_bug("invalid narray type : %d",NA_TYPE(na)); } return self; }
static VALUE rb_gl_buffer_write(int argc, VALUE *argv, VALUE self) { struct buffer *buf; VALUE _data, _offset; GLsizeiptr offset; long length; TypedData_Get_Struct(self, struct buffer, &buffer_type, buf); if (!buf->ptr) rb_raise(rb_eArgError, "write to unmapped buffer"); rb_scan_args(argc, argv, "11", &_data, &_offset); if (NIL_P(_data)) rb_raise(rb_eArgError, "cannot write nil to buffer"); _data = rb_String(_data); length = RSTRING_LEN(_data); if (NIL_P(_offset)) { offset = 0; } else { offset = NUM2SIZET(_offset); } if (buf->len != 0 && length + offset > buf->len) rb_raise(rb_eArgError, "write to %lu past end of buffer %lu", (unsigned long)(length + offset), (unsigned long)buf->len); memcpy((char *)buf->ptr + offset, RSTRING_PTR(_data), RSTRING_LEN(_data)); return self; }
/* * Generate a multi-click event at the current mouse position * * Unlike {Mouse.double_click} and {Mouse.triple_click} this will generate * a single event with the given number of clicks. * * You can optionally specify a point to click; the mouse cursor will * instantly jump to the given point; otherwise the click event happens * at the current cursor position. * * @overload multi_click(num_clicks) * @param num_clicks [Number,#to_i] * @return [CGPoint] * @overload multi_click(num_clicks, point) * @param num_clicks [Number,#to_i] * @param point [CGPoint] * @return [CGPoint] */ static VALUE rb_mouse_multi_click(const int argc, VALUE* const argv, UNUSED const VALUE self) { if (argc == 0) { rb_raise(rb_eArgError, "multi_click requires at least one arg"); return Qnil; } // TODO: there has got to be a more idiomatic way to do this coercion const size_t num_clicks = NUM2SIZET(argv[0]); switch (argc) { case 1: mouse_multi_click(num_clicks); break; case 2: default: mouse_multi_click2(num_clicks, rb_mouse_unwrap_point(argv[1])); } return CURRENT_POSITION; }
/* * call-seq: * Raindrops.new(size) -> raindrops object * * Initializes a Raindrops object to hold +size+ counters. +size+ is * only a hint and the actual number of counters the object has is * dependent on the CPU model, number of cores, and page size of * the machine. The actual size of the object will always be equal * or greater than the specified +size+. */ static VALUE init(VALUE self, VALUE size) { struct raindrops *r = DATA_PTR(self); int tries = 1; size_t tmp; if (r->drops != MAP_FAILED) rb_raise(rb_eRuntimeError, "already initialized"); r->size = NUM2SIZET(size); if (r->size < 1) rb_raise(rb_eArgError, "size must be >= 1"); tmp = PAGE_ALIGN(raindrop_size * r->size); r->capa = tmp / raindrop_size; assert(PAGE_ALIGN(raindrop_size * r->capa) == tmp && "not aligned"); retry: r->drops = mmap(NULL, tmp, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); if (r->drops == MAP_FAILED) { if ((errno == EAGAIN || errno == ENOMEM) && tries-- > 0) { rb_gc(); goto retry; } rb_sys_fail("mmap"); } r->pid = getpid(); return self; }
static void iter_nstruct_to_a(na_loop_t *const lp) { long i, len; VALUE opt, types, defs, def; VALUE elmt, velm, vary; size_t ofs, pos; narray_view_t *ne; opt = lp->option; types = RARRAY_AREF(opt,0); defs = RARRAY_AREF(opt,1); pos = lp->args[0].iter[0].pos; len = RARRAY_LEN(types); vary = rb_ary_new2(len); for (i=0; i<len; i++) { def = RARRAY_AREF(defs,i); ofs = NUM2SIZET(RARRAY_AREF(def,2)); //ofs = NUM2SIZET(RARRAY_AREF(ofsts,i)); elmt = RARRAY_AREF(types,i); GetNArrayView(elmt,ne); ne->offset = pos + ofs; if (ne->base.ndim==0) { velm = rb_funcall(elmt,rb_intern("extract"),0); } else { velm = rb_funcall(elmt,rb_intern("to_a"),0); } rb_ary_push(vary, velm); } rb_ary_push(lp->args[1].value, vary); }
// ------ static void iter_nstruct_from_a(na_loop_t *const lp) { long i, len; VALUE ary; VALUE types, defs, def; VALUE elmt, item; size_t ofs; narray_view_t *ne; types = RARRAY_AREF(lp->option,0); defs = RARRAY_AREF(lp->option,1); len = RARRAY_LEN(types); ary = lp->args[0].value; //rb_p(CLASS_OF(ary));rb_p(ary); for (i=0; i<len; i++) { def = RARRAY_AREF(defs,i); ofs = NUM2SIZET(RARRAY_AREF(def,2)); elmt = RARRAY_AREF(types,i); GetNArrayView(elmt,ne); ne->offset = lp->args[1].iter[0].pos + ofs; item = RARRAY_AREF(ary,i); //rb_p(ary); //rb_p(item); //rb_p(elmt); //abort(); rb_funcall(elmt, rb_intern("store"), 1, item); } }
static VALUE gl_VertexAttribPointerNV(VALUE obj,VALUE arg1,VALUE arg2,VALUE arg3,VALUE arg4,VALUE arg5) { GLuint index; GLuint size; GLenum type; GLsizei stride; LOAD_GL_FUNC(glVertexAttribPointerNV, "GL_NV_vertex_program"); index = (GLuint)NUM2UINT(arg1); size = (GLuint)NUM2UINT(arg2); type = (GLenum)NUM2INT(arg3); stride = (GLsizei)NUM2UINT(arg4); if (index>_MAX_VERTEX_ATTRIBS) rb_raise(rb_eArgError, "Index too large, maximum allowed value '%i'",_MAX_VERTEX_ATTRIBS); if (CheckBufferBinding(GL_ARRAY_BUFFER_BINDING)) { g_VertexAttrib_ptr[index] = arg5; fptr_glVertexAttribPointerNV(index,size,type,stride,(GLvoid *)NUM2SIZET(arg5)); } else { VALUE data; data = pack_array_or_pass_string(type,arg5); rb_str_freeze(data); g_VertexAttrib_ptr[index] = data; fptr_glVertexAttribPointerNV(index,size,type,stride,(GLvoid *)RSTRING_PTR(data)); } CHECK_GLERROR_FROM("glVertexAttribPointerNV"); return Qnil; }
// read from buffer and return a ruby string // params: start=0, length=self.length, encoding=Encoding.default_internal_encoding // return: ruby string VALUE ruv_buffer_read(int argc, VALUE* argv, VALUE rb_buffer) { VALUE rb_start, rb_length, rb_intern_enc, rb_str; size_t start, length; rb_encoding *intern_enc; ruv_buffer_t *buffer; char *str_p; Data_Get_Struct(rb_buffer, ruv_buffer_t, buffer); rb_scan_args(argc, argv, "03", &rb_start, &rb_length, &rb_intern_enc); if(!NIL_P(rb_start)) { Check_Type(rb_start, T_FIXNUM); start = NUM2SIZET(rb_start); } else { start = 0; } if(start >= buffer->length) { rb_raise(rb_eArgError, "start is out of bounds."); } if(!NIL_P(rb_length)) { Check_Type(rb_length, T_FIXNUM); length = NUM2SIZET(length); } else { length = buffer->length - start; } // make sure it's not out of bound length = MIN(length, buffer->length - start); if(!NIL_P(rb_intern_enc)) { intern_enc = rb_enc_get(rb_intern_enc); } else { intern_enc = rb_default_internal_encoding(); } str_p = buffer->data + start; rb_str = rb_tainted_str_new(str_p, length); if(intern_enc) { rb_str = rb_str_export_to_enc(rb_str, intern_enc); } return rb_str; }
static VALUE rb_queue_apply(VALUE self, SEL sel, VALUE n) { rb_vm_block_t *block = get_prepared_block(); dispatch_apply_f(NUM2SIZET(n), RQueue(self)->queue, (void *)block, rb_block_applier); GC_RELEASE(block); return Qnil; }
// read from buffer and return a ruby string // params: value, start=0, end=self.length // return: bytes copied VALUE ruv_buffer_fill(int argc, VALUE* argv, VALUE rb_buffer) { VALUE rb_value, rb_start, rb_length; size_t start, length; ruv_buffer_t *buffer; int value; Data_Get_Struct(rb_buffer, ruv_buffer_t, buffer); rb_scan_args(argc, argv, "12", &rb_value, &rb_start, &rb_length); value = NUM2INT(rb_value); if(value > 255 || value < 0) { rb_raise(rb_eArgError, "value must be between 0 to 255"); } if(!NIL_P(rb_start)) { Check_Type(rb_start, T_FIXNUM); start = NUM2SIZET(rb_start); } else { start = 0; } if(start >= buffer->length) { rb_raise(rb_eArgError, "start is out of bounds."); } if(!NIL_P(rb_length)) { Check_Type(rb_length, T_FIXNUM); length = NUM2SIZET(length); } else { length = buffer->length - start; } // make sure it's not out of bound length = MIN(length, buffer->length - start); memset(buffer->data + start, value, length); return SIZET2NUM(length); }
/* * call-seq: * rd.size = new_size * * Increases or decreases the current capacity of our Raindrop. * Raises RangeError if +new_size+ is too big or small for the * current backing store */ static VALUE setsize(VALUE self, VALUE new_size) { size_t new_rd_size = NUM2SIZET(new_size); struct raindrops *r = get(self); if (new_rd_size <= r->capa) r->size = new_rd_size; else resize(r, new_rd_size); return new_size; }
VALUE ruv_buffer_init(VALUE rb_buffer, VALUE rb_length) { Check_Type(rb_length, T_FIXNUM); size_t len = NUM2SIZET(rb_length); ruv_buffer_t* buffer; Data_Get_Struct(rb_buffer, ruv_buffer_t, buffer); buffer->data = (char*)malloc(len); buffer->length = len; return rb_buffer; }
static VALUE my_malloc_init(VALUE self, VALUE size) { struct my_malloc *ptr; size_t requested = NUM2SIZET(size); if (0 == requested) rb_raise(rb_eArgError, "unable to allocate 0 bytes"); Data_Get_Struct(self, struct my_malloc, ptr); ptr->ptr = malloc(requested); if (NULL == ptr->ptr) rb_raise(rb_eNoMemError, "unable to allocate %" PRIuSIZE " bytes", requested); ptr->size = requested; return self; }
void Init_oobgc() { mOOB = rb_define_module_under(rb_mGC, "OOB"); rb_autoload(mOOB, rb_intern_const("UnicornMiddleware"), "gctools/oobgc/unicorn_middleware.rb"); rb_define_singleton_method(mOOB, "setup", install, 0); rb_define_singleton_method(mOOB, "run", oobgc_run, 0); rb_define_singleton_method(mOOB, "dry_run", oobgc_dry_run, 0); rb_define_singleton_method(mOOB, "stat", oobgc_stat, 1); rb_define_singleton_method(mOOB, "clear", oobgc_clear, 0); #define S(name) sym_##name = ID2SYM(rb_intern(#name)); S(total_allocated_object); S(heap_swept_slot); S(heap_tomb_page_length); S(heap_final_slot); S(old_object); S(old_object_limit); S(remembered_shady_object); S(remembered_shady_object_limit); S(major_by); S(count); S(major_count); S(minor_count); S(sweep_count); #undef S id_start = rb_intern("start"); _oobgc.heap_obj_limit = NUM2SIZET(rb_hash_aref(rb_const_get(rb_mGC, rb_intern("INTERNAL_CONSTANTS")), ID2SYM(rb_intern("HEAP_OBJ_LIMIT")))); minor_gc_args = rb_hash_new(); rb_hash_aset(minor_gc_args, ID2SYM(rb_intern("full_mark")), Qfalse); rb_ivar_set(mOOB, rb_intern("minor_gc_args"), minor_gc_args); }
static VALUE //iter_struct_inspect(na_loop_t *const lp) iter_struct_inspect(char *ptr, size_t pos, VALUE opt) { VALUE types, defs, def, name, elmt, vary, v, x; size_t ofs; long i, len; narray_view_t *ne; types = RARRAY_AREF(opt,0); defs = RARRAY_AREF(opt,1); len = RARRAY_LEN(types); vary = rb_ary_new2(len); for (i=0; i<len; i++) { def = RARRAY_AREF(defs,i); name = RARRAY_AREF(def,0); ofs = NUM2SIZET(RARRAY_AREF(def,2)); elmt = RARRAY_AREF(types,i); GetNArrayView(elmt,ne); ne->offset = pos + ofs; v = rb_str_concat(rb_sym_to_s(name), rb_str_new2(": ")); x = rb_funcall(elmt, rb_intern("format_to_a"), 0); // <-- fix me if (ne->base.ndim==0) { x = rb_funcall(x, rb_intern("first"), 0); } x = rb_funcall(x, rb_intern("to_s"), 0); v = rb_str_concat(v, x); rb_ary_push(vary, v); } v = rb_ary_join(vary, rb_str_new2(", ")); v = rb_str_concat(rb_str_new2("["), v); v = rb_str_concat(v, rb_str_new2("]")); return v; }
VALUE na_make_view_struct(VALUE self, VALUE dtype, VALUE offset) { size_t i, n; int j, k, ndim; size_t *shape; size_t *idx1, *idx2; ssize_t stride; stridx_t *stridx; narray_t *na, *nt; narray_view_t *na1, *na2; VALUE klass; volatile VALUE view; GetNArray(self,na); // build from Numo::Struct if (rb_obj_is_kind_of(dtype,cNArray)) { GetNArray(dtype,nt); ndim = na->ndim + nt->ndim; shape = ALLOCA_N(size_t,ndim); // struct dimensions for (j=0; j<na->ndim; j++) { shape[j] = na->shape[j]; } // member dimension for (j=na->ndim,k=0; j<ndim; j++,k++) { shape[j] = nt->shape[k]; } klass = CLASS_OF(dtype); stridx = ALLOC_N(stridx_t, ndim); stride = na_dtype_elmsz(klass); for (j=ndim,k=nt->ndim; k; ) { SDX_SET_STRIDE(stridx[--j],stride); stride *= nt->shape[--k]; } } else { ndim = na->ndim; shape = ALLOCA_N(size_t,ndim); for (j=0; j<ndim; j++) { shape[j] = na->shape[j]; } klass = CLASS_OF(self); if (TYPE(dtype)==T_CLASS) { if (RTEST(rb_class_inherited_p(dtype,cNArray))) { klass = dtype; } } stridx = ALLOC_N(stridx_t, ndim); } view = na_s_allocate_view(klass); na_copy_flags(self, view); GetNArrayView(view, na2); na_setup_shape((narray_t*)na2, ndim, shape); na2->stridx = stridx; switch(na->type) { case NARRAY_DATA_T: case NARRAY_FILEMAP_T: stride = na_get_elmsz(self); for (j=na->ndim; j--;) { SDX_SET_STRIDE(na2->stridx[j], stride); stride *= na->shape[j]; } na2->offset = 0; na2->data = self; break; case NARRAY_VIEW_T: GetNArrayView(self, na1); for (j=na1->base.ndim; j--; ) { if (SDX_IS_INDEX(na1->stridx[j])) { n = na1->base.shape[j]; idx1 = SDX_GET_INDEX(na1->stridx[j]); idx2 = ALLOC_N(size_t, na1->base.shape[j]); for (i=0; i<n; i++) { idx2[i] = idx1[i]; } SDX_SET_INDEX(na2->stridx[j],idx2); } else { na2->stridx[j] = na1->stridx[j]; } } na2->offset = na1->offset; na2->data = na1->data; break; } if (RTEST(offset)) { na2->offset += NUM2SIZET(offset); } return view; }
VALUE ruv_buffer_write(int argc, VALUE* argv, VALUE rb_buffer) { VALUE rb_str, rb_offset, rb_length, rb_extern_enc, rb_cBuffer; size_t offset, length, max_length, char_count; ruv_buffer_t *buffer; rb_encoding *rb_extern_encoding; Data_Get_Struct(rb_buffer, ruv_buffer_t, buffer); rb_scan_args(argc, argv, "13", &rb_str, &rb_offset, &rb_length, &rb_extern_enc); StringValue(rb_str); // encoding: use specified external encoding if provided // otherwise use Encoding.default_external as default if(!NIL_P(rb_extern_enc)) { rb_extern_encoding = rb_enc_get(rb_extern_enc); } else { rb_extern_encoding = rb_default_external_encoding(); } // convert to external encoding rb_str = rb_str_export_to_enc(rb_str, rb_extern_encoding); // offset: either specified in params or 0 if(!NIL_P(rb_offset)) { Check_Type(rb_offset, T_FIXNUM); offset = NUM2SIZET(rb_offset); if(offset >= buffer->length) { rb_raise(rb_eArgError, "Overflow! offset is larger than buffer size."); } } else { offset = 0; } // max length: the smaller of the max available space or the whole ruby string max_length = MIN(buffer->length - offset, (size_t)RSTRING_LEN(rb_str)); // length: number of bytes to write. (include half chars) if(!NIL_P(rb_length)) { Check_Type(rb_length, T_FIXNUM); length = NUM2SIZET(rb_length); } else { length = max_length; } // If we are not writing the whole string into the buffer, // re-adjust length so we don't write half a character (uft8, etc) // 1). get char count from calculated byte length // 2). get byte length back from char count // This way only whole char is written to buffer if(length != (size_t)RSTRING_LEN(rb_str)) { char_count = rb_str_sublen(rb_str, length); length = rb_str_offset(rb_str, char_count); } memcpy(buffer->data + offset, RSTRING_PTR(rb_str), length); // set instance variable so we know how much characters are written rb_cBuffer = rb_obj_class(rb_buffer); rb_iv_set(rb_cBuffer, RUV_BUFFER_CHAR_WRITTEN_SYM, SIZET2NUM(char_count)); return SIZET2NUM(length); }
static VALUE nstruct_add_type(VALUE type, int argc, VALUE *argv, VALUE nst) { VALUE ofs, size; ID id; int i; VALUE name=Qnil; size_t *shape=NULL; int ndim=0; ssize_t stride; narray_view_t *nt; int j; for (i=0; i<argc; i++) { switch(TYPE(argv[i])) { case T_STRING: case T_SYMBOL: if (NIL_P(name)) { name = argv[i]; break; } rb_raise(rb_eArgError,"multiple name in struct definition"); case T_ARRAY: if (shape) { rb_raise(rb_eArgError,"multiple shape in struct definition"); } ndim = RARRAY_LEN(argv[i]); if (ndim > NA_MAX_DIMENSION) { rb_raise(rb_eArgError,"too large number of dimensions"); } if (ndim == 0) { rb_raise(rb_eArgError,"array is empty"); } shape = ALLOCA_N(size_t, ndim); na_array_to_internal_shape(Qnil, argv[i], shape); break; } } id = rb_to_id(name); name = ID2SYM(id); if (rb_obj_is_kind_of(type,cNArray)) { narray_t *na; GetNArray(type,na); type = CLASS_OF(type); ndim = na->ndim; shape = na->shape; } type = rb_narray_view_new(type,ndim,shape); GetNArrayView(type,nt); nt->stridx = ALLOC_N(stridx_t,ndim); stride = na_dtype_elmsz(CLASS_OF(type)); for (j=ndim; j--; ) { SDX_SET_STRIDE(nt->stridx[j], stride); stride *= shape[j]; } ofs = rb_iv_get(nst, "__offset__"); nt->offset = NUM2SIZET(ofs); size = rb_funcall(type, rb_intern("byte_size"), 0); rb_iv_set(nst, "__offset__", rb_funcall(ofs,'+',1,size)); rb_ary_push(rb_iv_get(nst,"__members__"), rb_ary_new3(4,name,type,ofs,size)); // <- field definition return Qnil; }