Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:07:14

0001 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
0002 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
0003 // Copyright (c) 2009 Boris Schaeling
0004 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
0005 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 
0011 #ifndef BOOST_PROCESS_PIPE_HPP
0012 #define BOOST_PROCESS_PIPE_HPP
0013 
0014 #include <boost/config.hpp>
0015 #include <boost/process/v1/detail/config.hpp>
0016 #include <streambuf>
0017 #include <istream>
0018 #include <ostream>
0019 #include <vector>
0020 
0021 #if defined(BOOST_POSIX_API)
0022 #include <boost/process/v1/detail/posix/basic_pipe.hpp>
0023 #elif defined(BOOST_WINDOWS_API)
0024 #include <boost/process/v1/detail/windows/basic_pipe.hpp>
0025 #endif
0026 
0027 namespace boost { namespace process { BOOST_PROCESS_V1_INLINE namespace v1 {
0028 
0029 using ::boost::process::v1::detail::api::basic_pipe;
0030 
0031 #if defined(BOOST_PROCESS_DOXYGEN)
0032 /** Class implementation of a pipe.
0033  *
0034  */
0035 template<class CharT, class Traits = std::char_traits<CharT>>
0036 class basic_pipe
0037 {
0038 public:
0039     typedef CharT                      char_type  ;
0040     typedef          Traits            traits_type;
0041     typedef typename Traits::int_type  int_type   ;
0042     typedef typename Traits::pos_type  pos_type   ;
0043     typedef typename Traits::off_type  off_type   ;
0044     typedef ::boost::detail::winapi::HANDLE_ native_handle;
0045 
0046     /// Default construct the pipe. Will be opened.
0047     basic_pipe();
0048 
0049     ///Construct a named pipe.
0050     inline explicit basic_pipe(const std::string & name);
0051     /** Copy construct the pipe.
0052      *  \note Duplicated the handles.
0053      */
0054     inline basic_pipe(const basic_pipe& p);
0055     /** Move construct the pipe. */
0056     basic_pipe(basic_pipe&& lhs);
0057     /** Copy assign the pipe.
0058      *  \note Duplicated the handles.
0059      */
0060     inline basic_pipe& operator=(const basic_pipe& p);
0061     /** Move assign the pipe. */
0062     basic_pipe& operator=(basic_pipe&& lhs);
0063     /** Destructor closes the handles. */
0064     ~basic_pipe();
0065     /** Get the native handle of the source. */
0066     native_handle native_source() const;
0067     /** Get the native handle of the sink. */
0068     native_handle native_sink  () const;
0069 
0070     /** Assign a new value to the source */
0071     void assign_source(native_handle h);
0072     /** Assign a new value to the sink */
0073     void assign_sink  (native_handle h);
0074 
0075 
0076     ///Write data to the pipe.
0077     int_type write(const char_type * data, int_type count);
0078     ///Read data from the pipe.
0079     int_type read(char_type * data, int_type count);
0080     ///Check if the pipe is open.
0081     bool is_open();
0082     ///Close the pipe
0083     void close();
0084 };
0085 
0086 #endif
0087 
0088 
0089 
0090 typedef basic_pipe<char>     pipe;
0091 typedef basic_pipe<wchar_t> wpipe;
0092 
0093 
0094 /** Implementation of the stream buffer for a pipe.
0095  */
0096 template<
0097     class CharT,
0098     class Traits = std::char_traits<CharT>
0099 >
0100 struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
0101 {
0102     typedef basic_pipe<CharT, Traits> pipe_type;
0103 
0104     typedef           CharT            char_type  ;
0105     typedef           Traits           traits_type;
0106     typedef  typename Traits::int_type int_type   ;
0107     typedef  typename Traits::pos_type pos_type   ;
0108     typedef  typename Traits::off_type off_type   ;
0109 
0110     constexpr static int default_buffer_size = BOOST_PROCESS_PIPE_SIZE;
0111 
0112     ///Default constructor, will also construct the pipe.
0113     basic_pipebuf() : _write(default_buffer_size), _read(default_buffer_size)
0114     {
0115         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128);
0116         this->setp(_write.data(), _write.data() + _write.size());
0117     }
0118     ///Copy Constructor.
0119     basic_pipebuf(const basic_pipebuf & ) = default;
0120     ///Move Constructor
0121     basic_pipebuf(basic_pipebuf && ) = default;
0122 
0123     ///Destructor -> writes the frest of the data
0124     ~basic_pipebuf()
0125     {
0126         try 
0127         {
0128             if (basic_pipebuf::is_open())
0129                 basic_pipebuf::overflow(Traits::eof());
0130         }
0131         catch (process_error & )
0132         {
0133         }
0134     }
0135 
0136     ///Move construct from a pipe.
0137     basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
0138                                     _write(default_buffer_size),
0139                                     _read(default_buffer_size)
0140     {
0141         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128);
0142         this->setp(_write.data(), _write.data() + _write.size());
0143     }
0144     ///Construct from a pipe.
0145     basic_pipebuf(const pipe_type & p) : _pipe(p),
0146                                         _write(default_buffer_size),
0147                                         _read(default_buffer_size)
0148     {
0149         this->setg(_read.data(),  _read.data()+ 128,  _read.data() + 128);
0150         this->setp(_write.data(), _write.data() + _write.size());
0151     }
0152     ///Copy assign.
0153     basic_pipebuf& operator=(const basic_pipebuf & ) = delete;
0154     ///Move assign.
0155     basic_pipebuf& operator=(basic_pipebuf && ) = default;
0156     ///Move assign a pipe.
0157     basic_pipebuf& operator=(pipe_type && p)
0158     {
0159         _pipe = std::move(p);
0160         return *this;
0161     }
0162     ///Copy assign a pipe.
0163     basic_pipebuf& operator=(const pipe_type & p)
0164     {
0165         _pipe = p;
0166         return *this;
0167     }
0168     ///Writes characters to the associated output sequence from the put area
0169     int_type overflow(int_type ch = traits_type::eof()) override
0170     {
0171         if (_pipe.is_open() && (ch != traits_type::eof()))
0172         {
0173             if (this->pptr() == this->epptr())
0174             {
0175                 bool wr = this->_write_impl();
0176                 if (wr)
0177                 {
0178                     *this->pptr() = ch;
0179                     this->pbump(1);
0180                     return ch;
0181                 }
0182             }
0183             else
0184             {
0185                 *this->pptr() = ch;
0186                 this->pbump(1);
0187                 if (this->_write_impl())
0188                     return ch;
0189             }
0190         }
0191         else if (ch == traits_type::eof())
0192            this->sync();
0193 
0194         return traits_type::eof();
0195     }
0196     ///Synchronizes the buffers with the associated character sequence
0197     int sync() override { return this->_write_impl() ? 0 : -1; }
0198 
0199     ///Reads characters from the associated input sequence to the get area
0200     int_type underflow() override
0201     {
0202         if (!_pipe.is_open())
0203             return traits_type::eof();
0204 
0205         if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer
0206             this->setg(_read.data(),  _read.data()+ 10,  _read.data() + 10);
0207 
0208 
0209         auto len = &_read.back() - this->egptr() ;
0210         auto res = _pipe.read(
0211                         this->egptr(),
0212                         static_cast<typename pipe_type::int_type>(len));
0213         if (res == 0)
0214             return traits_type::eof();
0215 
0216         this->setg(this->eback(), this->gptr(), this->egptr() + res);
0217         auto val = *this->gptr();
0218 
0219         return traits_type::to_int_type(val);
0220     }
0221 
0222 
0223     ///Set the pipe of the streambuf.
0224     void pipe(pipe_type&& p)      {_pipe = std::move(p); }
0225     ///Set the pipe of the streambuf.
0226     void pipe(const pipe_type& p) {_pipe = p; }
0227     ///Get a reference to the pipe.
0228     pipe_type &      pipe() &       {return _pipe;}
0229     ///Get a const reference to the pipe.
0230     const pipe_type &pipe() const & {return _pipe;}
0231     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0232     pipe_type &&     pipe()  &&     {return std::move(_pipe);}
0233 
0234     ///Check if the pipe is open
0235     bool is_open() const {return _pipe.is_open(); }
0236 
0237     ///Open a new pipe
0238     basic_pipebuf<CharT, Traits>* open()
0239     {
0240         if (is_open())
0241             return nullptr;
0242         _pipe = pipe();
0243         return this;
0244     }
0245 
0246     ///Open a new named pipe
0247     basic_pipebuf<CharT, Traits>* open(const std::string & name)
0248     {
0249         if (is_open())
0250             return nullptr;
0251         _pipe = pipe(name);
0252         return this;
0253     }
0254 
0255     ///Flush the buffer & close the pipe
0256     basic_pipebuf<CharT, Traits>* close()
0257     {
0258         if (!is_open())
0259             return nullptr;
0260         try {
0261           overflow(Traits::eof());
0262           _pipe.close();
0263           return this;
0264         }
0265         catch(...)
0266         {
0267           _pipe.close();
0268           throw ;
0269         }
0270         return this;
0271     }
0272 private:
0273     pipe_type _pipe;
0274     std::vector<char_type> _write;
0275     std::vector<char_type> _read;
0276 
0277     bool _write_impl()
0278     {
0279         if (!_pipe.is_open())
0280             return false;
0281 
0282         auto base = this->pbase();
0283 
0284         if (base == this->pptr())
0285             return true;
0286 
0287         std::ptrdiff_t wrt = _pipe.write(base,
0288                 static_cast<typename pipe_type::int_type>(this->pptr() - base));
0289 
0290         std::ptrdiff_t diff = this->pptr() - base;
0291 
0292         if (wrt < diff)
0293             std::move(base + wrt, base + diff, base);
0294         else if (wrt == 0) //broken pipe
0295             return false;
0296 
0297         this->pbump(static_cast<int>(-wrt));
0298 
0299         return true;
0300     }
0301 };
0302 
0303 typedef basic_pipebuf<char>     pipebuf;
0304 typedef basic_pipebuf<wchar_t> wpipebuf;
0305 
0306 /** Implementation of a reading pipe stream.
0307  *
0308  */
0309 template<
0310     class CharT,
0311     class Traits = std::char_traits<CharT>
0312 >
0313 class basic_ipstream : public std::basic_istream<CharT, Traits>
0314 {
0315     mutable basic_pipebuf<CharT, Traits> _buf;
0316 public:
0317 
0318     typedef basic_pipe<CharT, Traits> pipe_type;
0319 
0320     typedef           CharT            char_type  ;
0321     typedef           Traits           traits_type;
0322     typedef  typename Traits::int_type int_type   ;
0323     typedef  typename Traits::pos_type pos_type   ;
0324     typedef  typename Traits::off_type off_type   ;
0325 
0326     ///Get access to the underlying stream_buf
0327     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0328 
0329     ///Default constructor.
0330     basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
0331     {
0332         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0333     };
0334     ///Copy constructor.
0335     basic_ipstream(const basic_ipstream & ) = delete;
0336     ///Move constructor.
0337     basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0338     {
0339         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0340     }
0341 
0342     ///Move construct from a pipe.
0343     basic_ipstream(pipe_type && p)      : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
0344     {
0345         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0346     }
0347 
0348     ///Copy construct from a pipe.
0349     basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p)
0350     {
0351         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0352     }
0353 
0354     ///Copy assignment.
0355     basic_ipstream& operator=(const basic_ipstream & ) = delete;
0356     ///Move assignment
0357     basic_ipstream& operator=(basic_ipstream && lhs)
0358     {
0359         std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
0360         _buf = std::move(lhs._buf);
0361         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0362         return *this;
0363     };
0364     ///Move assignment of a pipe.
0365     basic_ipstream& operator=(pipe_type && p)
0366     {
0367         _buf = std::move(p);
0368         return *this;
0369     }
0370     ///Copy assignment of a pipe.
0371     basic_ipstream& operator=(const pipe_type & p)
0372     {
0373         _buf = p;
0374         return *this;
0375     }
0376     ///Set the pipe of the streambuf.
0377     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0378     ///Set the pipe of the streambuf.
0379     void pipe(const pipe_type& p) {_buf.pipe(p); }
0380     ///Get a reference to the pipe.
0381     pipe_type &      pipe() &       {return _buf.pipe();}
0382     ///Get a const reference to the pipe.
0383     const pipe_type &pipe() const & {return _buf.pipe();}
0384     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0385     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0386     ///Check if the pipe is open
0387     bool is_open() const {return _buf.is_open();}
0388 
0389     ///Open a new pipe
0390     void open()
0391     {
0392         if (_buf.open() == nullptr)
0393             this->setstate(std::ios_base::failbit);
0394         else
0395             this->clear();
0396     }
0397 
0398     ///Open a new named pipe
0399     void open(const std::string & name)
0400     {
0401         if (_buf.open() == nullptr)
0402             this->setstate(std::ios_base::failbit);
0403         else
0404             this->clear();
0405     }
0406 
0407     ///Flush the buffer & close the pipe
0408     void close()
0409     {
0410         if (_buf.close() == nullptr)
0411             this->setstate(std::ios_base::failbit);
0412     }
0413 };
0414 
0415 typedef basic_ipstream<char>     ipstream;
0416 typedef basic_ipstream<wchar_t> wipstream;
0417 
0418 /** Implementation of a write pipe stream.
0419  *
0420  */
0421 template<
0422     class CharT,
0423     class Traits = std::char_traits<CharT>
0424 >
0425 class basic_opstream : public std::basic_ostream<CharT, Traits>
0426 {
0427     mutable basic_pipebuf<CharT, Traits> _buf;
0428 public:
0429     typedef basic_pipe<CharT, Traits> pipe_type;
0430 
0431     typedef           CharT            char_type  ;
0432     typedef           Traits           traits_type;
0433     typedef  typename Traits::int_type int_type   ;
0434     typedef  typename Traits::pos_type pos_type   ;
0435     typedef  typename Traits::off_type off_type   ;
0436 
0437 
0438     ///Get access to the underlying stream_buf
0439     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0440 
0441     ///Default constructor.
0442     basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
0443     {
0444         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0445     };
0446     ///Copy constructor.
0447     basic_opstream(const basic_opstream & ) = delete;
0448     ///Move constructor.
0449     basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0450     {
0451         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0452     }
0453     ///Move construct from a pipe.
0454     basic_opstream(pipe_type && p)      : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
0455     {
0456         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0457     };
0458     ///Copy construct from a pipe.
0459     basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p)
0460     {
0461         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0462     };
0463     ///Copy assignment.
0464     basic_opstream& operator=(const basic_opstream & ) = delete;
0465     ///Move assignment
0466     basic_opstream& operator=(basic_opstream && lhs)
0467     {
0468         std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
0469         _buf = std::move(lhs._buf);
0470         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0471         return *this;
0472     };
0473 
0474     ///Move assignment of a pipe.
0475     basic_opstream& operator=(pipe_type && p)
0476     {
0477         _buf = std::move(p);
0478         return *this;
0479     }
0480     ///Copy assignment of a pipe.
0481     basic_opstream& operator=(const pipe_type & p)
0482     {
0483         _buf = p;
0484         return *this;
0485     }
0486     ///Set the pipe of the streambuf.
0487     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0488     ///Set the pipe of the streambuf.
0489     void pipe(const pipe_type& p) {_buf.pipe(p); }
0490     ///Get a reference to the pipe.
0491     pipe_type &      pipe() &       {return _buf.pipe();}
0492     ///Get a const reference to the pipe.
0493     const pipe_type &pipe() const & {return _buf.pipe();}
0494     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0495     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0496 
0497     ///Open a new pipe
0498     void open()
0499     {
0500         if (_buf.open() == nullptr)
0501             this->setstate(std::ios_base::failbit);
0502         else
0503             this->clear();
0504     }
0505 
0506     ///Open a new named pipe
0507     void open(const std::string & name)
0508     {
0509         if (_buf.open() == nullptr)
0510             this->setstate(std::ios_base::failbit);
0511         else
0512             this->clear();
0513     }
0514 
0515     ///Flush the buffer & close the pipe
0516     void close()
0517     {
0518         if (_buf.close() == nullptr)
0519             this->setstate(std::ios_base::failbit);
0520     }
0521 };
0522 
0523 typedef basic_opstream<char>     opstream;
0524 typedef basic_opstream<wchar_t> wopstream;
0525 
0526 
0527 /** Implementation of a read-write pipe stream.
0528  *
0529  */
0530 template<
0531     class CharT,
0532     class Traits = std::char_traits<CharT>
0533 >
0534 class basic_pstream : public std::basic_iostream<CharT, Traits>
0535 {
0536     mutable basic_pipebuf<CharT, Traits> _buf;
0537 public:
0538     typedef basic_pipe<CharT, Traits> pipe_type;
0539 
0540     typedef           CharT            char_type  ;
0541     typedef           Traits           traits_type;
0542     typedef  typename Traits::int_type int_type   ;
0543     typedef  typename Traits::pos_type pos_type   ;
0544     typedef  typename Traits::off_type off_type   ;
0545 
0546 
0547     ///Get access to the underlying stream_buf
0548     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0549 
0550     ///Default constructor.
0551     basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
0552     {
0553         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0554     };
0555     ///Copy constructor.
0556     basic_pstream(const basic_pstream & ) = delete;
0557     ///Move constructor.
0558     basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0559     {
0560         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0561     }
0562     ///Move construct from a pipe.
0563     basic_pstream(pipe_type && p)      : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
0564     {
0565         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0566     };
0567     ///Copy construct from a pipe.
0568     basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p)
0569     {
0570         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0571     };
0572     ///Copy assignment.
0573     basic_pstream& operator=(const basic_pstream & ) = delete;
0574     ///Move assignment
0575     basic_pstream& operator=(basic_pstream && lhs)
0576     {
0577         std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
0578         _buf = std::move(lhs._buf);
0579         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0580         return *this;
0581     };
0582     ///Move assignment of a pipe.
0583     basic_pstream& operator=(pipe_type && p)
0584     {
0585         _buf = std::move(p);
0586         return *this;
0587     }
0588     ///Copy assignment of a pipe.
0589     basic_pstream& operator=(const pipe_type & p)
0590     {
0591         _buf = p;
0592         return *this;
0593     }
0594     ///Set the pipe of the streambuf.
0595     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0596     ///Set the pipe of the streambuf.
0597     void pipe(const pipe_type& p) {_buf.pipe(p); }
0598     ///Get a reference to the pipe.
0599     pipe_type &      pipe() &       {return _buf.pipe();}
0600     ///Get a const reference to the pipe.
0601     const pipe_type &pipe() const & {return _buf.pipe();}
0602     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0603     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0604 
0605     ///Open a new pipe
0606     void open()
0607     {
0608         if (_buf.open() == nullptr)
0609             this->setstate(std::ios_base::failbit);
0610         else
0611             this->clear();
0612     }
0613 
0614     ///Open a new named pipe
0615     void open(const std::string & name)
0616     {
0617         if (_buf.open() == nullptr)
0618             this->setstate(std::ios_base::failbit);
0619         else
0620             this->clear();
0621     }
0622 
0623     ///Flush the buffer & close the pipe
0624     void close()
0625     {
0626         if (_buf.close() == nullptr)
0627             this->setstate(std::ios_base::failbit);
0628     }
0629 };
0630 
0631 typedef basic_pstream<char>     pstream;
0632 typedef basic_pstream<wchar_t> wpstream;
0633 
0634 
0635 
0636 }}}
0637 
0638 #endif