Skip to content

Commit

Permalink
C++ compatibility fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
nseam committed Aug 30, 2024
1 parent af76a93 commit 6f83607
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 183 deletions.
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
73 changes: 41 additions & 32 deletions DictBase.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class DictBase {

DictIteratorBase<K, V> 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<K, V> iter(this, i);
return iter;
}
Expand All @@ -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.
Expand All @@ -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<K, V>* GetSlotByKey(DictSlotsRef<K, V>*& 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;

Expand All @@ -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;
Expand All @@ -139,7 +139,7 @@ class DictBase {
* Returns slot by position.
*/
DictSlot<K, V>* GetSlotByPos(DictSlotsRef<K, V>*& 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;
}

/**
Expand Down Expand Up @@ -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;
}
Expand All @@ -189,7 +189,11 @@ class DictBase {
if (GetMode() == DictModeList) {
// In list mode value index is the slot index.
#ifndef __MQL__
if constexpr (std::is_same<K, int>::value) {
if
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
constexpr
#endif
(std::is_same<K, int>::value) {
#endif
position = (int)key;
#ifndef __MQL__
Expand All @@ -198,23 +202,27 @@ 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<K, int>::value) {
if
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
constexpr
#endif
(std::is_same<K, int>::value) {
#endif
_should_be_removed = position == (unsigned int)key;
#ifndef __MQL__
Expand All @@ -223,18 +231,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);
Expand All @@ -247,7 +255,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.
Expand All @@ -262,30 +270,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;

Expand All @@ -294,13 +302,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;
}
Expand Down
Loading

0 comments on commit 6f83607

Please sign in to comment.