blob: d1564e9fecced89a1c4aa957817cd7e3570f9fcd [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008
9#include "SkMetaData.h"
Herb Derbyd7b34a52017-03-20 11:19:23 -040010
Herb Derbyb549cc32017-03-27 13:35:15 -040011#include "SkMalloc.h"
reed@google.come7330712011-03-30 18:23:21 +000012#include "SkRefCnt.h"
13
14struct PtrPair {
15 void* fPtr;
16 SkMetaData::PtrProc fProc;
17};
18
19void* 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}
reed@android.com8a1c16f2008-12-17 15:59:43 +000030
halcanary96fcdcc2015-08-27 07:41:13 -070031SkMetaData::SkMetaData() : fRec(nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +000032{
33}
34
halcanary96fcdcc2015-08-27 07:41:13 -070035SkMetaData::SkMetaData(const SkMetaData& src) : fRec(nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +000036{
37 *this = src;
38}
39
40SkMetaData::~SkMetaData()
41{
42 this->reset();
43}
44
45void SkMetaData::reset()
46{
47 Rec* rec = fRec;
reed@google.come7330712011-03-30 18:23:21 +000048 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000055 Rec* next = rec->fNext;
56 Rec::Free(rec);
57 rec = next;
58 }
halcanary96fcdcc2015-08-27 07:41:13 -070059 fRec = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000060}
61
62SkMetaData& 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
75void SkMetaData::setS32(const char name[], int32_t value)
76{
77 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
78}
79
80void SkMetaData::setScalar(const char name[], SkScalar value)
81{
82 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
83}
84
85SkScalar* 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);
halcanary96fcdcc2015-08-27 07:41:13 -070090 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000091}
92
93void SkMetaData::setString(const char name[], const char value[])
94{
commit-bot@chromium.orga8c7f772014-01-24 21:46:29 +000095 (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
reed@android.com8a1c16f2008-12-17 15:59:43 +000096}
97
reed@google.come7330712011-03-30 18:23:21 +000098void 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);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101}
102
103void SkMetaData::setBool(const char name[], bool value)
104{
105 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
106}
107
reed@android.comf2b98d62010-12-20 18:26:13 +0000108void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
commit-bot@chromium.orga8c7f772014-01-24 21:46:29 +0000109 (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
reed@android.comf2b98d62010-12-20 18:26:13 +0000110}
111
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112void* 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
reed@google.come7330712011-03-30 18:23:21 +0000134 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140
141 rec->fNext = fRec;
142 fRec = rec;
143 return rec->data();
144}
145
146bool 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
159bool 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
172const 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 }
halcanary96fcdcc2015-08-27 07:41:13 -0700183 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184}
185
reed@google.come7330712011-03-30 18:23:21 +0000186bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187 const Rec* rec = this->find(name, kPtr_Type);
reed@google.come7330712011-03-30 18:23:21 +0000188 if (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 SkASSERT(rec->fDataCount == 1);
reed@google.come7330712011-03-30 18:23:21 +0000190 const PtrPair* pair = (const PtrPair*)rec->data();
191 if (ptr) {
192 *ptr = pair->fPtr;
193 }
194 if (proc) {
195 *proc = pair->fProc;
196 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197 return true;
198 }
199 return false;
200}
201
202const char* SkMetaData::findString(const char name[]) const
203{
204 const Rec* rec = this->find(name, kString_Type);
halcanary96fcdcc2015-08-27 07:41:13 -0700205 SkASSERT(rec == nullptr || rec->fDataLen == sizeof(char));
206 return rec ? (const char*)rec->data() : nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207}
208
209bool 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
reed@android.comf2b98d62010-12-20 18:26:13 +0000222const 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 }
halcanary96fcdcc2015-08-27 07:41:13 -0700231 return nullptr;
reed@android.comf2b98d62010-12-20 18:26:13 +0000232}
233
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234const 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 }
halcanary96fcdcc2015-08-27 07:41:13 -0700243 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244}
245
reed@google.come7330712011-03-30 18:23:21 +0000246bool SkMetaData::remove(const char name[], Type type) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247 Rec* rec = fRec;
halcanary96fcdcc2015-08-27 07:41:13 -0700248 Rec* prev = nullptr;
reed@google.come7330712011-03-30 18:23:21 +0000249 while (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250 Rec* next = rec->fNext;
reed@google.come7330712011-03-30 18:23:21 +0000251 if (rec->fType == type && !strcmp(rec->name(), name)) {
252 if (prev) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253 prev->fNext = next;
reed@google.come7330712011-03-30 18:23:21 +0000254 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255 fRec = next;
reed@google.come7330712011-03-30 18:23:21 +0000256 }
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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000264 Rec::Free(rec);
265 return true;
266 }
267 prev = rec;
268 rec = next;
269 }
270 return false;
271}
272
273bool SkMetaData::removeS32(const char name[])
274{
275 return this->remove(name, kS32_Type);
276}
277
278bool SkMetaData::removeScalar(const char name[])
279{
280 return this->remove(name, kScalar_Type);
281}
282
283bool SkMetaData::removeString(const char name[])
284{
285 return this->remove(name, kString_Type);
286}
287
288bool SkMetaData::removePtr(const char name[])
289{
290 return this->remove(name, kPtr_Type);
291}
292
293bool SkMetaData::removeBool(const char name[])
294{
295 return this->remove(name, kBool_Type);
296}
297
reed@android.comf2b98d62010-12-20 18:26:13 +0000298bool SkMetaData::removeData(const char name[]) {
299 return this->remove(name, kData_Type);
300}
301
reed@google.come7330712011-03-30 18:23:21 +0000302///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303
reed@google.come7330712011-03-30 18:23:21 +0000304SkMetaData::Iter::Iter(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 fRec = metadata.fRec;
306}
307
reed@google.come7330712011-03-30 18:23:21 +0000308void SkMetaData::Iter::reset(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309 fRec = metadata.fRec;
310}
311
reed@google.come7330712011-03-30 18:23:21 +0000312const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
halcanary96fcdcc2015-08-27 07:41:13 -0700313 const char* name = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000314
reed@google.come7330712011-03-30 18:23:21 +0000315 if (fRec) {
316 if (t) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317 *t = (SkMetaData::Type)fRec->fType;
reed@google.come7330712011-03-30 18:23:21 +0000318 }
319 if (count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320 *count = fRec->fDataCount;
reed@google.come7330712011-03-30 18:23:21 +0000321 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 name = fRec->name();
323
324 fRec = fRec->fNext;
325 }
326 return name;
327}
328
reed@google.come7330712011-03-30 18:23:21 +0000329///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330
reed@google.come7330712011-03-30 18:23:21 +0000331SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332 return (Rec*)sk_malloc_throw(size);
333}
334
reed@google.come7330712011-03-30 18:23:21 +0000335void SkMetaData::Rec::Free(Rec* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336 sk_free(rec);
337}