MQLArticles/Utils/Dict/DictT.mqh

434 lines
12 KiB
MQL5
Raw Permalink Normal View History

2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
//| DictT.mqh |
//| Copyright 2026, Niquel Mendoza. |
//| https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
#property link "https://www.mql5.com/"
#property strict
#ifndef MQLARTICLES_UTILS_DICT_DICTT_MQH
#define MQLARTICLES_UTILS_DICT_DICTT_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Defines.mqh"
//+------------------------------------------------------------------+
//| Clase CDictSValue |
//+------------------------------------------------------------------+
2026-06-01 15:53:51 -05:00
// Dict (string)->(TValue) + metodos
2026-05-31 15:01:31 -05:00
template <typename TValue>
class CDictSValue
{
private:
//--- Lo definimos aqui para compatiblidad con otras clases como el hashmap
struct DictSlot
{
uint hash_code;
string key;
TValue val;
};
struct DictBucket
{
DictSlot slots[MQLARTICLES_DICT_SLOT_SIZE];
int size;
};
//---
DictBucket m_buckets[];
int m_buckets_size;
int m_count;
//---
void Resize();
2026-05-31 15:28:34 -05:00
void Asignar(string& v, const uchar& text[], const int start, const int end);
bool Iguales(const uchar& val[], const int start, const int end, const string& val2) const;
2026-05-31 15:01:31 -05:00
public:
CDictSValue(void) { Init(64, 4); }
~CDictSValue(void) {}
//--- Init
void Init(int buckets_size, int slots_reserve);
//--- Metodos
// Set
bool Set(const string& key, const TValue val);
2026-05-31 15:28:34 -05:00
bool Set(const uchar& text[], const int start, const int end, const TValue val);
2026-05-31 15:01:31 -05:00
// Add
bool Add(const string& key, const TValue val);
2026-05-31 15:28:34 -05:00
bool Add(const uchar& text[], const int start, const int end, const TValue val);
2026-05-31 15:01:31 -05:00
// Try get
bool TryGet(const string& key, TValue& val) const;
2026-05-31 15:28:34 -05:00
bool TryGet(const uchar& text[], const int start, const int end, TValue& val) const;
2026-05-31 15:01:31 -05:00
//--- Utils
bool Contains(const string& key) const;
2026-06-01 15:53:51 -05:00
bool Contains(const uchar& text[], const int start, const int end) const;
2026-05-31 15:01:31 -05:00
bool Remove(const string& key);
void Clear();
__forceinline int Count() const { return m_count; }
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
void CDictSValue::Init(int buckets_size, int slots_reserve)
{
m_buckets_size = fmax(buckets_size, 32);
slots_reserve = fmax(slots_reserve, 4);
m_count = 0;
ArrayResize(m_buckets, m_buckets_size);
for(int i = 0; i < m_buckets_size; i++)
{
m_buckets[i].size = 0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
void CDictSValue::Resize()
{
const int new_size = m_buckets_size << 1;
DictBucket new_buckets[];
ArrayResize(new_buckets, new_size);
for(int i = 0; i < new_size; i++)
{
new_buckets[i].size = 0;
}
for(int i = 0; i < m_buckets_size; i++)
{
const int t = m_buckets[i].size;
for(int j = 0; j < t; j++)
{
const uint idx = m_buckets[i].slots[j].hash_code % new_size;
new_buckets[idx].slots[new_buckets[idx].size++] = m_buckets[i].slots[j];
}
}
ArraySwap(m_buckets, new_buckets);
m_buckets_size = new_size;
}
2026-05-31 15:28:34 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Iguales(const uchar& val[], const int start, const int end, const string& val2) const
{
const int len = StringLen(val2);
const int l = (end - start) + 1;
if(len != l)
return false;
for(int i = 0; i < len; i++)
{
if(val[start + i] != val2[i])
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
void CDictSValue::Asignar(string& v, const uchar& text[], const int start, const int end)
{
const int l = (end - start) + 1;
StringSetLength(v, l);
for(int i = 0; i < l; i++)
{
v.SetChar(i, text[start + i]);
}
}
2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// Notas:
// - En caso no exista lo crea
// - En caso se supera el factor de crecimiento 75% entonces resize al doble
template <typename TValue>
bool CDictSValue::Add(const string& key, const TValue val)
{
//--- Check
2026-05-31 15:28:34 -05:00
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
2026-05-31 15:01:31 -05:00
Resize();
//---
uint hash;
CDICT_HASH(key, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && m_buckets[idx].slots[i].key == key)
{
// Existe
return false;
}
}
//---
if(m_buckets[idx].size + 1 >= MQLARTICLES_DICT_SLOT_SIZE)
{
Resize();
return false;
}
//---
m_buckets[idx].slots[m_buckets[idx].size].hash_code = hash;
m_buckets[idx].slots[m_buckets[idx].size].key = key;
m_buckets[idx].slots[m_buckets[idx].size].val = val;
m_buckets[idx].size++;
m_count++;
return true;
}
2026-05-31 15:28:34 -05:00
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Add(const uchar& text[], const int start, const int end, const TValue val)
{
//--- Check
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//---
uint hash;
CDICT_HASH_U(text, start, end, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && Iguales(text, start, end, m_buckets[idx].slots[i].key))
{
// Existe
return false;
}
}
//---
if(m_buckets[idx].size + 1 >= MQLARTICLES_DICT_SLOT_SIZE)
{
Resize();
return false;
}
//---
m_buckets[idx].slots[m_buckets[idx].size].hash_code = hash;
Asignar(m_buckets[idx].slots[m_buckets[idx].size].key, text, start, end);
m_buckets[idx].slots[m_buckets[idx].size].val = val;
m_buckets[idx].size++;
m_count++;
return true;
}
//+------------------------------------------------------------------+
//| |
2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Set(const string& key, const TValue val)
{
//--- Check
2026-05-31 15:28:34 -05:00
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
2026-05-31 15:01:31 -05:00
Resize();
//---
uint hash;
CDICT_HASH(key, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && m_buckets[idx].slots[i].key == key)
{
// Existe
m_buckets[idx].slots[i].val = val;
return true;
}
}
//---
return false;
}
2026-05-31 15:28:34 -05:00
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Set(const uchar& text[], const int start, const int end, const TValue val)
{
//--- Check
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//---
uint hash;
CDICT_HASH_U(text, start, end, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && Iguales(text, start, end, m_buckets[idx].slots[i].key))
{
// Existe
m_buckets[idx].slots[i].val = val;
return true;
}
}
//---
return false;
}
2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::TryGet(const string& key, TValue& val) const
{
//---
uint hash;
CDICT_HASH(key, hash)
2026-05-31 15:28:34 -05:00
//---
2026-05-31 15:01:31 -05:00
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && m_buckets[idx].slots[i].key == key)
{
val = m_buckets[idx].slots[i].val;
return true;
}
}
return false;
}
2026-05-31 15:28:34 -05:00
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::TryGet(const uchar& text[], const int start, const int end, TValue& val) const
{
//---
uint hash;
CDICT_HASH_U(text, start, end, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
//---
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && Iguales(text, start, end, m_buckets[idx].slots[i].key))
{
val = m_buckets[idx].slots[i].val;
return true;
}
}
return false;
}
2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Contains(const string& key) const
{
2026-06-01 15:53:51 -05:00
//---
2026-05-31 15:01:31 -05:00
uint hash;
CDICT_HASH(key, hash)
2026-06-01 15:53:51 -05:00
//---
2026-05-31 15:01:31 -05:00
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
for(int i = 0; i < t; i++)
if(m_buckets[idx].slots[i].hash_code == hash && m_buckets[idx].slots[i].key == key)
return true;
return false;
}
2026-06-01 15:53:51 -05:00
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Contains(const uchar& text[], const int start, const int end) const
{
//---
uint hash;
CDICT_HASH_U(text, start, end, hash)
//---
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
for(int i = 0; i < t; i++)
if(m_buckets[idx].slots[i].hash_code == hash && Iguales(text, start, end, m_buckets[idx].slots[i].key))
return true;
return false;
}
2026-05-31 15:01:31 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
bool CDictSValue::Remove(const string& key)
{
uint hash;
CDICT_HASH(key, hash)
const uint idx = hash % m_buckets_size;
const int t = m_buckets[idx].size;
for(int i = 0; i < t; i++)
{
if(m_buckets[idx].slots[i].hash_code == hash && m_buckets[idx].slots[i].key == key)
{
m_buckets[idx].slots[i] = m_buckets[idx].slots[--m_buckets[idx].size];
m_count--;
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TValue>
void CDictSValue::Clear()
{
for(int i = 0; i < m_buckets_size; i++)
m_buckets[i].size = 0;
m_count = 0;
}
//+------------------------------------------------------------------+
#endif // MQLARTICLES_UTILS_DICT_DICTT_MQH