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