diff --git a/Include/Mql/Lang/GlobalVariable.mqh b/Include/Mql/Lang/GlobalVariable.mqh new file mode 100644 index 0000000..f6502cc --- /dev/null +++ b/Include/Mql/Lang/GlobalVariable.mqh @@ -0,0 +1,242 @@ +//+------------------------------------------------------------------+ +//| Module: Lang/GlobalVariable.mqh | +//| This file is part of the mql4-lib project: | +//| https://github.com/dingmaotu/mql4-lib | +//| | +//| Copyright 2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | +//+------------------------------------------------------------------+ +#property strict +//+------------------------------------------------------------------+ +//| Encapsulates global variable functions | +//+------------------------------------------------------------------+ +class GlobalVariable + { +public: + static int total() {return GlobalVariablesTotal();} + static string name(int index) {return GlobalVariableName(index);} + static void flush() {GlobalVariablesFlush();} + + static bool exists(string name) {return GlobalVariableCheck(name);} + static datetime lastAccess(string name) {return GlobalVariableTime(name);} + + static bool makeTemp(string name) {return GlobalVariableTemp(name);} + static double get(string name) {return GlobalVariableGet(name);} + static bool get(string name,double &value) {return GlobalVariableGet(name,value);} + static datetime set(string name,double value) {return GlobalVariableSet(name,value);} + static bool setOn(string name,double value,double check) {return GlobalVariableSetOnCondition(name,value,check);} + + static bool remove(string name) {return GlobalVariableDel(name);} + static bool removeAll(string prefix=NULL,datetime before=0) {return GlobalVariablesDeleteAll(prefix,before);} + }; +//+------------------------------------------------------------------+ +//| TempVar is a variable whose life time is the same as the program | +//+------------------------------------------------------------------+ +class TempVar + { +private: + string m_name; + bool m_owned; +public: + TempVar(string name,bool create=false):m_name(name),m_owned(create) + { + if(create) + { + GlobalVariable::makeTemp(name); + } + } + ~TempVar() {if(m_owned && isValid()) {GlobalVariable::remove(m_name);}} + + bool isValid() const {return GlobalVariable::exists(m_name);} + string getName() const {return m_name;} + bool set(double value) {return GlobalVariable::set(m_name,value);} + double get() const {return GlobalVariable::get(m_name);} + bool setOn(double value,double check) {return GlobalVariable::setOn(m_name,value,check);} + datetime lastAccess() const {return GlobalVariable::lastAccess(m_name);} + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class AtomicVar: public TempVar + { +public: + AtomicVar(string name,long initial,bool create=false):TempVar(name,create) + { + set(initial); + } + long increment(long by=1); + long decrement(long by=1) {return increment(-by);} + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +long AtomicVar::increment(long by) + { + bool success=false; + long value; + do + { + value=(long)get(); + success=setOn(value+by,value); + } + while(!success); + return (value+by); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class Semaphore + { +private: + TempVar m_var; +public: + Semaphore(string name,long initial=0); + bool isValid() const {return m_var.isValid();} + bool acquire(); + void release(); + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +Semaphore::Semaphore(string name,long initial) + :m_var(name,initial!=0) + { + if(initial!=0) + { + m_var.set(initial); + } + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool Semaphore::acquire(void) + { + bool success=false; + do + { + long value=(long)m_var.get(); + if(value == 0) return false; + success=m_var.setOn(value-1,value); + } + while(!success && !IsStopped()); + return success; + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void Semaphore::release(void) + { + bool success=false; + do + { + long value=(long)m_var.get(); + success=m_var.setOn(value+1,value); + } + while(!success && !IsStopped()); + } +//+------------------------------------------------------------------+ +//| CriticalSection object for making atomic operations | +//| | +//| An exmaple of creating a global context (the creation and destroy| +//| are both enclosed between the SAME critical section): | +//| | +//| enter() | +//| if(refcount==0) create context | +//| else refcontext | +//| increase refcount | +//| leave() | +//| | +//| enter() | +//| decrease refcount | +//| if(refcount==0) context destroy | +//| leave() | +//+------------------------------------------------------------------+ +class CriticalSection + { +private: + const string m_name; +public: + CriticalSection(string name):m_name(name){} + + bool isValid() const {return m_name!=NULL;} + string getName() const {return m_name;} + + void enter() { while(!GlobalVariable::makeTemp(m_name) && !IsStopped())Sleep(100); } + bool tryEnter() { return GlobalVariable::makeTemp(m_name); } + void leave() { GlobalVariable::remove(m_name);} + }; +//+------------------------------------------------------------------+ +//| A reference counted global pointer (or handle) | +//| Generic type parameter T can be long or int depending the handle | +//| length (64bit or 32bit) | +//| HandleManager should implement 2 static methods: create & destroy| +//+------------------------------------------------------------------+ +template +class GlobalHandle + { +private: + CriticalSection m_cs; + string m_refName; + string m_counterName; +protected: + T m_ref; +public: + GlobalHandle(string sharedKey=NULL):m_cs(sharedKey) + { + m_refName=m_cs.getName()+"_Ref"; + m_counterName=m_cs.getName()+"_Count"; + if(!m_cs.isValid()) m_ref=HandleManager::create(); + else + { + m_cs.enter(); + if(!GlobalVariable::exists(m_counterName)) + { + GlobalVariable::makeTemp(m_counterName); + GlobalVariable::set(m_counterName,0); + } + if(long(GlobalVariable::get(m_counterName))==0) + { + m_ref=HandleManager::create(); + if(!GlobalVariable::exists(m_refName)) + { + GlobalVariable::makeTemp(m_refName); + GlobalVariable::set(m_refName,m_ref); + } + } + else + { + m_ref=(T)(GlobalVariable::get(m_refName)); + } + GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)+1); + m_cs.leave(); + } + } + ~GlobalHandle() + { + if(!m_cs.isValid()) {HandleManager::destroy(m_ref); return;} + m_cs.enter(); + GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)-1); + if(long(GlobalVariable::get(m_counterName))==0) + { + HandleManager::destroy(m_ref); + GlobalVariable::remove(m_refName); + GlobalVariable::remove(m_counterName); + } + m_cs.leave(); + } + + T ref() const {return m_ref;} + }; +//+------------------------------------------------------------------+ diff --git a/Include/Mql/Lang/Mql.mqh b/Include/Mql/Lang/Mql.mqh new file mode 100644 index 0000000..8bb1493 --- /dev/null +++ b/Include/Mql/Lang/Mql.mqh @@ -0,0 +1,105 @@ +//+------------------------------------------------------------------+ +//| Module: Lang/Mql.mqh | +//| This file is part of the mql4-lib project: | +//| https://github.com/dingmaotu/mql4-lib | +//| | +//| Copyright 2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| 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 +//+------------------------------------------------------------------+ +//| Mql language specific methods | +//+------------------------------------------------------------------+ +class Mql + { +public: + static int getLastError() {return GetLastError();} + static string getErrorMessage(int errorCode) {return ErrorDescription(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);} + + static bool isEqual(double a,double b) {return CompareDoubles(a,b);} + + static bool isStopped() {return IsStopped();} + + static int getCodePage() {return MQLInfoInteger(MQL_CODEPAGE);} + static ENUM_PROGRAM_TYPE getProgramType() {return(ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE);} + static bool isScript() {return Mql::getProgramType()==PROGRAM_SCRIPT;} + static bool isExpert() {return Mql::getProgramType()==PROGRAM_EXPERT;} + static bool isIndicator() {return Mql::getProgramType()==PROGRAM_INDICATOR;} + static bool isDllAllowed() {return MQLInfoInteger(MQL_DLLS_ALLOWED)!=0;} + static bool isTradeAllowed() {return MQLInfoInteger(MQL_TRADE_ALLOWED)!=0;} + static bool isSignalsAllowed() {return MQLInfoInteger(MQL_SIGNALS_ALLOWED)!=0;} + static bool isDebug() {return MQLInfoInteger(MQL_DEBUG)!=0;} + static bool isProfiling() {return MQLInfoInteger(MQL_PROFILER)!=0;} + static bool isTesting() {return MQLInfoInteger(MQL_TESTER)!=0;} + static bool isOptimizing() {return MQLInfoInteger(MQL_OPTIMIZATION)!=0;} + static bool isVisual() {return MQLInfoInteger(MQL_VISUAL_MODE)!=0;} + static bool isFrameMode() {return MQLInfoInteger(MQL_FRAME_MODE)!=0;} + static ENUM_LICENSE_TYPE getLicenseType() {return(ENUM_LICENSE_TYPE)MQLInfoInteger(MQL_LICENSE_TYPE);} + static bool isFreeLicense() {return Mql::getLicenseType()==LICENSE_FREE;} + static bool isDemoLicense() {return Mql::getLicenseType()==LICENSE_DEMO;} + static bool isFullLicense() {return Mql::getLicenseType()==LICENSE_FULL;} + static bool isTimeLicense() {return Mql::getLicenseType()==LICENSE_TIME;} + + static string getProgramName() {return MQLInfoString(MQL_PROGRAM_NAME);} + static string getProgramPath() {return MQLInfoString(MQL_PROGRAM_PATH);} + }; + +#define ObjectAttr(Type, Private, Public) \ +public:\ + Type get##Public() const {return m_##Private;}\ + void set##Public(Type value) {m_##Private=value;}\ +private:\ + Type m_##Private\ + +#define ObjectAttrRead(Type, Private, Public) \ +public:\ + Type get##Public() const {return m_##Private;}\ +private:\ + Type m_##Private\ + +#define ObjectAttrWrite(Type, Private, Public) \ +public:\ + void set##Public(Type value) {m_##Private=value;}\ +private:\ + Type m_##Private\ + +#ifdef _DEBUG +#define Debug(msg) Print(">>> DEBUG: In ",__FUNCTION__,"(",__FILE__,":",__LINE__,") [", msg, "]") +#else +#define Debug(msg) +#endif + +//--- Execute some code in the global scope +#define BEGIN_EXECUTE(Name) class __Execute##Name\ + {\ + public:__Execute##Name()\ + { +#define END_EXECUTE(Name) \ + }\ + }\ +__execute##Name; +//+------------------------------------------------------------------+ diff --git a/Include/Mql/Lang/Native.mqh b/Include/Mql/Lang/Native.mqh new file mode 100644 index 0000000..11eea60 --- /dev/null +++ b/Include/Mql/Lang/Native.mqh @@ -0,0 +1,200 @@ +//+------------------------------------------------------------------+ +//| Module: Lang/Native.mqh | +//| This file is part of the mql4-lib project: | +//| https://github.com/dingmaotu/mql4-lib | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | +//+------------------------------------------------------------------+ +#property strict + +// Assume MT5 is 64bit, which is the default. +// Even though MT5 can be 32bit, there is no way to detect this +// by using preprocessor macros. Instead, MetaQuotes provides a +// function called IsX64 to detect this dynamically + +// This is just absurd. Why do you want to know the bitness of +// the runtime? To define pointer related entities at compile time! +// All integer types in MQL is uniform on both 32bit or 64bit +// architectures, so it is almost useless to have a runtime function IsX64. + +// Why not a __X64__? +#ifdef __MQL5__ +#define __X64__ +#endif + +#ifdef __X64__ +#define intptr_t long +#define uintptr_t ulong +#define size_t long +#else +#define intptr_t int +#define uintptr_t uint +#define size_t int +#endif + +//--- _WIN32_WINNT version constants +#define _WIN32_WINNT_NT4 0x0400 // Windows NT 4.0 +#define _WIN32_WINNT_WIN2K 0x0500 // Windows 2000 +#define _WIN32_WINNT_WINXP 0x0501 // Windows XP +#define _WIN32_WINNT_WS03 0x0502 // Windows Server 2003 +#define _WIN32_WINNT_WIN6 0x0600 // Windows Vista +#define _WIN32_WINNT_VISTA 0x0600 // Windows Vista +#define _WIN32_WINNT_WS08 0x0600 // Windows Server 2008 +#define _WIN32_WINNT_LONGHORN 0x0600 // Windows Vista +#define _WIN32_WINNT_WIN7 0x0601 // Windows 7 +#define _WIN32_WINNT_WIN8 0x0602 // Windows 8 +#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1 +#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 // Windows 10 +#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10 + +//--- define you own for your target platform +#define WINVER 0x0A00 +#define _WIN32_WINNT 0x0A00 + +#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000 +#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200 + +#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,intptr_t src,size_t length); +int lstrlen(intptr_t psz); +int lstrlenW(intptr_t psz); +uintptr_t lstrcpynW(string &s1,uintptr_t s2,int length); +uintptr_t lstrcpynW(uintptr_t s1,string &s2,int length); + +int MultiByteToWideChar(uint codePage, + uint flags, + const intptr_t multiByteString, + int lengthMultiByte, + string &str, + int length + ); +uint FormatMessageW(uint dwFlags, + intptr_t lpSource, + uint dwMessageId, + uint dwLanguageId, + ushort &buffer[], + uint nSize, + intptr_t Arguments + ); +#import + +//--- This is a standard header of the official MetaTrader distribution +#include +//+------------------------------------------------------------------+ +//| Copy the memory contents pointed by src to array | +//| array parameter should be initialized to the desired size | +//+------------------------------------------------------------------+ +void ArrayFromPointer(uchar &array[],intptr_t src,int count=WHOLE_ARRAY) + { + int size=(count==WHOLE_ARRAY)?ArraySize(array):count; + RtlMoveMemory(array,src,(size_t)size); + } +//+------------------------------------------------------------------+ +//| Copy array to the memory pointed by dest | +//+------------------------------------------------------------------+ +void ArrayToPointer(const uchar &array[],intptr_t dest,int count=WHOLE_ARRAY) + { + int size=(count==WHOLE_ARRAY)?ArraySize(array):count; + RtlMoveMemory(dest,array,(size_t)size); + } +//+------------------------------------------------------------------+ +//| For void** type, dereference a level to void* | +//+------------------------------------------------------------------+ +intptr_t DereferencePointer(intptr_t pointer) + { + intptr_t res=0; + RtlMoveMemory(res,pointer,sizeof(intptr_t)); + return res; + } +//+------------------------------------------------------------------+ +//| Read a valid wide character string to the MQL environment | +//+------------------------------------------------------------------+ +string StringFromPointer(intptr_t psz,int len=0) + { + if(len < 0) return NULL; + if(len==0) {len=lstrlenW(psz);} + string res; + StringInit(res,len+1); + lstrcpynW(res,psz,len+1); + return res; + } +//+------------------------------------------------------------------+ +//| Get the pointer address of a string | +//+------------------------------------------------------------------+ +uintptr_t StringToPointer(string &s) + { + return lstrcpynW(s,0,0); + } +//+------------------------------------------------------------------+ +//| Read a valid utf-8 string to the MQL environment | +//| With this function, there is no need to copy the string to char | +//| array, and convert with CharArrayToString | +//+------------------------------------------------------------------+ +string StringFromUtf8Pointer(intptr_t psz,int len) + { + if(len < 0) return NULL; + string res; + int required=MultiByteToWideChar(CP_UTF8,0,psz,len,res,0); + StringInit(res,required); + int resLength = MultiByteToWideChar(CP_UTF8,0,psz,len,res,required); + if(resLength != required) + { + return NULL; + } + else + { + return res; + } + } +//+------------------------------------------------------------------+ +//| for null-terminated string | +//+------------------------------------------------------------------+ +string StringFromUtf8Pointer(intptr_t psz) + { + if(psz==0) return NULL; + int len=lstrlen(psz); + if(len==0) return NULL; + return StringFromUtf8Pointer(psz, len); + } +//+------------------------------------------------------------------+ +//| Convert a utf-8 byte array to a string | +//+------------------------------------------------------------------+ +string StringFromUtf8(const uchar &utf8[]) + { + return CharArrayToString(utf8, 0, -1, CP_UTF8); + } +//+------------------------------------------------------------------+ +//| Convert a string to a utf-8 byte array | +//+------------------------------------------------------------------+ +void StringToUtf8(const string str,uchar &utf8[],bool ending=true) + { + if(!ending && str=="") return; + int count=ending ? -1 : StringLen(str); + StringToCharArray(str,utf8,0,count,CP_UTF8); + } +//+------------------------------------------------------------------+ +//| Get system defined error code message | +//+------------------------------------------------------------------+ +string GetErrorMessage(int errorCode) + { + static ushort buffer[64*1024]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + 0,errorCode,0,buffer,ArraySize(buffer),0); + return ShortArrayToString(buffer); + } +//+------------------------------------------------------------------+ diff --git a/Include/Zmq/AtomicCounter.mqh b/Include/Zmq/AtomicCounter.mqh index 4cf58cc..14d1b9c 100644 --- a/Include/Zmq/AtomicCounter.mqh +++ b/Include/Zmq/AtomicCounter.mqh @@ -1,11 +1,26 @@ //+------------------------------------------------------------------+ -//| AtomicCounter.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: AtomicCounter.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ #property strict -#include "Common.mqh" +#include #import "libzmq.dll" intptr_t zmq_atomic_counter_new(void); diff --git a/Include/Zmq/Common.mqh b/Include/Zmq/Common.mqh deleted file mode 100644 index 7a46dd3..0000000 --- a/Include/Zmq/Common.mqh +++ /dev/null @@ -1,117 +0,0 @@ -//+------------------------------------------------------------------+ -//| Common.mqh | -//| This file is part of mql4-lib project (Lang/Native.mqh): | -//| (github.com/dingmaotu/mql4-lib) | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | -//+------------------------------------------------------------------+ -#property strict - -#include "Errno.mqh" - -// Assume MT5 is 64bit, which is the default. -// Even though MT5 can be 32bit, there is no way to detect this -// by using preprocessor macros. Instead, MetaQuotes provides a -// function called IsX64 to detect this dynamically - -// This is just absurd. Why do you want to know the bitness of -// the runtime? To define pointer related entities at compile time! -// All integer types in MQL is uniform on both 32bit or 64bit -// architectures, so it is almost useless to have a runtime function IsX64. - -// Why not a __X64__? -#ifdef __MQL5__ -#define __X64__ -#endif - -#ifdef __X64__ -#define intptr_t long -#define uintptr_t ulong -#define size_t long -#else -#define intptr_t int -#define uintptr_t uint -#define size_t int -#endif - -#import "kernel32.dll" -void RtlMoveMemory(intptr_t dest,const uchar &array[],size_t length); -void RtlMoveMemory(uchar &array[],intptr_t src,size_t length); -int lstrlen(intptr_t psz); -int MultiByteToWideChar(uint codePage, - uint flags, - const intptr_t multiByteString, - int lengthMultiByte, - string &str, - int length - ); -#import -//+------------------------------------------------------------------+ -//| Copy the memory contents pointed by src to array | -//| array parameter should be initialized to the desired size | -//+------------------------------------------------------------------+ -void ArrayFromPointer(uchar &array[],intptr_t src,int count=WHOLE_ARRAY) - { - int size=(count==WHOLE_ARRAY)?ArraySize(array):count; - RtlMoveMemory(array,src,(size_t)size); - } -//+------------------------------------------------------------------+ -//| Copy array to the memory pointed by dest | -//+------------------------------------------------------------------+ -void ArrayToPointer(const uchar &array[],intptr_t dest,int count=WHOLE_ARRAY) - { - int size=(count==WHOLE_ARRAY)?ArraySize(array):count; - RtlMoveMemory(dest,array,(size_t)size); - } -//+------------------------------------------------------------------+ -//| Read a valid utf-8 string to the MQL environment | -//| With this function, there is no need to copy the string to char | -//| array, and convert with CharArrayToString | -//+------------------------------------------------------------------+ -string StringFromUtf8Pointer(intptr_t psz,int len) - { - if(len < 0) return NULL; - string res; - int required=MultiByteToWideChar(CP_UTF8,0,psz,len,res,0); - StringInit(res,required); - int resLength = MultiByteToWideChar(CP_UTF8,0,psz,len,res,required); - if(resLength != required) - { - return NULL; - } - else - { - return res; - } - } -//+------------------------------------------------------------------+ -//| for null-terminated string | -//+------------------------------------------------------------------+ -string StringFromUtf8Pointer(intptr_t psz) - { - int len=lstrlen(psz); - return StringFromUtf8Pointer(psz, len); - } -//+------------------------------------------------------------------+ -//| Convert a utf-8 byte array to a string | -//+------------------------------------------------------------------+ -string StringFromUtf8(const uchar &utf8[]) - { - return CharArrayToString(utf8, 0, -1, CP_UTF8); - } -//+------------------------------------------------------------------+ -//| Convert a string to a utf-8 byte array | -//+------------------------------------------------------------------+ -void StringToUtf8(const string str,uchar &utf8[],bool ending=true) - { - if(!ending && str=="") return; - int count=ending ? -1 : StringLen(str); - StringToCharArray(str,utf8,0,count,CP_UTF8); - } - -#ifdef _DEBUG -#define Debug(msg) Print(">>> DEBUG: In ",__FUNCTION__,"(",__FILE__,":",__LINE__,") [", msg, "]") -#else -#define Debug(msg) -#endif -//+------------------------------------------------------------------+ diff --git a/Include/Zmq/Context.mqh b/Include/Zmq/Context.mqh index 920667d..7aff7c6 100644 --- a/Include/Zmq/Context.mqh +++ b/Include/Zmq/Context.mqh @@ -1,12 +1,28 @@ //+------------------------------------------------------------------+ -//| Context.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: Context.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ - -#include "Common.mqh" +#property strict +#include +#include +#include #include "SocketOptions.mqh" -#include "GlobalHandle.mqh" //--- Context options #define ZMQ_IO_THREADS 1 diff --git a/Include/Zmq/Errno.mqh b/Include/Zmq/Errno.mqh index 000ece4..de51be7 100644 --- a/Include/Zmq/Errno.mqh +++ b/Include/Zmq/Errno.mqh @@ -1,5 +1,22 @@ //+------------------------------------------------------------------+ -//| Errno.mqh | +//| Module: Errno.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ // Following error codes come from Microsoft CRT header errno.h diff --git a/Include/Zmq/GlobalHandle.mqh b/Include/Zmq/GlobalHandle.mqh deleted file mode 100644 index 3de03b5..0000000 --- a/Include/Zmq/GlobalHandle.mqh +++ /dev/null @@ -1,122 +0,0 @@ -//+------------------------------------------------------------------+ -//| GlobalHandle.mqh | -//| This file is part of mql4-lib project (Lang/GlobalVariable.mqh): | -//| (github.com/dingmaotu/mql4-lib) | -//| Copyright 2017, Li Ding | -//| dingmaotu@hotmail.com | -//+------------------------------------------------------------------+ -#property strict -//+------------------------------------------------------------------+ -//| Wraps global variable functions | -//+------------------------------------------------------------------+ -class GlobalVariable - { -public: - static int total() {return GlobalVariablesTotal();} - static string name(int index) {return GlobalVariableName(index);} - static void flush() {GlobalVariablesFlush();} - - static bool exists(string name) {return GlobalVariableCheck(name);} - static datetime lastAccess(string name) {return GlobalVariableTime(name);} - - static bool makeTemp(string name) {return GlobalVariableTemp(name);} - static double get(string name) {return GlobalVariableGet(name);} - static bool get(string name,double &value) {return GlobalVariableGet(name,value);} - static datetime set(string name,double value) {return GlobalVariableSet(name,value);} - static bool setOn(string name,double value,double check) {return GlobalVariableSetOnCondition(name,value,check);} - - static bool remove(string name) {return GlobalVariableDel(name);} - static bool removeAll(string prefix=NULL,datetime before=0) {return GlobalVariablesDeleteAll(prefix,before);} - }; -//+------------------------------------------------------------------+ -//| CriticalSection object for making atomic operations | -//| | -//| An exmaple of creating a global context (the creation and destroy| -//| are both enclosed between the SAME critical section): | -//| | -//| enter() | -//| if(refcount==0) create context | -//| else refcontext | -//| increase refcount | -//| leave() | -//| | -//| enter() | -//| decrease refcount | -//| if(refcount==0) context destroy | -//| leave() | -//+------------------------------------------------------------------+ -class CriticalSection - { -private: - const string m_name; -public: - CriticalSection(string name):m_name(name){} - - bool isValid() const {return m_name!=NULL;} - string getName() const {return m_name;} - - void enter() { while(!GlobalVariable::makeTemp(m_name) && !IsStopped())Sleep(100); } - bool tryEnter() { return GlobalVariable::makeTemp(m_name); } - void leave() { GlobalVariable::remove(m_name);} - }; -//+------------------------------------------------------------------+ -//| A reference counted global pointer (or handle) | -//| HandleManager should implement 2 static methods: create & destroy| -//+------------------------------------------------------------------+ -template -class GlobalHandle - { -private: - CriticalSection m_cs; - string m_refName; - string m_counterName; -protected: - T m_ref; -public: - GlobalHandle(string sharedKey=NULL):m_cs(sharedKey) - { - m_refName=m_cs.getName()+"_Ref"; - m_counterName=m_cs.getName()+"_Count"; - if(!m_cs.isValid()) m_ref=HandleManager::create(); - else - { - m_cs.enter(); - if(!GlobalVariable::exists(m_counterName)) - { - GlobalVariable::makeTemp(m_counterName); - GlobalVariable::set(m_counterName,0); - } - if(long(GlobalVariable::get(m_counterName))==0) - { - m_ref=HandleManager::create(); - if(!GlobalVariable::exists(m_refName)) - { - GlobalVariable::makeTemp(m_refName); - GlobalVariable::set(m_refName,m_ref); - } - } - else - { - m_ref=(T)(GlobalVariable::get(m_refName)); - } - GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)+1); - m_cs.leave(); - } - } - ~GlobalHandle() - { - if(!m_cs.isValid()) {HandleManager::destroy(m_ref); return;} - m_cs.enter(); - GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)-1); - if(long(GlobalVariable::get(m_counterName))==0) - { - HandleManager::destroy(m_ref); - GlobalVariable::remove(m_refName); - GlobalVariable::remove(m_counterName); - } - m_cs.leave(); - } - - T ref() const {return m_ref;} - }; -//+------------------------------------------------------------------+ diff --git a/Include/Zmq/Socket.mqh b/Include/Zmq/Socket.mqh index 73dc02e..2bb2aa6 100644 --- a/Include/Zmq/Socket.mqh +++ b/Include/Zmq/Socket.mqh @@ -1,11 +1,27 @@ //+------------------------------------------------------------------+ -//| Socket.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: Socket.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ #property strict -#include "Common.mqh" +#include +#include #include "Context.mqh" #include "SocketOptions.mqh" #include "ZmqMsg.mqh" diff --git a/Include/Zmq/SocketOptions.mqh b/Include/Zmq/SocketOptions.mqh index bbf602f..b5e90fd 100644 --- a/Include/Zmq/SocketOptions.mqh +++ b/Include/Zmq/SocketOptions.mqh @@ -1,13 +1,26 @@ //+------------------------------------------------------------------+ -//| Socket.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: SocketOptions.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ -#property copyright "Copyright 2016, Li Ding" -#property link "dingmaotu@hotmail.com" #property strict -#include "Common.mqh" +#include #import "libzmq.dll" // We can overload the same function for different data types diff --git a/Include/Zmq/Z85.mqh b/Include/Zmq/Z85.mqh index 15dc980..b5fc683 100644 --- a/Include/Zmq/Z85.mqh +++ b/Include/Zmq/Z85.mqh @@ -1,13 +1,26 @@ //+------------------------------------------------------------------+ -//| Z85.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: Z85.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ -#property copyright "Copyright 2016, Li Ding" -#property link "dingmaotu@hotmail.com" #property strict -#include "Common.mqh" +#include #import "libzmq.dll" // Encode data with Z85 encoding. Returns 0(NULL) if failed diff --git a/Include/Zmq/Zmq.mqh b/Include/Zmq/Zmq.mqh index 332139e..173d11f 100644 Binary files a/Include/Zmq/Zmq.mqh and b/Include/Zmq/Zmq.mqh differ diff --git a/Include/Zmq/ZmqMsg.mqh b/Include/Zmq/ZmqMsg.mqh index ebd0a21..3d5ffa3 100644 --- a/Include/Zmq/ZmqMsg.mqh +++ b/Include/Zmq/ZmqMsg.mqh @@ -1,12 +1,26 @@ //+------------------------------------------------------------------+ -//| ZmqMsg.mqh | -//| Copyright 2016, Li Ding | -//| dingmaotu@hotmail.com | +//| Module: ZmqMsg.mqh | +//| This file is part of the mql-zmq project: | +//| https://github.com/dingmaotu/mql-zmq | +//| | +//| Copyright 2016-2017 Li Ding | +//| | +//| Licensed under the Apache License, Version 2.0 (the "License"); | +//| you may not use this file except in compliance with the License. | +//| You may obtain a copy of the License at | +//| | +//| http://www.apache.org/licenses/LICENSE-2.0 | +//| | +//| Unless required by applicable law or agreed to in writing, | +//| software distributed under the License is distributed on an | +//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | +//| either express or implied. | +//| See the License for the specific language governing permissions | +//| and limitations under the License. | //+------------------------------------------------------------------+ -#property copyright "Copyright 2016, Li Ding" -#property link "dingmaotu@hotmail.com" #property strict -#include "Common.mqh" +#include +#include //+------------------------------------------------------------------+ //| 0MQ Message struct | //+------------------------------------------------------------------+ @@ -121,7 +135,8 @@ string ZmqMsg::getData() void ZmqMsg::setData(const uchar &data[]) { intptr_t dest=data(); - ArrayToPointer(data,dest); + size_t size=size(); + ArrayToPointer(data,dest,size); } //+------------------------------------------------------------------+ //| Wraps zmq_msg_gets: get metadata associated with the msg |