| 
							- /*
 -   ==============================================================================
 - 
 -    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.
 - 
 -   ==============================================================================
 - */
 - 
 - #pragma once
 - 
 - 
 - //==============================================================================
 - /**
 -     A simple class to generate hash functions for some primitive types, intended for
 -     use with the HashMap class.
 -     @see HashMap
 - */
 - struct DefaultHashFunctions
 - {
 -     /** Generates a simple hash from an unsigned int. */
 -     static int generateHash (uint32 key, int upperLimit) noexcept           { return (int) (key % (uint32) upperLimit); }
 -     /** Generates a simple hash from an integer. */
 -     static int generateHash (int32 key, int upperLimit) noexcept            { return generateHash ((uint32) key, upperLimit); }
 -     /** Generates a simple hash from a uint64. */
 -     static int generateHash (uint64 key, int upperLimit) noexcept           { return (int) (key % (uint64) upperLimit); }
 -     /** Generates a simple hash from an int64. */
 -     static int generateHash (int64 key, int upperLimit) noexcept            { return generateHash ((uint64) key, upperLimit); }
 -     /** Generates a simple hash from a string. */
 -     static int generateHash (const String& key, int upperLimit) noexcept    { return generateHash ((uint32) key.hashCode(), upperLimit); }
 -     /** Generates a simple hash from a variant. */
 -     static int generateHash (const var& key, int upperLimit) noexcept       { return generateHash (key.toString(), upperLimit); }
 -     /** Generates a simple hash from a void ptr. */
 -     static int generateHash (const void* key, int upperLimit) noexcept      { return generateHash ((pointer_sized_uint) key, upperLimit); }
 - };
 - 
 - 
 - //==============================================================================
 - /**
 -     Holds a set of mappings between some key/value pairs.
 - 
 -     The types of the key and value objects are set as template parameters.
 -     You can also specify a class to supply a hash function that converts a key value
 -     into an hashed integer. This class must have the form:
 - 
 -     @code
 -     struct MyHashGenerator
 -     {
 -         int generateHash (MyKeyType key, int upperLimit) const
 -         {
 -             // The function must return a value 0 <= x < upperLimit
 -             return someFunctionOfMyKeyType (key) % upperLimit;
 -         }
 -     };
 -     @endcode
 - 
 -     Like the Array class, the key and value types are expected to be copy-by-value
 -     types, so if you define them to be pointer types, this class won't delete the
 -     objects that they point to.
 - 
 -     If you don't supply a class for the HashFunctionType template parameter, the
 -     default one provides some simple mappings for strings and ints.
 - 
 -     @code
 -     HashMap<int, String> hash;
 -     hash.set (1, "item1");
 -     hash.set (2, "item2");
 - 
 -     DBG (hash [1]); // prints "item1"
 -     DBG (hash [2]); // prints "item2"
 - 
 -     // This iterates the map, printing all of its key -> value pairs..
 -     for (HashMap<int, String>::Iterator i (hash); i.next();)
 -         DBG (i.getKey() << " -> " << i.getValue());
 -     @endcode
 - 
 -     @tparam HashFunctionType The class of hash function, which must be copy-constructible.
 -     @see CriticalSection, DefaultHashFunctions, NamedValueSet, SortedSet
 - */
 - template <typename KeyType,
 -           typename ValueType,
 -           class HashFunctionType = DefaultHashFunctions,
 -           class TypeOfCriticalSectionToUse = DummyCriticalSection>
 - class HashMap
 - {
 - private:
 -     typedef typename TypeHelpers::ParameterType<KeyType>::type   KeyTypeParameter;
 -     typedef typename TypeHelpers::ParameterType<ValueType>::type ValueTypeParameter;
 - 
 - public:
 -     //==============================================================================
 -     /** Creates an empty hash-map.
 - 
 -         @param numberOfSlots Specifies the number of hash entries the map will use. This will be
 -                             the "upperLimit" parameter that is passed to your generateHash()
 -                             function. The number of hash slots will grow automatically if necessary,
 -                             or it can be remapped manually using remapTable().
 -         @param hashFunction An instance of HashFunctionType, which will be copied and
 -                             stored to use with the HashMap. This parameter can be omitted
 -                             if HashFunctionType has a default constructor.
 -     */
 -     explicit HashMap (int numberOfSlots = defaultHashTableSize,
 -                       HashFunctionType hashFunction = HashFunctionType())
 -        : hashFunctionToUse (hashFunction), totalNumItems (0)
 -     {
 -         hashSlots.insertMultiple (0, nullptr, numberOfSlots);
 -     }
 - 
 -     /** Destructor. */
 -     ~HashMap()
 -     {
 -         clear();
 -     }
 - 
 -     //==============================================================================
 -     /** Removes all values from the map.
 -         Note that this will clear the content, but won't affect the number of slots (see
 -         remapTable and getNumSlots).
 -     */
 -     void clear()
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         for (auto i = hashSlots.size(); --i >= 0;)
 -         {
 -             auto* h = hashSlots.getUnchecked(i);
 - 
 -             while (h != nullptr)
 -             {
 -                 const ScopedPointer<HashEntry> deleter (h);
 -                 h = h->nextEntry;
 -             }
 - 
 -             hashSlots.set (i, nullptr);
 -         }
 - 
 -         totalNumItems = 0;
 -     }
 - 
 -     //==============================================================================
 -     /** Returns the current number of items in the map. */
 -     inline int size() const noexcept
 -     {
 -         return totalNumItems;
 -     }
 - 
 -     /** Returns the value corresponding to a given key.
 -         If the map doesn't contain the key, a default instance of the value type is returned.
 -         @param keyToLookFor    the key of the item being requested
 -     */
 -     inline ValueType operator[] (KeyTypeParameter keyToLookFor) const
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         if (auto* entry = getEntry (getSlot (keyToLookFor), keyToLookFor))
 -             return entry->value;
 - 
 -         return ValueType();
 -     }
 - 
 -     /** Returns a reference to the value corresponding to a given key.
 -         If the map doesn't contain the key, a default instance of the value type is
 -         added to the map and a reference to this is returned.
 -         @param keyToLookFor    the key of the item being requested
 -     */
 -     inline ValueType& getReference (KeyTypeParameter keyToLookFor)
 -     {
 -         const ScopedLockType sl (getLock());
 -         auto hashIndex = generateHashFor (keyToLookFor, getNumSlots());
 - 
 -         auto* firstEntry = hashSlots.getUnchecked (hashIndex);
 - 
 -         if (auto* entry = getEntry (firstEntry, keyToLookFor))
 -             return entry->value;
 - 
 -         auto* entry = new HashEntry (keyToLookFor, ValueType(), firstEntry);
 -         hashSlots.set (hashIndex, entry);
 -         ++totalNumItems;
 - 
 -         if (totalNumItems > (getNumSlots() * 3) / 2)
 -             remapTable (getNumSlots() * 2);
 - 
 -         return entry->value;
 -     }
 - 
 -     //==============================================================================
 -     /** Returns true if the map contains an item with the specied key. */
 -     bool contains (KeyTypeParameter keyToLookFor) const
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         return (getEntry (getSlot (keyToLookFor), keyToLookFor) != nullptr);
 -     }
 - 
 -     /** Returns true if the hash contains at least one occurrence of a given value. */
 -     bool containsValue (ValueTypeParameter valueToLookFor) const
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         for (auto i = getNumSlots(); --i >= 0;)
 -             for (auto* entry = hashSlots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
 -                 if (entry->value == valueToLookFor)
 -                     return true;
 - 
 -         return false;
 -     }
 - 
 -     //==============================================================================
 -     /** Adds or replaces an element in the hash-map.
 -         If there's already an item with the given key, this will replace its value. Otherwise, a new item
 -         will be added to the map.
 -     */
 -     void set (KeyTypeParameter newKey, ValueTypeParameter newValue)        { getReference (newKey) = newValue; }
 - 
 -     /** Removes an item with the given key. */
 -     void remove (KeyTypeParameter keyToRemove)
 -     {
 -         const ScopedLockType sl (getLock());
 -         auto hashIndex = generateHashFor (keyToRemove, getNumSlots());
 -         auto* entry = hashSlots.getUnchecked (hashIndex);
 -         HashEntry* previous = nullptr;
 - 
 -         while (entry != nullptr)
 -         {
 -             if (entry->key == keyToRemove)
 -             {
 -                 const ScopedPointer<HashEntry> deleter (entry);
 - 
 -                 entry = entry->nextEntry;
 - 
 -                 if (previous != nullptr)
 -                     previous->nextEntry = entry;
 -                 else
 -                     hashSlots.set (hashIndex, entry);
 - 
 -                 --totalNumItems;
 -             }
 -             else
 -             {
 -                 previous = entry;
 -                 entry = entry->nextEntry;
 -             }
 -         }
 -     }
 - 
 -     /** Removes all items with the given value. */
 -     void removeValue (ValueTypeParameter valueToRemove)
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         for (auto i = getNumSlots(); --i >= 0;)
 -         {
 -             auto* entry = hashSlots.getUnchecked(i);
 -             HashEntry* previous = nullptr;
 - 
 -             while (entry != nullptr)
 -             {
 -                 if (entry->value == valueToRemove)
 -                 {
 -                     const ScopedPointer<HashEntry> deleter (entry);
 - 
 -                     entry = entry->nextEntry;
 - 
 -                     if (previous != nullptr)
 -                         previous->nextEntry = entry;
 -                     else
 -                         hashSlots.set (i, entry);
 - 
 -                     --totalNumItems;
 -                 }
 -                 else
 -                 {
 -                     previous = entry;
 -                     entry = entry->nextEntry;
 -                 }
 -             }
 -         }
 -     }
 - 
 -     /** Remaps the hash-map to use a different number of slots for its hash function.
 -         Each slot corresponds to a single hash-code, and each one can contain multiple items.
 -         @see getNumSlots()
 -     */
 -     void remapTable (int newNumberOfSlots)
 -     {
 -         const ScopedLockType sl (getLock());
 - 
 -         Array<HashEntry*> newSlots;
 -         newSlots.insertMultiple (0, nullptr, newNumberOfSlots);
 - 
 -         for (auto i = getNumSlots(); --i >= 0;)
 -         {
 -             HashEntry* nextEntry = nullptr;
 - 
 -             for (auto* entry = hashSlots.getUnchecked(i); entry != nullptr; entry = nextEntry)
 -             {
 -                 auto hashIndex = generateHashFor (entry->key, newNumberOfSlots);
 - 
 -                 nextEntry = entry->nextEntry;
 -                 entry->nextEntry = newSlots.getUnchecked (hashIndex);
 - 
 -                 newSlots.set (hashIndex, entry);
 -             }
 -         }
 - 
 -         hashSlots.swapWith (newSlots);
 -     }
 - 
 -     /** Returns the number of slots which are available for hashing.
 -         Each slot corresponds to a single hash-code, and each one can contain multiple items.
 -         @see getNumSlots()
 -     */
 -     inline int getNumSlots() const noexcept
 -     {
 -         return hashSlots.size();
 -     }
 - 
 -     //==============================================================================
 -     /** Efficiently swaps the contents of two hash-maps. */
 -     template <class OtherHashMapType>
 -     void swapWith (OtherHashMapType& otherHashMap) noexcept
 -     {
 -         const ScopedLockType lock1 (getLock());
 -         const typename OtherHashMapType::ScopedLockType lock2 (otherHashMap.getLock());
 - 
 -         hashSlots.swapWith (otherHashMap.hashSlots);
 -         std::swap (totalNumItems, otherHashMap.totalNumItems);
 -     }
 - 
 -     //==============================================================================
 -     /** Returns the CriticalSection that locks this structure.
 -         To lock, you can call getLock().enter() and getLock().exit(), or preferably use
 -         an object of ScopedLockType as an RAII lock for it.
 -     */
 -     inline const TypeOfCriticalSectionToUse& getLock() const noexcept      { return lock; }
 - 
 -     /** Returns the type of scoped lock to use for locking this array */
 -     typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
 - 
 - private:
 -     //==============================================================================
 -     class HashEntry
 -     {
 -     public:
 -         HashEntry (KeyTypeParameter k, ValueTypeParameter val, HashEntry* const next)
 -             : key (k), value (val), nextEntry (next)
 -         {}
 - 
 -         const KeyType key;
 -         ValueType value;
 -         HashEntry* nextEntry;
 - 
 -         JUCE_DECLARE_NON_COPYABLE (HashEntry)
 -     };
 - 
 - public:
 -     //==============================================================================
 -     /** Iterates over the items in a HashMap.
 - 
 -         To use it, repeatedly call next() until it returns false, e.g.
 -         @code
 -         HashMap <String, String> myMap;
 - 
 -         HashMap<String, String>::Iterator i (myMap);
 - 
 -         while (i.next())
 -         {
 -             DBG (i.getKey() << " -> " << i.getValue());
 -         }
 -         @endcode
 - 
 -         The order in which items are iterated bears no resemblence to the order in which
 -         they were originally added!
 - 
 -         Obviously as soon as you call any non-const methods on the original hash-map, any
 -         iterators that were created beforehand will cease to be valid, and should not be used.
 - 
 -         @see HashMap
 -     */
 -     struct Iterator
 -     {
 -         Iterator (const HashMap& hashMapToIterate) noexcept
 -             : hashMap (hashMapToIterate), entry (nullptr), index (0)
 -         {}
 - 
 -         Iterator (const Iterator& other) noexcept
 -             : hashMap (other.hashMap), entry (other.entry), index (other.index)
 -         {}
 - 
 -         /** Moves to the next item, if one is available.
 -             When this returns true, you can get the item's key and value using getKey() and
 -             getValue(). If it returns false, the iteration has finished and you should stop.
 -         */
 -         bool next() noexcept
 -         {
 -             if (entry != nullptr)
 -                 entry = entry->nextEntry;
 - 
 -             while (entry == nullptr)
 -             {
 -                 if (index >= hashMap.getNumSlots())
 -                     return false;
 - 
 -                 entry = hashMap.hashSlots.getUnchecked (index++);
 -             }
 - 
 -             return true;
 -         }
 - 
 -         /** Returns the current item's key.
 -             This should only be called when a call to next() has just returned true.
 -         */
 -         KeyType getKey() const
 -         {
 -             return entry != nullptr ? entry->key : KeyType();
 -         }
 - 
 -         /** Returns the current item's value.
 -             This should only be called when a call to next() has just returned true.
 -         */
 -         ValueType getValue() const
 -         {
 -             return entry != nullptr ? entry->value : ValueType();
 -         }
 - 
 -         /** Resets the iterator to its starting position. */
 -         void reset() noexcept
 -         {
 -             entry = nullptr;
 -             index = 0;
 -         }
 - 
 -         Iterator& operator++() noexcept                         { next(); return *this; }
 -         ValueType operator*() const                             { return getValue(); }
 -         bool operator!= (const Iterator& other) const noexcept  { return entry != other.entry || index != other.index; }
 -         void resetToEnd() noexcept                              { index = hashMap.getNumSlots(); }
 - 
 -     private:
 -         //==============================================================================
 -         const HashMap& hashMap;
 -         HashEntry* entry;
 -         int index;
 - 
 -         // using the copy constructor is ok, but you cannot assign iterators
 -         Iterator& operator= (const Iterator&) JUCE_DELETED_FUNCTION;
 - 
 -         JUCE_LEAK_DETECTOR (Iterator)
 -     };
 - 
 -     /** Returns a start iterator for the values in this tree. */
 -     Iterator begin() const noexcept             { Iterator i (*this); i.next(); return i; }
 - 
 -     /** Returns an end iterator for the values in this tree. */
 -     Iterator end() const noexcept               { Iterator i (*this); i.resetToEnd(); return i; }
 - 
 - private:
 -     //==============================================================================
 -     enum { defaultHashTableSize = 101 };
 -     friend struct Iterator;
 - 
 -     HashFunctionType hashFunctionToUse;
 -     Array<HashEntry*> hashSlots;
 -     int totalNumItems;
 -     TypeOfCriticalSectionToUse lock;
 - 
 -     int generateHashFor (KeyTypeParameter key, int numSlots) const
 -     {
 -         const int hash = hashFunctionToUse.generateHash (key, numSlots);
 -         jassert (isPositiveAndBelow (hash, numSlots)); // your hash function is generating out-of-range numbers!
 -         return hash;
 -     }
 - 
 -     static inline HashEntry* getEntry (HashEntry* firstEntry, KeyType keyToLookFor) noexcept
 -     {
 -         for (auto* entry = firstEntry; entry != nullptr; entry = entry->nextEntry)
 -             if (entry->key == keyToLookFor)
 -                 return entry;
 - 
 -         return nullptr;
 -     }
 - 
 -     inline HashEntry* getSlot (KeyType key) const noexcept     { return hashSlots.getUnchecked (generateHashFor (key, getNumSlots())); }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HashMap)
 - };
 
 
  |