Mercurial > hg > gpsynth
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 |