]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal |
2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling | |
3 | // Copyright (c) 2009 Boris Schaeling | |
4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling | |
5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling | |
6 | // | |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | ||
10 | ||
11 | #ifndef BOOST_PROCESS_PIPE_HPP | |
12 | #define BOOST_PROCESS_PIPE_HPP | |
13 | ||
14 | #include <boost/config.hpp> | |
15 | #include <boost/process/detail/config.hpp> | |
16 | #include <streambuf> | |
17 | #include <istream> | |
18 | #include <ostream> | |
19 | #include <vector> | |
20 | ||
21 | #if defined(BOOST_POSIX_API) | |
22 | #include <boost/process/detail/posix/basic_pipe.hpp> | |
23 | #elif defined(BOOST_WINDOWS_API) | |
24 | #include <boost/process/detail/windows/basic_pipe.hpp> | |
25 | #endif | |
26 | ||
27 | namespace boost { namespace process { | |
28 | ||
29 | using ::boost::process::detail::api::basic_pipe; | |
30 | ||
31 | #if defined(BOOST_PROCESS_DOXYGEN) | |
32 | /** Class implementation of a pipe. | |
33 | * | |
34 | */ | |
35 | template<class CharT, class Traits = std::char_traits<CharT>> | |
36 | class basic_pipe | |
37 | { | |
38 | public: | |
39 | typedef CharT char_type ; | |
40 | typedef Traits traits_type; | |
41 | typedef typename Traits::int_type int_type ; | |
42 | typedef typename Traits::pos_type pos_type ; | |
43 | typedef typename Traits::off_type off_type ; | |
44 | typedef ::boost::detail::winapi::HANDLE_ native_handle; | |
45 | ||
46 | /// Default construct the pipe. Will be opened. | |
47 | basic_pipe(); | |
48 | ||
49 | ///Construct a named pipe. | |
50 | inline explicit basic_pipe(const std::string & name); | |
51 | /** Copy construct the pipe. | |
52 | * \note Duplicated the handles. | |
53 | */ | |
54 | inline basic_pipe(const basic_pipe& p); | |
55 | /** Move construct the pipe. */ | |
56 | basic_pipe(basic_pipe&& lhs); | |
57 | /** Copy assign the pipe. | |
58 | * \note Duplicated the handles. | |
59 | */ | |
60 | inline basic_pipe& operator=(const basic_pipe& p); | |
61 | /** Move assign the pipe. */ | |
62 | basic_pipe& operator=(basic_pipe&& lhs); | |
63 | /** Destructor closes the handles. */ | |
64 | ~basic_pipe(); | |
65 | /** Get the native handle of the source. */ | |
66 | native_handle native_source() const; | |
67 | /** Get the native handle of the sink. */ | |
68 | native_handle native_sink () const; | |
69 | ||
70 | /** Assign a new value to the source */ | |
71 | void assign_source(native_handle h); | |
72 | /** Assign a new value to the sink */ | |
73 | void assign_sink (native_handle h); | |
74 | ||
75 | ||
76 | ///Write data to the pipe. | |
77 | int_type write(const char_type * data, int_type count); | |
78 | ///Read data from the pipe. | |
79 | int_type read(char_type * data, int_type count); | |
80 | ///Check if the pipe is open. | |
81 | bool is_open(); | |
82 | ///Close the pipe | |
83 | void close(); | |
84 | }; | |
85 | ||
86 | #endif | |
87 | ||
88 | ||
89 | ||
90 | typedef basic_pipe<char> pipe; | |
91 | typedef basic_pipe<wchar_t> wpipe; | |
92 | ||
93 | ||
94 | /** Implementation of the stream buffer for a pipe. | |
95 | */ | |
96 | template< | |
97 | class CharT, | |
98 | class Traits = std::char_traits<CharT> | |
99 | > | |
100 | struct basic_pipebuf : std::basic_streambuf<CharT, Traits> | |
101 | { | |
102 | typedef basic_pipe<CharT, Traits> pipe_type; | |
103 | ||
104 | typedef CharT char_type ; | |
105 | typedef Traits traits_type; | |
106 | typedef typename Traits::int_type int_type ; | |
107 | typedef typename Traits::pos_type pos_type ; | |
108 | typedef typename Traits::off_type off_type ; | |
109 | ||
110 | constexpr static int default_buffer_size = BOOST_PROCESS_PIPE_SIZE; | |
111 | ||
112 | ///Default constructor, will also construct the pipe. | |
113 | basic_pipebuf() : _write(default_buffer_size), _read(default_buffer_size) | |
114 | { | |
115 | this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); | |
116 | this->setp(_write.data(), _write.data() + _write.size()); | |
117 | } | |
118 | ///Copy Constructor. | |
119 | basic_pipebuf(const basic_pipebuf & ) = default; | |
120 | ///Move Constructor | |
121 | basic_pipebuf(basic_pipebuf && ) = default; | |
122 | ||
92f5a8d4 TL |
123 | ///Destructor -> writes the frest of the data |
124 | ~basic_pipebuf() | |
125 | { | |
20effc67 TL |
126 | if (basic_pipebuf::is_open()) |
127 | basic_pipebuf::overflow(Traits::eof()); | |
92f5a8d4 TL |
128 | } |
129 | ||
b32b8144 FG |
130 | ///Move construct from a pipe. |
131 | basic_pipebuf(pipe_type && p) : _pipe(std::move(p)), | |
132 | _write(default_buffer_size), | |
133 | _read(default_buffer_size) | |
134 | { | |
135 | this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); | |
136 | this->setp(_write.data(), _write.data() + _write.size()); | |
137 | } | |
138 | ///Construct from a pipe. | |
139 | basic_pipebuf(const pipe_type & p) : _pipe(p), | |
140 | _write(default_buffer_size), | |
141 | _read(default_buffer_size) | |
142 | { | |
143 | this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); | |
144 | this->setp(_write.data(), _write.data() + _write.size()); | |
145 | } | |
146 | ///Copy assign. | |
147 | basic_pipebuf& operator=(const basic_pipebuf & ) = delete; | |
148 | ///Move assign. | |
149 | basic_pipebuf& operator=(basic_pipebuf && ) = default; | |
150 | ///Move assign a pipe. | |
151 | basic_pipebuf& operator=(pipe_type && p) | |
152 | { | |
153 | _pipe = std::move(p); | |
154 | return *this; | |
155 | } | |
156 | ///Copy assign a pipe. | |
157 | basic_pipebuf& operator=(const pipe_type & p) | |
158 | { | |
159 | _pipe = p; | |
160 | return *this; | |
161 | } | |
162 | ///Writes characters to the associated output sequence from the put area | |
163 | int_type overflow(int_type ch = traits_type::eof()) override | |
164 | { | |
92f5a8d4 | 165 | if (_pipe.is_open() && (ch != traits_type::eof())) |
b32b8144 FG |
166 | { |
167 | if (this->pptr() == this->epptr()) | |
168 | { | |
169 | bool wr = this->_write_impl(); | |
b32b8144 | 170 | if (wr) |
20effc67 TL |
171 | { |
172 | *this->pptr() = ch; | |
173 | this->pbump(1); | |
b32b8144 | 174 | return ch; |
20effc67 | 175 | } |
b32b8144 FG |
176 | } |
177 | else | |
178 | { | |
179 | *this->pptr() = ch; | |
180 | this->pbump(1); | |
181 | if (this->_write_impl()) | |
182 | return ch; | |
183 | } | |
184 | } | |
92f5a8d4 TL |
185 | else if (ch == traits_type::eof()) |
186 | this->sync(); | |
187 | ||
b32b8144 FG |
188 | return traits_type::eof(); |
189 | } | |
190 | ///Synchronizes the buffers with the associated character sequence | |
191 | int sync() override { return this->_write_impl() ? 0 : -1; } | |
192 | ||
193 | ///Reads characters from the associated input sequence to the get area | |
194 | int_type underflow() override | |
195 | { | |
196 | if (!_pipe.is_open()) | |
197 | return traits_type::eof(); | |
198 | ||
199 | if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer | |
200 | this->setg(_read.data(), _read.data()+ 10, _read.data() + 10); | |
201 | ||
202 | ||
203 | auto len = &_read.back() - this->egptr() ; | |
204 | auto res = _pipe.read( | |
205 | this->egptr(), | |
206 | static_cast<typename pipe_type::int_type>(len)); | |
207 | if (res == 0) | |
208 | return traits_type::eof(); | |
209 | ||
210 | this->setg(this->eback(), this->gptr(), this->egptr() + res); | |
211 | auto val = *this->gptr(); | |
212 | ||
213 | return traits_type::to_int_type(val); | |
214 | } | |
215 | ||
216 | ||
217 | ///Set the pipe of the streambuf. | |
218 | void pipe(pipe_type&& p) {_pipe = std::move(p); } | |
219 | ///Set the pipe of the streambuf. | |
220 | void pipe(const pipe_type& p) {_pipe = p; } | |
221 | ///Get a reference to the pipe. | |
222 | pipe_type & pipe() & {return _pipe;} | |
223 | ///Get a const reference to the pipe. | |
224 | const pipe_type &pipe() const & {return _pipe;} | |
225 | ///Get a rvalue reference to the pipe. Qualified as rvalue. | |
226 | pipe_type && pipe() && {return std::move(_pipe);} | |
92f5a8d4 TL |
227 | |
228 | ///Check if the pipe is open | |
229 | bool is_open() const {return _pipe.is_open(); } | |
230 | ||
231 | ///Open a new pipe | |
232 | basic_pipebuf<CharT, Traits>* open() | |
233 | { | |
234 | if (is_open()) | |
235 | return nullptr; | |
236 | _pipe = pipe(); | |
237 | return this; | |
238 | } | |
239 | ||
240 | ///Open a new named pipe | |
241 | basic_pipebuf<CharT, Traits>* open(const std::string & name) | |
242 | { | |
243 | if (is_open()) | |
244 | return nullptr; | |
245 | _pipe = pipe(name); | |
246 | return this; | |
247 | } | |
248 | ||
249 | ///Flush the buffer & close the pipe | |
250 | basic_pipebuf<CharT, Traits>* close() | |
251 | { | |
252 | if (!is_open()) | |
253 | return nullptr; | |
254 | overflow(Traits::eof()); | |
255 | return this; | |
256 | } | |
b32b8144 FG |
257 | private: |
258 | pipe_type _pipe; | |
259 | std::vector<char_type> _write; | |
260 | std::vector<char_type> _read; | |
261 | ||
262 | bool _write_impl() | |
263 | { | |
264 | if (!_pipe.is_open()) | |
265 | return false; | |
266 | ||
267 | auto base = this->pbase(); | |
92f5a8d4 TL |
268 | |
269 | if (base == this->pptr()) | |
270 | return true; | |
271 | ||
272 | std::ptrdiff_t wrt = _pipe.write(base, | |
b32b8144 | 273 | static_cast<typename pipe_type::int_type>(this->pptr() - base)); |
92f5a8d4 | 274 | |
b32b8144 FG |
275 | std::ptrdiff_t diff = this->pptr() - base; |
276 | ||
277 | if (wrt < diff) | |
278 | std::move(base + wrt, base + diff, base); | |
279 | else if (wrt == 0) //broken pipe | |
280 | return false; | |
281 | ||
1e59de90 | 282 | this->pbump(static_cast<int>(-wrt)); |
b32b8144 FG |
283 | |
284 | return true; | |
285 | } | |
286 | }; | |
287 | ||
288 | typedef basic_pipebuf<char> pipebuf; | |
289 | typedef basic_pipebuf<wchar_t> wpipebuf; | |
290 | ||
291 | /** Implementation of a reading pipe stream. | |
292 | * | |
293 | */ | |
294 | template< | |
295 | class CharT, | |
296 | class Traits = std::char_traits<CharT> | |
297 | > | |
298 | class basic_ipstream : public std::basic_istream<CharT, Traits> | |
299 | { | |
92f5a8d4 | 300 | mutable basic_pipebuf<CharT, Traits> _buf; |
b32b8144 FG |
301 | public: |
302 | ||
303 | typedef basic_pipe<CharT, Traits> pipe_type; | |
304 | ||
305 | typedef CharT char_type ; | |
306 | typedef Traits traits_type; | |
307 | typedef typename Traits::int_type int_type ; | |
308 | typedef typename Traits::pos_type pos_type ; | |
309 | typedef typename Traits::off_type off_type ; | |
310 | ||
311 | ///Get access to the underlying stream_buf | |
92f5a8d4 | 312 | basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; |
b32b8144 FG |
313 | |
314 | ///Default constructor. | |
315 | basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr) | |
316 | { | |
317 | std::basic_istream<CharT, Traits>::rdbuf(&_buf); | |
318 | }; | |
319 | ///Copy constructor. | |
320 | basic_ipstream(const basic_ipstream & ) = delete; | |
321 | ///Move constructor. | |
92f5a8d4 TL |
322 | basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) |
323 | { | |
324 | std::basic_istream<CharT, Traits>::rdbuf(&_buf); | |
325 | } | |
b32b8144 FG |
326 | |
327 | ///Move construct from a pipe. | |
328 | basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p)) | |
329 | { | |
330 | std::basic_istream<CharT, Traits>::rdbuf(&_buf); | |
331 | } | |
332 | ||
333 | ///Copy construct from a pipe. | |
334 | basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p) | |
335 | { | |
336 | std::basic_istream<CharT, Traits>::rdbuf(&_buf); | |
337 | } | |
338 | ||
339 | ///Copy assignment. | |
340 | basic_ipstream& operator=(const basic_ipstream & ) = delete; | |
341 | ///Move assignment | |
92f5a8d4 TL |
342 | basic_ipstream& operator=(basic_ipstream && lhs) |
343 | { | |
344 | std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); | |
f67539c2 | 345 | _buf = std::move(lhs._buf); |
92f5a8d4 | 346 | std::basic_istream<CharT, Traits>::rdbuf(&_buf); |
f67539c2 | 347 | return *this; |
92f5a8d4 | 348 | }; |
b32b8144 FG |
349 | ///Move assignment of a pipe. |
350 | basic_ipstream& operator=(pipe_type && p) | |
351 | { | |
352 | _buf = std::move(p); | |
353 | return *this; | |
354 | } | |
355 | ///Copy assignment of a pipe. | |
356 | basic_ipstream& operator=(const pipe_type & p) | |
357 | { | |
358 | _buf = p; | |
359 | return *this; | |
360 | } | |
361 | ///Set the pipe of the streambuf. | |
362 | void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } | |
363 | ///Set the pipe of the streambuf. | |
364 | void pipe(const pipe_type& p) {_buf.pipe(p); } | |
365 | ///Get a reference to the pipe. | |
366 | pipe_type & pipe() & {return _buf.pipe();} | |
367 | ///Get a const reference to the pipe. | |
368 | const pipe_type &pipe() const & {return _buf.pipe();} | |
369 | ///Get a rvalue reference to the pipe. Qualified as rvalue. | |
370 | pipe_type && pipe() && {return std::move(_buf).pipe();} | |
92f5a8d4 | 371 | ///Check if the pipe is open |
f67539c2 | 372 | bool is_open() const {return _buf.is_open();} |
92f5a8d4 TL |
373 | |
374 | ///Open a new pipe | |
375 | void open() | |
376 | { | |
377 | if (_buf.open() == nullptr) | |
378 | this->setstate(std::ios_base::failbit); | |
379 | else | |
380 | this->clear(); | |
381 | } | |
382 | ||
383 | ///Open a new named pipe | |
384 | void open(const std::string & name) | |
385 | { | |
386 | if (_buf.open() == nullptr) | |
387 | this->setstate(std::ios_base::failbit); | |
388 | else | |
389 | this->clear(); | |
390 | } | |
391 | ||
392 | ///Flush the buffer & close the pipe | |
393 | void close() | |
394 | { | |
395 | if (_buf.close() == nullptr) | |
396 | this->setstate(std::ios_base::failbit); | |
397 | } | |
b32b8144 FG |
398 | }; |
399 | ||
400 | typedef basic_ipstream<char> ipstream; | |
401 | typedef basic_ipstream<wchar_t> wipstream; | |
402 | ||
403 | /** Implementation of a write pipe stream. | |
404 | * | |
405 | */ | |
406 | template< | |
407 | class CharT, | |
408 | class Traits = std::char_traits<CharT> | |
409 | > | |
410 | class basic_opstream : public std::basic_ostream<CharT, Traits> | |
411 | { | |
92f5a8d4 | 412 | mutable basic_pipebuf<CharT, Traits> _buf; |
b32b8144 FG |
413 | public: |
414 | typedef basic_pipe<CharT, Traits> pipe_type; | |
415 | ||
416 | typedef CharT char_type ; | |
417 | typedef Traits traits_type; | |
418 | typedef typename Traits::int_type int_type ; | |
419 | typedef typename Traits::pos_type pos_type ; | |
420 | typedef typename Traits::off_type off_type ; | |
421 | ||
422 | ||
423 | ///Get access to the underlying stream_buf | |
92f5a8d4 | 424 | basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; |
b32b8144 FG |
425 | |
426 | ///Default constructor. | |
427 | basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr) | |
428 | { | |
429 | std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | |
430 | }; | |
431 | ///Copy constructor. | |
432 | basic_opstream(const basic_opstream & ) = delete; | |
433 | ///Move constructor. | |
92f5a8d4 TL |
434 | basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) |
435 | { | |
436 | std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | |
437 | } | |
b32b8144 FG |
438 | ///Move construct from a pipe. |
439 | basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p)) | |
440 | { | |
441 | std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | |
442 | }; | |
443 | ///Copy construct from a pipe. | |
444 | basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p) | |
445 | { | |
446 | std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | |
447 | }; | |
448 | ///Copy assignment. | |
449 | basic_opstream& operator=(const basic_opstream & ) = delete; | |
450 | ///Move assignment | |
92f5a8d4 TL |
451 | basic_opstream& operator=(basic_opstream && lhs) |
452 | { | |
453 | std::basic_ostream<CharT, Traits>::operator=(std::move(lhs)); | |
f67539c2 | 454 | _buf = std::move(lhs._buf); |
92f5a8d4 | 455 | std::basic_ostream<CharT, Traits>::rdbuf(&_buf); |
f67539c2 | 456 | return *this; |
92f5a8d4 TL |
457 | }; |
458 | ||
b32b8144 FG |
459 | ///Move assignment of a pipe. |
460 | basic_opstream& operator=(pipe_type && p) | |
461 | { | |
462 | _buf = std::move(p); | |
463 | return *this; | |
464 | } | |
465 | ///Copy assignment of a pipe. | |
466 | basic_opstream& operator=(const pipe_type & p) | |
467 | { | |
468 | _buf = p; | |
469 | return *this; | |
470 | } | |
471 | ///Set the pipe of the streambuf. | |
472 | void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } | |
473 | ///Set the pipe of the streambuf. | |
474 | void pipe(const pipe_type& p) {_buf.pipe(p); } | |
475 | ///Get a reference to the pipe. | |
476 | pipe_type & pipe() & {return _buf.pipe();} | |
477 | ///Get a const reference to the pipe. | |
478 | const pipe_type &pipe() const & {return _buf.pipe();} | |
479 | ///Get a rvalue reference to the pipe. Qualified as rvalue. | |
480 | pipe_type && pipe() && {return std::move(_buf).pipe();} | |
92f5a8d4 TL |
481 | |
482 | ///Open a new pipe | |
483 | void open() | |
484 | { | |
485 | if (_buf.open() == nullptr) | |
486 | this->setstate(std::ios_base::failbit); | |
487 | else | |
488 | this->clear(); | |
489 | } | |
490 | ||
491 | ///Open a new named pipe | |
492 | void open(const std::string & name) | |
493 | { | |
494 | if (_buf.open() == nullptr) | |
495 | this->setstate(std::ios_base::failbit); | |
496 | else | |
497 | this->clear(); | |
498 | } | |
499 | ||
500 | ///Flush the buffer & close the pipe | |
501 | void close() | |
502 | { | |
503 | if (_buf.close() == nullptr) | |
504 | this->setstate(std::ios_base::failbit); | |
505 | } | |
b32b8144 FG |
506 | }; |
507 | ||
508 | typedef basic_opstream<char> opstream; | |
509 | typedef basic_opstream<wchar_t> wopstream; | |
510 | ||
511 | ||
512 | /** Implementation of a read-write pipe stream. | |
513 | * | |
514 | */ | |
515 | template< | |
516 | class CharT, | |
517 | class Traits = std::char_traits<CharT> | |
518 | > | |
519 | class basic_pstream : public std::basic_iostream<CharT, Traits> | |
520 | { | |
92f5a8d4 | 521 | mutable basic_pipebuf<CharT, Traits> _buf; |
b32b8144 FG |
522 | public: |
523 | typedef basic_pipe<CharT, Traits> pipe_type; | |
524 | ||
525 | typedef CharT char_type ; | |
526 | typedef Traits traits_type; | |
527 | typedef typename Traits::int_type int_type ; | |
528 | typedef typename Traits::pos_type pos_type ; | |
529 | typedef typename Traits::off_type off_type ; | |
530 | ||
531 | ||
532 | ///Get access to the underlying stream_buf | |
92f5a8d4 | 533 | basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; |
b32b8144 FG |
534 | |
535 | ///Default constructor. | |
536 | basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr) | |
537 | { | |
538 | std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | |
539 | }; | |
540 | ///Copy constructor. | |
541 | basic_pstream(const basic_pstream & ) = delete; | |
542 | ///Move constructor. | |
92f5a8d4 TL |
543 | basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) |
544 | { | |
545 | std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | |
546 | } | |
b32b8144 FG |
547 | ///Move construct from a pipe. |
548 | basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p)) | |
549 | { | |
550 | std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | |
551 | }; | |
552 | ///Copy construct from a pipe. | |
553 | basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p) | |
554 | { | |
555 | std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | |
556 | }; | |
557 | ///Copy assignment. | |
558 | basic_pstream& operator=(const basic_pstream & ) = delete; | |
559 | ///Move assignment | |
92f5a8d4 TL |
560 | basic_pstream& operator=(basic_pstream && lhs) |
561 | { | |
562 | std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); | |
f67539c2 | 563 | _buf = std::move(lhs._buf); |
92f5a8d4 | 564 | std::basic_iostream<CharT, Traits>::rdbuf(&_buf); |
f67539c2 | 565 | return *this; |
92f5a8d4 | 566 | }; |
b32b8144 FG |
567 | ///Move assignment of a pipe. |
568 | basic_pstream& operator=(pipe_type && p) | |
569 | { | |
570 | _buf = std::move(p); | |
571 | return *this; | |
572 | } | |
573 | ///Copy assignment of a pipe. | |
574 | basic_pstream& operator=(const pipe_type & p) | |
575 | { | |
576 | _buf = p; | |
577 | return *this; | |
578 | } | |
579 | ///Set the pipe of the streambuf. | |
580 | void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } | |
581 | ///Set the pipe of the streambuf. | |
582 | void pipe(const pipe_type& p) {_buf.pipe(p); } | |
583 | ///Get a reference to the pipe. | |
584 | pipe_type & pipe() & {return _buf.pipe();} | |
585 | ///Get a const reference to the pipe. | |
586 | const pipe_type &pipe() const & {return _buf.pipe();} | |
587 | ///Get a rvalue reference to the pipe. Qualified as rvalue. | |
588 | pipe_type && pipe() && {return std::move(_buf).pipe();} | |
92f5a8d4 TL |
589 | |
590 | ///Open a new pipe | |
591 | void open() | |
592 | { | |
593 | if (_buf.open() == nullptr) | |
594 | this->setstate(std::ios_base::failbit); | |
595 | else | |
596 | this->clear(); | |
597 | } | |
598 | ||
599 | ///Open a new named pipe | |
600 | void open(const std::string & name) | |
601 | { | |
602 | if (_buf.open() == nullptr) | |
603 | this->setstate(std::ios_base::failbit); | |
604 | else | |
605 | this->clear(); | |
606 | } | |
607 | ||
608 | ///Flush the buffer & close the pipe | |
609 | void close() | |
610 | { | |
611 | if (_buf.close() == nullptr) | |
612 | this->setstate(std::ios_base::failbit); | |
613 | } | |
b32b8144 FG |
614 | }; |
615 | ||
616 | typedef basic_pstream<char> pstream; | |
617 | typedef basic_pstream<wchar_t> wpstream; | |
618 | ||
619 | ||
620 | ||
621 | }} | |
622 | ||
623 | ||
624 | ||
625 | #endif |