26 static inline int calcBufferStreamBufferSize (
int requestedSize, InputStream* source) noexcept
29 jassert (source !=
nullptr);
31 requestedSize = jmax (256, requestedSize);
32 auto sourceSize = source->getTotalLength();
34 if (sourceSize >= 0 && sourceSize < requestedSize)
35 return jmax (32, (
int) sourceSize);
42 : source (sourceStream, takeOwnership),
43 bufferSize (calcBufferStreamBufferSize (size, sourceStream)),
44 position (sourceStream->getPosition()),
45 bufferStart (position)
47 buffer.
malloc (bufferSize);
62 if (! ensureBuffered())
65 return position < lastReadPos ? buffer[(int) (position - bufferStart)] : 0;
70 return source->getTotalLength();
80 position = jmax ((int64) 0, newPosition);
86 return position >= lastReadPos && source->isExhausted();
89 bool BufferedInputStream::ensureBuffered()
91 auto bufferEndOverlap = lastReadPos - bufferOverlap;
93 if (position < bufferStart || position >= bufferEndOverlap)
97 if (position < lastReadPos
98 && position >= bufferEndOverlap
99 && position >= bufferStart)
101 auto bytesToKeep = (int) (lastReadPos - position);
102 memmove (buffer, buffer + (
int) (position - bufferStart), (
size_t) bytesToKeep);
104 bufferStart = position;
105 bytesRead = source->read (buffer + bytesToKeep,
106 (
int) (bufferSize - bytesToKeep));
111 lastReadPos += bytesRead;
112 bytesRead += bytesToKeep;
116 bufferStart = position;
118 if (! source->setPosition (bufferStart))
121 bytesRead = source->read (buffer, bufferSize);
126 lastReadPos = bufferStart + bytesRead;
129 while (bytesRead < bufferSize)
130 buffer[bytesRead++] = 0;
138 jassert (destBuffer !=
nullptr && maxBytesToRead >= 0);
140 if (position >= bufferStart
141 && position + maxBytesToRead <= lastReadPos)
143 memcpy (destBuffer, buffer + (
int) (position - bufferStart), (
size_t) maxBytesToRead);
144 position += maxBytesToRead;
145 return maxBytesToRead;
148 if (position < bufferStart || position >= lastReadPos)
149 if (! ensureBuffered())
154 while (maxBytesToRead > 0)
156 auto numToRead = jmin (maxBytesToRead, (
int) (lastReadPos - position));
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;
167 auto oldLastReadPos = lastReadPos;
169 if (! ensureBuffered()
170 || oldLastReadPos == lastReadPos
180 if (position >= bufferStart
181 && position < lastReadPos)
183 auto maxChars = (int) (lastReadPos - position);
184 auto* src = buffer + (int) (position - bufferStart);
186 for (
int i = 0; i < maxChars; ++i)
204 struct BufferedInputStreamTests :
public UnitTest 206 BufferedInputStreamTests()
207 :
UnitTest (
"BufferedInputStream", UnitTestCategories::streams)
210 void runTest()
override 212 const MemoryBlock data (
"abcdefghijklmnopqrstuvwxyz", 26);
219 expectEquals (stream.getPosition(), (int64) 0);
220 expectEquals (stream.getTotalLength(), (int64) data.
getSize());
221 expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
222 expect (! stream.isExhausted());
224 size_t numBytesRead = 0;
227 while (numBytesRead < data.
getSize())
229 expectEquals (stream.peekByte(), *(
char*) (data.
begin() + numBytesRead));
231 numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
233 expectEquals (stream.getPosition(), (int64) numBytesRead);
234 expectEquals (stream.getNumBytesRemaining(), (int64) (data.
getSize() - numBytesRead));
235 expect (stream.isExhausted() == (numBytesRead == data.
getSize()));
238 expectEquals (stream.getPosition(), (int64) data.
getSize());
239 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
240 expect (stream.isExhausted());
242 expect (readBuffer == data);
246 stream.setPosition (0);
247 expectEquals (stream.getPosition(), (int64) 0);
248 expectEquals (stream.getTotalLength(), (int64) data.
getSize());
249 expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
250 expect (! stream.isExhausted());
253 const int numBytesToSkip = 5;
255 while (numBytesRead < data.
getSize())
257 expectEquals (stream.peekByte(), *(
char*) (data.
begin() + numBytesRead));
259 stream.skipNextBytes (numBytesToSkip);
260 numBytesRead += numBytesToSkip;
261 numBytesRead = std::min (numBytesRead, data.
getSize());
263 expectEquals (stream.getPosition(), (int64) numBytesRead);
264 expectEquals (stream.getNumBytesRemaining(), (int64) (data.
getSize() - numBytesRead));
265 expect (stream.isExhausted() == (numBytesRead == data.
getSize()));
268 expectEquals (stream.getPosition(), (int64) data.
getSize());
269 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
270 expect (stream.isExhausted());
274 static BufferedInputStreamTests bufferedInputStreamTests;
size_t getSize() const noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)