| Index: src/core/SkValidatingReadBuffer.cpp
|
| diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp
|
| index 52006f23ad066391ee9731f942d737b54170c8b6..0ab12b5d0a764dc1b2e7870bb841e0ecc5836029 100644
|
| --- a/src/core/SkValidatingReadBuffer.cpp
|
| +++ b/src/core/SkValidatingReadBuffer.cpp
|
| @@ -86,6 +86,14 @@ int32_t SkValidatingReadBuffer::read32() {
|
| return this->readInt();
|
| }
|
|
|
| +uint8_t SkValidatingReadBuffer::peekByte() {
|
| + if (fReader.available() <= 0) {
|
| + fError = true;
|
| + return 0;
|
| + }
|
| + return *((uint8_t*) fReader.peek());
|
| +}
|
| +
|
| void SkValidatingReadBuffer::readString(SkString* string) {
|
| const size_t len = this->readUInt();
|
| const void* ptr = fReader.peek();
|
| @@ -219,12 +227,37 @@ bool SkValidatingReadBuffer::validateAvailable(size_t size) {
|
| }
|
|
|
| SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
|
| - SkString name;
|
| - this->readString(&name);
|
| + // The validating read buffer always uses strings and string-indices for unflattening.
|
| + SkASSERT(0 == this->factoryCount());
|
| +
|
| + uint8_t firstByte = this->peekByte();
|
| if (fError) {
|
| return nullptr;
|
| }
|
|
|
| + SkString name;
|
| + if (firstByte) {
|
| + // If the first byte is non-zero, the flattenable is specified by a string.
|
| + this->readString(&name);
|
| + if (fError) {
|
| + return nullptr;
|
| + }
|
| +
|
| + // Add the string to the dictionary.
|
| + fFlattenableDict.set(fFlattenableDict.count() + 1, name);
|
| + } else {
|
| + // Read the index. We are guaranteed that the first byte
|
| + // is zeroed, so we must shift down a byte.
|
| + uint32_t index = fReader.readU32() >> 8;
|
| + if (0 == index) {
|
| + return nullptr; // writer failed to give us the flattenable
|
| + }
|
| +
|
| + SkString* namePtr = fFlattenableDict.find(index);
|
| + SkASSERT(namePtr);
|
| + name = *namePtr;
|
| + }
|
| +
|
| // Is this the type we wanted ?
|
| const char* cname = name.c_str();
|
| SkFlattenable::Type baseType;
|
| @@ -232,28 +265,25 @@ SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type)
|
| return nullptr;
|
| }
|
|
|
| - SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname);
|
| - if (nullptr == factory) {
|
| - return nullptr; // writer failed to give us the flattenable
|
| + // Get the factory for this flattenable.
|
| + SkFlattenable::Factory factory = this->getCustomFactory(name);
|
| + if (!factory) {
|
| + factory = SkFlattenable::NameToFactory(cname);
|
| + if (!factory) {
|
| + return nullptr; // writer failed to give us the flattenable
|
| + }
|
| }
|
|
|
| - // if we get here, factory may still be null, but if that is the case, the
|
| - // failure was ours, not the writer.
|
| + // If we get here, the factory is non-null.
|
| sk_sp<SkFlattenable> obj;
|
| uint32_t sizeRecorded = this->readUInt();
|
| - if (factory) {
|
| - size_t offset = fReader.offset();
|
| - obj = (*factory)(*this);
|
| - // check that we read the amount we expected
|
| - size_t sizeRead = fReader.offset() - offset;
|
| - this->validate(sizeRecorded == sizeRead);
|
| - if (fError) {
|
| - obj = nullptr;
|
| - }
|
| - } else {
|
| - // we must skip the remaining data
|
| - this->skip(sizeRecorded);
|
| - SkASSERT(false);
|
| + size_t offset = fReader.offset();
|
| + obj = (*factory)(*this);
|
| + // check that we read the amount we expected
|
| + size_t sizeRead = fReader.offset() - offset;
|
| + this->validate(sizeRecorded == sizeRead);
|
| + if (fError) {
|
| + obj = nullptr;
|
| }
|
| return obj.release();
|
| }
|
|
|