SkStream.h revision 5e5adfd12cc2cb194db971708cd7f34ff47e10b4
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkStream_DEFINED
18#define SkStream_DEFINED
19
20#include "SkRefCnt.h"
21#include "SkScalar.h"
22
23class SkStream : public SkRefCnt {
24public:
25    virtual ~SkStream();
26    /** Called to rewind to the beginning of the stream. If this cannot be
27        done, return false.
28    */
29    virtual bool rewind() = 0;
30    /** If this stream represents a file, this method returns the file's name.
31        If it does not, it returns NULL (the default behavior).
32    */
33    virtual const char* getFileName();
34    /** Called to read or skip size number of bytes.
35        If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
36        If buffer is NULL and size == 0, return the total length of the stream.
37        If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
38        @param buffer   If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
39        @param size The number of bytes to skip or copy
40        @return bytes read on success
41    */
42    virtual size_t read(void* buffer, size_t size) = 0;
43
44    /** Return the total length of the stream.
45    */
46    size_t getLength() { return this->read(NULL, 0); }
47
48    /** Skip the specified number of bytes, returning the actual number
49        of bytes that could be skipped.
50    */
51    size_t skip(size_t bytes);
52
53    /** If the stream is backed by RAM, this method returns the starting
54        address for the data. If not (i.e. it is backed by a file or other
55        structure), this method returns NULL.
56        The default implementation returns NULL.
57    */
58    virtual const void* getMemoryBase();
59
60    int8_t   readS8();
61    int16_t  readS16();
62    int32_t  readS32();
63
64    uint8_t  readU8() { return (uint8_t)this->readS8(); }
65    uint16_t readU16() { return (uint16_t)this->readS16(); }
66    uint32_t readU32() { return (uint32_t)this->readS32(); }
67
68    bool     readBool() { return this->readU8() != 0; }
69    SkScalar readScalar();
70    size_t   readPackedUInt();
71};
72
73class SkWStream : SkNoncopyable {
74public:
75    virtual ~SkWStream();
76
77    /** Called to write bytes to a SkWStream. Returns true on success
78        @param buffer the address of at least size bytes to be written to the stream
79        @param size The number of bytes in buffer to write to the stream
80        @return true on success
81    */
82    virtual bool write(const void* buffer, size_t size) = 0;
83    virtual void newline();
84    virtual void flush();
85
86    // helpers
87
88    bool    write8(U8CPU);
89    bool    write16(U16CPU);
90    bool    write32(uint32_t);
91
92    bool    writeText(const char text[]);
93    bool    writeDecAsText(int32_t);
94    bool    writeHexAsText(uint32_t, int minDigits = 0);
95    bool    writeScalarAsText(SkScalar);
96
97    bool    writeBool(bool v) { return this->write8(v); }
98    bool    writeScalar(SkScalar);
99    bool    writePackedUInt(size_t);
100
101    bool writeStream(SkStream* input, size_t length);
102};
103
104////////////////////////////////////////////////////////////////////////////////////////
105
106#include "SkString.h"
107
108struct SkFILE;
109
110/** A stream that reads from a FILE*, which is opened in the constructor and
111    closed in the destructor
112 */
113class SkFILEStream : public SkStream {
114public:
115    /** Initialize the stream by calling fopen on the specified path. Will be
116        closed in the destructor.
117     */
118    explicit SkFILEStream(const char path[] = NULL);
119    virtual ~SkFILEStream();
120
121    /** Returns true if the current path could be opened.
122    */
123    bool isValid() const { return fFILE != NULL; }
124    /** Close the current file, and open a new file with the specified
125        path. If path is NULL, just close the current file.
126    */
127    void setPath(const char path[]);
128
129    virtual bool rewind();
130    virtual size_t read(void* buffer, size_t size);
131    virtual const char* getFileName();
132
133private:
134    SkFILE*     fFILE;
135    SkString    fName;
136};
137
138/** A stream that reads from a file descriptor
139 */
140class SkFDStream : public SkStream {
141public:
142    /** Initialize the stream with a dup() of the specified file descriptor.
143        If closeWhenDone is true, then the descriptor will be closed in the
144        destructor.
145     */
146    SkFDStream(int fileDesc, bool closeWhenDone);
147    virtual ~SkFDStream();
148
149    /** Returns true if the current path could be opened.
150     */
151    bool isValid() const { return fFD >= 0; }
152
153    virtual bool rewind();
154    virtual size_t read(void* buffer, size_t size);
155    virtual const char* getFileName() { return NULL; }
156
157private:
158    int     fFD;
159    bool    fCloseWhenDone;
160};
161
162class SkMemoryStream : public SkStream {
163public:
164    SkMemoryStream();
165    /** We allocate (and free) the memory. Write to it via getMemoryBase()
166    */
167    SkMemoryStream(size_t length);
168    /** if copyData is true, the stream makes a private copy of the data
169    */
170    SkMemoryStream(const void* data, size_t length, bool copyData = false);
171    virtual ~SkMemoryStream();
172
173    /** Resets the stream to the specified data and length,
174        just like the constructor.
175        if copyData is true, the stream makes a private copy of the data
176    */
177    virtual void setMemory(const void* data, size_t length,
178                           bool copyData = false);
179    void skipToAlign4();
180    virtual bool rewind();
181    virtual size_t read(void* buffer, size_t size);
182    virtual const void* getMemoryBase();
183    const void* getAtPos();
184    size_t seek(size_t offset);
185    size_t peek() const { return fOffset; }
186
187private:
188    const void* fSrc;
189    size_t fSize, fOffset;
190    SkBool8 fWeOwnTheData;
191};
192
193/** \class SkBufferStream
194    This is a wrapper class that adds buffering to another stream.
195    The caller can provide the buffer, or ask SkBufferStream to allocated/free
196    it automatically.
197*/
198class SkBufferStream : public SkStream {
199public:
200    /** Provide the stream to be buffered (proxy), and the size of the buffer that
201        should be used. This will be allocated and freed automatically. If bufferSize is 0,
202        a default buffer size will be used.
203        The proxy stream is referenced, and will be unreferenced in when the
204        bufferstream is destroyed.
205    */
206    SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
207    /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
208        This buffer is owned by the caller, and must be at least bufferSize bytes big.
209        Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
210        If buffer is not NULL, it is an error for bufferSize to be 0.
211     The proxy stream is referenced, and will be unreferenced in when the
212     bufferstream is destroyed.
213    */
214    SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
215    virtual ~SkBufferStream();
216
217    virtual bool        rewind();
218    virtual const char* getFileName();
219    virtual size_t      read(void* buffer, size_t size);
220    virtual const void* getMemoryBase();
221
222private:
223    enum {
224        kDefaultBufferSize  = 128
225    };
226    // illegal
227    SkBufferStream(const SkBufferStream&);
228    SkBufferStream& operator=(const SkBufferStream&);
229
230    SkStream*   fProxy;
231    char*       fBuffer;
232    size_t      fOrigBufferSize, fBufferSize, fBufferOffset;
233    bool        fWeOwnTheBuffer;
234
235    void    init(void*, size_t);
236};
237
238/////////////////////////////////////////////////////////////////////////////////////////////
239
240class SkFILEWStream : public SkWStream {
241public:
242            SkFILEWStream(const char path[]);
243    virtual ~SkFILEWStream();
244
245    /** Returns true if the current path could be opened.
246    */
247    bool isValid() const { return fFILE != NULL; }
248
249    virtual bool write(const void* buffer, size_t size);
250    virtual void flush();
251private:
252    SkFILE* fFILE;
253};
254
255class SkMemoryWStream : public SkWStream {
256public:
257    SkMemoryWStream(void* buffer, size_t size);
258    virtual bool write(const void* buffer, size_t size);
259
260private:
261    char*   fBuffer;
262    size_t  fMaxLength;
263    size_t  fBytesWritten;
264};
265
266class SkDynamicMemoryWStream : public SkWStream {
267public:
268    SkDynamicMemoryWStream();
269    virtual ~SkDynamicMemoryWStream();
270    virtual bool write(const void* buffer, size_t size);
271    // random access write
272    // modifies stream and returns true if offset + size is less than or equal to getOffset()
273    bool write(const void* buffer, size_t offset, size_t size);
274    bool read(void* buffer, size_t offset, size_t size);
275    size_t getOffset() { return fBytesWritten; }
276
277    // copy what has been written to the stream into dst
278    void    copyTo(void* dst) const;
279    /*  return a cache of the flattened data returned by copyTo().
280        This copy is only valid until the next call to write().
281        The memory is managed by the stream class.
282    */
283    const char* getStream() const;
284
285    // same as getStream, but additionally detach the flattened datat
286    const char* detach();
287
288    // reset the stream to its original state
289    void reset();
290    void padToAlign4();
291private:
292    struct Block;
293    Block*  fHead;
294    Block*  fTail;
295    size_t  fBytesWritten;
296    mutable char*   fCopyToCache;
297};
298
299
300class SkDebugWStream : public SkWStream {
301public:
302    // overrides
303    virtual bool write(const void* buffer, size_t size);
304    virtual void newline();
305};
306
307// for now
308typedef SkFILEStream SkURLStream;
309
310#endif
311
312