FastCollectionsByLeo/Src/ColHash/Dict/Main.mqh
2026-07-21 11:09:28 -05:00

868 lines
25 KiB
MQL5

//+------------------------------------------------------------------+
//| Main.mqh |
//| Copyright 2026,Niquel Mendoza. |
//| https://www.mql5.com/en/users/nique_372 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026,Niquel Mendoza."
#property link "https://www.mql5.com/en/users/nique_372"
#property strict
#ifndef FASTCOLLECTIONSBYLEO_COLHASH_DICT_MAIN_MQH
#define FASTCOLLECTIONSBYLEO_COLHASH_DICT_MAIN_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Defines.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define MQLARTICES_DICT_R_SIZE (4*MQLARTICLES_DICT_SLOT_SIZE)
#define MQLARTICLES_DICT_BIT_START_BOOL_V (60)
#define MQLARTICLES_DICT_BIT_START_SALTAR (52)
#define MQLARTICLES_DICT_BIT_END_C_TYPE (20)
#define MQLARTICLES_DICT_BIT_END_R_TYPE (4)
//--- Mascaras (en 'long' para evitar overflow de literal 32bit)
#define MQLARTICLES_DICT_MASK_R_TYPE (0xF)
//---
#define MQLARTICLES_DICT_TYPE(ref) ENUM_MQLARTICLES_DICT_DTYPE(ref & MQLARTICLES_DICT_MASK_R_TYPE)
#define MQLARTICLES_DICT_CTYPE(ref) short(ref >> MQLARTICLES_DICT_BIT_END_R_TYPE)
#define MQLARTICLES_DICT_KEYIDX(ref) int(ref >> MQLARTICLES_DICT_BIT_END_C_TYPE)
#define MQLARTICLES_DICT_SALTAR(ref) int(ref >> MQLARTICLES_DICT_BIT_START_SALTAR)
#define MQLARTICLES_DICT_BOOLV(ref) bool((ref >> MQLARTICLES_DICT_BIT_START_BOOL_V) & 1)
//---
#define MQLARTICLES_DICT_PACK(dtype, ctype, keyidx, saltar) \
( long(dtype) | \
long(ctype) << MQLARTICLES_DICT_BIT_END_R_TYPE | \
long(keyidx) << MQLARTICLES_DICT_BIT_END_C_TYPE | \
long(saltar) << MQLARTICLES_DICT_BIT_START_SALTAR )
#define MQLARTICLES_DICT_PACK_BOOL(ctype, keyidx, saltar, boolval) \
( MQLARTICLES_DICT_PACK(MQLARTICLES_DICT_DTYPE_BOOLEAN, ctype, keyidx, saltar) | \
(long(boolval) << MQLARTICLES_DICT_BIT_START_BOOL_V) )
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum ENUM_MQLARTICLES_DICT_DTYPE
{
MQLARTICLES_DICT_DTYPE_STRING,
MQLARTICLES_DICT_DTYPE_REAL,
MQLARTICLES_DICT_DTYPE_INTEGER,
MQLARTICLES_DICT_DTYPE_BOOLEAN,
};
#define MQLARTICLES_DICT_RESERVE_STR(R) \
if(m_strings_size + (R) >= m_strings_reserve) \
{ \
m_strings_reserve += ((R) << 1) + 8; \
ArrayResize(m_strings, m_strings_reserve); \
} \
//---
// General (ref=[4bit=RealType|16Bit=CType|KeyIndex=32Bit|ASaltar=8Bit])([64bit=KeyHash])
// Integer ocupa un slot mas (total 3): [64bit=Number]
// Real ocupa un slot mas (total 3): [64bit=Real Number]
// String ocupa un slot mas (total 3): [64bit=String index]
// Bool no ocupa otro slot.. sin oque aprovecha el slot 0 (total 2): [*ref|1bit=bool_value)
//
// "ASaltar" = tamano en slots de la entrada (2 para bool, 3 para el resto).
// Se usa para recorrer el bucket saltando entradas completas (i += saltar)
// y tambien para saber cuantos slots copiar/mover en Resize()/Remove().
//+------------------------------------------------------------------+
//| Clase CDict |
//+------------------------------------------------------------------+
namespace TSN
{
class CDict
{
protected:
//---
string m_strings[];
int m_strings_size;
int m_strings_reserve;
//---
struct DictBucket
{
long slots[MQLARTICES_DICT_R_SIZE];
int pos; // slots ocupados (no numero de entradas)
};
//---
union UDoubleLong { double d; long l; };
//---
DictBucket m_buckets[];
int m_buckets_size;
int m_count;
//--- Resize
void Resize();
template <typename TKey>
void Assing(const TKey& key[], int i, const int end, string& out);
public:
CDict(void) { Init(64, 4); }
~CDict(void) {}
//--- Init
void Init(int buckets_size, int slots_reserve);
//--- Set
bool Set(const string& key, const string val, short cts_type);
template <typename TKey>
bool Set(const TKey& key[], const int s, const int end, const string val, short cts_type);
bool Set(const string& key, const long val);
bool Set(const string& key, const bool val);
bool Set(const string& key, const double val);
//--- Get
bool TryGet(const string& key, string& val) const;
template <typename TKey>
bool TryGet(const TKey& key[], const int s, const int end, string& val) const;
bool TryGet(const string& key, long& val) const;
bool TryGet(const string& key, bool& val) const;
bool TryGet(const string& key, double& val) const;
//--- Utils
bool Contains(const string& key) const;
bool Remove(const string& key);
void Clear();
__forceinline int Count() const { return m_count; }
//--- Get all (values como string para "universal")
int GetValues(string& out[], string& keys[]) const;
int GetKeys(string& keys[]) const;
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CDict::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].pos = 0;
}
//---
m_strings_size = 0;
m_strings_reserve = slots_reserve;
ArrayResize(m_strings, m_strings_reserve);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CDict::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].pos = 0;
}
for(int i = 0; i < m_buckets_size; i++)
{
const int t = m_buckets[i].pos;
int p = 0;
while(p < t)
{
const long ref = m_buckets[i].slots[p];
const int saltar = MQLARTICLES_DICT_SALTAR(ref);
const ulong hash = ulong(m_buckets[i].slots[p + 1]);
const uint idx = uint(hash % (ulong)new_size);
const int dst = new_buckets[idx].pos;
for(int k = 0; k < saltar; k++)
new_buckets[idx].slots[dst + k] = m_buckets[i].slots[p + k];
new_buckets[idx].pos += saltar;
p += saltar;
}
}
ArraySwap(m_buckets, new_buckets);
m_buckets_size = new_size;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename TKey>
void CDict::Assing(const TKey &key[], int i, const int end, string &out)
{
out.Truncate((end - i) + 1);
int k = 0;
for(; i <= end; i++)
{
out.SetChar(k++, key[i]);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// Notas:
// - En caso no exista lo crea
// - En caso se supera el factor de crecimiento 75% entonces resize al doble
bool CDict::Set(const string& key, const string val, short cts_type)
{
//--- Check size
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//--- Alg
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
//--- Index
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//--- Linear (recorre entradas completas, no slots sueltos)
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
if(MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_STRING)
{
m_strings[m_buckets[idx].slots[i + 2]] = val;
return true;
}
// Existe con otro tipo: no se soporta cambio de tipo in-place
return false;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
//---
if(t + 3 >= MQLARTICES_DICT_R_SIZE)
{
Resize();
return Set(key, val, cts_type);
}
//--- Reservar strings (key + value), inline
MQLARTICLES_DICT_RESERVE_STR(2)
const int string_index = m_strings_size++;
m_strings[string_index] = val;
const int key_index = m_strings_size++;
m_strings[key_index] = key;
//--- Bucket
m_buckets[idx].slots[t] = MQLARTICLES_DICT_PACK(MQLARTICLES_DICT_DTYPE_STRING, cts_type, key_index, 3);
m_buckets[idx].slots[t + 1] = long(hash);
m_buckets[idx].slots[t + 2] = string_index;
m_buckets[idx].pos += 3;
m_count++;
return true;
}
//+------------------------------------------------------------------+
template <typename TKey>
bool CDict::Set(const TKey& key[], const int s, const int end, const string val, short cts_type)
{
//---
if(s < 0 || s > end)
return false;
//--- Check size
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//--- Alg
ulong hash = FNV_OFFSET_BASIS;
for(int i = s; i <= end; i++)
{
h ^= (uchar)key[i];
h *= FNV_PRIME;
}
//--- Index
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//--- Linear (recorre entradas completas, no slots sueltos)
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
if(MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_STRING)
{
m_strings[m_buckets[idx].slots[i + 2]] = val;
return true;
}
// Existe con otro tipo: no se soporta cambio de tipo in-place
return false;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
//---
if(t + 3 >= MQLARTICES_DICT_R_SIZE)
{
Resize();
return Set(key, s, end, val, cts_type);
}
//--- Reservar strings (key + value), inline
MQLARTICLES_DICT_RESERVE_STR(2)
const int string_index = m_strings_size++;
m_strings[string_index] = val;
const int key_index = m_strings_size++;
Assing(key, s, end, m_strings[key_index]);
//--- Bucket
m_buckets[idx].slots[t] = MQLARTICLES_DICT_PACK(MQLARTICLES_DICT_DTYPE_STRING, cts_type, key_index, 3);
m_buckets[idx].slots[t + 1] = long(hash);
m_buckets[idx].slots[t + 2] = string_index;
m_buckets[idx].pos += 3;
m_count++;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CDict::Set(const string& key, const long val)
{
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
//---
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
if(MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_INTEGER)
{
m_buckets[idx].slots[i + 2] = val;
return true;
}
return false;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
//---
if(t + 3 >= MQLARTICES_DICT_R_SIZE)
{
Resize();
return Set(key, val);
}
//---
MQLARTICLES_DICT_RESERVE_STR(1)
const int key_index = m_strings_size++;
m_strings[key_index] = key;
//---
m_buckets[idx].slots[t] = MQLARTICLES_DICT_PACK(MQLARTICLES_DICT_DTYPE_INTEGER, 0, key_index, 3);
m_buckets[idx].slots[t + 1] = long(hash);
m_buckets[idx].slots[t + 2] = val;
m_buckets[idx].pos += 3;
m_count++;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CDict::Set(const string& key, const double val)
{
//---
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
//---
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
UDoubleLong conv;
conv.d = val;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
if(MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_REAL)
{
m_buckets[idx].slots[i + 2] = conv.l;
return true;
}
return false;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
//--- ;
if(t + 3 >= MQLARTICES_DICT_R_SIZE)
{
Resize();
return Set(key, val);
}
//---
MQLARTICLES_DICT_RESERVE_STR(1)
const int key_index = m_strings_size++;
m_strings[key_index] = key;
//---
m_buckets[idx].slots[t] = MQLARTICLES_DICT_PACK(MQLARTICLES_DICT_DTYPE_REAL, 0, key_index, 3);
m_buckets[idx].slots[t + 1] = long(hash);
m_buckets[idx].slots[t + 2] = conv.l;
m_buckets[idx].pos += 3;
m_count++;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CDict::Set(const string& key, const bool val)
{
if(m_count > 0 && float(m_count) / float(m_buckets_size) > MQLARTICLES_DICT_FACTOR_CRECIMIENTO)
Resize();
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
//---
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
const int saltar = MQLARTICLES_DICT_SALTAR(ref);
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
if(MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_BOOLEAN)
{
m_buckets[idx].slots[i] = MQLARTICLES_DICT_PACK_BOOL(MQLARTICLES_DICT_CTYPE(ref), MQLARTICLES_DICT_KEYIDX(ref), saltar, val);
return true;
}
return false;
}
i += saltar;
}
//---
if(t + 2 >= MQLARTICES_DICT_R_SIZE)
{
Resize();
return Set(key, val);
}
//---
MQLARTICLES_DICT_RESERVE_STR(1)
const int key_index = m_strings_size++;
m_strings[key_index] = key;
//---
m_buckets[idx].slots[t] = MQLARTICLES_DICT_PACK_BOOL(0, key_index, 2, val);
m_buckets[idx].slots[t + 1] = long(hash);
m_buckets[idx].pos += 2;
m_count++;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CDict::TryGet(const string& key, string& val) const
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
UDoubleLong conv;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
switch(MQLARTICLES_DICT_TYPE(ref))
{
case MQLARTICLES_DICT_DTYPE_STRING:
val = m_strings[m_buckets[idx].slots[i + 2]];
break;
case MQLARTICLES_DICT_DTYPE_INTEGER:
val = string(m_buckets[idx].slots[i + 2]);
break;
case MQLARTICLES_DICT_DTYPE_REAL:
conv.l = m_buckets[idx].slots[i + 2];
val = string(conv.d);
break;
case MQLARTICLES_DICT_DTYPE_BOOLEAN:
val = MQLARTICLES_DICT_BOOLV(ref) ? "true" : "false";
break;
}
return true;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
template <typename TKey>
bool CDict::TryGet(const TKey& key[], const int s, const int end, string& val) const
{
//---
if(s < 0 || s > end)
return false;
//--- Alg
ulong hash = FNV_OFFSET_BASIS;
for(int i = s; i <= end; i++)
{
hash ^= (uchar)key[i];
hash *= FNV_PRIME;
}
//---
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
UDoubleLong conv;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
switch(MQLARTICLES_DICT_TYPE(ref))
{
case MQLARTICLES_DICT_DTYPE_STRING:
val = m_strings[m_buckets[idx].slots[i + 2]];
break;
case MQLARTICLES_DICT_DTYPE_INTEGER:
val = string(m_buckets[idx].slots[i + 2]);
break;
case MQLARTICLES_DICT_DTYPE_REAL:
conv.l = m_buckets[idx].slots[i + 2];
val = string(conv.d);
break;
case MQLARTICLES_DICT_DTYPE_BOOLEAN:
val = MQLARTICLES_DICT_BOOLV(ref) ? "true" : "false";
break;
}
return true;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
bool CDict::TryGet(const string& key, long& val) const
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash && MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_INTEGER)
{
val = m_buckets[idx].slots[i + 2];
return true;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
bool CDict::TryGet(const string& key, double& val) const
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
UDoubleLong conv;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash && MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_REAL)
{
conv.l = m_buckets[idx].slots[i + 2];
val = conv.d;
return true;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
bool CDict::TryGet(const string& key, bool& val) const
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash && MQLARTICLES_DICT_TYPE(ref) == MQLARTICLES_DICT_DTYPE_BOOLEAN)
{
val = MQLARTICLES_DICT_BOOLV(ref);
return true;
}
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CDict::Contains(const string& key) const
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
return true;
i += MQLARTICLES_DICT_SALTAR(ref);
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// Notas:
// - Se compacta el bucket desplazando el resto de entradas 'saltar'
// posiciones a la izquierda (no vale el swap-with-last clasico porque
// las entradas tienen tamano variable: 2 slots para bool, 3 para el resto).
// - No se liberan los strings huerfanos en m_strings (limitacion conocida,
// igual que en la version anterior).
bool CDict::Remove(const string& key)
{
//---
ulong hash = FNV_OFFSET_BASIS;
const int len = StringLen(key);
FNV1a_64_AsM_Str(key, len, hash, FNV_PRIME)
const uint idx = uint(hash % (ulong)m_buckets_size);
const int t = m_buckets[idx].pos;
//---
int i = 0;
while(i < t)
{
const long ref = m_buckets[idx].slots[i];
const int saltar = MQLARTICLES_DICT_SALTAR(ref);
if(ulong(m_buckets[idx].slots[i + 1]) == hash)
{
for(int k = i + saltar; k < t; k++)
m_buckets[idx].slots[k - saltar] = m_buckets[idx].slots[k];
m_buckets[idx].pos -= saltar;
m_count--;
return true;
}
i += saltar;
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CDict::Clear()
{
for(int i = 0; i < m_buckets_size; i++)
m_buckets[i].pos = 0;
m_count = 0;
m_strings_size = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CDict::GetValues(string& out[], string& keys[]) const
{
//---
int r = ArrayResize(out, m_buckets_size);
ArrayResize(keys, r);
int f = 0;
//---
UDoubleLong conv;
//---
for(int i = 0; i < m_buckets_size; i++)
{
const int t = m_buckets[i].pos;
int p = 0;
//---
while(p < t)
{
//---
const long ref = m_buckets[i].slots[p];
const int saltar = MQLARTICLES_DICT_SALTAR(ref);
//---
keys[f] = m_strings[MQLARTICLES_DICT_KEYIDX(ref)];
switch(MQLARTICLES_DICT_TYPE(ref))
{
case MQLARTICLES_DICT_DTYPE_STRING:
out[f] = m_strings[m_buckets[i].slots[p + 2]];
break;
case MQLARTICLES_DICT_DTYPE_INTEGER:
out[f] = IntegerToString(m_buckets[i].slots[p + 2]);
break;
case MQLARTICLES_DICT_DTYPE_REAL:
conv.l = m_buckets[i].slots[p + 2];
out[f] = DoubleToString(conv.d);
break;
case MQLARTICLES_DICT_DTYPE_BOOLEAN:
out[f] = MQLARTICLES_DICT_BOOLV(ref) ? "true" : "false";
break;
}
//---
f++;
if(f >= r)
{
r <<= 1;
ArrayResize(out, r, r);
ArrayResize(keys, r, r);
}
p += saltar;
}
}
//---
ArrayResize(keys, f);
return ArrayResize(out, f);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CDict::GetKeys(string &keys[]) const
{
//---
int r = ArrayResize(keys, m_buckets_size);
ArrayResize(keys, r);
int f = 0;
//---
for(int i = 0; i < m_buckets_size; i++)
{
const int t = m_buckets[i].pos;
int p = 0;
//---
while(p < t)
{
//---
const long ref = m_buckets[i].slots[p];
//---
keys[f++] = m_strings[MQLARTICLES_DICT_KEYIDX(ref)];
//---
if(f >= r)
{
r <<= 1;
ArrayResize(keys, r, r);
}
p += MQLARTICLES_DICT_SALTAR(ref);
}
}
//---
return ArrayResize(keys, f);
}
}
//+------------------------------------------------------------------+
#endif // FASTCOLLECTIONSBYLEO_COLHASH_DICT_MAIN_MQH