Skip to content

Commit

Permalink
Merge pull request #761 from nseam/v3.008-dev-new--cpp-compatibility
Browse files Browse the repository at this point in the history
C++ compatibility fixes.
  • Loading branch information
kenorb authored Aug 31, 2024
2 parents af76a93 + 997d430 commit 5ebdfa7
Show file tree
Hide file tree
Showing 12 changed files with 419 additions and 400 deletions.
158 changes: 79 additions & 79 deletions Array.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

/*
Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -610,16 +610,16 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) {
#ifdef __MQL4__
template <typename T>
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

Expand Down Expand Up @@ -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 <typename X>
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 <typename X>
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 <typename X>
/**
* 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 <typename X>
static int ArrayMinimum(ARRAY_REF(X, _array), int _start = 0, int _count = WHOLE_ARRAY) {
#ifdef __MQL__
return ::ArrayMinimum(_array);
Expand All @@ -707,23 +707,23 @@ template <typename X>
#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 <typename X>
/**
* 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 <typename X>
static int ArrayMaximum(ARRAY_REF(X, _array), int start = 0, int count = WHOLE_ARRAY) {
#ifdef __MQL__
return ::ArrayMaximum(_array);
Expand All @@ -740,22 +740,22 @@ template <typename X>
#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 <typename X>
/**
* 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 <typename X>
static int ArraySize(ARRAY_REF(X, array)) {
return ::ArraySize(array);
}
return ::ArraySize(array);
}

template <typename X>
static void ArrayStore(ARRAY_REF(X, array), int _idx, X value, int reserve_size = 0) {
Expand Down
53 changes: 28 additions & 25 deletions Dict.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,9 @@ class Dict : public DictBase<K, V> {

// 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
Expand All @@ -249,7 +249,7 @@ class Dict : public DictBase<K, V> {
// 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.
Expand All @@ -263,7 +263,7 @@ class Dict : public DictBase<K, V> {
// 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;
Expand All @@ -272,15 +272,16 @@ class Dict : public DictBase<K, V> {
unsigned int _num_conflicts = 0;

// Searching for empty DictSlot<K, V> 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;
Expand All @@ -289,19 +290,20 @@ class Dict : public DictBase<K, V> {
}

// 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;
}

Expand All @@ -326,24 +328,25 @@ class Dict : public DictBase<K, V> {
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<K, V>.
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;
}

Expand Down Expand Up @@ -378,15 +381,15 @@ class Dict : public DictBase<K, V> {

DictSlotsRef<K, V>* new_DictSlots = new DictSlotsRef<K, V>();

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) {
Expand Down
Loading

0 comments on commit 5ebdfa7

Please sign in to comment.