123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkData.h"
- #include "include/core/SkStream.h"
- #include "include/private/SkOnce.h"
- #include "src/core/SkOSFile.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkWriteBuffer.h"
- #include <new>
- SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
- fPtr = const_cast<void*>(ptr);
- fSize = size;
- fReleaseProc = proc;
- fReleaseProcContext = context;
- }
- /** This constructor means we are inline with our fPtr's contents.
- * Thus we set fPtr to point right after this.
- */
- SkData::SkData(size_t size) {
- fPtr = (char*)(this + 1); // contents are immediately after this
- fSize = size;
- fReleaseProc = nullptr;
- fReleaseProcContext = nullptr;
- }
- SkData::~SkData() {
- if (fReleaseProc) {
- fReleaseProc(fPtr, fReleaseProcContext);
- }
- }
- bool SkData::equals(const SkData* other) const {
- if (nullptr == other) {
- return false;
- }
- return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
- }
- size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
- size_t available = fSize;
- if (offset >= available || 0 == length) {
- return 0;
- }
- available -= offset;
- if (length > available) {
- length = available;
- }
- SkASSERT(length > 0);
- memcpy(buffer, this->bytes() + offset, length);
- return length;
- }
- void SkData::operator delete(void* p) {
- ::operator delete(p);
- }
- sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
- if (0 == length) {
- return SkData::MakeEmpty();
- }
- const size_t actualLength = length + sizeof(SkData);
- SkASSERT_RELEASE(length < actualLength); // Check for overflow.
- void* storage = ::operator new (actualLength);
- sk_sp<SkData> data(new (storage) SkData(length));
- if (srcOrNull) {
- memcpy(data->writable_data(), srcOrNull, length);
- }
- return data;
- }
- void SkData::DummyReleaseProc(const void*, void*) {}
- ///////////////////////////////////////////////////////////////////////////////
- sk_sp<SkData> SkData::MakeEmpty() {
- static SkOnce once;
- static SkData* empty;
- once([]{ empty = new SkData(nullptr, 0, nullptr, nullptr); });
- return sk_ref_sp(empty);
- }
- // assumes fPtr was allocated via sk_malloc
- static void sk_free_releaseproc(const void* ptr, void*) {
- sk_free((void*)ptr);
- }
- sk_sp<SkData> SkData::MakeFromMalloc(const void* data, size_t length) {
- return sk_sp<SkData>(new SkData(data, length, sk_free_releaseproc, nullptr));
- }
- sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
- SkASSERT(src);
- return PrivateNewWithCopy(src, length);
- }
- sk_sp<SkData> SkData::MakeUninitialized(size_t length) {
- return PrivateNewWithCopy(nullptr, length);
- }
- sk_sp<SkData> SkData::MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx) {
- return sk_sp<SkData>(new SkData(ptr, length, proc, ctx));
- }
- // assumes fPtr was allocated with sk_fmmap
- static void sk_mmap_releaseproc(const void* addr, void* ctx) {
- size_t length = reinterpret_cast<size_t>(ctx);
- sk_fmunmap(addr, length);
- }
- sk_sp<SkData> SkData::MakeFromFILE(FILE* f) {
- size_t size;
- void* addr = sk_fmmap(f, &size);
- if (nullptr == addr) {
- return nullptr;
- }
- return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
- }
- sk_sp<SkData> SkData::MakeFromFileName(const char path[]) {
- FILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr;
- if (nullptr == f) {
- return nullptr;
- }
- auto data = MakeFromFILE(f);
- sk_fclose(f);
- return data;
- }
- sk_sp<SkData> SkData::MakeFromFD(int fd) {
- size_t size;
- void* addr = sk_fdmmap(fd, &size);
- if (nullptr == addr) {
- return nullptr;
- }
- return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
- }
- // assumes context is a SkData
- static void sk_dataref_releaseproc(const void*, void* context) {
- SkData* src = reinterpret_cast<SkData*>(context);
- src->unref();
- }
- sk_sp<SkData> SkData::MakeSubset(const SkData* src, size_t offset, size_t length) {
- /*
- We could, if we wanted/need to, just make a deep copy of src's data,
- rather than referencing it. This would duplicate the storage (of the
- subset amount) but would possibly allow src to go out of scope sooner.
- */
- size_t available = src->size();
- if (offset >= available || 0 == length) {
- return SkData::MakeEmpty();
- }
- available -= offset;
- if (length > available) {
- length = available;
- }
- SkASSERT(length > 0);
- src->ref(); // this will be balanced in sk_dataref_releaseproc
- return sk_sp<SkData>(new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
- const_cast<SkData*>(src)));
- }
- sk_sp<SkData> SkData::MakeWithCString(const char cstr[]) {
- size_t size;
- if (nullptr == cstr) {
- cstr = "";
- size = 1;
- } else {
- size = strlen(cstr) + 1;
- }
- return MakeWithCopy(cstr, size);
- }
- ///////////////////////////////////////////////////////////////////////////////
- sk_sp<SkData> SkData::MakeFromStream(SkStream* stream, size_t size) {
- sk_sp<SkData> data(SkData::MakeUninitialized(size));
- if (stream->read(data->writable_data(), size) != size) {
- return nullptr;
- }
- return data;
- }
|