Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: src/core/SkData.cpp

Issue 15675025: One allocation for an SkData which makes a copy. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Clean Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkData.h" 8 #include "SkData.h"
9 #include "SkFlattenableBuffers.h" 9 #include "SkFlattenableBuffers.h"
10 #include "SkOSFile.h" 10 #include "SkOSFile.h"
11 11
12 SK_DEFINE_INST_COUNT(SkData) 12 SK_DEFINE_INST_COUNT(SkData)
13 13
14 SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { 14 SkData::SkData(const void* ptr, size_t size)
15 fPtr = ptr; 15 : fSize(size)
16 fSize = size; 16 , fPtr(ptr)
17 fReleaseProc = proc; 17 { }
18 fReleaseProcContext = context;
19 }
20
21 SkData::~SkData() {
22 if (fReleaseProc) {
23 fReleaseProc(fPtr, fSize, fReleaseProcContext);
24 }
25 }
26 18
27 bool SkData::equals(const SkData* other) const { 19 bool SkData::equals(const SkData* other) const {
28 if (NULL == other) { 20 if (NULL == other) {
29 return false; 21 return false;
30 } 22 }
31 23
32 return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); 24 return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
33 } 25 }
34 26
35 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { 27 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
36 size_t available = fSize; 28 size_t available = fSize;
37 if (offset >= available || 0 == length) { 29 if (offset >= available || 0 == length) {
38 return 0; 30 return 0;
39 } 31 }
40 available -= offset; 32 available -= offset;
41 if (length > available) { 33 if (length > available) {
42 length = available; 34 length = available;
43 } 35 }
44 SkASSERT(length > 0); 36 SkASSERT(length > 0);
45 37
46 memcpy(buffer, this->bytes() + offset, length); 38 memcpy(buffer, this->bytes() + offset, length);
47 return length; 39 return length;
48 } 40 }
49 41
50 /////////////////////////////////////////////////////////////////////////////// 42 ///////////////////////////////////////////////////////////////////////////////
51 43
52 SkData* SkData::NewEmpty() { 44 SkData* SkData::NewEmpty() {
53 static SkData* gEmptyRef; 45 static SkData* gEmptyRef;
54 if (NULL == gEmptyRef) { 46 if (NULL == gEmptyRef) {
55 gEmptyRef = new SkData(NULL, 0, NULL, NULL); 47 gEmptyRef = new SkData(NULL, 0);
56 } 48 }
57 gEmptyRef->ref(); 49 gEmptyRef->ref();
58 return gEmptyRef; 50 return gEmptyRef;
59 } 51 }
60 52
61 // assumes fPtr was allocated via sk_malloc 53 /** Assumes ptr was allocated via sk_malloc, ignores the size and context. */
62 static void sk_free_releaseproc(const void* ptr, size_t, void*) { 54 static void sk_free_releaseproc(const void* ptr, size_t) {
63 sk_free((void*)ptr); 55 sk_free((void*)ptr);
64 } 56 }
65 57
66 SkData* SkData::NewFromMalloc(const void* data, size_t length) { 58 SkData* SkData::NewFromMalloc(const void* data, size_t length) {
67 return new SkData(data, length, sk_free_releaseproc, NULL); 59 typedef SkManagedData<SkManagedDataProcs::ReleaseProc, void> SelfType;
60 return new SelfType(data, length, sk_free_releaseproc);
61 }
62
63 /** Assumes obj was allocated via sk_malloc, ignores context. */
64 static void sk_free_deleteproc(const void* obj) {
65 sk_free((void*)obj);
68 } 66 }
69 67
70 SkData* SkData::NewWithCopy(const void* data, size_t length) { 68 SkData* SkData::NewWithCopy(const void* data, size_t length) {
71 if (0 == length) { 69 if (0 == length) {
72 return SkData::NewEmpty(); 70 return SkData::NewEmpty();
73 } 71 }
74 72
75 void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc 73 typedef SkManagedData<void, SkManagedDataProcs::DeleterProc> SelfType;
74 size_t total_size = sizeof(SelfType) + length;
75 char* self = reinterpret_cast<char*>(sk_malloc_throw(total_size));
76 char* copy = self + sizeof(SelfType);
76 memcpy(copy, data, length); 77 memcpy(copy, data, length);
77 return new SkData(copy, length, sk_free_releaseproc, NULL); 78 return SelfType::Place(self, copy, length, sk_free_deleteproc);
78 }
79
80 SkData* SkData::NewWithProc(const void* data, size_t length,
81 ReleaseProc proc, void* context) {
82 return new SkData(data, length, proc, context);
83 } 79 }
84 80
85 // assumes fPtr was allocated with sk_fmmap 81 // assumes fPtr was allocated with sk_fmmap
86 static void sk_mmap_releaseproc(const void* addr, size_t length, void*) { 82 static void sk_mmap_releaseproc(const void* addr, size_t length) {
87 sk_fmunmap(addr, length); 83 sk_fmunmap(addr, length);
88 } 84 }
89 85
90 SkData* SkData::NewFromFILE(SkFILE* f) { 86 SkData* SkData::NewFromFILE(SkFILE* f) {
91 size_t size; 87 size_t size;
92 void* addr = sk_fmmap(f, &size); 88 void* addr = sk_fmmap(f, &size);
93 if (NULL == addr) { 89 if (NULL == addr) {
94 return NULL; 90 return NULL;
95 } 91 }
96 92
97 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 93 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc);
98 } 94 }
99 95
100 SkData* SkData::NewFromFileName(const char path[]) { 96 SkData* SkData::NewFromFileName(const char path[]) {
101 SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL; 97 SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL;
102 if (NULL == f) { 98 if (NULL == f) {
103 return NULL; 99 return NULL;
104 } 100 }
105 SkData* data = NewFromFILE(f); 101 SkData* data = NewFromFILE(f);
106 sk_fclose(f); 102 sk_fclose(f);
107 return data; 103 return data;
108 } 104 }
109 105
110 SkData* SkData::NewFromFD(int fd) { 106 SkData* SkData::NewFromFD(int fd) {
111 size_t size; 107 size_t size;
112 void* addr = sk_fdmmap(fd, &size); 108 void* addr = sk_fdmmap(fd, &size);
113 if (NULL == addr) { 109 if (NULL == addr) {
114 return NULL; 110 return NULL;
115 } 111 }
116 112
117 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); 113 return SkData::NewWithProc(addr, size, sk_mmap_releaseproc);
118 } 114 }
119 115
120 // assumes context is a SkData 116 struct SkAutoUnrefFunctor {
121 static void sk_dataref_releaseproc(const void*, size_t, void* context) { 117 public:
122 SkData* src = reinterpret_cast<SkData*>(context); 118 explicit SkAutoUnrefFunctor(SkRefCnt const * ptr) : fPtr(ptr) { }
123 src->unref(); 119 void operator()(const void* ptr, size_t length) const {
124 } 120 fPtr->unref();
121 }
122 private:
123 SkRefCnt const * fPtr;
124 };
125 125
126 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { 126 SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
127 /* 127 /*
128 We could, if we wanted/need to, just make a deep copy of src's data, 128 We could, if we wanted/need to, just make a deep copy of src's data,
129 rather than referencing it. This would duplicate the storage (of the 129 rather than referencing it. This would duplicate the storage (of the
130 subset amount) but would possibly allow src to go out of scope sooner. 130 subset amount) but would possibly allow src to go out of scope sooner.
131 */ 131 */
132 132
133 size_t available = src->size(); 133 size_t available = src->size();
134 if (offset >= available || 0 == length) { 134 if (offset >= available || 0 == length) {
135 return SkData::NewEmpty(); 135 return SkData::NewEmpty();
136 } 136 }
137 available -= offset; 137 available -= offset;
138 if (length > available) { 138 if (length > available) {
139 length = available; 139 length = available;
140 } 140 }
141 SkASSERT(length > 0); 141 SkASSERT(length > 0);
142 142
143 src->ref(); // this will be balanced in sk_dataref_releaseproc 143 src->ref(); // this will be balanced in SkAutoUnrefFunctor
144 return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, 144 typedef SkManagedData<SkAutoUnrefFunctor, void> SelfType;
145 const_cast<SkData*>(src)); 145 return new SelfType(src->bytes() + offset, length, SkAutoUnrefFunctor(src));
146 } 146 }
147 147
148 SkData* SkData::NewWithCString(const char cstr[]) { 148 SkData* SkData::NewWithCString(const char cstr[]) {
149 size_t size; 149 size_t size;
150 if (NULL == cstr) { 150 if (NULL == cstr) {
151 cstr = ""; 151 cstr = "";
152 size = 1; 152 size = 1;
153 } else { 153 } else {
154 size = strlen(cstr) + 1; 154 size = strlen(cstr) + 1;
155 } 155 }
156 return NewWithCopy(cstr, size); 156 return NewWithCopy(cstr, size);
157 } 157 }
158 158
159 SkData* SkData::NewUnowned(const void* data, size_t length) {
160 return new SkData(data, length);
161 }
162
159 /////////////////////////////////////////////////////////////////////////////// 163 ///////////////////////////////////////////////////////////////////////////////
160 164
161 void SkData::flatten(SkFlattenableWriteBuffer& buffer) const { 165 void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
162 buffer.writeByteArray(fPtr, fSize); 166 buffer.writeByteArray(fPtr, fSize);
163 } 167 }
164 168
165 SkData::SkData(SkFlattenableReadBuffer& buffer) { 169 SkFlattenable* SkData::CreateProc(SkFlattenableReadBuffer& buffer) {
166 fSize = buffer.getArrayCount(); 170 uint32_t length = buffer.getArrayCount();
167 fReleaseProcContext = NULL; 171 if (0 == length) {
168 172 return SkData::NewEmpty();
169 if (fSize > 0) {
170 fPtr = sk_malloc_throw(fSize);
171 fReleaseProc = sk_free_releaseproc;
172 } else {
173 fPtr = NULL;
174 fReleaseProc = NULL;
175 } 173 }
176 174
177 buffer.readByteArray(const_cast<void*>(fPtr)); 175 typedef SkManagedData<void, SkManagedDataProcs::DeleterProc> SelfType;
176 size_t total_size = sizeof(SelfType) + length;
177 char* self = reinterpret_cast<char*>(sk_malloc_throw(total_size));
178 char* copy = self + sizeof(SelfType);
179 buffer.readByteArray(copy);
180 return SelfType::Place(self, copy, length, sk_free_deleteproc);
178 } 181 }
179 182
180 /////////////////////////////////////////////////////////////////////////////// 183 ///////////////////////////////////////////////////////////////////////////////
181 /////////////////////////////////////////////////////////////////////////////// 184 ///////////////////////////////////////////////////////////////////////////////
182 185
183 #include "SkDataSet.h" 186 #include "SkDataSet.h"
184 #include "SkFlattenable.h" 187 #include "SkFlattenable.h"
185 #include "SkStream.h" 188 #include "SkStream.h"
186 189
187 static SkData* dupdata(SkData* data) { 190 static SkData* dupdata(SkData* data) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 } 332 }
330 333
331 SkDataSet* SkDataSet::NewEmpty() { 334 SkDataSet* SkDataSet::NewEmpty() {
332 static SkDataSet* gEmptySet; 335 static SkDataSet* gEmptySet;
333 if (NULL == gEmptySet) { 336 if (NULL == gEmptySet) {
334 gEmptySet = SkNEW_ARGS(SkDataSet, (NULL, 0)); 337 gEmptySet = SkNEW_ARGS(SkDataSet, (NULL, 0));
335 } 338 }
336 gEmptySet->ref(); 339 gEmptySet->ref();
337 return gEmptySet; 340 return gEmptySet;
338 } 341 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698