blob: 7ec3117f5041752d40bd66a4fa33afb010e4d008 [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); }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000043
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 /** 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
reed@google.com2e079422012-07-02 19:35:13 +000068 /**
69 * Create a new SkData from the stream contents. This balances the call
70 * SkWStream::writeData().
71 */
72 SkData* readData();
73
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000074private:
75 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000076};
77
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +000078class SK_API SkWStream : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000079public:
reed@google.com3b429982012-06-26 15:30:08 +000080 SK_DECLARE_INST_COUNT_ROOT(SkWStream)
81
reed@android.com8a1c16f2008-12-17 15:59:43 +000082 virtual ~SkWStream();
83
84 /** Called to write bytes to a SkWStream. Returns true on success
85 @param buffer the address of at least size bytes to be written to the stream
86 @param size The number of bytes in buffer to write to the stream
87 @return true on success
88 */
89 virtual bool write(const void* buffer, size_t size) = 0;
90 virtual void newline();
91 virtual void flush();
92
93 // helpers
rmistry@google.comfbfcd562012-08-23 18:09:54 +000094
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 bool write8(U8CPU);
96 bool write16(U16CPU);
97 bool write32(uint32_t);
98
99 bool writeText(const char text[]);
100 bool writeDecAsText(int32_t);
vandebo@chromium.orgd877fdb2010-10-12 23:08:13 +0000101 bool writeBigDecAsText(int64_t, int minDigits = 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 bool writeHexAsText(uint32_t, int minDigits = 0);
103 bool writeScalarAsText(SkScalar);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000104
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 bool writeBool(bool v) { return this->write8(v); }
106 bool writeScalar(SkScalar);
107 bool writePackedUInt(size_t);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000108
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 bool writeStream(SkStream* input, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000110
111 bool writeData(const SkData*);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112};
113
114////////////////////////////////////////////////////////////////////////////////////////
115
116#include "SkString.h"
117
118struct SkFILE;
119
120/** A stream that reads from a FILE*, which is opened in the constructor and
121 closed in the destructor
122 */
123class SkFILEStream : public SkStream {
124public:
reed@google.com3b429982012-06-26 15:30:08 +0000125 SK_DECLARE_INST_COUNT(SkFILEStream)
126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 /** Initialize the stream by calling fopen on the specified path. Will be
128 closed in the destructor.
129 */
130 explicit SkFILEStream(const char path[] = NULL);
131 virtual ~SkFILEStream();
132
133 /** Returns true if the current path could be opened.
134 */
135 bool isValid() const { return fFILE != NULL; }
136 /** Close the current file, and open a new file with the specified
137 path. If path is NULL, just close the current file.
138 */
139 void setPath(const char path[]);
140
tomhudson@google.com13413042011-10-03 16:01:10 +0000141 virtual bool rewind() SK_OVERRIDE;
142 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
143 virtual const char* getFileName() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144
145private:
146 SkFILE* fFILE;
147 SkString fName;
reed@google.com3b429982012-06-26 15:30:08 +0000148
149 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150};
151
152/** A stream that reads from a file descriptor
153 */
154class SkFDStream : public SkStream {
155public:
reed@google.com3b429982012-06-26 15:30:08 +0000156 SK_DECLARE_INST_COUNT(SkFDStream)
157
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 /** Initialize the stream with a dup() of the specified file descriptor.
159 If closeWhenDone is true, then the descriptor will be closed in the
160 destructor.
161 */
162 SkFDStream(int fileDesc, bool closeWhenDone);
163 virtual ~SkFDStream();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000164
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 /** Returns true if the current path could be opened.
166 */
167 bool isValid() const { return fFD >= 0; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000168
tomhudson@google.com13413042011-10-03 16:01:10 +0000169 virtual bool rewind() SK_OVERRIDE;
170 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
171 virtual const char* getFileName() SK_OVERRIDE { return NULL; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000172
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173private:
174 int fFD;
175 bool fCloseWhenDone;
reed@google.com3b429982012-06-26 15:30:08 +0000176
177 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178};
179
180class SkMemoryStream : public SkStream {
181public:
reed@google.com3b429982012-06-26 15:30:08 +0000182 SK_DECLARE_INST_COUNT(SkMemoryStream)
183
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 SkMemoryStream();
185 /** We allocate (and free) the memory. Write to it via getMemoryBase()
186 */
187 SkMemoryStream(size_t length);
188 /** if copyData is true, the stream makes a private copy of the data
189 */
190 SkMemoryStream(const void* data, size_t length, bool copyData = false);
scroggo@google.come4904202013-01-09 22:02:58 +0000191
192 /**
193 * Use the specified data as the memory for this stream. The stream will
194 * call ref() on the data (assuming it is not null).
195 */
196 SkMemoryStream(SkData*);
197
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198 virtual ~SkMemoryStream();
199
200 /** Resets the stream to the specified data and length,
201 just like the constructor.
202 if copyData is true, the stream makes a private copy of the data
203 */
204 virtual void setMemory(const void* data, size_t length,
205 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000206 /** Replace any memory buffer with the specified buffer. The caller
207 must have allocated data with sk_malloc or sk_realloc, since it
208 will be freed with sk_free.
209 */
210 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000211
212 /**
213 * Return the stream's data in a SkData. The caller must call unref() when
214 * it is finished using the data.
215 */
216 SkData* copyToData() const;
217
218 /**
219 * Use the specified data as the memory for this stream. The stream will
220 * call ref() on the data (assuming it is not null). The function returns
221 * the data parameter as a convenience.
222 */
223 SkData* setData(SkData*);
224
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000226 virtual bool rewind() SK_OVERRIDE;
227 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
228 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229 const void* getAtPos();
230 size_t seek(size_t offset);
231 size_t peek() const { return fOffset; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000232
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000234 SkData* fData;
235 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000236
237 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238};
239
240/** \class SkBufferStream
241 This is a wrapper class that adds buffering to another stream.
242 The caller can provide the buffer, or ask SkBufferStream to allocated/free
243 it automatically.
244*/
245class SkBufferStream : public SkStream {
246public:
reed@google.com3b429982012-06-26 15:30:08 +0000247 SK_DECLARE_INST_COUNT(SkBufferStream)
248
reed@android.com8a1c16f2008-12-17 15:59:43 +0000249 /** Provide the stream to be buffered (proxy), and the size of the buffer that
250 should be used. This will be allocated and freed automatically. If bufferSize is 0,
251 a default buffer size will be used.
252 The proxy stream is referenced, and will be unreferenced in when the
253 bufferstream is destroyed.
254 */
255 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
256 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
257 This buffer is owned by the caller, and must be at least bufferSize bytes big.
258 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
259 If buffer is not NULL, it is an error for bufferSize to be 0.
260 The proxy stream is referenced, and will be unreferenced in when the
261 bufferstream is destroyed.
262 */
263 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
264 virtual ~SkBufferStream();
265
tomhudson@google.com13413042011-10-03 16:01:10 +0000266 virtual bool rewind() SK_OVERRIDE;
267 virtual const char* getFileName() SK_OVERRIDE;
268 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
269 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270
271private:
272 enum {
273 kDefaultBufferSize = 128
274 };
275 // illegal
276 SkBufferStream(const SkBufferStream&);
277 SkBufferStream& operator=(const SkBufferStream&);
278
279 SkStream* fProxy;
280 char* fBuffer;
281 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
282 bool fWeOwnTheBuffer;
283
284 void init(void*, size_t);
reed@google.com3b429982012-06-26 15:30:08 +0000285
286 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287};
288
289/////////////////////////////////////////////////////////////////////////////////////////////
290
alokp@chromium.orgf7751ae2012-07-17 19:10:36 +0000291class SK_API SkFILEWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292public:
reed@google.com3b429982012-06-26 15:30:08 +0000293 SK_DECLARE_INST_COUNT(SkFILEWStream)
294
295 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 virtual ~SkFILEWStream();
297
298 /** Returns true if the current path could be opened.
299 */
300 bool isValid() const { return fFILE != NULL; }
301
tomhudson@google.com13413042011-10-03 16:01:10 +0000302 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
303 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000304
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305private:
306 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000307
308 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309};
310
311class SkMemoryWStream : public SkWStream {
312public:
reed@google.com3b429982012-06-26 15:30:08 +0000313 SK_DECLARE_INST_COUNT(SkMemoryWStream)
314
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000316 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000317 size_t bytesWritten() const { return fBytesWritten; }
318
reed@android.com8a1c16f2008-12-17 15:59:43 +0000319private:
320 char* fBuffer;
321 size_t fMaxLength;
322 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000323
324 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325};
326
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000327class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328public:
reed@google.com3b429982012-06-26 15:30:08 +0000329 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
330
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 SkDynamicMemoryWStream();
332 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000333
tomhudson@google.com13413042011-10-03 16:01:10 +0000334 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335 // random access write
336 // modifies stream and returns true if offset + size is less than or equal to getOffset()
337 bool write(const void* buffer, size_t offset, size_t size);
338 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000339 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000340 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341
342 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000343 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000344
345 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000346 * Return a copy of the data written so far. This call is responsible for
347 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000348 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000349 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000350
reed@android.com8a1c16f2008-12-17 15:59:43 +0000351 // reset the stream to its original state
352 void reset();
353 void padToAlign4();
354private:
355 struct Block;
356 Block* fHead;
357 Block* fTail;
358 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000359 mutable SkData* fCopy; // is invalidated if we write after it is created
360
361 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000362
363 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364};
365
366
367class SkDebugWStream : public SkWStream {
368public:
reed@google.com3b429982012-06-26 15:30:08 +0000369 SK_DECLARE_INST_COUNT(SkDebugWStream)
370
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000372 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
373 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000374
375private:
376 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000377};
378
379// for now
380typedef SkFILEStream SkURLStream;
381
382#endif