CryptoByLeo/Src/RSPParser/Node.mqh
Nique_372 4bd1a391ab
2026-09-26 21:47:11 -05:00

343 lines
12 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 CRYPTOBYLEO_RSPPARSER_NODE_MQH
#define CRYPTOBYLEO_RSPPARSER_NODE_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "RSP.mqh"
#include <TSN/MQLArticles/Utils/StructBytesCre.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define RSPDATA_TRIPLET_KEYVALUEMETA (3)
#define RSPDATA_IS_VALID (m_ctx!=NULL)
#define RSPDATA_IS_NOT_VALID (m_ctx==NULL)
#define RSPDATA_IS_VALID_F (RSPDATA_IS_VALID && m_idx!=-1)
#define RSPDATA_IS_VAL_TO_REVISE (((m_ctx.m_cinta[m_idx-1] >> RSPDATA_BITSTART_ISVAL_CLEAN) & RSPDATA_MASK_META_IS) == 0)
//--- forward
class CRSPIteradorBase;
template <typename TNumHashes, typename TBaseHash>
class CRSPIteratorHash;
//--- trim right
#define RSPNODE_CORRECT_R_WSPACES \
if(RSPDATA_IS_VAL_TO_REVISE)\
{\
int i = (start + slen) - 1;\
while(i >= start && m_ctx.m_raw[i] < 33)\
{\
i--;\
}\
slen = (i - start) + 1;\
m_ctx.m_cinta[m_idx] = long(RSPDATA_TYPE_PLAIN_VALUE)\
| long(slen) << TSN_SBL_BIT_STR_LEN\
| long(start) << TSN_SBL_BIT_STR_START;\
m_ctx.m_cinta[m_idx - 1] |= RSPDATA_BITSTART_ISVAL_CLEAN_F;\
}
//---
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct CRSPNode
{
CRSPParser* m_ctx;
int m_idx;
//----
CRSPNode(const int _idx, CRSPParser* _ctx) : m_idx(_idx), m_ctx(_ctx) {}
CRSPNode() : m_idx(-1), m_ctx(NULL) {}
//---
__forceinline int RootSize() const { return m_ctx.m_root_values; }
//---
// Navega en el root
CRSPNode operator[](const string& key);
CRSPNode At(const int index) const;
string AtKey(const int index);
//---
bool HasKey(const string& key);
//---
__forceinline ENUM_RSPDATA_TYPE GetType() const { return ENUM_RSPDATA_TYPE(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE); }
__forceinline uint GetFlag() const { return 1 << uint(m_ctx.m_cinta[m_idx] & TSN_SBL_BIT_MASK_TYPE); }
//--- Value
CRSPNode Value() const;
//-- to str
string ToString(const string def = "") const;
int ToStringUArray(uchar& data[]) const;
__forceinline int StrLenRaw() const;
__forceinline int StrStart() const;
__forceinline bool CompareStrWith(const string& str) const;
//-- to bytes (asume hex string)
int HexToBytes(uchar& buf[]) const;
//--- Is
__forceinline bool IsValid() const { return RSPDATA_IS_VALID_F; }
__forceinline bool IsInvalid() const { return !RSPDATA_IS_VALID_F; }
//--- Meta
__forceinline bool MetaIsCor() const { return ((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & RSPDATA_MASK_META_IS) != 0; }
__forceinline bool MetaCleanedKey() const { return ((m_ctx.m_cinta[m_idx] >> RSPDATA_BITSTART_ISKEY_CLEAN) & RSPDATA_MASK_META_IS) != 0; }
__forceinline bool MetaCleanedValue() const { return ((m_ctx.m_cinta[m_idx] >> RSPDATA_BITSTART_ISVAL_CLEAN) & RSPDATA_MASK_META_IS) != 0; }
//---
template <typename TNumHashes, typename THashBase>
TSN::CRSPIteratorHash<TNumHashes, THashBase> MakeHashIterator(const string& keys[]) const
{
if(RSPDATA_IS_NOT_VALID)
return CRSPIteratorHash<TNumHashes, THashBase>::EMPTY;
return CRSPIteratorHash<TNumHashes, THashBase>(keys, m_ctx, m_idx);
}
//---
template <typename THashBase>
CRSPIteradorBase* MakeInteligentIterador(const string& keys[]) const;
//---
static const CRSPNode EMPTY_NODE;
//---
bool MoveNextPositionsThis(const int posiciones);
CRSPNode MoveNextPositions(const int posiciones) const;
//---
static bool BytesEq(const uchar& a[], const uchar& b[]);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
const CRSPNode CRSPNode::EMPTY_NODE;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CRSPNode CRSPNode::operator[](const string& key)
{
//---
if(RSPDATA_IS_NOT_VALID)
return CRSPNode::EMPTY_NODE;
//---
int cur = 0;
while(cur < m_ctx.m_cinta_pos)
{
if(m_ctx.KeysEqual(key, cur)) // + 1 para estar en META
return CRSPNode(cur + 1, m_ctx);
cur += RSPDATA_TRIPLET_KEYVALUEMETA;
}
return CRSPNode::EMPTY_NODE;
}
//+------------------------------------------------------------------+
bool CRSPNode::HasKey(const string &key)
{
//---
if(RSPDATA_IS_NOT_VALID)
return false;
//---
int cur = 0;
while(cur < m_ctx.m_cinta_pos)
{
if(m_ctx.KeysEqual(key, cur)) // + 1 para estar en META
return true;
cur += RSPDATA_TRIPLET_KEYVALUEMETA;
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CRSPNode CRSPNode::At(const int index) const
{
//---
if(RSPDATA_IS_NOT_VALID || index < 0 || index >= m_ctx.m_cinta_pos)
return CRSPNode::EMPTY_NODE;
//--- devuelve META
return CRSPNode((index * RSPDATA_TRIPLET_KEYVALUEMETA) + 1, m_ctx);
}
//+------------------------------------------------------------------+
string CRSPNode::AtKey(const int index)
{
//---
if(RSPDATA_IS_NOT_VALID || index < 0 || index >= m_ctx.m_cinta_pos)
return "";
//--- devuelve string
const int base = (index * RSPDATA_TRIPLET_KEYVALUEMETA);
//---
const int start = int(m_ctx.m_cinta[base] >> TSN_SBL_BIT_STR_START);
int slen = int((m_ctx.m_cinta[base] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
//---
m_ctx.VerifyCleanKey(base, start, slen);
//---
return CharArrayToString(m_ctx.m_raw, start, slen);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CRSPNode CRSPNode::Value(void) const
{
//---
if(RSPDATA_IS_NOT_VALID)
return CRSPNode::EMPTY_NODE;
// si estamos en META +1 = value
return CRSPNode(m_idx + 1, m_ctx);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string CRSPNode::ToString(const string def = "") const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return def;
// ahora si en value
// tenemos que recortar por la parte alta
//---
const int start = TSN_SBL_CNG_STR_START(m_idx);;
int slen = TSN_SBL_CNG_STR_LEN(m_idx);
//---
RSPNODE_CORRECT_R_WSPACES
//---
return CharArrayToString(m_ctx.m_raw, start, slen);
}
//+------------------------------------------------------------------+
int CRSPNode::ToStringUArray(uchar &data[]) const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return 0;
// ahora si en value
// tenemos que recortar por la parte alta
//---
const int start = TSN_SBL_CNG_STR_START(m_idx);;
int slen = TSN_SBL_CNG_STR_LEN(m_idx);
//---
RSPNODE_CORRECT_R_WSPACES
//---
return ArrayCopy(data, m_ctx.m_raw, 0, start, slen);
}
//+------------------------------------------------------------------+
// interpretna un mensaje multiplo de 2 len como una cadena de bytes LE
// Si no hay caracters NO HEX se intemapn como FF (invalidos) nota eso
// osea que
// "kkkk" da buf[] = {0xff, 0xff}
int CRSPNode::HexToBytes(uchar &buf[]) const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return 0;
// ahora si en value
// tenemos que recortar por la parte alta
//---
const int start = TSN_SBL_CNG_STR_START(m_idx);;
int slen = TSN_SBL_CNG_STR_LEN(m_idx);
//---
RSPNODE_CORRECT_R_WSPACES
//---
return CHexUtils::HexToBytes(m_ctx.m_raw, start, slen, buf);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
__forceinline int CRSPNode::StrLenRaw(void) const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return 0;
return TSN_SBL_CNG_STR_LEN(m_idx);
}
//+------------------------------------------------------------------+
__forceinline int CRSPNode::StrStart(void) const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return 0;
return TSN_SBL_CNG_STR_START(m_idx);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CRSPNode::MoveNextPositionsThis(const int posiciones)
{
if(RSPDATA_IS_NOT_VALID)
return false;
const int next_pos = m_idx + posiciones;
if(next_pos >= m_ctx.m_cinta_pos)
return false;
m_idx = next_pos;
return true;
}
//+------------------------------------------------------------------+
CRSPNode CRSPNode::MoveNextPositions(const int posiciones) const
{
if(RSPDATA_IS_NOT_VALID)
return CRSPNode::EMPTY_NODE;
const int next_pos = m_idx + posiciones;
if(next_pos >= m_ctx.m_cinta_pos)
return CRSPNode::EMPTY_NODE;
return CRSPNode(next_pos, m_ctx);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static bool CRSPNode::BytesEq(const uchar &a[], const uchar &b[])
{
const int ta = ArraySize(a);
if(ta != ArraySize(b))
return false;
for(int i = 0; i < ta; i++)
{
if(a[i] != b[i])
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CRSPNode CRSPParser::GetRoot(void)
{
if(m_cinta_pos == 0)
return CRSPNode::EMPTY_NODE;
return CRSPNode(0, &this);
}
}
#endif // CRYPTOBYLEO_RSPPARSER_NODE_MQH