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