44#include < filesystem>
55#include < fstream>
66#include < iomanip>
7+ #include < iostream>
78#include < sstream>
89#include < string>
910#include < utility>
1011
12+ #ifdef GNUPLOTPP_HAS_FMT
13+ #include < fmt/format.h>
14+ #endif
15+
16+ #ifdef GNUPLOTPP_HAS_SPDLOG
17+ #include < spdlog/spdlog.h>
18+ #endif
19+
1120namespace gnuplotpp {
1221namespace {
1322
1423std::string quote (const std::filesystem::path& p) {
1524 return " '" + p.string () + " '" ;
1625}
1726
27+ std::string msg_io (const std::string& prefix,
28+ const std::filesystem::path& path,
29+ const std::error_code& ec) {
30+ #ifdef GNUPLOTPP_HAS_FMT
31+ return fmt::format (" {} '{}': {}" , prefix, path.string (), ec.message ());
32+ #else
33+ std::ostringstream os;
34+ os << prefix << " '" << path.string () << " ': " << ec.message ();
35+ return os.str ();
36+ #endif
37+ }
38+
39+ std::string msg_text (const std::string& prefix, const std::string& detail) {
40+ #ifdef GNUPLOTPP_HAS_FMT
41+ return fmt::format (" {}: {}" , prefix, detail);
42+ #else
43+ return prefix + " : " + detail;
44+ #endif
45+ }
46+
47+ void log_info (const std::string& msg) {
48+ #ifdef GNUPLOTPP_HAS_SPDLOG
49+ spdlog::info (" {}" , msg);
50+ #else
51+ std::clog << " [gnuplotpp] info: " << msg << " \n " ;
52+ #endif
53+ }
54+
55+ void log_error (const std::string& msg) {
56+ #ifdef GNUPLOTPP_HAS_SPDLOG
57+ spdlog::error (" {}" , msg);
58+ #else
59+ std::cerr << " [gnuplotpp] error: " << msg << " \n " ;
60+ #endif
61+ }
62+
1863std::string extension_for (OutputFormat format) {
1964 switch (format) {
2065 case OutputFormat::Pdf:
@@ -166,12 +211,15 @@ GnuplotBackend::GnuplotBackend(std::string executable)
166211RenderResult GnuplotBackend::render (const Figure& fig,
167212 const std::filesystem::path& out_dir) {
168213 RenderResult result;
214+ result.status = RenderStatus::Success;
169215
170216 std::error_code ec;
171217 std::filesystem::create_directories (out_dir / " tmp" , ec);
172218 if (ec) {
173219 result.ok = false ;
174- result.message = " failed to create output directories: " + ec.message ();
220+ result.status = RenderStatus::IoError;
221+ result.message = msg_io (" failed to create output directories" , out_dir / " tmp" , ec);
222+ log_error (result.message );
175223 return result;
176224 }
177225
@@ -190,17 +238,38 @@ RenderResult GnuplotBackend::render(const Figure& fig,
190238
191239 const auto & series = axis.series ()[series_idx];
192240 std::ofstream data_os (data_path);
241+ if (!data_os.is_open ()) {
242+ result.ok = false ;
243+ result.status = RenderStatus::IoError;
244+ result.message = msg_text (" failed to open data file for writing" , data_path.string ());
245+ log_error (result.message );
246+ return result;
247+ }
193248 data_os << std::scientific << std::setprecision (16 );
194249 for (std::size_t i = 0 ; i < series.x .size (); ++i) {
195250 data_os << series.x [i] << " " << series.y [i] << " \n " ;
196251 }
252+ if (!data_os.good ()) {
253+ result.ok = false ;
254+ result.status = RenderStatus::IoError;
255+ result.message = msg_text (" failed while writing data file" , data_path.string ());
256+ log_error (result.message );
257+ return result;
258+ }
197259 }
198260 }
199261
200262 const auto script_path = out_dir / " tmp" / " figure.gp" ;
201263 result.script_path = script_path;
202264
203265 std::ofstream script_os (script_path);
266+ if (!script_os.is_open ()) {
267+ result.ok = false ;
268+ result.status = RenderStatus::IoError;
269+ result.message = msg_text (" failed to open gnuplot script for writing" , script_path.string ());
270+ log_error (result.message );
271+ return result;
272+ }
204273 script_os << " set encoding utf8\n " ;
205274
206275 for (const auto format : fig.spec ().formats ) {
@@ -212,23 +281,44 @@ RenderResult GnuplotBackend::render(const Figure& fig,
212281 emit_plot_body (script_os, fig, data_files);
213282 script_os << " set output\n " ;
214283 }
284+ if (!script_os.good ()) {
285+ result.ok = false ;
286+ result.status = RenderStatus::IoError;
287+ result.message = msg_text (" failed while writing gnuplot script" , script_path.string ());
288+ log_error (result.message );
289+ return result;
290+ }
215291
216292 const std::string check_cmd = " command -v " + executable_ + " >/dev/null 2>&1" ;
217293 if (std::system (check_cmd.c_str ()) != 0 ) {
218294 result.ok = false ;
219- result.message = " gnuplot executable not found; generated script/data only" ;
295+ result.status = RenderStatus::ExternalToolMissing;
296+ result.message = msg_text (" gnuplot executable not found; generated script/data only" ,
297+ executable_);
298+ log_error (result.message );
220299 return result;
221300 }
222301
223- const std::string render_cmd = executable_ + " " + script_path.string () + " >/tmp/gnuplotpp.log 2>&1" ;
224- if (std::system (render_cmd.c_str ()) != 0 ) {
302+ const std::string render_cmd =
303+ executable_ + " " + quote (script_path) + " >/tmp/gnuplotpp.log 2>&1" ;
304+ const int rc = std::system (render_cmd.c_str ());
305+ if (rc != 0 ) {
225306 result.ok = false ;
307+ result.status = RenderStatus::ExternalToolFailure;
308+ #ifdef GNUPLOTPP_HAS_FMT
309+ result.message =
310+ fmt::format (" gnuplot failed (exit={}); inspect /tmp/gnuplotpp.log" , rc);
311+ #else
226312 result.message = " gnuplot failed; inspect /tmp/gnuplotpp.log" ;
313+ #endif
314+ log_error (result.message );
227315 return result;
228316 }
229317
230318 result.ok = true ;
319+ result.status = RenderStatus::Success;
231320 result.message = " render completed" ;
321+ log_info (result.message );
232322 return result;
233323}
234324
0 commit comments