//+------------------------------------------------------------------+ //| MetaTrader 5 API | //| Copyright 2000-2019, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #pragma once //+------------------------------------------------------------------+ //| Class of memory block | //+------------------------------------------------------------------+ class CMTMemPack { private: //--- constants enum { REALLOC_STEP =1024 // buffer reallocation step }; private: //--- data char *m_buffer; // data UINT m_buffer_len; // data length UINT m_buffer_max; // maximum number of bytes in buffer public: //--- constructor/destructor CMTMemPack(); ~CMTMemPack(); //--- correct the length in block void Clear() { m_buffer_len=0; } void Shutdown(); bool Reallocate(UINT growsize); //--- add unformatted data bool Add(const void *buf,UINT len); //--- swap array contents void Swap(CMTMemPack &pack); //--- buffer access char* Buffer() { return(m_buffer); } const UINT Len() const { return(m_buffer_len); } void Len(UINT val) { if(val<=m_buffer_max) m_buffer_len=val; } UINT Max() const { return(m_buffer_max); } }; //+------------------------------------------------------------------+ //| Constructor with memory pre-allocation | //+------------------------------------------------------------------+ inline CMTMemPack::CMTMemPack() : m_buffer(NULL), m_buffer_len(0), m_buffer_max(0) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ inline CMTMemPack::~CMTMemPack() { Shutdown(); } //+------------------------------------------------------------------+ //| Add data to buffer | //+------------------------------------------------------------------+ inline bool CMTMemPack::Add(const void *buf,UINT len) { //--- check if(!buf) return(false); //--- check for exceeding buffer size if(m_buffer==NULL || (len+m_buffer_len)>m_buffer_max) if(!Reallocate(len+m_buffer_len+REALLOC_STEP)) return(false); //--- append data to buffer memcpy(&m_buffer[m_buffer_len],buf,len); m_buffer_len+=len; //--- return(true); } //+------------------------------------------------------------------+ //| Swap buffer contents | //+------------------------------------------------------------------+ inline void CMTMemPack::Swap(CMTMemPack &pack) { char *buffer; // buffer UINT buffer_len; // data length UINT buffer_max; // maximum number of bytes in buffer //--- check if(this==&pack) return; //--- swap, remember own buffer buffer =m_buffer; buffer_len=m_buffer_len; buffer_max=m_buffer_max; //--- replace buffer with received one m_buffer =pack.m_buffer; m_buffer_len=pack.m_buffer_len; m_buffer_max=pack.m_buffer_max; //--- return own buffer pack.m_buffer =buffer; pack.m_buffer_len=buffer_len; pack.m_buffer_max=buffer_max; } //+------------------------------------------------------------------+ //| Deallocate memory in MemPack | //+------------------------------------------------------------------+ inline void CMTMemPack::Shutdown() { if(m_buffer) { delete[] m_buffer; m_buffer=NULL; } m_buffer_max=0; m_buffer_len=0; } //+------------------------------------------------------------------+ //| Reallocate data block | //+------------------------------------------------------------------+ inline bool CMTMemPack::Reallocate(UINT growsize) { char *newbuf; //--- check sizes if(growsize<=m_buffer_max) return(true); //--- try to allocate block of greater size if((newbuf=new(std::nothrow) char[growsize])==NULL) return(false); //--- copy values from old buffer if(m_buffer) { if(m_buffer_len>0) memcpy(newbuf,m_buffer,m_buffer_len); delete[] m_buffer; } m_buffer =newbuf; m_buffer_max=growsize; //--- return(true); } //+------------------------------------------------------------------+