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
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
50 BufferedInputStream::BufferedInputStream (InputStream& sourceStream, int size)
51 : BufferedInputStream (&sourceStream, size, false)
52{
53}
54
55 BufferedInputStream::~BufferedInputStream()
56{
57}
58
59//==============================================================================
60 char BufferedInputStream::peekByte()
61{
62 if (! ensureBuffered())
63 return 0;
64
65 return position < lastReadPos ? buffer[(int) (position - bufferStart)] : 0;
66}
67
68int64 BufferedInputStream::getTotalLength()
69{
70 return source->getTotalLength();
71}
72
73int64 BufferedInputStream::getPosition()
74{
75 return position;
76}
77
78 bool BufferedInputStream::setPosition (int64 newPosition)
79{
80 position = jmax ((int64) 0, newPosition);
81 return true;
82}
83
84 bool BufferedInputStream::isExhausted()
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
178 String BufferedInputStream::readString()
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//==============================================================================
201//==============================================================================
202#if JUCE_UNIT_TESTS
203
204 struct BufferedInputStreamTests : public UnitTest
205{
206 BufferedInputStreamTests()
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);
260 numBytesRead += 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
274 static BufferedInputStreamTests bufferedInputStreamTests;
275
276#endif
277
278} // namespace juce
juce::BufferedInputStream
Definition: juce_BufferedInputStream.h:37
juce::BufferedInputStream::~BufferedInputStream
~BufferedInputStream() override
Definition: juce_BufferedInputStream.cpp:55
juce::BufferedInputStream::BufferedInputStream
BufferedInputStream(InputStream *sourceStream, int bufferSize, bool deleteSourceWhenDestroyed)
Definition: juce_BufferedInputStream.cpp:41
juce::BufferedInputStream::getPosition
int64 getPosition() override
Definition: juce_BufferedInputStream.cpp:73
juce::BufferedInputStream::peekByte
char peekByte()
Definition: juce_BufferedInputStream.cpp:60
juce::BufferedInputStream::isExhausted
bool isExhausted() override
Definition: juce_BufferedInputStream.cpp:84
juce::BufferedInputStream::readString
String readString() override
Definition: juce_BufferedInputStream.cpp:178
juce::BufferedInputStream::read
int read(void *destBuffer, int maxBytesToRead) override
Definition: juce_BufferedInputStream.cpp:136
juce::BufferedInputStream::getTotalLength
int64 getTotalLength() override
Definition: juce_BufferedInputStream.cpp:68
juce::BufferedInputStream::setPosition
bool setPosition(int64 newPosition) override
Definition: juce_BufferedInputStream.cpp:78
juce::HeapBlock::malloc
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Definition: juce_HeapBlock.h:252
juce::InputStream
Definition: juce_InputStream.h:37
juce::InputStream::readString
virtual String readString()
Definition: juce_InputStream.cpp:182
juce::String
Definition: juce_String.h:39
juce::String::fromUTF8
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Definition: juce_String.cpp:2128
juce::UnitTest
Definition: juce_UnitTest.h:70