forked from nique_372/BasesParserSLan
1058 lines
34 KiB
MQL5
1058 lines
34 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| NodeBase.mqh |
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
//| https://www.mql5.com/ |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
#property link "https://www.mql5.com/"
|
|
#property strict
|
|
|
|
#ifndef BASESPARSERSLAN_SRC_NODEBASE_MQH
|
|
#define BASESPARSERSLAN_SRC_NODEBASE_MQH
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include "DomImp.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#define NODEBASEF_RES_BASE(_ctx_, _idx_) ((_ctx_ != NULL && int(_ctx_.m_cinta[_idx_] & TSN_SBL_BIT_MASK_TYPE) == TSN_SBL_BASE_TYPE_OBJ) ? _ctx_.FindNodePos(_idx_) : -1)
|
|
#define NODEBASEF_RES m_node_pos = NODEBASEF_RES_BASE(m_ctx, m_idx);
|
|
#define NODEBASE_IS_NOT_VALID_F (m_ctx == NULL)
|
|
#define NODEBASE_IS_VALID (m_ctx != NULL)
|
|
#define NODEBASE_IS_NOT_VALID_FULL (m_ctx == NULL || m_idx < 1 || m_end < 1)
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteradorArray;
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteratorObj;
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteratorArrayFast;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
struct CNodeSFLBase
|
|
{
|
|
//---
|
|
TCtx* m_ctx;
|
|
int m_idx;
|
|
int m_end;
|
|
int m_node_pos;
|
|
|
|
//---
|
|
CNodeSFLBase(TCtx* ctx, const int idx, const int end, const int node_pos)
|
|
: m_ctx(ctx), m_idx(idx), m_end(end), m_node_pos(node_pos) {}
|
|
|
|
//--- Acceso
|
|
TOut Get(const ulong hash_fnv1a_64); // obtener por hash
|
|
TOut At(const int index) const; // obtener por hash
|
|
TOut AtHomegeneo(const int index) const;
|
|
TOut AtObj(const int index) const; // Obtiene el valor...
|
|
TOut Query(const string& path);
|
|
|
|
//--- Keys
|
|
bool HasKey(const string &key) const;
|
|
int GetKeys(string &out[]) const;
|
|
int KeyToPosition(const string &key) const;
|
|
string AtObjKey(const int index) const;
|
|
string AtObjKeyHomogeneo(const int index) const;
|
|
|
|
// Array exist
|
|
template <typename T>
|
|
bool ExistInArrayHomogeneo(const T val) const;
|
|
|
|
//---
|
|
__forceinline void RecalcNodePos() { NODEBASEF_RES }
|
|
|
|
//--- Tipo
|
|
__forceinline TType GetType() const { return TType(m_ctx.m_cinta[m_idx] & 0xF); }
|
|
__forceinline uint GetFlag() const { return 1 << uint(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE); }
|
|
__forceinline string TypeToMqlStr() const { return TCtx::s_dtype_to_str[int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)]; }
|
|
|
|
//--- Bool
|
|
bool ToBool(const bool def) const;
|
|
bool ToBoolSafe(bool& val) const;
|
|
|
|
//--- To
|
|
template <typename TValue>
|
|
__forceinline TValue GetAs() { return TValue(&this); }
|
|
|
|
|
|
//--- Is
|
|
__forceinline bool IsValid() const;
|
|
__forceinline bool IsInvalid() const;
|
|
__forceinline bool IsArray() const;
|
|
__forceinline bool IsObject() const;
|
|
__forceinline bool IsValidDataType() const;
|
|
|
|
//--- Size (arr u obj)
|
|
int Size() const;
|
|
__forceinline bool InRange(const int index) const;
|
|
bool InRangeSafe(const int index) const;
|
|
|
|
//--- JIT
|
|
bool NodeHashing();
|
|
__forceinline bool ObjectIsJit() const;
|
|
__forceinline int ObjectAttempCount() const;
|
|
|
|
//--- Mov raw
|
|
bool MoveToNextToken(const bool solo_en_el_bloque_actual = true);
|
|
bool MoveNextPositionsThis(const int posiciones, const bool solo_en_el_bloque_actual = true);
|
|
TOut MoveNextPositions(const int posiciones, const bool solo_en_el_bloque_actual = true);
|
|
|
|
//--- Dom
|
|
bool ToDom(CDomNodeBase* root, CDomNodeManager* manager);
|
|
|
|
//--- Iteradores
|
|
CNodeBaseIteradorArray<TCtx, TOut> BeginArr() const;
|
|
CNodeBaseIteradorArrayFast<TCtx, TOut> BeginArrHomogeneo() const;
|
|
CNodeBaseIteratorObj<TCtx, TOut> BeginObj() const;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::Query(const string &path)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F ||
|
|
((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) & (TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
if(path == "")
|
|
return TOut(m_ctx, m_idx, m_end, m_node_pos); // clonamos
|
|
|
|
//---
|
|
if(path[0] != '/')
|
|
return TOut::EMPTY_NODE;
|
|
|
|
|
|
//---
|
|
TOut curr(m_ctx, m_idx, m_end, m_node_pos);
|
|
const int l = StringLen(path);
|
|
int p = 1;
|
|
|
|
//---
|
|
while(true)
|
|
{
|
|
const uchar t = (uchar)curr.GetType();
|
|
if(t == TSN_SBL_BASE_TYPE_OBJ)
|
|
{
|
|
//--- Calcula y va escapando el key hash...y avanza p
|
|
const ulong khash = TCtx::EscapePointer(path, p, l);
|
|
// Ahora mismo en final o /
|
|
|
|
//---
|
|
curr = curr.Get(khash);
|
|
if(curr.IsInvalid())
|
|
return TOut::EMPTY_NODE;
|
|
}
|
|
else
|
|
if(t == TSN_SBL_BASE_TYPE_ARR)
|
|
{
|
|
//---
|
|
uchar ch = (uchar)path[p] ^ '0';
|
|
int last_index = -1;
|
|
|
|
//---
|
|
if(ch < 10)
|
|
{
|
|
last_index = 0;
|
|
while(true)
|
|
{
|
|
//---
|
|
last_index = (last_index << 3) + (last_index << 1) + ch;
|
|
p++;
|
|
if(p >= l)
|
|
break;
|
|
|
|
//---
|
|
ch = (uchar)path[p];
|
|
// p luego del /
|
|
if(ch == '/')
|
|
{
|
|
p++;
|
|
break;
|
|
}
|
|
|
|
//--
|
|
ch ^= '0';
|
|
}
|
|
}
|
|
|
|
//---
|
|
if(!curr.InRangeSafe(last_index))
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//-- Accedemos
|
|
curr = curr.At(last_index);
|
|
}
|
|
else
|
|
{
|
|
// No se puede
|
|
return TOut::EMPTY_NODE;
|
|
}
|
|
|
|
//---
|
|
if(p >= l)
|
|
return curr;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::Get(const ulong hash_fnv1a_64)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//--- Iterar pares KEY+VAL
|
|
// Print("Call");
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & TSN_SBL_BIT_MASK_IS_HASHSING) == 0)
|
|
{
|
|
//Print("No esta hasheado buscando o(n)");
|
|
//---
|
|
int c = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_C_HASH) & TSN_SBL_BIT_MASK_NUM_C_HASH;
|
|
//Print("Contador actual: ", c);
|
|
if(c >= TSN_NODEBASEREAD_MIN_JIT_ATTEMPS_TO_PHASH) // Veriricamos si supero
|
|
{
|
|
if(NodeHashing())
|
|
{
|
|
//Print("Hasheado");
|
|
//--- Obtenemos posicion
|
|
int val_pos = m_ctx.PerfectHashAcces(hash_fnv1a_64, m_node_pos);
|
|
if(val_pos == -1)
|
|
{
|
|
return TOut::EMPTY_NODE;
|
|
}
|
|
else
|
|
{
|
|
val_pos++; // Luego de key
|
|
return TOut(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
|
}
|
|
}
|
|
//Print("No se pudo hashear");
|
|
// Si llega aqui es por que fallo.. en ese caso reiniciamos los intetnos..
|
|
|
|
//---
|
|
c = 0;
|
|
const long mask = long(TSN_SBL_BIT_MASK_NUM_C_HASH) << TSN_SBL_BIT_START_NUM_C_HASH; // máscara de 3 bits en pos 5
|
|
m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) | (c << TSN_SBL_BIT_START_NUM_C_HASH);
|
|
}
|
|
else
|
|
{
|
|
// Aun no.. solo aumentamos y modificamos..
|
|
c++;
|
|
const long mask = long(TSN_SBL_BIT_MASK_NUM_C_HASH) << TSN_SBL_BIT_START_NUM_C_HASH; // máscara de 3 bits en pos 5
|
|
m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) | (c << TSN_SBL_BIT_START_NUM_C_HASH);
|
|
}
|
|
|
|
//--- Linear probing.. de siempre...
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
while(cur < m_end)
|
|
{
|
|
if(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_KEY)
|
|
{
|
|
cur += m_ctx.GetStep(cur);
|
|
continue;
|
|
}
|
|
if(m_ctx.KeysEqual(hash_fnv1a_64, cur))
|
|
{
|
|
const int val_pos = cur + 1;
|
|
return TOut(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
|
}
|
|
|
|
//---
|
|
cur++; // salta KEY
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
}
|
|
return TOut::EMPTY_NODE;
|
|
}
|
|
|
|
//--- m_node_pos ya viene resuelto desde el constructor
|
|
int val_pos = m_ctx.PerfectHashAcces(hash_fnv1a_64, m_node_pos);
|
|
if(val_pos == -1)
|
|
{
|
|
return TOut::EMPTY_NODE;
|
|
}
|
|
else
|
|
{
|
|
val_pos++; // Luego de key
|
|
return TOut(m_ctx, val_pos, val_pos + m_ctx.GetStep(val_pos));
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| AtHomegeneo — acceso por indice en ARR con step fijo |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::AtHomegeneo(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
const int first = m_idx + TCtx::s_slots_size_arrobj;
|
|
const int step = m_ctx.GetStep(first);
|
|
const int cur = first + index * step;
|
|
return TOut(m_ctx, cur, cur + step);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::AtObj(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
int cur = 0;
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&TSN_SBL_BIT_MASK_IS_HASHSING) != 0)
|
|
{
|
|
cur = m_ctx.m_tables[m_node_pos].pos_arr[index] + 1;// Ahora mismo apunta a key saltos al valor..
|
|
}
|
|
else
|
|
{
|
|
cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
// Ahora mismo apunta a key..
|
|
for(int k = 0; k < index; k++)
|
|
{
|
|
cur++; // Salta key
|
|
cur += m_ctx.GetStep(cur);
|
|
}
|
|
}
|
|
|
|
//---
|
|
return TOut(m_ctx, cur, cur + m_ctx.GetStep(cur));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| At — acceso por indice en ARR |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::At(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
for(int k = 0; k < index; k++)
|
|
cur += m_ctx.GetStep(cur);
|
|
|
|
//---
|
|
return TOut(m_ctx, cur, cur + m_ctx.GetStep(cur));
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| AtObjKey — key string del par en posicion index dentro de OBJ |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
string CNodeSFLBase::AtObjKey(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return "";
|
|
|
|
//---
|
|
int cur = 0;
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&TSN_SBL_BIT_MASK_IS_HASHSING) != 0)
|
|
{
|
|
//--- Objeto ya hasheado, m_node_pos ya viene resuelto desde el constructor.
|
|
// Usamos pos_arr en vez de recorrer linealmente (esta funcion no fuerza el JIT, solo lo aprovecha).
|
|
cur = m_ctx.m_tables[m_node_pos].pos_arr[index];
|
|
}
|
|
else
|
|
{
|
|
cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
for(int k = 0; k < index; k++)
|
|
{
|
|
cur++; // salta KEY (1 pos)
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
}
|
|
}
|
|
|
|
//--- TSN_SBL_BIT_STR_MASK_LEN
|
|
// KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
|
const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
|
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
return CharArrayToString(m_ctx.m_raw, start, slen);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| AtObjKeyHomogeneo — igual pero asume step fijo del VAL |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
string CNodeSFLBase::AtObjKeyHomogeneo(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return "";
|
|
|
|
//--- step fijo = 1(KEY) + step(primer VAL)
|
|
const int first_val = m_idx + TCtx::s_slots_size_arrobj + 1;
|
|
const int val_step = m_ctx.GetStep(first_val);
|
|
const int pair_step = 1 + val_step; // key+val
|
|
const int key_pos = (m_idx + TCtx::s_slots_size_arrobj) + index * pair_step;
|
|
|
|
//--- KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
|
const int start = int(m_ctx.m_cinta[key_pos] >> TSN_SBL_BIT_STR_START);
|
|
const int slen = int((m_ctx.m_cinta[key_pos] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
return CharArrayToString(m_ctx.m_raw, start, slen);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
int CNodeSFLBase::KeyToPosition(const string &key) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return -1;
|
|
|
|
//---
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&TSN_SBL_BIT_MASK_IS_HASHSING) != 0)
|
|
{
|
|
//--- Ya hasheado, m_node_pos ya viene resuelto desde el constructor
|
|
return m_ctx.PerfectHashComputeHashIndex(key, m_node_pos);
|
|
}
|
|
else
|
|
{
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
int k = 0;
|
|
while(cur < m_end)
|
|
{
|
|
if(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_KEY)
|
|
{
|
|
cur += m_ctx.GetStep(cur);
|
|
continue;
|
|
}
|
|
if(m_ctx.KeysEqual(key, cur))
|
|
return k;
|
|
|
|
//---
|
|
cur++; // salta KEY
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
k++;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| GetKeys — vacia todas las keys del objeto a un array de strings |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
int CNodeSFLBase::GetKeys(string &out[]) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return 0;
|
|
|
|
//---
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&TSN_SBL_BIT_MASK_IS_HASHSING) != 0)
|
|
{
|
|
//--- Ya hasheado, m_node_pos ya viene resuelto desde el constructor
|
|
const int count = m_ctx.m_tables[m_node_pos].table_size;
|
|
ArrayResize(out, count);
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
const int cur = m_ctx.m_tables[m_node_pos].pos_arr[i];
|
|
const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
|
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
out[i] = CharArrayToString(m_ctx.m_raw, start, slen);
|
|
}
|
|
return count;
|
|
}
|
|
else
|
|
{
|
|
//---
|
|
const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
|
ArrayResize(out, count);
|
|
|
|
//---
|
|
int i = 0;
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
while(cur < m_end)
|
|
{
|
|
const int start = int(m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_START);
|
|
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
out[i++] = CharArrayToString(m_ctx.m_raw, start, slen);
|
|
|
|
//---
|
|
cur++; // salta KEY
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
}
|
|
|
|
//---
|
|
return count;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::HasKey(const string &key) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return false;
|
|
|
|
//--- Iterar pares KEY+VAL
|
|
if(((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING)&TSN_SBL_BIT_MASK_IS_HASHSING) == 0)
|
|
{
|
|
//--- Linear probing.. de siempre...
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
while(cur < m_end)
|
|
{
|
|
if(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_KEY)
|
|
{
|
|
cur += m_ctx.GetStep(cur);
|
|
continue;
|
|
}
|
|
if(m_ctx.KeysEqual(key, cur))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//---
|
|
cur++; // salta KEY
|
|
cur += m_ctx.GetStep(cur); // salta VAL
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
return m_ctx.PerfectHashComputeHash(key, m_node_pos) != -1;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::ToDom(CDomNodeBase* root, CDomNodeManager* manager)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || ((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) &
|
|
(TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
|
return false;
|
|
|
|
m_ctx.SerializeToDom(root, manager, m_idx, m_end);
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+}
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::NodeHashing(void)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return false;
|
|
|
|
//---
|
|
if(m_ctx.NodeHashing(m_idx, int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL),
|
|
m_end, m_node_pos))
|
|
{
|
|
m_ctx.m_cinta[m_idx] = m_ctx.m_cinta[m_idx] | (long(1) << TSN_SBL_BIT_START_IS_HASING);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Jit instrocpeccion |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::ObjectIsJit(void) const
|
|
{
|
|
return NODEBASE_IS_NOT_VALID_F || ((m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ) ? false
|
|
: ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_IS_HASING) & TSN_SBL_BIT_MASK_IS_HASHSING) != 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline int CNodeSFLBase::ObjectAttempCount(void) const
|
|
{
|
|
return NODEBASE_IS_NOT_VALID_F || ((m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ) ? 0
|
|
: int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_C_HASH) & TSN_SBL_BIT_MASK_NUM_C_HASH;
|
|
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Size |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
int CNodeSFLBase::Size() const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || ((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) & (TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
|
return 0;
|
|
|
|
//---
|
|
return int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::InRange(const int index) const
|
|
{
|
|
const int t = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
|
return index >= 0 && index < t;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::InRangeSafe(const int index) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || ((1 << int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)) & (TSN_SBL_BASE_F_OBJ | TSN_SBL_BASE_F_ARR)) == 0)
|
|
return false;
|
|
|
|
//---
|
|
const int t = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
|
|
return index >= 0 && index < t;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ToBool |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::ToBool(const bool def) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F)
|
|
return def;
|
|
|
|
//---
|
|
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
|
|
{
|
|
case TSN_SBL_BASE_TYPE_INT:
|
|
{
|
|
return m_ctx.m_cinta[m_idx + 1] != 0;
|
|
}
|
|
case TSN_SBL_BASE_TYPE_FLT:
|
|
{
|
|
static BitInterpreter un;
|
|
return un.double_value != 0.0;
|
|
}
|
|
case TSN_SBL_BASE_TYPE_BOL:
|
|
return ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_BOOL) & 1) != 0;
|
|
}
|
|
|
|
//---
|
|
return def;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::ToBoolSafe(bool & val) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F)
|
|
return false;
|
|
|
|
//---
|
|
switch(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE))
|
|
{
|
|
case TSN_SBL_BASE_TYPE_INT:
|
|
{
|
|
val = m_ctx.m_cinta[m_idx + 1] != 0;
|
|
return true;
|
|
}
|
|
case TSN_SBL_BASE_TYPE_FLT:
|
|
{
|
|
static BitInterpreter un;
|
|
val = un.double_value != 0.0;
|
|
return true;
|
|
}
|
|
case TSN_SBL_BASE_TYPE_BOL:
|
|
val = ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_BOOL) & 1) != 0;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Is |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::IsValid() const { return m_ctx != NULL && m_idx >= 0 && m_end >= 0; }
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::IsInvalid() const { return NODEBASE_IS_NOT_VALID_FULL; }
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::IsArray() const
|
|
{
|
|
return NODEBASE_IS_VALID && int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) == TSN_SBL_BASE_TYPE_ARR;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::IsObject() const
|
|
{
|
|
return NODEBASE_IS_VALID && int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) == TSN_SBL_BASE_TYPE_OBJ;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
__forceinline bool CNodeSFLBase::IsValidDataType(void) const
|
|
{
|
|
return NODEBASE_IS_VALID && TCtx::s_dtype_is_valid[uchar(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)];
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Navegacion raw |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::MoveToNextToken(const bool solo_en_el_bloque_actual = true)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F)
|
|
return false;
|
|
|
|
//---
|
|
const int next_pos = m_idx + m_ctx.GetStep(m_idx);
|
|
const int final_pos = next_pos + m_ctx.GetStep(next_pos);
|
|
|
|
//---
|
|
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
|
|
return false;
|
|
|
|
//---
|
|
m_idx = next_pos;
|
|
m_end = final_pos;
|
|
|
|
//---
|
|
NODEBASEF_RES
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
bool CNodeSFLBase::MoveNextPositionsThis(const int posiciones, const bool solo_en_el_bloque_actual = true)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F)
|
|
return false;
|
|
|
|
//---
|
|
const int next_pos = m_idx + posiciones;
|
|
const int final_pos = solo_en_el_bloque_actual ? m_end : next_pos + m_ctx.GetStep(next_pos);
|
|
|
|
//---
|
|
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
|
|
return false;
|
|
|
|
//---
|
|
m_idx = next_pos;
|
|
m_end = final_pos;
|
|
|
|
//---
|
|
NODEBASEF_RES
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
template <typename T>
|
|
bool CNodeSFLBase::ExistInArrayHomogeneo(const T val) const
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
|
return false;
|
|
|
|
//---
|
|
int cur = m_idx + TCtx::s_slots_size_arrobj;
|
|
|
|
//---
|
|
switch(int(m_ctx.m_cinta[cur] & TSN_SBL_BIT_MASK_TYPE))
|
|
{
|
|
case TSN_SBL_BASE_TYPE_INT:
|
|
{
|
|
while(cur < m_end)
|
|
{
|
|
if(val == T(m_ctx.m_cinta[cur + 1]))
|
|
return true;
|
|
cur += 2;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
case TSN_SBL_BASE_TYPE_FLT:
|
|
{
|
|
while(cur < m_end)
|
|
{
|
|
static BitInterpreter bit;
|
|
bit.long_value = m_ctx.m_cinta[cur + 1];
|
|
if(val == T(bit.double_value))
|
|
return true;
|
|
|
|
//---
|
|
cur += 2;
|
|
}
|
|
return false;
|
|
}
|
|
case TSN_SBL_BASE_TYPE_BOL:
|
|
{
|
|
while(cur < m_end)
|
|
{
|
|
if(val == T((m_ctx.m_cinta[cur] >> TSN_SBL_BIT_START_ENDTYPE) & 1))
|
|
return true;
|
|
cur++;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//---
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Navegacion raw |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
TOut CNodeSFLBase::MoveNextPositions(const int posiciones, const bool solo_en_el_bloque_actual = true)
|
|
{
|
|
//---
|
|
if(NODEBASE_IS_NOT_VALID_F)
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
const int next_pos = m_idx + posiciones;
|
|
const int final_pos = solo_en_el_bloque_actual ? m_end : next_pos + m_ctx.GetStep(next_pos);
|
|
|
|
//---
|
|
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
|
|
return TOut::EMPTY_NODE;
|
|
|
|
//---
|
|
// llamamos a la version con 3 (nodepos se calcula ahi mismo)
|
|
return TOut(m_ctx, next_pos, final_pos);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Iterador de arrays fast |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteradorArrayFast
|
|
{
|
|
TCtx* const m_ctx;
|
|
int m_cur;
|
|
const int m_end;
|
|
const int m_step;
|
|
|
|
//---
|
|
CNodeBaseIteradorArrayFast(TCtx* ctx, const int cur, const int end, const int step)
|
|
: m_ctx(ctx), m_cur(cur), m_end(end), m_step(step) {}
|
|
//---
|
|
CNodeBaseIteradorArrayFast()
|
|
: m_ctx(NULL), m_cur(0), m_end(0), m_step(0) {}
|
|
|
|
//---
|
|
__forceinline bool IsValid() { return m_cur < m_end; }
|
|
__forceinline void Kill() { m_cur = m_end; }
|
|
|
|
//---
|
|
void Next()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return;
|
|
m_cur += m_step;
|
|
}
|
|
|
|
//---
|
|
TOut Val()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return TOut::EMPTY_NODE;
|
|
const int fin = m_cur + m_step;
|
|
return TOut(m_ctx, m_cur, fin);
|
|
}
|
|
static const CNodeBaseIteradorArrayFast EMPTY_ITERATOR_ARR_FAST;
|
|
};
|
|
template <typename TCtx, typename TOut>
|
|
const CNodeBaseIteradorArrayFast<TCtx, TOut> CNodeBaseIteradorArrayFast::EMPTY_ITERATOR_ARR_FAST;
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Iterador de arrays |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteradorArray
|
|
{
|
|
TCtx* const m_ctx;
|
|
int m_cur;
|
|
const int m_end;
|
|
|
|
//---
|
|
CNodeBaseIteradorArray(TCtx* ctx, const int cur, const int end)
|
|
: m_ctx(ctx), m_cur(cur), m_end(end) {}
|
|
//---
|
|
CNodeBaseIteradorArray()
|
|
: m_ctx(NULL), m_cur(0), m_end(0) {}
|
|
|
|
//---
|
|
__forceinline bool IsValid() { return m_cur < m_end; }
|
|
__forceinline void Kill() { m_cur = m_end; }
|
|
|
|
//---
|
|
void Next()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return;
|
|
m_cur += m_ctx.GetStep(m_cur);
|
|
}
|
|
|
|
//---
|
|
TOut Val()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return TOut::EMPTY_NODE;
|
|
const int fin = m_cur + m_ctx.GetStep(m_cur);
|
|
return TOut(m_ctx, m_cur, fin);
|
|
}
|
|
static const CNodeBaseIteradorArray EMPTY_ITERATOR_ARR;
|
|
};
|
|
template <typename TCtx, typename TOut>
|
|
const CNodeBaseIteradorArray<TCtx, TOut> CNodeBaseIteradorArray::EMPTY_ITERATOR_ARR;
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Iterador de objetos |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TOut>
|
|
struct CNodeBaseIteratorObj
|
|
{
|
|
TCtx* const m_ctx;
|
|
int m_cur;
|
|
const int m_end;
|
|
|
|
|
|
//---
|
|
CNodeBaseIteratorObj(TCtx* ctx, const int cur, const int end)
|
|
: m_ctx(ctx), m_cur(cur), m_end(end) {}
|
|
//---
|
|
CNodeBaseIteratorObj()
|
|
: m_ctx(NULL), m_cur(0), m_end(0) {}
|
|
|
|
//---
|
|
__forceinline bool IsValid() { return m_cur < m_end; }
|
|
__forceinline void Kill() { m_cur = m_end; }
|
|
|
|
//---
|
|
void Next()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return;
|
|
m_cur++; // salta KEY (2 pos)
|
|
m_cur += m_ctx.GetStep(m_cur); // salta VAL
|
|
}
|
|
|
|
//---
|
|
string Key()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return "";
|
|
//--- KEY ocupa 1 pos: [tipo(4)|len(28low)|start(32high)] (igual que STRING)
|
|
const int s = int(m_ctx.m_cinta[m_cur] >> TSN_SBL_BIT_STR_START);
|
|
const int slen = int((m_ctx.m_cinta[m_cur] >> TSN_SBL_BIT_STR_LEN) & TSN_SBL_BIT_STR_MASK_LEN);
|
|
return CharArrayToString(m_ctx.m_raw, s, slen);
|
|
}
|
|
|
|
//---
|
|
TOut Val()
|
|
{
|
|
if(m_cur >= m_end)
|
|
return TOut::EMPTY_NODE;
|
|
const int pos = m_cur + 1;
|
|
const int fin = pos + m_ctx.GetStep(pos);
|
|
return TOut(m_ctx, pos, fin);
|
|
}
|
|
static const CNodeBaseIteratorObj EMPTY_ITERATOR_OBJ;
|
|
};
|
|
template <typename TCtx, typename TOut>
|
|
const CNodeBaseIteratorObj<TCtx, TOut> CNodeBaseIteratorObj::EMPTY_ITERATOR_OBJ;
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| BeginArr / BeginObj |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
CNodeBaseIteradorArray<TCtx, TOut> CNodeSFLBase::BeginArr() const
|
|
{
|
|
if(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
|
return CNodeBaseIteradorArray<TCtx, TOut>::EMPTY_ITERATOR_ARR;
|
|
return CNodeBaseIteradorArray<TCtx, TOut>(m_ctx, m_idx + TCtx::s_slots_size_arrobj, m_end);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
CNodeBaseIteradorArrayFast<TCtx, TOut> CNodeSFLBase::BeginArrHomogeneo() const
|
|
{
|
|
if(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
|
return CNodeBaseIteradorArrayFast<TCtx, TOut>::EMPTY_ITERATOR_ARR_FAST;
|
|
const int s = m_idx + TCtx::s_slots_size_arrobj;
|
|
return CNodeBaseIteradorArrayFast<TCtx, TOut>(m_ctx, s, m_end, m_ctx.GetStep(s));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
template <typename TCtx, typename TType, typename TOut>
|
|
CNodeBaseIteratorObj<TCtx, TOut> CNodeSFLBase::BeginObj() const
|
|
{
|
|
if(int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
|
return CNodeBaseIteratorObj<TCtx, TOut>::EMPTY_ITERATOR_OBJ;
|
|
return CNodeBaseIteratorObj<TCtx, TOut>(m_ctx, m_idx + TCtx::s_slots_size_arrobj, m_end);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
#endif // BASESPARSERSLAN_SRC_NODEBASE_MQH
|