1 
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 
9 
10 #include "SkMetaData.h"
11 #include "SkRefCnt.h"
12 
13 struct PtrPair {
14     void*               fPtr;
15     SkMetaData::PtrProc fProc;
16 };
17 
RefCntProc(void * ptr,bool doRef)18 void* 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 }
29 
SkMetaData()30 SkMetaData::SkMetaData() : fRec(nullptr)
31 {
32 }
33 
SkMetaData(const SkMetaData & src)34 SkMetaData::SkMetaData(const SkMetaData& src) : fRec(nullptr)
35 {
36     *this = src;
37 }
38 
~SkMetaData()39 SkMetaData::~SkMetaData()
40 {
41     this->reset();
42 }
43 
reset()44 void SkMetaData::reset()
45 {
46     Rec* rec = fRec;
47     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         }
54         Rec* next = rec->fNext;
55         Rec::Free(rec);
56         rec = next;
57     }
58     fRec = nullptr;
59 }
60 
operator =(const SkMetaData & src)61 SkMetaData& 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 
setS32(const char name[],int32_t value)74 void SkMetaData::setS32(const char name[], int32_t value)
75 {
76     (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
77 }
78 
setScalar(const char name[],SkScalar value)79 void SkMetaData::setScalar(const char name[], SkScalar value)
80 {
81     (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
82 }
83 
setScalars(const char name[],int count,const SkScalar values[])84 SkScalar* 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 nullptr;
90 }
91 
setString(const char name[],const char value[])92 void SkMetaData::setString(const char name[], const char value[])
93 {
94     (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
95 }
96 
setPtr(const char name[],void * ptr,PtrProc proc)97 void 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);
100 }
101 
setBool(const char name[],bool value)102 void SkMetaData::setBool(const char name[], bool value)
103 {
104     (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
105 }
106 
setData(const char name[],const void * data,size_t byteCount)107 void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
108     (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
109 }
110 
set(const char name[],const void * data,size_t dataSize,Type type,int count)111 void* 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 
133     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         }
138     }
139 
140     rec->fNext = fRec;
141     fRec = rec;
142     return rec->data();
143 }
144 
findS32(const char name[],int32_t * value) const145 bool 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 
findScalar(const char name[],SkScalar * value) const158 bool 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 
findScalars(const char name[],int * count,SkScalar values[]) const171 const 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 nullptr;
183 }
184 
findPtr(const char name[],void ** ptr,PtrProc * proc) const185 bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const {
186     const Rec* rec = this->find(name, kPtr_Type);
187     if (rec) {
188         SkASSERT(rec->fDataCount == 1);
189         const PtrPair* pair = (const PtrPair*)rec->data();
190         if (ptr) {
191             *ptr = pair->fPtr;
192         }
193         if (proc) {
194             *proc = pair->fProc;
195         }
196         return true;
197     }
198     return false;
199 }
200 
findString(const char name[]) const201 const char* SkMetaData::findString(const char name[]) const
202 {
203     const Rec* rec = this->find(name, kString_Type);
204     SkASSERT(rec == nullptr || rec->fDataLen == sizeof(char));
205     return rec ? (const char*)rec->data() : nullptr;
206 }
207 
findBool(const char name[],bool * value) const208 bool 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 
findData(const char name[],size_t * length) const221 const 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 nullptr;
231 }
232 
find(const char name[],Type type) const233 const 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 nullptr;
243 }
244 
remove(const char name[],Type type)245 bool SkMetaData::remove(const char name[], Type type) {
246     Rec* rec = fRec;
247     Rec* prev = nullptr;
248     while (rec) {
249         Rec* next = rec->fNext;
250         if (rec->fType == type && !strcmp(rec->name(), name)) {
251             if (prev) {
252                 prev->fNext = next;
253             } else {
254                 fRec = next;
255             }
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             }
263             Rec::Free(rec);
264             return true;
265         }
266         prev = rec;
267         rec = next;
268     }
269     return false;
270 }
271 
removeS32(const char name[])272 bool SkMetaData::removeS32(const char name[])
273 {
274     return this->remove(name, kS32_Type);
275 }
276 
removeScalar(const char name[])277 bool SkMetaData::removeScalar(const char name[])
278 {
279     return this->remove(name, kScalar_Type);
280 }
281 
removeString(const char name[])282 bool SkMetaData::removeString(const char name[])
283 {
284     return this->remove(name, kString_Type);
285 }
286 
removePtr(const char name[])287 bool SkMetaData::removePtr(const char name[])
288 {
289     return this->remove(name, kPtr_Type);
290 }
291 
removeBool(const char name[])292 bool SkMetaData::removeBool(const char name[])
293 {
294     return this->remove(name, kBool_Type);
295 }
296 
removeData(const char name[])297 bool SkMetaData::removeData(const char name[]) {
298     return this->remove(name, kData_Type);
299 }
300 
301 ///////////////////////////////////////////////////////////////////////////////
302 
Iter(const SkMetaData & metadata)303 SkMetaData::Iter::Iter(const SkMetaData& metadata) {
304     fRec = metadata.fRec;
305 }
306 
reset(const SkMetaData & metadata)307 void SkMetaData::Iter::reset(const SkMetaData& metadata) {
308     fRec = metadata.fRec;
309 }
310 
next(SkMetaData::Type * t,int * count)311 const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
312     const char* name = nullptr;
313 
314     if (fRec) {
315         if (t) {
316             *t = (SkMetaData::Type)fRec->fType;
317         }
318         if (count) {
319             *count = fRec->fDataCount;
320         }
321         name = fRec->name();
322 
323         fRec = fRec->fNext;
324     }
325     return name;
326 }
327 
328 ///////////////////////////////////////////////////////////////////////////////
329 
Alloc(size_t size)330 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
331     return (Rec*)sk_malloc_throw(size);
332 }
333 
Free(Rec * rec)334 void SkMetaData::Rec::Free(Rec* rec) {
335     sk_free(rec);
336 }
337