re2 2.0.0.beta1-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +28 -0
- data/README.md +239 -0
- data/Rakefile +155 -0
- data/dependencies.yml +9 -0
- data/ext/re2/extconf.rb +384 -0
- data/ext/re2/re2.cc +1889 -0
- data/ext/re2/recipes.rb +43 -0
- data/lib/2.7/re2.so +0 -0
- data/lib/3.0/re2.so +0 -0
- data/lib/re2/scanner.rb +15 -0
- data/lib/re2/string.rb +85 -0
- data/lib/re2/version.rb +5 -0
- data/lib/re2.rb +14 -0
- data/re2.gemspec +43 -0
- data/spec/kernel_spec.rb +13 -0
- data/spec/re2/match_data_spec.rb +302 -0
- data/spec/re2/regexp_spec.rb +456 -0
- data/spec/re2/scanner_spec.rb +204 -0
- data/spec/re2/set_spec.rb +168 -0
- data/spec/re2/string_spec.rb +56 -0
- data/spec/re2_spec.rb +75 -0
- data/spec/spec_helper.rb +19 -0
- metadata +119 -0
data/ext/re2/recipes.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
PACKAGE_ROOT_DIR = File.expand_path('../..', __dir__)
|
2
|
+
REQUIRED_MINI_PORTILE_VERSION = '~> 2.8.4' # keep this version in sync with the one in the gemspec
|
3
|
+
|
4
|
+
def build_recipe(name, version)
|
5
|
+
require 'rubygems'
|
6
|
+
gem('mini_portile2', REQUIRED_MINI_PORTILE_VERSION) # gemspec is not respected at install time
|
7
|
+
require 'mini_portile2'
|
8
|
+
|
9
|
+
MiniPortileCMake.new(name, version).tap do |recipe|
|
10
|
+
recipe.target = File.join(PACKAGE_ROOT_DIR, 'ports')
|
11
|
+
recipe.configure_options += [
|
12
|
+
# abseil needs a C++14 compiler
|
13
|
+
'-DCMAKE_CXX_STANDARD=17',
|
14
|
+
# needed for building the C extension shared library with -fPIC
|
15
|
+
'-DCMAKE_POSITION_INDEPENDENT_CODE=ON',
|
16
|
+
# ensures pkg-config and installed libraries will be in lib, not lib64
|
17
|
+
'-DCMAKE_INSTALL_LIBDIR=lib'
|
18
|
+
]
|
19
|
+
|
20
|
+
yield recipe
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_recipes
|
25
|
+
require 'yaml'
|
26
|
+
dependencies = YAML.load_file(File.join(PACKAGE_ROOT_DIR, 'dependencies.yml'))
|
27
|
+
|
28
|
+
abseil_recipe = build_recipe('abseil', dependencies['abseil']['version']) do |recipe|
|
29
|
+
recipe.files = [{
|
30
|
+
url: "https://github.com/abseil/abseil-cpp/archive/refs/tags/#{recipe.version}.tar.gz",
|
31
|
+
sha256: dependencies['abseil']['sha256']
|
32
|
+
}]
|
33
|
+
end
|
34
|
+
|
35
|
+
re2_recipe = build_recipe('libre2', dependencies['libre2']['version']) do |recipe|
|
36
|
+
recipe.files = [{
|
37
|
+
url: "https://github.com/google/re2/releases/download/#{recipe.version}/re2-#{recipe.version}.tar.gz",
|
38
|
+
sha256: dependencies['libre2']['sha256']
|
39
|
+
}]
|
40
|
+
end
|
41
|
+
|
42
|
+
[abseil_recipe, re2_recipe]
|
43
|
+
end
|
data/lib/2.7/re2.so
ADDED
Binary file
|
data/lib/3.0/re2.so
ADDED
Binary file
|
data/lib/re2/scanner.rb
ADDED
data/lib/re2/string.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# re2 (http://github.com/mudge/re2)
|
2
|
+
# Ruby bindings to re2, an "efficient, principled regular expression library"
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010-2014, Paul Mucur (http://mudge.name)
|
5
|
+
# Released under the BSD Licence, please see LICENSE.txt
|
6
|
+
|
7
|
+
require "re2"
|
8
|
+
|
9
|
+
module RE2
|
10
|
+
module String
|
11
|
+
|
12
|
+
# Replaces the first occurrence +pattern+ with +rewrite+ and returns a new
|
13
|
+
# string.
|
14
|
+
#
|
15
|
+
# @see RE2.Replace
|
16
|
+
def re2_sub(*args)
|
17
|
+
RE2.Replace(self, *args)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Replaces every occurrence of +pattern+ with +rewrite+ and return a new string.
|
21
|
+
#
|
22
|
+
# @see RE2.GlobalReplace
|
23
|
+
def re2_gsub(*args)
|
24
|
+
RE2.GlobalReplace(self, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Match the pattern and return either a boolean (if no submatches are required)
|
28
|
+
# or a {RE2::MatchData} instance.
|
29
|
+
#
|
30
|
+
# @return [Boolean, RE2::MatchData]
|
31
|
+
#
|
32
|
+
# @overload match(pattern)
|
33
|
+
# Returns an {RE2::MatchData} containing the matching
|
34
|
+
# pattern and all subpatterns resulting from looking for
|
35
|
+
# +pattern+.
|
36
|
+
#
|
37
|
+
# @param [String, RE2::Regexp] pattern the regular expression to match
|
38
|
+
# @return [RE2::MatchData] the matches
|
39
|
+
# @raise [NoMemoryError] if there was not enough memory to allocate the matches
|
40
|
+
# @example
|
41
|
+
# r = RE2::Regexp.new('w(o)(o)')
|
42
|
+
# "woo".re2_match(r) #=> #<RE2::MatchData "woo" 1:"o" 2:"o">
|
43
|
+
#
|
44
|
+
# @overload match(pattern, 0)
|
45
|
+
# Returns either true or false indicating whether a
|
46
|
+
# successful match was made.
|
47
|
+
#
|
48
|
+
# @param [String, RE2::Regexp] pattern the regular expression to match
|
49
|
+
# @return [Boolean] whether the match was successful
|
50
|
+
# @raise [NoMemoryError] if there was not enough memory to allocate the matches
|
51
|
+
# @example
|
52
|
+
# r = RE2::Regexp.new('w(o)(o)')
|
53
|
+
# "woo".re2_match(0) #=> true
|
54
|
+
# "bob".re2_match(0) #=> false
|
55
|
+
#
|
56
|
+
# @overload match(pattern, number_of_matches)
|
57
|
+
# See +match(pattern)+ but with a specific number of
|
58
|
+
# matches returned (padded with nils if necessary).
|
59
|
+
#
|
60
|
+
# @param [String, RE2::Regexp] pattern the regular expression to match
|
61
|
+
# @param [Integer] number_of_matches the number of matches to return
|
62
|
+
# @return [RE2::MatchData] the matches
|
63
|
+
# @raise [NoMemoryError] if there was not enough memory to allocate the matches
|
64
|
+
# @example
|
65
|
+
# r = RE2::Regexp.new('w(o)(o)')
|
66
|
+
# "woo".re2_match(r, 1) #=> #<RE2::MatchData "woo" 1:"o">
|
67
|
+
# "woo".re2_match(r, 3) #=> #<RE2::MatchData "woo" 1:"o" 2:"o" 3:nil>
|
68
|
+
def re2_match(pattern, *args)
|
69
|
+
RE2::Regexp.new(pattern).match(self, *args)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Escapes all potentially meaningful regexp characters.
|
73
|
+
# The returned string, used as a regular expression, will exactly match the
|
74
|
+
# original string.
|
75
|
+
#
|
76
|
+
# @return [String] the escaped string
|
77
|
+
# @example
|
78
|
+
# "1.5-2.0?".escape #=> "1\.5\-2\.0\?"
|
79
|
+
def re2_escape
|
80
|
+
RE2.QuoteMeta(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
alias_method :re2_quote, :re2_escape
|
84
|
+
end
|
85
|
+
end
|
data/lib/re2/version.rb
ADDED
data/lib/re2.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# re2 (http://github.com/mudge/re2)
|
2
|
+
# Ruby bindings to re2, an "efficient, principled regular expression library"
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010-2014, Paul Mucur (http://mudge.name)
|
5
|
+
# Released under the BSD Licence, please see LICENSE.txt
|
6
|
+
begin
|
7
|
+
::RUBY_VERSION =~ /(\d+\.\d+)/
|
8
|
+
require_relative "#{Regexp.last_match(1)}/re2.so"
|
9
|
+
rescue LoadError
|
10
|
+
require 're2.so'
|
11
|
+
end
|
12
|
+
|
13
|
+
require "re2/scanner"
|
14
|
+
require "re2/version"
|
data/re2.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'lib/re2/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "re2"
|
5
|
+
s.summary = "Ruby bindings to re2."
|
6
|
+
s.description = 'Ruby bindings to re2, "an efficient, principled regular expression library".'
|
7
|
+
s.version = RE2::VERSION
|
8
|
+
s.authors = ["Paul Mucur"]
|
9
|
+
s.homepage = "https://github.com/mudge/re2"
|
10
|
+
s.extensions = ["ext/re2/extconf.rb"]
|
11
|
+
s.license = "BSD-3-Clause"
|
12
|
+
s.required_ruby_version = ">= 2.7.0"
|
13
|
+
s.files = [
|
14
|
+
".rspec",
|
15
|
+
"dependencies.yml",
|
16
|
+
"ext/re2/extconf.rb",
|
17
|
+
"ext/re2/re2.cc",
|
18
|
+
"ext/re2/recipes.rb",
|
19
|
+
"Gemfile",
|
20
|
+
"lib/re2.rb",
|
21
|
+
"lib/re2/scanner.rb",
|
22
|
+
"lib/re2/string.rb",
|
23
|
+
"lib/re2/version.rb",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"re2.gemspec"
|
28
|
+
]
|
29
|
+
s.test_files = [
|
30
|
+
"spec/spec_helper.rb",
|
31
|
+
"spec/re2_spec.rb",
|
32
|
+
"spec/kernel_spec.rb",
|
33
|
+
"spec/re2/regexp_spec.rb",
|
34
|
+
"spec/re2/match_data_spec.rb",
|
35
|
+
"spec/re2/string_spec.rb",
|
36
|
+
"spec/re2/set_spec.rb",
|
37
|
+
"spec/re2/scanner_spec.rb"
|
38
|
+
]
|
39
|
+
s.add_development_dependency "rake-compiler", "~> 1.2.1"
|
40
|
+
s.add_development_dependency "rake-compiler-dock", "~> 1.3.0"
|
41
|
+
s.add_development_dependency("rspec", "~> 3.2")
|
42
|
+
s.add_runtime_dependency("mini_portile2", "~> 2.8.4") # keep version in sync with extconf.rb
|
43
|
+
end
|
data/spec/kernel_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec.describe Kernel do
|
2
|
+
describe "#RE2" do
|
3
|
+
it "returns an RE2::Regexp instance given a pattern" do
|
4
|
+
expect(RE2('w(o)(o)')).to be_a(RE2::Regexp)
|
5
|
+
end
|
6
|
+
|
7
|
+
it "returns an RE2::Regexp instance given a pattern and options" do
|
8
|
+
re = RE2('w(o)(o)', :case_sensitive => false)
|
9
|
+
expect(re).to be_a(RE2::Regexp)
|
10
|
+
expect(re).to_not be_case_sensitive
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
RSpec.describe RE2::MatchData do
|
3
|
+
describe "#to_a" do
|
4
|
+
it "is populated with the match and capturing groups" do
|
5
|
+
a = RE2::Regexp.new('w(o)(o)').match('woo').to_a
|
6
|
+
expect(a).to eq(["woo", "o", "o"])
|
7
|
+
end
|
8
|
+
|
9
|
+
it "populates optional capturing groups with nil if they are missing" do
|
10
|
+
a = RE2::Regexp.new('(\d?)(a)(b)').match('ab').to_a
|
11
|
+
expect(a).to eq(["ab", nil, "a", "b"])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#[]" do
|
16
|
+
it "accesses capturing groups by numerical index" do
|
17
|
+
md = RE2::Regexp.new('(\d)(\d{2})').match("123")
|
18
|
+
expect(md[1]).to eq("1")
|
19
|
+
expect(md[2]).to eq("23")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "has the whole match as the 0th item" do
|
23
|
+
md = RE2::Regexp.new('(\d)(\d{2})').match("123")
|
24
|
+
expect(md[0]).to eq("123")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "supports access by numerical ranges" do
|
28
|
+
md = RE2::Regexp.new('(\d+) (\d+) (\d+)').match("123 456 789")
|
29
|
+
expect(md[1..3]).to eq(["123", "456", "789"])
|
30
|
+
expect(md[1...3]).to eq(["123", "456"])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "supports slicing" do
|
34
|
+
md = RE2::Regexp.new('(\d+) (\d+) (\d+)').match("123 456 789")
|
35
|
+
expect(md[1, 3]).to eq(["123", "456", "789"])
|
36
|
+
expect(md[1, 2]).to eq(["123", "456"])
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns nil if attempting to access non-existent capturing groups by index" do
|
40
|
+
md = RE2::Regexp.new('(\d+)').match('bob 123')
|
41
|
+
expect(md[2]).to be_nil
|
42
|
+
expect(md[3]).to be_nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it "allows access by string names when there are named groups" do
|
46
|
+
md = RE2::Regexp.new('(?P<numbers>\d+)').match('bob 123')
|
47
|
+
expect(md["numbers"]).to eq("123")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows access by symbol names when there are named groups" do
|
51
|
+
md = RE2::Regexp.new('(?P<numbers>\d+)').match('bob 123')
|
52
|
+
expect(md[:numbers]).to eq("123")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "allows access by names and indices with mixed groups" do
|
56
|
+
md = RE2::Regexp.new('(?P<name>\w+)(\s*)(?P<numbers>\d+)').match("bob 123")
|
57
|
+
expect(md["name"]).to eq("bob")
|
58
|
+
expect(md[:name]).to eq("bob")
|
59
|
+
expect(md[2]).to eq(" ")
|
60
|
+
expect(md["numbers"]).to eq("123")
|
61
|
+
expect(md[:numbers]).to eq("123")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns nil if no such named group exists" do
|
65
|
+
md = RE2::Regexp.new('(\d+)').match("bob 123")
|
66
|
+
expect(md["missing"]).to be_nil
|
67
|
+
expect(md[:missing]).to be_nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "raises an error if given an inappropriate index" do
|
71
|
+
md = RE2::Regexp.new('(\d+)').match("bob 123")
|
72
|
+
expect { md[nil] }.to raise_error(TypeError)
|
73
|
+
end
|
74
|
+
|
75
|
+
if String.method_defined?(:encoding)
|
76
|
+
it "returns UTF-8 encoded strings by default" do
|
77
|
+
md = RE2::Regexp.new('(?P<name>\S+)').match("bob")
|
78
|
+
expect(md[0].encoding.name).to eq("UTF-8")
|
79
|
+
expect(md["name"].encoding.name).to eq("UTF-8")
|
80
|
+
expect(md[:name].encoding.name).to eq("UTF-8")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns Latin 1 strings encoding when utf-8 is false" do
|
84
|
+
md = RE2::Regexp.new('(?P<name>\S+)', :utf8 => false).match('bob')
|
85
|
+
expect(md[0].encoding.name).to eq("ISO-8859-1")
|
86
|
+
expect(md["name"].encoding.name).to eq("ISO-8859-1")
|
87
|
+
expect(md[:name].encoding.name).to eq("ISO-8859-1")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#string" do
|
93
|
+
it "returns the original string to match against" do
|
94
|
+
re = RE2::Regexp.new('(\D+)').match("bob")
|
95
|
+
expect(re.string).to eq("bob")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns a copy, not the actual original" do
|
99
|
+
string = "bob"
|
100
|
+
re = RE2::Regexp.new('(\D+)').match(string)
|
101
|
+
expect(re.string).to_not equal(string)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "returns a frozen string" do
|
105
|
+
re = RE2::Regexp.new('(\D+)').match("bob")
|
106
|
+
expect(re.string).to be_frozen
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#size" do
|
111
|
+
it "returns the number of capturing groups plus the matching string" do
|
112
|
+
md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
|
113
|
+
expect(md.size).to eq(3)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#length" do
|
118
|
+
it "returns the number of capturing groups plus the matching string" do
|
119
|
+
md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
|
120
|
+
expect(md.length).to eq(3)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#regexp" do
|
125
|
+
it "returns the original RE2::Regexp used" do
|
126
|
+
re = RE2::Regexp.new('(\d+)')
|
127
|
+
md = re.match("123")
|
128
|
+
expect(md.regexp).to equal(re)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#inspect" do
|
133
|
+
it "returns a text representation of the object and indices" do
|
134
|
+
md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
|
135
|
+
expect(md.inspect).to eq('#<RE2::MatchData "1234 56" 1:"1234" 2:"56">')
|
136
|
+
end
|
137
|
+
|
138
|
+
it "represents missing matches as nil" do
|
139
|
+
md = RE2::Regexp.new('(\d+) (\d+)?').match("1234 ")
|
140
|
+
expect(md.inspect).to eq('#<RE2::MatchData "1234 " 1:"1234" 2:nil>')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#to_s" do
|
145
|
+
it "returns the matching part of the original string" do
|
146
|
+
md = RE2::Regexp.new('(\d{2,5})').match("one two 23456")
|
147
|
+
expect(md.to_s).to eq("23456")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "#to_ary" do
|
152
|
+
it "allows the object to be expanded with an asterisk" do
|
153
|
+
md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
|
154
|
+
m1, m2, m3 = *md
|
155
|
+
expect(m1).to eq("1234 56")
|
156
|
+
expect(m2).to eq("1234")
|
157
|
+
expect(m3).to eq("56")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#begin" do
|
162
|
+
it "returns the offset of the start of a match by index" do
|
163
|
+
md = RE2::Regexp.new('(wo{2})').match('a woohoo')
|
164
|
+
expect(md.string[md.begin(0)..-1]).to eq('woohoo')
|
165
|
+
end
|
166
|
+
|
167
|
+
it "returns the offset of the start of a match by string name" do
|
168
|
+
md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
|
169
|
+
expect(md.string[md.begin('foo')..-1]).to eq('foobar')
|
170
|
+
end
|
171
|
+
|
172
|
+
it "returns the offset of the start of a match by symbol name" do
|
173
|
+
md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
|
174
|
+
expect(md.string[md.begin(:foo)..-1]).to eq('foobar')
|
175
|
+
end
|
176
|
+
|
177
|
+
it "returns the offset despite multibyte characters" do
|
178
|
+
md = RE2::Regexp.new('(Ruby)').match('I ♥ Ruby')
|
179
|
+
expect(md.string[md.begin(0)..-1]).to eq('Ruby')
|
180
|
+
end
|
181
|
+
|
182
|
+
it "returns nil for non-existent numerical matches" do
|
183
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
184
|
+
expect(md.begin(10)).to be_nil
|
185
|
+
end
|
186
|
+
|
187
|
+
it "returns nil for negative numerical matches" do
|
188
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
189
|
+
expect(md.begin(-4)).to be_nil
|
190
|
+
end
|
191
|
+
|
192
|
+
it "returns nil for non-existent named matches" do
|
193
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
194
|
+
expect(md.begin('foo')).to be_nil
|
195
|
+
end
|
196
|
+
|
197
|
+
it "returns nil for non-existent symbol named matches" do
|
198
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
199
|
+
expect(md.begin(:foo)).to be_nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#end" do
|
204
|
+
it "returns the offset of the character following the end of a match" do
|
205
|
+
md = RE2::Regexp.new('(wo{2})').match('a woohoo')
|
206
|
+
expect(md.string[0...md.end(0)]).to eq('a woo')
|
207
|
+
end
|
208
|
+
|
209
|
+
it "returns the offset of a match by string name" do
|
210
|
+
md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
|
211
|
+
expect(md.string[0...md.end('foo')]).to eq('a foo')
|
212
|
+
end
|
213
|
+
|
214
|
+
it "returns the offset of a match by symbol name" do
|
215
|
+
md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
|
216
|
+
expect(md.string[0...md.end(:foo)]).to eq('a foo')
|
217
|
+
end
|
218
|
+
|
219
|
+
it "returns the offset despite multibyte characters" do
|
220
|
+
md = RE2::Regexp.new('(Ruby)').match('I ♥ Ruby')
|
221
|
+
expect(md.string[0...md.end(0)]).to eq('I ♥ Ruby')
|
222
|
+
end
|
223
|
+
|
224
|
+
it "returns nil for non-existent numerical matches" do
|
225
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
226
|
+
expect(md.end(10)).to be_nil
|
227
|
+
end
|
228
|
+
|
229
|
+
it "returns nil for negative numerical matches" do
|
230
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
231
|
+
expect(md.end(-4)).to be_nil
|
232
|
+
end
|
233
|
+
|
234
|
+
it "returns nil for non-existent named matches" do
|
235
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
236
|
+
expect(md.end('foo')).to be_nil
|
237
|
+
end
|
238
|
+
|
239
|
+
it "returns nil for non-existent symbol named matches" do
|
240
|
+
md = RE2::Regexp.new('(\d)').match('123')
|
241
|
+
expect(md.end(:foo)).to be_nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "#deconstruct" do
|
246
|
+
it "returns all capturing groups" do
|
247
|
+
md = RE2::Regexp.new('w(o)(o)').match('woo')
|
248
|
+
|
249
|
+
expect(md.deconstruct).to eq(['o', 'o'])
|
250
|
+
end
|
251
|
+
|
252
|
+
it "includes optional capturing groups as nil" do
|
253
|
+
md = RE2::Regexp.new('w(.)(.)(.)?').match('woo')
|
254
|
+
|
255
|
+
expect(md.deconstruct).to eq(['o', 'o', nil])
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "#deconstruct_keys" do
|
260
|
+
it "returns all named captures if given nil" do
|
261
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
262
|
+
|
263
|
+
expect(md.deconstruct_keys(nil)).to eq(:numbers => '123', :letters => 'abc')
|
264
|
+
end
|
265
|
+
|
266
|
+
it "returns only named captures if given names" do
|
267
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
268
|
+
|
269
|
+
expect(md.deconstruct_keys([:numbers])).to eq(:numbers => '123')
|
270
|
+
end
|
271
|
+
|
272
|
+
it "returns named captures up until an invalid name is given" do
|
273
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
274
|
+
|
275
|
+
expect(md.deconstruct_keys([:numbers, :punctuation])).to eq(:numbers => '123')
|
276
|
+
end
|
277
|
+
|
278
|
+
it "returns an empty hash if given more capture names than exist" do
|
279
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
280
|
+
|
281
|
+
expect(md.deconstruct_keys([:numbers, :letters, :punctuation])).to eq({})
|
282
|
+
end
|
283
|
+
|
284
|
+
it "returns an empty hash if there are no named capturing groups" do
|
285
|
+
md = RE2::Regexp.new('(\d+) ([a-zA-Z]+)').match('123 abc')
|
286
|
+
|
287
|
+
expect(md.deconstruct_keys(nil)).to eq({})
|
288
|
+
end
|
289
|
+
|
290
|
+
it "raises an error if given a non-array of keys" do
|
291
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
292
|
+
|
293
|
+
expect { md.deconstruct_keys(0) }.to raise_error(TypeError)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "raises an error if given keys as non-symbols" do
|
297
|
+
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
298
|
+
|
299
|
+
expect { md.deconstruct_keys([0]) }.to raise_error(TypeError)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|