SkStream.h revision 8e3fb2d6f416eaa882d1e17421f38a3c55e2d3ff
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkStream_DEFINED
11#define SkStream_DEFINED
12
13#include "SkRefCnt.h"
14#include "SkScalar.h"
15
16class SkData;
17
18class SK_API SkStream : public SkRefCnt {
19public:
20    /**
21     *  Attempts to open the specified file, and return a stream to it (using
22     *  mmap if available). On success, the caller must call unref() on the
23     *  returned object. On failure, returns NULL.
24     */
25    static SkStream* NewFromFile(const char path[]);
26
27    SK_DECLARE_INST_COUNT(SkStream)
28
29    /** Called to rewind to the beginning of the stream. If this cannot be
30        done, return false.
31    */
32    virtual bool rewind() = 0;
33    /** If this stream represents a file, this method returns the file's name.
34        If it does not, it returns NULL (the default behavior).
35    */
36    virtual const char* getFileName();
37    /** Called to read or skip size number of bytes.
38        If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
39        If buffer is NULL and size == 0, return the total length of the stream.
40        If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
41        @param buffer   If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
42        @param size The number of bytes to skip or copy
43        @return bytes read on success
44    */
45    virtual size_t read(void* buffer, size_t size) = 0;
46
47    /** Return the total length of the stream.
48    */
49    size_t getLength() { return this->read(NULL, 0); }
50
51    /** Skip the specified number of bytes, returning the actual number
52        of bytes that could be skipped.
53    */
54    size_t skip(size_t bytes);
55
56    /** If the stream is backed by RAM, this method returns the starting
57        address for the data. If not (i.e. it is backed by a file or other
58        structure), this method returns NULL.
59        The default implementation returns NULL.
60    */
61    virtual const void* getMemoryBase();
62
63    int8_t   readS8();
64    int16_t  readS16();
65    int32_t  readS32();
66
67    uint8_t  readU8() { return (uint8_t)this->readS8(); }
68    uint16_t readU16() { return (uint16_t)this->readS16(); }
69    uint32_t readU32() { return (uint32_t)this->readS32(); }
70
71    bool     readBool() { return this->readU8() != 0; }
72    SkScalar readScalar();
73    size_t   readPackedUInt();
74
75    /**
76     *  Reconstitute an SkData object that was written to the stream
77     *  using SkWStream::writeData().
78     */
79    SkData* readData();
80
81private:
82    typedef SkRefCnt INHERITED;
83};
84
85class SK_API SkWStream : SkNoncopyable {
86public:
87    SK_DECLARE_INST_COUNT_ROOT(SkWStream)
88
89    virtual ~SkWStream();
90
91    /** Called to write bytes to a SkWStream. Returns true on success
92        @param buffer the address of at least size bytes to be written to the stream
93        @param size The number of bytes in buffer to write to the stream
94        @return true on success
95    */
96    virtual bool write(const void* buffer, size_t size) = 0;
97    virtual void newline();
98    virtual void flush();
99
100    // helpers
101
102    bool    write8(U8CPU);
103    bool    write16(U16CPU);
104    bool    write32(uint32_t);
105
106    bool    writeText(const char text[]);
107    bool    writeDecAsText(int32_t);
108    bool    writeBigDecAsText(int64_t, int minDigits = 0);
109    bool    writeHexAsText(uint32_t, int minDigits = 0);
110    bool    writeScalarAsText(SkScalar);
111
112    bool    writeBool(bool v) { return this->write8(v); }
113    bool    writeScalar(SkScalar);
114    bool    writePackedUInt(size_t);
115
116    bool writeStream(SkStream* input, size_t length);
117
118    /**
119     * Append an SkData object to the stream, such that it can be read
120     * out of the stream using SkStream::readData().
121     *
122     * Note that the encoding method used to write the SkData object
123     * to the stream may change over time.  This method DOES NOT
124     * just write the raw content of the SkData object to the stream.
125     */
126    bool writeData(const SkData*);
127};
128
129////////////////////////////////////////////////////////////////////////////////////////
130
131#include "SkString.h"
132
133struct SkFILE;
134
135/** A stream that reads from a FILE*, which is opened in the constructor and
136    closed in the destructor
137 */
138class SK_API SkFILEStream : public SkStream {
139public:
140    SK_DECLARE_INST_COUNT(SkFILEStream)
141
142    /** Initialize the stream by calling fopen on the specified path. Will be
143        closed in the destructor.
144     */
145    explicit SkFILEStream(const char path[] = NULL);
146    virtual ~SkFILEStream();
147
148    /** Returns true if the current path could be opened.
149    */
150    bool isValid() const { return fFILE != NULL; }
151    /** Close the current file, and open a new file with the specified
152        path. If path is NULL, just close the current file.
153    */
154    void setPath(const char path[]);
155
156    virtual bool rewind() SK_OVERRIDE;
157    virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
158    virtual const char* getFileName() SK_OVERRIDE;
159
160private:
161    SkFILE*     fFILE;
162    SkString    fName;
163
164    typedef SkStream INHERITED;
165};
166
167/** A stream that reads from a file descriptor
168 */
169class SK_API SkFDStream : public SkStream {
170public:
171    SK_DECLARE_INST_COUNT(SkFDStream)
172
173    /** Initialize the stream with a dup() of the specified file descriptor.
174        If closeWhenDone is true, then the descriptor will be closed in the
175        destructor.
176     */
177    SkFDStream(int fileDesc, bool closeWhenDone);
178    virtual ~SkFDStream();
179
180    /** Returns true if the current path could be opened.
181     */
182    bool isValid() const { return fFD >= 0; }
183
184    virtual bool rewind() SK_OVERRIDE;
185    virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
186    virtual const char* getFileName() SK_OVERRIDE { return NULL; }
187
188private:
189    int     fFD;
190    bool    fCloseWhenDone;
191
192    typedef SkStream INHERITED;
193};
194
195class SK_API SkMemoryStream : public SkStream {
196public:
197    SK_DECLARE_INST_COUNT(SkMemoryStream)
198
199    SkMemoryStream();
200    /** We allocate (and free) the memory. Write to it via getMemoryBase()
201    */
202    SkMemoryStream(size_t length);
203    /** if copyData is true, the stream makes a private copy of the data
204    */
205    SkMemoryStream(const void* data, size_t length, bool copyData = false);
206
207    /**
208     *  Use the specified data as the memory for this stream. The stream will
209     *  call ref() on the data (assuming it is not null).
210     */
211    SkMemoryStream(SkData*);
212
213    virtual ~SkMemoryStream();
214
215    /** Resets the stream to the specified data and length,
216        just like the constructor.
217        if copyData is true, the stream makes a private copy of the data
218    */
219    virtual void setMemory(const void* data, size_t length,
220                           bool copyData = false);
221    /** Replace any memory buffer with the specified buffer. The caller
222        must have allocated data with sk_malloc or sk_realloc, since it
223        will be freed with sk_free.
224    */
225    void setMemoryOwned(const void* data, size_t length);
226
227    /**
228     *  Return the stream's data in a SkData. The caller must call unref() when
229     *  it is finished using the data.
230     */
231    SkData* copyToData() const;
232
233    /**
234     *  Use the specified data as the memory for this stream. The stream will
235     *  call ref() on the data (assuming it is not null). The function returns
236     *  the data parameter as a convenience.
237     */
238    SkData* setData(SkData*);
239
240    void skipToAlign4();
241    virtual bool rewind() SK_OVERRIDE;
242    virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
243    virtual const void* getMemoryBase() SK_OVERRIDE;
244    const void* getAtPos();
245    size_t seek(size_t offset);
246    size_t peek() const { return fOffset; }
247
248private:
249    SkData* fData;
250    size_t  fOffset;
251
252    typedef SkStream INHERITED;
253};
254
255/** \class SkBufferStream
256    This is a wrapper class that adds buffering to another stream.
257    The caller can provide the buffer, or ask SkBufferStream to allocated/free
258    it automatically.
259*/
260class SK_API SkBufferStream : public SkStream {
261public:
262    SK_DECLARE_INST_COUNT(SkBufferStream)
263
264    /** Provide the stream to be buffered (proxy), and the size of the buffer that
265        should be used. This will be allocated and freed automatically. If bufferSize is 0,
266        a default buffer size will be used.
267        The proxy stream is referenced, and will be unreferenced in when the
268        bufferstream is destroyed.
269    */
270    SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
271    /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
272        This buffer is owned by the caller, and must be at least bufferSize bytes big.
273        Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
274        If buffer is not NULL, it is an error for bufferSize to be 0.
275     The proxy stream is referenced, and will be unreferenced in when the
276     bufferstream is destroyed.
277    */
278    SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
279    virtual ~SkBufferStream();
280
281    virtual bool        rewind() SK_OVERRIDE;
282    virtual const char* getFileName() SK_OVERRIDE;
283    virtual size_t      read(void* buffer, size_t size) SK_OVERRIDE;
284    virtual const void* getMemoryBase() SK_OVERRIDE;
285
286private:
287    enum {
288        kDefaultBufferSize  = 128
289    };
290    // illegal
291    SkBufferStream(const SkBufferStream&);
292    SkBufferStream& operator=(const SkBufferStream&);
293
294    SkStream*   fProxy;
295    char*       fBuffer;
296    size_t      fOrigBufferSize, fBufferSize, fBufferOffset;
297    bool        fWeOwnTheBuffer;
298
299    void    init(void*, size_t);
300
301    typedef SkStream INHERITED;
302};
303
304/////////////////////////////////////////////////////////////////////////////////////////////
305
306class SK_API SkFILEWStream : public SkWStream {
307public:
308    SK_DECLARE_INST_COUNT(SkFILEWStream)
309
310    SkFILEWStream(const char path[]);
311    virtual ~SkFILEWStream();
312
313    /** Returns true if the current path could be opened.
314    */
315    bool isValid() const { return fFILE != NULL; }
316
317    virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
318    virtual void flush() SK_OVERRIDE;
319
320private:
321    SkFILE* fFILE;
322
323    typedef SkWStream INHERITED;
324};
325
326class SkMemoryWStream : public SkWStream {
327public:
328    SK_DECLARE_INST_COUNT(SkMemoryWStream)
329
330    SkMemoryWStream(void* buffer, size_t size);
331    virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
332    size_t bytesWritten() const { return fBytesWritten; }
333
334private:
335    char*   fBuffer;
336    size_t  fMaxLength;
337    size_t  fBytesWritten;
338
339    typedef SkWStream INHERITED;
340};
341
342class SK_API SkDynamicMemoryWStream : public SkWStream {
343public:
344    SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
345
346    SkDynamicMemoryWStream();
347    virtual ~SkDynamicMemoryWStream();
348
349    virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
350    // random access write
351    // modifies stream and returns true if offset + size is less than or equal to getOffset()
352    bool write(const void* buffer, size_t offset, size_t size);
353    bool read(void* buffer, size_t offset, size_t size);
354    size_t getOffset() const { return fBytesWritten; }
355    size_t bytesWritten() const { return fBytesWritten; }
356
357    // copy what has been written to the stream into dst
358    void copyTo(void* dst) const;
359
360    /**
361     *  Return a copy of the data written so far. This call is responsible for
362     *  calling unref() when they are finished with the data.
363     */
364    SkData* copyToData() const;
365
366    // reset the stream to its original state
367    void reset();
368    void padToAlign4();
369private:
370    struct Block;
371    Block*  fHead;
372    Block*  fTail;
373    size_t  fBytesWritten;
374    mutable SkData* fCopy;  // is invalidated if we write after it is created
375
376    void invalidateCopy();
377
378    typedef SkWStream INHERITED;
379};
380
381
382class SK_API SkDebugWStream : public SkWStream {
383public:
384    SK_DECLARE_INST_COUNT(SkDebugWStream)
385
386    // overrides
387    virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
388    virtual void newline() SK_OVERRIDE;
389
390private:
391    typedef SkWStream INHERITED;
392};
393
394// for now
395typedef SkFILEStream SkURLStream;
396
397#endif
398