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.

199 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. 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. }
  158. END_JUCE_NAMESPACE