re2 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/Rakefile +4 -0
  2. data/ext/re2/re2.cc +42 -20
  3. data/test/leak.rb +32 -0
  4. data/test/re2_test.rb +20 -0
  5. 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
 
@@ -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
- rb_ary_store(array, i, Qnil);
148
+ rb_ary_push(array, Qnil);
145
149
  } else {
146
- rb_ary_store(array, i, rb_str_new2(m->matches[i].as_string().c_str()));
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 rb_str_new2(m->matches[nth].as_string().c_str());
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 = rb_str_new2("#<RE2::MatchData");
243
+ result = rb_str_new("#<RE2::MatchData", 16);
240
244
 
241
245
  for (i = 0; i < m->number_of_matches; i++) {
242
- rb_str_cat2(result, " ");
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
- rb_str_cat2(result, ":");
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
- rb_str_cat2(result, "nil");
258
+ rb_str_cat(result, "nil", 3);
255
259
  } else {
256
- rb_str_append(result, rb_str_inspect(match));
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
- rb_str_cat2(result, ">");
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 = rb_str_new2("#<RE2::Regexp /");
418
+ VALUE result = rb_str_new("#<RE2::Regexp /", 15);
413
419
 
414
420
  Data_Get_Struct(self, re2_pattern, p);
415
- rb_str_cat2(result, p->pattern->pattern().c_str());
416
- rb_str_cat2(result, "/>");
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 rb_str_new2(p->pattern->pattern().c_str());
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 rb_str_new2(p->pattern->error().c_str());
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 rb_str_new2(p->pattern->error_arg().c_str());
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
- OBJ_FREEZE(options);
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 = rb_str_dup_frozen(text);
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
- rb_str_update(str, 0, RSTRING_LEN(str), repl);
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
- rb_str_update(str, 0, RSTRING_LEN(str), repl);
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
- return rb_str_new2(RE2::QuoteMeta(unquoted_as_string_piece).c_str());
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
@@ -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
@@ -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
- - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
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-08-28 00:00:00 +01:00
17
+ date: 2010-09-26 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
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
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
- - !ruby/object:Gem::Version
62
- segments:
63
- - 0
64
- version: "0"
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
- - !ruby/object:Gem::Version
70
- segments:
71
- - 0
72
- version: "0"
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