Coverage Report

Created: 2024-05-20 07:14

/src/skia/src/core/SkData.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2011 Google Inc.
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/SkData.h"
9
10
#include "include/core/SkStream.h"
11
#include "include/private/base/SkAssert.h"
12
#include "include/private/base/SkMalloc.h"
13
#include "include/private/base/SkOnce.h"
14
#include "src/core/SkOSFile.h"
15
#include "src/core/SkStreamPriv.h"
16
17
#include <cstring>
18
#include <new>
19
20
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context)
21
    : fReleaseProc(proc)
22
    , fReleaseProcContext(context)
23
    , fPtr(ptr)
24
    , fSize(size)
25
781k
{}
26
27
/** This constructor means we are inline with our fPtr's contents.
28
 *  Thus we set fPtr to point right after this.
29
 */
30
SkData::SkData(size_t size)
31
    : fReleaseProc(nullptr)
32
    , fReleaseProcContext(nullptr)
33
    , fPtr((const char*)(this + 1))
34
    , fSize(size)
35
972k
{}
36
37
1.75M
SkData::~SkData() {
38
1.75M
    if (fReleaseProc) {
39
781k
        fReleaseProc(fPtr, fReleaseProcContext);
40
781k
    }
41
1.75M
}
42
43
0
bool SkData::equals(const SkData* other) const {
44
0
    if (this == other) {
45
0
        return true;
46
0
    }
47
0
    if (nullptr == other) {
48
0
        return false;
49
0
    }
50
0
    return fSize == other->fSize && !sk_careful_memcmp(fPtr, other->fPtr, fSize);
51
0
}
52
53
0
size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
54
0
    size_t available = fSize;
55
0
    if (offset >= available || 0 == length) {
56
0
        return 0;
57
0
    }
58
0
    available -= offset;
59
0
    if (length > available) {
60
0
        length = available;
61
0
    }
62
0
    SkASSERT(length > 0);
63
64
0
    if (buffer) {
65
0
        memcpy(buffer, this->bytes() + offset, length);
66
0
    }
67
0
    return length;
68
0
}
Unexecuted instantiation: SkData::copyRange(unsigned long, unsigned long, void*) const
Unexecuted instantiation: SkData::copyRange(unsigned long, unsigned long, void*) const
69
70
1.75M
void SkData::operator delete(void* p) {
71
1.75M
    ::operator delete(p);
72
1.75M
}
73
74
983k
sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
75
983k
    if (0 == length) {
76
11.0k
        return SkData::MakeEmpty();
77
11.0k
    }
78
79
972k
    const size_t actualLength = length + sizeof(SkData);
80
972k
    SkASSERT_RELEASE(length < actualLength);  // Check for overflow.
81
82
972k
    void* storage = ::operator new (actualLength);
83
972k
    sk_sp<SkData> data(new (storage) SkData(length));
84
972k
    if (srcOrNull) {
85
63.5k
        memcpy(data->writable_data(), srcOrNull, length);
86
63.5k
    }
87
972k
    return data;
88
983k
}
89
90
211k
void SkData::NoopReleaseProc(const void*, void*) {}
91
92
///////////////////////////////////////////////////////////////////////////////
93
94
21.9k
sk_sp<SkData> SkData::MakeEmpty() {
95
21.9k
    static SkOnce once;
96
21.9k
    static SkData* empty;
97
98
21.9k
    once([]{ empty = new SkData(nullptr, 0, nullptr, nullptr); });
99
21.9k
    return sk_ref_sp(empty);
100
21.9k
}
101
102
// assumes fPtr was allocated via sk_malloc
103
421k
static void sk_free_releaseproc(const void* ptr, void*) {
104
421k
    sk_free(const_cast<void*>(ptr));
105
421k
}
106
107
421k
sk_sp<SkData> SkData::MakeFromMalloc(const void* data, size_t length) {
108
421k
    return sk_sp<SkData>(new SkData(data, length, sk_free_releaseproc, nullptr));
109
421k
}
110
111
63.6k
sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
112
63.6k
    SkASSERT(src);
113
63.6k
    return PrivateNewWithCopy(src, length);
114
63.6k
}
115
116
919k
sk_sp<SkData> SkData::MakeUninitialized(size_t length) {
117
919k
    return PrivateNewWithCopy(nullptr, length);
118
919k
}
119
120
40.8k
sk_sp<SkData> SkData::MakeZeroInitialized(size_t length) {
121
40.8k
    auto data = MakeUninitialized(length);
122
40.8k
    if (length != 0) {
123
40.8k
        memset(data->writable_data(), 0, data->size());
124
40.8k
    }
125
40.8k
    return data;
126
40.8k
}
127
128
272k
sk_sp<SkData> SkData::MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx) {
129
272k
    return sk_sp<SkData>(new SkData(ptr, length, proc, ctx));
130
272k
}
131
132
// assumes fPtr was allocated with sk_fmmap
133
0
static void sk_mmap_releaseproc(const void* addr, void* ctx) {
134
0
    size_t length = reinterpret_cast<size_t>(ctx);
135
0
    sk_fmunmap(addr, length);
136
0
}
137
138
0
sk_sp<SkData> SkData::MakeFromFILE(FILE* f) {
139
0
    size_t size;
140
0
    void* addr = sk_fmmap(f, &size);
141
0
    if (nullptr == addr) {
142
0
        return nullptr;
143
0
    }
144
145
0
    return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
146
0
}
147
148
11
sk_sp<SkData> SkData::MakeFromFileName(const char path[]) {
149
11
    FILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr;
150
11
    if (nullptr == f) {
151
11
        return nullptr;
152
11
    }
153
0
    auto data = MakeFromFILE(f);
154
0
    sk_fclose(f);
155
0
    return data;
156
11
}
157
158
0
sk_sp<SkData> SkData::MakeFromFD(int fd) {
159
0
    size_t size;
160
0
    void* addr = sk_fdmmap(fd, &size);
161
0
    if (nullptr == addr) {
162
0
        return nullptr;
163
0
    }
164
0
    return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
165
0
}
166
167
// assumes context is a SkData
168
87.0k
static void sk_dataref_releaseproc(const void*, void* context) {
169
87.0k
    SkData* src = reinterpret_cast<SkData*>(context);
170
87.0k
    src->unref();
171
87.0k
}
172
173
88.8k
sk_sp<SkData> SkData::MakeSubset(const SkData* src, size_t offset, size_t length) {
174
    /*
175
        We could, if we wanted/need to, just make a deep copy of src's data,
176
        rather than referencing it. This would duplicate the storage (of the
177
        subset amount) but would possibly allow src to go out of scope sooner.
178
     */
179
180
88.8k
    size_t available = src->size();
181
88.8k
    if (offset >= available || 0 == length) {
182
1.78k
        return SkData::MakeEmpty();
183
1.78k
    }
184
87.0k
    available -= offset;
185
87.0k
    if (length > available) {
186
79.4k
        length = available;
187
79.4k
    }
188
87.0k
    SkASSERT(length > 0);
189
190
87.0k
    src->ref(); // this will be balanced in sk_dataref_releaseproc
191
87.0k
    return sk_sp<SkData>(new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
192
87.0k
                                    const_cast<SkData*>(src)));
193
88.8k
}
SkData::MakeSubset(SkData const*, unsigned long, unsigned long)
Line
Count
Source
173
88.8k
sk_sp<SkData> SkData::MakeSubset(const SkData* src, size_t offset, size_t length) {
174
    /*
175
        We could, if we wanted/need to, just make a deep copy of src's data,
176
        rather than referencing it. This would duplicate the storage (of the
177
        subset amount) but would possibly allow src to go out of scope sooner.
178
     */
179
180
88.8k
    size_t available = src->size();
181
88.8k
    if (offset >= available || 0 == length) {
182
1.78k
        return SkData::MakeEmpty();
183
1.78k
    }
184
87.0k
    available -= offset;
185
87.0k
    if (length > available) {
186
79.4k
        length = available;
187
79.4k
    }
188
87.0k
    SkASSERT(length > 0);
189
190
87.0k
    src->ref(); // this will be balanced in sk_dataref_releaseproc
191
87.0k
    return sk_sp<SkData>(new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
192
87.0k
                                    const_cast<SkData*>(src)));
193
88.8k
}
Unexecuted instantiation: SkData::MakeSubset(SkData const*, unsigned long, unsigned long)
194
195
0
sk_sp<SkData> SkData::MakeWithCString(const char cstr[]) {
196
0
    size_t size;
197
0
    if (nullptr == cstr) {
198
0
        cstr = "";
199
0
        size = 1;
200
0
    } else {
201
0
        size = strlen(cstr) + 1;
202
0
    }
203
0
    return MakeWithCopy(cstr, size);
204
0
}
205
206
///////////////////////////////////////////////////////////////////////////////
207
208
256k
sk_sp<SkData> SkData::MakeFromStream(SkStream* stream, size_t size) {
209
    // reduce the chance of OOM by checking that the stream has enough bytes to read from before
210
    // allocating that potentially large buffer.
211
256k
    if (StreamRemainingLengthIsBelow(stream, size)) {
212
247
        return nullptr;
213
247
    }
214
256k
    sk_sp<SkData> data(SkData::MakeUninitialized(size));
215
256k
    if (stream->read(data->writable_data(), size) != size) {
216
0
        return nullptr;
217
0
    }
218
256k
    return data;
219
256k
}