gfx/skia/trunk/src/utils/SkFrontBufferedStream.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright 2013 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkFrontBufferedStream.h"
     9 #include "SkStream.h"
    10 #include "SkTemplates.h"
    12 class FrontBufferedStream : public SkStreamRewindable {
    13 public:
    14     // Called by Create.
    15     FrontBufferedStream(SkStream*, size_t bufferSize);
    17     virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
    19     virtual bool isAtEnd() const SK_OVERRIDE;
    21     virtual bool rewind() SK_OVERRIDE;
    23     virtual bool hasPosition() const SK_OVERRIDE { return true; }
    25     virtual size_t getPosition() const SK_OVERRIDE { return fOffset; }
    27     virtual bool hasLength() const SK_OVERRIDE { return fHasLength; }
    29     virtual size_t getLength() const SK_OVERRIDE { return fLength; }
    31     virtual SkStreamRewindable* duplicate() const SK_OVERRIDE { return NULL; }
    33 private:
    34     SkAutoTUnref<SkStream>  fStream;
    35     const bool              fHasLength;
    36     const size_t            fLength;
    37     // Current offset into the stream. Always >= 0.
    38     size_t                  fOffset;
    39     // Amount that has been buffered by calls to read. Will always be less than
    40     // fBufferSize.
    41     size_t                  fBufferedSoFar;
    42     // Total size of the buffer.
    43     const size_t            fBufferSize;
    44     // FIXME: SkAutoTMalloc throws on failure. Instead, Create should return a
    45     // NULL stream.
    46     SkAutoTMalloc<char>     fBuffer;
    48     // Read up to size bytes from already buffered data, and copy to
    49     // dst, if non-NULL. Updates fOffset. Assumes that fOffset is less
    50     // than fBufferedSoFar.
    51     size_t readFromBuffer(char* dst, size_t size);
    53     // Buffer up to size bytes from the stream, and copy to dst if non-
    54     // NULL. Updates fOffset and fBufferedSoFar. Assumes that fOffset is
    55     // less than fBufferedSoFar, and size is greater than 0.
    56     size_t bufferAndWriteTo(char* dst, size_t size);
    58     // Read up to size bytes directly from the stream and into dst if non-
    59     // NULL. Updates fOffset. Assumes fOffset is at or beyond the buffered
    60     // data, and size is greater than 0.
    61     size_t readDirectlyFromStream(char* dst, size_t size);
    63     typedef SkStream INHERITED;
    64 };
    66 SkStreamRewindable* SkFrontBufferedStream::Create(SkStream* stream, size_t bufferSize) {
    67     if (NULL == stream) {
    68         return NULL;
    69     }
    70     return SkNEW_ARGS(FrontBufferedStream, (stream, bufferSize));
    71 }
    73 FrontBufferedStream::FrontBufferedStream(SkStream* stream, size_t bufferSize)
    74     : fStream(SkRef(stream))
    75     , fHasLength(stream->hasPosition() && stream->hasLength())
    76     , fLength(stream->getLength() - stream->getPosition())
    77     , fOffset(0)
    78     , fBufferedSoFar(0)
    79     , fBufferSize(bufferSize)
    80     , fBuffer(bufferSize) {}
    82 bool FrontBufferedStream::isAtEnd() const {
    83     if (fOffset < fBufferedSoFar) {
    84         // Even if the underlying stream is at the end, this stream has been
    85         // rewound after buffering, so it is not at the end.
    86         return false;
    87     }
    89     return fStream->isAtEnd();
    90 }
    92 bool FrontBufferedStream::rewind() {
    93     // Only allow a rewind if we have not exceeded the buffer.
    94     if (fOffset <= fBufferSize) {
    95         fOffset = 0;
    96         return true;
    97     }
    98     return false;
    99 }
   101 size_t FrontBufferedStream::readFromBuffer(char* dst, size_t size) {
   102     SkASSERT(fOffset < fBufferedSoFar);
   103     // Some data has already been copied to fBuffer. Read up to the
   104     // lesser of the size requested and the remainder of the buffered
   105     // data.
   106     const size_t bytesToCopy = SkTMin(size, fBufferedSoFar - fOffset);
   107     if (dst != NULL) {
   108         memcpy(dst, fBuffer + fOffset, bytesToCopy);
   109     }
   111     // Update fOffset to the new position. It is guaranteed to be
   112     // within the buffered data.
   113     fOffset += bytesToCopy;
   114     SkASSERT(fOffset <= fBufferedSoFar);
   116     return bytesToCopy;
   117 }
   119 size_t FrontBufferedStream::bufferAndWriteTo(char* dst, size_t size) {
   120     SkASSERT(size > 0);
   121     SkASSERT(fOffset >= fBufferedSoFar);
   122     // Data needs to be buffered. Buffer up to the lesser of the size requested
   123     // and the remainder of the max buffer size.
   124     const size_t bytesToBuffer = SkTMin(size, fBufferSize - fBufferedSoFar);
   125     char* buffer = fBuffer + fOffset;
   126     const size_t buffered = fStream->read(buffer, bytesToBuffer);
   128     fBufferedSoFar += buffered;
   129     fOffset = fBufferedSoFar;
   130     SkASSERT(fBufferedSoFar <= fBufferSize);
   132     // Copy the buffer to the destination buffer and update the amount read.
   133     if (dst != NULL) {
   134         memcpy(dst, buffer, buffered);
   135     }
   137     return buffered;
   138 }
   140 size_t FrontBufferedStream::readDirectlyFromStream(char* dst, size_t size) {
   141     SkASSERT(size > 0);
   142     // If we get here, we have buffered all that can be buffered.
   143     SkASSERT(fBufferSize == fBufferedSoFar && fOffset >= fBufferSize);
   145     const size_t bytesReadDirectly = fStream->read(dst, size);
   146     fOffset += bytesReadDirectly;
   148     // If we have read past the end of the buffer, rewinding is no longer
   149     // supported, so we can go ahead and free the memory.
   150     if (bytesReadDirectly > 0) {
   151         fBuffer.reset(0);
   152     }
   154     return bytesReadDirectly;
   155 }
   157 size_t FrontBufferedStream::read(void* voidDst, size_t size) {
   158     // Cast voidDst to a char* for easy addition.
   159     char* dst = reinterpret_cast<char*>(voidDst);
   160     SkDEBUGCODE(const size_t totalSize = size;)
   161     const size_t start = fOffset;
   163     // First, read any data that was previously buffered.
   164     if (fOffset < fBufferedSoFar) {
   165         const size_t bytesCopied = this->readFromBuffer(dst, size);
   167         // Update the remaining number of bytes needed to read
   168         // and the destination buffer.
   169         size -= bytesCopied;
   170         SkASSERT(size + (fOffset - start) == totalSize);
   171         if (dst != NULL) {
   172             dst += bytesCopied;
   173         }
   174     }
   176     // Buffer any more data that should be buffered, and copy it to the
   177     // destination.
   178     if (size > 0 && fBufferedSoFar < fBufferSize) {
   179         const size_t buffered = this->bufferAndWriteTo(dst, size);
   181         // Update the remaining number of bytes needed to read
   182         // and the destination buffer.
   183         size -= buffered;
   184         SkASSERT(size + (fOffset - start) == totalSize);
   185         if (dst != NULL) {
   186             dst += buffered;
   187         }
   188     }
   190     if (size > 0 && !fStream->isAtEnd()) {
   191         SkDEBUGCODE(const size_t bytesReadDirectly =) this->readDirectlyFromStream(dst, size);
   192         SkDEBUGCODE(size -= bytesReadDirectly;)
   193         SkASSERT(size + (fOffset - start) == totalSize);
   194     }
   196     return fOffset - start;
   197 }

mercurial