re2 0.1.0 → 0.1.1
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.
- data/Rakefile +4 -0
- data/ext/re2/re2.cc +42 -20
- data/test/leak.rb +32 -0
- data/test/re2_test.rb +20 -0
- metadata +40 -38
data/Rakefile
CHANGED
@@ -16,6 +16,10 @@ Rake::TestTask.new do |t|
|
|
16
16
|
t.verbose = true
|
17
17
|
end
|
18
18
|
|
19
|
+
task :valgrind do
|
20
|
+
system "valgrind --tool=memcheck --leak-check=full --show-reachable=no --num-callers=15 --track-fds=yes --workaround-gcc296-bugs=yes --max-stackframe=7304328 --dsymutil=yes --track-origins=yes --log-file=report.txt ruby test/leak.rb"
|
21
|
+
end
|
22
|
+
|
19
23
|
task :test => :compile
|
20
24
|
task :default => :test
|
21
25
|
|
data/ext/re2/re2.cc
CHANGED
@@ -19,6 +19,10 @@ extern "C" {
|
|
19
19
|
# define RSTRING_LEN(x) (RSTRING(x)->len)
|
20
20
|
#endif
|
21
21
|
|
22
|
+
#if !defined(RSTRING_PTR)
|
23
|
+
# define RSTRING_PTR(x) (RSTRING(x)->ptr)
|
24
|
+
#endif
|
25
|
+
|
22
26
|
typedef struct {
|
23
27
|
RE2 *pattern;
|
24
28
|
} re2_pattern;
|
@@ -141,9 +145,9 @@ extern "C" {
|
|
141
145
|
VALUE array = rb_ary_new2(m->number_of_matches);
|
142
146
|
for (i = 0; i < m->number_of_matches; i++) {
|
143
147
|
if (m->matches[i].empty()) {
|
144
|
-
|
148
|
+
rb_ary_push(array, Qnil);
|
145
149
|
} else {
|
146
|
-
|
150
|
+
rb_ary_push(array, rb_str_new(m->matches[i].data(), m->matches[i].size()));
|
147
151
|
}
|
148
152
|
}
|
149
153
|
return array;
|
@@ -158,7 +162,7 @@ extern "C" {
|
|
158
162
|
if (nth >= m->number_of_matches || m->matches[nth].empty()) {
|
159
163
|
return Qnil;
|
160
164
|
} else {
|
161
|
-
return
|
165
|
+
return rb_str_new(m->matches[nth].data(), m->matches[nth].size());
|
162
166
|
}
|
163
167
|
}
|
164
168
|
|
@@ -236,27 +240,29 @@ extern "C" {
|
|
236
240
|
|
237
241
|
Data_Get_Struct(self, re2_matchdata, m);
|
238
242
|
|
239
|
-
result =
|
243
|
+
result = rb_str_new("#<RE2::MatchData", 16);
|
240
244
|
|
241
245
|
for (i = 0; i < m->number_of_matches; i++) {
|
242
|
-
|
246
|
+
rb_str_cat(result, " ", 1);
|
243
247
|
|
244
248
|
if (i > 0) {
|
245
249
|
char buf[sizeof(i)*3+1];
|
246
250
|
snprintf(buf, sizeof(buf), "%d", i);
|
247
251
|
rb_str_cat2(result, buf);
|
248
|
-
|
252
|
+
rb_str_cat(result, ":", 1);
|
249
253
|
}
|
250
254
|
|
251
255
|
match = re2_matchdata_nth_match(i, self);
|
252
256
|
|
253
257
|
if (match == Qnil) {
|
254
|
-
|
258
|
+
rb_str_cat(result, "nil", 3);
|
255
259
|
} else {
|
256
|
-
|
260
|
+
rb_str_cat(result, "\"", 1);
|
261
|
+
rb_str_cat(result, RSTRING_PTR(match), RSTRING_LEN(match));
|
262
|
+
rb_str_cat(result, "\"", 1);
|
257
263
|
}
|
258
264
|
}
|
259
|
-
|
265
|
+
rb_str_cat(result, ">", 1);
|
260
266
|
|
261
267
|
return result;
|
262
268
|
}
|
@@ -409,11 +415,11 @@ extern "C" {
|
|
409
415
|
re2_regexp_inspect(VALUE self)
|
410
416
|
{
|
411
417
|
re2_pattern *p;
|
412
|
-
VALUE result =
|
418
|
+
VALUE result = rb_str_new("#<RE2::Regexp /", 15);
|
413
419
|
|
414
420
|
Data_Get_Struct(self, re2_pattern, p);
|
415
|
-
|
416
|
-
|
421
|
+
rb_str_cat(result, p->pattern->pattern().data(), p->pattern->pattern().size());
|
422
|
+
rb_str_cat(result, "/>", 2);
|
417
423
|
|
418
424
|
return result;
|
419
425
|
}
|
@@ -431,7 +437,7 @@ extern "C" {
|
|
431
437
|
{
|
432
438
|
re2_pattern *p;
|
433
439
|
Data_Get_Struct(self, re2_pattern, p);
|
434
|
-
return
|
440
|
+
return rb_str_new(p->pattern->pattern().data(), p->pattern->pattern().size());
|
435
441
|
}
|
436
442
|
|
437
443
|
/*
|
@@ -665,7 +671,7 @@ extern "C" {
|
|
665
671
|
{
|
666
672
|
re2_pattern *p;
|
667
673
|
Data_Get_Struct(self, re2_pattern, p);
|
668
|
-
return
|
674
|
+
return rb_str_new(p->pattern->error().data(), p->pattern->error().size());
|
669
675
|
}
|
670
676
|
|
671
677
|
/*
|
@@ -679,7 +685,7 @@ extern "C" {
|
|
679
685
|
{
|
680
686
|
re2_pattern *p;
|
681
687
|
Data_Get_Struct(self, re2_pattern, p);
|
682
|
-
return
|
688
|
+
return rb_str_new(p->pattern->error_arg().data(), p->pattern->error_arg().size());
|
683
689
|
}
|
684
690
|
|
685
691
|
/*
|
@@ -746,7 +752,7 @@ extern "C" {
|
|
746
752
|
BOOL2RUBY(p->pattern->options().one_line()));
|
747
753
|
|
748
754
|
/* This is a read-only hash after all... */
|
749
|
-
|
755
|
+
rb_obj_freeze(options);
|
750
756
|
|
751
757
|
return options;
|
752
758
|
}
|
@@ -844,7 +850,8 @@ extern "C" {
|
|
844
850
|
Data_Get_Struct(matchdata, re2_matchdata, m);
|
845
851
|
m->matches = new (std::nothrow) re2::StringPiece[n];
|
846
852
|
m->regexp = self;
|
847
|
-
m->string =
|
853
|
+
m->string = rb_str_dup(text);
|
854
|
+
rb_str_freeze(m->string);
|
848
855
|
|
849
856
|
if (m->matches == 0) {
|
850
857
|
rb_raise(rb_eNoMemError, "not enough memory to allocate StringPieces for matches");
|
@@ -896,6 +903,10 @@ extern "C" {
|
|
896
903
|
static VALUE
|
897
904
|
re2_Replace(VALUE self, VALUE str, VALUE pattern, VALUE rewrite)
|
898
905
|
{
|
906
|
+
|
907
|
+
/* Look out for frozen strings. */
|
908
|
+
rb_check_frozen(str);
|
909
|
+
|
899
910
|
UNUSED(self);
|
900
911
|
VALUE repl;
|
901
912
|
re2_pattern *p;
|
@@ -916,7 +927,10 @@ extern "C" {
|
|
916
927
|
repl = rb_str_new(str_as_string.c_str(), str_as_string.length());
|
917
928
|
|
918
929
|
/* Replace the original string with the replacement. */
|
919
|
-
|
930
|
+
if (RSTRING_LEN(str) != RSTRING_LEN(repl)) {
|
931
|
+
rb_str_resize(str, RSTRING_LEN(repl));
|
932
|
+
}
|
933
|
+
memcpy(RSTRING_PTR(str), RSTRING_PTR(repl), RSTRING_LEN(repl));
|
920
934
|
|
921
935
|
return str;
|
922
936
|
}
|
@@ -939,6 +953,10 @@ extern "C" {
|
|
939
953
|
static VALUE
|
940
954
|
re2_GlobalReplace(VALUE self, VALUE str, VALUE pattern, VALUE rewrite)
|
941
955
|
{
|
956
|
+
|
957
|
+
/* Look out for frozen strings. */
|
958
|
+
rb_check_frozen(str);
|
959
|
+
|
942
960
|
UNUSED(self);
|
943
961
|
|
944
962
|
/* Convert all the inputs to be pumped into RE2::GlobalReplace. */
|
@@ -959,7 +977,10 @@ extern "C" {
|
|
959
977
|
repl = rb_str_new(str_as_string.c_str(), str_as_string.length());
|
960
978
|
|
961
979
|
/* Replace the original string with the replacement. */
|
962
|
-
|
980
|
+
if (RSTRING_LEN(str) != RSTRING_LEN(repl)) {
|
981
|
+
rb_str_resize(str, RSTRING_LEN(repl));
|
982
|
+
}
|
983
|
+
memcpy(RSTRING_PTR(str), RSTRING_PTR(repl), RSTRING_LEN(repl));
|
963
984
|
|
964
985
|
return str;
|
965
986
|
}
|
@@ -979,7 +1000,8 @@ extern "C" {
|
|
979
1000
|
{
|
980
1001
|
UNUSED(self);
|
981
1002
|
re2::StringPiece unquoted_as_string_piece(StringValuePtr(unquoted));
|
982
|
-
|
1003
|
+
std::string quoted_string = RE2::QuoteMeta(unquoted_as_string_piece);
|
1004
|
+
return rb_str_new(quoted_string.data(), quoted_string.size());
|
983
1005
|
}
|
984
1006
|
|
985
1007
|
void
|
data/test/leak.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 're2'
|
3
|
+
|
4
|
+
loops = if ENV["LOOPS"]
|
5
|
+
ENV["LOOPS"].to_i
|
6
|
+
else
|
7
|
+
150
|
8
|
+
end
|
9
|
+
|
10
|
+
puts "Looping #{loops} times..."
|
11
|
+
|
12
|
+
loops.times do
|
13
|
+
r = RE2::Regexp.new('woo(oo)(o+)(\d*)')
|
14
|
+
r.ok?
|
15
|
+
r.match('wooo')
|
16
|
+
r.match('wooo', 0)
|
17
|
+
r.match('wooo', 1)
|
18
|
+
r.match('wooo', 2)
|
19
|
+
r =~ 'woooo'
|
20
|
+
r =~ 'bob'
|
21
|
+
RE2::Replace("woo", "woo", "bob")
|
22
|
+
RE2::GlobalReplace("woo", "woo", "bob")
|
23
|
+
m = r.match('woooooo1234')
|
24
|
+
m[0]
|
25
|
+
m[1]
|
26
|
+
m[0,2]
|
27
|
+
m[1..-1]
|
28
|
+
m.string
|
29
|
+
m.regexp
|
30
|
+
m.inspect
|
31
|
+
sleep 0.1
|
32
|
+
end
|
data/test/re2_test.rb
CHANGED
@@ -76,6 +76,16 @@ class RE2Test < Test::Unit::TestCase
|
|
76
76
|
assert_equal name_id, name.object_id
|
77
77
|
end
|
78
78
|
|
79
|
+
def test_replace_with_a_frozen_string
|
80
|
+
frozen_name = "Arnold".freeze
|
81
|
+
assert frozen_name.frozen?
|
82
|
+
|
83
|
+
# Ruby 1.9 raises a RuntimeError instead of a TypeError.
|
84
|
+
assert_raise TypeError, RuntimeError do
|
85
|
+
RE2::Replace(frozen_name, "o", "a")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
79
89
|
def test_global_replace
|
80
90
|
assert_equal "waa", RE2::GlobalReplace("woo", "o", "a")
|
81
91
|
assert_equal "hoo", RE2::GlobalReplace("woo", "w", "h")
|
@@ -88,6 +98,16 @@ class RE2Test < Test::Unit::TestCase
|
|
88
98
|
assert_equal name_id, name.object_id
|
89
99
|
end
|
90
100
|
|
101
|
+
def test_global_replace_with_a_frozen_string
|
102
|
+
frozen_name = "Arnold".freeze
|
103
|
+
assert frozen_name.frozen?
|
104
|
+
|
105
|
+
# Ruby 1.9 raises a RuntimeError instead of a TypeError.
|
106
|
+
assert_raise TypeError, RuntimeError do
|
107
|
+
RE2::GlobalReplace(frozen_name, "o", "a")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
91
111
|
def test_compiling
|
92
112
|
r = RE2::Regexp.new("woo")
|
93
113
|
assert r.ok?
|
metadata
CHANGED
@@ -3,48 +3,49 @@ name: re2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
version: 0.1.
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
|
-
- Paul Mucur
|
12
|
+
- Paul Mucur
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-09-26 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake-compiler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
33
|
description: Ruby bindings to re2, "an efficient, principled regular expression library".
|
34
34
|
email: ruby.re2@librelist.com
|
35
35
|
executables: []
|
36
36
|
|
37
37
|
extensions:
|
38
|
-
- ext/re2/extconf.rb
|
38
|
+
- ext/re2/extconf.rb
|
39
39
|
extra_rdoc_files: []
|
40
40
|
|
41
41
|
files:
|
42
|
-
- ext/re2/extconf.rb
|
43
|
-
- ext/re2/re2.cc
|
44
|
-
- LICENSE.txt
|
45
|
-
- README.md
|
46
|
-
- Rakefile
|
47
|
-
- test/re2_test.rb
|
42
|
+
- ext/re2/extconf.rb
|
43
|
+
- ext/re2/re2.cc
|
44
|
+
- LICENSE.txt
|
45
|
+
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- test/re2_test.rb
|
48
|
+
- test/leak.rb
|
48
49
|
has_rdoc: true
|
49
50
|
homepage: http://github.com/mudge/re2
|
50
51
|
licenses: []
|
@@ -53,23 +54,23 @@ post_install_message:
|
|
53
54
|
rdoc_options: []
|
54
55
|
|
55
56
|
require_paths:
|
56
|
-
- lib
|
57
|
+
- lib
|
57
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
59
|
none: false
|
59
60
|
requirements:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
65
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
67
|
none: false
|
67
68
|
requirements:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
73
74
|
requirements: []
|
74
75
|
|
75
76
|
rubyforge_project:
|
@@ -78,4 +79,5 @@ signing_key:
|
|
78
79
|
specification_version: 3
|
79
80
|
summary: Ruby bindings to re2.
|
80
81
|
test_files:
|
81
|
-
- test/re2_test.rb
|
82
|
+
- test/re2_test.rb
|
83
|
+
- test/leak.rb
|