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