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#pragma once
23
24#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
25#pragma GCC system_header
26#endif
27
28#include <stddef.h>
29#include "common.h"
30#include "array.h"
31#include "exception.h"
32#include <stdint.h>
33
34namespace kj {
35
36// =======================================================================================
37// Abstract interfaces
38
39class InputStream {
40public:
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 String readAllText(uint64_t limit = kj::maxValue);
71 Array<byte> readAllBytes(uint64_t limit = kj::maxValue);
72 // Read until EOF and return as one big byte array or string. Throw an exception if EOF is not
73 // seen before reading `limit` bytes.
74 //
75 // To prevent runaway memory allocation, consider using a more conservative value for `limit` than
76 // the default, particularly on untrusted data streams which may never see EOF.
77};
78
79class OutputStream {
80public:
81 virtual ~OutputStream() noexcept(false);
82
83 virtual void write(const void* buffer, size_t size) = 0;
84 // Always writes the full size. Throws exception on error.
85
86 virtual void write(ArrayPtr<const ArrayPtr<const byte>> pieces);
87 // Equivalent to write()ing each byte array in sequence, which is what the default implementation
88 // does. Override if you can do something better, e.g. use writev() to do the write in a single
89 // syscall.
90};
91
92class BufferedInputStream: public InputStream {
93 // An input stream which buffers some bytes in memory to reduce system call overhead.
94 // - OR -
95 // An input stream that actually reads from some in-memory data structure and wants to give its
96 // caller a direct pointer to that memory to potentially avoid a copy.
97
98public:
99 virtual ~BufferedInputStream() noexcept(false);
100
101 ArrayPtr<const byte> getReadBuffer();
102 // Get a direct pointer into the read buffer, which contains the next bytes in the input. If the
103 // caller consumes any bytes, it should then call skip() to indicate this. This always returns a
104 // non-empty buffer or throws an exception. Implemented in terms of tryGetReadBuffer().
105
106 virtual ArrayPtr<const byte> tryGetReadBuffer() = 0;
107 // Like getReadBuffer() but may return an empty buffer on EOF.
108};
109
110class BufferedOutputStream: public OutputStream {
111 // An output stream which buffers some bytes in memory to reduce system call overhead.
112 // - OR -
113 // An output stream that actually writes into some in-memory data structure and wants to give its
114 // caller a direct pointer to that memory to potentially avoid a copy.
115
116public:
117 virtual ~BufferedOutputStream() noexcept(false);
118
119 virtual ArrayPtr<byte> getWriteBuffer() = 0;
120 // Get a direct pointer into the write buffer. The caller may choose to fill in some prefix of
121 // this buffer and then pass it to write(), in which case write() may avoid a copy. It is
122 // incorrect to pass to write any slice of this buffer which is not a prefix.
123};
124
125// =======================================================================================
126// Buffered streams implemented as wrappers around regular streams
127
128class BufferedInputStreamWrapper: public BufferedInputStream {
129 // Implements BufferedInputStream in terms of an InputStream.
130 //
131 // Note that the underlying stream's position is unpredictable once the wrapper is destroyed,
132 // unless the entire stream was consumed. To read a predictable number of bytes in a buffered
133 // way without going over, you'd need this wrapper to wrap some other wrapper which itself
134 // implements an artificial EOF at the desired point. Such a stream should be trivial to write
135 // but is not provided by the library at this time.
136
137public:
138 explicit BufferedInputStreamWrapper(InputStream& inner, ArrayPtr<byte> buffer = nullptr);
139 // Creates a buffered stream wrapping the given non-buffered stream. No guarantee is made about
140 // the position of the inner stream after a buffered wrapper has been created unless the entire
141 // input is read.
142 //
143 // If the second parameter is non-null, the stream uses the given buffer instead of allocating
144 // its own. This may improve performance if the buffer can be reused.
145
146 KJ_DISALLOW_COPY(BufferedInputStreamWrapper);
147 ~BufferedInputStreamWrapper() noexcept(false);
148
149 // implements BufferedInputStream ----------------------------------
150 ArrayPtr<const byte> tryGetReadBuffer() override;
151 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
152 void skip(size_t bytes) override;
153
154private:
155 InputStream& inner;
156 Array<byte> ownedBuffer;
157 ArrayPtr<byte> buffer;
158 ArrayPtr<byte> bufferAvailable;
159};
160
161class BufferedOutputStreamWrapper: public BufferedOutputStream {
162 // Implements BufferedOutputStream in terms of an OutputStream. Note that writes to the
163 // underlying stream may be delayed until flush() is called or the wrapper is destroyed.
164
165public:
166 explicit BufferedOutputStreamWrapper(OutputStream& inner, ArrayPtr<byte> buffer = nullptr);
167 // Creates a buffered stream wrapping the given non-buffered stream.
168 //
169 // If the second parameter is non-null, the stream uses the given buffer instead of allocating
170 // its own. This may improve performance if the buffer can be reused.
171
172 KJ_DISALLOW_COPY(BufferedOutputStreamWrapper);
173 ~BufferedOutputStreamWrapper() noexcept(false);
174
175 void flush();
176 // Force the wrapper to write any remaining bytes in its buffer to the inner stream. Note that
177 // this only flushes this object's buffer; this object has no idea how to flush any other buffers
178 // that may be present in the underlying stream.
179
180 // implements BufferedOutputStream ---------------------------------
181 ArrayPtr<byte> getWriteBuffer() override;
182 void write(const void* buffer, size_t size) override;
183
184private:
185 OutputStream& inner;
186 Array<byte> ownedBuffer;
187 ArrayPtr<byte> buffer;
188 byte* bufferPos;
189 UnwindDetector unwindDetector;
190};
191
192// =======================================================================================
193// Array I/O
194
195class ArrayInputStream: public BufferedInputStream {
196public:
197 explicit ArrayInputStream(ArrayPtr<const byte> array);
198 KJ_DISALLOW_COPY(ArrayInputStream);
199 ~ArrayInputStream() noexcept(false);
200
201 // implements BufferedInputStream ----------------------------------
202 ArrayPtr<const byte> tryGetReadBuffer() override;
203 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
204 void skip(size_t bytes) override;
205
206private:
207 ArrayPtr<const byte> array;
208};
209
210class ArrayOutputStream: public BufferedOutputStream {
211public:
212 explicit ArrayOutputStream(ArrayPtr<byte> array);
213 KJ_DISALLOW_COPY(ArrayOutputStream);
214 ~ArrayOutputStream() noexcept(false);
215
216 ArrayPtr<byte> getArray() {
217 // Get the portion of the array which has been filled in.
218 return arrayPtr(array.begin(), fillPos);
219 }
220
221 // implements BufferedInputStream ----------------------------------
222 ArrayPtr<byte> getWriteBuffer() override;
223 void write(const void* buffer, size_t size) override;
224
225private:
226 ArrayPtr<byte> array;
227 byte* fillPos;
228};
229
230class VectorOutputStream: public BufferedOutputStream {
231public:
232 explicit VectorOutputStream(size_t initialCapacity = 4096);
233 KJ_DISALLOW_COPY(VectorOutputStream);
234 ~VectorOutputStream() noexcept(false);
235
236 ArrayPtr<byte> getArray() {
237 // Get the portion of the array which has been filled in.
238 return arrayPtr(vector.begin(), fillPos);
239 }
240
241 // implements BufferedInputStream ----------------------------------
242 ArrayPtr<byte> getWriteBuffer() override;
243 void write(const void* buffer, size_t size) override;
244
245private:
246 Array<byte> vector;
247 byte* fillPos;
248
249 void grow(size_t minSize);
250};
251
252// =======================================================================================
253// File descriptor I/O
254
255class AutoCloseFd {
256 // A wrapper around a file descriptor which automatically closes the descriptor when destroyed.
257 // The wrapper supports move construction for transferring ownership of the descriptor. If
258 // close() returns an error, the destructor throws an exception, UNLESS the destructor is being
259 // called during unwind from another exception, in which case the close error is ignored.
260 //
261 // If your code is not exception-safe, you should not use AutoCloseFd. In this case you will
262 // have to call close() yourself and handle errors appropriately.
263
264public:
265 inline AutoCloseFd(): fd(-1) {}
266 inline AutoCloseFd(decltype(nullptr)): fd(-1) {}
267 inline explicit AutoCloseFd(int fd): fd(fd) {}
268 inline AutoCloseFd(AutoCloseFd&& other) noexcept: fd(other.fd) { other.fd = -1; }
269 KJ_DISALLOW_COPY(AutoCloseFd);
270 ~AutoCloseFd() noexcept(false);
271
272 inline AutoCloseFd& operator=(AutoCloseFd&& other) {
273 AutoCloseFd old(kj::mv(*this));
274 fd = other.fd;
275 other.fd = -1;
276 return *this;
277 }
278
279 inline AutoCloseFd& operator=(decltype(nullptr)) {
280 AutoCloseFd old(kj::mv(*this));
281 return *this;
282 }
283
284 inline operator int() const { return fd; }
285 inline int get() const { return fd; }
286
287 operator bool() const = delete;
288 // Deleting this operator prevents accidental use in boolean contexts, which
289 // the int conversion operator above would otherwise allow.
290
291 inline bool operator==(decltype(nullptr)) { return fd < 0; }
292 inline bool operator!=(decltype(nullptr)) { return fd >= 0; }
293
294 inline int release() {
295 // Release ownership of an FD. Not recommended.
296 int result = fd;
297 fd = -1;
298 return result;
299 }
300
301private:
302 int fd;
303 UnwindDetector unwindDetector;
304};
305
306inline auto KJ_STRINGIFY(const AutoCloseFd& fd)
307 -> decltype(kj::toCharSequence(implicitCast<int>(fd))) {
308 return kj::toCharSequence(implicitCast<int>(fd));
309}
310
311class FdInputStream: public InputStream {
312 // An InputStream wrapping a file descriptor.
313
314public:
315 explicit FdInputStream(int fd): fd(fd) {}
316 explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
317 KJ_DISALLOW_COPY(FdInputStream);
318 ~FdInputStream() noexcept(false);
319
320 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
321
322 inline int getFd() const { return fd; }
323
324private:
325 int fd;
326 AutoCloseFd autoclose;
327};
328
329class FdOutputStream: public OutputStream {
330 // An OutputStream wrapping a file descriptor.
331
332public:
333 explicit FdOutputStream(int fd): fd(fd) {}
334 explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
335 KJ_DISALLOW_COPY(FdOutputStream);
336 ~FdOutputStream() noexcept(false);
337
338 void write(const void* buffer, size_t size) override;
339 void write(ArrayPtr<const ArrayPtr<const byte>> pieces) override;
340
341 inline int getFd() const { return fd; }
342
343private:
344 int fd;
345 AutoCloseFd autoclose;
346};
347
348// =======================================================================================
349// Win32 Handle I/O
350
351#ifdef _WIN32
352
353class AutoCloseHandle {
354 // A wrapper around a Win32 HANDLE which automatically closes the handle when destroyed.
355 // The wrapper supports move construction for transferring ownership of the handle. If
356 // CloseHandle() returns an error, the destructor throws an exception, UNLESS the destructor is
357 // being called during unwind from another exception, in which case the close error is ignored.
358 //
359 // If your code is not exception-safe, you should not use AutoCloseHandle. In this case you will
360 // have to call close() yourself and handle errors appropriately.
361
362public:
363 inline AutoCloseHandle(): handle((void*)-1) {}
364 inline AutoCloseHandle(decltype(nullptr)): handle((void*)-1) {}
365 inline explicit AutoCloseHandle(void* handle): handle(handle) {}
366 inline AutoCloseHandle(AutoCloseHandle&& other) noexcept: handle(other.handle) {
367 other.handle = (void*)-1;
368 }
369 KJ_DISALLOW_COPY(AutoCloseHandle);
370 ~AutoCloseHandle() noexcept(false);
371
372 inline AutoCloseHandle& operator=(AutoCloseHandle&& other) {
373 AutoCloseHandle old(kj::mv(*this));
374 handle = other.handle;
375 other.handle = (void*)-1;
376 return *this;
377 }
378
379 inline AutoCloseHandle& operator=(decltype(nullptr)) {
380 AutoCloseHandle old(kj::mv(*this));
381 return *this;
382 }
383
384 inline operator void*() const { return handle; }
385 inline void* get() const { return handle; }
386
387 operator bool() const = delete;
388 // Deleting this operator prevents accidental use in boolean contexts, which
389 // the void* conversion operator above would otherwise allow.
390
391 inline bool operator==(decltype(nullptr)) { return handle != (void*)-1; }
392 inline bool operator!=(decltype(nullptr)) { return handle == (void*)-1; }
393
394 inline void* release() {
395 // Release ownership of an FD. Not recommended.
396 void* result = handle;
397 handle = (void*)-1;
398 return result;
399 }
400
401private:
402 void* handle; // -1 (aka INVALID_HANDLE_VALUE) if not valid.
403};
404
405class HandleInputStream: public InputStream {
406 // An InputStream wrapping a Win32 HANDLE.
407
408public:
409 explicit HandleInputStream(void* handle): handle(handle) {}
410 explicit HandleInputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {}
411 KJ_DISALLOW_COPY(HandleInputStream);
412 ~HandleInputStream() noexcept(false);
413
414 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
415
416private:
417 void* handle;
418 AutoCloseHandle autoclose;
419};
420
421class HandleOutputStream: public OutputStream {
422 // An OutputStream wrapping a Win32 HANDLE.
423
424public:
425 explicit HandleOutputStream(void* handle): handle(handle) {}
426 explicit HandleOutputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {}
427 KJ_DISALLOW_COPY(HandleOutputStream);
428 ~HandleOutputStream() noexcept(false);
429
430 void write(const void* buffer, size_t size) override;
431
432private:
433 void* handle;
434 AutoCloseHandle autoclose;
435};
436
437#endif // _WIN32
438
439} // namespace kj
440