00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00019 #ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
00020 #define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
00021
00022 #include <boost/process/config.hpp>
00023
00024 #if defined(BOOST_POSIX_API)
00025 # include <sys/types.h>
00026 # include <unistd.h>
00027 #elif defined(BOOST_WINDOWS_API)
00028 # include <windows.h>
00029 #else
00030 # error "Unsupported platform."
00031 #endif
00032
00033 #include <boost/noncopyable.hpp>
00034 #include <boost/scoped_array.hpp>
00035 #include <boost/assert.hpp>
00036 #include <streambuf>
00037 #include <cstddef>
00038
00039 namespace boost {
00040 namespace process {
00041
00042 class postream;
00043
00044 namespace detail {
00045
00058 class systembuf : public std::streambuf, public boost::noncopyable
00059 {
00060 friend class ::boost::process::postream;
00061
00062 public:
00063 #if defined(BOOST_PROCESS_DOXYGEN)
00064
00067 typedef NativeHandleType handle_type;
00068 #elif defined(BOOST_POSIX_API)
00069 typedef int handle_type;
00070 #elif defined(BOOST_WINDOWS_API)
00071 typedef HANDLE handle_type;
00072 #endif
00073
00088 explicit systembuf(handle_type h, std::size_t bufsize = 8192)
00089 : handle_(h),
00090 bufsize_(bufsize),
00091 read_buf_(new char[bufsize]),
00092 write_buf_(new char[bufsize])
00093 {
00094 #if defined(BOOST_POSIX_API)
00095 BOOST_ASSERT(handle_ >= 0);
00096 #elif defined(BOOST_WINDOWS_API)
00097 BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
00098 #endif
00099 BOOST_ASSERT(bufsize_ > 0);
00100
00101 setp(write_buf_.get(), write_buf_.get() + bufsize_);
00102 }
00103
00104 protected:
00118 virtual int_type underflow()
00119 {
00120 BOOST_ASSERT(gptr() >= egptr());
00121
00122 bool ok;
00123 #if defined(BOOST_POSIX_API)
00124 ssize_t cnt = ::read(handle_, read_buf_.get(), bufsize_);
00125 ok = (cnt != -1 && cnt != 0);
00126 #elif defined(BOOST_WINDOWS_API)
00127 DWORD cnt;
00128 BOOL res = ::ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
00129 ok = (res && cnt > 0);
00130 #endif
00131
00132 if (!ok)
00133 return traits_type::eof();
00134 else
00135 {
00136 setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
00137 return traits_type::to_int_type(*gptr());
00138 }
00139 }
00140
00157 virtual int_type overflow(int c)
00158 {
00159 BOOST_ASSERT(pptr() >= epptr());
00160
00161 if (sync() == -1)
00162 return traits_type::eof();
00163
00164 if (!traits_type::eq_int_type(c, traits_type::eof()))
00165 {
00166 traits_type::assign(*pptr(), c);
00167 pbump(1);
00168 }
00169
00170 return traits_type::not_eof(c);
00171 }
00172
00183 virtual int sync()
00184 {
00185 #if defined(BOOST_POSIX_API)
00186 ssize_t cnt = pptr() - pbase();
00187 #elif defined(BOOST_WINDOWS_API)
00188 long cnt = pptr() - pbase();
00189 #endif
00190
00191 bool ok;
00192 #if defined(BOOST_POSIX_API)
00193 ok = ::write(handle_, pbase(), cnt) == cnt;
00194 #elif defined(BOOST_WINDOWS_API)
00195 DWORD rcnt;
00196 BOOL res = ::WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
00197 ok = (res && static_cast<long>(rcnt) == cnt);
00198 #endif
00199
00200 if (ok)
00201 pbump(-cnt);
00202 return ok ? 0 : -1;
00203 }
00204
00205 private:
00209 handle_type handle_;
00210
00214 std::size_t bufsize_;
00215
00219 boost::scoped_array<char> read_buf_;
00220
00224 boost::scoped_array<char> write_buf_;
00225 };
00226
00227 }
00228 }
00229 }
00230
00231 #endif