blob: 791e858d3e679e5fd4f689b395d4221dab2840ad [file] [log] [blame]
reed@google.com3a31ac12011-06-24 13:11:05 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "SkData.h"
19
20SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
21 fPtr = ptr;
22 fSize = size;
23 fReleaseProc = proc;
24 fReleaseProcContext = context;
25}
26
27SkData::~SkData() {
28 if (fReleaseProc) {
29 fReleaseProc(fPtr, fSize, fReleaseProcContext);
30 }
31}
32
33size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
34 size_t available = fSize;
35 if (offset >= available || 0 == length) {
36 return 0;
37 }
38 available -= offset;
39 if (length > available) {
40 length = available;
41 }
42 SkASSERT(length > 0);
43
44 memcpy(buffer, this->bytes() + offset, length);
45 return length;
46}
47
48///////////////////////////////////////////////////////////////////////////////
49
50SkData* SkData::NewEmpty() {
51 static SkData* gEmptyRef;
52 if (NULL == gEmptyRef) {
53 gEmptyRef = new SkData(NULL, 0, NULL, NULL);
54 }
55 gEmptyRef->ref();
56 return gEmptyRef;
57}
58
59// assumes fPtr was allocated via sk_malloc
reed@google.com8a85d0c2011-06-24 19:12:12 +000060static void sk_free_releaseproc(const void* ptr, size_t, void*) {
reed@google.com3a31ac12011-06-24 13:11:05 +000061 sk_free((void*)ptr);
62}
63
reed@google.com8a85d0c2011-06-24 19:12:12 +000064SkData* SkData::NewFromMalloc(const void* data, size_t length) {
65 return new SkData(data, length, sk_free_releaseproc, NULL);
66}
67
reed@google.com3a31ac12011-06-24 13:11:05 +000068SkData* SkData::NewWithCopy(const void* data, size_t length) {
69 if (0 == length) {
70 return SkData::NewEmpty();
71 }
72
reed@google.com8a85d0c2011-06-24 19:12:12 +000073 void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
reed@google.com3a31ac12011-06-24 13:11:05 +000074 memcpy(copy, data, length);
reed@google.com8a85d0c2011-06-24 19:12:12 +000075 return new SkData(copy, length, sk_free_releaseproc, NULL);
reed@google.com3a31ac12011-06-24 13:11:05 +000076}
77
78SkData* SkData::NewWithProc(const void* data, size_t length,
reed@google.com8a85d0c2011-06-24 19:12:12 +000079 ReleaseProc proc, void* context) {
reed@google.com3a31ac12011-06-24 13:11:05 +000080 return new SkData(data, length, proc, context);
81}
82
83// assumes context is a SkData
84static void sk_dataref_releaseproc(const void*, size_t, void* context) {
85 SkData* src = reinterpret_cast<SkData*>(context);
86 src->unref();
87}
88
89SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
90 /*
91 We could, if we wanted/need to, just make a deep copy of src's data,
92 rather than referencing it. This would duplicate the storage (of the
93 subset amount) but would possibly allow src to go out of scope sooner.
94 */
95
96 size_t available = src->size();
97 if (offset >= available || 0 == length) {
98 return SkData::NewEmpty();
99 }
100 available -= offset;
101 if (length > available) {
102 length = available;
103 }
104 SkASSERT(length > 0);
105
106 src->ref(); // this will be balanced in sk_dataref_releaseproc
107 return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
108 const_cast<SkData*>(src));
109}
110