1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 63a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */ 73a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 83a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com#include "SkData.h" 997de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org#include "SkLazyPtr.h" 1097de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org#include "SkOSFile.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 133a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 143a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { 153a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fPtr = ptr; 163a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fSize = size; 173a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc = proc; 183a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProcContext = context; 193a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 203a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 213a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::~SkData() { 223a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (fReleaseProc) { 233a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc(fPtr, fSize, fReleaseProcContext); 243a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 253a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 263a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 27dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.combool SkData::equals(const SkData* other) const { 28dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com if (NULL == other) { 29dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return false; 30dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 31dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 32dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); 33dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 34dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 353a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comsize_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { 363a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = fSize; 373a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 383a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return 0; 393a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 403a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 413a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 423a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 433a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 443a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 453a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 463a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com memcpy(buffer, this->bytes() + offset, length); 473a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return length; 483a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 493a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 503a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com/////////////////////////////////////////////////////////////////////////////// 513a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 5297de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgSkData* SkData::NewEmptyImpl() { 5397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org return new SkData(NULL, 0, NULL, NULL); 541f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org} 5597de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgvoid SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); } 561f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org 573a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewEmpty() { 5897de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org SK_DECLARE_STATIC_LAZY_PTR(SkData, empty, NewEmptyImpl, DeleteEmpty); 5997de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org return SkRef(empty.get()); 603a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 613a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 623a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com// assumes fPtr was allocated via sk_malloc 638a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comstatic void sk_free_releaseproc(const void* ptr, size_t, void*) { 643a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com sk_free((void*)ptr); 653a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 663a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 678a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkData::NewFromMalloc(const void* data, size_t length) { 688a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com return new SkData(data, length, sk_free_releaseproc, NULL); 698a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com} 708a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com 713a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewWithCopy(const void* data, size_t length) { 723a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (0 == length) { 733a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return SkData::NewEmpty(); 743a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 753a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 768a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc 773a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com memcpy(copy, data, length); 788a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com return new SkData(copy, length, sk_free_releaseproc, NULL); 793a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 803a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 813a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewWithProc(const void* data, size_t length, 828a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com ReleaseProc proc, void* context) { 833a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(data, length, proc, context); 843a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 853a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 866cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes fPtr was allocated with sk_fmmap 876cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_mmap_releaseproc(const void* addr, size_t length, void*) { 886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com sk_fmunmap(addr, length); 899711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 909711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 919711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.orgSkData* SkData::NewFromFILE(SkFILE* f) { 926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t size; 936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = sk_fmmap(f, &size); 949711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org if (NULL == addr) { 959711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org return NULL; 969711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org } 979711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 9811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 9911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 10011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 101792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.orgSkData* SkData::NewFromFileName(const char path[]) { 102792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL; 103792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org if (NULL == f) { 104792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return NULL; 105792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org } 106792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkData* data = NewFromFILE(f); 107792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org sk_fclose(f); 108792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return data; 109792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org} 110792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org 11111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comSkData* SkData::NewFromFD(int fd) { 11211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com size_t size; 11311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com void* addr = sk_fdmmap(fd, &size); 11411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (NULL == addr) { 11511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 11611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 11711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 1186cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 1199711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1209711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1216cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes context is a SkData 1226cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_dataref_releaseproc(const void*, size_t, void* context) { 1236cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkData* src = reinterpret_cast<SkData*>(context); 1246cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com src->unref(); 1259711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1269711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1273a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { 1283a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com /* 1293a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com We could, if we wanted/need to, just make a deep copy of src's data, 1303a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com rather than referencing it. This would duplicate the storage (of the 1313a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com subset amount) but would possibly allow src to go out of scope sooner. 1323a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */ 1333a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1343a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = src->size(); 1353a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 1363a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return SkData::NewEmpty(); 1373a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1383a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 1393a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 1403a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 1413a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1423a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 1433a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1443a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com src->ref(); // this will be balanced in sk_dataref_releaseproc 1453a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, 1463a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com const_cast<SkData*>(src)); 1473a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1483a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 149dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.comSkData* SkData::NewWithCString(const char cstr[]) { 150fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size_t size; 151fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com if (NULL == cstr) { 152fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com cstr = ""; 153fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = 1; 154dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } else { 155fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = strlen(cstr) + 1; 156dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 157fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com return NewWithCopy(cstr, size); 158dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 159