[glom] C++11: Replace Glib::Regex with std::regex.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] C++11: Replace Glib::Regex with std::regex.
- Date: Tue, 1 Sep 2015 10:16:56 +0000 (UTC)
commit b9879fc9a42397c541b190dfc3a1e07b0051dca4
Author: Murray Cumming <murrayc murrayc com>
Date: Tue Sep 1 11:55:01 2015 +0200
C++11: Replace Glib::Regex with std::regex.
Annoyingly:
* the std::regex API can't just give us a vector of
matches.
* It lets us iterate through the matches, but not with a
range-based for loop.
* We have to iterate over sub-matches. I guess it could be useful
to know what top-level strings are being used.
* Iterating doesn't work normally because the first (0) sub match
is really the full parent match.
Makefile_tests.am | 6 +
glom/libglom/connectionpool_backends/mysql_self.cc | 1 -
.../connectionpool_backends/postgres_self.cc | 149 ++++++++++++--------
.../connectionpool_backends/postgres_self.h | 6 +
tests/import/test_parsing.cc | 15 +-
tests/test_postgres_version_regexes.cc | 52 +++++++
6 files changed, 162 insertions(+), 67 deletions(-)
---
diff --git a/Makefile_tests.am b/Makefile_tests.am
index f61b64d..94b1c17 100644
--- a/Makefile_tests.am
+++ b/Makefile_tests.am
@@ -27,6 +27,7 @@ check_PROGRAMS = \
tests/test_document_autosave \
tests/test_field_file_format \
tests/test_parsing_time \
+ tests/test_postgres_version_regexes \
tests/test_signal_reemit \
tests/python/test_load_python_library\
tests/python/test_python_module \
@@ -68,6 +69,7 @@ TESTS = tests/test_document_load \
tests/test_field_file_format \
tests/test_field_file_format_in_locales.sh \
tests/test_parsing_time \
+ tests/test_postgres_version_regexes \
tests/test_signal_reemit \
tests/test_dtd_file_validation.sh \
tests/test_glade_file_validation.sh \
@@ -184,6 +186,10 @@ tests_test_parsing_time_SOURCES = tests/test_parsing_time.cc
tests_test_parsing_time_LDADD = $(tests_ldadd)
tests_test_parsing_time_CPPFLAGS = $(tests_cppflags)
+tests_test_postgres_version_regexes_SOURCES = tests/test_postgres_version_regexes.cc
+tests_test_postgres_version_regexes_LDADD = $(tests_ldadd)
+tests_test_postgres_version_regexes_CPPFLAGS = $(tests_cppflags)
+
tests_test_signal_reemit_SOURCES = tests/test_signal_reemit.cc
tests_test_signal_reemit_LDADD = $(LIBGLOM_LIBS)
tests_test_signal_reemit_CPPFLAGS = $(tests_cppflags)
diff --git a/glom/libglom/connectionpool_backends/mysql_self.cc
b/glom/libglom/connectionpool_backends/mysql_self.cc
index c9ca163..c63c0e2 100644
--- a/glom/libglom/connectionpool_backends/mysql_self.cc
+++ b/glom/libglom/connectionpool_backends/mysql_self.cc
@@ -31,7 +31,6 @@
#include <glibmm/miscutils.h>
#include <glibmm/stringutils.h>
#include <glibmm/timer.h>
-#include <glibmm/regex.h>
#include <glibmm/main.h>
#include <glibmm/shell.h>
#include <glibmm/i18n.h>
diff --git a/glom/libglom/connectionpool_backends/postgres_self.cc
b/glom/libglom/connectionpool_backends/postgres_self.cc
index 9d13ba9..ec954c7 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.cc
+++ b/glom/libglom/connectionpool_backends/postgres_self.cc
@@ -29,13 +29,13 @@
#include <glibmm/convert.h>
#include <glibmm/miscutils.h>
#include <glibmm/stringutils.h>
-#include <glibmm/regex.h>
#include <glibmm/main.h>
#include <glibmm/shell.h>
#include <glibmm/i18n.h>
#include <sstream> //For stringstream
#include <iostream>
+#include <regex>
#ifdef G_OS_WIN32
# include <windows.h>
@@ -225,107 +225,140 @@ Backend::InitErrors PostgresSelfHosted::initialize(const SlotProgress& slot_prog
return result ? InitErrors::NONE : InitErrors::COULD_NOT_START_SERVER;
}
-Glib::ustring PostgresSelfHosted::get_postgresql_utils_version(const SlotProgress& slot_progress)
+Glib::ustring PostgresSelfHosted::get_postgresql_utils_version_from_string(const std::string& version_output)
{
Glib::ustring result;
- const auto command = get_path_to_postgres_executable("pg_ctl") + " --version";
-
- //The first command does not return, but the second command can check whether it succeeded:
- std::string output;
- const auto spawn_result = Glom::Spawn::execute_command_line_and_wait(command, slot_progress, output);
- if(!spawn_result)
- {
- std::cerr << G_STRFUNC << ": Error while attempting to discover the pg_ctl version." << std::endl;
- return result;
- }
-
//Use a regex to get the version number:
- Glib::RefPtr<Glib::Regex> regex;
-
+ std::regex regex;
+
//We want the characters at the end:
- const gchar VERSION_REGEX[] = "pg_ctl \\(PostgreSQL\\) (.*)";
+ const gchar VERSION_REGEX[] = "pg_ctl \\(PostgreSQL\\) (\\S+)";
try
{
- regex = Glib::Regex::create(VERSION_REGEX);
+ regex = std::regex(VERSION_REGEX);
}
- catch(const Glib::Error& ex)
+ catch(const std::regex_error& ex)
{
- std::cerr << G_STRFUNC << ": Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": std::regex constructor() failed: " << ex.what() << std::endl;
return result;
}
- if(!regex)
- return result;
-
- typedef std::vector<Glib::ustring> type_vec_strings;
- const type_vec_strings vec = regex->split(output, Glib::REGEX_MATCH_NOTEMPTY);
- //std::cout << "DEBUG: output == " << output << std::endl;
- //std::cout << "DEBUG: vec.size() == " << vec.size() << std::endl;
-
// We get, for instance, "\n" and 8.4.1" and "\n".
- for(const auto& str : vec)
+ //TODO: Find a way to do a simple range-based for over the regex matches?
+ auto matches_begin =
+ std::sregex_iterator(version_output.begin(), version_output.end(), regex);
+ auto matches_end = std::sregex_iterator();
+
+ for(auto iter = matches_begin; iter != matches_end; ++iter)
{
- if(!str.empty())
- return str; //Found.
+ const auto match = *iter;
+
+ //We don't use a range-based for loop, so we can more easily
+ //skip the [0] match, which is the full (parent) match:
+ auto sub_matches_begin = match.cbegin();
+ ++sub_matches_begin; //Skip [0], which is the full (parent) match.
+ auto sub_matches_end = match.cend();
+ for(auto sub_iter = sub_matches_begin ; sub_iter != sub_matches_end; ++sub_iter)
+ {
+ const auto& sub = *sub_iter;
+ const auto str = sub.str();
+ //std::cout << "debug: str=" << str << std::endl;
+ if(!str.empty())
+ return str; //Found.
+ }
}
return result;
}
-float PostgresSelfHosted::get_postgresql_utils_version_as_number(const SlotProgress& slot_progress)
+Glib::ustring PostgresSelfHosted::get_postgresql_utils_version(const SlotProgress& slot_progress)
{
- float result = 0;
+ Glib::ustring result;
- const auto version_str = get_postgresql_utils_version(slot_progress);
+ const auto command = get_path_to_postgres_executable("pg_ctl") + " --version";
- Glib::RefPtr<Glib::Regex> regex;
+ //The first command does not return, but the second command can check whether it succeeded:
+ std::string output;
+ const auto spawn_result = Glom::Spawn::execute_command_line_and_wait(command, slot_progress, output);
+ if(!spawn_result)
+ {
+ std::cerr << G_STRFUNC << ": Error while attempting to discover the pg_ctl version." << std::endl;
+ return Glib::ustring();
+ }
+
+ return get_postgresql_utils_version_from_string(output);
+}
+
+float PostgresSelfHosted::get_postgresql_utils_version_as_number_from_string(const std::string& version_str)
+{
+ //std::cout << "debug: " << G_STRFUNC << ": " << version_str << std::endl;
+
+ float result = 0;
+
+ std::regex regex;
//We want the characters at the end:
- const gchar VERSION_REGEX[] = "^(\\d*)\\.(\\d*)";
+ const gchar VERSION_REGEX[] = "(\\d*)\\.(\\d*)";
try
{
- regex = Glib::Regex::create(VERSION_REGEX);
+ regex = std::regex(VERSION_REGEX);
}
- catch(const Glib::Error& ex)
+ catch(const std::regex_error& ex)
{
- std::cerr << G_STRFUNC << ": Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": std::regex constructor() failed: " << ex.what() << std::endl;
return result;
}
- if(!regex)
- return result;
-
- const auto vec = regex->split(version_str, Glib::REGEX_MATCH_NOTEMPTY);
- //std::cout << "DEBUG: str == " << version_str << std::endl;
- //std::cout << "DEBUG: vec.size() == " << vec.size() << std::endl;
-
//We need to loop over the numbers because we get some "" items that we want to ignore:
guint count = 0; //We want 2 numbers.
- for(const auto& str : vec)
- {
- //std::cout << "regex item: START" << *iter << "END" << std::endl;
- if(str.empty())
- continue;
+ auto matches_begin =
+ std::sregex_iterator(version_str.begin(), version_str.end(), regex);
+ auto matches_end = std::sregex_iterator();
- const auto num = atoi(str.c_str());
- if(count == 0)
- result = num;
- else if(count == 1)
+ for(auto iter = matches_begin; iter != matches_end; ++iter)
+ {
+ const auto match = *iter;
+ //std::cout << "match: START" << match.str() << "END" << std::endl;
+
+ //We don't use a range-based for loop, so we can more easily
+ //skip the [0] match, which is the full (parent) match:
+ auto sub_matches_begin = match.cbegin();
+ ++sub_matches_begin; //Skip [0], which is the full (parent) match.
+ auto sub_matches_end = match.cend();
+ for(auto sub_iter = sub_matches_begin ; sub_iter != sub_matches_end; ++sub_iter)
{
- result += (0.1 * num);
- break;
- }
+ const auto& sub = *sub_iter;
+ const auto str = sub.str();
+ if(str.empty())
+ continue;
+
+ const auto num = atoi(str.c_str());
+ if(count == 0)
+ result = num;
+ else if(count == 1)
+ {
+ result += (0.1 * num);
+ return result;
+ }
- ++count;
+ ++count;
+ }
}
return result;
}
+float PostgresSelfHosted::get_postgresql_utils_version_as_number(const SlotProgress& slot_progress)
+{
+ const std::string version_str = get_postgresql_utils_version(slot_progress);
+
+ return get_postgresql_utils_version_as_number_from_string(version_str);
+}
+
Backend::StartupErrors PostgresSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
{
diff --git a/glom/libglom/connectionpool_backends/postgres_self.h
b/glom/libglom/connectionpool_backends/postgres_self.h
index 1bd09f4..608e7ff 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.h
+++ b/glom/libglom/connectionpool_backends/postgres_self.h
@@ -54,6 +54,12 @@ public:
*/
static bool install_postgres(const SlotProgress& slot_progress);
+ ///This is public so it can be tested:
+ static Glib::ustring get_postgresql_utils_version_from_string(const std::string& version_output);
+
+ ///This is public so it can be tested:
+ static float get_postgresql_utils_version_as_number_from_string(const std::string& version_str);
+
private:
virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username,
const Glib::ustring& password, bool network_shared = false);
diff --git a/tests/import/test_parsing.cc b/tests/import/test_parsing.cc
index 16f5edb..755c949 100644
--- a/tests/import/test_parsing.cc
+++ b/tests/import/test_parsing.cc
@@ -1,13 +1,12 @@
#include <glom/import_csv/csv_parser.h>
#include <tests/import/utils.h>
-//#include <glibmm/regex.h>
#include <giomm/file.h>
#include <glibmm/convert.h>
#include <glibmm/miscutils.h>
-#include <glibmm/regex.h>
#include <glibmm/init.h>
#include <giomm/init.h>
#include <iostream>
+#include <regex>
#include <cstdlib>
namespace
@@ -51,26 +50,26 @@ void print_tokens()
// Check that a string (or regex) exists in the parsed tokens.
bool check_tokens(const std::string& regex)
{
- Glib::RefPtr<Glib::Regex> check;
+ std::regex check;
try
{
- check = Glib::Regex::create(regex);
+ check = std::regex(regex);
}
- catch(const Glib::Error& ex)
+ catch(const std::regex_error& ex)
{
- std::cerr << G_STRFUNC << ": Glib::Regex::create() failed: " << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": std::regex constructor failed: " << ex.what() << std::endl;
return false;
}
- if(!check && 0 == get_tokens_instance().size())
+ if(get_tokens_instance().empty())
return false;
for(type_tokens::const_iterator iter = get_tokens_instance().begin();
iter != get_tokens_instance().end();
++iter)
{
- if(check->match(*iter))
+ if(std::regex_match(*iter, check))
return true;
}
diff --git a/tests/test_postgres_version_regexes.cc b/tests/test_postgres_version_regexes.cc
new file mode 100644
index 0000000..96232b6
--- /dev/null
+++ b/tests/test_postgres_version_regexes.cc
@@ -0,0 +1,52 @@
+/* Glom
+ *
+ * Copyright (C) 2015 Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <glom/libglom/init.h>
+#include <glom/libglom/connectionpool_backends/postgres_self.h>
+#include <iostream>
+
+static bool test_postgres_utils_version()
+{
+ const auto str =
Glom::ConnectionPoolBackends::PostgresSelfHosted::get_postgresql_utils_version_from_string("pg_ctl
(PostgreSQL) 9.4.4");
+ //std::cout << "debug: str: " << str << std::endl;
+ return str == "9.4.4";
+}
+
+static bool test_postgres_utils_version_as_number()
+{
+ const auto number =
Glom::ConnectionPoolBackends::PostgresSelfHosted::get_postgresql_utils_version_as_number_from_string("pg_ctl
(PostgreSQL) 9.4.4");
+ //std::cout << "debug: number: " << number << std::endl;
+ return number == 9.4f;
+}
+
+int main()
+{
+ Glom::libglom_init();
+
+ if(! test_postgres_utils_version())
+ return EXIT_FAILURE;
+
+ if(!test_postgres_utils_version_as_number())
+ return EXIT_FAILURE;
+
+ Glom::libglom_deinit();
+
+ return EXIT_SUCCESS;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]