1 /*
2 * Copyright 2006 The Android Open Source Project
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 "SkMetaData.h"
9
10 #include "SkMalloc.h"
11 #include "SkRefCnt.h"
12 #include "SkTo.h"
13
14 struct PtrPair {
15 void* fPtr;
16 SkMetaData::PtrProc fProc;
17 };
18
RefCntProc(void * ptr,bool doRef)19 void* SkMetaData::RefCntProc(void* ptr, bool doRef) {
20 SkASSERT(ptr);
21 SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr);
22
23 if (doRef) {
24 refcnt->ref();
25 } else {
26 refcnt->unref();
27 }
28 return ptr;
29 }
30
SkMetaData()31 SkMetaData::SkMetaData() : fRec(nullptr)
32 {
33 }
34
SkMetaData(const SkMetaData & src)35 SkMetaData::SkMetaData(const SkMetaData& src) : fRec(nullptr)
36 {
37 *this = src;
38 }
39
~SkMetaData()40 SkMetaData::~SkMetaData()
41 {
42 this->reset();
43 }
44
reset()45 void SkMetaData::reset()
46 {
47 Rec* rec = fRec;
48 while (rec) {
49 if (kPtr_Type == rec->fType) {
50 PtrPair* pair = (PtrPair*)rec->data();
51 if (pair->fProc && pair->fPtr) {
52 pair->fPtr = pair->fProc(pair->fPtr, false);
53 }
54 }
55 Rec* next = rec->fNext;
56 Rec::Free(rec);
57 rec = next;
58 }
59 fRec = nullptr;
60 }
61
operator =(const SkMetaData & src)62 SkMetaData& SkMetaData::operator=(const SkMetaData& src)
63 {
64 this->reset();
65
66 const Rec* rec = src.fRec;
67 while (rec)
68 {
69 this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount);
70 rec = rec->fNext;
71 }
72 return *this;
73 }
74
setS32(const char name[],int32_t value)75 void SkMetaData::setS32(const char name[], int32_t value)
76 {
77 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
78 }
79
setScalar(const char name[],SkScalar value)80 void SkMetaData::setScalar(const char name[], SkScalar value)
81 {
82 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
83 }
84
setScalars(const char name[],int count,const SkScalar values[])85 SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
86 {
87 SkASSERT(count > 0);
88 if (count > 0)
89 return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
90 return nullptr;
91 }
92
setString(const char name[],const char value[])93 void SkMetaData::setString(const char name[], const char value[])
94 {
95 (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
96 }
97
setPtr(const char name[],void * ptr,PtrProc proc)98 void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
99 PtrPair pair = { ptr, proc };
100 (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1);
101 }
102
setBool(const char name[],bool value)103 void SkMetaData::setBool(const char name[], bool value)
104 {
105 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
106 }
107
setData(const char name[],const void * data,size_t byteCount)108 void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
109 (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
110 }
111
set(const char name[],const void * data,size_t dataSize,Type type,int count)112 void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
113 {
114 SkASSERT(name);
115 SkASSERT(dataSize);
116 SkASSERT(count > 0);
117
118 (void)this->remove(name, type);
119
120 size_t len = strlen(name);
121 Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
122
123 #ifndef SK_DEBUG
124 rec->fType = SkToU8(type);
125 #else
126 rec->fType = type;
127 #endif
128 rec->fDataLen = SkToU8(dataSize);
129 rec->fDataCount = SkToU16(count);
130 if (data)
131 memcpy(rec->data(), data, dataSize * count);
132 memcpy(rec->name(), name, len + 1);
133
134 if (kPtr_Type == type) {
135 PtrPair* pair = (PtrPair*)rec->data();
136 if (pair->fProc && pair->fPtr) {
137 pair->fPtr = pair->fProc(pair->fPtr, true);
138 }
139 }
140
141 rec->fNext = fRec;
142 fRec = rec;
143 return rec->data();
144 }
145
findS32(const char name[],int32_t * value) const146 bool SkMetaData::findS32(const char name[], int32_t* value) const
147 {
148 const Rec* rec = this->find(name, kS32_Type);
149 if (rec)
150 {
151 SkASSERT(rec->fDataCount == 1);
152 if (value)
153 *value = *(const int32_t*)rec->data();
154 return true;
155 }
156 return false;
157 }
158
findScalar(const char name[],SkScalar * value) const159 bool SkMetaData::findScalar(const char name[], SkScalar* value) const
160 {
161 const Rec* rec = this->find(name, kScalar_Type);
162 if (rec)
163 {
164 SkASSERT(rec->fDataCount == 1);
165 if (value)
166 *value = *(const SkScalar*)rec->data();
167 return true;
168 }
169 return false;
170 }
171
findScalars(const char name[],int * count,SkScalar values[]) const172 const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
173 {
174 const Rec* rec = this->find(name, kScalar_Type);
175 if (rec)
176 {
177 if (count)
178 *count = rec->fDataCount;
179 if (values)
180 memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
181 return (const SkScalar*)rec->data();
182 }
183 return nullptr;
184 }
185
findPtr(const char name[],void ** ptr,PtrProc * proc) const186 bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
187 const Rec* rec = this->find(name, kPtr_Type);
188 if (rec) {
189 SkASSERT(rec->fDataCount == 1);
190 const PtrPair* pair = (const PtrPair*)rec->data();
191 if (ptr) {
192 *ptr = pair->fPtr;
193 }
194 if (proc) {
195 *proc = pair->fProc;
196 }
197 return true;
198 }
199 return false;
200 }
201
findString(const char name[]) const202 const char* SkMetaData::findString(const char name[]) const
203 {
204 const Rec* rec = this->find(name, kString_Type);
205 SkASSERT(rec == nullptr || rec->fDataLen == sizeof(char));
206 return rec ? (const char*)rec->data() : nullptr;
207 }
208
findBool(const char name[],bool * value) const209 bool SkMetaData::findBool(const char name[], bool* value) const
210 {
211 const Rec* rec = this->find(name, kBool_Type);
212 if (rec)
213 {
214 SkASSERT(rec->fDataCount == 1);
215 if (value)
216 *value = *(const bool*)rec->data();
217 return true;
218 }
219 return false;
220 }
221
findData(const char name[],size_t * length) const222 const void* SkMetaData::findData(const char name[], size_t* length) const {
223 const Rec* rec = this->find(name, kData_Type);
224 if (rec) {
225 SkASSERT(rec->fDataLen == sizeof(char));
226 if (length) {
227 *length = rec->fDataCount;
228 }
229 return rec->data();
230 }
231 return nullptr;
232 }
233
find(const char name[],Type type) const234 const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
235 {
236 const Rec* rec = fRec;
237 while (rec)
238 {
239 if (rec->fType == type && !strcmp(rec->name(), name))
240 return rec;
241 rec = rec->fNext;
242 }
243 return nullptr;
244 }
245
remove(const char name[],Type type)246 bool SkMetaData::remove(const char name[], Type type) {
247 Rec* rec = fRec;
248 Rec* prev = nullptr;
249 while (rec) {
250 Rec* next = rec->fNext;
251 if (rec->fType == type && !strcmp(rec->name(), name)) {
252 if (prev) {
253 prev->fNext = next;
254 } else {
255 fRec = next;
256 }
257
258 if (kPtr_Type == type) {
259 PtrPair* pair = (PtrPair*)rec->data();
260 if (pair->fProc && pair->fPtr) {
261 (void)pair->fProc(pair->fPtr, false);
262 }
263 }
264 Rec::Free(rec);
265 return true;
266 }
267 prev = rec;
268 rec = next;
269 }
270 return false;
271 }
272
removeS32(const char name[])273 bool SkMetaData::removeS32(const char name[])
274 {
275 return this->remove(name, kS32_Type);
276 }
277
removeScalar(const char name[])278 bool SkMetaData::removeScalar(const char name[])
279 {
280 return this->remove(name, kScalar_Type);
281 }
282
removeString(const char name[])283 bool SkMetaData::removeString(const char name[])
284 {
285 return this->remove(name, kString_Type);
286 }
287
removePtr(const char name[])288 bool SkMetaData::removePtr(const char name[])
289 {
290 return this->remove(name, kPtr_Type);
291 }
292
removeBool(const char name[])293 bool SkMetaData::removeBool(const char name[])
294 {
295 return this->remove(name, kBool_Type);
296 }
297
removeData(const char name[])298 bool SkMetaData::removeData(const char name[]) {
299 return this->remove(name, kData_Type);
300 }
301
302 ///////////////////////////////////////////////////////////////////////////////
303
Iter(const SkMetaData & metadata)304 SkMetaData::Iter::Iter(const SkMetaData& metadata) {
305 fRec = metadata.fRec;
306 }
307
reset(const SkMetaData & metadata)308 void SkMetaData::Iter::reset(const SkMetaData& metadata) {
309 fRec = metadata.fRec;
310 }
311
next(SkMetaData::Type * t,int * count)312 const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
313 const char* name = nullptr;
314
315 if (fRec) {
316 if (t) {
317 *t = (SkMetaData::Type)fRec->fType;
318 }
319 if (count) {
320 *count = fRec->fDataCount;
321 }
322 name = fRec->name();
323
324 fRec = fRec->fNext;
325 }
326 return name;
327 }
328
329 ///////////////////////////////////////////////////////////////////////////////
330
Alloc(size_t size)331 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
332 return (Rec*)sk_malloc_throw(size);
333 }
334
Free(Rec * rec)335 void SkMetaData::Rec::Free(Rec* rec) {
336 sk_free(rec);
337 }
338