SkStreamBuffer.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. #ifndef SkStreamBuffer_DEFINED
  8. #define SkStreamBuffer_DEFINED
  9. #include "include/core/SkData.h"
  10. #include "include/core/SkStream.h"
  11. #include "include/core/SkTypes.h"
  12. #include "include/private/SkTHash.h"
  13. /**
  14. * Helper class for reading from a stream that may not have all its data
  15. * available yet.
  16. *
  17. * Used by GIFImageReader, and currently set up for that use case.
  18. *
  19. * Buffers up to 256 * 3 bytes (256 colors, with 3 bytes each) to support GIF.
  20. * FIXME (scroggo): Make this more general purpose?
  21. */
  22. class SkStreamBuffer : SkNoncopyable {
  23. public:
  24. SkStreamBuffer(std::unique_ptr<SkStream>);
  25. ~SkStreamBuffer();
  26. /**
  27. * Return a pointer the buffered data.
  28. *
  29. * The number of bytes buffered is the number passed to buffer()
  30. * after the last call to flush().
  31. */
  32. const char* get() const;
  33. /**
  34. * Buffer from the stream into our buffer.
  35. *
  36. * If this call returns true, get() can be used to access |bytes| bytes
  37. * from the stream. In addition, markPosition() can be called to mark this
  38. * position and enable calling getAtPosition() later to retrieve |bytes|
  39. * bytes.
  40. *
  41. * @param bytes Total number of bytes desired.
  42. *
  43. * @return Whether all bytes were successfully buffered.
  44. */
  45. bool buffer(size_t bytes);
  46. /**
  47. * Flush the buffer.
  48. *
  49. * After this call, no bytes are buffered.
  50. */
  51. void flush() {
  52. if (fHasLengthAndPosition) {
  53. if (fTrulyBuffered < fBytesBuffered) {
  54. fStream->move(fBytesBuffered - fTrulyBuffered);
  55. }
  56. fTrulyBuffered = 0;
  57. }
  58. fPosition += fBytesBuffered;
  59. fBytesBuffered = 0;
  60. }
  61. /**
  62. * Mark the current position in the stream to return to it later.
  63. *
  64. * This is the position of the start of the buffer. After this call, a
  65. * a client can call getDataAtPosition to retrieve all the bytes currently
  66. * buffered.
  67. *
  68. * @return size_t Position which can be passed to getDataAtPosition later
  69. * to retrieve the data currently buffered.
  70. */
  71. size_t markPosition();
  72. /**
  73. * Retrieve data at position, as previously marked by markPosition().
  74. *
  75. * @param position Position to retrieve data, as marked by markPosition().
  76. * @param length Amount of data required at position.
  77. * @return SkData The data at position.
  78. */
  79. sk_sp<SkData> getDataAtPosition(size_t position, size_t length);
  80. private:
  81. static constexpr size_t kMaxSize = 256 * 3;
  82. std::unique_ptr<SkStream> fStream;
  83. size_t fPosition;
  84. char fBuffer[kMaxSize];
  85. size_t fBytesBuffered;
  86. // If the stream has a length and position, we can make two optimizations:
  87. // - We can skip buffering
  88. // - During parsing, we can store the position and size of data that is
  89. // needed later during decoding.
  90. const bool fHasLengthAndPosition;
  91. // When fHasLengthAndPosition is true, we do not need to actually buffer
  92. // inside buffer(). We'll buffer inside get(). This keeps track of how many
  93. // bytes we've buffered inside get(), for the (non-existent) case of:
  94. // buffer(n)
  95. // get()
  96. // buffer(n + u)
  97. // get()
  98. // The second call to get() needs to only truly buffer the part that was
  99. // not already buffered.
  100. mutable size_t fTrulyBuffered;
  101. // Only used if !fHasLengthAndPosition. In that case, markPosition will
  102. // copy into an SkData, stored here.
  103. SkTHashMap<size_t, SkData*> fMarkedData;
  104. };
  105. #endif // SkStreamBuffer_DEFINED