//+------------------------------------------------------------------+ //| 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)<> 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