re2 2.27.0-arm-linux-gnu → 2.28.0-arm-linux-gnu
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/Gemfile +5 -0
- data/README.md +1 -1
- data/ext/re2/extconf.rb +2 -26
- data/ext/re2/re2.cc +58 -59
- data/lib/3.1/re2.so +0 -0
- data/lib/3.2/re2.so +0 -0
- data/lib/3.3/re2.so +0 -0
- data/lib/3.4/re2.so +0 -0
- data/lib/4.0/re2.so +0 -0
- data/lib/re2/version.rb +1 -1
- data/re2.gemspec +1 -1
- data/spec/re2/match_data_spec.rb +90 -2
- data/spec/re2/regexp_spec.rb +21 -5
- data/spec/re2/scanner_spec.rb +9 -0
- data/spec/re2/set_spec.rb +31 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 140f6962d695db89ed1410372669691144d1c71e31c49873504bcb68291ce986
|
|
4
|
+
data.tar.gz: 91120b25899a2db5f6b5e31c65a940710a9614123e9fac4c029f5ee42ed6863e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31498cbb945d8595590a63d93d3031f67de273e95fc976dfcd227e43fc619c93a6c8403d5e1eafded51559f7e985282836dab6072cc6056249a7d830c515565a
|
|
7
|
+
data.tar.gz: 53981ca65527f73169d63361022736afd5d301b6b7e1e3a4cd90463f176481a57efdab1e00428449e4296a67bde72f11c4b50fd77abf6990a21731144ff4b342
|
data/Gemfile
CHANGED
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.28.0
|
|
10
10
|
**Bundled RE2 version:** libre2.11 (2025-11-05)
|
|
11
11
|
|
|
12
12
|
```ruby
|
data/ext/re2/extconf.rb
CHANGED
|
@@ -132,38 +132,14 @@ module RE2
|
|
|
132
132
|
|
|
133
133
|
def build_extension
|
|
134
134
|
$CFLAGS << " -Wall -Wextra -funroll-loops"
|
|
135
|
-
$CXXFLAGS << " -Wall -Wextra -funroll-loops"
|
|
135
|
+
$CXXFLAGS << " -Wall -Wextra -funroll-loops -std=c++17"
|
|
136
136
|
|
|
137
137
|
# Pass -x c++ to force gcc to compile the test program
|
|
138
138
|
# as C++ (as it will end in .c by default).
|
|
139
|
-
compile_options = +"-x c++"
|
|
139
|
+
compile_options = +"-x c++ -std=c++17"
|
|
140
140
|
|
|
141
141
|
have_library("stdc++")
|
|
142
142
|
|
|
143
|
-
minimal_program = <<~SRC
|
|
144
|
-
#include <re2/re2.h>
|
|
145
|
-
int main() { return 0; }
|
|
146
|
-
SRC
|
|
147
|
-
|
|
148
|
-
re2_requires_version_flag = checking_for("re2 that requires explicit C++ version flag") do
|
|
149
|
-
!try_compile(minimal_program, compile_options)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
if re2_requires_version_flag
|
|
153
|
-
# Recent versions of RE2 depend directly on Abseil, which requires a
|
|
154
|
-
# compiler with C++17 support.
|
|
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|
|
|
156
|
-
checking_for("re2 that compiles with #{std} standard") do
|
|
157
|
-
if try_compile(minimal_program, compile_options + " -std=#{std}")
|
|
158
|
-
compile_options << " -std=#{std}"
|
|
159
|
-
$CPPFLAGS << " -std=#{std}"
|
|
160
|
-
|
|
161
|
-
true
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
143
|
# Determine which version of re2 the user has installed.
|
|
168
144
|
# Revision d9f8806c004d added an `endpos` argument to the
|
|
169
145
|
# generic Match() function.
|
data/ext/re2/re2.cc
CHANGED
|
@@ -42,6 +42,7 @@ typedef struct {
|
|
|
42
42
|
|
|
43
43
|
typedef struct {
|
|
44
44
|
RE2::Set *set;
|
|
45
|
+
bool compiled;
|
|
45
46
|
} re2_set;
|
|
46
47
|
|
|
47
48
|
struct nogvl_match_arg {
|
|
@@ -170,6 +171,13 @@ static void *nogvl_extract(void *ptr) {
|
|
|
170
171
|
return nullptr;
|
|
171
172
|
}
|
|
172
173
|
|
|
174
|
+
static std::string group_name(VALUE key) {
|
|
175
|
+
VALUE str = SYMBOL_P(key) ? rb_sym2str(key) : key;
|
|
176
|
+
str = rb_str_conv_enc(str, rb_enc_get(str), rb_utf8_encoding());
|
|
177
|
+
|
|
178
|
+
return std::string(RSTRING_PTR(str), RSTRING_LEN(str));
|
|
179
|
+
}
|
|
180
|
+
|
|
173
181
|
VALUE re2_mRE2, re2_cRegexp, re2_cMatchData, re2_cScanner, re2_cSet,
|
|
174
182
|
re2_eSetMatchError, re2_eSetUnsupportedError, re2_eRegexpUnsupportedError;
|
|
175
183
|
|
|
@@ -412,9 +420,9 @@ static re2_scanner *unwrap_re2_scanner(VALUE self) {
|
|
|
412
420
|
* in alphabetical order rather than definition order, as RE2 stores named
|
|
413
421
|
* groups internally in a sorted map.
|
|
414
422
|
*
|
|
415
|
-
* Note RE2
|
|
416
|
-
*
|
|
417
|
-
*
|
|
423
|
+
* Note RE2 stores capturing group names as UTF-8, even if the {RE2::Regexp}
|
|
424
|
+
* sets the `:utf8` option to false so strings will always be returned in
|
|
425
|
+
* UTF-8.
|
|
418
426
|
*
|
|
419
427
|
* @return [Array<String>] an array of names of named capturing groups
|
|
420
428
|
* @example
|
|
@@ -427,9 +435,7 @@ static VALUE re2_regexp_names(const VALUE self) {
|
|
|
427
435
|
VALUE names = rb_ary_new2(groups.size());
|
|
428
436
|
|
|
429
437
|
for (const auto& group : groups) {
|
|
430
|
-
rb_ary_push(names,
|
|
431
|
-
encoded_str_new(group.first.data(), group.first.size(),
|
|
432
|
-
p->pattern->options().encoding()));
|
|
438
|
+
rb_ary_push(names, rb_utf8_str_new(group.first.data(), group.first.size()));
|
|
433
439
|
}
|
|
434
440
|
|
|
435
441
|
return names;
|
|
@@ -523,6 +529,8 @@ static VALUE re2_scanner_rewind(VALUE self) {
|
|
|
523
529
|
}
|
|
524
530
|
|
|
525
531
|
static VALUE re2_scanner_initialize_copy(VALUE self, VALUE other) {
|
|
532
|
+
if (self == other) return self;
|
|
533
|
+
|
|
526
534
|
re2_scanner *self_c;
|
|
527
535
|
re2_scanner *other_c = unwrap_re2_scanner(other);
|
|
528
536
|
|
|
@@ -646,20 +654,13 @@ static re2::StringPiece *re2_matchdata_find_match(VALUE idx, const VALUE self) {
|
|
|
646
654
|
|
|
647
655
|
if (RB_INTEGER_TYPE_P(idx)) {
|
|
648
656
|
id = NUM2INT(idx);
|
|
649
|
-
} else if (SYMBOL_P(idx)) {
|
|
650
|
-
const auto& groups = p->pattern->NamedCapturingGroups();
|
|
651
|
-
auto search = groups.find(rb_id2name(SYM2ID(idx)));
|
|
652
|
-
|
|
653
|
-
if (search != groups.end()) {
|
|
654
|
-
id = search->second;
|
|
655
|
-
} else {
|
|
656
|
-
return nullptr;
|
|
657
|
-
}
|
|
658
657
|
} else {
|
|
659
|
-
|
|
658
|
+
if (!SYMBOL_P(idx)) {
|
|
659
|
+
StringValue(idx);
|
|
660
|
+
}
|
|
660
661
|
|
|
661
662
|
const auto& groups = p->pattern->NamedCapturingGroups();
|
|
662
|
-
auto search = groups.find(
|
|
663
|
+
auto search = groups.find(group_name(idx));
|
|
663
664
|
|
|
664
665
|
if (search != groups.end()) {
|
|
665
666
|
id = search->second;
|
|
@@ -1004,11 +1005,8 @@ static VALUE re2_matchdata_aref(int argc, VALUE *argv, const VALUE self) {
|
|
|
1004
1005
|
VALUE idx, rest;
|
|
1005
1006
|
rb_scan_args(argc, argv, "11", &idx, &rest);
|
|
1006
1007
|
|
|
1007
|
-
if (TYPE(idx) == T_STRING) {
|
|
1008
|
-
return re2_matchdata_named_match(
|
|
1009
|
-
std::string(RSTRING_PTR(idx), RSTRING_LEN(idx)), self);
|
|
1010
|
-
} else if (SYMBOL_P(idx)) {
|
|
1011
|
-
return re2_matchdata_named_match(rb_id2name(SYM2ID(idx)), self);
|
|
1008
|
+
if (TYPE(idx) == T_STRING || SYMBOL_P(idx)) {
|
|
1009
|
+
return re2_matchdata_named_match(group_name(idx), self);
|
|
1012
1010
|
} else if (!NIL_P(rest) || !RB_INTEGER_TYPE_P(idx) || NUM2INT(idx) < 0) {
|
|
1013
1011
|
return rb_ary_aref(argc, argv, re2_matchdata_to_a(self));
|
|
1014
1012
|
} else {
|
|
@@ -1122,6 +1120,7 @@ static VALUE re2_matchdata_deconstruct(const VALUE self) {
|
|
|
1122
1120
|
* Note RE2 only supports UTF-8 and ISO-8859-1 encoding so strings will be
|
|
1123
1121
|
* returned in UTF-8 by default or ISO-8859-1 if the `:utf8` option for the
|
|
1124
1122
|
* {RE2::Regexp} is set to `false` (any other encoding's behaviour is undefined).
|
|
1123
|
+
* Capturing group names will always be returned in UTF-8.
|
|
1125
1124
|
*
|
|
1126
1125
|
* @return [Hash] a hash of capturing group names to submatches
|
|
1127
1126
|
* @param [Array<Symbol>, nil] keys an array of `Symbol` capturing group names
|
|
@@ -1151,7 +1150,7 @@ static VALUE re2_matchdata_deconstruct_keys(const VALUE self, const VALUE keys)
|
|
|
1151
1150
|
if (NIL_P(keys)) {
|
|
1152
1151
|
for (const auto& group : groups) {
|
|
1153
1152
|
rb_hash_aset(capturing_groups,
|
|
1154
|
-
|
|
1153
|
+
rb_str_intern(rb_utf8_str_new(group.first.data(), group.first.size())),
|
|
1155
1154
|
re2_matchdata_nth_match(group.second, self));
|
|
1156
1155
|
}
|
|
1157
1156
|
} else {
|
|
@@ -1161,8 +1160,7 @@ static VALUE re2_matchdata_deconstruct_keys(const VALUE self, const VALUE keys)
|
|
|
1161
1160
|
for (int i = 0; i < RARRAY_LEN(keys); ++i) {
|
|
1162
1161
|
VALUE key = rb_ary_entry(keys, i);
|
|
1163
1162
|
Check_Type(key, T_SYMBOL);
|
|
1164
|
-
|
|
1165
|
-
auto search = groups.find(name);
|
|
1163
|
+
auto search = groups.find(group_name(key));
|
|
1166
1164
|
|
|
1167
1165
|
if (search != groups.end()) {
|
|
1168
1166
|
rb_hash_aset(capturing_groups, key, re2_matchdata_nth_match(search->second, self));
|
|
@@ -1182,6 +1180,7 @@ static VALUE re2_matchdata_deconstruct_keys(const VALUE self, const VALUE keys)
|
|
|
1182
1180
|
* Note RE2 only supports UTF-8 and ISO-8859-1 encoding so strings will be
|
|
1183
1181
|
* returned in UTF-8 by default or ISO-8859-1 if the `:utf8` option for the
|
|
1184
1182
|
* {RE2::Regexp} is set to `false` (any other encoding's behaviour is undefined).
|
|
1183
|
+
* Capturing group names will always be returned in UTF-8.
|
|
1185
1184
|
*
|
|
1186
1185
|
* @overload named_captures
|
|
1187
1186
|
* Returns a hash with string keys.
|
|
@@ -1219,12 +1218,9 @@ static VALUE re2_matchdata_named_captures(int argc, VALUE *argv, const VALUE sel
|
|
|
1219
1218
|
VALUE result = rb_hash_new();
|
|
1220
1219
|
|
|
1221
1220
|
for (const auto& group : groups) {
|
|
1222
|
-
VALUE key;
|
|
1221
|
+
VALUE key = rb_utf8_str_new(group.first.data(), group.first.size());
|
|
1223
1222
|
if (symbolize) {
|
|
1224
|
-
key =
|
|
1225
|
-
} else {
|
|
1226
|
-
key = encoded_str_new(group.first.data(), group.first.size(),
|
|
1227
|
-
p->pattern->options().encoding());
|
|
1223
|
+
key = rb_str_intern(key);
|
|
1228
1224
|
}
|
|
1229
1225
|
rb_hash_aset(result, key, re2_matchdata_nth_match(group.second, self));
|
|
1230
1226
|
}
|
|
@@ -1237,9 +1233,9 @@ static VALUE re2_matchdata_named_captures(int argc, VALUE *argv, const VALUE sel
|
|
|
1237
1233
|
* alphabetical order rather than definition order, as RE2 stores named groups
|
|
1238
1234
|
* internally in a sorted map.
|
|
1239
1235
|
*
|
|
1240
|
-
* Note RE2
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1236
|
+
* Note RE2 stores capturing group names as UTF-8, even if the {RE2::Regexp}
|
|
1237
|
+
* sets the `:utf8` option to false so strings will always be returned in
|
|
1238
|
+
* UTF-8.
|
|
1243
1239
|
*
|
|
1244
1240
|
* @return [Array<String>] an array of names of named capturing groups
|
|
1245
1241
|
* @example
|
|
@@ -1276,12 +1272,8 @@ static VALUE re2_matchdata_values_at(int argc, VALUE *argv, const VALUE self) {
|
|
|
1276
1272
|
for (int i = 0; i < argc; ++i) {
|
|
1277
1273
|
VALUE idx = argv[i];
|
|
1278
1274
|
|
|
1279
|
-
if (TYPE(idx) == T_STRING) {
|
|
1280
|
-
rb_ary_push(result, re2_matchdata_named_match(
|
|
1281
|
-
std::string(RSTRING_PTR(idx), RSTRING_LEN(idx)), self));
|
|
1282
|
-
} else if (SYMBOL_P(idx)) {
|
|
1283
|
-
rb_ary_push(result, re2_matchdata_named_match(
|
|
1284
|
-
rb_id2name(SYM2ID(idx)), self));
|
|
1275
|
+
if (TYPE(idx) == T_STRING || SYMBOL_P(idx)) {
|
|
1276
|
+
rb_ary_push(result, re2_matchdata_named_match(group_name(idx), self));
|
|
1285
1277
|
} else {
|
|
1286
1278
|
rb_ary_push(result, re2_matchdata_nth_match(NUM2INT(idx), self));
|
|
1287
1279
|
}
|
|
@@ -1291,6 +1283,8 @@ static VALUE re2_matchdata_values_at(int argc, VALUE *argv, const VALUE self) {
|
|
|
1291
1283
|
}
|
|
1292
1284
|
|
|
1293
1285
|
static VALUE re2_matchdata_initialize_copy(VALUE self, VALUE other) {
|
|
1286
|
+
if (self == other) return self;
|
|
1287
|
+
|
|
1294
1288
|
re2_matchdata *self_m;
|
|
1295
1289
|
re2_matchdata *other_m = unwrap_re2_matchdata(other);
|
|
1296
1290
|
|
|
@@ -1376,24 +1370,17 @@ static VALUE re2_regexp_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
1376
1370
|
|
|
1377
1371
|
TypedData_Get_Struct(self, re2_pattern, &re2_regexp_data_type, p);
|
|
1378
1372
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
if (p->pattern) {
|
|
1382
|
-
delete p->pattern;
|
|
1383
|
-
p->pattern = nullptr;
|
|
1384
|
-
}
|
|
1373
|
+
RE2::Options re2_options;
|
|
1385
1374
|
|
|
1386
1375
|
if (RTEST(options)) {
|
|
1387
|
-
RE2::Options re2_options;
|
|
1388
1376
|
parse_re2_options(&re2_options, options);
|
|
1389
|
-
|
|
1390
|
-
p->pattern = new(std::nothrow) RE2(
|
|
1391
|
-
re2::StringPiece(RSTRING_PTR(pattern), RSTRING_LEN(pattern)), re2_options);
|
|
1392
|
-
} else {
|
|
1393
|
-
p->pattern = new(std::nothrow) RE2(
|
|
1394
|
-
re2::StringPiece(RSTRING_PTR(pattern), RSTRING_LEN(pattern)));
|
|
1395
1377
|
}
|
|
1396
1378
|
|
|
1379
|
+
rb_check_frozen(self);
|
|
1380
|
+
|
|
1381
|
+
p->pattern = new(std::nothrow) RE2(
|
|
1382
|
+
re2::StringPiece(RSTRING_PTR(pattern), RSTRING_LEN(pattern)), re2_options);
|
|
1383
|
+
|
|
1397
1384
|
if (p->pattern == nullptr) {
|
|
1398
1385
|
rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object");
|
|
1399
1386
|
}
|
|
@@ -1778,9 +1765,9 @@ static VALUE re2_regexp_number_of_capturing_groups(const VALUE self) {
|
|
|
1778
1765
|
/*
|
|
1779
1766
|
* Returns a hash of names to capturing indices of groups.
|
|
1780
1767
|
*
|
|
1781
|
-
* Note RE2
|
|
1782
|
-
*
|
|
1783
|
-
*
|
|
1768
|
+
* Note RE2 stores capturing group names as UTF-8, even if the {RE2::Regexp}
|
|
1769
|
+
* sets the `:utf8` option to false so strings will always be returned in
|
|
1770
|
+
* UTF-8.
|
|
1784
1771
|
*
|
|
1785
1772
|
* @return [Hash] a hash of names to capturing indices
|
|
1786
1773
|
*/
|
|
@@ -1791,8 +1778,7 @@ static VALUE re2_regexp_named_capturing_groups(const VALUE self) {
|
|
|
1791
1778
|
|
|
1792
1779
|
for (const auto& group : groups) {
|
|
1793
1780
|
rb_hash_aset(capturing_groups,
|
|
1794
|
-
|
|
1795
|
-
p->pattern->options().encoding()),
|
|
1781
|
+
rb_utf8_str_new(group.first.data(), group.first.size()),
|
|
1796
1782
|
INT2FIX(group.second));
|
|
1797
1783
|
}
|
|
1798
1784
|
|
|
@@ -2503,9 +2489,12 @@ static VALUE re2_set_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
2503
2489
|
|
|
2504
2490
|
rb_check_frozen(self);
|
|
2505
2491
|
|
|
2492
|
+
/* Prevent re-initialisation: #match releases the GVL while holding a
|
|
2493
|
+
* pointer to s->set, so replacing s->set from another thread would free
|
|
2494
|
+
* the object out from under a concurrent match.
|
|
2495
|
+
*/
|
|
2506
2496
|
if (s->set) {
|
|
2507
|
-
|
|
2508
|
-
s->set = nullptr;
|
|
2497
|
+
rb_raise(rb_eTypeError, "already initialized RE2::Set");
|
|
2509
2498
|
}
|
|
2510
2499
|
|
|
2511
2500
|
s->set = new(std::nothrow) RE2::Set(re2_options, re2_anchor);
|
|
@@ -2570,6 +2559,7 @@ static VALUE re2_set_compile(VALUE self) {
|
|
|
2570
2559
|
bool compiled = s->set->Compile();
|
|
2571
2560
|
|
|
2572
2561
|
if (compiled) {
|
|
2562
|
+
s->compiled = true;
|
|
2573
2563
|
rb_obj_freeze(self);
|
|
2574
2564
|
}
|
|
2575
2565
|
|
|
@@ -2687,6 +2677,11 @@ static VALUE re2_set_match(int argc, VALUE *argv, const VALUE self) {
|
|
|
2687
2677
|
|
|
2688
2678
|
if (raise_exception) {
|
|
2689
2679
|
#ifdef HAVE_ERROR_INFO_ARGUMENT
|
|
2680
|
+
/* RE2::Set::Match dereferences a null program after a failed Compile. */
|
|
2681
|
+
if (!s->compiled) {
|
|
2682
|
+
rb_raise(re2_eSetMatchError, "#match must not be called before #compile");
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2690
2685
|
RE2::Set::ErrorInfo e;
|
|
2691
2686
|
nogvl_set_match_arg arg;
|
|
2692
2687
|
arg.set = s->set;
|
|
@@ -2729,6 +2724,10 @@ static VALUE re2_set_match(int argc, VALUE *argv, const VALUE self) {
|
|
|
2729
2724
|
rb_raise(re2_eSetUnsupportedError, "current version of RE2::Set::Match() does not output error information, :exception option can only be set to false");
|
|
2730
2725
|
#endif
|
|
2731
2726
|
} else {
|
|
2727
|
+
if (!s->compiled) {
|
|
2728
|
+
return rb_ary_new();
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2732
2731
|
nogvl_set_match_arg arg;
|
|
2733
2732
|
arg.set = s->set;
|
|
2734
2733
|
arg.text = re2::StringPiece(RSTRING_PTR(str), RSTRING_LEN(str));
|
data/lib/3.1/re2.so
CHANGED
|
Binary file
|
data/lib/3.2/re2.so
CHANGED
|
Binary file
|
data/lib/3.3/re2.so
CHANGED
|
Binary file
|
data/lib/3.4/re2.so
CHANGED
|
Binary file
|
data/lib/4.0/re2.so
CHANGED
|
Binary file
|
data/lib/re2/version.rb
CHANGED
data/re2.gemspec
CHANGED
|
@@ -41,7 +41,7 @@ Gem::Specification.new do |s|
|
|
|
41
41
|
"spec/re2/scanner_spec.rb"
|
|
42
42
|
]
|
|
43
43
|
s.add_development_dependency("rake-compiler", "~> 1.3.1")
|
|
44
|
-
s.add_development_dependency("rake-compiler-dock", "~> 1.
|
|
44
|
+
s.add_development_dependency("rake-compiler-dock", "~> 1.12.0")
|
|
45
45
|
s.add_development_dependency("rspec", "~> 3.2")
|
|
46
46
|
s.add_runtime_dependency("mini_portile2", "~> 2.8.9") # keep version in sync with extconf.rb
|
|
47
47
|
end
|
data/spec/re2/match_data_spec.rb
CHANGED
|
@@ -59,6 +59,15 @@ RSpec.describe RE2::MatchData do
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
describe "#initialize_copy" do
|
|
63
|
+
it "is a no-op when the source is the same object" do
|
|
64
|
+
md = RE2::Regexp.new('(\d+)').match("123")
|
|
65
|
+
md.send(:initialize_copy, md)
|
|
66
|
+
|
|
67
|
+
expect(md.to_a).to eq(["123", "123"])
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
62
71
|
describe "#to_a" do
|
|
63
72
|
it "is populated with the match and capturing groups" do
|
|
64
73
|
a = RE2::Regexp.new('w(o)(o)').match('woo').to_a
|
|
@@ -154,6 +163,24 @@ RSpec.describe RE2::MatchData do
|
|
|
154
163
|
expect(md[:numbers]).to eq("123")
|
|
155
164
|
end
|
|
156
165
|
|
|
166
|
+
it "allows access using a UTF-8 name and a UTF-8 pattern" do
|
|
167
|
+
re = RE2::Regexp.new('(?P<café>\d+)', log_errors: false)
|
|
168
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
169
|
+
|
|
170
|
+
md = re.match('bob 123')
|
|
171
|
+
|
|
172
|
+
expect(md[:café]).to eq("123")
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "allows access using a Latin-1 name and a Latin-1 pattern" do
|
|
176
|
+
re = RE2::Regexp.new('(?P<café>\d+)'.encode("ISO-8859-1"), utf8: false, log_errors: false)
|
|
177
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
178
|
+
|
|
179
|
+
md = re.match('bob 123')
|
|
180
|
+
|
|
181
|
+
expect(md["café".encode("ISO-8859-1")]).to eq("123")
|
|
182
|
+
end
|
|
183
|
+
|
|
157
184
|
it "allows access by names and indices with mixed groups", :aggregate_failures do
|
|
158
185
|
md = RE2::Regexp.new('(?P<name>\w+)(\s*)(?P<numbers>\d+)').match("bob 123")
|
|
159
186
|
|
|
@@ -199,6 +226,12 @@ RSpec.describe RE2::MatchData do
|
|
|
199
226
|
expect(md[:name].encoding.name).to eq("ISO-8859-1")
|
|
200
227
|
end
|
|
201
228
|
|
|
229
|
+
it "handles null bytes in symbol names" do
|
|
230
|
+
md = RE2::Regexp.new('(?P<name>\S+)').match("bob")
|
|
231
|
+
|
|
232
|
+
expect(md[:"name\0b"]).to be_nil
|
|
233
|
+
end
|
|
234
|
+
|
|
202
235
|
it "supports GC compaction" do
|
|
203
236
|
md = RE2::Regexp.new('(wo{2})').match('woohoo' * 5)
|
|
204
237
|
GC.compact
|
|
@@ -358,6 +391,24 @@ RSpec.describe RE2::MatchData do
|
|
|
358
391
|
expect(md.string[md.begin(:foo)..-1]).to eq('foobar')
|
|
359
392
|
end
|
|
360
393
|
|
|
394
|
+
it "returns the offset of the start of a match by non-ASCII symbol name" do
|
|
395
|
+
re = RE2::Regexp.new('(?P<café>fo{2})', log_errors: false)
|
|
396
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
397
|
+
|
|
398
|
+
md = re.match('a foobar')
|
|
399
|
+
|
|
400
|
+
expect(md.string[md.begin(:café)..-1]).to eq('foobar')
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it "returns the offset of the start of a match by Latin-1 string name" do
|
|
404
|
+
re = RE2::Regexp.new('(?P<café>fo{2})'.encode("ISO-8859-1"), utf8: false, log_errors: false)
|
|
405
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
406
|
+
|
|
407
|
+
md = re.match('a foobar')
|
|
408
|
+
|
|
409
|
+
expect(md.string[md.begin("café".encode("ISO-8859-1"))..-1]).to eq('foobar')
|
|
410
|
+
end
|
|
411
|
+
|
|
361
412
|
it "returns the offset of the start of a match by something that can be coerced to a String" do
|
|
362
413
|
md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
|
|
363
414
|
|
|
@@ -822,12 +873,33 @@ RSpec.describe RE2::MatchData do
|
|
|
822
873
|
expect(md.named_captures).to eq("empty" => "", "word" => "bob")
|
|
823
874
|
end
|
|
824
875
|
|
|
876
|
+
it "returns UTF-8 names even for Latin-1 patterns" do
|
|
877
|
+
md = RE2::Regexp.new('(?P<numbers>\d+)', utf8: false).match('123')
|
|
878
|
+
key = md.named_captures.keys.first
|
|
879
|
+
|
|
880
|
+
expect(key.encoding).to eq(Encoding::UTF_8)
|
|
881
|
+
end
|
|
882
|
+
|
|
825
883
|
it "returns symbol keys when symbolize_names: true" do
|
|
826
884
|
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
|
827
885
|
|
|
828
886
|
expect(md.named_captures(symbolize_names: true)).to eq(numbers: "123", letters: "abc")
|
|
829
887
|
end
|
|
830
888
|
|
|
889
|
+
it "returns garbage-collectable symbol keys when symbolize_names: true" do
|
|
890
|
+
md = RE2::Regexp.new('(?P<collectable_named_capture>\d+)').match('123')
|
|
891
|
+
key = md.named_captures(symbolize_names: true).keys.first
|
|
892
|
+
|
|
893
|
+
expect(ObjectSpace.each_object(Symbol)).to include(key)
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
it "correctly encodes non-ASCII capturing group names as symbols" do
|
|
897
|
+
re = RE2::Regexp.new('(?P<café>\d+)', log_errors: false)
|
|
898
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
899
|
+
|
|
900
|
+
expect(re.match('123').named_captures(symbolize_names: true)).to eq(café: "123")
|
|
901
|
+
end
|
|
902
|
+
|
|
831
903
|
it "returns string keys when symbolize_names: false" do
|
|
832
904
|
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
|
833
905
|
|
|
@@ -858,10 +930,10 @@ RSpec.describe RE2::MatchData do
|
|
|
858
930
|
expect(md.names.first.encoding).to eq(Encoding::UTF_8)
|
|
859
931
|
end
|
|
860
932
|
|
|
861
|
-
it "returns
|
|
933
|
+
it "returns UTF-8 strings if the pattern is not UTF-8" do
|
|
862
934
|
md = RE2::Regexp.new('(?P<numbers>\d+)', utf8: false).match('123')
|
|
863
935
|
|
|
864
|
-
expect(md.names.first.encoding).to eq(Encoding::
|
|
936
|
+
expect(md.names.first.encoding).to eq(Encoding::UTF_8)
|
|
865
937
|
end
|
|
866
938
|
|
|
867
939
|
it "raises an error when called on an uninitialized object" do
|
|
@@ -876,6 +948,22 @@ RSpec.describe RE2::MatchData do
|
|
|
876
948
|
expect(md.deconstruct_keys(nil)).to eq(numbers: '123', letters: 'abc')
|
|
877
949
|
end
|
|
878
950
|
|
|
951
|
+
it "returns garbage-collectable symbol keys if given nil" do
|
|
952
|
+
md = RE2::Regexp.new('(?P<collectable_deconstructed_key>\d+)').match('123')
|
|
953
|
+
key = md.deconstruct_keys(nil).keys.first
|
|
954
|
+
|
|
955
|
+
expect(ObjectSpace.each_object(Symbol)).to include(key)
|
|
956
|
+
end
|
|
957
|
+
|
|
958
|
+
it "returns UTF-8 named captures for a Latin-1 pattern if given nil" do
|
|
959
|
+
re = RE2::Regexp.new('(?P<café>\d+) (?P<letters>[a-zA-Z]+)'.encode("ISO-8859-1"), utf8: false, log_errors: false)
|
|
960
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
961
|
+
|
|
962
|
+
md = re.match('123 abc')
|
|
963
|
+
|
|
964
|
+
expect(md.deconstruct_keys(nil)).to eq(café: '123', letters: 'abc')
|
|
965
|
+
end
|
|
966
|
+
|
|
879
967
|
it "returns only named captures if given names" do
|
|
880
968
|
md = RE2::Regexp.new('(?P<numbers>\d+) (?P<letters>[a-zA-Z]+)').match('123 abc')
|
|
881
969
|
|
data/spec/re2/regexp_spec.rb
CHANGED
|
@@ -49,6 +49,13 @@ RSpec.describe RE2::Regexp do
|
|
|
49
49
|
|
|
50
50
|
expect { re.send(:initialize, 'bar') }.to raise_error(FrozenError)
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
it "cannot be re-initialized while parsing options" do
|
|
54
|
+
re = described_class.allocate
|
|
55
|
+
options = Hash.new { |_, key| re.send(:initialize, 'bar') if key == :utf8 }
|
|
56
|
+
|
|
57
|
+
expect { re.send(:initialize, 'woo', options) }.to raise_error(FrozenError)
|
|
58
|
+
end
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
describe "#dup" do
|
|
@@ -1048,6 +1055,13 @@ RSpec.describe RE2::Regexp do
|
|
|
1048
1055
|
expect(RE2::Regexp.new('???', log_errors: false).named_capturing_groups).to be_empty
|
|
1049
1056
|
end
|
|
1050
1057
|
|
|
1058
|
+
it "returns names as UTF-8 even if the pattern is Latin-1" do
|
|
1059
|
+
groups = RE2::Regexp.new('(?P<bob>a)', utf8: false).named_capturing_groups
|
|
1060
|
+
key = groups.keys.first
|
|
1061
|
+
|
|
1062
|
+
expect(key.encoding).to eq(Encoding::UTF_8)
|
|
1063
|
+
end
|
|
1064
|
+
|
|
1051
1065
|
it "raises an error when called on an uninitialized object" do
|
|
1052
1066
|
expect { described_class.allocate.named_capturing_groups }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
|
|
1053
1067
|
end
|
|
@@ -1071,15 +1085,17 @@ RSpec.describe RE2::Regexp do
|
|
|
1071
1085
|
end
|
|
1072
1086
|
|
|
1073
1087
|
it "returns UTF-8 strings if the pattern is UTF-8" do
|
|
1074
|
-
|
|
1088
|
+
re = RE2::Regexp.new('(?P<café>\d+)', log_errors: false)
|
|
1089
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
1075
1090
|
|
|
1076
|
-
expect(names.first.encoding).to eq(Encoding::UTF_8)
|
|
1091
|
+
expect(re.names.first.encoding).to eq(Encoding::UTF_8)
|
|
1077
1092
|
end
|
|
1078
1093
|
|
|
1079
|
-
it "returns
|
|
1080
|
-
|
|
1094
|
+
it "returns UTF-8 strings if the pattern is not UTF-8" do
|
|
1095
|
+
re = RE2::Regexp.new('(?P<café>a)'.encode("ISO-8859-1"), utf8: false, log_errors: false)
|
|
1096
|
+
skip "Underlying RE2 does not support non-ASCII capturing group names" unless re.ok?
|
|
1081
1097
|
|
|
1082
|
-
expect(names
|
|
1098
|
+
expect(re.names).to contain_exactly("café")
|
|
1083
1099
|
end
|
|
1084
1100
|
|
|
1085
1101
|
it "raises an error when called on an uninitialized object" do
|
data/spec/re2/scanner_spec.rb
CHANGED
|
@@ -106,6 +106,15 @@ RSpec.describe RE2::Scanner do
|
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
describe "#initialize_copy" do
|
|
110
|
+
it "is a no-op when the source is the same object" do
|
|
111
|
+
scanner = RE2::Regexp.new('(\w+)').scan("foo bar")
|
|
112
|
+
scanner.send(:initialize_copy, scanner)
|
|
113
|
+
|
|
114
|
+
expect(scanner.scan).to eq(["foo"])
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
109
118
|
describe "#scan" do
|
|
110
119
|
it "returns the next array of matches", :aggregate_failures do
|
|
111
120
|
r = RE2::Regexp.new('(\w+)')
|
data/spec/re2/set_spec.rb
CHANGED
|
@@ -49,6 +49,13 @@ RSpec.describe RE2::Set do
|
|
|
49
49
|
"anchor should be one of: :unanchored, :anchor_start, :anchor_both"
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
it "cannot be re-initialized before compilation" do
|
|
54
|
+
set = RE2::Set.new
|
|
55
|
+
set.add("abc")
|
|
56
|
+
|
|
57
|
+
expect { set.send(:initialize) }.to raise_error(TypeError, /already initialized RE2::Set/)
|
|
58
|
+
end
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
describe "#dup" do
|
|
@@ -212,6 +219,30 @@ RSpec.describe RE2::Set do
|
|
|
212
219
|
end
|
|
213
220
|
end
|
|
214
221
|
|
|
222
|
+
it "raises an error if called after a failed #compile" do
|
|
223
|
+
skip "Underlying RE2::Set::Match does not output error information" unless RE2::Set.match_raises_errors?
|
|
224
|
+
|
|
225
|
+
set = RE2::Set.new(:unanchored, max_mem: 1, log_errors: false)
|
|
226
|
+
set.add("a{1000}b{1000}c{1000}")
|
|
227
|
+
|
|
228
|
+
silence_stderr do
|
|
229
|
+
set.compile
|
|
230
|
+
|
|
231
|
+
expect { set.match("abc") }.to raise_error(RE2::Set::MatchError, "#match must not be called before #compile")
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "returns an empty array if called after a failed #compile when :exception is false" do
|
|
236
|
+
set = RE2::Set.new(:unanchored, max_mem: 1, log_errors: false)
|
|
237
|
+
set.add("a{1000}b{1000}c{1000}")
|
|
238
|
+
|
|
239
|
+
silence_stderr do
|
|
240
|
+
set.compile
|
|
241
|
+
|
|
242
|
+
expect(set.match("abc", exception: false)).to be_empty
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
215
246
|
it "raises an error if :exception is true and RE2 does not support it" do
|
|
216
247
|
skip "Underlying RE2::Set::Match outputs error information" if RE2::Set.match_raises_errors?
|
|
217
248
|
|
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.28.0
|
|
5
5
|
platform: arm-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Paul Mucur
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
33
|
+
version: 1.12.0
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
40
|
+
version: 1.12.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: 3.3.22
|
|
110
110
|
requirements: []
|
|
111
|
-
rubygems_version: 4.0.
|
|
111
|
+
rubygems_version: 4.0.6
|
|
112
112
|
specification_version: 4
|
|
113
113
|
summary: Ruby bindings to RE2.
|
|
114
114
|
test_files:
|