Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:58:04

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/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/detail/posix/basic_pipe.hpp>
0023 #elif defined(BOOST_WINDOWS_API)
0024 #include <boost/process/detail/windows/basic_pipe.hpp>
0025 #endif
0026 
0027 namespace boost { namespace process {
0028 
0029 using ::boost::process::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         overflow(Traits::eof());
0261         return this;
0262     }
0263 private:
0264     pipe_type _pipe;
0265     std::vector<char_type> _write;
0266     std::vector<char_type> _read;
0267 
0268     bool _write_impl()
0269     {
0270         if (!_pipe.is_open())
0271             return false;
0272 
0273         auto base = this->pbase();
0274 
0275         if (base == this->pptr())
0276             return true;
0277 
0278         std::ptrdiff_t wrt = _pipe.write(base,
0279                 static_cast<typename pipe_type::int_type>(this->pptr() - base));
0280 
0281         std::ptrdiff_t diff = this->pptr() - base;
0282 
0283         if (wrt < diff)
0284             std::move(base + wrt, base + diff, base);
0285         else if (wrt == 0) //broken pipe
0286             return false;
0287 
0288         this->pbump(static_cast<int>(-wrt));
0289 
0290         return true;
0291     }
0292 };
0293 
0294 typedef basic_pipebuf<char>     pipebuf;
0295 typedef basic_pipebuf<wchar_t> wpipebuf;
0296 
0297 /** Implementation of a reading pipe stream.
0298  *
0299  */
0300 template<
0301     class CharT,
0302     class Traits = std::char_traits<CharT>
0303 >
0304 class basic_ipstream : public std::basic_istream<CharT, Traits>
0305 {
0306     mutable basic_pipebuf<CharT, Traits> _buf;
0307 public:
0308 
0309     typedef basic_pipe<CharT, Traits> pipe_type;
0310 
0311     typedef           CharT            char_type  ;
0312     typedef           Traits           traits_type;
0313     typedef  typename Traits::int_type int_type   ;
0314     typedef  typename Traits::pos_type pos_type   ;
0315     typedef  typename Traits::off_type off_type   ;
0316 
0317     ///Get access to the underlying stream_buf
0318     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0319 
0320     ///Default constructor.
0321     basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
0322     {
0323         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0324     };
0325     ///Copy constructor.
0326     basic_ipstream(const basic_ipstream & ) = delete;
0327     ///Move constructor.
0328     basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0329     {
0330         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0331     }
0332 
0333     ///Move construct from a pipe.
0334     basic_ipstream(pipe_type && p)      : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
0335     {
0336         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0337     }
0338 
0339     ///Copy construct from a pipe.
0340     basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p)
0341     {
0342         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0343     }
0344 
0345     ///Copy assignment.
0346     basic_ipstream& operator=(const basic_ipstream & ) = delete;
0347     ///Move assignment
0348     basic_ipstream& operator=(basic_ipstream && lhs)
0349     {
0350         std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
0351         _buf = std::move(lhs._buf);
0352         std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0353         return *this;
0354     };
0355     ///Move assignment of a pipe.
0356     basic_ipstream& operator=(pipe_type && p)
0357     {
0358         _buf = std::move(p);
0359         return *this;
0360     }
0361     ///Copy assignment of a pipe.
0362     basic_ipstream& operator=(const pipe_type & p)
0363     {
0364         _buf = p;
0365         return *this;
0366     }
0367     ///Set the pipe of the streambuf.
0368     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0369     ///Set the pipe of the streambuf.
0370     void pipe(const pipe_type& p) {_buf.pipe(p); }
0371     ///Get a reference to the pipe.
0372     pipe_type &      pipe() &       {return _buf.pipe();}
0373     ///Get a const reference to the pipe.
0374     const pipe_type &pipe() const & {return _buf.pipe();}
0375     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0376     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0377     ///Check if the pipe is open
0378     bool is_open() const {return _buf.is_open();}
0379 
0380     ///Open a new pipe
0381     void open()
0382     {
0383         if (_buf.open() == nullptr)
0384             this->setstate(std::ios_base::failbit);
0385         else
0386             this->clear();
0387     }
0388 
0389     ///Open a new named pipe
0390     void open(const std::string & name)
0391     {
0392         if (_buf.open() == nullptr)
0393             this->setstate(std::ios_base::failbit);
0394         else
0395             this->clear();
0396     }
0397 
0398     ///Flush the buffer & close the pipe
0399     void close()
0400     {
0401         if (_buf.close() == nullptr)
0402             this->setstate(std::ios_base::failbit);
0403     }
0404 };
0405 
0406 typedef basic_ipstream<char>     ipstream;
0407 typedef basic_ipstream<wchar_t> wipstream;
0408 
0409 /** Implementation of a write pipe stream.
0410  *
0411  */
0412 template<
0413     class CharT,
0414     class Traits = std::char_traits<CharT>
0415 >
0416 class basic_opstream : public std::basic_ostream<CharT, Traits>
0417 {
0418     mutable basic_pipebuf<CharT, Traits> _buf;
0419 public:
0420     typedef basic_pipe<CharT, Traits> pipe_type;
0421 
0422     typedef           CharT            char_type  ;
0423     typedef           Traits           traits_type;
0424     typedef  typename Traits::int_type int_type   ;
0425     typedef  typename Traits::pos_type pos_type   ;
0426     typedef  typename Traits::off_type off_type   ;
0427 
0428 
0429     ///Get access to the underlying stream_buf
0430     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0431 
0432     ///Default constructor.
0433     basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
0434     {
0435         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0436     };
0437     ///Copy constructor.
0438     basic_opstream(const basic_opstream & ) = delete;
0439     ///Move constructor.
0440     basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0441     {
0442         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0443     }
0444     ///Move construct from a pipe.
0445     basic_opstream(pipe_type && p)      : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
0446     {
0447         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0448     };
0449     ///Copy construct from a pipe.
0450     basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p)
0451     {
0452         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0453     };
0454     ///Copy assignment.
0455     basic_opstream& operator=(const basic_opstream & ) = delete;
0456     ///Move assignment
0457     basic_opstream& operator=(basic_opstream && lhs)
0458     {
0459         std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
0460         _buf = std::move(lhs._buf);
0461         std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0462         return *this;
0463     };
0464 
0465     ///Move assignment of a pipe.
0466     basic_opstream& operator=(pipe_type && p)
0467     {
0468         _buf = std::move(p);
0469         return *this;
0470     }
0471     ///Copy assignment of a pipe.
0472     basic_opstream& operator=(const pipe_type & p)
0473     {
0474         _buf = p;
0475         return *this;
0476     }
0477     ///Set the pipe of the streambuf.
0478     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0479     ///Set the pipe of the streambuf.
0480     void pipe(const pipe_type& p) {_buf.pipe(p); }
0481     ///Get a reference to the pipe.
0482     pipe_type &      pipe() &       {return _buf.pipe();}
0483     ///Get a const reference to the pipe.
0484     const pipe_type &pipe() const & {return _buf.pipe();}
0485     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0486     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0487 
0488     ///Open a new pipe
0489     void open()
0490     {
0491         if (_buf.open() == nullptr)
0492             this->setstate(std::ios_base::failbit);
0493         else
0494             this->clear();
0495     }
0496 
0497     ///Open a new named pipe
0498     void open(const std::string & name)
0499     {
0500         if (_buf.open() == nullptr)
0501             this->setstate(std::ios_base::failbit);
0502         else
0503             this->clear();
0504     }
0505 
0506     ///Flush the buffer & close the pipe
0507     void close()
0508     {
0509         if (_buf.close() == nullptr)
0510             this->setstate(std::ios_base::failbit);
0511     }
0512 };
0513 
0514 typedef basic_opstream<char>     opstream;
0515 typedef basic_opstream<wchar_t> wopstream;
0516 
0517 
0518 /** Implementation of a read-write pipe stream.
0519  *
0520  */
0521 template<
0522     class CharT,
0523     class Traits = std::char_traits<CharT>
0524 >
0525 class basic_pstream : public std::basic_iostream<CharT, Traits>
0526 {
0527     mutable basic_pipebuf<CharT, Traits> _buf;
0528 public:
0529     typedef basic_pipe<CharT, Traits> pipe_type;
0530 
0531     typedef           CharT            char_type  ;
0532     typedef           Traits           traits_type;
0533     typedef  typename Traits::int_type int_type   ;
0534     typedef  typename Traits::pos_type pos_type   ;
0535     typedef  typename Traits::off_type off_type   ;
0536 
0537 
0538     ///Get access to the underlying stream_buf
0539     basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0540 
0541     ///Default constructor.
0542     basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
0543     {
0544         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0545     };
0546     ///Copy constructor.
0547     basic_pstream(const basic_pstream & ) = delete;
0548     ///Move constructor.
0549     basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
0550     {
0551         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0552     }
0553     ///Move construct from a pipe.
0554     basic_pstream(pipe_type && p)      : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
0555     {
0556         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0557     };
0558     ///Copy construct from a pipe.
0559     basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p)
0560     {
0561         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0562     };
0563     ///Copy assignment.
0564     basic_pstream& operator=(const basic_pstream & ) = delete;
0565     ///Move assignment
0566     basic_pstream& operator=(basic_pstream && lhs)
0567     {
0568         std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
0569         _buf = std::move(lhs._buf);
0570         std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0571         return *this;
0572     };
0573     ///Move assignment of a pipe.
0574     basic_pstream& operator=(pipe_type && p)
0575     {
0576         _buf = std::move(p);
0577         return *this;
0578     }
0579     ///Copy assignment of a pipe.
0580     basic_pstream& operator=(const pipe_type & p)
0581     {
0582         _buf = p;
0583         return *this;
0584     }
0585     ///Set the pipe of the streambuf.
0586     void pipe(pipe_type&& p)      {_buf.pipe(std::move(p)); }
0587     ///Set the pipe of the streambuf.
0588     void pipe(const pipe_type& p) {_buf.pipe(p); }
0589     ///Get a reference to the pipe.
0590     pipe_type &      pipe() &       {return _buf.pipe();}
0591     ///Get a const reference to the pipe.
0592     const pipe_type &pipe() const & {return _buf.pipe();}
0593     ///Get a rvalue reference to the pipe. Qualified as rvalue.
0594     pipe_type &&     pipe()  &&     {return std::move(_buf).pipe();}
0595 
0596     ///Open a new pipe
0597     void open()
0598     {
0599         if (_buf.open() == nullptr)
0600             this->setstate(std::ios_base::failbit);
0601         else
0602             this->clear();
0603     }
0604 
0605     ///Open a new named pipe
0606     void open(const std::string & name)
0607     {
0608         if (_buf.open() == nullptr)
0609             this->setstate(std::ios_base::failbit);
0610         else
0611             this->clear();
0612     }
0613 
0614     ///Flush the buffer & close the pipe
0615     void close()
0616     {
0617         if (_buf.close() == nullptr)
0618             this->setstate(std::ios_base::failbit);
0619     }
0620 };
0621 
0622 typedef basic_pstream<char>     pstream;
0623 typedef basic_pstream<wchar_t> wpstream;
0624 
0625 
0626 
0627 }}
0628 
0629 
0630 
0631 #endif