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.

201 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. BEGIN_JUCE_NAMESPACE
  19. namespace
  20. {
  21. int calcBufferStreamBufferSize (int requestedSize, InputStream* const source) noexcept
  22. {
  23. // You need to supply a real stream when creating a BufferedInputStream
  24. jassert (source != nullptr);
  25. requestedSize = jmax (256, requestedSize);
  26. const int64 sourceSize = source->getTotalLength();
  27. if (sourceSize >= 0 && sourceSize < requestedSize)
  28. requestedSize = jmax (32, (int) sourceSize);
  29. return requestedSize;
  30. }
  31. }
  32. //==============================================================================
  33. BufferedInputStream::BufferedInputStream (InputStream* const sourceStream, const int bufferSize_,
  34. const bool deleteSourceWhenDestroyed)
  35. : source (sourceStream, deleteSourceWhenDestroyed),
  36. bufferSize (calcBufferStreamBufferSize (bufferSize_, sourceStream)),
  37. position (sourceStream->getPosition()),
  38. lastReadPos (0),
  39. bufferStart (position),
  40. bufferOverlap (128)
  41. {
  42. buffer.malloc ((size_t) bufferSize);
  43. }
  44. BufferedInputStream::BufferedInputStream (InputStream& sourceStream, const int bufferSize_)
  45. : source (&sourceStream, false),
  46. bufferSize (calcBufferStreamBufferSize (bufferSize_, &sourceStream)),
  47. position (sourceStream.getPosition()),
  48. lastReadPos (0),
  49. bufferStart (position),
  50. bufferOverlap (128)
  51. {
  52. buffer.malloc ((size_t) bufferSize);
  53. }
  54. BufferedInputStream::~BufferedInputStream()
  55. {
  56. }
  57. //==============================================================================
  58. int64 BufferedInputStream::getTotalLength()
  59. {
  60. return source->getTotalLength();
  61. }
  62. int64 BufferedInputStream::getPosition()
  63. {
  64. return position;
  65. }
  66. bool BufferedInputStream::setPosition (int64 newPosition)
  67. {
  68. position = jmax ((int64) 0, newPosition);
  69. return true;
  70. }
  71. bool BufferedInputStream::isExhausted()
  72. {
  73. return (position >= lastReadPos)
  74. && source->isExhausted();
  75. }
  76. void BufferedInputStream::ensureBuffered()
  77. {
  78. const int64 bufferEndOverlap = lastReadPos - bufferOverlap;
  79. if (position < bufferStart || position >= bufferEndOverlap)
  80. {
  81. int bytesRead;
  82. if (position < lastReadPos
  83. && position >= bufferEndOverlap
  84. && position >= bufferStart)
  85. {
  86. const int bytesToKeep = (int) (lastReadPos - position);
  87. memmove (buffer, buffer + (int) (position - bufferStart), (size_t) bytesToKeep);
  88. bufferStart = position;
  89. bytesRead = source->read (buffer + bytesToKeep,
  90. (int) (bufferSize - bytesToKeep));
  91. lastReadPos += bytesRead;
  92. bytesRead += bytesToKeep;
  93. }
  94. else
  95. {
  96. bufferStart = position;
  97. source->setPosition (bufferStart);
  98. bytesRead = source->read (buffer, bufferSize);
  99. lastReadPos = bufferStart + bytesRead;
  100. }
  101. while (bytesRead < bufferSize)
  102. buffer [bytesRead++] = 0;
  103. }
  104. }
  105. int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
  106. {
  107. jassert (destBuffer != nullptr && maxBytesToRead >= 0);
  108. if (position >= bufferStart
  109. && position + maxBytesToRead <= lastReadPos)
  110. {
  111. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) maxBytesToRead);
  112. position += maxBytesToRead;
  113. return maxBytesToRead;
  114. }
  115. else
  116. {
  117. if (position < bufferStart || position >= lastReadPos)
  118. ensureBuffered();
  119. int bytesRead = 0;
  120. while (maxBytesToRead > 0)
  121. {
  122. const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position));
  123. if (bytesAvailable > 0)
  124. {
  125. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) bytesAvailable);
  126. maxBytesToRead -= bytesAvailable;
  127. bytesRead += bytesAvailable;
  128. position += bytesAvailable;
  129. destBuffer = static_cast <char*> (destBuffer) + bytesAvailable;
  130. }
  131. const int64 oldLastReadPos = lastReadPos;
  132. ensureBuffered();
  133. if (oldLastReadPos == lastReadPos)
  134. break; // if ensureBuffered() failed to read any more data, bail out
  135. if (isExhausted())
  136. break;
  137. }
  138. return bytesRead;
  139. }
  140. }
  141. String BufferedInputStream::readString()
  142. {
  143. if (position >= bufferStart
  144. && position < lastReadPos)
  145. {
  146. const int maxChars = (int) (lastReadPos - position);
  147. const char* const src = buffer + (int) (position - bufferStart);
  148. for (int i = 0; i < maxChars; ++i)
  149. {
  150. if (src[i] == 0)
  151. {
  152. position += i + 1;
  153. return String::fromUTF8 (src, i);
  154. }
  155. }
  156. }
  157. return InputStream::readString();
  158. }
  159. END_JUCE_NAMESPACE