Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/core/SkStream.cpp
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
#include "include/core/SkStream.h"
9
10
#include "include/core/SkData.h"
11
#include "include/core/SkString.h"
12
#include "include/core/SkTypes.h"
13
#include "include/private/SkFixed.h"
14
#include "include/private/SkTFitsIn.h"
15
#include "include/private/SkTPin.h"
16
#include "include/private/SkTo.h"
17
#include "src/core/SkOSFile.h"
18
#include "src/core/SkSafeMath.h"
19
#include "src/core/SkStreamPriv.h"
20
21
#include <limits>
22
23
///////////////////////////////////////////////////////////////////////////////
24
25
2.77k
bool SkStream::readS8(int8_t* i) {
26
2.77k
    return this->read(i, sizeof(*i)) == sizeof(*i);
27
2.77k
}
28
29
40.6k
bool SkStream::readS16(int16_t* i) {
30
40.6k
    return this->read(i, sizeof(*i)) == sizeof(*i);
31
40.6k
}
32
33
41.6M
bool SkStream::readS32(int32_t* i) {
34
41.6M
    return this->read(i, sizeof(*i)) == sizeof(*i);
35
41.6M
}
36
37
137k
bool SkStream::readScalar(SkScalar* i) {
38
137k
    return this->read(i, sizeof(*i)) == sizeof(*i);
39
137k
}
40
41
0
#define SK_MAX_BYTE_FOR_U8          0xFD
42
1.33M
#define SK_BYTE_SENTINEL_FOR_U16    0xFE
43
1.29M
#define SK_BYTE_SENTINEL_FOR_U32    0xFF
44
45
484M
bool SkStream::readPackedUInt(size_t* i) {
46
484M
    uint8_t byte;
47
484M
    if (!this->read(&byte, 1)) {
48
483M
        return false;
49
483M
    }
50
1.33M
    if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
51
40.6k
        uint16_t i16;
52
40.6k
        if (!this->readU16(&i16)) { return false; }
53
40.6k
        *i = i16;
54
1.29M
    } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
55
44.0k
        uint32_t i32;
56
44.0k
        if (!this->readU32(&i32)) { return false; }
57
44.0k
        *i = i32;
58
1.25M
    } else {
59
1.25M
        *i = byte;
60
1.25M
    }
61
1.33M
    return true;
62
1.33M
}
63
64
//////////////////////////////////////////////////////////////////////////////////////
65
66
SkWStream::~SkWStream()
67
160k
{
68
160k
}
69
70
void SkWStream::flush()
71
6.50k
{
72
6.50k
}
73
74
bool SkWStream::writeDecAsText(int32_t dec)
75
0
{
76
0
    char buffer[kSkStrAppendS32_MaxSize];
77
0
    char* stop = SkStrAppendS32(buffer, dec);
78
0
    return this->write(buffer, stop - buffer);
79
0
}
80
81
bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
82
0
{
83
0
    char buffer[kSkStrAppendU64_MaxSize];
84
0
    char* stop = SkStrAppendU64(buffer, dec, minDigits);
85
0
    return this->write(buffer, stop - buffer);
86
0
}
87
88
bool SkWStream::writeHexAsText(uint32_t hex, int digits)
89
0
{
90
0
    SkString    tmp;
91
0
    tmp.appendHex(hex, digits);
92
0
    return this->write(tmp.c_str(), tmp.size());
93
0
}
94
95
bool SkWStream::writeScalarAsText(SkScalar value)
96
2.64M
{
97
2.64M
    char buffer[kSkStrAppendScalar_MaxSize];
98
2.64M
    char* stop = SkStrAppendScalar(buffer, value);
99
2.64M
    return this->write(buffer, stop - buffer);
100
2.64M
}
101
102
0
bool SkWStream::writeScalar(SkScalar value) {
103
0
    return this->write(&value, sizeof(value));
104
0
}
105
106
0
int SkWStream::SizeOfPackedUInt(size_t value) {
107
0
    if (value <= SK_MAX_BYTE_FOR_U8) {
108
0
        return 1;
109
0
    } else if (value <= 0xFFFF) {
110
0
        return 3;
111
0
    }
112
0
    return 5;
113
0
}
114
115
0
bool SkWStream::writePackedUInt(size_t value) {
116
0
    uint8_t data[5];
117
0
    size_t len = 1;
118
0
    if (value <= SK_MAX_BYTE_FOR_U8) {
119
0
        data[0] = value;
120
0
        len = 1;
121
0
    } else if (value <= 0xFFFF) {
122
0
        uint16_t value16 = value;
123
0
        data[0] = SK_BYTE_SENTINEL_FOR_U16;
124
0
        memcpy(&data[1], &value16, 2);
125
0
        len = 3;
126
0
    } else {
127
0
        uint32_t value32 = SkToU32(value);
128
0
        data[0] = SK_BYTE_SENTINEL_FOR_U32;
129
0
        memcpy(&data[1], &value32, 4);
130
0
        len = 5;
131
0
    }
132
0
    return this->write(data, len);
133
0
}
134
135
0
bool SkWStream::writeStream(SkStream* stream, size_t length) {
136
0
    char scratch[1024];
137
0
    const size_t MAX = sizeof(scratch);
138
139
0
    while (length != 0) {
140
0
        size_t n = length;
141
0
        if (n > MAX) {
142
0
            n = MAX;
143
0
        }
144
0
        stream->read(scratch, n);
145
0
        if (!this->write(scratch, n)) {
146
0
            return false;
147
0
        }
148
0
        length -= n;
149
0
    }
150
0
    return true;
151
0
}
152
153
///////////////////////////////////////////////////////////////////////////////
154
155
SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t end, size_t start, size_t current)
156
    : fFILE(std::move(file))
157
    , fEnd(end)
158
    , fStart(std::min(start, fEnd))
159
    , fCurrent(SkTPin(current, fStart, fEnd))
160
0
{
161
0
    SkASSERT(fStart == start);
162
0
    SkASSERT(fCurrent == current);
163
0
}
Unexecuted instantiation: SkFILEStream::SkFILEStream(std::__1::shared_ptr<_IO_FILE>, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: SkFILEStream::SkFILEStream(std::__1::shared_ptr<_IO_FILE>, unsigned long, unsigned long, unsigned long)
164
165
SkFILEStream::SkFILEStream(std::shared_ptr<FILE> file, size_t end, size_t start)
166
    : SkFILEStream(std::move(file), end, start, start)
167
0
{ }
168
169
SkFILEStream::SkFILEStream(FILE* file, size_t size, size_t start)
170
    : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose), SkSafeMath::Add(start, size), start)
171
0
{ }
172
173
SkFILEStream::SkFILEStream(FILE* file, size_t size)
174
    : SkFILEStream(file, size, file ? sk_ftell(file) : 0)
175
0
{ }
176
177
SkFILEStream::SkFILEStream(FILE* file)
178
    : SkFILEStream(std::shared_ptr<FILE>(file, sk_fclose),
179
                   file ? sk_fgetsize(file) : 0,
180
                   file ? sk_ftell(file) : 0)
181
0
{ }
182
183
SkFILEStream::SkFILEStream(const char path[])
184
    : SkFILEStream(path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr)
185
0
{ }
186
187
0
SkFILEStream::~SkFILEStream() {
188
0
    this->close();
189
0
}
190
191
0
void SkFILEStream::close() {
192
0
    fFILE.reset();
193
0
    fEnd = 0;
194
0
    fStart = 0;
195
0
    fCurrent = 0;
196
0
}
197
198
0
size_t SkFILEStream::read(void* buffer, size_t size) {
199
0
    if (size > fEnd - fCurrent) {
200
0
        size = fEnd - fCurrent;
201
0
    }
202
0
    size_t bytesRead = size;
203
0
    if (buffer) {
204
0
        bytesRead = sk_qread(fFILE.get(), buffer, size, fCurrent);
205
0
    }
206
0
    if (bytesRead == SIZE_MAX) {
207
0
        return 0;
208
0
    }
209
0
    fCurrent += bytesRead;
210
0
    return bytesRead;
211
0
}
212
213
0
bool SkFILEStream::isAtEnd() const {
214
0
    if (fCurrent == fEnd) {
215
0
        return true;
216
0
    }
217
0
    return fCurrent >= sk_fgetsize(fFILE.get());
218
0
}
219
220
0
bool SkFILEStream::rewind() {
221
0
    fCurrent = fStart;
222
0
    return true;
223
0
}
224
225
0
SkStreamAsset* SkFILEStream::onDuplicate() const {
226
0
    return new SkFILEStream(fFILE, fEnd, fStart, fStart);
227
0
}
228
229
0
size_t SkFILEStream::getPosition() const {
230
0
    SkASSERT(fCurrent >= fStart);
231
0
    return fCurrent - fStart;
232
0
}
Unexecuted instantiation: SkFILEStream::getPosition() const
Unexecuted instantiation: SkFILEStream::getPosition() const
233
234
0
bool SkFILEStream::seek(size_t position) {
235
0
    fCurrent = std::min(SkSafeMath::Add(position, fStart), fEnd);
236
0
    return true;
237
0
}
238
239
0
bool SkFILEStream::move(long offset) {
240
0
    if (offset < 0) {
241
0
        if (offset == std::numeric_limits<long>::min() ||
242
0
            !SkTFitsIn<size_t>(-offset) ||
243
0
            (size_t) (-offset) >= this->getPosition())
244
0
        {
245
0
            fCurrent = fStart;
246
0
        } else {
247
0
            fCurrent += offset;
248
0
        }
249
0
    } else if (!SkTFitsIn<size_t>(offset)) {
250
0
        fCurrent = fEnd;
251
0
    } else {
252
0
        fCurrent = std::min(SkSafeMath::Add(fCurrent, (size_t) offset), fEnd);
253
0
    }
254
255
0
    SkASSERT(fCurrent >= fStart && fCurrent <= fEnd);
256
0
    return true;
257
0
}
Unexecuted instantiation: SkFILEStream::move(long)
Unexecuted instantiation: SkFILEStream::move(long)
258
259
0
SkStreamAsset* SkFILEStream::onFork() const {
260
0
    return new SkFILEStream(fFILE, fEnd, fStart, fCurrent);
261
0
}
262
263
0
size_t SkFILEStream::getLength() const {
264
0
    return fEnd - fStart;
265
0
}
266
267
///////////////////////////////////////////////////////////////////////////////
268
269
18.7k
static sk_sp<SkData> newFromParams(const void* src, size_t size, bool copyData) {
270
18.7k
    if (copyData) {
271
0
        return SkData::MakeWithCopy(src, size);
272
18.7k
    } else {
273
18.7k
        return SkData::MakeWithoutCopy(src, size);
274
18.7k
    }
275
18.7k
}
276
277
0
SkMemoryStream::SkMemoryStream() {
278
0
    fData = SkData::MakeEmpty();
279
0
    fOffset = 0;
280
0
}
281
282
0
SkMemoryStream::SkMemoryStream(size_t size) {
283
0
    fData = SkData::MakeUninitialized(size);
284
0
    fOffset = 0;
285
0
}
286
287
18.7k
SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
288
18.7k
    fData = newFromParams(src, size, copyData);
289
18.7k
    fOffset = 0;
290
18.7k
}
291
292
84.4k
SkMemoryStream::SkMemoryStream(sk_sp<SkData> data) : fData(std::move(data)) {
293
84.4k
    if (nullptr == fData) {
294
0
        fData = SkData::MakeEmpty();
295
0
    }
296
84.4k
    fOffset = 0;
297
84.4k
}
298
299
0
std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeCopy(const void* data, size_t length) {
300
0
    return std::make_unique<SkMemoryStream>(data, length, true);
301
0
}
302
303
0
std::unique_ptr<SkMemoryStream> SkMemoryStream::MakeDirect(const void* data, size_t length) {
304
0
    return std::make_unique<SkMemoryStream>(data, length, false);
305
0
}
306
307
50.2k
std::unique_ptr<SkMemoryStream> SkMemoryStream::Make(sk_sp<SkData> data) {
308
50.2k
    return std::make_unique<SkMemoryStream>(std::move(data));
309
50.2k
}
310
311
0
void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
312
0
    fData = SkData::MakeFromMalloc(src, size);
313
0
    fOffset = 0;
314
0
}
315
316
0
void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
317
0
    fData = newFromParams(src, size, copyData);
318
0
    fOffset = 0;
319
0
}
320
321
0
void SkMemoryStream::setData(sk_sp<SkData> data) {
322
0
    if (nullptr == data) {
323
0
        fData = SkData::MakeEmpty();
324
0
    } else {
325
0
        fData = data;
326
0
    }
327
0
    fOffset = 0;
328
0
}
329
330
0
void SkMemoryStream::skipToAlign4() {
331
    // cast to remove unary-minus warning
332
0
    fOffset += -(int)fOffset & 0x03;
333
0
}
334
335
532M
size_t SkMemoryStream::read(void* buffer, size_t size) {
336
532M
    size_t dataSize = fData->size();
337
338
532M
    if (size > dataSize - fOffset) {
339
483M
        size = dataSize - fOffset;
340
483M
    }
341
532M
    if (buffer) {
342
532M
        memcpy(buffer, fData->bytes() + fOffset, size);
343
532M
    }
344
532M
    fOffset += size;
345
532M
    return size;
346
532M
}
347
348
30.4k
size_t SkMemoryStream::peek(void* buffer, size_t size) const {
349
30.4k
    SkASSERT(buffer != nullptr);
350
351
30.4k
    const size_t currentOffset = fOffset;
352
30.4k
    SkMemoryStream* nonConstThis = const_cast<SkMemoryStream*>(this);
353
30.4k
    const size_t bytesRead = nonConstThis->read(buffer, size);
354
30.4k
    nonConstThis->fOffset = currentOffset;
355
30.4k
    return bytesRead;
356
30.4k
}
357
358
58.9k
bool SkMemoryStream::isAtEnd() const {
359
58.9k
    return fOffset == fData->size();
360
58.9k
}
361
362
18.6k
bool SkMemoryStream::rewind() {
363
18.6k
    fOffset = 0;
364
18.6k
    return true;
365
18.6k
}
366
367
6.64k
SkMemoryStream* SkMemoryStream::onDuplicate() const {
368
6.64k
    return new SkMemoryStream(fData);
369
6.64k
}
370
371
13.7k
size_t SkMemoryStream::getPosition() const {
372
13.7k
    return fOffset;
373
13.7k
}
374
375
4.76M
bool SkMemoryStream::seek(size_t position) {
376
4.76M
    fOffset = position > fData->size()
377
881
            ? fData->size()
378
4.76M
            : position;
379
4.76M
    return true;
380
4.76M
}
381
382
0
bool SkMemoryStream::move(long offset) {
383
0
    return this->seek(fOffset + offset);
384
0
}
385
386
0
SkMemoryStream* SkMemoryStream::onFork() const {
387
0
    std::unique_ptr<SkMemoryStream> that(this->duplicate());
388
0
    that->seek(fOffset);
389
0
    return that.release();
390
0
}
391
392
42.9k
size_t SkMemoryStream::getLength() const {
393
42.9k
    return fData->size();
394
42.9k
}
395
396
38.4k
const void* SkMemoryStream::getMemoryBase() {
397
38.4k
    return fData->data();
398
38.4k
}
399
400
0
const void* SkMemoryStream::getAtPos() {
401
0
    return fData->bytes() + fOffset;
402
0
}
403
404
/////////////////////////////////////////////////////////////////////////////////////////////////////////
405
/////////////////////////////////////////////////////////////////////////////////////////////////////////
406
407
SkFILEWStream::SkFILEWStream(const char path[])
408
0
{
409
0
    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
410
0
}
411
412
SkFILEWStream::~SkFILEWStream()
413
0
{
414
0
    if (fFILE) {
415
0
        sk_fclose(fFILE);
416
0
    }
417
0
}
418
419
0
size_t SkFILEWStream::bytesWritten() const {
420
0
    return sk_ftell(fFILE);
421
0
}
422
423
bool SkFILEWStream::write(const void* buffer, size_t size)
424
0
{
425
0
    if (fFILE == nullptr) {
426
0
        return false;
427
0
    }
428
429
0
    if (sk_fwrite(buffer, size, fFILE) != size)
430
0
    {
431
0
        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %zu bytes\n", size);)
432
0
        sk_fclose(fFILE);
433
0
        fFILE = nullptr;
434
0
        return false;
435
0
    }
436
0
    return true;
437
0
}
Unexecuted instantiation: SkFILEWStream::write(void const*, unsigned long)
Unexecuted instantiation: SkFILEWStream::write(void const*, unsigned long)
438
439
void SkFILEWStream::flush()
440
0
{
441
0
    if (fFILE) {
442
0
        sk_fflush(fFILE);
443
0
    }
444
0
}
445
446
void SkFILEWStream::fsync()
447
0
{
448
0
    flush();
449
0
    if (fFILE) {
450
0
        sk_fsync(fFILE);
451
0
    }
452
0
}
453
454
////////////////////////////////////////////////////////////////////////
455
456
366M
static inline void sk_memcpy_4bytes(void* dst, const void* src, size_t size) {
457
366M
    if (size == 4) {
458
11.4M
        memcpy(dst, src, 4);
459
354M
    } else {
460
354M
        memcpy(dst, src, size);
461
354M
    }
462
366M
}
463
464
547k
#define SkDynamicMemoryWStream_MinBlockSize   4096
465
466
struct SkDynamicMemoryWStream::Block {
467
    Block*  fNext;
468
    char*   fCurr;
469
    char*   fStop;
470
471
1.03M
    const char* start() const { return (const char*)(this + 1); }
472
1.58M
    char*   start() { return (char*)(this + 1); }
473
731M
    size_t  avail() const { return fStop - fCurr; }
474
1.03M
    size_t  written() const { return fCurr - this->start(); }
475
476
547k
    void init(size_t size) {
477
547k
        fNext = nullptr;
478
547k
        fCurr = this->start();
479
547k
        fStop = this->start() + size;
480
547k
    }
481
482
366M
    const void* append(const void* data, size_t size) {
483
366M
        SkASSERT((size_t)(fStop - fCurr) >= size);
484
366M
        sk_memcpy_4bytes(fCurr, data, size);
485
366M
        fCurr += size;
486
366M
        return (const void*)((const char*)data + size);
487
366M
    }
SkDynamicMemoryWStream::Block::append(void const*, unsigned long)
Line
Count
Source
482
362M
    const void* append(const void* data, size_t size) {
483
362M
        SkASSERT((size_t)(fStop - fCurr) >= size);
484
362M
        sk_memcpy_4bytes(fCurr, data, size);
485
362M
        fCurr += size;
486
362M
        return (const void*)((const char*)data + size);
487
362M
    }
SkDynamicMemoryWStream::Block::append(void const*, unsigned long)
Line
Count
Source
482
3.44M
    const void* append(const void* data, size_t size) {
483
3.44M
        SkASSERT((size_t)(fStop - fCurr) >= size);
484
3.44M
        sk_memcpy_4bytes(fCurr, data, size);
485
3.44M
        fCurr += size;
486
3.44M
        return (const void*)((const char*)data + size);
487
3.44M
    }
488
};
489
490
SkDynamicMemoryWStream::SkDynamicMemoryWStream(SkDynamicMemoryWStream&& other)
491
    : fHead(other.fHead)
492
    , fTail(other.fTail)
493
    , fBytesWrittenBeforeTail(other.fBytesWrittenBeforeTail)
494
0
{
495
0
    other.fHead = nullptr;
496
0
    other.fTail = nullptr;
497
0
    other.fBytesWrittenBeforeTail = 0;
498
0
}
499
500
0
SkDynamicMemoryWStream& SkDynamicMemoryWStream::operator=(SkDynamicMemoryWStream&& other) {
501
0
    if (this != &other) {
502
0
        this->~SkDynamicMemoryWStream();
503
0
        new (this) SkDynamicMemoryWStream(std::move(other));
504
0
    }
505
0
    return *this;
506
0
}
507
508
147k
SkDynamicMemoryWStream::~SkDynamicMemoryWStream() {
509
147k
    this->reset();
510
147k
}
511
512
149k
void SkDynamicMemoryWStream::reset() {
513
149k
    Block* block = fHead;
514
615k
    while (block != nullptr) {
515
465k
        Block* next = block->fNext;
516
465k
        sk_free(block);
517
465k
        block = next;
518
465k
    }
519
149k
    fHead = fTail = nullptr;
520
149k
    fBytesWrittenBeforeTail = 0;
521
149k
}
522
523
139k
size_t SkDynamicMemoryWStream::bytesWritten() const {
524
139k
    this->validate();
525
526
139k
    if (fTail) {
527
59.8k
        return fBytesWrittenBeforeTail + fTail->written();
528
59.8k
    }
529
80.0k
    return 0;
530
80.0k
}
531
532
365M
bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
533
365M
    if (count > 0) {
534
365M
        SkASSERT(buffer);
535
365M
        size_t size;
536
537
365M
        if (fTail) {
538
365M
            if (fTail->avail() > 0) {
539
365M
                size = std::min(fTail->avail(), count);
540
365M
                buffer = fTail->append(buffer, size);
541
365M
                SkASSERT(count >= size);
542
365M
                count -= size;
543
365M
                if (count == 0) {
544
365M
                    return true;
545
365M
                }
546
469k
            }
547
            // If we get here, we've just exhausted fTail, so update our tracker
548
469k
            fBytesWrittenBeforeTail += fTail->written();
549
469k
        }
550
551
547k
        size = std::max<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block));
552
547k
        size = SkAlign4(size);  // ensure we're always a multiple of 4 (see padToAlign4())
553
554
547k
        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
555
547k
        block->init(size);
556
547k
        block->append(buffer, count);
557
558
547k
        if (fTail != nullptr) {
559
469k
            fTail->fNext = block;
560
77.3k
        } else {
561
77.3k
            fHead = fTail = block;
562
77.3k
        }
563
547k
        fTail = block;
564
547k
        this->validate();
565
547k
    }
566
587k
    return true;
567
365M
}
SkDynamicMemoryWStream::write(void const*, unsigned long)
Line
Count
Source
532
362M
bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
533
362M
    if (count > 0) {
534
362M
        SkASSERT(buffer);
535
362M
        size_t size;
536
537
362M
        if (fTail) {
538
362M
            if (fTail->avail() > 0) {
539
362M
                size = std::min(fTail->avail(), count);
540
362M
                buffer = fTail->append(buffer, size);
541
362M
                SkASSERT(count >= size);
542
362M
                count -= size;
543
362M
                if (count == 0) {
544
361M
                    return true;
545
361M
                }
546
466k
            }
547
            // If we get here, we've just exhausted fTail, so update our tracker
548
466k
            fBytesWrittenBeforeTail += fTail->written();
549
466k
        }
550
551
503k
        size = std::max<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block));
552
503k
        size = SkAlign4(size);  // ensure we're always a multiple of 4 (see padToAlign4())
553
554
503k
        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
555
503k
        block->init(size);
556
503k
        block->append(buffer, count);
557
558
503k
        if (fTail != nullptr) {
559
466k
            fTail->fNext = block;
560
37.4k
        } else {
561
37.4k
            fHead = fTail = block;
562
37.4k
        }
563
503k
        fTail = block;
564
503k
        this->validate();
565
503k
    }
566
504k
    return true;
567
362M
}
SkDynamicMemoryWStream::write(void const*, unsigned long)
Line
Count
Source
532
3.47M
bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) {
533
3.47M
    if (count > 0) {
534
3.43M
        SkASSERT(buffer);
535
3.43M
        size_t size;
536
537
3.43M
        if (fTail) {
538
3.39M
            if (fTail->avail() > 0) {
539
3.39M
                size = std::min(fTail->avail(), count);
540
3.39M
                buffer = fTail->append(buffer, size);
541
3.39M
                SkASSERT(count >= size);
542
3.39M
                count -= size;
543
3.39M
                if (count == 0) {
544
3.39M
                    return true;
545
3.39M
                }
546
3.16k
            }
547
            // If we get here, we've just exhausted fTail, so update our tracker
548
3.16k
            fBytesWrittenBeforeTail += fTail->written();
549
3.16k
        }
550
551
43.0k
        size = std::max<size_t>(count, SkDynamicMemoryWStream_MinBlockSize - sizeof(Block));
552
43.0k
        size = SkAlign4(size);  // ensure we're always a multiple of 4 (see padToAlign4())
553
554
43.0k
        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
555
43.0k
        block->init(size);
556
43.0k
        block->append(buffer, count);
557
558
43.0k
        if (fTail != nullptr) {
559
3.16k
            fTail->fNext = block;
560
39.9k
        } else {
561
39.9k
            fHead = fTail = block;
562
39.9k
        }
563
43.0k
        fTail = block;
564
43.0k
        this->validate();
565
43.0k
    }
566
82.2k
    return true;
567
3.47M
}
568
569
0
bool SkDynamicMemoryWStream::writeToAndReset(SkDynamicMemoryWStream* dst) {
570
0
    SkASSERT(dst);
571
0
    SkASSERT(dst != this);
572
0
    if (0 == this->bytesWritten()) {
573
0
        return true;
574
0
    }
575
0
    if (0 == dst->bytesWritten()) {
576
0
        *dst = std::move(*this);
577
0
        return true;
578
0
    }
579
0
    dst->fTail->fNext = fHead;
580
0
    dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + dst->fTail->written();
581
0
    dst->fTail = fTail;
582
0
    fHead = fTail = nullptr;
583
0
    fBytesWrittenBeforeTail = 0;
584
0
    return true;
585
0
}
Unexecuted instantiation: SkDynamicMemoryWStream::writeToAndReset(SkDynamicMemoryWStream*)
Unexecuted instantiation: SkDynamicMemoryWStream::writeToAndReset(SkDynamicMemoryWStream*)
586
587
0
void SkDynamicMemoryWStream::prependToAndReset(SkDynamicMemoryWStream* dst) {
588
0
    SkASSERT(dst);
589
0
    SkASSERT(dst != this);
590
0
    if (0 == this->bytesWritten()) {
591
0
        return;
592
0
    }
593
0
    if (0 == dst->bytesWritten()) {
594
0
        *dst = std::move(*this);
595
0
        return;
596
0
    }
597
0
    fTail->fNext = dst->fHead;
598
0
    dst->fHead = fHead;
599
0
    dst->fBytesWrittenBeforeTail += fBytesWrittenBeforeTail + fTail->written();
600
0
    fHead = fTail = nullptr;
601
0
    fBytesWrittenBeforeTail = 0;
602
0
    return;
603
0
}
Unexecuted instantiation: SkDynamicMemoryWStream::prependToAndReset(SkDynamicMemoryWStream*)
Unexecuted instantiation: SkDynamicMemoryWStream::prependToAndReset(SkDynamicMemoryWStream*)
604
605
606
0
bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) {
607
0
    if (offset + count > this->bytesWritten()) {
608
0
        return false; // test does not partially modify
609
0
    }
610
0
    Block* block = fHead;
611
0
    while (block != nullptr) {
612
0
        size_t size = block->written();
613
0
        if (offset < size) {
614
0
            size_t part = offset + count > size ? size - offset : count;
615
0
            memcpy(buffer, block->start() + offset, part);
616
0
            if (count <= part) {
617
0
                return true;
618
0
            }
619
0
            count -= part;
620
0
            buffer = (void*) ((char* ) buffer + part);
621
0
        }
622
0
        offset = offset > size ? offset - size : 0;
623
0
        block = block->fNext;
624
0
    }
625
0
    return false;
626
0
}
627
628
7.51k
void SkDynamicMemoryWStream::copyTo(void* dst) const {
629
7.51k
    SkASSERT(dst);
630
7.51k
    Block* block = fHead;
631
418k
    while (block != nullptr) {
632
411k
        size_t size = block->written();
633
411k
        memcpy(dst, block->start(), size);
634
411k
        dst = (void*)((char*)dst + size);
635
411k
        block = block->fNext;
636
411k
    }
637
7.51k
}
638
639
0
bool SkDynamicMemoryWStream::writeToStream(SkWStream* dst) const {
640
0
    SkASSERT(dst);
641
0
    for (Block* block = fHead; block != nullptr; block = block->fNext) {
642
0
        if (!dst->write(block->start(), block->written())) {
643
0
            return false;
644
0
        }
645
0
    }
646
0
    return true;
647
0
}
Unexecuted instantiation: SkDynamicMemoryWStream::writeToStream(SkWStream*) const
Unexecuted instantiation: SkDynamicMemoryWStream::writeToStream(SkWStream*) const
648
649
0
void SkDynamicMemoryWStream::padToAlign4() {
650
    // The contract is to write zeros until the entire stream has written a multiple of 4 bytes.
651
    // Our Blocks are guaranteed always be (a) full (except the tail) and (b) a multiple of 4
652
    // so it is sufficient to just examine the tail (if present).
653
654
0
    if (fTail) {
655
        // cast to remove unary-minus warning
656
0
        int padBytes = -(int)fTail->written() & 0x03;
657
0
        if (padBytes) {
658
0
            int zero = 0;
659
0
            fTail->append(&zero, padBytes);
660
0
        }
661
0
    }
662
0
}
663
664
665
54.9k
void SkDynamicMemoryWStream::copyToAndReset(void* ptr) {
666
54.9k
    if (!ptr) {
667
0
        this->reset();
668
0
        return;
669
0
    }
670
    // By looping through the source and freeing as we copy, we
671
    // can reduce real memory use with large streams.
672
54.9k
    char* dst = reinterpret_cast<char*>(ptr);
673
54.9k
    Block* block = fHead;
674
136k
    while (block != nullptr) {
675
81.3k
        size_t len = block->written();
676
81.3k
        memcpy(dst, block->start(), len);
677
81.3k
        dst += len;
678
81.3k
        Block* next = block->fNext;
679
81.3k
        sk_free(block);
680
81.3k
        block = next;
681
81.3k
    }
682
54.9k
    fHead = fTail = nullptr;
683
54.9k
    fBytesWrittenBeforeTail = 0;
684
54.9k
}
685
686
0
bool SkDynamicMemoryWStream::writeToAndReset(SkWStream* dst) {
687
0
    SkASSERT(dst);
688
    // By looping through the source and freeing as we copy, we
689
    // can reduce real memory use with large streams.
690
0
    bool dstStreamGood = true;
691
0
    for (Block* block = fHead; block != nullptr; ) {
692
0
        if (dstStreamGood && !dst->write(block->start(), block->written())) {
693
0
            dstStreamGood = false;
694
0
        }
695
0
        Block* next = block->fNext;
696
0
        sk_free(block);
697
0
        block = next;
698
0
    }
699
0
    fHead = fTail = nullptr;
700
0
    fBytesWrittenBeforeTail = 0;
701
0
    return dstStreamGood;
702
0
}
Unexecuted instantiation: SkDynamicMemoryWStream::writeToAndReset(SkWStream*)
Unexecuted instantiation: SkDynamicMemoryWStream::writeToAndReset(SkWStream*)
703
704
132k
sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() {
705
132k
    const size_t size = this->bytesWritten();
706
132k
    if (0 == size) {
707
77.5k
        return SkData::MakeEmpty();
708
77.5k
    }
709
54.9k
    sk_sp<SkData> data = SkData::MakeUninitialized(size);
710
54.9k
    this->copyToAndReset(data->writable_data());
711
54.9k
    return data;
712
54.9k
}
713
714
#ifdef SK_DEBUG
715
157k
void SkDynamicMemoryWStream::validate() const {
716
157k
    if (!fHead) {
717
77.5k
        SkASSERT(!fTail);
718
77.5k
        SkASSERT(fBytesWrittenBeforeTail == 0);
719
77.5k
        return;
720
77.5k
    }
721
79.9k
    SkASSERT(fTail);
722
723
79.9k
    size_t bytes = 0;
724
79.9k
    const Block* block = fHead;
725
169k
    while (block) {
726
89.8k
        if (block->fNext) {
727
9.85k
            bytes += block->written();
728
9.85k
        }
729
89.8k
        block = block->fNext;
730
89.8k
    }
731
79.9k
    SkASSERT(bytes == fBytesWrittenBeforeTail);
732
79.9k
}
733
#endif
734
735
////////////////////////////////////////////////////////////////////////////////////////////////
736
737
class SkBlockMemoryRefCnt : public SkRefCnt {
738
public:
739
0
    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
740
741
0
    ~SkBlockMemoryRefCnt() override {
742
0
        SkDynamicMemoryWStream::Block* block = fHead;
743
0
        while (block != nullptr) {
744
0
            SkDynamicMemoryWStream::Block* next = block->fNext;
745
0
            sk_free(block);
746
0
            block = next;
747
0
        }
748
0
    }
749
750
    SkDynamicMemoryWStream::Block* const fHead;
751
};
752
753
class SkBlockMemoryStream : public SkStreamAsset {
754
public:
755
    SkBlockMemoryStream(sk_sp<SkBlockMemoryRefCnt> headRef, size_t size)
756
        : fBlockMemory(std::move(headRef)), fCurrent(fBlockMemory->fHead)
757
0
        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
758
759
0
    size_t read(void* buffer, size_t rawCount) override {
760
0
        size_t count = rawCount;
761
0
        if (fOffset + count > fSize) {
762
0
            count = fSize - fOffset;
763
0
        }
764
0
        size_t bytesLeftToRead = count;
765
0
        while (fCurrent != nullptr) {
766
0
            size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
767
0
            size_t bytesFromCurrent = std::min(bytesLeftToRead, bytesLeftInCurrent);
768
0
            if (buffer) {
769
0
                memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
770
0
                buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
771
0
            }
772
0
            if (bytesLeftToRead <= bytesFromCurrent) {
773
0
                fCurrentOffset += bytesFromCurrent;
774
0
                fOffset += count;
775
0
                return count;
776
0
            }
777
0
            bytesLeftToRead -= bytesFromCurrent;
778
0
            fCurrent = fCurrent->fNext;
779
0
            fCurrentOffset = 0;
780
0
        }
781
0
        SkASSERT(false);
782
0
        return 0;
783
0
    }
Unexecuted instantiation: SkBlockMemoryStream::read(void*, unsigned long)
Unexecuted instantiation: SkBlockMemoryStream::read(void*, unsigned long)
784
785
0
    bool isAtEnd() const override {
786
0
        return fOffset == fSize;
787
0
    }
788
789
0
    size_t peek(void* buff, size_t bytesToPeek) const override {
790
0
        SkASSERT(buff != nullptr);
791
792
0
        bytesToPeek = std::min(bytesToPeek, fSize - fOffset);
793
794
0
        size_t bytesLeftToPeek = bytesToPeek;
795
0
        char* buffer = static_cast<char*>(buff);
796
0
        const SkDynamicMemoryWStream::Block* current = fCurrent;
797
0
        size_t currentOffset = fCurrentOffset;
798
0
        while (bytesLeftToPeek) {
799
0
            SkASSERT(current);
800
0
            size_t bytesFromCurrent = std::min(current->written() - currentOffset, bytesLeftToPeek);
801
0
            memcpy(buffer, current->start() + currentOffset, bytesFromCurrent);
802
0
            bytesLeftToPeek -= bytesFromCurrent;
803
0
            buffer += bytesFromCurrent;
804
0
            current = current->fNext;
805
0
            currentOffset = 0;
806
0
        }
807
0
        return bytesToPeek;
808
0
    }
Unexecuted instantiation: SkBlockMemoryStream::peek(void*, unsigned long) const
Unexecuted instantiation: SkBlockMemoryStream::peek(void*, unsigned long) const
809
810
0
    bool rewind() override {
811
0
        fCurrent = fBlockMemory->fHead;
812
0
        fOffset = 0;
813
0
        fCurrentOffset = 0;
814
0
        return true;
815
0
    }
816
817
0
    SkBlockMemoryStream* onDuplicate() const override {
818
0
        return new SkBlockMemoryStream(fBlockMemory, fSize);
819
0
    }
820
821
0
    size_t getPosition() const override {
822
0
        return fOffset;
823
0
    }
824
825
0
    bool seek(size_t position) override {
826
        // If possible, skip forward.
827
0
        if (position >= fOffset) {
828
0
            size_t skipAmount = position - fOffset;
829
0
            return this->skip(skipAmount) == skipAmount;
830
0
        }
831
        // If possible, move backward within the current block.
832
0
        size_t moveBackAmount = fOffset - position;
833
0
        if (moveBackAmount <= fCurrentOffset) {
834
0
            fCurrentOffset -= moveBackAmount;
835
0
            fOffset -= moveBackAmount;
836
0
            return true;
837
0
        }
838
        // Otherwise rewind and move forward.
839
0
        return this->rewind() && this->skip(position) == position;
840
0
    }
841
842
0
    bool move(long offset) override {
843
0
        return seek(fOffset + offset);
844
0
    }
845
846
0
    SkBlockMemoryStream* onFork() const override {
847
0
        SkBlockMemoryStream* that = this->onDuplicate();
848
0
        that->fCurrent = this->fCurrent;
849
0
        that->fOffset = this->fOffset;
850
0
        that->fCurrentOffset = this->fCurrentOffset;
851
0
        return that;
852
0
    }
853
854
0
    size_t getLength() const override {
855
0
        return fSize;
856
0
    }
857
858
0
    const void* getMemoryBase() override {
859
0
        if (fBlockMemory->fHead && !fBlockMemory->fHead->fNext) {
860
0
            return fBlockMemory->fHead->start();
861
0
        }
862
0
        return nullptr;
863
0
    }
864
865
private:
866
    sk_sp<SkBlockMemoryRefCnt> const fBlockMemory;
867
    SkDynamicMemoryWStream::Block const * fCurrent;
868
    size_t const fSize;
869
    size_t fOffset;
870
    size_t fCurrentOffset;
871
};
872
873
0
std::unique_ptr<SkStreamAsset> SkDynamicMemoryWStream::detachAsStream() {
874
0
    if (nullptr == fHead) {
875
        // no need to reset.
876
0
        return SkMemoryStream::Make(nullptr);
877
0
    }
878
0
    if (fHead == fTail) {  // one block, may be worth shrinking.
879
0
        ptrdiff_t used = fTail->fCurr - (char*)fTail;
880
0
        fHead = fTail = (SkDynamicMemoryWStream::Block*)sk_realloc_throw(fTail, SkToSizeT(used));
881
0
        fTail->fStop = fTail->fCurr = (char*)fTail + used;  // Update pointers.
882
0
        SkASSERT(nullptr == fTail->fNext);
883
0
        SkASSERT(0 == fBytesWrittenBeforeTail);
884
0
    }
885
0
    std::unique_ptr<SkStreamAsset> stream
886
0
            = std::make_unique<SkBlockMemoryStream>(sk_make_sp<SkBlockMemoryRefCnt>(fHead),
887
0
                                                      this->bytesWritten());
888
0
    fHead = nullptr;    // signal reset() to not free anything
889
0
    this->reset();
890
0
    return stream;
891
0
}
Unexecuted instantiation: SkDynamicMemoryWStream::detachAsStream()
Unexecuted instantiation: SkDynamicMemoryWStream::detachAsStream()
892
893
///////////////////////////////////////////////////////////////////////////////
894
///////////////////////////////////////////////////////////////////////////////
895
896
0
static sk_sp<SkData> mmap_filename(const char path[]) {
897
0
    FILE* file = sk_fopen(path, kRead_SkFILE_Flag);
898
0
    if (nullptr == file) {
899
0
        return nullptr;
900
0
    }
901
902
0
    auto data = SkData::MakeFromFILE(file);
903
0
    sk_fclose(file);
904
0
    return data;
905
0
}
906
907
0
std::unique_ptr<SkStreamAsset> SkStream::MakeFromFile(const char path[]) {
908
0
    auto data(mmap_filename(path));
909
0
    if (data) {
910
0
        return std::make_unique<SkMemoryStream>(std::move(data));
911
0
    }
912
913
    // If we get here, then our attempt at using mmap failed, so try normal file access.
914
0
    auto stream = std::make_unique<SkFILEStream>(path);
915
0
    if (!stream->isValid()) {
916
0
        return nullptr;
917
0
    }
918
0
    return std::move(stream);
919
0
}
920
921
// Declared in SkStreamPriv.h:
922
0
sk_sp<SkData> SkCopyStreamToData(SkStream* stream) {
923
0
    SkASSERT(stream != nullptr);
924
925
0
    if (stream->hasLength()) {
926
0
        return SkData::MakeFromStream(stream, stream->getLength());
927
0
    }
928
929
0
    SkDynamicMemoryWStream tempStream;
930
0
    const size_t bufferSize = 4096;
931
0
    char buffer[bufferSize];
932
0
    do {
933
0
        size_t bytesRead = stream->read(buffer, bufferSize);
934
0
        tempStream.write(buffer, bytesRead);
935
0
    } while (!stream->isAtEnd());
936
0
    return tempStream.detachAsData();
937
0
}
Unexecuted instantiation: SkCopyStreamToData(SkStream*)
Unexecuted instantiation: SkCopyStreamToData(SkStream*)
938
939
0
bool SkStreamCopy(SkWStream* out, SkStream* input) {
940
0
    const char* base = static_cast<const char*>(input->getMemoryBase());
941
0
    if (base && input->hasPosition() && input->hasLength()) {
942
        // Shortcut that avoids the while loop.
943
0
        size_t position = input->getPosition();
944
0
        size_t length = input->getLength();
945
0
        SkASSERT(length >= position);
946
0
        return out->write(&base[position], length - position);
947
0
    }
948
0
    char scratch[4096];
949
0
    size_t count;
950
0
    while (true) {
951
0
        count = input->read(scratch, sizeof(scratch));
952
0
        if (0 == count) {
953
0
            return true;
954
0
        }
955
0
        if (!out->write(scratch, count)) {
956
0
            return false;
957
0
        }
958
0
    }
959
0
}
Unexecuted instantiation: SkStreamCopy(SkWStream*, SkStream*)
Unexecuted instantiation: SkStreamCopy(SkWStream*, SkStream*)