Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2019 Google Inc.
      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 "SkDescriptor.h"
      9 
     10 #include <new>
     11 
     12 #include "SkOpts.h"
     13 #include "SkTo.h"
     14 #include "SkTypes.h"
     15 
     16 std::unique_ptr<SkDescriptor> SkDescriptor::Alloc(size_t length) {
     17     SkASSERT(SkAlign4(length) == length);
     18     return std::unique_ptr<SkDescriptor>(static_cast<SkDescriptor*>(::operator new (length)));
     19 }
     20 
     21 void SkDescriptor::operator delete(void* p) { ::operator delete(p); }
     22 
     23 void* SkDescriptor::addEntry(uint32_t tag, size_t length, const void* data) {
     24     SkASSERT(tag);
     25     SkASSERT(SkAlign4(length) == length);
     26     SkASSERT(this->findEntry(tag, nullptr) == nullptr);
     27 
     28     Entry* entry = (Entry*)((char*)this + fLength);
     29     entry->fTag = tag;
     30     entry->fLen = SkToU32(length);
     31     if (data) {
     32         memcpy(entry + 1, data, length);
     33     }
     34 
     35     fCount += 1;
     36     fLength = SkToU32(fLength + sizeof(Entry) + length);
     37     return (entry + 1); // return its data
     38 }
     39 
     40 void SkDescriptor::computeChecksum() {
     41     fChecksum = SkDescriptor::ComputeChecksum(this);
     42 }
     43 
     44 const void* SkDescriptor::findEntry(uint32_t tag, uint32_t* length) const {
     45     const Entry* entry = (const Entry*)(this + 1);
     46     int          count = fCount;
     47 
     48     while (--count >= 0) {
     49         if (entry->fTag == tag) {
     50             if (length) {
     51                 *length = entry->fLen;
     52             }
     53             return entry + 1;
     54         }
     55         entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
     56     }
     57     return nullptr;
     58 }
     59 
     60 std::unique_ptr<SkDescriptor> SkDescriptor::copy() const {
     61     std::unique_ptr<SkDescriptor> desc = SkDescriptor::Alloc(fLength);
     62     memcpy(desc.get(), this, fLength);
     63     return desc;
     64 }
     65 
     66 bool SkDescriptor::operator==(const SkDescriptor& other) const {
     67 
     68     // the first value we should look at is the checksum, so this loop
     69     // should terminate early if they descriptors are different.
     70     // NOTE: if we wrote a sentinel value at the end of each, we could
     71     //       remove the aa < stop test in the loop...
     72     const uint32_t* aa = (const uint32_t*)this;
     73     const uint32_t* bb = (const uint32_t*)&other;
     74     const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
     75     do {
     76         if (*aa++ != *bb++)
     77             return false;
     78     } while (aa < stop);
     79     return true;
     80 }
     81 
     82 uint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
     83     const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
     84     size_t len = desc->fLength - sizeof(uint32_t);
     85     return SkOpts::hash(ptr, len);
     86 }
     87 
     88 SkAutoDescriptor::SkAutoDescriptor() = default;
     89 SkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); }
     90 SkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); }
     91 SkAutoDescriptor::~SkAutoDescriptor() { this->free(); }
     92 
     93 void SkAutoDescriptor::reset(size_t size) {
     94     this->free();
     95     if (size <= sizeof(fStorage)) {
     96         fDesc = reinterpret_cast<SkDescriptor*>(&fStorage);
     97     } else {
     98         fDesc = SkDescriptor::Alloc(size).release();
     99     }
    100 }
    101 
    102 void SkAutoDescriptor::reset(const SkDescriptor& desc) {
    103     size_t size = desc.getLength();
    104     this->reset(size);
    105     memcpy(fDesc, &desc, size);
    106 }
    107 
    108 void SkAutoDescriptor::free() {
    109     if (fDesc != (SkDescriptor*)&fStorage) {
    110         delete fDesc;
    111     }
    112 }
    113 
    114 
    115