File indexing completed on 2025-12-16 10:07:14
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/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
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 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)
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
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
0327 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0328
0329
0330 basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
0331 {
0332 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
0333 };
0334
0335 basic_ipstream(const basic_ipstream & ) = delete;
0336
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
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
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
0355 basic_ipstream& operator=(const basic_ipstream & ) = delete;
0356
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
0365 basic_ipstream& operator=(pipe_type && p)
0366 {
0367 _buf = std::move(p);
0368 return *this;
0369 }
0370
0371 basic_ipstream& operator=(const pipe_type & p)
0372 {
0373 _buf = p;
0374 return *this;
0375 }
0376
0377 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0378
0379 void pipe(const pipe_type& p) {_buf.pipe(p); }
0380
0381 pipe_type & pipe() & {return _buf.pipe();}
0382
0383 const pipe_type &pipe() const & {return _buf.pipe();}
0384
0385 pipe_type && pipe() && {return std::move(_buf).pipe();}
0386
0387 bool is_open() const {return _buf.is_open();}
0388
0389
0390 void open()
0391 {
0392 if (_buf.open() == nullptr)
0393 this->setstate(std::ios_base::failbit);
0394 else
0395 this->clear();
0396 }
0397
0398
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
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
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
0439 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0440
0441
0442 basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
0443 {
0444 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
0445 };
0446
0447 basic_opstream(const basic_opstream & ) = delete;
0448
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
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
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
0464 basic_opstream& operator=(const basic_opstream & ) = delete;
0465
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
0475 basic_opstream& operator=(pipe_type && p)
0476 {
0477 _buf = std::move(p);
0478 return *this;
0479 }
0480
0481 basic_opstream& operator=(const pipe_type & p)
0482 {
0483 _buf = p;
0484 return *this;
0485 }
0486
0487 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0488
0489 void pipe(const pipe_type& p) {_buf.pipe(p); }
0490
0491 pipe_type & pipe() & {return _buf.pipe();}
0492
0493 const pipe_type &pipe() const & {return _buf.pipe();}
0494
0495 pipe_type && pipe() && {return std::move(_buf).pipe();}
0496
0497
0498 void open()
0499 {
0500 if (_buf.open() == nullptr)
0501 this->setstate(std::ios_base::failbit);
0502 else
0503 this->clear();
0504 }
0505
0506
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
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
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
0548 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
0549
0550
0551 basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
0552 {
0553 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
0554 };
0555
0556 basic_pstream(const basic_pstream & ) = delete;
0557
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
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
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
0573 basic_pstream& operator=(const basic_pstream & ) = delete;
0574
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
0583 basic_pstream& operator=(pipe_type && p)
0584 {
0585 _buf = std::move(p);
0586 return *this;
0587 }
0588
0589 basic_pstream& operator=(const pipe_type & p)
0590 {
0591 _buf = p;
0592 return *this;
0593 }
0594
0595 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
0596
0597 void pipe(const pipe_type& p) {_buf.pipe(p); }
0598
0599 pipe_type & pipe() & {return _buf.pipe();}
0600
0601 const pipe_type &pipe() const & {return _buf.pipe();}
0602
0603 pipe_type && pipe() && {return std::move(_buf).pipe();}
0604
0605
0606 void open()
0607 {
0608 if (_buf.open() == nullptr)
0609 this->setstate(std::ios_base::failbit);
0610 else
0611 this->clear();
0612 }
0613
0614
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
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