Support C++11 <regex> as alternative to POSIX regex.h.
authorTeemu Murtola <teemu.murtola@gmail.com>
Sat, 29 Sep 2012 10:46:20 +0000 (13:46 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 4 Oct 2012 03:29:22 +0000 (05:29 +0200)
This allows using regex matching in selections also on Windows.

Change-Id: I0bb2ff3056dfa07779afeace1c02028bdfeb8707

CMakeLists.txt
src/config.h.cmakein
src/gromacs/utility/gmxregex.cpp

index 5001e79386fa1d8d41faa9f49d2550c20552acb9..8be8aadde792a7ecf41b93dbffd05104286d1156 100644 (file)
@@ -339,14 +339,18 @@ endif(GMX_OPENMM)
 # Basic system tests (standard libraries, headers, functions, types)   #
 ########################################################################
 include(CheckIncludeFiles)
+include(CheckIncludeFileCXX)
 check_include_files(unistd.h    HAVE_UNISTD_H)
 check_include_files(pwd.h        HAVE_PWD_H)
 check_include_files(pthread.h    HAVE_PTHREAD_H)
 check_include_files(dirent.h     HAVE_DIRENT_H)
-check_include_files(regex.h      HAVE_REGEX_H)
 check_include_files(sys/time.h   HAVE_SYS_TIME_H)
 check_include_files(io.h                HAVE_IO_H)
 
+check_include_files(regex.h      HAVE_POSIX_REGEX)
+check_include_file_cxx(regex     HAVE_CXX11_REGEX)
+# TODO: It could be nice to inform the user if no regex support is found,
+# as selections won't be fully functional.
 
 include(CheckFunctionExists)
 check_function_exists(strdup            HAVE_STRDUP)
index 17ea8393fd1135022cbad1bf83ae88565180d9b9..5458ee023cba93f916d972c6aaf550ed6168614d 100644 (file)
 /* Define to 1 if yo have the <dirent.h> header file. */
 #cmakedefine HAVE_DIRENT_H
 
-/* Define to 1 if yo have the <regex.h> header file. */
-#cmakedefine HAVE_REGEX_H
-
 /* Define to 1 if you have the <sys/time.h> header file. */
 #cmakedefine HAVE_SYS_TIME_H
 
 /* Define for sched.h (this is for thread_mpi)*/
 #define HAVE_SCHED_H
 
+/* Define to 1 if you have the POSIX <regex.h> header file. */
+#cmakedefine HAVE_POSIX_REGEX
+
+/* Define to 1 if you have the C++11 <regex> header file. */
+#cmakedefine HAVE_CXX11_REGEX
+
 /* Bytes in IEEE fp word are in big-endian order if set, little-endian if not.
    Only relevant when FLOAT_FORMAT_IEEE754 is defined. */
 #cmakedefine GMX_IEEE754_BIG_ENDIAN_BYTE_ORDER
index 2bd6cfc5f1480e54f3b68c84351695ba78a715a0..92c8ca6d8ae3f0fbe9655bee379eeed04dbdc44b 100644 (file)
 #include "config.h"
 #endif
 
-#if defined(HAVE_REGEX_H)
+#if defined(HAVE_POSIX_REGEX)
 // old Mac needs sys/types.h before regex.h
 #include <sys/types.h>
 #include <regex.h>
 #define USE_POSIX_REGEX
+#elif defined(HAVE_CXX11_REGEX)
+#include <regex>
+#define USE_CXX11_REGEX
 #endif
 
 #include "exceptions.h"
@@ -57,7 +60,7 @@ namespace gmx
 // static
 bool Regex::isSupported()
 {
-#if defined(USE_POSIX_REGEX)
+#if defined(USE_POSIX_REGEX) || defined(USE_CXX11_REGEX)
     return true;
 #else
     return false;
@@ -106,6 +109,47 @@ class Regex::Impl
 
         regex_t                 regex_;
 };
+#elif defined(USE_CXX11_REGEX)
+class Regex::Impl
+{
+    public:
+        explicit Impl(const char *value)
+        try : regex_(value, std::regex::nosubs | std::regex::extended)
+        {
+        }
+        catch (const std::regex_error &)
+        {
+            // TODO: Better error messages.
+            GMX_THROW(InvalidInputError(formatString(
+                            "Error in regular expression \"%s\"", value)));
+        }
+        explicit Impl(const std::string &value)
+        try : regex_(value, std::regex::nosubs | std::regex::extended)
+        {
+        }
+        catch (const std::regex_error &)
+        {
+            // TODO: Better error messages.
+            GMX_THROW(InvalidInputError(formatString(
+                            "Error in regular expression \"%s\"", value)));
+        }
+
+        bool match(const char *value) const
+        {
+            try
+            {
+                return std::regex_match(value, regex_);
+            }
+            catch (const std::regex_error &)
+            {
+                // TODO: Handle errors.
+                return false;
+            }
+        }
+
+    private:
+        std::regex              regex_;
+};
 #else
 class Regex::Impl
 {