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 "include/core/SkData.h"
12#include "include/core/SkRefCnt.h"
13#include "include/core/SkScalar.h"
14#include "include/private/SkTo.h"
15
16#include <memory.h>
17
18class SkStream;
19class SkStreamRewindable;
20class SkStreamSeekable;
21class SkStreamAsset;
22class SkStreamMemory;
23
24/**
25 * SkStream -- abstraction for a source of bytes. Subclasses can be backed by
26 * memory, or a file, or something else.
27 *
28 * NOTE:
29 *
30 * Classic "streams" APIs are sort of async, in that on a request for N
31 * bytes, they may return fewer than N bytes on a given call, in which case
32 * the caller can "try again" to get more bytes, eventually (modulo an error)
33 * receiving their total N bytes.
34 *
35 * Skia streams behave differently. They are effectively synchronous, and will
36 * always return all N bytes of the request if possible. If they return fewer
37 * (the read() call returns the number of bytes read) then that means there is
38 * no more data (at EOF or hit an error). The caller should *not* call again
39 * in hopes of fulfilling more of the request.
40 */
41class SK_API SkStream {
42public:
43 virtual ~SkStream() {}
44 SkStream() {}
45
46 /**
47 * Attempts to open the specified file as a stream, returns nullptr on failure.
48 */
49 static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
50
51 /** Reads or skips size number of bytes.
52 * If buffer == NULL, skip size bytes, return how many were skipped.
53 * If buffer != NULL, copy size bytes into buffer, return how many were copied.
54 * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
55 * @param size the number of bytes to skip or copy
56 * @return the number of bytes actually read.
57 */
58 virtual size_t read(void* buffer, size_t size) = 0;
59
60 /** Skip size number of bytes.
61 * @return the actual number bytes that could be skipped.
62 */
63 size_t skip(size_t size) {
64 return this->read(nullptr, size);
65 }
66
67 /**
68 * Attempt to peek at size bytes.
69 * If this stream supports peeking, copy min(size, peekable bytes) into
70 * buffer, and return the number of bytes copied.
71 * If the stream does not support peeking, or cannot peek any bytes,
72 * return 0 and leave buffer unchanged.
73 * The stream is guaranteed to be in the same visible state after this
74 * call, regardless of success or failure.
75 * @param buffer Must not be NULL, and must be at least size bytes. Destination
76 * to copy bytes.
77 * @param size Number of bytes to copy.
78 * @return The number of bytes peeked/copied.
79 */
80 virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
81
82 /** Returns true when all the bytes in the stream have been read.
83 * This may return true early (when there are no more bytes to be read)
84 * or late (after the first unsuccessful read).
85 */
86 virtual bool isAtEnd() const = 0;
87
88 bool SK_WARN_UNUSED_RESULT readS8(int8_t*);
89 bool SK_WARN_UNUSED_RESULT readS16(int16_t*);
90 bool SK_WARN_UNUSED_RESULT readS32(int32_t*);
91
92 bool SK_WARN_UNUSED_RESULT readU8(uint8_t* i) { return this->readS8((int8_t*)i); }
93 bool SK_WARN_UNUSED_RESULT readU16(uint16_t* i) { return this->readS16((int16_t*)i); }
94 bool SK_WARN_UNUSED_RESULT readU32(uint32_t* i) { return this->readS32((int32_t*)i); }
95
96 bool SK_WARN_UNUSED_RESULT readBool(bool* b) {
97 uint8_t i;
98 if (!this->readU8(&i)) { return false; }
99 *b = (i != 0);
100 return true;
101 }
102 bool SK_WARN_UNUSED_RESULT readScalar(SkScalar*);
103 bool SK_WARN_UNUSED_RESULT readPackedUInt(size_t*);
104
105//SkStreamRewindable
106 /** Rewinds to the beginning of the stream. Returns true if the stream is known
107 * to be at the beginning after this call returns.
108 */
109 virtual bool rewind() { return false; }
110
111 /** Duplicates this stream. If this cannot be done, returns NULL.
112 * The returned stream will be positioned at the beginning of its data.
113 */
114 std::unique_ptr<SkStream> duplicate() const {
115 return std::unique_ptr<SkStream>(this->onDuplicate());
116 }
117 /** Duplicates this stream. If this cannot be done, returns NULL.
118 * The returned stream will be positioned the same as this stream.
119 */
120 std::unique_ptr<SkStream> fork() const {
121 return std::unique_ptr<SkStream>(this->onFork());
122 }
123
124//SkStreamSeekable
125 /** Returns true if this stream can report it's current position. */
126 virtual bool hasPosition() const { return false; }
127 /** Returns the current position in the stream. If this cannot be done, returns 0. */
128 virtual size_t getPosition() const { return 0; }
129
130 /** Seeks to an absolute position in the stream. If this cannot be done, returns false.
131 * If an attempt is made to seek past the end of the stream, the position will be set
132 * to the end of the stream.
133 */
134 virtual bool seek(size_t /*position*/) { return false; }
135
136 /** Seeks to an relative offset in the stream. If this cannot be done, returns false.
137 * If an attempt is made to move to a position outside the stream, the position will be set
138 * to the closest point within the stream (beginning or end).
139 */
140 virtual bool move(long /*offset*/) { return false; }
141
142//SkStreamAsset
143 /** Returns true if this stream can report it's total length. */
144 virtual bool hasLength() const { return false; }
145 /** Returns the total length of the stream. If this cannot be done, returns 0. */
146 virtual size_t getLength() const { return 0; }
147
148//SkStreamMemory
149 /** Returns the starting address for the data. If this cannot be done, returns NULL. */
150 //TODO: replace with virtual const SkData* getData()
151 virtual const void* getMemoryBase() { return nullptr; }
152
153private:
154 virtual SkStream* onDuplicate() const { return nullptr; }
155 virtual SkStream* onFork() const { return nullptr; }
156
157 SkStream(SkStream&&) = delete;
158 SkStream(const SkStream&) = delete;
159 SkStream& operator=(SkStream&&) = delete;
160 SkStream& operator=(const SkStream&) = delete;
161};
162
163/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
164class SK_API SkStreamRewindable : public SkStream {
165public:
166 bool rewind() override = 0;
167 std::unique_ptr<SkStreamRewindable> duplicate() const {
168 return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
169 }
170private:
171 SkStreamRewindable* onDuplicate() const override = 0;
172};
173
174/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
175class SK_API SkStreamSeekable : public SkStreamRewindable {
176public:
177 std::unique_ptr<SkStreamSeekable> duplicate() const {
178 return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
179 }
180
181 bool hasPosition() const override { return true; }
182 size_t getPosition() const override = 0;
183 bool seek(size_t position) override = 0;
184 bool move(long offset) override = 0;
185
186 std::unique_ptr<SkStreamSeekable> fork() const {
187 return std::unique_ptr<SkStreamSeekable>(this->onFork());
188 }
189private:
190 SkStreamSeekable* onDuplicate() const override = 0;
191 SkStreamSeekable* onFork() const override = 0;
192};
193
194/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
195class SK_API SkStreamAsset : public SkStreamSeekable {
196public:
197 bool hasLength() const override { return true; }
198 size_t getLength() const override = 0;
199
200 std::unique_ptr<SkStreamAsset> duplicate() const {
201 return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
202 }
203 std::unique_ptr<SkStreamAsset> fork() const {
204 return std::unique_ptr<SkStreamAsset>(this->onFork());
205 }
206private:
207 SkStreamAsset* onDuplicate() const override = 0;
208 SkStreamAsset* onFork() const override = 0;
209};
210
211/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
212class SK_API SkStreamMemory : public SkStreamAsset {
213public:
214 const void* getMemoryBase() override = 0;
215
216 std::unique_ptr<SkStreamMemory> duplicate() const {
217 return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
218 }
219 std::unique_ptr<SkStreamMemory> fork() const {
220 return std::unique_ptr<SkStreamMemory>(this->onFork());
221 }
222private:
223 SkStreamMemory* onDuplicate() const override = 0;
224 SkStreamMemory* onFork() const override = 0;
225};
226
227class SK_API SkWStream {
228public:
229 virtual ~SkWStream();
230 SkWStream() {}
231
232 /** Called to write bytes to a SkWStream. Returns true on success
233 @param buffer the address of at least size bytes to be written to the stream
234 @param size The number of bytes in buffer to write to the stream
235 @return true on success
236 */
237 virtual bool write(const void* buffer, size_t size) = 0;
238 virtual void flush();
239
240 virtual size_t bytesWritten() const = 0;
241
242 // helpers
243
244 bool write8(U8CPU value) {
245 uint8_t v = SkToU8(value);
246 return this->write(&v, 1);
247 }
248 bool write16(U16CPU value) {
249 uint16_t v = SkToU16(value);
250 return this->write(&v, 2);
251 }
252 bool write32(uint32_t v) {
253 return this->write(&v, 4);
254 }
255
256 bool writeText(const char text[]) {
257 SkASSERT(text);
258 return this->write(text, strlen(text));
259 }
260
261 bool newline() { return this->write("\n", strlen("\n")); }
262
263 bool writeDecAsText(int32_t);
264 bool writeBigDecAsText(int64_t, int minDigits = 0);
265 bool writeHexAsText(uint32_t, int minDigits = 0);
266 bool writeScalarAsText(SkScalar);
267
268 bool writeBool(bool v) { return this->write8(v); }
269 bool writeScalar(SkScalar);
270 bool writePackedUInt(size_t);
271
272 bool writeStream(SkStream* input, size_t length);
273
274 /**
275 * This returns the number of bytes in the stream required to store
276 * 'value'.
277 */
278 static int SizeOfPackedUInt(size_t value);
279
280private:
281 SkWStream(const SkWStream&) = delete;
282 SkWStream& operator=(const SkWStream&) = delete;
283};
284
285class SK_API SkNullWStream : public SkWStream {
286public:
287 SkNullWStream() : fBytesWritten(0) {}
288
289 bool write(const void* , size_t n) override { fBytesWritten += n; return true; }
290 void flush() override {}
291 size_t bytesWritten() const override { return fBytesWritten; }
292
293private:
294 size_t fBytesWritten;
295};
296
297////////////////////////////////////////////////////////////////////////////////////////
298
299#include <stdio.h>
300
301/** A stream that wraps a C FILE* file stream. */
302class SK_API SkFILEStream : public SkStreamAsset {
303public:
304 /** Initialize the stream by calling sk_fopen on the specified path.
305 * This internal stream will be closed in the destructor.
306 */
307 explicit SkFILEStream(const char path[] = nullptr);
308
309 /** Initialize the stream with an existing C FILE stream.
310 * The current position of the C FILE stream will be considered the
311 * beginning of the SkFILEStream.
312 * The C FILE stream will be closed in the destructor.
313 */
314 explicit SkFILEStream(FILE* file);
315
316 ~SkFILEStream() override;
317
318 static std::unique_ptr<SkFILEStream> Make(const char path[]) {
319 std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
320 return stream->isValid() ? std::move(stream) : nullptr;
321 }
322
323 /** Returns true if the current path could be opened. */
324 bool isValid() const { return fFILE != nullptr; }
325
326 /** Close this SkFILEStream. */
327 void close();
328
329 size_t read(void* buffer, size_t size) override;
330 bool isAtEnd() const override;
331
332 bool rewind() override;
333 std::unique_ptr<SkStreamAsset> duplicate() const {
334 return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
335 }
336
337 size_t getPosition() const override;
338 bool seek(size_t position) override;
339 bool move(long offset) override;
340
341 std::unique_ptr<SkStreamAsset> fork() const {
342 return std::unique_ptr<SkStreamAsset>(this->onFork());
343 }
344
345 size_t getLength() const override;
346
347private:
348 explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset);
349 explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset, size_t originalOffset);
350
351 SkStreamAsset* onDuplicate() const override;
352 SkStreamAsset* onFork() const override;
353
354 std::shared_ptr<FILE> fFILE;
355 // My own council will I keep on sizes and offsets.
356 size_t fSize;
357 size_t fOffset;
358 size_t fOriginalOffset;
359
360 typedef SkStreamAsset INHERITED;
361};
362
363class SK_API SkMemoryStream : public SkStreamMemory {
364public:
365 SkMemoryStream();
366
367 /** We allocate (and free) the memory. Write to it via getMemoryBase() */
368 SkMemoryStream(size_t length);
369
370 /** If copyData is true, the stream makes a private copy of the data. */
371 SkMemoryStream(const void* data, size_t length, bool copyData = false);
372
373 /** Creates the stream to read from the specified data */
374 SkMemoryStream(sk_sp<SkData> data);
375
376 /** Returns a stream with a copy of the input data. */
377 static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);
378
379 /** Returns a stream with a bare pointer reference to the input data. */
380 static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);
381
382 /** Returns a stream with a shared reference to the input data. */
383 static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);
384
385 /** Resets the stream to the specified data and length,
386 just like the constructor.
387 if copyData is true, the stream makes a private copy of the data
388 */
389 virtual void setMemory(const void* data, size_t length,
390 bool copyData = false);
391 /** Replace any memory buffer with the specified buffer. The caller
392 must have allocated data with sk_malloc or sk_realloc, since it
393 will be freed with sk_free.
394 */
395 void setMemoryOwned(const void* data, size_t length);
396
397 sk_sp<SkData> asData() const { return fData; }
398 void setData(sk_sp<SkData> data);
399
400 void skipToAlign4();
401 const void* getAtPos();
402
403 size_t read(void* buffer, size_t size) override;
404 bool isAtEnd() const override;
405
406 size_t peek(void* buffer, size_t size) const override;
407
408 bool rewind() override;
409
410 std::unique_ptr<SkMemoryStream> duplicate() const {
411 return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
412 }
413
414 size_t getPosition() const override;
415 bool seek(size_t position) override;
416 bool move(long offset) override;
417
418 std::unique_ptr<SkMemoryStream> fork() const {
419 return std::unique_ptr<SkMemoryStream>(this->onFork());
420 }
421
422 size_t getLength() const override;
423
424 const void* getMemoryBase() override;
425
426private:
427 SkMemoryStream* onDuplicate() const override;
428 SkMemoryStream* onFork() const override;
429
430 sk_sp<SkData> fData;
431 size_t fOffset;
432
433 typedef SkStreamMemory INHERITED;
434};
435
436/////////////////////////////////////////////////////////////////////////////////////////////
437
438class SK_API SkFILEWStream : public SkWStream {
439public:
440 SkFILEWStream(const char path[]);
441 ~SkFILEWStream() override;
442
443 /** Returns true if the current path could be opened.
444 */
445 bool isValid() const { return fFILE != nullptr; }
446
447 bool write(const void* buffer, size_t size) override;
448 void flush() override;
449 void fsync();
450 size_t bytesWritten() const override;
451
452private:
453 FILE* fFILE;
454
455 typedef SkWStream INHERITED;
456};
457
458class SK_API SkDynamicMemoryWStream : public SkWStream {
459public:
460 SkDynamicMemoryWStream() = default;
461 SkDynamicMemoryWStream(SkDynamicMemoryWStream&&);
462 SkDynamicMemoryWStream& operator=(SkDynamicMemoryWStream&&);
463 ~SkDynamicMemoryWStream() override;
464
465 bool write(const void* buffer, size_t size) override;
466 size_t bytesWritten() const override;
467
468 bool read(void* buffer, size_t offset, size_t size);
469
470 /** More efficient version of read(dst, 0, bytesWritten()). */
471 void copyTo(void* dst) const;
472 bool writeToStream(SkWStream* dst) const;
473
474 /** Equivalent to copyTo() followed by reset(), but may save memory use. */
475 void copyToAndReset(void* dst);
476
477 /** Equivalent to writeToStream() followed by reset(), but may save memory use. */
478 bool writeToAndReset(SkWStream* dst);
479
480 /** Equivalent to writeToStream() followed by reset(), but may save memory use.
481 When the dst is also a SkDynamicMemoryWStream, the implementation is constant time. */
482 bool writeToAndReset(SkDynamicMemoryWStream* dst);
483
484 /** Prepend this stream to dst, resetting this. */
485 void prependToAndReset(SkDynamicMemoryWStream* dst);
486
487 /** Return the contents as SkData, and then reset the stream. */
488 sk_sp<SkData> detachAsData();
489
490 /** Reset, returning a reader stream with the current content. */
491 std::unique_ptr<SkStreamAsset> detachAsStream();
492
493 /** Reset the stream to its original, empty, state. */
494 void reset();
495 void padToAlign4();
496private:
497 struct Block;
498 Block* fHead = nullptr;
499 Block* fTail = nullptr;
500 size_t fBytesWrittenBeforeTail = 0;
501
502#ifdef SK_DEBUG
503 void validate() const;
504#else
505 void validate() const {}
506#endif
507
508 // For access to the Block type.
509 friend class SkBlockMemoryStream;
510 friend class SkBlockMemoryRefCnt;
511
512 typedef SkWStream INHERITED;
513};
514
515#endif
516