blob: 5a7dd96a3adc681c850b071faf5409cf4830bddb [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 /** Called to rewind to the beginning of the stream. If this cannot be
23 done, return false.
24 */
25 virtual bool rewind() = 0;
26 /** If this stream represents a file, this method returns the file's name.
27 If it does not, it returns NULL (the default behavior).
28 */
29 virtual const char* getFileName();
30 /** Called to read or skip size number of bytes.
31 If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
32 If buffer is NULL and size == 0, return the total length of the stream.
33 If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
34 @param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
35 @param size The number of bytes to skip or copy
36 @return bytes read on success
37 */
38 virtual size_t read(void* buffer, size_t size) = 0;
39
40 /** Return the total length of the stream.
41 */
42 size_t getLength() { return this->read(NULL, 0); }
43
44 /** Skip the specified number of bytes, returning the actual number
45 of bytes that could be skipped.
46 */
47 size_t skip(size_t bytes);
48
49 /** If the stream is backed by RAM, this method returns the starting
50 address for the data. If not (i.e. it is backed by a file or other
51 structure), this method returns NULL.
52 The default implementation returns NULL.
53 */
54 virtual const void* getMemoryBase();
55
56 int8_t readS8();
57 int16_t readS16();
58 int32_t readS32();
59
60 uint8_t readU8() { return (uint8_t)this->readS8(); }
61 uint16_t readU16() { return (uint16_t)this->readS16(); }
62 uint32_t readU32() { return (uint32_t)this->readS32(); }
63
64 bool readBool() { return this->readU8() != 0; }
65 SkScalar readScalar();
66 size_t readPackedUInt();
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000067
68private:
69 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000070};
71
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +000072class SK_API SkWStream : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000073public:
reed@google.com3b429982012-06-26 15:30:08 +000074 SK_DECLARE_INST_COUNT_ROOT(SkWStream)
75
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 virtual ~SkWStream();
77
78 /** Called to write bytes to a SkWStream. Returns true on success
79 @param buffer the address of at least size bytes to be written to the stream
80 @param size The number of bytes in buffer to write to the stream
81 @return true on success
82 */
83 virtual bool write(const void* buffer, size_t size) = 0;
84 virtual void newline();
85 virtual void flush();
86
87 // helpers
88
89 bool write8(U8CPU);
90 bool write16(U16CPU);
91 bool write32(uint32_t);
92
93 bool writeText(const char text[]);
94 bool writeDecAsText(int32_t);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +000095 bool writeBigDecAsText(int64_t, int minDigits = 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 bool writeHexAsText(uint32_t, int minDigits = 0);
97 bool writeScalarAsText(SkScalar);
98
99 bool writeBool(bool v) { return this->write8(v); }
100 bool writeScalar(SkScalar);
101 bool writePackedUInt(size_t);
102
103 bool writeStream(SkStream* input, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000104
105 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106};
107
108////////////////////////////////////////////////////////////////////////////////////////
109
110#include "SkString.h"
111
112struct SkFILE;
113
114/** A stream that reads from a FILE*, which is opened in the constructor and
115 closed in the destructor
116 */
117class SkFILEStream : public SkStream {
118public:
reed@google.com3b429982012-06-26 15:30:08 +0000119 SK_DECLARE_INST_COUNT(SkFILEStream)
120
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 /** Initialize the stream by calling fopen on the specified path. Will be
122 closed in the destructor.
123 */
124 explicit SkFILEStream(const char path[] = NULL);
125 virtual ~SkFILEStream();
126
127 /** Returns true if the current path could be opened.
128 */
129 bool isValid() const { return fFILE != NULL; }
130 /** Close the current file, and open a new file with the specified
131 path. If path is NULL, just close the current file.
132 */
133 void setPath(const char path[]);
134
tomhudson@google.com13413042011-10-03 16:01:10 +0000135 virtual bool rewind() SK_OVERRIDE;
136 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
137 virtual const char* getFileName() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138
139private:
140 SkFILE* fFILE;
141 SkString fName;
reed@google.com3b429982012-06-26 15:30:08 +0000142
143 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144};
145
146/** A stream that reads from a file descriptor
147 */
148class SkFDStream : public SkStream {
149public:
reed@google.com3b429982012-06-26 15:30:08 +0000150 SK_DECLARE_INST_COUNT(SkFDStream)
151
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 /** Initialize the stream with a dup() of the specified file descriptor.
153 If closeWhenDone is true, then the descriptor will be closed in the
154 destructor.
155 */
156 SkFDStream(int fileDesc, bool closeWhenDone);
157 virtual ~SkFDStream();
158
159 /** Returns true if the current path could be opened.
160 */
161 bool isValid() const { return fFD >= 0; }
162
tomhudson@google.com13413042011-10-03 16:01:10 +0000163 virtual bool rewind() SK_OVERRIDE;
164 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
165 virtual const char* getFileName() SK_OVERRIDE { return NULL; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166
167private:
168 int fFD;
169 bool fCloseWhenDone;
reed@google.com3b429982012-06-26 15:30:08 +0000170
171 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172};
173
174class SkMemoryStream : public SkStream {
175public:
reed@google.com3b429982012-06-26 15:30:08 +0000176 SK_DECLARE_INST_COUNT(SkMemoryStream)
177
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 SkMemoryStream();
179 /** We allocate (and free) the memory. Write to it via getMemoryBase()
180 */
181 SkMemoryStream(size_t length);
182 /** if copyData is true, the stream makes a private copy of the data
183 */
184 SkMemoryStream(const void* data, size_t length, bool copyData = false);
185 virtual ~SkMemoryStream();
186
187 /** Resets the stream to the specified data and length,
188 just like the constructor.
189 if copyData is true, the stream makes a private copy of the data
190 */
191 virtual void setMemory(const void* data, size_t length,
192 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000193 /** Replace any memory buffer with the specified buffer. The caller
194 must have allocated data with sk_malloc or sk_realloc, since it
195 will be freed with sk_free.
196 */
197 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000198
199 /**
200 * Return the stream's data in a SkData. The caller must call unref() when
201 * it is finished using the data.
202 */
203 SkData* copyToData() const;
204
205 /**
206 * Use the specified data as the memory for this stream. The stream will
207 * call ref() on the data (assuming it is not null). The function returns
208 * the data parameter as a convenience.
209 */
210 SkData* setData(SkData*);
211
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000213 virtual bool rewind() SK_OVERRIDE;
214 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
215 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 const void* getAtPos();
217 size_t seek(size_t offset);
218 size_t peek() const { return fOffset; }
219
220private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000221 SkData* fData;
222 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000223
224 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225};
226
227/** \class SkBufferStream
228 This is a wrapper class that adds buffering to another stream.
229 The caller can provide the buffer, or ask SkBufferStream to allocated/free
230 it automatically.
231*/
232class SkBufferStream : public SkStream {
233public:
reed@google.com3b429982012-06-26 15:30:08 +0000234 SK_DECLARE_INST_COUNT(SkBufferStream)
235
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 /** Provide the stream to be buffered (proxy), and the size of the buffer that
237 should be used. This will be allocated and freed automatically. If bufferSize is 0,
238 a default buffer size will be used.
239 The proxy stream is referenced, and will be unreferenced in when the
240 bufferstream is destroyed.
241 */
242 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
243 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
244 This buffer is owned by the caller, and must be at least bufferSize bytes big.
245 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
246 If buffer is not NULL, it is an error for bufferSize to be 0.
247 The proxy stream is referenced, and will be unreferenced in when the
248 bufferstream is destroyed.
249 */
250 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
251 virtual ~SkBufferStream();
252
tomhudson@google.com13413042011-10-03 16:01:10 +0000253 virtual bool rewind() SK_OVERRIDE;
254 virtual const char* getFileName() SK_OVERRIDE;
255 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
256 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257
258private:
259 enum {
260 kDefaultBufferSize = 128
261 };
262 // illegal
263 SkBufferStream(const SkBufferStream&);
264 SkBufferStream& operator=(const SkBufferStream&);
265
266 SkStream* fProxy;
267 char* fBuffer;
268 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
269 bool fWeOwnTheBuffer;
270
271 void init(void*, size_t);
reed@google.com3b429982012-06-26 15:30:08 +0000272
273 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274};
275
276/////////////////////////////////////////////////////////////////////////////////////////////
277
278class SkFILEWStream : public SkWStream {
279public:
reed@google.com3b429982012-06-26 15:30:08 +0000280 SK_DECLARE_INST_COUNT(SkFILEWStream)
281
282 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000283 virtual ~SkFILEWStream();
284
285 /** Returns true if the current path could be opened.
286 */
287 bool isValid() const { return fFILE != NULL; }
288
tomhudson@google.com13413042011-10-03 16:01:10 +0000289 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
290 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000291
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292private:
293 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000294
295 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296};
297
298class SkMemoryWStream : public SkWStream {
299public:
reed@google.com3b429982012-06-26 15:30:08 +0000300 SK_DECLARE_INST_COUNT(SkMemoryWStream)
301
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000303 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000304 size_t bytesWritten() const { return fBytesWritten; }
305
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306private:
307 char* fBuffer;
308 size_t fMaxLength;
309 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000310
311 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312};
313
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000314class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315public:
reed@google.com3b429982012-06-26 15:30:08 +0000316 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
317
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318 SkDynamicMemoryWStream();
319 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000320
tomhudson@google.com13413042011-10-03 16:01:10 +0000321 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 // random access write
323 // modifies stream and returns true if offset + size is less than or equal to getOffset()
324 bool write(const void* buffer, size_t offset, size_t size);
325 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000326 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000327 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328
329 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000330 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000331
332 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000333 * Return a copy of the data written so far. This call is responsible for
334 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000335 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000336 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000337
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 // reset the stream to its original state
339 void reset();
340 void padToAlign4();
341private:
342 struct Block;
343 Block* fHead;
344 Block* fTail;
345 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000346 mutable SkData* fCopy; // is invalidated if we write after it is created
347
348 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000349
350 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000351};
352
353
354class SkDebugWStream : public SkWStream {
355public:
reed@google.com3b429982012-06-26 15:30:08 +0000356 SK_DECLARE_INST_COUNT(SkDebugWStream)
357
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000359 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
360 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000361
362private:
363 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364};
365
366// for now
367typedef SkFILEStream SkURLStream;
368
369#endif