capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

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