//+------------------------------------------------------------------+ //| CYmlNode.mqh | //| 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 #ifndef YMLPARSERBYLEO_SRC_YMLNODE_MQH #define YMLPARSERBYLEO_SRC_YMLNODE_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "YmlParser.mqh" // 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) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #define YML_NODE_IS_NOT_VALID (m_ctx==NULL || m_idx == -1 || m_end == -1) struct CYmlIteratorArray; struct CYmlIteratorObj; //--- #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)) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ struct CYmlNode { public: //--- CYmlParser* m_ctx; int m_idx; int m_end; //--- CYmlNode() : m_ctx(NULL), m_idx(-1), m_end(-1) {} //--- CYmlNode(CYmlParser* _ctx, int _idx, int _end) : m_ctx(_ctx), m_idx(_idx), m_end(_end) {} //--- Operators CYmlNode operator[](const string& key) const; CYmlNode At(const int index) const; CYmlNode AtHomegeneo(const int index) const; //--- To // String string ToString(string def = "") const; // Int long ToInt(long def) const; bool ToIntSafe(long &val) const; // Version bool\true (si se pudo obtener) // Dbl double ToDouble(double def) const; bool ToDoubleSafe(double &val) const; // Version bool\true (si se pudo obtener) // Bool __forceinline bool ToBool(bool def) const; bool ToBoolSafe(bool& val) const; // Version bool\true (si se pudo obtener) //--- Set bool SetDbl(const double val); bool SetInt(const long val); bool SetBool(const bool val); //--- Type __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; //--- Is __forceinline bool IsValid() const; __forceinline bool IsNull() const; __forceinline bool IsArray() const; __forceinline bool IsObject() const; //--- Iterador CYmlIteratorArray BeginArr() const; CYmlIteratorObj BeginObj() const; //--- 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; //--- Size (arr o objeto) int Size() const; //--- // 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); //--- // 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); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ const CYmlNode EMPTY_YMLNODE; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CYmlNode CYmlNode::operator[](const string& key) const { //--- if(YML_NODE_IS_NOT_VALID) return EMPTY_YMLNODE; //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- 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; //--- const int len = StringLen(key); uint hash = 2166136261; for(int k = 0; k < len; k++) { hash ^= (uint)key[k]; hash *= 16777619; } //--- int cur = i + 1; // salta header OBJ while(cur < m_end) { if((m_ctx.m_cinta[cur] & 0xF) != YML_CLASIFIER_TOKEN_TYPE_KEY) { cur += m_ctx.GetStep(cur); continue; } if(hash == uint(m_ctx.m_cinta[cur] >> YMLPARSER_KEY_BIT_INIT_HASH)) { const int next_pos = cur + 2; const int final_pos = next_pos + m_ctx.GetStep(next_pos); return CYmlNode(m_ctx, next_pos, final_pos); } cur += 2; cur += m_ctx.GetStep(cur); } return EMPTY_YMLNODE; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CYmlNode CYmlNode::At(const int index) const { 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; //--- 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); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // 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); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CYmlNode CYmlNode::AtHomegeneo(const int index) const { 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); } // [obj=type arr][obj_implicito=obj][key][key][val][val][obj_implicito=obj][key][key][val][val] //+------------------------------------------------------------------+ //| Operaciones de bajo nivel mover la cinta custom | //+------------------------------------------------------------------+ bool CYmlNode::MoveToNextToken(bool solo_en_el_bloque_actual = true) { 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 const int final_pos = 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; } //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CYmlNode::AssingMqlParam(MqlParam& param) const { 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(""); return param.string_value != ""; } //--- case YML_CLASIFIER_TOKEN_TYPE_INTEGER: { param.type = TYPE_LONG; return ToIntSafe(param.integer_value); } //--- case YML_CLASIFIER_TOKEN_TYPE_DBL: { param.type = TYPE_DOUBLE; return ToDoubleSafe(param.double_value); } //--- case YML_CLASIFIER_TOKEN_TYPE_BOOL: { param.type = TYPE_BOOL; bool temp; if(!ToBoolSafe(temp)) 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(""); return param.string_value != ""; } //--- 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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ENUM_DATATYPE CYmlNode::GetTypeAsDataType(ENUM_DATATYPE def) const { 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 | //+------------------------------------------------------------------+ string CYmlNode::ToString(string def = "") const { 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: { const int start = (int)(m_ctx.m_cinta[new_index + 1] >> 32); const int end = (int)(m_ctx.m_cinta[new_index + 1] & 0xFFFFFFFF); const bool scape = (bool)((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 1); if(scape) return m_ctx.Unescape(start, end); return ShortArrayToString(m_ctx.m_yml, start, (end - start) + 1); // raw directo } //--- case YML_CLASIFIER_TOKEN_TYPE_INTEGER: return string(m_ctx.m_cinta[new_index + 1]); //--- case YML_CLASIFIER_TOKEN_TYPE_DBL: { CYmlParser::LongToDbl un; un.l = m_ctx.m_cinta[new_index + 1]; return string(un.d); } //--- case YML_CLASIFIER_TOKEN_TYPE_BOOL: return ((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 1) != 0 ? "true" : "false"; //--- case YML_CLASIFIER_TOKEN_TYPE_NULL: return def; //--- case YML_CLASIFIER_TOKEN_TYPE_STR_MULTILINE: { const int start = int(m_ctx.m_cinta[new_index + 1] >> 32); const int end = int(m_ctx.m_cinta[new_index + 1] & 0xFFFFFFFF); const int ident = int((m_ctx.m_cinta[new_index] >> YMLPARSER_BIT_END_TYPE) & 0xFFFF); bool con_saltos = bool((m_ctx.m_cinta[new_index] >> 32) & 1); //--- return m_ctx.ExtractMultiline(start, end, ident, con_saltos); } //--- 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 int | //+------------------------------------------------------------------+ long CYmlNode::ToInt(long def) const { if(YML_NODE_IS_NOT_VALID) return def; //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- switch(int(m_ctx.m_cinta[i] & 0xF)) { case YML_CLASIFIER_TOKEN_TYPE_INTEGER: return m_ctx.m_cinta[i + 1]; case YML_CLASIFIER_TOKEN_TYPE_DBL: { CYmlParser::LongToDbl un; un.l = m_ctx.m_cinta[i + 1]; return long(un.d); } case YML_CLASIFIER_TOKEN_TYPE_BOOL: return long((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1); } //--- return def; } //+------------------------------------------------------------------+ bool CYmlNode::ToIntSafe(long &val) const { 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 | //+------------------------------------------------------------------+ double CYmlNode::ToDouble(double def) const { if(YML_NODE_IS_NOT_VALID) return def; //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- switch(int(m_ctx.m_cinta[i] & 0xF)) { case YML_CLASIFIER_TOKEN_TYPE_INTEGER: return double(m_ctx.m_cinta[i + 1]); case YML_CLASIFIER_TOKEN_TYPE_DBL: { CYmlParser::LongToDbl un; un.l = m_ctx.m_cinta[i + 1]; return un.d; } case YML_CLASIFIER_TOKEN_TYPE_BOOL: return double((m_ctx.m_cinta[i] >> YMLPARSER_BIT_END_TYPE) & 1); } //--- return def; } //+------------------------------------------------------------------+ bool CYmlNode::ToDoubleSafe(double &val) const { 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 | //+------------------------------------------------------------------+ bool CYmlNode::ToBool(bool def) const { if(YML_NODE_IS_NOT_VALID) return def; //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- 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; } //+------------------------------------------------------------------+ bool CYmlNode::ToBoolSafe(bool &val) const { 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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CYmlNode::Size() const { if(YML_NODE_IS_NOT_VALID) return 0; //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- 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); } //+------------------------------------------------------------------+ //| Is | //+------------------------------------------------------------------+ __forceinline bool CYmlNode::IsValid() const { return !YML_NODE_IS_NOT_VALID; } //+------------------------------------------------------------------+ __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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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; m_ctx.m_cinta[i + 1] = un.l; return true; } //--- return false; } //+------------------------------------------------------------------+ //| Iterador de arrays | //+------------------------------------------------------------------+ struct CYmlIteratorObj { CYmlParser* m_ctx; int m_cur; const int m_end; //--- CYmlIteratorObj(CYmlParser* ctx, int cur, int end) : m_ctx(ctx), m_cur(cur), m_end(end) { } //--- CYmlIteratorObj() : 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 += 2; // salta KEY m_cur += m_ctx.GetStep(m_cur); // salta valor } //--- string Key() { if(m_cur >= m_end) 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; const int pos = m_cur + 2; const int fin = pos + m_ctx.GetStep(pos); return CYmlNode(m_ctx, pos, fin); } }; const CYmlIteratorObj EMPTY_YMLITERATOR_OBJ; //+------------------------------------------------------------------+ //| Iterador de arrays | //+------------------------------------------------------------------+ struct CYmlIteratorArray { 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; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CYmlIteratorArray CYmlNode::BeginArr() const { //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- 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); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CYmlIteratorObj CYmlNode::BeginObj() const { //--- const int i = YML_RESOLVE_PTR(m_ctx, m_idx); //--- const int tipo = int(m_ctx.m_cinta[i] & 0xF); if(tipo != YML_CLASIFIER_TOKEN_TYPE_OBJ) return EMPTY_YMLITERATOR_OBJ; //--- return CYmlIteratorObj(m_ctx, i + 1, m_end); } //+------------------------------------------------------------------+ #endif // YMLPARSERBYLEO_SRC_YMLNODE_MQH