Commit b290e98f authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto Committed by GitHub

Merge pull request #3757 from christopheraue/module_const_get_class_path

Extended Module#const_get to support class paths
parents cf23a853 f937af57
......@@ -84,6 +84,13 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
/*
* Finds the index of a substring in a string
*/
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
/*
* Appends self to other. Returns self as a concatnated string.
*
......
......@@ -2160,14 +2160,44 @@ mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
return const_defined(mrb, mod, id, inherit);
}
static mrb_value
mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
{
check_const_name_sym(mrb, id);
return mrb_const_get(mrb, mod, id);
}
static mrb_value
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
mrb_value path;
mrb_sym id;
char *ptr;
mrb_int off, end, len;
mrb_get_args(mrb, "n", &id);
check_const_name_sym(mrb, id);
return mrb_const_get(mrb, mod, id);
mrb_get_args(mrb, "o", &path);
if (mrb_symbol_p(path)) {
/* const get with symbol */
id = mrb_symbol(path);
return mrb_const_get_sym(mrb, mod, id);
}
/* const get with class path string */
path = mrb_string_type(mrb, path);
ptr = RSTRING_PTR(path);
len = RSTRING_LEN(path);
off = 0;
while (off < len) {
end = mrb_str_index_lit(mrb, path, "::", off);
end = (end == -1) ? len : end;
id = mrb_intern(mrb, ptr+off, end-off);
mod = mrb_const_get_sym(mrb, mod, id);
off = (end == len) ? end : end+2;
}
return mod;
}
static mrb_value
......
......@@ -478,15 +478,14 @@ str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
return str_subseq(mrb, str, beg, len);
}
static mrb_int
str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
MRB_API mrb_int
mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset)
{
mrb_int pos;
char *s, *sptr;
mrb_int len, slen;
char *s;
mrb_int len;
len = RSTRING_LEN(str);
slen = RSTRING_LEN(sub);
if (offset < 0) {
offset += len;
if (offset < 0) return -1;
......@@ -498,14 +497,24 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
}
if (slen == 0) return offset;
/* need proceed one character at a time */
sptr = RSTRING_PTR(sub);
slen = RSTRING_LEN(sub);
len = RSTRING_LEN(str) - offset;
pos = mrb_memsearch(sptr, slen, s, len);
if (pos < 0) return pos;
return pos + offset;
}
static mrb_int
str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
{
const char *ptr;
mrb_int len;
ptr = RSTRING_PTR(str2);
len = RSTRING_LEN(str2);
return mrb_str_index(mrb, str, ptr, len, offset);
}
static void
check_frozen(mrb_state *mrb, struct RString *s)
{
......@@ -1096,7 +1105,7 @@ num_index:
return str;
case MRB_TT_STRING:
if (str_index(mrb, str, indx, 0) != -1)
if (str_index_str(mrb, str, indx, 0) != -1)
return mrb_str_dup(mrb, indx);
return mrb_nil_value();
......@@ -1563,7 +1572,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
mrb_value str2;
mrb_get_args(mrb, "S", &str2);
if (str_index(mrb, self, str2, 0) < 0)
if (str_index_str(mrb, self, str2, 0) < 0)
return mrb_bool_value(FALSE);
return mrb_bool_value(TRUE);
}
......@@ -1590,7 +1599,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
* "hello".index(/[aeiou]/, -3) #=> 4
*/
static mrb_value
mrb_str_index(mrb_state *mrb, mrb_value str)
mrb_str_index_m(mrb_state *mrb, mrb_value str)
{
mrb_value *argv;
mrb_int argc;
......@@ -1631,7 +1640,7 @@ mrb_str_index(mrb_state *mrb, mrb_value str)
}
/* fall through */
case MRB_TT_STRING:
pos = str_index(mrb, str, sub, pos);
pos = str_index_str(mrb, str, sub, pos);
break;
}
......@@ -2752,7 +2761,7 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */
mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */
mrb_define_method(mrb, s, "index", mrb_str_index, MRB_ARGS_ANY()); /* 15.2.10.5.22 */
mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); /* 15.2.10.5.22 */
mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */
mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */
mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */
......
......@@ -268,6 +268,12 @@ assert('Module#const_get', '15.2.2.4.21') do
end
assert_equal 42, Test4ConstGet.const_get(:Const4Test4ConstGet)
assert_equal 42, Test4ConstGet.const_get("Const4Test4ConstGet")
assert_equal 42, Object.const_get("Test4ConstGet::Const4Test4ConstGet")
assert_raise(TypeError){ Test4ConstGet.const_get(123) }
assert_raise(NameError){ Test4ConstGet.const_get(:I_DO_NOT_EXIST) }
assert_raise(NameError){ Test4ConstGet.const_get("I_DO_NOT_EXIST::ME_NEITHER") }
end
assert('Module#const_missing', '15.2.2.4.22') do
......@@ -280,7 +286,7 @@ assert('Module#const_missing', '15.2.2.4.22') do
assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist)
end
assert('Module#const_get', '15.2.2.4.23') do
assert('Module#const_set', '15.2.2.4.23') do
module Test4ConstSet
Const4Test4ConstSet = 42
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment