File indexing completed on 2025-01-30 09:58:04
0001
0002
0003
0004
0005
0006
0007
0008
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
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
0047 basic_pipe();
0048
0049
0050 inline explicit basic_pipe(const std::string & name);
0051
0052
0053
0054 inline basic_pipe(const basic_pipe& p);
0055
0056 basic_pipe(basic_pipe&& lhs);
0057
0058
0059
0060 inline basic_pipe& operator=(const basic_pipe& p);
0061
0062 basic_pipe& operator=(basic_pipe&& lhs);
0063
0064 ~basic_pipe();
0065
0066 native_handle native_source() const;
0067
0068 native_handle native_sink () const;
0069
0070
0071 void assign_source(native_handle h);
0072
0073 void assign_sink (native_handle h);
0074
0075
0076
0077 int_type write(const char_type * data, int_type count);
0078
0079 int_type read(char_type * data, int_type count);
0080
0081 bool is_open();
0082
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
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
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
0119 basic_pipebuf(const basic_pipebuf & ) = default;
0120
0121 basic_pipebuf(basic_pipebuf && ) = default;
0122
0123
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
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
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
0153 basic_pipebuf& operator=(const basic_pipebuf & ) = delete;
0154
0155 basic_pipebuf& operator=(basic_pipebuf && ) = default;
0156
0157 basic_pipebuf& operator=(pipe_type && p)
0158 {
0159 _pipe = std::move(p);
0160 return *this;
0161 }
0162
0163 basic_pipebuf& operator=(const pipe_type & p)
0164 {
0165 _pipe = p;
0166 return *this;
0167 }
0168
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
0197 int sync() override { return this->_write_impl() ? 0 : -1; }
0198
0199
0200 int_type underflow() override
0201 {
0202 if (!_pipe.is_open())
0203 return traits_type::eof();
0204
0205 if (this->egptr() == &_read.back())
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
0224 void pipe(pipe_type&& p) {_pipe = std::move(p); }
0225
0226 void pipe(const pipe_type& p) {_pipe = p; }
0227
0228 pipe_type & pipe() & {return _pipe;}
0229
0230 const pipe_type &pipe() const & {return _pipe;}
0231
0232 pipe_type && pipe() && {return std::move(_pipe);}
0233
0234
0235 bool is_open() const {return _pipe.is_open(); }
0236
0237
0238 basic_pipebuf<CharT, Traits>* open()
0239 {
0240 if (is_open())
0241 return nullptr;
0242 _pipe = pipe();
0243 return this;
0244 }
0245
0246
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
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)
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
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
0318 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0319
0320
0321 basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
0322 {
0323 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0324 };
0325
0326 basic_ipstream(const basic_ipstream & ) = delete;
0327
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
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
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
0346 basic_ipstream& operator=(const basic_ipstream & ) = delete;
0347
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
0356 basic_ipstream& operator=(pipe_type && p)
0357 {
0358 _buf = std::move(p);
0359 return *this;
0360 }
0361
0362 basic_ipstream& operator=(const pipe_type & p)
0363 {
0364 _buf = p;
0365 return *this;
0366 }
0367
0368 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0369
0370 void pipe(const pipe_type& p) {_buf.pipe(p); }
0371
0372 pipe_type & pipe() & {return _buf.pipe();}
0373
0374 const pipe_type &pipe() const & {return _buf.pipe();}
0375
0376 pipe_type && pipe() && {return std::move(_buf).pipe();}
0377
0378 bool is_open() const {return _buf.is_open();}
0379
0380
0381 void open()
0382 {
0383 if (_buf.open() == nullptr)
0384 this->setstate(std::ios_base::failbit);
0385 else
0386 this->clear();
0387 }
0388
0389
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
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
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
0430 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0431
0432
0433 basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
0434 {
0435 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0436 };
0437
0438 basic_opstream(const basic_opstream & ) = delete;
0439
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
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
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
0455 basic_opstream& operator=(const basic_opstream & ) = delete;
0456
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
0466 basic_opstream& operator=(pipe_type && p)
0467 {
0468 _buf = std::move(p);
0469 return *this;
0470 }
0471
0472 basic_opstream& operator=(const pipe_type & p)
0473 {
0474 _buf = p;
0475 return *this;
0476 }
0477
0478 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0479
0480 void pipe(const pipe_type& p) {_buf.pipe(p); }
0481
0482 pipe_type & pipe() & {return _buf.pipe();}
0483
0484 const pipe_type &pipe() const & {return _buf.pipe();}
0485
0486 pipe_type && pipe() && {return std::move(_buf).pipe();}
0487
0488
0489 void open()
0490 {
0491 if (_buf.open() == nullptr)
0492 this->setstate(std::ios_base::failbit);
0493 else
0494 this->clear();
0495 }
0496
0497
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
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
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
0539 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0540
0541
0542 basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
0543 {
0544 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0545 };
0546
0547 basic_pstream(const basic_pstream & ) = delete;
0548
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
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
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
0564 basic_pstream& operator=(const basic_pstream & ) = delete;
0565
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
0574 basic_pstream& operator=(pipe_type && p)
0575 {
0576 _buf = std::move(p);
0577 return *this;
0578 }
0579
0580 basic_pstream& operator=(const pipe_type & p)
0581 {
0582 _buf = p;
0583 return *this;
0584 }
0585
0586 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0587
0588 void pipe(const pipe_type& p) {_buf.pipe(p); }
0589
0590 pipe_type & pipe() & {return _buf.pipe();}
0591
0592 const pipe_type &pipe() const & {return _buf.pipe();}
0593
0594 pipe_type && pipe() && {return std::move(_buf).pipe();}
0595
0596
0597 void open()
0598 {
0599 if (_buf.open() == nullptr)
0600 this->setstate(std::ios_base::failbit);
0601 else
0602 this->clear();
0603 }
0604
0605
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
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