forked from nique_372/MQLArticles
324 lines
9 KiB
MQL5
324 lines
9 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Bytes.mqh |
|
|
//| Copyright 2026, Niquel Mendoza |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza"
|
|
#property link "https://www.mql5.com"
|
|
#property strict
|
|
|
|
#ifndef MQLARTICLES_UTILS_BITS_BITFASTBUFFER_MQH
|
|
#define MQLARTICLES_UTILS_BITS_BITFASTBUFFER_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include "Def.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
struct CBitBuffer
|
|
{
|
|
public:
|
|
ulong m_bits[]; // bits como ulong
|
|
int m_r; // reserva de m_bits
|
|
int m_s; // bloques ya completos
|
|
int m_w; // bit de escritura
|
|
|
|
|
|
//--- inicializacion basica
|
|
CBitBuffer();
|
|
CBitBuffer(int reserve);
|
|
|
|
//--- From
|
|
void RobarDe(CBitBuffer& bit);
|
|
void FromBytesLE(const uchar& buf[]);
|
|
void FromBytesBE(const uchar& buf[]);
|
|
|
|
//--- To
|
|
int ToBytes(uchar &buf[], int w = 0);
|
|
|
|
//--- Clear
|
|
void Clear();
|
|
|
|
//--- Write
|
|
void WriteStringWPadd(const string& str);
|
|
void WriteBool(bool v);
|
|
template <typename TInteger>
|
|
void WriteInteger(const TInteger v);
|
|
template <typename TInteger>
|
|
void WriteIntegerArray(const TInteger& v[]);
|
|
void WriteDouble(const double v);
|
|
void WriteFloat(const float v);
|
|
|
|
//---
|
|
__forceinline void SyncArrayRSize() { m_r = ArraySize(m_bits); }
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CBitBuffer::CBitBuffer(void)
|
|
: m_s(0), m_w(0), m_r(2)
|
|
{
|
|
ArrayResize(m_bits, m_r, m_r);
|
|
m_bits[0] = 0ULL;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
CBitBuffer::CBitBuffer(int reserve)
|
|
: m_s(0), m_w(0), m_r(reserve)
|
|
{
|
|
ArrayResize(m_bits, m_r, m_r);
|
|
m_bits[0] = 0ULL;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::FromBytesLE(const uchar &buf[])
|
|
{
|
|
//---
|
|
const int k = ArraySize(buf);
|
|
if(k < 1)
|
|
return;
|
|
//---
|
|
if(k > m_r)
|
|
{
|
|
m_r = k;
|
|
ArrayResize(m_bits, m_r, m_r);
|
|
}
|
|
|
|
//---
|
|
CNumberUtils::ULL_LoadFromBytesLE(k, m_bits, m_s, buf, m_w);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::FromBytesBE(const uchar &buf[])
|
|
{
|
|
//---
|
|
const int k = ArraySize(buf);
|
|
if(k < 1)
|
|
return;
|
|
//---
|
|
if(k > m_r)
|
|
{
|
|
m_r = k;
|
|
ArrayResize(m_bits, m_r, m_r);
|
|
}
|
|
|
|
//---
|
|
CNumberUtils::ULL_LoadFromBytesBE(k, m_bits, m_s, buf, m_w);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::RobarDe(CBitBuffer &bit)
|
|
{
|
|
m_w = bit.m_w;
|
|
m_s = bit.m_s;
|
|
m_r = bit.m_r;
|
|
ArraySwap(m_bits, bit.m_bits);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int CBitBuffer::ToBytes(uchar &buf[], int w = 0)
|
|
{
|
|
//---
|
|
const int vs_bytes = (m_s << 3);
|
|
if(vs_bytes + w > ArraySize(buf))
|
|
ArrayResize(buf, vs_bytes + w);
|
|
|
|
//---
|
|
const int blocks = vs_bytes >> 3; // Cuantos bloques enteros procesaremos
|
|
const int sob = vs_bytes & 7; // % 8 cuantos sobraan
|
|
|
|
//--- Ahora si
|
|
int r = 0;
|
|
// bloques completos
|
|
for(; r < blocks; r++)
|
|
{
|
|
const ulong v = m_bits[r];
|
|
|
|
//--- write
|
|
buf[w++] = uchar(v);
|
|
buf[w++] = uchar(v >> 8);
|
|
buf[w++] = uchar(v >> 16);
|
|
buf[w++] = uchar(v >> 24);
|
|
buf[w++] = uchar(v >> 32);
|
|
buf[w++] = uchar(v >> 40);
|
|
buf[w++] = uchar(v >> 48);
|
|
buf[w++] = uchar(v >> 56);
|
|
}
|
|
// en caso haya sobrante
|
|
if(sob)
|
|
{
|
|
const ulong v = m_bits[r];
|
|
for(int j = 0; j < (sob << 3); j += 8)
|
|
buf[w++] = uchar(v >> j);
|
|
}
|
|
|
|
|
|
//---
|
|
return w;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::Clear(void)
|
|
{
|
|
m_w = 0;
|
|
m_s = 0;
|
|
m_bits[0] = 0ULL;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::WriteDouble(const double v)
|
|
{
|
|
TsnBitInterprete c;
|
|
c.double_value = v;
|
|
WriteInteger(c.ulong_value);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::WriteFloat(const float v)
|
|
{
|
|
TsnBitInterprete c;
|
|
c.float_value = v;
|
|
WriteInteger(c.uint_value);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TInteger>
|
|
void CBitBuffer::WriteIntegerArray(const TInteger &v[])
|
|
{
|
|
const int t = ArraySize(v);
|
|
for(int i = 0; i < t; i++)
|
|
WriteInteger(v[i]);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TInteger>
|
|
void CBitBuffer::WriteInteger(const TInteger v)
|
|
{
|
|
//---
|
|
MQLARTICLES_KEYBYTES_CHECK_RES(2)
|
|
|
|
//---
|
|
const int sl = 64 - m_w; // lo que logramos flushear
|
|
if(sl >= MQLARTICLES_BITBUFFER_BITS_SIZE(TInteger))
|
|
{
|
|
m_bits[m_s] |= ulong(v) << (m_w);
|
|
m_w += MQLARTICLES_BITBUFFER_BITS_SIZE(TInteger);
|
|
}
|
|
else // desborda
|
|
{
|
|
m_bits[m_s++] |= ulong(v) << (m_w);
|
|
m_bits[m_s] = ulong(v) >> sl;
|
|
m_w = (MQLARTICLES_BITBUFFER_BITS_SIZE(TInteger) - sl);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::WriteBool(bool v)
|
|
{
|
|
MQLARTICLES_KEYBYTES_CHECK_RES(0)
|
|
m_bits[m_s] |= ulong(v) << (m_w++);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CBitBuffer::WriteStringWPadd(const string &str)
|
|
{
|
|
//---
|
|
int len = StringLen(str);
|
|
int i = 0;
|
|
|
|
//--- pase 1 sobre lo que hay
|
|
const int uls_len = len >> 3;
|
|
MQLARTICLES_KEYBYTES_CHECK_RES(uls_len)
|
|
else
|
|
if((i = (m_w & 7)) != 0) // Si no es multiplo de 8
|
|
{
|
|
// No esta alineado hay que.. alinearlo
|
|
m_w += 8 - i;
|
|
}
|
|
|
|
//---- procesamos loq eu nos falta
|
|
if(m_w != 0)
|
|
{
|
|
//---
|
|
for(i = 0; i < len && m_w < 64; i++, m_w += 8)
|
|
m_bits[m_s] |= ulong(str[i]) << m_w;
|
|
|
|
//---
|
|
// Si ha salido por m_w.. igual antes de cada fncino chekeamos w
|
|
// ahi si w>=64 increma ms
|
|
//---
|
|
if(i >= len)
|
|
return;
|
|
|
|
//---
|
|
// Si se llego hasta aqui quiere decir que
|
|
// 1. aun nos queda len.. pero salimos por la condicion de m_w
|
|
len -= i; // le quitamos loq ue recorrimos
|
|
m_w = 0;
|
|
m_s++; // bloque completo
|
|
}
|
|
|
|
|
|
//---
|
|
int blocks = len >> 3;
|
|
int sob = len & 7;
|
|
|
|
//-- bloques completos
|
|
blocks += m_s;
|
|
for(; m_s < blocks; m_s++)
|
|
{
|
|
m_bits[m_s] = ulong(str[i++]) |
|
|
ulong(str[i++]) << 8 |
|
|
ulong(str[i++]) << 16 |
|
|
ulong(str[i++]) << 24 |
|
|
ulong(str[i++]) << 32 |
|
|
ulong(str[i++]) << 40 |
|
|
ulong(str[i++]) << 48 |
|
|
ulong(str[i++]) << 56;
|
|
}
|
|
|
|
//---
|
|
if(sob)
|
|
{
|
|
sob <<= 3;
|
|
m_bits[m_s] = 0ULL;
|
|
for(; m_w < sob; m_w += 8)
|
|
m_bits[m_s] |= ulong(str[i++]) << m_w;
|
|
// m_w aumenta
|
|
}
|
|
}
|
|
|
|
//---
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
#endif // MQLARTICLES_UTILS_BITS_BITFASTBUFFER_MQH
|