OpenShot Library | OpenShotAudio  0.2.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
int getBitRange(size_t bitRangeStart, size_t numBitsToRead) const noexcept
Reads a number of bits from the memory block, treating it as one long binary sequence.
void allocate(SizeType newNumElements, bool initialiseToZero)
Allocates a specified amount of memory and optionally clears it.
void insert(const void *dataToInsert, size_t numBytesToInsert, size_t insertPosition)
Inserts some data into the block.
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
void ensureSize(const size_t minimumSize, bool initialiseNewSpaceToZero=false)
Increases the block&#39;s size only if it&#39;s smaller than a given size.
bool operator!=(const MemoryBlock &other) const noexcept
Compares two memory blocks.
A simple class for holding temporary references to a string literal or String.
MemoryBlock() noexcept
Create an uninitialised block with 0 size.
bool operator==(const MemoryBlock &other) const noexcept
Compares two memory blocks.
~MemoryBlock() noexcept
Destructor.
int length() const noexcept
Returns the number of characters in the string.
void setBitRange(size_t bitRangeStart, size_t numBits, int binaryNumberToApply) noexcept
Sets a number of bits in the memory block, treating it as a long binary sequence. ...
void realloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Re-allocates a specified amount of memory.
void append(const void *data, size_t numBytes)
Adds another block of data to the end of this one.
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
Definition: juce_String.h:1202
void copyFrom(const void *srcData, int destinationOffset, size_t numBytes) noexcept
Copies data into this MemoryBlock from a memory address.
The JUCE String class!
Definition: juce_String.h:42
String toString() const
Attempts to parse the contents of the block as a zero-terminated UTF8 string.
void copyTo(void *destData, int sourceOffset, size_t numBytes) const noexcept
Copies data from this MemoryBlock to a memory address.
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Returns a pointer to the first occurrence of a substring in a string.
juce_wchar getAndAdvance() noexcept
Returns the character that this pointer is currently pointing to, and then advances the pointer to po...
void swapWith(MemoryBlock &other) noexcept
Exchanges the contents of this and another memory block.
bool matches(const void *data, size_t dataSize) const noexcept
Returns true if the data in this MemoryBlock matches the raw bytes passed-in.
void removeSection(size_t startByte, size_t numBytesToRemove)
Chops out a section of the block.
void reset()
Frees all the blocks data, setting its size to 0.
void free() noexcept
Frees any currently-allocated data.
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Swaps this object&#39;s data with the data of another HeapBlock.
void preallocateBytes(size_t numBytesNeeded)
Increases the string&#39;s internally allocated storage.
String::CharPointerType text
The text that is referenced.
bool fromBase64Encoding(StringRef encodedString)
Takes a string created by MemoryBlock::toBase64Encoding() and extracts the original data...
int getIntValue() const noexcept
Reads the value of the string as a decimal number (up to 32 bits in size).
int length() const noexcept
Returns the number of characters in the string.
A class to hold a resizable block of raw data.
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Creates a String from a UTF-8 encoded buffer.
void fillWith(uint8 valueToUse) noexcept
Fills the entire memory block with a repeated byte value.
void loadFromHexString(StringRef sourceHexString)
Parses a string of hexadecimal numbers and writes this data into the memory block.
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Resizes the memory block.
String toBase64Encoding() const
Returns a string of characters in a JUCE-specific text encoding that represents the binary contents o...
MemoryBlock & operator=(const MemoryBlock &)
Copies another memory block onto this one.
void replaceWith(const void *data, size_t numBytes)
Resizes this block to the given size and fills its contents from the supplied buffer.
void write(const juce_wchar charToWrite) noexcept
Writes a unicode character to this string, and advances this pointer to point to the next position...