• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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