1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/core/SkDescriptor.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include <new>
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
13cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
14cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cistd::unique_ptr<SkDescriptor> SkDescriptor::Alloc(size_t length) {
17cb93a386Sopenharmony_ci    SkASSERT(SkAlign4(length) == length);
18cb93a386Sopenharmony_ci    void* allocation = ::operator new (length);
19cb93a386Sopenharmony_ci    return std::unique_ptr<SkDescriptor>(new (allocation) SkDescriptor{});
20cb93a386Sopenharmony_ci}
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_civoid SkDescriptor::operator delete(void* p) { ::operator delete(p); }
23cb93a386Sopenharmony_civoid* SkDescriptor::operator new(size_t) {
24cb93a386Sopenharmony_ci    SK_ABORT("Descriptors are created with placement new.");
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_civoid* SkDescriptor::addEntry(uint32_t tag, size_t length, const void* data) {
28cb93a386Sopenharmony_ci    SkASSERT(tag);
29cb93a386Sopenharmony_ci    SkASSERT(SkAlign4(length) == length);
30cb93a386Sopenharmony_ci    SkASSERT(this->findEntry(tag, nullptr) == nullptr);
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    Entry* entry = (Entry*)((char*)this + fLength);
33cb93a386Sopenharmony_ci    entry->fTag = tag;
34cb93a386Sopenharmony_ci    entry->fLen = SkToU32(length);
35cb93a386Sopenharmony_ci    if (data) {
36cb93a386Sopenharmony_ci        memcpy(entry + 1, data, length);
37cb93a386Sopenharmony_ci    }
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    fCount += 1;
40cb93a386Sopenharmony_ci    fLength = SkToU32(fLength + sizeof(Entry) + length);
41cb93a386Sopenharmony_ci    return (entry + 1); // return its data
42cb93a386Sopenharmony_ci}
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_civoid SkDescriptor::computeChecksum() {
45cb93a386Sopenharmony_ci    fChecksum = SkDescriptor::ComputeChecksum(this);
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ciconst void* SkDescriptor::findEntry(uint32_t tag, uint32_t* length) const {
49cb93a386Sopenharmony_ci    const Entry* entry = (const Entry*)(this + 1);
50cb93a386Sopenharmony_ci    int          count = fCount;
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    while (--count >= 0) {
53cb93a386Sopenharmony_ci        if (entry->fTag == tag) {
54cb93a386Sopenharmony_ci            if (length) {
55cb93a386Sopenharmony_ci                *length = entry->fLen;
56cb93a386Sopenharmony_ci            }
57cb93a386Sopenharmony_ci            return entry + 1;
58cb93a386Sopenharmony_ci        }
59cb93a386Sopenharmony_ci        entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    return nullptr;
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_cistd::unique_ptr<SkDescriptor> SkDescriptor::copy() const {
65cb93a386Sopenharmony_ci    std::unique_ptr<SkDescriptor> desc = SkDescriptor::Alloc(fLength);
66cb93a386Sopenharmony_ci    memcpy(desc.get(), this, fLength);
67cb93a386Sopenharmony_ci    return desc;
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_cibool SkDescriptor::operator==(const SkDescriptor& other) const {
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    // the first value we should look at is the checksum, so this loop
73cb93a386Sopenharmony_ci    // should terminate early if they descriptors are different.
74cb93a386Sopenharmony_ci    // NOTE: if we wrote a sentinel value at the end of each, we could
75cb93a386Sopenharmony_ci    //       remove the aa < stop test in the loop...
76cb93a386Sopenharmony_ci    const uint32_t* aa = (const uint32_t*)this;
77cb93a386Sopenharmony_ci    const uint32_t* bb = (const uint32_t*)&other;
78cb93a386Sopenharmony_ci    const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
79cb93a386Sopenharmony_ci    do {
80cb93a386Sopenharmony_ci        if (*aa++ != *bb++)
81cb93a386Sopenharmony_ci            return false;
82cb93a386Sopenharmony_ci    } while (aa < stop);
83cb93a386Sopenharmony_ci    return true;
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ciSkString SkDescriptor::dumpRec() const {
87cb93a386Sopenharmony_ci    const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>(
88cb93a386Sopenharmony_ci            this->findEntry(kRec_SkDescriptorTag, nullptr));
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    SkString result;
91cb93a386Sopenharmony_ci    result.appendf("    Checksum: %x\n", fChecksum);
92cb93a386Sopenharmony_ci    if (rec != nullptr) {
93cb93a386Sopenharmony_ci        result.append(rec->dump());
94cb93a386Sopenharmony_ci    }
95cb93a386Sopenharmony_ci    return result;
96cb93a386Sopenharmony_ci}
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ciuint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
99cb93a386Sopenharmony_ci    const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
100cb93a386Sopenharmony_ci    size_t len = desc->fLength - sizeof(uint32_t);
101cb93a386Sopenharmony_ci    return SkOpts::hash(ptr, len);
102cb93a386Sopenharmony_ci}
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_cibool SkDescriptor::isValid() const {
105cb93a386Sopenharmony_ci    uint32_t count = fCount;
106cb93a386Sopenharmony_ci    size_t lengthRemaining = this->fLength;
107cb93a386Sopenharmony_ci    if (lengthRemaining < sizeof(SkDescriptor)) {
108cb93a386Sopenharmony_ci        return false;
109cb93a386Sopenharmony_ci    }
110cb93a386Sopenharmony_ci    lengthRemaining -= sizeof(SkDescriptor);
111cb93a386Sopenharmony_ci    size_t offset = sizeof(SkDescriptor);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    while (lengthRemaining > 0 && count > 0) {
114cb93a386Sopenharmony_ci        if (lengthRemaining < sizeof(Entry)) {
115cb93a386Sopenharmony_ci            return false;
116cb93a386Sopenharmony_ci        }
117cb93a386Sopenharmony_ci        lengthRemaining -= sizeof(Entry);
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci        const Entry* entry = (const Entry*)(reinterpret_cast<const char*>(this) + offset);
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci        if (lengthRemaining < entry->fLen) {
122cb93a386Sopenharmony_ci            return false;
123cb93a386Sopenharmony_ci        }
124cb93a386Sopenharmony_ci        lengthRemaining -= entry->fLen;
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci        // rec tags are always a known size.
127cb93a386Sopenharmony_ci        if (entry->fTag == kRec_SkDescriptorTag && entry->fLen != sizeof(SkScalerContextRec)) {
128cb93a386Sopenharmony_ci            return false;
129cb93a386Sopenharmony_ci        }
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci        offset += sizeof(Entry) + entry->fLen;
132cb93a386Sopenharmony_ci        count--;
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci    return lengthRemaining == 0 && count == 0;
135cb93a386Sopenharmony_ci}
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor() = default;
138cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); }
139cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); }
140cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(const SkAutoDescriptor& that) {
141cb93a386Sopenharmony_ci    this->reset(*that.getDesc());
142cb93a386Sopenharmony_ci}
143cb93a386Sopenharmony_ciSkAutoDescriptor& SkAutoDescriptor::operator=(const SkAutoDescriptor& that) {
144cb93a386Sopenharmony_ci    this->reset(*that.getDesc());
145cb93a386Sopenharmony_ci    return *this;
146cb93a386Sopenharmony_ci}
147cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(SkAutoDescriptor&& that) {
148cb93a386Sopenharmony_ci    if (that.fDesc == (SkDescriptor*)&that.fStorage) {
149cb93a386Sopenharmony_ci        this->reset(*that.getDesc());
150cb93a386Sopenharmony_ci    } else {
151cb93a386Sopenharmony_ci        fDesc = that.fDesc;
152cb93a386Sopenharmony_ci        that.fDesc = nullptr;
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ciSkAutoDescriptor& SkAutoDescriptor::operator=(SkAutoDescriptor&& that) {
156cb93a386Sopenharmony_ci    if (that.fDesc == (SkDescriptor*)&that.fStorage) {
157cb93a386Sopenharmony_ci        this->reset(*that.getDesc());
158cb93a386Sopenharmony_ci    } else {
159cb93a386Sopenharmony_ci        this->free();
160cb93a386Sopenharmony_ci        fDesc = that.fDesc;
161cb93a386Sopenharmony_ci        that.fDesc = nullptr;
162cb93a386Sopenharmony_ci    }
163cb93a386Sopenharmony_ci    return *this;
164cb93a386Sopenharmony_ci}
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ciSkAutoDescriptor::~SkAutoDescriptor() { this->free(); }
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_civoid SkAutoDescriptor::reset(size_t size) {
169cb93a386Sopenharmony_ci    this->free();
170cb93a386Sopenharmony_ci    if (size <= sizeof(fStorage)) {
171cb93a386Sopenharmony_ci        fDesc = new (&fStorage) SkDescriptor{};
172cb93a386Sopenharmony_ci    } else {
173cb93a386Sopenharmony_ci        fDesc = SkDescriptor::Alloc(size).release();
174cb93a386Sopenharmony_ci    }
175cb93a386Sopenharmony_ci}
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_civoid SkAutoDescriptor::reset(const SkDescriptor& desc) {
178cb93a386Sopenharmony_ci    size_t size = desc.getLength();
179cb93a386Sopenharmony_ci    this->reset(size);
180cb93a386Sopenharmony_ci    memcpy(fDesc, &desc, size);
181cb93a386Sopenharmony_ci}
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_civoid SkAutoDescriptor::free() {
184cb93a386Sopenharmony_ci    if (fDesc == (SkDescriptor*)&fStorage) {
185cb93a386Sopenharmony_ci        fDesc->~SkDescriptor();
186cb93a386Sopenharmony_ci    } else {
187cb93a386Sopenharmony_ci        delete fDesc;
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci}
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci
192