blob: dfc2a949018aadd2989deaa9dc0f9f4a0e346413 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkMetaData.h"
reed@google.come7330712011-03-30 18:23:21 +000011#include "SkRefCnt.h"
12
13struct PtrPair {
14 void* fPtr;
15 SkMetaData::PtrProc fProc;
16};
17
18void* SkMetaData::RefCntProc(void* ptr, bool doRef) {
19 SkASSERT(ptr);
20 SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr);
21
22 if (doRef) {
23 refcnt->ref();
24 } else {
25 refcnt->unref();
26 }
27 return ptr;
28}
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
30SkMetaData::SkMetaData() : fRec(NULL)
31{
32}
33
34SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL)
35{
36 *this = src;
37}
38
39SkMetaData::~SkMetaData()
40{
41 this->reset();
42}
43
44void SkMetaData::reset()
45{
46 Rec* rec = fRec;
reed@google.come7330712011-03-30 18:23:21 +000047 while (rec) {
48 if (kPtr_Type == rec->fType) {
49 PtrPair* pair = (PtrPair*)rec->data();
50 if (pair->fProc && pair->fPtr) {
51 pair->fPtr = pair->fProc(pair->fPtr, false);
52 }
53 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 Rec* next = rec->fNext;
55 Rec::Free(rec);
56 rec = next;
57 }
58 fRec = NULL;
59}
60
61SkMetaData& SkMetaData::operator=(const SkMetaData& src)
62{
63 this->reset();
64
65 const Rec* rec = src.fRec;
66 while (rec)
67 {
68 this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount);
69 rec = rec->fNext;
70 }
71 return *this;
72}
73
74void SkMetaData::setS32(const char name[], int32_t value)
75{
76 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
77}
78
79void SkMetaData::setScalar(const char name[], SkScalar value)
80{
81 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
82}
83
84SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
85{
86 SkASSERT(count > 0);
87 if (count > 0)
88 return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
89 return NULL;
90}
91
92void SkMetaData::setString(const char name[], const char value[])
93{
commit-bot@chromium.orga8c7f772014-01-24 21:46:29 +000094 (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
reed@android.com8a1c16f2008-12-17 15:59:43 +000095}
96
reed@google.come7330712011-03-30 18:23:21 +000097void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
98 PtrPair pair = { ptr, proc };
99 (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100}
101
102void SkMetaData::setBool(const char name[], bool value)
103{
104 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
105}
106
reed@android.comf2b98d62010-12-20 18:26:13 +0000107void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
commit-bot@chromium.orga8c7f772014-01-24 21:46:29 +0000108 (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
reed@android.comf2b98d62010-12-20 18:26:13 +0000109}
110
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
112{
113 SkASSERT(name);
114 SkASSERT(dataSize);
115 SkASSERT(count > 0);
116
117 (void)this->remove(name, type);
118
119 size_t len = strlen(name);
120 Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
121
122#ifndef SK_DEBUG
123 rec->fType = SkToU8(type);
124#else
125 rec->fType = type;
126#endif
127 rec->fDataLen = SkToU8(dataSize);
128 rec->fDataCount = SkToU16(count);
129 if (data)
130 memcpy(rec->data(), data, dataSize * count);
131 memcpy(rec->name(), name, len + 1);
132
reed@google.come7330712011-03-30 18:23:21 +0000133 if (kPtr_Type == type) {
134 PtrPair* pair = (PtrPair*)rec->data();
135 if (pair->fProc && pair->fPtr) {
136 pair->fPtr = pair->fProc(pair->fPtr, true);
137 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
140 rec->fNext = fRec;
141 fRec = rec;
142 return rec->data();
143}
144
145bool SkMetaData::findS32(const char name[], int32_t* value) const
146{
147 const Rec* rec = this->find(name, kS32_Type);
148 if (rec)
149 {
150 SkASSERT(rec->fDataCount == 1);
151 if (value)
152 *value = *(const int32_t*)rec->data();
153 return true;
154 }
155 return false;
156}
157
158bool SkMetaData::findScalar(const char name[], SkScalar* value) const
159{
160 const Rec* rec = this->find(name, kScalar_Type);
161 if (rec)
162 {
163 SkASSERT(rec->fDataCount == 1);
164 if (value)
165 *value = *(const SkScalar*)rec->data();
166 return true;
167 }
168 return false;
169}
170
171const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
172{
173 const Rec* rec = this->find(name, kScalar_Type);
174 if (rec)
175 {
176 if (count)
177 *count = rec->fDataCount;
178 if (values)
179 memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
180 return (const SkScalar*)rec->data();
181 }
182 return NULL;
183}
184
reed@google.come7330712011-03-30 18:23:21 +0000185bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 const Rec* rec = this->find(name, kPtr_Type);
reed@google.come7330712011-03-30 18:23:21 +0000187 if (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188 SkASSERT(rec->fDataCount == 1);
reed@google.come7330712011-03-30 18:23:21 +0000189 const PtrPair* pair = (const PtrPair*)rec->data();
190 if (ptr) {
191 *ptr = pair->fPtr;
192 }
193 if (proc) {
194 *proc = pair->fProc;
195 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196 return true;
197 }
198 return false;
199}
200
201const char* SkMetaData::findString(const char name[]) const
202{
203 const Rec* rec = this->find(name, kString_Type);
204 SkASSERT(rec == NULL || rec->fDataLen == sizeof(char));
205 return rec ? (const char*)rec->data() : NULL;
206}
207
208bool SkMetaData::findBool(const char name[], bool* value) const
209{
210 const Rec* rec = this->find(name, kBool_Type);
211 if (rec)
212 {
213 SkASSERT(rec->fDataCount == 1);
214 if (value)
215 *value = *(const bool*)rec->data();
216 return true;
217 }
218 return false;
219}
220
reed@android.comf2b98d62010-12-20 18:26:13 +0000221const void* SkMetaData::findData(const char name[], size_t* length) const {
222 const Rec* rec = this->find(name, kData_Type);
223 if (rec) {
224 SkASSERT(rec->fDataLen == sizeof(char));
225 if (length) {
226 *length = rec->fDataCount;
227 }
228 return rec->data();
229 }
230 return NULL;
231}
232
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
234{
235 const Rec* rec = fRec;
236 while (rec)
237 {
238 if (rec->fType == type && !strcmp(rec->name(), name))
239 return rec;
240 rec = rec->fNext;
241 }
242 return NULL;
243}
244
reed@google.come7330712011-03-30 18:23:21 +0000245bool SkMetaData::remove(const char name[], Type type) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246 Rec* rec = fRec;
247 Rec* prev = NULL;
reed@google.come7330712011-03-30 18:23:21 +0000248 while (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000249 Rec* next = rec->fNext;
reed@google.come7330712011-03-30 18:23:21 +0000250 if (rec->fType == type && !strcmp(rec->name(), name)) {
251 if (prev) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252 prev->fNext = next;
reed@google.come7330712011-03-30 18:23:21 +0000253 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254 fRec = next;
reed@google.come7330712011-03-30 18:23:21 +0000255 }
256
257 if (kPtr_Type == type) {
258 PtrPair* pair = (PtrPair*)rec->data();
259 if (pair->fProc && pair->fPtr) {
260 (void)pair->fProc(pair->fPtr, false);
261 }
262 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263 Rec::Free(rec);
264 return true;
265 }
266 prev = rec;
267 rec = next;
268 }
269 return false;
270}
271
272bool SkMetaData::removeS32(const char name[])
273{
274 return this->remove(name, kS32_Type);
275}
276
277bool SkMetaData::removeScalar(const char name[])
278{
279 return this->remove(name, kScalar_Type);
280}
281
282bool SkMetaData::removeString(const char name[])
283{
284 return this->remove(name, kString_Type);
285}
286
287bool SkMetaData::removePtr(const char name[])
288{
289 return this->remove(name, kPtr_Type);
290}
291
292bool SkMetaData::removeBool(const char name[])
293{
294 return this->remove(name, kBool_Type);
295}
296
reed@android.comf2b98d62010-12-20 18:26:13 +0000297bool SkMetaData::removeData(const char name[]) {
298 return this->remove(name, kData_Type);
299}
300
reed@google.come7330712011-03-30 18:23:21 +0000301///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302
reed@google.come7330712011-03-30 18:23:21 +0000303SkMetaData::Iter::Iter(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 fRec = metadata.fRec;
305}
306
reed@google.come7330712011-03-30 18:23:21 +0000307void SkMetaData::Iter::reset(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 fRec = metadata.fRec;
309}
310
reed@google.come7330712011-03-30 18:23:21 +0000311const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312 const char* name = NULL;
313
reed@google.come7330712011-03-30 18:23:21 +0000314 if (fRec) {
315 if (t) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316 *t = (SkMetaData::Type)fRec->fType;
reed@google.come7330712011-03-30 18:23:21 +0000317 }
318 if (count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000319 *count = fRec->fDataCount;
reed@google.come7330712011-03-30 18:23:21 +0000320 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000321 name = fRec->name();
322
323 fRec = fRec->fNext;
324 }
325 return name;
326}
327
reed@google.come7330712011-03-30 18:23:21 +0000328///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000329
reed@google.come7330712011-03-30 18:23:21 +0000330SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331 return (Rec*)sk_malloc_throw(size);
332}
333
reed@google.come7330712011-03-30 18:23:21 +0000334void SkMetaData::Rec::Free(Rec* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335 sk_free(rec);
336}