Chromium Code Reviews| Index: src/core/SkValidatingReadBuffer.cpp |
| diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp |
| index 52006f23ad066391ee9731f942d737b54170c8b6..c6c3fc50bc6ca04134a3466476e740575df26589 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,34 @@ bool SkValidatingReadBuffer::validateAvailable(size_t size) { |
| } |
| SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) { |
| - SkString name; |
| - this->readString(&name); |
| + uint8_t firstByte = this->peekByte(); |
|
reed1
2016/04/22 15:06:08
Can we assert that there is no "factory" here (sin
msarett
2016/04/22 18:54:09
I've made a protected getter for the factoryCount
|
| if (fError) { |
| return nullptr; |
| } |
| + SkString name; |
|
reed1
2016/04/22 15:06:08
Is it easy to share this section in a helper funct
msarett
2016/04/22 18:54:09
I refactored this, but it ultimately didn't work (
|
| + 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 +262,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(); |
| } |