text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

#ifndef DOXYGEN
 namespace AtomicHelpers
 {
     template <typename T> struct DiffTypeHelper     { typedef T Type; };
     template <typename T> struct DiffTypeHelper<T*> { typedef std::ptrdiff_t Type; };
 }
#endif

#if JUCE_ATOMIC_AVAILABLE
 //==============================================================================
 /**
     A simple wrapper around std::atomic.
 */
 template <typename Type>
 struct Atomic  final
 {
     typedef typename AtomicHelpers::DiffTypeHelper<Type>::Type DiffType;

     /** Creates a new value, initialised to zero. */
     Atomic() noexcept  : value (0) {}

     /** Creates a new value, with a given initial value. */
     Atomic (Type initialValue) noexcept  : value (initialValue) {}

     /** Copies another value (atomically). */
     Atomic (const Atomic& other) noexcept  : value (other.get()) {}

     /** Destructor. */
     ~Atomic() noexcept
     {
        #if __cpp_lib_atomic_is_always_lock_free
         static_assert (std::atomic<Type>::is_always_lock_free,
                        "This class can only be used for lock-free types");
        #endif
     }

     /** Atomically reads and returns the current value. */
     Type get() const noexcept               { return value.load(); }

     /** Atomically sets the current value. */
     void set (Type newValue) noexcept       { value = newValue; }

     /** Atomically sets the current value, returning the value that was replaced. */
     Type exchange (Type newValue) noexcept  { return value.exchange (newValue); }

     /** Atomically compares this value with a target value, and if it is equal, sets
         this to be equal to a new value.

         This operation is the atomic equivalent of doing this:
         @code
         bool compareAndSetBool (Type newValue, Type valueToCompare)
         {
             if (get() == valueToCompare)
             {
                 set (newValue);
                 return true;
             }

             return false;
         }
         @endcode

         Internally, this method calls std::atomic::compare_exchange_strong with
         memory_order_seq_cst (the strictest std::memory_order).

         @returns true if the comparison was true and the value was replaced; false if
                  the comparison failed and the value was left unchanged.
         @see compareAndSetValue
     */
     bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept
     {
         return value.compare_exchange_strong (valueToCompare, newValue);
     }

     /** Copies another value into this one (atomically). */
     Atomic<Type>& operator= (const Atomic& other) noexcept
     {
         value = other.value.load();
         return *this;
     }

     /** Copies another value into this one (atomically). */
     Atomic<Type>& operator= (Type newValue) noexcept
     {
         value = newValue;
         return *this;
     }

     /** Atomically adds a number to this value, returning the new value. */
     Type operator+= (DiffType amountToAdd) noexcept { return value += amountToAdd; }

     /** Atomically subtracts a number from this value, returning the new value. */
     Type operator-= (DiffType amountToSubtract) noexcept { return value -= amountToSubtract; }

     /** Atomically increments this value, returning the new value. */
     Type operator++() noexcept { return ++value; }

     /** Atomically decrements this value, returning the new value. */
     Type operator--() noexcept { return --value; }

     /** Implements a memory read/write barrier.

         Internally this calls std::atomic_thread_fence with
         memory_order_seq_cst (the strictest std::memory_order).
      */
     void memoryBarrier() noexcept          { atomic_thread_fence (std::memory_order_seq_cst); }

     /** The std::atomic object that this class operates on. */
     std::atomic<Type> value;

     //==============================================================================
    #ifndef DOXYGEN
     // This method has been deprecated as there is no equivalent method in std::atomic.
     JUCE_DEPRECATED (Type compareAndSetValue (Type, Type) noexcept);
    #endif
 };

#else

 #ifndef DOXYGEN
  template <typename Type> class AtomicBase;
 #endif

 //==============================================================================
 /**
     Simple class to hold a primitive value and perform atomic operations on it.

     The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
     There are methods to perform most of the basic atomic operations.
 */
 template <typename Type>
 class Atomic  final  : public AtomicBase<Type>
 {
 public:
     /** Resulting type when subtracting the underlying Type. */
     typedef typename AtomicBase<Type>::DiffType DiffType;

     /** Creates a new value, initialised to zero. */
     inline Atomic() noexcept {}

     /** Creates a new value, with a given initial value. */
     inline explicit Atomic (const Type initialValue) noexcept  : AtomicBase<Type> (initialValue) {}

     /** Copies another value (atomically). */
     inline Atomic (const Atomic& other) noexcept   : AtomicBase<Type> (other) {}

     /** Destructor. */
     inline ~Atomic() noexcept
     {
         static_assert (sizeof (Type) == 4 || sizeof (Type) == 8,
                        "Atomic can only be used for types which are 32 or 64 bits in size");
     }

     /** Atomically reads and returns the current value. */
     inline Type get() const noexcept   { return AtomicBase<Type>::get(); }

     /** Copies another value into this one (atomically). */
     inline Atomic& operator= (const Atomic& other) noexcept         { AtomicBase<Type>::operator= (other); return *this; }

     /** Copies another value into this one (atomically). */
     inline Atomic& operator= (const Type newValue) noexcept         { AtomicBase<Type>::operator= (newValue); return *this; }

     /** Atomically sets the current value. */
     inline void set (Type newValue) noexcept                        { exchange (newValue); }

     /** Atomically sets the current value, returning the value that was replaced. */
     inline Type exchange (Type v) noexcept                          { return AtomicBase<Type>::exchange (v); }

     /** Atomically adds a number to this value, returning the new value. */
     Type operator+= (DiffType amountToAdd) noexcept;

     /** Atomically subtracts a number from this value, returning the new value. */
     Type operator-= (DiffType amountToSubtract) noexcept;

     /** Atomically increments this value, returning the new value. */
     Type operator++() noexcept;

     /** Atomically decrements this value, returning the new value. */
     Type operator--() noexcept;

     /** Atomically compares this value with a target value, and if it is equal, sets
         this to be equal to a new value.

         This operation is the atomic equivalent of doing this:
         @code
         bool compareAndSetBool (Type newValue, Type valueToCompare)
         {
             if (get() == valueToCompare)
             {
                 set (newValue);
                 return true;
             }

             return false;
         }
         @endcode

         @returns true if the comparison was true and the value was replaced; false if
                  the comparison failed and the value was left unchanged.
         @see compareAndSetValue
     */
     inline bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept  { return AtomicBase<Type>::compareAndSetBool (newValue, valueToCompare); }

     /** Atomically compares this value with a target value, and if it is equal, sets
         this to be equal to a new value.

         This operation is the atomic equivalent of doing this:
         @code
         Type compareAndSetValue (Type newValue, Type valueToCompare)
         {
             Type oldValue = get();
             if (oldValue == valueToCompare)
                 set (newValue);

             return oldValue;
         }
         @endcode

         @returns the old value before it was changed.
         @see compareAndSetBool
     */
     inline Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept  { return AtomicBase<Type>::compareAndSetValue (newValue, valueToCompare); }

     /** Implements a memory read/write barrier. */
     static inline void memoryBarrier() noexcept { AtomicBase<Type>::memoryBarrier (); }
 };

 #ifndef DOXYGEN

  //==============================================================================
  // Internal implementation follows
  //==============================================================================
  template <typename Type>
  class AtomicBase
  {
  public:
      typedef typename AtomicHelpers::DiffTypeHelper<Type>::Type DiffType;

      inline AtomicBase() noexcept : value (0) {}
      inline explicit AtomicBase (const Type v) noexcept : value (v) {}
      inline AtomicBase (const AtomicBase& other) noexcept : value (other.get()) {}
      Type get() const noexcept;
      inline AtomicBase& operator= (const AtomicBase<Type>& other) noexcept { exchange (other.get()); return *this; }
      inline AtomicBase& operator= (const Type newValue) noexcept           { exchange (newValue);    return *this; }
      void set (Type newValue) noexcept                                     { exchange (newValue); }
      Type exchange (Type) noexcept;
      bool compareAndSetBool (Type, Type) noexcept;
      Type compareAndSetValue (Type, Type) noexcept;
      static void memoryBarrier() noexcept;

      //==============================================================================
      #if JUCE_64BIT
       JUCE_ALIGN (8)
      #else
       JUCE_ALIGN (4)
      #endif

      /** The raw value that this class operates on.
          This is exposed publicly in case you need to manipulate it directly
          for performance reasons.
      */
      volatile Type value;

  protected:
      template <typename Dest, typename Source>
      static inline Dest castTo (Source value) noexcept         { union { Dest d; Source s; } u; u.s = value; return u.d; }

      static inline Type castFrom32Bit (int32 value) noexcept   { return castTo <Type, int32> (value); }
      static inline Type castFrom64Bit (int64 value) noexcept   { return castTo <Type, int64> (value); }
      static inline int32 castTo32Bit (Type value) noexcept     { return castTo <int32, Type> (value); }
      static inline int64 castTo64Bit (Type value) noexcept     { return castTo <int64, Type> (value); }

      Type operator++ (int); // better to just use pre-increment with atomics..
      Type operator-- (int);

      /** This templated negate function will negate pointers as well as integers */
      template <typename ValueType>
      inline ValueType negateValue (ValueType n) noexcept
      {
          return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
              : (sizeof (ValueType) == 2 ? (ValueType) -(short) n
              : (sizeof (ValueType) == 4 ? (ValueType) -(int) n
              : ((ValueType) -(int64) n)));
      }

      /** This templated negate function will negate pointers as well as integers */
      template <typename PointerType>
      inline PointerType* negateValue (PointerType* n) noexcept
      {
          return reinterpret_cast<PointerType*> (-reinterpret_cast<pointer_sized_int> (n));
      }
  };

  //==============================================================================
  // Specialisation for void* which does not include the pointer arithmetic
  template <>
  class Atomic<void*> : public AtomicBase<void*>
  {
  public:
      inline Atomic() noexcept {}
      inline explicit Atomic (void* const initialValue) noexcept  : AtomicBase<void*> (initialValue) {}
      inline Atomic (const Atomic<void*>& other) noexcept   : AtomicBase<void*> (other) {}
      inline void* get() const noexcept   { return AtomicBase<void*>::get(); }
      inline Atomic& operator= (const Atomic& other) noexcept         { AtomicBase<void*>::operator= (other); return *this; }
      inline Atomic& operator= (void* const newValue) noexcept        { AtomicBase<void*>::operator= (newValue); return *this; }
      inline void set (void* newValue) noexcept                       { exchange (newValue); }
      inline void* exchange (void* v) noexcept                        { return AtomicBase<void*>::exchange (v); }
      inline bool compareAndSetBool (void* newValue, void* valueToCompare) noexcept  { return AtomicBase<void*>::compareAndSetBool (newValue, valueToCompare); }
      inline void* compareAndSetValue (void* newValue, void* valueToCompare) noexcept  { return AtomicBase<void*>::compareAndSetValue (newValue, valueToCompare); }
      static inline void memoryBarrier() noexcept { AtomicBase<void*>::memoryBarrier(); }
  };

  //==============================================================================
  /*
      The following code is in the header so that the atomics can be inlined where possible...
  */
  #if JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
   #define JUCE_ATOMICS_MAC_LEGACY 1      // Older OSX builds using gcc4.1 or earlier
  #elif JUCE_GCC || JUCE_CLANG
   #define JUCE_ATOMICS_GCC 1        // GCC with intrinsics
   #if JUCE_IOS || JUCE_ANDROID      // (64-bit ops will compile but not link on these mobile OSes)
    #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1
   #endif
  #endif

  template <typename Type>
  struct AtomicIncrementDecrement
  {
      static inline Type inc (AtomicBase<Type>& a) noexcept
      {
        #if JUCE_ATOMICS_MAC_LEGACY
         return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((volatile int32_t*) &a.value)
                                   : (Type) OSAtomicIncrement64Barrier ((volatile int64_t*) &a.value);
        #elif JUCE_ATOMICS_GCC
         return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) 1)
                                   : (Type) __sync_add_and_fetch ((int64_t*) & (a.value), 1);
        #endif
      }

      static inline Type dec (AtomicBase<Type>& a) noexcept
      {
        #if JUCE_ATOMICS_MAC_LEGACY
         return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((volatile int32_t*) &a.value)
                                   : (Type) OSAtomicDecrement64Barrier ((volatile int64_t*) &a.value);
        #elif JUCE_ATOMICS_GCC
         return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (& (a.value), (Type) -1)
                                   : (Type) __sync_add_and_fetch ((int64_t*) & (a.value), -1);
        #endif
      }
  };

  template <typename Type>
  struct AtomicIncrementDecrement<Type*>
  {
      static inline Type* inc (Atomic<Type*>& a) noexcept { return a.operator+= (1); }
      static inline Type* dec (Atomic<Type*>& a) noexcept { return a.operator-= (1); }
  };

  //==============================================================================
  template <typename Type>
  inline Type AtomicBase<Type>::get() const noexcept
  {
    #if JUCE_ATOMICS_MAC_LEGACY
     return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (volatile int32_t*) &value))
                               : castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (volatile int64_t*) &value));
    #elif JUCE_ATOMICS_GCC
     return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0))
                               : castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0));
    #endif
  }

  template <typename Type>
  inline Type AtomicBase<Type>::exchange (const Type newValue) noexcept
  {
     #if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC
      Type currentVal = value;
      while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
      return currentVal;
     #endif
  }

  template <typename Type>
  inline Type Atomic<Type>::operator+= (const DiffType amountToAdd) noexcept
  {
      Type amount = (Type() + amountToAdd);

     #if JUCE_ATOMICS_MAC_LEGACY
      return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amount), (volatile int32_t*) &AtomicBase<Type>::value)
                                : (Type) OSAtomicAdd64Barrier ((int64_t) amount, (volatile int64_t*) &AtomicBase<Type>::value);
     #elif JUCE_ATOMICS_GCC
      return (Type) __sync_add_and_fetch (& (AtomicBase<Type>::value), amount);
     #endif
  }

  template <typename Type>
  inline Type Atomic<Type>::operator-= (const DiffType amountToSubtract) noexcept
  {
      return operator+= (AtomicBase<Type>::negateValue (amountToSubtract));
  }

  template <typename Type>
  inline Type Atomic<Type>::operator++() noexcept   { return AtomicIncrementDecrement<Type>::inc (*this); }

  template <typename Type>
  inline Type Atomic<Type>::operator--() noexcept   { return AtomicIncrementDecrement<Type>::dec (*this); }

  template <typename Type>
  inline bool AtomicBase<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
  {
     #if JUCE_ATOMICS_MAC_LEGACY
      return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (volatile int32_t*) &value)
                                : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (volatile int64_t*) &value);
     #elif JUCE_ATOMICS_GCC
      return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
                                : __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
     #endif
  }

  template <typename Type>
  inline Type AtomicBase<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
  {
     #if JUCE_ATOMICS_MAC_LEGACY
      for (;;) // Annoying workaround for only having a bool CAS operation..
      {
          if (compareAndSetBool (newValue, valueToCompare))
              return valueToCompare;

          const Type result = value;
          if (result != valueToCompare)
              return result;
      }
     #elif JUCE_ATOMICS_GCC
      return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
                                : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
     #endif
  }

  template <typename Type>
  inline void AtomicBase<Type>::memoryBarrier() noexcept
  {
    #if JUCE_ATOMICS_MAC_LEGACY
      OSMemoryBarrier();
    #elif JUCE_ATOMICS_GCC
      __sync_synchronize();
    #endif
  }

 #endif

#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    A class to hold a resizable block of raw data.

*/
class JUCE_API  MemoryBlock
{
public:
    //==============================================================================
    /** Create an uninitialised block with 0 size. */
    MemoryBlock() noexcept;

    /** Creates a memory block with a given initial size.

        @param initialSize          the size of block to create
        @param initialiseToZero     whether to clear the memory or just leave it uninitialised
    */
    MemoryBlock (const size_t initialSize,
                 bool initialiseToZero = false);

    /** Creates a copy of another memory block. */
    MemoryBlock (const MemoryBlock&);

    /** Creates a memory block using a copy of a block of data.

        @param dataToInitialiseFrom     some data to copy into this block
        @param sizeInBytes              how much space to use
    */
    MemoryBlock (const void* dataToInitialiseFrom, size_t sizeInBytes);

    /** Destructor. */
    ~MemoryBlock() noexcept;

    /** Copies another memory block onto this one.
        This block will be resized and copied to exactly match the other one.
    */
    MemoryBlock& operator= (const MemoryBlock&);

    /** Move constructor */
    MemoryBlock (MemoryBlock&&) noexcept;

    /** Move assignment operator */
    MemoryBlock& operator= (MemoryBlock&&) noexcept;

    //==============================================================================
    /** Compares two memory blocks.
        @returns true only if the two blocks are the same size and have identical contents.
    */
    bool operator== (const MemoryBlock& other) const noexcept;

    /** Compares two memory blocks.
        @returns true if the two blocks are different sizes or have different contents.
    */
    bool operator!= (const MemoryBlock& other) const noexcept;

    /** Returns true if the data in this MemoryBlock matches the raw bytes passed-in. */
    bool matches (const void* data, size_t dataSize) const noexcept;

    //==============================================================================
    /** Returns a void pointer to the data.

        Note that the pointer returned will probably become invalid when the
        block is resized.
    */
    void* getData() const noexcept                                  { return data; }

    /** Returns a byte from the memory block.
        This returns a reference, so you can also use it to set a byte.
    */
    template <typename Type>
    char& operator[] (const Type offset) const noexcept             { return data [offset]; }

    /** Returns an iterator for the data. */
    char* begin() const noexcept                                    { return data; }

    /** Returns an end-iterator for the data. */
    char* end() const noexcept                                      { return begin() + getSize(); }

    //==============================================================================
    /** Returns the block's current allocated size, in bytes. */
    size_t getSize() const noexcept                                 { return size; }

    /** Resizes the memory block.

        Any data that is present in both the old and new sizes will be retained.
        When enlarging the block, the new space that is allocated at the end can either be
        cleared, or left uninitialised.

        @param newSize                      the new desired size for the block
        @param initialiseNewSpaceToZero     if the block gets enlarged, this determines
                                            whether to clear the new section or just leave it
                                            uninitialised
        @see ensureSize
    */
    void setSize (const size_t newSize,
                  bool initialiseNewSpaceToZero = false);

    /** Increases the block's size only if it's smaller than a given size.

        @param minimumSize                  if the block is already bigger than this size, no action
                                            will be taken; otherwise it will be increased to this size
        @param initialiseNewSpaceToZero     if the block gets enlarged, this determines
                                            whether to clear the new section or just leave it
                                            uninitialised
        @see setSize
    */
    void ensureSize (const size_t minimumSize,
                     bool initialiseNewSpaceToZero = false);

    /** Frees all the blocks data, setting its size to 0. */
    void reset();

    //==============================================================================
    /** Fills the entire memory block with a repeated byte value.
        This is handy for clearing a block of memory to zero.
    */
    void fillWith (uint8 valueToUse) noexcept;

    /** Adds another block of data to the end of this one.
        The data pointer must not be null. This block's size will be increased accordingly.
    */
    void append (const void* data, size_t numBytes);

    /** Resizes this block to the given size and fills its contents from the supplied buffer.
        The data pointer must not be null.
    */
    void replaceWith (const void* data, size_t numBytes);

    /** Inserts some data into the block.
        The dataToInsert pointer must not be null. This block's size will be increased accordingly.
        If the insert position lies outside the valid range of the block, it will be clipped to
        within the range before being used.
    */
    void insert (const void* dataToInsert, size_t numBytesToInsert, size_t insertPosition);

    /** Chops out a section  of the block.

        This will remove a section of the memory block and close the gap around it,
        shifting any subsequent data downwards and reducing the size of the block.

        If the range specified goes beyond the size of the block, it will be clipped.
    */
    void removeSection (size_t startByte, size_t numBytesToRemove);

    //==============================================================================
    /** Copies data into this MemoryBlock from a memory address.

        @param srcData              the memory location of the data to copy into this block
        @param destinationOffset    the offset in this block at which the data being copied should begin
        @param numBytes             how much to copy in (if this goes beyond the size of the memory block,
                                    it will be clipped so not to do anything nasty)
    */
    void copyFrom (const void* srcData,
                   int destinationOffset,
                   size_t numBytes) noexcept;

    /** Copies data from this MemoryBlock to a memory address.

        @param destData         the memory location to write to
        @param sourceOffset     the offset within this block from which the copied data will be read
        @param numBytes         how much to copy (if this extends beyond the limits of the memory block,
                                zeros will be used for that portion of the data)
    */
    void copyTo (void* destData,
                 int sourceOffset,
                 size_t numBytes) const noexcept;

    //==============================================================================
    /** Exchanges the contents of this and another memory block.
        No actual copying is required for this, so it's very fast.
    */
    void swapWith (MemoryBlock& other) noexcept;

    //==============================================================================
    /** Attempts to parse the contents of the block as a zero-terminated UTF8 string. */
    String toString() const;

    //==============================================================================
    /** Parses a string of hexadecimal numbers and writes this data into the memory block.

        The block will be resized to the number of valid bytes read from the string.
        Non-hex characters in the string will be ignored.

        @see String::toHexString()
    */
    void loadFromHexString (StringRef sourceHexString);

    //==============================================================================
    /** Sets a number of bits in the memory block, treating it as a long binary sequence. */
    void setBitRange (size_t bitRangeStart,
                      size_t numBits,
                      int binaryNumberToApply) noexcept;

    /** Reads a number of bits from the memory block, treating it as one long binary sequence */
    int getBitRange (size_t bitRangeStart,
                     size_t numBitsToRead) const noexcept;

    //==============================================================================
    /** Returns a string of characters in a JUCE-specific text encoding that represents the
        binary contents of this block.

        This uses a JUCE-specific (i.e. not standard!) 64-bit encoding system to convert binary
        data into a string of ASCII characters for purposes like storage in XML.
        Note that this proprietary format is mainly kept here for backwards-compatibility, and
        you may prefer to use the Base64::toBase64() method if you want to use the standard
        base-64 encoding.

        @see fromBase64Encoding, Base64::toBase64, Base64::convertToBase64
    */
    String toBase64Encoding() const;

    /** Takes a string created by MemoryBlock::toBase64Encoding() and extracts the original data.

        The string passed in must have been created by to64BitEncoding(), and this
        block will be resized to recreate the original data block.

        Note that these methods use a JUCE-specific (i.e. not standard!) 64-bit encoding system.
        You may prefer to use the Base64::convertFromBase64() method if you want to use the
        standard base-64 encoding.

        @see toBase64Encoding, Base64::convertFromBase64
    */
    bool fromBase64Encoding  (StringRef encodedString);

private:
    //==============================================================================
    typedef HeapBlock<char, true> HeapBlockType;
    HeapBlockType data;
    size_t size = 0;

    JUCE_LEAK_DETECTOR (MemoryBlock)
};

} // namespace juce

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

MemoryBlock::MemoryBlock() noexcept {}

MemoryBlock::MemoryBlock (size_t initialSize, bool initialiseToZero)
{
    if (initialSize > 0)
    {
        size = initialSize;
        data.allocate (initialSize, initialiseToZero);
    }
    else
    {
        size = 0;
    }
}

MemoryBlock::MemoryBlock (const MemoryBlock& other)
    : size (other.size)
{
    if (size > 0)
    {
        jassert (other.data != nullptr);
        data.malloc (size);
        memcpy (data, other.data, size);
    }
}

MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, const size_t sizeInBytes)
    : size (sizeInBytes)
{
    jassert (((ssize_t) sizeInBytes) >= 0);

    if (size > 0)
    {
        jassert (dataToInitialiseFrom != nullptr); // non-zero size, but a zero pointer passed-in?

        data.malloc (size);

        if (dataToInitialiseFrom != nullptr)
            memcpy (data, dataToInitialiseFrom, size);
    }
}

MemoryBlock::~MemoryBlock() noexcept
{
}

MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other)
{
    if (this != &other)
    {
        setSize (other.size, false);
        memcpy (data, other.data, size);
    }

    return *this;
}

MemoryBlock::MemoryBlock (MemoryBlock&& other) noexcept
    : data (static_cast<HeapBlockType&&> (other.data)),
      size (other.size)
{
}

MemoryBlock& MemoryBlock::operator= (MemoryBlock&& other) noexcept
{
    data = static_cast<HeapBlockType&&> (other.data);
    size = other.size;
    return *this;
}

//==============================================================================
bool MemoryBlock::operator== (const MemoryBlock& other) const noexcept
{
    return matches (other.data, other.size);
}

bool MemoryBlock::operator!= (const MemoryBlock& other) const noexcept
{
    return ! operator== (other);
}

bool MemoryBlock::matches (const void* dataToCompare, size_t dataSize) const noexcept
{
    return size == dataSize
            && memcmp (data, dataToCompare, size) == 0;
}

//==============================================================================
// this will resize the block to this size
void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
{
    if (size != newSize)
    {
        if (newSize <= 0)
        {
            reset();
        }
        else
        {
            if (data != nullptr)
            {
                data.realloc (newSize);

                if (initialiseToZero && (newSize > size))
                    zeromem (data + size, newSize - size);
            }
            else
            {
                data.allocate (newSize, initialiseToZero);
            }

            size = newSize;
        }
    }
}

void MemoryBlock::reset()
{
    data.free();
    size = 0;
}

void MemoryBlock::ensureSize (size_t minimumSize, bool initialiseToZero)
{
    if (size < minimumSize)
        setSize (minimumSize, initialiseToZero);
}

void MemoryBlock::swapWith (MemoryBlock& other) noexcept
{
    std::swap (size, other.size);
    data.swapWith (other.data);
}

//==============================================================================
void MemoryBlock::fillWith (uint8 value) noexcept
{
    memset (data, (int) value, size);
}

void MemoryBlock::append (const void* srcData, size_t numBytes)
{
    if (numBytes > 0)
    {
        jassert (srcData != nullptr); // this must not be null!
        auto oldSize = size;
        setSize (size + numBytes);
        memcpy (data + oldSize, srcData, numBytes);
    }
}

void MemoryBlock::replaceWith (const void* srcData, size_t numBytes)
{
    if (numBytes > 0)
    {
        jassert (srcData != nullptr); // this must not be null!
        setSize (numBytes);
        memcpy (data, srcData, numBytes);
    }
}

void MemoryBlock::insert (const void* srcData, size_t numBytes, size_t insertPosition)
{
    if (numBytes > 0)
    {
        jassert (srcData != nullptr); // this must not be null!
        insertPosition = jmin (size, insertPosition);
        auto trailingDataSize = size - insertPosition;
        setSize (size + numBytes, false);

        if (trailingDataSize > 0)
            memmove (data + insertPosition + numBytes,
                     data + insertPosition,
                     trailingDataSize);

        memcpy (data + insertPosition, srcData, numBytes);
    }
}

void MemoryBlock::removeSection (size_t startByte, size_t numBytesToRemove)
{
    if (startByte + numBytesToRemove >= size)
    {
        setSize (startByte);
    }
    else if (numBytesToRemove > 0)
    {
        memmove (data + startByte,
                 data + startByte + numBytesToRemove,
                 size - (startByte + numBytesToRemove));

        setSize (size - numBytesToRemove);
    }
}

void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
{
    auto* d = static_cast<const char*> (src);

    if (offset < 0)
    {
        d -= offset;
        num += (size_t) -offset;
        offset = 0;
    }

    if ((size_t) offset + num > size)
        num = size - (size_t) offset;

    if (num > 0)
        memcpy (data + offset, d, num);
}

void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
{
    auto* d = static_cast<char*> (dst);

    if (offset < 0)
    {
        zeromem (d, (size_t) -offset);
        d -= offset;
        num -= (size_t) -offset;
        offset = 0;
    }

    if ((size_t) offset + num > size)
    {
        auto newNum = (size_t) size - (size_t) offset;
        zeromem (d + newNum, num - newNum);
        num = newNum;
    }

    if (num > 0)
        memcpy (d, data + offset, num);
}

String MemoryBlock::toString() const
{
    return String::fromUTF8 (data, (int) size);
}

//==============================================================================
int MemoryBlock::getBitRange (size_t bitRangeStart, size_t numBits) const noexcept
{
    int res = 0;

    auto byte = bitRangeStart >> 3;
    auto offsetInByte = bitRangeStart & 7;
    size_t bitsSoFar = 0;

    while (numBits > 0 && (size_t) byte < size)
    {
        auto bitsThisTime = jmin (numBits, 8 - offsetInByte);
        const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;

        res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);

        bitsSoFar += bitsThisTime;
        numBits -= bitsThisTime;
        ++byte;
        offsetInByte = 0;
    }

    return res;
}

void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
{
    auto byte = bitRangeStart >> 3;
    auto offsetInByte = bitRangeStart & 7;
    uint32 mask = ~((((uint32) 0xffffffff) << (32 - numBits)) >> (32 - numBits));

    while (numBits > 0 && (size_t) byte < size)
    {
        auto bitsThisTime = jmin (numBits, 8 - offsetInByte);

        const uint32 tempMask = (mask << offsetInByte) | ~((((uint32) 0xffffffff) >> offsetInByte) << offsetInByte);
        const uint32 tempBits = (uint32) bitsToSet << offsetInByte;

        data[byte] = (char) (((uint32) data[byte] & tempMask) | tempBits);

        ++byte;
        numBits -= bitsThisTime;
        bitsToSet >>= bitsThisTime;
        mask >>= bitsThisTime;
        offsetInByte = 0;
    }
}

//==============================================================================
void MemoryBlock::loadFromHexString (StringRef hex)
{
    ensureSize ((size_t) hex.length() >> 1);
    char* dest = data;
    auto t = hex.text;

    for (;;)
    {
        int byte = 0;

        for (int loop = 2; --loop >= 0;)
        {
            byte <<= 4;

            for (;;)
            {
                auto c = t.getAndAdvance();

                if (c >= '0' && c <= '9')    { byte |= c - '0';        break; }
                if (c >= 'a' && c <= 'z')    { byte |= c - ('a' - 10); break; }
                if (c >= 'A' && c <= 'Z')    { byte |= c - ('A' - 10); break; }

                if (c == 0)
                {
                    setSize (static_cast<size_t> (dest - data));
                    return;
                }
            }
        }

        *dest++ = (char) byte;
    }
}

//==============================================================================
static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";

String MemoryBlock::toBase64Encoding() const
{
    auto numChars = ((size << 3) + 5) / 6;

    String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
    auto initialLen = destString.length();
    destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (size_t) initialLen + 2 + numChars);

    auto d = destString.getCharPointer();
    d += initialLen;
    d.write ('.');

    for (size_t i = 0; i < numChars; ++i)
        d.write ((juce_wchar) (uint8) base64EncodingTable[getBitRange (i * 6, 6)]);

    d.writeNull();
    return destString;
}

static const char base64DecodingTable[] =
{
    63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
    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,
    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
};

bool MemoryBlock::fromBase64Encoding (StringRef s)
{
    auto dot = CharacterFunctions::find (s.text, (juce_wchar) '.');

    if (dot.isEmpty())
        return false;

    auto numBytesNeeded = String (s.text, dot).getIntValue();

    setSize ((size_t) numBytesNeeded, true);

    auto srcChars = dot + 1;
    int pos = 0;

    for (;;)
    {
        auto c = (int) srcChars.getAndAdvance();

        if (c == 0)
            return true;

        c -= 43;

        if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
        {
            setBitRange ((size_t) pos, 6, base64DecodingTable[c]);
            pos += 6;
        }
    }
}

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/** Contains static methods for converting the byte order between different
    endiannesses.
*/
class JUCE_API  ByteOrder
{
public:
    //==============================================================================
    /** Swaps the upper and lower bytes of a 16-bit integer. */
    JUCE_CONSTEXPR static uint16 swap (uint16 value) noexcept;

    /** Reverses the order of the 4 bytes in a 32-bit integer. */
    static uint32 swap (uint32 value) noexcept;

    /** Reverses the order of the 8 bytes in a 64-bit integer. */
    static uint64 swap (uint64 value) noexcept;

    //==============================================================================
    /** Swaps the byte order of a 16-bit unsigned int if the CPU is big-endian */
    JUCE_CONSTEXPR static uint16 swapIfBigEndian (uint16 value) noexcept;

    /** Swaps the byte order of a 32-bit unsigned int if the CPU is big-endian */
    static uint32 swapIfBigEndian (uint32 value) noexcept;

    /** Swaps the byte order of a 64-bit unsigned int if the CPU is big-endian */
    static uint64 swapIfBigEndian (uint64 value) noexcept;

    /** Swaps the byte order of a 16-bit signed int if the CPU is big-endian */
    JUCE_CONSTEXPR static int16 swapIfBigEndian (int16 value) noexcept;

    /** Swaps the byte order of a 32-bit signed int if the CPU is big-endian */
    static int32 swapIfBigEndian (int32 value) noexcept;

    /** Swaps the byte order of a 64-bit signed int if the CPU is big-endian */
    static int64 swapIfBigEndian (int64 value) noexcept;

    /** Swaps the byte order of a 32-bit float if the CPU is big-endian */
    static float swapIfBigEndian (float value) noexcept;

    /** Swaps the byte order of a 64-bit float if the CPU is big-endian */
    static double swapIfBigEndian (double value) noexcept;

    /** Swaps the byte order of a 16-bit unsigned int if the CPU is little-endian */
    JUCE_CONSTEXPR static uint16 swapIfLittleEndian (uint16 value) noexcept;

    /** Swaps the byte order of a 32-bit unsigned int if the CPU is little-endian */
    static uint32 swapIfLittleEndian (uint32 value) noexcept;

    /** Swaps the byte order of a 64-bit unsigned int if the CPU is little-endian */
    static uint64 swapIfLittleEndian (uint64 value) noexcept;

    /** Swaps the byte order of a 16-bit signed int if the CPU is little-endian */
    JUCE_CONSTEXPR static int16 swapIfLittleEndian (int16 value) noexcept;

    /** Swaps the byte order of a 32-bit signed int if the CPU is little-endian */
    static int32 swapIfLittleEndian (int32 value) noexcept;

    /** Swaps the byte order of a 64-bit signed int if the CPU is little-endian */
    static int64 swapIfLittleEndian (int64 value) noexcept;

    /** Swaps the byte order of a 32-bit float if the CPU is little-endian */
    static float swapIfLittleEndian (float value) noexcept;

    /** Swaps the byte order of a 64-bit float if the CPU is little-endian */
    static double swapIfLittleEndian (double value) noexcept;

    //==============================================================================
    /** Turns 4 bytes into a little-endian integer. */
    static uint32 littleEndianInt (const void* bytes) noexcept;

    /** Turns 4 characters into a little-endian integer. */
    JUCE_CONSTEXPR static uint32 littleEndianInt (char c1, char c2, char c3, char c4) noexcept;

    /** Turns 8 bytes into a little-endian integer. */
    static uint64 littleEndianInt64 (const void* bytes) noexcept;

    /** Turns 2 bytes into a little-endian integer. */
    static uint16 littleEndianShort (const void* bytes) noexcept;

    /** Turns 4 bytes into a big-endian integer. */
    static uint32 bigEndianInt (const void* bytes) noexcept;

    /** Turns 8 bytes into a big-endian integer. */
    static uint64 bigEndianInt64 (const void* bytes) noexcept;

    /** Turns 2 bytes into a big-endian integer. */
    static uint16 bigEndianShort (const void* bytes) noexcept;

    //==============================================================================
    /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
    static int littleEndian24Bit (const void* bytes) noexcept;

    /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
    static int bigEndian24Bit (const void* bytes) noexcept;

    /** Copies a 24-bit number to 3 little-endian bytes. */
    static void littleEndian24BitToChars (int value, void* destBytes) noexcept;

    /** Copies a 24-bit number to 3 big-endian bytes. */
    static void bigEndian24BitToChars (int value, void* destBytes) noexcept;

    //==============================================================================
    /** Returns true if the current CPU is big-endian. */
    JUCE_CONSTEXPR static bool isBigEndian() noexcept;

private:
    ByteOrder() JUCE_DELETED_FUNCTION;

    JUCE_DECLARE_NON_COPYABLE (ByteOrder)
};

//==============================================================================
#if JUCE_MSVC && ! defined (__INTEL_COMPILER)
 #pragma intrinsic (_byteswap_ulong)
#endif

JUCE_CONSTEXPR inline uint16 ByteOrder::swap (uint16 n) noexcept
{
    return static_cast<uint16> ((n << 8) | (n >> 8));
}

inline uint32 ByteOrder::swap (uint32 n) noexcept
{
   #if JUCE_MAC || JUCE_IOS
    return OSSwapInt32 (n);
   #elif (JUCE_GCC  || JUCE_CLANG) && JUCE_INTEL && ! JUCE_NO_INLINE_ASM
    asm("bswap %%eax" : "=a"(n) : "a"(n));
    return n;
   #elif JUCE_MSVC
    return _byteswap_ulong (n);
   #elif JUCE_ANDROID
    return bswap_32 (n);
   #else
    return (n << 24) | (n >> 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8);
   #endif
}

inline uint64 ByteOrder::swap (uint64 value) noexcept
{
   #if JUCE_MAC || JUCE_IOS
    return OSSwapInt64 (value);
   #elif JUCE_MSVC
    return _byteswap_uint64 (value);
   #else
    return (((uint64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32));
   #endif
}

#if JUCE_LITTLE_ENDIAN
 JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept                                  { return v; }
 inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept                                                 { return v; }
 inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept                                                 { return v; }
 JUCE_CONSTEXPR inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept                                    { return v; }
 inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept                                                   { return v; }
 inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept                                                   { return v; }
 inline float ByteOrder::swapIfBigEndian (const float v) noexcept                                                   { return v; }
 inline double ByteOrder::swapIfBigEndian (const double v) noexcept                                                 { return v; }

 JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept                               { return swap (v); }
 inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept                                              { return swap (v); }
 inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept                                              { return swap (v); }
 JUCE_CONSTEXPR inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept                                 { return static_cast<int16> (swap (static_cast<uint16> (v))); }
 inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept                                                { return static_cast<int32> (swap (static_cast<uint32> (v))); }
 inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept                                                { return static_cast<int64> (swap (static_cast<uint64> (v))); }
 inline float ByteOrder::swapIfLittleEndian (const float v) noexcept                                                { union { uint32 asUInt; float asFloat;  } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; }
 inline double ByteOrder::swapIfLittleEndian (const double v) noexcept                                              { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; }

 inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept                                        { return *static_cast<const uint32*> (bytes); }
 JUCE_CONSTEXPR inline uint32 ByteOrder::littleEndianInt (char c1, char c2, char c3, char c4) noexcept              { return (((uint32) c4) << 24) + (((uint32) c3) << 16) + (((uint32) c2) << 8) + (uint32) c1; }

 inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept                                      { return *static_cast<const uint64*> (bytes); }
 inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept                                      { return *static_cast<const uint16*> (bytes); }
 inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept                                           { return swap (*static_cast<const uint32*> (bytes)); }
 inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept                                         { return swap (*static_cast<const uint64*> (bytes)); }
 inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept                                         { return swap (*static_cast<const uint16*> (bytes)); }
 JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept                                                       { return false; }
#else
 JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept                                  { return swap (v); }
 inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept                                                 { return swap (v); }
 inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept                                                 { return swap (v); }
 JUCE_CONSTEXPR inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept                                    { return static_cast<int16> (swap (static_cast<uint16> (v))); }
 inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept                                                   { return static_cast<int16> (swap (static_cast<uint16> (v))); }
 inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept                                                   { return static_cast<int16> (swap (static_cast<uint16> (v))); }
 inline float ByteOrder::swapIfBigEndian (const float v) noexcept                                                   { union { uint32 asUInt; float asFloat;  } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; }
 inline double ByteOrder::swapIfBigEndian (const double v) noexcept                                                 { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; }

 JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept                               { return v; }
 inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept                                              { return v; }
 inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept                                              { return v; }
 JUCE_CONSTEXPR inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept                                 { return v; }
 inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept                                                { return v; }
 inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept                                                { return v; }
 inline float ByteOrder::swapIfLittleEndian (const float v) noexcept                                                { return v; }
 inline double ByteOrder::swapIfLittleEndian (const double v) noexcept                                              { return v; }

 inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept                                        { return swap (*static_cast<const uint32*> (bytes)); }
 JUCE_CONSTEXPR inline uint32 ByteOrder::littleEndianInt (char c1, char c2, char c3, char c4) noexcept              { return (((uint32) c1) << 24) + (((uint32) c2) << 16) + (((uint32) c3) << 8) + (uint32) c4; }
 inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept                                      { return swap (*static_cast<const uint64*> (bytes)); }
 inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept                                      { return swap (*static_cast<const uint16*> (bytes)); }
 inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept                                           { return *static_cast<const uint32*> (bytes); }
 inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept                                         { return *static_cast<const uint64*> (bytes); }
 inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept                                         { return *static_cast<const uint16*> (bytes); }
 JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept                                                       { return true; }
#endif

inline int  ByteOrder::littleEndian24Bit (const void* const bytes) noexcept                                         { return (int) ((((unsigned int) static_cast<const int8*> (bytes)[2]) << 16) | (((unsigned int) static_cast<const uint8*> (bytes)[1]) << 8) | ((unsigned int) static_cast<const uint8*> (bytes)[0])); }
inline int  ByteOrder::bigEndian24Bit (const void* const bytes) noexcept                                            { return (int) ((((unsigned int) static_cast<const int8*> (bytes)[0]) << 16) | (((unsigned int) static_cast<const uint8*> (bytes)[1]) << 8) | ((unsigned int) static_cast<const uint8*> (bytes)[2])); }
inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept                   { static_cast<uint8*> (destBytes)[0] = (uint8) value;         static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) (value >> 16); }
inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept                      { static_cast<uint8*> (destBytes)[0] = (uint8) (value >> 16); static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) value; }

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/** Fills a block of memory with zeros. */
inline void zeromem (void* memory, size_t numBytes) noexcept        { memset (memory, 0, numBytes); }

/** Overwrites a structure or object with zeros. */
template <typename Type>
inline void zerostruct (Type& structure) noexcept                   { memset (&structure, 0, sizeof (structure)); }

/** Delete an object pointer, and sets the pointer to null.

    Remember that it's not good c++ practice to use delete directly - always try to use a ScopedPointer
    or other automatic lifetime-management system rather than resorting to deleting raw pointers!
*/
template <typename Type>
inline void deleteAndZero (Type& pointer)                           { delete pointer; pointer = nullptr; }

/** A handy function which adds a number of bytes to any type of pointer and returns the result.
    This can be useful to avoid casting pointers to a char* and back when you want to move them by
    a specific number of bytes,
*/
template <typename Type, typename IntegerType>
inline Type* addBytesToPointer (Type* basePointer, IntegerType bytes) noexcept  { return (Type*) (((char*) basePointer) + bytes); }

/** A handy function to round up a pointer to the nearest multiple of a given number of bytes.
    alignmentBytes must be a power of two. */
template <typename Type, typename IntegerType>
inline Type* snapPointerToAlignment (Type* basePointer, IntegerType alignmentBytes) noexcept
{
    return (Type*) ((((size_t) basePointer) + (alignmentBytes - 1)) & ~(alignmentBytes - 1));
}

/** A handy function which returns the difference between any two pointers, in bytes.
    The address of the second pointer is subtracted from the first, and the difference in bytes is returned.
*/
template <typename Type1, typename Type2>
inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept  { return (int) (((const char*) pointer1) - (const char*) pointer2); }

/** If a pointer is non-null, this returns a new copy of the object that it points to, or safely returns
    nullptr if the pointer is null.
*/
template <class Type>
inline Type* createCopyIfNotNull (const Type* objectToCopy) { return objectToCopy != nullptr ? new Type (*objectToCopy) : nullptr; }

//==============================================================================
/** A handy function to read un-aligned memory without a performance penalty or bus-error. */
template <typename Type>
inline Type readUnaligned (const void* srcPtr) noexcept
{
    Type value;
    memcpy (&value, srcPtr, sizeof (Type));
    return value;
}

/** A handy function to write un-aligned memory without a performance penalty or bus-error. */
template <typename Type>
inline void writeUnaligned (void* dstPtr, Type value) noexcept
{
    memcpy (dstPtr, &value, sizeof (Type));
}

//==============================================================================
#if JUCE_MAC || JUCE_IOS || DOXYGEN

 /** A handy C++ wrapper that creates and deletes an NSAutoreleasePool object using RAII.
     You should use the JUCE_AUTORELEASEPOOL macro to create a local auto-release pool on the stack.
 */
 class JUCE_API  ScopedAutoReleasePool
 {
 public:
     ScopedAutoReleasePool();
     ~ScopedAutoReleasePool();

 private:
     void* pool;

     JUCE_DECLARE_NON_COPYABLE (ScopedAutoReleasePool)
 };

 /** A macro that can be used to easily declare a local ScopedAutoReleasePool
     object for RAII-based obj-C autoreleasing.
     Because this may use the \@autoreleasepool syntax, you must follow the macro with
     a set of braces to mark the scope of the pool.
 */
#if (JUCE_COMPILER_SUPPORTS_ARC && defined (__OBJC__)) || DOXYGEN
 #define JUCE_AUTORELEASEPOOL  @autoreleasepool
#else
 #define JUCE_AUTORELEASEPOOL  const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__);
#endif

#else
 #define JUCE_AUTORELEASEPOOL
#endif

//==============================================================================
/* In a Windows DLL build, we'll expose some malloc/free functions that live inside the DLL, and use these for
   allocating all the objects - that way all juce objects in the DLL and in the host will live in the same heap,
   avoiding problems when an object is created in one module and passed across to another where it is deleted.
   By piggy-backing on the JUCE_LEAK_DETECTOR macro, these allocators can be injected into most juce classes.
*/
#if JUCE_MSVC && (defined (JUCE_DLL) || defined (JUCE_DLL_BUILD)) && ! (JUCE_DISABLE_DLL_ALLOCATORS || DOXYGEN)
 extern JUCE_API void* juceDLL_malloc (size_t);
 extern JUCE_API void  juceDLL_free (void*);

 #define JUCE_LEAK_DETECTOR(OwnerClass)  public:\
    static void* operator new (size_t sz)           { return juce::juceDLL_malloc (sz); } \
    static void* operator new (size_t, void* p)     { return p; } \
    static void operator delete (void* p)           { juce::juceDLL_free (p); } \
    static void operator delete (void*, void*)      {}
#endif

//==============================================================================
/** (Deprecated) This was a Windows-specific way of checking for object leaks - now please
    use the JUCE_LEAK_DETECTOR instead.
*/
#ifndef juce_UseDebuggingNewOperator
 #define juce_UseDebuggingNewOperator
#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    A smart-pointer that automatically creates and manages the lifetime of a
    shared static instance of a class.

    The SharedObjectType template type indicates the class to use for the shared
    object - the only requirements on this class are that it must have a public
    default constructor and destructor.

    The SharedResourcePointer offers a pattern that differs from using a singleton or
    static instance of an object, because it uses reference-counting to make sure that
    the underlying shared object is automatically created/destroyed according to the
    number of SharedResourcePointer objects that exist. When the last one is deleted,
    the underlying object is also immediately destroyed. This allows you to use scoping
    to manage the lifetime of a shared resource.

    Note: the construction/deletion of the shared object must not involve any
    code that makes recursive calls to a SharedResourcePointer, or you'll cause
    a deadlock.

    Example:
    @code
    // An example of a class that contains the shared data you want to use.
    struct MySharedData
    {
        // There's no need to ever create an instance of this class directly yourself,
        // but it does need a public constructor that does the initialisation.
        MySharedData()
        {
            sharedStuff = generateHeavyweightStuff();
        }

        Array<SomeKindOfData> sharedStuff;
    };

    struct DataUserClass
    {
        DataUserClass()
        {
            // Multiple instances of the DataUserClass will all have the same
            // shared common instance of MySharedData referenced by their sharedData
            // member variables.
            useSharedStuff (sharedData->sharedStuff);
        }

        // By keeping this pointer as a member variable, the shared resource
        // is guaranteed to be available for as long as the DataUserClass object.
        SharedResourcePointer<MySharedData> sharedData;
    };

    @endcode
 */
template <typename SharedObjectType>
class SharedResourcePointer
{
public:
    /** Creates an instance of the shared object.
        If other SharedResourcePointer objects for this type already exist, then
        this one will simply point to the same shared object that they are already
        using. Otherwise, if this is the first SharedResourcePointer to be created,
        then a shared object will be created automatically.
    */
    SharedResourcePointer()
    {
        initialise();
    }

    SharedResourcePointer (const SharedResourcePointer&)
    {
        initialise();
    }

    /** Destructor.
        If no other SharedResourcePointer objects exist, this will also delete
        the shared object to which it refers.
    */
    ~SharedResourcePointer()
    {
        auto& holder = getSharedObjectHolder();
        const SpinLock::ScopedLockType sl (holder.lock);

        if (--(holder.refCount) == 0)
            holder.sharedInstance = nullptr;
    }

    /** Returns the shared object. */
    operator SharedObjectType*() const noexcept         { return sharedObject; }

    /** Returns the shared object. */
    SharedObjectType& get() const noexcept              { return *sharedObject; }

    /** Returns the object that this pointer references.
        The pointer returned may be a nullptr, of course.
    */
    SharedObjectType& getObject() const noexcept        { return *sharedObject; }

    /** Returns the shared object. */
    SharedObjectType* operator->() const noexcept       { return sharedObject; }

    /** Returns the number of SharedResourcePointers that are currently holding the shared object. */
    int getReferenceCount() const noexcept              { return getSharedObjectHolder().refCount; }

private:
    struct SharedObjectHolder
    {
        SpinLock lock;
        ScopedPointer<SharedObjectType> sharedInstance;
        int refCount;
    };

    static SharedObjectHolder& getSharedObjectHolder() noexcept
    {
        static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { 0 };
        return *reinterpret_cast<SharedObjectHolder*> (holder);
    }

    SharedObjectType* sharedObject;

    void initialise()
    {
        auto& holder = getSharedObjectHolder();
        const SpinLock::ScopedLockType sl (holder.lock);

        if (++(holder.refCount) == 1)
            holder.sharedInstance = new SharedObjectType();

        sharedObject = holder.sharedInstance;
    }

    // There's no need to assign to a SharedResourcePointer because every
    // instance of the class is exactly the same!
    SharedResourcePointer& operator= (const SharedResourcePointer&) = delete;

    JUCE_LEAK_DETECTOR (SharedResourcePointer)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Macro to declare member variables and methods for a singleton class.

    To use this, add the line juce_DeclareSingleton (MyClass, doNotRecreateAfterDeletion)
    to the class's definition.

    Then put a macro juce_ImplementSingleton (MyClass) along with the class's
    implementation code.

    It's also a very good idea to also add the call clearSingletonInstance() in your class's
    destructor, in case it is deleted by other means than deleteInstance()

    Clients can then call the static method MyClass::getInstance() to get a pointer
    to the singleton, or MyClass::getInstanceWithoutCreating() which will return nullptr if
    no instance currently exists.

    e.g. @code

        class MySingleton
        {
        public:
            MySingleton()
            {
            }

            ~MySingleton()
            {
                // this ensures that no dangling pointers are left when the
                // singleton is deleted.
                clearSingletonInstance();
            }

            juce_DeclareSingleton (MySingleton, false)
        };

        juce_ImplementSingleton (MySingleton)

        // example of usage:
        MySingleton* m = MySingleton::getInstance(); // creates the singleton if there isn't already one.

        ...

        MySingleton::deleteInstance(); // safely deletes the singleton (if it's been created).

    @endcode

    If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
    than once during the process's lifetime - i.e. after you've created and deleted the
    object, getInstance() will refuse to create another one. This can be useful to stop
    objects being accidentally re-created during your app's shutdown code.

    If you know that your object will only be created and deleted by a single thread, you
    can use the slightly more efficient juce_DeclareSingleton_SingleThreaded() macro instead
    of this one.

    @see juce_ImplementSingleton, juce_DeclareSingleton_SingleThreaded
*/
#define juce_DeclareSingleton(classname, doNotRecreateAfterDeletion) \
\
    static classname* _singletonInstance;  \
    static juce::CriticalSection _singletonLock; \
\
    static classname* JUCE_CALLTYPE getInstance() \
    { \
        if (_singletonInstance == nullptr) \
        {\
            const juce::ScopedLock sl (_singletonLock); \
\
            if (_singletonInstance == nullptr) \
            { \
                static bool alreadyInside = false; \
                static bool createdOnceAlready = false; \
\
                const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
                jassert (! problem); \
                if (! problem) \
                { \
                    createdOnceAlready = true; \
                    alreadyInside = true; \
                    classname* newObject = new classname();  /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
                    alreadyInside = false; \
\
                    _singletonInstance = newObject; \
                } \
            } \
        } \
\
        return _singletonInstance; \
    } \
\
    static inline classname* JUCE_CALLTYPE getInstanceWithoutCreating() noexcept\
    { \
        return _singletonInstance; \
    } \
\
    static void JUCE_CALLTYPE deleteInstance() \
    { \
        const juce::ScopedLock sl (_singletonLock); \
        if (_singletonInstance != nullptr) \
        { \
            classname* const old = _singletonInstance; \
            _singletonInstance = nullptr; \
            delete old; \
        } \
    } \
\
    void clearSingletonInstance() noexcept\
    { \
        if (_singletonInstance == this) \
            _singletonInstance = nullptr; \
    }

//==============================================================================
/** This is a counterpart to the juce_DeclareSingleton macro.

    After adding the juce_DeclareSingleton to the class definition, this macro has
    to be used in the cpp file.
*/
#define juce_ImplementSingleton(classname) \
\
    classname* classname::_singletonInstance = nullptr; \
    juce::CriticalSection classname::_singletonLock;

//==============================================================================
/**
    Macro to declare member variables and methods for a singleton class.

    This is exactly the same as juce_DeclareSingleton, but doesn't use a critical
    section to make access to it thread-safe. If you know that your object will
    only ever be created or deleted by a single thread, then this is a
    more efficient version to use.

    If doNotRecreateAfterDeletion = true, it won't allow the object to be created more
    than once during the process's lifetime - i.e. after you've created and deleted the
    object, getInstance() will refuse to create another one. This can be useful to stop
    objects being accidentally re-created during your app's shutdown code.

    See the documentation for juce_DeclareSingleton for more information about
    how to use it, the only difference being that you have to use
    juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.

    @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton, juce_DeclareSingleton_SingleThreaded_Minimal
*/
#define juce_DeclareSingleton_SingleThreaded(classname, doNotRecreateAfterDeletion) \
\
    static classname* _singletonInstance;  \
\
    static classname* getInstance() \
    { \
        if (_singletonInstance == nullptr) \
        { \
            static bool alreadyInside = false; \
            static bool createdOnceAlready = false; \
\
            const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \
            jassert (! problem); \
            if (! problem) \
            { \
                createdOnceAlready = true; \
                alreadyInside = true; \
                classname* newObject = new classname();  /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \
                alreadyInside = false; \
\
                _singletonInstance = newObject; \
            } \
        } \
\
        return _singletonInstance; \
    } \
\
    static inline classname* getInstanceWithoutCreating() noexcept\
    { \
        return _singletonInstance; \
    } \
\
    static void deleteInstance() \
    { \
        if (_singletonInstance != nullptr) \
        { \
            classname* const old = _singletonInstance; \
            _singletonInstance = nullptr; \
            delete old; \
        } \
    } \
\
    void clearSingletonInstance() noexcept\
    { \
        if (_singletonInstance == this) \
            _singletonInstance = nullptr; \
    }

//==============================================================================
/**
    Macro to declare member variables and methods for a singleton class.

    This is like juce_DeclareSingleton_SingleThreaded, but doesn't do any checking
    for recursion or repeated instantiation. It's intended for use as a lightweight
    version of a singleton, where you're using it in very straightforward
    circumstances and don't need the extra checking.

    Juce use the normal juce_ImplementSingleton_SingleThreaded as the counterpart
    to this declaration, as you would with juce_DeclareSingleton_SingleThreaded.

    See the documentation for juce_DeclareSingleton for more information about
    how to use it, the only difference being that you have to use
    juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton.

    @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton
*/
#define juce_DeclareSingleton_SingleThreaded_Minimal(classname) \
\
    static classname* _singletonInstance;  \
\
    static classname* getInstance() \
    { \
        if (_singletonInstance == nullptr) \
            _singletonInstance = new classname(); \
\
        return _singletonInstance; \
    } \
\
    static inline classname* getInstanceWithoutCreating() noexcept\
    { \
        return _singletonInstance; \
    } \
\
    static void deleteInstance() \
    { \
        if (_singletonInstance != nullptr) \
        { \
            classname* const old = _singletonInstance; \
            _singletonInstance = nullptr; \
            delete old; \
        } \
    } \
\
    void clearSingletonInstance() noexcept\
    { \
        if (_singletonInstance == this) \
            _singletonInstance = nullptr; \
    }

//==============================================================================
/** This is a counterpart to the juce_DeclareSingleton_SingleThreaded macro.

    After adding juce_DeclareSingleton_SingleThreaded or juce_DeclareSingleton_SingleThreaded_Minimal
    to the class definition, this macro has to be used somewhere in the cpp file.
*/
#define juce_ImplementSingleton_SingleThreaded(classname) \
\
    classname* classname::_singletonInstance = nullptr;

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Embedding an instance of this class inside another class can be used as a low-overhead
    way of detecting leaked instances.

    This class keeps an internal static count of the number of instances that are
    active, so that when the app is shutdown and the static destructors are called,
    it can check whether there are any left-over instances that may have been leaked.

    To use it, use the JUCE_LEAK_DETECTOR macro as a simple way to put one in your
    class declaration. Have a look through the juce codebase for examples, it's used
    in most of the classes.
*/
template <class OwnerClass>
class LeakedObjectDetector
{
public:
    //==============================================================================
    LeakedObjectDetector() noexcept                                 { ++(getCounter().numObjects); }
    LeakedObjectDetector (const LeakedObjectDetector&) noexcept     { ++(getCounter().numObjects); }

    ~LeakedObjectDetector()
    {
        if (--(getCounter().numObjects) < 0)
        {
            DBG ("*** Dangling pointer deletion! Class: " << getLeakedObjectClassName());

            /** If you hit this, then you've managed to delete more instances of this class than you've
                created.. That indicates that you're deleting some dangling pointers.

                Note that although this assertion will have been triggered during a destructor, it might
                not be this particular deletion that's at fault - the incorrect one may have happened
                at an earlier point in the program, and simply not been detected until now.

                Most errors like this are caused by using old-fashioned, non-RAII techniques for
                your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
                ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
            */
            jassertfalse;
        }
    }

private:
    //==============================================================================
    class LeakCounter
    {
    public:
        LeakCounter() noexcept {}

        ~LeakCounter()
        {
            if (numObjects.value > 0)
            {
                DBG ("*** Leaked objects detected: " << numObjects.value << " instance(s) of class " << getLeakedObjectClassName());

                /** If you hit this, then you've leaked one or more objects of the type specified by
                    the 'OwnerClass' template parameter - the name should have been printed by the line above.

                    If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
                    your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
                    ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
                */
                jassertfalse;
            }
        }

        Atomic<int> numObjects;
    };

    static const char* getLeakedObjectClassName()
    {
        return OwnerClass::getLeakedObjectClassName();
    }

    static LeakCounter& getCounter() noexcept
    {
        static LeakCounter counter;
        return counter;
    }
};

//==============================================================================
#if DOXYGEN || ! defined (JUCE_LEAK_DETECTOR)
 #if (DOXYGEN || JUCE_CHECK_MEMORY_LEAKS)
  /** This macro lets you embed a leak-detecting object inside a class.

      To use it, simply declare a JUCE_LEAK_DETECTOR(YourClassName) inside a private section
      of the class declaration. E.g.

      @code
      class MyClass
      {
      public:
          MyClass();
          void blahBlah();

      private:
          JUCE_LEAK_DETECTOR (MyClass)
      };
      @endcode

      @see JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR, LeakedObjectDetector
  */
  #define JUCE_LEAK_DETECTOR(OwnerClass) \
        friend class juce::LeakedObjectDetector<OwnerClass>; \
        static const char* getLeakedObjectClassName() noexcept { return #OwnerClass; } \
        juce::LeakedObjectDetector<OwnerClass> JUCE_JOIN_MACRO (leakDetector, __LINE__);
 #else
  #define JUCE_LEAK_DETECTOR(OwnerClass)
 #endif
#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    This class holds a pointer which is automatically deleted when this object goes
    out of scope.

    Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
    gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
    as member variables is a good way to use RAII to avoid accidentally leaking dynamically
    created objects.

    A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
    to an object. If you use the assignment operator to assign a different object to a
    ScopedPointer, the old one will be automatically deleted.

    Important note: The class is designed to hold a pointer to an object, NOT to an array!
    It calls delete on its payload, not delete[], so do not give it an array to hold! For
    that kind of purpose, you should be using HeapBlock or Array instead.

    A const ScopedPointer is guaranteed not to lose ownership of its object or change the
    object to which it points during its lifetime. This means that making a copy of a const
    ScopedPointer is impossible, as that would involve the new copy taking ownership from the
    old one.

    If you need to get a pointer out of a ScopedPointer without it being deleted, you
    can use the release() method.

    Something to note is the main difference between this class and the std::auto_ptr class,
    which is that ScopedPointer provides a cast-to-object operator, whereas std::auto_ptr
    requires that you always call get() to retrieve the pointer. The advantages of providing
    the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
    exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
    use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
    to return a ScopedPointer as the result of a function. To avoid this causing errors,
    ScopedPointer contains an overloaded constructor that should cause a syntax error in these
    circumstances, but it does mean that instead of returning a ScopedPointer from a function,
    you'd need to return a raw pointer (or use a std::auto_ptr instead).
*/
template <class ObjectType>
class ScopedPointer
{
public:
    //==============================================================================
    /** Creates a ScopedPointer containing a null pointer. */
    inline ScopedPointer() noexcept   : object (nullptr)
    {
    }

    /** Creates a ScopedPointer containing a null pointer. */
    inline ScopedPointer (decltype (nullptr)) noexcept   : object (nullptr)
    {
    }

    /** Creates a ScopedPointer that owns the specified object. */
    inline ScopedPointer (ObjectType* const objectToTakePossessionOf) noexcept
        : object (objectToTakePossessionOf)
    {
    }

    /** Creates a ScopedPointer that takes its pointer from another ScopedPointer.

        Because a pointer can only belong to one ScopedPointer, this transfers
        the pointer from the other object to this one, and the other object is reset to
        be a null pointer.
    */
    ScopedPointer (ScopedPointer& objectToTransferFrom) noexcept
        : object (objectToTransferFrom.object)
    {
        objectToTransferFrom.object = nullptr;
    }

    /** Destructor.
        This will delete the object that this ScopedPointer currently refers to.
    */
    inline ~ScopedPointer()                 { ContainerDeletePolicy<ObjectType>::destroy (object); }

    /** Changes this ScopedPointer to point to a new object.

        Because a pointer can only belong to one ScopedPointer, this transfers
        the pointer from the other object to this one, and the other object is reset to
        be a null pointer.

        If this ScopedPointer already points to an object, that object
        will first be deleted.
    */
    ScopedPointer& operator= (ScopedPointer& objectToTransferFrom)
    {
        if (this != objectToTransferFrom.getAddress())
        {
            // Two ScopedPointers should never be able to refer to the same object - if
            // this happens, you must have done something dodgy!
            jassert (object == nullptr || object != objectToTransferFrom.object);

            ObjectType* const oldObject = object;
            object = objectToTransferFrom.object;
            objectToTransferFrom.object = nullptr;
            ContainerDeletePolicy<ObjectType>::destroy (oldObject);
        }

        return *this;
    }

    /** Changes this ScopedPointer to point to a new object.

        If this ScopedPointer already points to an object, that object
        will first be deleted.

        The pointer that you pass in may be a nullptr.
    */
    ScopedPointer& operator= (ObjectType* const newObjectToTakePossessionOf)
    {
        if (object != newObjectToTakePossessionOf)
        {
            ObjectType* const oldObject = object;
            object = newObjectToTakePossessionOf;
            ContainerDeletePolicy<ObjectType>::destroy (oldObject);
        }

        return *this;
    }

    /** Take ownership of another ScopedPointer */
    ScopedPointer (ScopedPointer&& other) noexcept
        : object (other.object)
    {
        other.object = nullptr;
    }

    /** Take ownership of another ScopedPointer */
    ScopedPointer& operator= (ScopedPointer&& other) noexcept
    {
        ContainerDeletePolicy<ObjectType>::destroy (object);
        object = other.object;
        other.object = nullptr;
        return *this;
    }

    //==============================================================================
    /** Returns the object that this ScopedPointer refers to. */
    inline operator ObjectType*() const noexcept                                    { return object; }

    /** Returns the object that this ScopedPointer refers to. */
    inline ObjectType* get() const noexcept                                         { return object; }

    /** Returns the object that this ScopedPointer refers to. */
    inline ObjectType& operator*() const noexcept                                   { return *object; }

    /** Lets you access methods and properties of the object that this ScopedPointer refers to. */
    inline ObjectType* operator->() const noexcept                                  { return object; }

    //==============================================================================
    /** Removes the current object from this ScopedPointer without deleting it.
        This will return the current object, and set the ScopedPointer to a null pointer.
    */
    ObjectType* release() noexcept                                                  { ObjectType* const o = object; object = nullptr; return o; }

    //==============================================================================
    /** Swaps this object with that of another ScopedPointer.
        The two objects simply exchange their pointers.
    */
    void swapWith (ScopedPointer<ObjectType>& other) noexcept
    {
        // Two ScopedPointers should never be able to refer to the same object - if
        // this happens, you must have done something dodgy!
        jassert (object != other.object || this == other.getAddress() || object == nullptr);

        std::swap (object, other.object);
    }

    /** If the pointer is non-null, this will attempt to return a new copy of the object that is pointed to.
        If the pointer is null, this will safely return a nullptr.
    */
    inline ObjectType* createCopy() const                                           { return createCopyIfNotNull (object); }

private:
    //==============================================================================
    ObjectType* object;

    // (Required as an alternative to the overloaded & operator).
    const ScopedPointer* getAddress() const noexcept                                { return this; }

  #if ! JUCE_MSVC  // (MSVC can't deal with multiple copy constructors)
    /* The copy constructors are private to stop people accidentally copying a const ScopedPointer
       (the compiler would let you do so by implicitly casting the source to its raw object pointer).

       A side effect of this is that in a compiler that doesn't support C++11, you may hit an
       error when you write something like this:

          ScopedPointer<MyClass> m = new MyClass();  // Compile error: copy constructor is private.

       Even though the compiler would normally ignore the assignment here, it can't do so when the
       copy constructor is private. It's very easy to fix though - just write it like this:

          ScopedPointer<MyClass> m (new MyClass());  // Compiles OK

       It's probably best to use the latter form when writing your object declarations anyway, as
       this is a better representation of the code that you actually want the compiler to produce.
    */
    JUCE_DECLARE_NON_COPYABLE (ScopedPointer)
  #endif
};

//==============================================================================
/** Compares a ScopedPointer with another pointer.
    This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator== (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
    return static_cast<ObjectType*> (pointer1) == pointer2;
}

/** Compares a ScopedPointer with another pointer.
    This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator!= (const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
    return static_cast<ObjectType*> (pointer1) != pointer2;
}

//==============================================================================
#ifndef DOXYGEN
// NB: This is just here to prevent any silly attempts to call deleteAndZero() on a ScopedPointer.
template <typename Type>
void deleteAndZero (ScopedPointer<Type>&)  { static_assert (sizeof (Type) == 12345,
                                                            "Attempt to call deleteAndZero() on a ScopedPointer"); }
#endif

} // namespace juce