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