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 153a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { 1633a30503d76fdd989358cedd78445ba96bb809ddreed fPtr = const_cast<void*>(ptr); 173a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fSize = size; 183a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc = proc; 193a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProcContext = context; 203a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 213a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 2233a30503d76fdd989358cedd78445ba96bb809ddreed// This constructor means we are inline with our fPtr's contents. Thus we set fPtr 2333a30503d76fdd989358cedd78445ba96bb809ddreed// to point right after this. We also set our releaseproc to sk_inplace_sentinel_releaseproc, 2433a30503d76fdd989358cedd78445ba96bb809ddreed// since we need to handle "delete" ourselves. See internal_displose(). 2533a30503d76fdd989358cedd78445ba96bb809ddreed// 2633a30503d76fdd989358cedd78445ba96bb809ddreedSkData::SkData(size_t size) { 2733a30503d76fdd989358cedd78445ba96bb809ddreed fPtr = (char*)(this + 1); // contents are immediately after this 2833a30503d76fdd989358cedd78445ba96bb809ddreed fSize = size; 29072803144a623f1a59eb73ca5f3ddf45222b5e06bsalomon fReleaseProc = NULL; 3033a30503d76fdd989358cedd78445ba96bb809ddreed fReleaseProcContext = NULL; 3133a30503d76fdd989358cedd78445ba96bb809ddreed} 3233a30503d76fdd989358cedd78445ba96bb809ddreed 333a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData::~SkData() { 343a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (fReleaseProc) { 353a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com fReleaseProc(fPtr, fSize, fReleaseProcContext); 363a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 373a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 383a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 39dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.combool SkData::equals(const SkData* other) const { 40dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com if (NULL == other) { 41dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return false; 42dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 43dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 44dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); 45dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 46dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com 473a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comsize_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { 483a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = fSize; 493a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 503a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return 0; 513a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 523a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 533a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 543a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 553a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 563a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 573a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 583a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com memcpy(buffer, this->bytes() + offset, length); 593a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return length; 603a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 613a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 6233a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) { 6333a30503d76fdd989358cedd78445ba96bb809ddreed if (0 == length) { 6433a30503d76fdd989358cedd78445ba96bb809ddreed return SkData::NewEmpty(); 6533a30503d76fdd989358cedd78445ba96bb809ddreed } 6633a30503d76fdd989358cedd78445ba96bb809ddreed char* storage = (char*)sk_malloc_throw(sizeof(SkData) + length); 6733a30503d76fdd989358cedd78445ba96bb809ddreed SkData* data = new (storage) SkData(length); 6833a30503d76fdd989358cedd78445ba96bb809ddreed if (srcOrNull) { 6933a30503d76fdd989358cedd78445ba96bb809ddreed memcpy(data->writable_data(), srcOrNull, length); 7033a30503d76fdd989358cedd78445ba96bb809ddreed } 7133a30503d76fdd989358cedd78445ba96bb809ddreed return data; 7233a30503d76fdd989358cedd78445ba96bb809ddreed} 7333a30503d76fdd989358cedd78445ba96bb809ddreed 743a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com/////////////////////////////////////////////////////////////////////////////// 753a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 76148ec59001ca7d7e54aec580a048c6dd2a085991mtklein// As a template argument these must have external linkage. 77148ec59001ca7d7e54aec580a048c6dd2a085991mtkleinSkData* sk_new_empty_data() { return new SkData(NULL, 0, NULL, NULL); } 78148ec59001ca7d7e54aec580a048c6dd2a085991mtkleinnamespace { void sk_unref_data(SkData* ptr) { return SkSafeUnref(ptr); } } 7933a30503d76fdd989358cedd78445ba96bb809ddreed 80148ec59001ca7d7e54aec580a048c6dd2a085991mtkleinSK_DECLARE_STATIC_LAZY_PTR(SkData, empty, sk_new_empty_data, sk_unref_data); 811f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org 823a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewEmpty() { 8397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org return SkRef(empty.get()); 843a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 853a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 863a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com// assumes fPtr was allocated via sk_malloc 878a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comstatic void sk_free_releaseproc(const void* ptr, size_t, void*) { 883a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com sk_free((void*)ptr); 893a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 903a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 918a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkData::NewFromMalloc(const void* data, size_t length) { 928a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com return new SkData(data, length, sk_free_releaseproc, NULL); 938a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com} 948a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com 9533a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::NewWithCopy(const void* src, size_t length) { 9633a30503d76fdd989358cedd78445ba96bb809ddreed SkASSERT(src); 9733a30503d76fdd989358cedd78445ba96bb809ddreed return PrivateNewWithCopy(src, length); 9833a30503d76fdd989358cedd78445ba96bb809ddreed} 993a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 10033a30503d76fdd989358cedd78445ba96bb809ddreedSkData* SkData::NewUninitialized(size_t length) { 10133a30503d76fdd989358cedd78445ba96bb809ddreed return PrivateNewWithCopy(NULL, length); 1023a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1033a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1043a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewWithProc(const void* data, size_t length, 1058a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com ReleaseProc proc, void* context) { 1063a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(data, length, proc, context); 1073a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1083a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1096cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes fPtr was allocated with sk_fmmap 1106cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_mmap_releaseproc(const void* addr, size_t length, void*) { 1116cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com sk_fmunmap(addr, length); 1129711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1139711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1149711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.orgSkData* SkData::NewFromFILE(SkFILE* f) { 1156cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com size_t size; 1166cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com void* addr = sk_fmmap(f, &size); 1179711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org if (NULL == addr) { 1189711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org return NULL; 1199711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org } 1209711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 12111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 12211c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com} 12311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 124792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.orgSkData* SkData::NewFromFileName(const char path[]) { 125792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL; 126792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org if (NULL == f) { 127792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return NULL; 128792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org } 129792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org SkData* data = NewFromFILE(f); 130792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org sk_fclose(f); 131792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org return data; 132792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org} 133792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org 13411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.comSkData* SkData::NewFromFD(int fd) { 13511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com size_t size; 13611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com void* addr = sk_fdmmap(fd, &size); 13711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com if (NULL == addr) { 13811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com return NULL; 13911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com } 14011c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com 1416cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 1429711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1439711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1446cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com// assumes context is a SkData 1456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comstatic void sk_dataref_releaseproc(const void*, size_t, void* context) { 1466cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com SkData* src = reinterpret_cast<SkData*>(context); 1476cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com src->unref(); 1489711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org} 1499711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org 1503a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comSkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { 1513a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com /* 1523a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com We could, if we wanted/need to, just make a deep copy of src's data, 1533a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com rather than referencing it. This would duplicate the storage (of the 1543a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com subset amount) but would possibly allow src to go out of scope sooner. 1553a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */ 1563a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1573a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com size_t available = src->size(); 1583a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (offset >= available || 0 == length) { 1593a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return SkData::NewEmpty(); 1603a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1613a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com available -= offset; 1623a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com if (length > available) { 1633a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com length = available; 1643a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com } 1653a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com SkASSERT(length > 0); 1663a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 1673a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com src->ref(); // this will be balanced in sk_dataref_releaseproc 1683a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, 1693a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com const_cast<SkData*>(src)); 1703a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com} 1713a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com 172dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.comSkData* SkData::NewWithCString(const char cstr[]) { 173fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size_t size; 174fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com if (NULL == cstr) { 175fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com cstr = ""; 176fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = 1; 177dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } else { 178fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com size = strlen(cstr) + 1; 179dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com } 180fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com return NewWithCopy(cstr, size); 181dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com} 1829594da111dc1c36c1912eb61207aaa54c17ea550reed 1839594da111dc1c36c1912eb61207aaa54c17ea550reed/////////////////////////////////////////////////////////////////////////////// 1849594da111dc1c36c1912eb61207aaa54c17ea550reed 1859594da111dc1c36c1912eb61207aaa54c17ea550reedSkData* SkData::NewFromStream(SkStream* stream, size_t size) { 1869594da111dc1c36c1912eb61207aaa54c17ea550reed SkAutoDataUnref data(SkData::NewUninitialized(size)); 1879594da111dc1c36c1912eb61207aaa54c17ea550reed if (stream->read(data->writable_data(), size) != size) { 1889594da111dc1c36c1912eb61207aaa54c17ea550reed return NULL; 1899594da111dc1c36c1912eb61207aaa54c17ea550reed } 1909594da111dc1c36c1912eb61207aaa54c17ea550reed return data.detach(); 1919594da111dc1c36c1912eb61207aaa54c17ea550reed} 1929594da111dc1c36c1912eb61207aaa54c17ea550reed 193