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 20 SkMetaData::SkMetaData() : fRec(NULL) 21 { 22 } 23 24 SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL) 25 { 26 *this = src; 27 } 28 29 SkMetaData::~SkMetaData() 30 { 31 this->reset(); 32 } 33 34 void 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 46 SkMetaData& 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 59 void SkMetaData::setS32(const char name[], int32_t value) 60 { 61 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1); 62 } 63 64 void SkMetaData::setScalar(const char name[], SkScalar value) 65 { 66 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); 67 } 68 69 SkScalar* 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 77 void SkMetaData::setString(const char name[], const char value[]) 78 { 79 (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); 80 } 81 82 void SkMetaData::setPtr(const char name[], void* ptr) 83 { 84 (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1); 85 } 86 87 void SkMetaData::setBool(const char name[], bool value) 88 { 89 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); 90 } 91 92 void* 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 143 bool 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 156 bool 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 169 const 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 183 bool 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 196 const 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 203 bool 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 216 const 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 228 bool 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 250 bool SkMetaData::removeS32(const char name[]) 251 { 252 return this->remove(name, kS32_Type); 253 } 254 255 bool SkMetaData::removeScalar(const char name[]) 256 { 257 return this->remove(name, kScalar_Type); 258 } 259 260 bool SkMetaData::removeString(const char name[]) 261 { 262 return this->remove(name, kString_Type); 263 } 264 265 bool SkMetaData::removePtr(const char name[]) 266 { 267 return this->remove(name, kPtr_Type); 268 } 269 270 bool SkMetaData::removeBool(const char name[]) 271 { 272 return this->remove(name, kBool_Type); 273 } 274 275 /////////////////////////////////////////////////////////////////////////////////// 276 277 SkMetaData::Iter::Iter(const SkMetaData& metadata) 278 { 279 fRec = metadata.fRec; 280 } 281 282 void SkMetaData::Iter::reset(const SkMetaData& metadata) 283 { 284 fRec = metadata.fRec; 285 } 286 287 const 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 306 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) 307 { 308 return (Rec*)sk_malloc_throw(size); 309 } 310 311 void SkMetaData::Rec::Free(Rec* rec) 312 { 313 sk_free(rec); 314 } 315 316 /////////////////////////////////////////////////////////////////////////////////// 317 /////////////////////////////////////////////////////////////////////////////////// 318 319 #ifdef SK_DEBUG 320 321 void 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