diff --git a/Convert.extern.h b/Convert.extern.h index a2f4bd2db..a21d6599e 100644 --- a/Convert.extern.h +++ b/Convert.extern.h @@ -25,8 +25,8 @@ #pragma once // Includes. -#include #include +#include // Define external global functions. double NormalizeDouble(double value, int digits) { return std::round(value / digits) * digits; } @@ -45,7 +45,7 @@ string DoubleToString(double value, int digits = 8) { string ShortToString(unsigned short symbol_code) { std::stringstream ss; - ss << symbol_code; + ss << (char)symbol_code; return ss.str(); } #endif diff --git a/DateTime.mqh b/DateTime.mqh index 2f9e1fa30..ab7abd69a 100644 --- a/DateTime.mqh +++ b/DateTime.mqh @@ -129,8 +129,8 @@ class DateTime { } #ifdef __debug_verbose__ - string _passed = - "time now " + (string)dt_curr.GetTimestamp() + ", time last " + (string)dt_last.GetTimestamp() + " "; + string _passed = "time now " + TimeToString(dt_curr.GetTimestamp()) + ", time last " + + TimeToString(dt_last.GetTimestamp()) + " "; if (_update) { _passed += "updating time "; diff --git a/DictSlot.mqh b/DictSlot.mqh index 41a85408d..eea48969d 100644 --- a/DictSlot.mqh +++ b/DictSlot.mqh @@ -40,6 +40,8 @@ class DictSlot { DictSlot(unsigned char flags = 0) : _flags(flags) {} + DictSlot(const DictSlot& r) : _flags(r._flags), key(r.key), value(r.value) {} + bool IsValid() { return !bool(_flags & DICT_SLOT_INVALID); } bool HasKey() { return bool(_flags & DICT_SLOT_HAS_KEY); } diff --git a/DictStruct.mqh b/DictStruct.mqh index 72e841a0e..5c47a1a06 100644 --- a/DictStruct.mqh +++ b/DictStruct.mqh @@ -89,17 +89,6 @@ class DictStruct : public DictBase { THIS_ATTR _mode = right._mode; } - void operator=(DictStruct& right) { - Clear(); - Resize(right.GetSlotCount()); - for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - THIS_ATTR _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; - } - THIS_ATTR _DictSlots_ref._num_used = right._DictSlots_ref._num_used; - THIS_ATTR _current_id = right._current_id; - THIS_ATTR _mode = right._mode; - } - void Clear() { for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) { THIS_ATTR _DictSlots_ref.DictSlots[i].SetFlags(0); @@ -124,7 +113,7 @@ class DictStruct : public DictBase { /** * Inserts value using hashless key. */ - bool Push(V& value) { + bool Push(const V& value) { if (!InsertInto(THIS_ATTR _DictSlots_ref, value)) return false; return true; } @@ -136,6 +125,8 @@ class DictStruct : public DictBase { /** * Inserts value using hashless key. + * + * @todo Get rid of this method. */ #ifdef __MQL__ template <> @@ -385,7 +376,7 @@ class DictStruct : public DictBase { /** * Inserts hashless value into given array of DictSlots. */ - bool InsertInto(DictSlotsRef& dictSlotsRef, V& value) { + bool InsertInto(DictSlotsRef& dictSlotsRef, const V& value) { if (THIS_ATTR _mode == DictModeUnknown) THIS_ATTR _mode = DictModeList; else if (THIS_ATTR _mode != DictModeList) { diff --git a/Object.extern.h b/Object.extern.h index f8b97dbd8..0b4bd3e35 100644 --- a/Object.extern.h +++ b/Object.extern.h @@ -25,5 +25,12 @@ * Includes external declarations related to objects. */ #ifndef __MQL__ -extern void *GetPointer(void *anyobject); +template +X* GetPointer(X& value) { + return &value; +} +template +X* GetPointer(X* ptr) { + return ptr; +} #endif diff --git a/Refs.struct.h b/Refs.struct.h index c97ad4b20..3225c782a 100644 --- a/Refs.struct.h +++ b/Refs.struct.h @@ -31,9 +31,15 @@ #endif // Includes. +#include + #include "Refs.rc.h" #include "Std.h" +#ifdef EMSCRIPTEN +#include +#endif + class Dynamic; // Forward class declaration. template @@ -87,6 +93,10 @@ struct SimpleRef { } }; +template +using base_type = + typename std::remove_cv::type>::type>::type; + /** * Class used to hold strong reference to reference-counted object. */ @@ -97,21 +107,34 @@ struct Ref { */ X* ptr_object; +#ifdef EMSCRIPTEN + typedef X element_type; +#endif + public: /** * Constructor. */ - Ref(X* _ptr) { THIS_REF = _ptr; } + Ref(X* _ptr) { + ptr_object = nullptr; + THIS_REF = _ptr; + } /** * Constructor. */ - Ref(Ref& ref) { THIS_REF = ref.Ptr(); } + Ref(const Ref& ref) { + ptr_object = nullptr; + Set(ref.Ptr()); + } /** * Constructor. */ - Ref(WeakRef& ref) { THIS_REF = ref.Ptr(); } + Ref(WeakRef& ref) { + ptr_object = nullptr; + Set(ref.Ptr()); + } /** * Constructor. @@ -126,7 +149,11 @@ struct Ref { /** * Returns pointer to target object. */ - X* Ptr() { return ptr_object; } + X* Ptr() const { return ptr_object; } + +#ifdef EMSCRIPTEN + X* get() const { return ptr_object; } +#endif /** * Checks whether any object is referenced. @@ -208,7 +235,11 @@ struct Ref { /** * Makes a strong reference to the given object. */ - X* operator=(X* _ptr) { + X* operator=(X* _ptr) { return Set(_ptr); } + /** + * Makes a strong reference to the given object. + */ + X* Set(X* _ptr) { if (ptr_object == _ptr) { // Assigning the same object. return Ptr(); @@ -240,18 +271,12 @@ struct Ref { /** * Makes a strong reference to the given weakly-referenced object. */ - X* operator=(WeakRef& right) { - THIS_REF = right.Ptr(); - return Ptr(); - } + X* operator=(const WeakRef& right) { return Set((X*)right.Ptr()); } /** * Makes a strong reference to the strongly-referenced object. */ - X* operator=(Ref& right) { - THIS_REF = right.Ptr(); - return Ptr(); - } + X* operator=(const Ref& right) { return Set((X*)right.Ptr()); } /** * Equality operator. @@ -259,6 +284,11 @@ struct Ref { bool operator==(const Ref& r) { return ptr_object != NULL && ptr_object == r.ptr_object; } }; +template +Ref make_ref() { + return Ref(); +} + /** * Class used to hold weak reference to reference-counted object. */ diff --git a/Serializer/SerializerConverter.h b/Serializer/SerializerConverter.h index 7e9490239..571bb1353 100644 --- a/Serializer/SerializerConverter.h +++ b/Serializer/SerializerConverter.h @@ -39,6 +39,10 @@ class SerializerNode; #include "SerializerDict.h" #include "SerializerNode.h" +#ifdef __debug__ +#include "SerializerJson.h" +#endif + class SerializerConverter { public: SerializerNode* root_node; @@ -70,8 +74,9 @@ class SerializerConverter { SerializerConverter _converter(_serializer.GetRoot(), serializer_flags); #ifdef __debug__ Print("FromObject(): serializer flags: ", serializer_flags); - Print("FromObject(): result: ", - _serializer.GetRoot() != NULL ? _serializer.GetRoot().ToString(SERIALIZER_JSON_NO_WHITESPACES) : "NULL"); + Print("FromObject(): result: ", _serializer.GetRoot() != NULL + ? _serializer.GetRoot() PTR_DEREF ToString(SERIALIZER_JSON_NO_WHITESPACES) + : "NULL"); #endif return _converter; } @@ -84,8 +89,9 @@ class SerializerConverter { SerializerConverter _converter(_serializer.GetRoot(), serializer_flags); #ifdef __debug__ Print("FromObject(): serializer flags: ", serializer_flags); - Print("FromObject(): result: ", - _serializer.GetRoot() != NULL ? _serializer.GetRoot().ToString(SERIALIZER_JSON_NO_WHITESPACES) : "NULL"); + Print("FromObject(): result: ", _serializer.GetRoot() != NULL + ? _serializer.GetRoot() PTR_DEREF ToString(SERIALIZER_JSON_NO_WHITESPACES) + : "NULL"); #endif return _converter; } @@ -115,7 +121,7 @@ class SerializerConverter { SerializerConverter _converter(((C*)NULL)PTR_DEREF Parse(arg), 0); #ifdef __debug__ Print("FromString(): result: ", - _converter.Node() != NULL ? _converter.Node().ToString(SERIALIZER_JSON_NO_WHITESPACES) : "NULL"); + _converter.Node() != NULL ? _converter.Node() PTR_DEREF ToString(SERIALIZER_JSON_NO_WHITESPACES) : "NULL"); #endif return _converter; } diff --git a/Serializer/SerializerJson.h b/Serializer/SerializerJson.h index fd3ed5fed..491954708 100644 --- a/Serializer/SerializerJson.h +++ b/Serializer/SerializerJson.h @@ -195,7 +195,7 @@ class SerializerJson { #ifdef __debug__ Print("SerializerJson: Value \"" + extracted + "\" for key " + - (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif expectingValue = false; @@ -217,7 +217,8 @@ class SerializerJson { } #ifdef __debug__ - Print("SerializerJson: Entering object for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + Print("SerializerJson: Entering object for key " + + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif node = new SerializerNode(SerializerNodeObject, current, key); @@ -237,16 +238,18 @@ class SerializerJson { } #ifdef __debug__ - Print("SerializerJson: Leaving object for key " + (current != NULL && current.GetKeyParam() != NULL - ? ("\"" + current.GetKeyParam().ToString() + "\"") - : "")); + Print("SerializerJson: Leaving object for key " + + (current != NULL && current PTR_DEREF GetKeyParam() != NULL + ? ("\"" + current PTR_DEREF GetKeyParam() PTR_DEREF ToString() + "\"") + : "")); #endif current = PTR_ATTRIB(current, GetParent()); expectingValue = false; } else if (ch == '[') { #ifdef __debug__ - Print("SerializerJson: Entering list for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + Print("SerializerJson: Entering list for key " + + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif if (expectingKey) { @@ -264,7 +267,8 @@ class SerializerJson { key = NULL; } else if (ch == ']') { #ifdef __debug__ - Print("SerializerJson: Leaving list for key " + (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + Print("SerializerJson: Leaving list for key " + + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif if (expectingKey || expectingValue || PTR_ATTRIB(current, GetType()) != SerializerNodeArray) { @@ -285,8 +289,8 @@ class SerializerJson { value = StringFind(extracted, ".") != -1 ? SerializerNodeParam::FromValue(StringToDouble(extracted)) : SerializerNodeParam::FromValue(StringToInteger(extracted)); #ifdef __debug__ - Print("SerializerJson: Value " + value.AsString() + " for key " + - (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + Print("SerializerJson: Value " + value PTR_DEREF AsString() + " for key " + + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif PTR_ATTRIB(current, AddChild(new SerializerNode(PTR_ATTRIB(current, GetType()) == SerializerNodeObject @@ -306,8 +310,8 @@ class SerializerJson { value = SerializerNodeParam::FromValue(ch == 't' ? true : false); #ifdef __debug__ - Print("SerializerJson: Value " + (value.ToBool() ? "true" : "false") + " for key " + - (key != NULL ? ("\"" + key.ToString() + "\"") : "")); + Print(string("SerializerJson: Value ") + (value PTR_DEREF ToBool() ? "true" : "false") + " for key " + + (key != NULL ? ("\"" + key PTR_DEREF ToString() + "\"") : "")); #endif // Skipping value. diff --git a/String.extern.h b/String.extern.h index b1043fd2b..55a0f4f78 100644 --- a/String.extern.h +++ b/String.extern.h @@ -78,6 +78,8 @@ void PrintTo(std::ostream& out, Arg&& arg, Args&&... args) { out << std::forward(arg); using expander = int[]; (void)expander{0, (void(out << std::forward(args)), 0)...}; + out << "\n"; + out.flush(); } template diff --git a/Task/Task.h b/Task/Task.h index 0854b9d18..c2ca184cc 100644 --- a/Task/Task.h +++ b/Task/Task.h @@ -30,10 +30,6 @@ #pragma once #endif -// Prevents processing this includes file for the second time. -#ifndef TASK_H -#define TASK_H - // Includes. #include "../DictStruct.mqh" #include "../Terminal.define.h" @@ -54,12 +50,12 @@ class Task : public Taskable { * Class constructor. */ Task() {} - Task(TaskEntry &_entry) { Add(_entry); } + Task(const TaskEntry &_entry) { Add(_entry); } /** * Class copy constructor. */ - Task(Task &_task) { tasks = PTR_TO_REF(_task.GetTasks()); } + Task(const Task &_task) { tasks = PTR_TO_REF(_task.GetTasks()); } /** * Class deconstructor. @@ -71,7 +67,7 @@ class Task : public Taskable { /** * Adds new task. */ - void Add(TaskEntry &_entry) { tasks.Push(_entry); } + void Add(const TaskEntry &_entry) { tasks.Push(_entry); } /* Virtual methods */ @@ -214,7 +210,7 @@ class Task : public Taskable { /** * Returns tasks. */ - DictStruct *GetTasks() { return &tasks; } + const DictStruct *GetTasks() const { return &tasks; } /** * Count entry flags. @@ -317,4 +313,17 @@ class Task : public Taskable { /* Other methods */ }; -#endif // TASK_H + +#ifdef EMSCRIPTEN +#include +#include + +EMSCRIPTEN_BINDINGS(Task) { + emscripten::class_("Task").smart_ptr>("Ref").constructor(emscripten::optional_override([]() { + return Ref(new Task()); + })) + //.function("Add", optional_override([](Task &self, Ref task) { self.Add(task.Ptr()); })) + ; +} + +#endif diff --git a/Task/Task.struct.h b/Task/Task.struct.h index 391eebc9c..db3a202cb 100644 --- a/Task/Task.struct.h +++ b/Task/Task.struct.h @@ -65,6 +65,15 @@ struct TaskEntry { public: // Constructors. TaskEntry() { Init(); } + TaskEntry(const TaskEntry &_entry) + : action(_entry.action), + cond(_entry.cond), + expires(_entry.expires), + last_process(_entry.last_process), + last_success(_entry.last_success), + flags(_entry.flags) { + Init(); + } TaskEntry(const TaskActionEntry &_action, const TaskConditionEntry &_cond) : action(_action), cond(_cond) { Init(); } template TaskEntry(AE _aid, CE _cid) : action(_aid), cond(_cid) { @@ -143,3 +152,10 @@ struct TaskEntry { SERIALIZER_EMPTY_STUB; }; + +#ifdef EMSCRIPTEN +#include + +EMSCRIPTEN_BINDINGS(TaskEntry) { emscripten::class_("TaskEntry").constructor(); } + +#endif diff --git a/Task/TaskManager.h b/Task/TaskManager.h index 7cd985fde..d549cc95f 100644 --- a/Task/TaskManager.h +++ b/Task/TaskManager.h @@ -30,10 +30,6 @@ #pragma once #endif -// Prevents processing this includes file for the second time. -#ifndef TASK_MANAGER_H -#define TASK_MANAGER_H - // Includes. #include "../DictObject.mqh" #include "../Serializer/SerializerConverter.h" @@ -95,6 +91,11 @@ class TaskManager { return Add((Task *)_task_obj); } + /** + * Clears tasks list. + */ + void Clear() { tasks.Clear(); } + /* Processing methods */ /** @@ -110,4 +111,18 @@ class TaskManager { } }; -#endif // TASK_MANAGER_H +#ifdef EMSCRIPTEN +#include + +EMSCRIPTEN_BINDINGS(TaskManager) { + emscripten::class_("TaskManager") + .constructor() + .function("Add", emscripten::optional_override([](TaskManager &self, Ref task) { + Print("Adding Task"); + self.Add(task.Ptr()); + })) + // .function("Add", emscripten::select_overload(&TaskManager::Add)) + .function("Clear", &TaskManager::Clear) + .function("Process", &TaskManager::Process); +} +#endif diff --git a/Trade/TradeSignal.h b/Trade/TradeSignal.h index 7a48524f5..4a11e43de 100644 --- a/Trade/TradeSignal.h +++ b/Trade/TradeSignal.h @@ -179,3 +179,12 @@ class TradeSignal { */ string ToString() { return signal.ToString(); } }; + +#ifdef EMSCRIPTEN +#include + +EMSCRIPTEN_BINDINGS(TradeSignal) { + emscripten::class_("TradeSignal").constructor().function("ToString", &TradeSignal::ToString); +} + +#endif diff --git a/Trade/TradeSignalManager.h b/Trade/TradeSignalManager.h index 87dd5c017..b9a03fb82 100644 --- a/Trade/TradeSignalManager.h +++ b/Trade/TradeSignalManager.h @@ -181,3 +181,15 @@ class TradeSignalManager : Dynamic { .ToString(SERIALIZER_JSON_NO_WHITESPACES); } }; + +#ifdef EMSCRIPTEN +#include + +EMSCRIPTEN_BINDINGS(TradeSignalManager) { + emscripten::class_("TradeSignalManager") + .constructor() + .function("SignalAdd", &TradeSignalManager::SignalAdd) + .function("ToString", &TradeSignalManager::ToString); +} + +#endif