Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/io.h @ 134:41e769c91eca
Add Capnp and KJ builds for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 14:48:23 +0100 |
parents | |
children | 0994c39f1e94 |
comparison
equal
deleted
inserted
replaced
133:1ac99bfc383d | 134:41e769c91eca |
---|---|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 #ifndef KJ_IO_H_ | |
23 #define KJ_IO_H_ | |
24 | |
25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | |
26 #pragma GCC system_header | |
27 #endif | |
28 | |
29 #include <stddef.h> | |
30 #include "common.h" | |
31 #include "array.h" | |
32 #include "exception.h" | |
33 | |
34 namespace kj { | |
35 | |
36 // ======================================================================================= | |
37 // Abstract interfaces | |
38 | |
39 class InputStream { | |
40 public: | |
41 virtual ~InputStream() noexcept(false); | |
42 | |
43 size_t read(void* buffer, size_t minBytes, size_t maxBytes); | |
44 // Reads at least minBytes and at most maxBytes, copying them into the given buffer. Returns | |
45 // the size read. Throws an exception on errors. Implemented in terms of tryRead(). | |
46 // | |
47 // maxBytes is the number of bytes the caller really wants, but minBytes is the minimum amount | |
48 // needed by the caller before it can start doing useful processing. If the stream returns less | |
49 // than maxBytes, the caller will usually call read() again later to get the rest. Returning | |
50 // less than maxBytes is useful when it makes sense for the caller to parallelize processing | |
51 // with I/O. | |
52 // | |
53 // Never blocks if minBytes is zero. If minBytes is zero and maxBytes is non-zero, this may | |
54 // attempt a non-blocking read or may just return zero. To force a read, use a non-zero minBytes. | |
55 // To detect EOF without throwing an exception, use tryRead(). | |
56 // | |
57 // If the InputStream can't produce minBytes, it MUST throw an exception, as the caller is not | |
58 // expected to understand how to deal with partial reads. | |
59 | |
60 virtual size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) = 0; | |
61 // Like read(), but may return fewer than minBytes on EOF. | |
62 | |
63 inline void read(void* buffer, size_t bytes) { read(buffer, bytes, bytes); } | |
64 // Convenience method for reading an exact number of bytes. | |
65 | |
66 virtual void skip(size_t bytes); | |
67 // Skips past the given number of bytes, discarding them. The default implementation read()s | |
68 // into a scratch buffer. | |
69 }; | |
70 | |
71 class OutputStream { | |
72 public: | |
73 virtual ~OutputStream() noexcept(false); | |
74 | |
75 virtual void write(const void* buffer, size_t size) = 0; | |
76 // Always writes the full size. Throws exception on error. | |
77 | |
78 virtual void write(ArrayPtr<const ArrayPtr<const byte>> pieces); | |
79 // Equivalent to write()ing each byte array in sequence, which is what the default implementation | |
80 // does. Override if you can do something better, e.g. use writev() to do the write in a single | |
81 // syscall. | |
82 }; | |
83 | |
84 class BufferedInputStream: public InputStream { | |
85 // An input stream which buffers some bytes in memory to reduce system call overhead. | |
86 // - OR - | |
87 // An input stream that actually reads from some in-memory data structure and wants to give its | |
88 // caller a direct pointer to that memory to potentially avoid a copy. | |
89 | |
90 public: | |
91 virtual ~BufferedInputStream() noexcept(false); | |
92 | |
93 ArrayPtr<const byte> getReadBuffer(); | |
94 // Get a direct pointer into the read buffer, which contains the next bytes in the input. If the | |
95 // caller consumes any bytes, it should then call skip() to indicate this. This always returns a | |
96 // non-empty buffer or throws an exception. Implemented in terms of tryGetReadBuffer(). | |
97 | |
98 virtual ArrayPtr<const byte> tryGetReadBuffer() = 0; | |
99 // Like getReadBuffer() but may return an empty buffer on EOF. | |
100 }; | |
101 | |
102 class BufferedOutputStream: public OutputStream { | |
103 // An output stream which buffers some bytes in memory to reduce system call overhead. | |
104 // - OR - | |
105 // An output stream that actually writes into some in-memory data structure and wants to give its | |
106 // caller a direct pointer to that memory to potentially avoid a copy. | |
107 | |
108 public: | |
109 virtual ~BufferedOutputStream() noexcept(false); | |
110 | |
111 virtual ArrayPtr<byte> getWriteBuffer() = 0; | |
112 // Get a direct pointer into the write buffer. The caller may choose to fill in some prefix of | |
113 // this buffer and then pass it to write(), in which case write() may avoid a copy. It is | |
114 // incorrect to pass to write any slice of this buffer which is not a prefix. | |
115 }; | |
116 | |
117 // ======================================================================================= | |
118 // Buffered streams implemented as wrappers around regular streams | |
119 | |
120 class BufferedInputStreamWrapper: public BufferedInputStream { | |
121 // Implements BufferedInputStream in terms of an InputStream. | |
122 // | |
123 // Note that the underlying stream's position is unpredictable once the wrapper is destroyed, | |
124 // unless the entire stream was consumed. To read a predictable number of bytes in a buffered | |
125 // way without going over, you'd need this wrapper to wrap some other wrapper which itself | |
126 // implements an artificial EOF at the desired point. Such a stream should be trivial to write | |
127 // but is not provided by the library at this time. | |
128 | |
129 public: | |
130 explicit BufferedInputStreamWrapper(InputStream& inner, ArrayPtr<byte> buffer = nullptr); | |
131 // Creates a buffered stream wrapping the given non-buffered stream. No guarantee is made about | |
132 // the position of the inner stream after a buffered wrapper has been created unless the entire | |
133 // input is read. | |
134 // | |
135 // If the second parameter is non-null, the stream uses the given buffer instead of allocating | |
136 // its own. This may improve performance if the buffer can be reused. | |
137 | |
138 KJ_DISALLOW_COPY(BufferedInputStreamWrapper); | |
139 ~BufferedInputStreamWrapper() noexcept(false); | |
140 | |
141 // implements BufferedInputStream ---------------------------------- | |
142 ArrayPtr<const byte> tryGetReadBuffer() override; | |
143 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | |
144 void skip(size_t bytes) override; | |
145 | |
146 private: | |
147 InputStream& inner; | |
148 Array<byte> ownedBuffer; | |
149 ArrayPtr<byte> buffer; | |
150 ArrayPtr<byte> bufferAvailable; | |
151 }; | |
152 | |
153 class BufferedOutputStreamWrapper: public BufferedOutputStream { | |
154 // Implements BufferedOutputStream in terms of an OutputStream. Note that writes to the | |
155 // underlying stream may be delayed until flush() is called or the wrapper is destroyed. | |
156 | |
157 public: | |
158 explicit BufferedOutputStreamWrapper(OutputStream& inner, ArrayPtr<byte> buffer = nullptr); | |
159 // Creates a buffered stream wrapping the given non-buffered stream. | |
160 // | |
161 // If the second parameter is non-null, the stream uses the given buffer instead of allocating | |
162 // its own. This may improve performance if the buffer can be reused. | |
163 | |
164 KJ_DISALLOW_COPY(BufferedOutputStreamWrapper); | |
165 ~BufferedOutputStreamWrapper() noexcept(false); | |
166 | |
167 void flush(); | |
168 // Force the wrapper to write any remaining bytes in its buffer to the inner stream. Note that | |
169 // this only flushes this object's buffer; this object has no idea how to flush any other buffers | |
170 // that may be present in the underlying stream. | |
171 | |
172 // implements BufferedOutputStream --------------------------------- | |
173 ArrayPtr<byte> getWriteBuffer() override; | |
174 void write(const void* buffer, size_t size) override; | |
175 | |
176 private: | |
177 OutputStream& inner; | |
178 Array<byte> ownedBuffer; | |
179 ArrayPtr<byte> buffer; | |
180 byte* bufferPos; | |
181 UnwindDetector unwindDetector; | |
182 }; | |
183 | |
184 // ======================================================================================= | |
185 // Array I/O | |
186 | |
187 class ArrayInputStream: public BufferedInputStream { | |
188 public: | |
189 explicit ArrayInputStream(ArrayPtr<const byte> array); | |
190 KJ_DISALLOW_COPY(ArrayInputStream); | |
191 ~ArrayInputStream() noexcept(false); | |
192 | |
193 // implements BufferedInputStream ---------------------------------- | |
194 ArrayPtr<const byte> tryGetReadBuffer() override; | |
195 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | |
196 void skip(size_t bytes) override; | |
197 | |
198 private: | |
199 ArrayPtr<const byte> array; | |
200 }; | |
201 | |
202 class ArrayOutputStream: public BufferedOutputStream { | |
203 public: | |
204 explicit ArrayOutputStream(ArrayPtr<byte> array); | |
205 KJ_DISALLOW_COPY(ArrayOutputStream); | |
206 ~ArrayOutputStream() noexcept(false); | |
207 | |
208 ArrayPtr<byte> getArray() { | |
209 // Get the portion of the array which has been filled in. | |
210 return arrayPtr(array.begin(), fillPos); | |
211 } | |
212 | |
213 // implements BufferedInputStream ---------------------------------- | |
214 ArrayPtr<byte> getWriteBuffer() override; | |
215 void write(const void* buffer, size_t size) override; | |
216 | |
217 private: | |
218 ArrayPtr<byte> array; | |
219 byte* fillPos; | |
220 }; | |
221 | |
222 class VectorOutputStream: public BufferedOutputStream { | |
223 public: | |
224 explicit VectorOutputStream(size_t initialCapacity = 4096); | |
225 KJ_DISALLOW_COPY(VectorOutputStream); | |
226 ~VectorOutputStream() noexcept(false); | |
227 | |
228 ArrayPtr<byte> getArray() { | |
229 // Get the portion of the array which has been filled in. | |
230 return arrayPtr(vector.begin(), fillPos); | |
231 } | |
232 | |
233 // implements BufferedInputStream ---------------------------------- | |
234 ArrayPtr<byte> getWriteBuffer() override; | |
235 void write(const void* buffer, size_t size) override; | |
236 | |
237 private: | |
238 Array<byte> vector; | |
239 byte* fillPos; | |
240 | |
241 void grow(size_t minSize); | |
242 }; | |
243 | |
244 // ======================================================================================= | |
245 // File descriptor I/O | |
246 | |
247 class AutoCloseFd { | |
248 // A wrapper around a file descriptor which automatically closes the descriptor when destroyed. | |
249 // The wrapper supports move construction for transferring ownership of the descriptor. If | |
250 // close() returns an error, the destructor throws an exception, UNLESS the destructor is being | |
251 // called during unwind from another exception, in which case the close error is ignored. | |
252 // | |
253 // If your code is not exception-safe, you should not use AutoCloseFd. In this case you will | |
254 // have to call close() yourself and handle errors appropriately. | |
255 | |
256 public: | |
257 inline AutoCloseFd(): fd(-1) {} | |
258 inline AutoCloseFd(decltype(nullptr)): fd(-1) {} | |
259 inline explicit AutoCloseFd(int fd): fd(fd) {} | |
260 inline AutoCloseFd(AutoCloseFd&& other) noexcept: fd(other.fd) { other.fd = -1; } | |
261 KJ_DISALLOW_COPY(AutoCloseFd); | |
262 ~AutoCloseFd() noexcept(false); | |
263 | |
264 inline AutoCloseFd& operator=(AutoCloseFd&& other) { | |
265 AutoCloseFd old(kj::mv(*this)); | |
266 fd = other.fd; | |
267 other.fd = -1; | |
268 return *this; | |
269 } | |
270 | |
271 inline AutoCloseFd& operator=(decltype(nullptr)) { | |
272 AutoCloseFd old(kj::mv(*this)); | |
273 return *this; | |
274 } | |
275 | |
276 inline operator int() const { return fd; } | |
277 inline int get() const { return fd; } | |
278 | |
279 operator bool() const = delete; | |
280 // Deleting this operator prevents accidental use in boolean contexts, which | |
281 // the int conversion operator above would otherwise allow. | |
282 | |
283 inline bool operator==(decltype(nullptr)) { return fd < 0; } | |
284 inline bool operator!=(decltype(nullptr)) { return fd >= 0; } | |
285 | |
286 private: | |
287 int fd; | |
288 UnwindDetector unwindDetector; | |
289 }; | |
290 | |
291 inline auto KJ_STRINGIFY(const AutoCloseFd& fd) | |
292 -> decltype(kj::toCharSequence(implicitCast<int>(fd))) { | |
293 return kj::toCharSequence(implicitCast<int>(fd)); | |
294 } | |
295 | |
296 class FdInputStream: public InputStream { | |
297 // An InputStream wrapping a file descriptor. | |
298 | |
299 public: | |
300 explicit FdInputStream(int fd): fd(fd) {} | |
301 explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {} | |
302 KJ_DISALLOW_COPY(FdInputStream); | |
303 ~FdInputStream() noexcept(false); | |
304 | |
305 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; | |
306 | |
307 private: | |
308 int fd; | |
309 AutoCloseFd autoclose; | |
310 }; | |
311 | |
312 class FdOutputStream: public OutputStream { | |
313 // An OutputStream wrapping a file descriptor. | |
314 | |
315 public: | |
316 explicit FdOutputStream(int fd): fd(fd) {} | |
317 explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {} | |
318 KJ_DISALLOW_COPY(FdOutputStream); | |
319 ~FdOutputStream() noexcept(false); | |
320 | |
321 void write(const void* buffer, size_t size) override; | |
322 void write(ArrayPtr<const ArrayPtr<const byte>> pieces) override; | |
323 | |
324 private: | |
325 int fd; | |
326 AutoCloseFd autoclose; | |
327 }; | |
328 | |
329 } // namespace kj | |
330 | |
331 #endif // KJ_IO_H_ |