1
+ #define __STDC_WANT_LIB_EXT1__ 1
1
2
#include < matplot/util/popen.h>
2
3
#include < array>
3
4
#include < system_error>
5
+ #include < cstring> // strerror
4
6
5
7
#ifdef _WIN32
6
8
@@ -19,7 +21,7 @@ int common_pipe::open(const std::string& cmd, char mode)
19
21
20
22
// Create a pipe for the child process's input
21
23
if (!CreatePipe (&hChildStdinRd, &hChildStdinWr, &saAttr, 0 ))
22
- return error (GetLastError (), " CreatePipe" );
24
+ return report (GetLastError (), " CreatePipe" );
23
25
24
26
// Ensure the write handle to the pipe is not inherited by child
25
27
// processes
@@ -94,7 +96,7 @@ int common_pipe::open(const std::string& cmd, char mode)
94
96
int common_pipe::close (int *exit_code)
95
97
{
96
98
if (!opened ())
97
- return error (EINVAL, " common_pipe::close" );
99
+ return report (EINVAL, " common_pipe::close" );
98
100
// Close the pipe to process:
99
101
fclose (file_);
100
102
file_ = nullptr ;
@@ -130,9 +132,9 @@ int common_pipe::open(const std::string &cmd, char mode)
130
132
constexpr auto WRITE = 1u ;
131
133
int fd[2 ];
132
134
if (::pipe (fd) == -1 )
133
- return error (errno, " pipe" );
135
+ return report (errno, " pipe" );
134
136
if ((pid = ::fork ()) == -1 )
135
- return error (errno, " fork" );
137
+ return report (errno, " fork" );
136
138
137
139
if (pid == 0 ) { // child process
138
140
if (mode == ' r' ) {
@@ -160,7 +162,7 @@ int common_pipe::open(const std::string &cmd, char mode)
160
162
else
161
163
file_ = ::fdopen (fd[WRITE], " w" );
162
164
if (file_ == nullptr )
163
- return error (errno, " fdopen" );
165
+ return report (errno, " fdopen" );
164
166
return 0 ;
165
167
}
166
168
@@ -183,8 +185,15 @@ int common_pipe::close(int *exit_code)
183
185
184
186
#endif // POSIX implementation
185
187
186
- inline int common_pipe::error (int code, const std::string& what) const
188
+ inline int common_pipe::report (int code, const std::string& what)
187
189
{
190
+ #if defined(_MSC_VER)
191
+ const auto len = strerrorlen_s (code);
192
+ error_.assign (len, ' ' );
193
+ strerror_s (error_.c_str (), len+1 , code);
194
+ #else
195
+ error_ = std::strerror (code);
196
+ #endif
188
197
if (exceptions_)
189
198
throw std::system_error{code, std::generic_category (), what};
190
199
return code;
@@ -198,33 +207,33 @@ int opipe::write(std::string_view data)
198
207
{
199
208
constexpr auto CSIZE = sizeof (std::string_view::value_type);
200
209
if (!opened ())
201
- return error (EINVAL, " opipe::write" );
210
+ return report (EINVAL, " opipe::write" );
202
211
if (auto sz = std::fwrite (data.data (), CSIZE, data.length (), file_);
203
212
sz != data.size ()) {
204
213
if (auto err = std::ferror (file_); err != 0 )
205
- return error (EIO, " fwrite error" );
214
+ return report (EIO, " fwrite error" );
206
215
if (auto err = std::feof (file_); err != 0 )
207
- return error (EIO, " fwrite eof" );
216
+ return report (EIO, " fwrite eof" );
208
217
}
209
218
return 0 ;
210
219
}
211
220
212
221
int opipe::flush (std::string_view data)
213
222
{
214
223
if (!opened ())
215
- return error (EINVAL, " opipe::flush" );
224
+ return report (EINVAL, " opipe::flush" );
216
225
if (!data.empty ())
217
226
if (auto err = write (data); err != 0 )
218
- return error (err, " opipe::write" );
227
+ return report (err, " opipe::write" );
219
228
if (auto res = std::fflush (file_); res != 0 )
220
- return error (errno, " fflush" );
229
+ return report (errno, " fflush" );
221
230
return 0 ;
222
231
}
223
232
224
233
int ipipe::read (std::string &data)
225
234
{
226
235
if (!opened ())
227
- return error (EINVAL, " ipipe::read" );
236
+ return report (EINVAL, " ipipe::read" );
228
237
data.clear ();
229
238
auto buffer = std::array<char , 128 >{};
230
239
while (!std::feof (file_) && !std::ferror (file_)) {
@@ -234,7 +243,7 @@ int ipipe::read(std::string &data)
234
243
data.append (buffer.data (), count);
235
244
}
236
245
if (std::ferror (file_))
237
- return error (EIO, " fread" );
246
+ return report (EIO, " fread" );
238
247
return 0 ;
239
248
}
240
249
0 commit comments