annotate third_party/boost/process/detail/systembuf.hpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
rev   line source
ian@0 1 //
ian@0 2 // Boost.Process
ian@0 3 // ~~~~~~~~~~~~~
ian@0 4 //
ian@0 5 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
ian@0 6 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
ian@0 7 // Copyright (c) 2009 Boris Schaeling
ian@0 8 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
ian@0 9 //
ian@0 10 // Distributed under the Boost Software License, Version 1.0. (See accompanying
ian@0 11 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
ian@0 12 //
ian@0 13
ian@0 14 /**
ian@0 15 * \file boost/process/detail/systembuf.hpp
ian@0 16 *
ian@0 17 * Includes the declaration of the systembuf class.
ian@0 18 */
ian@0 19
ian@0 20 #ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
ian@0 21 #define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
ian@0 22
ian@0 23 #include <boost/process/config.hpp>
ian@0 24
ian@0 25 #if defined(BOOST_POSIX_API)
ian@0 26 # include <sys/types.h>
ian@0 27 # include <unistd.h>
ian@0 28 #elif defined(BOOST_WINDOWS_API)
ian@0 29 # include <windows.h>
ian@0 30 #else
ian@0 31 # error "Unsupported platform."
ian@0 32 #endif
ian@0 33
ian@0 34 #include <boost/noncopyable.hpp>
ian@0 35 #include <boost/scoped_array.hpp>
ian@0 36 #include <boost/assert.hpp>
ian@0 37 #include <streambuf>
ian@0 38 #include <cstddef>
ian@0 39
ian@0 40 namespace boost {
ian@0 41 namespace process {
ian@0 42
ian@0 43 class postream;
ian@0 44
ian@0 45 namespace detail {
ian@0 46
ian@0 47 /**
ian@0 48 * std::streambuf implementation for handles.
ian@0 49 *
ian@0 50 * systembuf provides a std::streambuf implementation for handles.
ian@0 51 * Contrarywise to the handle class, this class does \b not take
ian@0 52 * ownership of the native handle; this should be taken care of
ian@0 53 * somewhere else.
ian@0 54 *
ian@0 55 * This class follows the expected semantics of a std::streambuf object.
ian@0 56 * However, it is not copyable to avoid introducing inconsistences with
ian@0 57 * the on-disk file and the in-memory buffers.
ian@0 58 */
ian@0 59 class systembuf : public std::streambuf, public boost::noncopyable
ian@0 60 {
ian@0 61 friend class boost::process::postream;
ian@0 62
ian@0 63 public:
ian@0 64 #if defined(BOOST_PROCESS_DOXYGEN)
ian@0 65 /**
ian@0 66 * Opaque name for the native handle type.
ian@0 67 */
ian@0 68 typedef NativeHandleType handle_type;
ian@0 69 #elif defined(BOOST_POSIX_API)
ian@0 70 typedef int handle_type;
ian@0 71 #elif defined(BOOST_WINDOWS_API)
ian@0 72 typedef HANDLE handle_type;
ian@0 73 #endif
ian@0 74
ian@0 75 /**
ian@0 76 * Constructs a new systembuf for the given handle.
ian@0 77 *
ian@0 78 * This constructor creates a new systembuf object that reads or
ian@0 79 * writes data from/to the \a h native handle. This handle
ian@0 80 * is \b not owned by the created systembuf object; the code
ian@0 81 * should take care of it externally.
ian@0 82 *
ian@0 83 * This class buffers input and output; the buffer size may be
ian@0 84 * tuned through the \a bufsize parameter, which defaults to 8192
ian@0 85 * bytes.
ian@0 86 *
ian@0 87 * \see pistream and postream
ian@0 88 */
ian@0 89 explicit systembuf(handle_type h, std::size_t bufsize = 8192)
ian@0 90 : handle_(h),
ian@0 91 bufsize_(bufsize),
ian@0 92 read_buf_(new char[bufsize]),
ian@0 93 write_buf_(new char[bufsize])
ian@0 94 {
ian@0 95 #if defined(BOOST_POSIX_API)
ian@0 96 BOOST_ASSERT(handle_ >= 0);
ian@0 97 #elif defined(BOOST_WINDOWS_API)
ian@0 98 BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
ian@0 99 #endif
ian@0 100 BOOST_ASSERT(bufsize_ > 0);
ian@0 101 setp(write_buf_.get(), write_buf_.get() + bufsize_);
ian@0 102 }
ian@0 103
ian@0 104 protected:
ian@0 105 /**
ian@0 106 * Reads new data from the native handle.
ian@0 107 *
ian@0 108 * This operation is called by input methods when there is no more
ian@0 109 * data in the input buffer. The function fills the buffer with new
ian@0 110 * data, if available.
ian@0 111 *
ian@0 112 * \pre All input positions are exhausted (gptr() >= egptr()).
ian@0 113 * \post The input buffer has new data, if available.
ian@0 114 * \returns traits_type::eof() if a read error occurrs or there are
ian@0 115 * no more data to be read. Otherwise returns
ian@0 116 * traits_type::to_int_type(*gptr()).
ian@0 117 */
ian@0 118 virtual int_type underflow()
ian@0 119 {
ian@0 120 BOOST_ASSERT(gptr() >= egptr());
ian@0 121
ian@0 122 bool ok;
ian@0 123 #if defined(BOOST_POSIX_API)
ian@0 124 ssize_t cnt = read(handle_, read_buf_.get(), bufsize_);
ian@0 125 ok = (cnt != -1 && cnt != 0);
ian@0 126 #elif defined(BOOST_WINDOWS_API)
ian@0 127 DWORD cnt;
ian@0 128 BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
ian@0 129 ok = (res && cnt > 0);
ian@0 130 #endif
ian@0 131
ian@0 132 if (!ok)
ian@0 133 return traits_type::eof();
ian@0 134 else
ian@0 135 {
ian@0 136 setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
ian@0 137 return traits_type::to_int_type(*gptr());
ian@0 138 }
ian@0 139 }
ian@0 140
ian@0 141 /**
ian@0 142 * Makes room in the write buffer for additional data.
ian@0 143 *
ian@0 144 * This operation is called by output methods when there is no more
ian@0 145 * space in the output buffer to hold a new element. The function
ian@0 146 * first flushes the buffer's contents to disk and then clears it to
ian@0 147 * leave room for more characters. The given \a c character is
ian@0 148 * stored at the beginning of the new space.
ian@0 149 *
ian@0 150 * \pre All output positions are exhausted (pptr() >= epptr()).
ian@0 151 * \post The output buffer has more space if no errors occurred
ian@0 152 * during the write to disk.
ian@0 153 * \post *(pptr() - 1) is \a c.
ian@0 154 * \returns traits_type::eof() if a write error occurrs. Otherwise
ian@0 155 * returns traits_type::not_eof(c).
ian@0 156 */
ian@0 157 virtual int_type overflow(int c)
ian@0 158 {
ian@0 159 BOOST_ASSERT(pptr() >= epptr());
ian@0 160
ian@0 161 if (sync() == -1)
ian@0 162 return traits_type::eof();
ian@0 163
ian@0 164 if (!traits_type::eq_int_type(c, traits_type::eof()))
ian@0 165 {
ian@0 166 traits_type::assign(*pptr(), static_cast<traits_type::char_type>(
ian@0 167 c));
ian@0 168 pbump(1);
ian@0 169 }
ian@0 170
ian@0 171 return traits_type::not_eof(c);
ian@0 172 }
ian@0 173
ian@0 174 /**
ian@0 175 * Flushes the output buffer to disk.
ian@0 176 *
ian@0 177 * Synchronizes the systembuf buffers with the contents of the file
ian@0 178 * associated to this object through the native handle. The output buffer
ian@0 179 * is flushed to disk and cleared to leave new room for more data.
ian@0 180 *
ian@0 181 * \returns 0 on success, -1 if an error occurred.
ian@0 182 */
ian@0 183 virtual int sync()
ian@0 184 {
ian@0 185 #if defined(BOOST_POSIX_API)
ian@0 186 ssize_t cnt = pptr() - pbase();
ian@0 187 bool ok = (write(handle_, pbase(), cnt) == cnt);
ian@0 188 if (ok)
ian@0 189 pbump(static_cast<int>(-cnt));
ian@0 190 return ok ? 0 : -1;
ian@0 191 #elif defined(BOOST_WINDOWS_API)
ian@0 192 long cnt = pptr() - pbase();
ian@0 193 DWORD rcnt;
ian@0 194 BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
ian@0 195 bool ok = (res && static_cast<long>(rcnt) == cnt);
ian@0 196 if (ok)
ian@0 197 pbump(-cnt);
ian@0 198 return ok ? 0 : -1;
ian@0 199 #endif
ian@0 200 }
ian@0 201
ian@0 202 private:
ian@0 203 /**
ian@0 204 * Native handle used by the systembuf object.
ian@0 205 */
ian@0 206 handle_type handle_;
ian@0 207
ian@0 208 /**
ian@0 209 * Internal buffer size used during read and write operations.
ian@0 210 */
ian@0 211 std::size_t bufsize_;
ian@0 212
ian@0 213 /**
ian@0 214 * Internal buffer used during read operations.
ian@0 215 */
ian@0 216 boost::scoped_array<char> read_buf_;
ian@0 217
ian@0 218 /**
ian@0 219 * Internal buffer used during write operations.
ian@0 220 */
ian@0 221 boost::scoped_array<char> write_buf_;
ian@0 222 };
ian@0 223
ian@0 224 }
ian@0 225 }
ian@0 226 }
ian@0 227
ian@0 228 #endif