diff --git a/re2/re2.cc b/re2/re2.cc index f3f96aeb5..4e42f8b38 100644 --- a/re2/re2.cc +++ b/re2/re2.cc @@ -177,10 +177,10 @@ void RE2::Init(const StringPiece& pattern, const Options& options) { entire_regexp_ = NULL; suffix_regexp_ = NULL; prog_ = NULL; + num_captures_ = -1; rprog_ = NULL; error_ = empty_string; error_code_ = NoError; - num_captures_ = -1; named_groups_ = NULL; group_names_ = NULL; @@ -218,6 +218,11 @@ void RE2::Init(const StringPiece& pattern, const Options& options) { return; } + // We used to compute this lazily, but it's used during the + // typical control flow for a match call, so we now compute + // it eagerly, which avoids the overhead of std::once_flag. + num_captures_ = suffix_regexp_->NumCaptures(); + // Could delay this until the first match call that // cares about submatch information, but the one-pass // machine's memory gets cut from the DFA memory budget, @@ -301,16 +306,6 @@ int RE2::ReverseProgramFanout(std::map* histogram) const { return Fanout(prog, histogram); } -// Returns num_captures_, computing it if needed, or -1 if the -// regexp wasn't valid on construction. -int RE2::NumberOfCapturingGroups() const { - std::call_once(num_captures_once_, [](const RE2* re) { - if (re->suffix_regexp_ != NULL) - re->num_captures_ = re->suffix_regexp_->NumCaptures(); - }, this); - return num_captures_; -} - // Returns named_groups_, computing it if needed. const std::map& RE2::NamedCapturingGroups() const { std::call_once(named_groups_once_, [](const RE2* re) { diff --git a/re2/re2.h b/re2/re2.h index c93de5623..f846029d8 100644 --- a/re2/re2.h +++ b/re2/re2.h @@ -479,7 +479,7 @@ class RE2 { // Return the number of capturing subpatterns, or -1 if the // regexp wasn't valid on construction. The overall match ($0) // does not count: if the regexp is "(a)(b)", returns 2. - int NumberOfCapturingGroups() const; + int NumberOfCapturingGroups() const { return num_captures_; } // Return a map from names to capturing indices. // The map records the index of the leftmost group @@ -744,6 +744,7 @@ class RE2 { re2::Regexp* entire_regexp_; // parsed regular expression re2::Regexp* suffix_regexp_; // parsed regular expression, prefix removed re2::Prog* prog_; // compiled program for regexp + int num_captures_; // Number of capturing groups bool is_one_pass_; // can use prog_->SearchOnePass? mutable re2::Prog* rprog_; // reverse program for regexp @@ -751,7 +752,6 @@ class RE2 { // (or points to empty string) mutable ErrorCode error_code_; // Error code mutable string error_arg_; // Fragment of regexp showing error - mutable int num_captures_; // Number of capturing groups // Map from capture names to indices mutable const std::map* named_groups_; @@ -761,7 +761,6 @@ class RE2 { // Onces for lazy computations. mutable std::once_flag rprog_once_; - mutable std::once_flag num_captures_once_; mutable std::once_flag named_groups_once_; mutable std::once_flag group_names_once_;