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 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 30 SkMetaData::SkMetaData() : fRec(nullptr) 31 { 32 } 33 34 SkMetaData::SkMetaData(const SkMetaData& src) : fRec(nullptr) 35 { 36 *this = src; 37 } 38 39 SkMetaData::~SkMetaData() 40 { 41 this->reset(); 42 } 43 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 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 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 79 void SkMetaData::setScalar(const char name[], SkScalar value) 80 { 81 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); 82 } 83 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 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 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 102 void SkMetaData::setBool(const char name[], bool value) 103 { 104 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); 105 } 106 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 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 145 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 158 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 171 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 185 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 201 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 208 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 221 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 233 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 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 272 bool SkMetaData::removeS32(const char name[]) 273 { 274 return this->remove(name, kS32_Type); 275 } 276 277 bool SkMetaData::removeScalar(const char name[]) 278 { 279 return this->remove(name, kScalar_Type); 280 } 281 282 bool SkMetaData::removeString(const char name[]) 283 { 284 return this->remove(name, kString_Type); 285 } 286 287 bool SkMetaData::removePtr(const char name[]) 288 { 289 return this->remove(name, kPtr_Type); 290 } 291 292 bool SkMetaData::removeBool(const char name[]) 293 { 294 return this->remove(name, kBool_Type); 295 } 296 297 bool SkMetaData::removeData(const char name[]) { 298 return this->remove(name, kData_Type); 299 } 300 301 /////////////////////////////////////////////////////////////////////////////// 302 303 SkMetaData::Iter::Iter(const SkMetaData& metadata) { 304 fRec = metadata.fRec; 305 } 306 307 void SkMetaData::Iter::reset(const SkMetaData& metadata) { 308 fRec = metadata.fRec; 309 } 310 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 330 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) { 331 return (Rec*)sk_malloc_throw(size); 332 } 333 334 void SkMetaData::Rec::Free(Rec* rec) { 335 sk_free(rec); 336 } 337