re2 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/ext/re2/re2.cc +109 -26
  2. data/test/re2_test.rb +36 -12
  3. metadata +4 -4
data/ext/re2/re2.cc CHANGED
@@ -19,16 +19,16 @@ extern "C" {
19
19
  # define RSTRING_LEN(x) (RSTRING(x)->len)
20
20
  #endif
21
21
 
22
- typedef struct _re2p {
22
+ struct re2_pattern {
23
23
  RE2 *pattern;
24
- } re2_pattern;
24
+ };
25
25
 
26
26
  VALUE re2_cRE2;
27
27
 
28
28
  /* Symbols used in RE2 options. */
29
29
  static ID id_utf8, id_posix_syntax, id_longest_match, id_log_errors,
30
- id_max_mem, id_literal, id_never_nl, id_case_sensitive,
31
- id_perl_classes, id_word_boundary, id_one_line;
30
+ id_max_mem, id_literal, id_never_nl, id_case_sensitive,
31
+ id_perl_classes, id_word_boundary, id_one_line;
32
32
 
33
33
  void
34
34
  re2_free(re2_pattern* self)
@@ -42,9 +42,8 @@ extern "C" {
42
42
  static VALUE
43
43
  re2_allocate(VALUE klass)
44
44
  {
45
- re2_pattern *p = (re2_pattern*)malloc(sizeof(re2_pattern));
46
- p->pattern = NULL;
47
- return Data_Wrap_Struct(klass, 0, re2_free, p);
45
+ re2_pattern *p;
46
+ return Data_Make_Struct(klass, re2_pattern, 0, re2_free, p);
48
47
  }
49
48
 
50
49
  /*
@@ -124,7 +123,11 @@ extern "C" {
124
123
  rb_raise(rb_eArgError, "options should be a hash");
125
124
  }
126
125
 
127
- re2_options = new RE2::Options();
126
+ re2_options = new (std::nothrow) RE2::Options();
127
+
128
+ if (re2_options == 0) {
129
+ rb_raise(rb_eNoMemError, "not enough memory to allocate RE2::Options");
130
+ }
128
131
 
129
132
  utf8 = rb_hash_aref(options, ID2SYM(id_utf8));
130
133
  if (!NIL_P(utf8)) {
@@ -181,9 +184,13 @@ extern "C" {
181
184
  re2_options->set_one_line(RTEST(one_line));
182
185
  }
183
186
 
184
- p->pattern = new RE2(StringValuePtr(pattern), *re2_options);
187
+ p->pattern = new (std::nothrow) RE2(StringValuePtr(pattern), *re2_options);
185
188
  } else {
186
- p->pattern = new RE2(StringValuePtr(pattern));
189
+ p->pattern = new (std::nothrow) RE2(StringValuePtr(pattern));
190
+ }
191
+
192
+ if (p->pattern == 0) {
193
+ rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object");
187
194
  }
188
195
 
189
196
  return self;
@@ -202,7 +209,7 @@ extern "C" {
202
209
  static VALUE
203
210
  re2_inspect(VALUE self)
204
211
  {
205
- VALUE result = rb_str_buf_new(0);
212
+ VALUE result = rb_str_buf_new(2);
206
213
  re2_pattern *p;
207
214
 
208
215
  rb_str_buf_cat2(result, "/");
@@ -624,19 +631,34 @@ extern "C" {
624
631
  n = p->pattern->NumberOfCapturingGroups();
625
632
  }
626
633
 
627
- text_as_string_piece = new re2::StringPiece(StringValuePtr(text));
634
+ text_as_string_piece = new (std::nothrow) re2::StringPiece(StringValuePtr(text));
635
+
636
+ if (text_as_string_piece == 0) {
637
+ rb_raise(rb_eNoMemError, "not enough memory to allocate StringPiece for text");
638
+ }
628
639
 
629
640
  if (n == 0) {
630
- return BOOL2RUBY(p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, 0, 0));
641
+ matched = p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, 0, 0);
642
+
643
+ delete text_as_string_piece;
644
+
645
+ return BOOL2RUBY(matched);
646
+
631
647
  } else {
632
648
 
633
649
  /* Because match returns the whole match as well. */
634
650
  n += 1;
635
651
 
636
- string_matches = new re2::StringPiece[n];
652
+ string_matches = new (std::nothrow) re2::StringPiece[n];
653
+
654
+ if (string_matches == 0) {
655
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of StringPieces for matches");
656
+ }
637
657
 
638
658
  matched = p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, string_matches, n);
639
659
 
660
+ delete text_as_string_piece;
661
+
640
662
  if (matched) {
641
663
  matches = rb_ary_new();
642
664
 
@@ -648,8 +670,13 @@ extern "C" {
648
670
  }
649
671
  }
650
672
 
673
+ delete[] string_matches;
674
+
651
675
  return matches;
652
676
  } else {
677
+
678
+ delete[] string_matches;
679
+
653
680
  return Qnil;
654
681
  }
655
682
  }
@@ -729,7 +756,7 @@ extern "C" {
729
756
  {
730
757
  UNUSED(self);
731
758
  int n;
732
- bool matched;
759
+ bool matched, re2_given;
733
760
  re2_pattern *p;
734
761
  VALUE matches;
735
762
  RE2 *compiled_pattern;
@@ -737,18 +764,36 @@ extern "C" {
737
764
  const RE2::Arg **args;
738
765
  std::string *string_matches;
739
766
 
740
- if (rb_obj_is_kind_of(re, re2_cRE2)) {
767
+ re2_given = rb_obj_is_kind_of(re, re2_cRE2);
768
+
769
+ if (re2_given) {
741
770
  Data_Get_Struct(re, re2_pattern, p);
742
771
  compiled_pattern = p->pattern;
743
772
  } else {
744
- compiled_pattern = new RE2(StringValuePtr(re));
773
+ compiled_pattern = new (std::nothrow) RE2(StringValuePtr(re));
774
+
775
+ if (compiled_pattern == 0) {
776
+ rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object for pattern");
777
+ }
745
778
  }
746
779
 
747
780
  n = compiled_pattern->NumberOfCapturingGroups();
748
781
 
749
- argv = new RE2::Arg[n];
750
- args = new const RE2::Arg*[n];
751
- string_matches = new std::string[n];
782
+ argv = new (std::nothrow) RE2::Arg[n];
783
+ args = new (std::nothrow) const RE2::Arg*[n];
784
+ string_matches = new (std::nothrow) std::string[n];
785
+
786
+ if (argv == 0) {
787
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of RE2::Args");
788
+ }
789
+
790
+ if (args == 0) {
791
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of pointers to RE2::Args");
792
+ }
793
+
794
+ if (string_matches == 0) {
795
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of strings for matches");
796
+ }
752
797
 
753
798
  for (int i = 0; i < n; i++) {
754
799
  args[i] = &argv[i];
@@ -757,6 +802,13 @@ extern "C" {
757
802
 
758
803
  matched = RE2::FullMatchN(StringValuePtr(text), *compiled_pattern, args, n);
759
804
 
805
+ if (!re2_given) {
806
+ delete compiled_pattern;
807
+ }
808
+
809
+ delete[] argv;
810
+ delete[] args;
811
+
760
812
  if (matched) {
761
813
  matches = rb_ary_new();
762
814
 
@@ -768,8 +820,11 @@ extern "C" {
768
820
  }
769
821
  }
770
822
 
823
+ delete[] string_matches;
824
+
771
825
  return matches;
772
826
  } else {
827
+ delete[] string_matches;
773
828
  return Qnil;
774
829
  }
775
830
  }
@@ -788,7 +843,7 @@ extern "C" {
788
843
  {
789
844
  UNUSED(self);
790
845
  int n;
791
- bool matched;
846
+ bool matched, re2_given;
792
847
  re2_pattern *p;
793
848
  VALUE matches;
794
849
  RE2 *compiled_pattern;
@@ -796,18 +851,36 @@ extern "C" {
796
851
  const RE2::Arg **args;
797
852
  std::string *string_matches;
798
853
 
799
- if (rb_obj_is_kind_of(re, re2_cRE2)) {
854
+ re2_given = rb_obj_is_kind_of(re, re2_cRE2);
855
+
856
+ if (re2_given) {
800
857
  Data_Get_Struct(re, re2_pattern, p);
801
858
  compiled_pattern = p->pattern;
802
859
  } else {
803
- compiled_pattern = new RE2(StringValuePtr(re));
860
+ compiled_pattern = new (std::nothrow) RE2(StringValuePtr(re));
861
+
862
+ if (compiled_pattern == 0) {
863
+ rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object for pattern");
864
+ }
804
865
  }
805
866
 
806
867
  n = compiled_pattern->NumberOfCapturingGroups();
807
868
 
808
- argv = new RE2::Arg[n];
809
- args = new const RE2::Arg*[n];
810
- string_matches = new std::string[n];
869
+ argv = new (std::nothrow) RE2::Arg[n];
870
+ args = new (std::nothrow) const RE2::Arg*[n];
871
+ string_matches = new (std::nothrow) std::string[n];
872
+
873
+ if (argv == 0) {
874
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of RE2::Args");
875
+ }
876
+
877
+ if (args == 0) {
878
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of pointers to RE2::Args");
879
+ }
880
+
881
+ if (string_matches == 0) {
882
+ rb_raise(rb_eNoMemError, "not enough memory to allocate array of strings for matches");
883
+ }
811
884
 
812
885
  for (int i = 0; i < n; i++) {
813
886
  args[i] = &argv[i];
@@ -816,6 +889,13 @@ extern "C" {
816
889
 
817
890
  matched = RE2::PartialMatchN(StringValuePtr(text), *compiled_pattern, args, n);
818
891
 
892
+ if (!re2_given) {
893
+ delete compiled_pattern;
894
+ }
895
+
896
+ delete[] argv;
897
+ delete[] args;
898
+
819
899
  if (matched) {
820
900
  matches = rb_ary_new();
821
901
 
@@ -827,8 +907,11 @@ extern "C" {
827
907
  }
828
908
  }
829
909
 
910
+ delete[] string_matches;
911
+
830
912
  return matches;
831
913
  } else {
914
+ delete[] string_matches;
832
915
  return Qnil;
833
916
  }
834
917
  }
data/test/re2_test.rb CHANGED
@@ -74,6 +74,18 @@ class RE2Test < Test::Unit::TestCase
74
74
  assert !RE2::FullMatch("woo", "wowzer")
75
75
  end
76
76
 
77
+ def test_full_match_with_compiled_pattern
78
+ r = RE2.new("woo")
79
+ assert RE2::FullMatch("woo", r)
80
+ assert !RE2::FullMatch("wowzer", r)
81
+
82
+ assert RE2::FullMatch("woo", RE2("woo"))
83
+ assert RE2::FullMatch("woo", RE2("wo+"))
84
+ assert RE2::FullMatch("woo", RE2("woo?"))
85
+ assert RE2::FullMatch("woo", RE2("wo{2}"))
86
+ assert !RE2::FullMatch("woo", RE2("wowzer"))
87
+ end
88
+
77
89
  def test_full_match_n
78
90
  assert_equal ["oo"], RE2::FullMatchN("woo", "w(oo)")
79
91
  assert_equal ["12"], RE2::FullMatchN("woo12w", 'woo(\d{2})w')
@@ -95,6 +107,17 @@ class RE2Test < Test::Unit::TestCase
95
107
  assert !RE2::PartialMatch("woo", "ha")
96
108
  end
97
109
 
110
+ def test_partial_match_with_compiled_pattern
111
+ r = RE2.new("woo")
112
+ assert RE2::PartialMatch("woo", r)
113
+ assert !RE2::PartialMatch("wowzer", r)
114
+
115
+ assert RE2::PartialMatch("woo", RE2("oo"))
116
+ assert RE2::PartialMatch("woo", RE2("oo?"))
117
+ assert RE2::PartialMatch("woo", RE2("o{2}"))
118
+ assert !RE2::PartialMatch("woo", RE2("ha"))
119
+ end
120
+
98
121
  def test_partial_match_n
99
122
  assert_equal ["oo"], RE2::PartialMatchN("awooa", "w(oo)")
100
123
  assert_equal ["12"], RE2::PartialMatchN("awoo12wa", 'woo(\d{2})w')
@@ -170,6 +193,9 @@ class RE2Test < Test::Unit::TestCase
170
193
  assert_equal ["woo", "o"], RE2.new('w(o)(o)').match('woo', 1)
171
194
  assert_equal ["woo", "o", "o"], RE2.new('w(o)(o)').match('woo', 2)
172
195
  assert_equal ["woo", "o", "o", nil], RE2.new('w(o)(o)').match('woo', 3)
196
+ assert_equal ["w", nil], RE2.new('w(o)?(o)?').match('w', 1)
197
+ assert_equal ["w", nil, nil], RE2.new('w(o)?(o)?').match('w', 2)
198
+ assert_equal ["w", nil, nil, nil], RE2.new('w(o)?(o)?').match('w', 3)
173
199
  end
174
200
 
175
201
  def test_compiling_with_options
@@ -185,26 +211,24 @@ class RE2Test < Test::Unit::TestCase
185
211
  assert r.options[:utf8]
186
212
  end
187
213
 
188
- def test_full_match_with_re2
189
- r = RE2.new("woo")
190
- assert RE2::FullMatch("woo", r)
191
- assert !RE2::FullMatch("wowzer", r)
192
- end
193
-
194
- def test_partial_match_with_re2
195
- r = RE2.new("woo")
196
- assert RE2::PartialMatch("woo", r)
197
- assert !RE2::PartialMatch("wowzer", r)
198
- end
199
-
200
214
  def test_replace_with_re2
201
215
  r = RE2.new("wo{2}")
202
216
  assert_equal "miaow", RE2::Replace("woo", r, "miaow")
217
+
218
+ assert_equal "wao", RE2::Replace("woo", RE2("o"), "a")
219
+ assert_equal "hoo", RE2::Replace("woo", RE2("w"), "h")
220
+ assert_equal "we", RE2::Replace("woo", RE2("o+"), "e")
221
+ assert_equal "Good morning", RE2::Replace("hi", RE2("hih?"), "Good morning")
222
+ assert_equal "hi", RE2::Replace("Good morning", RE2("gOOD MORNING", :case_sensitive => false), "hi")
203
223
  end
204
224
 
205
225
  def test_global_replace_with_re2
206
226
  r = RE2.new("o")
207
227
  assert_equal "wii", RE2::GlobalReplace("woo", r, "i")
228
+
229
+ assert_equal "waa", RE2::GlobalReplace("woo", RE2("o"), "a")
230
+ assert_equal "hoo", RE2::GlobalReplace("woo", RE2("w"), "h")
231
+ assert_equal "we", RE2::GlobalReplace("woo", RE2("o+"), "e")
208
232
  end
209
233
 
210
234
  def test_quote_meta
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: re2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Paul Mucur
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-28 00:00:00 +01:00
18
+ date: 2010-07-29 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency