re2 2.0.0-x86_64-darwin → 2.1.0-x86_64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE-DEPENDENCIES.txt +237 -0
- data/LICENSE.txt +1 -1
- data/README.md +47 -16
- data/ext/re2/re2.cc +74 -23
- data/lib/2.6/re2.bundle +0 -0
- data/lib/2.7/re2.bundle +0 -0
- data/lib/3.0/re2.bundle +0 -0
- data/lib/3.1/re2.bundle +0 -0
- data/lib/3.2/re2.bundle +0 -0
- data/lib/re2/version.rb +1 -1
- data/re2.gemspec +5 -4
- data/spec/kernel_spec.rb +3 -3
- data/spec/re2/match_data_spec.rb +24 -0
- data/spec/re2/regexp_spec.rb +6 -0
- data/spec/re2/scanner_spec.rb +76 -22
- data/spec/re2/set_spec.rb +41 -1
- data/spec/re2/string_spec.rb +7 -3
- data/spec/re2_spec.rb +104 -10
- data/spec/spec_helper.rb +10 -0
- metadata +6 -4
data/re2.gemspec
CHANGED
@@ -2,8 +2,8 @@ require_relative 'lib/re2/version'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "re2"
|
5
|
-
s.summary = "Ruby bindings to
|
6
|
-
s.description = 'Ruby bindings to
|
5
|
+
s.summary = "Ruby bindings to RE2."
|
6
|
+
s.description = 'Ruby bindings to RE2, "a fast, safe, thread-friendly alternative to backtracking regular expression engines like those used in PCRE, Perl, and Python".'
|
7
7
|
s.version = RE2::VERSION
|
8
8
|
s.authors = ["Paul Mucur", "Stan Hu"]
|
9
9
|
s.homepage = "https://github.com/mudge/re2"
|
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
"lib/re2/string.rb",
|
23
23
|
"lib/re2/version.rb",
|
24
24
|
"LICENSE.txt",
|
25
|
+
"LICENSE-DEPENDENCIES.txt",
|
25
26
|
"README.md",
|
26
27
|
"Rakefile",
|
27
28
|
"re2.gemspec"
|
@@ -36,8 +37,8 @@ Gem::Specification.new do |s|
|
|
36
37
|
"spec/re2/set_spec.rb",
|
37
38
|
"spec/re2/scanner_spec.rb"
|
38
39
|
]
|
39
|
-
s.add_development_dependency
|
40
|
-
s.add_development_dependency
|
40
|
+
s.add_development_dependency("rake-compiler", "~> 1.2.1")
|
41
|
+
s.add_development_dependency("rake-compiler-dock", "~> 1.3.0")
|
41
42
|
s.add_development_dependency("rspec", "~> 3.2")
|
42
43
|
s.add_runtime_dependency("mini_portile2", "~> 2.8.4") # keep version in sync with extconf.rb
|
43
44
|
end
|
data/spec/kernel_spec.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
RSpec.describe Kernel do
|
2
|
-
describe "
|
2
|
+
describe ".RE2" do
|
3
3
|
it "returns an RE2::Regexp instance given a pattern" do
|
4
4
|
expect(RE2('w(o)(o)')).to be_a(RE2::Regexp)
|
5
5
|
end
|
6
6
|
|
7
7
|
it "returns an RE2::Regexp instance given a pattern and options" do
|
8
8
|
re = RE2('w(o)(o)', :case_sensitive => false)
|
9
|
-
|
10
|
-
expect(re).
|
9
|
+
|
10
|
+
expect(re).not_to be_case_sensitive
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
data/spec/re2/match_data_spec.rb
CHANGED
@@ -10,6 +10,18 @@ RSpec.describe RE2::MatchData do
|
|
10
10
|
a = RE2::Regexp.new('(\d?)(a)(b)').match('ab').to_a
|
11
11
|
expect(a).to eq(["ab", nil, "a", "b"])
|
12
12
|
end
|
13
|
+
|
14
|
+
it "returns UTF-8 strings if the pattern is UTF-8" do
|
15
|
+
a = RE2::Regexp.new('w(o)(o)').match('woo').to_a
|
16
|
+
|
17
|
+
expect(a.map(&:encoding)).to all eq(Encoding::UTF_8)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
|
21
|
+
a = RE2::Regexp.new('w(o)(o)', :utf8 => false).match('woo').to_a
|
22
|
+
|
23
|
+
expect(a.map(&:encoding)).to all eq(Encoding::ISO_8859_1)
|
24
|
+
end
|
13
25
|
end
|
14
26
|
|
15
27
|
describe "#[]" do
|
@@ -19,6 +31,18 @@ RSpec.describe RE2::MatchData do
|
|
19
31
|
expect(md[2]).to eq("23")
|
20
32
|
end
|
21
33
|
|
34
|
+
it "returns a UTF-8 string by numerical index if the pattern is UTF-8" do
|
35
|
+
md = RE2::Regexp.new('(\d)(\d{2})').match("123")
|
36
|
+
|
37
|
+
expect(md[1].encoding).to eq(Encoding::UTF_8)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns a ISO-8859-1 string by numerical index if the pattern is not UTF-8" do
|
41
|
+
md = RE2::Regexp.new('(\d)(\d{2})', :utf8 => false).match("123")
|
42
|
+
|
43
|
+
expect(md[1].encoding).to eq(Encoding::ISO_8859_1)
|
44
|
+
end
|
45
|
+
|
22
46
|
it "has the whole match as the 0th item" do
|
23
47
|
md = RE2::Regexp.new('(\d)(\d{2})').match("123")
|
24
48
|
expect(md[0]).to eq("123")
|
data/spec/re2/regexp_spec.rb
CHANGED
@@ -287,6 +287,12 @@ RSpec.describe RE2::Regexp do
|
|
287
287
|
expect(re.match("My age is 99", 0)).to eq(false)
|
288
288
|
end
|
289
289
|
|
290
|
+
it "returns only true or false if the pattern has no capturing groups" do
|
291
|
+
re = RE2::Regexp.new('My name is')
|
292
|
+
|
293
|
+
expect(re.match('My name is Robert Paulson')).to eq(true)
|
294
|
+
end
|
295
|
+
|
290
296
|
it "raises an exception when given nil" do
|
291
297
|
expect { re.match(nil) }.to raise_error(TypeError)
|
292
298
|
end
|
data/spec/re2/scanner_spec.rb
CHANGED
@@ -21,9 +21,10 @@ RSpec.describe RE2::Scanner do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe "#scan" do
|
24
|
-
it "returns the next array of matches" do
|
24
|
+
it "returns the next array of matches", :aggregate_failures do
|
25
25
|
r = RE2::Regexp.new('(\w+)')
|
26
26
|
scanner = r.scan("It is a truth universally acknowledged")
|
27
|
+
|
27
28
|
expect(scanner.scan).to eq(["It"])
|
28
29
|
expect(scanner.scan).to eq(["is"])
|
29
30
|
expect(scanner.scan).to eq(["a"])
|
@@ -33,41 +34,73 @@ RSpec.describe RE2::Scanner do
|
|
33
34
|
expect(scanner.scan).to be_nil
|
34
35
|
end
|
35
36
|
|
37
|
+
it "returns UTF-8 matches if the pattern is UTF-8" do
|
38
|
+
r = RE2::Regexp.new('(\w+)')
|
39
|
+
scanner = r.scan("It")
|
40
|
+
matches = scanner.scan
|
41
|
+
|
42
|
+
expect(matches.first.encoding).to eq(Encoding::UTF_8)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns ISO-8859-1 matches if the pattern is not UTF-8" do
|
46
|
+
r = RE2::Regexp.new('(\w+)', :utf8 => false)
|
47
|
+
scanner = r.scan("It")
|
48
|
+
matches = scanner.scan
|
49
|
+
|
50
|
+
expect(matches.first.encoding).to eq(Encoding::ISO_8859_1)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns multiple capturing groups at a time", :aggregate_failures do
|
54
|
+
r = RE2::Regexp.new('(\w+) (\w+)')
|
55
|
+
scanner = r.scan("It is a truth universally acknowledged")
|
56
|
+
|
57
|
+
expect(scanner.scan).to eq(["It", "is"])
|
58
|
+
expect(scanner.scan).to eq(["a", "truth"])
|
59
|
+
expect(scanner.scan).to eq(["universally", "acknowledged"])
|
60
|
+
expect(scanner.scan).to be_nil
|
61
|
+
end
|
62
|
+
|
36
63
|
it "returns an empty array if there are no capturing groups" do
|
37
64
|
r = RE2::Regexp.new('\w+')
|
38
65
|
scanner = r.scan("Foo bar")
|
66
|
+
|
39
67
|
expect(scanner.scan).to eq([])
|
40
68
|
end
|
41
69
|
|
42
70
|
it "returns nil if there is no match" do
|
43
71
|
r = RE2::Regexp.new('\d+')
|
44
72
|
scanner = r.scan("Foo bar")
|
73
|
+
|
45
74
|
expect(scanner.scan).to be_nil
|
46
75
|
end
|
47
76
|
|
48
77
|
it "returns nil if the regexp is invalid" do
|
49
78
|
r = RE2::Regexp.new('???', :log_errors => false)
|
50
79
|
scanner = r.scan("Foo bar")
|
80
|
+
|
51
81
|
expect(scanner.scan).to be_nil
|
52
82
|
end
|
53
83
|
|
54
|
-
it "returns an empty array if the input is empty" do
|
84
|
+
it "returns an empty array if the input is empty", :aggregate_failures do
|
55
85
|
r = RE2::Regexp.new("")
|
56
86
|
scanner = r.scan("")
|
87
|
+
|
57
88
|
expect(scanner.scan).to eq([])
|
58
89
|
expect(scanner.scan).to be_nil
|
59
90
|
end
|
60
91
|
|
61
|
-
it "returns an array of nil with an empty input and capture" do
|
92
|
+
it "returns an array of nil with an empty input and capture", :aggregate_failures do
|
62
93
|
r = RE2::Regexp.new("()")
|
63
94
|
scanner = r.scan("")
|
95
|
+
|
64
96
|
expect(scanner.scan).to eq([nil])
|
65
97
|
expect(scanner.scan).to be_nil
|
66
98
|
end
|
67
99
|
|
68
|
-
it "returns an empty array for every match if the pattern is empty" do
|
100
|
+
it "returns an empty array for every match if the pattern is empty", :aggregate_failures do
|
69
101
|
r = RE2::Regexp.new("")
|
70
102
|
scanner = r.scan("Foo")
|
103
|
+
|
71
104
|
expect(scanner.scan).to eq([])
|
72
105
|
expect(scanner.scan).to eq([])
|
73
106
|
expect(scanner.scan).to eq([])
|
@@ -75,9 +108,10 @@ RSpec.describe RE2::Scanner do
|
|
75
108
|
expect(scanner.scan).to be_nil
|
76
109
|
end
|
77
110
|
|
78
|
-
it "returns an array of nil if the pattern is an empty capturing group" do
|
111
|
+
it "returns an array of nil if the pattern is an empty capturing group", :aggregate_failures do
|
79
112
|
r = RE2::Regexp.new("()")
|
80
113
|
scanner = r.scan("Foo")
|
114
|
+
|
81
115
|
expect(scanner.scan).to eq([nil])
|
82
116
|
expect(scanner.scan).to eq([nil])
|
83
117
|
expect(scanner.scan).to eq([nil])
|
@@ -85,9 +119,10 @@ RSpec.describe RE2::Scanner do
|
|
85
119
|
expect(scanner.scan).to be_nil
|
86
120
|
end
|
87
121
|
|
88
|
-
it "returns array of nils with multiple empty capturing groups" do
|
122
|
+
it "returns array of nils with multiple empty capturing groups", :aggregate_failures do
|
89
123
|
r = RE2::Regexp.new("()()()")
|
90
124
|
scanner = r.scan("Foo")
|
125
|
+
|
91
126
|
expect(scanner.scan).to eq([nil, nil, nil])
|
92
127
|
expect(scanner.scan).to eq([nil, nil, nil])
|
93
128
|
expect(scanner.scan).to eq([nil, nil, nil])
|
@@ -95,17 +130,34 @@ RSpec.describe RE2::Scanner do
|
|
95
130
|
expect(scanner.scan).to be_nil
|
96
131
|
end
|
97
132
|
|
98
|
-
it "supports empty groups with multibyte characters" do
|
133
|
+
it "supports empty groups with multibyte characters", :aggregate_failures do
|
99
134
|
r = RE2::Regexp.new("()€")
|
100
135
|
scanner = r.scan("€")
|
136
|
+
|
101
137
|
expect(scanner.scan).to eq([nil])
|
102
138
|
expect(scanner.scan).to be_nil
|
103
139
|
end
|
140
|
+
|
141
|
+
it "raises a Type Error if given input that can't be coerced to a String" do
|
142
|
+
r = RE2::Regexp.new('(\w+)')
|
143
|
+
|
144
|
+
expect { r.scan(0) }.to raise_error(TypeError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "accepts input that can be coerced to a String", :aggregate_failures do
|
148
|
+
r = RE2::Regexp.new('(\w+)')
|
149
|
+
scanner = r.scan(StringLike.new("Hello world"))
|
150
|
+
|
151
|
+
expect(scanner.scan).to eq(["Hello"])
|
152
|
+
expect(scanner.scan).to eq(["world"])
|
153
|
+
expect(scanner.scan).to be_nil
|
154
|
+
end
|
104
155
|
end
|
105
156
|
|
106
157
|
it "is enumerable" do
|
107
158
|
r = RE2::Regexp.new('(\d)')
|
108
159
|
scanner = r.scan("There are 1 some 2 numbers 3")
|
160
|
+
|
109
161
|
expect(scanner).to be_a(Enumerable)
|
110
162
|
end
|
111
163
|
|
@@ -113,12 +165,8 @@ RSpec.describe RE2::Scanner do
|
|
113
165
|
it "yields each match" do
|
114
166
|
r = RE2::Regexp.new('(\d)')
|
115
167
|
scanner = r.scan("There are 1 some 2 numbers 3")
|
116
|
-
matches = []
|
117
|
-
scanner.each do |match|
|
118
|
-
matches << match
|
119
|
-
end
|
120
168
|
|
121
|
-
expect(
|
169
|
+
expect { |b| scanner.each(&b) }.to yield_successive_args(["1"], ["2"], ["3"])
|
122
170
|
end
|
123
171
|
|
124
172
|
it "returns an enumerator when not given a block" do
|
@@ -135,22 +183,28 @@ RSpec.describe RE2::Scanner do
|
|
135
183
|
end
|
136
184
|
|
137
185
|
describe "#rewind" do
|
138
|
-
it "resets any consumption" do
|
186
|
+
it "resets any consumption", :aggregate_failures do
|
139
187
|
r = RE2::Regexp.new('(\d)')
|
140
188
|
scanner = r.scan("There are 1 some 2 numbers 3")
|
189
|
+
|
141
190
|
expect(scanner.to_enum.first).to eq(["1"])
|
142
191
|
expect(scanner.to_enum.first).to eq(["2"])
|
192
|
+
|
143
193
|
scanner.rewind
|
194
|
+
|
144
195
|
expect(scanner.to_enum.first).to eq(["1"])
|
145
196
|
end
|
146
197
|
|
147
|
-
it "resets the eof? check" do
|
198
|
+
it "resets the eof? check", :aggregate_failures do
|
148
199
|
r = RE2::Regexp.new('(\d)')
|
149
200
|
scanner = r.scan("1")
|
150
201
|
scanner.scan
|
151
|
-
|
202
|
+
|
203
|
+
expect(scanner).to be_eof
|
204
|
+
|
152
205
|
scanner.rewind
|
153
|
-
|
206
|
+
|
207
|
+
expect(scanner).not_to be_eof
|
154
208
|
end
|
155
209
|
end
|
156
210
|
|
@@ -159,7 +213,7 @@ RSpec.describe RE2::Scanner do
|
|
159
213
|
r = RE2::Regexp.new('(\d)')
|
160
214
|
scanner = r.scan("1 2 3")
|
161
215
|
|
162
|
-
expect(scanner
|
216
|
+
expect(scanner).not_to be_eof
|
163
217
|
end
|
164
218
|
|
165
219
|
it "returns true if the input has been consumed" do
|
@@ -167,7 +221,7 @@ RSpec.describe RE2::Scanner do
|
|
167
221
|
scanner = r.scan("1")
|
168
222
|
scanner.scan
|
169
223
|
|
170
|
-
expect(scanner
|
224
|
+
expect(scanner).to be_eof
|
171
225
|
end
|
172
226
|
|
173
227
|
it "returns false if no match is made" do
|
@@ -175,14 +229,14 @@ RSpec.describe RE2::Scanner do
|
|
175
229
|
scanner = r.scan("a")
|
176
230
|
scanner.scan
|
177
231
|
|
178
|
-
expect(scanner
|
232
|
+
expect(scanner).not_to be_eof
|
179
233
|
end
|
180
234
|
|
181
235
|
it "returns false with an empty input that has not been scanned" do
|
182
236
|
r = RE2::Regexp.new("")
|
183
237
|
scanner = r.scan("")
|
184
238
|
|
185
|
-
expect(scanner
|
239
|
+
expect(scanner).not_to be_eof
|
186
240
|
end
|
187
241
|
|
188
242
|
it "returns false with an empty input that has not been matched" do
|
@@ -190,7 +244,7 @@ RSpec.describe RE2::Scanner do
|
|
190
244
|
scanner = r.scan("")
|
191
245
|
scanner.scan
|
192
246
|
|
193
|
-
expect(scanner
|
247
|
+
expect(scanner).not_to be_eof
|
194
248
|
end
|
195
249
|
|
196
250
|
it "returns true with an empty input that has been matched" do
|
@@ -198,7 +252,7 @@ RSpec.describe RE2::Scanner do
|
|
198
252
|
scanner = r.scan("")
|
199
253
|
scanner.scan
|
200
254
|
|
201
|
-
expect(scanner
|
255
|
+
expect(scanner).to be_eof
|
202
256
|
end
|
203
257
|
end
|
204
258
|
end
|
data/spec/re2/set_spec.rb
CHANGED
@@ -67,11 +67,17 @@ RSpec.describe RE2::Set do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
it "raises an error if given a
|
70
|
+
it "raises an error if given a pattern that can't be coerced to a String" do
|
71
71
|
set = RE2::Set.new(:unanchored, :log_errors => false)
|
72
72
|
|
73
73
|
expect { set.add(0) }.to raise_error(TypeError)
|
74
74
|
end
|
75
|
+
|
76
|
+
it "accepts a pattern that can be coerced to a String" do
|
77
|
+
set = RE2::Set.new
|
78
|
+
|
79
|
+
expect(set.add(StringLike.new("abc"))).to eq(0)
|
80
|
+
end
|
75
81
|
end
|
76
82
|
|
77
83
|
describe "#compile" do
|
@@ -96,6 +102,24 @@ RSpec.describe RE2::Set do
|
|
96
102
|
expect(set.match("abcdefghi", :exception => false)).to eq([0, 1, 2])
|
97
103
|
end
|
98
104
|
|
105
|
+
it "returns an empty array if there is no match" do
|
106
|
+
set = RE2::Set.new
|
107
|
+
set.add("abc")
|
108
|
+
set.compile
|
109
|
+
|
110
|
+
expect(set.match("def", :exception => false)).to be_empty
|
111
|
+
end
|
112
|
+
|
113
|
+
it "returns an empty array if there is no match when :exception is true" do
|
114
|
+
skip "Underlying RE2::Set::Match does not output error information" unless RE2::Set.match_raises_errors?
|
115
|
+
|
116
|
+
set = RE2::Set.new
|
117
|
+
set.add("abc")
|
118
|
+
set.compile
|
119
|
+
|
120
|
+
expect(set.match("def")).to be_empty
|
121
|
+
end
|
122
|
+
|
99
123
|
it "raises an error if called before #compile by default" do
|
100
124
|
skip "Underlying RE2::Set::Match does not output error information" unless RE2::Set.match_raises_errors?
|
101
125
|
|
@@ -139,6 +163,22 @@ RSpec.describe RE2::Set do
|
|
139
163
|
|
140
164
|
expect { set.match("", 0) }.to raise_error(TypeError)
|
141
165
|
end
|
166
|
+
|
167
|
+
it "raises a Type Error if given input that can't be coerced to a String" do
|
168
|
+
set = RE2::Set.new
|
169
|
+
set.add("abc")
|
170
|
+
set.compile
|
171
|
+
|
172
|
+
expect { set.match(0, :exception => false) }.to raise_error(TypeError)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "accepts input if it can be coerced to a String" do
|
176
|
+
set = RE2::Set.new
|
177
|
+
set.add("abc")
|
178
|
+
set.compile
|
179
|
+
|
180
|
+
expect(set.match(StringLike.new("abcdef"), :exception => false)).to contain_exactly(0)
|
181
|
+
end
|
142
182
|
end
|
143
183
|
|
144
184
|
def silence_stderr
|
data/spec/re2/string_spec.rb
CHANGED
@@ -12,7 +12,8 @@ RSpec.describe RE2::String do
|
|
12
12
|
|
13
13
|
it "doesn't perform an in-place replacement" do
|
14
14
|
string = "My name is Robert Paulson"
|
15
|
-
|
15
|
+
|
16
|
+
expect(string.re2_sub('Robert', 'Crobert')).not_to equal(string)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -23,13 +24,15 @@ RSpec.describe RE2::String do
|
|
23
24
|
|
24
25
|
it "doesn't perform an in-place replacement" do
|
25
26
|
string = "My name is Robert Paulson"
|
26
|
-
|
27
|
+
|
28
|
+
expect(string.re2_gsub('a', 'e')).not_to equal(string)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
describe "#re2_match" do
|
31
|
-
it "delegates to RE2::Regexp#match to perform matches" do
|
33
|
+
it "delegates to RE2::Regexp#match to perform matches", :aggregate_failures do
|
32
34
|
md = "My name is Robert Paulson".re2_match('My name is (\S+) (\S+)')
|
35
|
+
|
33
36
|
expect(md).to be_a(RE2::MatchData)
|
34
37
|
expect(md[0]).to eq("My name is Robert Paulson")
|
35
38
|
expect(md[1]).to eq("Robert")
|
@@ -38,6 +41,7 @@ RSpec.describe RE2::String do
|
|
38
41
|
|
39
42
|
it "supports limiting the number of matches" do
|
40
43
|
md = "My name is Robert Paulson".re2_match('My name is (\S+) (\S+)', 0)
|
44
|
+
|
41
45
|
expect(md).to eq(true)
|
42
46
|
end
|
43
47
|
end
|
data/spec/re2_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
RSpec.describe RE2 do
|
2
|
-
describe "
|
2
|
+
describe ".Replace" do
|
3
3
|
it "only replaces the first occurrence of the pattern" do
|
4
4
|
expect(RE2.Replace("woo", "o", "a")).to eq("wao")
|
5
5
|
end
|
@@ -15,29 +15,68 @@ RSpec.describe RE2 do
|
|
15
15
|
it "does not perform replacements in-place" do
|
16
16
|
name = "Robert"
|
17
17
|
replacement = RE2.Replace(name, "R", "Cr")
|
18
|
-
|
18
|
+
|
19
|
+
expect(name).not_to equal(replacement)
|
19
20
|
end
|
20
21
|
|
21
22
|
it "supports passing an RE2::Regexp as the pattern" do
|
22
23
|
re = RE2::Regexp.new('wo{2}')
|
24
|
+
|
23
25
|
expect(RE2.Replace("woo", re, "miaow")).to eq("miaow")
|
24
26
|
end
|
25
27
|
|
26
28
|
it "respects any passed RE2::Regexp's flags" do
|
27
29
|
re = RE2::Regexp.new('gOOD MORNING', :case_sensitive => false)
|
30
|
+
|
28
31
|
expect(RE2.Replace("Good morning", re, "hi")).to eq("hi")
|
29
32
|
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
it "supports passing something that can be coerced to a String as input" do
|
35
|
+
expect(RE2.Replace(StringLike.new("woo"), "oo", "ah")).to eq("wah")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "supports passing something that can be coerced to a String as a pattern" do
|
39
|
+
expect(RE2.Replace("woo", StringLike.new("oo"), "ah")).to eq("wah")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "supports passing something that can be coerced to a String as a replacement" do
|
43
|
+
expect(RE2.Replace("woo", "oo", StringLike.new("ah"))).to eq("wah")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns UTF-8 strings if the pattern is UTF-8" do
|
47
|
+
original = "Foo".encode("ISO-8859-1")
|
48
|
+
replacement = RE2.Replace(original, "oo", "ah")
|
49
|
+
|
50
|
+
expect(replacement.encoding).to eq(Encoding::UTF_8)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
|
54
|
+
original = "Foo"
|
55
|
+
replacement = RE2.Replace(original, RE2("oo", :utf8 => false), "ah")
|
56
|
+
|
57
|
+
expect(replacement.encoding).to eq(Encoding::ISO_8859_1)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns UTF-8 strings when given a String pattern" do
|
61
|
+
replacement = RE2.Replace("Foo", "oo".encode("ISO-8859-1"), "ah")
|
62
|
+
|
63
|
+
expect(replacement.encoding).to eq(Encoding::UTF_8)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "raises a Type Error for input that can't be converted to String" do
|
67
|
+
expect { RE2.Replace(0, "oo", "ah") }.to raise_error(TypeError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "raises a Type Error for a non-RE2::Regexp pattern that can't be converted to String" do
|
71
|
+
expect { RE2.Replace("woo", 0, "ah") }.to raise_error(TypeError)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "raises a Type Error for a replacement that can't be converted to String" do
|
75
|
+
expect { RE2.Replace("woo", "oo", 0) }.to raise_error(TypeError)
|
37
76
|
end
|
38
77
|
end
|
39
78
|
|
40
|
-
describe "
|
79
|
+
describe ".GlobalReplace" do
|
41
80
|
it "replaces every occurrence of a pattern" do
|
42
81
|
expect(RE2.GlobalReplace("woo", "o", "a")).to eq("waa")
|
43
82
|
end
|
@@ -53,23 +92,78 @@ RSpec.describe RE2 do
|
|
53
92
|
it "does not perform replacement in-place" do
|
54
93
|
name = "Robert"
|
55
94
|
replacement = RE2.GlobalReplace(name, "(?i)R", "w")
|
56
|
-
|
95
|
+
|
96
|
+
expect(name).not_to equal(replacement)
|
57
97
|
end
|
58
98
|
|
59
99
|
it "supports passing an RE2::Regexp as the pattern" do
|
60
100
|
re = RE2::Regexp.new('wo{2,}')
|
101
|
+
|
61
102
|
expect(RE2.GlobalReplace("woowooo", re, "miaow")).to eq("miaowmiaow")
|
62
103
|
end
|
63
104
|
|
64
105
|
it "respects any passed RE2::Regexp's flags" do
|
65
106
|
re = RE2::Regexp.new('gOOD MORNING', :case_sensitive => false)
|
107
|
+
|
66
108
|
expect(RE2.GlobalReplace("Good morning Good morning", re, "hi")).to eq("hi hi")
|
67
109
|
end
|
110
|
+
|
111
|
+
it "supports passing something that can be coerced to a String as input" do
|
112
|
+
expect(RE2.GlobalReplace(StringLike.new("woo"), "o", "a")).to eq("waa")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "supports passing something that can be coerced to a String as a pattern" do
|
116
|
+
expect(RE2.GlobalReplace("woo", StringLike.new("o"), "a")).to eq("waa")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "supports passing something that can be coerced to a String as a replacement" do
|
120
|
+
expect(RE2.GlobalReplace("woo", "o", StringLike.new("a"))).to eq("waa")
|
121
|
+
end
|
122
|
+
|
123
|
+
it "returns UTF-8 strings if the pattern is UTF-8" do
|
124
|
+
original = "Foo".encode("ISO-8859-1")
|
125
|
+
replacement = RE2.GlobalReplace(original, "oo", "ah")
|
126
|
+
|
127
|
+
expect(replacement.encoding).to eq(Encoding::UTF_8)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
|
131
|
+
original = "Foo"
|
132
|
+
replacement = RE2.GlobalReplace(original, RE2("oo", :utf8 => false), "ah")
|
133
|
+
|
134
|
+
expect(replacement.encoding).to eq(Encoding::ISO_8859_1)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns UTF-8 strings when given a String pattern" do
|
138
|
+
replacement = RE2.GlobalReplace("Foo", "oo".encode("ISO-8859-1"), "ah")
|
139
|
+
|
140
|
+
expect(replacement.encoding).to eq(Encoding::UTF_8)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "raises a Type Error for input that can't be converted to String" do
|
144
|
+
expect { RE2.GlobalReplace(0, "o", "a") }.to raise_error(TypeError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "raises a Type Error for a non-RE2::Regexp pattern that can't be converted to String" do
|
148
|
+
expect { RE2.GlobalReplace("woo", 0, "a") }.to raise_error(TypeError)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "raises a Type Error for a replacement that can't be converted to String" do
|
152
|
+
expect { RE2.GlobalReplace("woo", "o", 0) }.to raise_error(TypeError)
|
153
|
+
end
|
68
154
|
end
|
69
155
|
|
70
156
|
describe "#QuoteMeta" do
|
71
157
|
it "escapes a string so it can be used as a regular expression" do
|
72
158
|
expect(RE2.QuoteMeta("1.5-2.0?")).to eq('1\.5\-2\.0\?')
|
73
159
|
end
|
160
|
+
|
161
|
+
it "raises a Type Error for input that can't be converted to String" do
|
162
|
+
expect { RE2.QuoteMeta(0) }.to raise_error(TypeError)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "supports passing something that can be coerced to a String as input" do
|
166
|
+
expect(RE2.QuoteMeta(StringLike.new("1.5"))).to eq('1\.5')
|
167
|
+
end
|
74
168
|
end
|
75
169
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
require "re2"
|
2
2
|
|
3
|
+
# To test passing objects that can be coerced to a String.
|
4
|
+
class StringLike
|
5
|
+
attr_reader :str
|
6
|
+
alias_method :to_str, :str
|
7
|
+
|
8
|
+
def initialize(str)
|
9
|
+
@str = str
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
3
13
|
RSpec.configure do |config|
|
4
14
|
config.expect_with :rspec do |expectations|
|
5
15
|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: re2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Paul Mucur
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-09-
|
12
|
+
date: 2023-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
@@ -53,7 +53,8 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '3.2'
|
56
|
-
description: Ruby bindings to
|
56
|
+
description: Ruby bindings to RE2, "a fast, safe, thread-friendly alternative to backtracking
|
57
|
+
regular expression engines like those used in PCRE, Perl, and Python".
|
57
58
|
email:
|
58
59
|
executables: []
|
59
60
|
extensions: []
|
@@ -61,6 +62,7 @@ extra_rdoc_files: []
|
|
61
62
|
files:
|
62
63
|
- ".rspec"
|
63
64
|
- Gemfile
|
65
|
+
- LICENSE-DEPENDENCIES.txt
|
64
66
|
- LICENSE.txt
|
65
67
|
- README.md
|
66
68
|
- Rakefile
|
@@ -111,7 +113,7 @@ requirements: []
|
|
111
113
|
rubygems_version: 3.3.26
|
112
114
|
signing_key:
|
113
115
|
specification_version: 4
|
114
|
-
summary: Ruby bindings to
|
116
|
+
summary: Ruby bindings to RE2.
|
115
117
|
test_files:
|
116
118
|
- spec/spec_helper.rb
|
117
119
|
- spec/re2_spec.rb
|