• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "tools/SkMetaData.h"
9 
10 #include "include/private/SkMalloc.h"
11 #include "include/private/SkTo.h"
12 
reset()13 void SkMetaData::reset()
14 {
15     Rec* rec = fRec;
16     while (rec) {
17         Rec* next = rec->fNext;
18         Rec::Free(rec);
19         rec = next;
20     }
21     fRec = nullptr;
22 }
23 
setS32(const char name[],int32_t value)24 void SkMetaData::setS32(const char name[], int32_t value)
25 {
26     (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
27 }
28 
setScalar(const char name[],SkScalar value)29 void SkMetaData::setScalar(const char name[], SkScalar value)
30 {
31     (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
32 }
33 
setScalars(const char name[],int count,const SkScalar values[])34 SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
35 {
36     SkASSERT(count > 0);
37     if (count > 0)
38         return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
39     return nullptr;
40 }
41 
setPtr(const char name[],void * ptr)42 void SkMetaData::setPtr(const char name[], void* ptr) {
43     (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
44 }
45 
setBool(const char name[],bool value)46 void SkMetaData::setBool(const char name[], bool value)
47 {
48     (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
49 }
50 
set(const char name[],const void * data,size_t dataSize,Type type,int count)51 void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
52 {
53     SkASSERT(name);
54     SkASSERT(dataSize);
55     SkASSERT(count > 0);
56 
57     FindResult result = this->findWithPrev(name, type);
58 
59     Rec* rec;
60     bool reuseRec = result.rec &&
61                     result.rec->fDataLen == dataSize &&
62                     result.rec->fDataCount == count;
63     if (reuseRec) {
64         rec = result.rec;
65     } else {
66         size_t len = strlen(name);
67         rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
68         rec->fType = SkToU8(type);
69         rec->fDataLen = SkToU8(dataSize);
70         rec->fDataCount = SkToU16(count);
71 
72         memcpy(rec->name(), name, len + 1);
73     }
74     if (data) {
75         memcpy(rec->data(), data, dataSize * count);
76     }
77 
78     if (reuseRec) {
79         // Do nothing, reused
80     } else if (result.rec) {
81         // Had one, but had to create a new one. Invalidates iterators.
82         // Delayed removal since name or data may have been in the result.rec.
83         this->remove(result);
84         if (result.prev) {
85             rec->fNext = result.prev->fNext;
86             result.prev->fNext = rec;
87         }
88     } else {
89         // Adding a new one, stick it at head.
90         rec->fNext = fRec;
91         fRec = rec;
92     }
93     return rec->data();
94 }
95 
findS32(const char name[],int32_t * value) const96 bool SkMetaData::findS32(const char name[], int32_t* value) const
97 {
98     const Rec* rec = this->find(name, kS32_Type);
99     if (rec)
100     {
101         SkASSERT(rec->fDataCount == 1);
102         if (value)
103             *value = *(const int32_t*)rec->data();
104         return true;
105     }
106     return false;
107 }
108 
findScalar(const char name[],SkScalar * value) const109 bool SkMetaData::findScalar(const char name[], SkScalar* value) const
110 {
111     const Rec* rec = this->find(name, kScalar_Type);
112     if (rec)
113     {
114         SkASSERT(rec->fDataCount == 1);
115         if (value)
116             *value = *(const SkScalar*)rec->data();
117         return true;
118     }
119     return false;
120 }
121 
findScalars(const char name[],int * count,SkScalar values[]) const122 const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
123 {
124     const Rec* rec = this->find(name, kScalar_Type);
125     if (rec)
126     {
127         if (count)
128             *count = rec->fDataCount;
129         if (values)
130             memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
131         return (const SkScalar*)rec->data();
132     }
133     return nullptr;
134 }
135 
findPtr(const char name[],void ** ptr) const136 bool SkMetaData::findPtr(const char name[], void** ptr) const {
137     const Rec* rec = this->find(name, kPtr_Type);
138     if (rec) {
139         SkASSERT(rec->fDataCount == 1);
140         void** found = (void**)rec->data();
141         if (ptr) {
142             *ptr = *found;
143         }
144         return true;
145     }
146     return false;
147 }
148 
findBool(const char name[],bool * value) const149 bool SkMetaData::findBool(const char name[], bool* value) const
150 {
151     const Rec* rec = this->find(name, kBool_Type);
152     if (rec)
153     {
154         SkASSERT(rec->fDataCount == 1);
155         if (value)
156             *value = *(const bool*)rec->data();
157         return true;
158     }
159     return false;
160 }
161 
findWithPrev(const char name[],Type type) const162 SkMetaData::FindResult SkMetaData::findWithPrev(const char name[], Type type) const {
163     FindResult current { fRec, nullptr };
164     while (current.rec) {
165         if (current.rec->fType == type && !strcmp(current.rec->name(), name))
166             return current;
167         current.prev = current.rec;
168         current.rec = current.rec->fNext;
169     }
170     return current;
171 }
172 
173 
find(const char name[],Type type) const174 const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const {
175     return this->findWithPrev(name, type).rec;
176 }
177 
remove(FindResult result)178 void SkMetaData::remove(FindResult result) {
179     SkASSERT(result.rec);
180     if (result.prev) {
181         result.prev->fNext = result.rec->fNext;
182     } else {
183         fRec = result.rec->fNext;
184     }
185     Rec::Free(result.rec);
186 }
187 
remove(const char name[],Type type)188 bool SkMetaData::remove(const char name[], Type type) {
189     FindResult result = this->findWithPrev(name, type);
190     if (!result.rec) {
191         return false;
192     }
193     this->remove(result);
194     return true;
195 }
196 
removeS32(const char name[])197 bool SkMetaData::removeS32(const char name[])
198 {
199     return this->remove(name, kS32_Type);
200 }
201 
removeScalar(const char name[])202 bool SkMetaData::removeScalar(const char name[])
203 {
204     return this->remove(name, kScalar_Type);
205 }
206 
removePtr(const char name[])207 bool SkMetaData::removePtr(const char name[])
208 {
209     return this->remove(name, kPtr_Type);
210 }
211 
removeBool(const char name[])212 bool SkMetaData::removeBool(const char name[])
213 {
214     return this->remove(name, kBool_Type);
215 }
216 
217 ///////////////////////////////////////////////////////////////////////////////
218 
Iter(const SkMetaData & metadata)219 SkMetaData::Iter::Iter(const SkMetaData& metadata) {
220     fRec = metadata.fRec;
221 }
222 
reset(const SkMetaData & metadata)223 void SkMetaData::Iter::reset(const SkMetaData& metadata) {
224     fRec = metadata.fRec;
225 }
226 
next(SkMetaData::Type * t,int * count)227 const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
228     const char* name = nullptr;
229 
230     if (fRec) {
231         if (t) {
232             *t = (SkMetaData::Type)fRec->fType;
233         }
234         if (count) {
235             *count = fRec->fDataCount;
236         }
237         name = fRec->name();
238 
239         fRec = fRec->fNext;
240     }
241     return name;
242 }
243 
244 ///////////////////////////////////////////////////////////////////////////////
245 
Alloc(size_t size)246 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
247     return (Rec*)sk_malloc_throw(size);
248 }
249 
Free(Rec * rec)250 void SkMetaData::Rec::Free(Rec* rec) {
251     sk_free(rec);
252 }
253