|
1 /* |
|
2 * Copyright 2006 The Android Open Source Project |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #ifndef SkStream_DEFINED |
|
9 #define SkStream_DEFINED |
|
10 |
|
11 #include "SkRefCnt.h" |
|
12 #include "SkScalar.h" |
|
13 |
|
14 class SkData; |
|
15 |
|
16 class SkStream; |
|
17 class SkStreamRewindable; |
|
18 class SkStreamSeekable; |
|
19 class SkStreamAsset; |
|
20 class SkStreamMemory; |
|
21 |
|
22 /** |
|
23 * SkStream -- abstraction for a source of bytes. Subclasses can be backed by |
|
24 * memory, or a file, or something else. |
|
25 * |
|
26 * NOTE: |
|
27 * |
|
28 * Classic "streams" APIs are sort of async, in that on a request for N |
|
29 * bytes, they may return fewer than N bytes on a given call, in which case |
|
30 * the caller can "try again" to get more bytes, eventually (modulo an error) |
|
31 * receiving their total N bytes. |
|
32 * |
|
33 * Skia streams behave differently. They are effectively synchronous, and will |
|
34 * always return all N bytes of the request if possible. If they return fewer |
|
35 * (the read() call returns the number of bytes read) then that means there is |
|
36 * no more data (at EOF or hit an error). The caller should *not* call again |
|
37 * in hopes of fulfilling more of the request. |
|
38 */ |
|
39 class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt |
|
40 public: |
|
41 /** |
|
42 * Attempts to open the specified file, and return a stream to it (using |
|
43 * mmap if available). On success, the caller must call unref() on the |
|
44 * returned object. On failure, returns NULL. |
|
45 */ |
|
46 static SkStreamAsset* NewFromFile(const char path[]); |
|
47 |
|
48 SK_DECLARE_INST_COUNT(SkStream) |
|
49 |
|
50 /** Reads or skips size number of bytes. |
|
51 * If buffer == NULL, skip size bytes, return how many were skipped. |
|
52 * If buffer != NULL, copy size bytes into buffer, return how many were copied. |
|
53 * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer |
|
54 * @param size the number of bytes to skip or copy |
|
55 * @return the number of bytes actually read. |
|
56 */ |
|
57 virtual size_t read(void* buffer, size_t size) = 0; |
|
58 |
|
59 /** Skip size number of bytes. |
|
60 * @return the actual number bytes that could be skipped. |
|
61 */ |
|
62 size_t skip(size_t size) { |
|
63 return this->read(NULL, size); |
|
64 } |
|
65 |
|
66 /** Returns true when all the bytes in the stream have been read. |
|
67 * This may return true early (when there are no more bytes to be read) |
|
68 * or late (after the first unsuccessful read). |
|
69 */ |
|
70 virtual bool isAtEnd() const = 0; |
|
71 |
|
72 int8_t readS8(); |
|
73 int16_t readS16(); |
|
74 int32_t readS32(); |
|
75 |
|
76 uint8_t readU8() { return (uint8_t)this->readS8(); } |
|
77 uint16_t readU16() { return (uint16_t)this->readS16(); } |
|
78 uint32_t readU32() { return (uint32_t)this->readS32(); } |
|
79 |
|
80 bool readBool() { return this->readU8() != 0; } |
|
81 SkScalar readScalar(); |
|
82 size_t readPackedUInt(); |
|
83 |
|
84 /** |
|
85 * Reconstitute an SkData object that was written to the stream |
|
86 * using SkWStream::writeData(). |
|
87 */ |
|
88 SkData* readData(); |
|
89 |
|
90 //SkStreamRewindable |
|
91 /** Rewinds to the beginning of the stream. Returns true if the stream is known |
|
92 * to be at the beginning after this call returns. |
|
93 */ |
|
94 virtual bool rewind() { return false; } |
|
95 |
|
96 /** Duplicates this stream. If this cannot be done, returns NULL. |
|
97 * The returned stream will be positioned at the beginning of its data. |
|
98 */ |
|
99 virtual SkStreamRewindable* duplicate() const { return NULL; } |
|
100 |
|
101 //SkStreamSeekable |
|
102 /** Returns true if this stream can report it's current position. */ |
|
103 virtual bool hasPosition() const { return false; } |
|
104 /** Returns the current position in the stream. If this cannot be done, returns 0. */ |
|
105 virtual size_t getPosition() const { return 0; } |
|
106 |
|
107 /** Seeks to an absolute position in the stream. If this cannot be done, returns false. |
|
108 * If an attempt is made to seek past the end of the stream, the position will be set |
|
109 * to the end of the stream. |
|
110 */ |
|
111 virtual bool seek(size_t position) { return false; } |
|
112 |
|
113 /** Seeks to an relative offset in the stream. If this cannot be done, returns false. |
|
114 * If an attempt is made to move to a position outside the stream, the position will be set |
|
115 * to the closest point within the stream (beginning or end). |
|
116 */ |
|
117 virtual bool move(long offset) { return false; } |
|
118 |
|
119 /** Duplicates this stream. If this cannot be done, returns NULL. |
|
120 * The returned stream will be positioned the same as this stream. |
|
121 */ |
|
122 virtual SkStreamSeekable* fork() const { return NULL; } |
|
123 |
|
124 //SkStreamAsset |
|
125 /** Returns true if this stream can report it's total length. */ |
|
126 virtual bool hasLength() const { return false; } |
|
127 /** Returns the total length of the stream. If this cannot be done, returns 0. */ |
|
128 virtual size_t getLength() const { return 0; } |
|
129 |
|
130 //SkStreamMemory |
|
131 /** Returns the starting address for the data. If this cannot be done, returns NULL. */ |
|
132 //TODO: replace with virtual const SkData* getData() |
|
133 virtual const void* getMemoryBase() { return NULL; } |
|
134 |
|
135 private: |
|
136 typedef SkRefCnt INHERITED; |
|
137 }; |
|
138 |
|
139 /** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */ |
|
140 class SK_API SkStreamRewindable : public SkStream { |
|
141 public: |
|
142 virtual bool rewind() SK_OVERRIDE = 0; |
|
143 virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0; |
|
144 }; |
|
145 |
|
146 /** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */ |
|
147 class SK_API SkStreamSeekable : public SkStreamRewindable { |
|
148 public: |
|
149 virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0; |
|
150 |
|
151 virtual bool hasPosition() const SK_OVERRIDE { return true; } |
|
152 virtual size_t getPosition() const SK_OVERRIDE = 0; |
|
153 virtual bool seek(size_t position) SK_OVERRIDE = 0; |
|
154 virtual bool move(long offset) SK_OVERRIDE = 0; |
|
155 virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0; |
|
156 }; |
|
157 |
|
158 /** SkStreamAsset is a SkStreamSeekable for which getLength is required. */ |
|
159 class SK_API SkStreamAsset : public SkStreamSeekable { |
|
160 public: |
|
161 virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0; |
|
162 virtual SkStreamAsset* fork() const SK_OVERRIDE = 0; |
|
163 |
|
164 virtual bool hasLength() const SK_OVERRIDE { return true; } |
|
165 virtual size_t getLength() const SK_OVERRIDE = 0; |
|
166 }; |
|
167 |
|
168 /** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */ |
|
169 class SK_API SkStreamMemory : public SkStreamAsset { |
|
170 public: |
|
171 virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0; |
|
172 virtual SkStreamMemory* fork() const SK_OVERRIDE = 0; |
|
173 |
|
174 virtual const void* getMemoryBase() SK_OVERRIDE = 0; |
|
175 }; |
|
176 |
|
177 class SK_API SkWStream : SkNoncopyable { |
|
178 public: |
|
179 SK_DECLARE_INST_COUNT_ROOT(SkWStream) |
|
180 |
|
181 virtual ~SkWStream(); |
|
182 |
|
183 /** Called to write bytes to a SkWStream. Returns true on success |
|
184 @param buffer the address of at least size bytes to be written to the stream |
|
185 @param size The number of bytes in buffer to write to the stream |
|
186 @return true on success |
|
187 */ |
|
188 virtual bool write(const void* buffer, size_t size) = 0; |
|
189 virtual void newline(); |
|
190 virtual void flush(); |
|
191 |
|
192 virtual size_t bytesWritten() const = 0; |
|
193 |
|
194 // helpers |
|
195 |
|
196 bool write8(U8CPU); |
|
197 bool write16(U16CPU); |
|
198 bool write32(uint32_t); |
|
199 |
|
200 bool writeText(const char text[]); |
|
201 bool writeDecAsText(int32_t); |
|
202 bool writeBigDecAsText(int64_t, int minDigits = 0); |
|
203 bool writeHexAsText(uint32_t, int minDigits = 0); |
|
204 bool writeScalarAsText(SkScalar); |
|
205 |
|
206 bool writeBool(bool v) { return this->write8(v); } |
|
207 bool writeScalar(SkScalar); |
|
208 bool writePackedUInt(size_t); |
|
209 |
|
210 bool writeStream(SkStream* input, size_t length); |
|
211 |
|
212 /** |
|
213 * Append an SkData object to the stream, such that it can be read |
|
214 * out of the stream using SkStream::readData(). |
|
215 * |
|
216 * Note that the encoding method used to write the SkData object |
|
217 * to the stream may change over time. This method DOES NOT |
|
218 * just write the raw content of the SkData object to the stream. |
|
219 */ |
|
220 bool writeData(const SkData*); |
|
221 |
|
222 /** |
|
223 * This returns the number of bytes in the stream required to store |
|
224 * 'value'. |
|
225 */ |
|
226 static int SizeOfPackedUInt(size_t value); |
|
227 }; |
|
228 |
|
229 //////////////////////////////////////////////////////////////////////////////////////// |
|
230 |
|
231 #include "SkString.h" |
|
232 #include <stdio.h> |
|
233 |
|
234 struct SkFILE; |
|
235 |
|
236 /** A stream that wraps a C FILE* file stream. */ |
|
237 class SK_API SkFILEStream : public SkStreamAsset { |
|
238 public: |
|
239 SK_DECLARE_INST_COUNT(SkFILEStream) |
|
240 |
|
241 /** Initialize the stream by calling sk_fopen on the specified path. |
|
242 * This internal stream will be closed in the destructor. |
|
243 */ |
|
244 explicit SkFILEStream(const char path[] = NULL); |
|
245 |
|
246 enum Ownership { |
|
247 kCallerPasses_Ownership, |
|
248 kCallerRetains_Ownership |
|
249 }; |
|
250 /** Initialize the stream with an existing C file stream. |
|
251 * While this stream exists, it assumes exclusive access to the C file stream. |
|
252 * The C file stream will be closed in the destructor unless the caller specifies |
|
253 * kCallerRetains_Ownership. |
|
254 */ |
|
255 explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership); |
|
256 |
|
257 virtual ~SkFILEStream(); |
|
258 |
|
259 /** Returns true if the current path could be opened. */ |
|
260 bool isValid() const { return fFILE != NULL; } |
|
261 |
|
262 /** Close the current file, and open a new file with the specified path. |
|
263 * If path is NULL, just close the current file. |
|
264 */ |
|
265 void setPath(const char path[]); |
|
266 |
|
267 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; |
|
268 virtual bool isAtEnd() const SK_OVERRIDE; |
|
269 |
|
270 virtual bool rewind() SK_OVERRIDE; |
|
271 virtual SkStreamAsset* duplicate() const SK_OVERRIDE; |
|
272 |
|
273 virtual size_t getPosition() const SK_OVERRIDE; |
|
274 virtual bool seek(size_t position) SK_OVERRIDE; |
|
275 virtual bool move(long offset) SK_OVERRIDE; |
|
276 virtual SkStreamAsset* fork() const SK_OVERRIDE; |
|
277 |
|
278 virtual size_t getLength() const SK_OVERRIDE; |
|
279 |
|
280 virtual const void* getMemoryBase() SK_OVERRIDE; |
|
281 |
|
282 private: |
|
283 SkFILE* fFILE; |
|
284 SkString fName; |
|
285 Ownership fOwnership; |
|
286 // fData is lazilly initialized when needed. |
|
287 mutable SkAutoTUnref<SkData> fData; |
|
288 |
|
289 typedef SkStreamAsset INHERITED; |
|
290 }; |
|
291 |
|
292 class SK_API SkMemoryStream : public SkStreamMemory { |
|
293 public: |
|
294 SK_DECLARE_INST_COUNT(SkMemoryStream) |
|
295 |
|
296 SkMemoryStream(); |
|
297 |
|
298 /** We allocate (and free) the memory. Write to it via getMemoryBase() */ |
|
299 SkMemoryStream(size_t length); |
|
300 |
|
301 /** If copyData is true, the stream makes a private copy of the data. */ |
|
302 SkMemoryStream(const void* data, size_t length, bool copyData = false); |
|
303 |
|
304 /** Use the specified data as the memory for this stream. |
|
305 * The stream will call ref() on the data (assuming it is not NULL). |
|
306 */ |
|
307 SkMemoryStream(SkData*); |
|
308 |
|
309 virtual ~SkMemoryStream(); |
|
310 |
|
311 /** Resets the stream to the specified data and length, |
|
312 just like the constructor. |
|
313 if copyData is true, the stream makes a private copy of the data |
|
314 */ |
|
315 virtual void setMemory(const void* data, size_t length, |
|
316 bool copyData = false); |
|
317 /** Replace any memory buffer with the specified buffer. The caller |
|
318 must have allocated data with sk_malloc or sk_realloc, since it |
|
319 will be freed with sk_free. |
|
320 */ |
|
321 void setMemoryOwned(const void* data, size_t length); |
|
322 |
|
323 /** Return the stream's data in a SkData. |
|
324 * The caller must call unref() when it is finished using the data. |
|
325 */ |
|
326 SkData* copyToData() const; |
|
327 |
|
328 /** |
|
329 * Use the specified data as the memory for this stream. |
|
330 * The stream will call ref() on the data (assuming it is not NULL). |
|
331 * The function returns the data parameter as a convenience. |
|
332 */ |
|
333 SkData* setData(SkData*); |
|
334 |
|
335 void skipToAlign4(); |
|
336 const void* getAtPos(); |
|
337 size_t peek() const { return fOffset; } |
|
338 |
|
339 virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; |
|
340 virtual bool isAtEnd() const SK_OVERRIDE; |
|
341 |
|
342 virtual bool rewind() SK_OVERRIDE; |
|
343 virtual SkMemoryStream* duplicate() const SK_OVERRIDE; |
|
344 |
|
345 virtual size_t getPosition() const SK_OVERRIDE; |
|
346 virtual bool seek(size_t position) SK_OVERRIDE; |
|
347 virtual bool move(long offset) SK_OVERRIDE; |
|
348 virtual SkMemoryStream* fork() const SK_OVERRIDE; |
|
349 |
|
350 virtual size_t getLength() const SK_OVERRIDE; |
|
351 |
|
352 virtual const void* getMemoryBase() SK_OVERRIDE; |
|
353 |
|
354 private: |
|
355 SkData* fData; |
|
356 size_t fOffset; |
|
357 |
|
358 typedef SkStreamMemory INHERITED; |
|
359 }; |
|
360 |
|
361 ///////////////////////////////////////////////////////////////////////////////////////////// |
|
362 |
|
363 class SK_API SkFILEWStream : public SkWStream { |
|
364 public: |
|
365 SK_DECLARE_INST_COUNT(SkFILEWStream) |
|
366 |
|
367 SkFILEWStream(const char path[]); |
|
368 virtual ~SkFILEWStream(); |
|
369 |
|
370 /** Returns true if the current path could be opened. |
|
371 */ |
|
372 bool isValid() const { return fFILE != NULL; } |
|
373 |
|
374 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; |
|
375 virtual void flush() SK_OVERRIDE; |
|
376 virtual size_t bytesWritten() const SK_OVERRIDE; |
|
377 |
|
378 private: |
|
379 SkFILE* fFILE; |
|
380 |
|
381 typedef SkWStream INHERITED; |
|
382 }; |
|
383 |
|
384 class SkMemoryWStream : public SkWStream { |
|
385 public: |
|
386 SK_DECLARE_INST_COUNT(SkMemoryWStream) |
|
387 |
|
388 SkMemoryWStream(void* buffer, size_t size); |
|
389 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; |
|
390 virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; } |
|
391 |
|
392 private: |
|
393 char* fBuffer; |
|
394 size_t fMaxLength; |
|
395 size_t fBytesWritten; |
|
396 |
|
397 typedef SkWStream INHERITED; |
|
398 }; |
|
399 |
|
400 class SK_API SkDynamicMemoryWStream : public SkWStream { |
|
401 public: |
|
402 SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream) |
|
403 |
|
404 SkDynamicMemoryWStream(); |
|
405 virtual ~SkDynamicMemoryWStream(); |
|
406 |
|
407 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; |
|
408 virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; } |
|
409 // random access write |
|
410 // modifies stream and returns true if offset + size is less than or equal to getOffset() |
|
411 bool write(const void* buffer, size_t offset, size_t size); |
|
412 bool read(void* buffer, size_t offset, size_t size); |
|
413 size_t getOffset() const { return fBytesWritten; } |
|
414 |
|
415 // copy what has been written to the stream into dst |
|
416 void copyTo(void* dst) const; |
|
417 |
|
418 /** |
|
419 * Return a copy of the data written so far. This call is responsible for |
|
420 * calling unref() when they are finished with the data. |
|
421 */ |
|
422 SkData* copyToData() const; |
|
423 |
|
424 /** Reset, returning a reader stream with the current content. */ |
|
425 SkStreamAsset* detachAsStream(); |
|
426 |
|
427 /** Reset the stream to its original, empty, state. */ |
|
428 void reset(); |
|
429 void padToAlign4(); |
|
430 private: |
|
431 struct Block; |
|
432 Block* fHead; |
|
433 Block* fTail; |
|
434 size_t fBytesWritten; |
|
435 mutable SkData* fCopy; // is invalidated if we write after it is created |
|
436 |
|
437 void invalidateCopy(); |
|
438 |
|
439 // For access to the Block type. |
|
440 friend class SkBlockMemoryStream; |
|
441 friend class SkBlockMemoryRefCnt; |
|
442 |
|
443 typedef SkWStream INHERITED; |
|
444 }; |
|
445 |
|
446 |
|
447 class SK_API SkDebugWStream : public SkWStream { |
|
448 public: |
|
449 SkDebugWStream() : fBytesWritten(0) {} |
|
450 SK_DECLARE_INST_COUNT(SkDebugWStream) |
|
451 |
|
452 // overrides |
|
453 virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; |
|
454 virtual void newline() SK_OVERRIDE; |
|
455 virtual size_t bytesWritten() const SK_OVERRIDE { return fBytesWritten; } |
|
456 |
|
457 private: |
|
458 size_t fBytesWritten; |
|
459 typedef SkWStream INHERITED; |
|
460 }; |
|
461 |
|
462 // for now |
|
463 typedef SkFILEStream SkURLStream; |
|
464 |
|
465 #endif |