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.
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::process::process_error". [details]
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  	
123  	    ///Move construct from a pipe.
124  	    basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
125  	                                    _write(default_buffer_size),
126  	                                    _read(default_buffer_size)
127  	    {
128  	        this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128);
129  	        this->setp(_write.data(), _write.data() + _write.size());
130  	    }
131  	    ///Construct from a pipe.
132  	    basic_pipebuf(const pipe_type & p) : _pipe(p),
133  	                                        _write(default_buffer_size),
134  	                                        _read(default_buffer_size)
135  	    {
136  	        this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128);
137  	        this->setp(_write.data(), _write.data() + _write.size());
138  	    }
139  	    ///Copy assign.
140  	    basic_pipebuf& operator=(const basic_pipebuf & ) = delete;
141  	    ///Move assign.
142  	    basic_pipebuf& operator=(basic_pipebuf && ) = default;
143  	    ///Move assign a pipe.
144  	    basic_pipebuf& operator=(pipe_type && p)
145  	    {
146  	        _pipe = std::move(p);
147  	        return *this;
148  	    }
149  	    ///Copy assign a pipe.
150  	    basic_pipebuf& operator=(const pipe_type & p)
151  	    {
152  	        _pipe = p;
153  	        return *this;
154  	    }
155  	    ///Writes characters to the associated output sequence from the put area
156  	    int_type overflow(int_type ch = traits_type::eof()) override
157  	    {
158  	        if ((ch != traits_type::eof()) && _pipe.is_open())
159  	        {
160  	            if (this->pptr() == this->epptr())
161  	            {
162  	                bool wr = this->_write_impl();
163  	                *this->pptr() = ch;
164  	                this->pbump(1);
165  	                if (wr)
166  	                    return ch;
167  	            }
168  	            else
169  	            {
170  	                *this->pptr() = ch;
171  	                this->pbump(1);
172  	                if (this->_write_impl())
173  	                    return ch;
174  	            }
175  	        }
176  	        return traits_type::eof();
177  	    }
178  	    ///Synchronizes the buffers with the associated character sequence
179  	    int sync() override { return this->_write_impl() ? 0 : -1; }
180  	
181  	    ///Reads characters from the associated input sequence to the get area
182  	    int_type underflow() override
183  	    {
184  	        if (!_pipe.is_open())
185  	            return traits_type::eof();
186  	
187  	        if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer
188  	            this->setg(_read.data(),  _read.data()+ 10,  _read.data() + 10);
189  	
190  	
191  	        auto len = &_read.back() - this->egptr() ;
192  	        auto res = _pipe.read(
193  	                        this->egptr(),
194  	                        static_cast<typename pipe_type::int_type>(len));
195  	        if (res == 0)
196  	            return traits_type::eof();
197  	
198  	        this->setg(this->eback(), this->gptr(), this->egptr() + res);
199  	        auto val = *this->gptr();
200  	
201  	        return traits_type::to_int_type(val);
202  	    }
203  	
204  	
205  	    ///Set the pipe of the streambuf.
206  	    void pipe(pipe_type&& p)      {_pipe = std::move(p); }
207  	    ///Set the pipe of the streambuf.
208  	    void pipe(const pipe_type& p) {_pipe = p; }
209  	    ///Get a reference to the pipe.
210  	    pipe_type &      pipe() &       {return _pipe;}
211  	    ///Get a const reference to the pipe.
212  	    const pipe_type &pipe() const & {return _pipe;}
213  	    ///Get a rvalue reference to the pipe. Qualified as rvalue.
214  	    pipe_type &&     pipe()  &&     {return std::move(_pipe);}
215  	private:
216  	    pipe_type _pipe;
217  	    std::vector<char_type> _write;
218  	    std::vector<char_type> _read;
219  	
220  	    bool _write_impl()
221  	    {
222  	        if (!_pipe.is_open())
223  	            return false;
224  	
225  	        auto base = this->pbase();
226  	        auto wrt = _pipe.write(base,
227  	                static_cast<typename pipe_type::int_type>(this->pptr() - base));
228  	        std::ptrdiff_t diff = this->pptr() - base;
229  	
230  	        if (wrt < diff)
231  	            std::move(base + wrt, base + diff, base);
232  	        else if (wrt == 0) //broken pipe
233  	            return false;
234  	
235  	        this->pbump(-wrt);
236  	
237  	        return true;
238  	    }
239  	};
240  	
241  	typedef basic_pipebuf<char>     pipebuf;
242  	typedef basic_pipebuf<wchar_t> wpipebuf;
243  	
244  	/** Implementation of a reading pipe stream.
245  	 *
246  	 */
247  	template<
248  	    class CharT,
249  	    class Traits = std::char_traits<CharT>
250  	>
251  	class basic_ipstream : public std::basic_istream<CharT, Traits>
252  	{
253  	    basic_pipebuf<CharT, Traits> _buf;
254  	public:
255  	
256  	    typedef basic_pipe<CharT, Traits> pipe_type;
257  	
258  	    typedef           CharT            char_type  ;
259  	    typedef           Traits           traits_type;
260  	    typedef  typename Traits::int_type int_type   ;
261  	    typedef  typename Traits::pos_type pos_type   ;
262  	    typedef  typename Traits::off_type off_type   ;
263  	
264  	    ///Get access to the underlying stream_buf
265  	    basic_pipebuf<CharT, Traits>* rdbuf() {return &_buf;};
266  	
267  	    ///Default constructor.
(1) Event fun_call_w_exception: Called function throws an exception of type "boost::process::process_error". [details]
268  	    basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
269  	    {
270  	        std::basic_istream<CharT, Traits>::rdbuf(&_buf);
271  	    };
272  	    ///Copy constructor.
273  	    basic_ipstream(const basic_ipstream & ) = delete;
274  	    ///Move constructor.
275  	    basic_ipstream(basic_ipstream && ) = default;
276  	
277  	    ///Move construct from a pipe.
278  	    basic_ipstream(pipe_type && p)      : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
279  	    {
280  	        std::basic_istream<CharT, Traits>::rdbuf(&_buf);
281  	    }
282  	
283  	    ///Copy construct from a pipe.
284  	    basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p)
285  	    {
286  	        std::basic_istream<CharT, Traits>::rdbuf(&_buf);
287  	    }
288  	
289  	    ///Copy assignment.
290  	    basic_ipstream& operator=(const basic_ipstream & ) = delete;
291  	    ///Move assignment
292  	    basic_ipstream& operator=(basic_ipstream && ) = default;
293  	    ///Move assignment of a pipe.
294  	    basic_ipstream& operator=(pipe_type && p)
295  	    {
296  	        _buf = std::move(p);
297  	        return *this;
298  	    }
299  	    ///Copy assignment of a pipe.
300  	    basic_ipstream& operator=(const pipe_type & p)
301  	    {
302  	        _buf = p;
303  	        return *this;
304  	    }
305  	    ///Set the pipe of the streambuf.
306  	    void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
307  	    ///Set the pipe of the streambuf.
308  	    void pipe(const pipe_type& p) {_buf.pipe(p); }
309  	    ///Get a reference to the pipe.
310  	    pipe_type &      pipe() &       {return _buf.pipe();}
311  	    ///Get a const reference to the pipe.
312  	    const pipe_type &pipe() const & {return _buf.pipe();}
313  	    ///Get a rvalue reference to the pipe. Qualified as rvalue.
314  	    pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
315  	};
316  	
317  	typedef basic_ipstream<char>     ipstream;
318  	typedef basic_ipstream<wchar_t> wipstream;
319  	
320  	/** Implementation of a write pipe stream.
321  	 *
322  	 */
323  	template<
324  	    class CharT,
325  	    class Traits = std::char_traits<CharT>
326  	>
327  	class basic_opstream : public std::basic_ostream<CharT, Traits>
328  	{
329  	    basic_pipebuf<CharT, Traits> _buf;
330  	public:
331  	    typedef basic_pipe<CharT, Traits> pipe_type;
332  	
333  	    typedef           CharT            char_type  ;
334  	    typedef           Traits           traits_type;
335  	    typedef  typename Traits::int_type int_type   ;
336  	    typedef  typename Traits::pos_type pos_type   ;
337  	    typedef  typename Traits::off_type off_type   ;
338  	
339  	
340  	    ///Get access to the underlying stream_buf
341  	    basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
342  	
343  	    ///Default constructor.
344  	    basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
345  	    {
346  	        std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
347  	    };
348  	    ///Copy constructor.
349  	    basic_opstream(const basic_opstream & ) = delete;
350  	    ///Move constructor.
351  	    basic_opstream(basic_opstream && ) = default;
352  	
353  	    ///Move construct from a pipe.
354  	    basic_opstream(pipe_type && p)      : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
355  	    {
356  	        std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
357  	    };
358  	    ///Copy construct from a pipe.
359  	    basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p)
360  	    {
361  	        std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
362  	    };
363  	    ///Copy assignment.
364  	    basic_opstream& operator=(const basic_opstream & ) = delete;
365  	    ///Move assignment
366  	    basic_opstream& operator=(basic_opstream && ) = default;
367  	    ///Move assignment of a pipe.
368  	    basic_opstream& operator=(pipe_type && p)
369  	    {
370  	        _buf = std::move(p);
371  	        return *this;
372  	    }
373  	    ///Copy assignment of a pipe.
374  	    basic_opstream& operator=(const pipe_type & p)
375  	    {
376  	        _buf = p;
377  	        return *this;
378  	    }
379  	    ///Set the pipe of the streambuf.
380  	    void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
381  	    ///Set the pipe of the streambuf.
382  	    void pipe(const pipe_type& p) {_buf.pipe(p); }
383  	    ///Get a reference to the pipe.
384  	    pipe_type &      pipe() &       {return _buf.pipe();}
385  	    ///Get a const reference to the pipe.
386  	    const pipe_type &pipe() const & {return _buf.pipe();}
387  	    ///Get a rvalue reference to the pipe. Qualified as rvalue.
388  	    pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
389  	};
390  	
391  	typedef basic_opstream<char>     opstream;
392  	typedef basic_opstream<wchar_t> wopstream;
393  	
394  	
395  	/** Implementation of a read-write pipe stream.
396  	 *
397  	 */
398  	template<
399  	    class CharT,
400  	    class Traits = std::char_traits<CharT>
401  	>
402  	class basic_pstream : public std::basic_iostream<CharT, Traits>
403  	{
404  	    basic_pipebuf<CharT, Traits> _buf;
405  	public:
406  	    typedef basic_pipe<CharT, Traits> pipe_type;
407  	
408  	    typedef           CharT            char_type  ;
409  	    typedef           Traits           traits_type;
410  	    typedef  typename Traits::int_type int_type   ;
411  	    typedef  typename Traits::pos_type pos_type   ;
412  	    typedef  typename Traits::off_type off_type   ;
413  	
414  	
415  	    ///Get access to the underlying stream_buf
416  	    basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
417  	
418  	    ///Default constructor.
419  	    basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
420  	    {
421  	        std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
422  	    };
423  	    ///Copy constructor.
424  	    basic_pstream(const basic_pstream & ) = delete;
425  	    ///Move constructor.
426  	    basic_pstream(basic_pstream && ) = default;
427  	
428  	    ///Move construct from a pipe.
429  	    basic_pstream(pipe_type && p)      : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
430  	    {
431  	        std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
432  	    };
433  	    ///Copy construct from a pipe.
434  	    basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p)
435  	    {
436  	        std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
437  	    };
438  	    ///Copy assignment.
439  	    basic_pstream& operator=(const basic_pstream & ) = delete;
440  	    ///Move assignment
441  	    basic_pstream& operator=(basic_pstream && ) = default;
442  	    ///Move assignment of a pipe.
443  	    basic_pstream& operator=(pipe_type && p)
444  	    {
445  	        _buf = std::move(p);
446  	        return *this;
447  	    }
448  	    ///Copy assignment of a pipe.
449  	    basic_pstream& operator=(const pipe_type & p)
450  	    {
451  	        _buf = p;
452  	        return *this;
453  	    }
454  	    ///Set the pipe of the streambuf.
455  	    void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
456  	    ///Set the pipe of the streambuf.
457  	    void pipe(const pipe_type& p) {_buf.pipe(p); }
458  	    ///Get a reference to the pipe.
459  	    pipe_type &      pipe() &       {return _buf.pipe();}
460  	    ///Get a const reference to the pipe.
461  	    const pipe_type &pipe() const & {return _buf.pipe();}
462  	    ///Get a rvalue reference to the pipe. Qualified as rvalue.
463  	    pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
464  	};
465  	
466  	typedef basic_pstream<char>     pstream;
467  	typedef basic_pstream<wchar_t> wpstream;
468  	
469  	
470  	
471  	}}
472  	
473  	
474  	
475  	#endif
476