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" 129594da111dc1c36c1912eb61207aaa54c17ea550reed#include "SkStream.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 143a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1533a30503d76fdd989358cedd78445ba96bb809ddreedstatic void sk_inplace_sentinel_releaseproc(const void*, size_t, void*) { 1633a30503d76fdd989358cedd78445ba96bb809ddreed // we should never get called, as we are just a sentinel 1733a30503d76fdd989358cedd78445ba96bb809ddreed sk_throw(); 1833a30503d76fdd989358cedd78445ba96bb809ddreed} 1933a30503d76fdd989358cedd78445ba96bb809ddreed 203a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { 2133a30503d76fdd989358cedd78445ba96bb809ddreed fPtr = const_cast<void*>(ptr); 223a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fSize = size; 233a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc = proc; 243a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProcContext = context; 253a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 263a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 2733a30503d76fdd989358cedd78445ba96bb809ddreed// This constructor means we are inline with our fPtr's contents. Thus we set fPtr 2833a30503d76fdd989358cedd78445ba96bb809ddreed// to point right after this. We also set our releaseproc to sk_inplace_sentinel_releaseproc, 2933a30503d76fdd989358cedd78445ba96bb809ddreed// since we need to handle "delete" ourselves. See internal_displose(). 3033a30503d76fdd989358cedd78445ba96bb809ddreed// 3133a30503d76fdd989358cedd78445ba96bb809ddreedSkData::SkData(size_t size) { 3233a30503d76fdd989358cedd78445ba96bb809ddreed fPtr = (char*)(this + 1); // contents are immediately after this 3333a30503d76fdd989358cedd78445ba96bb809ddreed fSize = size; 3433a30503d76fdd989358cedd78445ba96bb809ddreed fReleaseProc = sk_inplace_sentinel_releaseproc; 3533a30503d76fdd989358cedd78445ba96bb809ddreed fReleaseProcContext = NULL; 3633a30503d76fdd989358cedd78445ba96bb809ddreed} 3733a30503d76fdd989358cedd78445ba96bb809ddreed 383a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::~SkData() { 393a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (fReleaseProc) { 403a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc(fPtr, fSize, fReleaseProcContext); 413a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 423a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 433a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 4433a30503d76fdd989358cedd78445ba96bb809ddreedvoid SkData::internal_dispose() const { 4533a30503d76fdd989358cedd78445ba96bb809ddreed if (sk_inplace_sentinel_releaseproc == fReleaseProc) { 4633a30503d76fdd989358cedd78445ba96bb809ddreed const_cast<SkData*>(this)->fReleaseProc = NULL; // so we don't call it in our destructor 4733a30503d76fdd989358cedd78445ba96bb809ddreed 4833a30503d76fdd989358cedd78445ba96bb809ddreed this->internal_dispose_restore_refcnt_to_1(); 4933a30503d76fdd989358cedd78445ba96bb809ddreed this->~SkData(); // explicitly call this for refcnt bookkeeping 5033a30503d76fdd989358cedd78445ba96bb809ddreed 5133a30503d76fdd989358cedd78445ba96bb809ddreed sk_free(const_cast<SkData*>(this)); 5233a30503d76fdd989358cedd78445ba96bb809ddreed } else { 5333a30503d76fdd989358cedd78445ba96bb809ddreed this->internal_dispose_restore_refcnt_to_1(); 5433a30503d76fdd989358cedd78445ba96bb809ddreed SkDELETE(this); 5533a30503d76fdd989358cedd78445ba96bb809ddreed } 5633a30503d76fdd989358cedd78445ba96bb809ddreed} 5733a30503d76fdd989358cedd78445ba96bb809ddreed 58dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.combool SkData::equals(const SkData* other) const { 59dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com if (NULL == other) { 60dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return false; 61dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 62dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 63dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); 64dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 65dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 663a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comsize_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { 673a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = fSize; 683a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 693a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return 0; 703a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 713a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 723a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 733a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 743a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 753a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 763a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 773a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com memcpy(buffer, this->bytes() + offset, length); 783a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return length; 793a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 803a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 8133a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) { 8233a30503d76fdd989358cedd78445ba96bb809ddreed if (0 == length) { 8333a30503d76fdd989358cedd78445ba96bb809ddreed return SkData::NewEmpty(); 8433a30503d76fdd989358cedd78445ba96bb809ddreed } 8533a30503d76fdd989358cedd78445ba96bb809ddreed char* storage = (char*)sk_malloc_throw(sizeof(SkData) + length); 8633a30503d76fdd989358cedd78445ba96bb809ddreed SkData* data = new (storage) SkData(length); 8733a30503d76fdd989358cedd78445ba96bb809ddreed if (srcOrNull) { 8833a30503d76fdd989358cedd78445ba96bb809ddreed memcpy(data->writable_data(), srcOrNull, length); 8933a30503d76fdd989358cedd78445ba96bb809ddreed } 9033a30503d76fdd989358cedd78445ba96bb809ddreed return data; 9133a30503d76fdd989358cedd78445ba96bb809ddreed} 9233a30503d76fdd989358cedd78445ba96bb809ddreed 933a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com/////////////////////////////////////////////////////////////////////////////// 943a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 9597de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgSkData* SkData::NewEmptyImpl() { 9697de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org return new SkData(NULL, 0, NULL, NULL); 971f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org} 9833a30503d76fdd989358cedd78445ba96bb809ddreed 9997de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgvoid SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); } 1001f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org 1013a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewEmpty() { 10297de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org SK_DECLARE_STATIC_LAZY_PTR(SkData, empty, NewEmptyImpl, DeleteEmpty); 10397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org return SkRef(empty.get()); 1043a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1053a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1063a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com// assumes fPtr was allocated via sk_malloc 1078a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comstatic void sk_free_releaseproc(const void* ptr, size_t, void*) { 1083a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com sk_free((void*)ptr); 1093a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1103a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1118a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkData::NewFromMalloc(const void* data, size_t length) { 1128a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com return new SkData(data, length, sk_free_releaseproc, NULL); 1138a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com} 1148a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com 11533a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::NewWithCopy(const void* src, size_t length) { 11633a30503d76fdd989358cedd78445ba96bb809ddreed SkASSERT(src); 11733a30503d76fdd989358cedd78445ba96bb809ddreed return PrivateNewWithCopy(src, length); 11833a30503d76fdd989358cedd78445ba96bb809ddreed} 1193a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 12033a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::NewUninitialized(size_t length) { 12133a30503d76fdd989358cedd78445ba96bb809ddreed return PrivateNewWithCopy(NULL, length); 1223a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1233a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1243a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewWithProc(const void* data, size_t length, 1258a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com ReleaseProc proc, void* context) { 1263a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(data, length, proc, context); 1273a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1283a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1296cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes fPtr was allocated with sk_fmmap 1306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_mmap_releaseproc(const void* addr, size_t length, void*) { 1316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com sk_fmunmap(addr, length); 1329711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1339711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1349711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.orgSkData* SkData::NewFromFILE(SkFILE* f) { 1356cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t size; 1366cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = sk_fmmap(f, &size); 1379711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org if (NULL == addr) { 1389711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org return NULL; 1399711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org } 1409711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 14111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 14211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 14311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 144792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.orgSkData* SkData::NewFromFileName(const char path[]) { 145792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL; 146792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org if (NULL == f) { 147792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return NULL; 148792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org } 149792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkData* data = NewFromFILE(f); 150792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org sk_fclose(f); 151792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return data; 152792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org} 153792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org 15411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comSkData* SkData::NewFromFD(int fd) { 15511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com size_t size; 15611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com void* addr = sk_fdmmap(fd, &size); 15711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (NULL == addr) { 15811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 15911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 16011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 1616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 1629711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1639711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1646cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes context is a SkData 1656cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_dataref_releaseproc(const void*, size_t, void* context) { 1666cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkData* src = reinterpret_cast<SkData*>(context); 1676cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com src->unref(); 1689711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1699711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1703a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { 1713a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com /* 1723a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com We could, if we wanted/need to, just make a deep copy of src's data, 1733a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com rather than referencing it. This would duplicate the storage (of the 1743a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com subset amount) but would possibly allow src to go out of scope sooner. 1753a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */ 1763a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1773a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = src->size(); 1783a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 1793a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return SkData::NewEmpty(); 1803a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1813a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 1823a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 1833a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 1843a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1853a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 1863a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1873a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com src->ref(); // this will be balanced in sk_dataref_releaseproc 1883a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, 1893a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com const_cast<SkData*>(src)); 1903a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1913a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 192dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.comSkData* SkData::NewWithCString(const char cstr[]) { 193fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size_t size; 194fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com if (NULL == cstr) { 195fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com cstr = ""; 196fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = 1; 197dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } else { 198fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = strlen(cstr) + 1; 199dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 200fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com return NewWithCopy(cstr, size); 201dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 2029594da111dc1c36c1912eb61207aaa54c17ea550reed 2039594da111dc1c36c1912eb61207aaa54c17ea550reed/////////////////////////////////////////////////////////////////////////////// 2049594da111dc1c36c1912eb61207aaa54c17ea550reed 2059594da111dc1c36c1912eb61207aaa54c17ea550reedSkData* SkData::NewFromStream(SkStream* stream, size_t size) { 2069594da111dc1c36c1912eb61207aaa54c17ea550reed SkAutoDataUnref data(SkData::NewUninitialized(size)); 2079594da111dc1c36c1912eb61207aaa54c17ea550reed if (stream->read(data->writable_data(), size) != size) { 2089594da111dc1c36c1912eb61207aaa54c17ea550reed return NULL; 2099594da111dc1c36c1912eb61207aaa54c17ea550reed } 2109594da111dc1c36c1912eb61207aaa54c17ea550reed return data.detach(); 2119594da111dc1c36c1912eb61207aaa54c17ea550reed} 2129594da111dc1c36c1912eb61207aaa54c17ea550reed 213