Index: third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
index 874b7d06e12a3f288ac7c7d56ac845b6f1a6bcfa..1d53d47486886a9f6ab030f6ae4063d2b27aebd7 100644 |
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
@@ -107,12 +107,57 @@ std::unique_ptr<ImageDecoder> ImageDecoder::create(SniffResult sniffResult, Alph |
return nullptr; |
} |
+namespace { |
Peter Kasting
2016/08/16 20:12:25
Instead of adding all this, why not just use FastS
f(malita)
2016/08/16 21:54:03
I wasn't familiar with FastSharedBufferReader, goo
|
+ |
+constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; |
+static_assert(kLongestSignatureLength == 14, "kLongestSignatureLength mismatch"); |
+ |
+// Offers contiguous access to the first LEN bytes in the buffer. |
+// If the first segment is large enough to hold all the requested data, we use a pointer to |
+// the actual segment data. |
+// Otherwise, we copy/consolidate the data in a local buffer. |
+template <typename T, size_t LEN> |
+class SpeculativeSegmentReader { |
+ STACK_ALLOCATED(); |
+public: |
+ SpeculativeSegmentReader(const T& data, size_t (*accessSegment)(const T&, const char*&, size_t)) |
+ { |
+ m_dataLen = accessSegment(data, m_data, 0); |
+ if (!m_dataLen || m_dataLen >= LEN) { |
+ // We either don't have any data, or the first segment is large enough. |
+ // Either way, we don't need a copy: just use the actual/contiguous segment data. |
+ return; |
+ } |
+ |
+ // The signature is fragmented: we need to make a copy. |
+ std::copy(m_data, m_data + m_dataLen, m_buffer); |
+ m_data = m_buffer; |
+ |
+ do { |
+ const char* segmentData; |
+ const size_t segmentLen = accessSegment(data, segmentData, m_dataLen); |
+ if (!segmentLen) |
+ break; |
+ const size_t usableLen = std::min(segmentLen, LEN - m_dataLen); |
+ std::copy(segmentData, segmentData + usableLen, m_buffer + m_dataLen); |
+ m_dataLen += usableLen; |
+ } while (m_dataLen < LEN); |
+ } |
+ |
+ const char* data() const { return m_data; } |
+ size_t dataLen() const { return m_dataLen; } |
+ |
+private: |
+ const char* m_data; |
+ size_t m_dataLen; |
+ char m_buffer[LEN]; |
+}; |
+ |
+} // anonymous ns |
+ |
ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, size_t length) |
{ |
- const size_t longestSignatureLength = sizeof("RIFF????WEBPVP") - 1; |
- DCHECK_EQ(14u, longestSignatureLength); |
- |
- if (length < longestSignatureLength) |
+ if (length < kLongestSignatureLength) |
return SniffResult::InsufficientData; |
if (matchesJPEGSignature(contents)) |
return SniffResult::JPEG; |
@@ -131,16 +176,20 @@ ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, |
ImageDecoder::SniffResult ImageDecoder::determineImageType(const SharedBuffer& data) |
{ |
- const char* contents; |
- const size_t length = data.getSomeData<size_t>(contents); |
- return determineImageType(contents, length); |
+ const SpeculativeSegmentReader<SharedBuffer, kLongestSignatureLength> sniffer(data, |
+ [] (const SharedBuffer& data, const char*& segmentData, size_t offset) -> size_t { |
+ return data.getSomeData<size_t>(segmentData, offset); |
+ }); |
+ return determineImageType(sniffer.data(), sniffer.dataLen()); |
} |
ImageDecoder::SniffResult ImageDecoder::determineImageType(const SegmentReader& data) |
{ |
- const char* contents; |
- const size_t length = data.getSomeData(contents, 0); |
- return determineImageType(contents, length); |
+ const SpeculativeSegmentReader<SegmentReader, kLongestSignatureLength> sniffer(data, |
+ [] (const SegmentReader& data, const char*& segmentData, size_t offset) -> size_t { |
+ return data.getSomeData(segmentData, offset); |
+ }); |
+ return determineImageType(sniffer.data(), sniffer.dataLen()); |
} |
size_t ImageDecoder::frameCount() |