//+------------------------------------------------------------------+ //| HashMap.mqh - Simple HashMap implementation for EscapeEA | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, EscapeEA" #property link "https://www.escapeea.com" #property version "1.00" //+------------------------------------------------------------------+ //| Template class for key-value pairs | //+------------------------------------------------------------------+ template class CKeyValuePair { public: TKey key; TValue value; CKeyValuePair() {} CKeyValuePair(TKey k, TValue v): key(k), value(v) {} }; //+------------------------------------------------------------------+ //| HashMap class | //+------------------------------------------------------------------+ template class CHashMap { private: CKeyValuePair m_items[]; // Find the index of a key in the array int FindIndex(TKey key) const { for(int i = 0; i < ArraySize(m_items); i++) if(m_items[i].key == key) return i; return -1; } public: // Constructor CHashMap() { ArrayResize(m_items, 0); } // Destructor ~CHashMap() { ArrayFree(m_items); } // Add or update a key-value pair void Add(TKey key, TValue value) { int index = FindIndex(key); if(index >= 0) m_items[index].value = value; else { int size = ArraySize(m_items); ArrayResize(m_items, size + 1); m_items[size] = CKeyValuePair(key, value); } } // Check if a key exists bool ContainsKey(TKey key) const { return (FindIndex(key) >= 0); } // Try to get a value by key bool TryGetValue(TKey key, TValue &value) const { int index = FindIndex(key); if(index >= 0) { value = m_items[index].value; return true; } return false; } // Remove a key-value pair by key bool Remove(TKey key) { int index = FindIndex(key); if(index >= 0) { int size = ArraySize(m_items); if(index < size - 1) m_items[index] = m_items[size - 1]; ArrayResize(m_items, size - 1); return true; } return false; } // Clear all items void Clear() { ArrayFree(m_items); ArrayResize(m_items, 0); } // Get the number of items int Count() const { return ArraySize(m_items); } }; //+------------------------------------------------------------------+ //| Specialization for string keys | //+------------------------------------------------------------------+ template class CHashMap : public CHashMap { private: static ulong StringHash(const string str) { ulong hash = 5381; int len = StringLen(str); for(int i = 0; i < len; i++) hash = ((hash << 5) + hash) + str[i]; return hash; } public: // Add or update a key-value pair with string key void Add(string key, TValue value) { CHashMap::Add(StringHash(key), value); } // Check if a string key exists bool ContainsKey(string key) const { return CHashMap::ContainsKey(StringHash(key)); } // Try to get a value by string key bool TryGetValue(string key, TValue &value) const { return CHashMap::TryGetValue(StringHash(key), value); } // Remove a key-value pair by string key bool Remove(string key) { return CHashMap::Remove(StringHash(key)); } };