diff --git a/spec/std/match_data_spec.cr b/spec/std/match_data_spec.cr index 6b9407052ee7..7da44dbae781 100644 --- a/spec/std/match_data_spec.cr +++ b/spec/std/match_data_spec.cr @@ -13,6 +13,12 @@ describe "Regex::MatchData" do /fox/.match("the fox").to_s.should eq(%(#)) end + it "does size" do + "Crystal".match(/[p-s]/).not_nil!.size.should eq(1) + "Crystal".match(/r(ys)/).not_nil!.size.should eq(2) + "Crystal".match(/r(ys)(?ta)/).not_nil!.size.should eq(3) + end + describe "#[]" do it "captures empty group" do ("foo" =~ /(?z?)foo/).should eq(0) diff --git a/spec/std/regex_spec.cr b/spec/std/regex_spec.cr index 34f66da91e6d..948b73dbb8fa 100644 --- a/spec/std/regex_spec.cr +++ b/spec/std/regex_spec.cr @@ -8,7 +8,7 @@ describe "Regex" do it "does =~" do (/foo/ =~ "bar foo baz").should eq(4) - $~.size.should eq(0) + $~.group_size.should eq(0) end it "does inspect" do @@ -64,7 +64,7 @@ describe "Regex" do it "matches with =~ and captures" do ("fooba" =~ /f(o+)(bar?)/).should eq(0) - $~.size.should eq(2) + $~.group_size.should eq(2) $1.should eq("oo") $2.should eq("ba") end @@ -77,7 +77,7 @@ describe "Regex" do it "matches with === and captures" do "foo" =~ /foo/ (/f(o+)(bar?)/ === "fooba").should be_true - $~.size.should eq(2) + $~.group_size.should eq(2) $1.should eq("oo") $2.should eq("ba") end diff --git a/spec/std/string_spec.cr b/spec/std/string_spec.cr index cf1c82a6ca08..597da99741b8 100644 --- a/spec/std/string_spec.cr +++ b/spec/std/string_spec.cr @@ -1779,7 +1779,7 @@ describe "String" do it "matches empty string" do match = "".match(/.*/).not_nil! - match.size.should eq(0) + match.group_size.should eq(0) match[0].should eq("") end diff --git a/src/regex/match_data.cr b/src/regex/match_data.cr index d255641f603d..9023dbcbc838 100644 --- a/src/regex/match_data.cr +++ b/src/regex/match_data.cr @@ -26,11 +26,11 @@ class Regex # Returns the number of capture groups, including named capture groups. # # ``` - # "Crystal".match(/[p-s]/).not_nil!.size # => 0 - # "Crystal".match(/r(ys)/).not_nil!.size # => 1 - # "Crystal".match(/r(ys)(?ta)/).not_nil!.size # => 2 + # "Crystal".match(/[p-s]/).not_nil!.group_size # => 0 + # "Crystal".match(/r(ys)/).not_nil!.group_size # => 1 + # "Crystal".match(/r(ys)(?ta)/).not_nil!.group_size # => 2 # ``` - getter size : Int32 + getter group_size : Int32 # Returns the original string. # @@ -40,7 +40,18 @@ class Regex getter string : String # :nodoc: - def initialize(@regex : Regex, @code : LibPCRE::Pcre, @string : String, @pos : Int32, @ovector : Int32*, @size : Int32) + def initialize(@regex : Regex, @code : LibPCRE::Pcre, @string : String, @pos : Int32, @ovector : Int32*, @group_size : Int32) + end + + # Returns the number of elements in this match object. + # + # ``` + # "Crystal".match(/[p-s]/).not_nil!.size # => 1 + # "Crystal".match(/r(ys)/).not_nil!.size # => 2 + # "Crystal".match(/r(ys)(?ta)/).not_nil!.size # => 3 + # ``` + def size + group_size + 1 end # Return the position of the first character of the *n*th match. @@ -204,7 +215,7 @@ class Regex name_table = @regex.name_table caps = [] of String? - (1..size).each do |i| + (1...size).each do |i| caps << self[i]? unless name_table.has_key? i end @@ -226,7 +237,7 @@ class Regex name_table = @regex.name_table caps = {} of String => String? - (1..size).each do |i| + (1...size).each do |i| if name = name_table[i]? caps[name] = self[i]? end @@ -247,7 +258,7 @@ class Regex # match.to_a # => ["Cr", "Cr", nil] # ``` def to_a - (0..size).map { |i| self[i]? } + (0...size).map { |i| self[i]? } end # Convert this match data into a hash. @@ -265,7 +276,7 @@ class Regex name_table = @regex.name_table hash = {} of (String | Int32) => String? - (0..size).each do |i| + (0...size).each do |i| hash[name_table.fetch(i) { i }] = self[i]? end @@ -281,13 +292,12 @@ class Regex io << "# 0 + if size > 1 io << " " - size.times do |i| - io << " " if i > 0 - io << name_table.fetch(i + 1) { i + 1 } + (1...size).join " ", io do |i| + io << name_table.fetch(i) { i } io << ":" - self[i + 1]?.inspect(io) + self[i]?.inspect(io) end end io << ">" @@ -306,7 +316,7 @@ class Regex return false unless regex == other.regex return false unless string == other.string - return @ovector.memcmp(other.@ovector, (size + 1) * 2) == 0 + return @ovector.memcmp(other.@ovector, size * 2) == 0 end private def check_index_out_of_bounds(index) @@ -314,7 +324,7 @@ class Regex end private def valid_group?(index) - index <= @size + index < size end private def raise_invalid_group_index(index)