Coverage Report

Created: 2024-05-20 07:14

/src/skia/include/core/SkStream.h
Line
Count
Source (jump to first uncovered line)
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:
31
919k
    virtual ~SkStream() {}
32
919k
    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
     */
51
7.05k
    size_t skip(size_t size) {
52
7.05k
        return this->read(nullptr, size);
53
7.05k
    }
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
     */
68
0
    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
83
183k
    [[nodiscard]] bool readU8(uint8_t* i) { return this->readS8((int8_t*)i); }
84
170k
    [[nodiscard]] bool readU16(uint16_t* i) { return this->readS16((int16_t*)i); }
85
40.4M
    [[nodiscard]] bool readU32(uint32_t* i) { return this->readS32((int32_t*)i); }
86
87
0
    [[nodiscard]] bool readBool(bool* b) {
88
0
        uint8_t i;
89
0
        if (!this->readU8(&i)) { return false; }
90
0
        *b = (i != 0);
91
0
        return true;
92
0
    }
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
     */
100
0
    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
     */
105
0
    std::unique_ptr<SkStream> duplicate() const {
106
0
        return std::unique_ptr<SkStream>(this->onDuplicate());
107
0
    }
108
    /** Duplicates this stream. If this cannot be done, returns NULL.
109
     *  The returned stream will be positioned the same as this stream.
110
     */
111
0
    std::unique_ptr<SkStream> fork() const {
112
0
        return std::unique_ptr<SkStream>(this->onFork());
113
0
    }
114
115
//SkStreamSeekable
116
    /** Returns true if this stream can report its current position. */
117
0
    virtual bool hasPosition() const { return false; }
118
    /** Returns the current position in the stream. If this cannot be done, returns 0. */
119
0
    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
     */
125
0
    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
     */
131
0
    virtual bool move(long /*offset*/) { return false; }
132
133
//SkStreamAsset
134
    /** Returns true if this stream can report its total length. */
135
0
    virtual bool hasLength() const { return false; }
136
    /** Returns the total length of the stream. If this cannot be done, returns 0. */
137
0
    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. */
141
0
    virtual const void* getMemoryBase() { return nullptr; }
142
0
    virtual sk_sp<SkData> getData() const { return nullptr; }
143
144
private:
145
0
    virtual SkStream* onDuplicate() const { return nullptr; }
146
0
    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;
158
0
    std::unique_ptr<SkStreamRewindable> duplicate() const {
159
0
        return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
160
0
    }
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:
168
0
    std::unique_ptr<SkStreamSeekable> duplicate() const {
169
0
        return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
170
0
    }
171
172
1.80M
    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
177
0
    std::unique_ptr<SkStreamSeekable> fork() const {
178
0
        return std::unique_ptr<SkStreamSeekable>(this->onFork());
179
0
    }
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:
188
1.81M
    bool hasLength() const override { return true; }
189
    size_t getLength() const override = 0;
190
191
4.10k
    std::unique_ptr<SkStreamAsset> duplicate() const {
192
4.10k
        return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
193
4.10k
    }
194
0
    std::unique_ptr<SkStreamAsset> fork() const {
195
0
        return std::unique_ptr<SkStreamAsset>(this->onFork());
196
0
    }
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
207
0
    std::unique_ptr<SkStreamMemory> duplicate() const {
208
0
        return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
209
0
    }
210
0
    std::unique_ptr<SkStreamMemory> fork() const {
211
0
        return std::unique_ptr<SkStreamMemory>(this->onFork());
212
0
    }
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();
221
26.7k
    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
235
0
    bool write8(U8CPU value)   {
236
0
        uint8_t v = SkToU8(value);
237
0
        return this->write(&v, 1);
238
0
    }
239
0
    bool write16(U16CPU value) {
240
0
        uint16_t v = SkToU16(value);
241
0
        return this->write(&v, 2);
242
0
    }
243
0
    bool write32(uint32_t v) {
244
0
        return this->write(&v, 4);
245
0
    }
246
247
13.0M
    bool writeText(const char text[]) {
248
13.0M
        SkASSERT(text);
249
13.0M
        return this->write(text, std::strlen(text));
250
13.0M
    }
251
252
28.1k
    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
259
0
    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:
278
5.12k
    SkNullWStream() : fBytesWritten(0) {}
279
280
387k
    bool write(const void* , size_t n) override { fBytesWritten += n; return true; }
281
0
    void flush() override {}
282
0
    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
314
0
    static std::unique_ptr<SkFILEStream> Make(const char path[]) {
315
0
        std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
316
0
        return stream->isValid() ? std::move(stream) : nullptr;
317
0
    }
318
319
    /** Returns true if the current path could be opened. */
320
0
    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;
329
0
    std::unique_ptr<SkStreamAsset> duplicate() const {
330
0
        return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
331
0
    }
332
333
    size_t getPosition() const override;
334
    bool seek(size_t position) override;
335
    bool move(long offset) override;
336
337
0
    std::unique_ptr<SkStreamAsset> fork() const {
338
0
        return std::unique_ptr<SkStreamAsset>(this->onFork());
339
0
    }
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
395
0
    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
407
0
    std::unique_ptr<SkMemoryStream> duplicate() const {
408
0
        return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
409
0
    }
410
411
    size_t getPosition() const override;
412
    bool seek(size_t position) override;
413
    bool move(long offset) override;
414
415
0
    std::unique_ptr<SkMemoryStream> fork() const {
416
0
        return std::unique_ptr<SkMemoryStream>(this->onFork());
417
0
    }
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
    */
442
0
    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
21.6k
    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
502
60.8k
    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