diff options
| -rw-r--r-- | build_config/ci/gcc-clang.rb | 6 | ||||
| -rw-r--r-- | examples/mrbgems/c_and_ruby_extension_example/src/example.c | 5 | ||||
| -rw-r--r-- | examples/mrbgems/c_extension_example/src/example.c | 5 | ||||
| -rw-r--r-- | include/mruby.h | 14 | ||||
| -rw-r--r-- | include/mruby/array.h | 2 | ||||
| -rw-r--r-- | include/mruby/hash.h | 2 | ||||
| -rw-r--r-- | include/mruby/string.h | 21 | ||||
| -rw-r--r-- | mrbgems/mruby-io/src/file.c | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-kernel-ext/src/kernel.c | 43 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/mrblib/string.rb | 30 | ||||
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 64 | ||||
| -rw-r--r-- | mrbgems/mruby-struct/src/struct.c | 2 | ||||
| -rw-r--r-- | mrblib/string.rb | 44 | ||||
| -rw-r--r-- | src/class.c | 2 | ||||
| -rw-r--r-- | src/error.c | 2 | ||||
| -rw-r--r-- | src/kernel.c | 1 | ||||
| -rw-r--r-- | src/object.c | 53 | ||||
| -rw-r--r-- | src/string.c | 58 | ||||
| -rw-r--r-- | src/vm.c | 6 |
20 files changed, 185 insertions, 181 deletions
diff --git a/build_config/ci/gcc-clang.rb b/build_config/ci/gcc-clang.rb index aa4a1a87d..eb4331e65 100644 --- a/build_config/ci/gcc-clang.rb +++ b/build_config/ci/gcc-clang.rb @@ -6,7 +6,7 @@ MRuby::Build.new('full-debug') do |conf| # include all core GEMs conf.gembox 'full-core' - conf.cc.defines += %w(MRB_GC_STRESS MRB_USE_DEBUG_HOOK) + conf.cc.defines += %w(MRB_GC_STRESS MRB_USE_DEBUG_HOOK MRB_UTF8_STRING) conf.enable_test end @@ -18,7 +18,7 @@ MRuby::Build.new do |conf| conf.gembox 'full-core' conf.gem :core => 'mruby-bin-debugger' conf.compilers.each do |c| - c.defines += %w(MRB_GC_FIXED_ARENA) + c.defines += %w(MRB_GC_FIXED_ARENA MRB_UTF8_STRING) end conf.enable_bintest conf.enable_test @@ -30,7 +30,7 @@ MRuby::Build.new('cxx_abi') do |conf| conf.gembox 'full-core' conf.cc.flags += %w(-fpermissive) conf.compilers.each do |c| - c.defines += %w(MRB_GC_FIXED_ARENA) + c.defines += %w(MRB_GC_FIXED_ARENA MRB_UTF8_STRING) end conf.enable_test diff --git a/examples/mrbgems/c_and_ruby_extension_example/src/example.c b/examples/mrbgems/c_and_ruby_extension_example/src/example.c index 1fdb1078d..f1d7971c2 100644 --- a/examples/mrbgems/c_and_ruby_extension_example/src/example.c +++ b/examples/mrbgems/c_and_ruby_extension_example/src/example.c @@ -5,9 +5,8 @@ static mrb_value mrb_c_method(mrb_state *mrb, mrb_value self) { - mrb_value self_str = mrb_str_to_str(mrb, self); - - printf("%s: A C Extension\n", mrb_str_to_cstr(mrb, self_str)); + mrb_ensure_string_type(mrb, self); + printf("%s: A C Extension\n", mrb_str_to_cstr(mrb, self)); return self; } diff --git a/examples/mrbgems/c_extension_example/src/example.c b/examples/mrbgems/c_extension_example/src/example.c index 727c7c698..fe872c933 100644 --- a/examples/mrbgems/c_extension_example/src/example.c +++ b/examples/mrbgems/c_extension_example/src/example.c @@ -5,9 +5,8 @@ static mrb_value mrb_c_method(mrb_state *mrb, mrb_value self) { - mrb_value self_str = mrb_str_to_str(mrb, self); - - printf("%s: A C Extension\n", mrb_str_to_cstr(mrb, self_str)); + mrb_ensure_string_type(mrb, self); + printf("%s: A C Extension\n", mrb_str_to_cstr(mrb, self)); return self; } diff --git a/include/mruby.h b/include/mruby.h index 87c902df0..4e0f9dddc 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1249,7 +1249,6 @@ MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name); MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value a, mrb_value b); MRB_API mrb_bool mrb_obj_equal(mrb_state *mrb, mrb_value a, mrb_value b); MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2); -MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base); #ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_to_float(mrb_state *mrb, mrb_value val); #endif @@ -1368,11 +1367,22 @@ MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj); /* mrb_gc_unregister() removes the object from GC root. */ MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); +/* type conversion/check functions */ +MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self); +MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); +MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); +MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); +MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str); +MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); +/* obsolete: use mrb_ensure_string_type() instead */ +#define mrb_string_type(mrb, str) mrb_ensure_string_type(mrb,str) +#define mrb_to_str(mrb, str) mrb_ensure_string_type(mrb,str) +/* obsolete: use mrb_obj_as_string() instead */ +#define mrb_str_to_str(mrb, str) mrb_obj_as_string(mrb, str) MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); #define mrb_as_int(mrb, val) mrb_integer(mrb_to_int(mrb, val)) /* string type checking (contrary to the name, it doesn't convert) */ -MRB_API mrb_value mrb_to_str(mrb_state *mrb, mrb_value val); MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); MRB_INLINE void mrb_check_frozen(mrb_state *mrb, void *o) diff --git a/include/mruby/array.h b/include/mruby/array.h index e8a003e47..8bb652472 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -204,8 +204,6 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val * @param other The array to replace it with. */ MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); -MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self); -MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); /* * Unshift an element into the array diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 749ea3869..1b37a12d4 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -37,8 +37,6 @@ struct RHash { size_t mrb_hash_memsize(mrb_value obj); MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); -MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); -MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); /* * Initializes a new hash. diff --git a/include/mruby/string.h b/include/mruby/string.h index 9c88a0856..b214aa7c8 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -324,20 +324,6 @@ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); */ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); -/** - * Returns a Ruby string type. - * - * - * @param mrb The current mruby state. - * @param str Ruby string. - * @return [mrb_value] A Ruby string. - */ -MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str); -MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); -/* obsolete: use mrb_ensure_string_type() instead */ -MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); - - MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa); #define mrb_str_buf_new(mrb, capa) mrb_str_new_capa(mrb, (capa)) @@ -373,13 +359,6 @@ MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, m MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); /** - * Returns a converted string type. - * For type checking, non converting `mrb_to_str` is recommended. - * obsolete: use `mrb_obj_as_string()` instead. - */ -#define mrb_str_to_str(mrb, str) mrb_obj_as_string(mrb, str) - -/** * Returns true if the strings match and false if the strings don't match. * * @param mrb The current mruby state. diff --git a/mrbgems/mruby-io/src/file.c b/mrbgems/mruby-io/src/file.c index 6c62db662..a19858a63 100644 --- a/mrbgems/mruby-io/src/file.c +++ b/mrbgems/mruby-io/src/file.c @@ -116,14 +116,14 @@ static mrb_value mrb_file_s_unlink(mrb_state *mrb, mrb_value obj) { const mrb_value *argv; - mrb_value pathv; mrb_int argc, i; char *path; mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { const char *utf8_path; - pathv = mrb_ensure_string_type(mrb, argv[i]); + mrb_value pathv = argv[i]; + mrb_ensure_string_type(mrb, pathv); utf8_path = RSTRING_CSTR(mrb, pathv); path = mrb_locale_from_utf8(utf8_path, -1); if (UNLINK(path) < 0) { diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 15b4c5f72..2d93e4fef 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -3,6 +3,8 @@ #include <mruby/array.h> #include <mruby/hash.h> #include <mruby/range.h> +#include <mruby/string.h> +#include <mruby/numeric.h> #include <mruby/presym.h> static mrb_value @@ -107,11 +109,43 @@ mrb_f_method(mrb_state *mrb, mrb_value self) static mrb_value mrb_f_integer(mrb_state *mrb, mrb_value self) { - mrb_value arg; + mrb_value val, tmp; mrb_int base = 0; - mrb_get_args(mrb, "o|i", &arg, &base); - return mrb_convert_to_integer(mrb, arg, base); + mrb_get_args(mrb, "o|i", &val, &base); + if (mrb_nil_p(val)) { + if (base != 0) goto arg_error; + mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); + } + switch (mrb_type(val)) { +#ifndef MRB_NO_FLOAT + case MRB_TT_FLOAT: + if (base != 0) goto arg_error; + return mrb_float_to_integer(mrb, val); +#endif + + case MRB_TT_INTEGER: + if (base != 0) goto arg_error; + return val; + + case MRB_TT_STRING: + string_conv: + return mrb_str_to_inum(mrb, val, base, TRUE); + + default: + break; + } + if (base != 0) { + tmp = mrb_obj_as_string(mrb, val); + if (mrb_string_p(tmp)) { + val = tmp; + goto string_conv; + } +arg_error: + mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); + } + /* to raise TypeError */ + return mrb_to_int(mrb, val); } #ifndef MRB_NO_FLOAT @@ -202,7 +236,8 @@ mrb_f_hash(mrb_state *mrb, mrb_value self) if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) { return mrb_hash_new(mrb); } - return mrb_ensure_hash_type(mrb, arg); + mrb_ensure_hash_type(mrb, arg); + return arg; } void diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index ba5ba4cda..93ddf2ad5 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -586,7 +586,7 @@ mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fm ++argc; --argv; - mrb_to_str(mrb, fmt); + mrb_ensure_string_type(mrb, fmt); p = RSTRING_PTR(fmt); end = p + RSTRING_LEN(fmt); blen = 0; diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 2b3071567..d485c51ef 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -111,36 +111,6 @@ class String (s == self) ? nil : self.replace(s) end - ## - # call-seq: - # str.casecmp(other_str) -> -1, 0, +1 or nil - # - # Case-insensitive version of <code>String#<=></code>. - # - # "abcdef".casecmp("abcde") #=> 1 - # "aBcDeF".casecmp("abcdef") #=> 0 - # "abcdef".casecmp("abcdefg") #=> -1 - # "abcdef".casecmp("ABCDEF") #=> 0 - # - def casecmp(str) - self.downcase <=> str.__to_str.downcase - rescue NoMethodError - nil - end - - ## - # call-seq: - # str.casecmp?(other) -> true, false, or nil - # - # Returns true if str and other_str are equal after case folding, - # false if they are not equal, and nil if other_str is not a string. - - def casecmp?(str) - c = self.casecmp(str) - return nil if c.nil? - return c == 0 - end - def partition(sep) raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String n = index(sep) diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index f5f46c082..8fafcc089 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -195,14 +195,14 @@ static mrb_value mrb_str_start_with(mrb_state *mrb, mrb_value self) { const mrb_value *argv; - mrb_value sub; mrb_int argc, i; mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { size_t len_l, len_r; int ai = mrb_gc_arena_save(mrb); - sub = mrb_ensure_string_type(mrb, argv[i]); + mrb_value sub = argv[i]; + mrb_ensure_string_type(mrb, sub); mrb_gc_arena_restore(mrb, ai); len_l = RSTRING_LEN(self); len_r = RSTRING_LEN(sub); @@ -225,14 +225,14 @@ static mrb_value mrb_str_end_with(mrb_state *mrb, mrb_value self) { const mrb_value *argv; - mrb_value sub; mrb_int argc, i; mrb_get_args(mrb, "*", &argv, &argc); for (i = 0; i < argc; i++) { size_t len_l, len_r; int ai = mrb_gc_arena_save(mrb); - sub = mrb_ensure_string_type(mrb, argv[i]); + mrb_value sub = argv[i]; + mrb_ensure_string_type(mrb, sub); mrb_gc_arena_restore(mrb, ai); len_l = RSTRING_LEN(self); len_r = RSTRING_LEN(sub); @@ -1174,6 +1174,60 @@ mrb_str_del_suffix(mrb_state *mrb, mrb_value self) return mrb_str_substr(mrb, self, 0, slen-plen); } +#define lesser(a,b) (((a)>(b))?(b):(a)) + +/* + * call-seq: + * str.casecmp(other_str) -> -1, 0, +1 or nil + * + * Case-insensitive version of <code>String#<=></code>. + * + * "abcdef".casecmp("abcde") #=> 1 + * "aBcDeF".casecmp("abcdef") #=> 0 + * "abcdef".casecmp("abcdefg") #=> -1 + * "abcdef".casecmp("ABCDEF") #=> 0 + */ +static mrb_value +mrb_str_casecmp(mrb_state *mrb, mrb_value self) +{ + mrb_value str; + + mrb_get_args(mrb, "o", &str); + if (!mrb_string_p(str)) return mrb_nil_value(); + + struct RString *s1 = mrb_str_ptr(self); + struct RString *s2 = mrb_str_ptr(str); + mrb_int len = lesser(RSTR_LEN(s1), RSTR_LEN(s2)); + char *p1 = RSTR_PTR(s1); + char *p2 = RSTR_PTR(s2); + + for (mrb_int i=0; i<len; i++) { + int c1 = p1[i], c2 = p2[i]; + if (ISASCII(c1) && ISUPPER(c1)) c1 = TOLOWER(c1); + if (ISASCII(c2) && ISUPPER(c2)) c2 = TOLOWER(c2); + if (c1 > c2) return mrb_fixnum_value(1); + if (c1 < c2) return mrb_fixnum_value(-1); + } + if (RSTR_LEN(s1) == RSTR_LEN(s2)) return mrb_fixnum_value(0); + if (RSTR_LEN(s1) > RSTR_LEN(s2)) return mrb_fixnum_value(1); + return mrb_fixnum_value(-1); +} + +/* + * call-seq: + * str.casecmp?(other) -> true, false, or nil + * + * Returns true if str and other_str are equal after case folding, + * false if they are not equal, and nil if other is not a string. + */ +static mrb_value +mrb_str_casecmp_p(mrb_state *mrb, mrb_value self) +{ + mrb_value c = mrb_str_casecmp(mrb, self); + if (mrb_nil_p(c)) return c; + return mrb_bool_value(mrb_fixnum(c) == 0); +} + static mrb_value mrb_str_lines(mrb_state *mrb, mrb_value self) { @@ -1231,6 +1285,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "delete_prefix", mrb_str_del_prefix, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "delete_suffix!", mrb_str_del_suffix_bang, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "delete_suffix", mrb_str_del_suffix, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "casecmp", mrb_str_casecmp, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "casecmp?", mrb_str_casecmp_p, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "__lines", mrb_str_lines, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index df76d7a33..e8f06b802 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -202,7 +202,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl } else { /* old style: should we warn? */ - mrb_to_str(mrb, name); + mrb_ensure_string_type(mrb, name); id = mrb_obj_to_sym(mrb, name); if (!mrb_const_name_p(mrb, RSTRING_PTR(name), RSTRING_LEN(name))) { mrb_name_error(mrb, id, "identifier %v needs to be constant", name); diff --git a/mrblib/string.rb b/mrblib/string.rb index 675026e73..2b3178688 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -42,32 +42,6 @@ class String self end - # private method for gsub/sub - def __sub_replace(pre, m, post) - s = "" - i = 0 - while j = index("\\", i) - break if j == length-1 - t = case self[j+1] - when "\\" - "\\" - when "`" - pre - when "&", "0" - m - when "'" - post - when "1", "2", "3", "4", "5", "6", "7", "8", "9" - "" - else - self[j, 2] - end - s += self[i, j-i] + t - i = j + 2 - end - s + self[i, length-i] - end - ## # Replace all matches of +pattern+ with +replacement+. # Call block (if given) for each match and replace @@ -84,9 +58,6 @@ class String if args.length == 2 && block block = nil end - if !replace.nil? || !block - replace.__to_str - end offset = 0 result = [] while found = index(pattern, offset) @@ -95,7 +66,7 @@ class String result << if block block.call(pattern).to_s else - replace.__sub_replace(self[0, found], pattern, self[offset..-1] || "") + self.__sub_replace(replace, pattern, found) end if plen == 0 result << self[offset, 1] @@ -144,25 +115,20 @@ class String end pattern, replace = *args - pattern.__to_str if args.length == 2 && block block = nil end - unless block - replace.__to_str - end result = [] - this = dup found = index(pattern) - return this unless found - result << this[0, found] + return self.dup unless found + result << self[0, found] offset = found + pattern.length result << if block block.call(pattern).to_s else - replace.__sub_replace(this[0, found], pattern, this[offset..-1] || "") + self.__sub_replace(replace, pattern, found) end - result << this[offset..-1] if offset < length + result << self[offset..-1] if offset < length result.join end diff --git a/src/class.c b/src/class.c index 855a7715c..b683deda0 100644 --- a/src/class.c +++ b/src/class.c @@ -2379,7 +2379,7 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod) } /* const get with class path string */ - path = mrb_ensure_string_type(mrb, path); + mrb_ensure_string_type(mrb, path); ptr = RSTRING_PTR(path); len = RSTRING_LEN(path); off = 0; diff --git a/src/error.c b/src/error.c index 0ef7bc9c1..206d1a0e8 100644 --- a/src/error.c +++ b/src/error.c @@ -27,7 +27,7 @@ mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len) MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str) { - mrb_to_str(mrb, str); + mrb_ensure_string_type(mrb, str); return mrb_obj_new(mrb, c, 1, &str); } diff --git a/src/kernel.c b/src/kernel.c index 812229ba7..14922b39a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -652,7 +652,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */ - mrb_define_method(mrb, krn, "__to_str", mrb_to_str, MRB_ARGS_NONE()); /* internal */ mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); } diff --git a/src/object.c b/src/object.c index 8fe4688ac..fd2cd3968 100644 --- a/src/object.c +++ b/src/object.c @@ -495,46 +495,6 @@ mrb_to_int(mrb_state *mrb, mrb_value val) return val; } -MRB_API mrb_value -mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) -{ - mrb_value tmp; - - if (mrb_nil_p(val)) { - if (base != 0) goto arg_error; - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); - } - switch (mrb_type(val)) { -#ifndef MRB_NO_FLOAT - case MRB_TT_FLOAT: - if (base != 0) goto arg_error; - return mrb_float_to_integer(mrb, val); -#endif - - case MRB_TT_INTEGER: - if (base != 0) goto arg_error; - return val; - - case MRB_TT_STRING: - string_conv: - return mrb_str_to_inum(mrb, val, base, TRUE); - - default: - break; - } - if (base != 0) { - tmp = mrb_check_string_type(mrb, val); - if (!mrb_nil_p(tmp)) { - val = tmp; - goto string_conv; - } -arg_error: - mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); - } - /* to raise TypeError */ - return mrb_to_int(mrb, val); -} - #ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_to_float(mrb_state *mrb, mrb_value val) @@ -559,19 +519,6 @@ mrb_to_float(mrb_state *mrb, mrb_value val) #endif MRB_API mrb_value -mrb_to_str(mrb_state *mrb, mrb_value val) -{ - return mrb_ensure_string_type(mrb, val); -} - -/* obsolete: use mrb_ensure_string_type() instead */ -MRB_API mrb_value -mrb_string_type(mrb_state *mrb, mrb_value str) -{ - return mrb_ensure_string_type(mrb, str); -} - -MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str) { if (!mrb_string_p(str)) { diff --git a/src/string.c b/src/string.c index 30d1bcab3..1a8b01c66 100644 --- a/src/string.c +++ b/src/string.c @@ -237,7 +237,7 @@ str_modify_keep_ascii(mrb_state *mrb, struct RString *s) static void check_null_byte(mrb_state *mrb, mrb_value str) { - mrb_to_str(mrb, str); + mrb_ensure_string_type(mrb, str); if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str))) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); } @@ -1071,7 +1071,7 @@ mrb_string_value_ptr(mrb_state *mrb, mrb_value str) MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value ptr) { - mrb_to_str(mrb, ptr); + mrb_ensure_string_type(mrb, ptr); return RSTRING_LEN(ptr); } @@ -1358,8 +1358,7 @@ mrb_str_aset(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, mrb_ { mrb_int beg, len, charlen; - mrb_to_str(mrb, replace); - + mrb_ensure_string_type(mrb, replace); switch (str_convert_range(mrb, str, indx, alen, &beg, &len)) { case STR_OUT_OF_RANGE: default: @@ -2400,7 +2399,7 @@ mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck) const char *s; mrb_int len; - mrb_to_str(mrb, str); + mrb_ensure_string_type(mrb, str); s = RSTRING_PTR(str); len = RSTRING_LEN(str); return mrb_str_len_to_inum(mrb, s, len, base, badcheck); @@ -2699,7 +2698,7 @@ mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2) MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2) { - mrb_to_str(mrb, str2); + mrb_ensure_string_type(mrb, str2); return mrb_str_cat_str(mrb, str1, str2); } @@ -2848,6 +2847,51 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str) } } +static mrb_value +sub_replace(mrb_state *mrb, mrb_value self) +{ + char *p, *match; + mrb_int plen, mlen; + mrb_int found, offset; + mrb_value result; + + mrb_get_args(mrb, "ssi", &p, &plen, &match, &mlen, &found); + result = mrb_str_new(mrb, 0, 0); + for (mrb_int i=0; i<plen; i++) { + if (p[i] != '\\' || i+1==plen) { + mrb_str_cat(mrb, result, p+i, 1); + continue; + } + i++; + switch (p[i]) { + case '\\': + mrb_str_cat(mrb, result, "\\", 1); + break; + case '`': + mrb_str_cat(mrb, result, RSTRING_PTR(self), chars2bytes(self, 0, found)); + break; + case '&': case '0': + mrb_str_cat(mrb, result, match, mlen); + break; + case '\'': + offset = chars2bytes(self, 0, found) + mlen; + if (RSTRING_LEN(self) > offset) { + mrb_str_cat(mrb, result, RSTRING_PTR(self)+offset, RSTRING_LEN(self)-offset); + } + break; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + /* ignore sub-group match (no Regexp supported) */ + break; + default: + mrb_str_cat(mrb, result, &p[i-1], 2); + break; + } + } + return result; +} + /* ---------------------------*/ void mrb_init_string(mrb_state *mrb) @@ -2909,4 +2953,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "setbyte", mrb_str_setbyte, MRB_ARGS_REQ(2)); mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1)); + + mrb_define_method(mrb, s, "__sub_replace", sub_replace, MRB_ARGS_REQ(3)); /* internal */ } @@ -2671,7 +2671,8 @@ RETRY_TRY_BLOCK: int i; int lim = a+b*2+1; - hash = mrb_ensure_hash_type(mrb, regs[a]); + hash = regs[a]; + mrb_ensure_hash_type(mrb, hash); for (i=a+1; i<lim; i+=2) { mrb_hash_set(mrb, hash, regs[i], regs[i+1]); } @@ -2679,8 +2680,9 @@ RETRY_TRY_BLOCK: NEXT; } CASE(OP_HASHCAT, B) { - mrb_value hash = mrb_ensure_hash_type(mrb, regs[a]); + mrb_value hash = regs[a]; + mrb_ensure_hash_type(mrb, hash); mrb_hash_merge(mrb, hash, regs[a+1]); mrb_gc_arena_restore(mrb, ai); NEXT; |
