]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/pipe.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / process / pipe.hpp
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.
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 ///Destructor -> writes the frest of the data
124 ~basic_pipebuf()
125 {
126 if (is_open())
127 overflow(Traits::eof());
128 }
129
130 ///Move construct from a pipe.
131 basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
132 _write(default_buffer_size),
133 _read(default_buffer_size)
134 {
135 this->setg(_read.data(), _read.data()+ 128, _read.data() + 128);
136 this->setp(_write.data(), _write.data() + _write.size());
137 }
138 ///Construct from a pipe.
139 basic_pipebuf(const pipe_type & p) : _pipe(p),
140 _write(default_buffer_size),
141 _read(default_buffer_size)
142 {
143 this->setg(_read.data(), _read.data()+ 128, _read.data() + 128);
144 this->setp(_write.data(), _write.data() + _write.size());
145 }
146 ///Copy assign.
147 basic_pipebuf& operator=(const basic_pipebuf & ) = delete;
148 ///Move assign.
149 basic_pipebuf& operator=(basic_pipebuf && ) = default;
150 ///Move assign a pipe.
151 basic_pipebuf& operator=(pipe_type && p)
152 {
153 _pipe = std::move(p);
154 return *this;
155 }
156 ///Copy assign a pipe.
157 basic_pipebuf& operator=(const pipe_type & p)
158 {
159 _pipe = p;
160 return *this;
161 }
162 ///Writes characters to the associated output sequence from the put area
163 int_type overflow(int_type ch = traits_type::eof()) override
164 {
165 if (_pipe.is_open() && (ch != traits_type::eof()))
166 {
167 if (this->pptr() == this->epptr())
168 {
169 bool wr = this->_write_impl();
170 *this->pptr() = ch;
171 this->pbump(1);
172 if (wr)
173 return ch;
174 }
175 else
176 {
177 *this->pptr() = ch;
178 this->pbump(1);
179 if (this->_write_impl())
180 return ch;
181 }
182 }
183 else if (ch == traits_type::eof())
184 this->sync();
185
186 return traits_type::eof();
187 }
188 ///Synchronizes the buffers with the associated character sequence
189 int sync() override { return this->_write_impl() ? 0 : -1; }
190
191 ///Reads characters from the associated input sequence to the get area
192 int_type underflow() override
193 {
194 if (!_pipe.is_open())
195 return traits_type::eof();
196
197 if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer
198 this->setg(_read.data(), _read.data()+ 10, _read.data() + 10);
199
200
201 auto len = &_read.back() - this->egptr() ;
202 auto res = _pipe.read(
203 this->egptr(),
204 static_cast<typename pipe_type::int_type>(len));
205 if (res == 0)
206 return traits_type::eof();
207
208 this->setg(this->eback(), this->gptr(), this->egptr() + res);
209 auto val = *this->gptr();
210
211 return traits_type::to_int_type(val);
212 }
213
214
215 ///Set the pipe of the streambuf.
216 void pipe(pipe_type&& p) {_pipe = std::move(p); }
217 ///Set the pipe of the streambuf.
218 void pipe(const pipe_type& p) {_pipe = p; }
219 ///Get a reference to the pipe.
220 pipe_type & pipe() & {return _pipe;}
221 ///Get a const reference to the pipe.
222 const pipe_type &pipe() const & {return _pipe;}
223 ///Get a rvalue reference to the pipe. Qualified as rvalue.
224 pipe_type && pipe() && {return std::move(_pipe);}
225
226 ///Check if the pipe is open
227 bool is_open() const {return _pipe.is_open(); }
228
229 ///Open a new pipe
230 basic_pipebuf<CharT, Traits>* open()
231 {
232 if (is_open())
233 return nullptr;
234 _pipe = pipe();
235 return this;
236 }
237
238 ///Open a new named pipe
239 basic_pipebuf<CharT, Traits>* open(const std::string & name)
240 {
241 if (is_open())
242 return nullptr;
243 _pipe = pipe(name);
244 return this;
245 }
246
247 ///Flush the buffer & close the pipe
248 basic_pipebuf<CharT, Traits>* close()
249 {
250 if (!is_open())
251 return nullptr;
252 overflow(Traits::eof());
253 return this;
254 }
255 private:
256 pipe_type _pipe;
257 std::vector<char_type> _write;
258 std::vector<char_type> _read;
259
260 bool _write_impl()
261 {
262 if (!_pipe.is_open())
263 return false;
264
265 auto base = this->pbase();
266
267 if (base == this->pptr())
268 return true;
269
270 std::ptrdiff_t wrt = _pipe.write(base,
271 static_cast<typename pipe_type::int_type>(this->pptr() - base));
272
273 std::ptrdiff_t diff = this->pptr() - base;
274
275 if (wrt < diff)
276 std::move(base + wrt, base + diff, base);
277 else if (wrt == 0) //broken pipe
278 return false;
279
280 this->pbump(-wrt);
281
282 return true;
283 }
284 };
285
286 typedef basic_pipebuf<char> pipebuf;
287 typedef basic_pipebuf<wchar_t> wpipebuf;
288
289 /** Implementation of a reading pipe stream.
290 *
291 */
292 template<
293 class CharT,
294 class Traits = std::char_traits<CharT>
295 >
296 class basic_ipstream : public std::basic_istream<CharT, Traits>
297 {
298 mutable basic_pipebuf<CharT, Traits> _buf;
299 public:
300
301 typedef basic_pipe<CharT, Traits> pipe_type;
302
303 typedef CharT char_type ;
304 typedef Traits traits_type;
305 typedef typename Traits::int_type int_type ;
306 typedef typename Traits::pos_type pos_type ;
307 typedef typename Traits::off_type off_type ;
308
309 ///Get access to the underlying stream_buf
310 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
311
312 ///Default constructor.
313 basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
314 {
315 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
316 };
317 ///Copy constructor.
318 basic_ipstream(const basic_ipstream & ) = delete;
319 ///Move constructor.
320 basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
321 {
322 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
323 }
324
325 ///Move construct from a pipe.
326 basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
327 {
328 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
329 }
330
331 ///Copy construct from a pipe.
332 basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p)
333 {
334 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
335 }
336
337 ///Copy assignment.
338 basic_ipstream& operator=(const basic_ipstream & ) = delete;
339 ///Move assignment
340 basic_ipstream& operator=(basic_ipstream && lhs)
341 {
342 std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
343 _buf = std::move(lhs);
344 std::basic_istream<CharT, Traits>::rdbuf(&_buf);
345 };
346 ///Move assignment of a pipe.
347 basic_ipstream& operator=(pipe_type && p)
348 {
349 _buf = std::move(p);
350 return *this;
351 }
352 ///Copy assignment of a pipe.
353 basic_ipstream& operator=(const pipe_type & p)
354 {
355 _buf = p;
356 return *this;
357 }
358 ///Set the pipe of the streambuf.
359 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
360 ///Set the pipe of the streambuf.
361 void pipe(const pipe_type& p) {_buf.pipe(p); }
362 ///Get a reference to the pipe.
363 pipe_type & pipe() & {return _buf.pipe();}
364 ///Get a const reference to the pipe.
365 const pipe_type &pipe() const & {return _buf.pipe();}
366 ///Get a rvalue reference to the pipe. Qualified as rvalue.
367 pipe_type && pipe() && {return std::move(_buf).pipe();}
368 ///Check if the pipe is open
369 bool is_open() const {return _buf->is_open();}
370
371 ///Open a new pipe
372 void open()
373 {
374 if (_buf.open() == nullptr)
375 this->setstate(std::ios_base::failbit);
376 else
377 this->clear();
378 }
379
380 ///Open a new named pipe
381 void open(const std::string & name)
382 {
383 if (_buf.open() == nullptr)
384 this->setstate(std::ios_base::failbit);
385 else
386 this->clear();
387 }
388
389 ///Flush the buffer & close the pipe
390 void close()
391 {
392 if (_buf.close() == nullptr)
393 this->setstate(std::ios_base::failbit);
394 }
395 };
396
397 typedef basic_ipstream<char> ipstream;
398 typedef basic_ipstream<wchar_t> wipstream;
399
400 /** Implementation of a write pipe stream.
401 *
402 */
403 template<
404 class CharT,
405 class Traits = std::char_traits<CharT>
406 >
407 class basic_opstream : public std::basic_ostream<CharT, Traits>
408 {
409 mutable basic_pipebuf<CharT, Traits> _buf;
410 public:
411 typedef basic_pipe<CharT, Traits> pipe_type;
412
413 typedef CharT char_type ;
414 typedef Traits traits_type;
415 typedef typename Traits::int_type int_type ;
416 typedef typename Traits::pos_type pos_type ;
417 typedef typename Traits::off_type off_type ;
418
419
420 ///Get access to the underlying stream_buf
421 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
422
423 ///Default constructor.
424 basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
425 {
426 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
427 };
428 ///Copy constructor.
429 basic_opstream(const basic_opstream & ) = delete;
430 ///Move constructor.
431 basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
432 {
433 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
434 }
435 ///Move construct from a pipe.
436 basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
437 {
438 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
439 };
440 ///Copy construct from a pipe.
441 basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p)
442 {
443 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
444 };
445 ///Copy assignment.
446 basic_opstream& operator=(const basic_opstream & ) = delete;
447 ///Move assignment
448 basic_opstream& operator=(basic_opstream && lhs)
449 {
450 std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
451 _buf = std::move(lhs);
452 std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
453 };
454
455 ///Move assignment of a pipe.
456 basic_opstream& operator=(pipe_type && p)
457 {
458 _buf = std::move(p);
459 return *this;
460 }
461 ///Copy assignment of a pipe.
462 basic_opstream& operator=(const pipe_type & p)
463 {
464 _buf = p;
465 return *this;
466 }
467 ///Set the pipe of the streambuf.
468 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
469 ///Set the pipe of the streambuf.
470 void pipe(const pipe_type& p) {_buf.pipe(p); }
471 ///Get a reference to the pipe.
472 pipe_type & pipe() & {return _buf.pipe();}
473 ///Get a const reference to the pipe.
474 const pipe_type &pipe() const & {return _buf.pipe();}
475 ///Get a rvalue reference to the pipe. Qualified as rvalue.
476 pipe_type && pipe() && {return std::move(_buf).pipe();}
477
478 ///Open a new pipe
479 void open()
480 {
481 if (_buf.open() == nullptr)
482 this->setstate(std::ios_base::failbit);
483 else
484 this->clear();
485 }
486
487 ///Open a new named pipe
488 void open(const std::string & name)
489 {
490 if (_buf.open() == nullptr)
491 this->setstate(std::ios_base::failbit);
492 else
493 this->clear();
494 }
495
496 ///Flush the buffer & close the pipe
497 void close()
498 {
499 if (_buf.close() == nullptr)
500 this->setstate(std::ios_base::failbit);
501 }
502 };
503
504 typedef basic_opstream<char> opstream;
505 typedef basic_opstream<wchar_t> wopstream;
506
507
508 /** Implementation of a read-write pipe stream.
509 *
510 */
511 template<
512 class CharT,
513 class Traits = std::char_traits<CharT>
514 >
515 class basic_pstream : public std::basic_iostream<CharT, Traits>
516 {
517 mutable basic_pipebuf<CharT, Traits> _buf;
518 public:
519 typedef basic_pipe<CharT, Traits> pipe_type;
520
521 typedef CharT char_type ;
522 typedef Traits traits_type;
523 typedef typename Traits::int_type int_type ;
524 typedef typename Traits::pos_type pos_type ;
525 typedef typename Traits::off_type off_type ;
526
527
528 ///Get access to the underlying stream_buf
529 basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
530
531 ///Default constructor.
532 basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
533 {
534 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
535 };
536 ///Copy constructor.
537 basic_pstream(const basic_pstream & ) = delete;
538 ///Move constructor.
539 basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
540 {
541 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
542 }
543 ///Move construct from a pipe.
544 basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
545 {
546 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
547 };
548 ///Copy construct from a pipe.
549 basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p)
550 {
551 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
552 };
553 ///Copy assignment.
554 basic_pstream& operator=(const basic_pstream & ) = delete;
555 ///Move assignment
556 basic_pstream& operator=(basic_pstream && lhs)
557 {
558 std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
559 _buf = std::move(lhs);
560 std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
561 };
562 ///Move assignment of a pipe.
563 basic_pstream& operator=(pipe_type && p)
564 {
565 _buf = std::move(p);
566 return *this;
567 }
568 ///Copy assignment of a pipe.
569 basic_pstream& operator=(const pipe_type & p)
570 {
571 _buf = p;
572 return *this;
573 }
574 ///Set the pipe of the streambuf.
575 void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); }
576 ///Set the pipe of the streambuf.
577 void pipe(const pipe_type& p) {_buf.pipe(p); }
578 ///Get a reference to the pipe.
579 pipe_type & pipe() & {return _buf.pipe();}
580 ///Get a const reference to the pipe.
581 const pipe_type &pipe() const & {return _buf.pipe();}
582 ///Get a rvalue reference to the pipe. Qualified as rvalue.
583 pipe_type && pipe() && {return std::move(_buf).pipe();}
584
585 ///Open a new pipe
586 void open()
587 {
588 if (_buf.open() == nullptr)
589 this->setstate(std::ios_base::failbit);
590 else
591 this->clear();
592 }
593
594 ///Open a new named pipe
595 void open(const std::string & name)
596 {
597 if (_buf.open() == nullptr)
598 this->setstate(std::ios_base::failbit);
599 else
600 this->clear();
601 }
602
603 ///Flush the buffer & close the pipe
604 void close()
605 {
606 if (_buf.close() == nullptr)
607 this->setstate(std::ios_base::failbit);
608 }
609 };
610
611 typedef basic_pstream<char> pstream;
612 typedef basic_pstream<wchar_t> wpstream;
613
614
615
616 }}
617
618
619
620 #endif