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