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 "SkRefCnt.h"
     12 #include "SkScalar.h"
     13 
     14 class SkData;
     15 
     16 class SkStream;
     17 class SkStreamRewindable;
     18 class SkStreamSeekable;
     19 class SkStreamAsset;
     20 class SkStreamMemory;
     21 
     22 /**
     23  *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by
     24  *  memory, or a file, or something else.
     25  *
     26  *  NOTE:
     27  *
     28  *  Classic "streams" APIs are sort of async, in that on a request for N
     29  *  bytes, they may return fewer than N bytes on a given call, in which case
     30  *  the caller can "try again" to get more bytes, eventually (modulo an error)
     31  *  receiving their total N bytes.
     32  *
     33  *  Skia streams behave differently. They are effectively synchronous, and will
     34  *  always return all N bytes of the request if possible. If they return fewer
     35  *  (the read() call returns the number of bytes read) then that means there is
     36  *  no more data (at EOF or hit an error). The caller should *not* call again
     37  *  in hopes of fulfilling more of the request.
     38  */
     39 class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt
     40 public:
     41     /**
     42      *  Attempts to open the specified file, and return a stream to it (using
     43      *  mmap if available). On success, the caller must call unref() on the
     44      *  returned object. On failure, returns NULL.
     45      */
     46     static SkStreamAsset* NewFromFile(const char path[]);
     47 
     48     SK_DECLARE_INST_COUNT(SkStream)
     49 
     50     /** Reads or skips size number of bytes.
     51      *  If buffer == NULL, skip size bytes, return how many were skipped.
     52      *  If buffer != NULL, copy size bytes into buffer, return how many were copied.
     53      *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
     54      *  @param size the number of bytes to skip or copy
     55      *  @return the number of bytes actually read.
     56      */
     57     virtual size_t read(void* buffer, size_t size) = 0;
     58 
     59     /** Skip size number of bytes.
     60      *  @return the actual number bytes that could be skipped.
     61      */
     62     size_t skip(size_t size) {
     63         //return this->read(NULL, size);
     64         //TODO: remove this old logic after updating existing implementations
     65         return 0 == size ? 0 : this->read(NULL, size);
     66     }
     67 
     68     /** Returns true when all the bytes in the stream have been read.
     69      *  This may return true early (when there are no more bytes to be read)
     70      *  or late (after the first unsuccessful read).
     71      *
     72      *  In Progress: do not use until all implementations are updated.
     73      *  TODO: after this is implemented everywhere, make pure virtual.
     74      */
     75     virtual bool isAtEnd() const {
     76         SkASSERT(false);
     77         return true;
     78     }
     79 
     80     int8_t   readS8();
     81     int16_t  readS16();
     82     int32_t  readS32();
     83 
     84     uint8_t  readU8() { return (uint8_t)this->readS8(); }
     85     uint16_t readU16() { return (uint16_t)this->readS16(); }
     86     uint32_t readU32() { return (uint32_t)this->readS32(); }
     87 
     88     bool     readBool() { return this->readU8() != 0; }
     89     SkScalar readScalar();
     90     size_t   readPackedUInt();
     91 
     92     /**
     93      *  Reconstitute an SkData object that was written to the stream
     94      *  using SkWStream::writeData().
     95      */
     96     SkData* readData();
     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     virtual SkStreamRewindable* duplicate() const { return NULL; }
    108 
    109 //SkStreamSeekable
    110     /** Returns true if this stream can report it's current position. */
    111     virtual bool hasPosition() const { return false; }
    112     /** Returns the current position in the stream. If this cannot be done, returns 0. */
    113     virtual size_t getPosition() const { return 0; }
    114 
    115     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
    116      *  If an attempt is made to seek past the end of the stream, the position will be set
    117      *  to the end of the stream.
    118      */
    119     virtual bool seek(size_t position) { return false; }
    120 
    121     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
    122      *  If an attempt is made to move to a position outside the stream, the position will be set
    123      *  to the closest point within the stream (beginning or end).
    124      */
    125     virtual bool move(long offset) { return false; }
    126 
    127     /** Duplicates this stream. If this cannot be done, returns NULL.
    128      *  The returned stream will be positioned the same as this stream.
    129      */
    130     virtual SkStreamSeekable* fork() const { return NULL; }
    131 
    132 //SkStreamAsset
    133     /** Returns true if this stream can report it's total length. */
    134     virtual bool hasLength() const { return false; }
    135     /** Returns the total length of the stream. If this cannot be done, returns 0. */
    136     virtual size_t getLength() const {
    137         //return 0;
    138         //TODO: remove the following after everyone is updated.
    139         return ((SkStream*)this)->read(NULL, 0);
    140     }
    141 
    142 //SkStreamMemory
    143     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
    144     //TODO: replace with virtual const SkData* getData()
    145     virtual const void* getMemoryBase() { return NULL; }
    146 
    147 private:
    148     typedef SkRefCnt INHERITED;
    149 };
    150 
    151 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
    152 class SK_API SkStreamRewindable : public SkStream {
    153 public:
    154     //TODO: remove the following after everyone is updated (ensures new behavior on new classes).
    155     virtual bool isAtEnd() const SK_OVERRIDE = 0;
    156     //TODO: remove the following after everyone is updated (ensures new behavior on new classes).
    157     virtual size_t getLength() const SK_OVERRIDE { return 0; }
    158 
    159     virtual bool rewind() SK_OVERRIDE = 0;
    160     virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0;
    161 };
    162 
    163 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
    164 class SK_API SkStreamSeekable : public SkStreamRewindable {
    165 public:
    166     virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0;
    167 
    168     virtual bool hasPosition() const SK_OVERRIDE { return true; }
    169     virtual size_t getPosition() const SK_OVERRIDE = 0;
    170     virtual bool seek(size_t position) SK_OVERRIDE = 0;
    171     virtual bool move(long offset) SK_OVERRIDE = 0;
    172     virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0;
    173 };
    174 
    175 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
    176 class SK_API SkStreamAsset : public SkStreamSeekable {
    177 public:
    178     virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0;
    179     virtual SkStreamAsset* fork() const SK_OVERRIDE = 0;
    180 
    181     virtual bool hasLength() const SK_OVERRIDE { return true; }
    182     virtual size_t getLength() const SK_OVERRIDE = 0;
    183 };
    184 
    185 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
    186 class SK_API SkStreamMemory : public SkStreamAsset {
    187 public:
    188     virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0;
    189     virtual SkStreamMemory* fork() const SK_OVERRIDE = 0;
    190 
    191     virtual const void* getMemoryBase() SK_OVERRIDE = 0;
    192 };
    193 
    194 class SK_API SkWStream : SkNoncopyable {
    195 public:
    196     SK_DECLARE_INST_COUNT_ROOT(SkWStream)
    197 
    198     virtual ~SkWStream();
    199 
    200     /** Called to write bytes to a SkWStream. Returns true on success
    201         @param buffer the address of at least size bytes to be written to the stream
    202         @param size The number of bytes in buffer to write to the stream
    203         @return true on success
    204     */
    205     virtual bool write(const void* buffer, size_t size) = 0;
    206     virtual void newline();
    207     virtual void flush();
    208 
    209     // helpers
    210 
    211     bool    write8(U8CPU);
    212     bool    write16(U16CPU);
    213     bool    write32(uint32_t);
    214 
    215     bool    writeText(const char text[]);
    216     bool    writeDecAsText(int32_t);
    217     bool    writeBigDecAsText(int64_t, int minDigits = 0);
    218     bool    writeHexAsText(uint32_t, int minDigits = 0);
    219     bool    writeScalarAsText(SkScalar);
    220 
    221     bool    writeBool(bool v) { return this->write8(v); }
    222     bool    writeScalar(SkScalar);
    223     bool    writePackedUInt(size_t);
    224 
    225     bool writeStream(SkStream* input, size_t length);
    226 
    227     /**
    228      * Append an SkData object to the stream, such that it can be read
    229      * out of the stream using SkStream::readData().
    230      *
    231      * Note that the encoding method used to write the SkData object
    232      * to the stream may change over time.  This method DOES NOT
    233      * just write the raw content of the SkData object to the stream.
    234      */
    235     bool writeData(const SkData*);
    236 };
    237 
    238 ////////////////////////////////////////////////////////////////////////////////////////
    239 
    240 #include "SkString.h"
    241 
    242 struct SkFILE;
    243 
    244 /** A stream that wraps a C FILE* file stream. */
    245 class SK_API SkFILEStream : public SkStreamAsset {
    246 public:
    247     SK_DECLARE_INST_COUNT(SkFILEStream)
    248 
    249     /** Initialize the stream by calling sk_fopen on the specified path.
    250      *  This internal stream will be closed in the destructor.
    251      */
    252     explicit SkFILEStream(const char path[] = NULL);
    253 
    254     enum Ownership {
    255         kCallerPasses_Ownership,
    256         kCallerRetains_Ownership
    257     };
    258     /** Initialize the stream with an existing C file stream.
    259      *  While this stream exists, it assumes exclusive access to the C file stream.
    260      *  The C file stream will be closed in the destructor unless the caller specifies
    261      *  kCallerRetains_Ownership.
    262      */
    263     explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership);
    264 
    265     virtual ~SkFILEStream();
    266 
    267     /** Returns true if the current path could be opened. */
    268     bool isValid() const { return fFILE != NULL; }
    269 
    270     /** Close the current file, and open a new file with the specified path.
    271      *  If path is NULL, just close the current file.
    272      */
    273     void setPath(const char path[]);
    274 
    275     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
    276     virtual bool isAtEnd() const SK_OVERRIDE;
    277 
    278     virtual bool rewind() SK_OVERRIDE;
    279     virtual SkStreamAsset* duplicate() const SK_OVERRIDE;
    280 
    281     virtual size_t getPosition() const SK_OVERRIDE;
    282     virtual bool seek(size_t position) SK_OVERRIDE;
    283     virtual bool move(long offset) SK_OVERRIDE;
    284     virtual SkStreamAsset* fork() const SK_OVERRIDE;
    285 
    286     virtual size_t getLength() const SK_OVERRIDE;
    287 
    288     virtual const void* getMemoryBase() SK_OVERRIDE;
    289 
    290 private:
    291     SkFILE*     fFILE;
    292     SkString    fName;
    293     Ownership   fOwnership;
    294     // fData is lazilly initialized when needed.
    295     mutable SkAutoTUnref<SkData> fData;
    296 
    297     typedef SkStreamAsset INHERITED;
    298 };
    299 
    300 class SK_API SkMemoryStream : public SkStreamMemory {
    301 public:
    302     SK_DECLARE_INST_COUNT(SkMemoryStream)
    303 
    304     SkMemoryStream();
    305 
    306     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
    307     SkMemoryStream(size_t length);
    308 
    309     /** If copyData is true, the stream makes a private copy of the data. */
    310     SkMemoryStream(const void* data, size_t length, bool copyData = false);
    311 
    312     /** Use the specified data as the memory for this stream.
    313      *  The stream will call ref() on the data (assuming it is not NULL).
    314      */
    315     SkMemoryStream(SkData*);
    316 
    317     virtual ~SkMemoryStream();
    318 
    319     /** Resets the stream to the specified data and length,
    320         just like the constructor.
    321         if copyData is true, the stream makes a private copy of the data
    322     */
    323     virtual void setMemory(const void* data, size_t length,
    324                            bool copyData = false);
    325     /** Replace any memory buffer with the specified buffer. The caller
    326         must have allocated data with sk_malloc or sk_realloc, since it
    327         will be freed with sk_free.
    328     */
    329     void setMemoryOwned(const void* data, size_t length);
    330 
    331     /** Return the stream's data in a SkData.
    332      *  The caller must call unref() when it is finished using the data.
    333      */
    334     SkData* copyToData() const;
    335 
    336     /**
    337      *  Use the specified data as the memory for this stream.
    338      *  The stream will call ref() on the data (assuming it is not NULL).
    339      *  The function returns the data parameter as a convenience.
    340      */
    341     SkData* setData(SkData*);
    342 
    343     void skipToAlign4();
    344     const void* getAtPos();
    345     size_t peek() const { return fOffset; }
    346 
    347     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
    348     virtual bool isAtEnd() const SK_OVERRIDE;
    349 
    350     virtual bool rewind() SK_OVERRIDE;
    351     virtual SkMemoryStream* duplicate() const SK_OVERRIDE;
    352 
    353     virtual size_t getPosition() const SK_OVERRIDE;
    354     virtual bool seek(size_t position) SK_OVERRIDE;
    355     virtual bool move(long offset) SK_OVERRIDE;
    356     virtual SkMemoryStream* fork() const SK_OVERRIDE;
    357 
    358     virtual size_t getLength() const SK_OVERRIDE;
    359 
    360     virtual const void* getMemoryBase() SK_OVERRIDE;
    361 
    362 private:
    363     SkData* fData;
    364     size_t  fOffset;
    365 
    366     typedef SkStreamMemory INHERITED;
    367 };
    368 
    369 /////////////////////////////////////////////////////////////////////////////////////////////
    370 
    371 class SK_API SkFILEWStream : public SkWStream {
    372 public:
    373     SK_DECLARE_INST_COUNT(SkFILEWStream)
    374 
    375     SkFILEWStream(const char path[]);
    376     virtual ~SkFILEWStream();
    377 
    378     /** Returns true if the current path could be opened.
    379     */
    380     bool isValid() const { return fFILE != NULL; }
    381 
    382     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    383     virtual void flush() SK_OVERRIDE;
    384 
    385 private:
    386     SkFILE* fFILE;
    387 
    388     typedef SkWStream INHERITED;
    389 };
    390 
    391 class SkMemoryWStream : public SkWStream {
    392 public:
    393     SK_DECLARE_INST_COUNT(SkMemoryWStream)
    394 
    395     SkMemoryWStream(void* buffer, size_t size);
    396     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    397     size_t bytesWritten() const { return fBytesWritten; }
    398 
    399 private:
    400     char*   fBuffer;
    401     size_t  fMaxLength;
    402     size_t  fBytesWritten;
    403 
    404     typedef SkWStream INHERITED;
    405 };
    406 
    407 class SK_API SkDynamicMemoryWStream : public SkWStream {
    408 public:
    409     SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
    410 
    411     SkDynamicMemoryWStream();
    412     virtual ~SkDynamicMemoryWStream();
    413 
    414     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    415     // random access write
    416     // modifies stream and returns true if offset + size is less than or equal to getOffset()
    417     bool write(const void* buffer, size_t offset, size_t size);
    418     bool read(void* buffer, size_t offset, size_t size);
    419     size_t getOffset() const { return fBytesWritten; }
    420     size_t bytesWritten() const { return fBytesWritten; }
    421 
    422     // copy what has been written to the stream into dst
    423     void copyTo(void* dst) const;
    424 
    425     /**
    426      *  Return a copy of the data written so far. This call is responsible for
    427      *  calling unref() when they are finished with the data.
    428      */
    429     SkData* copyToData() const;
    430 
    431     /** Reset, returning a reader stream with the current content. */
    432     SkStreamAsset* detachAsStream();
    433 
    434     /** Reset the stream to its original, empty, state. */
    435     void reset();
    436     void padToAlign4();
    437 private:
    438     struct Block;
    439     Block*  fHead;
    440     Block*  fTail;
    441     size_t  fBytesWritten;
    442     mutable SkData* fCopy;  // is invalidated if we write after it is created
    443 
    444     void invalidateCopy();
    445 
    446     // For access to the Block type.
    447     friend class SkBlockMemoryStream;
    448     friend class SkBlockMemoryRefCnt;
    449 
    450     typedef SkWStream INHERITED;
    451 };
    452 
    453 
    454 class SK_API SkDebugWStream : public SkWStream {
    455 public:
    456     SK_DECLARE_INST_COUNT(SkDebugWStream)
    457 
    458     // overrides
    459     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    460     virtual void newline() SK_OVERRIDE;
    461 
    462 private:
    463     typedef SkWStream INHERITED;
    464 };
    465 
    466 // for now
    467 typedef SkFILEStream SkURLStream;
    468 
    469 #endif
    470