1/* libs/graphics/views/SkMetaData.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkMetaData.h" 19 20SkMetaData::SkMetaData() : fRec(NULL) 21{ 22} 23 24SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL) 25{ 26 *this = src; 27} 28 29SkMetaData::~SkMetaData() 30{ 31 this->reset(); 32} 33 34void SkMetaData::reset() 35{ 36 Rec* rec = fRec; 37 while (rec) 38 { 39 Rec* next = rec->fNext; 40 Rec::Free(rec); 41 rec = next; 42 } 43 fRec = NULL; 44} 45 46SkMetaData& SkMetaData::operator=(const SkMetaData& src) 47{ 48 this->reset(); 49 50 const Rec* rec = src.fRec; 51 while (rec) 52 { 53 this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount); 54 rec = rec->fNext; 55 } 56 return *this; 57} 58 59void SkMetaData::setS32(const char name[], int32_t value) 60{ 61 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1); 62} 63 64void SkMetaData::setScalar(const char name[], SkScalar value) 65{ 66 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); 67} 68 69SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[]) 70{ 71 SkASSERT(count > 0); 72 if (count > 0) 73 return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count); 74 return NULL; 75} 76 77void SkMetaData::setString(const char name[], const char value[]) 78{ 79 (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); 80} 81 82void SkMetaData::setPtr(const char name[], void* ptr) 83{ 84 (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1); 85} 86 87void SkMetaData::setBool(const char name[], bool value) 88{ 89 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); 90} 91 92void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count) 93{ 94 SkASSERT(name); 95 SkASSERT(dataSize); 96 SkASSERT(count > 0); 97 98 (void)this->remove(name, type); 99 100 size_t len = strlen(name); 101 Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1); 102 103#ifndef SK_DEBUG 104 rec->fType = SkToU8(type); 105#else 106 rec->fType = type; 107#endif 108 rec->fDataLen = SkToU8(dataSize); 109 rec->fDataCount = SkToU16(count); 110 if (data) 111 memcpy(rec->data(), data, dataSize * count); 112 memcpy(rec->name(), name, len + 1); 113 114#ifdef SK_DEBUG 115 rec->fName = rec->name(); 116 switch (type) { 117 case kS32_Type: 118 rec->fData.fS32 = *(const int32_t*)rec->data(); 119 break; 120 case kScalar_Type: 121 rec->fData.fScalar = *(const SkScalar*)rec->data(); 122 break; 123 case kString_Type: 124 rec->fData.fString = (const char*)rec->data(); 125 break; 126 case kPtr_Type: 127 rec->fData.fPtr = *(void**)rec->data(); 128 break; 129 case kBool_Type: 130 rec->fData.fBool = *(const bool*)rec->data(); 131 break; 132 default: 133 SkASSERT(!"bad type"); 134 break; 135 } 136#endif 137 138 rec->fNext = fRec; 139 fRec = rec; 140 return rec->data(); 141} 142 143bool SkMetaData::findS32(const char name[], int32_t* value) const 144{ 145 const Rec* rec = this->find(name, kS32_Type); 146 if (rec) 147 { 148 SkASSERT(rec->fDataCount == 1); 149 if (value) 150 *value = *(const int32_t*)rec->data(); 151 return true; 152 } 153 return false; 154} 155 156bool SkMetaData::findScalar(const char name[], SkScalar* value) const 157{ 158 const Rec* rec = this->find(name, kScalar_Type); 159 if (rec) 160 { 161 SkASSERT(rec->fDataCount == 1); 162 if (value) 163 *value = *(const SkScalar*)rec->data(); 164 return true; 165 } 166 return false; 167} 168 169const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const 170{ 171 const Rec* rec = this->find(name, kScalar_Type); 172 if (rec) 173 { 174 if (count) 175 *count = rec->fDataCount; 176 if (values) 177 memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen); 178 return (const SkScalar*)rec->data(); 179 } 180 return NULL; 181} 182 183bool SkMetaData::findPtr(const char name[], void** value) const 184{ 185 const Rec* rec = this->find(name, kPtr_Type); 186 if (rec) 187 { 188 SkASSERT(rec->fDataCount == 1); 189 if (value) 190 *value = *(void**)rec->data(); 191 return true; 192 } 193 return false; 194} 195 196const char* SkMetaData::findString(const char name[]) const 197{ 198 const Rec* rec = this->find(name, kString_Type); 199 SkASSERT(rec == NULL || rec->fDataLen == sizeof(char)); 200 return rec ? (const char*)rec->data() : NULL; 201} 202 203bool SkMetaData::findBool(const char name[], bool* value) const 204{ 205 const Rec* rec = this->find(name, kBool_Type); 206 if (rec) 207 { 208 SkASSERT(rec->fDataCount == 1); 209 if (value) 210 *value = *(const bool*)rec->data(); 211 return true; 212 } 213 return false; 214} 215 216const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const 217{ 218 const Rec* rec = fRec; 219 while (rec) 220 { 221 if (rec->fType == type && !strcmp(rec->name(), name)) 222 return rec; 223 rec = rec->fNext; 224 } 225 return NULL; 226} 227 228bool SkMetaData::remove(const char name[], Type type) 229{ 230 Rec* rec = fRec; 231 Rec* prev = NULL; 232 while (rec) 233 { 234 Rec* next = rec->fNext; 235 if (rec->fType == type && !strcmp(rec->name(), name)) 236 { 237 if (prev) 238 prev->fNext = next; 239 else 240 fRec = next; 241 Rec::Free(rec); 242 return true; 243 } 244 prev = rec; 245 rec = next; 246 } 247 return false; 248} 249 250bool SkMetaData::removeS32(const char name[]) 251{ 252 return this->remove(name, kS32_Type); 253} 254 255bool SkMetaData::removeScalar(const char name[]) 256{ 257 return this->remove(name, kScalar_Type); 258} 259 260bool SkMetaData::removeString(const char name[]) 261{ 262 return this->remove(name, kString_Type); 263} 264 265bool SkMetaData::removePtr(const char name[]) 266{ 267 return this->remove(name, kPtr_Type); 268} 269 270bool SkMetaData::removeBool(const char name[]) 271{ 272 return this->remove(name, kBool_Type); 273} 274 275/////////////////////////////////////////////////////////////////////////////////// 276 277SkMetaData::Iter::Iter(const SkMetaData& metadata) 278{ 279 fRec = metadata.fRec; 280} 281 282void SkMetaData::Iter::reset(const SkMetaData& metadata) 283{ 284 fRec = metadata.fRec; 285} 286 287const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) 288{ 289 const char* name = NULL; 290 291 if (fRec) 292 { 293 if (t) 294 *t = (SkMetaData::Type)fRec->fType; 295 if (count) 296 *count = fRec->fDataCount; 297 name = fRec->name(); 298 299 fRec = fRec->fNext; 300 } 301 return name; 302} 303 304/////////////////////////////////////////////////////////////////////////////////// 305 306SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) 307{ 308 return (Rec*)sk_malloc_throw(size); 309} 310 311void SkMetaData::Rec::Free(Rec* rec) 312{ 313 sk_free(rec); 314} 315 316/////////////////////////////////////////////////////////////////////////////////// 317/////////////////////////////////////////////////////////////////////////////////// 318 319#ifdef SK_DEBUG 320 321void SkMetaData::UnitTest() 322{ 323#ifdef SK_SUPPORT_UNITTEST 324 SkMetaData m1; 325 326 SkASSERT(!m1.findS32("int")); 327 SkASSERT(!m1.findScalar("scalar")); 328 SkASSERT(!m1.findString("hello")); 329 SkASSERT(!m1.removeS32("int")); 330 SkASSERT(!m1.removeScalar("scalar")); 331 SkASSERT(!m1.removeString("hello")); 332 SkASSERT(!m1.removeString("true")); 333 SkASSERT(!m1.removeString("false")); 334 335 m1.setS32("int", 12345); 336 m1.setScalar("scalar", SK_Scalar1 * 42); 337 m1.setString("hello", "world"); 338 m1.setPtr("ptr", &m1); 339 m1.setBool("true", true); 340 m1.setBool("false", false); 341 342 int32_t n; 343 SkScalar s; 344 345 m1.setScalar("scalar", SK_Scalar1/2); 346 347 SkASSERT(m1.findS32("int", &n) && n == 12345); 348 SkASSERT(m1.findScalar("scalar", &s) && s == SK_Scalar1/2); 349 SkASSERT(!strcmp(m1.findString("hello"), "world")); 350 SkASSERT(m1.hasBool("true", true)); 351 SkASSERT(m1.hasBool("false", false)); 352 353 Iter iter(m1); 354 const char* name; 355 356 static const struct { 357 const char* fName; 358 SkMetaData::Type fType; 359 int fCount; 360 } gElems[] = { 361 { "int", SkMetaData::kS32_Type, 1 }, 362 { "scalar", SkMetaData::kScalar_Type, 1 }, 363 { "ptr", SkMetaData::kPtr_Type, 1 }, 364 { "hello", SkMetaData::kString_Type, sizeof("world") }, 365 { "true", SkMetaData::kBool_Type, 1 }, 366 { "false", SkMetaData::kBool_Type, 1 } 367 }; 368 369 int loop = 0; 370 int count; 371 SkMetaData::Type t; 372 while ((name = iter.next(&t, &count)) != NULL) 373 { 374 int match = 0; 375 for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++) 376 { 377 if (!strcmp(name, gElems[i].fName)) 378 { 379 match += 1; 380 SkASSERT(gElems[i].fType == t); 381 SkASSERT(gElems[i].fCount == count); 382 } 383 } 384 SkASSERT(match == 1); 385 loop += 1; 386 } 387 SkASSERT(loop == SK_ARRAY_COUNT(gElems)); 388 389 SkASSERT(m1.removeS32("int")); 390 SkASSERT(m1.removeScalar("scalar")); 391 SkASSERT(m1.removeString("hello")); 392 SkASSERT(m1.removeBool("true")); 393 SkASSERT(m1.removeBool("false")); 394 395 SkASSERT(!m1.findS32("int")); 396 SkASSERT(!m1.findScalar("scalar")); 397 SkASSERT(!m1.findString("hello")); 398 SkASSERT(!m1.findBool("true")); 399 SkASSERT(!m1.findBool("false")); 400#endif 401} 402 403#endif 404 405 406