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     }
     65 
     66     /** Returns true when all the bytes in the stream have been read.
     67      *  This may return true early (when there are no more bytes to be read)
     68      *  or late (after the first unsuccessful read).
     69      */
     70     virtual bool isAtEnd() const = 0;
     71 
     72     int8_t   readS8();
     73     int16_t  readS16();
     74     int32_t  readS32();
     75 
     76     uint8_t  readU8() { return (uint8_t)this->readS8(); }
     77     uint16_t readU16() { return (uint16_t)this->readS16(); }
     78     uint32_t readU32() { return (uint32_t)this->readS32(); }
     79 
     80     bool     readBool() { return this->readU8() != 0; }
     81     SkScalar readScalar();
     82     size_t   readPackedUInt();
     83 
     84 //SkStreamRewindable
     85     /** Rewinds to the beginning of the stream. Returns true if the stream is known
     86      *  to be at the beginning after this call returns.
     87      */
     88     virtual bool rewind() { return false; }
     89 
     90     /** Duplicates this stream. If this cannot be done, returns NULL.
     91      *  The returned stream will be positioned at the beginning of its data.
     92      */
     93     virtual SkStreamRewindable* duplicate() const { return NULL; }
     94 
     95 //SkStreamSeekable
     96     /** Returns true if this stream can report it's current position. */
     97     virtual bool hasPosition() const { return false; }
     98     /** Returns the current position in the stream. If this cannot be done, returns 0. */
     99     virtual size_t getPosition() const { return 0; }
    100 
    101     /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
    102      *  If an attempt is made to seek past the end of the stream, the position will be set
    103      *  to the end of the stream.
    104      */
    105     virtual bool seek(size_t position) { return false; }
    106 
    107     /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
    108      *  If an attempt is made to move to a position outside the stream, the position will be set
    109      *  to the closest point within the stream (beginning or end).
    110      */
    111     virtual bool move(long offset) { return false; }
    112 
    113     /** Duplicates this stream. If this cannot be done, returns NULL.
    114      *  The returned stream will be positioned the same as this stream.
    115      */
    116     virtual SkStreamSeekable* fork() const { return NULL; }
    117 
    118 //SkStreamAsset
    119     /** Returns true if this stream can report it's total length. */
    120     virtual bool hasLength() const { return false; }
    121     /** Returns the total length of the stream. If this cannot be done, returns 0. */
    122     virtual size_t getLength() const { return 0; }
    123 
    124 //SkStreamMemory
    125     /** Returns the starting address for the data. If this cannot be done, returns NULL. */
    126     //TODO: replace with virtual const SkData* getData()
    127     virtual const void* getMemoryBase() { return NULL; }
    128 
    129 private:
    130     typedef SkRefCnt INHERITED;
    131 };
    132 
    133 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
    134 class SK_API SkStreamRewindable : public SkStream {
    135 public:
    136     virtual bool rewind() SK_OVERRIDE = 0;
    137     virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0;
    138 };
    139 
    140 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
    141 class SK_API SkStreamSeekable : public SkStreamRewindable {
    142 public:
    143     virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0;
    144 
    145     virtual bool hasPosition() const SK_OVERRIDE { return true; }
    146     virtual size_t getPosition() const SK_OVERRIDE = 0;
    147     virtual bool seek(size_t position) SK_OVERRIDE = 0;
    148     virtual bool move(long offset) SK_OVERRIDE = 0;
    149     virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0;
    150 };
    151 
    152 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
    153 class SK_API SkStreamAsset : public SkStreamSeekable {
    154 public:
    155     virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0;
    156     virtual SkStreamAsset* fork() const SK_OVERRIDE = 0;
    157 
    158     virtual bool hasLength() const SK_OVERRIDE { return true; }
    159     virtual size_t getLength() const SK_OVERRIDE = 0;
    160 };
    161 
    162 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
    163 class SK_API SkStreamMemory : public SkStreamAsset {
    164 public:
    165     virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0;
    166     virtual SkStreamMemory* fork() const SK_OVERRIDE = 0;
    167 
    168     virtual const void* getMemoryBase() SK_OVERRIDE = 0;
    169 };
    170 
    171 class SK_API SkWStream : SkNoncopyable {
    172 public:
    173     SK_DECLARE_INST_COUNT_ROOT(SkWStream)
    174 
    175     virtual ~SkWStream();
    176 
    177     /** Called to write bytes to a SkWStream. Returns true on success
    178         @param buffer the address of at least size bytes to be written to the stream
    179         @param size The number of bytes in buffer to write to the stream
    180         @return true on success
    181     */
    182     virtual bool write(const void* buffer, size_t size) = 0;
    183     virtual void newline();
    184     virtual void flush();
    185 
    186     virtual size_t bytesWritten() const = 0;
    187 
    188     // helpers
    189 
    190     bool    write8(U8CPU);
    191     bool    write16(U16CPU);
    192     bool    write32(uint32_t);
    193 
    194     bool    writeText(const char text[]);
    195     bool    writeDecAsText(int32_t);
    196     bool    writeBigDecAsText(int64_t, int minDigits = 0);
    197     bool    writeHexAsText(uint32_t, int minDigits = 0);
    198     bool    writeScalarAsText(SkScalar);
    199 
    200     bool    writeBool(bool v) { return this->write8(v); }
    201     bool    writeScalar(SkScalar);
    202     bool    writePackedUInt(size_t);
    203 
    204     bool    writeStream(SkStream* input, size_t length);
    205 
    206     /**
    207      * This returns the number of bytes in the stream required to store
    208      * 'value'.
    209      */
    210     static int SizeOfPackedUInt(size_t value);
    211 };
    212 
    213 ////////////////////////////////////////////////////////////////////////////////////////
    214 
    215 #include "SkString.h"
    216 #include <stdio.h>
    217 
    218 struct SkFILE;
    219 
    220 /** A stream that wraps a C FILE* file stream. */
    221 class SK_API SkFILEStream : public SkStreamAsset {
    222 public:
    223     SK_DECLARE_INST_COUNT(SkFILEStream)
    224 
    225     /** Initialize the stream by calling sk_fopen on the specified path.
    226      *  This internal stream will be closed in the destructor.
    227      */
    228     explicit SkFILEStream(const char path[] = NULL);
    229 
    230     enum Ownership {
    231         kCallerPasses_Ownership,
    232         kCallerRetains_Ownership
    233     };
    234     /** Initialize the stream with an existing C file stream.
    235      *  While this stream exists, it assumes exclusive access to the C file stream.
    236      *  The C file stream will be closed in the destructor unless the caller specifies
    237      *  kCallerRetains_Ownership.
    238      */
    239     explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership);
    240 
    241     virtual ~SkFILEStream();
    242 
    243     /** Returns true if the current path could be opened. */
    244     bool isValid() const { return fFILE != NULL; }
    245 
    246     /** Close the current file, and open a new file with the specified path.
    247      *  If path is NULL, just close the current file.
    248      */
    249     void setPath(const char path[]);
    250 
    251     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
    252     virtual bool isAtEnd() const SK_OVERRIDE;
    253 
    254     virtual bool rewind() SK_OVERRIDE;
    255     virtual SkStreamAsset* duplicate() const SK_OVERRIDE;
    256 
    257     virtual size_t getPosition() const SK_OVERRIDE;
    258     virtual bool seek(size_t position) SK_OVERRIDE;
    259     virtual bool move(long offset) SK_OVERRIDE;
    260     virtual SkStreamAsset* fork() const SK_OVERRIDE;
    261 
    262     virtual size_t getLength() const SK_OVERRIDE;
    263 
    264     virtual const void* getMemoryBase() SK_OVERRIDE;
    265 
    266 private:
    267     SkFILE*     fFILE;
    268     SkString    fName;
    269     Ownership   fOwnership;
    270     // fData is lazilly initialized when needed.
    271     mutable SkAutoTUnref<SkData> fData;
    272 
    273     typedef SkStreamAsset INHERITED;
    274 };
    275 
    276 class SK_API SkMemoryStream : public SkStreamMemory {
    277 public:
    278     SK_DECLARE_INST_COUNT(SkMemoryStream)
    279 
    280     SkMemoryStream();
    281 
    282     /** We allocate (and free) the memory. Write to it via getMemoryBase() */
    283     SkMemoryStream(size_t length);
    284 
    285     /** If copyData is true, the stream makes a private copy of the data. */
    286     SkMemoryStream(const void* data, size_t length, bool copyData = false);
    287 
    288     /** Use the specified data as the memory for this stream.
    289      *  The stream will call ref() on the data (assuming it is not NULL).
    290      */
    291     SkMemoryStream(SkData*);
    292 
    293     virtual ~SkMemoryStream();
    294 
    295     /** Resets the stream to the specified data and length,
    296         just like the constructor.
    297         if copyData is true, the stream makes a private copy of the data
    298     */
    299     virtual void setMemory(const void* data, size_t length,
    300                            bool copyData = false);
    301     /** Replace any memory buffer with the specified buffer. The caller
    302         must have allocated data with sk_malloc or sk_realloc, since it
    303         will be freed with sk_free.
    304     */
    305     void setMemoryOwned(const void* data, size_t length);
    306 
    307     /** Return the stream's data in a SkData.
    308      *  The caller must call unref() when it is finished using the data.
    309      */
    310     SkData* copyToData() const;
    311 
    312     /**
    313      *  Use the specified data as the memory for this stream.
    314      *  The stream will call ref() on the data (assuming it is not NULL).
    315      *  The function returns the data parameter as a convenience.
    316      */
    317     SkData* setData(SkData*);
    318 
    319     void skipToAlign4();
    320     const void* getAtPos();
    321     size_t peek() const { return fOffset; }
    322 
    323     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
    324     virtual bool isAtEnd() const SK_OVERRIDE;
    325 
    326     virtual bool rewind() SK_OVERRIDE;
    327     virtual SkMemoryStream* duplicate() const SK_OVERRIDE;
    328 
    329     virtual size_t getPosition() const SK_OVERRIDE;
    330     virtual bool seek(size_t position) SK_OVERRIDE;
    331     virtual bool move(long offset) SK_OVERRIDE;
    332     virtual SkMemoryStream* fork() const SK_OVERRIDE;
    333 
    334     virtual size_t getLength() const SK_OVERRIDE;
    335 
    336     virtual const void* getMemoryBase() SK_OVERRIDE;
    337 
    338 private:
    339     SkData* fData;
    340     size_t  fOffset;
    341 
    342     typedef SkStreamMemory INHERITED;
    343 };
    344 
    345 /////////////////////////////////////////////////////////////////////////////////////////////
    346 
    347 class SK_API SkFILEWStream : public SkWStream {
    348 public:
    349     SK_DECLARE_INST_COUNT(SkFILEWStream)
    350 
    351     SkFILEWStream(const char path[]);
    352     virtual ~SkFILEWStream();
    353 
    354     /** Returns true if the current path could be opened.
    355     */
    356     bool isValid() const { return fFILE != NULL; }
    357 
    358     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    359     virtual void flush() SK_OVERRIDE;
    360     virtual size_t bytesWritten() const SK_OVERRIDE;
    361 
    362 private:
    363     SkFILE* fFILE;
    364 
    365     typedef SkWStream INHERITED;
    366 };
    367 
    368 class SkMemoryWStream : public SkWStream {
    369 public:
    370     SK_DECLARE_INST_COUNT(SkMemoryWStream)
    371 
    372     SkMemoryWStream(void* buffer, size_t size);
    373     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    374     virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; }
    375 
    376 private:
    377     char*   fBuffer;
    378     size_t  fMaxLength;
    379     size_t  fBytesWritten;
    380 
    381     typedef SkWStream INHERITED;
    382 };
    383 
    384 class SK_API SkDynamicMemoryWStream : public SkWStream {
    385 public:
    386     SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
    387 
    388     SkDynamicMemoryWStream();
    389     virtual ~SkDynamicMemoryWStream();
    390 
    391     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    392     virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; }
    393     // random access write
    394     // modifies stream and returns true if offset + size is less than or equal to getOffset()
    395     bool write(const void* buffer, size_t offset, size_t size);
    396     bool read(void* buffer, size_t offset, size_t size);
    397     size_t getOffset() const { return fBytesWritten; }
    398 
    399     // copy what has been written to the stream into dst
    400     void copyTo(void* dst) const;
    401 
    402     /**
    403      *  Return a copy of the data written so far. This call is responsible for
    404      *  calling unref() when they are finished with the data.
    405      */
    406     SkData* copyToData() const;
    407 
    408     /** Reset, returning a reader stream with the current content. */
    409     SkStreamAsset* detachAsStream();
    410 
    411     /** Reset the stream to its original, empty, state. */
    412     void reset();
    413     void padToAlign4();
    414 private:
    415     struct Block;
    416     Block*  fHead;
    417     Block*  fTail;
    418     size_t  fBytesWritten;
    419     mutable SkData* fCopy;  // is invalidated if we write after it is created
    420 
    421     void invalidateCopy();
    422 
    423     // For access to the Block type.
    424     friend class SkBlockMemoryStream;
    425     friend class SkBlockMemoryRefCnt;
    426 
    427     typedef SkWStream INHERITED;
    428 };
    429 
    430 
    431 class SK_API SkDebugWStream : public SkWStream {
    432 public:
    433     SkDebugWStream() : fBytesWritten(0) {}
    434     SK_DECLARE_INST_COUNT(SkDebugWStream)
    435 
    436     // overrides
    437     virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
    438     virtual void newline() SK_OVERRIDE;
    439     virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; }
    440 
    441 private:
    442     size_t fBytesWritten;
    443     typedef SkWStream INHERITED;
    444 };
    445 
    446 // for now
    447 typedef SkFILEStream SkURLStream;
    448 
    449 #endif
    450