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