brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · 9afb869 Raw
159 lines · c
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 at6//7//     http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// 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 and13// 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 off21 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 128  #elif __cplusplus >= 199711L29    #define HAVE_STD_REGEX 130  #endif31#endif32 33// Prefer C regex libraries when compiling w/o exceptions so that we can34// correctly report errors.35#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \36    defined(HAVE_STD_REGEX) && \37    (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))38  #undef HAVE_STD_REGEX39#endif40 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#else48#error No regular expression backend was found!49#endif50 51// clang-format on52 53#include <string>54 55#include "check.h"56 57namespace benchmark {58 59// A wrapper around the POSIX regular expression API that provides automatic60// cleanup61class 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 human70  // 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 object79#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#else84#error No regular expression backend implementation available85#endif86};87 88#if defined(HAVE_STD_REGEX)89 90inline bool Regex::Init(const std::string& spec, std::string* error) {91#ifdef BENCHMARK_HAS_NO_EXCEPTIONS92  ((void)error);  // suppress unused warning93#else94  try {95#endif96  re_ = std::regex(spec, std::regex_constants::extended);97  init_ = true;98#ifndef BENCHMARK_HAS_NO_EXCEPTIONS99}100catch (const std::regex_error& e) {101  if (error) {102    *error = e.what();103  }104}105#endif106return init_;107}108 109inline Regex::~Regex() {}110 111inline bool Regex::Match(const std::string& str) {112  if (!init_) {113    return false;114  }115  return std::regex_search(str, re_);116}117 118#else119inline bool Regex::Init(const std::string& spec, std::string* error) {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 terminate128      // 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 142inline Regex::~Regex() {143  if (init_) {144    regfree(&re_);145  }146}147 148inline 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#endif155 156}  // end namespace benchmark157 158#endif  // BENCHMARK_RE_H_159