VALUE rb_string_value(volatile VALUE* object_variable) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); if(!kind_of<String>(env->get_object(*object_variable))) { *object_variable = rb_str_to_str(*object_variable); } return *object_variable; }
void rb_io_check_closed(rb_io_t* iot) { VALUE io_handle = iot->handle; NativeMethodEnvironment* env = NativeMethodEnvironment::get(); IO* io = c_as<IO>(env->get_object(io_handle)); if(io->descriptor()->to_native() == -1) { rb_raise(rb_eIOError, "closed stream"); } }
VALUE rb_ary_unshift(VALUE self, VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Array* array = capi_get_array(env, self); array->unshift(env->state(), env->get_object(object)); capi_update_array(env, self); return self; }
VALUE rb_ary_unshift(VALUE self_handle, VALUE object_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Array* self = capi_get_array(env, self_handle); self->unshift(env->state(), env->get_object(object_handle)); capi_update_array(env, self_handle); return self_handle; }
void rb_io_check_writable(rb_io_t* iot) { VALUE io_handle = iot->handle; NativeMethodEnvironment* env = NativeMethodEnvironment::get(); IO* io = c_as<IO>(env->get_object(io_handle)); int io_mode = io->mode()->to_native() & O_ACCMODE; if(!(O_WRONLY == io_mode || O_RDWR == io_mode)) { rb_raise(rb_eIOError, "not opened for writing"); } }
VALUE rb_ivar_defined(VALUE obj_handle, ID ivar_name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Symbol* ivar = reinterpret_cast<Symbol*>(ivar_name); Object* obj = env->get_object(obj_handle); Object* ret = obj->ivar_defined(env->state(), ivar); return env->get_handle(ret); }
char* rb_string_value_ptr(volatile VALUE* object_variable) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); VALUE str = rb_string_value(object_variable); // Type check. (void)c_as<String>(env->get_object(str)); return RSTRING_PTR(str); }
void rb_io_check_readable(rb_io_t* iot) { VALUE io_handle = iot->handle; NativeMethodEnvironment* env = NativeMethodEnvironment::get(); IO* io = c_as<IO>(env->get_object(io_handle)); if ((io->mode()->to_native() & O_ACCMODE) != O_RDONLY) { rb_raise(rb_eIOError, "not opened for reading"); } }
void capi_define_method(const char* file, VALUE target, const char* name, CApiGenericFunction fptr, int arity, CApiMethodKind kind) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); VM* state = env->state(); Symbol* method_name = state->symbol(name); Module* module = NULL; if (kind == cCApiSingletonMethod) { module = c_as<Module>(env->get_object(target)->metaclass(env->state())); } else { module = c_as<Module>(env->get_object(target)); } NativeMethod* method = NULL; method = NativeMethod::create(state, String::create(state, file), module, method_name, fptr, Fixnum::from(arity)); MethodVisibility* visibility = MethodVisibility::create(state); visibility->method(state, method); switch(kind) { case cCApiPrivateMethod: visibility->visibility(state, state->symbol("private")); break; case cCApiProtectedMethod: visibility->visibility(state, state->symbol("protected")); break; default: /* Also catches singletons for now. @todo Verify OK. --rue */ visibility->visibility(state, state->symbol("public")); break; } module->method_table()->store(state, method_name, visibility); state->global_cache->clear(module, method_name); }
VALUE rb_file_path_value(volatile VALUE* obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); STATE = env->state(); if(!kind_of<String>(env->get_object(*obj))) { *obj = rb_funcall(env->get_handle(G(type)), rb_intern("coerce_to_path"), 1, *obj); } return *obj; }
VALUE rb_call_super(int argc, const VALUE *argv) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object** args = reinterpret_cast<Object**>(alloca(sizeof(Object*) * argc)); for(int i = 0; i < argc; i++) { args[i] = env->get_object(argv[i]); } return capi_call_super_native(env, argc, args); }
int rb_big_sign(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Bignum* big = c_as<Bignum>(env->get_object(obj)); if (big->mp_val()->sign == MP_NEG) { return -1; } return 1; }
int rb_enc_get_index(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* val = env->get_object(obj); Encoding* enc = Encoding::get_object_encoding(env->state(), val); if(enc->nil_p()) return 0; return Encoding::find_index(env->state(), enc->get_encoding()->name); }
rb_encoding* rb_enc_get(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* val = env->get_object(obj); if(!val->reference_p() && !val->symbol_p()) return 0; Encoding* enc = Encoding::get_object_encoding(env->state(), val); if(enc->nil_p()) return 0; return enc->get_encoding(); }
VALUE rb_call_super(int argc, const VALUE *argv) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* args[argc]; for(int i = 0; i < argc; i++) { args[i] = env->get_object(argv[i]); } return capi_call_super_native(env, argc, args); }
double rb_num2dbl(VALUE val) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); if(try_as<Float>(env->get_object(val))) { return capi_get_float(env, val)->val; } // @todo should coerce other types return 0.0; }
void test_native_method_environment_get_object() { NativeMethodEnvironment* nme = create_native_method_environment(); String* str = String::create(state, "test"); Integer* id = str->id(state); VALUE handle = nme->get_handle(str); TS_ASSERT_EQUALS(id, nme->get_object(handle)->id(state)); destroy_native_method_environment(nme); }
/* For debugging. */ void __show_subtend__(VALUE obj_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* object = env->get_object(obj_handle); if(!object) { std::cout << "the object is NULL, check if an exception was raised." << std::endl; return; } object->show(env->state()); }
/** * Common implementation for rb_funcall* */ VALUE capi_funcall_backend(const char* file, int line, VALUE receiver, ID method_name, size_t arg_count, VALUE* arg_array) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); env->flush_cached_data(); Array* args = Array::create(env->state(), arg_count); for(size_t i = 0; i < arg_count; i++) { args->set(env->state(), i, env->get_object(arg_array[i])); } Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { blk = env->get_object(blk_handle); env->set_outgoing_block(0); } Object* recv = env->get_object(receiver); // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); Object* ret = recv->send(env->state(), env->current_call_frame(), reinterpret_cast<Symbol*>(method_name), args, blk); // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; if(ret) ret_handle = env->get_handle(ret); // Re-entering extension code ENTER_CAPI(env->state()); env->update_cached_data(); // An exception occurred if(!ret) env->current_ep()->return_to(env); return ret_handle; }
void capi_define_method(const char* file, VALUE target, const char* name, CApiGenericFunction fptr, int arity, CApiMethodKind kind) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State* state = env->state(); Symbol* method_name = state->symbol(name); Module* module = NULL; if(kind == cCApiSingletonMethod) { module = c_as<Module>(env->get_object(target)->singleton_class(env->state())); } else { module = c_as<Module>(env->get_object(target)); } NativeMethod* method = NULL; method = NativeMethod::create(state, String::create(state, file), module, method_name, (void*)fptr, Fixnum::from(arity), env->current_native_frame()->capi_lock_index()); Symbol* visibility; switch(kind) { case cCApiPrivateMethod: visibility = G(sym_private); break; case cCApiProtectedMethod: visibility = G(sym_protected); break; default: /* Also catches singletons for now. @todo Verify OK. --rue */ visibility = G(sym_public); break; } module->add_method(state, method_name, method, visibility); System::vm_reset_method_cache(env->state(), module, method_name, env->current_call_frame()); }
long long rb_num2ll(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* object = env->get_object(obj); if(Bignum* big = try_as<Bignum>(object)) { return big->to_long_long(); } return (long long)rb_num2long(obj); }
unsigned long rb_num2ulong(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* object = env->get_object(obj); if(try_as<Bignum>(object)) { return rb_big2ulong(obj); } return (unsigned long)rb_num2long(obj); }
/** @note Shares code with rb_define_class_under, change there too. --rue */ VALUE rb_define_module_under(VALUE parent_handle, const char* name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Module* parent = c_as<Module>(env->get_object(parent_handle)); Symbol* constant = env->state()->symbol(name); Module* module = rubinius::Helpers::open_module(env->state(), env->current_call_frame(), parent, constant); return env->get_handle(module); }
VALUE rb_obj_as_string(VALUE obj_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* object = env->get_object(obj_handle); if (kind_of<String>(object)) { return obj_handle; } return rb_funcall2(obj_handle, rb_intern("to_s"), 0, NULL); }
double rb_big2dbl(VALUE obj) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Bignum* big = c_as<Bignum>(env->get_object(obj)); double d = big->to_double(env->state()); if(std::isinf(d)) { rb_warn("Bignum out of Float range"); d = HUGE_VAL; } return d; }
char* rb_str_copied_ptr(VALUE self) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); String* str = c_as<String>(env->get_object(self)); char* data = (char*)malloc(sizeof(char) * str->byte_size() + 1); memcpy(data, str->c_str(env->state()), str->byte_size()); data[str->byte_size()] = 0; return data; }
VALUE rb_ary_to_ary(VALUE object) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object* obj = env->get_object(object); if(kind_of<Array>(obj)) { return object; } ID to_ary_id = rb_intern("to_ary"); if(rb_respond_to(object, to_ary_id)) { return rb_funcall(object, to_ary_id, 0); } else { Array* array = Array::create(env->state(), 1); array->set(env->state(), 0, env->get_object(object)); return env->get_handle(array); } }
/** * Common implementation for rb_funcall* * * @todo Set up permanent SendSites through macroing? * @todo Stricter action check? */ VALUE capi_funcall_backend(const char* file, int line, VALUE receiver, ID method_name, std::size_t arg_count, VALUE* arg_array) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); env->flush_cached_data(false); Array* args = Array::create(env->state(), arg_count); for(size_t i = 0; i < arg_count; i++) { args->set(env->state(), i, env->get_object(arg_array[i])); } Object* recv = env->get_object(receiver); Object* ret = recv->send(env->state(), env->current_call_frame(), reinterpret_cast<Symbol*>(method_name), args, RBX_Qnil); env->update_cached_data(); // An exception occurred if(!ret) env->current_ep()->return_to(env); return env->get_handle(ret); }
VALUE rb_class_name(VALUE class_handle) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); State* state = env->state(); Class* class_object = c_as<Class>(env->get_object(class_handle)); String* str = class_object->get_name(state); if(str->nil_p()) { std::string desc = class_object->to_string(state); str = String::create(state, desc.c_str(), desc.size()); } return env->get_handle(str); }
VALUE rb_const_get_at(VALUE module_handle, ID id_name) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Symbol* name = reinterpret_cast<Symbol*>(id_name); Module* module = c_as<Module>(env->get_object(module_handle)); bool found = false; Object* val = module->get_const(env->state(), name, &found); if(found) return env->get_handle(val); return const_missing(module_handle, id_name); }