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

source code of flutter_engine/third_party/skia/include/core/SkStream.h