| |
| /* |
| * 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 "SkData.h" |
| |
| SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { |
| fPtr = ptr; |
| fSize = size; |
| fReleaseProc = proc; |
| fReleaseProcContext = context; |
| } |
| |
| SkData::~SkData() { |
| if (fReleaseProc) { |
| fReleaseProc(fPtr, fSize, fReleaseProcContext); |
| } |
| } |
| |
| 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; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| SkData* SkData::NewEmpty() { |
| static SkData* gEmptyRef; |
| if (NULL == gEmptyRef) { |
| gEmptyRef = new SkData(NULL, 0, NULL, NULL); |
| } |
| gEmptyRef->ref(); |
| return gEmptyRef; |
| } |
| |
| // assumes fPtr was allocated via sk_malloc |
| static void sk_free_releaseproc(const void* ptr, size_t, void*) { |
| sk_free((void*)ptr); |
| } |
| |
| SkData* SkData::NewFromMalloc(const void* data, size_t length) { |
| return new SkData(data, length, sk_free_releaseproc, NULL); |
| } |
| |
| SkData* SkData::NewWithCopy(const void* data, size_t length) { |
| if (0 == length) { |
| return SkData::NewEmpty(); |
| } |
| |
| void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc |
| memcpy(copy, data, length); |
| return new SkData(copy, length, sk_free_releaseproc, NULL); |
| } |
| |
| SkData* SkData::NewWithProc(const void* data, size_t length, |
| ReleaseProc proc, void* context) { |
| return new SkData(data, length, proc, context); |
| } |
| |
| // assumes context is a SkData |
| static void sk_dataref_releaseproc(const void*, size_t, void* context) { |
| SkData* src = reinterpret_cast<SkData*>(context); |
| src->unref(); |
| } |
| |
| SkData* SkData::NewSubset(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::NewEmpty(); |
| } |
| available -= offset; |
| if (length > available) { |
| length = available; |
| } |
| SkASSERT(length > 0); |
| |
| src->ref(); // this will be balanced in sk_dataref_releaseproc |
| return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, |
| const_cast<SkData*>(src)); |
| } |
| |