Index: src/core/SkData.cpp |
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp |
index c65328720a789051e49be9d41d4a0a6866a022fc..6e99ba6f166dbadaf634140b1bc57f208821ca09 100644 |
--- a/src/core/SkData.cpp |
+++ b/src/core/SkData.cpp |
@@ -11,6 +11,12 @@ |
#include "SkReadBuffer.h" |
#include "SkWriteBuffer.h" |
+// Sentinel for when the SkData is inplace new contiguous with its contents. Don't call! |
+// |
+static void sk_inplace_sentinel_releaseproc(const void*, size_t, void*) { |
+ sk_throw(); |
+} |
+ |
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { |
fPtr = ptr; |
fSize = size; |
@@ -18,12 +24,37 @@ SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { |
fReleaseProcContext = context; |
} |
+// This constructor means we are inline with our fPtr's contents. Thus we set fPtr |
+// to point right after this. We also set our releaseproc to gInplaceReleaseProc, as a sentinel |
bungeman-skia
2014/09/11 15:17:16
update comment from gInplaceReleaseProc?
reed1
2014/09/11 15:28:02
Done.
|
+// that we need to handle "delete" ourselves. See internal_displose(). |
+// |
+SkData::SkData(size_t size) { |
+ fPtr = (char*)(this + 1); // contents are immediately after this |
+ fSize = size; |
+ fReleaseProc = sk_inplace_sentinel_releaseproc; |
+ fReleaseProcContext = NULL; |
+} |
+ |
SkData::~SkData() { |
if (fReleaseProc) { |
fReleaseProc(fPtr, fSize, fReleaseProcContext); |
} |
} |
+void SkData::internal_dispose() const { |
+ if (sk_inplace_sentinel_releaseproc == fReleaseProc) { |
+ const_cast<SkData*>(this)->fReleaseProc = NULL; // so we don't call it in our destructor |
+ |
+ this->internal_dispose_restore_refcnt_to_1(); |
+ this->~SkData(); // explicitly call this for refcnt bookkeeping |
+ |
+ sk_free(const_cast<SkData*>(this)); |
+ } else { |
+ this->internal_dispose_restore_refcnt_to_1(); |
+ SkDELETE(this); |
+ } |
+} |
+ |
bool SkData::equals(const SkData* other) const { |
if (NULL == other) { |
return false; |
@@ -47,11 +78,24 @@ size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { |
return length; |
} |
+SkData* SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) { |
+ if (0 == length) { |
+ return SkData::NewEmpty(); |
+ } |
+ char* storage = (char*)sk_malloc_throw(sizeof(SkData) + length); |
+ SkData* data = new (storage) SkData(length); |
+ if (srcOrNull) { |
+ memcpy(data->writable_data(), srcOrNull, length); |
+ } |
+ return data; |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
SkData* SkData::NewEmptyImpl() { |
return new SkData(NULL, 0, NULL, NULL); |
} |
+ |
void SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); } |
SkData* SkData::NewEmpty() { |
@@ -68,14 +112,13 @@ 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(); |
- } |
+SkData* SkData::NewWithCopy(const void* src, size_t length) { |
+ SkASSERT(src); |
+ return PrivateNewWithCopy(src, length); |
+} |
- 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::NewUninitialized(size_t length) { |
+ return PrivateNewWithCopy(NULL, length); |
} |
SkData* SkData::NewWithProc(const void* data, size_t length, |