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"
20 #if !defined(HAVE_STD_REGEX) && \
21 !defined(HAVE_GNU_POSIX_REGEX) && \
22 !defined(HAVE_POSIX_REGEX)
23 // No explicit regex selection; detect based on builtin hints.
24 #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE)
25 #define HAVE_POSIX_REGEX 1
26 #elif __cplusplus >= 199711L
27 #define HAVE_STD_REGEX 1
31 // Prefer C regex libraries when compiling w/o exceptions so that we can
32 // correctly report errors.
33 #if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \
34 defined(BENCHMARK_HAVE_STD_REGEX) && \
35 (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))
39 #if defined(HAVE_STD_REGEX)
41 #elif defined(HAVE_GNU_POSIX_REGEX)
43 #elif defined(HAVE_POSIX_REGEX)
46 #error No regular expression backend was found!
54 // A wrapper around the POSIX regular expression API that provides automatic
58 Regex() : init_(false) {}
62 // Compile a regular expression matcher from spec. Returns true on success.
64 // On failure (and if error is not nullptr), error is populated with a human
65 // readable error message if an error occurs.
66 bool Init(const std::string
& spec
, std::string
* error
);
68 // Returns whether str matches the compiled regular expression.
69 bool Match(const std::string
& str
);
73 // Underlying regular expression object
74 #if defined(HAVE_STD_REGEX)
76 #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
79 #error No regular expression backend implementation available
83 #if defined(HAVE_STD_REGEX)
85 inline bool Regex::Init(const std::string
& spec
, std::string
* error
) {
86 #ifdef BENCHMARK_HAS_NO_EXCEPTIONS
87 ((void)error
); // suppress unused warning
91 re_
= std::regex(spec
, std::regex_constants::extended
);
93 #ifndef BENCHMARK_HAS_NO_EXCEPTIONS
94 } catch (const std::regex_error
& e
) {
103 inline Regex::~Regex() {}
105 inline bool Regex::Match(const std::string
& str
) {
109 return std::regex_search(str
, re_
);
113 inline bool Regex::Init(const std::string
& spec
, std::string
* error
) {
114 int ec
= regcomp(&re_
, spec
.c_str(), REG_EXTENDED
| REG_NOSUB
);
117 size_t needed
= regerror(ec
, &re_
, nullptr, 0);
118 char* errbuf
= new char[needed
];
119 regerror(ec
, &re_
, errbuf
, needed
);
121 // regerror returns the number of bytes necessary to null terminate
122 // the string, so we move that when assigning to error.
124 error
->assign(errbuf
, needed
- 1);
136 inline Regex::~Regex() {
142 inline bool Regex::Match(const std::string
& str
) {
146 return regexec(&re_
, str
.c_str(), 0, nullptr, 0) == 0;
150 } // end namespace benchmark
152 #endif // BENCHMARK_RE_H_