summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-04-05 04:41:17 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-04-05 04:41:17 +0900
commit492688eecd2e0adbe3cd9338a80eec1d9b6a0b6a (patch)
treec522bc61a378c83e58809058469002eeefd29db9
parent001ce2612b96d489799962c725586be0f3c8b53f (diff)
downloadmruby-492688eecd2e0adbe3cd9338a80eec1d9b6a0b6a.tar.gz
mruby-492688eecd2e0adbe3cd9338a80eec1d9b6a0b6a.zip
factor out redundant Regexp check into functions
-rw-r--r--src/string.c251
1 files changed, 24 insertions, 227 deletions
diff --git a/src/string.c b/src/string.c
index c4074a64f..329a3da9d 100644
--- a/src/string.c
+++ b/src/string.c
@@ -622,29 +622,22 @@ mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr)
mrb_value str = mrb_str_to_str(mrb, ptr);
return RSTRING_PTR(str);
}
-/* 15.2.10.5.5 */
-
-/*
- * call-seq:
- * str =~ obj -> fixnum or nil
- *
- * Match---If <i>obj</i> is a <code>Regexp</code>, use it as a pattern to match
- * against <i>str</i>,and returns the position the match starts, or
- * <code>nil</code> if there is no match. Otherwise, invokes
- * <i>obj.=~</i>, passing <i>str</i> as an argument. The default
- * <code>=~</code> in <code>Object</code> returns <code>nil</code>.
- *
- * "cat o' 9 tails" =~ /\d/ #=> 7
- * "cat o' 9 tails" =~ 9 #=> nil
- */
static mrb_value
-mrb_str_match(mrb_state *mrb, mrb_value self/* x */)
+noregexp(mrb_state *mrb, mrb_value self)
{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
+ mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented");
return mrb_nil_value();
}
+static void
+regexp_check(mrb_state *mrb, mrb_value obj)
+{
+ if (!strcmp(mrb_obj_classname(mrb, obj), REGEXP_CLASS)) {
+ noregexp(mrb, obj);
+ }
+}
+
static inline mrb_int
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
@@ -730,9 +723,7 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
{
mrb_int idx;
- if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- }
+ regexp_check(mrb, indx);
switch (mrb_type(indx)) {
case MRB_TT_FIXNUM:
idx = mrb_fixnum(indx);
@@ -825,9 +816,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
argc = mrb_get_args(mrb, "o|o", &a1, &a2);
if (argc == 2) {
- if (!strcmp(mrb_obj_classname(mrb, a1), REGEXP_CLASS)) {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- }
+ regexp_check(mrb, a1);
return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
}
if (argc != 1) {
@@ -1193,62 +1182,6 @@ mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2)
return str;
}
-/* 15.2.10.5.18 */
-/*
- * call-seq:
- * str.gsub(pattern, replacement) => new_str
- * str.gsub(pattern) {|match| block } => new_str
- *
- * Returns a copy of <i>str</i> with <em>all</em> occurrences of <i>pattern</i>
- * replaced with either <i>replacement</i> or the value of the block. The
- * <i>pattern</i> will typically be a <code>Regexp</code>; if it is a
- * <code>String</code> then no regular expression metacharacters will be
- * interpreted (that is <code>/\d/</code> will match a digit, but
- * <code>'\d'</code> will match a backslash followed by a 'd').
- *
- * If a string is used as the replacement, special variables from the match
- * (such as <code>$&</code> and <code>$1</code>) cannot be substituted into it,
- * as substitution into the string occurs before the pattern match
- * starts. However, the sequences <code>\1</code>, <code>\2</code>, and so on
- * may be used to interpolate successive groups in the match.
- *
- * In the block form, the current match string is passed in as a parameter, and
- * variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- * returned by the block will be substituted for the match on each call.
- *
- * When neither a block nor a second argument is supplied, an
- * <code>Enumerator</code> is returned.
- *
- * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
- * "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>"
- * "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 "
- * "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}"
- * 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
- */
-static mrb_value
-mrb_str_gsub(mrb_state *mrb, mrb_value self)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
-/* 15.2.10.5.19 */
-/*
- * call-seq:
- * str.gsub!(pattern, replacement) => str or nil
- * str.gsub!(pattern) {|match| block } => str or nil
- *
- * Performs the substitutions of <code>String#gsub</code> in place, returning
- * <i>str</i>, or <code>nil</code> if no substitutions were performed.
- */
-static mrb_value
-mrb_str_gsub_bang(mrb_state *mrb, mrb_value self)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
mrb_int
mrb_str_hash(mrb_state *mrb, mrb_value str)
{
@@ -1357,9 +1290,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
sub = mrb_nil_value();
}
- if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- }
+ regexp_check(mrb, sub);
if (pos < 0) {
pos += RSTRING_LEN(str);
if (pos < 0) {
@@ -1555,26 +1486,6 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str)
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
}
-/* 15.2.10.5.27 */
-/*
- * call-seq:
- * str.match(pattern) => matchdata or nil
- *
- * Converts <i>pattern</i> to a <code>Regexp</code> (if it isn't already one),
- * then invokes its <code>match</code> method on <i>str</i>.
- *
- * 'hello'.match('(.)\1') #=> #<MatchData:0x401b3d30>
- * 'hello'.match('(.)\1')[0] #=> "ll"
- * 'hello'.match(/(.)\1/)[0] #=> "ll"
- * 'hello'.match('xx') #=> nil
- */
-static mrb_value
-mrb_str_match_m(mrb_state *mrb, mrb_value self)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
/* ---------------------------------- */
/* 15.2.10.5.29 */
/*
@@ -1715,9 +1626,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
if (pos < 0) {
pos += len;
if (pos < 0) {
- if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- }
+ regexp_check(mrb, sub);
return mrb_nil_value();
}
}
@@ -1730,9 +1639,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
else
sub = mrb_nil_value();
}
- if (!strcmp(mrb_obj_classname(mrb, sub), REGEXP_CLASS)) {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- }
+ regexp_check(mrb, sub);
switch (mrb_type(sub)) {
case MRB_TT_FIXNUM: {
@@ -1765,44 +1672,6 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
return mrb_nil_value();
}
-/* 15.2.10.5.32 */
-/*
- * call-seq:
- * str.scan(pattern) => array
- * str.scan(pattern) {|match, ...| block } => str
- *
- * Both forms iterate through <i>str</i>, matching the pattern (which may be a
- * <code>Regexp</code> or a <code>String</code>). For each match, a result is
- * generated and either added to the result array or passed to the block. If
- * the pattern contains no groups, each individual result consists of the
- * matched string, <code>$&</code>. If the pattern contains groups, each
- * individual result is itself an array containing one entry per group.
- *
- * a = "cruel world"
- * a.scan(/\w+/) #=> ["cruel", "world"]
- * a.scan(/.../) #=> ["cru", "el ", "wor"]
- * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
- * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
- *
- * And the block form:
- *
- * a.scan(/\w+/) {|w| print "<<#{w}>> " }
- * print "\n"
- * a.scan(/(.)(.)/) {|x,y| print y, x }
- * print "\n"
- *
- * <em>produces:</em>
- *
- * <<cruel>> <<world>>
- * rceu lowlr
- */
-static mrb_value
-mrb_str_scan(mrb_state *mrb, mrb_value str)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
static const char isspacetable[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1901,7 +1770,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
}
else {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
+ noregexp(mrb, str);
}
}
@@ -1970,7 +1839,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
beg = ptr - temp;
}
else {
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
+ noregexp(mrb, str);
}
if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
if (RSTRING_LEN(str) == beg) {
@@ -1991,70 +1860,6 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
return result;
}
-
-/* 15.2.10.5.37 */
-/*
- * call-seq:
- * str.sub!(pattern, replacement) => str or nil
- * str.sub!(pattern) {|match| block } => str or nil
- *
- * Performs the substitutions of <code>String#sub</code> in place,
- * returning <i>str</i>, or <code>nil</code> if no substitutions were
- * performed.
- */
-static mrb_value
-mrb_str_sub_bang(mrb_state *mrb, mrb_value str)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
-/* 15.2.10.5.36 */
-
-/*
- * call-seq:
- * str.sub(pattern, replacement) -> new_str
- * str.sub(pattern, hash) -> new_str
- * str.sub(pattern) {|match| block } -> new_str
- *
- * Returns a copy of <i>str</i> with the <em>first</em> occurrence of
- * <i>pattern</i> substituted for the second argument. The <i>pattern</i> is
- * typically a <code>Regexp</code>; if given as a <code>String</code>, any
- * regular expression metacharacters it contains will be interpreted
- * literally, e.g. <code>'\\\d'</code> will match a backlash followed by 'd',
- * instead of a digit.
- *
- * If <i>replacement</i> is a <code>String</code> it will be substituted for
- * the matched text. It may contain back-references to the pattern's capture
- * groups of the form <code>\\\d</code>, where <i>d</i> is a group number, or
- * <code>\\\k<n></code>, where <i>n</i> is a group name. If it is a
- * double-quoted string, both back-references must be preceded by an
- * additional backslash. However, within <i>replacement</i> the special match
- * variables, such as <code>&$</code>, will not refer to the current match.
- *
- * If the second argument is a <code>Hash</code>, and the matched text is one
- * of its keys, the corresponding value is the replacement string.
- *
- * In the block form, the current match string is passed in as a parameter,
- * and variables such as <code>$1</code>, <code>$2</code>, <code>$`</code>,
- * <code>$&</code>, and <code>$'</code> will be set appropriately. The value
- * returned by the block will be substituted for the match on each call.
- *
- * "hello".sub(/[aeiou]/, '*') #=> "h*llo"
- * "hello".sub(/([aeiou])/, '<\1>') #=> "h<e>llo"
- * "hello".sub(/./) {|s| s.ord.to_s + ' ' } #=> "104 ello"
- * "hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*') #=> "h*e*llo"
- * 'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
- * #=> "Is /bin/bash your preferred shell?"
- */
-
-static mrb_value
-mrb_str_sub(mrb_state *mrb, mrb_value self)
-{
- mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented");
- return mrb_nil_value();
-}
-
mrb_value
mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
{
@@ -2682,7 +2487,7 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "*", mrb_str_times, ARGS_REQ(1)); /* 15.2.10.5.1 */
mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, ARGS_REQ(1)); /* 15.2.10.5.3 */
mrb_define_method(mrb, s, "==", mrb_str_equal_m, ARGS_REQ(1)); /* 15.2.10.5.4 */
- mrb_define_method(mrb, s, "=~", mrb_str_match, ARGS_REQ(1)); /* 15.2.10.5.5 */
+ mrb_define_method(mrb, s, "=~", noregexp, ARGS_REQ(1)); /* 15.2.10.5.5 */
mrb_define_method(mrb, s, "[]", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.6 */
mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, ARGS_NONE()); /* 15.2.10.5.7 */
mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, ARGS_REQ(1)); /* 15.2.10.5.8 */
@@ -2696,8 +2501,8 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "eql?", mrb_str_eql, ARGS_REQ(1)); /* 15.2.10.5.17 */
// NOTE: Regexp not implemented
- mrb_define_method(mrb, s, "gsub", mrb_str_gsub, ARGS_REQ(1)); /* 15.2.10.5.18 */
- mrb_define_method(mrb, s, "gsub!", mrb_str_gsub_bang, ARGS_REQ(1)); /* 15.2.10.5.19 */
+ mrb_define_method(mrb, s, "gsub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.18 */
+ mrb_define_method(mrb, s, "gsub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.19 */
mrb_define_method(mrb, s, "hash", mrb_str_hash_m, ARGS_REQ(1)); /* 15.2.10.5.20 */
mrb_define_method(mrb, s, "include?", mrb_str_include, ARGS_REQ(1)); /* 15.2.10.5.21 */
@@ -2705,24 +2510,16 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "initialize", mrb_str_init, ARGS_REQ(1)); /* 15.2.10.5.23 */
mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.24 */
mrb_define_method(mrb, s, "intern", mrb_str_intern, ARGS_NONE()); /* 15.2.10.5.25 */
-
- // NOTE: Regexp not implemented
- mrb_define_method(mrb, s, "match", mrb_str_match_m, ARGS_REQ(1)); /* 15.2.10.5.27 */
-
+ mrb_define_method(mrb, s, "match", noregexp, ARGS_REQ(1)); /* 15.2.10.5.27 */
mrb_define_method(mrb, s, "replace", mrb_str_replace, ARGS_REQ(1)); /* 15.2.10.5.28 */
mrb_define_method(mrb, s, "reverse", mrb_str_reverse, ARGS_NONE()); /* 15.2.10.5.29 */
mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, ARGS_NONE()); /* 15.2.10.5.30 */
mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, ARGS_ANY()); /* 15.2.10.5.31 */
-
- // NOTE: Regexp not implemented
- mrb_define_method(mrb, s, "scan", mrb_str_scan, ARGS_REQ(1)); /* 15.2.10.5.32 */
-
+ mrb_define_method(mrb, s, "scan", noregexp, ARGS_REQ(1)); /* 15.2.10.5.32 */
mrb_define_method(mrb, s, "slice", mrb_str_aref_m, ARGS_ANY()); /* 15.2.10.5.34 */
mrb_define_method(mrb, s, "split", mrb_str_split_m, ARGS_ANY()); /* 15.2.10.5.35 */
-
- // NOTE: Regexp not implemented
- mrb_define_method(mrb, s, "sub", mrb_str_sub, ARGS_REQ(1)); /* 15.2.10.5.36 */
- mrb_define_method(mrb, s, "sub!", mrb_str_sub_bang, ARGS_REQ(1)); /* 15.2.10.5.37 */
+ mrb_define_method(mrb, s, "sub", noregexp, ARGS_REQ(1)); /* 15.2.10.5.36 */
+ mrb_define_method(mrb, s, "sub!", noregexp, ARGS_REQ(1)); /* 15.2.10.5.37 */
mrb_define_method(mrb, s, "to_i", mrb_str_to_i, ARGS_ANY()); /* 15.2.10.5.38 */
mrb_define_method(mrb, s, "to_f", mrb_str_to_f, ARGS_NONE()); /* 15.2.10.5.39 */