OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
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
23namespace juce
24{
25
26static 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//==============================================================================
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
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
79{
80 position = jmax ((int64) 0, newPosition);
81 return true;
82}
83
85{
86 return position >= lastReadPos && source->isExhausted();
87}
88
89bool BufferedInputStream::ensureBuffered()
90{
91 auto bufferEndOverlap = lastReadPos - bufferOverlap;
92
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;
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
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
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);
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
197}
198
199
200//==============================================================================
201//==============================================================================
202#if JUCE_UNIT_TESTS
203
205{
207 : UnitTest ("BufferedInputStream", UnitTestCategories::streams)
208 {}
209
210 void runTest() override
211 {
212 const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
213 MemoryInputStream mi (data, true);
214
215 BufferedInputStream stream (mi, (int) data.getSize());
216
217 beginTest ("Read");
218
219 expectEquals (stream.getPosition(), (int64) 0);
220 expectEquals (stream.getTotalLength(), (int64) data.getSize());
221 expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
222 expect (! stream.isExhausted());
223
224 size_t numBytesRead = 0;
225 MemoryBlock readBuffer (data.getSize());
226
227 while (numBytesRead < data.getSize())
228 {
229 expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
230
231 numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
232
233 expectEquals (stream.getPosition(), (int64) numBytesRead);
234 expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
235 expect (stream.isExhausted() == (numBytesRead == data.getSize()));
236 }
237
238 expectEquals (stream.getPosition(), (int64) data.getSize());
239 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
240 expect (stream.isExhausted());
241
242 expect (readBuffer == data);
243
244 beginTest ("Skip");
245
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());
251
252 numBytesRead = 0;
253 const int numBytesToSkip = 5;
254
255 while (numBytesRead < data.getSize())
256 {
257 expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
258
259 stream.skipNextBytes (numBytesToSkip);
261 numBytesRead = std::min (numBytesRead, data.getSize());
262
263 expectEquals (stream.getPosition(), (int64) numBytesRead);
264 expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
265 expect (stream.isExhausted() == (numBytesRead == data.getSize()));
266 }
267
268 expectEquals (stream.getPosition(), (int64) data.getSize());
269 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
270 expect (stream.isExhausted());
271 }
272};
273
274static BufferedInputStreamTests bufferedInputStreamTests;
275
276#endif
277
278} // namespace juce
Array()=default
ElementType * data() noexcept
Definition juce_Array.h:360
BufferedInputStream(InputStream *sourceStream, int bufferSize, bool deleteSourceWhenDestroyed)
int read(void *destBuffer, int maxBytesToRead) override
bool setPosition(int64 newPosition) override
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
virtual String readString()
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)