factor out redundant Regexp check into functions

This commit is contained in:
Yukihiro "Matz" Matsumoto
2013-04-05 04:41:17 +09:00
parent 001ce2612b
commit 492688eecd
+24 -227
View File
@@ -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 */