Skip to content

Commit

Permalink
Replaced regex with custom string parsing and a few more low hanging …
Browse files Browse the repository at this point in the history
…improvements
  • Loading branch information
mikucionisaau committed Oct 23, 2024
1 parent 24db6b8 commit 69591ea
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 65 deletions.
26 changes: 25 additions & 1 deletion source/matplot/backend/backend_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace matplot {
class MATPLOT_EXPORTS backend_interface {
/// Virtual functions you can override to create any backend
public:
virtual ~backend_interface() noexcept = default;
/// \brief True if backend is in interactive mode
/// One backends might support both interactive and
/// non-interactive mode.
Expand Down Expand Up @@ -213,7 +214,30 @@ namespace matplot {
/// This is useful when tracing the gnuplot commands
/// and when generating a gnuplot file.
virtual void include_comment(const std::string &text);
};
}; // backend_interface
/// Captures (backend) version information.
struct Version {
int major{}, minor{}, patch{};
constexpr bool operator==(const Version &o) const {
return major == o.major && minor == o.minor && patch == o.patch;
}
constexpr bool operator!=(const Version &other) const { return !(*this == other); }
constexpr bool operator<(const Version &other) const {
if (major < other.major)
return true;
else if (major == other.major) {
if (minor < other.minor)
return true;
else if (minor == other.minor)
return patch < other.patch;
}
return false;
}
constexpr bool operator>(const Version &other) const { return other < *this; }
constexpr bool operator<=(const Version &other) const { return !(other < *this); }
constexpr bool operator>=(const Version &other) const { return !(other > *this); }
constexpr operator bool() const { return *this != Version{0,0,0}; }
}; // struct Version
} // namespace backend

} // namespace matplot
Expand Down
75 changes: 32 additions & 43 deletions source/matplot/backend/gnuplot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <matplot/util/common.h>
#include <matplot/util/popen.h>
#include <iostream>
#include <regex>
#include <charconv>
#include <thread>
#include <cstring>
#include <cstdlib>
Expand Down Expand Up @@ -317,13 +317,28 @@ namespace matplot::backend {
}
}

/// returns the next word in text after prefix terminated with white space.
std::string_view word_after(std::string_view text, std::string_view prefix)
{
auto res = text.substr(0,0);
if (auto b = text.find(prefix); b != std::string_view::npos) {
b += prefix.length();
while (b < text.length() && std::isspace(text[b]))
++b; // skip white space before word
auto e = b;
while (e < text.length() && !std::isspace(text[e]))
++e; // scan until white space or end
res = text.substr(b, e-b);
}
return res;
}

std::string gnuplot::default_terminal_type() {
static std::string terminal_type;
const bool dont_know_term_type = terminal_type.empty();
if (dont_know_term_type) {
terminal_type = run_and_get_output("gnuplot -e \"show terminal\" 2>&1");
terminal_type = std::regex_replace(terminal_type,
std::regex("[^]*terminal type is ([^ ]+)[^]*"), "$1");
terminal_type = word_after(terminal_type, "terminal type is ");
const bool still_dont_know_term_type = terminal_type.empty();
if (still_dont_know_term_type) {
terminal_type = "qt";
Expand All @@ -334,51 +349,25 @@ namespace matplot::backend {

bool gnuplot::terminal_is_available(std::string_view term) {
std::string msg = run_and_get_output("gnuplot -e \"set terminal " +
std::string(term.data()) + "\" 2>&1");
std::string{term} + "\" 2>&1");
return msg.empty();
}

std::tuple<int, int, int> gnuplot::gnuplot_version() {
static std::tuple<int, int, int> version{0, 0, 0};
const bool dont_know_gnuplot_version_yet =
version == std::tuple<int, int, int>({0, 0, 0});
if (dont_know_gnuplot_version_yet) {
std::string version_str =
run_and_get_output("gnuplot --version 2>&1");
std::string version_major = std::regex_replace(
version_str,
std::regex("[^]*gnuplot (\\d+)\\.\\d+ patchlevel \\d+ *"),
"$1");
std::string version_minor = std::regex_replace(
version_str,
std::regex("[^]*gnuplot \\d+\\.(\\d+) patchlevel \\d+ *"),
"$1");
std::string version_patch = std::regex_replace(
version_str,
std::regex("[^]*gnuplot \\d+\\.\\d+ patchlevel (\\d+) *"),
"$1");
try {
std::get<0>(version) = std::stoi(version_major);
} catch (...) {
std::get<0>(version) = 0;
}
try {
std::get<1>(version) = std::stoi(version_minor);
} catch (...) {
std::get<1>(version) = 0;
}
try {
std::get<2>(version) = std::stoi(version_patch);
} catch (...) {
std::get<2>(version) = 0;
}
const bool still_dont_know_gnuplot_version =
version == std::tuple<int, int, int>({0, 0, 0});
if (still_dont_know_gnuplot_version) {
// assume it's 5.2.6 by convention
version = std::tuple<int, int, int>({5, 2, 6});
Version gnuplot::gnuplot_version() {
static auto version = Version{0, 0, 0};
if (!version) {
const auto version_str = run_and_get_output("gnuplot --version 2>&1");
const auto major = word_after(version_str, "gnuplot");
const auto minor = word_after(major, ".");
const auto patch = word_after(version_str, "patchlevel");
if (!major.empty() && !minor.empty() && !patch.empty()) {
std::from_chars(major.begin(), major.end(), version.major);
std::from_chars(minor.begin(), minor.end(), version.minor);
std::from_chars(patch.begin(), patch.end(), version.patch);
}
}
if (!version)
version = {5, 2, 6}; // assume by convention
return version;
}

Expand Down
2 changes: 1 addition & 1 deletion source/matplot/backend/gnuplot.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace matplot::backend {
/// Identify the default terminal type in the system
static std::string default_terminal_type();
static bool terminal_is_available(std::string_view);
static std::tuple<int, int, int> gnuplot_version();
static Version gnuplot_version();
static bool terminal_has_title_option(const std::string &t);
static bool terminal_has_size_option(const std::string &t);
static bool terminal_has_position_option(const std::string &t);
Expand Down
22 changes: 10 additions & 12 deletions source/matplot/core/axes_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ namespace matplot {
run_command("set polar");
}
auto set_or_unset_axis = [this](class axis_type &ax,
std::string axis_name,
const std::string &axis_name,
bool minor_ticks = false) {
// cb is the only axis we don't unset if tics are empty
// r-axis labels should still be handled even if axis is invisible since we use the grid
Expand Down Expand Up @@ -694,8 +694,7 @@ namespace matplot {
// Gnuplot version needs to be 5.2.6+ for keyentry
bool ok = true;
if (parent_->backend_->consumes_gnuplot_commands()) {
if (backend::gnuplot::gnuplot_version() <
std::tuple<int, int, int>{5, 2, 6}) {
if (backend::gnuplot::gnuplot_version() < backend::Version{5, 2, 6}) {
ok = false;
}
}
Expand Down Expand Up @@ -916,9 +915,8 @@ namespace matplot {
static bool msg_shown_once = false;
// Gnuplot version needs to be 5.2.6+ for keyentry
if (parent_->backend_->consumes_gnuplot_commands()) {
std::tuple<int, int, int> v =
backend::gnuplot::gnuplot_version();
if (v < std::tuple<int, int, int>{5, 2, 6}) {
const auto v = backend::gnuplot::gnuplot_version();
if (v < backend::Version{5, 2, 6}) {
if (!msg_shown_once) {
std::cerr
<< "You need gnuplot 5.2.6+ to include legends"
Expand Down Expand Up @@ -2745,9 +2743,9 @@ namespace matplot {
}

std::vector<function_line_handle>
axes_type::fplot(std::vector<function_line::function_type> equations,
std::array<double, 2> x_range,
std::vector<std::string> line_specs) {
axes_type::fplot(const std::vector<function_line::function_type> &equations,
const std::array<double, 2> &x_range,
const std::vector<std::string> &line_specs) {
axes_silencer temp_silencer_{this};
std::vector<function_line_handle> res;
auto it_line_specs = line_specs.begin();
Expand All @@ -2764,9 +2762,9 @@ namespace matplot {
}

std::vector<function_line_handle>
axes_type::fplot(std::vector<function_line::function_type> equations,
std::vector<double> x_range,
std::vector<std::string> line_specs) {
axes_type::fplot(const std::vector<function_line::function_type>& equations,
const std::vector<double>& x_range,
const std::vector<std::string>& line_specs) {
return this->fplot(equations, to_array<2>(x_range), line_specs);
}

Expand Down
12 changes: 6 additions & 6 deletions source/matplot/core/axes_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -979,15 +979,15 @@ namespace matplot {

/// Lambda function line plot - list of functions
std::vector<function_line_handle>
fplot(std::vector<function_line::function_type> equations,
std::array<double, 2> x_range = {-5, 5},
std::vector<std::string> line_specs = {});
fplot(const std::vector<function_line::function_type> &equations,
const std::array<double, 2> &x_range = {-5, 5},
const std::vector<std::string> &line_specs = {});

/// Lambda function line plot - list of functions and line specs
std::vector<function_line_handle>
fplot(std::vector<function_line::function_type> equations,
std::vector<double> x_range,
std::vector<std::string> line_specs = {});
fplot(const std::vector<function_line::function_type> &equations,
const std::vector<double> &x_range,
const std::vector<std::string> &line_specs = {});

using implicit_function_type = std::function<double(double, double)>;

Expand Down
3 changes: 1 addition & 2 deletions source/matplot/core/figure_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,7 @@ namespace matplot {
// In gnuplot 5.5 we have the wall function to set the axes color
// with a rectangle workaround, which does not work well for 3d.
static const auto v = backend::gnuplot::gnuplot_version();
const bool has_wall_option =
std::get<0>(v) > 5 || (std::get<0>(v) == 5 && std::get<1>(v) >= 5);
const bool has_wall_option = v >= backend::Version{5,5,0};
// So we only plot the default background if it's not 3d or version is
// higher than 5.5. Otherwise, gnuplot won't be able to set the axes
// colors.
Expand Down

0 comments on commit 69591ea

Please sign in to comment.