blob: 08d087815bf04c15210b7058e1374da19e4d334f [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);
191 virtual ~SkMemoryStream();
192
193 /** Resets the stream to the specified data and length,
194 just like the constructor.
195 if copyData is true, the stream makes a private copy of the data
196 */
197 virtual void setMemory(const void* data, size_t length,
198 bool copyData = false);
djsollen@google.com57f49692011-02-23 20:46:31 +0000199 /** Replace any memory buffer with the specified buffer. The caller
200 must have allocated data with sk_malloc or sk_realloc, since it
201 will be freed with sk_free.
202 */
203 void setMemoryOwned(const void* data, size_t length);
reed@google.com8a85d0c2011-06-24 19:12:12 +0000204
205 /**
206 * Return the stream's data in a SkData. The caller must call unref() when
207 * it is finished using the data.
208 */
209 SkData* copyToData() const;
210
211 /**
212 * Use the specified data as the memory for this stream. The stream will
213 * call ref() on the data (assuming it is not null). The function returns
214 * the data parameter as a convenience.
215 */
216 SkData* setData(SkData*);
217
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 void skipToAlign4();
tomhudson@google.com13413042011-10-03 16:01:10 +0000219 virtual bool rewind() SK_OVERRIDE;
220 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
221 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 const void* getAtPos();
223 size_t seek(size_t offset);
224 size_t peek() const { return fOffset; }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000225
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226private:
reed@google.com8a85d0c2011-06-24 19:12:12 +0000227 SkData* fData;
228 size_t fOffset;
reed@google.com3b429982012-06-26 15:30:08 +0000229
230 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231};
232
233/** \class SkBufferStream
234 This is a wrapper class that adds buffering to another stream.
235 The caller can provide the buffer, or ask SkBufferStream to allocated/free
236 it automatically.
237*/
238class SkBufferStream : public SkStream {
239public:
reed@google.com3b429982012-06-26 15:30:08 +0000240 SK_DECLARE_INST_COUNT(SkBufferStream)
241
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 /** Provide the stream to be buffered (proxy), and the size of the buffer that
243 should be used. This will be allocated and freed automatically. If bufferSize is 0,
244 a default buffer size will be used.
245 The proxy stream is referenced, and will be unreferenced in when the
246 bufferstream is destroyed.
247 */
248 SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
249 /** Provide the stream to be buffered (proxy), and a buffer and size to be used.
250 This buffer is owned by the caller, and must be at least bufferSize bytes big.
251 Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
252 If buffer is not NULL, it is an error for bufferSize to be 0.
253 The proxy stream is referenced, and will be unreferenced in when the
254 bufferstream is destroyed.
255 */
256 SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
257 virtual ~SkBufferStream();
258
tomhudson@google.com13413042011-10-03 16:01:10 +0000259 virtual bool rewind() SK_OVERRIDE;
260 virtual const char* getFileName() SK_OVERRIDE;
261 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
262 virtual const void* getMemoryBase() SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263
264private:
265 enum {
266 kDefaultBufferSize = 128
267 };
268 // illegal
269 SkBufferStream(const SkBufferStream&);
270 SkBufferStream& operator=(const SkBufferStream&);
271
272 SkStream* fProxy;
273 char* fBuffer;
274 size_t fOrigBufferSize, fBufferSize, fBufferOffset;
275 bool fWeOwnTheBuffer;
276
277 void init(void*, size_t);
reed@google.com3b429982012-06-26 15:30:08 +0000278
279 typedef SkStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000280};
281
282/////////////////////////////////////////////////////////////////////////////////////////////
283
alokp@chromium.orgf7751ae2012-07-17 19:10:36 +0000284class SK_API SkFILEWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285public:
reed@google.com3b429982012-06-26 15:30:08 +0000286 SK_DECLARE_INST_COUNT(SkFILEWStream)
287
288 SkFILEWStream(const char path[]);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289 virtual ~SkFILEWStream();
290
291 /** Returns true if the current path could be opened.
292 */
293 bool isValid() const { return fFILE != NULL; }
294
tomhudson@google.com13413042011-10-03 16:01:10 +0000295 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
296 virtual void flush() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000297
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298private:
299 SkFILE* fFILE;
reed@google.com3b429982012-06-26 15:30:08 +0000300
301 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302};
303
304class SkMemoryWStream : public SkWStream {
305public:
reed@google.com3b429982012-06-26 15:30:08 +0000306 SK_DECLARE_INST_COUNT(SkMemoryWStream)
307
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 SkMemoryWStream(void* buffer, size_t size);
tomhudson@google.com13413042011-10-03 16:01:10 +0000309 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
junov@chromium.org1cc8f6f2012-02-22 21:00:42 +0000310 size_t bytesWritten() const { return fBytesWritten; }
311
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312private:
313 char* fBuffer;
314 size_t fMaxLength;
315 size_t fBytesWritten;
reed@google.com3b429982012-06-26 15:30:08 +0000316
317 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318};
319
ctguil@chromium.orgdfc5ffe2011-03-30 20:14:49 +0000320class SK_API SkDynamicMemoryWStream : public SkWStream {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321public:
reed@google.com3b429982012-06-26 15:30:08 +0000322 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
323
reed@android.com8a1c16f2008-12-17 15:59:43 +0000324 SkDynamicMemoryWStream();
325 virtual ~SkDynamicMemoryWStream();
reed@google.com8a85d0c2011-06-24 19:12:12 +0000326
tomhudson@google.com13413042011-10-03 16:01:10 +0000327 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 // random access write
329 // modifies stream and returns true if offset + size is less than or equal to getOffset()
330 bool write(const void* buffer, size_t offset, size_t size);
331 bool read(void* buffer, size_t offset, size_t size);
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000332 size_t getOffset() const { return fBytesWritten; }
reed@google.com8a85d0c2011-06-24 19:12:12 +0000333 size_t bytesWritten() const { return fBytesWritten; }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334
335 // copy what has been written to the stream into dst
reed@google.com8a85d0c2011-06-24 19:12:12 +0000336 void copyTo(void* dst) const;
reed@google.com70442a62011-06-23 21:48:04 +0000337
338 /**
reed@google.com8a85d0c2011-06-24 19:12:12 +0000339 * Return a copy of the data written so far. This call is responsible for
340 * calling unref() when they are finished with the data.
reed@google.com70442a62011-06-23 21:48:04 +0000341 */
reed@google.com8d0b5772011-06-24 13:07:31 +0000342 SkData* copyToData() const;
reed@google.com70442a62011-06-23 21:48:04 +0000343
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344 // reset the stream to its original state
345 void reset();
346 void padToAlign4();
347private:
348 struct Block;
349 Block* fHead;
350 Block* fTail;
351 size_t fBytesWritten;
reed@google.com8a85d0c2011-06-24 19:12:12 +0000352 mutable SkData* fCopy; // is invalidated if we write after it is created
353
354 void invalidateCopy();
reed@google.com3b429982012-06-26 15:30:08 +0000355
356 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000357};
358
359
360class SkDebugWStream : public SkWStream {
361public:
reed@google.com3b429982012-06-26 15:30:08 +0000362 SK_DECLARE_INST_COUNT(SkDebugWStream)
363
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 // overrides
tomhudson@google.com13413042011-10-03 16:01:10 +0000365 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
366 virtual void newline() SK_OVERRIDE;
reed@google.com3b429982012-06-26 15:30:08 +0000367
368private:
369 typedef SkWStream INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370};
371
372// for now
373typedef SkFILEStream SkURLStream;
374
375#endif