Line data Source code
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 "SkData.h"
9 : #include "SkOSFile.h"
10 : #include "SkOnce.h"
11 : #include "SkReadBuffer.h"
12 : #include "SkStream.h"
13 : #include "SkWriteBuffer.h"
14 :
15 167 : SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
16 167 : fPtr = const_cast<void*>(ptr);
17 167 : fSize = size;
18 167 : fReleaseProc = proc;
19 167 : fReleaseProcContext = context;
20 167 : }
21 :
22 : /** This constructor means we are inline with our fPtr's contents.
23 : * Thus we set fPtr to point right after this.
24 : */
25 0 : SkData::SkData(size_t size) {
26 0 : fPtr = (char*)(this + 1); // contents are immediately after this
27 0 : fSize = size;
28 0 : fReleaseProc = nullptr;
29 0 : fReleaseProcContext = nullptr;
30 0 : }
31 :
32 296 : SkData::~SkData() {
33 148 : if (fReleaseProc) {
34 127 : fReleaseProc(fPtr, fReleaseProcContext);
35 : }
36 148 : }
37 :
38 0 : bool SkData::equals(const SkData* other) const {
39 0 : if (nullptr == other) {
40 0 : return false;
41 : }
42 :
43 0 : return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
44 : }
45 :
46 0 : size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
47 0 : size_t available = fSize;
48 0 : if (offset >= available || 0 == length) {
49 0 : return 0;
50 : }
51 0 : available -= offset;
52 0 : if (length > available) {
53 0 : length = available;
54 : }
55 0 : SkASSERT(length > 0);
56 :
57 0 : memcpy(buffer, this->bytes() + offset, length);
58 0 : return length;
59 : }
60 :
61 0 : sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
62 0 : if (0 == length) {
63 0 : return SkData::MakeEmpty();
64 : }
65 :
66 0 : const size_t actualLength = length + sizeof(SkData);
67 0 : if (actualLength < length) {
68 : // we overflowed
69 0 : sk_throw();
70 : }
71 :
72 0 : void* storage = ::operator new (actualLength);
73 0 : sk_sp<SkData> data(new (storage) SkData(length));
74 0 : if (srcOrNull) {
75 0 : memcpy(data->writable_data(), srcOrNull, length);
76 : }
77 0 : return data;
78 : }
79 :
80 0 : void SkData::DummyReleaseProc(const void*, void*) {}
81 :
82 : ///////////////////////////////////////////////////////////////////////////////
83 :
84 0 : sk_sp<SkData> SkData::MakeEmpty() {
85 : static SkOnce once;
86 : static SkData* empty;
87 :
88 0 : once([]{ empty = new SkData(nullptr, 0, nullptr, nullptr); });
89 0 : return sk_ref_sp(empty);
90 : }
91 :
92 : // assumes fPtr was allocated via sk_malloc
93 0 : static void sk_free_releaseproc(const void* ptr, void*) {
94 0 : sk_free((void*)ptr);
95 0 : }
96 :
97 0 : sk_sp<SkData> SkData::MakeFromMalloc(const void* data, size_t length) {
98 0 : return sk_sp<SkData>(new SkData(data, length, sk_free_releaseproc, nullptr));
99 : }
100 :
101 0 : sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
102 0 : SkASSERT(src);
103 0 : return PrivateNewWithCopy(src, length);
104 : }
105 :
106 0 : sk_sp<SkData> SkData::MakeUninitialized(size_t length) {
107 0 : return PrivateNewWithCopy(nullptr, length);
108 : }
109 :
110 167 : sk_sp<SkData> SkData::MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx) {
111 167 : return sk_sp<SkData>(new SkData(ptr, length, proc, ctx));
112 : }
113 :
114 : // assumes fPtr was allocated with sk_fmmap
115 0 : static void sk_mmap_releaseproc(const void* addr, void* ctx) {
116 0 : size_t length = reinterpret_cast<size_t>(ctx);
117 0 : sk_fmunmap(addr, length);
118 0 : }
119 :
120 0 : sk_sp<SkData> SkData::MakeFromFILE(FILE* f) {
121 : size_t size;
122 0 : void* addr = sk_fmmap(f, &size);
123 0 : if (nullptr == addr) {
124 0 : return nullptr;
125 : }
126 :
127 0 : return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
128 : }
129 :
130 0 : sk_sp<SkData> SkData::MakeFromFileName(const char path[]) {
131 0 : FILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr;
132 0 : if (nullptr == f) {
133 0 : return nullptr;
134 : }
135 0 : auto data = MakeFromFILE(f);
136 0 : sk_fclose(f);
137 0 : return data;
138 : }
139 :
140 0 : sk_sp<SkData> SkData::MakeFromFD(int fd) {
141 : size_t size;
142 0 : void* addr = sk_fdmmap(fd, &size);
143 0 : if (nullptr == addr) {
144 0 : return nullptr;
145 : }
146 0 : return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
147 : }
148 :
149 : // assumes context is a SkData
150 0 : static void sk_dataref_releaseproc(const void*, void* context) {
151 0 : SkData* src = reinterpret_cast<SkData*>(context);
152 0 : src->unref();
153 0 : }
154 :
155 0 : sk_sp<SkData> SkData::MakeSubset(const SkData* src, size_t offset, size_t length) {
156 : /*
157 : We could, if we wanted/need to, just make a deep copy of src's data,
158 : rather than referencing it. This would duplicate the storage (of the
159 : subset amount) but would possibly allow src to go out of scope sooner.
160 : */
161 :
162 0 : size_t available = src->size();
163 0 : if (offset >= available || 0 == length) {
164 0 : return SkData::MakeEmpty();
165 : }
166 0 : available -= offset;
167 0 : if (length > available) {
168 0 : length = available;
169 : }
170 0 : SkASSERT(length > 0);
171 :
172 0 : src->ref(); // this will be balanced in sk_dataref_releaseproc
173 0 : return sk_sp<SkData>(new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
174 0 : const_cast<SkData*>(src)));
175 : }
176 :
177 0 : sk_sp<SkData> SkData::MakeWithCString(const char cstr[]) {
178 : size_t size;
179 0 : if (nullptr == cstr) {
180 0 : cstr = "";
181 0 : size = 1;
182 : } else {
183 0 : size = strlen(cstr) + 1;
184 : }
185 0 : return MakeWithCopy(cstr, size);
186 : }
187 :
188 : ///////////////////////////////////////////////////////////////////////////////
189 :
190 0 : sk_sp<SkData> SkData::MakeFromStream(SkStream* stream, size_t size) {
191 0 : sk_sp<SkData> data(SkData::MakeUninitialized(size));
192 0 : if (stream->read(data->writable_data(), size) != size) {
193 0 : return nullptr;
194 : }
195 0 : return data;
196 : }
|