//+------------------------------------------------------------------+ //| DomImp.mqh | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com/" #property strict #ifndef BASESPARSERSLAN_SRC_DOM_IMP_MQH #define BASESPARSERSLAN_SRC_DOM_IMP_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "DomDef.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| Keys | //+------------------------------------------------------------------+ __forceinline int CDomNodeBase::GetKeys(string &out[]) const { return m_type == TSN_SBL_BASE_TYPE_OBJ ? m_ctx.m_objs[m_v.ix].GetKeys(out) : 0; } //+------------------------------------------------------------------+ __forceinline bool CDomNodeBase::HasKey(const string &key) const { return m_type == TSN_SBL_BASE_TYPE_OBJ ? m_ctx.m_objs[m_v.ix].Contains(key) : false; } //+------------------------------------------------------------------+ bool CDomNodeBase::Remove(const string &key) { if(m_type != TSN_SBL_BASE_TYPE_OBJ) return false; //--- CHashMapFast(string, CDomNodeBase*)* ptr = m_ctx.m_objs[m_v.ix]; //--- uint i; int bit_pos; if(!ptr.Find(key, i, bit_pos)) return false; //--- CDomNodeBase* f = ptr.m_table[TSN_FASTHASHMAP_INDEX(i, bit_pos)].value; // En caso el contexto del objeto... a eliminar es el mismo (proviene de la misma pila) // ENtonces eliminamos.. if(f.m_ctx == m_ctx && CheckPointer(f) == POINTER_DYNAMIC) delete f; ptr.Remove(i, bit_pos); return true; } //+------------------------------------------------------------------+ bool CDomNodeBase::NewObj(int inital_hash_map_size) { if(m_type == TSN_SBL_BASE_TYPE_OBJ) return false; // Ya es obj m_type = TSN_SBL_BASE_TYPE_OBJ; m_v.ix = m_ctx.ReserveObj(inital_hash_map_size); return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ __forceinline int CDomNodeBase::Size(void) const { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { return m_ctx.m_objs[m_v.ix].Count(); } case TSN_SBL_BASE_TYPE_ARR: { return m_ctx.m_node[m_v.ix].values_size; } default: return 0; } } //+------------------------------------------------------------------+ __forceinline bool CDomNodeBase::InRange(const int index) const { const int t = Size(); return index >= 0 && index < t; } //+------------------------------------------------------------------+ __forceinline bool CDomNodeBase::Remove(const int index) { return m_type == TSN_SBL_BASE_TYPE_ARR ? m_ctx.DeleteElementArr(m_v.ix, index) : false; } //+------------------------------------------------------------------+ __forceinline bool CDomNodeBase::AddItem(CDomNodeBase* node) { return m_type == TSN_SBL_BASE_TYPE_ARR ? m_ctx.AddElementArr(m_v.ix, node) : false; } //+------------------------------------------------------------------+ bool CDomNodeBase::NewArr(int inital_reserve) { if(m_type == TSN_SBL_BASE_TYPE_ARR) return false; // Ya es obj m_type = TSN_SBL_BASE_TYPE_ARR; m_v.ix = m_ctx.ReserveArr(inital_reserve); return true; } //+------------------------------------------------------------------+ template __forceinline int CDomNodeBase::ToArray(T &array[]) const { return m_ctx.ToArray(m_v.ix, array); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CDomNodeBase::Clear() { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { //--- CHashMapFast(string, CDomNodeBase*)* ptr = m_ctx.m_objs[m_v.ix]; CHashMapFastIterator(string, CDomNodeBase*) it = ptr.BeginIteration(); //--- while(it.IsValid()) { CDomNodeBase* f = it.Val(); // En caso el contexto del objeto... a eliminar es el mismo (proviene de la misma pila) // ENtonces eliminamos.. if(f.m_ctx == m_ctx && CheckPointer(f) == POINTER_DYNAMIC) delete f; //--- it.Next(); } //--- ptr.Clear(); break; } case TSN_SBL_BASE_TYPE_ARR: { m_ctx.ClearArray(m_v.ix); break; } } } //+------------------------------------------------------------------+ //| Asignaciones | //+------------------------------------------------------------------+ void CDomNodeBase::operator=(CDomNodeBase& v) { m_v = v.m_v; m_ctx = v.m_ctx; m_type = v.m_type; } //+------------------------------------------------------------------+ bool CDomNodeBase::operator=(const string& v) { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { m_ctx.FreeObj(m_v.ix); m_type = TSN_SBL_BASE_TYPE_STR; break; } case TSN_SBL_BASE_TYPE_ARR: { m_ctx.FreeArr(m_v.ix); m_type = TSN_SBL_BASE_TYPE_STR; break; } case TSN_SBL_BASE_TYPE_INT: case TSN_SBL_BASE_TYPE_FLT: case TSN_SBL_BASE_TYPE_BOL: m_type = TSN_SBL_BASE_TYPE_STR; break; case TSN_SBL_BASE_TYPE_STR: { m_ctx.m_string_stack[m_v.ix] = v; return true; } case TSN_SBL_BASE_DOM_NULL: { m_type = TSN_SBL_BASE_TYPE_STR; break; } default: { return false; } } //--- m_v.ix = m_ctx.ReserveString(); m_ctx.m_string_stack[m_v.ix] = v; return true; } //+------------------------------------------------------------------+ bool CDomNodeBase::operator=(const bool v) { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { m_ctx.FreeObj(m_v.ix); m_type = TSN_SBL_BASE_TYPE_BOL; break; } case TSN_SBL_BASE_TYPE_ARR: { m_ctx.FreeArr(m_v.ix); m_type = TSN_SBL_BASE_TYPE_BOL; break; } case TSN_SBL_BASE_TYPE_INT: case TSN_SBL_BASE_TYPE_FLT: { m_type = TSN_SBL_BASE_TYPE_BOL; break; } case TSN_SBL_BASE_TYPE_BOL: break; case TSN_SBL_BASE_TYPE_STR: { m_ctx.FreeString(m_v.ix); m_type = TSN_SBL_BASE_TYPE_BOL; break; } case TSN_SBL_BASE_DOM_NULL: { m_type = TSN_SBL_BASE_TYPE_BOL; break; } default: { return false; } } //--- m_v.bv = v; return true; } //+------------------------------------------------------------------+ bool CDomNodeBase::operator=(const double v) { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { m_ctx.FreeObj(m_v.ix); m_type = TSN_SBL_BASE_TYPE_FLT; break; } case TSN_SBL_BASE_TYPE_ARR: { m_ctx.FreeArr(m_v.ix); m_type = TSN_SBL_BASE_TYPE_FLT; break; } case TSN_SBL_BASE_TYPE_INT: { m_type = TSN_SBL_BASE_TYPE_FLT; break; } case TSN_SBL_BASE_TYPE_FLT: break; case TSN_SBL_BASE_TYPE_BOL: { m_type = TSN_SBL_BASE_TYPE_FLT; break; } case TSN_SBL_BASE_TYPE_STR: { m_ctx.FreeString(m_v.ix); m_type = TSN_SBL_BASE_TYPE_FLT; break; } case TSN_SBL_BASE_DOM_NULL: { m_type = TSN_SBL_BASE_TYPE_FLT; break; } default: { return false; } } //--- m_v.dv = v; return true; } //+------------------------------------------------------------------+ bool CDomNodeBase::operator=(const long v) { switch(m_type) { case TSN_SBL_BASE_TYPE_OBJ: { m_ctx.FreeObj(m_v.ix); m_type = TSN_SBL_BASE_TYPE_INT; break; } case TSN_SBL_BASE_TYPE_ARR: { m_ctx.FreeArr(m_v.ix); m_type = TSN_SBL_BASE_TYPE_INT; break; } case TSN_SBL_BASE_TYPE_INT: break; // Nada sale case TSN_SBL_BASE_TYPE_FLT: case TSN_SBL_BASE_TYPE_BOL: { m_type = TSN_SBL_BASE_TYPE_INT; break; } case TSN_SBL_BASE_TYPE_STR: { m_ctx.FreeString(m_v.ix); m_type = TSN_SBL_BASE_TYPE_INT; break; } case TSN_SBL_BASE_DOM_NULL: { m_type = TSN_SBL_BASE_TYPE_INT; break; } default: { return false; } } //--- m_v.iv = v; return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CDomNodeBase* CDomNodeBase::At(const int idx) const { if(m_type != TSN_SBL_BASE_TYPE_ARR) return NULL; return m_ctx.m_node[m_v.ix].values[idx]; } //+------------------------------------------------------------------+ CDomNodeBase* CDomNodeBase::Get(const string &key) { if(m_type != TSN_SBL_BASE_TYPE_OBJ) return NULL; //---- CHashMapFast(string, CDomNodeBase*)* ptr = m_ctx.m_objs[m_v.ix]; const int idx = ptr.Find(key); return idx == -1 ? NULL : ptr.m_table[idx].value; } // En caso no existe da error //+------------------------------------------------------------------+ CDomNodeBase* CDomNodeBase::operator[](const string& key) { if(m_type != TSN_SBL_BASE_TYPE_OBJ) return NULL; //--- CHashMapFast(string, CDomNodeBase*)* ptr = m_ctx.m_objs[m_v.ix]; const int idx = ptr.Find(key); if(idx != -1) { return ptr.m_table[idx].value; // puntero } //--- No existe creamos entonces... if(!ptr.Add(key)) return NULL; //--- return (ptr.m_table[ptr.m_last_created_pos].value = new CDomNodeBase(m_ctx)); } // En caso no existe lo crea. //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ long CDomNodeBase::ToInt(const long def) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: return m_v.iv; case TSN_SBL_BASE_TYPE_FLT: return (long)m_v.dv; case TSN_SBL_BASE_TYPE_BOL: return m_v.bv; case TSN_SBL_BASE_TYPE_STR: return (long)m_ctx.m_string_stack[m_v.ix]; default: return def; } } //+------------------------------------------------------------------+ bool CDomNodeBase::ToIntSafe(long &val) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: val = m_v.iv; return true; case TSN_SBL_BASE_TYPE_FLT: val = (long)m_v.dv; return true; case TSN_SBL_BASE_TYPE_BOL: val = m_v.bv; return true; case TSN_SBL_BASE_TYPE_STR: val = (long)m_ctx.m_string_stack[m_v.ix]; return true; default: return false; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double CDomNodeBase::ToDouble(const double def) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: return (double)m_v.iv; case TSN_SBL_BASE_TYPE_FLT: return m_v.dv; case TSN_SBL_BASE_TYPE_BOL: return m_v.bv; case TSN_SBL_BASE_TYPE_STR: return (double)m_ctx.m_string_stack[m_v.ix]; default: return def; } } //+------------------------------------------------------------------+ bool CDomNodeBase::ToDoubleSafe(double &val) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: val = (double)m_v.iv; return true; case TSN_SBL_BASE_TYPE_FLT: val = m_v.dv; return true; case TSN_SBL_BASE_TYPE_BOL: val = m_v.bv; return true; case TSN_SBL_BASE_TYPE_STR: val = (double)m_ctx.m_string_stack[m_v.ix]; return true; default: return false; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CDomNodeBase::ToBool(const bool def) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: return m_v.iv != 0; case TSN_SBL_BASE_TYPE_FLT: return m_v.dv != 0.0; case TSN_SBL_BASE_TYPE_BOL: return m_v.bv; default: return def; } } //+------------------------------------------------------------------+ bool CDomNodeBase::ToBoolSafe(bool &val) const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: val = m_v.iv != 0; return true; case TSN_SBL_BASE_TYPE_FLT: val = m_v.dv != 0.0; return true; case TSN_SBL_BASE_TYPE_BOL: val = m_v.bv; return true; default: return false; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string CDomNodeBase::ToString(const string def = "") const { switch(m_type) { case TSN_SBL_BASE_TYPE_INT: return (string)m_v.iv; case TSN_SBL_BASE_TYPE_FLT: return (string)m_v.dv; case TSN_SBL_BASE_TYPE_BOL: return (string)m_v.bv; case TSN_SBL_BASE_TYPE_STR: return m_ctx.m_string_stack[m_v.ix]; default: return def; } } //+------------------------------------------------------------------+ int CDomNodeBase::StrLenRaw(void) const { return m_type == TSN_SBL_BASE_TYPE_STR ? StringLen(m_ctx.m_string_stack[m_v.ix]) : 0; } } //+------------------------------------------------------------------+ #endif // BASESPARSERSLAN_SRC_DOM_IMP_MQH