SkFrontBufferedStream.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. */
  7. #include "include/core/SkStream.h"
  8. #include "include/private/SkTemplates.h"
  9. #include "include/utils/SkFrontBufferedStream.h"
  10. class FrontBufferedStream : public SkStreamRewindable {
  11. public:
  12. // Called by Make.
  13. FrontBufferedStream(std::unique_ptr<SkStream>, size_t bufferSize);
  14. size_t read(void* buffer, size_t size) override;
  15. size_t peek(void* buffer, size_t size) const override;
  16. bool isAtEnd() const override;
  17. bool rewind() override;
  18. bool hasLength() const override { return fHasLength; }
  19. size_t getLength() const override { return fLength; }
  20. private:
  21. SkStreamRewindable* onDuplicate() const override { return nullptr; }
  22. std::unique_ptr<SkStream> fStream;
  23. const bool fHasLength;
  24. const size_t fLength;
  25. // Current offset into the stream. Always >= 0.
  26. size_t fOffset;
  27. // Amount that has been buffered by calls to read. Will always be less than
  28. // fBufferSize.
  29. size_t fBufferedSoFar;
  30. // Total size of the buffer.
  31. const size_t fBufferSize;
  32. // FIXME: SkAutoTMalloc throws on failure. Instead, Create should return a
  33. // nullptr stream.
  34. SkAutoTMalloc<char> fBuffer;
  35. // Read up to size bytes from already buffered data, and copy to
  36. // dst, if non-nullptr. Updates fOffset. Assumes that fOffset is less
  37. // than fBufferedSoFar.
  38. size_t readFromBuffer(char* dst, size_t size);
  39. // Buffer up to size bytes from the stream, and copy to dst if non-
  40. // nullptr. Updates fOffset and fBufferedSoFar. Assumes that fOffset is
  41. // less than fBufferedSoFar, and size is greater than 0.
  42. size_t bufferAndWriteTo(char* dst, size_t size);
  43. // Read up to size bytes directly from the stream and into dst if non-
  44. // nullptr. Updates fOffset. Assumes fOffset is at or beyond the buffered
  45. // data, and size is greater than 0.
  46. size_t readDirectlyFromStream(char* dst, size_t size);
  47. typedef SkStream INHERITED;
  48. };
  49. std::unique_ptr<SkStreamRewindable> SkFrontBufferedStream::Make(std::unique_ptr<SkStream> stream,
  50. size_t bufferSize) {
  51. if (!stream) {
  52. return nullptr;
  53. }
  54. return std::unique_ptr<SkStreamRewindable>(new FrontBufferedStream(std::move(stream),
  55. bufferSize));
  56. }
  57. FrontBufferedStream::FrontBufferedStream(std::unique_ptr<SkStream> stream, size_t bufferSize)
  58. : fStream(std::move(stream))
  59. , fHasLength(fStream->hasPosition() && fStream->hasLength())
  60. , fLength(fStream->getLength() - fStream->getPosition())
  61. , fOffset(0)
  62. , fBufferedSoFar(0)
  63. , fBufferSize(bufferSize)
  64. , fBuffer(bufferSize) {}
  65. bool FrontBufferedStream::isAtEnd() const {
  66. if (fOffset < fBufferedSoFar) {
  67. // Even if the underlying stream is at the end, this stream has been
  68. // rewound after buffering, so it is not at the end.
  69. return false;
  70. }
  71. return fStream->isAtEnd();
  72. }
  73. bool FrontBufferedStream::rewind() {
  74. // Only allow a rewind if we have not exceeded the buffer.
  75. if (fOffset <= fBufferSize) {
  76. fOffset = 0;
  77. return true;
  78. }
  79. return false;
  80. }
  81. size_t FrontBufferedStream::readFromBuffer(char* dst, size_t size) {
  82. SkASSERT(fOffset < fBufferedSoFar);
  83. // Some data has already been copied to fBuffer. Read up to the
  84. // lesser of the size requested and the remainder of the buffered
  85. // data.
  86. const size_t bytesToCopy = SkTMin(size, fBufferedSoFar - fOffset);
  87. if (dst != nullptr) {
  88. memcpy(dst, fBuffer + fOffset, bytesToCopy);
  89. }
  90. // Update fOffset to the new position. It is guaranteed to be
  91. // within the buffered data.
  92. fOffset += bytesToCopy;
  93. SkASSERT(fOffset <= fBufferedSoFar);
  94. return bytesToCopy;
  95. }
  96. size_t FrontBufferedStream::bufferAndWriteTo(char* dst, size_t size) {
  97. SkASSERT(size > 0);
  98. SkASSERT(fOffset >= fBufferedSoFar);
  99. SkASSERT(fBuffer);
  100. // Data needs to be buffered. Buffer up to the lesser of the size requested
  101. // and the remainder of the max buffer size.
  102. const size_t bytesToBuffer = SkTMin(size, fBufferSize - fBufferedSoFar);
  103. char* buffer = fBuffer + fOffset;
  104. const size_t buffered = fStream->read(buffer, bytesToBuffer);
  105. fBufferedSoFar += buffered;
  106. fOffset = fBufferedSoFar;
  107. SkASSERT(fBufferedSoFar <= fBufferSize);
  108. // Copy the buffer to the destination buffer and update the amount read.
  109. if (dst != nullptr) {
  110. memcpy(dst, buffer, buffered);
  111. }
  112. return buffered;
  113. }
  114. size_t FrontBufferedStream::readDirectlyFromStream(char* dst, size_t size) {
  115. SkASSERT(size > 0);
  116. // If we get here, we have buffered all that can be buffered.
  117. SkASSERT(fBufferSize == fBufferedSoFar && fOffset >= fBufferSize);
  118. const size_t bytesReadDirectly = fStream->read(dst, size);
  119. fOffset += bytesReadDirectly;
  120. // If we have read past the end of the buffer, rewinding is no longer
  121. // supported, so we can go ahead and free the memory.
  122. if (bytesReadDirectly > 0) {
  123. sk_free(fBuffer.release());
  124. }
  125. return bytesReadDirectly;
  126. }
  127. size_t FrontBufferedStream::peek(void* dst, size_t size) const {
  128. // Keep track of the offset so we can return to it.
  129. const size_t start = fOffset;
  130. if (start >= fBufferSize) {
  131. // This stream is not able to buffer.
  132. return 0;
  133. }
  134. size = SkTMin(size, fBufferSize - start);
  135. FrontBufferedStream* nonConstThis = const_cast<FrontBufferedStream*>(this);
  136. const size_t bytesRead = nonConstThis->read(dst, size);
  137. nonConstThis->fOffset = start;
  138. return bytesRead;
  139. }
  140. size_t FrontBufferedStream::read(void* voidDst, size_t size) {
  141. // Cast voidDst to a char* for easy addition.
  142. char* dst = reinterpret_cast<char*>(voidDst);
  143. SkDEBUGCODE(const size_t totalSize = size;)
  144. const size_t start = fOffset;
  145. // First, read any data that was previously buffered.
  146. if (fOffset < fBufferedSoFar) {
  147. const size_t bytesCopied = this->readFromBuffer(dst, size);
  148. // Update the remaining number of bytes needed to read
  149. // and the destination buffer.
  150. size -= bytesCopied;
  151. SkASSERT(size + (fOffset - start) == totalSize);
  152. if (dst != nullptr) {
  153. dst += bytesCopied;
  154. }
  155. }
  156. // Buffer any more data that should be buffered, and copy it to the
  157. // destination.
  158. if (size > 0 && fBufferedSoFar < fBufferSize && !fStream->isAtEnd()) {
  159. const size_t buffered = this->bufferAndWriteTo(dst, size);
  160. // Update the remaining number of bytes needed to read
  161. // and the destination buffer.
  162. size -= buffered;
  163. SkASSERT(size + (fOffset - start) == totalSize);
  164. if (dst != nullptr) {
  165. dst += buffered;
  166. }
  167. }
  168. if (size > 0 && !fStream->isAtEnd()) {
  169. SkDEBUGCODE(const size_t bytesReadDirectly =) this->readDirectlyFromStream(dst, size);
  170. SkDEBUGCODE(size -= bytesReadDirectly;)
  171. SkASSERT(size + (fOffset - start) == totalSize);
  172. }
  173. return fOffset - start;
  174. }