//+------------------------------------------------------------------+ //| 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 void WriteInteger(const TInteger v); template 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 void CBitBuffer::WriteIntegerArray(const TInteger &v[]) { const int t = ArraySize(v); for(int i = 0; i < t; i++) WriteInteger(v[i]); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template 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