YamlParserByLeo/Src/YmlNode.mqh

1041 lines
28 KiB
MQL5
Raw Permalink Normal View History

2026-04-03 22:37:29 -05:00
//+------------------------------------------------------------------+
2026-04-03 22:17:13 -05:00
//| CYmlNode.mqh |
2026-04-03 21:12:36 -05:00
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Niquel Mendoza."
#property link "https://www.mql5.com/es/users/nique_372"
#property strict
2026-04-04 20:27:55 -05:00
#ifndef YMLPARSERBYLEO_SRC_YMLNODE_MQH
#define YMLPARSERBYLEO_SRC_YMLNODE_MQH
2026-04-03 21:12:36 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "YmlParser.mqh"
2026-04-04 08:07:02 -05:00
2026-04-03 21:12:36 -05:00
// KEY 2 pos [tipo|scape|hash][start<<32|end]
// STR 2 pos [tipo|scape][start<<32|end]
// STR_MULTI 2 pos [tipo|ident|saltos][start<<32|end]
// INTEGER 2 pos [tipo][valor_long]
// DBL 2 pos [tipo][valor_long (bits del double)]
// BOOL 1 pos [tipo|valor]
// NULL 1 pos [tipo]
// ARR 1 pos [tipo|count|closing_pos] (elementos siguen inmediatamente)
// OBJ 1 pos [tipo|count|closing_pos] (key+val siguen inmediatamente)
// ---
// REF_CREATE 1 pos [tipo|closing_pos] (sigue NAME 2pos + valor) (puede ser simple o compleja pero ocupa mismos dos pos)
// NAME 1 pos [start<<32|end] (nombre del anchor, siempre tras REF_CREATE)
// ---
// PTR 1 pos [tipo|pos_ref_create] (apunta a REF_CREATE)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-04 16:19:18 -05:00
#define YML_NODE_IS_NOT_VALID (m_ctx==NULL || m_idx == -1 || m_end == -1)
2026-04-05 11:18:49 -05:00
struct CYmlIteratorArray;
struct CYmlIteratorObj;
2026-04-04 20:03:17 -05:00
//---
#define YML_RESOLVE_PTR(ctx, idx) ((int(ctx.m_cinta[idx] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_PTR) ? (int(ctx.m_cinta[idx] >> YMLPARSER_BIT_END_TYPE) + 2) : (idx))
2026-04-03 22:17:13 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct CYmlNode
2026-04-03 21:12:36 -05:00
{
2026-04-03 22:17:13 -05:00
public:
2026-04-03 21:12:36 -05:00
//---
2026-04-04 16:19:18 -05:00
CYmlParser* m_ctx;
2026-04-05 15:04:14 -05:00
int m_idx;
int m_end;
2026-04-03 21:12:36 -05:00
//---
2026-04-03 22:17:13 -05:00
CYmlNode()
2026-04-04 16:19:18 -05:00
: m_ctx(NULL), m_idx(-1), m_end(-1) {}
2026-04-03 22:17:13 -05:00
//---
CYmlNode(CYmlParser* _ctx, int _idx, int _end)
2026-04-04 16:19:18 -05:00
: m_ctx(_ctx), m_idx(_idx), m_end(_end) {}
2026-04-03 21:12:36 -05:00
2026-04-03 22:37:29 -05:00
//--- Operators
2026-04-05 15:04:14 -05:00
CYmlNode operator[](const string& key) const;
CYmlNode At(const int index) const;
CYmlNode AtHomegeneo(const int index) const;
2026-04-03 22:37:29 -05:00
//--- To
2026-04-04 08:07:02 -05:00
// String
2026-04-05 15:04:14 -05:00
string ToString(string def = "") const;
2026-04-04 08:07:02 -05:00
// Int
2026-04-05 15:04:14 -05:00
long ToInt(long def) const;
bool ToIntSafe(long &val) const; // Version bool\true (si se pudo obtener)
2026-04-04 08:07:02 -05:00
// Dbl
2026-04-05 15:04:14 -05:00
double ToDouble(double def) const;
bool ToDoubleSafe(double &val) const; // Version bool\true (si se pudo obtener)
2026-04-04 08:07:02 -05:00
// Bool
2026-04-05 15:04:14 -05:00
__forceinline bool ToBool(bool def) const;
bool ToBoolSafe(bool& val) const; // Version bool\true (si se pudo obtener)
2026-04-03 22:37:29 -05:00
2026-04-06 07:49:32 -05:00
//--- Set
bool SetDbl(const double val);
bool SetInt(const long val);
bool SetBool(const bool val);
2026-04-04 20:03:17 -05:00
//--- Type
2026-04-05 15:04:14 -05:00
__forceinline ENUM_YML_CLASIFIER_TYPE_VAL GetType() const { return ENUM_YML_CLASIFIER_TYPE_VAL(m_ctx.m_cinta[m_idx] & 0xF); }
ENUM_DATATYPE GetTypeAsDataType(ENUM_DATATYPE def) const;
bool AssingMqlParam(MqlParam& param) const;
2026-04-04 20:03:17 -05:00
//--- Is
__forceinline bool IsValid() const;
__forceinline bool IsNull() const;
__forceinline bool IsArray() const;
__forceinline bool IsObject() const;
2026-04-05 11:18:49 -05:00
//--- Iterador
CYmlIteratorArray BeginArr() const;
CYmlIteratorObj BeginObj() const;
2026-04-04 20:03:17 -05:00
2026-04-06 07:33:39 -05:00
//--- Obtencion de key
// Esto solo aplica para los obejtos o blouqes (key:vak) donde val es homogeneo en todos (ocupa las miams posicons de cinta)
string AtObjKeyHomgenero(const int index) const;
// Obtinee key val=cualquiera
string AtObjKey(const int index) const;
2026-04-04 20:03:17 -05:00
//--- Size (arr o objeto)
2026-04-05 15:04:14 -05:00
int Size() const;
2026-04-05 11:18:49 -05:00
//---
2026-04-05 15:04:14 -05:00
// solo_en_el_bloque_actual= solo te permite moverte en el bloque acutal (ejemplo si estas en un objeto)
// Si el nueva posicion empeiza fuera de ese bloque entonces false, si quieres moveremtne libremente usa el parametro
// solo_en_el_bloque_actual = false
bool MoveToNextToken(bool solo_en_el_bloque_actual = true);
2026-04-06 09:56:37 -05:00
//---
// No safe
// Retorna el nodo a "posiciones" del m_idx actual
CYmlNode MoveNextPositions(int posiciones, bool solo_en_el_bloque_actual = true);
// Este muta el objeto actual no retorna
bool MoveNextPositionsThis(int posiciones, bool solo_en_el_bloque_actual = true);
2026-04-03 22:17:13 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
const CYmlNode EMPTY_YMLNODE;
2026-04-04 20:03:17 -05:00
2026-04-03 22:17:13 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
CYmlNode CYmlNode::operator[](const string& key) const
2026-04-03 22:17:13 -05:00
{
2026-04-04 20:03:17 -05:00
//---
2026-04-03 22:17:13 -05:00
if(YML_NODE_IS_NOT_VALID)
return EMPTY_YMLNODE;
2026-04-04 20:03:17 -05:00
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-03 22:17:13 -05:00
2026-04-04 20:03:17 -05:00
//---
const int tipo = int(m_ctx.m_cinta[i] & 0xF);
if(tipo != YML_CLASIFIER_TOKEN_TYPE_OBJ && tipo != YML_CLASIFIER_TOKEN_TYPE_REFERENCE_COMPLEX)
return EMPTY_YMLNODE;
//---
2026-04-03 22:17:13 -05:00
const int len = StringLen(key);
2026-04-04 20:03:17 -05:00
uint hash = 2166136261;
for(int k = 0; k < len; k++)
2026-04-03 21:12:36 -05:00
{
2026-04-04 20:03:17 -05:00
hash ^= (uint)key[k];
hash *= 16777619;
2026-04-03 22:17:13 -05:00
}
2026-04-03 21:12:36 -05:00
2026-04-03 22:17:13 -05:00
//---
2026-04-04 20:03:17 -05:00
int cur = i + 1; // salta header OBJ
2026-04-04 16:19:18 -05:00
while(cur < m_end)
2026-04-03 22:17:13 -05:00
{
2026-04-04 16:19:18 -05:00
if((m_ctx.m_cinta[cur] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_KEY)
2026-04-03 22:17:13 -05:00
{
2026-04-04 16:19:18 -05:00
cur += m_ctx.GetStep(cur);
2026-04-03 22:17:13 -05:00
continue;
}
2026-04-04 16:19:18 -05:00
if(hash == uint(m_ctx.m_cinta[cur] >> YMLPARSER_KEY_BIT_INIT_HASH))
2026-04-03 22:17:13 -05:00
{
2026-04-04 20:03:17 -05:00
const int next_pos = cur + 2;
2026-04-04 16:19:18 -05:00
const int final_pos = next_pos + m_ctx.GetStep(next_pos);
2026-04-04 20:03:17 -05:00
return CYmlNode(m_ctx, next_pos, final_pos);
2026-04-03 22:17:13 -05:00
}
cur += 2;
2026-04-04 16:19:18 -05:00
cur += m_ctx.GetStep(cur);
2026-04-03 21:12:36 -05:00
}
2026-04-04 20:03:17 -05:00
return EMPTY_YMLNODE;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
CYmlNode CYmlNode::At(const int index) const
2026-04-04 20:03:17 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return EMPTY_YMLNODE;
2026-04-03 21:12:36 -05:00
2026-04-03 22:17:13 -05:00
//---
2026-04-04 20:03:17 -05:00
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
if(int(m_ctx.m_cinta[i] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_ARR)
return EMPTY_YMLNODE;
//---
const int count = int((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 0xFFFFFFF);
if(index < 0 || index >= count)
return EMPTY_YMLNODE;
//---
int cur = i + 1; // primer elemento
for(int k = 0; k < index; k++)
cur += m_ctx.GetStep(cur);
//---
const int final_pos = cur + m_ctx.GetStep(cur);
return CYmlNode(m_ctx, cur, final_pos);
}
2026-04-06 07:33:39 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// At, para bloques implicitos
// ejemplo
// - valor : 10
// numeros: 10
// [obj][key][key][val][val][obj][key][key][val][val]
string CYmlNode::AtObjKey(const int index) const
{
if(YML_NODE_IS_NOT_VALID)
return "";
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
if(int(m_ctx.m_cinta[i] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_OBJ)
return "";
//---
const int count = int((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 0xFFFFFFF);
if(index < 0 || index >= count)
return "";
//---
int cur = i + 1; // primer elemento
for(int k = 0; k < index; k++)
{
cur += 2;
cur += m_ctx.GetStep(cur);
}
cur += 1; // Ahora mismo nos ubicamos en la poscion del iniico de key avanzamos a la info
//---
const int start = int(m_ctx.m_cinta[cur] >> 32);
const int end = int(m_ctx.m_cinta[cur] & 0xFFFFFFFF);
//---
return ShortArrayToString(m_ctx.m_yml, start, (end - start) + 1);
}
//+------------------------------------------------------------------+
string CYmlNode::AtObjKeyHomgenero(const int index) const
{
if(YML_NODE_IS_NOT_VALID)
return "";
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
if(int(m_ctx.m_cinta[i] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_OBJ)
return "";
//---
const int count = int((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 0xFFFFFFF);
if(index < 0 || index >= count)
return "";
//---
// [obj][key][key][val][val][key][key][val][val][key][key]
// i = primer elemtno (en este caso key)
// i+3 = primer val
const int cur = ((i + 1) + (index * (2 + m_ctx.GetStep(i + 3)))) + 1;
//---
const int start = int(m_ctx.m_cinta[cur] >> 32);
const int end = int(m_ctx.m_cinta[cur] & 0xFFFFFFFF);
//---
return ShortArrayToString(m_ctx.m_yml, start, (end - start) + 1);
}
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
CYmlNode CYmlNode::AtHomegeneo(const int index) const
2026-04-04 20:03:17 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return EMPTY_YMLNODE;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
if(int(m_ctx.m_cinta[i] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_ARR)
return EMPTY_YMLNODE;
//---
const int count = int((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 0xFFFFFFF);
if(index < 0 || index >= count)
return EMPTY_YMLNODE;
//---
// step fijo del primer elemento
const int first = i + 1;
const int step = m_ctx.GetStep(first);
const int cur = first + index * step;
return CYmlNode(m_ctx, cur, cur + step);
2026-04-03 22:17:13 -05:00
}
2026-04-06 07:33:39 -05:00
// [obj=type arr][obj_implicito=obj][key][key][val][val][obj_implicito=obj][key][key][val][val]
2026-04-03 21:12:36 -05:00
//+------------------------------------------------------------------+
2026-04-06 09:56:37 -05:00
//| Operaciones de bajo nivel mover la cinta custom |
2026-04-03 22:37:29 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::MoveToNextToken(bool solo_en_el_bloque_actual = true)
2026-04-05 11:18:49 -05:00
{
2026-04-05 15:04:14 -05:00
if(YML_NODE_IS_NOT_VALID)
return false;
//--- Nuevas posiciones
const int next_pos = m_idx + m_ctx.GetStep(m_idx); // usa GetStep, no hardcodea 2
2026-04-05 11:18:49 -05:00
const int final_pos = next_pos + m_ctx.GetStep(next_pos);
2026-04-05 15:04:14 -05:00
//--- Check
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;
return true;
2026-04-05 11:18:49 -05:00
}
2026-04-06 09:56:37 -05:00
//+------------------------------------------------------------------+
bool CYmlNode::MoveNextPositionsThis(int posiciones, bool solo_en_el_bloque_actual = true)
{
if(YML_NODE_IS_NOT_VALID)
return false;
//--- Nuevas posiciones
const int next_pos = m_idx + posiciones; // usa GetStep, no hardcodea 2
// si solo nos movemos en el bloque actual el end sera el actual del bloque actual (si es que tamos)
// si no si es libre enotnfes al siguiente token
const int final_pos = solo_en_el_bloque_actual ? m_end : next_pos + m_ctx.GetStep(next_pos);
//--- Check
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;
//---
return true;
}
//+------------------------------------------------------------------+
CYmlNode CYmlNode::MoveNextPositions(int posiciones, bool solo_en_el_bloque_actual = true)
{
if(YML_NODE_IS_NOT_VALID)
return EMPTY_YMLNODE;
//--- Nuevas posiciones
const int next_pos = m_idx + posiciones; // usa GetStep, no hardcodea 2
const int final_pos = solo_en_el_bloque_actual ? m_end : next_pos + m_ctx.GetStep(next_pos);
//--- Check
if(next_pos >= (solo_en_el_bloque_actual ? m_end : m_ctx.m_cinta_pos))
return EMPTY_YMLNODE;
//---
return CYmlNode(m_ctx, next_pos, final_pos);
}
2026-04-05 11:18:49 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::AssingMqlParam(MqlParam& param) const
2026-04-05 11:18:49 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int new_index = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
switch(int(m_ctx.m_cinta[new_index] & 0xF))
{
//---
case YML_CLASIFIER_TOKEN_TYPE_KEY:
return false;
//---
case YML_CLASIFIER_TOKEN_TYPE_STR:
{
param.type = TYPE_STRING;
param.string_value = ToString("");
2026-04-06 07:33:39 -05:00
return param.string_value != "";
2026-04-05 11:18:49 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
{
param.type = TYPE_LONG;
2026-04-06 07:33:39 -05:00
return ToIntSafe(param.integer_value);
2026-04-05 11:18:49 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
param.type = TYPE_DOUBLE;
2026-04-06 07:33:39 -05:00
return ToDoubleSafe(param.double_value);
2026-04-05 11:18:49 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
{
param.type = TYPE_BOOL;
bool temp;
2026-04-05 15:04:14 -05:00
if(!ToBoolSafe(temp))
2026-04-05 11:18:49 -05:00
return false;
param.integer_value = temp;
return true;
}
//---
case YML_CLASIFIER_TOKEN_TYPE_NULL:
return false;
//---
case YML_CLASIFIER_TOKEN_TYPE_STR_MULTILINE:
{
param.type = TYPE_STRING;
param.string_value = ToString("");
2026-04-06 07:33:39 -05:00
return param.string_value != "";
2026-04-05 11:18:49 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_ARR:
case YML_CLASIFIER_TOKEN_TYPE_OBJ:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_SIMPLE:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_COMPLEX:
case YML_CLASIFIER_TOKEN_TYPE_PTR:
return false;
}
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
ENUM_DATATYPE CYmlNode::GetTypeAsDataType(ENUM_DATATYPE def) const
2026-04-05 11:18:49 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return def;
//---
const int new_index = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
switch(int(m_ctx.m_cinta[new_index] & 0xF))
{
//---
case YML_CLASIFIER_TOKEN_TYPE_KEY:
return def;
//---
case YML_CLASIFIER_TOKEN_TYPE_STR:
return TYPE_STRING;
//---
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
return TYPE_LONG;
//---
case YML_CLASIFIER_TOKEN_TYPE_DBL:
return TYPE_DOUBLE;
//---
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
return TYPE_BOOL;
//---
case YML_CLASIFIER_TOKEN_TYPE_NULL:
return def;
//---
case YML_CLASIFIER_TOKEN_TYPE_STR_MULTILINE:
return TYPE_STRING;
//---
case YML_CLASIFIER_TOKEN_TYPE_ARR:
case YML_CLASIFIER_TOKEN_TYPE_OBJ:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_SIMPLE:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_COMPLEX:
case YML_CLASIFIER_TOKEN_TYPE_PTR:
return def;
}
//---
return def;
}
//+------------------------------------------------------------------+
//| To String |
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
string CYmlNode::ToString(string def = "") const
2026-04-03 22:37:29 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return def;
//---
2026-04-04 20:03:17 -05:00
const int new_index = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-04 16:19:18 -05:00
//---
switch(int(m_ctx.m_cinta[new_index] & 0xF))
2026-04-03 22:37:29 -05:00
{
//---
case YML_CLASIFIER_TOKEN_TYPE_KEY:
return def;
//---
case YML_CLASIFIER_TOKEN_TYPE_STR:
{
2026-04-04 16:19:18 -05:00
const int start = (int)(m_ctx.m_cinta[new_index + 1] >> 32);
const int end = (int)(m_ctx.m_cinta[new_index + 1] & 0xFFFFFFFF);
2026-04-06 09:56:37 -05:00
const bool scape = (bool)((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 1);
2026-04-03 22:37:29 -05:00
if(scape)
2026-04-04 16:19:18 -05:00
return m_ctx.Unescape(start, end);
2026-04-03 22:37:29 -05:00
2026-04-04 16:19:18 -05:00
return ShortArrayToString(m_ctx.m_yml, start, (end - start) + 1); // raw directo
2026-04-03 22:37:29 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
2026-04-04 16:19:18 -05:00
return string(m_ctx.m_cinta[new_index + 1]);
2026-04-03 22:37:29 -05:00
//---
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
2026-04-04 16:19:18 -05:00
un.l = m_ctx.m_cinta[new_index + 1];
2026-04-03 22:37:29 -05:00
return string(un.d);
}
//---
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
2026-04-04 16:19:18 -05:00
return ((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 1) != 0 ? "true" : "false";
2026-04-03 22:37:29 -05:00
//---
case YML_CLASIFIER_TOKEN_TYPE_NULL:
2026-04-04 08:07:02 -05:00
return def;
2026-04-03 22:37:29 -05:00
//---
case YML_CLASIFIER_TOKEN_TYPE_STR_MULTILINE:
{
2026-04-05 22:25:16 -05:00
const int start = int(m_ctx.m_cinta[new_index + 1] >> 32);
2026-04-04 16:19:18 -05:00
const int end = int(m_ctx.m_cinta[new_index + 1] & 0xFFFFFFFF);
2026-04-05 22:25:16 -05:00
const int ident = int((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 0xFFFF);
2026-04-04 16:19:18 -05:00
bool con_saltos = bool((m_ctx.m_cinta[new_index] >> 32) & 1);
2026-04-03 22:37:29 -05:00
//---
2026-04-04 16:19:18 -05:00
return m_ctx.ExtractMultiline(start, end, ident, con_saltos);
2026-04-03 22:37:29 -05:00
}
//---
case YML_CLASIFIER_TOKEN_TYPE_ARR:
case YML_CLASIFIER_TOKEN_TYPE_OBJ:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_SIMPLE:
case YML_CLASIFIER_TOKEN_TYPE_REFERENCE_COMPLEX:
case YML_CLASIFIER_TOKEN_TYPE_PTR:
return def;
}
//---
return def;
}
2026-04-04 08:07:02 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
//| To int |
2026-04-04 08:07:02 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
long CYmlNode::ToInt(long def) const
2026-04-04 08:07:02 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return def;
2026-04-04 20:03:17 -05:00
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-04 16:19:18 -05:00
2026-04-04 20:03:17 -05:00
//---
2026-04-04 16:19:18 -05:00
switch(int(m_ctx.m_cinta[i] & 0xF))
2026-04-04 08:07:02 -05:00
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
2026-04-04 16:19:18 -05:00
return m_ctx.m_cinta[i + 1];
2026-04-04 08:07:02 -05:00
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
2026-04-04 16:19:18 -05:00
un.l = m_ctx.m_cinta[i + 1];
return long(un.d);
2026-04-04 08:07:02 -05:00
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
2026-04-04 16:19:18 -05:00
return long((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1);
2026-04-04 08:07:02 -05:00
}
2026-04-04 20:03:17 -05:00
//---
return def;
2026-04-04 08:07:02 -05:00
}
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::ToIntSafe(long &val) const
2026-04-05 11:18:49 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
switch(int(m_ctx.m_cinta[i] & 0xF))
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
{
val = m_ctx.m_cinta[i + 1];;
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
un.l = m_ctx.m_cinta[i + 1];
val = long(un.d);
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
val = long((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1);
return true;
}
//---
return false;
}
//+------------------------------------------------------------------+
//| To Double |
2026-04-04 08:07:02 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
double CYmlNode::ToDouble(double def) const
2026-04-04 08:07:02 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return def;
2026-04-04 16:19:18 -05:00
//---
2026-04-04 20:03:17 -05:00
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-04 16:19:18 -05:00
//---
switch(int(m_ctx.m_cinta[i] & 0xF))
2026-04-04 08:07:02 -05:00
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
2026-04-04 16:19:18 -05:00
return double(m_ctx.m_cinta[i + 1]);
2026-04-04 08:07:02 -05:00
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
2026-04-04 16:19:18 -05:00
un.l = m_ctx.m_cinta[i + 1];
2026-04-04 08:07:02 -05:00
return un.d;
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
2026-04-04 16:19:18 -05:00
return double((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1);
2026-04-04 08:07:02 -05:00
}
2026-04-04 16:19:18 -05:00
//---
2026-04-04 08:07:02 -05:00
return def;
}
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::ToDoubleSafe(double &val) const
2026-04-05 11:18:49 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
switch(int(m_ctx.m_cinta[i] & 0xF))
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
{
val = double(m_ctx.m_cinta[i + 1]);
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
un.l = m_ctx.m_cinta[i + 1];
val = un.d;
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
{
val = double((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1);
return true;
}
}
//---
return false;
}
//+------------------------------------------------------------------+
//| To Bool |
2026-04-04 08:07:02 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::ToBool(bool def) const
2026-04-04 08:07:02 -05:00
{
2026-04-04 16:19:18 -05:00
if(YML_NODE_IS_NOT_VALID)
return def;
//---
2026-04-04 20:03:17 -05:00
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-04 16:19:18 -05:00
//---
switch(int(m_ctx.m_cinta[i] & 0xF))
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
return m_ctx.m_cinta[i + 1] != 0;
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
un.l = m_ctx.m_cinta[i + 1];
return un.d != 0.0;
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
return ((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1) != 0;
}
//---
return def;
2026-04-04 08:07:02 -05:00
}
2026-04-05 11:18:49 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
bool CYmlNode::ToBoolSafe(bool &val) const
2026-04-05 11:18:49 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
switch(int(m_ctx.m_cinta[i] & 0xF))
{
case YML_CLASIFIER_TOKEN_TYPE_INTEGER:
{
val = m_ctx.m_cinta[i + 1] != 0;
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_DBL:
{
CYmlParser::LongToDbl un;
un.l = m_ctx.m_cinta[i + 1];
val = un.d != 0.0;
return true;
}
case YML_CLASIFIER_TOKEN_TYPE_BOOL:
{
val = ((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1) != 0;
return true;
}
}
//---
return false;
}
2026-04-04 08:07:02 -05:00
//+------------------------------------------------------------------+
//| |
2026-04-03 22:37:29 -05:00
//+------------------------------------------------------------------+
2026-04-05 15:04:14 -05:00
int CYmlNode::Size() const
2026-04-04 16:19:18 -05:00
{
if(YML_NODE_IS_NOT_VALID)
return 0;
//---
2026-04-04 20:03:17 -05:00
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-04 16:19:18 -05:00
//---
const int tipo = int(m_ctx.m_cinta[i] & 0xF);
if(tipo != YML_CLASIFIER_TOKEN_TYPE_ARR && tipo != YML_CLASIFIER_TOKEN_TYPE_OBJ)
return 0;
//---
return int((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 0xFFFFFFF);
}
2026-04-04 20:03:17 -05:00
2026-04-05 11:18:49 -05:00
//+------------------------------------------------------------------+
//| Is |
//+------------------------------------------------------------------+
__forceinline bool CYmlNode::IsValid() const { return !YML_NODE_IS_NOT_VALID; }
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
__forceinline bool CYmlNode::IsNull() const
{
if(YML_NODE_IS_NOT_VALID)
return true;
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
return int(m_ctx.m_cinta[i] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_NULL;
}
//+------------------------------------------------------------------+
__forceinline bool CYmlNode::IsArray() const
{
if(YML_NODE_IS_NOT_VALID)
return false;
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
return int(m_ctx.m_cinta[i] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_ARR;
}
//+------------------------------------------------------------------+
__forceinline bool CYmlNode::IsObject() const
{
if(YML_NODE_IS_NOT_VALID)
return false;
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
const int t = int(m_ctx.m_cinta[i] & 0xF);
return t == YML_CLASIFIER_TOKEN_TYPE_OBJ || t == YML_CLASIFIER_TOKEN_TYPE_REFERENCE_COMPLEX;
}
2026-04-06 07:49:32 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CYmlNode::SetBool(const bool val)
{
//---
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
if(int(m_ctx.m_cinta[i] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_BOOL)
{
m_ctx.m_cinta[i] = YML_CLASIFIER_TOKEN_TYPE_BOOL | (long(val) << YMLPARSER_BIT_END_TYPE);
return true;
}
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CYmlNode::SetInt(const long val)
{
//---
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
if(int(m_ctx.m_cinta[i] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_INTEGER)
{
m_ctx.m_cinta[i + 1] = val;
return true;
}
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CYmlNode::SetDbl(const double val)
{
//---
if(YML_NODE_IS_NOT_VALID)
return false;
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
if(int(m_ctx.m_cinta[i] & 0xF) == YML_CLASIFIER_TOKEN_TYPE_DBL)
{
CYmlParser::LongToDbl un;
un.d = val;
2026-04-06 09:56:37 -05:00
2026-04-06 07:49:32 -05:00
m_ctx.m_cinta[i + 1] = un.l;
return true;
}
//---
return false;
}
2026-04-05 11:18:49 -05:00
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
//| Iterador de arrays |
//+------------------------------------------------------------------+
struct CYmlIteratorObj
2026-04-04 20:03:17 -05:00
{
CYmlParser* m_ctx;
int m_cur;
const int m_end;
2026-04-05 11:18:49 -05:00
2026-04-04 20:03:17 -05:00
//---
2026-04-05 11:18:49 -05:00
CYmlIteratorObj(CYmlParser* ctx, int cur, int end)
: m_ctx(ctx), m_cur(cur), m_end(end)
2026-04-04 20:03:17 -05:00
{
}
//---
2026-04-05 11:18:49 -05:00
CYmlIteratorObj()
: m_ctx(NULL), m_cur(0), m_end(0)
2026-04-04 20:03:17 -05:00
{
}
//---
__forceinline bool IsValid() { return m_cur < m_end; }
//---
void Next()
{
if(m_cur >= m_end)
return;
2026-04-05 11:18:49 -05:00
m_cur += 2; // salta KEY
m_cur += m_ctx.GetStep(m_cur); // salta valor
2026-04-04 20:03:17 -05:00
}
//---
string Key()
{
2026-04-05 11:18:49 -05:00
if(m_cur >= m_end)
2026-04-04 20:03:17 -05:00
return "";
const int s = int(m_ctx.m_cinta[m_cur + 1] >> 32);
const int e = int(m_ctx.m_cinta[m_cur + 1] & 0xFFFFFFFF);
const bool scape = bool((m_ctx.m_cinta[m_cur] >> YMLPARSER_BIT_END_TYPE) & 1);
return scape ? m_ctx.Unescape(s, e)
: ShortArrayToString(m_ctx.m_yml, s, (e - s) + 1);
}
//---
CYmlNode Val()
{
if(m_cur >= m_end)
return EMPTY_YMLNODE;
2026-04-05 11:18:49 -05:00
const int pos = m_cur + 2;
2026-04-04 20:03:17 -05:00
const int fin = pos + m_ctx.GetStep(pos);
return CYmlNode(m_ctx, pos, fin);
}
};
2026-04-05 11:18:49 -05:00
const CYmlIteratorObj EMPTY_YMLITERATOR_OBJ;
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
//| Iterador de arrays |
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
struct CYmlIteratorArray
2026-04-04 20:03:17 -05:00
{
2026-04-05 11:18:49 -05:00
CYmlParser* m_ctx;
int m_cur;
const int m_end;
//---
CYmlIteratorArray(CYmlParser* ctx, int cur, int end)
: m_ctx(ctx), m_cur(cur), m_end(end)
{
}
//---
CYmlIteratorArray()
: m_ctx(NULL), m_cur(0), m_end(0)
{
}
//---
__forceinline bool IsValid() { return m_cur < m_end; }
//---
void Next()
{
if(m_cur >= m_end)
return;
m_cur += m_ctx.GetStep(m_cur);
}
//---
CYmlNode Val()
{
if(m_cur >= m_end)
return EMPTY_YMLNODE;
const int pos = m_cur;
const int fin = pos + m_ctx.GetStep(pos);
return CYmlNode(m_ctx, pos, fin);
}
};
const CYmlIteratorArray EMPTY_YMLITERATOR_ARR;
2026-04-04 20:03:17 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
//| |
//+------------------------------------------------------------------+
CYmlIteratorArray CYmlNode::BeginArr() const
2026-04-04 20:03:17 -05:00
{
2026-04-05 11:18:49 -05:00
//---
2026-04-04 20:03:17 -05:00
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
2026-04-05 11:18:49 -05:00
//---
const int tipo = int(m_ctx.m_cinta[i] & 0xF);
if(tipo != YML_CLASIFIER_TOKEN_TYPE_ARR)
return EMPTY_YMLITERATOR_ARR;
//---
return CYmlIteratorArray(m_ctx, i + 1, m_end);
2026-04-04 20:03:17 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
CYmlIteratorObj CYmlNode::BeginObj() const
2026-04-04 20:03:17 -05:00
{
//---
const int i = YML_RESOLVE_PTR(m_ctx, m_idx);
//---
const int tipo = int(m_ctx.m_cinta[i] & 0xF);
2026-04-05 11:18:49 -05:00
if(tipo != YML_CLASIFIER_TOKEN_TYPE_OBJ)
return EMPTY_YMLITERATOR_OBJ;
//---
return CYmlIteratorObj(m_ctx, i + 1, m_end);
2026-04-04 20:03:17 -05:00
}
2026-04-05 11:18:49 -05:00
2026-04-06 07:49:32 -05:00
2026-04-04 16:19:18 -05:00
//+------------------------------------------------------------------+
2026-04-05 11:18:49 -05:00
#endif // YMLPARSERBYLEO_SRC_YMLNODE_MQH