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.

196 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 && source->isExhausted();
  73. }
  74. void BufferedInputStream::ensureBuffered()
  75. {
  76. const int64 bufferEndOverlap = lastReadPos - bufferOverlap;
  77. if (position < bufferStart || position >= bufferEndOverlap)
  78. {
  79. int bytesRead;
  80. if (position < lastReadPos
  81. && position >= bufferEndOverlap
  82. && position >= bufferStart)
  83. {
  84. const int bytesToKeep = (int) (lastReadPos - position);
  85. memmove (buffer, buffer + (int) (position - bufferStart), (size_t) bytesToKeep);
  86. bufferStart = position;
  87. bytesRead = source->read (buffer + bytesToKeep,
  88. (int) (bufferSize - bytesToKeep));
  89. lastReadPos += bytesRead;
  90. bytesRead += bytesToKeep;
  91. }
  92. else
  93. {
  94. bufferStart = position;
  95. source->setPosition (bufferStart);
  96. bytesRead = source->read (buffer, bufferSize);
  97. lastReadPos = bufferStart + bytesRead;
  98. }
  99. while (bytesRead < bufferSize)
  100. buffer [bytesRead++] = 0;
  101. }
  102. }
  103. int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
  104. {
  105. jassert (destBuffer != nullptr && maxBytesToRead >= 0);
  106. if (position >= bufferStart
  107. && position + maxBytesToRead <= lastReadPos)
  108. {
  109. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) maxBytesToRead);
  110. position += maxBytesToRead;
  111. return maxBytesToRead;
  112. }
  113. else
  114. {
  115. if (position < bufferStart || position >= lastReadPos)
  116. ensureBuffered();
  117. int bytesRead = 0;
  118. while (maxBytesToRead > 0)
  119. {
  120. const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position));
  121. if (bytesAvailable > 0)
  122. {
  123. memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) bytesAvailable);
  124. maxBytesToRead -= bytesAvailable;
  125. bytesRead += bytesAvailable;
  126. position += bytesAvailable;
  127. destBuffer = static_cast <char*> (destBuffer) + bytesAvailable;
  128. }
  129. const int64 oldLastReadPos = lastReadPos;
  130. ensureBuffered();
  131. if (oldLastReadPos == lastReadPos)
  132. break; // if ensureBuffered() failed to read any more data, bail out
  133. if (isExhausted())
  134. break;
  135. }
  136. return bytesRead;
  137. }
  138. }
  139. String BufferedInputStream::readString()
  140. {
  141. if (position >= bufferStart
  142. && position < lastReadPos)
  143. {
  144. const int maxChars = (int) (lastReadPos - position);
  145. const char* const src = buffer + (int) (position - bufferStart);
  146. for (int i = 0; i < maxChars; ++i)
  147. {
  148. if (src[i] == 0)
  149. {
  150. position += i + 1;
  151. return String::fromUTF8 (src, i);
  152. }
  153. }
  154. }
  155. return InputStream::readString();
  156. }