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 13struct PtrPair { 14 void* fPtr; 15 SkMetaData::PtrProc fProc; 16}; 17 18void* 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 30SkMetaData::SkMetaData() : fRec(NULL) 31{ 32} 33 34SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL) 35{ 36 *this = src; 37} 38 39SkMetaData::~SkMetaData() 40{ 41 this->reset(); 42} 43 44void 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 = NULL; 59} 60 61SkMetaData& 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 74void SkMetaData::setS32(const char name[], int32_t value) 75{ 76 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1); 77} 78 79void SkMetaData::setScalar(const char name[], SkScalar value) 80{ 81 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); 82} 83 84SkScalar* 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 NULL; 90} 91 92void SkMetaData::setString(const char name[], const char value[]) 93{ 94 (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); 95} 96 97void 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 102void SkMetaData::setBool(const char name[], bool value) 103{ 104 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); 105} 106 107void SkMetaData::setData(const char name[], const void* data, size_t byteCount) { 108 (void)this->set(name, data, sizeof(char), kData_Type, byteCount); 109} 110 111void* 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 145bool 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 158bool 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 171const 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 NULL; 183} 184 185bool 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 201const char* SkMetaData::findString(const char name[]) const 202{ 203 const Rec* rec = this->find(name, kString_Type); 204 SkASSERT(rec == NULL || rec->fDataLen == sizeof(char)); 205 return rec ? (const char*)rec->data() : NULL; 206} 207 208bool 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 221const 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 NULL; 231} 232 233const 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 NULL; 243} 244 245bool SkMetaData::remove(const char name[], Type type) { 246 Rec* rec = fRec; 247 Rec* prev = NULL; 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 272bool SkMetaData::removeS32(const char name[]) 273{ 274 return this->remove(name, kS32_Type); 275} 276 277bool SkMetaData::removeScalar(const char name[]) 278{ 279 return this->remove(name, kScalar_Type); 280} 281 282bool SkMetaData::removeString(const char name[]) 283{ 284 return this->remove(name, kString_Type); 285} 286 287bool SkMetaData::removePtr(const char name[]) 288{ 289 return this->remove(name, kPtr_Type); 290} 291 292bool SkMetaData::removeBool(const char name[]) 293{ 294 return this->remove(name, kBool_Type); 295} 296 297bool SkMetaData::removeData(const char name[]) { 298 return this->remove(name, kData_Type); 299} 300 301/////////////////////////////////////////////////////////////////////////////// 302 303SkMetaData::Iter::Iter(const SkMetaData& metadata) { 304 fRec = metadata.fRec; 305} 306 307void SkMetaData::Iter::reset(const SkMetaData& metadata) { 308 fRec = metadata.fRec; 309} 310 311const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) { 312 const char* name = NULL; 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 330SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) { 331 return (Rec*)sk_malloc_throw(size); 332} 333 334void SkMetaData::Rec::Free(Rec* rec) { 335 sk_free(rec); 336} 337 338