Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkStream_DEFINED
      9 #define SkStream_DEFINED
     10 
     11 #include "SkData.h"
     12 #include "SkRefCnt.h"
     13 #include "SkScalar.h"
     14 
     15 #include <memory.h>
     16 
     17 class SkStream;
     18 class SkStreamRewindable;
     19 class SkStreamSeekable;
     20 class SkStreamAsset;
     21 class SkStreamMemory;
     22 
     23 /**
     24  *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by
     25  *  memory, or a file, or something else.
     26  *
     27  *  NOTE:
     28  *
     29  *  Classic "streams" APIs are sort of async, in that on a request for N
     30  *  bytes, they may return fewer than N bytes on a given call, in which case
     31  *  the caller can "try again" to get more bytes, eventually (modulo an error)
     32  *  receiving their total N bytes.
     33  *
     34  *  Skia streams behave differently. They are effectively synchronous, and will
     35  *  always return all N bytes of the request if possible. If they return fewer
     36  *  (the read() call returns the number of bytes read) then that means there is
     37  *  no more data (at EOF or hit an error). The caller should *not* call again
     38  *  in hopes of fulfilling more of the request.
     39  */
     40 class SK_API SkStream : public SkNoncopyable {
     41 public:
     42     virtual ~SkStream() {}
     43 
     44     /**
     45      *  Attempts to open the specified file as a stream, returns nullptr on failure.
     46      */
     47     static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
     48 
     49     /** Reads or skips size number of bytes.
     50      *  If buffer == NULL, skip size bytes, return how many were skipped.
     51      *  If buffer != NULL, copy size bytes into buffer, return how many were copied.
     52      *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
     53      *  @param size the number of bytes to skip or copy
     54      *  @return the number of bytes actually read.
     55      */
     56     virtual size_t read(void* buffer, size_t size) = 0;
     57 
     58     /** Skip size number of bytes.
     59      *  @return the actual number bytes that could be skipped.
     60      */
     61     size_t skip(size_t size) {
     62         return this->read(nullptr, size);
     63     }
     64 
     65     /**
     66      *  Attempt to peek at size bytes.
     67      *  If this stream supports peeking, copy min(size, peekable bytes) into
     68      *  buffer, and return the number of bytes copied.
     69      *  If the stream does not support peeking, or cannot peek any bytes,
     70      *  return 0 and leave buffer unchanged.
     71      *  The stream is guaranteed to be in the same visible state after this
     72      *  call, regardless of success or failure.
     73      *  @param buffer Must not be NULL, and must be at least size bytes. Destination
     74      *      to copy bytes.
     75      *  @param size Number of bytes to copy.
     76      *  @return The number of bytes peeked/copied.
     77      */
     78     virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
     79 
     80     /** Returns true when all the bytes in the stream have been read.
     81      *  This may return true early (when there are no more bytes to be read)
     82      *  or late (after the first unsuccessful read).
     83      */
     84     virtual bool isAtEnd() const = 0;
     85 
     86     int8_t   readS8();
     87     int16_t  readS16();
     88     int32_t  readS32();
     89 
     90     uint8_t  readU8() { return (uint8_t)this->readS8(); }
     91     uint16_t readU16() { return (uint16_t)this->readS16(); }
     92     uint32_t readU32() { return (uint32_t)this->readS32(); }
     93 
     94     bool     readBool() { return this->readU8() != 0; }
     95     SkScalar readScalar();
     96     size_t   readPackedUInt();
     97 
     98 //SkStreamRewindable
     99     /** Rewinds to the beginning of the stream. Returns true if the stream is known
    100      *  to be at the beginning after this call returns.
    101      */
    102     virtual bool rewind() { return false; }
    103 
    104     /** Duplicates this stream. If this cannot be done, returns NULL.
    105      *  The returned stream will be positioned at the beginning of its data.
    106      */
    107     std::unique_ptr<SkStream> duplicate() const {
    108         return std::unique_ptr<SkStream>(this->onDuplicate());
    109     }
    110     /** Duplicates this stream. If this cannot be done, returns NULL.
    111      *  The returned stream will be positioned the same as this stream.
    112      */
    113     std::unique_ptr<SkStream> fork() const {
    114         return std::unique_ptr<SkStream>(this->onFork());
    115     }
    116 
    117 //SkStreamSeekable
    118     /** Returns true if this stream can report it's current position. */
    119     virtual bool hasPosition() const { return false; }
    120     /** Returns the current position in the stream. If this cannot be done, returns 0. */
    121     virtual size_t getPosition() const { return 0; }
    122 
    123     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
    124      *  If an attempt is made to seek past the end of the stream, the position will be set
    125      *  to the end of the stream.
    126      */
    127     virtual bool seek(size_t /*position*/) { return false; }
    128 
    129     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
    130      *  If an attempt is made to move to a position outside the stream, the position will be set
    131      *  to the closest point within the stream (beginning or end).
    132      */
    133     virtual bool move(long /*offset*/) { return false; }
    134 
    135 //SkStreamAsset
    136     /** Returns true if this stream can report it's total length. */
    137     virtual bool hasLength() const { return false; }
    138     /** Returns the total length of the stream. If this cannot be done, returns 0. */
    139     virtual size_t getLength() const { return 0; }
    140 
    141 //SkStreamMemory
    142     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
    143     //TODO: replace with virtual const SkData* getData()
    144     virtual const void* getMemoryBase() { return nullptr; }
    145 
    146 private:
    147     virtual SkStream* onDuplicate() const { return nullptr; }
    148     virtual SkStream* onFork() const { return nullptr; }
    149 };
    150 
    151 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
    152 class SK_API SkStreamRewindable : public SkStream {
    153 public:
    154     bool rewind() override = 0;
    155     std::unique_ptr<SkStreamRewindable> duplicate() const {
    156         return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
    157     }
    158 private:
    159     SkStreamRewindable* onDuplicate() const override = 0;
    160 };
    161 
    162 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
    163 class SK_API SkStreamSeekable : public SkStreamRewindable {
    164 public:
    165     std::unique_ptr<SkStreamSeekable> duplicate() const {
    166         return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
    167     }
    168 
    169     bool hasPosition() const override { return true; }
    170     size_t getPosition() const override = 0;
    171     bool seek(size_t position) override = 0;
    172     bool move(long offset) override = 0;
    173 
    174     std::unique_ptr<SkStreamSeekable> fork() const {
    175         return std::unique_ptr<SkStreamSeekable>(this->onFork());
    176     }
    177 private:
    178     SkStreamSeekable* onDuplicate() const override = 0;
    179     SkStreamSeekable* onFork() const override = 0;
    180 };
    181 
    182 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
    183 class SK_API SkStreamAsset : public SkStreamSeekable {
    184 public:
    185     bool hasLength() const override { return true; }
    186     size_t getLength() const override = 0;
    187 
    188     std::unique_ptr<SkStreamAsset> duplicate() const {
    189         return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
    190     }
    191     std::unique_ptr<SkStreamAsset> fork() const {
    192         return std::unique_ptr<SkStreamAsset>(this->onFork());
    193     }
    194 private:
    195     SkStreamAsset* onDuplicate() const override = 0;
    196     SkStreamAsset* onFork() const override = 0;
    197 };
    198 
    199 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
    200 class SK_API SkStreamMemory : public SkStreamAsset {
    201 public:
    202     const void* getMemoryBase() override = 0;
    203 
    204     std::unique_ptr<SkStreamMemory> duplicate() const {
    205         return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
    206     }
    207     std::unique_ptr<SkStreamMemory> fork() const {
    208         return std::unique_ptr<SkStreamMemory>(this->onFork());
    209     }
    210 private:
    211     SkStreamMemory* onDuplicate() const override = 0;
    212     SkStreamMemory* onFork() const override = 0;
    213 };
    214 
    215 class SK_API SkWStream : SkNoncopyable {
    216 public:
    217     virtual ~SkWStream();
    218 
    219     /** Called to write bytes to a SkWStream. Returns true on success
    220         @param buffer the address of at least size bytes to be written to the stream
    221         @param size The number of bytes in buffer to write to the stream
    222         @return true on success
    223     */
    224     virtual bool write(const void* buffer, size_t size) = 0;
    225     virtual void flush();
    226 
    227     virtual size_t bytesWritten() const = 0;
    228 
    229     // helpers
    230 
    231     bool write8(U8CPU value)   {
    232         uint8_t v = SkToU8(value);
    233         return this->write(&v, 1);
    234     }
    235     bool write16(U16CPU value) {
    236         uint16_t v = SkToU16(value);
    237         return this->write(&v, 2);
    238     }
    239     bool write32(uint32_t v) {
    240         return this->write(&v, 4);
    241     }
    242 
    243     bool writeText(const char text[]) {
    244         SkASSERT(text);
    245         return this->write(text, strlen(text));
    246     }
    247 
    248     bool newline() { return this->write("\n", strlen("\n")); }
    249 
    250     bool    writeDecAsText(int32_t);
    251     bool    writeBigDecAsText(int64_t, int minDigits = 0);
    252     bool    writeHexAsText(uint32_t, int minDigits = 0);
    253     bool    writeScalarAsText(SkScalar);
    254 
    255     bool    writeBool(bool v) { return this->write8(v); }
    256     bool    writeScalar(SkScalar);
    257     bool    writePackedUInt(size_t);
    258 
    259     bool    writeStream(SkStream* input, size_t length);
    260 
    261     /**
    262      * This returns the number of bytes in the stream required to store
    263      * 'value'.
    264      */
    265     static int SizeOfPackedUInt(size_t value);
    266 };
    267 
    268 class SK_API SkNullWStream : public SkWStream {
    269 public:
    270     SkNullWStream() : fBytesWritten(0) {}
    271 
    272     bool write(const void*, size_t n) override { fBytesWritten += n; return true; }
    273     void flush() override {}
    274     size_t bytesWritten() const override { return fBytesWritten; }
    275 
    276 private:
    277     size_t fBytesWritten;
    278 };
    279 
    280 ////////////////////////////////////////////////////////////////////////////////////////
    281 
    282 #include <stdio.h>
    283 
    284 /** A stream that wraps a C FILE* file stream. */
    285 class SK_API SkFILEStream : public SkStreamAsset {
    286 public:
    287     /** Initialize the stream by calling sk_fopen on the specified path.
    288      *  This internal stream will be closed in the destructor.
    289      */
    290     explicit SkFILEStream(const char path[] = nullptr);
    291 
    292     /** Initialize the stream with an existing C file stream.
    293      *  The C file stream will be closed in the destructor.
    294      */
    295     explicit SkFILEStream(FILE* file);
    296 
    297     ~SkFILEStream() override;
    298 
    299     static std::unique_ptr<SkFILEStream> Make(const char path[]) {
    300         std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
    301         return stream->isValid() ? std::move(stream) : nullptr;
    302     }
    303 
    304     /** Returns true if the current path could be opened. */
    305     bool isValid() const { return fFILE != nullptr; }
    306 
    307     /** Close this SkFILEStream. */
    308     void close();
    309 
    310     size_t read(void* buffer, size_t size) override;
    311     bool isAtEnd() const override;
    312 
    313     bool rewind() override;
    314     std::unique_ptr<SkStreamAsset> duplicate() const {
    315         return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
    316     }
    317 
    318     size_t getPosition() const override;
    319     bool seek(size_t position) override;
    320     bool move(long offset) override;
    321 
    322     std::unique_ptr<SkStreamAsset> fork() const {
    323         return std::unique_ptr<SkStreamAsset>(this->onFork());
    324     }
    325 
    326     size_t getLength() const override;
    327 
    328 private:
    329     explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset);
    330     explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset, size_t originalOffset);
    331 
    332     SkStreamAsset* onDuplicate() const override;
    333     SkStreamAsset* onFork() const override;
    334 
    335     std::shared_ptr<FILE> fFILE;
    336     // My own council will I keep on sizes and offsets.
    337     size_t fSize;
    338     size_t fOffset;
    339     size_t fOriginalOffset;
    340 
    341     typedef SkStreamAsset INHERITED;
    342 };
    343 
    344 class SK_API SkMemoryStream : public SkStreamMemory {
    345 public:
    346     SkMemoryStream();
    347 
    348     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
    349     SkMemoryStream(size_t length);
    350 
    351     /** If copyData is true, the stream makes a private copy of the data. */
    352     SkMemoryStream(const void* data, size_t length, bool copyData = false);
    353 
    354     /** Creates the stream to read from the specified data */
    355     SkMemoryStream(sk_sp<SkData>);
    356 
    357     /** Returns a stream with a copy of the input data. */
    358     static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);
    359 
    360     /** Returns a stream with a bare pointer reference to the input data. */
    361     static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);
    362 
    363     /** Returns a stream with a shared reference to the input data. */
    364     static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);
    365 
    366     /** Resets the stream to the specified data and length,
    367         just like the constructor.
    368         if copyData is true, the stream makes a private copy of the data
    369     */
    370     virtual void setMemory(const void* data, size_t length,
    371                            bool copyData = false);
    372     /** Replace any memory buffer with the specified buffer. The caller
    373         must have allocated data with sk_malloc or sk_realloc, since it
    374         will be freed with sk_free.
    375     */
    376     void setMemoryOwned(const void* data, size_t length);
    377 
    378     sk_sp<SkData> asData() const { return fData; }
    379     void setData(sk_sp<SkData>);
    380 
    381     void skipToAlign4();
    382     const void* getAtPos();
    383 
    384     size_t read(void* buffer, size_t size) override;
    385     bool isAtEnd() const override;
    386 
    387     size_t peek(void* buffer, size_t size) const override;
    388 
    389     bool rewind() override;
    390 
    391     std::unique_ptr<SkMemoryStream> duplicate() const {
    392         return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
    393     }
    394 
    395     size_t getPosition() const override;
    396     bool seek(size_t position) override;
    397     bool move(long offset) override;
    398 
    399     std::unique_ptr<SkMemoryStream> fork() const {
    400         return std::unique_ptr<SkMemoryStream>(this->onFork());
    401     }
    402 
    403     size_t getLength() const override;
    404 
    405     const void* getMemoryBase() override;
    406 
    407 private:
    408     SkMemoryStream* onDuplicate() const override;
    409     SkMemoryStream* onFork() const override;
    410 
    411     sk_sp<SkData>   fData;
    412     size_t          fOffset;
    413 
    414     typedef SkStreamMemory INHERITED;
    415 };
    416 
    417 /////////////////////////////////////////////////////////////////////////////////////////////
    418 
    419 class SK_API SkFILEWStream : public SkWStream {
    420 public:
    421     SkFILEWStream(const char path[]);
    422     ~SkFILEWStream() override;
    423 
    424     /** Returns true if the current path could be opened.
    425     */
    426     bool isValid() const { return fFILE != nullptr; }
    427 
    428     bool write(const void* buffer, size_t size) override;
    429     void flush() override;
    430     void fsync();
    431     size_t bytesWritten() const override;
    432 
    433 private:
    434     FILE* fFILE;
    435 
    436     typedef SkWStream INHERITED;
    437 };
    438 
    439 class SK_API SkDynamicMemoryWStream : public SkWStream {
    440 public:
    441     SkDynamicMemoryWStream();
    442     ~SkDynamicMemoryWStream() override;
    443 
    444     bool write(const void* buffer, size_t size) override;
    445     size_t bytesWritten() const override;
    446 
    447     bool read(void* buffer, size_t offset, size_t size);
    448 
    449     /** More efficient version of read(dst, 0, bytesWritten()). */
    450     void copyTo(void* dst) const;
    451     bool writeToStream(SkWStream* dst) const;
    452 
    453     /** Equivalent to copyTo() followed by reset(), but may save memory use. */
    454     void copyToAndReset(void* dst);
    455 
    456     /** Equivalent to writeToStream() followed by reset(), but may save memory use. */
    457     bool writeToAndReset(SkWStream* dst);
    458 
    459     /** Return the contents as SkData, and then reset the stream. */
    460     sk_sp<SkData> detachAsData();
    461 
    462     /** Reset, returning a reader stream with the current content. */
    463     std::unique_ptr<SkStreamAsset> detachAsStream();
    464 
    465     /** Reset the stream to its original, empty, state. */
    466     void reset();
    467     void padToAlign4();
    468 private:
    469     struct Block;
    470     Block*  fHead;
    471     Block*  fTail;
    472     size_t  fBytesWrittenBeforeTail;
    473 
    474 #ifdef SK_DEBUG
    475     void validate() const;
    476 #else
    477     void validate() const {}
    478 #endif
    479 
    480     // For access to the Block type.
    481     friend class SkBlockMemoryStream;
    482     friend class SkBlockMemoryRefCnt;
    483 
    484     typedef SkWStream INHERITED;
    485 };
    486 
    487 #endif
    488