/* * call-seq: * Struct.new( [aString] [, aSym]+> ) -> StructClass * StructClass.new(arg, ...) -> obj * StructClass[arg, ...] -> obj * * Creates a new class, named by <i>aString</i>, containing accessor * methods for the given symbols. If the name <i>aString</i> is * omitted, an anonymous structure class will be created. Otherwise, * the name of this struct will appear as a constant in class * <code>Struct</code>, so it must be unique for all * <code>Struct</code>s in the system and should start with a capital * letter. Assigning a structure class to a constant effectively gives * the class the name of the constant. * * <code>Struct::new</code> returns a new <code>Class</code> object, * which can then be used to create specific instances of the new * structure. The number of actual parameters must be * less than or equal to the number of attributes defined for this * class; unset parameters default to <code>nil</code>. Passing too many * parameters will raise an <code>ArgumentError</code>. * * The remaining methods listed in this section (class and instance) * are defined for this generated class. * * # Create a structure with a name in Struct * Struct.new("Customer", :name, :address) #=> Struct::Customer * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main"> * * # Create a structure named by its constant * Customer = Struct.new(:name, :address) #=> Customer * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main"> */ static mrb_value mrb_struct_s_def(mrb_state *mrb, mrb_value klass) { mrb_value name, rest; mrb_value *pargv; int argcnt; mrb_int i; mrb_value b, st; mrb_sym id; mrb_value *argv; int argc; name = mrb_nil_value(); rest = mrb_nil_value(); mrb_get_args(mrb, "*&", &argv, &argc, &b); if (argc == 0) { /* special case to avoid crash */ rest = mrb_ary_new(mrb); } else { if (argc > 0) name = argv[0]; if (argc > 1) rest = argv[1]; if (mrb_array_p(rest)) { if (!mrb_nil_p(name) && mrb_symbol_p(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ mrb_ary_unshift(mrb, rest, name); name = mrb_nil_value(); } } else { pargv = &argv[1]; argcnt = argc-1; if (!mrb_nil_p(name) && mrb_symbol_p(name)) { /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ name = mrb_nil_value(); pargv = &argv[0]; argcnt++; } rest = mrb_ary_new_from_values(mrb, argcnt, pargv); } for (i=0; i<RARRAY_LEN(rest); i++) { id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]); RARRAY_PTR(rest)[i] = mrb_symbol_value(id); } } st = make_struct(mrb, name, rest, struct_class(mrb)); if (!mrb_nil_p(b)) { mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(klass)); } return st; }
/* * call-seq: * struct[symbol] -> anObject * struct[fixnum] -> anObject * * Attribute Reference---Returns the value of the instance variable * named by <i>symbol</i>, or indexed (0..length-1) by * <i>fixnum</i>. Will raise <code>NameError</code> if the named * variable does not exist, or <code>IndexError</code> if the index is * out of range. * * Customer = Struct.new(:name, :address, :zip) * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) * * joe["name"] #=> "Joe Smith" * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ mrb_value mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx) { mrb_int i; if (mrb_string_p(idx)) { mrb_value sym = mrb_check_intern_str(mrb, idx); if (mrb_nil_p(sym)) { mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx); } idx = sym; } if (mrb_symbol_p(idx)) { return mrb_struct_aref_id(mrb, s, mrb_symbol(idx)); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); if (RSTRUCT_LEN(s) <= i) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); return RSTRUCT_PTR(s)[i]; }
/* * call-seq: * obj.method_missing(symbol [, *args] ) -> result * * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle. * <i>symbol</i> is the symbol for the method called, and <i>args</i> * are any arguments that were passed to it. By default, the interpreter * raises an error when this method is called. However, it is possible * to override the method to provide more dynamic behavior. * If it is decided that a particular method should not be handled, then * <i>super</i> should be called, so that ancestors can pick up the * missing method. * The example below creates * a class <code>Roman</code>, which responds to methods with names * consisting of roman numerals, returning the corresponding integer * values. * * class Roman * def romanToInt(str) * # ... * end * def method_missing(methId) * str = methId.id2name * romanToInt(str) * end * end * * r = Roman.new * r.iv #=> 4 * r.xxiii #=> 23 * r.mm #=> 2000 */ static mrb_value mrb_bob_missing(mrb_state *mrb, mrb_value mod) { mrb_value name, *a; int alen; mrb_value inspect; mrb_get_args(mrb, "o*", &name, &a, &alen); if (!mrb_symbol_p(name)) { mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); } } else { inspect = mrb_any_to_s(mrb, mod); } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S", mrb_sym2str(mrb, mrb_symbol(name)), inspect); /* not reached */ return mrb_nil_value(); }
mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { mrb_int i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_string_p(idx) || mrb_symbol_p(idx)) { return mrb_struct_aset_id(mrb, s, mrb_obj_to_sym(mrb, idx), val); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } if (RSTRUCT_LEN(s) <= i) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } return RSTRUCT_PTR(s)[i] = val; }
static mrb_int getButtonArg(mrb_state *mrb) { mrb_int num; mrb_value arg; mrb_get_args(mrb, "o", &arg); if (mrb_fixnum_p(arg)) { num = mrb_fixnum(arg); } else if (mrb_symbol_p(arg) && rgssVer >= 3) { mrb_value symHash = getMrbData(mrb)->buttoncodeHash; mrb_value numVal = mrb_hash_fetch(mrb, symHash, arg, mrb_fixnum_value(Input::None)); num = mrb_fixnum(numVal); } else { // FIXME: RMXP allows only few more types that // don't make sense (symbols in pre 3, floats) num = 0; } return num; }
bool rubyval_to_ccvaluemapintkey(mrb_state* mrb, mrb_value arg, cocos2d::ValueMapIntKey* ret, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); ValueMapIntKey& dict = *ret; for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); int int_key = 0; if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); int_key = atoi(kstr); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); int_key = atoi(kstr); } else { return false; } Value val; if (! rubyval_to_ccvalue(mrb, hv, &val)) { return false; } dict[int_key] = val; } return true; }
bool rubyval_to_dictionary(mrb_state* mrb, mrb_value arg, __Dictionary** outValue, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); __Dictionary* dic = __Dictionary::create(); for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else { CCASSERT(false, "not supported key value type"); } } *outValue = dic; return true; }
mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { long i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_string_p(idx) || mrb_symbol_p(idx)) { return mrb_struct_aset_id(mrb, s, mrb_to_id(mrb, idx), val); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); } if (RSTRUCT_LEN(s) <= i) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); } mrb_struct_modify(s); return RSTRUCT_PTR(s)[i] = val; }
static mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { mrb_int i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_string_p(idx)) { mrb_value sym = mrb_check_intern_str(mrb, idx); if (mrb_nil_p(sym)) { mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx); } idx = sym; } if (mrb_symbol_p(idx)) { return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val); } i = mrb_int(mrb, idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } if (RSTRUCT_LEN(s) <= i) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } return RSTRUCT_PTR(s)[i] = val; }
static mrb_sym mrb_sym_value(mrb_state *mrb, mrb_value val) { if (mrb_string_p(val)) { return mrb_intern_str(mrb, val); } else if(!mrb_symbol_p(val)) { mrb_value obj = mrb_funcall(mrb, val, "inspect", 0); mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol", mrb_string_value_ptr(mrb, obj)); } return mrb_symbol(val); }
static mrb_value get_sym_or_str_arg(mrb_state *mrb) { mrb_value sym_or_str; mrb_get_args(mrb, "o", &sym_or_str); if (mrb_symbol_p(sym_or_str) || mrb_string_p(sym_or_str)) { return sym_or_str; } else { mrb_value obj = mrb_funcall(mrb, sym_or_str, "inspect", 0); mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); return mrb_nil_value(); } }
TMO mrb_timeout_value(mrb_state *mrb, mrb_value tmo) { if (mrb_fixnum_p(tmo)) { return (TMO)mrb_fixnum(tmo); } if (mrb_symbol_p(tmo)) { if (mrb_symbol(tmo) == mrb_intern_lit(mrb, "polling")) { return (TMO)TMO_POL; } if (mrb_symbol(tmo) == mrb_intern_lit(mrb, "forever")) { return (TMO)TMO_FEVR; } } mrb_raisef(mrb, E_TYPE_ERROR, "wrong timeout value (%S)", tmo); }
/* * call-seq: * obj.respond_to?(symbol, include_private=false) -> true or false * * Returns +true+ if _obj_ responds to the given * method. Private methods are included in the search only if the * optional second parameter evaluates to +true+. * * If the method is not implemented, * as Process.fork on Windows, File.lchmod on GNU/Linux, etc., * false is returned. * * If the method is not defined, <code>respond_to_missing?</code> * method is called and the result is returned. */ mrb_value obj_respond_to(mrb_state *mrb, mrb_value self) { mrb_value *argv; int argc; mrb_value mid, priv; mrb_sym id, rtm_id; mrb_bool respond_to_p = TRUE; mrb_get_args(mrb, "*", &argv, &argc); mid = argv[0]; if (argc > 1) priv = argv[1]; else priv = mrb_nil_value(); if (mrb_symbol_p(mid)) { id = mrb_symbol(mid); } else { mrb_value tmp; if (!mrb_string_p(mid)) { tmp = mrb_check_string_type(mrb, mid); if (mrb_nil_p(tmp)) { tmp = mrb_inspect(mrb, mid); mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); } } tmp = mrb_check_intern_str(mrb, mid); if (mrb_nil_p(tmp)) { respond_to_p = FALSE; } else { id = mrb_symbol(tmp); } } if (respond_to_p) { respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv)); } if (!respond_to_p) { rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19); if (basic_obj_respond_to(mrb, self, rtm_id, !mrb_test(priv))) { return mrb_funcall_argv(mrb, self, rtm_id, argc, argv); } } return mrb_bool_value(respond_to_p); }
static mrb_sym get_valid_iv_sym(mrb_state *mrb, mrb_value iv_name) { mrb_sym iv_name_id; mrb_assert(mrb_symbol_p(iv_name) || mrb_string_p(iv_name)); if (mrb_string_p(iv_name)) { iv_name_id = mrb_intern_cstr(mrb, RSTRING_PTR(iv_name)); valid_iv_name(mrb, iv_name_id, RSTRING_PTR(iv_name), RSTRING_LEN(iv_name)); } else { iv_name_id = mrb_symbol(iv_name); check_iv_name(mrb, iv_name_id); } return iv_name_id; }
/* * call-seq: * struct[symbol] -> anObject * struct[fixnum] -> anObject * * Attribute Reference---Returns the value of the instance variable * named by <i>symbol</i>, or indexed (0..length-1) by * <i>fixnum</i>. Will raise <code>NameError</code> if the named * variable does not exist, or <code>IndexError</code> if the index is * out of range. * * Customer = Struct.new(:name, :address, :zip) * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) * * joe["name"] #=> "Joe Smith" * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ mrb_value mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx) { long i; if (mrb_string_p(idx) || mrb_symbol_p(idx)) { return mrb_struct_aref_id(mrb, s, mrb_to_id(mrb, idx)); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); if (RSTRUCT_LEN(s) <= i) mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); return RSTRUCT_PTR(s)[i]; }
/* * call-seq: * struct[symbol] -> anObject * struct[fixnum] -> anObject * * Attribute Reference---Returns the value of the instance variable * named by <i>symbol</i>, or indexed (0..length-1) by * <i>fixnum</i>. Will raise <code>NameError</code> if the named * variable does not exist, or <code>IndexError</code> if the index is * out of range. * * Customer = Struct.new(:name, :address, :zip) * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) * * joe["name"] #=> "Joe Smith" * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ static mrb_value mrb_struct_aref(mrb_state *mrb, mrb_value s) { mrb_value idx; mrb_get_args(mrb, "o", &idx); if (mrb_string_p(idx)) { mrb_value sym = mrb_check_intern_str(mrb, idx); if (mrb_nil_p(sym)) { mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx); } idx = sym; } if (mrb_symbol_p(idx)) { return struct_aref_sym(mrb, s, mrb_symbol(idx)); } return struct_aref_int(mrb, s, mrb_int(mrb, idx)); }
static mrb_value mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) { mrb_value id; mrb_bool method_defined_p; id = get_sym_or_str_arg(mrb); if (mrb_symbol_p(id)) { method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id)); } else { mrb_value sym = mrb_check_intern_str(mrb, id); if (mrb_nil_p(sym)) { method_defined_p = FALSE; } else { method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym)); } } return mrb_bool_value(method_defined_p); }
static mrb_value struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id) { mrb_value members, *ptr; const mrb_value *ptr_members; mrb_int i, len; members = struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); ptr = RSTRUCT_PTR(obj); for (i=0; i<len; i++) { mrb_value slot = ptr_members[i]; if (mrb_symbol_p(slot) && mrb_symbol(slot) == id) { return ptr[i]; } } mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id)); return mrb_nil_value(); /* not reached */ }
static mrb_value mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) { mrb_value id; mrb_bool defined_p; id = get_sym_or_str_arg(mrb); if (mrb_symbol_p(id)) { check_cv_name_sym(mrb, mrb_symbol(id)); defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(id)); } else { mrb_value sym; check_cv_name_str(mrb, id); sym = mrb_check_intern_str(mrb, id); if (mrb_nil_p(sym)) { defined_p = FALSE; } else { defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(sym)); } } return mrb_bool_value(defined_p); }
static mrb_value cfunc_call(mrb_state *mrb, mrb_value self) { int margc; mrb_value mresult_type, mname, *margs; void **values = NULL; ffi_type **args = NULL; mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc); void *fp = NULL; if(mrb_string_p(mname) || mrb_symbol_p(mname)) { void *dlh = dlopen(NULL, RTLD_LAZY); fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname)); dlclose(dlh); } else { fp = cfunc_pointer_ptr(mname); } if(fp == NULL) { mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname)); goto cfunc_call_exit; } args = malloc(sizeof(ffi_type*) * margc); values = malloc(sizeof(void*) * margc); mrb_sym sym_to_ffi_value = mrb_intern(mrb, "to_ffi_value"); mrb_value nil_ary[1]; nil_ary[0] = mrb_nil_value(); for(int i = 0; i < margc; ++i) { if(mrb_respond_to(mrb, margs[i], sym_to_ffi_value)) { args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value; values[i] = cfunc_pointer_ptr(mrb_funcall_argv(mrb, margs[i], sym_to_ffi_value, 1, nil_ary)); } else { cfunc_mrb_raise_without_jump(mrb, E_TYPE_ERROR, "ignore argument type %s", mrb_obj_classname(mrb, margs[i])); goto cfunc_call_exit; } } ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value; if (result_type == NULL) { cfunc_mrb_raise_without_jump(mrb, E_ARGUMENT_ERROR, "ignore return type %s", mrb_class_name(mrb, mrb_class_ptr(mresult_type))); goto cfunc_call_exit; } mrb_value mresult = mrb_nil_value(); ffi_cif cif; if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) { void *result; if(result_type->size > sizeof(long)) { result = malloc(result_type->size); } else if(result_type->size) { result = malloc(sizeof(long)); } else { result = NULL; } ffi_call(&cif, fp, result, values); if(result) { mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, true); mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr); } } else { mrb_raisef(mrb, E_NAME_ERROR, "Can't find C function %s", mname); goto cfunc_call_exit; } cfunc_call_exit: free(values); free(args); return mresult; }