blob: 58f5443affdf28cbfd4724c655dad97d9d7f3caa [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkStream_DEFINED
11#define SkStream_DEFINED
12
13#include "SkRefCnt.h"
14#include "SkScalar.h"
15
reed@google.com8d0b5772011-06-24 13:07:31 +000016class SkData;
reed@google.com70442a62011-06-23 21:48:04 +000017
reed@google.comf3166342011-04-26 20:06:08 +000018class SK_API SkStream : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000019public:
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000020 SK_DECLARE_INST_COUNT(SkStream)
21
reed@android.com8a1c16f2008-12-17 15:59:43 +000022 virtual ~SkStream();
23 /** Called to rewind to the beginning of the stream. If this cannot be
24 done, return false.
25 */
26 virtual bool rewind() = 0;
27 /** If this stream represents a file, this method returns the file's name.
28 If it does not, it returns NULL (the default behavior).
29 */
30 virtual const char* getFileName();
31 /** Called to read or skip size number of bytes.
32 If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
33 If buffer is NULL and size == 0, return the total length of the stream.
34 If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
35 @param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
36 @param size The number of bytes to skip or copy
37 @return bytes read on success
38 */
39 virtual size_t read(void* buffer, size_t size) = 0;
40
41 /** Return the total length of the stream.
42 */
43 size_t getLength() { return this->read(NULL, 0); }
44
45 /** Skip the specified number of bytes, returning the actual number
46 of bytes that could be skipped.
47 */
48 size_t skip(size_t bytes);
49
50 /** If the stream is backed by RAM, this method returns the starting
51 address for the data. If not (i.e. it is backed by a file or other
52 structure), this method returns NULL.
53 The default implementation returns NULL.
54 */
55 virtual const void* getMemoryBase();
56
57 int8_t readS8();
58 int16_t readS16();
59 int32_t readS32();
60
61 uint8_t readU8() { return (uint8_t)this->readS8(); }
62 uint16_t readU16() { return (uint16_t)this->readS16(); }
63 uint32_t readU32() { return (uint32_t)this->readS32(); }
64
65 bool readBool() { return this->readU8() != 0; }
66 SkScalar readScalar();
67 size_t readPackedUInt();
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000068
69private:
70 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000071};
72
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +000073class SK_API SkWStream : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000074public:
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);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +000094 bool writeBigDecAsText(int64_t, int minDigits = 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 bool writeHexAsText(uint32_t, int minDigits = 0);
96 bool writeScalarAsText(SkScalar);
97
98 bool writeBool(bool v) { return this->write8(v); }
99 bool writeScalar(SkScalar);
100 bool writePackedUInt(size_t);
101
102 bool writeStream(SkStream* input, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000103
104 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105};
106
107////////////////////////////////////////////////////////////////////////////////////////
108
109#include "SkString.h"
110
111struct SkFILE;
112
113/** A stream that reads from a FILE*, which is opened in the constructor and
114 closed in the destructor
115 */
116class SkFILEStream : public SkStream {
117public:
118 /** Initialize the stream by calling fopen on the specified path. Will be
119 closed in the destructor.
120 */
121 explicit SkFILEStream(const char path[] = NULL);
122 virtual ~SkFILEStream();
123
124 /** Returns true if the current path could be opened.
125 */
126 bool isValid() const { return fFILE != NULL; }
127 /** Close the current file, and open a new file with the specified
128 path. If path is NULL, just close the current file.
129 */
130 void setPath(const char path[]);
131
tomhudson@google.com13413042011-10-03 16:01:10 +0000132 virtual bool rewind() SK_OVERRIDE;
133 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
134 virtual const char* getFileName() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135
136private:
137 SkFILE* fFILE;
138 SkString fName;
139};
140
141/** A stream that reads from a file descriptor
142 */
143class SkFDStream : public SkStream {
144public:
145 /** Initialize the stream with a dup() of the specified file descriptor.
146 If closeWhenDone is true, then the descriptor will be closed in the
147 destructor.
148 */
149 SkFDStream(int fileDesc, bool closeWhenDone);
150 virtual ~SkFDStream();
151
152 /** Returns true if the current path could be opened.
153 */
154 bool isValid() const { return fFD >= 0; }
155
tomhudson@google.com13413042011-10-03 16:01:10 +0000156 virtual bool rewind() SK_OVERRIDE;
157 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
158 virtual const char* getFileName() SK_OVERRIDE { return NULL; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159
160private:
161 int fFD;
162 bool fCloseWhenDone;
163};
164
165class SkMemoryStream : public SkStream {
166public:
167 SkMemoryStream();
168 /** We allocate (and free) the memory. Write to it via getMemoryBase()
169 */
170 SkMemoryStream(size_t length);
171 /** if copyData is true, the stream makes a private copy of the data
172 */
173 SkMemoryStream(const void* data, size_t length, bool copyData = false);
174 virtual ~SkMemoryStream();
175
176 /** Resets the stream to the specified data and length,
177 just like the constructor.
178 if copyData is true, the stream makes a private copy of the data
179 */
180 virtual void setMemory(const void* data, size_t length,
181 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000182 /** Replace any memory buffer with the specified buffer. The caller
183 must have allocated data with sk_malloc or sk_realloc, since it
184 will be freed with sk_free.
185 */
186 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000187
188 /**
189 * Return the stream's data in a SkData. The caller must call unref() when
190 * it is finished using the data.
191 */
192 SkData* copyToData() const;
193
194 /**
195 * Use the specified data as the memory for this stream. The stream will
196 * call ref() on the data (assuming it is not null). The function returns
197 * the data parameter as a convenience.
198 */
199 SkData* setData(SkData*);
200
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000202 virtual bool rewind() SK_OVERRIDE;
203 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
204 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205 const void* getAtPos();
206 size_t seek(size_t offset);
207 size_t peek() const { return fOffset; }
208
209private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000210 SkData* fData;
211 size_t fOffset;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212};
213
214/** \class SkBufferStream
215 This is a wrapper class that adds buffering to another stream.
216 The caller can provide the buffer, or ask SkBufferStream to allocated/free
217 it automatically.
218*/
219class SkBufferStream : public SkStream {
220public:
221 /** Provide the stream to be buffered (proxy), and the size of the buffer that
222 should be used. This will be allocated and freed automatically. If bufferSize is 0,
223 a default buffer size will be used.
224 The proxy stream is referenced, and will be unreferenced in when the
225 bufferstream is destroyed.
226 */
227 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
228 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
229 This buffer is owned by the caller, and must be at least bufferSize bytes big.
230 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
231 If buffer is not NULL, it is an error for bufferSize to be 0.
232 The proxy stream is referenced, and will be unreferenced in when the
233 bufferstream is destroyed.
234 */
235 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
236 virtual ~SkBufferStream();
237
tomhudson@google.com13413042011-10-03 16:01:10 +0000238 virtual bool rewind() SK_OVERRIDE;
239 virtual const char* getFileName() SK_OVERRIDE;
240 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
241 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242
243private:
244 enum {
245 kDefaultBufferSize = 128
246 };
247 // illegal
248 SkBufferStream(const SkBufferStream&);
249 SkBufferStream& operator=(const SkBufferStream&);
250
251 SkStream* fProxy;
252 char* fBuffer;
253 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
254 bool fWeOwnTheBuffer;
255
256 void init(void*, size_t);
257};
258
259/////////////////////////////////////////////////////////////////////////////////////////////
260
261class SkFILEWStream : public SkWStream {
262public:
263 SkFILEWStream(const char path[]);
264 virtual ~SkFILEWStream();
265
266 /** Returns true if the current path could be opened.
267 */
268 bool isValid() const { return fFILE != NULL; }
269
tomhudson@google.com13413042011-10-03 16:01:10 +0000270 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
271 virtual void flush() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000272private:
273 SkFILE* fFILE;
274};
275
276class SkMemoryWStream : public SkWStream {
277public:
278 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000279 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000280 size_t bytesWritten() const { return fBytesWritten; }
281
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282private:
283 char* fBuffer;
284 size_t fMaxLength;
285 size_t fBytesWritten;
286};
287
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000288class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289public:
290 SkDynamicMemoryWStream();
291 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000292
tomhudson@google.com13413042011-10-03 16:01:10 +0000293 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294 // random access write
295 // modifies stream and returns true if offset + size is less than or equal to getOffset()
296 bool write(const void* buffer, size_t offset, size_t size);
297 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000298 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000299 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000300
301 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000302 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000303
304 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000305 * Return a copy of the data written so far. This call is responsible for
306 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000307 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000308 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000309
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 // reset the stream to its original state
311 void reset();
312 void padToAlign4();
313private:
314 struct Block;
315 Block* fHead;
316 Block* fTail;
317 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000318 mutable SkData* fCopy; // is invalidated if we write after it is created
319
320 void invalidateCopy();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321};
322
323
324class SkDebugWStream : public SkWStream {
325public:
326 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000327 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
328 virtual void newline() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000329};
330
331// for now
332typedef SkFILEStream SkURLStream;
333
334#endif