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