//***************************************************************************** //* CpaListB.cpp * //***************************************************************************** //* * //* Functions of the CPA_BaseObjectList class : list of CPA_BaseObject with * //* different sort orders and fast search functions. * //* * //***************************************************************************** //* Author : Yann Le Tensorer, Alexis Vaisse * //***************************************************************************** #include "stdafx.h" #ifdef ACTIVE_EDITOR #include "itf/CPAListB.hpp" #include "itf/CPABaseO.hpp" #define C_lSizeIncrease 16 // When the array must be reallocated, we add space for 16 more objects #define stricmp __asmstricmp //***************************************************************************** //********** Construction and destruction ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - constructor //----------------------------------------------------------------------------- CPA_BaseObjectList::CPA_BaseObjectList (const CString _csTypeName /* = "" */) { m_csTypeName = _csTypeName; m_szTypeName = (char *) (LPCTSTR) m_csTypeName; m_lNumberOfObjects = 0; m_lMaxNumberOfObjects = 0; m_lCurrentUniqueIndex = 0; for (int i = E_lo_First ; i <= E_lo_Last ; i ++) m_Array [i] = NULL; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - destructor //----------------------------------------------------------------------------- CPA_BaseObjectList::~CPA_BaseObjectList () { DeleteAllElements (); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - ReallocArray // Change the size of the arrray //----------------------------------------------------------------------------- void CPA_BaseObjectList::ReallocArray (long _lNewSize) { for (int i = E_lo_First ; i <= E_lo_Last ; i ++) { if (_lNewSize == 0) { if (m_Array [i] != NULL) { free (m_Array [i]); m_Array [i] = NULL; } } else { if (m_Array [i] == NULL) m_Array [i] = (tdp_BaseObjectPointer *) malloc ( sizeof (tdp_BaseObjectPointer) * _lNewSize); else m_Array [i] = (tdp_BaseObjectPointer *) realloc (m_Array [i] , sizeof (tdp_BaseObjectPointer) * _lNewSize); } } m_lMaxNumberOfObjects = _lNewSize; if (m_lNumberOfObjects > m_lMaxNumberOfObjects) m_lNumberOfObjects = m_lMaxNumberOfObjects; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - DeleteAllElements // Empty the list but do not delete the CPA_BaseObject //----------------------------------------------------------------------------- void CPA_BaseObjectList::DeleteAllElements () { ReallocArray (0); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - DeleteAllObjects // Empty the list and delete all CPA_BaseObject //----------------------------------------------------------------------------- void CPA_BaseObjectList::DeleteAllObjects () { // Delete all objects using object order (any order could workd) for (long i = 0 ; i < m_lNumberOfObjects ; i ++) delete m_Array [E_lo_Object] [i]; DeleteAllElements (); } //***************************************************************************** //********** Low level functions ********** //***************************************************************************** //============================================================================= // asm defined stricmp to fasten a little bit the very very slow function // written by microsoft... //============================================================================= int __asmstricmp(char * a, char * b) { char retour; _asm { mov eax,a mov ebx,b boucle: mov ecx,dword ptr[eax] mov edx,dword ptr[ebx] ;============= first word cmp cl,97 jge sub32cl cmp dl,97 jge sub32dl jmp suite sub32cl: sub cl,32 cmp dl,97 jl suite sub32dl: sub dl,32 suite: sub cl,dl cmp dl,0 je fin cmp cl,0 jne fin cmp ch,97 jge sub32ch cmp dh,97 jge sub32dh jmp suite2 sub32ch: sub ch,32 cmp dh,97 jl suite2 sub32dh: sub dh,32 suite2: sub ch,dh cmp dh,0 je fin2 cmp ch,0 jne fin2 ;================ end first word shr ecx,16 shr edx,16 ;============= second word cmp cl,97 jge sub32clx cmp dl,97 jge sub32dlx jmp suitex sub32clx: sub cl,32 cmp dl,97 jl suitex sub32dlx: sub dl,32 suitex: sub cl,dl cmp dl,0 je fin cmp cl,0 jne fin cmp ch,97 jge sub32chx cmp dh,97 jge sub32dhx jmp suite2x sub32chx: sub ch,32 cmp dh,97 jl suite2x sub32dhx: sub dh,32 suite2x: sub ch,dh cmp dh,0 je fin2 cmp ch,0 jne fin2 ;================ end second word add eax,4 add ebx,4 jmp boucle fin: mov retour,cl jmp VraieFin fin2: mov retour,ch VraieFin: } return (int)retour; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchName // Low level function to find an object with a given name in a given list //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchName(CPA_BaseObject** _p_oList, unsigned long _ulListSize, char* _NameToFind,BOOL* _bFound,CPA_BaseObject* _p_oAdress) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; while (Bas!=Haut+1) { signe=stricmp((_p_oList[Milieu]->fn_p_szGetName()),_NameToFind); /* This is used to continue search on adress if wanted */ if (signe==0 && _p_oAdress!=NULL) signe=(long)(_p_oList[Milieu]-_p_oAdress); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { *_bFound=TRUE; return Milieu; } }; *_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchType // Low level function to find an object with a given type in a given list //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchType(CPA_BaseObject** _p_oList, unsigned long _ulListSize, char* _TypeToFind,BOOL* _bFound,CPA_BaseObject* _p_oAdress) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; while (Bas!=Haut+1) { signe=stricmp((_p_oList[Milieu]->fn_p_szGetType()),_TypeToFind); /* This is used to continue search on adress if wanted */ if (signe==0 && _p_oAdress!=NULL) signe=(long)(_p_oList[Milieu]-_p_oAdress); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { *_bFound=TRUE; return Milieu; } }; *_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchData // Low level function to find an object with a given data in a given list //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchData(CPA_BaseObject** _p_oList, unsigned long _ulListSize, void* _DataToFind,BOOL* _bFound,CPA_BaseObject* _p_oAdress) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; while (Bas!=Haut+1) { signe=(long)_p_oList[Milieu]->GetData()-(long)_DataToFind; /* This is used to continue search on adress if wanted */ if (signe==0 && _p_oAdress!=NULL) signe=(long)(_p_oList[Milieu]-_p_oAdress); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { *_bFound=TRUE; return Milieu; } }; *_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchOwner // Low level function to find an object with a given owner in a given list //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchOwner(CPA_BaseObject** _p_oList, unsigned long _ulListSize, CPA_BaseObject* _OwnerToFind,BOOL* _bFound,CPA_BaseObject* _p_oAdress) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; while (Bas!=Haut+1) { signe=(long)(_p_oList[Milieu]->GetOwner()-_OwnerToFind); /* This is used to continue search on adress if wanted */ if (signe==0 && _p_oAdress!=NULL) signe=(long)(_p_oList[Milieu]-_p_oAdress); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { *_bFound=TRUE; return Milieu; } }; *_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchBaseObject // Low level function to find the index of an object in a given list //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchBaseObject(CPA_BaseObject** _List, unsigned long _ListSize, CPA_BaseObject* _BaseObjectToFind,BOOL* _bFound) { unsigned long Haut=-1; unsigned long Bas=_ListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; while (Bas!=Haut+1) { signe=(long)(_List[Milieu]-_BaseObjectToFind); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { *_bFound=TRUE; return Milieu; } } *_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchNamesTypesOwners // Low level function to find objects which have a given name, an optional type and an optional owner //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchNamesTypesOwners( CPA_List *_p_oReturnList, CPA_BaseObject** _p_oList, unsigned long _ulListSize, BOOL* _p_bFound, char* _Name, char* _type, CPA_BaseObject* _Owner) { int Count=0; BOOL CountOnly; int index,i; /* Avoid crashes, please do not replace with ASSERT... */ if (_p_bFound==NULL || !stricmp(_Name,"") || _p_oList== NULL || ((long)_ulListSize)<=0) { if (_p_bFound!=NULL) *_p_bFound=FALSE; return 0; } if (_p_oReturnList==NULL) CountOnly=TRUE; else CountOnly=FALSE; /* we search the name in the sorted list */ index=fn_lDichoSearchName(_p_oList,_ulListSize,_Name,_p_bFound); if (*_p_bFound) { i=index; /* we search the same names before */ while (i>=0 && !stricmp(_p_oList[i]->fn_p_szGetName(),_Name)) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Owner!=NO_CRITERIA*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { if (CountOnly==FALSE) _p_oReturnList->AddTail(_p_oList[i]); Count++; } } i--; } i=index+1; /* we search the same names after */ while ((i<(long)_ulListSize) && !stricmp(_p_oList[i]->fn_p_szGetName(),_Name) ) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Type!=NULL*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { if (CountOnly==FALSE) _p_oReturnList->AddTail(_p_oList[i]); Count++; } } i++; } } if (Count==0) *_p_bFound=FALSE; return Count; }; //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchNameTypeOwner // Low level function to find an object which has a given name, an optional type and an optional owner //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchNameTypeOwner( CPA_BaseObject** _p_oList, unsigned long _ulListSize, BOOL* _p_bFound, char* _NameToFind, char* _type, CPA_BaseObject* _Owner ) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; long i; /* Avoid crashes, please do not replace with ASSERT... */ if (_p_bFound==NULL || _p_oList== NULL || ((long)_ulListSize)<=0) { if (_p_bFound!=NULL) *_p_bFound=FALSE; return 0; } while (Bas!=Haut+1) { signe=stricmp((_p_oList[Milieu]->fn_p_szGetName()),_NameToFind); if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { /* the name was found !*/ /* search for type and owner if necessary*/ i=Milieu; while (i>=0 && !stricmp(_p_oList[i]->fn_p_szGetName(),_NameToFind)) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Owner!=NO_CRITERIA*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { *_p_bFound=TRUE; return i; } } i--; } i=Milieu+1; /* we search the same names after */ while ((i<(long)_ulListSize) && !stricmp(_p_oList[i]->fn_p_szGetName(),_NameToFind)) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Type!=NULL*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { *_p_bFound=TRUE; return i; } } i++; } *_p_bFound=FALSE; return Bas; } }; *_p_bFound=FALSE; return Bas; }; //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchDataTypeOwner // Low level function to find an object which has a given data, an optional type and an optional owner //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchDataTypeOwner( CPA_BaseObject** _p_oList, unsigned long _ulListSize, BOOL* _p_bFound, void* _data, char* _type, CPA_BaseObject* _Owner ) { unsigned long Haut=-1; unsigned long Bas=_ulListSize; unsigned long Milieu=(Haut+Bas)>>1; long signe; int i; /* Avoid crashes, please do not replace with ASSERT... */ if (_p_bFound==NULL || _p_oList== NULL || ((long)_ulListSize)<=0) { if (_p_bFound!=NULL) *_p_bFound=FALSE; return 0; } while (Bas!=Haut+1) { signe=(long)_p_oList[Milieu]->GetData()-(long)_data; if (signe<0) { Haut=Milieu; Milieu=(Bas+Milieu)>>1; } else if (signe>0) { Bas=Milieu; Milieu=(Haut+Milieu)>>1; } else { /* the data was found !*/ /* search for type and owner if necessary*/ i=Milieu; while (i>=0 && _p_oList[i]->GetData()==_data) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Owner!=NO_CRITERIA*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { *_p_bFound=TRUE; return i; } } i--; } i=Milieu+1; /* we search the same datas after */ while ((i<(long)_ulListSize) && _p_oList[i]->GetData()==_data ) { /* also test Type if _Type!=NULL*/ if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { /* also test Owner if _Type!=NULL*/ if (_Owner==NO_CRITERIA || (_p_oList[i]->GetOwner()==_Owner)) { *_p_bFound=TRUE; return i; } } i++; } *_p_bFound=FALSE; return Bas; } }; *_p_bFound=FALSE; return Bas; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lDichoSearchOwnersAndTypes // Low level function to find objects which have a given owner and a given type //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lDichoSearchOwnersAndTypes(CPA_List * _p_oReturnList, CPA_BaseObject** _p_oList, unsigned long _ulListSize, BOOL* _p_bFound, CPA_BaseObject* _Owner,char* _type) { int Count=0; BOOL CountOnly; int index,i; /* Avoid crashes, please do not replace with ASSERT... */ if (_p_bFound==NULL || _Owner==NULL || _p_oList== NULL || ((long)_ulListSize)<=0) { if (_p_bFound!=NULL) *_p_bFound=FALSE; return 0; } if (_p_oReturnList==NULL) CountOnly=TRUE; else CountOnly=FALSE; /* we search the owner in the sorted list */ index=fn_lDichoSearchOwner(_p_oList,_ulListSize,_Owner,_p_bFound); if (*_p_bFound) { i=index; /* we search the same owners before */ while (i>=0 && _p_oList[i]->GetOwner()==_Owner ) { if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { if (CountOnly==FALSE) _p_oReturnList->AddTail(_p_oList[i]); Count++; } i--; } i=index+1; /* we search the same owners after */ while (i<(long)_ulListSize && _p_oList[i]->GetOwner()==_Owner) { if (!stricmp(_type,"") || !stricmp(_p_oList[i]->fn_p_szGetType(),_type)) { if (CountOnly==FALSE) _p_oReturnList->AddTail(_p_oList[i]); Count++; } i++; } } if (Count==0) *_p_bFound=FALSE; return Count; } //***************************************************************************** //********** Medium level functions ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - FindObjectWithType // Return all the objects of the list with the given type //----------------------------------------------------------------------------- long CPA_BaseObjectList::FindObjectWithType (CPA_List * _p_oList , const CString _csTypeName) { char * szTypeNameToFind = (char *) (LPCTSTR) _csTypeName; if (! m_csTypeName . IsEmpty ()) // All objects of the list have the same type { if (m_csTypeName . CompareNoCase (_csTypeName) != 0) return 0; // Not the same type --> no object found // We just make a copy of the list for (long i = 0 ; i < m_lNumberOfObjects ; i ++) _p_oList -> AddTail (m_Array [E_lo_Edited] [i]); return m_lNumberOfObjects; } else // Not all objects have the same type : we must check the type { long lNumberOfObjectFound = 0; tdp_BaseObjectPointer * pBaseObjectPointer = m_Array [E_lo_Edited]; for (long i = m_lNumberOfObjects ; i > 0 ; i --) { if (stricmp ((* pBaseObjectPointer) -> fn_p_szGetType () , szTypeNameToFind) == 0) { _p_oList -> AddTail (* pBaseObjectPointer); lNumberOfObjectFound ++; } pBaseObjectPointer ++; } return lNumberOfObjectFound; } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - FindIndex // 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 //----------------------------------------------------------------------------- long CPA_BaseObjectList::FindIndex (tdeListOrder _eListOrder , CPA_BaseObject * _p_oObject , BOOL * _bExist) { switch (_eListOrder) { case E_lo_Object : return fn_lDichoSearchBaseObject (m_Array [E_lo_Object] , m_lNumberOfObjects , _p_oObject , _bExist); case E_lo_Type : return fn_lDichoSearchType (m_Array [E_lo_Type ] , m_lNumberOfObjects , _p_oObject -> fn_p_szGetType () , _bExist , _p_oObject); case E_lo_Data : return fn_lDichoSearchData (m_Array [E_lo_Data ] , m_lNumberOfObjects , _p_oObject -> GetData () , _bExist , _p_oObject); case E_lo_Owner : return fn_lDichoSearchOwner (m_Array [E_lo_Owner ] , m_lNumberOfObjects , _p_oObject -> GetOwner () , _bExist , _p_oObject); case E_lo_Alpha : return fn_lDichoSearchName (m_Array [E_lo_Alpha ] , m_lNumberOfObjects , _p_oObject -> fn_p_szGetName () , _bExist , _p_oObject); default : ASSERT (0); * _bExist = FALSE; return -1; } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - InsertObjectInList // Insert the give object into the given list in the given position // Shift the index after this position // m_lNumberOfObjects has already been increased //----------------------------------------------------------------------------- void CPA_BaseObjectList::InsertObjectInList (tdeListOrder _eListOrder , CPA_BaseObject * _p_oObject , long _lIndex) { // Shift the index after _lIndex memmove (& m_Array [_eListOrder] [_lIndex + 1] , & m_Array [_eListOrder] [_lIndex] , (m_lNumberOfObjects - _lIndex - 1) * sizeof (tdp_BaseObjectPointer)); m_Array [_eListOrder] [_lIndex] = _p_oObject; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - RemoveObjectFromList // Remove the given index from the given list // Shift the index after this position // m_lNumberOfObject has already been decreased //----------------------------------------------------------------------------- void CPA_BaseObjectList::RemoveObjectFromList (tdeListOrder _eListOrder , long _lIndex) { // Shift the index after _lIndex memmove (& m_Array [_eListOrder] [_lIndex] , & m_Array [_eListOrder] [_lIndex + 1] , (m_lNumberOfObjects - _lIndex) * sizeof (tdp_BaseObjectPointer)); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - MoveIndexInList // Move an object from one position to another inside a given list //----------------------------------------------------------------------------- void CPA_BaseObjectList::MoveIndexInList (tdeListOrder _eListOrder , long _lOldIndex , long _lNewIndex) { tdp_BaseObjectPointer pBaseObject = m_Array [_eListOrder] [_lOldIndex]; if (_lOldIndex < _lNewIndex) { memmove (& m_Array [_eListOrder] [_lOldIndex] , & m_Array [_eListOrder] [_lOldIndex + 1] , (_lNewIndex - _lOldIndex - 1) * sizeof (tdp_BaseObjectPointer)); m_Array [_eListOrder] [_lNewIndex - 1] = pBaseObject; } else { memmove (& m_Array [_eListOrder] [_lNewIndex + 1] , & m_Array [_eListOrder] [_lNewIndex] , (_lOldIndex - _lNewIndex) * sizeof (tdp_BaseObjectPointer)); m_Array [_eListOrder] [_lNewIndex] = pBaseObject; } } //***************************************************************************** //********** Type management ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bIsOfType // Return TRUE if the list is of the given type //----------------------------------------------------------------------------- BOOL CPA_BaseObjectList::fn_bIsOfType (const CString _csTypeName) { return m_csTypeName . CompareNoCase (_csTypeName) == 0; } //***************************************************************************** //********** Add and remove objects ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bAddObject // 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 CPA_BaseObjectList::fn_bAddObject (CPA_BaseObject * _p_oObject) { ASSERT (m_csTypeName . IsEmpty () || _p_oObject -> fn_bIsOfType (m_csTypeName)); long lIndex [C_lNumberOfLists]; for (int eListType = E_lo_First ; eListType <= E_lo_Last ; eListType ++) { BOOL bExist = FALSE; // For the list with non specific order, we find the index where to insert the object if (eListType == E_lo_Common) lIndex [eListType] = 0; // Beginning of the list else if (eListType == E_lo_Edited) lIndex [eListType] = m_lNumberOfObjects; // End of the list else lIndex [eListType] = FindIndex ((tdeListOrder) eListType , _p_oObject , & bExist); // If the object is already in the list, return FALSE if (bExist) return FALSE; } // Increase the size of the array and check if the array is big enough m_lNumberOfObjects ++; if (m_lNumberOfObjects > m_lMaxNumberOfObjects) ReallocArray ((m_lNumberOfObjects + C_lSizeIncrease - 1) / C_lSizeIncrease * C_lSizeIncrease); for (eListType = E_lo_First ; eListType <= E_lo_Last ; eListType ++) { // Insert the object into the list InsertObjectInList ((tdeListOrder) eListType , _p_oObject , lIndex [eListType]); } return TRUE; // The object has been inserted succesfully } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bRemoveObject // 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 //----------------------------------------------------------------------------- BOOL CPA_BaseObjectList::fn_bRemoveObject (CPA_BaseObject * _p_oObject) { long lIndex [C_lNumberOfLists]; for (int eListType = E_lo_First ; eListType <= E_lo_Last ; eListType ++) { BOOL bExist; if (eListType == E_lo_Data || eListType == E_lo_Common || eListType == E_lo_Edited ) { // For specific order (E_lo_Common and E_lo_Edited), dicho search does not exist // For data order, we cannot use dicho search because this function can be called by destructor of CPA_BaseObject, // and in this case, the GetData pure virtual function is no longer available lIndex [eListType] = GetIndexOfObject (_p_oObject , (tdeListOrder) eListType); bExist = lIndex [eListType] != -1; } else lIndex [eListType] = FindIndex ((tdeListOrder) eListType , _p_oObject , & bExist); // If the object is not in the list, return FALSE if (! bExist) return FALSE; } // Decrease the size of the array m_lNumberOfObjects --; for (eListType = E_lo_First ; eListType <= E_lo_Last ; eListType ++) { // Remove the object from the list RemoveObjectFromList ((tdeListOrder) eListType , lIndex [eListType]); } // Check if one can decrease the maximum size of the array if (m_lNumberOfObjects <= m_lMaxNumberOfObjects - C_lSizeIncrease) ReallocArray ((m_lNumberOfObjects + C_lSizeIncrease - 1) / C_lSizeIncrease * C_lSizeIncrease); return TRUE; } //***************************************************************************** //********** Get functions ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetObjectWithIndex // Return the object with the given index into the given sort order //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetObjectWithIndex (long _lIndex , tdeListOrder _eListOrder) { return m_Array [_eListOrder] [_lIndex]; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetIndexOfObject // 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) or for E_lo_Data // If the object is not into the list, return -1 // Do not use this function too much, because it is slower than the others //----------------------------------------------------------------------------- long CPA_BaseObjectList::GetIndexOfObject (CPA_BaseObject * _p_oObject , tdeListOrder _eListOrder) { ASSERT (_eListOrder == E_lo_Common || _eListOrder == E_lo_Edited || _eListOrder == E_lo_Data); tdp_BaseObjectPointer * pBaseObjectPointer = m_Array [_eListOrder]; long i = m_lNumberOfObjects; while (--i >= 0 && * (pBaseObjectPointer++) != _p_oObject) ; if (i != -1) return m_lNumberOfObjects - i - 1; else return -1; } //***************************************************************************** //********** Search functions ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bExist // Return TRUE if the object is into the list //----------------------------------------------------------------------------- BOOL CPA_BaseObjectList::fn_bExist (CPA_BaseObject * _p_oObject) { BOOL bExist; FindIndex (E_lo_Object , _p_oObject , & bExist); return bExist; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bExist // Return TRUE if there is an object with the given name, // eventually with the given type and the given owner into the list //----------------------------------------------------------------------------- BOOL CPA_BaseObjectList::fn_bExist (const CString _csObjectName , const CString _csTypeName /* = "" */ , CPA_BaseObject * _p_oOwner /* = NO_CRITERIA */) { return fn_p_oFindObject (_csObjectName , _csTypeName , _p_oOwner) != NULL; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_lFindObjects // Find object from the list, put them into _p_oList // and return the number of found objects //----------------------------------------------------------------------------- long CPA_BaseObjectList::fn_lFindObjects (CPA_List * _p_oList , const CString _csObjectName , const CString _csTypeName /* = "" */ , CPA_BaseObject * _p_oOwner /* = NO_CRITERIA */) { if (_csObjectName . IsEmpty ()) // No name to search { if (_p_oOwner == NO_CRITERIA) return FindObjectWithType (_p_oList , _csTypeName); // Search with the type only BOOL bExist; return fn_lDichoSearchOwnersAndTypes (_p_oList , m_Array [E_lo_Owner] , m_lNumberOfObjects , & bExist , _p_oOwner , (char *) (LPCTSTR) _csTypeName); } else { BOOL bExist; return fn_lDichoSearchNamesTypesOwners (_p_oList , m_Array [E_lo_Alpha] , m_lNumberOfObjects , & bExist , (char *) (LPCTSTR) _csObjectName , (char *) (LPCTSTR) _csTypeName , _p_oOwner); } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_p_oFindObject // Find an object from the list with the given name, // eventually the given type and the given owner // If the object is into the list, return it else return NULL //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::fn_p_oFindObject (const CString _csObjectName , const CString _csTypeName /* = "" */ , CPA_BaseObject * _p_oOwner /* = NO_CRITERIA */) { ASSERT (_csObjectName && ! _csObjectName . IsEmpty ()); BOOL bExist; long lIndex = fn_lDichoSearchNameTypeOwner (m_Array [E_lo_Alpha] , m_lNumberOfObjects , & bExist , (char *) (LPCTSTR) _csObjectName , (char *) (LPCTSTR) _csTypeName , _p_oOwner); if (bExist) return m_Array [E_lo_Alpha] [lIndex]; else return NULL; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_p_oFindObject // Find an object from the list with the given data, // eventually the given type and the given owner // If the object is into the list, return it else return NULL //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::fn_p_oFindObjectWithdData (void * _p_vData , const CString _csTypeName /* = "" */ , CPA_BaseObject * _p_oOwner /* = NO_CRITERIA */) { BOOL bExist; long lIndex = fn_lDichoSearchDataTypeOwner (m_Array [E_lo_Data] , m_lNumberOfObjects , & bExist , _p_vData , (char *) (LPCTSTR) _csTypeName , _p_oOwner); if (bExist) return m_Array [E_lo_Data] [lIndex]; else return NULL; } //***************************************************************************** //********** Change order ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vBeforeChangingObjectName // Before changing the name of a CPA_BaseObject, one must // call this function to reorganize the alphabetic order sorted list //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vBeforeChangingObjectName (CPA_BaseObject * _p_oObject , char * _szNewName) { // If old name and new name are equal, we do nothing if (stricmp (_p_oObject -> fn_p_szGetName () , _szNewName) == 0) return; BOOL bExist; long lOldIndex = fn_lDichoSearchName (m_Array [E_lo_Alpha] , m_lNumberOfObjects , _p_oObject -> fn_p_szGetName () , & bExist , _p_oObject); ASSERT (bExist); // The object must exist long lNewIndex = fn_lDichoSearchName (m_Array [E_lo_Alpha] , m_lNumberOfObjects , _szNewName , & bExist , _p_oObject); MoveIndexInList (E_lo_Alpha , lOldIndex , lNewIndex); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vBeforeChangingObjectData // Before changing the data of a CPA_BaseObject, one must // call this function to reorganize the list //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vBeforeChangingObjectData (CPA_BaseObject * _p_oObject , void * _pNewData) { // If old data and new data are equal, we do nothing if (_p_oObject -> GetData () == _pNewData) return; BOOL bExist; long lOldIndex = fn_lDichoSearchData (m_Array [E_lo_Data] , m_lNumberOfObjects , _p_oObject -> GetData () , & bExist , _p_oObject); ASSERT (bExist); // The object must exist long lNewIndex = fn_lDichoSearchData (m_Array [E_lo_Data] , m_lNumberOfObjects , _pNewData , & bExist , _p_oObject); MoveIndexInList (E_lo_Data , lOldIndex , lNewIndex); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vBeforeChangingObjectOwner // Before changing the owner of a CPA_BaseObject, one must // call this function to reorganize the list //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vBeforeChangingObjectOwner (CPA_BaseObject * _p_oObject , CPA_BaseObject * _pNewOwner) { // If old owner and new owner are equal, we do nothing if (_p_oObject -> GetOwner () == _pNewOwner) return; BOOL bExist; long lOldIndex = fn_lDichoSearchOwner (m_Array [E_lo_Owner] , m_lNumberOfObjects , _p_oObject -> GetOwner () , & bExist , _p_oObject); ASSERT (bExist); // The object must exist long lNewIndex = fn_lDichoSearchOwner (m_Array [E_lo_Owner] , m_lNumberOfObjects , _pNewOwner , & bExist , _p_oObject); MoveIndexInList (E_lo_Owner , lOldIndex , lNewIndex); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vExchangeObjectOrder // Exchange two objects in a specific order (must be E_lo_Common or E_lo_Edited) //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vExchangeObjectOrder (long _lIndex1 , long _lIndex2 , tdeListOrder _eListOrder) { ASSERT (_eListOrder == E_lo_Common || _eListOrder == E_lo_Edited); // Exchange the two pointers tdp_BaseObjectPointer pPointer = m_Array [_eListOrder] [_lIndex1]; m_Array [_eListOrder] [_lIndex1] = m_Array [_eListOrder] [_lIndex2]; m_Array [_eListOrder] [_lIndex2] = pPointer; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vChangeObjectOrder // Change the position in a specific order sorted list of // an object (which must already be in the list) // Shift objects if necessary (must be E_lo_Common or E_lo_Edited) //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vChangeObjectOrder (long _lOldIndex , long _lNewIndex , tdeListOrder _eListOrder) { ASSERT (_eListOrder == E_lo_Common || _eListOrder == E_lo_Edited); MoveIndexInList (_eListOrder , _lOldIndex , _lNewIndex); } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bExchangeObjectOrder // Exchange two objects in a specific order (must be E_lo_Common or E_lo_Edited) // 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 CPA_BaseObjectList::fn_bExchangeObjectOrder (CPA_BaseObject * _p_oObject1 , CPA_BaseObject * _p_oObject2 , tdeListOrder _eListOrder) { long lIndex1 = GetIndexOfObject (_p_oObject1 , _eListOrder); long lIndex2 = GetIndexOfObject (_p_oObject2 , _eListOrder); if (lIndex1 == -1 || lIndex2 == -1) return FALSE; fn_vExchangeObjectOrder (lIndex1 , lIndex2 , _eListOrder); return TRUE; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_bChangeObjectOrder // Change the position in a specific order sorted list of an object. // Shift objects if necessary (must be E_lo_Common or E_lo_Edited). // If you know the old index if the object in the list (without calling the GetIndexOfObject function), // call the fn_vChangeObjectOrder function which is faster // Return FALSE if the object is not in the list, else return TRUE //----------------------------------------------------------------------------- BOOL CPA_BaseObjectList::fn_bChangeObjectOrder (CPA_BaseObject* _p_oObject , long _lNewIndex , tdeListOrder _eListOrder) { long lOldIndex = GetIndexOfObject (_p_oObject , _eListOrder); if (lOldIndex == -1) return FALSE; fn_vChangeObjectOrder (lOldIndex , _lNewIndex , _eListOrder); return TRUE; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vReSortListWithAlphaOrder // If some objects may have been renamed without calling the // fn_vBeforeChangingObjectName function, call this function to sort the list //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vReSortListWithAlphaOrder () { // We check if the list is sorted or not BOOL bListSorted = TRUE; tdp_BaseObjectPointer * pBaseObjectPointer = m_Array [E_lo_Alpha]; for (long i = 0 ; i < m_lNumberOfObjects - 1 ; i ++) { if (stricmp ((* pBaseObjectPointer) -> fn_p_szGetName () , (* (pBaseObjectPointer+1)) -> fn_p_szGetName ()) > 0) { bListSorted = FALSE; break; } pBaseObjectPointer ++; } // If the list is already sorted, we do nothing if (bListSorted) return; // Else we resort the list for (i = 1 ; i < m_lNumberOfObjects ; i ++) { // We take the object number i CPA_BaseObject * pBaseObject = m_Array [E_lo_Alpha] [i]; BOOL bExist; // We find the correct index long lNewIndex = fn_lDichoSearchName (m_Array [E_lo_Alpha] , i , pBaseObject -> fn_p_szGetName () , & bExist , pBaseObject); if (lNewIndex != i) { memmove (& m_Array [E_lo_Alpha] [lNewIndex + 1] , & m_Array [E_lo_Alpha] [lNewIndex] , (i - lNewIndex) * sizeof (tdp_BaseObjectPointer)); m_Array [E_lo_Alpha] [lNewIndex] = pBaseObject; } } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - 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 CPA_BaseObjectList::fn_vReSortListWithDataOrder () { // We check if the list is sorted or not BOOL bListSorted = TRUE; tdp_BaseObjectPointer * pBaseObjectPointer = m_Array [E_lo_Data]; for (long i = 0 ; i < m_lNumberOfObjects - 1 ; i ++) { if ((* pBaseObjectPointer) -> GetData () > (* (pBaseObjectPointer+1)) -> GetData ()) { bListSorted = FALSE; break; } pBaseObjectPointer ++; } // If the list is already sorted, we do nothing if (bListSorted) return; // Else we resort the list for (i = 1 ; i < m_lNumberOfObjects ; i ++) { // We take the object number i CPA_BaseObject * pBaseObject = m_Array [E_lo_Data] [i]; BOOL bExist; // We find the correct index long lNewIndex = fn_lDichoSearchData (m_Array [E_lo_Data] , i , pBaseObject -> GetData () , & bExist , pBaseObject); if (lNewIndex != i) { memmove (& m_Array [E_lo_Data] [lNewIndex + 1] , & m_Array [E_lo_Data] [lNewIndex] , (i - lNewIndex) * sizeof (tdp_BaseObjectPointer)); m_Array [E_lo_Data] [lNewIndex] = pBaseObject; } } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - 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 CPA_BaseObjectList::fn_vReSortListWithOwnerOrder () { // We check if the list is sorted or not BOOL bListSorted = TRUE; tdp_BaseObjectPointer * pBaseObjectPointer = m_Array [E_lo_Owner]; for (long i = 0 ; i < m_lNumberOfObjects - 1 ; i ++) { if ((* pBaseObjectPointer) -> GetOwner () > (* (pBaseObjectPointer+1)) -> GetOwner ()) { bListSorted = FALSE; break; } pBaseObjectPointer ++; } // If the list is already sorted, we do nothing if (bListSorted) return; // Else we resort the list for (i = 1 ; i < m_lNumberOfObjects ; i ++) { // We take the object number i CPA_BaseObject * pBaseObject = m_Array [E_lo_Owner] [i]; BOOL bExist; // We find the correct index long lNewIndex = fn_lDichoSearchOwner (m_Array [E_lo_Owner] , i , pBaseObject -> GetOwner () , & bExist , pBaseObject); if (lNewIndex != i) { memmove (& m_Array [E_lo_Owner] [lNewIndex + 1] , & m_Array [E_lo_Owner] [lNewIndex] , (i - lNewIndex) * sizeof (tdp_BaseObjectPointer)); m_Array [E_lo_Owner] [lNewIndex] = pBaseObject; } } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - fn_vReSortList // Call the three previous functions //----------------------------------------------------------------------------- void CPA_BaseObjectList::fn_vReSortList () { fn_vReSortListWithAlphaOrder (); fn_vReSortListWithDataOrder (); fn_vReSortListWithOwnerOrder (); } //***************************************************************************** //********** To go through the list ********** //***************************************************************************** //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetHeadElement // Same as CPA_List::GetHeadElement //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetHeadElement (Position & _Position) { if (m_lNumberOfObjects > 0) { _Position = 1; return m_Array [E_lo_GoThrough] [0]; } else { _Position = 0; return NULL; } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetTailElement // Same as CPA_List::GetTailElement //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetTailElement (Position & _Position) { if (m_lNumberOfObjects > 0) { _Position = m_lNumberOfObjects; return m_Array [E_lo_GoThrough] [m_lNumberOfObjects - 1]; } else { _Position = 0; return NULL; } } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetNextElement // Same as CPA_List::GetNextElement //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetNextElement (Position & _Position) { if (!_Position) return NULL; if (_Position >= m_lNumberOfObjects) { _Position = 0; return NULL; } return m_Array [E_lo_GoThrough] [_Position++]; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetPrevElement // Same as CList::GetNex //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetPrevElement (Position & _Position) { if (! _Position) return NULL; return m_Array [E_lo_GoThrough] [-- _Position]; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetNext // Same as CList::GetNext //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetNext (Position & _Position) { if (! _Position) return NULL; Position ActualPosition = _Position; if (_Position < m_lNumberOfObjects) _Position ++; else _Position = 0; return m_Array [E_lo_GoThrough] [ActualPosition - 1]; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - GetPrev // Same as CList::GetPrev //----------------------------------------------------------------------------- CPA_BaseObject * CPA_BaseObjectList::GetPrev (Position & _Position) { if (! _Position) return NULL; return m_Array [E_lo_GoThrough] [-- _Position]; } //----------------------------------------------------------------------------- // Class CPA_BaseObjectList - New Name // Type + number //----------------------------------------------------------------------------- CString CPA_BaseObjectList::GetNewName (const CString csDefaultBaseName /*=""*/) { CString csName; if( csDefaultBaseName == "") { ASSERT(m_csTypeName != ""); csName.Format("%s%d",m_csTypeName,++m_lCurrentUniqueIndex); } else { csName.Format("%s%d",csDefaultBaseName,++m_lCurrentUniqueIndex); } return csName; } #undef stricmp #endif // ACTIVE_EDITOR