blob: 99ab2ce221170f8627a1b0c46027a1f1708e3fc8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
Hal Canarye574f1e2019-07-15 14:01:37 -04008#include "tools/SkMetaData.h"
Herb Derbyd7b34a52017-03-20 11:19:23 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/private/SkMalloc.h"
11#include "include/private/SkTo.h"
reed@google.come7330712011-03-30 18:23:21 +000012
reed@android.com8a1c16f2008-12-17 15:59:43 +000013void SkMetaData::reset()
14{
15 Rec* rec = fRec;
reed@google.come7330712011-03-30 18:23:21 +000016 while (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000017 Rec* next = rec->fNext;
18 Rec::Free(rec);
19 rec = next;
20 }
halcanary96fcdcc2015-08-27 07:41:13 -070021 fRec = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000022}
23
reed@android.com8a1c16f2008-12-17 15:59:43 +000024void SkMetaData::setS32(const char name[], int32_t value)
25{
26 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
27}
28
29void SkMetaData::setScalar(const char name[], SkScalar value)
30{
31 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
32}
33
34SkScalar* 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);
halcanary96fcdcc2015-08-27 07:41:13 -070039 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000040}
41
Hal Canaryca9e1872019-07-25 10:36:30 -040042void SkMetaData::setPtr(const char name[], void* ptr) {
43 (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
46void SkMetaData::setBool(const char name[], bool value)
47{
48 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
49}
50
51void* 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
Ben Wagner19684732020-08-21 16:52:48 -040057 FindResult result = this->findWithPrev(name, type);
reed@android.com8a1c16f2008-12-17 15:59:43 +000058
Ben Wagner19684732020-08-21 16:52:48 -040059 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);
reed@android.com8a1c16f2008-12-17 15:59:43 +000071
Ben Wagner19684732020-08-21 16:52:48 -040072 memcpy(rec->name(), name, len + 1);
73 }
74 if (data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000075 memcpy(rec->data(), data, dataSize * count);
Ben Wagner19684732020-08-21 16:52:48 -040076 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000077
Ben Wagner19684732020-08-21 16:52:48 -040078 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 return rec->data();
94}
95
96bool 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
109bool 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
122const 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 }
halcanary96fcdcc2015-08-27 07:41:13 -0700133 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134}
135
Hal Canaryca9e1872019-07-25 10:36:30 -0400136bool SkMetaData::findPtr(const char name[], void** ptr) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 const Rec* rec = this->find(name, kPtr_Type);
reed@google.come7330712011-03-30 18:23:21 +0000138 if (rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 SkASSERT(rec->fDataCount == 1);
Hal Canaryca9e1872019-07-25 10:36:30 -0400140 void** found = (void**)rec->data();
reed@google.come7330712011-03-30 18:23:21 +0000141 if (ptr) {
Hal Canaryca9e1872019-07-25 10:36:30 -0400142 *ptr = *found;
reed@google.come7330712011-03-30 18:23:21 +0000143 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 return true;
145 }
146 return false;
147}
148
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149bool 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
Ben Wagner19684732020-08-21 16:52:48 -0400162SkMetaData::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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169 }
Ben Wagner19684732020-08-21 16:52:48 -0400170 return current;
171}
172
173
174const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const {
175 return this->findWithPrev(name, type).rec;
176}
177
178void 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);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186}
187
reed@google.come7330712011-03-30 18:23:21 +0000188bool SkMetaData::remove(const char name[], Type type) {
Ben Wagner19684732020-08-21 16:52:48 -0400189 FindResult result = this->findWithPrev(name, type);
190 if (!result.rec) {
191 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192 }
Ben Wagner19684732020-08-21 16:52:48 -0400193 this->remove(result);
194 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195}
196
197bool SkMetaData::removeS32(const char name[])
198{
199 return this->remove(name, kS32_Type);
200}
201
202bool SkMetaData::removeScalar(const char name[])
203{
204 return this->remove(name, kScalar_Type);
205}
206
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207bool SkMetaData::removePtr(const char name[])
208{
209 return this->remove(name, kPtr_Type);
210}
211
212bool SkMetaData::removeBool(const char name[])
213{
214 return this->remove(name, kBool_Type);
215}
216
reed@google.come7330712011-03-30 18:23:21 +0000217///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218
reed@google.come7330712011-03-30 18:23:21 +0000219SkMetaData::Iter::Iter(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 fRec = metadata.fRec;
221}
222
reed@google.come7330712011-03-30 18:23:21 +0000223void SkMetaData::Iter::reset(const SkMetaData& metadata) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000224 fRec = metadata.fRec;
225}
226
reed@google.come7330712011-03-30 18:23:21 +0000227const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) {
halcanary96fcdcc2015-08-27 07:41:13 -0700228 const char* name = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229
reed@google.come7330712011-03-30 18:23:21 +0000230 if (fRec) {
231 if (t) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232 *t = (SkMetaData::Type)fRec->fType;
reed@google.come7330712011-03-30 18:23:21 +0000233 }
234 if (count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000235 *count = fRec->fDataCount;
reed@google.come7330712011-03-30 18:23:21 +0000236 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237 name = fRec->name();
238
239 fRec = fRec->fNext;
240 }
241 return name;
242}
243
reed@google.come7330712011-03-30 18:23:21 +0000244///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245
reed@google.come7330712011-03-30 18:23:21 +0000246SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247 return (Rec*)sk_malloc_throw(size);
248}
249
reed@google.come7330712011-03-30 18:23:21 +0000250void SkMetaData::Rec::Free(Rec* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 sk_free(rec);
252}