[Feature #13712] String#start_with? supports regexp
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60234 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ae2578f6bc
commit
6187b0001b
1
NEWS
1
NEWS
@ -108,6 +108,7 @@ with all sufficient information, see the ChangeLog file or Redmine
|
|||||||
* String#delete_suffix! is added to remove suffix destructively [Feature #13665]
|
* String#delete_suffix! is added to remove suffix destructively [Feature #13665]
|
||||||
* String#each_grapheme_cluster and String#grapheme_clusters is added to
|
* String#each_grapheme_cluster and String#grapheme_clusters is added to
|
||||||
enumerate grapheme clusters [Feature #13780]
|
enumerate grapheme clusters [Feature #13780]
|
||||||
|
* String#start_with? supports regexp [Feature #13712]
|
||||||
|
|
||||||
* Regexp/String: Updated Unicode version from 9.0.0 to 10.0.0 [Feature #13685]
|
* Regexp/String: Updated Unicode version from 9.0.0 to 10.0.0 [Feature #13685]
|
||||||
|
|
||||||
|
@ -1570,6 +1570,7 @@ VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourcel
|
|||||||
VALUE rb_reg_check_preprocess(VALUE);
|
VALUE rb_reg_check_preprocess(VALUE);
|
||||||
long rb_reg_search0(VALUE, VALUE, long, int, int);
|
long rb_reg_search0(VALUE, VALUE, long, int, int);
|
||||||
VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
|
VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
|
||||||
|
bool rb_reg_start_with_p(VALUE re, VALUE str);
|
||||||
void rb_backref_set_string(VALUE string, long pos, long len);
|
void rb_backref_set_string(VALUE string, long pos, long len);
|
||||||
int rb_match_count(VALUE match);
|
int rb_match_count(VALUE match);
|
||||||
int rb_match_nth_defined(int nth, VALUE match);
|
int rb_match_nth_defined(int nth, VALUE match);
|
||||||
|
77
re.c
77
re.c
@ -1580,6 +1580,83 @@ rb_reg_search(VALUE re, VALUE str, long pos, int reverse)
|
|||||||
return rb_reg_search0(re, str, pos, reverse, 1);
|
return rb_reg_search0(re, str, pos, reverse, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
rb_reg_start_with_p(VALUE re, VALUE str)
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
VALUE match;
|
||||||
|
struct re_registers regi, *regs = ®i;
|
||||||
|
regex_t *reg;
|
||||||
|
int tmpreg;
|
||||||
|
onig_errmsg_buffer err = "";
|
||||||
|
|
||||||
|
reg = rb_reg_prepare_re0(re, str, err);
|
||||||
|
tmpreg = reg != RREGEXP_PTR(re);
|
||||||
|
if (!tmpreg) RREGEXP(re)->usecnt++;
|
||||||
|
|
||||||
|
match = rb_backref_get();
|
||||||
|
if (!NIL_P(match)) {
|
||||||
|
if (FL_TEST(match, MATCH_BUSY)) {
|
||||||
|
match = Qnil;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
regs = RMATCH_REGS(match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NIL_P(match)) {
|
||||||
|
MEMZERO(regs, struct re_registers, 1);
|
||||||
|
}
|
||||||
|
result = onig_match(reg,
|
||||||
|
(UChar*)(RSTRING_PTR(str)),
|
||||||
|
((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
|
||||||
|
(UChar*)(RSTRING_PTR(str)),
|
||||||
|
regs, ONIG_OPTION_NONE);
|
||||||
|
if (!tmpreg) RREGEXP(re)->usecnt--;
|
||||||
|
if (tmpreg) {
|
||||||
|
if (RREGEXP(re)->usecnt) {
|
||||||
|
onig_free(reg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
onig_free(RREGEXP_PTR(re));
|
||||||
|
RREGEXP_PTR(re) = reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result < 0) {
|
||||||
|
if (regs == ®i)
|
||||||
|
onig_region_free(regs, 0);
|
||||||
|
if (result == ONIG_MISMATCH) {
|
||||||
|
rb_backref_set(Qnil);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
onig_error_code_to_str((UChar*)err, (int)result);
|
||||||
|
rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NIL_P(match)) {
|
||||||
|
int err;
|
||||||
|
match = match_alloc(rb_cMatch);
|
||||||
|
err = rb_reg_region_copy(RMATCH_REGS(match), regs);
|
||||||
|
onig_region_free(regs, 0);
|
||||||
|
if (err) rb_memerror();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FL_UNSET(match, FL_TAINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
RMATCH(match)->str = rb_str_new4(str);
|
||||||
|
OBJ_INFECT(match, str);
|
||||||
|
|
||||||
|
RMATCH(match)->regexp = re;
|
||||||
|
RMATCH(match)->rmatch->char_offset_updated = 0;
|
||||||
|
rb_backref_set(match);
|
||||||
|
|
||||||
|
OBJ_INFECT(match, re);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_reg_nth_defined(int nth, VALUE match)
|
rb_reg_nth_defined(int nth, VALUE match)
|
||||||
{
|
{
|
||||||
|
19
string.c
19
string.c
@ -9219,11 +9219,20 @@ rb_str_start_with(int argc, VALUE *argv, VALUE str)
|
|||||||
|
|
||||||
for (i=0; i<argc; i++) {
|
for (i=0; i<argc; i++) {
|
||||||
VALUE tmp = argv[i];
|
VALUE tmp = argv[i];
|
||||||
StringValue(tmp);
|
switch (TYPE(tmp)) {
|
||||||
rb_enc_check(str, tmp);
|
case T_REGEXP:
|
||||||
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
|
{
|
||||||
if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
|
bool r = rb_reg_start_with_p(tmp, str);
|
||||||
return Qtrue;
|
if (r) return Qtrue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
StringValue(tmp);
|
||||||
|
rb_enc_check(str, tmp);
|
||||||
|
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
|
||||||
|
if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
@ -1723,6 +1723,11 @@ CODE
|
|||||||
|
|
||||||
bug5536 = '[ruby-core:40623]'
|
bug5536 = '[ruby-core:40623]'
|
||||||
assert_raise(TypeError, bug5536) {S("str").start_with? :not_convertible_to_string}
|
assert_raise(TypeError, bug5536) {S("str").start_with? :not_convertible_to_string}
|
||||||
|
|
||||||
|
assert_equal(true, "hello".start_with?(/hel/))
|
||||||
|
assert_equal("hel", $&)
|
||||||
|
assert_equal(false, "hello".start_with?(/el/))
|
||||||
|
assert_nil($&)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_strip
|
def test_strip
|
||||||
|
Loading…
x
Reference in New Issue
Block a user