forked from nique_372/MQLArticles
		
	
		
			
				
	
	
		
			844 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			844 lines
		
	
	
	
		
			50 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 UTILS_FA_SIMPLE_MANAGER_MQH
 | 
						|
#define UTILS_FA_SIMPLE_MANAGER_MQH
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Includes                                                         |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//--- CLoggerBase
 | 
						|
#include "SimpleLogger.mqh"
 | 
						|
 | 
						|
//---
 | 
						|
#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_DEBUG, 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_DEBUG. 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_DEBUG
 | 
						|
 | 
						|
//---
 | 
						|
template<typename T>
 | 
						|
class CManagerBase : public CLoggerBase
 | 
						|
 {
 | 
						|
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
 | 
						|
  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);
 | 
						|
 | 
						|
  //--- 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() {}
 | 
						|
  virtual void       OnNewElement(int new_pos) {}                // Function executed each time a new element is added at index new_pos
 | 
						|
  virtual void       OnDeleteElement(int delete_pos, T* item) {} // Function executed each time an element is deleted at delete_pos
 | 
						|
 | 
						|
public:
 | 
						|
                     CManagerBase(bool funcionar_solo_como_container_);
 | 
						|
                    ~CManagerBase();
 | 
						|
 | 
						|
  //--- General
 | 
						|
  void               SetCleanInDestructor(bool new_val) { clean_in_destructor = new_val; }
 | 
						|
  inline int         Size() const { return total; }
 | 
						|
  void               CleanItems(bool delete_ptrs);        // Clean the class and remove items
 | 
						|
 | 
						|
  //--- Basic operations
 | 
						|
  // Add
 | 
						|
  virtual void       AddItem(T* item, bool check_duplicate); // Add item to end of array (pointer)
 | 
						|
  void               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
 | 
						|
  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*                 Pop();                             // Remove last and return (The function does not delete the pointer)
 | 
						|
 | 
						|
  // Replace
 | 
						|
  bool               Replace(int index, T* new_item);   // Replace item
 | 
						|
 | 
						|
  // 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
 | 
						|
 | 
						|
  //--- Utilities
 | 
						|
  void               Compact();                         // Remove invalid items
 | 
						|
  bool               Swap(int index1, int index2);      // Swap items
 | 
						|
  void               Reverse();                         // Reverse order
 | 
						|
  virtual void       PrintInfo();                       // Debug info
 | 
						|
 | 
						|
  //--- Operators
 | 
						|
#ifdef CMANAGERBASE_DEBUG
 | 
						|
  T*                 operator[](const int index) { return InRange(index, FUNCION_ACTUAL) ? items[index] : NULL; }
 | 
						|
#else
 | 
						|
  T*                 operator[](const int index) { return items[index]; }
 | 
						|
#endif
 | 
						|
 | 
						|
  //--- Logs
 | 
						|
  void               AddLogFlags(const uint8_t flags) override;
 | 
						|
  void               RemoveLogFlags(const uint8_t flags) override;
 | 
						|
  void               EnableAllLogs() override;
 | 
						|
  void               DisableAllLogs() override;
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Constructor                                                      |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T> CManagerBase::CManagerBase(bool funcionar_solo_como_container_) : total(0)
 | 
						|
 {
 | 
						|
  ArrayResize(items, 0);
 | 
						|
  this.funcionar_solo_como_container = funcionar_solo_como_container_;
 | 
						|
  this.clean_in_destructor = true;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T> CManagerBase::~CManagerBase()
 | 
						|
 {
 | 
						|
  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>
 | 
						|
inline bool CManagerBase::InRange(const int index, const string& function_name) const
 | 
						|
 {
 | 
						|
  if(index < total && index >= 0)
 | 
						|
    return true;
 | 
						|
  else
 | 
						|
   {
 | 
						|
    LogError(StringFormat("(%s) Index %d is invalid, array range [ %d - %d ]", function_name, index, total), function_name);
 | 
						|
    return false;
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Functions for (add - insert - replace) elements                  |
 | 
						|
//| (without calling virtual functions, class-specific use)          |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::RemoveInternal(int index)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  for(int i = index; i < total - 1; i++)
 | 
						|
    items[i] = items[i + 1];
 | 
						|
 | 
						|
//---
 | 
						|
  total--;
 | 
						|
  ArrayResize(items, total);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
inline void CManagerBase::AddItemInternal(T* item)
 | 
						|
 {
 | 
						|
  ArrayResize(items, total + 1);
 | 
						|
  items[total] = item;
 | 
						|
  total++;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
inline void CManagerBase::ReplaceInternal(int index, T* new_item)
 | 
						|
 {
 | 
						|
  items[index] = new_item;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::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>
 | 
						|
void CManagerBase::AddItem(T* item, bool check_duplicate)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(!CheckPointer(item))
 | 
						|
   {
 | 
						|
    LogError("Cannot add NULL item", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//--- Only check if exists if requested
 | 
						|
  if(check_duplicate)
 | 
						|
   {
 | 
						|
    if(Exist(item) != -1)
 | 
						|
     {
 | 
						|
      LogWarning("Item not added, it's duplicated", FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
   }
 | 
						|
 | 
						|
//--- Resize
 | 
						|
  ArrayResize(items, total + 1);
 | 
						|
  items[total] = item;
 | 
						|
 | 
						|
//--- Add log_flags
 | 
						|
  if(!funcionar_solo_como_container)
 | 
						|
    items[total].AddLogFlags(LogFlags());
 | 
						|
 | 
						|
//---
 | 
						|
  OnNewElement(total);
 | 
						|
 | 
						|
//---
 | 
						|
  total++;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::AddItem(T& item, bool check_duplicate)
 | 
						|
 {
 | 
						|
  AddItem(GetPointer(item), check_duplicate);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
inline void CManagerBase::AddItemFast(T* item)
 | 
						|
 {
 | 
						|
  ArrayResize(items, total + 1);
 | 
						|
  items[total] = item;
 | 
						|
  OnNewElement(total);
 | 
						|
  total++;
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::Insert(T* item, int index)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(CheckPointer(item) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    LogError("Cannot insert NULL item", FUNCION_ACTUAL);
 | 
						|
    return false;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  if(!InRange(index, FUNCION_ACTUAL))
 | 
						|
    return false;
 | 
						|
 | 
						|
//---
 | 
						|
  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);
 | 
						|
 | 
						|
//--- Log
 | 
						|
  LogInfo(StringFormat("Item inserted at index %d. Total: %d", index, total), FUNCION_ACTUAL);
 | 
						|
  return true;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::Insert(T& item, int index)
 | 
						|
 {
 | 
						|
  return Insert(::GetPointer(item), index);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::Remove(int index)
 | 
						|
 {
 | 
						|
//---
 | 
						|
#ifdef CMANAGERBASE_DEBUG
 | 
						|
  if(!InRange(index, FUNCION_ACTUAL))
 | 
						|
    return false;
 | 
						|
#endif
 | 
						|
 | 
						|
//---
 | 
						|
  OnDeleteElement(index, items[index]);
 | 
						|
 | 
						|
//---
 | 
						|
  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>
 | 
						|
bool CManagerBase::Remove(T* item)
 | 
						|
 {
 | 
						|
// Find already checks if the item is invalid, and if it returns -1, Remove handles it (if CMANAGERBASE_DEBUG is enabled)
 | 
						|
  return Remove(Find(item));
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::Replace(int index, T* new_item)
 | 
						|
 {
 | 
						|
#ifdef CMANAGERBASE_DEBUG
 | 
						|
  if(!InRange(index, FUNCION_ACTUAL))
 | 
						|
    return false;
 | 
						|
#endif
 | 
						|
 | 
						|
//---
 | 
						|
  if(CheckPointer(new_item) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    LogError("Cannot replace with NULL item", FUNCION_ACTUAL);
 | 
						|
    return false;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  OnDeleteElement(index, items[index]);
 | 
						|
  items[index] = new_item;
 | 
						|
  OnNewElement(index);
 | 
						|
 | 
						|
//---
 | 
						|
  LogInfo(StringFormat("Item replaced at index %d", index), FUNCION_ACTUAL);
 | 
						|
  return true;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
T* CManagerBase::Pop()
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(total == 0)
 | 
						|
   {
 | 
						|
    LogWarning("No items to Pop", FUNCION_ACTUAL);
 | 
						|
    return NULL;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  const int last_index = total - 1;
 | 
						|
  T* last_item = items[last_index];
 | 
						|
  OnDeleteElement(last_index, last_item);
 | 
						|
 | 
						|
//---
 | 
						|
  total--;
 | 
						|
  ArrayResize(items, total);
 | 
						|
 | 
						|
//---
 | 
						|
  LogInfo(StringFormat("Pop executed. Total: %d", total), FUNCION_ACTUAL);
 | 
						|
  return last_item;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::RemoveFirst()
 | 
						|
 {
 | 
						|
  return Remove(0);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
bool CManagerBase::RemoveLast()
 | 
						|
 {
 | 
						|
  return Remove(total - 1);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
int CManagerBase::Find(T* item)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(CheckPointer(item) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    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>
 | 
						|
int CManagerBase::Exist(T* item)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(CheckPointer(item) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    LogError("Pointer is invalid", FUNCION_ACTUAL);
 | 
						|
    return -1;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  const void* ptr1 = item;
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
   {
 | 
						|
    const void* ptr2 = items[i];
 | 
						|
    if(ptr2 == ptr1)
 | 
						|
      return i;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  return -1;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
T* CManagerBase::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>
 | 
						|
T* CManagerBase::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>
 | 
						|
int CManagerBase::GetActiveCount()
 | 
						|
 {
 | 
						|
  int count = 0;
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
    if(CheckPointer(items[i]) != POINTER_INVALID)
 | 
						|
      count++;
 | 
						|
 | 
						|
//---
 | 
						|
  return count;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::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>
 | 
						|
bool CManagerBase::Swap(int index1, int index2)
 | 
						|
 {
 | 
						|
#ifdef CMANAGERBASE_DEBUG
 | 
						|
  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>
 | 
						|
void CManagerBase::Reverse()
 | 
						|
 {
 | 
						|
  ArrayReverse(items);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::CleanItems(bool delete_ptrs)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(total < 1)
 | 
						|
    return;
 | 
						|
 | 
						|
//---
 | 
						|
  const int t = total;
 | 
						|
  OnAntesClear();
 | 
						|
 | 
						|
//---
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
   {
 | 
						|
    OnDeleteElement(i, items[i]);
 | 
						|
    if(delete_ptrs && CheckPointer(items[i]) == POINTER_DYNAMIC)
 | 
						|
     {
 | 
						|
      delete items[i];
 | 
						|
      items[i] = NULL;
 | 
						|
     }
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  ArrayResize(items, 0);
 | 
						|
  total = 0;
 | 
						|
 | 
						|
//--- Log
 | 
						|
  LogWarning(StringFormat("Manager cleaned, objects before = %d, now = 0", t), FUNCION_ACTUAL);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Function to print manager information                            |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
template<typename T>
 | 
						|
void CManagerBase::PrintInfo()
 | 
						|
 {
 | 
						|
  LogInfo(StringFormat("Manager Info - Total: %d, Active: %d, ArraySize: %d", total, GetActiveCount(), ArraySize(items)), FUNCION_ACTUAL);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| 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                total;
 | 
						|
  CLoggerBase*       items[];
 | 
						|
 | 
						|
  void               PropagateFlags(const uint8_t flags, bool enable);
 | 
						|
 | 
						|
  void               RemoveLogger(int index);
 | 
						|
  bool               RemoveLogger(CLoggerBase * _logger);
 | 
						|
  void               AddLogger(CLoggerBase * _logger);
 | 
						|
  void               AddLogger(CLoggerBase & _logger);
 | 
						|
  virtual void       CleanItems(const string &den_name) final;
 | 
						|
 | 
						|
public:
 | 
						|
                     CSpecializedManager();
 | 
						|
  void               AddLogFlags(const uint8_t flags) override;
 | 
						|
  void               RemoveLogFlags(const uint8_t flags) override;
 | 
						|
  void               EnableAllLogs() override;
 | 
						|
  void               DisableAllLogs() override;
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Constructor                                                      |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CSpecializedManager::CSpecializedManager() : total(0)
 | 
						|
 {
 | 
						|
  ArrayResize(items, 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 items");
 | 
						|
#endif
 | 
						|
 | 
						|
//---
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
    if(CheckPointer(items[i]) == POINTER_DYNAMIC)
 | 
						|
      delete items[i];
 | 
						|
 | 
						|
//---
 | 
						|
  total = 0;
 | 
						|
  ArrayResize(items, 0);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CSpecializedManager::AddLogger(CLoggerBase* _logger)
 | 
						|
 {
 | 
						|
  if(CheckPointer(_logger) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    LogFatalError("El puntero *_logger es inválido", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  AddArrayNoVerification1(this.items, _logger, total, 0);
 | 
						|
 | 
						|
//---
 | 
						|
  total = ArraySize(items);
 | 
						|
 | 
						|
//---
 | 
						|
  _logger.AddLogFlags(LogFlags());
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CSpecializedManager::AddLogger(CLoggerBase &_logger)
 | 
						|
 {
 | 
						|
  AddLogger(GetPointer(_logger));
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CSpecializedManager::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);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
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 < total; i++)
 | 
						|
   {
 | 
						|
    items[i].EnableAllLogs();
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CSpecializedManager::DisableAllLogs()
 | 
						|
 {
 | 
						|
  CLoggerBase::DisableAllLogs();
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
   {
 | 
						|
    items[i].DisableAllLogs();
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CSpecializedManager::RemoveLogger(int index)
 | 
						|
 {
 | 
						|
  if(index < 0 || index >= total)
 | 
						|
   {
 | 
						|
    LogError(StringFormat("Índice inválido: %d. Rango válido: 0-%d", index, total - 1), FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
  if(total == 0)
 | 
						|
   {
 | 
						|
    LogWarning("No hay loggers para remover", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
  for(int i = index; i < total - 1; i++)
 | 
						|
   {
 | 
						|
    items[i] = items[i + 1];
 | 
						|
   }
 | 
						|
 | 
						|
  total--;
 | 
						|
  ArrayResize(items, total);
 | 
						|
 | 
						|
  LogInfo(StringFormat("Logger en índice %d removido. Total restante: %d", index, total), FUNCION_ACTUAL);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
bool CSpecializedManager::RemoveLogger(CLoggerBase* _logger)
 | 
						|
 {
 | 
						|
  if(CheckPointer(_logger) == POINTER_INVALID)
 | 
						|
   {
 | 
						|
    LogError("No se puede remover logger nulo", FUNCION_ACTUAL);
 | 
						|
    return false;
 | 
						|
   }
 | 
						|
 | 
						|
  for(int i = 0; i < total; i++)
 | 
						|
   {
 | 
						|
    if(items[i] == _logger)
 | 
						|
     {
 | 
						|
      RemoveLogger(i);
 | 
						|
      return true;
 | 
						|
     }
 | 
						|
   }
 | 
						|
 | 
						|
  LogWarning("Logger no encontrado para remover", FUNCION_ACTUAL);
 | 
						|
  return false;
 | 
						|
 }
 | 
						|
#endif
 | 
						|
//+------------------------------------------------------------------+
 |