[llvm-exegesis][NFC] Improve parsing of the YAML files
[llvm-core.git] / utils / benchmark / src / re.h
blob924d2f0ba7e5108eaeb3d3ac62070ad84ffc4716
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.
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
28 #endif
29 #endif
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))
36 #undef HAVE_STD_REGEX
37 #endif
39 #if defined(HAVE_STD_REGEX)
40 #include <regex>
41 #elif defined(HAVE_GNU_POSIX_REGEX)
42 #include <gnuregex.h>
43 #elif defined(HAVE_POSIX_REGEX)
44 #include <regex.h>
45 #else
46 #error No regular expression backend was found!
47 #endif
48 #include <string>
50 #include "check.h"
52 namespace benchmark {
54 // A wrapper around the POSIX regular expression API that provides automatic
55 // cleanup
56 class Regex {
57 public:
58 Regex() : init_(false) {}
60 ~Regex();
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);
71 private:
72 bool init_;
73 // Underlying regular expression object
74 #if defined(HAVE_STD_REGEX)
75 std::regex re_;
76 #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
77 regex_t re_;
78 #else
79 #error No regular expression backend implementation available
80 #endif
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
88 #else
89 try {
90 #endif
91 re_ = std::regex(spec, std::regex_constants::extended);
92 init_ = true;
93 #ifndef BENCHMARK_HAS_NO_EXCEPTIONS
94 } catch (const std::regex_error& e) {
95 if (error) {
96 *error = e.what();
99 #endif
100 return init_;
103 inline Regex::~Regex() {}
105 inline bool Regex::Match(const std::string& str) {
106 if (!init_) {
107 return false;
109 return std::regex_search(str, re_);
112 #else
113 inline bool Regex::Init(const std::string& spec, std::string* error) {
114 int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB);
115 if (ec != 0) {
116 if (error) {
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.
123 CHECK_NE(needed, 0);
124 error->assign(errbuf, needed - 1);
126 delete[] errbuf;
129 return false;
132 init_ = true;
133 return true;
136 inline Regex::~Regex() {
137 if (init_) {
138 regfree(&re_);
142 inline bool Regex::Match(const std::string& str) {
143 if (!init_) {
144 return false;
146 return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0;
148 #endif
150 } // end namespace benchmark
152 #endif // BENCHMARK_RE_H_