 
/*******************************************************************************/
/**  CpaListB.hpp                                                             **/
/*******************************************************************************/
/**                                                                           **/
/** Definition of the CPA_BaseObjectList class : list of CPA_BaseObject with  **/
/** different sort orders and fast search functions.                          **/
/**                                                                           **/
/*******************************************************************************/
/** Author : Yann Le Tensorer, Alexis Vaisse                                  **/
/*******************************************************************************/
 
 
#ifndef __CPABLIST_HPP__
#define __CPABLIST_HPP__
 
 
#ifdef ACTIVE_EDITOR
 
 
/****************************************/
#ifndef CPA_EXPORT
#if defined(CPA_WANTS_IMPORT)
#define CPA_EXPORT __declspec(dllimport)
#elif defined(CPA_WANTS_EXPORT)
#define CPA_EXPORT __declspec(dllexport)
#else
#define CPA_EXPORT
#endif
#endif
/****************************************/
 
 
#include "Lst.hpp"
 
class   CPA_BaseObject;
typedef CPA_BaseObject * tdp_BaseObjectPointer;
typedef long             Position;
 
 
typedef enum eListOrder_ 
{
    E_lo_Object ,
    E_lo_First  = E_lo_Object ,    /* Sort by adress of the CPA_BaseObject (to quickly find an object)*/
    E_lo_Type   ,                  /* Sort by type*/
    E_lo_Data   ,                  /* Sort by adress of the data*/
    E_lo_Owner  ,                  /* Sort by adress of the owner*/
    E_lo_Alpha  ,                  /* Sort by alphabetic order*/
	E_lo_Common ,                  /* Specific order*/
	E_lo_Edited ,                  /* Specific order*/
    E_lo_Last   = E_lo_Edited
}
tdeListOrder;
 
#define NO_CRITERIA ((CPA_BaseObject *) -1)
#define C_lNumberOfLists (E_lo_Last + 1)
#define E_lo_GoThrough  E_lo_Edited  /* When we go through the list with GetNext..., we use the E_lo_Edited order*/
 
 
 
/*---------------------------------*/
class CPA_EXPORT CPA_BaseObjectList
{
private:
    CString	m_csTypeName;                                               /* Type name of the list. Can be ""*/
    char *  m_szTypeName;                                               /* Same string, with a char **/
 
    long    m_lNumberOfObjects;                                         /* Number of objects in the list*/
    long    m_lMaxNumberOfObjects;                                      /* Maximum number of objects in the list (that is the size*/
                                                                        /* of m_lIndexArray). If one try to add one more object,*/
	long	m_lCurrentUniqueIndex;
	
	/* The array will have to be reallocated*/
    tdp_BaseObjectPointer * m_Array [C_lNumberOfLists];                 /* Contains the list of pointers to CPA_ObjectBase sorted*/
                                                                        /* for each order. The actual size of the array is m_lMaxNumberOfObjects*/
 
/* --- Low level functions ---*/
    void    ReallocArray              (long _lNewSize);                 /* Change the size of the arrray*/
    long    fn_lDichoSearchName       (CPA_BaseObject** _List , unsigned long _ListSize , char * _NameToFind , BOOL * _bFound , CPA_BaseObject * _BaseObjectToFind = NULL);
                                                                        /* Low level function to find an object with a given name in a given list*/
    long    fn_lDichoSearchType       (CPA_BaseObject** _List, unsigned long _ListSize, char* _TypeToFind,BOOL* _bFound , CPA_BaseObject * _BaseObjectToFind = NULL);
                                                                        /* Low level function to find an object with a given type in a given list*/
    long    fn_lDichoSearchData       (CPA_BaseObject** _List, unsigned long _ListSize, void* _DataToFind,BOOL* _bFound , CPA_BaseObject * _BaseObjectToFind = NULL);
                                                                        /* Low level function to find an object with a given data in a given list*/
    long    fn_lDichoSearchOwner      (CPA_BaseObject** _List, unsigned long _ListSize, CPA_BaseObject* _OwnerToFind,BOOL* _bFound , CPA_BaseObject * _BaseObjectToFind = NULL);
                                                                        /* Low level function to find an object with a given owner in a given list*/
    long    fn_lDichoSearchBaseObject (CPA_BaseObject** _List, unsigned long _ListSize, CPA_BaseObject* _BaseObjectToFind,BOOL* _bFound);
                                                                        /* Low level function to find the index of an object in a given list*/
	long	fn_lDichoSearchNamesTypesOwners(                            /* Low level function to find objects with a given name, an optional type and an optional owner*/
								CPA_List<CPA_BaseObject> *_p_oReturnList, 
								CPA_BaseObject** _p_oList, 
								unsigned long _ulListSize,
								BOOL* _p_bFound, 
								char* _Name,
								char* _type=NULL,
								CPA_BaseObject* _Owner=NO_CRITERIA);
	long	fn_lDichoSearchOwnersAndTypes(                              /* Low level function to find objects with a given owner and an optional type*/
								CPA_List<CPA_BaseObject> * _p_oReturnList, 
								CPA_BaseObject** _p_oList, 
								unsigned long _ulListSize, 
								BOOL* _p_bFound, 
								CPA_BaseObject* _Owner,
								char* _type=NULL);
	long	fn_lDichoSearchNameTypeOwner(                               /* Low level function to find an object with a given name, an optional type and an optional owner*/
								CPA_BaseObject** _p_oList, 
								unsigned long _ulListSize, 
								BOOL* _bFound,
								char* _NameToFind,
								char* _type=NULL,
								CPA_BaseObject* _Owner=NO_CRITERIA
								);
	long	fn_lDichoSearchDataTypeOwner(                               /* Low level function to find an object with a given data, an optional type and an optional owner*/
								CPA_BaseObject** _p_oList, 
								unsigned long _ulListSize, 
								BOOL* _bFound,
								void* _data,
								char* _type=NULL,
								CPA_BaseObject* _Owner=NO_CRITERIA
								);
 
/* --- Medium level functions ---*/
    long    FindObjectWithType   (CPA_List<CPA_BaseObject> * _p_oList ,
                                  const CString _csTypeName);           /* Return all the objects of the list with the given type*/
    long    FindIndex            (tdeListOrder _eListOrder , CPA_BaseObject * _p_oObject , BOOL * _bExist);
                                                                        /* Return the index of an object into a list with a given order*/
                                                                        /* If the object is into the list, set _bExist to TRUE and return the index*/
                                                                        /* If not, set _bExist to FALSE and return the index where to insert the object*/
    void    InsertObjectInList   (tdeListOrder _eListOrder , CPA_BaseObject * _p_oObject , long _lIndex);
                                                                        /* Insert the give object into the given list in the given Position*/
                                                                        /* Shift the index after this Position*/
    void    RemoveObjectFromList (tdeListOrder _eListOrder , long _lIndex);
                                                                        /* Remove the given index from the given list*/
                                                                        /* Shift the index after this Position*/
    void    MoveIndexInList      (tdeListOrder _eListOrder , long _lOldIndex , long _lNewIndex);
                                                                        /* Move an object from one Position to another inside a given list*/
public:
 
/* --- Construction and destruction ---*/
            CPA_BaseObjectList  (const CString _csTypeName = "");       /* Constructor*/
           ~CPA_BaseObjectList  ();                                     /* Destructor*/
 
	void    DeleteAllElements ();                                       /* Empty the list but do not delete the CPA_BaseObject*/
	void    DeleteAllObjects  ();                                       /* Empty the list and delete all CPA_BaseObject*/
 
/* --- Type ---*/
    CString fn_csGetTypeName ()         { return m_csTypeName; }        /* Return the type name of the list, "" for no type*/
    char *  fn_szGetTypeName ()         { return m_szTypeName; }        /* Same string with a char **/
                                        
    BOOL    fn_bIsOfType     (const CString _csTypeName) ;              /* Return TRUE if the list is of the given type*/
 
/* --- Add and remove objects ---*/
	BOOL    fn_bAddObject    (CPA_BaseObject * _p_oObject);             /* Insert an object into the list.*/
                                                                        /* If the list has a type and the object has not the same type -> ASSERT*/
                                                                        /* If the object is already in the list, return FALSE*/
                                                                        /* Else insert the object into the list and return TRUE*/
	BOOL    fn_bRemoveObject (CPA_BaseObject * _p_oObject);             /* Remove an object from the list*/
                                                                        /* If the object is not into the list, return FALSE*/
                                                                        /* Else remove the object from the list and return TRUE*/
/* --- Get functions ---*/
    long             GetCount ()        { return m_lNumberOfObjects; }  /* Return the number of objects in the list*/
    CPA_BaseObject * GetObjectWithIndex (long _lIndex , tdeListOrder _eListOrder = E_lo_GoThrough);
                                                                        /* Return the object with the given index into the given sort order*/
    long             GetIndexOfObject   (CPA_BaseObject * _p_oObject ,
                                         tdeListOrder _eListOrder);     /* Return the index (between 0 et GetCount () - 1) of a given object*/
                                                                        /* for a specific order (must be E_lo_Common or E_lo_Edited)*/
                                                                        /* If the object is not into the list, return -1*/
                                                                        /* Do not use this function too much, because it is slower than the others*/
/* --- Search functions ---*/
	BOOL    fn_bExist        (CPA_BaseObject * _p_oObject);             /* Return TRUE if the object is into the list*/
	BOOL    fn_bExist        (const CString _csObjectName ,             /* Return TRUE if there is an object with the given name,*/
				              const CString _csTypeName = "" ,          /* eventually with the given type and the given owner*/
				              CPA_BaseObject * _p_oOwner = NO_CRITERIA);/* into the list*/
 
    long    fn_lFindObjects  (CPA_List<CPA_BaseObject> * _p_oList ,     /* Find object from the list, put them into _p_oList*/
						      const CString    _csObjectName      ,     /* and return the number of found objects*/
						      const CString    _csTypeName   = "" ,
						      CPA_BaseObject * _p_oOwner     = NO_CRITERIA);
 
	CPA_BaseObject * fn_p_oFindObject                                   /* Find an object from the list with the given name,*/
                             (const CString    _csObjectName ,          /* eventually the given type and the given owner */
                              const CString    _csTypeName = "" ,       /* If the object is into the list, return it*/
                              CPA_BaseObject * _p_oOwner   = NO_CRITERIA); /* Else return NULL*/
                                                                        
	CPA_BaseObject * fn_p_oFindObjectWithdData                          /* Find an object from the list with the given data,*/
                             (void           * _p_vData ,               /* eventually the given type and the given owner*/
                              const CString    _csTypeName = "" ,       /* If the object is into the list, return it*/
                              CPA_BaseObject * _p_oOwner   = NO_CRITERIA); /* Else return NULL*/
 
/* --- Change order ---*/
    void    fn_vBeforeChangingObjectName (CPA_BaseObject * _p_oObject , /* Before changing the name of a CPA_BaseObject, one must*/
                                          char * _szNewName);           /* call this function to reorganize the alphabetic order sorted list*/
    void    fn_vBeforeChangingObjectData (CPA_BaseObject * _p_oObject , /* Before changing the data of a CPA_BaseObject, one must*/
                                          void * _pNewData);            /* call this function to reorganize the list*/
    void    fn_vBeforeChangingObjectOwner (CPA_BaseObject * _p_oObject ,/* Before changing the owner of a CPA_BaseObject, one must*/
                                          CPA_BaseObject * _pNewOwner); /* call this function to reorganize the list*/
    void    fn_vExchangeObjectOrder   (long          _lIndex1 ,         /* Exchange two objects in a specific order*/
                                       long          _lIndex2 ,         /* (must be E_lo_Common or E_lo_Edited)*/
                                       tdeListOrder  _eListOrder);
    void    fn_vChangeObjectOrder     (long          _lOldIndex ,       /* Change the position in a specific order sorted list of*/
                                       long          _lNewIndex ,       /* an object (which must already be in the list)*/
                                       tdeListOrder  _eListOrder);      /* Shift objects if necessary*/
                                                                        /* (must be E_lo_Common or E_lo_Edited)*/
    BOOL    fn_bExchangeObjectOrder   (CPA_BaseObject * _p_oObject1 ,   /* Exchange two objects in a specific order*/
                                       CPA_BaseObject * _p_oObject2 ,   /* (must be E_lo_Common or E_lo_Edited)*/
                                       tdeListOrder     _eListOrder);   /* If you know the index of the two objects in the list*/
                                                                        /* (without calling the GetIndexOfObject function),*/
                                                                        /* call the fn_vExchangeObjectOrder function which is faster*/
                                                                        /* Return FALSE if one object is not in the list, else return TRUE*/
    BOOL    fn_bChangeObjectOrder     (CPA_BaseObject* _p_oObject ,     /* Change the position in a specific order sorted list of*/
                                       long            _lNewIndex ,     /* an object. Shift objects if necessary (must be E_lo_Common*/
                                       tdeListOrder    _eListOrder);    /* or E_lo_Edited). If you know the old index if the object in*/
                                                                        /* the list (without calling the GetIndexOfObject function),*/
                                                                        /* call the fn_vChangingObjectOrder function which is faster*/
                                                                        /* Return FALSE if the object is not in the list, else return TRUE*/
    void    fn_vReSortListWithAlphaOrder ();                            /* If some objects may have been renamed without calling the*/
                                                                        /* fn_vBeforeChangingObjectName function, call this function to sort the list*/
    void    fn_vReSortListWithDataOrder  ();                            /* If data of some objects may have been changed without calling the*/
                                                                        /* fn_vBeforeChangingObjectData function, call this function to sort the list*/
    void    fn_vReSortListWithOwnerOrder ();                            /* If owner of some objects may have been changed without calling the*/
                                                                        /* fn_vBeforeChangingObjectOwner function, call this function to sort the list*/
    void    fn_vReSortList               ();                            /* Call the three previous functions*/
 
/* --- To go through the list*/
    Position         GetHeadPosition ()  { return m_lNumberOfObjects ? 1 : 0;                                      }
    CPA_BaseObject * GetHead         ()  { return m_Array [E_lo_GoThrough] [0];                                    }
    CPA_BaseObject * GetHeadElement  (Position & _Position);
 
    Position         GetTailPosition ()  { return m_lNumberOfObjects;                                              }
    CPA_BaseObject * GetTail         ()  { return m_Array [E_lo_GoThrough] [m_lNumberOfObjects - 1];               }
    CPA_BaseObject * GetTailElement  (Position & _Position);
 
    CPA_BaseObject * GetAt           (Position _Position)       { return m_Array [E_lo_GoThrough] [_Position - 1]; }
    CPA_BaseObject * GetAtElement    (Position _Position)       { return m_Array [E_lo_GoThrough] [_Position - 1]; }
 
    CPA_BaseObject * GetNext         (Position & _Position);
    CPA_BaseObject * GetNextElement  (Position & _Position);        
    CPA_BaseObject * GetPrev         (Position & _Position);
    CPA_BaseObject * GetPrevElement  (Position & _Position);                  
 
    CPA_BaseObject * operator[]      (long _lIndex)             { return m_Array [E_lo_GoThrough] [_lIndex];       }
 
 
/* --- To get a new name*/
	CString GetNewName (const CString csDefaultBaseName = "");
};
 
 
#endif /* ACTIVE_EDITOR*/
 
#endif /* __CPABLIST_HPP__*/
