forked from nique_372/BasesParserSLan
814 lines
30 KiB
MQL5
814 lines
30 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_NODE_NODEBASE_MQH
| |
#define BASESPARSERSLAN_SRC_NODE_NODEBASE_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "..\\DOM\\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;
| |
| |
//---
| |
// 1. todo lo que implica devolver un string key si fall retona NULL
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
struct CNodeSFLBase
| |
{
| |
public:
| |
//---
| |
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 operator[](const string& key);
| |
TOut Get(const ulong h); // obtener por hash FNV1A64
| |
__forceinline TOut At(const int index) const; // obtener por hash
| |
TOut AtHomegeneo(const int index) const;
| |
TOut AtObj(const int index) const; // Obtiene el valor...
| |
| |
//--- Pointer (JsonPointer)
| |
TOut operator[](BSFLPointerQuery& query);
| |
| |
//--- Keys
| |
bool HasKey(const string &key) const;
| |
int GetKeys(string &out[]) const;
| |
int KeyToPosition(const string &key) const;
| |
// retorna una posicion en tape
| |
int AtObjKey(const int index) const;
| |
int AtObjKeyHomogeneo(const int index) const;
| |
| |
//--- Arrays
| |
template <typename T>
| |
bool ExistInArrayHomogeneo(const T val) const;
| |
template <typename T>
| |
int ToArray(T &out_arr[]) const;
| |
template <typename T>
| |
bool ExistInArray(const uint flags, const T val) const;
| |
| |
//---
| |
__forceinline void RecalcNodePos() { NODEBASEF_RES }
| |
| |
//--- Tipo
| |
__forceinline TType GetType() const { return TType(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE); }
| |
__forceinline uint GetFlag() const { return 1u << int(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(TOut(m_ctx, m_idx, m_end, m_node_pos)); }
| |
| |
| |
//--- 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
| |
__forceinline bool ObjectIsJit() const;
| |
__forceinline ulong 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;
| |
| |
//--- string statico reservado para uso interno... solo para funciones de aqui.. no usar fuera de esto
| |
static string __s_node_str;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
string CNodeSFLBase::__s_node_str;
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
TOut CNodeSFLBase::operator[](const string& key)
| |
{
| |
//---
| |
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;
| |
| |
//---
| |
ulong h = FNV_OFFSET_BASIS;
| |
FNV1A_64_AsM_Str(key, StringLen(key), h, FNV_PRIME)
| |
| |
//---
| |
if(m_node_pos != -1)
| |
{
| |
const int cur = m_ctx.PerfectHashAcces(h, m_ctx.m_tables[m_node_pos]);
| |
return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
| |
}
| |
| |
//--- Aun es valido
| |
if(m_ctx.m_cinta[m_idx] < TSN_SBL_BIT_JIT_ATTEMPS_MASK) // si no tiene el valor invalido de attemps
| |
{
| |
const ulong v = --m_ctx.m_cinta[m_idx + 1]; // reducimos en 1..
| |
if(v <= 1) // listo para el JIT
| |
{
| |
const int num_el = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
| |
if(v == 0) // primer valor
| |
m_ctx.m_cinta[m_idx + 1] = num_el < TSN_NODEBASEREAD_MIN_JIT_VALUES_TO_HASH ?
| |
TSN_SBL_BIT_JIT_INV_VAL : TSN_NODEBASEREAD_MIN_JIT_ATTEMPS_TO_PHASH;
| |
else // vale entonces se terminaons los intetenos... probamos..
| |
m_ctx.NodeHashing(m_idx, num_el, m_end, m_node_pos); // si sale false ya pone el try=invalid..
| |
// aparte ya aqui si resulta volveiamos a linear por ultima vez...
| |
}
| |
}
| |
| |
//--- En caso aun estemos porbando o no vale la pena.. entonces lineal..
| |
const int cur = m_ctx.NodeFindByHashFvn1A64(h, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end);
| |
return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
TOut CNodeSFLBase::Get(const ulong h)
| |
{
| |
//---
| |
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;
| |
| |
//---
| |
if(m_node_pos != -1)
| |
{
| |
const int cur = m_ctx.PerfectHashAcces(h, m_ctx.m_tables[m_node_pos]);
| |
return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
| |
}
| |
| |
//---
| |
if(m_ctx.m_cinta[m_idx] < TSN_SBL_BIT_JIT_ATTEMPS_MASK) // si no tiene el valor invalido de attemps
| |
{
| |
const ulong v = --m_ctx.m_cinta[m_idx + 1]; // reducimos en 1..
| |
if(v <= 1) // listo para el JIT
| |
{
| |
const int num_el = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
| |
if(v == 0) // primer valor
| |
m_ctx.m_cinta[m_idx + 1] = num_el < TSN_NODEBASEREAD_MIN_JIT_VALUES_TO_HASH ?
| |
TSN_SBL_BIT_JIT_INV_VAL : TSN_NODEBASEREAD_MIN_JIT_ATTEMPS_TO_PHASH;
| |
else // vale entonces se terminaons los intetenos... probamos..
| |
m_ctx.NodeHashing(m_idx, num_el, m_end, m_node_pos); // si sale false ya pone el try=invalid..
| |
// aparte ya aqui si resulta volveiamos a linear por ultima vez...
| |
}
| |
}
| |
| |
//--- En caso aun estemos porbando o no vale la pena.. entonces lineal..
| |
const int cur = m_ctx.NodeFindByHashFvn1A64(h, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end);
| |
return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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 + TSN_SBL_SLOT_ARR_SIZE;
| |
const int cur = first + index * m_ctx.GetStep(first);
| |
return TOut(m_ctx, cur);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
// En caso index>obj size... comportameint indefinido
| |
// dado que podra retornba un indice fuera de "rango" del objeto.. asi qeu podira ser basura.. no un valor real por ejemp
| |
// [obj][obj][number][number][bool]
| |
// ahi si se punta al indice 1... entonces daria como resultao bool...
| |
// asi que siempre consultar InRangeSafe (SIEMPRE)
| |
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;
| |
| |
//---
| |
// + 1 para aptunar luyego de key
| |
const int cur = ((m_node_pos != -1) ? m_ctx.m_tables[m_node_pos].pos_arr[index] :
| |
m_ctx.NodeObjAtSlow(m_idx + TSN_SBL_SLOT_OBJ_SIZE, index)) + TSN_SBL_KEYSLOT_SIZE;
| |
| |
//---
| |
return TOut(m_ctx, cur);
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| AtObjKey — key string del par en posicion index dentro de OBJ |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
int 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 -1;
| |
| |
//---
| |
return ((m_node_pos != -1) ? m_ctx.m_tables[m_node_pos].pos_arr[index] :
| |
m_ctx.NodeObjAtSlow(m_idx + TSN_SBL_SLOT_OBJ_SIZE, index));
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| AtObjKeyHomogeneo — igual pero asume step fijo del VAL |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
int 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 -1;
| |
| |
//---
| |
const int first_val = m_idx + TSN_SBL_SLOT_OBJ_SIZE + 1;
| |
const int val_step = m_ctx.GetStep(first_val);
| |
const int pair_step = TSN_SBL_KEYSLOT_SIZE + val_step; // key+val
| |
const int key_pos = (m_idx + TSN_SBL_SLOT_OBJ_SIZE) + index * pair_step;
| |
| |
//---
| |
return key_pos;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
| |
//---
| |
ulong h = FNV_OFFSET_BASIS;
| |
FNV1A_64_AsM_Str(key, StringLen(key), h, FNV_PRIME)
| |
| |
//---
| |
if(m_node_pos != -1) // Ya hasheado, m_node_pos ya viene resuelto desde el constructor
| |
return m_ctx.PerfectHashComputeHashIndex(h, m_ctx.m_tables[m_node_pos]);
| |
else
| |
return m_ctx.NodeKeyToPositionSlow(h, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
//---
| |
return m_ctx.NodeGetKeys(m_idx, out, m_end);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
| |
//---
| |
ulong h = FNV_OFFSET_BASIS;
| |
FNV1A_64_AsM_Str(key, StringLen(key), h, FNV_PRIME)
| |
| |
//---
| |
return (m_node_pos != -1 ?
| |
m_ctx.PerfectHashComputeHashIndex(h, m_ctx.m_tables[m_node_pos]) :
| |
m_ctx.NodeFindByHashFvn1A64(h, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end)) != -1;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| At — acceso por indice en ARR |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
__forceinline 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;
| |
return TOut(m_ctx, m_ctx.NodeAt(m_idx + TSN_SBL_SLOT_ARR_SIZE, index));
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
return m_ctx.SerializeToDom(root, manager, m_idx, m_end);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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
| |
: TSN_SBL_CNG_OBJ_JIT(m_idx) != 0;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
__forceinline ulong 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
| |
: TSN_SBL_CNG_OBJ_JIT_ATTMP(m_idx);
| |
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| 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_UINT:
| |
case TSN_SBL_BASE_TYPE_INT:
| |
return m_ctx.m_cinta[m_idx + 1] != 0;
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete un;
| |
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
| |
return un.double_value != 0.0;
| |
}
| |
case TSN_SBL_BASE_TYPE_BOL:
| |
return TSN_SBL_CNG_BOOL(m_idx) != 0;
| |
default:
| |
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_UINT:
| |
case TSN_SBL_BASE_TYPE_INT:
| |
{
| |
val = m_ctx.m_cinta[m_idx + 1] != 0;
| |
return true;
| |
}
| |
case TSN_SBL_BASE_TYPE_FLT:
| |
{
| |
TsnBitInterprete un;
| |
un.ulong_value = m_ctx.m_cinta[m_idx + 1];
| |
val = un.double_value != 0.0;
| |
return true;
| |
}
| |
case TSN_SBL_BASE_TYPE_BOL:
| |
val = TSN_SBL_CNG_BOOL(m_idx) != 0;
| |
return true;
| |
default:
| |
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_to_str[uchar(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE)].Length();
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| 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_tok_pos = m_idx + m_ctx.GetStepPure(m_idx);
| |
if(next_tok_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
| |
return false;
| |
| |
//---
| |
m_idx = next_tok_pos;
| |
TOut::OnMute(this);
| |
| |
//---
| |
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;
| |
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
| |
return false;
| |
| |
//---
| |
m_idx = next_pos;
| |
// La idea aqui seria resolver el final..
| |
// En json es facil solo calutar step
| |
// En yaml.. tenemos ref\alaises asi que ahi en base a eso avanzamos o saltamos y reciente ahi idx muta
| |
// Y se calcula end
| |
TOut::OnMute(this);
| |
| |
//---
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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;
| |
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);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Arrays |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
template <typename T>
| |
__forceinline 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;
| |
return m_ctx.ExistInArrayHomogeneo(m_idx + TSN_SBL_SLOT_ARR_SIZE, val, m_end);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
template <typename T>
| |
int CNodeSFLBase::ToArray(T &out_arr[]) 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 0;
| |
| |
//---
| |
const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_NUM_EL) & TSN_SBL_BIT_MASK_NUM_EL);
| |
ArrayResize(out_arr, count);
| |
m_ctx.ToArray(m_idx + TSN_SBL_SLOT_ARR_SIZE, out_arr, m_end);
| |
return count;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template <typename TCtx, typename TType, typename TOut>
| |
template <typename T>
| |
__forceinline bool CNodeSFLBase::ExistInArray(const uint flags, 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;
| |
//---
| |
return m_ctx.ExistInArray(m_idx + TSN_SBL_SLOT_ARR_SIZE, val, flags, m_end);
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
// ADVERTENCIA:
| |
// 1. El flujo CORRECTO es solo usar una vez este iterador (un solo bucle de consulta)
| |
// Ahora dentro de se bucle puede llamar a las funciones que ud desee
| |
// Y dentro de esas funciones como Value etc... NO SE VALIDA el is valid..
| |
// dado qeu se COMPRENDE que si se llama de esas funciones ES POR QUE se esta en la parte valida del bucle
| |
// Solo las funciones Next tiene el chekeo.. de "es valido"
| |
// 2. Aparte KEY siempre debera de tener un slot eso ya esta MENCIONADO en SPEC.md
| |
| |
//+------------------------------------------------------------------+
| |
//| 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; }
| |
| |
//---
| |
__forceinline void Next()
| |
{
| |
if(m_cur >= m_end)
| |
return;
| |
m_cur += m_step;
| |
}
| |
| |
//---
| |
__forceinline TOut Val()
| |
{
| |
return TOut(m_ctx, m_cur, m_cur + m_step);
| |
}
| |
| |
//---
| |
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; }
| |
| |
//---
| |
__forceinline void Next()
| |
{
| |
if(m_cur >= m_end)
| |
return;
| |
m_cur += m_ctx.GetStep(m_cur);
| |
}
| |
| |
//---
| |
__forceinline TOut Val()
| |
{
| |
return TOut(m_ctx, m_cur, (m_cur + m_ctx.GetStep(m_cur)));
| |
}
| |
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; }
| |
| |
//---
| |
__forceinline void Next()
| |
{
| |
if(m_cur >= m_end)
| |
return;
| |
m_cur += TSN_SBL_KEYSLOT_SIZE; // KEY SIEMPRE UN SLOT
| |
m_cur += m_ctx.GetStep(m_cur);
| |
}
| |
| |
//---
| |
__forceinline int KeyIndex() const { return m_cur; }
| |
__forceinline ulong KeyValue() const { return m_ctx.m_cinta[m_cur]; }
| |
| |
//---
| |
__forceinline TOut Val() const
| |
{
| |
const int pos = m_cur + TSN_SBL_KEYSLOT_SIZE;
| |
return TOut(m_ctx, pos, (pos + m_ctx.GetStep(pos)));
| |
}
| |
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 + TSN_SBL_SLOT_ARR_SIZE, 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 + TSN_SBL_SLOT_ARR_SIZE;
| |
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 + TSN_SBL_SLOT_OBJ_SIZE, m_end);
| |
}
| |
}
| |
//+------------------------------------------------------------------+
| |
#endif // BASESPARSERSLAN_SRC_NODE_NODEBASE_MQH
|