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