re2 2.25.0 → 2.26.0
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 +4 -4
- data/README.md +1 -1
- data/Rakefile +0 -4
- data/ext/re2/extconf.rb +3 -4
- data/ext/re2/re2.cc +7 -7
- data/lib/re2/version.rb +1 -1
- data/spec/re2/match_data_spec.rb +86 -2
- data/spec/re2/scanner_spec.rb +22 -13
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e424609ac6f07a3b9ad8ebaa3dacdae7b2f9ef421f450ee83d5b1e11d1088423
|
|
4
|
+
data.tar.gz: 8a650664e82ace10809cc4f65af1f40177b3b70bdc92f495a7b79db65859ead2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 676b8efebf7d2c7f7d8a4cdd984ce4050d798ce9198010364cd6b0c9cf02e25276699fcefbe3c1a387ef74f1ee9fae97a18364df60370ca76aeab6f9a15d9fee
|
|
7
|
+
data.tar.gz: e0595b1d2bc13e0b40e880fe78090a1ac2780a2c7a6a2e8d0a456af3c18dc6aac70ae7b81cb6cac4f1f6cde223a099e6f31f27d1c0b173250851a7d2f9677dab
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Python".
|
|
|
6
6
|
|
|
7
7
|
[](https://github.com/mudge/re2/actions)
|
|
8
8
|
|
|
9
|
-
**Current version:** 2.
|
|
9
|
+
**Current version:** 2.26.0
|
|
10
10
|
**Bundled RE2 version:** libre2.11 (2025-11-05)
|
|
11
11
|
|
|
12
12
|
```ruby
|
data/Rakefile
CHANGED
data/ext/re2/extconf.rb
CHANGED
|
@@ -139,7 +139,6 @@ module RE2
|
|
|
139
139
|
compile_options = +"-x c++"
|
|
140
140
|
|
|
141
141
|
have_library("stdc++")
|
|
142
|
-
have_header("stdint.h")
|
|
143
142
|
|
|
144
143
|
minimal_program = <<~SRC
|
|
145
144
|
#include <re2/re2.h>
|
|
@@ -153,7 +152,7 @@ module RE2
|
|
|
153
152
|
if re2_requires_version_flag
|
|
154
153
|
# Recent versions of RE2 depend directly on Abseil, which requires a
|
|
155
154
|
# compiler with C++17 support.
|
|
156
|
-
abort "Cannot compile re2 with your compiler: recent versions require C++17 support." unless %w[c++20 c++17 c++11
|
|
155
|
+
abort "Cannot compile re2 with your compiler: recent versions require C++17 support." unless %w[c++20 c++17 c++11].any? do |std|
|
|
157
156
|
checking_for("re2 that compiles with #{std} standard") do
|
|
158
157
|
if try_compile(minimal_program, compile_options + " -std=#{std}")
|
|
159
158
|
compile_options << " -std=#{std}"
|
|
@@ -268,8 +267,8 @@ module RE2
|
|
|
268
267
|
message "Cross build is #{cross_build_p ? "enabled" : "disabled"}.\n"
|
|
269
268
|
|
|
270
269
|
recipe.host = target_host
|
|
271
|
-
# Ensure x64-mingw-ucrt
|
|
272
|
-
#
|
|
270
|
+
# Ensure x64-mingw-ucrt uses different library paths since the host is
|
|
271
|
+
# the same (x86_64-w64-mingw32).
|
|
273
272
|
recipe.target = File.join(recipe.target, target_arch) if cross_build_p
|
|
274
273
|
|
|
275
274
|
yield recipe
|
data/ext/re2/re2.cc
CHANGED
|
@@ -469,7 +469,7 @@ static VALUE re2_scanner_scan(VALUE self) {
|
|
|
469
469
|
VALUE result = rb_ary_new2(c->number_of_capturing_groups);
|
|
470
470
|
|
|
471
471
|
for (int i = 0; i < c->number_of_capturing_groups; ++i) {
|
|
472
|
-
if (matches[i].
|
|
472
|
+
if (matches[i].data() == NULL) {
|
|
473
473
|
rb_ary_push(result, Qnil);
|
|
474
474
|
} else {
|
|
475
475
|
rb_ary_push(result, encoded_str_new(matches[i].data(),
|
|
@@ -525,7 +525,7 @@ static re2::StringPiece *re2_matchdata_find_match(VALUE idx, const VALUE self) {
|
|
|
525
525
|
if (id >= 0 && id < m->number_of_matches) {
|
|
526
526
|
re2::StringPiece *match = &m->matches[id];
|
|
527
527
|
|
|
528
|
-
if (
|
|
528
|
+
if (match->data() != NULL) {
|
|
529
529
|
return match;
|
|
530
530
|
}
|
|
531
531
|
}
|
|
@@ -615,7 +615,7 @@ static VALUE re2_matchdata_pre_match(const VALUE self) {
|
|
|
615
615
|
re2_pattern *p = unwrap_re2_regexp(m->regexp);
|
|
616
616
|
|
|
617
617
|
re2::StringPiece *match = &m->matches[0];
|
|
618
|
-
if (match->
|
|
618
|
+
if (match->data() == NULL) {
|
|
619
619
|
return Qnil;
|
|
620
620
|
}
|
|
621
621
|
|
|
@@ -642,7 +642,7 @@ static VALUE re2_matchdata_post_match(const VALUE self) {
|
|
|
642
642
|
re2_pattern *p = unwrap_re2_regexp(m->regexp);
|
|
643
643
|
|
|
644
644
|
re2::StringPiece *match = &m->matches[0];
|
|
645
|
-
if (match->
|
|
645
|
+
if (match->data() == NULL) {
|
|
646
646
|
return Qnil;
|
|
647
647
|
}
|
|
648
648
|
|
|
@@ -766,7 +766,7 @@ static VALUE re2_matchdata_to_a(const VALUE self) {
|
|
|
766
766
|
for (int i = 0; i < m->number_of_matches; ++i) {
|
|
767
767
|
re2::StringPiece *match = &m->matches[i];
|
|
768
768
|
|
|
769
|
-
if (match->
|
|
769
|
+
if (match->data() == NULL) {
|
|
770
770
|
rb_ary_push(array, Qnil);
|
|
771
771
|
} else {
|
|
772
772
|
rb_ary_push(array, encoded_str_new(match->data(), match->size(),
|
|
@@ -786,7 +786,7 @@ static VALUE re2_matchdata_nth_match(int nth, const VALUE self) {
|
|
|
786
786
|
} else {
|
|
787
787
|
re2::StringPiece *match = &m->matches[nth];
|
|
788
788
|
|
|
789
|
-
if (match->
|
|
789
|
+
if (match->data() == NULL) {
|
|
790
790
|
return Qnil;
|
|
791
791
|
} else {
|
|
792
792
|
return encoded_str_new(match->data(), match->size(),
|
|
@@ -955,7 +955,7 @@ static VALUE re2_matchdata_deconstruct(const VALUE self) {
|
|
|
955
955
|
for (int i = 1; i < m->number_of_matches; ++i) {
|
|
956
956
|
re2::StringPiece *match = &m->matches[i];
|
|
957
957
|
|
|
958
|
-
if (match->
|
|
958
|
+
if (match->data() == NULL) {
|
|
959
959
|
rb_ary_push(array, Qnil);
|
|
960
960
|
} else {
|
|
961
961
|
rb_ary_push(array, encoded_str_new(match->data(), match->size(),
|
data/lib/re2/version.rb
CHANGED
data/spec/re2/match_data_spec.rb
CHANGED
|
@@ -66,10 +66,16 @@ RSpec.describe RE2::MatchData do
|
|
|
66
66
|
expect(a).to eq(["woo", "o", "o"])
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
it "populates optional capturing groups with
|
|
69
|
+
it "populates optional capturing groups with empty strings if they match zero characters" do
|
|
70
70
|
a = RE2::Regexp.new('(\d?)(a)(b)').match('ab').to_a
|
|
71
71
|
|
|
72
|
-
expect(a).to eq(["ab",
|
|
72
|
+
expect(a).to eq(["ab", "", "a", "b"])
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "distinguishes between zero-length matches and unmatched groups" do
|
|
76
|
+
a = RE2::Regexp.new('()(a)?').match('b').to_a
|
|
77
|
+
|
|
78
|
+
expect(a).to eq(["", "", nil])
|
|
73
79
|
end
|
|
74
80
|
|
|
75
81
|
it "returns UTF-8 strings if the pattern is UTF-8" do
|
|
@@ -158,6 +164,12 @@ RSpec.describe RE2::MatchData do
|
|
|
158
164
|
expect(md[:numbers]).to eq("123")
|
|
159
165
|
end
|
|
160
166
|
|
|
167
|
+
it "returns an empty string for a zero-length capturing group" do
|
|
168
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
169
|
+
|
|
170
|
+
expect(md[1]).to eq("")
|
|
171
|
+
end
|
|
172
|
+
|
|
161
173
|
it "returns nil if no such named group exists", :aggregate_failures do
|
|
162
174
|
md = RE2::Regexp.new('(\d+)').match("bob 123")
|
|
163
175
|
|
|
@@ -281,6 +293,12 @@ RSpec.describe RE2::MatchData do
|
|
|
281
293
|
expect(md.inspect).to eq('#<RE2::MatchData "1234 " 1:"1234" 2:nil>')
|
|
282
294
|
end
|
|
283
295
|
|
|
296
|
+
it "represents zero-length capturing groups as empty strings" do
|
|
297
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
298
|
+
|
|
299
|
+
expect(md.inspect).to eq('#<RE2::MatchData "" 1:"">')
|
|
300
|
+
end
|
|
301
|
+
|
|
284
302
|
it "supports matches with null bytes" do
|
|
285
303
|
md = RE2::Regexp.new("(\\w\0\\w) (\\w\0\\w)").match("a\0b c\0d")
|
|
286
304
|
|
|
@@ -299,6 +317,12 @@ RSpec.describe RE2::MatchData do
|
|
|
299
317
|
expect(md.to_s).to eq("23456")
|
|
300
318
|
end
|
|
301
319
|
|
|
320
|
+
it "returns an empty string for a zero-length match" do
|
|
321
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
322
|
+
|
|
323
|
+
expect(md.to_s).to eq("")
|
|
324
|
+
end
|
|
325
|
+
|
|
302
326
|
it "raises an error when called on an uninitialized object" do
|
|
303
327
|
expect { described_class.allocate.to_s }.to raise_error(TypeError, /uninitialized RE2::MatchData/)
|
|
304
328
|
end
|
|
@@ -346,6 +370,12 @@ RSpec.describe RE2::MatchData do
|
|
|
346
370
|
expect(md.string[md.begin(0)..-1]).to eq('Ruby')
|
|
347
371
|
end
|
|
348
372
|
|
|
373
|
+
it "returns the offset for a zero-length capturing group" do
|
|
374
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
375
|
+
|
|
376
|
+
expect(md.begin(1)).to eq(0)
|
|
377
|
+
end
|
|
378
|
+
|
|
349
379
|
it "returns nil for non-existent numerical matches" do
|
|
350
380
|
md = RE2::Regexp.new('(\d)').match('123')
|
|
351
381
|
|
|
@@ -419,6 +449,12 @@ RSpec.describe RE2::MatchData do
|
|
|
419
449
|
expect(md.string[0...md.end(0)]).to eq('I ♥ Ruby')
|
|
420
450
|
end
|
|
421
451
|
|
|
452
|
+
it "returns the offset for a zero-length capturing group" do
|
|
453
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
454
|
+
|
|
455
|
+
expect(md.end(1)).to eq(0)
|
|
456
|
+
end
|
|
457
|
+
|
|
422
458
|
it "returns nil for non-existent numerical matches" do
|
|
423
459
|
md = RE2::Regexp.new('(\d)').match('123')
|
|
424
460
|
|
|
@@ -492,6 +528,12 @@ RSpec.describe RE2::MatchData do
|
|
|
492
528
|
expect(md.pre_match.encoding).to eq(Encoding::ISO_8859_1)
|
|
493
529
|
end
|
|
494
530
|
|
|
531
|
+
it "returns the text before a zero-length match" do
|
|
532
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
533
|
+
|
|
534
|
+
expect(md.pre_match).to eq("")
|
|
535
|
+
end
|
|
536
|
+
|
|
495
537
|
it "raises an error when called on an uninitialized object" do
|
|
496
538
|
expect { described_class.allocate.pre_match }.to raise_error(TypeError, /uninitialized RE2::MatchData/)
|
|
497
539
|
end
|
|
@@ -528,6 +570,12 @@ RSpec.describe RE2::MatchData do
|
|
|
528
570
|
expect(md.post_match.encoding).to eq(Encoding::ISO_8859_1)
|
|
529
571
|
end
|
|
530
572
|
|
|
573
|
+
it "returns the text after a zero-length match" do
|
|
574
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
575
|
+
|
|
576
|
+
expect(md.post_match).to eq("bob")
|
|
577
|
+
end
|
|
578
|
+
|
|
531
579
|
it "raises an error when called on an uninitialized object" do
|
|
532
580
|
expect { described_class.allocate.post_match }.to raise_error(TypeError, /uninitialized RE2::MatchData/)
|
|
533
581
|
end
|
|
@@ -564,6 +612,12 @@ RSpec.describe RE2::MatchData do
|
|
|
564
612
|
expect(md.offset(0)).to eq([4, 8])
|
|
565
613
|
end
|
|
566
614
|
|
|
615
|
+
it "returns identical offsets for a zero-length capturing group" do
|
|
616
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
617
|
+
|
|
618
|
+
expect(md.offset(1)).to eq([0, 0])
|
|
619
|
+
end
|
|
620
|
+
|
|
567
621
|
it "returns nil for non-existent numerical matches" do
|
|
568
622
|
md = RE2::Regexp.new('(\d)').match("123")
|
|
569
623
|
|
|
@@ -618,6 +672,12 @@ RSpec.describe RE2::MatchData do
|
|
|
618
672
|
expect(md.match_length(0)).to eq(6)
|
|
619
673
|
end
|
|
620
674
|
|
|
675
|
+
it "returns zero for a zero-length capturing group" do
|
|
676
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
677
|
+
|
|
678
|
+
expect(md.match_length(1)).to eq(0)
|
|
679
|
+
end
|
|
680
|
+
|
|
621
681
|
it "returns nil for non-existent numerical matches" do
|
|
622
682
|
md = RE2::Regexp.new('(\d)').match("123")
|
|
623
683
|
|
|
@@ -672,6 +732,12 @@ RSpec.describe RE2::MatchData do
|
|
|
672
732
|
expect(md.values_at(:a, :z)).to eq(["123", nil])
|
|
673
733
|
end
|
|
674
734
|
|
|
735
|
+
it "returns an empty string for a zero-length capturing group" do
|
|
736
|
+
md = RE2::Regexp.new('()(b)').match("bob")
|
|
737
|
+
|
|
738
|
+
expect(md.values_at(1, 2)).to eq(["", "b"])
|
|
739
|
+
end
|
|
740
|
+
|
|
675
741
|
it "returns the full match when given index 0" do
|
|
676
742
|
md = RE2::Regexp.new('(\d+) (\d+)').match("123 456")
|
|
677
743
|
|
|
@@ -702,6 +768,12 @@ RSpec.describe RE2::MatchData do
|
|
|
702
768
|
expect(md.deconstruct).to eq(['o', 'o', nil])
|
|
703
769
|
end
|
|
704
770
|
|
|
771
|
+
it "includes zero-length capturing groups as empty strings" do
|
|
772
|
+
md = RE2::Regexp.new('()').match("bob")
|
|
773
|
+
|
|
774
|
+
expect(md.deconstruct).to eq([""])
|
|
775
|
+
end
|
|
776
|
+
|
|
705
777
|
it "raises an error when called on an uninitialized object" do
|
|
706
778
|
expect { described_class.allocate.deconstruct }.to raise_error(TypeError, /uninitialized RE2::MatchData/)
|
|
707
779
|
end
|
|
@@ -744,6 +816,12 @@ RSpec.describe RE2::MatchData do
|
|
|
744
816
|
expect(md.named_captures).to eq("a" => "123", "b" => nil)
|
|
745
817
|
end
|
|
746
818
|
|
|
819
|
+
it "returns an empty string for a zero-length named capturing group" do
|
|
820
|
+
md = RE2::Regexp.new('(?P<empty>)(?P<word>\w+)').match("bob")
|
|
821
|
+
|
|
822
|
+
expect(md.named_captures).to eq("empty" => "", "word" => "bob")
|
|
823
|
+
end
|
|
824
|
+
|
|
747
825
|
it "returns symbol keys when symbolize_names: true" do
|
|
748
826
|
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
|
749
827
|
|
|
@@ -822,6 +900,12 @@ RSpec.describe RE2::MatchData do
|
|
|
822
900
|
expect(md.deconstruct_keys(nil)).to eq({})
|
|
823
901
|
end
|
|
824
902
|
|
|
903
|
+
it "returns an empty string for a zero-length named capturing group" do
|
|
904
|
+
md = RE2::Regexp.new('(?P<empty>)(?P<word>\w+)').match("bob")
|
|
905
|
+
|
|
906
|
+
expect(md.deconstruct_keys(nil)).to eq(empty: "", word: "bob")
|
|
907
|
+
end
|
|
908
|
+
|
|
825
909
|
it "raises an error if given a non-array of keys" do
|
|
826
910
|
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
|
827
911
|
|
data/spec/re2/scanner_spec.rb
CHANGED
|
@@ -185,11 +185,11 @@ RSpec.describe RE2::Scanner do
|
|
|
185
185
|
expect(scanner.scan).to be_nil
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
-
it "returns an array of
|
|
188
|
+
it "returns an array of empty strings with an empty input and capture", :aggregate_failures do
|
|
189
189
|
r = RE2::Regexp.new("()")
|
|
190
190
|
scanner = r.scan("")
|
|
191
191
|
|
|
192
|
-
expect(scanner.scan).to eq([
|
|
192
|
+
expect(scanner.scan).to eq([""])
|
|
193
193
|
expect(scanner.scan).to be_nil
|
|
194
194
|
end
|
|
195
195
|
|
|
@@ -204,25 +204,34 @@ RSpec.describe RE2::Scanner do
|
|
|
204
204
|
expect(scanner.scan).to be_nil
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
it "returns an array of
|
|
207
|
+
it "returns an array of empty strings if the pattern is an empty capturing group", :aggregate_failures do
|
|
208
208
|
r = RE2::Regexp.new("()")
|
|
209
209
|
scanner = r.scan("Foo")
|
|
210
210
|
|
|
211
|
-
expect(scanner.scan).to eq([
|
|
212
|
-
expect(scanner.scan).to eq([
|
|
213
|
-
expect(scanner.scan).to eq([
|
|
214
|
-
expect(scanner.scan).to eq([
|
|
211
|
+
expect(scanner.scan).to eq([""])
|
|
212
|
+
expect(scanner.scan).to eq([""])
|
|
213
|
+
expect(scanner.scan).to eq([""])
|
|
214
|
+
expect(scanner.scan).to eq([""])
|
|
215
215
|
expect(scanner.scan).to be_nil
|
|
216
216
|
end
|
|
217
217
|
|
|
218
|
-
it "returns array of
|
|
218
|
+
it "returns array of empty strings with multiple empty capturing groups", :aggregate_failures do
|
|
219
219
|
r = RE2::Regexp.new("()()()")
|
|
220
220
|
scanner = r.scan("Foo")
|
|
221
221
|
|
|
222
|
-
expect(scanner.scan).to eq([
|
|
223
|
-
expect(scanner.scan).to eq([
|
|
224
|
-
expect(scanner.scan).to eq([
|
|
225
|
-
expect(scanner.scan).to eq([
|
|
222
|
+
expect(scanner.scan).to eq(["", "", ""])
|
|
223
|
+
expect(scanner.scan).to eq(["", "", ""])
|
|
224
|
+
expect(scanner.scan).to eq(["", "", ""])
|
|
225
|
+
expect(scanner.scan).to eq(["", "", ""])
|
|
226
|
+
expect(scanner.scan).to be_nil
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "distinguishes zero-length matches from unmatched groups", :aggregate_failures do
|
|
230
|
+
r = RE2::Regexp.new("()(a)?")
|
|
231
|
+
scanner = r.scan("b")
|
|
232
|
+
|
|
233
|
+
expect(scanner.scan).to eq(["", nil])
|
|
234
|
+
expect(scanner.scan).to eq(["", nil])
|
|
226
235
|
expect(scanner.scan).to be_nil
|
|
227
236
|
end
|
|
228
237
|
|
|
@@ -230,7 +239,7 @@ RSpec.describe RE2::Scanner do
|
|
|
230
239
|
r = RE2::Regexp.new("()€")
|
|
231
240
|
scanner = r.scan("€")
|
|
232
241
|
|
|
233
|
-
expect(scanner.scan).to eq([
|
|
242
|
+
expect(scanner.scan).to eq([""])
|
|
234
243
|
expect(scanner.scan).to be_nil
|
|
235
244
|
end
|
|
236
245
|
|