diff --git a/Array.mqh b/Array.mqh index a0eeeac1e..80fd81e39 100644 --- a/Array.mqh +++ b/Array.mqh @@ -21,8 +21,8 @@ */ #ifndef __MQL__ -// Allows the preprocessor to include a header file when it is needed. -#pragma once + // Allows the preprocessor to include a header file when it is needed. + #pragma once #endif // Includes. @@ -35,16 +35,16 @@ // Defines. #ifndef MODE_ASCEND -#define MODE_ASCEND 0 + #define MODE_ASCEND 0 #endif #ifndef MODE_DESCEND -#define MODE_DESCEND 1 + #define MODE_DESCEND 1 #endif // Other constants. // @see https://docs.mql4.com/constants/namedconstants/otherconstants #ifndef WHOLE_ARRAY -// Indicates that all array elements will be processed. -#define WHOLE_ARRAY 0 + // Indicates that all array elements will be processed. + #define WHOLE_ARRAY 0 #endif /* @@ -119,7 +119,7 @@ class Array { int i; string result = ""; for (i = 0; i < ArraySize(arr); i++) { - result += StringFormat("%d:%d%s", i, arr[i], sep); + result += StringFormat("%d:%d%s", i, arr[i], C_STR(sep)); } // Return text without last separator. return StringSubstr(result, 0, StringLen(result) - StringLen(sep)); @@ -136,7 +136,7 @@ class Array { int i; string result = ""; for (i = 0; i < ArraySize(arr); i++) { - result += StringFormat("%d:%g%s", i, arr[i], sep); + result += StringFormat("%d:%g%s", i, arr[i], C_STR(sep)); } // Return text without last separator. return StringSubstr(result, 0, StringLen(result) - StringLen(sep)); @@ -404,7 +404,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { int i; string res = ""; for (i = 0; i < ArraySize(arr); i++) { - res += StringFormat("%g%s", NormalizeDouble(arr[i], digits), dlm); + res += StringFormat("%g%s", NormalizeDouble(arr[i], digits), C_STR(dlm)); } res = StringSubstr(res, 0, StringLen(res) - StringLen(dlm)); return res; @@ -610,16 +610,16 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { #ifdef __MQL4__ template static bool ArraySort2D(T& arr[][], int count = WHOLE_ARRAY, int start = 0, int direction = MODE_ASCEND) { -#ifdef __MQL4__ + #ifdef __MQL4__ return (bool)::ArraySort(arr, count, start, direction); -#else + #else if (direction == MODE_DESCEND) { return ::ArrayReverse(arr, start, count); } else { // @fixme: Add support for _count amd _start. return ::ArraySort(arr); } -#endif + #endif } #endif @@ -655,42 +655,42 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { return result; } -/** - * Initializes a numeric array by a preset value. - * - * @param array[] - * Numeric array that should be initialized. - * @param char value - * New value that should be set to all array elements. - * @return int - * Number of initialized elements. - * - * @docs - * - https://docs.mql4.com/array/arrayinitialize - * - https://www.mql5.com/en/docs/array/arrayinitialize - */ -template -static int ArrayInitialize(ARRAY_REF(X, array), char value) { - return ::ArrayInitialize(array, value); -} + /** + * Initializes a numeric array by a preset value. + * + * @param array[] + * Numeric array that should be initialized. + * @param char value + * New value that should be set to all array elements. + * @return int + * Number of initialized elements. + * + * @docs + * - https://docs.mql4.com/array/arrayinitialize + * - https://www.mql5.com/en/docs/array/arrayinitialize + */ + template + static int ArrayInitialize(ARRAY_REF(X, array), char value) { + return ::ArrayInitialize(array, value); + } -/** - * Searches for the lowest element in the first dimension of a multidimensional numeric array. - * - * @param void &array[] - * A numeric array, in which search is made. - * @param int start - * Index to start checking with. - * @param int count - * Number of elements for search. By default, searches in the entire array. - * @return int - * The function returns an index of a found element. - * - * @docs - * - https://docs.mql4.com/array/arraymaximum - * - https://www.mql5.com/en/docs/array/arraymaximum - */ -template + /** + * Searches for the lowest element in the first dimension of a multidimensional numeric array. + * + * @param void &array[] + * A numeric array, in which search is made. + * @param int start + * Index to start checking with. + * @param int count + * Number of elements for search. By default, searches in the entire array. + * @return int + * The function returns an index of a found element. + * + * @docs + * - https://docs.mql4.com/array/arraymaximum + * - https://www.mql5.com/en/docs/array/arraymaximum + */ + template static int ArrayMinimum(ARRAY_REF(X, _array), int _start = 0, int _count = WHOLE_ARRAY) { #ifdef __MQL__ return ::ArrayMinimum(_array); @@ -707,23 +707,23 @@ template #endif } -/** - * Searches for the largest element in the first dimension of a multidimensional numeric array. - * - * @param void &array[] - * A numeric array, in which search is made. - * @param int start - * Index to start checking with. - * @param int count - * Number of elements for search. By default, searches in the entire array. - * @return int - * The function returns an index of a found element. - * - * @docs - * - https://docs.mql4.com/array/arraymaximum - * - https://www.mql5.com/en/docs/array/arraymaximum - */ -template + /** + * Searches for the largest element in the first dimension of a multidimensional numeric array. + * + * @param void &array[] + * A numeric array, in which search is made. + * @param int start + * Index to start checking with. + * @param int count + * Number of elements for search. By default, searches in the entire array. + * @return int + * The function returns an index of a found element. + * + * @docs + * - https://docs.mql4.com/array/arraymaximum + * - https://www.mql5.com/en/docs/array/arraymaximum + */ + template static int ArrayMaximum(ARRAY_REF(X, _array), int start = 0, int count = WHOLE_ARRAY) { #ifdef __MQL__ return ::ArrayMaximum(_array); @@ -740,22 +740,22 @@ template #endif } -/** - * Returns the number of elements of a selected array. - * - * @param void &array[] - * Array of any type. - * @return int - * Value of int type. - * - * @docs - * - https://docs.mql4.com/array/arraysize - * - https://www.mql5.com/en/docs/array/arraysize - */ -template + /** + * Returns the number of elements of a selected array. + * + * @param void &array[] + * Array of any type. + * @return int + * Value of int type. + * + * @docs + * - https://docs.mql4.com/array/arraysize + * - https://www.mql5.com/en/docs/array/arraysize + */ + template static int ArraySize(ARRAY_REF(X, array)) { - return ::ArraySize(array); -} + return ::ArraySize(array); + } template static void ArrayStore(ARRAY_REF(X, array), int _idx, X value, int reserve_size = 0) { diff --git a/Dict.mqh b/Dict.mqh index f123cf539..cd16c0c05 100644 --- a/Dict.mqh +++ b/Dict.mqh @@ -232,9 +232,9 @@ class Dict : public DictBase { // If we don't have a slot then we should consider growing up number of slots or overwrite some existing slot. - bool _is_performant = dictSlotsRef.IsPerformant(); // Whether there is no performance problems. - bool _is_full = - dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots); // Whether we don't have empty slots to use. + bool _is_performant = dictSlotsRef PTR_DEREF IsPerformant(); // Whether there is no performance problems. + bool _is_full = dictSlotsRef PTR_DEREF _num_used == + ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Whether we don't have empty slots to use. if ((_is_full || !_is_performant) && allow_resize) { // We have to resize the dict as it is either full or have perfomance problems due to massive number of conflicts @@ -249,7 +249,7 @@ class Dict : public DictBase { // Overflow listener will decide if we can grow up the dict. if (THIS_ATTR overflow_listener( _is_full ? DICT_LISTENER_FULL_CAN_RESIZE : DICT_LISTENER_NOT_PERFORMANT_CAN_RESIZE, - dictSlotsRef._num_used, 0)) { + dictSlotsRef PTR_DEREF _num_used, 0)) { // We can freely grow up the dict. if (!GrowUp()) { // Can't resize the dict. Error happened. @@ -263,7 +263,7 @@ class Dict : public DictBase { // for an empty slot. // Position we will start from in order to search free slot. - position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef.DictSlots); + position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Saving position for further, possible overwrite. unsigned int _starting_position = position; @@ -272,15 +272,16 @@ class Dict : public DictBase { unsigned int _num_conflicts = 0; // Searching for empty DictSlot or used one with the matching key. It skips used, hashless DictSlots. - while (dictSlotsRef.DictSlots[position].IsUsed() && - (!dictSlotsRef.DictSlots[position].HasKey() || dictSlotsRef.DictSlots[position].key != key)) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed() && + (!dictSlotsRef PTR_DEREF DictSlots[position].HasKey() || + dictSlotsRef PTR_DEREF DictSlots[position].key != key)) { ++_num_conflicts; if (THIS_ATTR overflow_listener != NULL) { // We had to skip slot as it is already occupied. Now we are checking if // there is too many conflicts/skips and thus we can overwrite slot in // the starting position. - if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef._num_used, + if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef PTR_DEREF _num_used, _num_conflicts)) { // Looks like dict is working as buffer and we can overwrite slot in the starting position. position = _starting_position; @@ -289,19 +290,20 @@ class Dict : public DictBase { } // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } // Acknowledging slots array about number of conflicts as it calculates average number of conflicts per insert. - dictSlotsRef.AddConflicts(_num_conflicts); + dictSlotsRef PTR_DEREF AddConflicts(_num_conflicts); // Incrementing number of slots used only if we're writing into empty slot. - if (!dictSlotsRef.DictSlots[position].IsUsed()) { - ++dictSlotsRef._num_used; + if (!dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { + ++dictSlotsRef PTR_DEREF _num_used; } // Writing slot in the position of empty slot or, when overwriting, in starting position. - WriteSlot(dictSlotsRef.DictSlots[position], key, value, DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + WriteSlot(dictSlotsRef PTR_DEREF DictSlots[position], key, value, + DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); return true; } @@ -326,24 +328,25 @@ class Dict : public DictBase { return false; } - if (dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { - // No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots. + if (dictSlotsRef PTR_DEREF _num_used == ArraySize(dictSlotsRef PTR_DEREF DictSlots)) { + // No dictSlotsRef PTR_DEREF DictSlots available, we need to expand array of dictSlotsRef PTR_DEREF DictSlots. if (!GrowUp()) return false; } - unsigned int position = THIS_ATTR Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots); + unsigned int position = + THIS_ATTR Hash((unsigned int)dictSlotsRef PTR_DEREF _list_index) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Searching for empty DictSlot. - while (dictSlotsRef.DictSlots[position].IsUsed()) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } - dictSlotsRef.DictSlots[position].value = value; - dictSlotsRef.DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + dictSlotsRef PTR_DEREF DictSlots[position].value = value; + dictSlotsRef PTR_DEREF DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); - ++dictSlotsRef._list_index; - ++dictSlotsRef._num_used; + ++dictSlotsRef PTR_DEREF _list_index; + ++dictSlotsRef PTR_DEREF _num_used; return true; } @@ -378,15 +381,15 @@ class Dict : public DictBase { DictSlotsRef* new_DictSlots = new DictSlotsRef(); - if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) return false; + if (ArrayResize(new_DictSlots PTR_DEREF DictSlots, new_size) == -1) return false; int i; for (i = 0; i < new_size; ++i) { - new_DictSlots.DictSlots[i].SetFlags(0); + new_DictSlots PTR_DEREF DictSlots[i].SetFlags(0); } - new_DictSlots._num_used = 0; + new_DictSlots PTR_DEREF _num_used = 0; // Copies entire array of DictSlots into new array of DictSlots. Hashes will be rehashed. for (i = 0; i < ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) { diff --git a/DictBase.mqh b/DictBase.mqh index 187191f2d..c9d1f140b 100644 --- a/DictBase.mqh +++ b/DictBase.mqh @@ -72,8 +72,8 @@ class DictBase { DictIteratorBase Begin() { // Searching for first item index. - for (unsigned int i = 0; i < (unsigned int)ArraySize(_DictSlots_ref.DictSlots); ++i) { - if (_DictSlots_ref.DictSlots[i].IsValid() && _DictSlots_ref.DictSlots[i].IsUsed()) { + for (unsigned int i = 0; i < (unsigned int)ArraySize(_DictSlots_ref PTR_DEREF DictSlots); ++i) { + if (_DictSlots_ref PTR_DEREF DictSlots[i].IsValid() && _DictSlots_ref PTR_DEREF DictSlots[i].IsUsed()) { DictIteratorBase iter(this, i); return iter; } @@ -83,7 +83,7 @@ class DictBase { return invalid; } - const unsigned int GetSlotCount() const { return ArraySize(_DictSlots_ref.DictSlots); } + const unsigned int GetSlotCount() const { return ArraySize(_DictSlots_ref PTR_DEREF DictSlots); } /** * Adds flags to dict. @@ -101,14 +101,14 @@ class DictBase { return NULL; } - return &_DictSlots_ref.DictSlots[_idx]; + return &_DictSlots_ref PTR_DEREF DictSlots[_idx]; } /** * Returns slot by key. */ DictSlot* GetSlotByKey(DictSlotsRef*& dictSlotsRef, const K _key, unsigned int& position) { - unsigned int numSlots = ArraySize(dictSlotsRef.DictSlots); + unsigned int numSlots = ArraySize(dictSlotsRef PTR_DEREF DictSlots); if (numSlots == 0) return NULL; @@ -117,19 +117,19 @@ class DictBase { unsigned int tries_left = numSlots; while (tries_left-- > 0) { - if (dictSlotsRef.DictSlots[position].WasUsed() == false) { + if (dictSlotsRef PTR_DEREF DictSlots[position].WasUsed() == false) { // We stop searching now. return NULL; } - if (dictSlotsRef.DictSlots[position].IsUsed() && dictSlotsRef.DictSlots[position].HasKey() && - dictSlotsRef.DictSlots[position].key == _key) { + if (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed() && dictSlotsRef PTR_DEREF DictSlots[position].HasKey() && + dictSlotsRef PTR_DEREF DictSlots[position].key == _key) { // _key matches, returing value from the DictSlot. - return &dictSlotsRef.DictSlots[position]; + return &dictSlotsRef PTR_DEREF DictSlots[position]; } // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } return NULL; @@ -139,7 +139,7 @@ class DictBase { * Returns slot by position. */ DictSlot* GetSlotByPos(DictSlotsRef*& dictSlotsRef, const unsigned int position) { - return dictSlotsRef.DictSlots[position].IsUsed() ? &dictSlotsRef.DictSlots[position] : NULL; + return dictSlotsRef PTR_DEREF DictSlots[position].IsUsed() ? &dictSlotsRef PTR_DEREF DictSlots[position] : NULL; } /** @@ -179,7 +179,7 @@ class DictBase { * Removes value from the dictionary by the given key (if exists). */ void InternalUnset(const K key) { - if (ArraySize(_DictSlots_ref.DictSlots) == 0) { + if (ArraySize(_DictSlots_ref PTR_DEREF DictSlots) == 0) { // Nothing to unset. return; } @@ -198,20 +198,20 @@ class DictBase { } #endif } else { - position = Hash(key) % ArraySize(_DictSlots_ref.DictSlots); + position = Hash(key) % ArraySize(_DictSlots_ref PTR_DEREF DictSlots); } - unsigned int tries_left = ArraySize(_DictSlots_ref.DictSlots); + unsigned int tries_left = ArraySize(_DictSlots_ref PTR_DEREF DictSlots); while (tries_left-- > 0) { - if (_DictSlots_ref.DictSlots[position].WasUsed() == false) { + if (_DictSlots_ref PTR_DEREF DictSlots[position].WasUsed() == false) { // We stop searching now. return; } bool _should_be_removed = false; - if (_DictSlots_ref.DictSlots[position].IsUsed()) { + if (_DictSlots_ref PTR_DEREF DictSlots[position].IsUsed()) { if (GetMode() == DictModeList) { #ifndef __MQL__ if constexpr (std::is_same::value) { @@ -223,18 +223,18 @@ class DictBase { } #endif } else { - _should_be_removed = - _DictSlots_ref.DictSlots[position].HasKey() && _DictSlots_ref.DictSlots[position].key == key; + _should_be_removed = _DictSlots_ref PTR_DEREF DictSlots[position].HasKey() && + _DictSlots_ref PTR_DEREF DictSlots[position].key == key; } } if (_should_be_removed) { // Key/index perfectly matches, it indicates key/index exists in the dictionary. - _DictSlots_ref.DictSlots[position].RemoveFlags(DICT_SLOT_IS_USED); + _DictSlots_ref PTR_DEREF DictSlots[position].RemoveFlags(DICT_SLOT_IS_USED); if (GetMode() == DictModeDict) { // In List mode we don't decrement number of used elements. - --_DictSlots_ref._num_used; + --_DictSlots_ref PTR_DEREF _num_used; } else if (HasFlags(DICT_FLAG_FILL_HOLES_UNSORTED)) { // This is List mode and we need to fill this hole. FillHoleUnsorted(position); @@ -247,7 +247,7 @@ class DictBase { } // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(_DictSlots_ref.DictSlots); + position = (position + 1) % ArraySize(_DictSlots_ref PTR_DEREF DictSlots); } // No key found. @@ -262,30 +262,30 @@ class DictBase { // We've just removed last element, thus don't need to do anything. } else { // Moving last slot into given one. - _DictSlots_ref.DictSlots[_hole_slot_idx] = _DictSlots_ref.DictSlots[Size() - 1]; + _DictSlots_ref PTR_DEREF DictSlots[_hole_slot_idx] = _DictSlots_ref PTR_DEREF DictSlots[Size() - 1]; // Marking last slot as unused. - _DictSlots_ref.DictSlots[Size() - 1].RemoveFlags(DICT_SLOT_IS_USED); + _DictSlots_ref PTR_DEREF DictSlots[Size() - 1].RemoveFlags(DICT_SLOT_IS_USED); } // One element less in the List-based Dict. - --_DictSlots_ref._num_used; + --_DictSlots_ref PTR_DEREF _num_used; } /** * Returns number of used DictSlots. */ - const unsigned int Size() { return _DictSlots_ref._num_used; } + const unsigned int Size() { return _DictSlots_ref PTR_DEREF _num_used; } /** * Returns number of all (reserved) DictSlots. */ - const unsigned int ReservedSize() { return ArraySize(_DictSlots_ref.DictSlots); } + const unsigned int ReservedSize() { return ArraySize(_DictSlots_ref PTR_DEREF DictSlots); } /** * Checks whether given key exists in the dictionary. */ bool KeyExists(const K key, unsigned int& position) { - int numSlots = ArraySize(_DictSlots_ref.DictSlots); + int numSlots = ArraySize(_DictSlots_ref PTR_DEREF DictSlots); if (numSlots == 0) return false; @@ -294,13 +294,14 @@ class DictBase { unsigned int tries_left = numSlots; while (tries_left-- > 0) { - if (_DictSlots_ref.DictSlots[position].WasUsed() == false) { + if (_DictSlots_ref PTR_DEREF DictSlots[position].WasUsed() == false) { // We stop searching now. return false; } - if (_DictSlots_ref.DictSlots[position].IsUsed() && _DictSlots_ref.DictSlots[position].HasKey() && - _DictSlots_ref.DictSlots[position].key == key) { + if (_DictSlots_ref PTR_DEREF DictSlots[position].IsUsed() && + _DictSlots_ref PTR_DEREF DictSlots[position].HasKey() && + _DictSlots_ref PTR_DEREF DictSlots[position].key == key) { // Key perfectly matches, it indicates key exists in the dictionary. return true; } diff --git a/DictObject.mqh b/DictObject.mqh index 63db36d87..24d31e41c 100644 --- a/DictObject.mqh +++ b/DictObject.mqh @@ -72,18 +72,19 @@ class DictObject : public DictBase { DictObject(const DictObject& right) { Clear(); Resize(right.GetSlotCount()); - for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - this PTR_DEREF _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref PTR_DEREF DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref PTR_DEREF DictSlots[i]; } - this PTR_DEREF _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + this PTR_DEREF _DictSlots_ref PTR_DEREF _num_used = right._DictSlots_ref PTR_DEREF _num_used; this PTR_DEREF _current_id = right._current_id; this PTR_DEREF _mode = right._mode; } DictObjectIterator Begin() { // Searching for first item index. - for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { - if (this PTR_DEREF _DictSlots_ref.DictSlots[i].IsValid() && this PTR_DEREF _DictSlots_ref.DictSlots[i].IsUsed()) { + for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots); ++i) { + if (this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].IsValid() && + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].IsUsed()) { DictObjectIterator iter(THIS_REF, i); return iter; } @@ -96,22 +97,22 @@ class DictObject : public DictBase { void operator=(const DictObject& right) { Clear(); Resize(right.GetSlotCount()); - for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - this PTR_DEREF _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref PTR_DEREF DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref PTR_DEREF DictSlots[i]; } - this PTR_DEREF _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + this PTR_DEREF _DictSlots_ref PTR_DEREF _num_used = right._DictSlots_ref PTR_DEREF _num_used; this PTR_DEREF _current_id = right._current_id; this PTR_DEREF _mode = right._mode; } void Clear() { - _DictSlots_ref = new DictSlotsRef(); + THIS_ATTR _DictSlots_ref = new DictSlotsRef(); - for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { - this PTR_DEREF _DictSlots_ref.DictSlots[i].SetFlags(0); + for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].SetFlags(0); } - this PTR_DEREF _DictSlots_ref._num_used = 0; + this PTR_DEREF _DictSlots_ref PTR_DEREF _num_used = 0; } /** @@ -232,9 +233,9 @@ class DictObject : public DictBase { // If we don't have a slot then we should consider growing up number of slots or overwrite some existing slot. - bool _is_performant = dictSlotsRef.IsPerformant(); // Whether there is no performance problems. - bool _is_full = - dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots); // Whether we don't have empty slots to use. + bool _is_performant = dictSlotsRef PTR_DEREF IsPerformant(); // Whether there is no performance problems. + bool _is_full = dictSlotsRef PTR_DEREF _num_used == + ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Whether we don't have empty slots to use. if ((_is_full || !_is_performant) && allow_resize) { // We have to resize the dict as it is either full or have perfomance problems due to massive number of conflicts @@ -249,7 +250,7 @@ class DictObject : public DictBase { // Overflow listener will decide if we can grow up the dict. if (THIS_ATTR overflow_listener( _is_full ? DICT_LISTENER_FULL_CAN_RESIZE : DICT_LISTENER_NOT_PERFORMANT_CAN_RESIZE, - dictSlotsRef._num_used, 0)) { + dictSlotsRef PTR_DEREF _num_used, 0)) { // We can freely grow up the dict. if (!GrowUp()) { // Can't resize the dict. Error happened. @@ -263,7 +264,7 @@ class DictObject : public DictBase { // for an empty slot. // Position we will start from in order to search free slot. - position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef.DictSlots); + position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Saving position for further, possible overwrite. unsigned int _starting_position = position; @@ -272,15 +273,16 @@ class DictObject : public DictBase { unsigned int _num_conflicts = 0; // Searching for empty DictSlot or used one with the matching key. It skips used, hashless DictSlots. - while (dictSlotsRef.DictSlots[position].IsUsed() && - (!dictSlotsRef.DictSlots[position].HasKey() || dictSlotsRef.DictSlots[position].key != key)) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed() && + (!dictSlotsRef PTR_DEREF DictSlots[position].HasKey() || + dictSlotsRef PTR_DEREF DictSlots[position].key != key)) { ++_num_conflicts; if (THIS_ATTR overflow_listener != NULL) { // We had to skip slot as it is already occupied. Now we are checking if // there is too many conflicts/skips and thus we can overwrite slot in // the starting position. - if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef._num_used, + if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef PTR_DEREF _num_used, _num_conflicts)) { // Looks like dict is working as buffer and we can overwrite slot in the starting position. position = _starting_position; @@ -289,19 +291,20 @@ class DictObject : public DictBase { } // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } // Acknowledging slots array about number of conflicts as it calculates average number of conflicts per insert. - dictSlotsRef.AddConflicts(_num_conflicts); + dictSlotsRef PTR_DEREF AddConflicts(_num_conflicts); // Incrementing number of slots used only if we're writing into empty slot. - if (!dictSlotsRef.DictSlots[position].IsUsed()) { - ++dictSlotsRef._num_used; + if (!dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { + ++dictSlotsRef PTR_DEREF _num_used; } // Writing slot in the position of empty slot or, when overwriting, in starting position. - WriteSlot(dictSlotsRef.DictSlots[position], key, value, DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + WriteSlot(dictSlotsRef PTR_DEREF DictSlots[position], key, value, + DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); return true; } @@ -326,25 +329,25 @@ class DictObject : public DictBase { return false; } - if (dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { - // No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots. + if (dictSlotsRef PTR_DEREF _num_used == ArraySize(dictSlotsRef PTR_DEREF DictSlots)) { + // No dictSlotsRef PTR_DEREF DictSlots available, we need to expand array of dictSlotsRef PTR_DEREF DictSlots. if (!GrowUp()) return false; } - unsigned int position = - this PTR_DEREF Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots); + unsigned int position = this PTR_DEREF Hash((unsigned int)dictSlotsRef PTR_DEREF _list_index) % + ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Searching for empty DictSlot. - while (dictSlotsRef.DictSlots[position].IsUsed()) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } - dictSlotsRef.DictSlots[position].value = value; - dictSlotsRef.DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + dictSlotsRef PTR_DEREF DictSlots[position].value = value; + dictSlotsRef PTR_DEREF DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); - ++dictSlotsRef._list_index; - ++dictSlotsRef._num_used; + ++dictSlotsRef PTR_DEREF _list_index; + ++dictSlotsRef PTR_DEREF _num_used; return true; } @@ -352,8 +355,8 @@ class DictObject : public DictBase { * Expands array of DictSlots by given percentage value. */ bool GrowUp(int percent = DICT_GROW_UP_PERCENT_DEFAULT) { - return Resize(MathMax( - 10, (int)((float)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f)))); + return Resize(MathMax(10, (int)((float)ArraySize(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots) * + ((float)(percent + 100) / 100.0f)))); } public: @@ -361,7 +364,7 @@ class DictObject : public DictBase { * Ensures that there is at least given number of slots in dict. */ bool Reserve(int _size) { - if (_size <= ArraySize(THIS_ATTR _DictSlots_ref.DictSlots)) { + if (_size <= ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots)) { return true; } return Resize(_size); @@ -372,8 +375,8 @@ class DictObject : public DictBase { * Shrinks or expands array of DictSlots. */ bool Resize(int new_size) { - if (new_size <= - MathMin(this PTR_DEREF _DictSlots_ref._num_used, ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots))) { + if (new_size <= MathMin(this PTR_DEREF _DictSlots_ref PTR_DEREF _num_used, + ArraySize(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots))) { // We already use minimum number of slots possible. return true; } @@ -382,26 +385,26 @@ class DictObject : public DictBase { int i; - if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) return false; + if (ArrayResize(new_DictSlots PTR_DEREF DictSlots, new_size) == -1) return false; for (i = 0; i < new_size; ++i) { - new_DictSlots.DictSlots[i].SetFlags(0); + new_DictSlots PTR_DEREF DictSlots[i].SetFlags(0); } // Copies entire array of DictSlots into new array of DictSlots. Hashes will be rehashed. - for (i = 0; i < ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { - if (!this PTR_DEREF _DictSlots_ref.DictSlots[i].IsUsed()) continue; + for (i = 0; i < ArraySize(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots); ++i) { + if (!this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].IsUsed()) continue; - if (this PTR_DEREF _DictSlots_ref.DictSlots[i].HasKey()) { - if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref.DictSlots[i].key, - this PTR_DEREF _DictSlots_ref.DictSlots[i].value, false)) + if (this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].HasKey()) { + if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].key, + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].value, false)) return false; } else { - if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref.DictSlots[i].value)) return false; + if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i].value)) return false; } } // Freeing old DictSlots array. - ArrayFree(this PTR_DEREF _DictSlots_ref.DictSlots); + ArrayFree(this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots); delete THIS_ATTR _DictSlots_ref; diff --git a/DictStruct.mqh b/DictStruct.mqh index 5b5c6e1c9..7d29195f7 100644 --- a/DictStruct.mqh +++ b/DictStruct.mqh @@ -56,10 +56,10 @@ class DictStruct : public DictBase { DictStruct(const DictStruct& right) { Clear(); Resize(right.GetSlotCount()); - for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref PTR_DEREF DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref PTR_DEREF DictSlots[i]; } - THIS_ATTR _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + THIS_ATTR _DictSlots_ref PTR_DEREF _num_used = right._DictSlots_ref PTR_DEREF _num_used; THIS_ATTR _current_id = right._current_id; THIS_ATTR _mode = right._mode; } @@ -70,10 +70,10 @@ class DictStruct : public DictBase { DictStruct(DictStruct& right) { Clear(); Resize(right.GetSlotCount()); - for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref PTR_DEREF DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref PTR_DEREF DictSlots[i]; } - THIS_ATTR _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + THIS_ATTR _DictSlots_ref PTR_DEREF _num_used = right._DictSlots_ref PTR_DEREF _num_used; THIS_ATTR _current_id = right._current_id; THIS_ATTR _mode = right._mode; } @@ -81,29 +81,30 @@ class DictStruct : public DictBase { void operator=(const 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]; + for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref PTR_DEREF DictSlots); ++i) { + THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i] = right._DictSlots_ref PTR_DEREF DictSlots[i]; } - THIS_ATTR _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + THIS_ATTR _DictSlots_ref PTR_DEREF _num_used = right._DictSlots_ref PTR_DEREF _num_used; THIS_ATTR _current_id = right._current_id; THIS_ATTR _mode = right._mode; } void Clear() { - delete _DictSlots_ref; - _DictSlots_ref = new DictSlotsRef(); + delete THIS_ATTR _DictSlots_ref; + THIS_ATTR _DictSlots_ref = new DictSlotsRef(); - for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) { - THIS_ATTR _DictSlots_ref.DictSlots[i].SetFlags(0); + for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots); ++i) { + THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].SetFlags(0); } - THIS_ATTR _DictSlots_ref._num_used = 0; + THIS_ATTR _DictSlots_ref PTR_DEREF _num_used = 0; } DictStructIterator Begin() { // Searching for first item index. - for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) { - if (THIS_ATTR _DictSlots_ref.DictSlots[i].IsValid() && THIS_ATTR _DictSlots_ref.DictSlots[i].IsUsed()) { + for (unsigned int i = 0; i < (unsigned int)ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots); ++i) { + if (THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].IsValid() && + THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].IsUsed()) { DictStructIterator iter(THIS_REF, i); return iter; } @@ -279,9 +280,9 @@ class DictStruct : public DictBase { // If we don't have a slot then we should consider growing up number of slots or overwrite some existing slot. - bool _is_performant = dictSlotsRef.IsPerformant(); // Whether there is no performance problems. - bool _is_full = - dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots); // Whether we don't have empty slots to use. + bool _is_performant = dictSlotsRef PTR_DEREF IsPerformant(); // Whether there is no performance problems. + bool _is_full = dictSlotsRef PTR_DEREF _num_used == + ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Whether we don't have empty slots to use. if ((_is_full || !_is_performant) && allow_resize) { // We have to resize the dict as it is either full or have perfomance problems due to massive number of conflicts @@ -296,7 +297,7 @@ class DictStruct : public DictBase { // Overflow listener will decide if we can grow up the dict. if (THIS_ATTR overflow_listener( _is_full ? DICT_LISTENER_FULL_CAN_RESIZE : DICT_LISTENER_NOT_PERFORMANT_CAN_RESIZE, - dictSlotsRef._num_used, 0)) { + dictSlotsRef PTR_DEREF _num_used, 0)) { // We can freely grow up the dict. if (!GrowUp()) { // Can't resize the dict. Error happened. @@ -310,7 +311,7 @@ class DictStruct : public DictBase { // for an empty slot. // Position we will start from in order to search free slot. - position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef.DictSlots); + position = THIS_ATTR Hash(key) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Saving position for further, possible overwrite. unsigned int _starting_position = position; @@ -319,15 +320,16 @@ class DictStruct : public DictBase { unsigned int _num_conflicts = 0; // Searching for empty DictSlot or used one with the matching key. It skips used, hashless DictSlots. - while (dictSlotsRef.DictSlots[position].IsUsed() && - (!dictSlotsRef.DictSlots[position].HasKey() || dictSlotsRef.DictSlots[position].key != key)) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed() && + (!dictSlotsRef PTR_DEREF DictSlots[position].HasKey() || + dictSlotsRef PTR_DEREF DictSlots[position].key != key)) { ++_num_conflicts; if (THIS_ATTR overflow_listener != NULL) { // We had to skip slot as it is already occupied. Now we are checking if // there is too many conflicts/skips and thus we can overwrite slot in // the starting position. - if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef._num_used, + if (THIS_ATTR overflow_listener(DICT_LISTENER_CONFLICTS_CAN_OVERWRITE, dictSlotsRef PTR_DEREF _num_used, _num_conflicts)) { // Looks like dict is working as buffer and we can overwrite slot in the starting position. position = _starting_position; @@ -336,19 +338,20 @@ class DictStruct : public DictBase { } // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } // Acknowledging slots array about number of conflicts as it calculates average number of conflicts per insert. - dictSlotsRef.AddConflicts(_num_conflicts); + dictSlotsRef PTR_DEREF AddConflicts(_num_conflicts); // Incrementing number of slots used only if we're writing into empty slot. - if (!dictSlotsRef.DictSlots[position].IsUsed()) { - ++dictSlotsRef._num_used; + if (!dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { + ++dictSlotsRef PTR_DEREF _num_used; } // Writing slot in the position of empty slot or, when overwriting, in starting position. - WriteSlot(dictSlotsRef.DictSlots[position], key, value, DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + WriteSlot(dictSlotsRef PTR_DEREF DictSlots[position], key, value, + DICT_SLOT_HAS_KEY | DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); return true; } @@ -372,24 +375,25 @@ class DictStruct : public DictBase { return false; } - if (dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { - // No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots. + if (dictSlotsRef PTR_DEREF _num_used == ArraySize(dictSlotsRef PTR_DEREF DictSlots)) { + // No dictSlotsRef PTR_DEREF DictSlots available, we need to expand array of dictSlotsRef PTR_DEREF DictSlots. if (!GrowUp()) return false; } - unsigned int position = THIS_ATTR Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots); + unsigned int position = + THIS_ATTR Hash((unsigned int)dictSlotsRef PTR_DEREF _list_index) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); // Searching for empty DictSlot. - while (dictSlotsRef.DictSlots[position].IsUsed()) { + while (dictSlotsRef PTR_DEREF DictSlots[position].IsUsed()) { // Position may overflow, so we will start from the beginning. - position = (position + 1) % ArraySize(dictSlotsRef.DictSlots); + position = (position + 1) % ArraySize(dictSlotsRef PTR_DEREF DictSlots); } - dictSlotsRef.DictSlots[position].value = value; - dictSlotsRef.DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); + dictSlotsRef PTR_DEREF DictSlots[position].value = value; + dictSlotsRef PTR_DEREF DictSlots[position].SetFlags(DICT_SLOT_IS_USED | DICT_SLOT_WAS_USED); - ++dictSlotsRef._list_index; - ++dictSlotsRef._num_used; + ++dictSlotsRef PTR_DEREF _list_index; + ++dictSlotsRef PTR_DEREF _num_used; return true; } @@ -397,8 +401,8 @@ class DictStruct : public DictBase { * Expands array of DictSlots by given percentage value. */ bool GrowUp(int percent = DICT_GROW_UP_PERCENT_DEFAULT) { - return Resize( - MathMax(10, (int)((float)ArraySize(THIS_ATTR _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f)))); + return Resize(MathMax( + 10, (int)((float)ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots) * ((float)(percent + 100) / 100.0f)))); } public: @@ -406,7 +410,7 @@ class DictStruct : public DictBase { * Ensures that there is at least given number of slots in dict. */ bool Reserve(int _size) { - if (_size <= ArraySize(THIS_ATTR _DictSlots_ref.DictSlots)) { + if (_size <= ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots)) { return true; } return Resize(_size); @@ -417,33 +421,34 @@ class DictStruct : public DictBase { * Shrinks or expands array of DictSlots. */ bool Resize(int new_size) { - if (new_size <= MathMin(THIS_ATTR _DictSlots_ref._num_used, ArraySize(THIS_ATTR _DictSlots_ref.DictSlots))) { + if (new_size <= MathMin(THIS_ATTR _DictSlots_ref PTR_DEREF _num_used, + ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots))) { // We already use minimum number of slots possible. return true; } DictSlotsRef* new_DictSlots = new DictSlotsRef(); - if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) { + if (ArrayResize(new_DictSlots PTR_DEREF DictSlots, new_size) == -1) { return false; } int i; for (i = 0; i < new_size; ++i) { - new_DictSlots.DictSlots[i].SetFlags(0); + new_DictSlots PTR_DEREF DictSlots[i].SetFlags(0); } // Copies entire array of DictSlots into new array of DictSlots. Hashes will be rehashed. - for (i = 0; i < ArraySize(THIS_ATTR _DictSlots_ref.DictSlots); ++i) { - if (!THIS_ATTR _DictSlots_ref.DictSlots[i].IsUsed()) continue; + for (i = 0; i < ArraySize(THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots); ++i) { + if (!THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].IsUsed()) continue; - if (THIS_ATTR _DictSlots_ref.DictSlots[i].HasKey()) { - if (!InsertInto(new_DictSlots, THIS_ATTR _DictSlots_ref.DictSlots[i].key, - THIS_ATTR _DictSlots_ref.DictSlots[i].value, false)) + if (THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].HasKey()) { + if (!InsertInto(new_DictSlots, THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].key, + THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].value, false)) return false; } else { - if (!InsertInto(new_DictSlots, THIS_ATTR _DictSlots_ref.DictSlots[i].value)) return false; + if (!InsertInto(new_DictSlots, THIS_ATTR _DictSlots_ref PTR_DEREF DictSlots[i].value)) return false; } } // Freeing old DictSlots array. diff --git a/Log.mqh b/Log.mqh index 13bc13fd4..262c93076 100644 --- a/Log.mqh +++ b/Log.mqh @@ -76,7 +76,7 @@ class Log : public Object { /** * Class copy constructor. */ - Log(const Log &_log) : filename(_log.filename), last_entry(_log.last_entry), log_level(_log.log_level) {} + Log(const Log &_log) : last_entry(_log.last_entry), log_level(_log.log_level), filename(_log.filename) {} /** * Class deconstructor. @@ -149,7 +149,7 @@ class Log : public Object { * Adds a log entry. */ bool Add(string msg, string prefix, string suffix, ENUM_LOG_LEVEL entry_log_level = V_INFO) { - return Add(prefix, msg, suffix, entry_log_level); + return Add(entry_log_level, prefix, msg, suffix); } bool Add(ARRAY_REF(double, arr), string prefix, string suffix, ENUM_LOG_LEVEL entry_log_level = V_INFO) { return Add(prefix, Array::ArrToString(arr), suffix, entry_log_level); diff --git a/Std.h b/Std.h index b31c8c581..215986aae 100644 --- a/Std.h +++ b/Std.h @@ -37,7 +37,7 @@ #include #endif -#ifndef __MQL__ +#ifndef __FUNCSIG__ #define __FUNCSIG__ __FUNCTION__ #endif @@ -62,7 +62,7 @@ #define int64 long #define nullptr NULL #else - #define GET_PTR(obj) (*obj) + #define GET_PTR(obj) (&obj) #define THIS_ATTR this-> #define THIS_PTR (this) #define THIS_REF (*this) @@ -405,8 +405,8 @@ struct AsSeriesReleaseEnsurer { int num_buffs; AsSeriesReleaseEnsurer(int _num_buffs) : released(false), num_buffs(_num_buffs) {} void done(int _num_buffs) { - if (_num_buffs != num_buffs) { #ifdef __MQL__ + if (_num_buffs != num_buffs) { Alert("You have acquired ", num_buffs, " buffers via ACQUIRE_BUFFER", num_buffs, "(), but now trying to release with mismatched RELEASE_BUFFER", _num_buffs, "()!"); DebugBreak(); @@ -574,3 +574,12 @@ struct AsSeriesReleaseEnsurer { #define RELEASE_BUFFER8(A, B, C, D, E, F, G, H) \ RELEASE_BUFFER8_NO_ENSURE(A, B, C, D, E, F, G, H); \ SET_BUFFER_AS_SERIES_RELEASE_ENSURER_END(8); + +#ifndef __MQL__ +// clang-format off + # if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + # else + #define constexpr + # endif +// clang-format on +#endif diff --git a/Terminal.mqh b/Terminal.mqh index 6015a1da7..a55001967 100644 --- a/Terminal.mqh +++ b/Terminal.mqh @@ -51,8 +51,8 @@ class Terminal; // Provide backward compatibility for MQL4 in MQL5. //#include "MQL4.mqh" #else -// Provides forward compatibility for MQL5 in MQL4. -#include "MQL5.mqh" + // Provides forward compatibility for MQL5 in MQL4. + #include "MQL5.mqh" #endif /** @@ -736,128 +736,129 @@ class Terminal : public Object { case 4206: text = "No specified subwindow."; break; - /* Return Codes of the Trade Server */ - // @docs: https://www.mql5.com/en/docs/constants/errorswarnings/enum_trade_return_codes - case 10004: // TRADE_RETCODE_REQUOTE - text = "Requote"; - break; - case 10006: // TRADE_RETCODE_REJECT - text = "Request rejected"; - break; - case 10007: // TRADE_RETCODE_CANCEL - text = "Request canceled by trader"; - break; - case 10008: // TRADE_RETCODE_PLACED - text = "Order placed"; - break; - case 10009: // TRADE_RETCODE_DONE - text = "Request completed"; - break; - case 10010: // TRADE_RETCODE_DONE_PARTIAL - text = "Only part of the request was completed"; - break; - case 10011: // TRADE_RETCODE_ERROR - text = "Request processing error"; - break; - case 10012: // TRADE_RETCODE_TIMEOUT - text = "Request canceled by timeout"; - break; - case 10013: // TRADE_RETCODE_INVALID - text = "Invalid request"; - break; - case 10014: // TRADE_RETCODE_INVALID_VOLUME - text = "Invalid volume in the request"; - break; - case 10015: // TRADE_RETCODE_INVALID_PRICE - text = "Invalid price in the request"; - break; - case 10016: // TRADE_RETCODE_INVALID_STOPS - text = "Invalid stops in the request"; - break; - case 10017: // TRADE_RETCODE_TRADE_DISABLED - text = "Trade is disabled"; - break; - case 10018: // TRADE_RETCODE_MARKET_CLOSED - text = "Market is closed"; - break; - case 10019: // TRADE_RETCODE_NO_MONEY - text = "There is not enough money to complete the request"; - break; - case 10020: // TRADE_RETCODE_PRICE_CHANGED - text = "Prices changed"; - break; - case 10021: // TRADE_RETCODE_PRICE_OFF - text = "There are no quotes to process the request"; - break; - case 10022: // TRADE_RETCODE_INVALID_EXPIRATION - text = "Invalid order expiration date in the request"; - break; - case 10023: // TRADE_RETCODE_ORDER_CHANGED - text = "Order state changed"; - break; - case 10024: // TRADE_RETCODE_TOO_MANY_REQUESTS - text = "Too frequent requests"; - break; - case 10025: // TRADE_RETCODE_NO_CHANGES - text = "No changes in request"; - break; - case 10026: // TRADE_RETCODE_SERVER_DISABLES_AT - text = "Autotrading disabled by server"; - break; - case 10027: // TRADE_RETCODE_CLIENT_DISABLES_AT - text = "Autotrading disabled by client terminal"; - break; - case 10028: // TRADE_RETCODE_LOCKED - text = "Request locked for processing"; - break; - case 10029: // TRADE_RETCODE_FROZEN - text = "Order or position frozen"; - break; - case 10030: // TRADE_RETCODE_INVALID_FILL - text = "Invalid order filling type"; - break; - case 10031: // TRADE_RETCODE_CONNECTION - text = "No connection with the trade server"; - break; - case 10032: // TRADE_RETCODE_ONLY_REAL - text = "Operation is allowed only for live accounts"; - break; - case 10033: // TRADE_RETCODE_LIMIT_ORDERS - text = "The number of pending orders has reached the limit"; - break; - case 10034: // TRADE_RETCODE_LIMIT_VOLUME - text = "The volume of orders and positions for the symbol has reached the limit"; - break; - case 10035: // TRADE_RETCODE_INVALID_ORDER - text = "Incorrect or prohibited order type"; - break; - case 10036: // TRADE_RETCODE_POSITION_CLOSED - text = "Position with the specified POSITION_IDENTIFIER has already been closed"; - break; - case 10039: // TRADE_RETCODE_CLOSE_ORDER_EXIST - text = "A close order already exists for a specified position"; - break; - case 10040: // TRADE_RETCODE_LIMIT_POSITIONS - text = "The number of open positions simultaneously present on an account can be limited by the server settings"; - break; - case 10041: // TRADE_RETCODE_REJECT_CANCEL - text = "The pending order activation request is rejected, the order is canceled"; - break; - case 10042: // TRADE_RETCODE_LONG_ONLY - text = "The request is rejected because only long positions are allowed"; - break; - case 10043: // TRADE_RETCODE_SHORT_ONLY - text = "The request is rejected because only short positions are allowed"; - break; - case 10044: // TRADE_RETCODE_CLOSE_ONLY - text = "The request is rejected because only position closing is allowed"; - break; - case 10045: // TRADE_RETCODE_FIFO_CLOSE - text = "The request is rejected because position closing is allowed only by FIFO rule"; - break; - case 10046: // TRADE_RETCODE_HEDGE_PROHIBITED - text = "The request is rejected because opposite positions on a single symbol are disabled"; - break; + /* Return Codes of the Trade Server */ + // @docs: https://www.mql5.com/en/docs/constants/errorswarnings/enum_trade_return_codes + case 10004: // TRADE_RETCODE_REQUOTE + text = "Requote"; + break; + case 10006: // TRADE_RETCODE_REJECT + text = "Request rejected"; + break; + case 10007: // TRADE_RETCODE_CANCEL + text = "Request canceled by trader"; + break; + case 10008: // TRADE_RETCODE_PLACED + text = "Order placed"; + break; + case 10009: // TRADE_RETCODE_DONE + text = "Request completed"; + break; + case 10010: // TRADE_RETCODE_DONE_PARTIAL + text = "Only part of the request was completed"; + break; + case 10011: // TRADE_RETCODE_ERROR + text = "Request processing error"; + break; + case 10012: // TRADE_RETCODE_TIMEOUT + text = "Request canceled by timeout"; + break; + case 10013: // TRADE_RETCODE_INVALID + text = "Invalid request"; + break; + case 10014: // TRADE_RETCODE_INVALID_VOLUME + text = "Invalid volume in the request"; + break; + case 10015: // TRADE_RETCODE_INVALID_PRICE + text = "Invalid price in the request"; + break; + case 10016: // TRADE_RETCODE_INVALID_STOPS + text = "Invalid stops in the request"; + break; + case 10017: // TRADE_RETCODE_TRADE_DISABLED + text = "Trade is disabled"; + break; + case 10018: // TRADE_RETCODE_MARKET_CLOSED + text = "Market is closed"; + break; + case 10019: // TRADE_RETCODE_NO_MONEY + text = "There is not enough money to complete the request"; + break; + case 10020: // TRADE_RETCODE_PRICE_CHANGED + text = "Prices changed"; + break; + case 10021: // TRADE_RETCODE_PRICE_OFF + text = "There are no quotes to process the request"; + break; + case 10022: // TRADE_RETCODE_INVALID_EXPIRATION + text = "Invalid order expiration date in the request"; + break; + case 10023: // TRADE_RETCODE_ORDER_CHANGED + text = "Order state changed"; + break; + case 10024: // TRADE_RETCODE_TOO_MANY_REQUESTS + text = "Too frequent requests"; + break; + case 10025: // TRADE_RETCODE_NO_CHANGES + text = "No changes in request"; + break; + case 10026: // TRADE_RETCODE_SERVER_DISABLES_AT + text = "Autotrading disabled by server"; + break; + case 10027: // TRADE_RETCODE_CLIENT_DISABLES_AT + text = "Autotrading disabled by client terminal"; + break; + case 10028: // TRADE_RETCODE_LOCKED + text = "Request locked for processing"; + break; + case 10029: // TRADE_RETCODE_FROZEN + text = "Order or position frozen"; + break; + case 10030: // TRADE_RETCODE_INVALID_FILL + text = "Invalid order filling type"; + break; + case 10031: // TRADE_RETCODE_CONNECTION + text = "No connection with the trade server"; + break; + case 10032: // TRADE_RETCODE_ONLY_REAL + text = "Operation is allowed only for live accounts"; + break; + case 10033: // TRADE_RETCODE_LIMIT_ORDERS + text = "The number of pending orders has reached the limit"; + break; + case 10034: // TRADE_RETCODE_LIMIT_VOLUME + text = "The volume of orders and positions for the symbol has reached the limit"; + break; + case 10035: // TRADE_RETCODE_INVALID_ORDER + text = "Incorrect or prohibited order type"; + break; + case 10036: // TRADE_RETCODE_POSITION_CLOSED + text = "Position with the specified POSITION_IDENTIFIER has already been closed"; + break; + case 10039: // TRADE_RETCODE_CLOSE_ORDER_EXIST + text = "A close order already exists for a specified position"; + break; + case 10040: // TRADE_RETCODE_LIMIT_POSITIONS + text = + "The number of open positions simultaneously present on an account can be limited by the server settings"; + break; + case 10041: // TRADE_RETCODE_REJECT_CANCEL + text = "The pending order activation request is rejected, the order is canceled"; + break; + case 10042: // TRADE_RETCODE_LONG_ONLY + text = "The request is rejected because only long positions are allowed"; + break; + case 10043: // TRADE_RETCODE_SHORT_ONLY + text = "The request is rejected because only short positions are allowed"; + break; + case 10044: // TRADE_RETCODE_CLOSE_ONLY + text = "The request is rejected because only position closing is allowed"; + break; + case 10045: // TRADE_RETCODE_FIFO_CLOSE + text = "The request is rejected because position closing is allowed only by FIFO rule"; + break; + case 10046: // TRADE_RETCODE_HEDGE_PROHIBITED + text = "The request is rejected because opposite positions on a single symbol are disabled"; + break; default: text = "Unknown error."; } @@ -1002,7 +1003,7 @@ class Terminal : public Object { case TERMINAL_COND_IS_CONNECTED: return !IsConnected(); default: - Print(StringFormat("Invalid terminal condition: %s!", EnumToString(_cond), __FUNCTION__)); + Print(StringFormat("Invalid terminal condition: %s!", C_STR(EnumToString(_cond)), __FUNCTION__)); return false; } } @@ -1037,7 +1038,7 @@ class Terminal : public Object { case TERMINAL_ACTION_CRASH: delete THIS_PTR; default: - Print(StringFormat("Invalid terminal action: %s!", EnumToString(_action), __FUNCTION__)); + Print(StringFormat("Invalid terminal action: %s!", C_STR(EnumToString(_action)), __FUNCTION__)); return false; } } @@ -1051,7 +1052,8 @@ class Terminal : public Object { /** * Returns textual representation of the Terminal class. */ - string ToString(string _sep = "; ") { + string const ToString() override { + string _sep = "; "; return StringFormat("Allow DLL: %s", IsDllsAllowed() ? "Yes" : "No") + _sep + StringFormat("Allow Libraries: %s", IsLibrariesAllowed() ? "Yes" : "No") + _sep + StringFormat("CPUs: %d", GetCpuCores()) + _sep + @@ -1071,16 +1073,18 @@ class Terminal : public Object { StringFormat("Memory (physical): %d", GetPhysicalMemory()) + _sep + StringFormat("Memory (total): %d", GetTotalMemory()) + _sep + StringFormat("Memory (used): %d", GetUsedMemory()) + _sep + - StringFormat("Path (Common): %s", GetCommonPath()) + _sep + StringFormat("Path (Data): %s", GetDataPath()) + - _sep + StringFormat("Path (Expert): %s", GetExpertPath()) + _sep + - StringFormat("Path (Terminal): %s", GetTerminalPath()) + _sep + - StringFormat("Program name: %s", WindowExpertName()) + _sep + + StringFormat("Path (Common): %s", C_STR(GetCommonPath())) + _sep + + StringFormat("Path (Data): %s", C_STR(GetDataPath())) + _sep + + StringFormat("Path (Expert): %s", C_STR(GetExpertPath())) + _sep + + StringFormat("Path (Terminal): %s", C_STR(GetTerminalPath())) + _sep + + StringFormat("Program name: %s", C_STR(WindowExpertName())) + _sep + StringFormat("Screen DPI: %d", GetScreenDpi()) + _sep + StringFormat("Terminal build: %d", GetBuild()) + - _sep + StringFormat("Terminal code page: %d", IntegerToString(GetCodePage())) + _sep + - StringFormat("Terminal company: %s", GetCompany()) + _sep + + _sep + StringFormat("Terminal code page: %d", C_STR(IntegerToString(GetCodePage()))) + _sep + + StringFormat("Terminal company: %s", C_STR(GetCompany())) + _sep + StringFormat("Terminal connected: %s", IsConnected() ? "Yes" : "No") + _sep + - StringFormat("Terminal language: %s", GetLanguage()) + _sep + StringFormat("Terminal name: %s", GetName()) + - _sep + StringFormat("Terminal max bars: %d", GetMaxBars()) + _sep + + StringFormat("Terminal language: %s", C_STR(GetLanguage())) + _sep + + StringFormat("Terminal name: %s", C_STR(GetName())) + _sep + + StringFormat("Terminal max bars: %d", GetMaxBars()) + _sep + StringFormat("Trade allowed: %s", IsTradeAllowed() ? "Yes" : "No") + _sep + StringFormat("Trade context busy: %s", IsTradeContextBusy() ? "Yes" : "No") + _sep + StringFormat("Trade perm: %s", CheckPermissionToTrade() ? "Yes" : "No") + _sep + diff --git a/tests/AccountTest.cpp b/tests/AccountTest.cpp index 64570c48c..4fb5082c8 100644 --- a/tests/AccountTest.cpp +++ b/tests/AccountTest.cpp @@ -34,30 +34,26 @@ typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned short ushort; - // Includes. -#include "../Account.mqh" +#include "../Account/Account.h" int main(int argc, char **argv) { - // Initialize class. - Account *acc = new Account(); - // Defines variables. - double _balance = AccountInfoDouble(ACCOUNT_BALANCE); - double _credit = AccountInfoDouble(ACCOUNT_CREDIT); - double _equity = AccountInfoDouble(ACCOUNT_EQUITY); + // double _balance = AccountInfoDouble(ACCOUNT_BALANCE); + // double _credit = AccountInfoDouble(ACCOUNT_CREDIT); + // double _equity = AccountInfoDouble(ACCOUNT_EQUITY); // Dummy calls. - acc.GetAccountName(); - acc.GetCompanyName(); - acc.GetLogin(); - acc.GetServerName(); + // acc.GetAccountName(); + // acc.GetCompanyName(); + // acc.GetLogin(); + // acc.GetServerName(); // Print account details. - Print(acc.ToString()); - Print(acc.ToCSV()); + // Print(acc.ToString()); + // Print(acc.ToCSV()); // Clean up. - delete acc; + // delete acc; } diff --git a/tests/ObjectTest.cpp b/tests/ObjectTest.cpp index bd281a86c..200b014a7 100644 --- a/tests/ObjectTest.cpp +++ b/tests/ObjectTest.cpp @@ -29,7 +29,7 @@ // Defines aliases for data types. typedef std::string string; -typedef unsigned chart uchar; +typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned short ushort; diff --git a/tests/SymbolInfoTest.cpp b/tests/SymbolInfoTest.cpp index 5060f3bed..9603626e8 100644 --- a/tests/SymbolInfoTest.cpp +++ b/tests/SymbolInfoTest.cpp @@ -40,13 +40,15 @@ typedef unsigned short ushort; int main(int argc, char **argv) { SymbolInfo *si = new SymbolInfo(); + MqlTick dtick, ltick; + // Test saving ticks. - si.SaveTick(dtick); - si.SaveTick(ltick); - si.ResetTicks(); + si->SaveTick(dtick); + si->SaveTick(ltick); + si->ResetTicks(); // Print. - Print("MARKET: ", si.ToString()); - Print("CSV (Header): ", si.ToCSV(true)); - Print("CSV (Data): ", si.ToCSV()); + Print("MARKET: ", si->ToString()); + Print("CSV (Header): ", si->ToCSV(true)); + Print("CSV (Data): ", si->ToCSV()); delete si; } diff --git a/tests/TerminalTest.cpp b/tests/TerminalTest.cpp index f5b3696b2..7471e025b 100644 --- a/tests/TerminalTest.cpp +++ b/tests/TerminalTest.cpp @@ -30,11 +30,7 @@ // Variables. Terminal *terminal; -long TimeTradeServer() { return 0; } - -datetime TimeCurrent() { return 0; } - -datetime TimeCurrent(MqlDateTime &dt_struct) { return 0; } +datetime TimeTradeServer() { return 0; } int main(int argc, char **argv) { terminal = new Terminal();