OpenShot Library | libopenshot-audio  0.2.0
juce_BufferedInputStream.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 static inline int calcBufferStreamBufferSize (int requestedSize, InputStream* source) noexcept
27 {
28  // You need to supply a real stream when creating a BufferedInputStream
29  jassert (source != nullptr);
30 
31  requestedSize = jmax (256, requestedSize);
32  auto sourceSize = source->getTotalLength();
33 
34  if (sourceSize >= 0 && sourceSize < requestedSize)
35  return jmax (32, (int) sourceSize);
36 
37  return requestedSize;
38 }
39 
40 //==============================================================================
41 BufferedInputStream::BufferedInputStream (InputStream* sourceStream, int size, bool takeOwnership)
42  : source (sourceStream, takeOwnership),
43  bufferSize (calcBufferStreamBufferSize (size, sourceStream)),
44  position (sourceStream->getPosition()),
45  bufferStart (position)
46 {
47  buffer.malloc (bufferSize);
48 }
49 
51  : BufferedInputStream (&sourceStream, size, false)
52 {
53 }
54 
56 {
57 }
58 
59 //==============================================================================
61 {
62  if (! ensureBuffered())
63  return 0;
64 
65  return position < lastReadPos ? buffer[(int) (position - bufferStart)] : 0;
66 }
67 
69 {
70  return source->getTotalLength();
71 }
72 
74 {
75  return position;
76 }
77 
78 bool BufferedInputStream::setPosition (int64 newPosition)
79 {
80  position = jmax ((int64) 0, newPosition);
81  return true;
82 }
83 
85 {
86  return position >= lastReadPos && source->isExhausted();
87 }
88 
89 bool BufferedInputStream::ensureBuffered()
90 {
91  auto bufferEndOverlap = lastReadPos - bufferOverlap;
92 
93  if (position < bufferStart || position >= bufferEndOverlap)
94  {
95  int bytesRead;
96 
97  if (position < lastReadPos
98  && position >= bufferEndOverlap
99  && position >= bufferStart)
100  {
101  auto bytesToKeep = (int) (lastReadPos - position);
102  memmove (buffer, buffer + (int) (position - bufferStart), (size_t) bytesToKeep);
103 
104  bufferStart = position;
105  bytesRead = source->read (buffer + bytesToKeep,
106  (int) (bufferSize - bytesToKeep));
107 
108  if (bytesRead < 0)
109  return false;
110 
111  lastReadPos += bytesRead;
112  bytesRead += bytesToKeep;
113  }
114  else
115  {
116  bufferStart = position;
117 
118  if (! source->setPosition (bufferStart))
119  return false;
120 
121  bytesRead = source->read (buffer, bufferSize);
122 
123  if (bytesRead < 0)
124  return false;
125 
126  lastReadPos = bufferStart + bytesRead;
127  }
128 
129  while (bytesRead < bufferSize)
130  buffer[bytesRead++] = 0;
131  }
132 
133  return true;
134 }
135 
136 int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
137 {
138  jassert (destBuffer != nullptr && maxBytesToRead >= 0);
139 
140  if (position >= bufferStart
141  && position + maxBytesToRead <= lastReadPos)
142  {
143  memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) maxBytesToRead);
144  position += maxBytesToRead;
145  return maxBytesToRead;
146  }
147 
148  if (position < bufferStart || position >= lastReadPos)
149  if (! ensureBuffered())
150  return 0;
151 
152  int bytesRead = 0;
153 
154  while (maxBytesToRead > 0)
155  {
156  auto numToRead = jmin (maxBytesToRead, (int) (lastReadPos - position));
157 
158  if (numToRead > 0)
159  {
160  memcpy (destBuffer, buffer + (int) (position - bufferStart), (size_t) numToRead);
161  maxBytesToRead -= numToRead;
162  bytesRead += numToRead;
163  position += numToRead;
164  destBuffer = static_cast<char*> (destBuffer) + numToRead;
165  }
166 
167  auto oldLastReadPos = lastReadPos;
168 
169  if (! ensureBuffered()
170  || oldLastReadPos == lastReadPos
171  || isExhausted())
172  break;
173  }
174 
175  return bytesRead;
176 }
177 
179 {
180  if (position >= bufferStart
181  && position < lastReadPos)
182  {
183  auto maxChars = (int) (lastReadPos - position);
184  auto* src = buffer + (int) (position - bufferStart);
185 
186  for (int i = 0; i < maxChars; ++i)
187  {
188  if (src[i] == 0)
189  {
190  position += i + 1;
191  return String::fromUTF8 (src, i);
192  }
193  }
194  }
195 
196  return InputStream::readString();
197 }
198 
199 //==============================================================================
200 #if JUCE_UNIT_TESTS
201 
202 struct BufferedInputStreamTests : public UnitTest
203 {
204  BufferedInputStreamTests()
205  : UnitTest ("BufferedInputStream", "Streams")
206  {}
207 
208  void runTest() override
209  {
210  const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
211  MemoryInputStream mi (data, true);
212 
213  BufferedInputStream stream (mi, (int) data.getSize());
214 
215  beginTest ("Read");
216 
217  expectEquals (stream.getPosition(), (int64) 0);
218  expectEquals (stream.getTotalLength(), (int64) data.getSize());
219  expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
220  expect (! stream.isExhausted());
221 
222  size_t numBytesRead = 0;
223  MemoryBlock readBuffer (data.getSize());
224 
225  while (numBytesRead < data.getSize())
226  {
227  expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
228 
229  numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
230 
231  expectEquals (stream.getPosition(), (int64) numBytesRead);
232  expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
233  expect (stream.isExhausted() == (numBytesRead == data.getSize()));
234  }
235 
236  expectEquals (stream.getPosition(), (int64) data.getSize());
237  expectEquals (stream.getNumBytesRemaining(), (int64) 0);
238  expect (stream.isExhausted());
239 
240  expect (readBuffer == data);
241 
242  beginTest ("Skip");
243 
244  stream.setPosition (0);
245  expectEquals (stream.getPosition(), (int64) 0);
246  expectEquals (stream.getTotalLength(), (int64) data.getSize());
247  expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
248  expect (! stream.isExhausted());
249 
250  numBytesRead = 0;
251  const int numBytesToSkip = 5;
252 
253  while (numBytesRead < data.getSize())
254  {
255  expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
256 
257  stream.skipNextBytes (numBytesToSkip);
258  numBytesRead += numBytesToSkip;
259  numBytesRead = std::min (numBytesRead, data.getSize());
260 
261  expectEquals (stream.getPosition(), (int64) numBytesRead);
262  expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
263  expect (stream.isExhausted() == (numBytesRead == data.getSize()));
264  }
265 
266  expectEquals (stream.getPosition(), (int64) data.getSize());
267  expectEquals (stream.getNumBytesRemaining(), (int64) 0);
268  expect (stream.isExhausted());
269  }
270 };
271 
272 static BufferedInputStreamTests bufferedInputStreamTests;
273 
274 #endif
275 
276 } // namespace juce
juce::BufferedInputStream::~BufferedInputStream
~BufferedInputStream() override
Destructor.
Definition: juce_BufferedInputStream.cpp:55
juce::BufferedInputStream::read
int read(void *destBuffer, int maxBytesToRead) override
Reads some data from the stream into a memory buffer.
Definition: juce_BufferedInputStream.cpp:136
juce::InputStream
The base class for streams that read data.
Definition: juce_InputStream.h:40
juce::BufferedInputStream::BufferedInputStream
BufferedInputStream(InputStream *sourceStream, int bufferSize, bool deleteSourceWhenDestroyed)
Creates a BufferedInputStream from an input source.
Definition: juce_BufferedInputStream.cpp:41
juce::BufferedInputStream::getPosition
int64 getPosition() override
Returns the offset of the next byte that will be read from the stream.
Definition: juce_BufferedInputStream.cpp:73
juce::BufferedInputStream::getTotalLength
int64 getTotalLength() override
Returns the total number of bytes available for reading in this stream.
Definition: juce_BufferedInputStream.cpp:68
juce::BufferedInputStream
Wraps another input stream, and reads from it using an intermediate buffer.
Definition: juce_BufferedInputStream.h:40
juce::BufferedInputStream::peekByte
char peekByte()
Returns the next byte that would be read by a call to readByte()
Definition: juce_BufferedInputStream.cpp:60
juce::HeapBlock::malloc
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
Definition: juce_HeapBlock.h:256
juce::InputStream::readString
virtual String readString()
Reads a zero-terminated UTF-8 string from the stream.
Definition: juce_InputStream.cpp:162
juce::BufferedInputStream::readString
String readString() override
Reads a zero-terminated UTF-8 string from the stream.
Definition: juce_BufferedInputStream.cpp:178
juce::BufferedInputStream::isExhausted
bool isExhausted() override
Returns true if the stream has no more data to read.
Definition: juce_BufferedInputStream.cpp:84
juce::UnitTest
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
juce::BufferedInputStream::setPosition
bool setPosition(int64 newPosition) override
Tries to move the current read position of the stream.
Definition: juce_BufferedInputStream.cpp:78
juce::String
The JUCE String class!
Definition: juce_String.h:42
juce::String::fromUTF8
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Creates a String from a UTF-8 encoded buffer.
Definition: juce_String.cpp:2123