blob: f968c46e19fa9ba836231f79a36b2d39dcfee2ae [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkStream_DEFINED
9#define SkStream_DEFINED
10
11#include "SkRefCnt.h"
12#include "SkScalar.h"
13
reed@google.com8d0b5772011-06-24 13:07:31 +000014class SkData;
reed@google.com70442a62011-06-23 21:48:04 +000015
reed@google.com3b345052013-05-07 15:59:16 +000016/**
17 * SkStream -- abstraction for a source of bytes. Subclasses can be backed by
18 * memory, or a file, or something else.
19 *
20 * NOTE:
21 *
22 * Classic "streams" APIs are sort of async, in that on a request for N
23 * bytes, they may return fewer than N bytes on a given call, in which case
24 * the caller can "try again" to get more bytes, eventually (modulo an error)
25 * receiving their total N bytes.
26 *
27 * Skia streams behave differently. They are effectively synchronous, and will
28 * always return all N bytes of the request if possible. If they return fewer
29 * (the read() call returns the number of bytes read) then that means there is
30 * no more data (at EOF or hit an error). The caller should *not* call again
31 * in hopes of fulfilling more of the request.
32 */
reed@google.comf3166342011-04-26 20:06:08 +000033class SK_API SkStream : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000034public:
reed@google.come1575aa2013-03-18 21:08:46 +000035 /**
36 * Attempts to open the specified file, and return a stream to it (using
37 * mmap if available). On success, the caller must call unref() on the
38 * returned object. On failure, returns NULL.
39 */
40 static SkStream* NewFromFile(const char path[]);
skia.committer@gmail.com8eaddb02013-03-19 07:15:10 +000041
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000042 SK_DECLARE_INST_COUNT(SkStream)
43
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 /** Called to rewind to the beginning of the stream. If this cannot be
45 done, return false.
46 */
47 virtual bool rewind() = 0;
48 /** If this stream represents a file, this method returns the file's name.
49 If it does not, it returns NULL (the default behavior).
50 */
51 virtual const char* getFileName();
52 /** Called to read or skip size number of bytes.
53 If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
54 If buffer is NULL and size == 0, return the total length of the stream.
55 If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
56 @param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
57 @param size The number of bytes to skip or copy
58 @return bytes read on success
59 */
60 virtual size_t read(void* buffer, size_t size) = 0;
61
62 /** Return the total length of the stream.
63 */
64 size_t getLength() { return this->read(NULL, 0); }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000065
reed@android.com8a1c16f2008-12-17 15:59:43 +000066 /** Skip the specified number of bytes, returning the actual number
67 of bytes that could be skipped.
68 */
69 size_t skip(size_t bytes);
70
71 /** If the stream is backed by RAM, this method returns the starting
72 address for the data. If not (i.e. it is backed by a file or other
73 structure), this method returns NULL.
74 The default implementation returns NULL.
75 */
76 virtual const void* getMemoryBase();
77
78 int8_t readS8();
79 int16_t readS16();
80 int32_t readS32();
81
82 uint8_t readU8() { return (uint8_t)this->readS8(); }
83 uint16_t readU16() { return (uint16_t)this->readS16(); }
84 uint32_t readU32() { return (uint32_t)this->readS32(); }
85
86 bool readBool() { return this->readU8() != 0; }
87 SkScalar readScalar();
88 size_t readPackedUInt();
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000089
reed@google.com2e079422012-07-02 19:35:13 +000090 /**
epoger@google.com8e3fb2d2013-03-20 15:56:03 +000091 * Reconstitute an SkData object that was written to the stream
92 * using SkWStream::writeData().
reed@google.com2e079422012-07-02 19:35:13 +000093 */
94 SkData* readData();
95
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000096private:
97 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000098};
99
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000100class SK_API SkWStream : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101public:
reed@google.com3b429982012-06-26 15:30:08 +0000102 SK_DECLARE_INST_COUNT_ROOT(SkWStream)
103
reed@android.com8a1c16f2008-12-17 15:59:43 +0000104 virtual ~SkWStream();
105
106 /** Called to write bytes to a SkWStream. Returns true on success
107 @param buffer the address of at least size bytes to be written to the stream
108 @param size The number of bytes in buffer to write to the stream
109 @return true on success
110 */
111 virtual bool write(const void* buffer, size_t size) = 0;
112 virtual void newline();
113 virtual void flush();
114
115 // helpers
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000116
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117 bool write8(U8CPU);
118 bool write16(U16CPU);
119 bool write32(uint32_t);
120
121 bool writeText(const char text[]);
122 bool writeDecAsText(int32_t);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000123 bool writeBigDecAsText(int64_t, int minDigits = 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 bool writeHexAsText(uint32_t, int minDigits = 0);
125 bool writeScalarAsText(SkScalar);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 bool writeBool(bool v) { return this->write8(v); }
128 bool writeScalar(SkScalar);
129 bool writePackedUInt(size_t);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000130
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 bool writeStream(SkStream* input, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000132
epoger@google.com8e3fb2d2013-03-20 15:56:03 +0000133 /**
134 * Append an SkData object to the stream, such that it can be read
135 * out of the stream using SkStream::readData().
136 *
137 * Note that the encoding method used to write the SkData object
138 * to the stream may change over time. This method DOES NOT
139 * just write the raw content of the SkData object to the stream.
140 */
reed@google.com8a85d0c2011-06-24 19:12:12 +0000141 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142};
143
144////////////////////////////////////////////////////////////////////////////////////////
145
146#include "SkString.h"
147
148struct SkFILE;
149
150/** A stream that reads from a FILE*, which is opened in the constructor and
151 closed in the destructor
152 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000153class SK_API SkFILEStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154public:
reed@google.com3b429982012-06-26 15:30:08 +0000155 SK_DECLARE_INST_COUNT(SkFILEStream)
156
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 /** Initialize the stream by calling fopen on the specified path. Will be
158 closed in the destructor.
159 */
160 explicit SkFILEStream(const char path[] = NULL);
161 virtual ~SkFILEStream();
162
163 /** Returns true if the current path could be opened.
164 */
165 bool isValid() const { return fFILE != NULL; }
166 /** Close the current file, and open a new file with the specified
167 path. If path is NULL, just close the current file.
168 */
169 void setPath(const char path[]);
170
tomhudson@google.com13413042011-10-03 16:01:10 +0000171 virtual bool rewind() SK_OVERRIDE;
172 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
173 virtual const char* getFileName() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174
175private:
176 SkFILE* fFILE;
177 SkString fName;
reed@google.com3b429982012-06-26 15:30:08 +0000178
179 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180};
181
182/** A stream that reads from a file descriptor
183 */
reed@google.coma718c5e2013-03-05 17:49:10 +0000184class SK_API SkFDStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185public:
reed@google.com3b429982012-06-26 15:30:08 +0000186 SK_DECLARE_INST_COUNT(SkFDStream)
187
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188 /** Initialize the stream with a dup() of the specified file descriptor.
189 If closeWhenDone is true, then the descriptor will be closed in the
190 destructor.
191 */
192 SkFDStream(int fileDesc, bool closeWhenDone);
193 virtual ~SkFDStream();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000194
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195 /** Returns true if the current path could be opened.
196 */
197 bool isValid() const { return fFD >= 0; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000198
tomhudson@google.com13413042011-10-03 16:01:10 +0000199 virtual bool rewind() SK_OVERRIDE;
200 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
201 virtual const char* getFileName() SK_OVERRIDE { return NULL; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000202
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203private:
204 int fFD;
205 bool fCloseWhenDone;
reed@google.com3b429982012-06-26 15:30:08 +0000206
207 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208};
209
reed@google.coma718c5e2013-03-05 17:49:10 +0000210class SK_API SkMemoryStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211public:
reed@google.com3b429982012-06-26 15:30:08 +0000212 SK_DECLARE_INST_COUNT(SkMemoryStream)
213
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 SkMemoryStream();
215 /** We allocate (and free) the memory. Write to it via getMemoryBase()
216 */
217 SkMemoryStream(size_t length);
218 /** if copyData is true, the stream makes a private copy of the data
219 */
220 SkMemoryStream(const void* data, size_t length, bool copyData = false);
scroggo@google.come4904202013-01-09 22:02:58 +0000221
222 /**
223 * Use the specified data as the memory for this stream. The stream will
224 * call ref() on the data (assuming it is not null).
225 */
226 SkMemoryStream(SkData*);
227
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228 virtual ~SkMemoryStream();
229
230 /** Resets the stream to the specified data and length,
231 just like the constructor.
232 if copyData is true, the stream makes a private copy of the data
233 */
234 virtual void setMemory(const void* data, size_t length,
235 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000236 /** Replace any memory buffer with the specified buffer. The caller
237 must have allocated data with sk_malloc or sk_realloc, since it
238 will be freed with sk_free.
239 */
240 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000241
242 /**
243 * Return the stream's data in a SkData. The caller must call unref() when
244 * it is finished using the data.
245 */
246 SkData* copyToData() const;
247
248 /**
249 * Use the specified data as the memory for this stream. The stream will
250 * call ref() on the data (assuming it is not null). The function returns
251 * the data parameter as a convenience.
252 */
253 SkData* setData(SkData*);
254
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000256 virtual bool rewind() SK_OVERRIDE;
257 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
258 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259 const void* getAtPos();
260 size_t seek(size_t offset);
261 size_t peek() const { return fOffset; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000262
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000264 SkData* fData;
265 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000266
267 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268};
269
270/** \class SkBufferStream
271 This is a wrapper class that adds buffering to another stream.
272 The caller can provide the buffer, or ask SkBufferStream to allocated/free
273 it automatically.
274*/
reed@google.coma718c5e2013-03-05 17:49:10 +0000275class SK_API SkBufferStream : public SkStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000276public:
reed@google.com3b429982012-06-26 15:30:08 +0000277 SK_DECLARE_INST_COUNT(SkBufferStream)
278
reed@android.com8a1c16f2008-12-17 15:59:43 +0000279 /** Provide the stream to be buffered (proxy), and the size of the buffer that
280 should be used. This will be allocated and freed automatically. If bufferSize is 0,
281 a default buffer size will be used.
282 The proxy stream is referenced, and will be unreferenced in when the
283 bufferstream is destroyed.
284 */
285 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
286 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
287 This buffer is owned by the caller, and must be at least bufferSize bytes big.
288 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
289 If buffer is not NULL, it is an error for bufferSize to be 0.
290 The proxy stream is referenced, and will be unreferenced in when the
291 bufferstream is destroyed.
292 */
293 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
294 virtual ~SkBufferStream();
295
tomhudson@google.com13413042011-10-03 16:01:10 +0000296 virtual bool rewind() SK_OVERRIDE;
297 virtual const char* getFileName() SK_OVERRIDE;
298 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
299 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000300
301private:
302 enum {
303 kDefaultBufferSize = 128
304 };
305 // illegal
306 SkBufferStream(const SkBufferStream&);
307 SkBufferStream& operator=(const SkBufferStream&);
308
309 SkStream* fProxy;
310 char* fBuffer;
311 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
312 bool fWeOwnTheBuffer;
313
314 void init(void*, size_t);
reed@google.com3b429982012-06-26 15:30:08 +0000315
316 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317};
318
319/////////////////////////////////////////////////////////////////////////////////////////////
320
alokp@chromium.orgf7751ae2012-07-17 19:10:36 +0000321class SK_API SkFILEWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322public:
reed@google.com3b429982012-06-26 15:30:08 +0000323 SK_DECLARE_INST_COUNT(SkFILEWStream)
324
325 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 virtual ~SkFILEWStream();
327
328 /** Returns true if the current path could be opened.
329 */
330 bool isValid() const { return fFILE != NULL; }
331
tomhudson@google.com13413042011-10-03 16:01:10 +0000332 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
333 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000334
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335private:
336 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000337
338 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000339};
340
341class SkMemoryWStream : public SkWStream {
342public:
reed@google.com3b429982012-06-26 15:30:08 +0000343 SK_DECLARE_INST_COUNT(SkMemoryWStream)
344
reed@android.com8a1c16f2008-12-17 15:59:43 +0000345 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000346 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000347 size_t bytesWritten() const { return fBytesWritten; }
348
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349private:
350 char* fBuffer;
351 size_t fMaxLength;
352 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000353
354 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000355};
356
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000357class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358public:
reed@google.com3b429982012-06-26 15:30:08 +0000359 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
360
reed@android.com8a1c16f2008-12-17 15:59:43 +0000361 SkDynamicMemoryWStream();
362 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000363
tomhudson@google.com13413042011-10-03 16:01:10 +0000364 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000365 // random access write
366 // modifies stream and returns true if offset + size is less than or equal to getOffset()
367 bool write(const void* buffer, size_t offset, size_t size);
368 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000369 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000370 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371
372 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000373 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000374
375 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000376 * Return a copy of the data written so far. This call is responsible for
377 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000378 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000379 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000380
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 // reset the stream to its original state
382 void reset();
383 void padToAlign4();
384private:
385 struct Block;
386 Block* fHead;
387 Block* fTail;
388 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000389 mutable SkData* fCopy; // is invalidated if we write after it is created
390
391 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000392
393 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394};
395
396
reed@google.coma718c5e2013-03-05 17:49:10 +0000397class SK_API SkDebugWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398public:
reed@google.com3b429982012-06-26 15:30:08 +0000399 SK_DECLARE_INST_COUNT(SkDebugWStream)
400
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000402 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
403 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000404
405private:
406 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407};
408
409// for now
410typedef SkFILEStream SkURLStream;
411
412#endif