MQLArticles/Utils/Bits/BitFastBuffer.mqh
Nique_372 70f8467554
2026-09-03 21:50:10 -05:00

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