/* * call-seq: * db[nth] * db[start..end] * db[start, length] * * Element reference - with the following syntax: * * * db[nth] * * Retrieves the +nth+ item from an array. Index starts from * zero. If index is the negative, counts backward from the end * of the array. The index of the last element is -1. Returns * +nil+, if the +nth+ element does not exist in the array. * * * db[start..end] * * Returns an array containing the objects from +start+ to +end+, * including both ends. if end is larger than the length of the * array, it will be rounded to the length. If +start+ is out of * an array range , returns +nil+. And if +start+ is larger than * end with in array range, returns empty array ([]). * * * db[start, length] * * Returns an array containing +length+ items from +start+. * Returns +nil+ if +length+ is negative. */ static VALUE bdb_sary_aref(int argc, VALUE *argv, VALUE obj) { VALUE arg1, arg2; long beg, len; bdb_DB *dbst; GetDB(obj, dbst); if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { beg = NUM2LONG(arg1); len = NUM2LONG(arg2); if (beg < 0) { beg = dbst->len + beg; } return bdb_sary_subseq(obj, beg, len); } if (FIXNUM_P(arg1)) { return bdb_sary_entry(obj, arg1); } else if (TYPE(arg1) == T_BIGNUM) { rb_raise(rb_eIndexError, "index too big"); } else { switch (rb_range_beg_len(arg1, &beg, &len, dbst->len, 0)) { case Qfalse: break; case Qnil: return Qnil; default: return bdb_sary_subseq(obj, beg, len); } } return bdb_sary_entry(obj, arg1); }
static VALUE range_relative_to(VALUE range, SEL sel, VALUE max) { long beg, len, m = NUM2LONG(max); rb_range_beg_len(range, &beg, &len, m, 0); return rb_range_new(LONG2NUM(beg), LONG2NUM(beg + len - 1), 0); }
static VALUE bdb_sary_slice_bang(int argc, VALUE *argv, VALUE obj) { VALUE arg1, arg2; long pos, len; bdb_DB *dbst; GetDB(obj, dbst); if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { pos = NUM2LONG(arg1); len = NUM2LONG(arg2); delete_pos_len: if (pos < 0) { pos = dbst->len + pos; } arg2 = bdb_sary_subseq(obj, pos, len); bdb_sary_replace(obj, pos, len, Qnil); return arg2; } if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, dbst->len, 1)) { goto delete_pos_len; } pos = NUM2LONG(arg1); if (pos >= dbst->len) return Qnil; if (pos < 0) pos += dbst->len; if (pos < 0) return Qnil; arg1 = INT2NUM(pos); arg2 = bdb_sary_at(obj, arg1); if (bdb_del(obj, arg1) != Qnil) dbst->len--; return arg2; }
/* call-seq: * fill( color ) * fill( color, start [, length] ) * fill( color, range ) * fill { |index| block } * fill( start [, length] ) { |index| block } * fill( range ) { |index| block } * * Set the selected LEDs to the given `color`. The `color` msut be given as a * 24-bit RGB value. You can also supply a block that receives an LED index and * returns a 24-bit RGB color. * * Examples: * leds.fill( 0x00FF00 ) * leds.fill( 0xFF0000, 2, 2 ) * leds.fill( 0x0000FF, (4...8) ) * leds.fill { |i| 256 << i } * * Returns this PixelPi::Leds instance. */ static VALUE pp_leds_fill( int argc, VALUE* argv, VALUE self ) { ws2811_t *ledstring = pp_leds_struct( self ); ws2811_channel_t channel = ledstring->channel[0]; ws2811_led_t color = 0; VALUE item, arg1, arg2, v; long ii, beg = 0, end = 0, len = 0; int block_p = 0; if (rb_block_given_p()) { block_p = 1; rb_scan_args( argc, argv, "02", &arg1, &arg2 ); argc += 1; } else { rb_scan_args( argc, argv, "12", &item, &arg1, &arg2 ); color = FIX2UINT(item); } switch (argc) { case 1: beg = 0; len = channel.count; break; case 2: if (rb_range_beg_len(arg1, &beg, &len, channel.count, 1)) { break; } /* fall through */ case 3: beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1); if (beg < 0) { beg = channel.count + beg; if (beg < 0) beg = 0; } len = NIL_P(arg2) ? channel.count - beg : NUM2LONG(arg2); break; } if (len < 0) return self; end = beg + len; end = MIN((long) channel.count, end); for (ii=beg; ii<end; ii++) { if (block_p) { v = rb_yield(INT2NUM(ii)); color = FIX2UINT(v); } channel.leds[ii] = color; } return self; }
/* * call-seq: * db[nth] = val * db[start..end] = val * db[start, length] = val * * Element assignment - with the following syntax: * * * db[nth] = val * * Changes the +nth+ element of the array into +val+. If +nth+ is * larger than array length, the array shall be extended * automatically. Extended region shall be initialized by +nil+. * * * db[start..end] = val * * Replaces the items from +start+ to +end+ with +val+. If +val+ * is not an array, the type of +val+ will be converted into the * Array using +to_a+ method. * * * db[start, length] = val * * Replaces the +length+ items from +start+ with +val+. If +val+ * is not an array, the type of +val+ will be converted into the * Array using +to_a+. */ static VALUE bdb_sary_aset(int argc, VALUE *argv, VALUE obj) { long beg, len; bdb_DB *dbst; GetDB(obj, dbst); if (argc == 3) { bdb_sary_replace(obj, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]); return argv[2]; } if (argc != 2) { rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc); } if (FIXNUM_P(argv[0])) { beg = FIX2LONG(argv[0]); goto fixnum; } else if (rb_range_beg_len(argv[0], &beg, &len, dbst->len, 1)) { bdb_sary_replace(obj, beg, len, argv[1]); return argv[1]; } if (TYPE(argv[0]) == T_BIGNUM) { rb_raise(rb_eIndexError, "index too big"); } beg = NUM2LONG(argv[0]); fixnum: if (beg < 0) { beg += dbst->len; if (beg < 0) { rb_raise(rb_eIndexError, "index %ld out of array", beg - dbst->len); } } if (beg > dbst->len) { VALUE nargv[2]; int i; nargv[1] = Qnil; for (i = dbst->len; i < beg; i++) { nargv[0] = INT2NUM(i); bdb_put(2, nargv, obj); dbst->len++; } } argv[0] = INT2NUM(beg); bdb_put(2, argv, obj); dbst->len++; return argv[1]; }
/* * Document-method: []= * * call-seq: * [index]= value * [range]= value-array * * Element Assignment - Sets the element at _index_ or replaces the subset * specified by _range_. Values can be only be positive numerics. Even * values will be set to 0 (n % 2 = 0) and uneven values will be set to 1 * (n % 2 = 1). */ static VALUE bf_bit_set(VALUE self, VALUE position, VALUE value) { BitField *ptr; Data_Get_Struct(self, BitField, ptr); if(rb_obj_is_kind_of(position, rb_cRange) && rb_obj_is_kind_of(value, rb_cArray)) { long beg, len; VALUE tmp; switch(rb_range_beg_len(position, &beg, &len, (long int)ptr->data.size()-1, 2)) { case Qfalse: case Qnil: return Qfalse; default: for(long i = beg+len-1; i >= beg; i--) { tmp = rb_ary_pop(value); if(tmp != Qnil) { /* Is the array value a number? */ Check_Type(tmp, T_FIXNUM); ptr->data[i] = FIX2INT(tmp) % 2; } else { rb_raise(rb_eRangeError, "Array is smaller than given range."); } } } } else { /* Sanity checks for position and value */ Check_Type(position, T_FIXNUM); Check_Type(value, T_FIXNUM); int pos = FIX2INT(position); if(pos < 0 || pos >= ptr->data.size()) { rb_raise(rb_eRangeError, "BitField out of range with value %d.", pos); } ptr->data[pos] = FIX2INT(value) % 2; } return Qnil; }
static VALUE apply_actions(VALUE field, VALUE actions) { long j, actions_len = RARRAY_LEN(actions); long beg, len; VALUE num = 0, modi = 0; for (j = 0; j < actions_len; j++) { VALUE action = rb_ary_entry(actions, j); VALUE klass = rb_class_of(action); if (klass == rb_cRange) { /* copied from rb_str_aref */ len = rb_str_strlen(field); if (RTEST(rb_range_beg_len(action, &beg, &len, len, 0))) field = rb_str_substr(field, beg, len); } else if (klass == rb_cArray) { num = rb_str_to_inum(field, 10, 0); modi = rb_ary_entry(action, 1); if ( (FIXNUM_P(num) || TYPE(num) == T_BIGNUM && RBIGNUM_LEN(num) <= (SIZEOF_LONG/SIZEOF_BDIGITS) ) && FIXNUM_P(modi) && FIX2LONG(modi)) { long modl = NUM2LONG(modi); long numl = (NUM2LONG(num) / modl) * modl; char buf[30]; int wrtn = snprintf(buf, 30, RSTRING_PTR(rb_ary_entry(action, 0)), numl); if (wrtn < 30) { field = rb_str_new(buf, wrtn); continue; } } else { num = rb_funcall2(num, idDiv, 1, &modi); num = rb_funcall2(num, idMul, 1, &modi); } field = rb_str_format(1, &num, rb_ary_entry(action, 0)); } } return field; }
/* * call-seq: * RepeatedField.[](index) => value * * Accesses the element at the given index. Returns nil on out-of-bounds */ VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); int element_size = native_slot_size(self->field_type); upb_fieldtype_t field_type = self->field_type; VALUE field_type_class = self->field_type_class; VALUE arg = argv[0]; long beg, len; if (argc == 1){ if (FIXNUM_P(arg)) { /* standard case */ int index = index_position(argv[0], self); if (index < 0 || index >= self->size) { return Qnil; } void* memory = (void *) (((uint8_t *)self->elements) + index * element_size); return native_slot_get(field_type, field_type_class, memory); }else{ /* check if idx is Range */ size_t off; switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) { case Qfalse: break; case Qnil: return Qnil; default: return RepeatedField_subarray(_self, beg, len); } } } /* assume 2 arguments */ beg = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); if (beg < 0) { beg += self->size; } if (beg >= self->size) { return Qnil; } return RepeatedField_subarray(_self, beg, len); }
/* * Document-method: [] * * call-seq: * [index] -> value * [range] -> new_ary * * Element Reference - Returns the element at _index_ or the subset * specified by _range_. Negative or indices greater than the size of * the BitField will be nil. */ static VALUE bf_bit_get(VALUE self, VALUE position) { BitField *ptr; Data_Get_Struct(self, BitField, ptr); /* Is position a range? */ if(rb_obj_is_kind_of(position, rb_cRange)) { long beg, len; VALUE range_ary = rb_ary_new(); switch(rb_range_beg_len(position, &beg, &len, (long int)ptr->data.size()-1, 2)) { case Qfalse: case Qnil: return Qnil; default: for(long i = beg; i < beg+len; i++) { if(i < 0 || i >= ptr->data.size()) { rb_ary_push(range_ary, Qnil); } else { rb_ary_push(range_ary, LONG2NUM(ptr->data[i])); } } } return range_ary; } else { /* Sanity checks for position and value */ Check_Type(position, T_FIXNUM); long pos = FIX2INT(position); if(pos < 0 || pos >= ptr->data.size()) { return Qnil; } else { return LONG2NUM(ptr->data[pos]); } } }
/* * Array reference - creates new memory for range rather than shared object * Note: Almost exactly the same as the implementation from * Ruby 1.9.2 p0 */ static VALUE ary_aref(int argc, VALUE *argv, VALUE ary) { VALUE arg; long beg, len; if (argc == 2) { beg = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); if (beg < 0) { beg += RARRAY_LEN(ary); } return my_ary_subseq(ary, beg, len); } if (argc != 1) { rb_scan_args(argc, argv, "11", 0, 0); } arg = argv[0]; /* special case - speeding up */ if (FIXNUM_P(arg)) { return rb_ary_entry(ary, FIX2LONG(arg)); } /* check if idx is Range */ switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) { case Qfalse: break; case Qnil: return Qnil; default: return my_ary_subseq(ary, beg, len); } return rb_ary_entry(ary, NUM2LONG(arg)); }
static VALUE bdb_sary_fill(int argc, VALUE *argv, VALUE obj) { VALUE item, arg1, arg2, tmp[2]; long beg, len, i; bdb_DB *dbst; GetDB(obj, dbst); rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); switch (argc) { case 1: len = dbst->len; beg = 0; break; case 2: if (rb_range_beg_len(arg1, &beg, &len, dbst->len, 1)) { break; } /* fall through */ case 3: beg = NIL_P(arg1)?0:NUM2LONG(arg1); if (beg < 0) { beg += dbst->len; if (beg < 0) beg = 0; } len = NIL_P(arg2)?dbst->len - beg:NUM2LONG(arg2); break; } tmp[1] = item; for (i = 0; i < len; i++) { tmp[0] = INT2NUM(i + beg); bdb_put(2, tmp, obj); if ((i + beg) >= dbst->len) dbst->len++; } return obj; }
static VALUE vm_backtrace_to_ary(rb_thread_t *th, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str) { VALUE level, vn; long lev, n; VALUE btval = backtrace_object(th); VALUE r; rb_backtrace_t *bt; GetCoreDataFromValue(btval, rb_backtrace_t, bt); rb_scan_args(argc, argv, "02", &level, &vn); if (argc == 2 && NIL_P(vn)) argc--; switch (argc) { case 0: lev = lev_default + lev_plus; n = bt->backtrace_size - lev; break; case 1: { long beg, len; switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) { case Qfalse: lev = NUM2LONG(level); if (lev < 0) { rb_raise(rb_eArgError, "negative level (%ld)", lev); } lev += lev_plus; n = bt->backtrace_size - lev; break; case Qnil: return Qnil; default: lev = beg + lev_plus; n = len; break; } break; } case 2: lev = NUM2LONG(level); n = NUM2LONG(vn); if (lev < 0) { rb_raise(rb_eArgError, "negative level (%ld)", lev); } if (n < 0) { rb_raise(rb_eArgError, "negative size (%ld)", n); } lev += lev_plus; break; default: lev = n = 0; /* to avoid warning */ break; } if (n == 0) { return rb_ary_new(); } if (to_str) { r = backtrace_to_str_ary(btval, lev, n); } else { r = backtrace_to_location_ary(btval, lev, n); } RB_GC_GUARD(btval); return r; }