blob: 30855b35f4e2212dffd2a054c0ba5816e9aa9cdf [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:
reed@google.come1575aa2013-03-18 21:08:46 +000020 /**
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[]);
skia.committer@gmail.com8eaddb02013-03-19 07:15:10 +000026
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000027 SK_DECLARE_INST_COUNT(SkStream)
28
reed@android.com8a1c16f2008-12-17 15:59:43 +000029 /** 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); }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000050
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 /** 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();
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000074
reed@google.com2e079422012-07-02 19:35:13 +000075 /**
epoger@google.com8e3fb2d2013-03-20 15:56:03 +000076 * Reconstitute an SkData object that was written to the stream
77 * using SkWStream::writeData().
reed@google.com2e079422012-07-02 19:35:13 +000078 */
79 SkData* readData();
80
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000081private:
82 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000083};
84
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +000085class SK_API SkWStream : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000086public:
reed@google.com3b429982012-06-26 15:30:08 +000087 SK_DECLARE_INST_COUNT_ROOT(SkWStream)
88
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 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
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000101
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 bool write8(U8CPU);
103 bool write16(U16CPU);
104 bool write32(uint32_t);
105
106 bool writeText(const char text[]);
107 bool writeDecAsText(int32_t);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000108 bool writeBigDecAsText(int64_t, int minDigits = 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 bool writeHexAsText(uint32_t, int minDigits = 0);
110 bool writeScalarAsText(SkScalar);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000111
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 bool writeBool(bool v) { return this->write8(v); }
113 bool writeScalar(SkScalar);
114 bool writePackedUInt(size_t);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000115
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 bool writeStream(SkStream* input, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000117
epoger@google.com8e3fb2d2013-03-20 15:56:03 +0000118 /**
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 */
reed@google.com8a85d0c2011-06-24 19:12:12 +0000126 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127};
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 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000138class SK_API SkFILEStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139public:
reed@google.com3b429982012-06-26 15:30:08 +0000140 SK_DECLARE_INST_COUNT(SkFILEStream)
141
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142 /** 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
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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159
160private:
161 SkFILE* fFILE;
162 SkString fName;
reed@google.com3b429982012-06-26 15:30:08 +0000163
164 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165};
166
167/** A stream that reads from a file descriptor
168 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000169class SK_API SkFDStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170public:
reed@google.com3b429982012-06-26 15:30:08 +0000171 SK_DECLARE_INST_COUNT(SkFDStream)
172
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173 /** 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();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000179
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180 /** Returns true if the current path could be opened.
181 */
182 bool isValid() const { return fFD >= 0; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000183
tomhudson@google.com13413042011-10-03 16:01:10 +0000184 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; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000187
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188private:
189 int fFD;
190 bool fCloseWhenDone;
reed@google.com3b429982012-06-26 15:30:08 +0000191
192 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193};
194
reed@google.coma718c5e2013-03-05 17:49:10 +0000195class SK_API SkMemoryStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196public:
reed@google.com3b429982012-06-26 15:30:08 +0000197 SK_DECLARE_INST_COUNT(SkMemoryStream)
198
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199 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);
scroggo@google.come4904202013-01-09 22:02:58 +0000206
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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 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);
djsollen@google.com57f49692011-02-23 20:46:31 +0000221 /** 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);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000226
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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000241 virtual bool rewind() SK_OVERRIDE;
242 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
243 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244 const void* getAtPos();
245 size_t seek(size_t offset);
246 size_t peek() const { return fOffset; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000247
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000249 SkData* fData;
250 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000251
252 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253};
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*/
reed@google.coma718c5e2013-03-05 17:49:10 +0000260class SK_API SkBufferStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261public:
reed@google.com3b429982012-06-26 15:30:08 +0000262 SK_DECLARE_INST_COUNT(SkBufferStream)
263
reed@android.com8a1c16f2008-12-17 15:59:43 +0000264 /** 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
tomhudson@google.com13413042011-10-03 16:01:10 +0000281 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285
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);
reed@google.com3b429982012-06-26 15:30:08 +0000300
301 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302};
303
304/////////////////////////////////////////////////////////////////////////////////////////////
305
alokp@chromium.orgf7751ae2012-07-17 19:10:36 +0000306class SK_API SkFILEWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307public:
reed@google.com3b429982012-06-26 15:30:08 +0000308 SK_DECLARE_INST_COUNT(SkFILEWStream)
309
310 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311 virtual ~SkFILEWStream();
312
313 /** Returns true if the current path could be opened.
314 */
315 bool isValid() const { return fFILE != NULL; }
316
tomhudson@google.com13413042011-10-03 16:01:10 +0000317 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
318 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000319
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320private:
321 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000322
323 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000324};
325
326class SkMemoryWStream : public SkWStream {
327public:
reed@google.com3b429982012-06-26 15:30:08 +0000328 SK_DECLARE_INST_COUNT(SkMemoryWStream)
329
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000331 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000332 size_t bytesWritten() const { return fBytesWritten; }
333
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334private:
335 char* fBuffer;
336 size_t fMaxLength;
337 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000338
339 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340};
341
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000342class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343public:
reed@google.com3b429982012-06-26 15:30:08 +0000344 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
345
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 SkDynamicMemoryWStream();
347 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000348
tomhudson@google.com13413042011-10-03 16:01:10 +0000349 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 // 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);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000354 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000355 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000356
357 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000358 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000359
360 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000361 * Return a copy of the data written so far. This call is responsible for
362 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000363 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000364 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000365
reed@android.com8a1c16f2008-12-17 15:59:43 +0000366 // 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;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000374 mutable SkData* fCopy; // is invalidated if we write after it is created
375
376 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000377
378 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000379};
380
381
reed@google.coma718c5e2013-03-05 17:49:10 +0000382class SK_API SkDebugWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000383public:
reed@google.com3b429982012-06-26 15:30:08 +0000384 SK_DECLARE_INST_COUNT(SkDebugWStream)
385
reed@android.com8a1c16f2008-12-17 15:59:43 +0000386 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000387 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
388 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000389
390private:
391 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392};
393
394// for now
395typedef SkFILEStream SkURLStream;
396
397#endif