262 lines
7.8 KiB
MQL5
262 lines
7.8 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| Pointer.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_EXTRADEF_POINTER_CPILER_MQH
| |
#define BASESPARSERSLAN_SRC_EXTRADEF_POINTER_CPILER_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
#include "Def.mqh"
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
namespace TSN
| |
{
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
struct BSFLPointerCompiler
| |
{
| |
public:
| |
uchar m_raw[]; // raw
| |
int m_pos; // posicion de lecutra curr
| |
int m_len; // tamaño de raw
| |
int m_offset; // offset de lecutra
| |
int m_w; // posicion de escritura
| |
| |
public:
| |
BSFLPointerCompiler();
| |
| |
//--- Asignacion
| |
__forceinline void Assing(const string& str, uint cp = CP_ACP);
| |
__forceinline void CalcLen() { m_len = ArraySize(m_raw); }
| |
void CorrectPadding();
| |
| |
//--- Reserva
| |
void CalcReserve(ulong& ins[]);
| |
| |
//--- Compilacion
| |
ENUM_BSFL_POINTER_PARSE_RES Compile(ulong& ins[]); // metodo de bajo nivel
| |
BSFLPointerQuery Compile(); // devuelve uno
| |
bool Compile(BSFLPointerQuery& query); // toma uno ya existente
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
BSFLPointerCompiler::BSFLPointerCompiler(void)
| |
: m_pos(0), m_len(0), m_offset(0), m_w(0)
| |
{
| |
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
__forceinline void BSFLPointerCompiler::Assing(const string &str, uint cp)
| |
{
| |
m_len = StringToCharArray(str, m_raw, 0, WHOLE_ARRAY, cp);
| |
m_len -= (m_len != -1);
| |
m_offset = 0;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void BSFLPointerCompiler::CorrectPadding(void)
| |
{
| |
ArrayResize(m_raw, m_len + 2);
| |
m_raw[m_len] = '/'; // para forzar cierre / o luego del ~(algo) se cierre bien
| |
m_raw[m_len + 1] = '/'; // en el pero caso luego del ~(algo) neceista un char mas.. asi que usarmoes esto
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void BSFLPointerCompiler::CalcReserve(ulong &ins[])
| |
{
| |
// Ahora toca caluclar el len loq ue sabes es uqe si o si por cada token neeismtos dos ulongs
| |
// enotnces "lo peorsito" /a que impliciaria un solo token "" requeria 2..
| |
// lo cual = len
| |
// o por jeemplo /a
| |
const int req = m_w + m_len;
| |
if(ArraySize(ins) < req)
| |
ArrayResize(ins, req);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
BSFLPointerQuery BSFLPointerCompiler::Compile(void)
| |
{
| |
//---
| |
// usuairo ya se encarga de llenra el buffer y correct padding
| |
//---
| |
ulong ins[];
| |
CalcReserve(ins);
| |
const ENUM_BSFL_POINTER_PARSE_RES res = Compile(ins);
| |
if(res) // hay errores
| |
return BSFLPointerQuery::EMPTY_QUERY;
| |
| |
//---
| |
ArrayResize(m_raw, ArraySize(m_raw) - 2); // quitamos padding
| |
m_len = 0; // viene de 0
| |
m_w = 0;
| |
| |
//---
| |
return BSFLPointerQuery(ins, m_w, m_raw);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
bool BSFLPointerCompiler::Compile(BSFLPointerQuery& query)
| |
{
| |
//---
| |
CalcReserve(query.m_ins);
| |
const ENUM_BSFL_POINTER_PARSE_RES res = Compile(query.m_ins);
| |
if(res) // hay errores
| |
return false;
| |
| |
//---
| |
// size
| |
query.m_size = m_w;
| |
// raw
| |
ArrayResize(m_raw, ArraySize(m_raw) - 2); // quitamos padding
| |
m_len = ArraySize(query.m_raw);
| |
ArraySwap(m_raw, query.m_raw);
| |
| |
//---
| |
m_w = 0;
| |
| |
//---
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
// Las intrucciones de salida van de aparares
| |
// slot 0 = numero [0-31 bits [32 bit = hash que viene es valido o no?¿]
| |
// slot 1 = hash completo de FNV1A64
| |
//---notas
| |
// m_w no se reinica tu eres el encagaro de dalre un valor antes y luego reicniarlo de su uso
| |
// en caso desea reusarlo... puede ponerlo en 0 por jemeplo poara uqe eimpziar a esicbri desde la proxima ahi
| |
ENUM_BSFL_POINTER_PARSE_RES BSFLPointerCompiler::Compile(ulong& ins[])
| |
{
| |
//---
| |
m_pos = m_offset;
| |
| |
//---
| |
if(m_raw[m_pos++] != '/')
| |
return BSFL_POINTER_PARSE_RES_ERR_QUERY_MUST_START_WITH_BR;
| |
| |
//---
| |
while(m_pos < m_len)
| |
{
| |
uchar ch = m_raw[m_pos] ^ '0';
| |
//Print(CharToString(m_raw[m_pos]));
| |
ulong v;
| |
if(ch < 10)
| |
{
| |
const int l = m_pos;
| |
v = 0; // reiniciamos
| |
| |
//---
| |
while(true)
| |
{
| |
DOMBASEUTIL_PARSE_NUM_U1(v)
| |
if(!v) // leading zeros
| |
{
| |
v = INT_MAX;
| |
break;
| |
}
| |
| |
//---
| |
DOMBASEUTIL_PARSE_NUM_UNROLLED_8(v)
| |
STRCONV_TOV_ALG(v, ch)
| |
if((ch = m_raw[++m_pos] ^ '0') > 9 && v < INT_MAX) // pass
| |
break;
| |
| |
//---
| |
v = INT_MAX; // error no cumple
| |
break;
| |
}
| |
| |
//--- ponemos el numero INT_MAX invalido o el valor que haya..
| |
ins[m_w] = v;
| |
| |
//--- vale entonces es invalido este numero.. pongamolos al dia
| |
// en caso sigamos.. aun.. o fallo....
| |
// primero resolvemos esto
| |
const int t = m_pos;
| |
m_pos = l;
| |
v = 14695981039346656037ULL;
| |
ch = m_raw[m_pos];
| |
// start
| |
ins[m_w] |= ulong(m_pos) << BSFLPOINTER_BIT_START_H;
| |
| |
//---
| |
while(m_pos < t)
| |
{
| |
v ^= ch;
| |
v *= 1099511628211ULL;
| |
ch = m_raw[++m_pos];
| |
}
| |
}
| |
else
| |
{
| |
ins[m_w] = INT_MAX | ulong(m_pos) << BSFLPOINTER_BIT_START_H;
| |
ch ^= '0'; // deshace
| |
v = 14695981039346656037ULL;
| |
}
| |
| |
| |
//---
| |
while(ch != '/')
| |
{
| |
//Print(CharToString(ch), " ", ch);
| |
//---
| |
m_pos++;
| |
| |
//---
| |
if(ch == '~')
| |
{
| |
const uchar n = m_raw[m_pos++] ^ '0';
| |
if(n > 1)
| |
return BSFL_POINTER_PARSE_RES_ERR_INVALID_ESCAPE;
| |
| |
//---
| |
ch = (n == 1) ? '/' : '~';
| |
}
| |
| |
//---
| |
v ^= ch;
| |
v *= 1099511628211ULL;
| |
ch = m_raw[m_pos];
| |
}
| |
| |
//---
| |
const ulong start = (ins[m_w] >> BSFLPOINTER_BIT_START_H);
| |
//Print(CharArrayToString(m_raw, start, (m_pos - start)));
| |
ins[m_w++] |= ulong(m_pos - start) << BSFLPOINTER_BIT_START_LEN;
| |
ins[m_w++] = v;
| |
| |
//---
| |
m_pos++; // luego del '/'
| |
}
| |
| |
//---
| |
return BSFL_POINTER_PARSE_RES_EXITO;
| |
}
| |
| |
//--- end namespace
| |
}
| |
//+------------------------------------------------------------------+
| |
#endif // BASESPARSERSLAN_SRC_EXTRADEF_POINTER_CPILER_MQH
|