//========================================================================================
// E library
//
// - List management header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-May-05 16:09:08
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//========================================================================================
#ifndef _ELists_h
#define _ELists_h


#include <sys/types.h>
#include <string.h>


#ifndef _ETypes_h
#include <ETypes.h>
#endif

#define EList(pQualifier, pType, pList)                      pQualifier pType*  pList;pQualifier  EIndex  pList##_Count
#define EListI(pQualifier, pType, pList)                     pQualifier pType*  pList = NULL;pQualifier EIndex  pList##_Count = 0
#define EListNI(pType, pInitialAlloc, pList)                 pType*  pList;ENewN(pInitialAlloc, pList);EIndex  pList##_Count;if(pList) { pList##_Count = pInitialAlloc; } else { pList##_Count = 0; }

#define EList_i32(pQualifier, pType, pList)                  pQualifier pType*  pList;pQualifier  int32_t  pList##_Count
#define EList_i32I(pQualifier, pType, pList)                 pQualifier pType*  pList = NULL;pQualifier  int32_t  pList##_Count = 0

#define EListA(pQualifier, pType, pList)                     pQualifier pType*  pList;pQualifier EIndex  pList##_Count, pList##_CountAllocated
#define EListAI(pQualifier, pType, pList)                    pQualifier pType*  pList = NULL;pQualifier EIndex  pList##_Count = 0, pList##_CountAllocated = 0
#define EListANI(pQualifier, pType, pList, pInitialAlloc)    pQualifier  pType*  pList;ENewN(pInitialAlloc, pList);EIndex  pList##_Count, pList##_CountAllocated;if(pList) { pList##_Count = 0;pList##_CountAllocated = pInitialAlloc; } else { pList##_Count = pList##_CountAllocated = 0; }
#define EListANI_s(pQualifier, pType, pList, pInitialAlloc)  EListAI_s(pQualifier, pType, pList);if(pInitialAlloc > 0) ENewN(pInitialAlloc, (pList).Items);else (pList).Items = NULL;if((pList).Items) { (pList).Count = 0;(pList).CountAllocated = pInitialAlloc; } else { (pList).Count = (pList).CountAllocated = 0; }

//========================================================================================================================================
// Declare a lazily-reallocated list
//
// Arguments
//  pQualifier  E.g. "static"
//  pType       Type of the elements
//  pList       The name of the variable
//
// Description
//  Declares a list variable.<BR>
//  Same as EListA_s(), but it does not initializes the list.<BR>
//  This may be needed if you want to pre-allocate the list to some size before adding more elements to it.<BR>
//  The type must be declared like this:
//  <PRE>EListA_t(MyStruct);</PRE>
//  Then, your list type can be passed to functions as:
// <PRE>MyStructListA</PRE> or <PRE>MyStructListA*</PRE>
//  Built-in types already have list types declared (char, EString etc.). Check include/ELists.h<BR>
//  The fields <B>Items</B>, <B>Count</B> and <B>CountAllocated</B> contain the list elements, the count and the currently allocated size of the list.
//
// Examples
// <PRE>
//  EListA_s(static, MyStruct, _MyString);
//  EListA_s(extern, MyStruct, _MyString);
// </PRE>
//
// See also
//  EListA_s(), EList_StructAddA_s(), EList_StructInsertA_s(), EList_PointerAddA_s(), EList_FreeA_s(), EList_FreeAChk_s(), EList_ObjectsFreeA_s() ...
//========================================================================================================================================
#define EListA_s(pQualifier, pType, pList)   pQualifier pType##ListA  pList


//========================================================================================================================================
// Declare and initialize lazily-reallocated list
//
// Arguments
//  pQualifier  E.g. "static"
//  pType       Type of the elements
//  pList       The name of the variable
//
// Description
//  Same as EListA_s(), but it also initializes the list.
//
// Examples
// <PRE>
//  EListAI_s(static, MyStruct, _MyString);
//  EListAI_s(extern, MyStruct, _MyString);
// </PRE>
//
// See also
//  EListA_s(), EList_StructAddA_s(), EList_StructInsertA_s(), EList_PointerAddA_s(), EList_FreeA_s(), EList_FreeAChk_s(), EList_ObjectsFreeA_s() ...
//========================================================================================================================================
#define EListAI_s(pQualifier, pType, pList)  pQualifier pType##ListA  pList = { .Items = NULL, .Count = 0, .CountAllocated = 0 }

#define EListA_sa(pQualifier, pType, pCount, pList)  pQualifier pType##ListA  pList[pCount]


#define EListS_s(p)                         { .Items= p, .Count = ECount(p) }
#define EListS_S(pList, pDst)               (pDst).Items= pList, (pDst).Count = ECount(pList)
#define EList_s(pQualifier, pType, pList)   pQualifier pType##List  pList
#define EListI_s(pQualifier, pType, pList)  pQualifier pType##List  pList = { .Items = NULL, .Count = 0 }

EListA_t(char);
EListA_t(int8_t);
EListA_t(uint8_t);
EList_t(uint32_t);
EListA_t(EUnsignedInt);

EList_t(EUInt16_3);
EList_t(EUInt16_4);

EList_t(EIndex);
EListA_t(EIndex);

EListA_t(EFloat32_2);
EListA_t(EFloat32_3);
EListA_t(EFloat32_4);

EListA_t(EFloat64_2);
EListA_t(EFloat64_3);
EListA_t(EFloat64_4);

EList_t(EString);
EListA_t(EString);

typedef char*  ECharPtr;

EList_t(ECharPtr);  // ECharPtrList
EListA_t(ECharPtr);  // ECharPtrList


#define EList_Init(pList)                               do { pList = NULL;pList##_Count = 0; } while(0)
#define EList_Init_s(pList)                             do { (pList).Items = NULL;(pList).Count = 0; } while(0)
#define EList_Init_p(pList)                             do { (pList)->Items = NULL;(pList)->Count = 0; } while(0)

#define EList_Free(pList)                               do { EFreeClr(pList);pList##_Count = 0; } while(0)
#define EList_Free_s(pList)                             do { EFreeClr((pList).Items);(pList).Count = 0; } while(0)
#define EList_Free_p(pList)                             do { EFreeClr((pList)->Items);(pList)->Count = 0; } while(0)

#define EList_FreeChk(pList)                            do { EFreeChkClr(pList);pList##_Count = 0; } while(0)
#define EList_FreeChk_s(pList)                          do { EFreeChkClr((pList).Items);(pList).Count = 0; } while(0)
#define EList_FreeChk_p(pList)                          do { EFreeChkClr((pList)->Items);(pList)->Count = 0; } while(0)

#define EList_InitA(pList)                              do { pList = NULL;pList##_Count = pList##_CountAllocated = 0; } while(0)
#define EList_InitA_s(pList)                            do { (pList).Items = NULL;(pList).Count = (pList).CountAllocated = 0; } while(0)
#define EList_InitA_p(pList)                            do { (pList)->Items = NULL;(pList)->Count = (pList)->CountAllocated = 0; } while(0)
#define EList_InitAN(pList, pInitialAlloc)              do { ENewN(pInitialAlloc, pList);pList##_Count = 0;if(pList) pList##_CountAllocated = pInitialAlloc;else pList##_CountAllocated = 0; } while(0)
#define EList_InitAN_s(pList, pInitialAlloc)            do { ENewN(pInitialAlloc, (pList).Items);(pList).Count = 0;if((pList).Items) (pList).CountAllocated = pInitialAlloc;else (pList).CountAllocated = 0; } while(0)

#define EList_FreeA(pList)                              do { EFreeClr(pList);pList##_Count = pList##_CountAllocated = 0; } while(0)
#define EList_FreeA_s(pList)                            do { EFreeClr((pList).Items);(pList).Count = (pList).CountAllocated = 0; } while(0)
#define EList_FreeA_p(pList)                            do { EFreeClr((pList)->Items);(pList)->Count = (pList)->CountAllocated = 0; } while(0)
#define EList_FreeAChk(pList)                           do { if(pList) { EFreeClr(pList);pList##_Count = pList##_CountAllocated = 0; } } while(0)
#define EList_FreeAChk_s(pList)                         do { EFreeChkClr((pList).Items);(pList).Count = (pList).CountAllocated = 0; } while(0)
#define EList_FreeAChk_p(pList)                         do { EFreeChkClr((pList)->Items);(pList)->Count = (pList)->CountAllocated = 0; } while(0)

// Optimize lazily allocated list (reallocate to _Count, if necessary)
#define EList_ResizeA(pList)                              if(pList##_Count < pList##_CountAllocated) EResizeNT(typeof(pList[0]), pList##_Count, pList)
#define EList_ResizeNA(pList, pCount)                     do { if(pCount != pList##_CountAllocated) { EResizeNT(typeof(pList[0]), pCount, pList);pList##_Count = pList##_CountAllocated = pCount; } } while(0)
#define EList_ResizeNA_s(pList, pCount)                   do { if(pCount != (pList).CountAllocated) { EResizeNT(typeof((pList).Items[0]), pCount, pList.Items);(pList).Count = (pList).CountAllocated = pCount; } } while(0)

#define EList_IndexAdd(pList, pValue)                     ELst_IndexAdd(&(pList), &(pList##_Count),  pValue)
#define EList_IndexAddA(pList, pAllocStep, pValue)        ELst_IndexAddA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep,  pValue)
#define EList_IndexAddA_s(pList, pAllocStep, pValue)      ELst_IndexAddA(&(pList).Items, &(pList).Count, &(pList).CountAllocated, pAllocStep,  pValue)
#define EList_IndexAddAChk_s(pList, pAllocStep, pValue)   ELst_IndexAddAChk(&(pList).Items, &(pList).Count, &(pList).CountAllocated, pAllocStep,  pValue)
#define EList_IndexInsert(pList, pWhere, pValue)          ELst_IndexInsert(&(pList), &(pList##_Count), pWhere, pValue)

#define EList_Int32AddA_i32(pList, pAllocStep, pValue)    ELst_Int32AddA_i32(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep,  pValue)
#define EList_Int32GetIndex(pList, pValue)                ELst_Int32GetIndex(pList, pList##_Count,  pValue)
#define EList_IndexAddAChk(pList, pAllocStep, pValue)     ELst_IndexAddAChk(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep,  pValue)
#define EList_IndexGetIndex(pList, pValue)                ELst_IndexGetIndex(pList, pList##_Count,  pValue)
#define EList_IndexRemove(pList, pValue)                  ELst_IndexRemove(&(pList), &(pList##_Count),  pValue)
#define EList_IndexRemoveNoRealloc(pList, pValue)         ELst_IndexRemoveNoRealloc(&(pList), &(pList##_Count),  pValue)
#define EList_IndexRemoveNoRealloc_s(pList, pValue)       ELst_IndexRemoveNoRealloc(&(pList).Items, &(pList).Count,  pValue)

#define EList_IndexRemoveByIndex(pList, pIndex)             ELst_IndexRemoveByIndex(&(pList), &(pList##_Count),  pIndex)
#define EList_IndexRemoveByIndex_s(pList, pIndex)           ELst_IndexRemoveByIndex(&((pList).Items), &((pList).Count),  pIndex)
#define EList_IndexRemoveByIndexNoRealloc(pList, pIndex  )  ELst_IndexRemoveByIndexNoRealloc(&(pList), &(pList##_Count),  pIndex)
#define EList_IndexRemoveByIndexNoRealloc_s(pList, pIndex)  ELst_IndexRemoveByIndexNoRealloc(&(pList).Items, &(pList).Count,  pIndex)

#define EList_IntAdd(pList, pValue)                       ELst_IntAdd(&(pList), &(pList##_Count),  pValue)
#define EList_IntInsert(pList, pWhere, pValue)            ELst_IntInsert(&(pList), &(pList##_Count),  pWhere,  pValue)
#define EList_IntRemove(pList, pValue)                    ELst_IntRemove(&(pList), &(pList##_Count),  pValue)
#define EList_IntRemoveByIndex(pList, pValue)             ELst_IntRemoveByIndex(&(pList), &(pList##_Count),  pValue)

#define EList_Int16Add(pList, pValue)                     ELst_Int16Add(&(pList), &(pList##_Count),  pValue)
#define EList_Int16Add_s(pList, pValue)                   ELst_Int16Add(&(pList).Items, &(pList).Count,  pValue)
#define EList_Int16Insert(pList, pWhere, pValue)          ELst_Int16Insert(&(pList), &(pList##_Count), pWhere,  pValue)
#define EList_Int16Remove(pList, pValue)                  ELst_Int16Remove(&(pList), &(pList##_Count),  pValue)
#define EList_Int16RemoveByIndex(pList, pValue)           ELst_Int16RemoveByIndex(&(pList), &(pList##_Count),  pValue)

#define EList_StructAdd_i32(pList)                        (typeof(pList[0])*)ELst_StructAdd_i32(&(pList), &(pList##_Count), sizeof(pList[0]))
#define EList_StructAdd(pList)                            (typeof(pList[0])*)ELst_StructAdd(&(pList), &(pList##_Count), sizeof(pList[0]))
#define EList_StructAdd_s(pList)                          (typeof((pList).Items[0])*)ELst_StructAdd(&((pList).Items), &((pList).Count), sizeof((pList).Items[0]))
#define EList_StructAdd_p(pList)                          (typeof((pList)->Items[0])*)ELst_StructAdd(&((pList)->Items), &((pList)->Count), sizeof((pList)->Items[0]))
#define EList_StructAddClr(pList)                         (typeof(pList[0])*)ELst_StructAddClr(&(pList), &(pList##_Count), sizeof(pList[0]))
#define EList_StructAddClr_s(pList)                       (typeof((pList).Items[0])*)ELst_StructAddClr(&((pList).Items), &((pList).Count), sizeof((pList).Items[0]))
#define EList_StructAddS(pList, pElemetSize)              (typeof(pList[0])*)ELst_StructAdd(&(pList), &(pList##_Count), pElemetSize)
#define EList_StructAddSClr(pList, pElemetSize)           (typeof(pList[0])*)ELst_StructAddClr(&(pList), &(pList##_Count), pElemetSize)
#define EList_StructAddS_s(pList, pElemetSize)            (typeof((pList).Items[0])*)ELst_StructAdd(&((pList).Items), &((pList).Count), pElemetSize)

#define EList_StructAddA(pList, pAllocStep)                (typeof(pList[0])*)ELst_StructAddA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, sizeof(pList[0]))

//========================================================================================================================================
// Add a struct to a lazily-reallocated list
//
// Arguments
//  pList         The name of the list variable
//  pAllocStep    Allocation step / strategy
//
// Description
//  Adds a struct to the end of a list. pAllocStep may be a positive integer (linear increment), or a special value, such as EListAlloc2X (double the size, if out of space).
//  Linear increments are more memory-efficient, but they may be slower when used a high number of times. In those cases, EListAlloc2X may be faster, but it results in a
//  quadratic memory use increase. In the worst case, you may only need one extra element in a million-element list, but it may end up allocating memory for another million elements.
//  Choose your strategy wisely. If possible, pre-compute the size of the resulting list and allocate it once.
//
// Example
// <PRE>
//  EListAI_s(static, MyStruct, _MyList);   // Declare and initialize list
//  ...
//  MyStruct*  LNewStruct = EList_StructAddA_s(MyStruct, 64)
// </PRE>
//
// See also
//  EListA_s()
//========================================================================================================================================
#define EList_StructAddA_s(pList, pAllocStep)              (typeof((pList).Items[0])*)ELst_StructAddA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, sizeof((pList).Items[0]))
#define EList_StructAddA_p(pList, pAllocStep)              (typeof((pList)->Items[0])*)ELst_StructAddA(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pAllocStep, sizeof((pList)->Items[0]))

#define EList_StructAddAClr(pList, pIncrement)             (typeof(pList[0])*)ELst_StructAddAClr(&(pList), &(pList##_Count), &(pList##_CountAllocated), pIncrement, sizeof(pList[0]))
#define EList_StructAddAClr_s(pList, pAllocStep)           (typeof((pList).Items[0])*)ELst_StructAddAClr(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, sizeof((pList).Items[0]))
#define EList_StructAddAClr_p(pList, pAllocStep)           (typeof((pList)->Items[0])*)ELst_StructAddAClr(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pAllocStep, sizeof((pList)->Items[0]))

#define EList_StructAddAClrNew(pList, pIncrement)          (typeof(pList[0])*)ELst_StructAddAClrNew(&(pList), &(pList##_Count), &(pList##_CountAllocated), pIncrement, sizeof(pList[0]))
#define EList_StructAddAClrNew_s(pList, pIncrement)        (typeof((pList).Items[0])*)ELst_StructAddAClrNew(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pIncrement, sizeof((pList).Items[0]))

#define EList_StructRemoveByIndex(pList, pIndex)           ELst_StructRemoveByIndex(&(pList), &(pList##_Count), sizeof(pList[0]), pIndex)
#define EList_StructRemoveByIndex_s(pList, pIndex)         ELst_StructRemoveByIndex(&((pList).Items), &((pList).Count), sizeof((pList).Items[0]), pIndex)
#define EList_StructRemoveByIndex_p(pList, pIndex)         ELst_StructRemoveByIndex(&((pList)->Items), &((pList)->Count), sizeof((pList)->Items[0]), pIndex)
#define EList_StructRemoveByIndexNoRealloc(pList, pIndex)  ELst_StructRemoveByIndexNoRealloc(&(pList), &(pList##_Count), sizeof(pList[0]), pIndex)
#define EList_StructRemoveByIndexNoRealloc_s(pList, pIndex)  ELst_StructRemoveByIndexNoRealloc(&(pList).Items, &(pList).Count, sizeof((pList).Items[0]), pIndex)
#define EList_StructsAddA(pList, pCount)                   (typeof(pList[0])*)ELst_StructsAddA(&(pList), &(pList##_Count), &(pList##_CountAllocated), sizeof(pList[0]), pCount)
#define EList_StructsAddA_s(pList, pCount)                 (typeof((pList).Items[0])*)ELst_StructsAddA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), sizeof((pList).Items[0]), pCount)

#define EList_PointerAdd_i32(pList, pPointer)              ELst_PointerAdd_i32(&(pList), &(pList##_Count), pPointer)
#define EList_PointerAddChk_i32(pList, pPointer)           ELst_PointerAddChk_i32(&(pList), &(pList##_Count), pPointer)

#define EList_PointerAdd(pList, pPointer)                  ELst_PointerAdd(&(pList), &(pList##_Count), pPointer)
#define EList_PointerAdd_s(pList, pPointer)                ELst_PointerAdd(&((pList).Items), &((pList).Count), pPointer)
#define EList_PointerAddChk(pList, pPointer)               ELst_PointerAddChk(&(pList), &(pList##_Count), pPointer)
#define EList_PointerAddChk_i32(pList, pPointer)           ELst_PointerAddChk_i32(&(pList), &(pList##_Count), pPointer)
#define EList_PointerRemove(pList, pPointer)               ELst_PointerRemove(&(pList), &(pList##_Count), pPointer)
#define EList_PointerRemove_s(pList, pPointer)             ELst_PointerRemove(&((pList).Items), &((pList).Count), pPointer)

#define EList_PointerAddA(pList, pAllocStep, pPointer)               ELst_PointerAddA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pPointer)
#define EList_PointerAddA_s(pList, pAllocStep, pPointer)             ELst_PointerAddA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, pPointer)
#define EList_PointerAddA_p(pList, pAllocStep, pPointer)             ELst_PointerAddA(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pAllocStep, pPointer)
#define EList_PointerAddAChk(pList, pAllocStep, pPointer)            ELst_PointerAddAChk(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pPointer)
#define EList_PointerAddAChk_p(pList, pAllocStep, pPointer)          ELst_PointerAddAChk(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pAllocStep, pPointer)
#define EList_PointerAddAChk_s(pList, pAllocStep, pPointer)          ELst_PointerAddAChk(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, pPointer)
#define EList_PointerInsertA(pList, pAllocStep, pWhere, pPointer)    ELst_PointerInsertA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pWhere, pPointer);
#define EList_PointerInsertA_s(pList, pAllocStep, pWhere, pPointer)  ELst_PointerInsertA(&(pList).Items, &(pList).Count, &(pList).CountAllocated, pAllocStep, pWhere, pPointer);
#define EList_PointerRemoveA(pList, pPointer)                        ELst_PointerRemoveA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pPointer)
#define EList_PointerRemoveA_s(pList, pPointer)                      ELst_PointerRemoveA(&(pList).Items, &(pList).Count, &(pList).CountAllocated, pPointer)
#define EList_PointersFree(pList)                                    ELst_PointersFree(&(pList), &(pList##_Count))
#define EList_PointersFree_s(pList)                                  ELst_PointersFree(&((pList).Items), &((pList).Count))
#define EList_PointersFreeChk(pList)                                 do { if(pList) ELst_PointersFree(&(pList), &(pList##_Count)); } while(0)
#define EList_PointersFreeChk_s(pList)                               do { if((pList).Items) ELst_PointersFree(&((pList).Items), &((pList).Count)); } while(0)
#define EList_PointersFreeA(pList)                                   do { ELst_PointersFree(&(pList), &(pList##_Count));pList##_CountAllocated = 0; } while(0)

#define EList_PointerGetIndex(pList, pPointer)                     ELst_PointerGetIndex(pList, pList##_Count, pPointer)
#define EList_PointerGetIndex_s(pList, pPointer)                   ELst_PointerGetIndex((pList).Items, (pList).Count, pPointer)
#define EList_PointerGetIndex_p(pList, pPointer)                   ELst_PointerGetIndex((pList)->Items, (pList)->Count, pPointer)
#define EList_PointerGetCount(pList, pPointer)                     ELst_PointerGetCount(pList, pList##_Count, pPointer)
#define EList_PointerRemoveByIndex(pList, pIndex)                  ELst_PointerRemoveByIndex(&(pList), &(pList##_Count), pIndex)
#define EList_PointerRemoveByIndex_s(pList, pIndex)                ELst_PointerRemoveByIndex(&(pList).Items, &(pList).Count, pIndex)

#define EList_PointerRemoveByIndexNoRealloc(pList, pIndex)         ELst_PointerRemoveByIndexNoRealloc(&(pList), &(pList##_Count), pIndex)
#define EList_PointerRemoveByIndexNoRealloc_s(pList, pIndex)       ELst_PointerRemoveByIndexNoRealloc(&(pList).Items, &(pList).Count, pIndex)


#define EList_IndicesBackupAndRemove(pStructs,  pIndices, pRemap)  ELst_IndicesBackupAndRemove( &(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pRemap)
#define EList_IndicesInsertFromBackup(pStructs, pIndices)          ELst_IndicesInsertFromBackup(&(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices))

#define EList_StructsBackupAndRemoveA_s(pStructs,  pIndices,  pStructSize)  do { ELst_StructsBackupAndRemove(&((pStructs).Items), &((pStructs).Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pStructSize);(pStructs).CountAllocated = (pStructs).Count; } while(0)

#define EList_StructsInsertFromBackup(pStructs, pIndices,  pStructSize)     ELst_StructsInsertFromBackup(&(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pStructSize)
#define EList_StructsInsertFromBackup_s(pStructs, pIndices,  pStructSize)   ELst_StructsInsertFromBackup(&((pStructs).Items), &((pStructs).Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pStructSize)
#define EList_StructsInsertFromBackupA(pStructs, pIndices,  pStructSize)    do { ELst_StructsInsertFromBackup(&(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pStructSize);pStructs##_CountAllocated = pStructs##_Count; } while(0)
#define EList_StructsInsertFromBackupA_s(pStructs, pIndices,  pStructSize)  do { ELst_StructsInsertFromBackup(&((pStructs).Items), &((pStructs).Count),  pIndices##_Indices, pIndices##_Count,  &(pIndices),  pStructSize);(pStructs).CountAllocated = (pStructs).Count; } while(0)

#define EList_StructInsert(pStructs, pWhere)                       ELst_StructInsert(&(pStructs), &(pStructs##_Count), (sizeof(pStructs[0])), pWhere)
#define EList_StructInsert_s(pStructs, pWhere)                     ELst_StructInsert(&((pStructs).Items), &((pStructs).Count), (sizeof((pStructs).Items[0])), pWhere)
#define EList_StructInsert_p(pStructs, pWhere)                     ELst_StructInsert(&((pStructs)->Items), &((pStructs)->Count), (sizeof((pStructs)->Items[0])), pWhere)
#define EList_StructInsertA(pStructs, pAllocStep, pWhere)          ELst_StructInsertA(&(pStructs), &(pStructs##_Count), &(pStructs##_CountAllocated), pAllocStep, (sizeof(pStructs[0])), pWhere)
#define EList_StructInsertA_s(pStructs, pAllocStep, pWhere)        ELst_StructInsertA(&((pStructs).Items), &((pStructs).Count), &((pStructs).CountAllocated), pAllocStep, (sizeof((pStructs).Items[0])), pWhere)
#define EList_StructInsertA_p(pStructs, pAllocStep, pWhere)        ELst_StructInsertA(&((pStructs)->Items), &((pStructs)->Count), &((pStructs)->CountAllocated), pAllocStep, (sizeof((pStructs)->Items[0])), pWhere)
#define EList_StructInsertA_pr(pStructs, pAllocStep, pWhere, pNew)  pNew = (typeof((pStructs)->Items[0])*)ELst_StructInsertA(&((pStructs)->Items), &((pStructs)->Count), &((pStructs)->CountAllocated), pAllocStep, (sizeof((pStructs)->Items[0])), pWhere)
#define EList_StructsInsertA_pr(pStructs, pAllocStep, pCount, pWhere, pNew)  pNew = (typeof((pStructs)->Items[0])*)ELst_StructsInsertA(&((pStructs)->Items), &((pStructs)->Count), &((pStructs)->CountAllocated), pAllocStep, pCount, (sizeof((pStructs)->Items[0])), pWhere)

#define EList_StructsRemove(pStructs,  pIndices)                   ELst_StructsRemove(&(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  (sizeof(pStructs[0])))
#define EList_StructsRemoveA(pStructs,  pIndices)                  do { ELst_StructsRemove(&(pStructs), &(pStructs##_Count),  pIndices##_Indices, pIndices##_Count,  (sizeof(pStructs[0])));pStructs##_CountAllocated = pStructs##_Count; } while(0)
#define EList_StructsRemoveA_s(pStructs,  pIndices)                do { ELst_StructsRemove(&((pStructs).Items), &((pStructs).Count),  pIndices##_Indices, pIndices##_Count,  (sizeof((pStructs).Items[0])));(pStructs).CountAllocated = (pStructs).Count; } while(0)


#define EList_ObjectAdd(pList, pWhat)                                ELst_ObjectAdd(&(pList), &(pList##_Count), pWhat)
#define EList_ObjectAdd_s(pList, pWhat)                              ELst_ObjectAdd(&(pList).Items, &(pList).Count, pWhat)
#define EList_ObjectAdd_p(pList, pWhat)                              ELst_ObjectAdd(&(pList)->Items, &(pList)->Count, pWhat)
#define EList_ObjectAddChk(pList, pWhat)                             ELst_ObjectAddChk(&(pList), &(pList##_Count), pWhat)
#define EList_ObjectAddA(pList, pAllocStep, pWhat)                   ELst_ObjectAddA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pWhat)
#define EList_ObjectAddA_s(pList, pAllocStep, pWhat)                 ELst_ObjectAddA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, pWhat)
#define EList_ObjectAddA_p(pList, pAllocStep, pWhat)                 ELst_ObjectAddA(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pAllocStep, pWhat)
#define EList_ObjectAddAChk(pList, pAllocStep, pWhat,  pIndexRet)    ELst_ObjectAddAChk(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pWhat,  pIndexRet)
#define EList_ObjectAddAChk_s(pList, pAllocStep, pWhat,  pIndexRet)  ELst_ObjectAddAChk(&(pList).Items, &(pList).Count, &(pList).CountAllocated, pAllocStep, pWhat,  pIndexRet)
#define EList_ObjectAddAChk_p(pList, pAllocStep, pWhat,  pIndexRet)  ELst_ObjectAddAChk(&(pList)->Items, &(pList)->Count, &(pList)->CountAllocated, pAllocStep, pWhat,  pIndexRet)
#define EList_ObjectInsert(pList, pWhere, pWhat)                     ELst_ObjectInsert(&(pList), &(pList##_Count), pWhere, pWhat)
#define EList_ObjectInsert_s(pList, pWhere, pWhat)                   ELst_ObjectInsert(&(pList).Items, &(pList).Count, pWhere, pWhat)
#define EList_ObjectInsertA(pList, pAllocStep, pWhere, pWhat)        ELst_ObjectInsertA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pAllocStep, pWhere, pWhat)
#define EList_ObjectInsertA_s(pList, pAllocStep, pWhere, pWhat)      ELst_ObjectInsertA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pAllocStep, pWhere, pWhat)
#define EList_ObjectRemove(pList, pWhat)                             ELst_ObjectRemove(&(pList), &(pList##_Count), pWhat)
#define EList_ObjectRemoveNoFree(pList, pWhat)                       ELst_ObjectRemoveNoFree(&(pList), &(pList##_Count), pWhat)
#define EList_ObjectRemove_s(pList, pWhat)                           ELst_ObjectRemove(&((pList).Items), &((pList).Count), pWhat)
#define EList_ObjectRemoveA(pList, pPointer)                         ELst_ObjectRemoveA(&(pList), &(pList##_Count), &(pList##_CountAllocated), pPointer)
#define EList_ObjectRemoveA_s(pList, pPointer)                       ELst_ObjectRemoveA(&((pList).Items), &((pList).Count), &((pList).CountAllocated), pPointer)
#define EList_ObjectRemoveA_p(pList, pPointer)                       ELst_ObjectRemoveA(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated), pPointer)
#define EList_ObjectRemoveByIndex(pList, pIndex)                     ELst_ObjectRemoveByIndex(&(pList), &(pList##_Count), pIndex)
#define EList_ObjectRemoveByIndex_s(pList, pIndex)                   ELst_ObjectRemoveByIndex(&((pList).Items), &((pList).Count), pIndex)
#define EList_ObjectRemoveByIndex_p(pList, pIndex)                   ELst_ObjectRemoveByIndex(&((pList)->Items), &((pList)->Count), pIndex)
#define EList_ObjectRemoveByIndexNoRealloc_s(pList, pIndex)          ELst_ObjectRemoveByIndexNoRealloc(&((pList).Items), &((pList).Count), pIndex)
#define EList_ObjectRemoveByIndexNoRealloc_p(pList, pIndex)          ELst_ObjectRemoveByIndexNoRealloc(&((pList)->Items), &((pList)->Count), pIndex)
#define EList_ObjectsFree(pList)                                     ELst_ObjectsFree(&(pList), &(pList##_Count))
#define EList_ObjectsFree_s(pList)                                   ELst_ObjectsFree(&((pList).Items), &((pList).Count))
#define EList_ObjectsFreeA(pList)                                    ELst_ObjectsFreeA(&(pList), &(pList##_Count), &(pList##_CountAllocated))
#define EListDbg_ObjectsFreeA(pList)                                 ELst_ObjectsFreeA(&(pList), &(pList##_Count), &(pList##_CountAllocated))
#define EList_ObjectsFreeA_s(pList)                                  ELst_ObjectsFreeA(&((pList).Items), &((pList).Count), &((pList).CountAllocated))
#define EList_ObjectsFreeA_p(pList)                                  ELst_ObjectsFreeA(&((pList)->Items), &((pList)->Count), &((pList)->CountAllocated))
#define EList_ObjectsSort_s(pList, pCompareFunc)                     ELst_ObjectsSort_s(&(pList), pCompareFunc)
#define EList_ObjectsSort_p(pList, pCompareFunc)                     ELst_ObjectsSort_s(pList, pCompareFunc)


#define EList_AddSpaceA_p(pList, pNNewElements, pIncrement) do\
{\
	const EIndex  lNNewElements = pNNewElements, lIncrement = pIncrement;\
	const EIndex  lOldCount = (pList)->Count;\
	if((pList)->CountAllocated < lOldCount + lNNewElements)\
	{\
		const EIndex  lItemSize = sizeof((pList)->Items[0]);\
		const EIndex  lNBlocks = (lOldCount + lNNewElements + lIncrement - 1) / lIncrement;\
		(pList)->Items = (typeof((pList)->Items[0])*)ERealloc((pList)->Items, lItemSize * lIncrement * lNBlocks);\
		(pList)->CountAllocated = lIncrement * lNBlocks;\
	}\
} while(0)


#define EList_MakeSpaceA_p(pList, pNNewElements, pIncrement) do\
{\
	const EIndex  lNNewElements = pNNewElements, lIncrement = pIncrement;\
	if((pList)->CountAllocated < lNNewElements)\
	{\
		const EIndex  lItemSize = sizeof((pList)->Items[0]);\
		const EIndex  lNBlocks = (lNNewElements + lIncrement - 1) / lIncrement;\
		(pList)->Items = (typeof((pList)->Items[0])*)ERealloc((pList)->Items, lItemSize * lIncrement * lNBlocks);\
		(pList)->CountAllocated = lIncrement * lNBlocks;\
	}\
} while(0)


#define EList_MakeSpaceA_s(pList, pNNewElements, pIncrement) do\
{\
	const EIndex  lNNewElements = pNNewElements, lIncrement = pIncrement;\
	if((pList).CountAllocated < lNNewElements)\
	{\
		const EIndex  lItemSize = sizeof((pList)->Items[0]);\
		const EIndex  lNBlocks = (lNNewElements + lIncrement - 1) / lIncrement;\
		(pList).Items = (typeof((pList).Items[0])*)ERealloc((pList).Items, lItemSize * lIncrement * lNBlocks);\
		(pList).CountAllocated = lIncrement * lNBlocks;\
	}\
} while(0)


#define EList_MakeSpaceA(pList, pNNewElements, pIncrement) do\
{\
	const EIndex  lNNewElements = pNNewElements, lIncrement = pIncrement;\
	if(pList##_CountAllocated < lNNewElements)\
	{\
		const EIndex  lItemSize = sizeof((pList)[0]);\
		const EIndex  lNBlocks = (lNNewElements + lIncrement - 1) / lIncrement;\
		pList = (typeof((pList)[0])*)ERealloc(pList, lItemSize * lIncrement * lNBlocks);\
		pList##_CountAllocated = lIncrement * lNBlocks;\
	}\
} while(0)


#define _EList_ObjectRemoveByIndexNoDel(pList, pIndex)               _ELst_ObjectRemoveByIndexNoDel(&(pList), &(pList##_Count), pIndex)


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif

typedef struct
{
	EIndex  Key, Value;
} EIndexKeyValue;
EListA_t(EIndexKeyValue);

enum
{
	EPtrFIRST = 1,
	EPtrADDED,
	EPtrREALLOCATED
};


extern EIndex   ELst_IndexAdd(EIndex** PListPtr, EIndex* PNumOfInts, const EIndex PNewItem);
extern EIndex   ELst_IndexAddChk(EIndex** PListP, EIndex* PCountP, const EIndex PNewItem);
extern EIndex   ELst_IndexAddA(EIndex** PListPtr, EIndex* PNumOfInts, EIndex* PNumOfIntsAllocated, const EIndex PAllocStep, const EIndex PValue);
extern EIndex   ELst_Int32AddA_i32(int32_t** PListPtr, int32_t* PNumOfInts, int32_t* PNumOfIntsAllocated, const int32_t PAllocStep, const int32_t PValue);
extern EIndex   ELst_Int32GetIndex(const int32_t* PList, const EIndex PCount,  const EIndex PTheIndex);

extern EIndex   ELst_IndexAddAChk(EIndex** PListPtr, EIndex* PNumOfInts, EIndex* PNumOfIntsAllocated, const EIndex PAllocStep, const EIndex PValue);
extern int      ELst_IndexInsert(EIndex** PListPtr, EIndex* PCountP, EIndex PWhere, const EIndex PValue);
extern EIndex   ELst_IndexGetIndex(const EIndex* PList, const EIndex PCount,  const EIndex PTheIndex);
extern EIndex   ELst_IndexRemove(EIndex** PListPtr, EIndex* PNumOfInts, const EIndex PValue);
extern EIndex   ELst_IndexRemoveNoRealloc(EIndex** PListPtr, EIndex* PNumOfInts, const EIndex PValue);
extern EIndex   ELst_IndexRemoveByIndex(EIndex** PListPtr, EIndex* PNumOfInts, const EIndex PIndex);
extern EIndex   ELst_IndexRemoveByIndexNoRealloc(EIndex** PListPtr, EIndex* PNumOfInts, const EIndex PIndex);

extern EIndex   ELst_IntAdd(int** PListPtr, EIndex* PNumOfInts, const int PNewItem);
extern int      ELst_IntInsert(int** PListPtr, EIndex* PCountP, EIndex PWhere, const int PValue);
extern EIndex   ELst_IntRemove(int** PListPtr, EIndex* PNumOfInts, const int PValue);
extern EIndex   ELst_IntRemoveByIndex(int** PListPtr, EIndex* PNumOfInts, const EIndex PIndex);

extern EIndex   ELst_Int16Add(int16_t** PListPtr, EIndex* PNumOfInts, const int16_t PNewItem);
extern int      ELst_Int16Insert(int16_t** PListPtr, EIndex* PCountP, EIndex PWhere, const int16_t PValue);
extern EIndex   ELst_Int16Remove(int16_t** PListPtr, EIndex* PNumOfInts, const int16_t PValue);
extern EIndex   ELst_Int16RemoveByIndex(int16_t** PListPtr, EIndex* PNumOfInts, const EIndex PIndex);

extern void*    ELst_StructAdd_i32(void* PListPtr, int32_t* PCountP, const ESize PStructSize);
extern void*    ELst_StructAdd(void* PListPtr, EIndex* PCountP, const ESize PStructSize);
extern void*    ELst_StructAddClr(void* PListPtr, EIndex* PCountP, const ESize PStructSize);
extern void*    ELst_StructInsert_i32(void* PListPtr, int* PCountP, const ESize PStructSize, const int PWhere);
extern void*    ELst_StructInsert(void* PListPtr, EIndex* PCountP, const ESize PStructSize, const EIndex PWhere);
extern void*    ELst_StructInsertA(void* PListP, EIndex* PCountP, EIndex* PCountAllocatedP, const EIndex PAllocStep, const ESize PStructSize, EIndex PWhere);
extern void*    ELst_StructsInsert(void* PListPtr, EIndex* PCountP, const ESize PStructSize, const EIndex PCount, EIndex PWhere);
extern void*    ELst_StructsInsertA(void* PListP, EIndex* PCountP, EIndex* PCountAllocatedP, const EIndex PAllocStep, const ESize PStructSize, const EIndex PCount, EIndex PWhere);

extern void*    ELst_StructAddA(void* PListPtr, EIndex* PCountP, EIndex* PNumOfStructsAllocated, const EIndex PAllocStep, const ESize PStructSize);
extern void*    ELst_StructAddAClr(void* PListPtr, EIndex* PCountP, EIndex* PNumOfStructsAllocated, const EIndex PAllocStep, const ESize PStructSize);
extern void*    ELst_StructAddAClrNew(void* PListPtr, EIndex* PCountP, EIndex* PNumOfStructsAllocated, const EIndex PAllocStep, const ESize PStructSize);

extern int      ELst_StructRemoveByIndex(void* PListPtr, EIndex* PNumOfElements, const ESize PStructSize, const EIndex PIndex);
extern int      ELst_StructRemoveByIndexNoRealloc(void* PListPtr, EIndex* PNumOfElements, const ESize PStructSize, const EIndex PIndex);

extern void*    ELst_StructsAddA(void* PListPtr, EIndex* PCountP, EIndex* PStructsCountAllocated,  const ESize PStructSize, const ESize PCount);

extern int      ELst_PointerAdd_i32(void* PListPtr, int* PCountP, const void* PNewPtr);
extern int      ELst_PointerAdd(void* PListPtr, EIndex* PCountP, const void* PNewPtr);

extern EIndex   ELst_PointerAddChk(void* PListPtr, EIndex* PCountP, const void* PNewPtr);
extern int32_t  ELst_PointerAddChk_i32(void* PListPtr, int* PCountP, const void* PNewPtr);

extern EIndex   ELst_PointerAddA(void* PListPtr, EIndex* PCountP, EIndex* PNumOfAllocatedPointers, const EIndex PAllocStep, const void* PNewPtr);

extern EIndex   ELst_PointerAddAChk(void* PListPtr, EIndex* PCountP, EIndex* PNumOfAllocatedPointers, const EIndex PAllocStep, const void* PNewPtr);
extern int32_t  ELst_PointerAddAChk_i32(void* PListPtr, int32_t* PCountP, int32_t* PNumOfAllocatedPointers, const int32_t PAllocStep, const void* PNewPtr);

extern int      ELst_PointerInsert(void* PListPtr, EIndex* PCountP, EIndex PWhere, const void* PNewPtr);
extern int      ELst_PointerInsertA(void* PListPtr, EIndex* PCountP, EIndex* PNumOfAllocatedPointers, const EIndex PAllocStep, EIndex PWhere, const void* PNewPtr);


extern int      ELst_PointerRemoveByIndex(void* PListP, EIndex* PCountP, const EIndex PIndex);
extern int      ELst_PointerRemoveByIndexNoRealloc(void* PListP, EIndex* PCountP, const EIndex PIndex);

extern int32_t  ELst_PointerRemove_i32(void* PListPtr, int32_t* PCountP, const void* PThePtr);
extern EIndex   ELst_PointerRemove(void* PListPtr, EIndex* PCountP, const void* PThePtr);

extern EIndex   ELst_PointerRemoveA(void* PListPtr, EIndex* PCountP, EIndex* PNumOfAllocatedPointers, const void* PThePtr);

extern EIndex   ELst_PointerGetIndex(const void* PList, const EIndex PCountP,  const void* PThePtr);
extern EIndex   ELst_PointerGetCount(const void* PList, const EIndex PCountP,  const void* PThePtr);

extern void     ELst_PointersFree(void* PListPtr, EIndex* PCountP);


extern void     ELst_IndicesBackupAndRemove(EIndex** PStructsP, EIndex* PStructs_CountP,  const EIndex* PIndices, const EIndex PIndices_Count,  EIndex** PBackupBufferP,  const EBool PRemap);
extern void     ELst_IndicesInsertFromBackup(EIndex** PStructsP, EIndex* PStructs_CountP,  const EIndex* PIndices, const EIndex PIndices_Count,  EIndex** PBackupBufferP);


extern void     ELst_StructsRemove(void* PStructsP, EIndex* PStructs_CountP,  const EIndex* PIndices, const EIndex PIndices_Count,  const EIndex PStructSize);
extern void     ELst_StructsBackupAndRemove(void* PStructsPIn, EIndex* PNumOfStructsP, const EIndex* PIndices, const EIndex PNumOfIndices, void* PBackupBufferPIn, const EIndex PStructSize);
extern void     ELst_StructsInsertFromBackup(void* PStructsPIn, EIndex* PNumOfStructsP, const EIndex* PIndices, const EIndex PNumOfIndices, void* PBackupBufferPIn, const EIndex PStructSize);

extern EIndex*  ELst_DelCreateRemappingTable(const EIndex PTotalOldIndices_Count, const EIndex* PIndices, const EIndex PIndices_Count);
extern EIndex*  ELst_AddCreateRemappingTable(const EIndex PTotalOldIndices_Count, const EIndex* PIndices, const EIndex PIndices_Count);


extern int      E_IndexCmpDescending(const void* P0, const void* P1);


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _ELists_h
