OpenShot Audio Library | OpenShotAudio  0.6.0
juce_MemoryBlock.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 
27 
28 MemoryBlock::MemoryBlock (size_t initialSize, bool initialiseToZero)
29 {
30  if (initialSize > 0)
31  {
32  size = initialSize;
33  data.allocate (initialSize, initialiseToZero);
34  }
35  else
36  {
37  size = 0;
38  }
39 }
40 
42  : size (other.size)
43 {
44  if (size > 0)
45  {
46  jassert (other.data != nullptr);
47  data.malloc (size);
48  memcpy (data, other.data, size);
49  }
50 }
51 
52 MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, const size_t sizeInBytes)
53  : size (sizeInBytes)
54 {
55  jassert (((ssize_t) sizeInBytes) >= 0);
56 
57  if (size > 0)
58  {
59  jassert (dataToInitialiseFrom != nullptr); // non-zero size, but a zero pointer passed-in?
60 
61  data.malloc (size);
62 
63  if (dataToInitialiseFrom != nullptr)
64  memcpy (data, dataToInitialiseFrom, size);
65  }
66 }
67 
69 {
70 }
71 
73 {
74  if (this != &other)
75  {
76  setSize (other.size, false);
77  memcpy (data, other.data, size);
78  }
79 
80  return *this;
81 }
82 
84  : data (std::move (other.data)),
85  size (other.size)
86 {
87 }
88 
90 {
91  data = std::move (other.data);
92  size = other.size;
93  return *this;
94 }
95 
96 //==============================================================================
97 bool MemoryBlock::operator== (const MemoryBlock& other) const noexcept
98 {
99  return matches (other.data, other.size);
100 }
101 
102 bool MemoryBlock::operator!= (const MemoryBlock& other) const noexcept
103 {
104  return ! operator== (other);
105 }
106 
107 bool MemoryBlock::matches (const void* dataToCompare, size_t dataSize) const noexcept
108 {
109  return size == dataSize
110  && memcmp (data, dataToCompare, size) == 0;
111 }
112 
113 //==============================================================================
114 // this will resize the block to this size
115 void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
116 {
117  if (size != newSize)
118  {
119  if (newSize <= 0)
120  {
121  reset();
122  }
123  else
124  {
125  if (data != nullptr)
126  {
127  data.realloc (newSize);
128 
129  if (initialiseToZero && (newSize > size))
130  zeromem (data + size, newSize - size);
131  }
132  else
133  {
134  data.allocate (newSize, initialiseToZero);
135  }
136 
137  size = newSize;
138  }
139  }
140 }
141 
143 {
144  data.free();
145  size = 0;
146 }
147 
148 void MemoryBlock::ensureSize (size_t minimumSize, bool initialiseToZero)
149 {
150  if (size < minimumSize)
151  setSize (minimumSize, initialiseToZero);
152 }
153 
154 void MemoryBlock::swapWith (MemoryBlock& other) noexcept
155 {
156  std::swap (size, other.size);
157  data.swapWith (other.data);
158 }
159 
160 //==============================================================================
161 void MemoryBlock::fillWith (uint8 value) noexcept
162 {
163  memset (data, (int) value, size);
164 }
165 
166 void MemoryBlock::append (const void* srcData, size_t numBytes)
167 {
168  if (numBytes > 0)
169  {
170  jassert (srcData != nullptr); // this must not be null!
171  auto oldSize = size;
172  setSize (size + numBytes);
173  memcpy (data + oldSize, srcData, numBytes);
174  }
175 }
176 
177 void MemoryBlock::replaceAll (const void* srcData, size_t numBytes)
178 {
179  if (numBytes <= 0)
180  {
181  reset();
182  return;
183  }
184 
185  jassert (srcData != nullptr); // this must not be null!
186  setSize (numBytes);
187  memcpy (data, srcData, numBytes);
188 }
189 
190 void MemoryBlock::insert (const void* srcData, size_t numBytes, size_t insertPosition)
191 {
192  if (numBytes > 0)
193  {
194  jassert (srcData != nullptr); // this must not be null!
195  insertPosition = jmin (size, insertPosition);
196  auto trailingDataSize = size - insertPosition;
197  setSize (size + numBytes, false);
198 
199  if (trailingDataSize > 0)
200  memmove (data + insertPosition + numBytes,
201  data + insertPosition,
202  trailingDataSize);
203 
204  memcpy (data + insertPosition, srcData, numBytes);
205  }
206 }
207 
208 void MemoryBlock::removeSection (size_t startByte, size_t numBytesToRemove)
209 {
210  if (startByte + numBytesToRemove >= size)
211  {
212  setSize (startByte);
213  }
214  else if (numBytesToRemove > 0)
215  {
216  memmove (data + startByte,
217  data + startByte + numBytesToRemove,
218  size - (startByte + numBytesToRemove));
219 
220  setSize (size - numBytesToRemove);
221  }
222 }
223 
224 void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
225 {
226  auto* d = static_cast<const char*> (src);
227 
228  if (offset < 0)
229  {
230  d -= offset;
231  num += (size_t) -offset;
232  offset = 0;
233  }
234 
235  if ((size_t) offset + num > size)
236  num = size - (size_t) offset;
237 
238  if (num > 0)
239  memcpy (data + offset, d, num);
240 }
241 
242 void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
243 {
244  auto* d = static_cast<char*> (dst);
245 
246  if (offset < 0)
247  {
248  zeromem (d, (size_t) -offset);
249  d -= offset;
250  num -= (size_t) -offset;
251  offset = 0;
252  }
253 
254  if ((size_t) offset + num > size)
255  {
256  auto newNum = (size_t) size - (size_t) offset;
257  zeromem (d + newNum, num - newNum);
258  num = newNum;
259  }
260 
261  if (num > 0)
262  memcpy (d, data + offset, num);
263 }
264 
266 {
267  return String::fromUTF8 (data, (int) size);
268 }
269 
270 //==============================================================================
271 int MemoryBlock::getBitRange (size_t bitRangeStart, size_t numBits) const noexcept
272 {
273  int res = 0;
274 
275  auto byte = bitRangeStart >> 3;
276  auto offsetInByte = bitRangeStart & 7;
277  size_t bitsSoFar = 0;
278 
279  while (numBits > 0 && (size_t) byte < size)
280  {
281  auto bitsThisTime = jmin (numBits, 8 - offsetInByte);
282  const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
283 
284  res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
285 
286  bitsSoFar += bitsThisTime;
287  numBits -= bitsThisTime;
288  ++byte;
289  offsetInByte = 0;
290  }
291 
292  return res;
293 }
294 
295 void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
296 {
297  auto byte = bitRangeStart >> 3;
298  auto offsetInByte = bitRangeStart & 7;
299  uint32 mask = ~((((uint32) 0xffffffff) << (32 - numBits)) >> (32 - numBits));
300 
301  while (numBits > 0 && (size_t) byte < size)
302  {
303  auto bitsThisTime = jmin (numBits, 8 - offsetInByte);
304 
305  const uint32 tempMask = (mask << offsetInByte) | ~((((uint32) 0xffffffff) >> offsetInByte) << offsetInByte);
306  const uint32 tempBits = (uint32) bitsToSet << offsetInByte;
307 
308  data[byte] = (char) (((uint32) data[byte] & tempMask) | tempBits);
309 
310  ++byte;
311  numBits -= bitsThisTime;
312  bitsToSet >>= bitsThisTime;
313  mask >>= bitsThisTime;
314  offsetInByte = 0;
315  }
316 }
317 
318 //==============================================================================
320 {
321  ensureSize ((size_t) hex.length() >> 1);
322  char* dest = data;
323  auto t = hex.text;
324 
325  for (;;)
326  {
327  juce_wchar byte = 0;
328 
329  for (int loop = 2; --loop >= 0;)
330  {
331  byte <<= 4;
332 
333  for (;;)
334  {
335  auto c = t.getAndAdvance();
336 
337  if (c >= '0' && c <= '9') { byte |= c - '0'; break; }
338  if (c >= 'a' && c <= 'z') { byte |= c - ('a' - 10); break; }
339  if (c >= 'A' && c <= 'Z') { byte |= c - ('A' - 10); break; }
340 
341  if (c == 0)
342  {
343  setSize (static_cast<size_t> (dest - data));
344  return;
345  }
346  }
347  }
348 
349  *dest++ = (char) byte;
350  }
351 }
352 
353 //==============================================================================
354 static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
355 
357 {
358  auto numChars = ((size << 3) + 5) / 6;
359 
360  String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
361  auto initialLen = destString.length();
362  destString.preallocateBytes ((size_t) initialLen * sizeof (String::CharPointerType::CharType) + 2 + numChars);
363 
364  auto d = destString.getCharPointer();
365  d += initialLen;
366  d.write ('.');
367 
368  for (size_t i = 0; i < numChars; ++i)
369  d.write ((juce_wchar) (uint8) base64EncodingTable[getBitRange (i * 6, 6)]);
370 
371  d.writeNull();
372  return destString;
373 }
374 
375 static const char base64DecodingTable[] =
376 {
377  63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
378  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
379  0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52
380 };
381 
383 {
384  auto dot = CharacterFunctions::find (s.text, (juce_wchar) '.');
385 
386  if (dot.isEmpty())
387  return false;
388 
389  auto numBytesNeeded = String (s.text, dot).getIntValue();
390 
391  setSize ((size_t) numBytesNeeded, true);
392 
393  auto srcChars = dot + 1;
394  int pos = 0;
395 
396  for (;;)
397  {
398  auto c = (int) srcChars.getAndAdvance();
399 
400  if (c == 0)
401  return true;
402 
403  c -= 43;
404 
405  if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
406  {
407  setBitRange ((size_t) pos, 6, base64DecodingTable[c]);
408  pos += 6;
409  }
410  }
411 }
412 
413 } // namespace juce
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
void allocate(SizeType newNumElements, bool initialiseToZero)
void realloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
void free() noexcept
void copyFrom(const void *srcData, int destinationOffset, size_t numBytes) noexcept
bool fromBase64Encoding(StringRef encodedString)
String toBase64Encoding() const
bool matches(const void *data, size_t dataSize) const noexcept
void append(const void *data, size_t numBytes)
void replaceAll(const void *data, size_t numBytes)
String toString() const
void copyTo(void *destData, int sourceOffset, size_t numBytes) const noexcept
void insert(const void *dataToInsert, size_t numBytesToInsert, size_t insertPosition)
void swapWith(MemoryBlock &other) noexcept
int getBitRange(size_t bitRangeStart, size_t numBitsToRead) const noexcept
void loadFromHexString(StringRef sourceHexString)
void removeSection(size_t startByte, size_t numBytesToRemove)
MemoryBlock & operator=(const MemoryBlock &)
void fillWith(uint8 valueToUse) noexcept
bool operator!=(const MemoryBlock &other) const noexcept
void setSize(size_t newSize, bool initialiseNewSpaceToZero=false)
void ensureSize(size_t minimumSize, bool initialiseNewSpaceToZero=false)
void setBitRange(size_t bitRangeStart, size_t numBits, int binaryNumberToApply) noexcept
bool operator==(const MemoryBlock &other) const noexcept
int length() const noexcept
String::CharPointerType text
CharPointerType getCharPointer() const noexcept
Definition: juce_String.h:1153
int length() const noexcept
void preallocateBytes(size_t numBytesNeeded)
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
int getIntValue() const noexcept