OpenShot Library | libopenshot-audio 0.2.0
juce_MemoryInputStream.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
26MemoryInputStream::MemoryInputStream (const void* sourceData, size_t sourceDataSize, bool keepCopy)
27 : data (sourceData),
28 dataSize (sourceDataSize)
29{
30 if (keepCopy)
31 createInternalCopy();
32}
33
34MemoryInputStream::MemoryInputStream (const MemoryBlock& sourceData, bool keepCopy)
35 : data (sourceData.getData()),
36 dataSize (sourceData.getSize())
37{
38 if (keepCopy)
39 createInternalCopy();
40}
41
42void MemoryInputStream::createInternalCopy()
43{
44 internalCopy.malloc (dataSize);
45 memcpy (internalCopy, data, dataSize);
46 data = internalCopy;
47}
48
50{
51}
52
54{
55 return (int64) dataSize;
56}
57
58int MemoryInputStream::read (void* buffer, int howMany)
59{
60 jassert (buffer != nullptr && howMany >= 0);
61
62 if (howMany <= 0 || position >= dataSize)
63 return 0;
64
65 auto num = jmin ((size_t) howMany, dataSize - position);
66
67 if (num > 0)
68 {
69 memcpy (buffer, addBytesToPointer (data, position), num);
70 position += num;
71 }
72
73 return (int) num;
74}
75
77{
78 return position >= dataSize;
79}
80
81bool MemoryInputStream::setPosition (const int64 pos)
82{
83 position = (size_t) jlimit ((int64) 0, (int64) dataSize, pos);
84 return true;
85}
86
88{
89 return (int64) position;
90}
91
92void MemoryInputStream::skipNextBytes (int64 numBytesToSkip)
93{
94 if (numBytesToSkip > 0)
95 setPosition (getPosition() + numBytesToSkip);
96}
97
98//==============================================================================
99#if JUCE_UNIT_TESTS
100
101class MemoryStreamTests : public UnitTest
102{
103public:
104 MemoryStreamTests()
105 : UnitTest ("MemoryInputStream & MemoryOutputStream", "Streams")
106 {}
107
108 void runTest() override
109 {
110 beginTest ("Basics");
111 Random r = getRandom();
112
113 int randomInt = r.nextInt();
114 int64 randomInt64 = r.nextInt64();
115 double randomDouble = r.nextDouble();
116 String randomString (createRandomWideCharString (r));
117
118 MemoryOutputStream mo;
119 mo.writeInt (randomInt);
120 mo.writeIntBigEndian (randomInt);
121 mo.writeCompressedInt (randomInt);
122 mo.writeString (randomString);
123 mo.writeInt64 (randomInt64);
124 mo.writeInt64BigEndian (randomInt64);
125 mo.writeDouble (randomDouble);
126 mo.writeDoubleBigEndian (randomDouble);
127
128 MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
129 expect (mi.readInt() == randomInt);
130 expect (mi.readIntBigEndian() == randomInt);
131 expect (mi.readCompressedInt() == randomInt);
132 expectEquals (mi.readString(), randomString);
133 expect (mi.readInt64() == randomInt64);
134 expect (mi.readInt64BigEndian() == randomInt64);
135 expect (mi.readDouble() == randomDouble);
136 expect (mi.readDoubleBigEndian() == randomDouble);
137
138 const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
139 MemoryInputStream stream (data, true);
140
141 beginTest ("Read");
142
143 expectEquals (stream.getPosition(), (int64) 0);
144 expectEquals (stream.getTotalLength(), (int64) data.getSize());
145 expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
146 expect (! stream.isExhausted());
147
148 size_t numBytesRead = 0;
149 MemoryBlock readBuffer (data.getSize());
150
151 while (numBytesRead < data.getSize())
152 {
153 numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
154
155 expectEquals (stream.getPosition(), (int64) numBytesRead);
156 expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
157 expect (stream.isExhausted() == (numBytesRead == data.getSize()));
158 }
159
160 expectEquals (stream.getPosition(), (int64) data.getSize());
161 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
162 expect (stream.isExhausted());
163
164 expect (readBuffer == data);
165
166 beginTest ("Skip");
167
168 stream.setPosition (0);
169 expectEquals (stream.getPosition(), (int64) 0);
170 expectEquals (stream.getTotalLength(), (int64) data.getSize());
171 expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
172 expect (! stream.isExhausted());
173
174 numBytesRead = 0;
175 const int numBytesToSkip = 5;
176
177 while (numBytesRead < data.getSize())
178 {
179 stream.skipNextBytes (numBytesToSkip);
180 numBytesRead += numBytesToSkip;
181 numBytesRead = std::min (numBytesRead, data.getSize());
182
183 expectEquals (stream.getPosition(), (int64) numBytesRead);
184 expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
185 expect (stream.isExhausted() == (numBytesRead == data.getSize()));
186 }
187
188 expectEquals (stream.getPosition(), (int64) data.getSize());
189 expectEquals (stream.getNumBytesRemaining(), (int64) 0);
190 expect (stream.isExhausted());
191 }
192
193 static String createRandomWideCharString (Random& r)
194 {
195 juce_wchar buffer [50] = { 0 };
196
197 for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
198 {
199 if (r.nextBool())
200 {
201 do
202 {
203 buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
204 }
205 while (! CharPointer_UTF16::canRepresent (buffer[i]));
206 }
207 else
208 buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
209 }
210
211 return CharPointer_UTF32 (buffer);
212 }
213};
214
215static MemoryStreamTests memoryInputStreamUnitTests;
216
217#endif
218
219} // namespace juce
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
A class to hold a resizable block of raw data.
void skipNextBytes(int64 numBytesToSkip) override
Reads and discards a number of bytes from the stream.
bool isExhausted() override
Returns true if the stream has no more data to read.
int64 getTotalLength() override
Returns the total number of bytes available for reading in this stream.
~MemoryInputStream() override
Destructor.
int read(void *destBuffer, int maxBytesToRead) override
Reads some data from the stream into a memory buffer.
int64 getPosition() override
Returns the offset of the next byte that will be read from the stream.
bool setPosition(int64) override
Tries to move the current read position of the stream.
MemoryInputStream(const void *sourceData, size_t sourceDataSize, bool keepInternalCopyOfData)
Creates a MemoryInputStream.
This is a base class for classes that perform a unit test.