re2 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|