ext/re2/re2.cc in re2-0.0.2 vs ext/re2/re2.cc in re2-0.0.3

- old
+ new

@@ -17,20 +17,20 @@ #if !defined(RSTRING_LEN) # define RSTRING_LEN(x) (RSTRING(x)->len) #endif - typedef struct _re2p { + struct re2_pattern { RE2 *pattern; - } re2_pattern; + }; VALUE re2_cRE2; /* Symbols used in RE2 options. */ static ID id_utf8, id_posix_syntax, id_longest_match, id_log_errors, - id_max_mem, id_literal, id_never_nl, id_case_sensitive, - id_perl_classes, id_word_boundary, id_one_line; + id_max_mem, id_literal, id_never_nl, id_case_sensitive, + id_perl_classes, id_word_boundary, id_one_line; void re2_free(re2_pattern* self) { if (self->pattern) { @@ -40,13 +40,12 @@ } static VALUE re2_allocate(VALUE klass) { - re2_pattern *p = (re2_pattern*)malloc(sizeof(re2_pattern)); - p->pattern = NULL; - return Data_Wrap_Struct(klass, 0, re2_free, p); + re2_pattern *p; + return Data_Make_Struct(klass, re2_pattern, 0, re2_free, p); } /* * call-seq: * RE2(pattern) -> re2 @@ -122,12 +121,16 @@ if (RTEST(options)) { if (TYPE(options) != T_HASH) { rb_raise(rb_eArgError, "options should be a hash"); } - re2_options = new RE2::Options(); + re2_options = new (std::nothrow) RE2::Options(); + if (re2_options == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate RE2::Options"); + } + utf8 = rb_hash_aref(options, ID2SYM(id_utf8)); if (!NIL_P(utf8)) { re2_options->set_utf8(RTEST(utf8)); } @@ -179,15 +182,19 @@ one_line = rb_hash_aref(options, ID2SYM(id_one_line)); if (!NIL_P(one_line)) { re2_options->set_one_line(RTEST(one_line)); } - p->pattern = new RE2(StringValuePtr(pattern), *re2_options); + p->pattern = new (std::nothrow) RE2(StringValuePtr(pattern), *re2_options); } else { - p->pattern = new RE2(StringValuePtr(pattern)); + p->pattern = new (std::nothrow) RE2(StringValuePtr(pattern)); } + if (p->pattern == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object"); + } + return self; } /* * call-seq: @@ -200,11 +207,11 @@ * re2.inspect #=> "/woo?/" */ static VALUE re2_inspect(VALUE self) { - VALUE result = rb_str_buf_new(0); + VALUE result = rb_str_buf_new(2); re2_pattern *p; rb_str_buf_cat2(result, "/"); Data_Get_Struct(self, re2_pattern, p); rb_str_buf_cat2(result, p->pattern->pattern().c_str()); @@ -622,23 +629,38 @@ n = NUM2INT(number_of_matches); } else { n = p->pattern->NumberOfCapturingGroups(); } - text_as_string_piece = new re2::StringPiece(StringValuePtr(text)); + text_as_string_piece = new (std::nothrow) re2::StringPiece(StringValuePtr(text)); + if (text_as_string_piece == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate StringPiece for text"); + } + if (n == 0) { - return BOOL2RUBY(p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, 0, 0)); + matched = p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, 0, 0); + + delete text_as_string_piece; + + return BOOL2RUBY(matched); + } else { /* Because match returns the whole match as well. */ n += 1; - string_matches = new re2::StringPiece[n]; + string_matches = new (std::nothrow) re2::StringPiece[n]; + if (string_matches == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of StringPieces for matches"); + } + matched = p->pattern->Match(*text_as_string_piece, 0, RE2::UNANCHORED, string_matches, n); + delete text_as_string_piece; + if (matched) { matches = rb_ary_new(); for (int i = 0; i < n; i++) { if (!string_matches[i].empty()) { @@ -646,12 +668,17 @@ } else { rb_ary_push(matches, Qnil); } } + delete[] string_matches; + return matches; } else { + + delete[] string_matches; + return Qnil; } } } @@ -727,38 +754,63 @@ static VALUE re2_FullMatchN(VALUE self, VALUE text, VALUE re) { UNUSED(self); int n; - bool matched; + bool matched, re2_given; re2_pattern *p; VALUE matches; RE2 *compiled_pattern; RE2::Arg *argv; const RE2::Arg **args; std::string *string_matches; - if (rb_obj_is_kind_of(re, re2_cRE2)) { + re2_given = rb_obj_is_kind_of(re, re2_cRE2); + + if (re2_given) { Data_Get_Struct(re, re2_pattern, p); compiled_pattern = p->pattern; } else { - compiled_pattern = new RE2(StringValuePtr(re)); + compiled_pattern = new (std::nothrow) RE2(StringValuePtr(re)); + + if (compiled_pattern == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object for pattern"); + } } n = compiled_pattern->NumberOfCapturingGroups(); - argv = new RE2::Arg[n]; - args = new const RE2::Arg*[n]; - string_matches = new std::string[n]; + argv = new (std::nothrow) RE2::Arg[n]; + args = new (std::nothrow) const RE2::Arg*[n]; + string_matches = new (std::nothrow) std::string[n]; + if (argv == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of RE2::Args"); + } + + if (args == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of pointers to RE2::Args"); + } + + if (string_matches == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of strings for matches"); + } + for (int i = 0; i < n; i++) { args[i] = &argv[i]; argv[i] = &string_matches[i]; } matched = RE2::FullMatchN(StringValuePtr(text), *compiled_pattern, args, n); + if (!re2_given) { + delete compiled_pattern; + } + + delete[] argv; + delete[] args; + if (matched) { matches = rb_ary_new(); for (int i = 0; i < n; i++) { if (!string_matches[i].empty()) { @@ -766,12 +818,15 @@ } else { rb_ary_push(matches, Qnil); } } + delete[] string_matches; + return matches; } else { + delete[] string_matches; return Qnil; } } /* @@ -786,38 +841,63 @@ static VALUE re2_PartialMatchN(VALUE self, VALUE text, VALUE re) { UNUSED(self); int n; - bool matched; + bool matched, re2_given; re2_pattern *p; VALUE matches; RE2 *compiled_pattern; RE2::Arg *argv; const RE2::Arg **args; std::string *string_matches; - if (rb_obj_is_kind_of(re, re2_cRE2)) { + re2_given = rb_obj_is_kind_of(re, re2_cRE2); + + if (re2_given) { Data_Get_Struct(re, re2_pattern, p); compiled_pattern = p->pattern; } else { - compiled_pattern = new RE2(StringValuePtr(re)); + compiled_pattern = new (std::nothrow) RE2(StringValuePtr(re)); + + if (compiled_pattern == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate RE2 object for pattern"); + } } n = compiled_pattern->NumberOfCapturingGroups(); - argv = new RE2::Arg[n]; - args = new const RE2::Arg*[n]; - string_matches = new std::string[n]; + argv = new (std::nothrow) RE2::Arg[n]; + args = new (std::nothrow) const RE2::Arg*[n]; + string_matches = new (std::nothrow) std::string[n]; + if (argv == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of RE2::Args"); + } + + if (args == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of pointers to RE2::Args"); + } + + if (string_matches == 0) { + rb_raise(rb_eNoMemError, "not enough memory to allocate array of strings for matches"); + } + for (int i = 0; i < n; i++) { args[i] = &argv[i]; argv[i] = &string_matches[i]; } matched = RE2::PartialMatchN(StringValuePtr(text), *compiled_pattern, args, n); + if (!re2_given) { + delete compiled_pattern; + } + + delete[] argv; + delete[] args; + if (matched) { matches = rb_ary_new(); for (int i = 0; i < n; i++) { if (!string_matches[i].empty()) { @@ -825,11 +905,14 @@ } else { rb_ary_push(matches, Qnil); } } + delete[] string_matches; + return matches; } else { + delete[] string_matches; return Qnil; } } /*