2026-10-05 17:54:12 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| NodeBase.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza. |
|
| | | //| https://www.mql5.com/ |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com/"
|
| | | #property strict
|
| | |
|
2026-10-05 18:16:09 -05:00 | | | #ifndef BASESPARSERSLAN_SRC_NODE_NODEBASE_MQH
|
| | | #define BASESPARSERSLAN_SRC_NODE_NODEBASE_MQH
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-10-05 18:16:09 -05:00 | | | #include "..\\DOM\\DomImp.mqh"
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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;
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
| | | // 1. todo lo que implica devolver un string key si fall retona NULL
|
| | |
|
2026-10-05 17:54:12 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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
|
2026-10-08 13:38:10 -05:00 | | | TOut operator[](const string& key);
|
| | | TOut Get(const ulong h); // obtener por hash FNV1A64
|
2026-10-06 08:02:39 -05:00 | | | __forceinline TOut At(const int index) const; // obtener por hash
|
2026-10-05 17:54:12 -05:00 | | | TOut AtHomegeneo(const int index) const;
|
| | | TOut AtObj(const int index) const; // Obtiene el valor...
|
2026-10-05 18:16:09 -05:00 | | |
|
2026-10-05 21:57:35 -05:00 | | | //--- Pointer (JsonPointer)
|
| | | TOut operator[](BSFLPointerQuery& query);
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //--- Keys
|
| | | bool HasKey(const string &key) const;
|
| | | int GetKeys(string &out[]) const;
|
| | | int KeyToPosition(const string &key) const;
|
2026-10-08 13:38:10 -05:00 | | | // retorna una posicion en tape
|
| | | int AtObjKey(const int index) const;
|
| | | int AtObjKeyHomogeneo(const int index) const;
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //--- 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
|
2026-10-08 13:38:10 -05:00 | | | __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); }
|
2026-10-05 17:54:12 -05:00 | | | __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;
|
2026-10-08 13:38:10 -05:00 | | | __forceinline ulong ObjectAttempCount() const;
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //--- 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;
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //--- string statico reservado para uso interno... solo para funciones de aqui.. no usar fuera de esto
|
| | | static string __s_node_str;
|
| | | };
|
2026-10-05 18:16:09 -05:00 | | |
|
2026-10-08 13:38:10 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
| | | string CNodeSFLBase::__s_node_str;
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
2026-10-08 13:38:10 -05:00 | | | TOut CNodeSFLBase::operator[](const string& key)
|
2026-10-05 17:54:12 -05:00 | | | {
|
| | | //---
|
| | | 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;
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
| | | ulong h = FNV_OFFSET_BASIS;
|
| | | FNV1A_64_AsM_Str(key, StringLen(key), h, FNV_PRIME)
|
2026-10-05 17:54:12 -05:00 | | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
2026-10-05 17:54:12 -05:00 | | | if(m_node_pos != -1)
|
| | | {
|
2026-10-08 13:38:10 -05:00 | | | const int cur = m_ctx.PerfectHashAcces(h, m_ctx.m_tables[m_node_pos]);
|
2026-10-08 19:54:34 -05:00 | | | return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //--- Aun es valido
|
| | | if(m_ctx.m_cinta[m_idx] < TSN_SBL_BIT_JIT_ATTEMPS_MASK) // si no tiene el valor invalido de attemps
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | const ulong v = --m_ctx.m_cinta[m_idx + 1]; // reducimos en 1..
|
| | | if(v <= 1) // listo para el JIT
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | 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...
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | }
|
| | |
|
| | | //--- En caso aun estemos porbando o no vale la pena.. entonces lineal..
|
2026-10-08 13:38:10 -05:00 | | | 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)
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | const int cur = m_ctx.PerfectHashAcces(h, m_ctx.m_tables[m_node_pos]);
|
2026-10-08 19:54:34 -05:00 | | | return cur == -1 ? TOut::EMPTY_NODE : TOut(m_ctx, cur + TSN_SBL_KEYSLOT_SIZE);
|
2026-10-08 13:38:10 -05:00 | | | }
|
| | |
|
| | | //---
|
| | | 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
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | 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...
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | }
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //--- 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);
|
| | | }
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| 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;
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | const int first = m_idx + TSN_SBL_SLOT_ARR_SIZE;
|
2026-10-05 17:54:12 -05:00 | | | const int cur = first + index * m_ctx.GetStep(first);
|
| | | return TOut(m_ctx, cur);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-10-08 13:38:10 -05:00 | | | // 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)
|
2026-10-05 17:54:12 -05:00 | | | 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;
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | // + 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;
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //---
|
| | | return TOut(m_ctx, cur);
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| AtObjKey — key string del par en posicion index dentro de OBJ |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
2026-10-08 13:38:10 -05:00 | | | int CNodeSFLBase::AtObjKey(const int index) const
|
2026-10-05 17:54:12 -05:00 | | | {
|
| | | //---
|
| | | if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
2026-10-08 13:38:10 -05:00 | | | return -1;
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | 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));
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| AtObjKeyHomogeneo — igual pero asume step fijo del VAL |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
2026-10-08 13:38:10 -05:00 | | | int CNodeSFLBase::AtObjKeyHomogeneo(const int index) const
|
2026-10-05 17:54:12 -05:00 | | | {
|
| | | //---
|
| | | if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ)
|
2026-10-08 13:38:10 -05:00 | | | return -1;
|
2026-10-05 17:54:12 -05:00 | | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
| | | const int first_val = m_idx + TSN_SBL_SLOT_OBJ_SIZE + 1;
|
2026-10-05 17:54:12 -05:00 | | | const int val_step = m_ctx.GetStep(first_val);
|
2026-10-08 13:38:10 -05:00 | | | 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;
|
2026-10-05 17:54:12 -05:00 | | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
| | | return key_pos;
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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;
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | 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]);
|
2026-10-05 17:54:12 -05:00 | | | else
|
2026-10-08 13:38:10 -05:00 | | | return m_ctx.NodeKeyToPositionSlow(h, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-10-08 13:38:10 -05:00 | | | //| |
|
2026-10-05 17:54:12 -05:00 | | | //+------------------------------------------------------------------+
|
| | | 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;
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | return m_ctx.NodeGetKeys(m_idx, out, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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;
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //---
|
| | | ulong h = FNV_OFFSET_BASIS;
|
| | | FNV1A_64_AsM_Str(key, StringLen(key), h, FNV_PRIME)
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | 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;
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| 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));
|
| | | }
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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
|
2026-10-08 13:38:10 -05:00 | | | : TSN_SBL_CNG_OBJ_JIT(m_idx) != 0;
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
2026-10-08 13:38:10 -05:00 | | | __forceinline ulong CNodeSFLBase::ObjectAttempCount(void) const
|
2026-10-05 17:54:12 -05:00 | | | {
|
| | | return NODEBASE_IS_NOT_VALID_F || ((m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_OBJ) ? 0
|
2026-10-08 13:38:10 -05:00 | | | : TSN_SBL_CNG_OBJ_JIT_ATTMP(m_idx);
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| 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;
|
2026-10-08 13:38:10 -05:00 | | | un.ulong_value = m_ctx.m_cinta[m_idx + 1];
|
2026-10-05 17:54:12 -05:00 | | | return un.double_value != 0.0;
|
| | | }
|
| | | case TSN_SBL_BASE_TYPE_BOL:
|
2026-10-08 13:38:10 -05:00 | | | return TSN_SBL_CNG_BOOL(m_idx) != 0;
|
2026-10-05 17:54:12 -05:00 | | | 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;
|
2026-10-08 13:38:10 -05:00 | | | un.ulong_value = m_ctx.m_cinta[m_idx + 1];
|
2026-10-05 17:54:12 -05:00 | | | val = un.double_value != 0.0;
|
| | | return true;
|
| | | }
|
| | | case TSN_SBL_BASE_TYPE_BOL:
|
2026-10-08 13:38:10 -05:00 | | | val = TSN_SBL_CNG_BOOL(m_idx) != 0;
|
2026-10-05 17:54:12 -05:00 | | | 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;
|
2026-10-08 13:38:10 -05:00 | | | return m_ctx.ExistInArrayHomogeneo(m_idx + TSN_SBL_SLOT_ARR_SIZE, val, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
| | | template <typename T>
|
| | | int CNodeSFLBase::ToArray(T &out_arr[]) const
|
| | | {
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
2026-10-05 17:54:12 -05:00 | | | 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);
|
2026-10-08 13:38:10 -05:00 | | | m_ctx.ToArray(m_idx + TSN_SBL_SLOT_ARR_SIZE, out_arr, m_end);
|
2026-10-05 17:54:12 -05:00 | | | return count;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | template <typename TCtx, typename TType, typename TOut>
|
| | | template <typename T>
|
| | | __forceinline bool CNodeSFLBase::ExistInArray(const uint flags, const T val) const
|
| | | {
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | if(NODEBASE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE) != TSN_SBL_BASE_TYPE_ARR)
|
2026-10-05 17:54:12 -05:00 | | | return false;
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | return m_ctx.ExistInArray(m_idx + TSN_SBL_SLOT_ARR_SIZE, val, flags, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | |
|
| | |
|
2026-10-08 13:38:10 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // 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
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| 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; }
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | __forceinline void Next()
|
2026-10-05 17:54:12 -05:00 | | | {
|
| | | if(m_cur >= m_end)
|
| | | return;
|
| | | m_cur += m_step;
|
| | | }
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | __forceinline TOut Val()
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | return TOut(m_ctx, m_cur, m_cur + m_step);
|
2026-10-05 17:54:12 -05:00 | | | }
|
2026-10-08 13:38:10 -05:00 | | |
|
| | | //---
|
2026-10-05 17:54:12 -05:00 | | | 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);
|
| | | }
|
| | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | __forceinline TOut Val()
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-08 13:38:10 -05:00 | | | return TOut(m_ctx, m_cur, (m_cur + m_ctx.GetStep(m_cur)));
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | 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;
|
2026-10-08 13:38:10 -05:00 | | | m_cur += TSN_SBL_KEYSLOT_SIZE; // KEY SIEMPRE UN SLOT
|
| | | m_cur += m_ctx.GetStep(m_cur);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | |
|
| | | //---
|
2026-10-08 21:47:12 -05:00 | | | __forceinline int KeyIndex() const { return m_cur; }
|
| | | __forceinline ulong KeyValue() const { return m_ctx.m_cinta[m_cur]; }
|
2026-10-05 17:54:12 -05:00 | | |
|
| | | //---
|
2026-10-08 13:38:10 -05:00 | | | __forceinline TOut Val() const
|
2026-10-05 17:54:12 -05:00 | | | {
|
2026-10-09 09:09:23 -05:00 | | | const int pos = m_cur + TSN_SBL_KEYSLOT_SIZE;
|
2026-10-08 13:38:10 -05:00 | | | return TOut(m_ctx, pos, (pos + m_ctx.GetStep(pos)));
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | 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;
|
2026-10-08 13:38:10 -05:00 | | | return CNodeBaseIteradorArray<TCtx, TOut>(m_ctx, m_idx + TSN_SBL_SLOT_ARR_SIZE, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
| | | 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;
|
2026-10-08 13:38:10 -05:00 | | | const int s = m_idx + TSN_SBL_SLOT_ARR_SIZE;
|
2026-10-05 17:54:12 -05:00 | | | 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;
|
2026-10-08 13:38:10 -05:00 | | | return CNodeBaseIteratorObj<TCtx, TOut>(m_ctx, m_idx + TSN_SBL_SLOT_OBJ_SIZE, m_end);
|
2026-10-05 17:54:12 -05:00 | | | }
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-10-05 18:16:09 -05:00 | | | #endif // BASESPARSERSLAN_SRC_NODE_NODEBASE_MQH
|