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.
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