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