1 // Copyright 2015 Google Inc. All rights reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef BENCHMARK_RE_H_
16 #define BENCHMARK_RE_H_
18 #include "internal_macros.h"
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
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))
41 #if defined(HAVE_STD_REGEX)
43 #elif defined(HAVE_GNU_POSIX_REGEX)
45 #elif defined(HAVE_POSIX_REGEX)
48 #error No regular expression backend was found!
59 // A wrapper around the POSIX regular expression API that provides automatic
63 Regex() : init_(false) {}
67 // Compile a regular expression matcher from spec. Returns true on success.
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
);
73 // Returns whether str matches the compiled regular expression.
74 bool Match(const std::string
& str
);
78 // Underlying regular expression object
79 #if defined(HAVE_STD_REGEX)
81 #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
84 #error No regular expression backend implementation available
88 #if defined(HAVE_STD_REGEX)
90 inline bool Regex::Init(const std::string
& spec
, std::string
* error
) {
91 #ifdef BENCHMARK_HAS_NO_EXCEPTIONS
92 ((void)error
); // suppress unused warning
96 re_
= std::regex(spec
, std::regex_constants::extended
);
98 #ifndef BENCHMARK_HAS_NO_EXCEPTIONS
100 catch (const std::regex_error
& e
) {
109 inline Regex::~Regex() {}
111 inline bool Regex::Match(const std::string
& str
) {
115 return std::regex_search(str
, re_
);
119 inline bool Regex::Init(const std::string
& spec
, std::string
* error
) {
120 int ec
= regcomp(&re_
, spec
.c_str(), REG_EXTENDED
| REG_NOSUB
);
123 size_t needed
= regerror(ec
, &re_
, nullptr, 0);
124 char* errbuf
= new char[needed
];
125 regerror(ec
, &re_
, errbuf
, needed
);
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);
142 inline Regex::~Regex() {
148 inline bool Regex::Match(const std::string
& str
) {
152 return regexec(&re_
, str
.c_str(), 0, nullptr, 0) == 0;
156 } // end namespace benchmark
158 #endif // BENCHMARK_RE_H_