forked from nique_372/MQLArticles
1115 lines
67 KiB
MQL5
1115 lines
67 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| Managers.mqh |
| |
//| Copyright 2025, Niquel Mendoza. |
| |
//| https://www.mql5.com/es/users/nique_372/news |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2025, Niquel Mendoza."
| |
#property link "https://www.mql5.com/es/users/nique_372/news"
| |
#property strict
| |
| |
#ifndef MQLARTICLES_UTILS_FA_MANAGERS_MQH
| |
#define MQLARTICLES_UTILS_FA_MANAGERS_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| Includes |
| |
//+------------------------------------------------------------------+
| |
//--- CLoggerBase
| |
#include "SimpleLogger.mqh"
| |
| |
//--- Basic Functions
| |
#include "FuncionesBases.mqh"
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Base class for object managers |
| |
//+------------------------------------------------------------------+
| |
/*
| |
ADVERTENCIA: ESTA CLASE SI ELIMINA LOS ITEMS POR DEFECTO, TAMBIEN PROPAGA LOS FLAGS, ES COMO UNA EVOLUCION DE CSPECILZIAEDMANAGER, DADO QUE
| |
NO SOLO PROPAGA LOS FLAGS SI NO QUE SE PEUDEN HACER MAS COSAS CON LOS ITEMS.
| |
| |
WARNING: IF THIS CLASS REMOVES THE DEFAULT ITEMS, IT ALSO PROPAGATES THE FLAGS. IT IS LIKE AN EVOLUTION OF CSPECILZIAEDMANAGER,
| |
SINCE IT NOT ONLY PROPAGATES THE FLAGS BUT MORE THINGS CAN BE DONE WITH THE ITEMS.
| |
*/
| |
| |
| |
/*
| |
Spanish:
| |
Antes de incluir mqhs se podria poner CMANAGERBASE_STRICT_MODE, este define unicamente quitara verificacion de fuera de rango... para CheckPoitner
| |
este siempre se debera de hacer, esto lo hago para optimizar, por que si se que un codigo no dara errores entonces, creo que hacer esos check, estan
| |
por demas.. cuando lo programo, ahi creo qeu si es muy necesario..
| |
| |
English:
| |
Before including mqhs, you could set CMANAGERBASE_STRICT_MODE. This defines that it will only remove the out-of-range check... for CheckPointer,
| |
this should always be done. I do this for optimization purposes, because if I know a code won't produce errors, then I think doing those checks is unnecessary...
| |
when I program it, I think it's very necessary.
| |
*/
| |
| |
//---
| |
//#define CMANAGERBASE_STRICT_MODE
| |
| |
#define MANAGER_BASE_ACTION_NO_CHANGE_SIZE 0
| |
#define MANAGER_BASE_ACTION_CHANGE_SIZE 1
| |
#define MANAGER_BASE_ACTION_CLEAR_ITEMS 2
| |
| |
// Notas para CManagerBasesSimple:
| |
// P no debe tener constructor con parametros o tener uno default, si la clase es pura entonces se tendra que crear una clase hija.
| |
// P should not have a constructor with parameters or should have a default one; if the class is pure, then a child class will have to be created.
| |
// P debe de heredar de CLoggerBase
| |
// T es libre puede o no ser heredero de CLoggerBase
| |
| |
//+------------------------------------------------------------------+
| |
class CEmptyClass
| |
{
| |
public:
| |
CEmptyClass(void) {}
| |
~CEmptyClass(void) {}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| CManagerBasesSimple class |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
class CManagerBasesSimple : public P
| |
{
| |
protected:
| |
T* items[]; // Pointers Array
| |
int total; // Total number of items
| |
bool clean_in_destructor; // Flag indicating whether items will be deleted in the destructor
| |
| |
//--- Internal methods (without calling virtual functions, class-specific use)
| |
void RemoveInternal(int index);
| |
inline void AddItemInternal(T* item);
| |
inline void ReplaceInternal(int index, T* new_item);
| |
void InsertInternal(T* item, int index);
| |
| |
//--- Virtual functions
| |
virtual void OnAntesClear() {}
| |
| |
// Function executed each time a new element is added at index new_pos
| |
virtual void OnNewElement(int new_pos, int8_t action) {}
| |
| |
// Function executed each time an element is deleted at delete_pos
| |
virtual void OnDeleteElement(int delete_pos, T* item, int8_t action) {}
| |
| |
public:
| |
CManagerBasesSimple();
| |
~CManagerBasesSimple();
| |
| |
//--- General
| |
void SetCleanInDestructor(bool new_val) { clean_in_destructor = new_val; }
| |
__forceinline int Size() const { return total; }
| |
void CleanItems(bool delete_ptrs); // Clean the class and remove items
| |
| |
//--- Basic operations
| |
// Add
| |
virtual bool AddItem(T* item, bool check_duplicate); // Add item to end of array (pointer)
| |
bool AddItem(T& item, bool check_duplicate); // Add item to end of array (reference - usage: instance)
| |
inline void AddItemFast(T* item); // Add item to end of array (pointer), without checks
| |
| |
// Insert
| |
virtual bool Insert(T* item, int index); // Insert at position
| |
bool Insert(T& item, int index); // Insert at position
| |
| |
// Remove
| |
bool Remove(int index); // Remove by index (The function does not delete the pointer)
| |
bool Remove(T* item); // Remove by object (The function does not delete the pointer)
| |
bool RemoveFirst(); // Remove first (The function does not delete the pointer)
| |
bool RemoveLast(); // Remove last (The function does not delete the pointer)
| |
T* RemoveLastAndReturn(); // Remove last and return (The function does not delete the pointer)
| |
| |
// Delete
| |
bool Delete(int index); // Delete pointer
| |
| |
// Replace
| |
virtual bool Replace(int index, T* new_item); // Replace item (The function does not delete the pointer)
| |
| |
// Check index
| |
inline bool InRange(const int index, const string& function_name) const; // Check index
| |
| |
// Search
| |
int Find(T* item); // Find index
| |
int Exist(T* item); // Check if item exists (unique), returns its index if exists
| |
T* GetFirst(); // First item
| |
T* GetLast(); // Last item
| |
int GetActiveCount(); // Non-invalid items
| |
| |
// Get
| |
bool GetData(T* &dst_array[], int start = 0, int count = WHOLE_ARRAY) const;
| |
| |
//--- Utilities
| |
void Compact(); // Remove invalid items
| |
bool Swap(int index1, int index2); // Swap items
| |
void Reverse(); // Reverse order
| |
virtual void Summary(); // Info
| |
| |
//--- Operators
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
T* operator[](const int index) { return InRange(index, FUNCION_ACTUAL) ? items[index] : NULL; }
| |
#else
| |
T* operator[](const int index) { return items[index]; }
| |
#endif
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Constructor and Destructor |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P> CManagerBasesSimple::CManagerBasesSimple() : total(0)
| |
{
| |
ArrayResize(items, 0);
| |
this.clean_in_destructor = true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P> CManagerBasesSimple::~CManagerBasesSimple()
| |
{
| |
if(clean_in_destructor)
| |
CleanItems(true);
| |
else
| |
{
| |
ArrayResize(items, 0);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Function to check if an index is in the range [0 - (total-1)] |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
inline bool CManagerBasesSimple::InRange(const int index, const string& function_name) const
| |
{
| |
if(index < total && index >= 0)
| |
return true;
| |
else
| |
{
| |
LogError(StringFormat("Index %d is invalid, array range [ %d - %d ]", index, total - 1), function_name);
| |
return false;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Functions for (add - insert - replace) elements |
| |
//| (without calling virtual functions, class-specific use) |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::RemoveInternal(int index)
| |
{
| |
//---
| |
for(int i = index; i < total - 1; i++)
| |
items[i] = items[i + 1];
| |
| |
//---
| |
total--;
| |
ArrayResize(items, total);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
inline void CManagerBasesSimple::AddItemInternal(T* item)
| |
{
| |
ArrayResize(items, total + 1);
| |
items[total] = item;
| |
total++;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
inline void CManagerBasesSimple::ReplaceInternal(int index, T* new_item)
| |
{
| |
items[index] = new_item;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::InsertInternal(T* item, int index)
| |
{
| |
//---
| |
ArrayResize(items, total + 1);
| |
| |
//---
| |
for(int i = total; i > index; i--)
| |
items[i] = items[i - 1];
| |
| |
//---
| |
items[index] = item;
| |
total++;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Functions to (add - insert - replace) items |
| |
//| (public with calls to virtual functions) |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::AddItem(T* item, bool check_duplicate)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Cannot add NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//--- Only check if exists if requested
| |
if(check_duplicate)
| |
{
| |
if(Exist(item) != -1)
| |
{
| |
LogWarning("Item not added, it's duplicated", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
}
| |
| |
//--- Resize
| |
ArrayResize(items, total + 1);
| |
items[total] = item;
| |
| |
//---
| |
total++;
| |
| |
//---
| |
OnNewElement((total - 1), MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::AddItem(T& item, bool check_duplicate)
| |
{
| |
return AddItem(GetPointer(item), check_duplicate);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
inline void CManagerBasesSimple::AddItemFast(T* item)
| |
{
| |
items[ArrayResize(items, (++total)) - 1] = item;
| |
OnNewElement((total - 1), MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Insert(T* item, int index)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Cannot insert NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//---
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
ArrayResize(items, total + 1);
| |
| |
//--- Move elements to the right
| |
for(int i = total; i > index; i--)
| |
items[i] = items[i - 1];
| |
| |
//---
| |
items[index] = item;
| |
total++;
| |
| |
//---
| |
OnNewElement(index, MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
| |
//--- Log
| |
LogInfo(StringFormat("Item inserted at index %d. Total: %d", index, total), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Insert(T& item, int index)
| |
{
| |
return Insert(::GetPointer(item), index);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Delete(int index)
| |
{
| |
//---
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
//---
| |
if(CheckPointer(items[index]) == POINTER_DYNAMIC)
| |
{
| |
delete items[index];
| |
items[index] = NULL;
| |
return true;
| |
}
| |
else
| |
{
| |
LogError("The pointer was not removed because it is not dynamic or is invalid", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Remove(int index)
| |
{
| |
//---
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
OnDeleteElement(index, items[index], MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
| |
//---
| |
for(int i = index; i < total - 1; i++)
| |
items[i] = items[i + 1];
| |
| |
//---
| |
total--;
| |
ArrayResize(items, total);
| |
| |
//--- Log
| |
LogInfo(StringFormat("Item removed from index %d. Total: %d", index, total), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Remove(T* item)
| |
{
| |
// Find already checks if the item is invalid, and if it returns -1, Remove handles it (if CMANAGERBASE_STRICT_MODE is enabled)
| |
return Remove(Find(item));
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Replace(int index, T* new_item)
| |
{
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
if(!CheckPointer(new_item))
| |
{
| |
LogError("Cannot replace with NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//---
| |
OnDeleteElement(index, items[index], MANAGER_BASE_ACTION_NO_CHANGE_SIZE);
| |
items[index] = new_item;
| |
OnNewElement(index, MANAGER_BASE_ACTION_NO_CHANGE_SIZE);
| |
| |
//---
| |
LogInfo(StringFormat("Item replaced at index %d", index), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
T* CManagerBasesSimple::RemoveLastAndReturn()
| |
{
| |
//---
| |
if(total == 0)
| |
{
| |
LogWarning("No items to RemoveLastAndReturn", FUNCION_ACTUAL);
| |
return NULL;
| |
}
| |
| |
//---
| |
const int last_index = total - 1;
| |
T* last_item = items[last_index];
| |
OnDeleteElement(last_index, last_item, MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
| |
//---
| |
total--;
| |
ArrayResize(items, total);
| |
| |
//---
| |
LogInfo(StringFormat("RemoveLastAndReturn executed. Total: %d", total), FUNCION_ACTUAL);
| |
return last_item;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::RemoveFirst()
| |
{
| |
return Remove(0);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::RemoveLast()
| |
{
| |
return Remove(total - 1);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
int CManagerBasesSimple::Find(T* item)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Cannot find index of item*, its pointer is invalid", FUNCION_ACTUAL);
| |
return -1;
| |
}
| |
| |
//---
| |
for(int i = 0; i < total; i++)
| |
if(items[i] == item)
| |
return i;
| |
| |
//---
| |
LogWarning("Index not found for item pointer", FUNCION_ACTUAL);
| |
return -1;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
int CManagerBasesSimple::Exist(T* item)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Pointer is invalid", FUNCION_ACTUAL);
| |
return -1;
| |
}
| |
| |
//---
| |
const void* const ptr1 = item;
| |
for(int i = 0; i < total; i++)
| |
{
| |
const void* const ptr2 = items[i];
| |
if(ptr2 == ptr1)
| |
return i;
| |
}
| |
| |
//---
| |
return -1;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
T* CManagerBasesSimple::GetFirst()
| |
{
| |
if(total > 0)
| |
return items[0];
| |
| |
LogWarning("Total size of items is less than 1, there is no first item, will return NULL", FUNCION_ACTUAL);
| |
return NULL;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
T* CManagerBasesSimple::GetLast()
| |
{
| |
if(total > 0)
| |
return items[total - 1];
| |
| |
LogWarning("Total size of items is less than 1, there is no last item, will return NULL", FUNCION_ACTUAL);
| |
return NULL;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
int CManagerBasesSimple::GetActiveCount()
| |
{
| |
int count = 0;
| |
for(int i = 0; i < total; i++)
| |
if(CheckPointer(items[i]) != POINTER_INVALID)
| |
count++;
| |
| |
//---
| |
return count;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::Compact()
| |
{
| |
//---
| |
int write_pos = 0;
| |
| |
//---
| |
for(int i = 0; i < total; i++)
| |
{
| |
if(CheckPointer(items[i]) != POINTER_INVALID)
| |
{
| |
if(write_pos != i)
| |
items[write_pos] = items[i];
| |
write_pos++;
| |
}
| |
}
| |
| |
//---
| |
int old_total = total;
| |
total = write_pos;
| |
ArrayResize(items, total);
| |
| |
//--- Log
| |
LogInfo(StringFormat("Compaction completed: %d -> %d items", old_total, total), FUNCION_ACTUAL);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::Swap(int index1, int index2)
| |
{
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index1, FUNCION_ACTUAL) || !InRange(index2, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
T* temp = items[index1];
| |
items[index1] = items[index2];
| |
items[index2] = temp;
| |
| |
//--- Log
| |
LogCaution(StringFormat("Items swapped: indices %d and %d", index1, index2), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::Reverse()
| |
{
| |
ArrayReverse(items);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::CleanItems(bool delete_ptrs)
| |
{
| |
//---
| |
if(total < 1)
| |
return;
| |
| |
//---
| |
const int t = total;
| |
OnAntesClear();
| |
| |
//---
| |
for(int i = 0; i < total; i++)
| |
{
| |
OnDeleteElement(i, items[i], MANAGER_BASE_ACTION_CLEAR_ITEMS);
| |
if(delete_ptrs && CheckPointer(items[i]) == POINTER_DYNAMIC)
| |
{
| |
delete items[i];
| |
items[i] = NULL;
| |
}
| |
}
| |
| |
//---
| |
total = ArrayResize(items, 0);
| |
| |
//--- Log
| |
LogWarning(StringFormat("Manager cleaned, objects before = %d, now = 0", t), FUNCION_ACTUAL);
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
bool CManagerBasesSimple::GetData(T* &dst_array[], int start = 0, int count = WHOLE_ARRAY) const
| |
{
| |
//---
| |
count = (count == WHOLE_ARRAY) ? (total - start) : count; // Count real
| |
const int end = (start + (count - 1)); // Indice final
| |
if(start < 0 || end >= total) // Strat menor a 0 | final mayor o igual a total
| |
return false;
| |
| |
//---
| |
ArrayResize(dst_array, count);
| |
| |
//---
| |
for(int id = 0, is = start; is <= end; id++, is++)
| |
{
| |
dst_array[id] = items[is];
| |
}
| |
return true;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| Function to print manager information |
| |
//+------------------------------------------------------------------+
| |
template<typename T, typename P>
| |
void CManagerBasesSimple::Summary()
| |
{
| |
LogInfo(StringFormat("<< ManagerInfo >> Total: %d | Active: %d | ArraySize: %d", total, GetActiveCount(), ArraySize(items)), FUNCION_ACTUAL);
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| CManagerBase class |
| |
//+------------------------------------------------------------------+
| |
// Nota: T debe de ser herededo de CLoggerBase si o si
| |
| |
template<typename T>
| |
class CManagerBase : public CManagerBasesSimple<T, CLoggerBase>
| |
{
| |
protected:
| |
bool funcionar_solo_como_container; // Flag indicating whether the class only functions as a manager (No flags are propagated)
| |
| |
//--- Function to propagate logging flags
| |
void PropagateFlags(const uint8_t flags, bool enable);
| |
| |
public:
| |
CManagerBase(bool funcionar_solo_como_container_);
| |
~CManagerBase() {}
| |
| |
//--- Basic operations
| |
// Add
| |
using CManagerBasesSimple<T, CLoggerBase>::AddItem; // reference
| |
bool AddItem(T* item, bool check_duplicate) override; // Add item to end of array (pointer)
| |
| |
// Insert
| |
using CManagerBasesSimple<T, CLoggerBase>::Insert; // reference
| |
bool Insert(T* item, int index) override; // Insert at position
| |
| |
// Replace
| |
bool Replace(int index, T* new_item) override; // Replace item (The function does not delete the pointer)
| |
| |
//--- Logs
| |
void AddLogFlags(const uint8_t flags) override;
| |
void RemoveLogFlags(const uint8_t flags) override;
| |
void EnableAllLogs() override;
| |
void DisableAllLogs() override;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Constructor and Destructor |
| |
//+------------------------------------------------------------------+
| |
template<typename T> CManagerBase::CManagerBase(bool funcionar_solo_como_container_)
| |
{
| |
this.funcionar_solo_como_container = funcionar_solo_como_container_;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Functions to (add - insert - replace) items |
| |
//| (public with calls to virtual functions) |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
bool CManagerBase::AddItem(T* item, bool check_duplicate)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Cannot add NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//--- Only check if exists if requested
| |
if(check_duplicate)
| |
{
| |
if(Exist(item) != -1)
| |
{
| |
LogWarning("Item not added, it's duplicated", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
}
| |
| |
//--- Resize
| |
ArrayResize(items, total + 1);
| |
items[total] = item;
| |
| |
//--- Add log_flags
| |
if(!funcionar_solo_como_container)
| |
items[total].AddLogFlags(LogFlags());
| |
| |
//---
| |
total++;
| |
| |
//---
| |
OnNewElement((total - 1), MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
bool CManagerBase::Insert(T* item, int index)
| |
{
| |
//---
| |
if(!CheckPointer(item))
| |
{
| |
LogError("Cannot insert NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//---
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
ArrayResize(items, total + 1);
| |
| |
//--- Move elements to the right
| |
for(int i = total; i > index; i--)
| |
items[i] = items[i - 1];
| |
| |
//---
| |
items[index] = item;
| |
| |
//--- Add log_flags
| |
if(!funcionar_solo_como_container)
| |
items[index].AddLogFlags(LogFlags());
| |
| |
//---
| |
total++;
| |
| |
//---
| |
OnNewElement(index, MANAGER_BASE_ACTION_CHANGE_SIZE);
| |
| |
//--- Log
| |
LogInfo(StringFormat("Item inserted at index %d. Total: %d", index, total), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
bool CManagerBase::Replace(int index, T* new_item)
| |
{
| |
#ifdef CMANAGERBASE_STRICT_MODE
| |
if(!InRange(index, FUNCION_ACTUAL))
| |
return false;
| |
#endif
| |
| |
//---
| |
if(!CheckPointer(new_item))
| |
{
| |
LogError("Cannot replace with NULL item", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//---
| |
OnDeleteElement(index, items[index], MANAGER_BASE_ACTION_NO_CHANGE_SIZE);
| |
items[index] = new_item;
| |
OnNewElement(index, MANAGER_BASE_ACTION_NO_CHANGE_SIZE);
| |
| |
//--- Add log_flags
| |
if(!funcionar_solo_como_container)
| |
items[index].AddLogFlags(LogFlags());
| |
| |
//---
| |
LogInfo(StringFormat("Item replaced at index %d", index), FUNCION_ACTUAL);
| |
return true;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Functions for propagating logging flags |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
void CManagerBase::PropagateFlags(const uint8_t flags, bool enable)
| |
{
| |
for(int i = 0; i < total; i++)
| |
{
| |
if(enable)
| |
items[i].AddLogFlags(flags);
| |
else
| |
items[i].RemoveLogFlags(flags);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
void CManagerBase::AddLogFlags(const uint8_t flags)
| |
{
| |
CLoggerBase::AddLogFlags(flags);
| |
| |
if(funcionar_solo_como_container)
| |
return;
| |
| |
PropagateFlags(flags, true);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
void CManagerBase::RemoveLogFlags(const uint8_t flags)
| |
{
| |
CLoggerBase::RemoveLogFlags(flags);
| |
| |
if(funcionar_solo_como_container)
| |
return;
| |
| |
PropagateFlags(flags, false);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
void CManagerBase::EnableAllLogs()
| |
{
| |
CLoggerBase::EnableAllLogs();
| |
| |
if(funcionar_solo_como_container)
| |
return;
| |
| |
for(int i = 0; i < total; i++)
| |
{
| |
items[i].EnableAllLogs();
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
template<typename T>
| |
void CManagerBase::DisableAllLogs()
| |
{
| |
CLoggerBase::DisableAllLogs();
| |
| |
if(funcionar_solo_como_container)
| |
return;
| |
| |
for(int i = 0; i < total; i++)
| |
{
| |
items[i].DisableAllLogs();
| |
}
| |
}
| |
| |
| |
| |
//+------------------------------------------------------------------------------+
| |
//| Base class for flag propagation |
| |
//| Utils: When you have a class with several objects separate from CLoggerBase, |
| |
//| so propagating logs to instances or pointers is necessary |
| |
//+------------------------------------------------------------------------------+
| |
/*
| |
Spanish:
| |
ADVERTENCIA NO SE ELIMINAN LOS ITEMS, PERO SI HAY UNA FUNCION INTEGRADA PARA HCERLO PERO ESTA SOLO ESTA COMO FUNCIONALDAD, IDEALMENTE SOLO SUAR PARA PROPAGAR FLAGS
| |
English:
| |
WARNING ITEMS ARE NOT REMOVED, BUT THERE IS A BUILT-IN FUNCTION TO DO SO, BUT THIS IS ONLY FOR FUNCTIONALITY, IDEALLY ONLY USED TO PROPAGATE FLAGS
| |
*/
| |
| |
//--- Implementation
| |
class CSpecializedManager : public CLoggerBase
| |
{
| |
protected:
| |
int m_loggers_total;
| |
CLoggerBase* m_loggers[];
| |
| |
//--- Propaga flags
| |
void PropagateFlags(const uint8_t flags, bool enable);
| |
| |
//--- Elimina un logger
| |
bool RemoveLogger(CLoggerBase * _logger);
| |
| |
//---
| |
void DeleteLoggerAlredyExist(CLoggerBase *_logger);
| |
| |
//--- Añade un logger
| |
void AddLogger(CLoggerBase * _logger);
| |
__forceinline void AddLogger(CLoggerBase & _logger);
| |
| |
//--- Elimina los items (Delete si son dynamicos)
| |
virtual void CleanItems(const string &den_name);
| |
virtual void CleanItemsNoDelete(const string& den_name);
| |
| |
public:
| |
CSpecializedManager();
| |
~CSpecializedManager() {}
| |
| |
void AddLogFlags(const uint8_t flags) override;
| |
void RemoveLogFlags(const uint8_t flags) override;
| |
void EnableAllLogs() override;
| |
void DisableAllLogs() override;
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| Constructor |
| |
//+------------------------------------------------------------------+
| |
CSpecializedManager::CSpecializedManager() : m_loggers_total(0)
| |
{
| |
ArrayResize(m_loggers, 0);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::CleanItems(const string &den_name)
| |
{
| |
#ifdef CSM_DEBUG_ELIMIACIONES
| |
const string f = StringFormat("CSpecializedManger[%s]::CleanItems", den_name);
| |
FastLog(f, "WARNING", "Se esta limpiando los m_loggers");
| |
#endif
| |
| |
//---
| |
for(int i = 0; i < m_loggers_total; i++)
| |
if(CheckPointer(m_loggers[i]) == POINTER_DYNAMIC)
| |
delete m_loggers[i];
| |
| |
//---
| |
m_loggers_total = ArrayResize(m_loggers, 0);
| |
| |
//---
| |
#ifdef CSM_DEBUG_ELIMIACIONES
| |
FastLog(f, WARNING_TEXT, "Fin de limpieza");
| |
#endif
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::CleanItemsNoDelete(const string &den_name)
| |
{
| |
#ifdef CSM_DEBUG_ELIMIACIONES
| |
const string f = StringFormat("CSpecializedManger[%s]::CleanItems", den_name);
| |
FastLog(f, WARNING_TEXT, "Se esta limpiando los m_loggers");
| |
#endif
| |
//---
| |
m_loggers_total = ArrayResize(m_loggers, 0);
| |
//---
| |
#ifdef CSM_DEBUG_ELIMIACIONES
| |
FastLog(f, WARNING_TEXT, "Fin de limpieza");
| |
#endif
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::AddLogger(CLoggerBase* _logger)
| |
{
| |
//---
| |
if(!CheckPointer(_logger))
| |
{
| |
LogFatalError("El puntero *_logger es inválido", FUNCION_ACTUAL);
| |
return;
| |
}
| |
| |
//---
| |
m_loggers[ArrayResize(m_loggers, (++m_loggers_total)) - 1] = _logger;
| |
| |
//---
| |
_logger.AddLogFlags(LogFlags());
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
__forceinline void CSpecializedManager::AddLogger(CLoggerBase &_logger)
| |
{
| |
AddLogger(GetPointer(_logger));
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CSpecializedManager::RemoveLogger(CLoggerBase* _logger)
| |
{
| |
//---
| |
if(!CheckPointer(_logger))
| |
{
| |
LogError("Se esta removiendo un logger NULL", FUNCION_ACTUAL);
| |
}
| |
| |
//---
| |
for(int i = 0; i < m_loggers_total; i++)
| |
{
| |
if(m_loggers[i] == _logger)
| |
{
| |
//---
| |
m_loggers[i] = m_loggers[--m_loggers_total];
| |
ArrayResize(m_loggers, m_loggers_total);
| |
| |
//---
| |
LogInfo(StringFormat("Logger en índice %d removido. Total restante: %d", i, m_loggers_total), FUNCION_ACTUAL);
| |
| |
//---
| |
return true;
| |
}
| |
}
| |
| |
//---
| |
LogWarning("Logger no encontrado para remover", FUNCION_ACTUAL);
| |
return false;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::DeleteLoggerAlredyExist(CLoggerBase *_logger)
| |
{
| |
//---
| |
const ENUM_POINTER_TYPE type_ptr = CheckPointer(_logger);
| |
if(type_ptr == POINTER_INVALID)
| |
return; // Early exit
| |
| |
//---
| |
for(int i = 0; i < m_loggers_total; i++)
| |
{
| |
if(m_loggers[i] == _logger)
| |
{
| |
//--- Eliminamos el puntero solo si es dincamico
| |
if(type_ptr == POINTER_DYNAMIC)
| |
delete m_loggers[i];
| |
| |
//--- Lo eliminamos del array
| |
m_loggers[i] = m_loggers[--m_loggers_total];
| |
ArrayResize(m_loggers, m_loggers_total);
| |
| |
//---
| |
LogInfo(StringFormat("Logger en índice %d removido. Total restante: %d", i, m_loggers_total), FUNCION_ACTUAL);
| |
| |
//---
| |
return;
| |
}
| |
}
| |
| |
//---
| |
LogWarning("Logger no encontrado para remover", FUNCION_ACTUAL);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::PropagateFlags(const uint8_t flags, bool enable)
| |
{
| |
for(int i = 0; i < m_loggers_total; i++)
| |
{
| |
if(enable)
| |
m_loggers[i].AddLogFlags(flags);
| |
else
| |
m_loggers[i].RemoveLogFlags(flags);
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::AddLogFlags(const uint8_t flags)
| |
{
| |
CLoggerBase::AddLogFlags(flags);
| |
PropagateFlags(flags, true);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::RemoveLogFlags(const uint8_t flags)
| |
{
| |
CLoggerBase::RemoveLogFlags(flags);
| |
PropagateFlags(flags, false);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::EnableAllLogs()
| |
{
| |
CLoggerBase::EnableAllLogs();
| |
for(int i = 0; i < m_loggers_total; i++)
| |
{
| |
m_loggers[i].EnableAllLogs();
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void CSpecializedManager::DisableAllLogs()
| |
{
| |
CLoggerBase::DisableAllLogs();
| |
for(int i = 0; i < m_loggers_total; i++)
| |
{
| |
m_loggers[i].DisableAllLogs();
| |
}
| |
}
| |
| |
| |
#endif
| |
//+------------------------------------------------------------------+
|