Beobachten
1
0
Fork
Du hast bereits einen Fork von CryptoByLeo erstellt
0
CryptoByLeo/Src/RSPParser/Node.mqh

365 Zeilen
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)
//---
#define RSPNODE_NH(NH) TSN::MQLARTICLES_STRUCT_BYTES_##NH
//--- forward
class CRSPIteradorBase;
template <typename TNumHashes, typename TBaseHash>
class CRSPIteratorHash;
//---
#define RSPNODE_CORRECT_VAL \
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;
int StrLenRaw() 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 = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
//---
RSPNODE_CORRECT_VAL
//---
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 = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
//---
RSPNODE_CORRECT_VAL
//---
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 = int(m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_STR_START);
int slen = int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
//---
RSPNODE_CORRECT_VAL
//---
const int sob = slen & 1; // % 2 (vemos si hay sobrante o si es multiplo de dos exacto)
int exact_len = slen - sob;
ArrayResize(buf, (slen >> 1) + (sob << 1));
int w = 0;
//---
exact_len += start; // para que peuda empzar bien..
int i = start;
//---
for(i; i < exact_len; i += 2)
buf[w++] = g_arr_valid_hex_chars[m_ctx.m_raw[i]] | g_arr_valid_hex_chars[m_ctx.m_raw[i + 1]] << 4;
if(sob) // solo rellenmaso alto (la parte alta la inteprntamos como 0)
buf[w++] = m_ctx.m_raw[i];
//---
return w;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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 int((m_ctx.m_cinta[m_idx] >> TSN_SBL_BIT_START_ENDTYPE) & TSN_SBL_BIT_STR_MASK_LEN);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CRSPNode::CompareStrWith(const string &str) const
{
if(RSPDATA_IS_NOT_VALID || (m_ctx.m_cinta[m_idx]&TSN_SBL_BIT_MASK_TYPE) != RSPDATA_TYPE_PLAIN_VALUE)
return false;
return m_ctx.StrEquals(str, 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