annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/kj/io.h @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
jpayne@69 2 // Licensed under the MIT License:
jpayne@69 3 //
jpayne@69 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
jpayne@69 5 // of this software and associated documentation files (the "Software"), to deal
jpayne@69 6 // in the Software without restriction, including without limitation the rights
jpayne@69 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jpayne@69 8 // copies of the Software, and to permit persons to whom the Software is
jpayne@69 9 // furnished to do so, subject to the following conditions:
jpayne@69 10 //
jpayne@69 11 // The above copyright notice and this permission notice shall be included in
jpayne@69 12 // all copies or substantial portions of the Software.
jpayne@69 13 //
jpayne@69 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jpayne@69 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jpayne@69 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jpayne@69 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jpayne@69 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jpayne@69 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jpayne@69 20 // THE SOFTWARE.
jpayne@69 21
jpayne@69 22 #pragma once
jpayne@69 23
jpayne@69 24 #include <stddef.h>
jpayne@69 25 #include "common.h"
jpayne@69 26 #include "array.h"
jpayne@69 27 #include "exception.h"
jpayne@69 28 #include <stdint.h>
jpayne@69 29
jpayne@69 30 KJ_BEGIN_HEADER
jpayne@69 31
jpayne@69 32 namespace kj {
jpayne@69 33
jpayne@69 34 // =======================================================================================
jpayne@69 35 // Abstract interfaces
jpayne@69 36
jpayne@69 37 class InputStream {
jpayne@69 38 public:
jpayne@69 39 virtual ~InputStream() noexcept(false);
jpayne@69 40
jpayne@69 41 size_t read(void* buffer, size_t minBytes, size_t maxBytes);
jpayne@69 42 // Reads at least minBytes and at most maxBytes, copying them into the given buffer. Returns
jpayne@69 43 // the size read. Throws an exception on errors. Implemented in terms of tryRead().
jpayne@69 44 //
jpayne@69 45 // maxBytes is the number of bytes the caller really wants, but minBytes is the minimum amount
jpayne@69 46 // needed by the caller before it can start doing useful processing. If the stream returns less
jpayne@69 47 // than maxBytes, the caller will usually call read() again later to get the rest. Returning
jpayne@69 48 // less than maxBytes is useful when it makes sense for the caller to parallelize processing
jpayne@69 49 // with I/O.
jpayne@69 50 //
jpayne@69 51 // Never blocks if minBytes is zero. If minBytes is zero and maxBytes is non-zero, this may
jpayne@69 52 // attempt a non-blocking read or may just return zero. To force a read, use a non-zero minBytes.
jpayne@69 53 // To detect EOF without throwing an exception, use tryRead().
jpayne@69 54 //
jpayne@69 55 // If the InputStream can't produce minBytes, it MUST throw an exception, as the caller is not
jpayne@69 56 // expected to understand how to deal with partial reads.
jpayne@69 57
jpayne@69 58 virtual size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) = 0;
jpayne@69 59 // Like read(), but may return fewer than minBytes on EOF.
jpayne@69 60
jpayne@69 61 inline void read(void* buffer, size_t bytes) { read(buffer, bytes, bytes); }
jpayne@69 62 // Convenience method for reading an exact number of bytes.
jpayne@69 63
jpayne@69 64 virtual void skip(size_t bytes);
jpayne@69 65 // Skips past the given number of bytes, discarding them. The default implementation read()s
jpayne@69 66 // into a scratch buffer.
jpayne@69 67
jpayne@69 68 String readAllText(uint64_t limit = kj::maxValue);
jpayne@69 69 Array<byte> readAllBytes(uint64_t limit = kj::maxValue);
jpayne@69 70 // Read until EOF and return as one big byte array or string. Throw an exception if EOF is not
jpayne@69 71 // seen before reading `limit` bytes.
jpayne@69 72 //
jpayne@69 73 // To prevent runaway memory allocation, consider using a more conservative value for `limit` than
jpayne@69 74 // the default, particularly on untrusted data streams which may never see EOF.
jpayne@69 75 };
jpayne@69 76
jpayne@69 77 class OutputStream {
jpayne@69 78 public:
jpayne@69 79 virtual ~OutputStream() noexcept(false);
jpayne@69 80
jpayne@69 81 virtual void write(const void* buffer, size_t size) = 0;
jpayne@69 82 // Always writes the full size. Throws exception on error.
jpayne@69 83
jpayne@69 84 virtual void write(ArrayPtr<const ArrayPtr<const byte>> pieces);
jpayne@69 85 // Equivalent to write()ing each byte array in sequence, which is what the default implementation
jpayne@69 86 // does. Override if you can do something better, e.g. use writev() to do the write in a single
jpayne@69 87 // syscall.
jpayne@69 88 };
jpayne@69 89
jpayne@69 90 class BufferedInputStream: public InputStream {
jpayne@69 91 // An input stream which buffers some bytes in memory to reduce system call overhead.
jpayne@69 92 // - OR -
jpayne@69 93 // An input stream that actually reads from some in-memory data structure and wants to give its
jpayne@69 94 // caller a direct pointer to that memory to potentially avoid a copy.
jpayne@69 95
jpayne@69 96 public:
jpayne@69 97 virtual ~BufferedInputStream() noexcept(false);
jpayne@69 98
jpayne@69 99 ArrayPtr<const byte> getReadBuffer();
jpayne@69 100 // Get a direct pointer into the read buffer, which contains the next bytes in the input. If the
jpayne@69 101 // caller consumes any bytes, it should then call skip() to indicate this. This always returns a
jpayne@69 102 // non-empty buffer or throws an exception. Implemented in terms of tryGetReadBuffer().
jpayne@69 103
jpayne@69 104 virtual ArrayPtr<const byte> tryGetReadBuffer() = 0;
jpayne@69 105 // Like getReadBuffer() but may return an empty buffer on EOF.
jpayne@69 106 };
jpayne@69 107
jpayne@69 108 class BufferedOutputStream: public OutputStream {
jpayne@69 109 // An output stream which buffers some bytes in memory to reduce system call overhead.
jpayne@69 110 // - OR -
jpayne@69 111 // An output stream that actually writes into some in-memory data structure and wants to give its
jpayne@69 112 // caller a direct pointer to that memory to potentially avoid a copy.
jpayne@69 113
jpayne@69 114 public:
jpayne@69 115 virtual ~BufferedOutputStream() noexcept(false);
jpayne@69 116
jpayne@69 117 virtual ArrayPtr<byte> getWriteBuffer() = 0;
jpayne@69 118 // Get a direct pointer into the write buffer. The caller may choose to fill in some prefix of
jpayne@69 119 // this buffer and then pass it to write(), in which case write() may avoid a copy. It is
jpayne@69 120 // incorrect to pass to write any slice of this buffer which is not a prefix.
jpayne@69 121 };
jpayne@69 122
jpayne@69 123 // =======================================================================================
jpayne@69 124 // Buffered streams implemented as wrappers around regular streams
jpayne@69 125
jpayne@69 126 class BufferedInputStreamWrapper: public BufferedInputStream {
jpayne@69 127 // Implements BufferedInputStream in terms of an InputStream.
jpayne@69 128 //
jpayne@69 129 // Note that the underlying stream's position is unpredictable once the wrapper is destroyed,
jpayne@69 130 // unless the entire stream was consumed. To read a predictable number of bytes in a buffered
jpayne@69 131 // way without going over, you'd need this wrapper to wrap some other wrapper which itself
jpayne@69 132 // implements an artificial EOF at the desired point. Such a stream should be trivial to write
jpayne@69 133 // but is not provided by the library at this time.
jpayne@69 134
jpayne@69 135 public:
jpayne@69 136 explicit BufferedInputStreamWrapper(InputStream& inner, ArrayPtr<byte> buffer = nullptr);
jpayne@69 137 // Creates a buffered stream wrapping the given non-buffered stream. No guarantee is made about
jpayne@69 138 // the position of the inner stream after a buffered wrapper has been created unless the entire
jpayne@69 139 // input is read.
jpayne@69 140 //
jpayne@69 141 // If the second parameter is non-null, the stream uses the given buffer instead of allocating
jpayne@69 142 // its own. This may improve performance if the buffer can be reused.
jpayne@69 143
jpayne@69 144 KJ_DISALLOW_COPY_AND_MOVE(BufferedInputStreamWrapper);
jpayne@69 145 ~BufferedInputStreamWrapper() noexcept(false);
jpayne@69 146
jpayne@69 147 // implements BufferedInputStream ----------------------------------
jpayne@69 148 ArrayPtr<const byte> tryGetReadBuffer() override;
jpayne@69 149 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
jpayne@69 150 void skip(size_t bytes) override;
jpayne@69 151
jpayne@69 152 private:
jpayne@69 153 InputStream& inner;
jpayne@69 154 Array<byte> ownedBuffer;
jpayne@69 155 ArrayPtr<byte> buffer;
jpayne@69 156 ArrayPtr<byte> bufferAvailable;
jpayne@69 157 };
jpayne@69 158
jpayne@69 159 class BufferedOutputStreamWrapper: public BufferedOutputStream {
jpayne@69 160 // Implements BufferedOutputStream in terms of an OutputStream. Note that writes to the
jpayne@69 161 // underlying stream may be delayed until flush() is called or the wrapper is destroyed.
jpayne@69 162
jpayne@69 163 public:
jpayne@69 164 explicit BufferedOutputStreamWrapper(OutputStream& inner, ArrayPtr<byte> buffer = nullptr);
jpayne@69 165 // Creates a buffered stream wrapping the given non-buffered stream.
jpayne@69 166 //
jpayne@69 167 // If the second parameter is non-null, the stream uses the given buffer instead of allocating
jpayne@69 168 // its own. This may improve performance if the buffer can be reused.
jpayne@69 169
jpayne@69 170 KJ_DISALLOW_COPY_AND_MOVE(BufferedOutputStreamWrapper);
jpayne@69 171 ~BufferedOutputStreamWrapper() noexcept(false);
jpayne@69 172
jpayne@69 173 void flush();
jpayne@69 174 // Force the wrapper to write any remaining bytes in its buffer to the inner stream. Note that
jpayne@69 175 // this only flushes this object's buffer; this object has no idea how to flush any other buffers
jpayne@69 176 // that may be present in the underlying stream.
jpayne@69 177
jpayne@69 178 // implements BufferedOutputStream ---------------------------------
jpayne@69 179 ArrayPtr<byte> getWriteBuffer() override;
jpayne@69 180 void write(const void* buffer, size_t size) override;
jpayne@69 181
jpayne@69 182 private:
jpayne@69 183 OutputStream& inner;
jpayne@69 184 Array<byte> ownedBuffer;
jpayne@69 185 ArrayPtr<byte> buffer;
jpayne@69 186 byte* bufferPos;
jpayne@69 187 UnwindDetector unwindDetector;
jpayne@69 188 };
jpayne@69 189
jpayne@69 190 // =======================================================================================
jpayne@69 191 // Array I/O
jpayne@69 192
jpayne@69 193 class ArrayInputStream: public BufferedInputStream {
jpayne@69 194 public:
jpayne@69 195 explicit ArrayInputStream(ArrayPtr<const byte> array);
jpayne@69 196 KJ_DISALLOW_COPY_AND_MOVE(ArrayInputStream);
jpayne@69 197 ~ArrayInputStream() noexcept(false);
jpayne@69 198
jpayne@69 199 // implements BufferedInputStream ----------------------------------
jpayne@69 200 ArrayPtr<const byte> tryGetReadBuffer() override;
jpayne@69 201 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
jpayne@69 202 void skip(size_t bytes) override;
jpayne@69 203
jpayne@69 204 private:
jpayne@69 205 ArrayPtr<const byte> array;
jpayne@69 206 };
jpayne@69 207
jpayne@69 208 class ArrayOutputStream: public BufferedOutputStream {
jpayne@69 209 public:
jpayne@69 210 explicit ArrayOutputStream(ArrayPtr<byte> array);
jpayne@69 211 KJ_DISALLOW_COPY_AND_MOVE(ArrayOutputStream);
jpayne@69 212 ~ArrayOutputStream() noexcept(false);
jpayne@69 213
jpayne@69 214 ArrayPtr<byte> getArray() {
jpayne@69 215 // Get the portion of the array which has been filled in.
jpayne@69 216 return arrayPtr(array.begin(), fillPos);
jpayne@69 217 }
jpayne@69 218
jpayne@69 219 // implements BufferedInputStream ----------------------------------
jpayne@69 220 ArrayPtr<byte> getWriteBuffer() override;
jpayne@69 221 void write(const void* buffer, size_t size) override;
jpayne@69 222
jpayne@69 223 private:
jpayne@69 224 ArrayPtr<byte> array;
jpayne@69 225 byte* fillPos;
jpayne@69 226 };
jpayne@69 227
jpayne@69 228 class VectorOutputStream: public BufferedOutputStream {
jpayne@69 229 public:
jpayne@69 230 explicit VectorOutputStream(size_t initialCapacity = 4096);
jpayne@69 231 KJ_DISALLOW_COPY_AND_MOVE(VectorOutputStream);
jpayne@69 232 ~VectorOutputStream() noexcept(false);
jpayne@69 233
jpayne@69 234 ArrayPtr<byte> getArray() {
jpayne@69 235 // Get the portion of the array which has been filled in.
jpayne@69 236 return arrayPtr(vector.begin(), fillPos);
jpayne@69 237 }
jpayne@69 238
jpayne@69 239 void clear() { fillPos = vector.begin(); }
jpayne@69 240
jpayne@69 241 // implements BufferedInputStream ----------------------------------
jpayne@69 242 ArrayPtr<byte> getWriteBuffer() override;
jpayne@69 243 void write(const void* buffer, size_t size) override;
jpayne@69 244
jpayne@69 245 private:
jpayne@69 246 Array<byte> vector;
jpayne@69 247 byte* fillPos;
jpayne@69 248
jpayne@69 249 void grow(size_t minSize);
jpayne@69 250 };
jpayne@69 251
jpayne@69 252 // =======================================================================================
jpayne@69 253 // File descriptor I/O
jpayne@69 254
jpayne@69 255 class AutoCloseFd {
jpayne@69 256 // A wrapper around a file descriptor which automatically closes the descriptor when destroyed.
jpayne@69 257 // The wrapper supports move construction for transferring ownership of the descriptor. If
jpayne@69 258 // close() returns an error, the destructor throws an exception, UNLESS the destructor is being
jpayne@69 259 // called during unwind from another exception, in which case the close error is ignored.
jpayne@69 260 //
jpayne@69 261 // If your code is not exception-safe, you should not use AutoCloseFd. In this case you will
jpayne@69 262 // have to call close() yourself and handle errors appropriately.
jpayne@69 263
jpayne@69 264 public:
jpayne@69 265 inline AutoCloseFd(): fd(-1) {}
jpayne@69 266 inline AutoCloseFd(decltype(nullptr)): fd(-1) {}
jpayne@69 267 inline explicit AutoCloseFd(int fd): fd(fd) {}
jpayne@69 268 inline AutoCloseFd(AutoCloseFd&& other) noexcept: fd(other.fd) { other.fd = -1; }
jpayne@69 269 KJ_DISALLOW_COPY(AutoCloseFd);
jpayne@69 270 ~AutoCloseFd() noexcept(false);
jpayne@69 271
jpayne@69 272 inline AutoCloseFd& operator=(AutoCloseFd&& other) {
jpayne@69 273 AutoCloseFd old(kj::mv(*this));
jpayne@69 274 fd = other.fd;
jpayne@69 275 other.fd = -1;
jpayne@69 276 return *this;
jpayne@69 277 }
jpayne@69 278
jpayne@69 279 inline AutoCloseFd& operator=(decltype(nullptr)) {
jpayne@69 280 AutoCloseFd old(kj::mv(*this));
jpayne@69 281 return *this;
jpayne@69 282 }
jpayne@69 283
jpayne@69 284 inline operator int() const { return fd; }
jpayne@69 285 inline int get() const { return fd; }
jpayne@69 286
jpayne@69 287 operator bool() const = delete;
jpayne@69 288 // Deleting this operator prevents accidental use in boolean contexts, which
jpayne@69 289 // the int conversion operator above would otherwise allow.
jpayne@69 290
jpayne@69 291 inline bool operator==(decltype(nullptr)) { return fd < 0; }
jpayne@69 292 inline bool operator!=(decltype(nullptr)) { return fd >= 0; }
jpayne@69 293
jpayne@69 294 inline int release() {
jpayne@69 295 // Release ownership of an FD. Not recommended.
jpayne@69 296 int result = fd;
jpayne@69 297 fd = -1;
jpayne@69 298 return result;
jpayne@69 299 }
jpayne@69 300
jpayne@69 301 private:
jpayne@69 302 int fd;
jpayne@69 303 };
jpayne@69 304
jpayne@69 305 inline auto KJ_STRINGIFY(const AutoCloseFd& fd)
jpayne@69 306 -> decltype(kj::toCharSequence(implicitCast<int>(fd))) {
jpayne@69 307 return kj::toCharSequence(implicitCast<int>(fd));
jpayne@69 308 }
jpayne@69 309
jpayne@69 310 class FdInputStream: public InputStream {
jpayne@69 311 // An InputStream wrapping a file descriptor.
jpayne@69 312
jpayne@69 313 public:
jpayne@69 314 explicit FdInputStream(int fd): fd(fd) {}
jpayne@69 315 explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
jpayne@69 316 KJ_DISALLOW_COPY_AND_MOVE(FdInputStream);
jpayne@69 317 ~FdInputStream() noexcept(false);
jpayne@69 318
jpayne@69 319 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
jpayne@69 320
jpayne@69 321 inline int getFd() const { return fd; }
jpayne@69 322
jpayne@69 323 private:
jpayne@69 324 int fd;
jpayne@69 325 AutoCloseFd autoclose;
jpayne@69 326 };
jpayne@69 327
jpayne@69 328 class FdOutputStream: public OutputStream {
jpayne@69 329 // An OutputStream wrapping a file descriptor.
jpayne@69 330
jpayne@69 331 public:
jpayne@69 332 explicit FdOutputStream(int fd): fd(fd) {}
jpayne@69 333 explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
jpayne@69 334 KJ_DISALLOW_COPY_AND_MOVE(FdOutputStream);
jpayne@69 335 ~FdOutputStream() noexcept(false);
jpayne@69 336
jpayne@69 337 void write(const void* buffer, size_t size) override;
jpayne@69 338 void write(ArrayPtr<const ArrayPtr<const byte>> pieces) override;
jpayne@69 339
jpayne@69 340 inline int getFd() const { return fd; }
jpayne@69 341
jpayne@69 342 private:
jpayne@69 343 int fd;
jpayne@69 344 AutoCloseFd autoclose;
jpayne@69 345 };
jpayne@69 346
jpayne@69 347 // =======================================================================================
jpayne@69 348 // Win32 Handle I/O
jpayne@69 349
jpayne@69 350 #ifdef _WIN32
jpayne@69 351
jpayne@69 352 class AutoCloseHandle {
jpayne@69 353 // A wrapper around a Win32 HANDLE which automatically closes the handle when destroyed.
jpayne@69 354 // The wrapper supports move construction for transferring ownership of the handle. If
jpayne@69 355 // CloseHandle() returns an error, the destructor throws an exception, UNLESS the destructor is
jpayne@69 356 // being called during unwind from another exception, in which case the close error is ignored.
jpayne@69 357 //
jpayne@69 358 // If your code is not exception-safe, you should not use AutoCloseHandle. In this case you will
jpayne@69 359 // have to call close() yourself and handle errors appropriately.
jpayne@69 360
jpayne@69 361 public:
jpayne@69 362 inline AutoCloseHandle(): handle((void*)-1) {}
jpayne@69 363 inline AutoCloseHandle(decltype(nullptr)): handle((void*)-1) {}
jpayne@69 364 inline explicit AutoCloseHandle(void* handle): handle(handle) {}
jpayne@69 365 inline AutoCloseHandle(AutoCloseHandle&& other) noexcept: handle(other.handle) {
jpayne@69 366 other.handle = (void*)-1;
jpayne@69 367 }
jpayne@69 368 KJ_DISALLOW_COPY(AutoCloseHandle);
jpayne@69 369 ~AutoCloseHandle() noexcept(false);
jpayne@69 370
jpayne@69 371 inline AutoCloseHandle& operator=(AutoCloseHandle&& other) {
jpayne@69 372 AutoCloseHandle old(kj::mv(*this));
jpayne@69 373 handle = other.handle;
jpayne@69 374 other.handle = (void*)-1;
jpayne@69 375 return *this;
jpayne@69 376 }
jpayne@69 377
jpayne@69 378 inline AutoCloseHandle& operator=(decltype(nullptr)) {
jpayne@69 379 AutoCloseHandle old(kj::mv(*this));
jpayne@69 380 return *this;
jpayne@69 381 }
jpayne@69 382
jpayne@69 383 inline operator void*() const { return handle; }
jpayne@69 384 inline void* get() const { return handle; }
jpayne@69 385
jpayne@69 386 operator bool() const = delete;
jpayne@69 387 // Deleting this operator prevents accidental use in boolean contexts, which
jpayne@69 388 // the void* conversion operator above would otherwise allow.
jpayne@69 389
jpayne@69 390 inline bool operator==(decltype(nullptr)) { return handle != (void*)-1; }
jpayne@69 391 inline bool operator!=(decltype(nullptr)) { return handle == (void*)-1; }
jpayne@69 392
jpayne@69 393 inline void* release() {
jpayne@69 394 // Release ownership of an FD. Not recommended.
jpayne@69 395 void* result = handle;
jpayne@69 396 handle = (void*)-1;
jpayne@69 397 return result;
jpayne@69 398 }
jpayne@69 399
jpayne@69 400 private:
jpayne@69 401 void* handle; // -1 (aka INVALID_HANDLE_VALUE) if not valid.
jpayne@69 402 };
jpayne@69 403
jpayne@69 404 class HandleInputStream: public InputStream {
jpayne@69 405 // An InputStream wrapping a Win32 HANDLE.
jpayne@69 406
jpayne@69 407 public:
jpayne@69 408 explicit HandleInputStream(void* handle): handle(handle) {}
jpayne@69 409 explicit HandleInputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {}
jpayne@69 410 KJ_DISALLOW_COPY_AND_MOVE(HandleInputStream);
jpayne@69 411 ~HandleInputStream() noexcept(false);
jpayne@69 412
jpayne@69 413 size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override;
jpayne@69 414
jpayne@69 415 private:
jpayne@69 416 void* handle;
jpayne@69 417 AutoCloseHandle autoclose;
jpayne@69 418 };
jpayne@69 419
jpayne@69 420 class HandleOutputStream: public OutputStream {
jpayne@69 421 // An OutputStream wrapping a Win32 HANDLE.
jpayne@69 422
jpayne@69 423 public:
jpayne@69 424 explicit HandleOutputStream(void* handle): handle(handle) {}
jpayne@69 425 explicit HandleOutputStream(AutoCloseHandle handle): handle(handle), autoclose(mv(handle)) {}
jpayne@69 426 KJ_DISALLOW_COPY_AND_MOVE(HandleOutputStream);
jpayne@69 427 ~HandleOutputStream() noexcept(false);
jpayne@69 428
jpayne@69 429 void write(const void* buffer, size_t size) override;
jpayne@69 430
jpayne@69 431 private:
jpayne@69 432 void* handle;
jpayne@69 433 AutoCloseHandle autoclose;
jpayne@69 434 };
jpayne@69 435
jpayne@69 436 #endif // _WIN32
jpayne@69 437
jpayne@69 438 } // namespace kj
jpayne@69 439
jpayne@69 440 KJ_END_HEADER