OpenShot Audio Library | OpenShotAudio  0.6.0
juce_MemoryInputStream.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
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 MemoryInputStream::MemoryInputStream (const void* sourceData, size_t sourceDataSize, bool keepCopy)
27  : data (sourceData),
28  dataSize (sourceDataSize)
29 {
30  if (keepCopy)
31  {
32  internalCopy = MemoryBlock (sourceData, sourceDataSize);
33  data = internalCopy.getData();
34  }
35 }
36 
37 MemoryInputStream::MemoryInputStream (const MemoryBlock& sourceData, bool keepCopy)
38  : data (sourceData.getData()),
39  dataSize (sourceData.getSize())
40 {
41  if (keepCopy)
42  {
43  internalCopy = sourceData;
44  data = internalCopy.getData();
45  }
46 }
47 
49  : internalCopy (std::move (source))
50 {
51  data = internalCopy.getData();
52  dataSize = internalCopy.getSize();
53 }
54 
56 
58 {
59  return (int64) dataSize;
60 }
61 
62 int MemoryInputStream::read (void* buffer, int howMany)
63 {
64  jassert (buffer != nullptr && howMany >= 0);
65 
66  if (howMany <= 0 || position >= dataSize)
67  return 0;
68 
69  auto num = jmin ((size_t) howMany, dataSize - position);
70 
71  if (num > 0)
72  {
73  memcpy (buffer, addBytesToPointer (data, position), num);
74  position += num;
75  }
76 
77  return (int) num;
78 }
79 
81 {
82  return position >= dataSize;
83 }
84 
85 bool MemoryInputStream::setPosition (const int64 pos)
86 {
87  position = (size_t) jlimit ((int64) 0, (int64) dataSize, pos);
88  return true;
89 }
90 
92 {
93  return (int64) position;
94 }
95 
96 void MemoryInputStream::skipNextBytes (int64 numBytesToSkip)
97 {
98  if (numBytesToSkip > 0)
99  setPosition (getPosition() + numBytesToSkip);
100 }
101 
102 
103 //==============================================================================
104 //==============================================================================
105 #if JUCE_UNIT_TESTS
106 
107 class MemoryStreamTests final : public UnitTest
108 {
109 public:
110  MemoryStreamTests()
111  : UnitTest ("MemoryInputStream & MemoryOutputStream", UnitTestCategories::streams)
112  {}
113 
114  void runTest() override
115  {
116  beginTest ("Basics");
117  Random r = getRandom();
118 
119  int randomInt = r.nextInt();
120  int64 randomInt64 = r.nextInt64();
121  double randomDouble = r.nextDouble();
122  String randomString (createRandomWideCharString (r));
123 
124  MemoryOutputStream mo;
125  mo.writeInt (randomInt);
126  mo.writeIntBigEndian (randomInt);
127  mo.writeCompressedInt (randomInt);
128  mo.writeString (randomString);
129  mo.writeInt64 (randomInt64);
130  mo.writeInt64BigEndian (randomInt64);
131  mo.writeDouble (randomDouble);
132  mo.writeDoubleBigEndian (randomDouble);
133 
134  MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
135  expect (mi.readInt() == randomInt);
136  expect (mi.readIntBigEndian() == randomInt);
137  expect (mi.readCompressedInt() == randomInt);
138  expectEquals (mi.readString(), randomString);
139  expect (mi.readInt64() == randomInt64);
140  expect (mi.readInt64BigEndian() == randomInt64);
141  expectEquals (mi.readDouble(), randomDouble);
142  expectEquals (mi.readDoubleBigEndian(), randomDouble);
143 
144  const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
145  MemoryInputStream stream (data, true);
146 
147  beginTest ("Read");
148 
149  expectEquals (stream.getPosition(), (int64) 0);
150  expectEquals (stream.getTotalLength(), (int64) data.getSize());
151  expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
152  expect (! stream.isExhausted());
153 
154  size_t numBytesRead = 0;
155  MemoryBlock readBuffer (data.getSize());
156 
157  while (numBytesRead < data.getSize())
158  {
159  numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
160 
161  expectEquals (stream.getPosition(), (int64) numBytesRead);
162  expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
163  expect (stream.isExhausted() == (numBytesRead == data.getSize()));
164  }
165 
166  expectEquals (stream.getPosition(), (int64) data.getSize());
167  expectEquals (stream.getNumBytesRemaining(), (int64) 0);
168  expect (stream.isExhausted());
169 
170  expect (readBuffer == data);
171 
172  beginTest ("Skip");
173 
174  stream.setPosition (0);
175  expectEquals (stream.getPosition(), (int64) 0);
176  expectEquals (stream.getTotalLength(), (int64) data.getSize());
177  expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
178  expect (! stream.isExhausted());
179 
180  numBytesRead = 0;
181  const int numBytesToSkip = 5;
182 
183  while (numBytesRead < data.getSize())
184  {
185  stream.skipNextBytes (numBytesToSkip);
186  numBytesRead += numBytesToSkip;
187  numBytesRead = std::min (numBytesRead, data.getSize());
188 
189  expectEquals (stream.getPosition(), (int64) numBytesRead);
190  expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
191  expect (stream.isExhausted() == (numBytesRead == data.getSize()));
192  }
193 
194  expectEquals (stream.getPosition(), (int64) data.getSize());
195  expectEquals (stream.getNumBytesRemaining(), (int64) 0);
196  expect (stream.isExhausted());
197  }
198 
199  static String createRandomWideCharString (Random& r)
200  {
201  juce_wchar buffer [50] = { 0 };
202 
203  for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
204  {
205  if (r.nextBool())
206  {
207  do
208  {
209  buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
210  }
211  while (! CharPointer_UTF16::canRepresent (buffer[i]));
212  }
213  else
214  buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
215  }
216 
217  return CharPointer_UTF32 (buffer);
218  }
219 };
220 
221 static MemoryStreamTests memoryInputStreamUnitTests;
222 
223 #endif
224 
225 } // namespace juce
static bool canRepresent(juce_wchar character) noexcept
void * getData() noexcept
size_t getSize() const noexcept
void skipNextBytes(int64 numBytesToSkip) override
~MemoryInputStream() override
int read(void *destBuffer, int maxBytesToRead) override
bool setPosition(int64) override
MemoryInputStream(const void *sourceData, size_t sourceDataSize, bool keepInternalCopyOfData)