From 1c82191d7a663c9fa9051fa575dda609b9637aac Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 31 Jul 2014 15:19:27 +0100 Subject: [PATCH 1/6] Consistent indentation in CMakeLists.txt --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4fa73aa..4db039cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,11 +11,11 @@ find_package(Threads REQUIRED) include(ExternalProject) set_directory_properties(properties EP_PREFIX "${CMAKE_BINARY_DIR}/third_party") ExternalProject_Add(googletest - URL "https://googletest.googlecode.com/files/gtest-1.7.0.zip" - URL_MD5 2d6ec8ccdf5c46b05ba54a9fd1d130d7 - SOURCE_DIR "${CMAKE_BINARY_DIR}/third_party/gtest" - CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" - INSTALL_COMMAND "") + URL "https://googletest.googlecode.com/files/gtest-1.7.0.zip" + URL_MD5 2d6ec8ccdf5c46b05ba54a9fd1d130d7 + SOURCE_DIR "${CMAKE_BINARY_DIR}/third_party/gtest" + CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + INSTALL_COMMAND "") ExternalProject_Get_Property(googletest source_dir) include_directories(${source_dir}/include) ExternalProject_Get_Property(googletest binary_dir) @@ -49,20 +49,20 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # Set OS if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - add_definitions(-DOS_MACOSX) + add_definitions(-DOS_MACOSX) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_definitions(-DOS_LINUX) + add_definitions(-DOS_LINUX) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - add_definitions(-DOS_WINDOWS) + add_definitions(-DOS_WINDOWS) endif() # Set CPU if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86") - add_definitions(-DARCH_X86) + add_definitions(-DARCH_X86) endif() # Read the git tags to determine the project version From fac16a662efb4ded79f74c795d81bdd688cb49a7 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 31 Jul 2014 15:19:54 +0100 Subject: [PATCH 2/6] CMakeLists.txt comments --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4db039cb..80650c59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project (benchmark) # Make sure we can import out CMake functions list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -# We need threads in this project +# Resolve dependent packages find_package(Threads REQUIRED) # Import and build Google Test diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2afb0cb..73992efe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,12 +1,15 @@ +# Define the source files set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc" "sleep.cc" "sysinfo.cc" "walltime.cc") set(RE_FILES "re.cc") +# Build a regular expression library add_library(benchmark_re ${RE_FILES}) set_target_properties(benchmark_re PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) +# Build the benchmark library add_library(benchmark ${SOURCE_FILES} ${RE_FILES}) set_target_properties(benchmark PROPERTIES VERSION ${GENERIC_LIB_VERSION} From edfa60a1d12ab746e088c216fafbfc4d7a6c50e6 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 31 Jul 2014 15:20:20 +0100 Subject: [PATCH 3/6] Resolve regular expression engines --- CMakeLists.txt | 6 ++++++ cmake/AddCXXCompilerFlag.cmake | 16 ++++++++-------- cmake/CXXFeatureCheck.cmake | 35 ++++++++++++++++++++++++++++++++++ cmake/gnu_posix_regex.cpp | 12 ++++++++++++ cmake/posix_regex.cpp | 12 ++++++++++++ cmake/std_regex.cpp | 8 ++++++++ 6 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 cmake/CXXFeatureCheck.cmake create mode 100644 cmake/gnu_posix_regex.cpp create mode 100644 cmake/posix_regex.cpp create mode 100644 cmake/std_regex.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 80650c59..340055ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,12 @@ message("-- Version: ${VERSION}") set(GENERIC_LIB_VERSION ${VERSION}) string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION) +# C++ feature checks +include(CXXFeatureCheck) +cxx_feature_check(STD_REGEX) +cxx_feature_check(GNU_POSIX_REGEX) +cxx_feature_check(POSIX_REGEX) + # Set up directories include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${PROJECT_SOURCE_DIR}/src) diff --git a/cmake/AddCXXCompilerFlag.cmake b/cmake/AddCXXCompilerFlag.cmake index d4a2de05..31a284fe 100644 --- a/cmake/AddCXXCompilerFlag.cmake +++ b/cmake/AddCXXCompilerFlag.cmake @@ -1,21 +1,21 @@ -# - Adds a compiler FLAG if it is supported by the compiler +# - Adds a compiler flag if it is supported by the compiler # -# This function checks that the supplied compiler FLAG is supported and then -# adds it to the corresponding compiler FLAGs +# This function checks that the supplied compiler flag is supported and then +# adds it to the corresponding compiler flags # -# add_cxx_compiler_FLAG( []) +# add_cxx_compiler_flag( []) # # - Example # # include(AddCXXCompilerFlag) -# add_cxx_compiler_FLAG(-Wall) -# add_cxx_compiler_FLAG(-no-strict-aliasing RELEASE) +# add_cxx_compiler_flag(-Wall) +# add_cxx_compiler_flag(-no-strict-aliasing RELEASE) # Requires CMake 2.6+ -if(__add_cxx_compiler_FLAG) +if(__add_cxx_compiler_flag) return() endif() -set(__add_cxx_compiler_FLAG INCLUDED) +set(__add_cxx_compiler_flag INCLUDED) include(CheckCXXCompilerFlag) diff --git a/cmake/CXXFeatureCheck.cmake b/cmake/CXXFeatureCheck.cmake new file mode 100644 index 00000000..9d809046 --- /dev/null +++ b/cmake/CXXFeatureCheck.cmake @@ -0,0 +1,35 @@ +# - Compile and run code to check for C++ features +# +# This functions compiles a source file under the `cmake` folder +# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake +# environment +# +# add_cxx_compiler_FLAG( []) +# +# - Example +# +# include(AddCXXCompilerFlag) +# add_cxx_compiler_FLAG(-Wall) +# add_cxx_compiler_FLAG(-no-strict-aliasing RELEASE) +# Requires CMake 2.6+ + +if(__cxx_feature_check_FLAG) + return() +endif() +set(__cxx_feature_check_FLAG INCLUDED) + +function(cxx_feature_check FILE) + string(TOLOWER ${FILE} FILE) + string(TOUPPER ${FILE} VAR) + string(TOUPPER "HAVE_${VAR}" FEATURE) + message("-- Performing Test ${FEATURE}") + try_run(RUN_${FEATURE} COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp) + if(RUN_${FEATURE} EQUAL 0) + message("-- Performing Test ${FEATURE} -- Success") + set(HAVE_${VAR} 1 PARENT_SCOPE) + add_definitions(-DHAVE_${VAR}) + else() + message("-- Performing Test ${FEATURE} -- Failed") + endif() +endfunction() + diff --git a/cmake/gnu_posix_regex.cpp b/cmake/gnu_posix_regex.cpp new file mode 100644 index 00000000..480ab25c --- /dev/null +++ b/cmake/gnu_posix_regex.cpp @@ -0,0 +1,12 @@ +#include +#include +int main() { + std::string str = "test0159"; + regex_t re; + int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB); + if (ec != 0) { + return ec; + } + return regexec(&re, str.c_str(), 0, NULL, 0) ? -1 : 0; +} + diff --git a/cmake/posix_regex.cpp b/cmake/posix_regex.cpp new file mode 100644 index 00000000..1f7fe07e --- /dev/null +++ b/cmake/posix_regex.cpp @@ -0,0 +1,12 @@ +#include +#include +int main() { + std::string str = "test0159"; + regex_t re; + int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB); + if (ec != 0) { + return ec; + } + return regexec(&re, str.c_str(), 0, NULL, 0) ? -1 : 0; +} + diff --git a/cmake/std_regex.cpp b/cmake/std_regex.cpp new file mode 100644 index 00000000..4f227d44 --- /dev/null +++ b/cmake/std_regex.cpp @@ -0,0 +1,8 @@ +#include +#include +int main() { + const std::string str = "test0159"; + const std::regex re("^[a-z]+[0-9]+$", std::regex_constants::extended | std::regex_constants::nosubs); + return std::regex_search(str, re) ? 0 : -1; +} + From f043826542d6a35909825bc89892bc3a4b4edf3e Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Wed, 30 Jul 2014 19:08:32 +0100 Subject: [PATCH 4/6] C++11 regular expressions --- src/CMakeLists.txt | 12 +++++++++- src/re.h | 14 ++++++++++-- src/{re.cc => re_posix.cc} | 0 src/re_std.cc | 45 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) rename src/{re.cc => re_posix.cc} (100%) create mode 100644 src/re_std.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73992efe..fd3bfc73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,16 @@ # Define the source files set(SOURCE_FILES "benchmark.cc" "colorprint.cc" "commandlineflags.cc" "sleep.cc" "sysinfo.cc" "walltime.cc") -set(RE_FILES "re.cc") + +# Determine the correct regular expression engine to use +if(HAVE_STD_REGEX) + set(RE_FILES "re_std.cc") +elseif(HAVE_GNU_POSIX_REGEX) + set(RE_FILES "re_posix.cc") +elseif(HAVE_POSIX_REGEX) + set(RE_FILES "re_posix.cc") +else() + message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") +endif() # Build a regular expression library add_library(benchmark_re ${RE_FILES}) diff --git a/src/re.h b/src/re.h index b179bb2a..a2e9fdfd 100644 --- a/src/re.h +++ b/src/re.h @@ -15,10 +15,14 @@ #ifndef BENCHMARK_RE_H_ #define BENCHMARK_RE_H_ -#if defined OS_FREEBSD +#if defined(HAVE_STD_REGEX) +#include +#elif defined(HAVE_GNU_POSIX_REGEX) #include -#else +#elif defined(HAVE_POSIX_REGEX) #include +#else +#error No regular expression backend was found! #endif #include @@ -42,7 +46,13 @@ class Regex { private: bool init_; // Underlying regular expression object +#if defined(HAVE_STD_REGEX) + std::regex re_; +#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX) regex_t re_; +#else +# error No regular expression backend implementation available +#endif }; } // end namespace benchmark diff --git a/src/re.cc b/src/re_posix.cc similarity index 100% rename from src/re.cc rename to src/re_posix.cc diff --git a/src/re_std.cc b/src/re_std.cc new file mode 100644 index 00000000..30883fda --- /dev/null +++ b/src/re_std.cc @@ -0,0 +1,45 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "re.h" + +namespace benchmark { + +Regex::Regex() : init_(false) { } + +bool Regex::Init(const std::string& spec, std::string* error) { + try { + re_ = std::regex(spec, std::regex_constants::extended); + + init_ = true; + } catch (const std::regex_error& e) { + if (error) { + *error = e.what(); + } + } + return init_; +} + +Regex::~Regex() { } + +bool Regex::Match(const std::string& str) { + if (!init_) { + return false; + } + + return std::regex_search(str, re_); +} + +} // end namespace benchmark From 0fd0be9789aa7fe9b60b66926f731663355bc791 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 31 Jul 2014 15:44:26 +0100 Subject: [PATCH 5/6] Added more complicated regex test patterns --- test/re_test.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/re_test.cc b/test/re_test.cc index c5ff9aa6..3bfac830 100644 --- a/test/re_test.cc +++ b/test/re_test.cc @@ -22,9 +22,49 @@ TEST(Regex, RegexSimple) { EXPECT_FALSE(re.Match("")); EXPECT_TRUE(re.Match("a")); EXPECT_TRUE(re.Match("aa")); + EXPECT_TRUE(re.Match("baa")); EXPECT_FALSE(re.Match("b")); } +TEST(Regex, RegexWildcard) { + benchmark::Regex re; + EXPECT_TRUE(re.Init("^a*$", NULL)); + + EXPECT_TRUE(re.Match("")); + EXPECT_TRUE(re.Match("a")); + EXPECT_TRUE(re.Match("aa")); + EXPECT_FALSE(re.Match("baa")); + EXPECT_FALSE(re.Match("b")); +} + +TEST(Regex, RegexAny) { + benchmark::Regex re; + EXPECT_TRUE(re.Init(".", NULL)); + + EXPECT_FALSE(re.Match("")); + EXPECT_TRUE(re.Match("a")); + EXPECT_TRUE(re.Match("aa")); +} + +TEST(Regex, RegexExact) { + benchmark::Regex re; + EXPECT_TRUE(re.Init("^.$", NULL)); + + EXPECT_FALSE(re.Match("")); + EXPECT_TRUE(re.Match("a")); + EXPECT_FALSE(re.Match("aa")); +} + +TEST(Regex, RegexComplicated) { + benchmark::Regex re; + EXPECT_TRUE(re.Init("([0-9]+ )?(mon|low)key(s)?", NULL)); + + EXPECT_TRUE(re.Match("something monkey hands")); + EXPECT_TRUE(re.Match("1 lowkey")); + EXPECT_TRUE(re.Match("19 monkeys")); + EXPECT_FALSE(re.Match("09 a")); +} + TEST(Regex, InvalidNoErrorMessage) { benchmark::Regex re; EXPECT_FALSE(re.Init("[", NULL)); From 9593e640763ad0cbd36d5c9104af5a389dd94cdb Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Fri, 22 Aug 2014 14:36:19 +0100 Subject: [PATCH 6/6] Fixed the CMake add_cxx_compiler_flag function --- cmake/AddCXXCompilerFlag.cmake | 9 ++++----- cmake/CXXFeatureCheck.cmake | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cmake/AddCXXCompilerFlag.cmake b/cmake/AddCXXCompilerFlag.cmake index 31a284fe..e52c1848 100644 --- a/cmake/AddCXXCompilerFlag.cmake +++ b/cmake/AddCXXCompilerFlag.cmake @@ -25,13 +25,12 @@ function(add_cxx_compiler_flag FLAG) string(TOLOWER ${VARIANT} VARIANT) set(VARIANT " ${VARIANT}") endif() - message("-- Check compiler${VARIANT} flag ${FLAG}") - string(TOUPPER ${FLAG} SANITIZED_FLAG) - string(REGEX REPLACE "[^A-Za-z_0-9]" "_" ${SANITIZED_FLAG} SANITIZED_FLAG) + string(TOUPPER "HAVE_${FLAG}" SANITIZED_FLAG) + string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) + string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) check_cxx_compiler_flag(${FLAG} ${SANITIZED_FLAG}) if(${SANITIZED_FLAG}) - message("-- Check compiler${VARIANT} flag ${FLAG} -- works") - string(REGEX REPLACE "[^A-Za-z_0-9]" "_" "${VARIANT}" VARIANT) + string(REGEX REPLACE "[^A-Za-z_0-9]" "_" VARIANT "${VARIANT}") string(TOUPPER "${VARIANT}" VARIANT) set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS}${VARIANT} ${FLAG}" PARENT_SCOPE) endif() diff --git a/cmake/CXXFeatureCheck.cmake b/cmake/CXXFeatureCheck.cmake index 9d809046..7adebcac 100644 --- a/cmake/CXXFeatureCheck.cmake +++ b/cmake/CXXFeatureCheck.cmake @@ -4,19 +4,18 @@ # and adds the corresponding `HAVE_[FILENAME]` flag to the CMake # environment # -# add_cxx_compiler_FLAG( []) +# cxx_feature_check( []) # # - Example # -# include(AddCXXCompilerFlag) -# add_cxx_compiler_FLAG(-Wall) -# add_cxx_compiler_FLAG(-no-strict-aliasing RELEASE) +# include(CXXFeatureCheck) +# cxx_feature_check(STD_REGEX) # Requires CMake 2.6+ -if(__cxx_feature_check_FLAG) +if(__cxx_feature_check) return() endif() -set(__cxx_feature_check_FLAG INCLUDED) +set(__cxx_feature_check INCLUDED) function(cxx_feature_check FILE) string(TOLOWER ${FILE} FILE)