626 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			626 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright (c) 2006, 2007 Julio M. Merino Vidal
 | ||
|  | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
 | ||
|  | // Copyright (c) 2009 Boris Schaeling
 | ||
|  | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
 | ||
|  | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
 | ||
|  | //
 | ||
|  | // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | ||
|  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef BOOST_PROCESS_PIPE_HPP
 | ||
|  | #define BOOST_PROCESS_PIPE_HPP
 | ||
|  | 
 | ||
|  | #include <boost/config.hpp>
 | ||
|  | #include <boost/process/detail/config.hpp>
 | ||
|  | #include <streambuf>
 | ||
|  | #include <istream>
 | ||
|  | #include <ostream>
 | ||
|  | #include <vector>
 | ||
|  | 
 | ||
|  | #if defined(BOOST_POSIX_API)
 | ||
|  | #include <boost/process/detail/posix/basic_pipe.hpp>
 | ||
|  | #elif defined(BOOST_WINDOWS_API)
 | ||
|  | #include <boost/process/detail/windows/basic_pipe.hpp>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | namespace boost { namespace process { | ||
|  | 
 | ||
|  | using ::boost::process::detail::api::basic_pipe; | ||
|  | 
 | ||
|  | #if defined(BOOST_PROCESS_DOXYGEN)
 | ||
|  | /** Class implementation of a pipe.
 | ||
|  |  * | ||
|  |  */ | ||
|  | template<class CharT, class Traits = std::char_traits<CharT>> | ||
|  | class basic_pipe | ||
|  | { | ||
|  | public: | ||
|  |     typedef CharT                      char_type  ; | ||
|  |     typedef          Traits            traits_type; | ||
|  |     typedef typename Traits::int_type  int_type   ; | ||
|  |     typedef typename Traits::pos_type  pos_type   ; | ||
|  |     typedef typename Traits::off_type  off_type   ; | ||
|  |     typedef ::boost::detail::winapi::HANDLE_ native_handle; | ||
|  | 
 | ||
|  |     /// Default construct the pipe. Will be opened.
 | ||
|  |     basic_pipe(); | ||
|  | 
 | ||
|  |     ///Construct a named pipe.
 | ||
|  |     inline explicit basic_pipe(const std::string & name); | ||
|  |     /** Copy construct the pipe.
 | ||
|  |      *  \note Duplicated the handles. | ||
|  |      */ | ||
|  |     inline basic_pipe(const basic_pipe& p); | ||
|  |     /** Move construct the pipe. */ | ||
|  |     basic_pipe(basic_pipe&& lhs); | ||
|  |     /** Copy assign the pipe.
 | ||
|  |      *  \note Duplicated the handles. | ||
|  |      */ | ||
|  |     inline basic_pipe& operator=(const basic_pipe& p); | ||
|  |     /** Move assign the pipe. */ | ||
|  |     basic_pipe& operator=(basic_pipe&& lhs); | ||
|  |     /** Destructor closes the handles. */ | ||
|  |     ~basic_pipe(); | ||
|  |     /** Get the native handle of the source. */ | ||
|  |     native_handle native_source() const; | ||
|  |     /** Get the native handle of the sink. */ | ||
|  |     native_handle native_sink  () const; | ||
|  | 
 | ||
|  |     /** Assign a new value to the source */ | ||
|  |     void assign_source(native_handle h); | ||
|  |     /** Assign a new value to the sink */ | ||
|  |     void assign_sink  (native_handle h); | ||
|  | 
 | ||
|  | 
 | ||
|  |     ///Write data to the pipe.
 | ||
|  |     int_type write(const char_type * data, int_type count); | ||
|  |     ///Read data from the pipe.
 | ||
|  |     int_type read(char_type * data, int_type count); | ||
|  |     ///Check if the pipe is open.
 | ||
|  |     bool is_open(); | ||
|  |     ///Close the pipe
 | ||
|  |     void close(); | ||
|  | }; | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | typedef basic_pipe<char>     pipe; | ||
|  | typedef basic_pipe<wchar_t> wpipe; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** Implementation of the stream buffer for a pipe.
 | ||
|  |  */ | ||
|  | template< | ||
|  |     class CharT, | ||
|  |     class Traits = std::char_traits<CharT> | ||
|  | > | ||
|  | struct basic_pipebuf : std::basic_streambuf<CharT, Traits> | ||
|  | { | ||
|  |     typedef basic_pipe<CharT, Traits> pipe_type; | ||
|  | 
 | ||
|  |     typedef           CharT            char_type  ; | ||
|  |     typedef           Traits           traits_type; | ||
|  |     typedef  typename Traits::int_type int_type   ; | ||
|  |     typedef  typename Traits::pos_type pos_type   ; | ||
|  |     typedef  typename Traits::off_type off_type   ; | ||
|  | 
 | ||
|  |     constexpr static int default_buffer_size = BOOST_PROCESS_PIPE_SIZE; | ||
|  | 
 | ||
|  |     ///Default constructor, will also construct the pipe.
 | ||
|  |     basic_pipebuf() : _write(default_buffer_size), _read(default_buffer_size) | ||
|  |     { | ||
|  |         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128); | ||
|  |         this->setp(_write.data(), _write.data() + _write.size()); | ||
|  |     } | ||
|  |     ///Copy Constructor.
 | ||
|  |     basic_pipebuf(const basic_pipebuf & ) = default; | ||
|  |     ///Move Constructor
 | ||
|  |     basic_pipebuf(basic_pipebuf && ) = default; | ||
|  | 
 | ||
|  |     ///Destructor -> writes the frest of the data
 | ||
|  |     ~basic_pipebuf() | ||
|  |     { | ||
|  |         if (basic_pipebuf::is_open()) | ||
|  |             basic_pipebuf::overflow(Traits::eof()); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Move construct from a pipe.
 | ||
|  |     basic_pipebuf(pipe_type && p) : _pipe(std::move(p)), | ||
|  |                                     _write(default_buffer_size), | ||
|  |                                     _read(default_buffer_size) | ||
|  |     { | ||
|  |         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128); | ||
|  |         this->setp(_write.data(), _write.data() + _write.size()); | ||
|  |     } | ||
|  |     ///Construct from a pipe.
 | ||
|  |     basic_pipebuf(const pipe_type & p) : _pipe(p), | ||
|  |                                         _write(default_buffer_size), | ||
|  |                                         _read(default_buffer_size) | ||
|  |     { | ||
|  |         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128); | ||
|  |         this->setp(_write.data(), _write.data() + _write.size()); | ||
|  |     } | ||
|  |     ///Copy assign.
 | ||
|  |     basic_pipebuf& operator=(const basic_pipebuf & ) = delete; | ||
|  |     ///Move assign.
 | ||
|  |     basic_pipebuf& operator=(basic_pipebuf && ) = default; | ||
|  |     ///Move assign a pipe.
 | ||
|  |     basic_pipebuf& operator=(pipe_type && p) | ||
|  |     { | ||
|  |         _pipe = std::move(p); | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Copy assign a pipe.
 | ||
|  |     basic_pipebuf& operator=(const pipe_type & p) | ||
|  |     { | ||
|  |         _pipe = p; | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Writes characters to the associated output sequence from the put area
 | ||
|  |     int_type overflow(int_type ch = traits_type::eof()) override | ||
|  |     { | ||
|  |         if (_pipe.is_open() && (ch != traits_type::eof())) | ||
|  |         { | ||
|  |             if (this->pptr() == this->epptr()) | ||
|  |             { | ||
|  |                 bool wr = this->_write_impl(); | ||
|  |                 if (wr) | ||
|  |                 { | ||
|  |                     *this->pptr() = ch; | ||
|  |                     this->pbump(1); | ||
|  |                     return ch; | ||
|  |                 } | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 *this->pptr() = ch; | ||
|  |                 this->pbump(1); | ||
|  |                 if (this->_write_impl()) | ||
|  |                     return ch; | ||
|  |             } | ||
|  |         } | ||
|  |         else if (ch == traits_type::eof()) | ||
|  |            this->sync(); | ||
|  | 
 | ||
|  |         return traits_type::eof(); | ||
|  |     } | ||
|  |     ///Synchronizes the buffers with the associated character sequence
 | ||
|  |     int sync() override { return this->_write_impl() ? 0 : -1; } | ||
|  | 
 | ||
|  |     ///Reads characters from the associated input sequence to the get area
 | ||
|  |     int_type underflow() override | ||
|  |     { | ||
|  |         if (!_pipe.is_open()) | ||
|  |             return traits_type::eof(); | ||
|  | 
 | ||
|  |         if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer
 | ||
|  |             this->setg(_read.data(),  _read.data()+ 10,  _read.data() + 10); | ||
|  | 
 | ||
|  | 
 | ||
|  |         auto len = &_read.back() - this->egptr() ; | ||
|  |         auto res = _pipe.read( | ||
|  |                         this->egptr(), | ||
|  |                         static_cast<typename pipe_type::int_type>(len)); | ||
|  |         if (res == 0) | ||
|  |             return traits_type::eof(); | ||
|  | 
 | ||
|  |         this->setg(this->eback(), this->gptr(), this->egptr() + res); | ||
|  |         auto val = *this->gptr(); | ||
|  | 
 | ||
|  |         return traits_type::to_int_type(val); | ||
|  |     } | ||
|  | 
 | ||
|  | 
 | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(pipe_type&& p)      {_pipe = std::move(p); } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(const pipe_type& p) {_pipe = p; } | ||
|  |     ///Get a reference to the pipe.
 | ||
|  |     pipe_type &      pipe() &       {return _pipe;} | ||
|  |     ///Get a const reference to the pipe.
 | ||
|  |     const pipe_type &pipe() const & {return _pipe;} | ||
|  |     ///Get a rvalue reference to the pipe. Qualified as rvalue.
 | ||
|  |     pipe_type &&     pipe()  &&     {return std::move(_pipe);} | ||
|  | 
 | ||
|  |     ///Check if the pipe is open
 | ||
|  |     bool is_open() const {return _pipe.is_open(); } | ||
|  | 
 | ||
|  |     ///Open a new pipe
 | ||
|  |     basic_pipebuf<CharT, Traits>* open() | ||
|  |     { | ||
|  |         if (is_open()) | ||
|  |             return nullptr; | ||
|  |         _pipe = pipe(); | ||
|  |         return this; | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Open a new named pipe
 | ||
|  |     basic_pipebuf<CharT, Traits>* open(const std::string & name) | ||
|  |     { | ||
|  |         if (is_open()) | ||
|  |             return nullptr; | ||
|  |         _pipe = pipe(name); | ||
|  |         return this; | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Flush the buffer & close the pipe
 | ||
|  |     basic_pipebuf<CharT, Traits>* close() | ||
|  |     { | ||
|  |         if (!is_open()) | ||
|  |             return nullptr; | ||
|  |         overflow(Traits::eof()); | ||
|  |         return this; | ||
|  |     } | ||
|  | private: | ||
|  |     pipe_type _pipe; | ||
|  |     std::vector<char_type> _write; | ||
|  |     std::vector<char_type> _read; | ||
|  | 
 | ||
|  |     bool _write_impl() | ||
|  |     { | ||
|  |         if (!_pipe.is_open()) | ||
|  |             return false; | ||
|  | 
 | ||
|  |         auto base = this->pbase(); | ||
|  | 
 | ||
|  |         if (base == this->pptr()) | ||
|  |             return true; | ||
|  | 
 | ||
|  |         std::ptrdiff_t wrt = _pipe.write(base, | ||
|  |                 static_cast<typename pipe_type::int_type>(this->pptr() - base)); | ||
|  | 
 | ||
|  |         std::ptrdiff_t diff = this->pptr() - base; | ||
|  | 
 | ||
|  |         if (wrt < diff) | ||
|  |             std::move(base + wrt, base + diff, base); | ||
|  |         else if (wrt == 0) //broken pipe
 | ||
|  |             return false; | ||
|  | 
 | ||
|  |         this->pbump(static_cast<int>(-wrt)); | ||
|  | 
 | ||
|  |         return true; | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | typedef basic_pipebuf<char>     pipebuf; | ||
|  | typedef basic_pipebuf<wchar_t> wpipebuf; | ||
|  | 
 | ||
|  | /** Implementation of a reading pipe stream.
 | ||
|  |  * | ||
|  |  */ | ||
|  | template< | ||
|  |     class CharT, | ||
|  |     class Traits = std::char_traits<CharT> | ||
|  | > | ||
|  | class basic_ipstream : public std::basic_istream<CharT, Traits> | ||
|  | { | ||
|  |     mutable basic_pipebuf<CharT, Traits> _buf; | ||
|  | public: | ||
|  | 
 | ||
|  |     typedef basic_pipe<CharT, Traits> pipe_type; | ||
|  | 
 | ||
|  |     typedef           CharT            char_type  ; | ||
|  |     typedef           Traits           traits_type; | ||
|  |     typedef  typename Traits::int_type int_type   ; | ||
|  |     typedef  typename Traits::pos_type pos_type   ; | ||
|  |     typedef  typename Traits::off_type off_type   ; | ||
|  | 
 | ||
|  |     ///Get access to the underlying stream_buf
 | ||
|  |     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; | ||
|  | 
 | ||
|  |     ///Default constructor.
 | ||
|  |     basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy constructor.
 | ||
|  |     basic_ipstream(const basic_ipstream & ) = delete; | ||
|  |     ///Move constructor.
 | ||
|  |     basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Move construct from a pipe.
 | ||
|  |     basic_ipstream(pipe_type && p)      : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p)) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Copy construct from a pipe.
 | ||
|  |     basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Copy assignment.
 | ||
|  |     basic_ipstream& operator=(const basic_ipstream & ) = delete; | ||
|  |     ///Move assignment
 | ||
|  |     basic_ipstream& operator=(basic_ipstream && lhs) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); | ||
|  |         _buf = std::move(lhs._buf); | ||
|  |         std::basic_istream<CharT, Traits>::rdbuf(&_buf); | ||
|  |         return *this; | ||
|  |     }; | ||
|  |     ///Move assignment of a pipe.
 | ||
|  |     basic_ipstream& operator=(pipe_type && p) | ||
|  |     { | ||
|  |         _buf = std::move(p); | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Copy assignment of a pipe.
 | ||
|  |     basic_ipstream& operator=(const pipe_type & p) | ||
|  |     { | ||
|  |         _buf = p; | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(const pipe_type& p) {_buf.pipe(p); } | ||
|  |     ///Get a reference to the pipe.
 | ||
|  |     pipe_type &      pipe() &       {return _buf.pipe();} | ||
|  |     ///Get a const reference to the pipe.
 | ||
|  |     const pipe_type &pipe() const & {return _buf.pipe();} | ||
|  |     ///Get a rvalue reference to the pipe. Qualified as rvalue.
 | ||
|  |     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();} | ||
|  |     ///Check if the pipe is open
 | ||
|  |     bool is_open() const {return _buf.is_open();} | ||
|  | 
 | ||
|  |     ///Open a new pipe
 | ||
|  |     void open() | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Open a new named pipe
 | ||
|  |     void open(const std::string & name) | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Flush the buffer & close the pipe
 | ||
|  |     void close() | ||
|  |     { | ||
|  |         if (_buf.close() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | typedef basic_ipstream<char>     ipstream; | ||
|  | typedef basic_ipstream<wchar_t> wipstream; | ||
|  | 
 | ||
|  | /** Implementation of a write pipe stream.
 | ||
|  |  * | ||
|  |  */ | ||
|  | template< | ||
|  |     class CharT, | ||
|  |     class Traits = std::char_traits<CharT> | ||
|  | > | ||
|  | class basic_opstream : public std::basic_ostream<CharT, Traits> | ||
|  | { | ||
|  |     mutable basic_pipebuf<CharT, Traits> _buf; | ||
|  | public: | ||
|  |     typedef basic_pipe<CharT, Traits> pipe_type; | ||
|  | 
 | ||
|  |     typedef           CharT            char_type  ; | ||
|  |     typedef           Traits           traits_type; | ||
|  |     typedef  typename Traits::int_type int_type   ; | ||
|  |     typedef  typename Traits::pos_type pos_type   ; | ||
|  |     typedef  typename Traits::off_type off_type   ; | ||
|  | 
 | ||
|  | 
 | ||
|  |     ///Get access to the underlying stream_buf
 | ||
|  |     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; | ||
|  | 
 | ||
|  |     ///Default constructor.
 | ||
|  |     basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr) | ||
|  |     { | ||
|  |         std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy constructor.
 | ||
|  |     basic_opstream(const basic_opstream & ) = delete; | ||
|  |     ///Move constructor.
 | ||
|  |     basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) | ||
|  |     { | ||
|  |         std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     } | ||
|  |     ///Move construct from a pipe.
 | ||
|  |     basic_opstream(pipe_type && p)      : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p)) | ||
|  |     { | ||
|  |         std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy construct from a pipe.
 | ||
|  |     basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p) | ||
|  |     { | ||
|  |         std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy assignment.
 | ||
|  |     basic_opstream& operator=(const basic_opstream & ) = delete; | ||
|  |     ///Move assignment
 | ||
|  |     basic_opstream& operator=(basic_opstream && lhs) | ||
|  |     { | ||
|  |         std::basic_ostream<CharT, Traits>::operator=(std::move(lhs)); | ||
|  |         _buf = std::move(lhs._buf); | ||
|  |         std::basic_ostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |         return *this; | ||
|  |     }; | ||
|  | 
 | ||
|  |     ///Move assignment of a pipe.
 | ||
|  |     basic_opstream& operator=(pipe_type && p) | ||
|  |     { | ||
|  |         _buf = std::move(p); | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Copy assignment of a pipe.
 | ||
|  |     basic_opstream& operator=(const pipe_type & p) | ||
|  |     { | ||
|  |         _buf = p; | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(const pipe_type& p) {_buf.pipe(p); } | ||
|  |     ///Get a reference to the pipe.
 | ||
|  |     pipe_type &      pipe() &       {return _buf.pipe();} | ||
|  |     ///Get a const reference to the pipe.
 | ||
|  |     const pipe_type &pipe() const & {return _buf.pipe();} | ||
|  |     ///Get a rvalue reference to the pipe. Qualified as rvalue.
 | ||
|  |     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();} | ||
|  | 
 | ||
|  |     ///Open a new pipe
 | ||
|  |     void open() | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Open a new named pipe
 | ||
|  |     void open(const std::string & name) | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Flush the buffer & close the pipe
 | ||
|  |     void close() | ||
|  |     { | ||
|  |         if (_buf.close() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | typedef basic_opstream<char>     opstream; | ||
|  | typedef basic_opstream<wchar_t> wopstream; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** Implementation of a read-write pipe stream.
 | ||
|  |  * | ||
|  |  */ | ||
|  | template< | ||
|  |     class CharT, | ||
|  |     class Traits = std::char_traits<CharT> | ||
|  | > | ||
|  | class basic_pstream : public std::basic_iostream<CharT, Traits> | ||
|  | { | ||
|  |     mutable basic_pipebuf<CharT, Traits> _buf; | ||
|  | public: | ||
|  |     typedef basic_pipe<CharT, Traits> pipe_type; | ||
|  | 
 | ||
|  |     typedef           CharT            char_type  ; | ||
|  |     typedef           Traits           traits_type; | ||
|  |     typedef  typename Traits::int_type int_type   ; | ||
|  |     typedef  typename Traits::pos_type pos_type   ; | ||
|  |     typedef  typename Traits::off_type off_type   ; | ||
|  | 
 | ||
|  | 
 | ||
|  |     ///Get access to the underlying stream_buf
 | ||
|  |     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; | ||
|  | 
 | ||
|  |     ///Default constructor.
 | ||
|  |     basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr) | ||
|  |     { | ||
|  |         std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy constructor.
 | ||
|  |     basic_pstream(const basic_pstream & ) = delete; | ||
|  |     ///Move constructor.
 | ||
|  |     basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) | ||
|  |     { | ||
|  |         std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     } | ||
|  |     ///Move construct from a pipe.
 | ||
|  |     basic_pstream(pipe_type && p)      : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p)) | ||
|  |     { | ||
|  |         std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy construct from a pipe.
 | ||
|  |     basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p) | ||
|  |     { | ||
|  |         std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |     }; | ||
|  |     ///Copy assignment.
 | ||
|  |     basic_pstream& operator=(const basic_pstream & ) = delete; | ||
|  |     ///Move assignment
 | ||
|  |     basic_pstream& operator=(basic_pstream && lhs) | ||
|  |     { | ||
|  |         std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); | ||
|  |         _buf = std::move(lhs._buf); | ||
|  |         std::basic_iostream<CharT, Traits>::rdbuf(&_buf); | ||
|  |         return *this; | ||
|  |     }; | ||
|  |     ///Move assignment of a pipe.
 | ||
|  |     basic_pstream& operator=(pipe_type && p) | ||
|  |     { | ||
|  |         _buf = std::move(p); | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Copy assignment of a pipe.
 | ||
|  |     basic_pstream& operator=(const pipe_type & p) | ||
|  |     { | ||
|  |         _buf = p; | ||
|  |         return *this; | ||
|  |     } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); } | ||
|  |     ///Set the pipe of the streambuf.
 | ||
|  |     void pipe(const pipe_type& p) {_buf.pipe(p); } | ||
|  |     ///Get a reference to the pipe.
 | ||
|  |     pipe_type &      pipe() &       {return _buf.pipe();} | ||
|  |     ///Get a const reference to the pipe.
 | ||
|  |     const pipe_type &pipe() const & {return _buf.pipe();} | ||
|  |     ///Get a rvalue reference to the pipe. Qualified as rvalue.
 | ||
|  |     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();} | ||
|  | 
 | ||
|  |     ///Open a new pipe
 | ||
|  |     void open() | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Open a new named pipe
 | ||
|  |     void open(const std::string & name) | ||
|  |     { | ||
|  |         if (_buf.open() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |         else | ||
|  |             this->clear(); | ||
|  |     } | ||
|  | 
 | ||
|  |     ///Flush the buffer & close the pipe
 | ||
|  |     void close() | ||
|  |     { | ||
|  |         if (_buf.close() == nullptr) | ||
|  |             this->setstate(std::ios_base::failbit); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | typedef basic_pstream<char>     pstream; | ||
|  | typedef basic_pstream<wchar_t> wpstream; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | }} | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif
 |