OpenShot Audio Library | OpenShotAudio  0.3.1
juce_MemoryBlock.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 
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::replaceWith (const void* srcData, size_t numBytes)
178 {
179  if (numBytes > 0)
180  {
181  jassert (srcData != nullptr); // this must not be null!
182  setSize (numBytes);
183  memcpy (data, srcData, numBytes);
184  }
185 }
186 
187 void MemoryBlock::insert (const void* srcData, size_t numBytes, size_t insertPosition)
188 {
189  if (numBytes > 0)
190  {
191  jassert (srcData != nullptr); // this must not be null!
192  insertPosition = jmin (size, insertPosition);
193  auto trailingDataSize = size - insertPosition;
194  setSize (size + numBytes, false);
195 
196  if (trailingDataSize > 0)
197  memmove (data + insertPosition + numBytes,
198  data + insertPosition,
199  trailingDataSize);
200 
201  memcpy (data + insertPosition, srcData, numBytes);
202  }
203 }
204 
205 void MemoryBlock::removeSection (size_t startByte, size_t numBytesToRemove)
206 {
207  if (startByte + numBytesToRemove >= size)
208  {
209  setSize (startByte);
210  }
211  else if (numBytesToRemove > 0)
212  {
213  memmove (data + startByte,
214  data + startByte + numBytesToRemove,
215  size - (startByte + numBytesToRemove));
216 
217  setSize (size - numBytesToRemove);
218  }
219 }
220 
221 void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
222 {
223  auto* d = static_cast<const char*> (src);
224 
225  if (offset < 0)
226  {
227  d -= offset;
228  num += (size_t) -offset;
229  offset = 0;
230  }
231 
232  if ((size_t) offset + num > size)
233  num = size - (size_t) offset;
234 
235  if (num > 0)
236  memcpy (data + offset, d, num);
237 }
238 
239 void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
240 {
241  auto* d = static_cast<char*> (dst);
242 
243  if (offset < 0)
244  {
245  zeromem (d, (size_t) -offset);
246  d -= offset;
247  num -= (size_t) -offset;
248  offset = 0;
249  }
250 
251  if ((size_t) offset + num > size)
252  {
253  auto newNum = (size_t) size - (size_t) offset;
254  zeromem (d + newNum, num - newNum);
255  num = newNum;
256  }
257 
258  if (num > 0)
259  memcpy (d, data + offset, num);
260 }
261 
263 {
264  return String::fromUTF8 (data, (int) size);
265 }
266 
267 //==============================================================================
268 int MemoryBlock::getBitRange (size_t bitRangeStart, size_t numBits) const noexcept
269 {
270  int res = 0;
271 
272  auto byte = bitRangeStart >> 3;
273  auto offsetInByte = bitRangeStart & 7;
274  size_t bitsSoFar = 0;
275 
276  while (numBits > 0 && (size_t) byte < size)
277  {
278  auto bitsThisTime = jmin (numBits, 8 - offsetInByte);
279  const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
280 
281  res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
282 
283  bitsSoFar += bitsThisTime;
284  numBits -= bitsThisTime;
285  ++byte;
286  offsetInByte = 0;
287  }
288 
289  return res;
290 }
291 
292 void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
293 {
294  auto byte = bitRangeStart >> 3;
295  auto offsetInByte = bitRangeStart & 7;
296  uint32 mask = ~((((uint32) 0xffffffff) << (32 - numBits)) >> (32 - numBits));
297 
298  while (numBits > 0 && (size_t) byte < size)
299  {
300  auto bitsThisTime = jmin (numBits, 8 - offsetInByte);
301 
302  const uint32 tempMask = (mask << offsetInByte) | ~((((uint32) 0xffffffff) >> offsetInByte) << offsetInByte);
303  const uint32 tempBits = (uint32) bitsToSet << offsetInByte;
304 
305  data[byte] = (char) (((uint32) data[byte] & tempMask) | tempBits);
306 
307  ++byte;
308  numBits -= bitsThisTime;
309  bitsToSet >>= bitsThisTime;
310  mask >>= bitsThisTime;
311  offsetInByte = 0;
312  }
313 }
314 
315 //==============================================================================
317 {
318  ensureSize ((size_t) hex.length() >> 1);
319  char* dest = data;
320  auto t = hex.text;
321 
322  for (;;)
323  {
324  int byte = 0;
325 
326  for (int loop = 2; --loop >= 0;)
327  {
328  byte <<= 4;
329 
330  for (;;)
331  {
332  auto c = t.getAndAdvance();
333 
334  if (c >= '0' && c <= '9') { byte |= c - '0'; break; }
335  if (c >= 'a' && c <= 'z') { byte |= c - ('a' - 10); break; }
336  if (c >= 'A' && c <= 'Z') { byte |= c - ('A' - 10); break; }
337 
338  if (c == 0)
339  {
340  setSize (static_cast<size_t> (dest - data));
341  return;
342  }
343  }
344  }
345 
346  *dest++ = (char) byte;
347  }
348 }
349 
350 //==============================================================================
351 static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
352 
354 {
355  auto numChars = ((size << 3) + 5) / 6;
356 
357  String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
358  auto initialLen = destString.length();
359  destString.preallocateBytes ((size_t) initialLen * sizeof (String::CharPointerType::CharType) + 2 + numChars);
360 
361  auto d = destString.getCharPointer();
362  d += initialLen;
363  d.write ('.');
364 
365  for (size_t i = 0; i < numChars; ++i)
366  d.write ((juce_wchar) (uint8) base64EncodingTable[getBitRange (i * 6, 6)]);
367 
368  d.writeNull();
369  return destString;
370 }
371 
372 static const char base64DecodingTable[] =
373 {
374  63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
375  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,
376  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
377 };
378 
380 {
381  auto dot = CharacterFunctions::find (s.text, (juce_wchar) '.');
382 
383  if (dot.isEmpty())
384  return false;
385 
386  auto numBytesNeeded = String (s.text, dot).getIntValue();
387 
388  setSize ((size_t) numBytesNeeded, true);
389 
390  auto srcChars = dot + 1;
391  int pos = 0;
392 
393  for (;;)
394  {
395  auto c = (int) srcChars.getAndAdvance();
396 
397  if (c == 0)
398  return true;
399 
400  c -= 43;
401 
402  if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
403  {
404  setBitRange ((size_t) pos, 6, base64DecodingTable[c]);
405  pos += 6;
406  }
407  }
408 }
409 
410 } // 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
void ensureSize(const size_t minimumSize, bool initialiseNewSpaceToZero=false)
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 setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
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 replaceWith(const void *data, size_t numBytes)
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 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:1198
int length() const noexcept
void preallocateBytes(size_t numBytesNeeded)
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
int getIntValue() const noexcept