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