OpenShot Audio Library | OpenShotAudio  0.6.0
juce_HeapBlock.h
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 #if ! (DOXYGEN || JUCE_EXCEPTIONS_DISABLED)
27 namespace HeapBlockHelper
28 {
29  template <bool shouldThrow>
30  struct ThrowOnFail { static void checkPointer (void*) {} };
31 
32  template <>
33  struct ThrowOnFail<true> { static void checkPointer (void* data) { if (data == nullptr) throw std::bad_alloc(); } };
34 }
35 #endif
36 
37 //==============================================================================
85 template <class ElementType, bool throwOnFailure = false>
86 class HeapBlock
87 {
88 private:
89  template <class OtherElementType>
90  using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,
91  std::remove_pointer_t<OtherElementType>>>;
92 
93 public:
94  //==============================================================================
100  HeapBlock() = default;
101 
110  template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
111  explicit HeapBlock (SizeType numElements)
112  : data (mallocWrapper (static_cast<size_t> (numElements) * sizeof (ElementType)))
113  {
114  }
115 
121  template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
122  HeapBlock (SizeType numElements, bool initialiseToZero)
123  : data (initialiseToZero ? callocWrapper (static_cast<size_t> (numElements), sizeof (ElementType))
124  : mallocWrapper (static_cast<size_t> (numElements) * sizeof (ElementType)))
125  {
126  }
127 
132  {
133  std::free (data);
134  }
135 
137  HeapBlock (HeapBlock&& other) noexcept
138  : data (other.data)
139  {
140  other.data = nullptr;
141  }
142 
144  HeapBlock& operator= (HeapBlock&& other) noexcept
145  {
146  std::swap (data, other.data);
147  return *this;
148  }
149 
154  template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
156  : data (reinterpret_cast<ElementType*> (other.data))
157  {
158  other.data = nullptr;
159  }
160 
165  template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
167  {
168  free();
169  data = reinterpret_cast<ElementType*> (other.data);
170  other.data = nullptr;
171  return *this;
172  }
173 
174  //==============================================================================
179  inline operator ElementType*() const noexcept { return data; }
180 
185  inline ElementType* get() const noexcept { return data; }
186 
191  inline ElementType* getData() const noexcept { return data; }
192 
197  inline operator void*() const noexcept { return static_cast<void*> (data); }
198 
203  inline operator const void*() const noexcept { return static_cast<const void*> (data); }
204 
209  inline ElementType* operator->() const noexcept { return data; }
210 
215  template <typename IndexType>
216  ElementType& operator[] (IndexType index) const noexcept { return data [index]; }
217 
221  template <typename IndexType>
222  ElementType* operator+ (IndexType index) const noexcept { return data + index; }
223 
224  //==============================================================================
228  inline bool operator== (const ElementType* otherPointer) const noexcept { return otherPointer == data; }
229 
233  inline bool operator!= (const ElementType* otherPointer) const noexcept { return otherPointer != data; }
234 
235  //==============================================================================
248  template <typename SizeType>
249  void malloc (SizeType newNumElements, size_t elementSize = sizeof (ElementType))
250  {
251  std::free (data);
252  data = mallocWrapper (static_cast<size_t> (newNumElements) * elementSize);
253  }
254 
258  template <typename SizeType>
259  void calloc (SizeType newNumElements, const size_t elementSize = sizeof (ElementType))
260  {
261  std::free (data);
262  data = callocWrapper (static_cast<size_t> (newNumElements), elementSize);
263  }
264 
269  template <typename SizeType>
270  void allocate (SizeType newNumElements, bool initialiseToZero)
271  {
272  std::free (data);
273  data = initialiseToZero ? callocWrapper (static_cast<size_t> (newNumElements), sizeof (ElementType))
274  : mallocWrapper (static_cast<size_t> (newNumElements) * sizeof (ElementType));
275  }
276 
282  template <typename SizeType>
283  void realloc (SizeType newNumElements, size_t elementSize = sizeof (ElementType))
284  {
285  data = reallocWrapper (data, static_cast<size_t> (newNumElements) * elementSize);
286  }
287 
291  void free() noexcept
292  {
293  std::free (data);
294  data = nullptr;
295  }
296 
300  template <bool otherBlockThrows>
302  {
303  std::swap (data, other.data);
304  }
305 
310  template <typename SizeType>
311  void clear (SizeType numElements) noexcept
312  {
313  zeromem (data, sizeof (ElementType) * static_cast<size_t> (numElements));
314  }
315 
317  using Type = ElementType;
318 
319 private:
320  //==============================================================================
321  // Calls to malloc, calloc and realloc with zero size have implementation-defined
322  // behaviour where either nullptr or a non-null pointer is returned.
323  template <typename Functor>
324  static ElementType* wrapper (size_t size, Functor&& f)
325  {
326  if (size == 0)
327  return nullptr;
328 
329  auto* memory = static_cast<ElementType*> (f());
330 
331  #if JUCE_EXCEPTIONS_DISABLED
332  jassert (memory != nullptr); // without exceptions, you'll need to find a better way to handle this failure case.
333  #else
334  HeapBlockHelper::ThrowOnFail<throwOnFailure>::checkPointer (memory);
335  #endif
336 
337  return memory;
338  }
339 
340  static ElementType* mallocWrapper (size_t size)
341  {
342  return wrapper (size, [size] { return std::malloc (size); });
343  }
344 
345  static ElementType* callocWrapper (size_t num, size_t size)
346  {
347  return wrapper (num * size, [num, size] { return std::calloc (num, size); });
348  }
349 
350  static ElementType* reallocWrapper (void* ptr, size_t newSize)
351  {
352  return wrapper (newSize, [ptr, newSize] { return std::realloc (ptr, newSize); });
353  }
354 
355  template <class OtherElementType, bool otherThrowOnFailure>
356  friend class HeapBlock;
357 
358  //==============================================================================
359  ElementType* data = nullptr;
360 
361  #if ! (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD))
362  JUCE_DECLARE_NON_COPYABLE (HeapBlock)
363  JUCE_PREVENT_HEAP_ALLOCATION // Creating a 'new HeapBlock' would be missing the point!
364  #endif
365 };
366 
367 } // namespace juce
HeapBlock & operator=(HeapBlock &&other) noexcept
HeapBlock(SizeType numElements)
HeapBlock(HeapBlock< OtherElementType, otherThrowOnFailure > &&other) noexcept
ElementType * get() const noexcept
ElementType Type
void clear(SizeType numElements) noexcept
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
bool operator!=(const ElementType *otherPointer) const noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
ElementType * getData() const noexcept
HeapBlock(HeapBlock &&other) noexcept
ElementType * operator+(IndexType index) const noexcept
HeapBlock()=default
void allocate(SizeType newNumElements, bool initialiseToZero)
HeapBlock(SizeType numElements, bool initialiseToZero)
bool operator==(const ElementType *otherPointer) const noexcept
void realloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
ElementType * operator->() const noexcept
void free() noexcept
ElementType & operator[](IndexType index) const noexcept
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))