SkStreamBuffer.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright 2016 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 "src/codec/SkStreamBuffer.h"
  8. SkStreamBuffer::SkStreamBuffer(std::unique_ptr<SkStream> stream)
  9. : fStream(std::move(stream))
  10. , fPosition(0)
  11. , fBytesBuffered(0)
  12. , fHasLengthAndPosition(fStream->hasLength() && fStream->hasPosition())
  13. , fTrulyBuffered(0)
  14. {}
  15. SkStreamBuffer::~SkStreamBuffer() {
  16. fMarkedData.foreach([](size_t, SkData** data) { (*data)->unref(); });
  17. }
  18. const char* SkStreamBuffer::get() const {
  19. SkASSERT(fBytesBuffered >= 1);
  20. if (fHasLengthAndPosition && fTrulyBuffered < fBytesBuffered) {
  21. const size_t bytesToBuffer = fBytesBuffered - fTrulyBuffered;
  22. char* dst = SkTAddOffset<char>(const_cast<char*>(fBuffer), fTrulyBuffered);
  23. SkDEBUGCODE(const size_t bytesRead =)
  24. // This stream is rewindable, so it should be safe to call the non-const
  25. // read()
  26. const_cast<SkStream*>(fStream.get())->read(dst, bytesToBuffer);
  27. SkASSERT(bytesRead == bytesToBuffer);
  28. fTrulyBuffered = fBytesBuffered;
  29. }
  30. return fBuffer;
  31. }
  32. bool SkStreamBuffer::buffer(size_t totalBytesToBuffer) {
  33. // FIXME (scroggo): What should we do if the client tries to read too much?
  34. // Should not be a problem in GIF.
  35. SkASSERT(totalBytesToBuffer <= kMaxSize);
  36. if (totalBytesToBuffer <= fBytesBuffered) {
  37. return true;
  38. }
  39. if (fHasLengthAndPosition) {
  40. const size_t remaining = fStream->getLength() - fStream->getPosition() + fTrulyBuffered;
  41. fBytesBuffered = SkTMin(remaining, totalBytesToBuffer);
  42. } else {
  43. const size_t extraBytes = totalBytesToBuffer - fBytesBuffered;
  44. const size_t bytesBuffered = fStream->read(fBuffer + fBytesBuffered, extraBytes);
  45. fBytesBuffered += bytesBuffered;
  46. }
  47. return fBytesBuffered == totalBytesToBuffer;
  48. }
  49. size_t SkStreamBuffer::markPosition() {
  50. SkASSERT(fBytesBuffered >= 1);
  51. if (!fHasLengthAndPosition) {
  52. sk_sp<SkData> data(SkData::MakeWithCopy(fBuffer, fBytesBuffered));
  53. SkASSERT(nullptr == fMarkedData.find(fPosition));
  54. fMarkedData.set(fPosition, data.release());
  55. }
  56. return fPosition;
  57. }
  58. sk_sp<SkData> SkStreamBuffer::getDataAtPosition(size_t position, size_t length) {
  59. if (!fHasLengthAndPosition) {
  60. SkData** data = fMarkedData.find(position);
  61. SkASSERT(data);
  62. SkASSERT((*data)->size() == length);
  63. return sk_ref_sp<SkData>(*data);
  64. }
  65. SkASSERT(length <= fStream->getLength() &&
  66. position <= fStream->getLength() - length);
  67. const size_t oldPosition = fStream->getPosition();
  68. if (!fStream->seek(position)) {
  69. return nullptr;
  70. }
  71. sk_sp<SkData> data(SkData::MakeUninitialized(length));
  72. void* dst = data->writable_data();
  73. const bool success = fStream->read(dst, length) == length;
  74. fStream->seek(oldPosition);
  75. return success ? data : nullptr;
  76. }