forked from nique_372/TSNStd
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 TSNSTD_SRC_BITBUFFER_BITFASTBUFFER_MQH
| |
#define TSNSTD_SRC_BITBUFFER_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
| |
__forceinline 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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
__forceinline 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 // TSNSTD_SRC_BITBUFFER_BITFASTBUFFER_MQH
|