diff --git a/Include/Mql/Lang/Error.mqh b/Include/Mql/Lang/Error.mqh new file mode 100644 index 0000000..69c446c Binary files /dev/null and b/Include/Mql/Lang/Error.mqh differ diff --git a/Include/Mql/Lang/GlobalVariable.mqh b/Include/Mql/Lang/GlobalVariable.mqh index f6502cc..6b42888 100644 --- a/Include/Mql/Lang/GlobalVariable.mqh +++ b/Include/Mql/Lang/GlobalVariable.mqh @@ -91,7 +91,7 @@ long AtomicVar::increment(long by) value=(long)get(); success=setOn(value+by,value); } - while(!success); + while(!success && !IsStopped()); return (value+by); } //+------------------------------------------------------------------+ diff --git a/Include/Mql/Lang/Mql.mqh b/Include/Mql/Lang/Mql.mqh index 8bb1493..856a278 100644 --- a/Include/Mql/Lang/Mql.mqh +++ b/Include/Mql/Lang/Mql.mqh @@ -19,14 +19,7 @@ //| and limitations under the License. | //+------------------------------------------------------------------+ #property strict - -#import "stdlib.ex4" -string ErrorDescription(int error_code); -int RGB(int red_value,int green_value,int blue_value); -bool CompareDoubles(double number1,double number2); -string DoubleToStrMorePrecision(double number,int precision); -string IntegerToHexString(int integer_number); -#import +#include "Error.mqh" //+------------------------------------------------------------------+ //| Mql language specific methods | //+------------------------------------------------------------------+ @@ -34,13 +27,29 @@ class Mql { public: static int getLastError() {return GetLastError();} - static string getErrorMessage(int errorCode) {return ErrorDescription(errorCode);} + static string getErrorMessage(int errorCode) {return GetErrorDescription(errorCode);} - static string doubleToString(double value,int precision) {return DoubleToStrMorePrecision(value,precision);} - static string integerToHexString(int value) {return IntegerToHexString(value);} - static int rgb(int red,int green,int blue) {return RGB(red,green,blue);} + //--- Prefer global DoubleToString function + static string doubleToString(double value,int precision) {return DoubleToString(value,precision);} + //--- Adapted from stdlib.mq4 by using `StringSetCharacter` instead of `StringSetChar` + static string integerToHexString(int value) + { + static const string digits="0123456789ABCDEF"; + string hex="00000000"; + int digit,shift=28; + for(int i=0; i<8; i++) + { + digit=(value>>shift)&0x0F; + StringSetCharacter(hex,i,digits[digit]); + shift-=4; + } + return(hex); + } + //--- Prefer Canvas/Canvas.mqh XRGB + static int rgb(int r,int g,int b) {return int(0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b));} - static bool isEqual(double a,double b) {return CompareDoubles(a,b);} + //--- Prefer Lang/Number.mqh Double::IsEqual + static bool isEqual(double a,double b) {return NormalizeDouble(a-b,8)==0;} static bool isStopped() {return IsStopped();} @@ -67,7 +76,19 @@ public: static string getProgramName() {return MQLInfoString(MQL_PROGRAM_NAME);} static string getProgramPath() {return MQLInfoString(MQL_PROGRAM_PATH);} }; - +//+------------------------------------------------------------------+ +//| Object getter/setter generator | +//| ObjectAttr generates: | +//| 1. private member m_property | +//| 2. public method setProperty | +//| 3. public method getProperty | +//| ObjectAttrBool is specific to boolean type properties: | +//| 1. private member m_isProperty | +//| 2. public method setProperty | +//| 3. public method isProperty | +//| Use *Read or *Write versions for read only or write only | +//| properties | +//+------------------------------------------------------------------+ #define ObjectAttr(Type, Private, Public) \ public:\ Type get##Public() const {return m_##Private;}\ @@ -87,13 +108,35 @@ public:\ private:\ Type m_##Private\ +#define ObjectAttrBool(Public) \ +public:\ + bool is##Public() const {return m_is##Public;}\ + void set##Public(bool value) {m_is##Public=value;}\ +private:\ + bool m_is##Public\ + +#define ObjectAttrBoolRead(Public) \ +public:\ + bool is##Public() const {return m_is##Public;}\ +private:\ + bool m_is##Public\ + +#define ObjectAttrBoolWrite(Public) \ +public:\ + void set##Public(bool value) {m_is##Public=value;}\ +private:\ + bool m_##Private\ +//+------------------------------------------------------------------+ +//| Print debug messages: only generate code for debugging runs | +//+------------------------------------------------------------------+ #ifdef _DEBUG -#define Debug(msg) Print(">>> DEBUG: In ",__FUNCTION__,"(",__FILE__,":",__LINE__,") [", msg, "]") +#define Debug(msg) PrintFormat(">>> DEBUG[%s,%d,%s]: %s",__FILE__,__LINE__,__FUNCTION__,msg); #else #define Debug(msg) #endif - -//--- Execute some code in the global scope +//+------------------------------------------------------------------+ +//| Execute some code in the global scope | +//+------------------------------------------------------------------+ #define BEGIN_EXECUTE(Name) class __Execute##Name\ {\ public:__Execute##Name()\ diff --git a/Include/Mql/Lang/Native.mqh b/Include/Mql/Lang/Native.mqh index 9ee2d37..f4b6ccd 100644 --- a/Include/Mql/Lang/Native.mqh +++ b/Include/Mql/Lang/Native.mqh @@ -48,6 +48,10 @@ #import "kernel32.dll" void RtlMoveMemory(intptr_t dest,const uchar &array[],size_t length); void RtlMoveMemory(uchar &array[],intptr_t src,size_t length); +void RtlMoveMemory(intptr_t dest,const MqlRates &array[],size_t length); +void RtlMoveMemory(MqlRates &array[],intptr_t src,size_t length); +void RtlMoveMemory(intptr_t dest,const MqlTick &value,size_t length); +void RtlMoveMemory(MqlTick &value,intptr_t src,size_t length); void RtlMoveMemory(intptr_t &dest,intptr_t src,size_t length); int lstrlen(intptr_t psz); int lstrlenW(intptr_t psz); @@ -65,19 +69,41 @@ int MultiByteToWideChar(uint codePage, //+------------------------------------------------------------------+ //| Copy the memory contents pointed by src to array | //| array parameter should be initialized to the desired size | +//| Need to import RtlMoveMemory with appropriate parameter type T | //+------------------------------------------------------------------+ -void ArrayFromPointer(uchar &array[],intptr_t src,int count=WHOLE_ARRAY) +template +void ArrayFromPointer(T &array[],intptr_t src,int count=WHOLE_ARRAY) { int size=(count==WHOLE_ARRAY)?ArraySize(array):count; - RtlMoveMemory(array,src,(size_t)size); + RtlMoveMemory(array,src,(size_t)(size*sizeof(T))); } //+------------------------------------------------------------------+ //| Copy array to the memory pointed by dest | +//| Need to import RtlMoveMemory with appropriate parameter type T | //+------------------------------------------------------------------+ -void ArrayToPointer(const uchar &array[],intptr_t dest,int count=WHOLE_ARRAY) +template +void ArrayToPointer(const T &array[],intptr_t dest,int count=WHOLE_ARRAY) { int size=(count==WHOLE_ARRAY)?ArraySize(array):count; - RtlMoveMemory(dest,array,(size_t)size); + RtlMoveMemory(dest,array,(size_t)(size*sizeof(T))); + } +//+------------------------------------------------------------------+ +//| Copy the memory contents pointed by src to value type T | +//| Need to import RtlMoveMemory with appropriate parameter type T | +//+------------------------------------------------------------------+ +template +void ValueFromPointer(T &value,intptr_t src) + { + RtlMoveMemory(value,src,(size_t)sizeof(T)); + } +//+------------------------------------------------------------------+ +//| Copy value to the memory pointed by dest | +//| Need to import RtlMoveMemory with appropriate parameter type T | +//+------------------------------------------------------------------+ +template +void ValueToPointer(const T &value,intptr_t dest) + { + RtlMoveMemory(dest,value,(size_t)sizeof(T)); } //+------------------------------------------------------------------+ //| For void** type, dereference a level to void* | diff --git a/Include/Zmq/ZmqMsg.mqh b/Include/Zmq/ZmqMsg.mqh index f17e107..88d2032 100644 --- a/Include/Zmq/ZmqMsg.mqh +++ b/Include/Zmq/ZmqMsg.mqh @@ -88,9 +88,17 @@ public: size_t size() {return zmq_msg_size(this);} - void getData(uchar &data[]); string getData(); - void setData(const uchar &data[]); + + template + void getData(T &array[]) const {ArrayFromPointer(array,data());} + template + void setData(const T &array[]) {ArrayToPointer(array,data());} + + template + void getData(T &value) const {ValueFromPointer(value,data());} + template + void setData(const T &value) {ValueToPointer(value,data());} bool more() {return 1==zmq_msg_more(this);} @@ -111,16 +119,6 @@ bool ZmqMsg::setStringData(string data,bool nullterminated) return res; } //+------------------------------------------------------------------+ -//| Get message data as bytes array | -//+------------------------------------------------------------------+ -void ZmqMsg::getData(uchar &data[]) - { - size_t size=size(); - intptr_t src=data(); - if(ArraySize(data)