/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/codec/SkCodec.h"
#include "include/core/SkStream.h"
#include "FrontBufferedStream.h"

#include <algorithm>
#include <memory>

namespace {
class FrontBufferedStream : public SkStreamRewindable {
public:
    // Called by Make.
    FrontBufferedStream(std::unique_ptr<SkStream>, size_t bufferSize);
    ~FrontBufferedStream() override;

    bool failedToAllocateBuffer() const { return !fBuffer; }

    size_t read(void* buffer, size_t size) override;

    size_t peek(void* buffer, size_t size) const override;

    bool isAtEnd() const override;

    bool rewind() override;

    bool hasLength() const override { return fHasLength; }

    size_t getLength() const override { return fLength; }

private:
    SkStreamRewindable* onDuplicate() const override { return nullptr; }

    std::unique_ptr<SkStream>        fStream;
    const bool                       fHasLength;
    const size_t                     fLength;
    // Current offset into the stream. Always >= 0.
    size_t                           fOffset;
    // Amount that has been buffered by calls to read. Will always be less than
    // fBufferSize.
    size_t                           fBufferedSoFar;
    // Total size of the buffer.
    const size_t                     fBufferSize;
    char*                            fBuffer;
    inline static constexpr size_t   kStorageSize = SkCodec::MinBufferedBytesNeeded();
    char                             fStorage[kStorageSize];

    // Read up to size bytes from already buffered data, and copy to
    // dst, if non-nullptr. Updates fOffset. Assumes that fOffset is less
    // than fBufferedSoFar.
    size_t readFromBuffer(char* dst, size_t size);

    // Buffer up to size bytes from the stream, and copy to dst if non-
    // nullptr. Updates fOffset and fBufferedSoFar. Assumes that fOffset is
    // less than fBufferedSoFar, and size is greater than 0.
    size_t bufferAndWriteTo(char* dst, size_t size);

    // Read up to size bytes directly from the stream and into dst if non-
    // nullptr. Updates fOffset. Assumes fOffset is at or beyond the buffered
    // data, and size is greater than 0.
    size_t readDirectlyFromStream(char* dst, size_t size);

    using INHERITED = SkStream;
};
} // anonymous namespace

namespace android {
namespace skia {

std::unique_ptr<SkStreamRewindable> FrontBufferedStream::Make(std::unique_ptr<SkStream> stream,
                                                              size_t bufferSize) {
    if (!stream) {
        return nullptr;
    }
    auto frontBufferedStream = std::make_unique<::FrontBufferedStream>(
            std::move(stream), bufferSize);
    if (frontBufferedStream->failedToAllocateBuffer()) {
        return nullptr;
    }

    // Work around a warning regarding a copy on older compilers.
    return std::move(frontBufferedStream);
}
} // namespace skia
} // namespace android

namespace {
FrontBufferedStream::FrontBufferedStream(std::unique_ptr<SkStream> stream, size_t bufferSize)
    : fStream(std::move(stream))
    , fHasLength(fStream->hasPosition() && fStream->hasLength())
    , fLength(fStream->getLength() - fStream->getPosition())
    , fOffset(0)
    , fBufferedSoFar(0)
    , fBufferSize(bufferSize)
    , fBuffer(bufferSize <= kStorageSize ? fStorage
                                         : reinterpret_cast<char*>(malloc(bufferSize))) {}

FrontBufferedStream::~FrontBufferedStream() {
    if (fBuffer != fStorage) {
        free(fBuffer);
    }
}

bool FrontBufferedStream::isAtEnd() const {
    if (fOffset < fBufferedSoFar) {
        // Even if the underlying stream is at the end, this stream has been
        // rewound after buffering, so it is not at the end.
        return false;
    }

    return fStream->isAtEnd();
}

bool FrontBufferedStream::rewind() {
    // Only allow a rewind if we have not exceeded the buffer.
    if (fOffset <= fBufferSize) {
        fOffset = 0;
        return true;
    }
    return false;
}

size_t FrontBufferedStream::readFromBuffer(char* dst, size_t size) {
    SkASSERT(fOffset < fBufferedSoFar);
    // Some data has already been copied to fBuffer. Read up to the
    // lesser of the size requested and the remainder of the buffered
    // data.
    const size_t bytesToCopy = std::min(size, fBufferedSoFar - fOffset);
    if (dst != nullptr) {
        memcpy(dst, fBuffer + fOffset, bytesToCopy);
    }

    // Update fOffset to the new position. It is guaranteed to be
    // within the buffered data.
    fOffset += bytesToCopy;
    SkASSERT(fOffset <= fBufferedSoFar);

    return bytesToCopy;
}

size_t FrontBufferedStream::bufferAndWriteTo(char* dst, size_t size) {
    SkASSERT(size > 0);
    SkASSERT(fOffset >= fBufferedSoFar);
    SkASSERT(fBuffer);
    // Data needs to be buffered. Buffer up to the lesser of the size requested
    // and the remainder of the max buffer size.
    const size_t bytesToBuffer = std::min(size, fBufferSize - fBufferedSoFar);
    char* buffer = fBuffer + fOffset;
    const size_t buffered = fStream->read(buffer, bytesToBuffer);

    fBufferedSoFar += buffered;
    fOffset = fBufferedSoFar;
    SkASSERT(fBufferedSoFar <= fBufferSize);

    // Copy the buffer to the destination buffer and update the amount read.
    if (dst != nullptr) {
        memcpy(dst, buffer, buffered);
    }

    return buffered;
}

size_t FrontBufferedStream::readDirectlyFromStream(char* dst, size_t size) {
    SkASSERT(size > 0);
    // If we get here, we have buffered all that can be buffered.
    SkASSERT(fBufferSize == fBufferedSoFar && fOffset >= fBufferSize);

    const size_t bytesReadDirectly = fStream->read(dst, size);
    fOffset += bytesReadDirectly;

    // If we have read past the end of the buffer, rewinding is no longer
    // supported, so we can go ahead and free the memory.
    if (bytesReadDirectly > 0 && fBuffer != fStorage) {
        free(fBuffer);
        fBuffer = nullptr;
    }

    return bytesReadDirectly;
}

size_t FrontBufferedStream::peek(void* dst, size_t size) const {
    // Keep track of the offset so we can return to it.
    const size_t start = fOffset;

    if (start >= fBufferSize) {
        // This stream is not able to buffer.
        return 0;
    }

    size = std::min(size, fBufferSize - start);
    FrontBufferedStream* nonConstThis = const_cast<FrontBufferedStream*>(this);
    const size_t bytesRead = nonConstThis->read(dst, size);
    nonConstThis->fOffset = start;
    return bytesRead;
}

size_t FrontBufferedStream::read(void* voidDst, size_t size) {
    // Cast voidDst to a char* for easy addition.
    char* dst = reinterpret_cast<char*>(voidDst);
    SkDEBUGCODE(const size_t totalSize = size;)
    const size_t start = fOffset;

    // First, read any data that was previously buffered.
    if (fOffset < fBufferedSoFar) {
        const size_t bytesCopied = this->readFromBuffer(dst, size);

        // Update the remaining number of bytes needed to read
        // and the destination buffer.
        size -= bytesCopied;
        SkASSERT(size + (fOffset - start) == totalSize);
        if (dst != nullptr) {
            dst += bytesCopied;
        }
    }

    // Buffer any more data that should be buffered, and copy it to the
    // destination.
    if (size > 0 && fBufferedSoFar < fBufferSize && !fStream->isAtEnd()) {
        const size_t buffered = this->bufferAndWriteTo(dst, size);

        // Update the remaining number of bytes needed to read
        // and the destination buffer.
        size -= buffered;
        SkASSERT(size + (fOffset - start) == totalSize);
        if (dst != nullptr) {
            dst += buffered;
        }
    }

    if (size > 0 && !fStream->isAtEnd()) {
        SkDEBUGCODE(const size_t bytesReadDirectly =) this->readDirectlyFromStream(dst, size);
        SkDEBUGCODE(size -= bytesReadDirectly;)
        SkASSERT(size + (fOffset - start) == totalSize);
    }

    return fOffset - start;
}
} // anonymous namespace
