Home | History | Annotate | Download | only in core
      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