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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 477c8a61880d0b90859d119d21612ccaa439fd6e7a5d06946b5044a6520b2fab
4
- data.tar.gz: '0973c566418525946e61a99d1d317bd708a52dc395053064261c6d581ebb797c'
3
+ metadata.gz: e424609ac6f07a3b9ad8ebaa3dacdae7b2f9ef421f450ee83d5b1e11d1088423
4
+ data.tar.gz: 8a650664e82ace10809cc4f65af1f40177b3b70bdc92f495a7b79db65859ead2
5
5
  SHA512:
6
- metadata.gz: 9e18ab14bd16e37917b988483dd432b7469da78113c1f67dcaefaf5102771c635dfde842779b6b325ffd857d0203acc9c32cd88c5f1cb7017fdf05f93f89adf1
7
- data.tar.gz: 20081d9a25c5789a2c585b0c33049c8431ab0f5abc29b2bc0c4e4baa6a1bc6b3da24fd609fe7f05e65a4d5eb4759c20ba3c481f31bc85c25d3cbf2f8efb56d18
6
+ metadata.gz: 676b8efebf7d2c7f7d8a4cdd984ce4050d798ce9198010364cd6b0c9cf02e25276699fcefbe3c1a387ef74f1ee9fae97a18364df60370ca76aeab6f9a15d9fee
7
+ data.tar.gz: e0595b1d2bc13e0b40e880fe78090a1ac2780a2c7a6a2e8d0a456af3c18dc6aac70ae7b81cb6cac4f1f6cde223a099e6f31f27d1c0b173250851a7d2f9677dab
data/README.md CHANGED
@@ -6,7 +6,7 @@ Python".
6
6
 
7
7
  [![Build Status](https://github.com/mudge/re2/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/mudge/re2/actions)
8
8
 
9
- **Current version:** 2.25.0
9
+ **Current version:** 2.26.0
10
10
  **Bundled RE2 version:** libre2.11 (2025-11-05)
11
11
 
12
12
  ```ruby
data/Rakefile CHANGED
@@ -24,10 +24,6 @@ cross_platforms = %w[
24
24
  arm-linux-musl
25
25
  arm64-darwin
26
26
  x64-mingw-ucrt
27
- x64-mingw32
28
- x86-linux-gnu
29
- x86-linux-musl
30
- x86-mingw32
31
27
  x86_64-darwin
32
28
  x86_64-linux-gnu
33
29
  x86_64-linux-musl
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 c++0x].any? do |std|
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 and x64-mingw32 use different library paths since the host
272
- # is the same (x86_64-w64-mingw32).
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].empty()) {
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 (!match->empty()) {
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->empty()) {
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->empty()) {
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->empty()) {
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->empty()) {
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->empty()) {
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
@@ -10,5 +10,5 @@
10
10
 
11
11
 
12
12
  module RE2
13
- VERSION = "2.25.0"
13
+ VERSION = "2.26.0"
14
14
  end
@@ -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 nil if they are missing" do
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", nil, "a", "b"])
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
 
@@ -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 nil with an empty input and capture", :aggregate_failures do
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([nil])
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 nil if the pattern is an empty capturing group", :aggregate_failures do
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([nil])
212
- expect(scanner.scan).to eq([nil])
213
- expect(scanner.scan).to eq([nil])
214
- expect(scanner.scan).to eq([nil])
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 nils with multiple empty capturing groups", :aggregate_failures do
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([nil, nil, nil])
223
- expect(scanner.scan).to eq([nil, nil, nil])
224
- expect(scanner.scan).to eq([nil, nil, nil])
225
- expect(scanner.scan).to eq([nil, nil, nil])
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([nil])
242
+ expect(scanner.scan).to eq([""])
234
243
  expect(scanner.scan).to be_nil
235
244
  end
236
245
 
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.25.0
4
+ version: 2.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Mucur