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 "SkFlattenableBuffers.h"
10
SK_DEFINE_INST_COUNT(SkData)11 SK_DEFINE_INST_COUNT(SkData)
12
13 SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
14 fPtr = ptr;
15 fSize = size;
16 fReleaseProc = proc;
17 fReleaseProcContext = context;
18 }
19
~SkData()20 SkData::~SkData() {
21 if (fReleaseProc) {
22 fReleaseProc(fPtr, fSize, fReleaseProcContext);
23 }
24 }
25
equals(const SkData * other) const26 bool SkData::equals(const SkData* other) const {
27 if (NULL == other) {
28 return false;
29 }
30
31 return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
32 }
33
copyRange(size_t offset,size_t length,void * buffer) const34 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
35 size_t available = fSize;
36 if (offset >= available || 0 == length) {
37 return 0;
38 }
39 available -= offset;
40 if (length > available) {
41 length = available;
42 }
43 SkASSERT(length > 0);
44
45 memcpy(buffer, this->bytes() + offset, length);
46 return length;
47 }
48
49 ///////////////////////////////////////////////////////////////////////////////
50
NewEmpty()51 SkData* SkData::NewEmpty() {
52 static SkData* gEmptyRef;
53 if (NULL == gEmptyRef) {
54 gEmptyRef = new SkData(NULL, 0, NULL, NULL);
55 }
56 gEmptyRef->ref();
57 return gEmptyRef;
58 }
59
60 // assumes fPtr was allocated via sk_malloc
sk_free_releaseproc(const void * ptr,size_t,void *)61 static void sk_free_releaseproc(const void* ptr, size_t, void*) {
62 sk_free((void*)ptr);
63 }
64
NewFromMalloc(const void * data,size_t length)65 SkData* SkData::NewFromMalloc(const void* data, size_t length) {
66 return new SkData(data, length, sk_free_releaseproc, NULL);
67 }
68
NewWithCopy(const void * data,size_t length)69 SkData* SkData::NewWithCopy(const void* data, size_t length) {
70 if (0 == length) {
71 return SkData::NewEmpty();
72 }
73
74 void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
75 memcpy(copy, data, length);
76 return new SkData(copy, length, sk_free_releaseproc, NULL);
77 }
78
NewWithProc(const void * data,size_t length,ReleaseProc proc,void * context)79 SkData* SkData::NewWithProc(const void* data, size_t length,
80 ReleaseProc proc, void* context) {
81 return new SkData(data, length, proc, context);
82 }
83
84 // assumes context is a SkData
sk_dataref_releaseproc(const void *,size_t,void * context)85 static void sk_dataref_releaseproc(const void*, size_t, void* context) {
86 SkData* src = reinterpret_cast<SkData*>(context);
87 src->unref();
88 }
89
NewSubset(const SkData * src,size_t offset,size_t length)90 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
91 /*
92 We could, if we wanted/need to, just make a deep copy of src's data,
93 rather than referencing it. This would duplicate the storage (of the
94 subset amount) but would possibly allow src to go out of scope sooner.
95 */
96
97 size_t available = src->size();
98 if (offset >= available || 0 == length) {
99 return SkData::NewEmpty();
100 }
101 available -= offset;
102 if (length > available) {
103 length = available;
104 }
105 SkASSERT(length > 0);
106
107 src->ref(); // this will be balanced in sk_dataref_releaseproc
108 return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
109 const_cast<SkData*>(src));
110 }
111
NewWithCString(const char cstr[])112 SkData* SkData::NewWithCString(const char cstr[]) {
113 size_t size;
114 if (NULL == cstr) {
115 cstr = "";
116 size = 1;
117 } else {
118 size = strlen(cstr) + 1;
119 }
120 return NewWithCopy(cstr, size);
121 }
122
123 ///////////////////////////////////////////////////////////////////////////////
124
flatten(SkFlattenableWriteBuffer & buffer) const125 void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
126 buffer.writeByteArray(fPtr, fSize);
127 }
128
SkData(SkFlattenableReadBuffer & buffer)129 SkData::SkData(SkFlattenableReadBuffer& buffer) {
130 fSize = buffer.getArrayCount();
131 fReleaseProcContext = NULL;
132
133 if (fSize > 0) {
134 fPtr = sk_malloc_throw(fSize);
135 fReleaseProc = sk_free_releaseproc;
136 } else {
137 fPtr = NULL;
138 fReleaseProc = NULL;
139 }
140
141 buffer.readByteArray(const_cast<void*>(fPtr));
142 }
143
144 ///////////////////////////////////////////////////////////////////////////////
145 ///////////////////////////////////////////////////////////////////////////////
146
147 #include "SkDataSet.h"
148 #include "SkFlattenable.h"
149 #include "SkStream.h"
150
dupdata(SkData * data)151 static SkData* dupdata(SkData* data) {
152 if (data) {
153 data->ref();
154 } else {
155 data = SkData::NewEmpty();
156 }
157 return data;
158 }
159
findValue(const char key[],const SkDataSet::Pair array[],int n)160 static SkData* findValue(const char key[], const SkDataSet::Pair array[], int n) {
161 for (int i = 0; i < n; ++i) {
162 if (!strcmp(key, array[i].fKey)) {
163 return array[i].fValue;
164 }
165 }
166 return NULL;
167 }
168
allocatePairStorage(int count,size_t storage)169 static SkDataSet::Pair* allocatePairStorage(int count, size_t storage) {
170 size_t size = count * sizeof(SkDataSet::Pair) + storage;
171 return (SkDataSet::Pair*)sk_malloc_throw(size);
172 }
173
SkDataSet(const char key[],SkData * value)174 SkDataSet::SkDataSet(const char key[], SkData* value) {
175 size_t keyLen = strlen(key);
176
177 fCount = 1;
178 fKeySize = keyLen + 1;
179 fPairs = allocatePairStorage(1, keyLen + 1);
180
181 fPairs[0].fKey = (char*)(fPairs + 1);
182 memcpy(const_cast<char*>(fPairs[0].fKey), key, keyLen + 1);
183
184 fPairs[0].fValue = dupdata(value);
185 }
186
SkDataSet(const Pair array[],int count)187 SkDataSet::SkDataSet(const Pair array[], int count) {
188 if (count < 1) {
189 fCount = 0;
190 fKeySize = 0;
191 fPairs = NULL;
192 return;
193 }
194
195 int i;
196 size_t keySize = 0;
197 for (i = 0; i < count; ++i) {
198 keySize += strlen(array[i].fKey) + 1;
199 }
200
201 Pair* pairs = fPairs = allocatePairStorage(count, keySize);
202 char* keyStorage = (char*)(pairs + count);
203
204 keySize = 0; // reset this, so we can compute the size for unique keys
205 int uniqueCount = 0;
206 for (int i = 0; i < count; ++i) {
207 if (!findValue(array[i].fKey, pairs, uniqueCount)) {
208 size_t len = strlen(array[i].fKey);
209 memcpy(keyStorage, array[i].fKey, len + 1);
210 pairs[uniqueCount].fKey = keyStorage;
211 keyStorage += len + 1;
212 keySize += len + 1;
213
214 pairs[uniqueCount].fValue = dupdata(array[i].fValue);
215 uniqueCount += 1;
216 }
217 }
218 fCount = uniqueCount;
219 fKeySize = keySize;
220 }
221
~SkDataSet()222 SkDataSet::~SkDataSet() {
223 for (int i = 0; i < fCount; ++i) {
224 fPairs[i].fValue->unref();
225 }
226 sk_free(fPairs); // this also frees the key storage
227 }
228
find(const char key[]) const229 SkData* SkDataSet::find(const char key[]) const {
230 return findValue(key, fPairs, fCount);
231 }
232
writeToStream(SkWStream * stream) const233 void SkDataSet::writeToStream(SkWStream* stream) const {
234 stream->write32(fCount);
235 if (fCount > 0) {
236 stream->write32(fKeySize);
237 // our first key points to all the key storage
238 stream->write(fPairs[0].fKey, fKeySize);
239 for (int i = 0; i < fCount; ++i) {
240 stream->writeData(fPairs[i].fValue);
241 }
242 }
243 }
244
flatten(SkFlattenableWriteBuffer & buffer) const245 void SkDataSet::flatten(SkFlattenableWriteBuffer& buffer) const {
246 buffer.writeInt(fCount);
247 if (fCount > 0) {
248 buffer.writeByteArray(fPairs[0].fKey, fKeySize);
249 for (int i = 0; i < fCount; ++i) {
250 buffer.writeFlattenable(fPairs[i].fValue);
251 }
252 }
253 }
254
SkDataSet(SkStream * stream)255 SkDataSet::SkDataSet(SkStream* stream) {
256 fCount = stream->readU32();
257 if (fCount > 0) {
258 fKeySize = stream->readU32();
259 fPairs = allocatePairStorage(fCount, fKeySize);
260 char* keyStorage = (char*)(fPairs + fCount);
261
262 stream->read(keyStorage, fKeySize);
263
264 for (int i = 0; i < fCount; ++i) {
265 fPairs[i].fKey = keyStorage;
266 keyStorage += strlen(keyStorage) + 1;
267 fPairs[i].fValue = stream->readData();
268 }
269 } else {
270 fKeySize = 0;
271 fPairs = NULL;
272 }
273 }
274
SkDataSet(SkFlattenableReadBuffer & buffer)275 SkDataSet::SkDataSet(SkFlattenableReadBuffer& buffer) {
276 fCount = buffer.readInt();
277 if (fCount > 0) {
278 fKeySize = buffer.getArrayCount();
279 fPairs = allocatePairStorage(fCount, fKeySize);
280 char* keyStorage = (char*)(fPairs + fCount);
281
282 buffer.readByteArray(keyStorage);
283
284 for (int i = 0; i < fCount; ++i) {
285 fPairs[i].fKey = keyStorage;
286 keyStorage += strlen(keyStorage) + 1;
287 fPairs[i].fValue = buffer.readFlattenableT<SkData>();
288 }
289 } else {
290 fKeySize = 0;
291 fPairs = NULL;
292 }
293 }
294
NewEmpty()295 SkDataSet* SkDataSet::NewEmpty() {
296 static SkDataSet* gEmptySet;
297 if (NULL == gEmptySet) {
298 gEmptySet = SkNEW_ARGS(SkDataSet, (NULL, 0));
299 }
300 gEmptySet->ref();
301 return gEmptySet;
302 }
303