static VALUE range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg) { int c; VALUE b = RANGE_BEG(range); VALUE e = RANGE_END(range); VALUE v = b; if (EXCL(range)) { while (r_lt(v, e)) { (*func) (v, arg); RETURN_IF_BROKEN(); v = rb_vm_call(v, selSucc, 0, NULL); } } else { while (RTEST(c = r_le(v, e))) { (*func) (v, arg); RETURN_IF_BROKEN(); if (c == INT2FIX(0)) break; v = rb_vm_call(v, selSucc, 0, NULL); } } return range; }
static VALUE rhash_each_pair(VALUE hash, SEL sel) { RETURN_ENUMERATOR(hash, 0, 0); rhash_foreach(hash, each_pair_i, 0); RETURN_IF_BROKEN(); return hash; }
static VALUE rhash_select(VALUE hash, SEL sel) { RETURN_ENUMERATOR(hash, 0, 0); VALUE result = rb_hash_new(); rhash_foreach(hash, select_i, result); RETURN_IF_BROKEN(); return result; }
static VALUE loop_i(void) { for (;;) { rb_yield(Qundef); RETURN_IF_BROKEN(); } return Qnil; }
static VALUE rhash_select_bang(VALUE hash, SEL sel) { RETURN_ENUMERATOR(hash, 0, 0); rhash_modify(hash); const long n = rhash_len(hash); rb_hash_foreach(hash, keep_if_i, hash); RETURN_IF_BROKEN(); return n == rhash_len(hash) ? Qnil : hash; }
static VALUE env_each_value(VALUE ehash, SEL sel) { RETURN_ENUMERATOR(ehash, 0, 0); VALUE values = env_values(Qnil, 0); /* rb_secure(4); */ for (long i = 0, count = RARRAY_LEN(values); i < count; i++) { rb_yield(RARRAY_AT(values, i)); RETURN_IF_BROKEN(); } return ehash; }
static VALUE send_internal(int argc, VALUE *argv, VALUE recv, int scope) { if (argc == 0) { rb_raise(rb_eArgError, "no method name given"); } VALUE vid = *argv++; argc--; VALUE retval = rb_call(recv, rb_to_id(vid), argc, argv, scope, true); RETURN_IF_BROKEN(); return retval; }
static int env_update_i(VALUE key, VALUE val, VALUE ctx) { if (key != Qundef) { if (rb_block_given_p()) { val = rb_yield_values(3, key, rb_f_getenv(Qnil, 0, key), val); RETURN_IF_BROKEN(); } env_aset(Qnil, 0, key, val); } return ST_CONTINUE; }
static VALUE rb_struct_each(VALUE s, SEL sel) { long i; RETURN_ENUMERATOR(s, 0, 0); for (i=0; i<RSTRUCT_LEN(s); i++) { rb_yield(RSTRUCT_PTR(s)[i]); RETURN_IF_BROKEN(); } return s; }
static VALUE loop_i(void) { int count = 0; for (;;) { rb_yield(Qundef); RETURN_IF_BROKEN(); if (++count >= 100) { TEST_THREAD_CANCEL(); count = 0; } } return Qnil; }
static VALUE rhash_delete_if(VALUE hash, SEL sel) { RETURN_ENUMERATOR(hash, 0, 0); rhash_modify(hash); VALUE ary = rb_ary_new(); rhash_foreach(hash, delete_if_i, ary); RETURN_IF_BROKEN(); for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) { VALUE key = RARRAY_AT(ary, i); rhash_delete_key(hash, key); } return hash; }
static VALUE rhash_update(VALUE hash1, SEL sel, VALUE hash2) { rhash_modify(hash1); hash2 = to_hash(hash2); if (rb_block_given_p()) { rb_hash_foreach(hash2, update_block_i, hash1); RETURN_IF_BROKEN(); } else { rb_hash_foreach(hash2, update_i, hash1); } return hash1; }
static VALUE rb_struct_each_pair(VALUE s, SEL sel) { VALUE members; long i; RETURN_ENUMERATOR(s, 0, 0); members = rb_struct_members(s); for (i=0; i<RSTRUCT_LEN(s); i++) { rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]); RETURN_IF_BROKEN(); } return s; }
static VALUE range_each(VALUE range, SEL sel) { VALUE beg, end; RETURN_ENUMERATOR(range, 0, 0); beg = RANGE_BEG(range); end = RANGE_END(range); if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */ long lim = FIX2LONG(end); long i; if (!EXCL(range)) lim += 1; for (i = FIX2LONG(beg); i < lim; i++) { rb_yield(LONG2FIX(i)); RETURN_IF_BROKEN(); } } else if (SYMBOL_P(beg) && SYMBOL_P(end)) { /* symbols are special */ VALUE args[2]; args[0] = rb_sym_to_s(end); args[1] = EXCL(range) ? Qtrue : Qfalse; rb_objc_block_call(rb_sym_to_s(beg), selUpto, 2, args, sym_each_i, 0); } else { VALUE tmp = rb_check_string_type(beg); if (!NIL_P(tmp)) { VALUE args[2]; args[0] = end; args[1] = EXCL(range) ? Qtrue : Qfalse; rb_objc_block_call(beg, selUpto, 2, args, rb_yield, 0); } else { if (!discrete_object_p(beg)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(beg)); } range_each_func(range, each_i, NULL); } } return range; }
static int rb_objc_yield_classes(VALUE of) { const int count = objc_getClassList(NULL, 0); assert(count > 0); Class *buf = (Class *)alloca(sizeof(Class) * count); objc_getClassList(buf, count); const bool only_modules = of == rb_cModule; int rcount = 0; for (int i = 0; i < count; i++) { Class k = buf[i]; if (class_getName(k)[0] == '_') { continue; } if (only_modules) { if (!RCLASS_MODULE(k)) { continue; } } else { bool nsobject_based = false; Class sk = k; do { sk = (Class)RCLASS_SUPER(sk); if (sk == (Class)rb_cNSObject) { nsobject_based = true; break; } } while (sk != NULL); if (!nsobject_based) { continue; } } rb_yield((VALUE)k); RETURN_IF_BROKEN(); rcount++; } return rcount; }
static int rb_objc_yield_classes(VALUE of) { int i, count, rcount; Class *buf; count = objc_getClassList(NULL, 0); assert(count > 0); buf = (Class *)alloca(sizeof(Class) * count); objc_getClassList(buf, count); for (i = rcount = 0; i < count; i++) { Class sk, k = buf[i]; bool nsobject_based; if (class_getName(k)[0] == '_') continue; if (of == rb_cModule && !RCLASS_MODULE(k)) continue; nsobject_based = false; sk = k; do { sk = (Class)RCLASS_SUPER(sk); if (sk == (Class)rb_cNSObject) { nsobject_based = true; break; } } while (sk != NULL); if (nsobject_based) { rb_yield((VALUE)k); RETURN_IF_BROKEN(); rcount++; } } return rcount; }
static VALUE rb_struct_select(VALUE s, SEL sel, int argc, VALUE *argv) { VALUE result; long i; if (argc > 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } result = rb_ary_new(); for (i = 0; i < RSTRUCT_LEN(s); i++) { VALUE v = rb_yield(RSTRUCT_PTR(s)[i]); RETURN_IF_BROKEN(); if (RTEST(v)) { rb_ary_push(result, RSTRUCT_PTR(s)[i]); } } return result; }
static VALUE env_reject_bang(VALUE ehash, SEL sel) { RETURN_ENUMERATOR(ehash, 0, 0); VALUE keys = env_keys(Qnil, 0); /* rb_secure(4); */ bool deleted = false; for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) { VALUE key = RARRAY_AT(keys, i); VALUE val = rb_f_getenv(Qnil, 0, key); if (!NIL_P(val)) { VALUE v = rb_yield_values(2, key, val); RETURN_IF_BROKEN(); if (RTEST(v)) { rb_obj_untaint(key); env_delete(Qnil, key); deleted = true; } } } return deleted ? envtbl : Qnil; }
static VALUE env_select(VALUE ehash, SEL sel) { RETURN_ENUMERATOR(ehash, 0, 0); rb_secure(4); VALUE result = rb_hash_new(); char **env = GET_ENVIRON(); while (*env != NULL) { const char *s = strchr(*env, '='); if (s != NULL) { VALUE k = env_str_new(*env, s - *env); VALUE v = env_str_new2(s + 1); VALUE v2 = rb_yield_values(2, k, v); RETURN_IF_BROKEN(); if (RTEST(v2)) { rb_hash_aset(result, k, v); } } env++; } return result; }
static VALUE env_each_pair(VALUE ehash, SEL sel) { RETURN_ENUMERATOR(ehash, 0, 0); rb_secure(4); VALUE ary = rb_ary_new(); char **env = GET_ENVIRON(); while (*env != NULL) { const char *s = strchr(*env, '='); if (s != NULL) { rb_ary_push(ary, env_str_new(*env, s - *env)); rb_ary_push(ary, env_str_new2(s + 1)); } env++; } for (long i = 0, count = RARRAY_LEN(ary); i < count; i += 2) { rb_yield(rb_assoc_new(RARRAY_AT(ary, i), RARRAY_AT(ary, i + 1))); RETURN_IF_BROKEN(); } return ehash; }
static VALUE range_step(VALUE range, SEL sel, int argc, VALUE *argv) { VALUE b, e, step, tmp; RETURN_ENUMERATOR(range, argc, argv); b = RANGE_BEG(range); e = RANGE_END(range); if (argc == 0) { step = INT2FIX(1); } else { rb_scan_args(argc, argv, "01", &step); if (!rb_obj_is_kind_of(step, rb_cNumeric)) { step = rb_to_int(step); } VALUE zero = INT2FIX(0); if (rb_vm_call(step, selLT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be negative"); } else if (!rb_vm_call(step, selGT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be 0"); } } if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */ long end = FIX2LONG(e); long i, unit = FIX2LONG(step); if (!EXCL(range)) end += 1; i = FIX2LONG(b); while (i < end) { rb_yield(LONG2NUM(i)); RETURN_IF_BROKEN(); if (i + unit < i) break; i += unit; } } else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */ VALUE args[2]; VALUE iter[2]; args[0] = rb_sym_to_s(e); args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(rb_sym_to_s(b), selUpto, 2, args, sym_step_i, (VALUE)iter); } else if (ruby_float_step(b, e, step, EXCL(range))) { /* done */ } else if (rb_obj_is_kind_of(b, rb_cNumeric) || !NIL_P(rb_check_to_integer(b, "to_int")) || !NIL_P(rb_check_to_integer(e, "to_int"))) { SEL op = EXCL(range) ? selLT : selLE; VALUE v = b; int i = 0; while (RTEST(rb_vm_call(v, op, 1, &e))) { rb_yield(v); RETURN_IF_BROKEN(); i++; VALUE tmp = rb_vm_call(INT2NUM(i), selMULT, 1, &step); v = rb_vm_call(b, selPLUS, 1, &tmp); } } else { tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { VALUE args[2], iter[2]; b = tmp; args[0] = e; args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(b, selUpto, 2, args, step_i, (VALUE)iter); } else { VALUE args[2]; if (!discrete_object_p(b)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(b)); } args[0] = INT2FIX(1); args[1] = step; return range_each_func(range, step_i, args); } } return range; }