• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkData.h"
9 #include "include/core/SkStream.h"
10 #include "include/private/SkOnce.h"
11 #include "src/core/SkOSFile.h"
12 #include "src/core/SkReadBuffer.h"
13 #include "src/core/SkWriteBuffer.h"
14 #include <new>
15 
SkData(const void * ptr,size_t size,ReleaseProc proc,void * context)16 SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context)
17     : fReleaseProc(proc)
18     , fReleaseProcContext(context)
19     , fPtr(ptr)
20     , fSize(size)
21     , fNativeBuffer(nullptr)
22 {}
23 
SkData(const void * ptr,size_t size,OH_NativeBuffer * nativeBuffer,ReleaseProc proc,void * context)24 SkData::SkData(const void* ptr, size_t size, OH_NativeBuffer* nativeBuffer, ReleaseProc proc, void* context)
25     : fReleaseProc(proc)
26     , fReleaseProcContext(context)
27     , fPtr(ptr)
28     , fSize(size)
29     , fNativeBuffer(nativeBuffer)
30 {}
31 
32 /** This constructor means we are inline with our fPtr's contents.
33  *  Thus we set fPtr to point right after this.
34  */
SkData(size_t size)35 SkData::SkData(size_t size)
36     : fReleaseProc(nullptr)
37     , fReleaseProcContext(nullptr)
38     , fPtr((const char*)(this + 1))
39     , fSize(size)
40     , fNativeBuffer(nullptr)
41 {}
42 
~SkData()43 SkData::~SkData() {
44     if (fReleaseProc) {
45         fReleaseProc(fPtr, fReleaseProcContext);
46     }
47 }
48 
equals(const SkData * other) const49 bool SkData::equals(const SkData* other) const {
50     if (this == other) {
51         return true;
52     }
53     if (nullptr == other) {
54         return false;
55     }
56     return fSize == other->fSize && !sk_careful_memcmp(fPtr, other->fPtr, fSize);
57 }
58 
copyRange(size_t offset,size_t length,void * buffer) const59 size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
60     size_t available = fSize;
61     if (offset >= available || 0 == length) {
62         return 0;
63     }
64     available -= offset;
65     if (length > available) {
66         length = available;
67     }
68     SkASSERT(length > 0);
69 
70     memcpy(buffer, this->bytes() + offset, length);
71     return length;
72 }
73 
operator delete(void * p)74 void SkData::operator delete(void* p) {
75     ::operator delete(p);
76 }
77 
PrivateNewWithCopy(const void * srcOrNull,size_t length)78 sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
79     if (0 == length) {
80         return SkData::MakeEmpty();
81     }
82 
83     const size_t actualLength = length + sizeof(SkData);
84     SkASSERT_RELEASE(length < actualLength);  // Check for overflow.
85 
86     void* storage = ::operator new (actualLength);
87     sk_sp<SkData> data(new (storage) SkData(length));
88     if (srcOrNull) {
89         memcpy(data->writable_data(), srcOrNull, length);
90     }
91     return data;
92 }
93 
NoopReleaseProc(const void *,void *)94 void SkData::NoopReleaseProc(const void*, void*) {}
95 
96 ///////////////////////////////////////////////////////////////////////////////
97 
MakeEmpty()98 sk_sp<SkData> SkData::MakeEmpty() {
99     static SkOnce once;
100     static SkData* empty;
101 
102     once([]{ empty = new SkData(nullptr, 0, nullptr, nullptr); });
103     return sk_ref_sp(empty);
104 }
105 
106 // assumes fPtr was allocated via sk_malloc
sk_free_releaseproc(const void * ptr,void *)107 static void sk_free_releaseproc(const void* ptr, void*) {
108     sk_free((void*)ptr);
109 }
110 
MakeFromMalloc(const void * data,size_t length)111 sk_sp<SkData> SkData::MakeFromMalloc(const void* data, size_t length) {
112     return sk_sp<SkData>(new SkData(data, length, sk_free_releaseproc, nullptr));
113 }
114 
MakeWithCopy(const void * src,size_t length)115 sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
116     SkASSERT(src);
117     return PrivateNewWithCopy(src, length);
118 }
119 
MakeUninitialized(size_t length)120 sk_sp<SkData> SkData::MakeUninitialized(size_t length) {
121     return PrivateNewWithCopy(nullptr, length);
122 }
123 
MakeWithProc(const void * ptr,size_t length,ReleaseProc proc,void * ctx)124 sk_sp<SkData> SkData::MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx) {
125     return sk_sp<SkData>(new SkData(ptr, length, proc, ctx));
126 }
127 
128 // assumes fPtr was allocated with sk_fmmap
sk_mmap_releaseproc(const void * addr,void * ctx)129 static void sk_mmap_releaseproc(const void* addr, void* ctx) {
130     size_t length = reinterpret_cast<size_t>(ctx);
131     sk_fmunmap(addr, length);
132 }
133 
MakeFromFILE(FILE * f)134 sk_sp<SkData> SkData::MakeFromFILE(FILE* f) {
135     size_t size;
136     void* addr = sk_fmmap(f, &size);
137     if (nullptr == addr) {
138         return nullptr;
139     }
140 
141     return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
142 }
143 
MakeFromFileName(const char path[])144 sk_sp<SkData> SkData::MakeFromFileName(const char path[]) {
145     FILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr;
146     if (nullptr == f) {
147         return nullptr;
148     }
149     auto data = MakeFromFILE(f);
150     sk_fclose(f);
151     return data;
152 }
153 
MakeFromFD(int fd)154 sk_sp<SkData> SkData::MakeFromFD(int fd) {
155     size_t size;
156     void* addr = sk_fdmmap(fd, &size);
157     if (nullptr == addr) {
158         return nullptr;
159     }
160     return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
161 }
162 
MakeFromOHNativeBuffer(OH_NativeBuffer * nativeBuffer,size_t size)163 sk_sp<SkData> SkData::MakeFromOHNativeBuffer(OH_NativeBuffer* nativeBuffer, size_t size) {
164     return sk_sp<SkData>(new SkData(nullptr, size, nativeBuffer, nullptr, nullptr));
165 }
166 
167 // assumes context is a SkData
sk_dataref_releaseproc(const void *,void * context)168 static void sk_dataref_releaseproc(const void*, void* context) {
169     SkData* src = reinterpret_cast<SkData*>(context);
170     src->unref();
171 }
172 
MakeSubset(const SkData * src,size_t offset,size_t length)173 sk_sp<SkData> SkData::MakeSubset(const SkData* src, size_t offset, size_t length) {
174     /*
175         We could, if we wanted/need to, just make a deep copy of src's data,
176         rather than referencing it. This would duplicate the storage (of the
177         subset amount) but would possibly allow src to go out of scope sooner.
178      */
179 
180     size_t available = src->size();
181     if (offset >= available || 0 == length) {
182         return SkData::MakeEmpty();
183     }
184     available -= offset;
185     if (length > available) {
186         length = available;
187     }
188     SkASSERT(length > 0);
189 
190     src->ref(); // this will be balanced in sk_dataref_releaseproc
191     return sk_sp<SkData>(new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
192                                     const_cast<SkData*>(src)));
193 }
194 
MakeWithCString(const char cstr[])195 sk_sp<SkData> SkData::MakeWithCString(const char cstr[]) {
196     size_t size;
197     if (nullptr == cstr) {
198         cstr = "";
199         size = 1;
200     } else {
201         size = strlen(cstr) + 1;
202     }
203     return MakeWithCopy(cstr, size);
204 }
205 
206 ///////////////////////////////////////////////////////////////////////////////
207 
MakeFromStream(SkStream * stream,size_t size)208 sk_sp<SkData> SkData::MakeFromStream(SkStream* stream, size_t size) {
209     sk_sp<SkData> data(SkData::MakeUninitialized(size));
210     if (stream->read(data->writable_data(), size) != size) {
211         return nullptr;
212     }
213     return data;
214 }
215