blob: c9418709a1f222d97a080f3c63578ed112d081b6 [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 /**
76 * Create a new SkData from the stream contents. This balances the call
77 * SkWStream::writeData().
78 */
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
118 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119};
120
121////////////////////////////////////////////////////////////////////////////////////////
122
123#include "SkString.h"
124
125struct SkFILE;
126
127/** A stream that reads from a FILE*, which is opened in the constructor and
128 closed in the destructor
129 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000130class SK_API SkFILEStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131public:
reed@google.com3b429982012-06-26 15:30:08 +0000132 SK_DECLARE_INST_COUNT(SkFILEStream)
133
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 /** Initialize the stream by calling fopen on the specified path. Will be
135 closed in the destructor.
136 */
137 explicit SkFILEStream(const char path[] = NULL);
138 virtual ~SkFILEStream();
139
140 /** Returns true if the current path could be opened.
141 */
142 bool isValid() const { return fFILE != NULL; }
143 /** Close the current file, and open a new file with the specified
144 path. If path is NULL, just close the current file.
145 */
146 void setPath(const char path[]);
147
tomhudson@google.com13413042011-10-03 16:01:10 +0000148 virtual bool rewind() SK_OVERRIDE;
149 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
150 virtual const char* getFileName() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151
152private:
153 SkFILE* fFILE;
154 SkString fName;
reed@google.com3b429982012-06-26 15:30:08 +0000155
156 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157};
158
159/** A stream that reads from a file descriptor
160 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000161class SK_API SkFDStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162public:
reed@google.com3b429982012-06-26 15:30:08 +0000163 SK_DECLARE_INST_COUNT(SkFDStream)
164
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 /** Initialize the stream with a dup() of the specified file descriptor.
166 If closeWhenDone is true, then the descriptor will be closed in the
167 destructor.
168 */
169 SkFDStream(int fileDesc, bool closeWhenDone);
170 virtual ~SkFDStream();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000171
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172 /** Returns true if the current path could be opened.
173 */
174 bool isValid() const { return fFD >= 0; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000175
tomhudson@google.com13413042011-10-03 16:01:10 +0000176 virtual bool rewind() SK_OVERRIDE;
177 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
178 virtual const char* getFileName() SK_OVERRIDE { return NULL; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000179
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180private:
181 int fFD;
182 bool fCloseWhenDone;
reed@google.com3b429982012-06-26 15:30:08 +0000183
184 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185};
186
reed@google.coma718c5e2013-03-05 17:49:10 +0000187class SK_API SkMemoryStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188public:
reed@google.com3b429982012-06-26 15:30:08 +0000189 SK_DECLARE_INST_COUNT(SkMemoryStream)
190
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191 SkMemoryStream();
192 /** We allocate (and free) the memory. Write to it via getMemoryBase()
193 */
194 SkMemoryStream(size_t length);
195 /** if copyData is true, the stream makes a private copy of the data
196 */
197 SkMemoryStream(const void* data, size_t length, bool copyData = false);
scroggo@google.come4904202013-01-09 22:02:58 +0000198
199 /**
200 * Use the specified data as the memory for this stream. The stream will
201 * call ref() on the data (assuming it is not null).
202 */
203 SkMemoryStream(SkData*);
204
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205 virtual ~SkMemoryStream();
206
207 /** Resets the stream to the specified data and length,
208 just like the constructor.
209 if copyData is true, the stream makes a private copy of the data
210 */
211 virtual void setMemory(const void* data, size_t length,
212 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000213 /** Replace any memory buffer with the specified buffer. The caller
214 must have allocated data with sk_malloc or sk_realloc, since it
215 will be freed with sk_free.
216 */
217 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000218
219 /**
220 * Return the stream's data in a SkData. The caller must call unref() when
221 * it is finished using the data.
222 */
223 SkData* copyToData() const;
224
225 /**
226 * Use the specified data as the memory for this stream. The stream will
227 * call ref() on the data (assuming it is not null). The function returns
228 * the data parameter as a convenience.
229 */
230 SkData* setData(SkData*);
231
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000233 virtual bool rewind() SK_OVERRIDE;
234 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
235 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 const void* getAtPos();
237 size_t seek(size_t offset);
238 size_t peek() const { return fOffset; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000239
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000241 SkData* fData;
242 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000243
244 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245};
246
247/** \class SkBufferStream
248 This is a wrapper class that adds buffering to another stream.
249 The caller can provide the buffer, or ask SkBufferStream to allocated/free
250 it automatically.
251*/
reed@google.coma718c5e2013-03-05 17:49:10 +0000252class SK_API SkBufferStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253public:
reed@google.com3b429982012-06-26 15:30:08 +0000254 SK_DECLARE_INST_COUNT(SkBufferStream)
255
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 /** Provide the stream to be buffered (proxy), and the size of the buffer that
257 should be used. This will be allocated and freed automatically. If bufferSize is 0,
258 a default buffer size will be used.
259 The proxy stream is referenced, and will be unreferenced in when the
260 bufferstream is destroyed.
261 */
262 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
263 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
264 This buffer is owned by the caller, and must be at least bufferSize bytes big.
265 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
266 If buffer is not NULL, it is an error for bufferSize to be 0.
267 The proxy stream is referenced, and will be unreferenced in when the
268 bufferstream is destroyed.
269 */
270 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
271 virtual ~SkBufferStream();
272
tomhudson@google.com13413042011-10-03 16:01:10 +0000273 virtual bool rewind() SK_OVERRIDE;
274 virtual const char* getFileName() SK_OVERRIDE;
275 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
276 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000277
278private:
279 enum {
280 kDefaultBufferSize = 128
281 };
282 // illegal
283 SkBufferStream(const SkBufferStream&);
284 SkBufferStream& operator=(const SkBufferStream&);
285
286 SkStream* fProxy;
287 char* fBuffer;
288 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
289 bool fWeOwnTheBuffer;
290
291 void init(void*, size_t);
reed@google.com3b429982012-06-26 15:30:08 +0000292
293 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294};
295
296/////////////////////////////////////////////////////////////////////////////////////////////
297
alokp@chromium.orgf7751ae2012-07-17 19:10:36 +0000298class SK_API SkFILEWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299public:
reed@google.com3b429982012-06-26 15:30:08 +0000300 SK_DECLARE_INST_COUNT(SkFILEWStream)
301
302 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 virtual ~SkFILEWStream();
304
305 /** Returns true if the current path could be opened.
306 */
307 bool isValid() const { return fFILE != NULL; }
308
tomhudson@google.com13413042011-10-03 16:01:10 +0000309 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
310 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000311
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312private:
313 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000314
315 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316};
317
318class SkMemoryWStream : public SkWStream {
319public:
reed@google.com3b429982012-06-26 15:30:08 +0000320 SK_DECLARE_INST_COUNT(SkMemoryWStream)
321
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000323 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000324 size_t bytesWritten() const { return fBytesWritten; }
325
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326private:
327 char* fBuffer;
328 size_t fMaxLength;
329 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000330
331 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332};
333
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000334class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335public:
reed@google.com3b429982012-06-26 15:30:08 +0000336 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
337
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338 SkDynamicMemoryWStream();
339 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000340
tomhudson@google.com13413042011-10-03 16:01:10 +0000341 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000342 // random access write
343 // modifies stream and returns true if offset + size is less than or equal to getOffset()
344 bool write(const void* buffer, size_t offset, size_t size);
345 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000346 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000347 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000348
349 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000350 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000351
352 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000353 * Return a copy of the data written so far. This call is responsible for
354 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000355 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000356 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000357
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 // reset the stream to its original state
359 void reset();
360 void padToAlign4();
361private:
362 struct Block;
363 Block* fHead;
364 Block* fTail;
365 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000366 mutable SkData* fCopy; // is invalidated if we write after it is created
367
368 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000369
370 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371};
372
373
reed@google.coma718c5e2013-03-05 17:49:10 +0000374class SK_API SkDebugWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000375public:
reed@google.com3b429982012-06-26 15:30:08 +0000376 SK_DECLARE_INST_COUNT(SkDebugWStream)
377
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000379 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
380 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000381
382private:
383 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000384};
385
386// for now
387typedef SkFILEStream SkURLStream;
388
389#endif