10a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger/* 20a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * Copyright 2013 Google Inc. 30a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * 40a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be 50a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * found in the LICENSE file. 60a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger */ 70a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 80a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkFrontBufferedStream.h" 9910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkStream.h" 10910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger#include "SkTemplates.h" 11910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 12910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerclass FrontBufferedStream : public SkStreamRewindable { 13910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerpublic: 14910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Called by Create. 15910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger FrontBufferedStream(SkStream*, size_t bufferSize); 16910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 17910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; 18910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 19910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual bool isAtEnd() const SK_OVERRIDE; 20910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 21910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual bool rewind() SK_OVERRIDE; 22910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 23910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual bool hasPosition() const SK_OVERRIDE { return true; } 24910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 25910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual size_t getPosition() const SK_OVERRIDE { return fOffset; } 26910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 271cadd3c11c7d87f410bcaf0f229a89eca7a3a121Derek Sollenberger virtual bool hasLength() const SK_OVERRIDE { return fHasLength; } 28910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 291cadd3c11c7d87f410bcaf0f229a89eca7a3a121Derek Sollenberger virtual size_t getLength() const SK_OVERRIDE { return fLength; } 30910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 31910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger virtual SkStreamRewindable* duplicate() const SK_OVERRIDE { return NULL; } 32910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 33910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerprivate: 34910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkAutoTUnref<SkStream> fStream; 351cadd3c11c7d87f410bcaf0f229a89eca7a3a121Derek Sollenberger const bool fHasLength; 361cadd3c11c7d87f410bcaf0f229a89eca7a3a121Derek Sollenberger const size_t fLength; 37910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Current offset into the stream. Always >= 0. 38910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger size_t fOffset; 39910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Amount that has been buffered by calls to read. Will always be less than 40910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // fBufferSize. 41910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger size_t fBufferedSoFar; 42910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Total size of the buffer. 43910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const size_t fBufferSize; 44910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // FIXME: SkAutoTMalloc throws on failure. Instead, Create should return a 45910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // NULL stream. 46910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkAutoTMalloc<char> fBuffer; 47910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 48910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Read up to size bytes from already buffered data, and copy to 49910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // dst, if non-NULL. Updates fOffset. Assumes that fOffset is less 50910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // than fBufferedSoFar. 51910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger size_t readFromBuffer(char* dst, size_t size); 52910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 53910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Buffer up to size bytes from the stream, and copy to dst if non- 54910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // NULL. Updates fOffset and fBufferedSoFar. Assumes that fOffset is 55910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // less than fBufferedSoFar, and size is greater than 0. 56910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger size_t bufferAndWriteTo(char* dst, size_t size); 57910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 58910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Read up to size bytes directly from the stream and into dst if non- 59910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // NULL. Updates fOffset. Assumes fOffset is at or beyond the buffered 60910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // data, and size is greater than 0. 61910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger size_t readDirectlyFromStream(char* dst, size_t size); 62910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 63910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger typedef SkStream INHERITED; 64910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}; 650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 660a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerSkStreamRewindable* SkFrontBufferedStream::Create(SkStream* stream, size_t bufferSize) { 670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (NULL == stream) { 680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return NULL; 690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 70910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkNEW_ARGS(FrontBufferedStream, (stream, bufferSize)); 710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 73910f694aefb0b671dd8522a9afe9b6be645701c1Derek SollenbergerFrontBufferedStream::FrontBufferedStream(SkStream* stream, size_t bufferSize) 740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger : fStream(SkRef(stream)) 759d69b801ead364f1c43d5adb3ccbb5c5c98b3999Leon Scroggins III , fHasLength(stream->hasPosition() && stream->hasLength()) 769d69b801ead364f1c43d5adb3ccbb5c5c98b3999Leon Scroggins III , fLength(stream->getLength() - stream->getPosition()) 770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fOffset(0) 780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fBufferedSoFar(0) 790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fBufferSize(bufferSize) 800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger , fBuffer(bufferSize) {} 810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 82910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerbool FrontBufferedStream::isAtEnd() const { 830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (fOffset < fBufferedSoFar) { 840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Even if the underlying stream is at the end, this stream has been 850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // rewound after buffering, so it is not at the end. 860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return false; 870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return fStream->isAtEnd(); 900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 92910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerbool FrontBufferedStream::rewind() { 930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Only allow a rewind if we have not exceeded the buffer. 940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (fOffset <= fBufferSize) { 950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fOffset = 0; 960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return true; 970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return false; 990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 101910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergersize_t FrontBufferedStream::readFromBuffer(char* dst, size_t size) { 1020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fOffset < fBufferedSoFar); 1030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Some data has already been copied to fBuffer. Read up to the 1040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // lesser of the size requested and the remainder of the buffered 1050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // data. 1060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t bytesToCopy = SkTMin(size, fBufferedSoFar - fOffset); 1070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (dst != NULL) { 1080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger memcpy(dst, fBuffer + fOffset, bytesToCopy); 1090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Update fOffset to the new position. It is guaranteed to be 1120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // within the buffered data. 1130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fOffset += bytesToCopy; 1140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fOffset <= fBufferedSoFar); 1150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return bytesToCopy; 1170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 119910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergersize_t FrontBufferedStream::bufferAndWriteTo(char* dst, size_t size) { 1200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(size > 0); 1210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fOffset >= fBufferedSoFar); 1220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Data needs to be buffered. Buffer up to the lesser of the size requested 1230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // and the remainder of the max buffer size. 1240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t bytesToBuffer = SkTMin(size, fBufferSize - fBufferedSoFar); 1250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger char* buffer = fBuffer + fOffset; 1260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t buffered = fStream->read(buffer, bytesToBuffer); 1270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fBufferedSoFar += buffered; 1290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fOffset = fBufferedSoFar; 1300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fBufferedSoFar <= fBufferSize); 1310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Copy the buffer to the destination buffer and update the amount read. 1330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (dst != NULL) { 1340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger memcpy(dst, buffer, buffered); 1350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return buffered; 1380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 140910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergersize_t FrontBufferedStream::readDirectlyFromStream(char* dst, size_t size) { 1410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(size > 0); 1420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // If we get here, we have buffered all that can be buffered. 1430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(fBufferSize == fBufferedSoFar && fOffset >= fBufferSize); 1440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t bytesReadDirectly = fStream->read(dst, size); 1460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fOffset += bytesReadDirectly; 1470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // If we have read past the end of the buffer, rewinding is no longer 1490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // supported, so we can go ahead and free the memory. 1500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (bytesReadDirectly > 0) { 1510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fBuffer.reset(0); 1520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return bytesReadDirectly; 1550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 157910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergersize_t FrontBufferedStream::read(void* voidDst, size_t size) { 1580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Cast voidDst to a char* for easy addition. 1590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger char* dst = reinterpret_cast<char*>(voidDst); 1600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDEBUGCODE(const size_t totalSize = size;) 1610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t start = fOffset; 1620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // First, read any data that was previously buffered. 1640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (fOffset < fBufferedSoFar) { 1650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t bytesCopied = this->readFromBuffer(dst, size); 1660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Update the remaining number of bytes needed to read 1680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // and the destination buffer. 1690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger size -= bytesCopied; 1700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(size + (fOffset - start) == totalSize); 1710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (dst != NULL) { 1720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger dst += bytesCopied; 1730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Buffer any more data that should be buffered, and copy it to the 1770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // destination. 178226fe6c926409f3b64b07f0b74e92e34cc0b515eLeon Scroggins III if (size > 0 && fBufferedSoFar < fBufferSize && !fStream->isAtEnd()) { 1790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t buffered = this->bufferAndWriteTo(dst, size); 1800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Update the remaining number of bytes needed to read 1820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // and the destination buffer. 1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger size -= buffered; 1840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(size + (fOffset - start) == totalSize); 1850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (dst != NULL) { 1860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger dst += buffered; 1870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (size > 0 && !fStream->isAtEnd()) { 1910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDEBUGCODE(const size_t bytesReadDirectly =) this->readDirectlyFromStream(dst, size); 1920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDEBUGCODE(size -= bytesReadDirectly;) 1930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkASSERT(size + (fOffset - start) == totalSize); 1940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return fOffset - start; 1970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 198