SetFileByLeo/Src/Node.mqh
2026-07-07 15:36:07 -05:00

864 lines
27 KiB
MQL5

//+------------------------------------------------------------------+
//| Node.mqh |
//| Copyright 2026, Niquel Mendoza. |
//| https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
#property link "https://www.mql5.com/"
#property strict
#ifndef SETFILEBYLEO_SRC_NODE_MQH
#define SETFILEBYLEO_SRC_NODE_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Parser.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
// Layout cinta:
// ROOT 1 pos [tipo(4)|count(resto)<<END_TYPE][jittry<<36]
// KEY 1 pos [tipo(4)|len(28)<<LEN_PLAIN|start(32)<<START_STR] (igual que STRING)
// META 1 pos [tipo(4)|op_type(VAL/Y/N)<<END_TYPE] -- no es valor, precede al/los valor(es)
// INTEGER 2 pos [tipo(4)] [valor_long]
// REAL 2 pos [tipo(4)] [valor_long (bits double)]
// BOOLEAN 1 pos [tipo(4)|val<<END_TYPE]
// STRING 1 pos [tipo(4)|len(28)<<LEN_PLAIN|start(32)<<START_STR]
//
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define SETFILE_NODE_IS_NOT_VALID_F (m_ctx == NULL)
#define SETFILE_NODE_IS_VALID (m_ctx != NULL)
//--- Avanza lo que ocupa una entrada completa (KEY+META+valor(es)) partiendo de la
// posicion del KEY. Asume estructura correcta (sin validar tipos).
#define SETFILE_ENTRY_STEP(idx) \
(2 + m_ctx.GetStep((idx) + 2) * (int(m_ctx.m_cinta[(idx) + 1] >> TSN_SETFILE_BIT_END_TYPE) != SETFILE_TOK_OP_TYPE_VAL ? 4 : 1))
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct CSetIteratorObj;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct CSetNode
{
CSetFileParser* const m_ctx;
int m_idx;
int m_end;
//---
CSetNode(void)
: m_ctx(NULL), m_idx(-1), m_end(-1) {}
CSetNode(CSetFileParser* _ctx, const int _idx, const int _end)
: m_ctx(_ctx), m_idx(_idx), m_end(_end) {}
//---
__forceinline bool IsJit() const;
__forceinline int AttempCount() const;
bool NodeHashing();
//---
CSetNode operator[](const string& key);
CSetNode AtObj(const int index) const; // acceso posicional a la entrada index del root
//--- Keys
string AtObjKey(const int index) const;
bool HasKey(const string& key) const;
int KeyToPosition(const string& key) const;
int GetKeys(string& out[]) const;
//--- Root
__forceinline int RootSize() const;
CSetIteratorObj BeginObj() const;
__forceinline bool InRange(const int index) const;
bool InRangeSafe(const int index) const;
//---
__forceinline ENUM_SETFILE_TOK_OP_TYPE OpType() const;
__forceinline bool IsOptimizable() const;
__forceinline bool IsEnabled() const;
bool SetEnabled(const bool val);
//--- Valor
CSetNode Value() const;
__forceinline ENUM_SETFILE_TOKENS GetType() const;
__forceinline uint GetFlag() const;
//-- To
long ToInt(const long def = 0) const;
double ToDouble(const double def = 0.0) const;
bool ToBool(const bool def = false) const;
string ToString(const string def = "") const;
//-- To safe
bool ToIntSafe(long& val) const;
bool ToDoubleSafe(double& val) const;
bool ToBoolSafe(bool& val) const;
//--- Rango (idx = META de la entrada, solo valido si IsOptimizable())
CSetNode Start() const;
CSetNode Step() const;
CSetNode Stop() const;
//--- Mutacion (in-place, solo mismo tipo)
bool SetInt(const long val);
bool SetDbl(const double val);
bool SetBool(const bool val);
//--- Validez
__forceinline bool IsValid() const;
__forceinline bool IsInvalid() const;
//---
bool MoveToNextToken();
CSetNode MoveNextPositions(const int posiciones);
bool MoveNextPositionsThis(const int posiciones);
};
//---
const CSetNode EMPTY_SET_NODE;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct CSetIteratorObj
{
CSetFileParser* const m_ctx;
int m_cur;
const int m_end;
//---
CSetIteratorObj(CSetFileParser* ctx, const int cur, const int end)
: m_ctx(ctx), m_cur(cur), m_end(end) {}
CSetIteratorObj(void)
: 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 += SETFILE_ENTRY_STEP(m_cur);
}
//---
string Key()
{
if(m_cur >= m_end)
return "";
const int start = int(m_ctx.m_cinta[m_cur] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_cur] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
return CharArrayToString(m_ctx.m_data, start, slen);
}
//---
CSetNode Val()
{
if(m_cur >= m_end)
return EMPTY_SET_NODE;
return CSetNode(m_ctx, m_cur + 1, m_end); // deja el nodo en META, igual que operator[]/AtObj
}
};
//---
const CSetIteratorObj EMPTY_SET_ITERATOR_OBJ;
//+------------------------------------------------------------------+
//| IsJit / AttempCount / NodeHashing |
//+------------------------------------------------------------------+
__forceinline bool CSetNode::IsJit() const
{
return SETFILE_NODE_IS_VALID && m_ctx.m_table_ready;
}
//+------------------------------------------------------------------+
__forceinline int CSetNode::AttempCount() const
{
return SETFILE_NODE_IS_NOT_VALID_F ? 0 : int(m_ctx.m_cinta[0] >> TSN_SETFILE_BIT_START_JIT_TRY);
}
//+------------------------------------------------------------------+
bool CSetNode::NodeHashing(void)
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F || m_idx != 0)
return false;
//---
const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & TSN_SETFILE_MASK_COUNT);
return m_ctx.NodeHashing(m_idx, count, m_end);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CSetNode CSetNode::operator[](const string &key)
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return EMPTY_SET_NODE;
//---
if(!m_ctx.m_table_ready)
{
//--- No esta hasheado, verificamos si ya toca intentar
int c = int(m_ctx.m_cinta[0] >> TSN_SETFILE_BIT_START_JIT_TRY);
if(c >= TSN_SETFILE_JIT_MIN_REF_TO_HASING)
{
if(NodeHashing())
{
//--- Ya hasheado, obtenemos posicion (del KEY) via hash perfecto
const int key_pos = m_ctx.PerfectHashComputeHash(key);
if(key_pos == -1)
return EMPTY_SET_NODE;
return CSetNode(m_ctx, key_pos + 1, m_end); // +1: de KEY a META
}
//--- Fallo el hasheo, reiniciamos el contador
c = 0;
}
else
{
c++;
}
const long mask = long(TSN_SETFILE_MASK_JIT_TRY) << TSN_SETFILE_BIT_START_JIT_TRY;
m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) | (long(c) << TSN_SETFILE_BIT_START_JIT_TRY);
//--- Lineal (siempre, este intento no se hasheo o fallo)
int cur = 1;
while(cur < m_end)
{
const int step = SETFILE_ENTRY_STEP(cur);
if(m_ctx.StrEquals(key, cur))
return CSetNode(m_ctx, cur + 1, m_end);
cur += step;
}
return EMPTY_SET_NODE;
}
//--- ya hasheado
const int key_pos = m_ctx.PerfectHashComputeHash(key);
if(key_pos == -1)
return EMPTY_SET_NODE;
return CSetNode(m_ctx, key_pos + 1, m_end);
}
//+------------------------------------------------------------------+
//| AtObj — acceso posicional a la entrada index del root |
//| (JIT: pos_arr[index] ya da la posicion del KEY directo) |
//+------------------------------------------------------------------+
CSetNode CSetNode::AtObj(const int index) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return EMPTY_SET_NODE;
//---
if(m_ctx.m_table_ready)
{
const int cur = m_ctx.m_table_pos_arr[index];
return CSetNode(m_ctx, cur + 1, m_end); // deja el nodo en META
}
//---
int cur = 1;
for(int k = 0; k < index; k++)
cur += SETFILE_ENTRY_STEP(cur);
return CSetNode(m_ctx, cur + 1, m_end); // deja el nodo en META, igual que operator[]
}
//+------------------------------------------------------------------+
//| AtObjKey — key de la entrada index del root |
//+------------------------------------------------------------------+
string CSetNode::AtObjKey(const int index) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return "";
//---
int cur = 0;
if(m_ctx.m_table_ready)
{
cur = m_ctx.m_table_pos_arr[index];
}
else
{
cur = 1;
for(int k = 0; k < index; k++)
cur += SETFILE_ENTRY_STEP(cur);
}
//---
const int start = int(m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
return CharArrayToString(m_ctx.m_data, start, slen);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CSetNode::HasKey(const string &key) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
if(m_ctx.m_table_ready)
return m_ctx.PerfectHashComputeHash(key) != -1;
//---
int cur = 1;
while(cur < m_ctx.m_cinta_pos)
{
if(m_ctx.StrEquals(key, cur))
return true;
cur += SETFILE_ENTRY_STEP(cur);
}
return false;
}
//+------------------------------------------------------------------+
//| KeyToPosition |
//+------------------------------------------------------------------+
int CSetNode::KeyToPosition(const string &key) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return -1;
//---
if(m_ctx.m_table_ready)
return m_ctx.PerfectHashComputeHashIndex(key);
//---
int cur = 1;
int k = 0;
while(cur < m_ctx.m_cinta_pos)
{
if(m_ctx.StrEquals(key, cur))
return k;
cur += SETFILE_ENTRY_STEP(cur);
k++;
}
return -1;
}
//+------------------------------------------------------------------+
//| GetKeys — con JIT usamos pos_arr (ya resuelto), sin recorrer |
//| calculando steps entrada por entrada. |
//+------------------------------------------------------------------+
int CSetNode::GetKeys(string &out[]) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return 0;
//---
if(m_ctx.m_table_ready)
{
const int count = m_ctx.m_table_size;
ArrayResize(out, count);
for(int i = 0; i < count; i++)
{
const int cur = m_ctx.m_table_pos_arr[i];
const int start = int(m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
out[i] = CharArrayToString(m_ctx.m_data, start, slen);
}
return count;
}
//---
const int count = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & TSN_SETFILE_MASK_COUNT);
ArrayResize(out, count);
//---
int i = 0;
int cur = 1; // en key
while(cur < m_ctx.m_cinta_pos)
{
const int start = int(m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[cur] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
out[i++] = CharArrayToString(m_ctx.m_data, start, slen);
cur += SETFILE_ENTRY_STEP(cur);
}
return count;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
__forceinline int CSetNode::RootSize() const
{
return SETFILE_NODE_IS_NOT_VALID_F || m_idx != 0 ? 0 : int((m_ctx.m_cinta[0] >> TSN_SETFILE_BIT_END_TYPE) & TSN_SETFILE_MASK_COUNT);
}
//+------------------------------------------------------------------+
__forceinline bool CSetNode::InRange(const int index) const
{
const int t = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & TSN_SETFILE_MASK_COUNT);
return index >= 0 && index < t;
}
//+------------------------------------------------------------------+
bool CSetNode::InRangeSafe(const int index) const
{
if(SETFILE_NODE_IS_NOT_VALID_F || m_idx != 0)
return false;
const int t = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & TSN_SETFILE_MASK_COUNT);
return index >= 0 && index < t;
}
//+------------------------------------------------------------------+
//| BeginObj |
//+------------------------------------------------------------------+
CSetIteratorObj CSetNode::BeginObj() const
{
if(SETFILE_NODE_IS_NOT_VALID_F || m_idx != 0)
return EMPTY_SET_ITERATOR_OBJ;
return CSetIteratorObj(m_ctx, 1, m_end);
}
//+------------------------------------------------------------------+
//| OpType / IsOptimizable / IsEnabled — leen el META |
//+------------------------------------------------------------------+
__forceinline ENUM_SETFILE_TOK_OP_TYPE CSetNode::OpType() const
{
return ENUM_SETFILE_TOK_OP_TYPE(int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE));
}
//+------------------------------------------------------------------+
__forceinline bool CSetNode::IsOptimizable() const
{
return int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) != SETFILE_TOK_OP_TYPE_VAL;
}
//+------------------------------------------------------------------+
__forceinline bool CSetNode::IsEnabled() const
{
return int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) == SETFILE_TOK_OP_TYPE_Y;
}
//+------------------------------------------------------------------+
//| SetEnabled — togglea Y/N en los bits altos del META |
//+------------------------------------------------------------------+
bool CSetNode::SetEnabled(const bool val)
{
if(SETFILE_NODE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & 0xf) != SETFILE_TOK_META)
return false;
//---
const long mask = long(0x3) << TSN_SETFILE_BIT_END_TYPE;
m_ctx.m_cinta[m_idx] = (m_ctx.m_cinta[m_idx] & ~mask) |
(long(val ? SETFILE_TOK_OP_TYPE_Y : SETFILE_TOK_OP_TYPE_N) << TSN_SETFILE_BIT_END_TYPE);
return true;
}
//+------------------------------------------------------------------+
//| Value — nodo del primer valor (idx+2 respecto al KEY) |
//+------------------------------------------------------------------+
CSetNode CSetNode::Value() const
{
if(SETFILE_NODE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & 0xf) != SETFILE_TOK_META)
return EMPTY_SET_NODE;
//---
const int pos = m_idx + 1;
return CSetNode(m_ctx, pos, pos + m_ctx.GetStep(pos));
}
//+------------------------------------------------------------------+
__forceinline ENUM_SETFILE_TOKENS CSetNode::GetType() const
{
return ENUM_SETFILE_TOKENS(m_ctx.m_cinta[m_idx] & 0xF);
}
//+------------------------------------------------------------------+
__forceinline uint CSetNode::GetFlag() const
{
return 1 << uint(m_ctx.m_cinta[m_idx] & 0xF);
}
//+------------------------------------------------------------------+
//| Start / Step / Stop — mismo step que Value(), offsets +1/+2/+3 |
//+------------------------------------------------------------------+
CSetNode CSetNode::Start() const
{
if(SETFILE_NODE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & 0xf) != SETFILE_TOK_META)
return EMPTY_SET_NODE;
//---
const int val_pos = m_idx + 1;
const int step = m_ctx.GetStep(val_pos);
const int pos = val_pos + step;
return CSetNode(m_ctx, pos, pos + step);
}
//+------------------------------------------------------------------+
CSetNode CSetNode::Step() const
{
if(SETFILE_NODE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & 0xf) != SETFILE_TOK_META)
return EMPTY_SET_NODE;
//---
const int val_pos = m_idx + 1;
const int step = m_ctx.GetStep(val_pos);
const int pos = val_pos + step * 2;
return CSetNode(m_ctx, pos, pos + step);
}
//+------------------------------------------------------------------+
CSetNode CSetNode::Stop() const
{
if(SETFILE_NODE_IS_NOT_VALID_F || (m_ctx.m_cinta[m_idx] & 0xf) != SETFILE_TOK_META)
return EMPTY_SET_NODE;
//---
const int val_pos = m_idx + 1;
const int step = m_ctx.GetStep(val_pos);
const int pos = val_pos + step * 3;
return CSetNode(m_ctx, pos, pos + step);
}
//+------------------------------------------------------------------+
//| ToInt |
//+------------------------------------------------------------------+
long CSetNode::ToInt(const long def = 0) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return def;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
return m_ctx.m_cinta[m_idx + 1];
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
return long(un.double_value);
}
case SETFILE_TOK_BOOLEAN:
return long((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1);
case SETFILE_TOK_STRING:
{
const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
return long(CharArrayToString(m_ctx.m_data, start, slen));
}
}
return def;
}
//+------------------------------------------------------------------+
bool CSetNode::ToIntSafe(long &val) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
val = m_ctx.m_cinta[m_idx + 1];
return true;
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
val = long(un.double_value);
return true;
}
case SETFILE_TOK_BOOLEAN:
val = long((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1);
return true;
case SETFILE_TOK_STRING:
{
const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
val = long(CharArrayToString(m_ctx.m_data, start, slen));
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| ToDouble |
//+------------------------------------------------------------------+
double CSetNode::ToDouble(const double def = 0.0) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return def;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
return double(m_ctx.m_cinta[m_idx + 1]);
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
return un.double_value;
}
case SETFILE_TOK_BOOLEAN:
return double((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1);
case SETFILE_TOK_STRING:
{
const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
return double(CharArrayToString(m_ctx.m_data, start, slen));
}
}
return def;
}
//+------------------------------------------------------------------+
bool CSetNode::ToDoubleSafe(double &val) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
val = double(m_ctx.m_cinta[m_idx + 1]);
return true;
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
val = un.double_value;
return true;
}
case SETFILE_TOK_BOOLEAN:
val = double((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1);
return true;
case SETFILE_TOK_STRING:
{
const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
val = double(CharArrayToString(m_ctx.m_data, start, slen));
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| ToBool |
//+------------------------------------------------------------------+
bool CSetNode::ToBool(const bool def = false) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return def;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
return m_ctx.m_cinta[m_idx + 1] != 0;
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
return un.double_value != 0.0;
}
case SETFILE_TOK_BOOLEAN:
return ((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1) != 0;
}
return def;
}
//+------------------------------------------------------------------+
bool CSetNode::ToBoolSafe(bool &val) const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
val = m_ctx.m_cinta[m_idx + 1] != 0;
return true;
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
val = un.double_value != 0.0;
return true;
}
case SETFILE_TOK_BOOLEAN:
val = ((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1) != 0;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| ToString — sin unescape, los valores de .set no llevan escapes |
//+------------------------------------------------------------------+
string CSetNode::ToString(const string def = "") const
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return def;
//---
switch(int(m_ctx.m_cinta[m_idx] & 0xF))
{
case SETFILE_TOK_INTEGER:
return string(m_ctx.m_cinta[m_idx + 1]);
case SETFILE_TOK_REAL:
{
static BitInterpreter un;
un.long_value = m_ctx.m_cinta[m_idx + 1];
return string(un.double_value);
}
case SETFILE_TOK_BOOLEAN:
return ((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_END_TYPE) & 1) != 0 ? "true" : "false";
case SETFILE_TOK_STRING:
{
const int start = int(m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_STR);
const int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SETFILE_BIT_START_LEN_PLAIN) & 0xFFFFFFF);
return CharArrayToString(m_ctx.m_data, start, slen);
}
}
return def;
}
//+------------------------------------------------------------------+
//| SetInt |
//+------------------------------------------------------------------+
bool CSetNode::SetInt(const long val)
{
if(SETFILE_NODE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & 0xF) != SETFILE_TOK_INTEGER)
return false;
//---
m_ctx.m_cinta[m_idx + 1] = val;
return true;
}
//+------------------------------------------------------------------+
//| SetDbl |
//+------------------------------------------------------------------+
bool CSetNode::SetDbl(const double val)
{
if(SETFILE_NODE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & 0xF) != SETFILE_TOK_REAL)
return false;
//---
static BitInterpreter un;
un.double_value = val;
m_ctx.m_cinta[m_idx + 1] = un.long_value;
return true;
}
//+------------------------------------------------------------------+
//| SetBool |
//+------------------------------------------------------------------+
bool CSetNode::SetBool(const bool val)
{
if(SETFILE_NODE_IS_NOT_VALID_F || int(m_ctx.m_cinta[m_idx] & 0xF) != SETFILE_TOK_BOOLEAN)
return false;
//---
m_ctx.m_cinta[m_idx] = SETFILE_TOK_BOOLEAN | long(val) << TSN_SETFILE_BIT_END_TYPE;
return true;
}
//+------------------------------------------------------------------+
//| Is |
//+------------------------------------------------------------------+
__forceinline bool CSetNode::IsValid() const { return m_ctx != NULL && m_idx >= 0 && m_end >= 0; }
__forceinline bool CSetNode::IsInvalid() const { return m_ctx == NULL || m_idx < 0 || m_end < 0; }
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CSetNode::MoveToNextToken()
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
const int next_end = m_idx + m_ctx.GetStep(m_idx);
if(next_end >= m_end)
return false;
//---
m_idx = next_end;
return true;
}
//+------------------------------------------------------------------+
CSetNode CSetNode::MoveNextPositions(const int posiciones)
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return EMPTY_SET_NODE;
//---
const int next_pos = m_idx + posiciones;
if(next_pos >= m_end)
return EMPTY_SET_NODE;
//---
return CSetNode(m_ctx, next_pos, m_end);
}
//+------------------------------------------------------------------+
bool CSetNode::MoveNextPositionsThis(const int posiciones)
{
//---
if(SETFILE_NODE_IS_NOT_VALID_F)
return false;
//---
const int next_pos = m_idx + posiciones;
if(next_pos >= m_end)
return false;
//---
m_idx = next_pos;
return true;
}
//+------------------------------------------------------------------+
CSetNode CSetFileParser::GetRoot()
{
if(m_cinta_pos == 0)
return EMPTY_SET_NODE;
return CSetNode(&this, 0, m_cinta_pos);
}
}
//+------------------------------------------------------------------+
#endif // SETFILEBYLEO_SRC_NODE_MQH