[前][次][番号順一覧][スレッド一覧]

ruby-changes:68013

From: Nobuyoshi <ko1@a...>
Date: Thu, 16 Sep 2021 21:16:09 +0900 (JST)
Subject: [ruby-changes:68013] f2cb6288bc (master): [Feature #18172] Add MatchData#match_length

https://git.ruby-lang.org/ruby.git/commit/?id=f2cb6288bc

From f2cb6288bc6f1d5e693841734ce5eb04ff41c2a9 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Thu, 16 Sep 2021 19:50:29 +0900
Subject: [Feature #18172] Add MatchData#match_length

The method to return the length of the matched substring
corresponding to the given argument.
---
 re.c                     | 37 +++++++++++++++++++++++++++++++++++++
 test/ruby/test_regexp.rb | 17 +++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/re.c b/re.c
index 5d5f6fc..8e2df1f 100644
--- a/re.c
+++ b/re.c
@@ -1335,6 +1335,42 @@ match_nth(VALUE match, VALUE n) https://github.com/ruby/ruby/blob/trunk/re.c#L1335
     return rb_str_subseq(RMATCH(match)->str, start, end - start);
 }
 
+/*
+ *  call-seq:
+ *     mtch.match_length(n)   -> array
+ *
+ *  Returns the length of the captured substring corresponding to the argument.
+ *  <em>n</em> can be a string or symbol to reference a named capture.
+ *
+ *     m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ *     m.match_length(0)       #=> 6
+ *     m.match_length(4)       #=> 1
+ *     m.match_length(5)       #=> nil
+ *
+ *     m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge")
+ *     m.match_length(:foo)    #=> 1
+ *     m.match_length(:bar)    #=> 2
+ *
+ */
+
+static VALUE
+match_nth_length(VALUE match, VALUE n)
+{
+    int i = match_backref_number(match, n);
+    struct re_registers *regs = RMATCH_REGS(match);
+
+    match_check(match);
+    backref_number_check(regs, i);
+
+    if (BEG(i) < 0)
+	return Qnil;
+
+    update_char_offset(match);
+    const struct rmatch_offset *const ofs =
+	&RMATCH(match)->rmatch->char_offset[i];
+    return LONG2NUM(ofs->end - ofs->beg);
+}
+
 #define MATCH_BUSY FL_USER2
 
 void
@@ -4136,6 +4172,7 @@ Init_Regexp(void) https://github.com/ruby/ruby/blob/trunk/re.c#L4172
     rb_define_method(rb_cMatch, "begin", match_begin, 1);
     rb_define_method(rb_cMatch, "end", match_end, 1);
     rb_define_method(rb_cMatch, "match", match_nth, 1);
+    rb_define_method(rb_cMatch, "match_length", match_nth_length, 1);
     rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
     rb_define_method(rb_cMatch, "[]", match_aref, -1);
     rb_define_method(rb_cMatch, "captures", match_captures, 0);
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 66a60b8..b9e64a4 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -490,6 +490,23 @@ class TestRegexp < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb#L490
     assert_equal("oge\u3042", m.match(:bar))
   end
 
+  def test_match_matchsubstring
+    m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+    assert_equal(6, m.match_length(0))
+    assert_equal(1, m.match_length(4))
+    assert_nil(m.match_length(5))
+
+    m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+    assert_equal(1, m.match_length(1))
+    assert_nil(m.match_length(2))
+    assert_equal(1, m.match_length(3))
+
+    m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
+    assert_equal(1, m.match_length(:foo))
+    assert_nil(m.match_length(:n))
+    assert_equal(4, m.match_length(:bar))
+  end
+
   def test_match_inspect
     m = /(...)(...)(...)(...)?/.match("foobarbaz")
     assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect)
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]