The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
6.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. namespace
  19. {
  20. int calcBufferStreamBufferSize (int requestedSize, InputStream* const source) noexcept
  21. {
  22. // You need to supply a real stream when creating a BufferedInputStream
  23. jassert (source != nullptr);
  24. requestedSize = jmax (256, requestedSize);
  25. const int64 sourceSize = source->getTotalLength();
  26. if (sourceSize >= 0 && sourceSize < requestedSize)
  27. requestedSize = jmax (32, (int) sourceSize);
  28. return requestedSize;
  29. }
  30. }
  31. //==============================================================================
  32. BufferedInputStream::BufferedInputStream (InputStream* const sourceStream, const int bufferSize_,
  33. const bool deleteSourceWhenDestroyed)
  34. : source (sourceStream, deleteSourceWhenDestroyed),
  35. bufferSize (calcBufferStreamBufferSize (bufferSize_, sourceStream)),
  36. position (sourceStream->getPosition()),
  37. lastReadPos (0),
  38. bufferStart (position),
  39. bufferOverlap (128)
  40. {
  41. buffer.malloc ((size_t) bufferSize);
  42. }
  43. BufferedInputStream::BufferedInputStream (InputStream& sourceStream, const int bufferSize_)
  44. : source (&sourceStream, false),
  45. bufferSize (calcBufferStreamBufferSize (bufferSize_, &sourceStream)),
  46. position (sourceStream.getPosition()),
  47. lastReadPos (0),
  48. bufferStart (position),
  49. bufferOverlap (128)
  50. {
  51. buffer.malloc ((size_t) bufferSize);
  52. }
  53. BufferedInputStream::~BufferedInputStream()
  54. {
  55. }
  56. //==============================================================================
  57. int64 BufferedInputStream::getTotalLength()
  58. {
  59. return source->getTotalLength();
  60. }
  61. int64 BufferedInputStream::getPosition()
  62. {
  63. return position;
  64. }
  65. bool BufferedInputStream::setPosition (int64 newPosition)
  66. {
  67. position = jmax ((int64) 0, newPosition);
  68. return true;
  69. }
  70. bool BufferedInputStream::isExhausted()
  71. {
  72. return (position >= lastReadPos)
  73. && source->isExhausted();
  74. }
  75. void BufferedInputStream::ensureBuffered()
  76. {
  77. const int64 bufferEndOverlap = lastReadPos - bufferOverlap;
  78. if (position < bufferStart || position >= bufferEndOverlap)
  79. {
  80. int bytesRead;
  81. if (position < lastReadPos
  82. && position >= bufferEndOverlap
  83. && position >= bufferStart)
  84. {
  85. const int bytesToKeep = (int) (lastReadPos - position);
  86. memmove (buffer, buffer + (int) (position - bufferStart), (size_t) bytesToKeep);
  87. bufferStart = position;
  88. bytesRead = source->read (buffer + bytesToKeep,
  89. (int) (bufferSize - bytesToKeep));
  90. lastReadPos += bytesRead;
  91. bytesRead += bytesToKeep;
  92. }
  93. else
  94. {
  95. bufferStart = position;
  96. source->setPosition (bufferStart);
  97. bytesRead = source->read (buffer, bufferSize);
  98. lastReadPos = bufferStart + bytesRead;
  99. }
  100. while (bytesRead < bufferSize)
  101. buffer [bytesRead++] = 0;
  102. }
  103. }
  104. int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
  105. {
  106. jassert (destBuffer != nullptr && maxBytesToRead >= 0);
  107. if (position >= bufferStart
  108. && position + maxBytesToRead <= lastReadPos)
  109. {
  110. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) maxBytesToRead);
  111. position += maxBytesToRead;
  112. return maxBytesToRead;
  113. }
  114. else
  115. {
  116. if (position < bufferStart || position >= lastReadPos)
  117. ensureBuffered();
  118. int bytesRead = 0;
  119. while (maxBytesToRead > 0)
  120. {
  121. const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position));
  122. if (bytesAvailable > 0)
  123. {
  124. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) bytesAvailable);
  125. maxBytesToRead -= bytesAvailable;
  126. bytesRead += bytesAvailable;
  127. position += bytesAvailable;
  128. destBuffer = static_cast <char*> (destBuffer) + bytesAvailable;
  129. }
  130. const int64 oldLastReadPos = lastReadPos;
  131. ensureBuffered();
  132. if (oldLastReadPos == lastReadPos)
  133. break; // if ensureBuffered() failed to read any more data, bail out
  134. if (isExhausted())
  135. break;
  136. }
  137. return bytesRead;
  138. }
  139. }
  140. String BufferedInputStream::readString()
  141. {
  142. if (position >= bufferStart
  143. && position < lastReadPos)
  144. {
  145. const int maxChars = (int) (lastReadPos - position);
  146. const char* const src = buffer + (int) (position - bufferStart);
  147. for (int i = 0; i < maxChars; ++i)
  148. {
  149. if (src[i] == 0)
  150. {
  151. position += i + 1;
  152. return String::fromUTF8 (src, i);
  153. }
  154. }
  155. }
  156. return InputStream::readString();
  157. }