2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h"
15 static void sk_inplace_sentinel_releaseproc(const void*, size_t, void*) {
16 // we should never get called, as we are just a sentinel
20 SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
21 fPtr = const_cast<void*>(ptr);
24 fReleaseProcContext = context;
27 // This constructor means we are inline with our fPtr's contents. Thus we set fPtr
28 // to point right after this. We also set our releaseproc to sk_inplace_sentinel_releaseproc,
29 // since we need to handle "delete" ourselves. See internal_displose().
31 SkData::SkData(size_t size) {
32 fPtr = (char*)(this + 1); // contents are immediately after this
34 fReleaseProc = sk_inplace_sentinel_releaseproc;
35 fReleaseProcContext = NULL;
40 fReleaseProc(fPtr, fSize, fReleaseProcContext);
44 void SkData::internal_dispose() const {
45 if (sk_inplace_sentinel_releaseproc == fReleaseProc) {
46 const_cast<SkData*>(this)->fReleaseProc = NULL; // so we don't call it in our destructor
48 this->internal_dispose_restore_refcnt_to_1();
49 this->~SkData(); // explicitly call this for refcnt bookkeeping
51 sk_free(const_cast<SkData*>(this));
53 this->internal_dispose_restore_refcnt_to_1();
58 bool SkData::equals(const SkData* other) const {
63 return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
66 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
67 size_t available = fSize;
68 if (offset >= available || 0 == length) {
72 if (length > available) {
77 memcpy(buffer, this->bytes() + offset, length);
81 SkData* SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
83 return SkData::NewEmpty();
85 char* storage = (char*)sk_malloc_throw(sizeof(SkData) + length);
86 SkData* data = new (storage) SkData(length);
88 memcpy(data->writable_data(), srcOrNull, length);
93 ///////////////////////////////////////////////////////////////////////////////
95 SkData* SkData::NewEmptyImpl() {
96 return new SkData(NULL, 0, NULL, NULL);
99 void SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); }
101 SkData* SkData::NewEmpty() {
102 SK_DECLARE_STATIC_LAZY_PTR(SkData, empty, NewEmptyImpl, DeleteEmpty);
103 return SkRef(empty.get());
106 // assumes fPtr was allocated via sk_malloc
107 static void sk_free_releaseproc(const void* ptr, size_t, void*) {
111 SkData* SkData::NewFromMalloc(const void* data, size_t length) {
112 return new SkData(data, length, sk_free_releaseproc, NULL);
115 SkData* SkData::NewWithCopy(const void* src, size_t length) {
117 return PrivateNewWithCopy(src, length);
120 SkData* SkData::NewUninitialized(size_t length) {
121 return PrivateNewWithCopy(NULL, length);
124 SkData* SkData::NewWithProc(const void* data, size_t length,
125 ReleaseProc proc, void* context) {
126 return new SkData(data, length, proc, context);
129 // assumes fPtr was allocated with sk_fmmap
130 static void sk_mmap_releaseproc(const void* addr, size_t length, void*) {
131 sk_fmunmap(addr, length);
134 SkData* SkData::NewFromFILE(SkFILE* f) {
136 void* addr = sk_fmmap(f, &size);
141 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
144 SkData* SkData::NewFromFileName(const char path[]) {
145 SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL;
149 SkData* data = NewFromFILE(f);
154 SkData* SkData::NewFromFD(int fd) {
156 void* addr = sk_fdmmap(fd, &size);
161 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL);
164 // assumes context is a SkData
165 static void sk_dataref_releaseproc(const void*, size_t, void* context) {
166 SkData* src = reinterpret_cast<SkData*>(context);
170 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
172 We could, if we wanted/need to, just make a deep copy of src's data,
173 rather than referencing it. This would duplicate the storage (of the
174 subset amount) but would possibly allow src to go out of scope sooner.
177 size_t available = src->size();
178 if (offset >= available || 0 == length) {
179 return SkData::NewEmpty();
182 if (length > available) {
185 SkASSERT(length > 0);
187 src->ref(); // this will be balanced in sk_dataref_releaseproc
188 return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
189 const_cast<SkData*>(src));
192 SkData* SkData::NewWithCString(const char cstr[]) {
198 size = strlen(cstr) + 1;
200 return NewWithCopy(cstr, size);
203 ///////////////////////////////////////////////////////////////////////////////
205 SkData* SkData::NewFromStream(SkStream* stream, size_t size) {
206 SkAutoDataUnref data(SkData::NewUninitialized(size));
207 if (stream->read(data->writable_data(), size) != size) {
210 return data.detach();