12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- /*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/codec/SkStreamBuffer.h"
- SkStreamBuffer::SkStreamBuffer(std::unique_ptr<SkStream> stream)
- : fStream(std::move(stream))
- , fPosition(0)
- , fBytesBuffered(0)
- , fHasLengthAndPosition(fStream->hasLength() && fStream->hasPosition())
- , fTrulyBuffered(0)
- {}
- SkStreamBuffer::~SkStreamBuffer() {
- fMarkedData.foreach([](size_t, SkData** data) { (*data)->unref(); });
- }
- const char* SkStreamBuffer::get() const {
- SkASSERT(fBytesBuffered >= 1);
- if (fHasLengthAndPosition && fTrulyBuffered < fBytesBuffered) {
- const size_t bytesToBuffer = fBytesBuffered - fTrulyBuffered;
- char* dst = SkTAddOffset<char>(const_cast<char*>(fBuffer), fTrulyBuffered);
- SkDEBUGCODE(const size_t bytesRead =)
- // This stream is rewindable, so it should be safe to call the non-const
- // read()
- const_cast<SkStream*>(fStream.get())->read(dst, bytesToBuffer);
- SkASSERT(bytesRead == bytesToBuffer);
- fTrulyBuffered = fBytesBuffered;
- }
- return fBuffer;
- }
- bool SkStreamBuffer::buffer(size_t totalBytesToBuffer) {
- // FIXME (scroggo): What should we do if the client tries to read too much?
- // Should not be a problem in GIF.
- SkASSERT(totalBytesToBuffer <= kMaxSize);
- if (totalBytesToBuffer <= fBytesBuffered) {
- return true;
- }
- if (fHasLengthAndPosition) {
- const size_t remaining = fStream->getLength() - fStream->getPosition() + fTrulyBuffered;
- fBytesBuffered = SkTMin(remaining, totalBytesToBuffer);
- } else {
- const size_t extraBytes = totalBytesToBuffer - fBytesBuffered;
- const size_t bytesBuffered = fStream->read(fBuffer + fBytesBuffered, extraBytes);
- fBytesBuffered += bytesBuffered;
- }
- return fBytesBuffered == totalBytesToBuffer;
- }
- size_t SkStreamBuffer::markPosition() {
- SkASSERT(fBytesBuffered >= 1);
- if (!fHasLengthAndPosition) {
- sk_sp<SkData> data(SkData::MakeWithCopy(fBuffer, fBytesBuffered));
- SkASSERT(nullptr == fMarkedData.find(fPosition));
- fMarkedData.set(fPosition, data.release());
- }
- return fPosition;
- }
- sk_sp<SkData> SkStreamBuffer::getDataAtPosition(size_t position, size_t length) {
- if (!fHasLengthAndPosition) {
- SkData** data = fMarkedData.find(position);
- SkASSERT(data);
- SkASSERT((*data)->size() == length);
- return sk_ref_sp<SkData>(*data);
- }
- SkASSERT(length <= fStream->getLength() &&
- position <= fStream->getLength() - length);
- const size_t oldPosition = fStream->getPosition();
- if (!fStream->seek(position)) {
- return nullptr;
- }
- sk_sp<SkData> data(SkData::MakeUninitialized(length));
- void* dst = data->writable_data();
- const bool success = fStream->read(dst, length) == length;
- fStream->seek(oldPosition);
- return success ? data : nullptr;
- }
|