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