benchmark/src/re.h
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef BENCHMARK_RE_H_
16 #define BENCHMARK_RE_H_
17 
18 #include "internal_macros.h"
19 
20 // clang-format off
21 
22 #if !defined(HAVE_STD_REGEX) && \
23  !defined(HAVE_GNU_POSIX_REGEX) && \
24  !defined(HAVE_POSIX_REGEX)
25  // No explicit regex selection; detect based on builtin hints.
26  #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE)
27  #define HAVE_POSIX_REGEX 1
28  #elif __cplusplus >= 199711L
29  #define HAVE_STD_REGEX 1
30  #endif
31 #endif
32 
33 // Prefer C regex libraries when compiling w/o exceptions so that we can
34 // correctly report errors.
35 #if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \
36  defined(BENCHMARK_HAVE_STD_REGEX) && \
37  (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))
38  #undef HAVE_STD_REGEX
39 #endif
40 
41 #if defined(HAVE_STD_REGEX)
42  #include <regex>
43 #elif defined(HAVE_GNU_POSIX_REGEX)
44  #include <gnuregex.h>
45 #elif defined(HAVE_POSIX_REGEX)
46  #include <regex.h>
47 #else
48 #error No regular expression backend was found!
49 #endif
50 
51 // clang-format on
52 
53 #include <string>
54 
55 #include "check.h"
56 
57 namespace benchmark {
58 
59 // A wrapper around the POSIX regular expression API that provides automatic
60 // cleanup
61 class Regex {
62  public:
63  Regex() : init_(false) {}
64 
65  ~Regex();
66 
67  // Compile a regular expression matcher from spec. Returns true on success.
68  //
69  // On failure (and if error is not nullptr), error is populated with a human
70  // readable error message if an error occurs.
71  bool Init(const std::string& spec, std::string* error);
72 
73  // Returns whether str matches the compiled regular expression.
74  bool Match(const std::string& str);
75 
76  private:
77  bool init_;
78 // Underlying regular expression object
79 #if defined(HAVE_STD_REGEX)
80  std::regex re_;
81 #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
82  regex_t re_;
83 #else
84 #error No regular expression backend implementation available
85 #endif
86 };
87 
88 #if defined(HAVE_STD_REGEX)
89 
90 inline bool Regex::Init(const std::string& spec, std::string* error) {
91 #ifdef BENCHMARK_HAS_NO_EXCEPTIONS
92  ((void)error); // suppress unused warning
93 #else
94  try {
95 #endif
96  re_ = std::regex(spec, std::regex_constants::extended);
97  init_ = true;
98 #ifndef BENCHMARK_HAS_NO_EXCEPTIONS
99 }
100 catch (const std::regex_error& e) {
101  if (error) {
102  *error = e.what();
103  }
104 }
105 #endif
106 return init_;
107 }
108 
109 inline Regex::~Regex() {}
110 
111 inline bool Regex::Match(const std::string& str) {
112  if (!init_) {
113  return false;
114  }
115  return std::regex_search(str, re_);
116 }
117 
118 #else
120  int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB);
121  if (ec != 0) {
122  if (error) {
123  size_t needed = regerror(ec, &re_, nullptr, 0);
124  char* errbuf = new char[needed];
125  regerror(ec, &re_, errbuf, needed);
126 
127  // regerror returns the number of bytes necessary to null terminate
128  // the string, so we move that when assigning to error.
129  BM_CHECK_NE(needed, 0);
130  error->assign(errbuf, needed - 1);
131 
132  delete[] errbuf;
133  }
134 
135  return false;
136  }
137 
138  init_ = true;
139  return true;
140 }
141 
142 inline Regex::~Regex() {
143  if (init_) {
144  regfree(&re_);
145  }
146 }
147 
148 inline bool Regex::Match(const std::string& str) {
149  if (!init_) {
150  return false;
151  }
152  return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0;
153 }
154 #endif
155 
156 } // end namespace benchmark
157 
158 #endif // BENCHMARK_RE_H_
xds_interop_client.str
str
Definition: xds_interop_client.py:487
check.h
benchmark
Definition: bm_alarm.cc:55
false
#define false
Definition: setup_once.h:323
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
run_interop_tests.spec
def spec
Definition: run_interop_tests.py:1394
BM_CHECK_NE
#define BM_CHECK_NE(a, b)
Definition: benchmark/src/check.h:69
benchmark::Regex::init_
bool init_
Definition: benchmark/src/re.h:77
internal_macros.h
benchmark::Regex::Init
bool Init(const std::string &spec, std::string *error)
Definition: benchmark/src/re.h:119
benchmark::Regex::Regex
Regex()
Definition: benchmark/src/re.h:63
benchmark::Regex
Definition: benchmark/src/re.h:61
benchmark::Regex::~Regex
~Regex()
Definition: benchmark/src/re.h:142
benchmark::Regex::Match
bool Match(const std::string &str)
Definition: benchmark/src/re.h:148


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:00