static VALUE yield_block(int argc, VALUE *argv, VALUE self) { rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); return rb_block_call(self, rb_to_id(argv[0]), argc-1, argv+1, rb_yield_block, 0); }
static VALUE rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid) { ID id = rb_to_id(mid); return check_method_visibility(mod, id, NOEX_PUBLIC); }
static VALUE rb_mod_private_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE); }
static VALUE rb_thread_aset(VALUE self, SEL sel, VALUE key, VALUE val) { key = ID2SYM(rb_to_id(key)); return rb_hash_aset(rb_vm_thread_locals(self, true), key, val); }
static inline VALUE vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, int num, const rb_block_t *blockptr, VALUE flag, ID id, const rb_method_entry_t *me, VALUE recv) { VALUE val; start_method_dispatch: if (me != 0) { if ((me->flag == 0)) { normal_method_dispatch: switch (me->def->type) { case VM_METHOD_TYPE_ISEQ:{ vm_setup_method(th, cfp, recv, num, blockptr, flag, me); return Qundef; } case VM_METHOD_TYPE_NOTIMPLEMENTED: case VM_METHOD_TYPE_CFUNC:{ val = vm_call_cfunc(th, cfp, num, recv, blockptr, me); break; } case VM_METHOD_TYPE_ATTRSET:{ if (num != 1) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num); } val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1)); cfp->sp -= 2; break; } case VM_METHOD_TYPE_IVAR:{ if (num != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num); } val = rb_attr_get(recv, me->def->body.attr.id); cfp->sp -= 1; break; } case VM_METHOD_TYPE_MISSING:{ VALUE *argv = ALLOCA_N(VALUE, num+1); argv[0] = ID2SYM(me->def->original_id); MEMCPY(argv+1, cfp->sp - num, VALUE, num); cfp->sp += - num - 1; val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv); break; } case VM_METHOD_TYPE_BMETHOD:{ VALUE *argv = ALLOCA_N(VALUE, num); MEMCPY(argv, cfp->sp - num, VALUE, num); cfp->sp += - num - 1; val = vm_call_bmethod(th, recv, num, argv, blockptr, me); break; } case VM_METHOD_TYPE_ZSUPER:{ VALUE klass = RCLASS_SUPER(me->klass); me = rb_method_entry(klass, id); if (me != 0) { goto normal_method_dispatch; } else { goto start_method_dispatch; } } case VM_METHOD_TYPE_OPTIMIZED:{ switch (me->def->body.optimize_type) { case OPTIMIZED_METHOD_TYPE_SEND: { rb_control_frame_t *reg_cfp = cfp; rb_num_t i = num - 1; VALUE sym; if (num == 0) { rb_raise(rb_eArgError, "no method name given"); } sym = TOPN(i); id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym); /* shift arguments */ if (i > 0) { MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i); } me = rb_method_entry(CLASS_OF(recv), id); num -= 1; DEC_SP(1); flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT; goto start_method_dispatch; } case OPTIMIZED_METHOD_TYPE_CALL: { rb_proc_t *proc; int argc = num; VALUE *argv = ALLOCA_N(VALUE, num); GetProcPtr(recv, proc); MEMCPY(argv, cfp->sp - num, VALUE, num); cfp->sp -= num + 1; val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr); break; } default: rb_bug("eval_invoke_method: unsupported optimized method type (%d)", me->def->body.optimize_type); } break; } default:{ rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type); break; } } } else { int noex_safe; if (!(flag & VM_CALL_FCALL_BIT) && (me->flag & NOEX_MASK) & NOEX_PRIVATE) { int stat = NOEX_PRIVATE; if (flag & VM_CALL_VCALL_BIT) { stat |= NOEX_VCALL; } val = vm_method_missing(th, id, recv, num, blockptr, stat); } else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) { VALUE defined_class = me->klass; if (TYPE(defined_class) == T_ICLASS) { defined_class = RBASIC(defined_class)->klass; } if (!rb_obj_is_kind_of(cfp->self, defined_class)) { val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED); } else { goto normal_method_dispatch; } } else if ((noex_safe = NOEX_SAFE(me->flag)) > th->safe_level && (noex_safe > 2)) { rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id)); } else { goto normal_method_dispatch; } } } else { /* method missing */ int stat = 0; if (flag & VM_CALL_VCALL_BIT) { stat |= NOEX_VCALL; } if (flag & VM_CALL_SUPER_BIT) { stat |= NOEX_SUPER; } if (id == idMethodMissing) { VALUE *argv = ALLOCA_N(VALUE, num); vm_method_missing_args(th, argv, num - 1, 0, stat); rb_raise_method_missing(th, num, argv, recv, stat); } else { val = vm_method_missing(th, id, recv, num, blockptr, stat); } } RUBY_VM_CHECK_INTS(); return val; }
VALUE rb_obj_public_method(VALUE obj, VALUE vid) { return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qtrue); }
static VALUE rb_mod_define_method(int argc, VALUE *argv, VALUE mod) { ID id; VALUE body; NODE *node; int noex = NOEX_PUBLIC; if (argc == 1) { id = rb_to_id(argv[0]); body = rb_block_lambda(); } else if (argc == 2) { id = rb_to_id(argv[0]); body = argv[1]; if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Method)", rb_obj_classname(body)); } } else { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } if (RDATA(body)->dmark == (RUBY_DATA_FUNC) bm_mark) { struct METHOD *method = (struct METHOD *)DATA_PTR(body); VALUE rclass = method->rclass; if (rclass != mod) { if (RCLASS_SINGLETON(rclass)) { rb_raise(rb_eTypeError, "can't bind singleton method to a different class"); } if (!RTEST(rb_class_inherited_p(mod, rclass))) { rb_raise(rb_eTypeError, "bind argument must be a subclass of %s", rb_class2name(rclass)); } } node = method->body; } else if (rb_obj_is_proc(body)) { rb_proc_t *proc; body = proc_dup(body); GetProcPtr(body, proc); if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) { proc->block.iseq->defined_method_id = id; proc->block.iseq->klass = mod; proc->is_lambda = Qtrue; proc->is_from_method = Qtrue; } node = NEW_BMETHOD(body); } else { /* type error */ rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)"); } /* TODO: visibility */ rb_add_method(mod, id, node, noex); return body; }
static VALUE rb_mod_method_defined(VALUE mod, VALUE mid) { return rb_method_boundp(mod, rb_to_id(mid), 1); }
static VALUE rb_mod_instance_method(VALUE mod, SEL sel, VALUE vid) { return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qfalse); }
VALUE rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self, Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt, int argc, const VALUE *argv) { RoxorVM *vm = (RoxorVM *)_vm; #if ROXOR_VM_DEBUG bool cached = true; #endif bool cache_method = true; Class current_super_class = vm->get_current_super_class(); SEL current_super_sel = vm->get_current_super_sel(); if (opt & DISPATCH_SUPER) { // TODO goto recache; } if (cache->sel != sel || cache->klass != klass || cache->flag == 0) { recache: #if ROXOR_VM_DEBUG cached = false; #endif Method method; if (opt & DISPATCH_SUPER) { if (!sel_equal(klass, current_super_sel, sel)) { current_super_sel = sel; current_super_class = klass; } else { // Let's make sure the current_super_class is valid before // using it; we check this by verifying that it's a real // super class of the current class, as we may be calling // a super method of the same name but on a totally different // class hierarchy. Class k = klass; bool current_super_class_ok = false; while (k != NULL) { if (k == current_super_class) { current_super_class_ok = true; break; } k = class_getSuperclass(k); } if (!current_super_class_ok) { current_super_class = klass; } } method = rb_vm_super_lookup(current_super_class, sel, ¤t_super_class); } else { current_super_sel = 0; method = class_getInstanceMethod(klass, sel); } if (method != NULL) { recache2: IMP imp = method_getImplementation(method); if (UNAVAILABLE_IMP(imp)) { // Method was undefined. goto call_method_missing; } rb_vm_method_node_t *node = GET_CORE()->method_node_get(method); if (node != NULL) { // ruby call fill_rcache(cache, klass, sel, node); } else { // objc call fill_ocache(cache, self, klass, imp, sel, method, argc); } if (opt & DISPATCH_SUPER) { cache->flag |= MCACHE_SUPER; } } else { // Method is not found... #if !defined(MACRUBY_STATIC) // Force a method resolving, because the objc cache might be // wrong. if (rb_vm_resolve_method(klass, sel)) { goto recache; } #endif // Does the receiver implements -forwardInvocation:? if ((opt & DISPATCH_SUPER) == 0 && rb_objc_supports_forwarding(self, sel)) { //#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 // In earlier versions of the Objective-C runtime, there seems // to be a bug where class_getInstanceMethod isn't atomic, // and might return NULL while at the exact same time another // thread registers the related method. // As a work-around, we double-check if the method still does // not exist here. If he does, we can dispatch it properly. // note: OS X 10.7 also, this workaround is required. see #1476 method = class_getInstanceMethod(klass, sel); if (method != NULL) { goto recache2; } //#endif fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL, argc); goto dispatch; } // Let's see if are not trying to call a Ruby method that accepts // a regular argument then an optional Hash argument, to be // compatible with the Ruby specification. const char *selname = (const char *)sel; size_t selname_len = strlen(selname); if (argc > 1) { const char *p = strchr(selname, ':'); if (p != NULL && p + 1 != '\0') { char *tmp = (char *)malloc(selname_len + 1); assert(tmp != NULL); strncpy(tmp, selname, p - selname + 1); tmp[p - selname + 1] = '\0'; sel = sel_registerName(tmp); VALUE h = rb_hash_new(); bool ok = true; p += 1; for (int i = 1; i < argc; i++) { const char *p2 = strchr(p, ':'); if (p2 == NULL) { ok = false; break; } strlcpy(tmp, p, selname_len); tmp[p2 - p] = '\0'; p = p2 + 1; rb_hash_aset(h, ID2SYM(rb_intern(tmp)), argv[i]); } free(tmp); tmp = NULL; if (ok) { argc = 2; ((VALUE *)argv)[1] = h; // bad, I know... Method m = class_getInstanceMethod(klass, sel); if (m != NULL) { method = m; cache_method = false; goto recache2; } } } } // Enable helpers for classes which are not RubyObject based. if ((RCLASS_VERSION(klass) & RCLASS_IS_OBJECT_SUBCLASS) != RCLASS_IS_OBJECT_SUBCLASS) { // Let's try to see if we are not given a helper selector. SEL new_sel = helper_sel(selname, selname_len); if (new_sel != NULL) { Method m = class_getInstanceMethod(klass, new_sel); if (m != NULL) { sel = new_sel; method = m; // We need to invert arguments because // #[]= and setObject:forKey: take arguments // in a reverse order if (new_sel == selSetObjectForKey && argc == 2) { VALUE swap = argv[0]; ((VALUE *)argv)[0] = argv[1]; ((VALUE *)argv)[1] = swap; cache_method = false; } goto recache2; } } } // Let's see if we are not trying to call a BridgeSupport function. if (selname[selname_len - 1] == ':') { selname_len--; } std::string name(selname, selname_len); bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name); if (bs_func != NULL) { if ((unsigned)argc < bs_func->args_count || ((unsigned)argc > bs_func->args_count && bs_func->variadic == false)) { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, bs_func->args_count); } std::string types; vm_gen_bs_func_types(argc, argv, bs_func, types); cache->flag = MCACHE_FCALL; cache->sel = sel; cache->klass = klass; cache->as.fcall.bs_function = bs_func; cache->as.fcall.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name); assert(cache->as.fcall.imp != NULL); cache->as.fcall.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub( types, bs_func->variadic, bs_func->args_count, false); } else { // Still nothing, then let's call #method_missing. goto call_method_missing; } } } dispatch: if (cache->flag & MCACHE_RCALL) { if (!cache_method) { cache->flag = 0; } #if ROXOR_VM_DEBUG printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache %p cached %s)\n", class_isMetaClass(klass) ? '+' : '-', class_getName(klass), (void *)self, sel_getName(sel), cache->as.rcall.node->ruby_imp, block, argc, opt, cache, cached ? "true" : "false"); #endif bool block_already_current = vm->is_block_current(block); Class current_klass = vm->get_current_class(); if (!block_already_current) { vm->add_current_block(block); } vm->set_current_class(NULL); Class old_current_super_class = vm->get_current_super_class(); vm->set_current_super_class(current_super_class); SEL old_current_super_sel = vm->get_current_super_sel(); vm->set_current_super_sel(current_super_sel); const bool should_pop_broken_with = sel != selInitialize && sel != selInitialize2; struct Finally { bool block_already_current; Class current_class; Class current_super_class; SEL current_super_sel; bool should_pop_broken_with; RoxorVM *vm; Finally(bool _block_already_current, Class _current_class, Class _current_super_class, SEL _current_super_sel, bool _should_pop_broken_with, RoxorVM *_vm) { block_already_current = _block_already_current; current_class = _current_class; current_super_class = _current_super_class; current_super_sel = _current_super_sel; should_pop_broken_with = _should_pop_broken_with; vm = _vm; } ~Finally() { if (!block_already_current) { vm->pop_current_block(); } vm->set_current_class(current_class); if (should_pop_broken_with) { vm->pop_broken_with(); } vm->set_current_super_class(current_super_class); vm->set_current_super_sel(current_super_sel); vm->pop_current_binding(); } } finalizer(block_already_current, current_klass, old_current_super_class, old_current_super_sel, should_pop_broken_with, vm); // DTrace probe: method__entry if (MACRUBY_METHOD_ENTRY_ENABLED()) { char *class_name = (char *)rb_class2name((VALUE)klass); char *method_name = (char *)sel_getName(sel); char file[PATH_MAX]; unsigned long line = 0; GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line, NULL, 0); MACRUBY_METHOD_ENTRY(class_name, method_name, file, line); } VALUE v = ruby_dispatch(top, self, sel, cache->as.rcall.node, opt, argc, argv); // DTrace probe: method__return if (MACRUBY_METHOD_RETURN_ENABLED()) { char *class_name = (char *)rb_class2name((VALUE)klass); char *method_name = (char *)sel_getName(sel); char file[PATH_MAX]; unsigned long line = 0; GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line, NULL, 0); MACRUBY_METHOD_RETURN(class_name, method_name, file, line); } return v; } else if (cache->flag & MCACHE_OCALL) { if (cache->as.ocall.argc != argc) { goto recache; } if (!cache_method) { cache->flag = 0; } if (block != NULL) { rb_warn("passing a block to an Objective-C method - " \ "will be ignored"); } else if (sel == selNew) { if (self == rb_cNSMutableArray) { self = rb_cRubyArray; } } else if (sel == selClass) { // Because +[NSObject class] returns self. if (RCLASS_META(klass)) { return RCLASS_MODULE(self) ? rb_cModule : rb_cClass; } // Because the CF classes should be hidden, for Ruby compat. if (self == Qnil) { return rb_cNilClass; } if (self == Qtrue) { return rb_cTrueClass; } if (self == Qfalse) { return rb_cFalseClass; } return rb_class_real((VALUE)klass, true); } #if ROXOR_VM_DEBUG printf("objc dispatch %c[<%s %p> %s] imp=%p cache=%p argc=%d (cached=%s)\n", class_isMetaClass(klass) ? '+' : '-', class_getName(klass), (void *)self, sel_getName(sel), cache->as.ocall.imp, cache, argc, cached ? "true" : "false"); #endif id ocrcv = RB2OC(self); if (cache->as.ocall.bs_method != NULL) { Class ocklass = object_getClass(ocrcv); for (int i = 0; i < (int)cache->as.ocall.bs_method->args_count; i++) { bs_element_arg_t *arg = &cache->as.ocall.bs_method->args[i]; if (arg->sel_of_type != NULL) { // BridgeSupport tells us that this argument contains a // selector of the given type, but we don't have any // information regarding the target. RubyCocoa and the // other ObjC bridges do not really require it since they // use the NSObject message forwarding mechanism, but // MacRuby registers all methods in the runtime. // // Therefore, we apply here a naive heuristic by assuming // that either the receiver or one of the arguments of this // call is the future target. const int arg_i = arg->index; assert(arg_i >= 0 && arg_i < argc); if (argv[arg_i] != Qnil) { ID arg_selid = rb_to_id(argv[arg_i]); SEL arg_sel = sel_registerName(rb_id2name(arg_selid)); if (reinstall_method_maybe(ocklass, arg_sel, arg->sel_of_type)) { goto sel_target_found; } for (int j = 0; j < argc; j++) { if (j != arg_i && !SPECIAL_CONST_P(argv[j])) { if (reinstall_method_maybe(*(Class *)argv[j], arg_sel, arg->sel_of_type)) { goto sel_target_found; } } } } sel_target_found: // There can only be one sel_of_type argument. break; } } } return __rb_vm_objc_dispatch(cache->as.ocall.stub, cache->as.ocall.imp, ocrcv, sel, argc, argv); } else if (cache->flag & MCACHE_FCALL) { #if ROXOR_VM_DEBUG printf("C dispatch %s() imp=%p argc=%d (cached=%s)\n", cache->as.fcall.bs_function->name, cache->as.fcall.imp, argc, cached ? "true" : "false"); #endif return (*cache->as.fcall.stub)(cache->as.fcall.imp, argc, argv); } printf("method dispatch is b0rked\n"); abort(); call_method_missing: // Before calling method_missing, let's check if we are not in the following // cases: // // def foo; end; foo(42) // def foo(x); end; foo // // If yes, we need to raise an ArgumentError exception instead. const char *selname = sel_getName(sel); const size_t selname_len = strlen(selname); SEL new_sel = 0; if (argc > 0 && selname[selname_len - 1] == ':') { char buf[100]; assert(sizeof buf > selname_len - 1); strlcpy(buf, selname, sizeof buf); buf[selname_len - 1] = '\0'; new_sel = sel_registerName(buf); } else if (argc == 0) { char buf[100]; snprintf(buf, sizeof buf, "%s:", selname); new_sel = sel_registerName(buf); } if (new_sel != 0) { Method m = class_getInstanceMethod(klass, new_sel); if (m != NULL) { IMP mimp = method_getImplementation(m); if (!UNAVAILABLE_IMP(mimp)) { unsigned expected_argc; rb_vm_method_node_t *node = GET_CORE()->method_node_get(m); if (node != NULL) { expected_argc = node->arity.min; } else { expected_argc = rb_method_getNumberOfArguments(m); expected_argc -= 2; // removing receiver and selector } rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, expected_argc); } } } rb_vm_method_missing_reason_t status; if (opt & DISPATCH_VCALL) { status = METHOD_MISSING_VCALL; } else if (opt & DISPATCH_SUPER) { status = METHOD_MISSING_SUPER; } else { status = METHOD_MISSING_DEFAULT; } return method_missing((VALUE)self, sel, block, argc, argv, status); }
/* * Interprets cblas argument which could be :unit (true) or :nonunit (false or anything other than true/:unit) * * Called by nm_cblas_trsm -- basically inline */ static inline enum CBLAS_DIAG blas_diag_sym(VALUE op) { if (rb_to_id(op) == nm_rb_unit || op == Qtrue) return CblasUnit; return CblasNonUnit; }
static VALUE rldap_search(int argc, VALUE *argv, VALUE obj) { RLDAP_WRAP *wrapper; char *base, *filter; int retval, count, i, scope; LDAPMessage *res, *msg; VALUE ary, rbase, rfilter, rscope; ID iscope; rb_scan_args(argc, argv, "21", &rbase, &rfilter, &rscope); switch(TYPE(rscope)) { case T_NIL: scope = LDAP_SCOPE_SUBTREE; break; case T_FIXNUM: scope = FIX2INT(rscope); break; case T_SYMBOL: case T_STRING: iscope = rb_to_id(rscope); if (iscope == rb_intern("subtree")) scope = LDAP_SCOPE_SUBTREE; if (iscope == rb_intern("base")) scope = LDAP_SCOPE_BASE; if (iscope == rb_intern("one")) scope = LDAP_SCOPE_ONE; break; default: rb_raise(rb_eTypeError, "not a valid scope"); break; } wrapper = get_wrapper(obj); base = StringValuePtr(rbase); filter = StringValuePtr(rfilter); retval = ldap_search_ext_s(wrapper->ld, base, scope, filter, NULL, 0, NULL, NULL, NULL, 0, &res); if (retval != LDAP_SUCCESS) rldap_raise(retval); count = ldap_count_entries(wrapper->ld, res); if (count == -1) { int errno; ldap_get_option(wrapper->ld, LDAP_OPT_RESULT_CODE, &errno); rldap_raise(errno); } ary = rb_ary_new2((long)count); msg = ldap_first_entry(wrapper->ld, res); for (i=0; i<count; i++) { rb_ary_store(ary, (long)i, ldapmessage2obj(wrapper->ld, msg)); msg = ldap_next_entry(wrapper->ld, msg); } return ary; }
static VALUE rb_mod_protected_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED); }
static VALUE rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid) { ID id = rb_to_id(mid); return check_method_visibility(mod, id, NOEX_PRIVATE); }
static VALUE rb_mod_autoload_p(VALUE mod, VALUE sym) { return rb_autoload_p(mod, rb_to_id(sym)); }
static VALUE rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid) { ID id = rb_to_id(mid); return check_method_visibility(mod, id, NOEX_PROTECTED); }
static VALUE so_to_id(VALUE self, VALUE obj) { return ID2SYM(rb_to_id(obj)); }
static VALUE rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) { rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); return mod; }
static VALUE rrrd_rrd_fetch(int argc, VALUE *argv, VALUE self) { VALUE function, options; VALUE resolution, starts_at, ends_at; rb_scan_args(argc, argv, "11", &function, &options); list arguments = rrrd_list_new(); rrrd_add_filename_arg(self, &arguments); // consolidation function function = rb_str_new2(rb_id2name(rb_to_id(function))); function = rb_funcall(function, rb_intern("upcase"), 0); rrrd_add_arg(&arguments, STR2CSTR(function)); if (RTEST(options)) { // extract options from hash resolution = rb_hash_aref(options, ID2SYM(rb_intern("resolution"))); starts_at = rb_hash_aref(options, ID2SYM(rb_intern("starts_at"))); ends_at = rb_hash_aref(options, ID2SYM(rb_intern("ends_at"))); // resolution if (RTEST(resolution)) { resolution = rb_fix2str(resolution, 10); rrrd_add_arg(&arguments, "--resolution"); rrrd_add_arg(&arguments, STR2CSTR(resolution)); } // start time if (RTEST(starts_at)) { starts_at = rb_funcall(starts_at, rb_intern("to_i"), 0); starts_at = rb_fix2str(starts_at, 10); rrrd_add_arg(&arguments, "--start"); rrrd_add_arg(&arguments, STR2CSTR(starts_at)); } // end time if (RTEST(ends_at)) { ends_at = rb_funcall(ends_at, rb_intern("to_i"), 0); ends_at = rb_fix2str(ends_at, 10); rrrd_add_arg(&arguments, "--end"); rrrd_add_arg(&arguments, STR2CSTR(ends_at)); } } time_t start, end; unsigned long step, ds_count; char **raw_names; rrd_value_t *raw_data; rrd_fetch(arguments.length, arguments.strings, &start, &end, &step, &ds_count, &raw_names, &raw_data); rrrd_free_arguments(arguments); rrrd_check_for_errors(); int i; int index = 0; VALUE data = rb_ary_new(); for (i = start + step; i <= end; i+= step) { int j; VALUE timestamp = rb_time_new(i, 0); VALUE values = rb_hash_new(); for (j = 0; j < ds_count; j++) { VALUE key = ID2SYM(rb_intern(raw_names[j])); rb_hash_aset(values, key, rb_float_new(raw_data[index++])); } VALUE args[] = { timestamp, values }; VALUE tuple = rb_class_new_instance(2, args, Tuple); rb_ary_push(data, tuple); } free(raw_data); return data; }
VALUE rb_obj_method(VALUE obj, VALUE vid) { return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qfalse); }
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 = NUM2SIZE(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; }
static VALUE rb_mod_public_instance_method(VALUE mod, VALUE vid) { return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qtrue); }
static VALUE rb_mod_public_method_defined(VALUE mod, VALUE mid) { return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC); }