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