#ifndef    __list_h__
#define    __list_h__

#include "utility.h"

/**********************************************************/
/* This object is a double link list.                     */
/* methods:                                               */
/*   init(addr of the list, size per entry, list size)    */
/*      The list's type depends on what user want to store*/
/*      . For example: if you want a list for int, you s- */
/*      hould declare like "int* v", and call the init()  */
/*      like "init(&v, sizeof(int), 5)", which will creat */
/*      a double link list with 5 elements.               */
/*                                                        */
/*   free(addr of the list)                               */
/*      Free the memory  the list use. You should call it */
/*      when you don't need the container.                */
/*                                                        */
/*                                                        */
/*   getSize(addr of the list)                            */
/*      Return the number of elements.                    */
/*                                                        */
/*   getEntrySize(addr of the list)                       */
/*      Return the size per entry, it dependent on what   */
/*      type of data you store in the container.          */
/*                                                        */
/*   getFront(addr of the list)                           */
/*      Return a const pointer which point to the entry   */
/*      at the head of the list.                          */
/*                                                        */
/*   getBack(addr of the list)                            */
/*      Return a const pointer which point to the entry   */
/*      at the end of the list.                           */
/*                                                        */
/*   getBegin(addr of the list)                           */
/*      Return a pointer which point to the iterator at   */
/*      the head of the list.                             */
/*                                                        */
/*   getEnd(addr of the list)                             */
/*      Return a pointer which point to the iterator at   */
/*      the end of the list (which cannot be modified).   */
/*                                                        */
/*                                                        */
/*   setSize(addr of the list, new_size)                  */
/*      Resize the lsit to new_size at the back of the    */
/*      list. Note that it won't initalize the newly ele- */
/*      ments when you increase the size.                 */
/*                                                        */
/*   setFront(addr of the list, data)                     */
/*      Let the first element be the data you given.      */
/*                                                        */
/*   setBack(addr of the list, data)                      */
/*      Let the last element be the data you given.       */
/*                                                        */
/*                                                        */
/*   addBack(addr of the list, data)                      */
/*      Add an element which contain data at the back of  */
/*      the list.                                         */
/*                                                        */
/*   delBack(addr of the list)                            */
/*      Remove the last element of the list.              */
/*                                                        */
/*   addFront(addr of the list, data)                     */
/*      Add an element which contain data at the front of */
/*      the list.                                         */
/*                                                        */
/*   delFront(addr of the list)                           */
/*      Remove the first element of the list.             */
/*                                                        */
/*                                                        */
/*   rm(addr of the list, addr of the iter1, iter2)       */
/*      Remove the part of iter1 ~ iter2 (include iter1   */
/*      but not iter2)                                    */
/*                                                        */
/*   copy(addr of the list, addr of the iter1, iter2,     */
/*        addr of the list2)                              */
/*      Create a new list which contain the part of the   */
/*      iter1 ~ iter2 (include iter1 but not iter2) and   */
/*      saved it to list2.                                */
/*                                                        */
/*   move(addr of the list, addr of the iter1, iter2,     */
/*        addr of the list2)                              */
/*      Move the part iter1 ~ iter2 to list2.             */
/*                                                        */
/*   swap(addr of the l1, addr of the iter. i1, i2,       */
/*        addr of the l2, addr of the iter. j1, j2)       */
/*      Swap the part of l1 from i1 to i2.previous and    */
/*      the part of l2 from j1 to j2.previous.            */
/*                                                        */
/*                                                        */
/*   iterGetEntry(addr of the iteator)                    */
/*      Return a const pointer which point to the data of */
/*      the iterator.                                     */
/*                                                        */
/*   iterGetNext(addr of the iterator)                    */
/*      Return a pointer which point to the next iterator */
/*                                                        */
/*   iterGetPrev(addr of the iterator)                    */
/*      Return a pointer which point to the previous ite- */
/*      ator.                                             */
/*                                                        */
/*                                                        */
/*   iterSetEntry(addr of the iterator, data)             */
/*      Let the data which is stored in iterator be the   */
/*      data you given.                                   */
/*                                                        */
/*   iterGoNext(addr of the iterator)                     */
/*      Instead of return a pointer, it will change the   */
/*      pointer you given.                                */
/*                                                        */
/*   iterGoPrev(addr of the iterator)                     */
/*      Instead of return a pointer, it will change the   */
/*      pointer you given.                                */
/*                                                        */
/*                                                        */
/*   iterDel(addr of the iterator)                        */
/*      Delete the iterator you given, returning a pointer*/
/*      to the next iterator                              */
/*                                                        */
/*   iterDelPrev(addr of the iterator)                    */
/*      Delete the previous of the iterator you given.    */
/*                                                        */
/*   iterDelPrev(addr of the iterator)                    */
/*      Delete the next of the iterator you given.        */
/*                                                        */
/*                                                        */
/**********************************************************/

pvoid ctl_list_initX(ppvoid l, size_t size, uint count);
pvoid ctl_list_freeX(ppvoid l);

int   ctl_list_getSizeX     (ppcvoid l);
int   ctl_list_getEntrySizeX(ppcvoid l);
pvoid ctl_list_getFrontX    ( ppvoid l);
pvoid ctl_list_getBackX     ( ppvoid l);
pvoid ctl_list_getBeginX    ( ppvoid l);
pvoid ctl_list_getEndX      ( ppvoid l);

int   ctl_list_setSizeX (ppvoid l, uint count);
pvoid ctl_list_setFrontX(ppvoid l, pcvoid data);
pvoid ctl_list_setBackX (ppvoid l, pcvoid data);

int ctl_list_addFrontX(ppvoid l, pcvoid data);
int ctl_list_delFrontX(ppvoid l);
int ctl_list_addBackX (ppvoid l, pcvoid data);
int ctl_list_delBackX (ppvoid l);

int   ctl_list_rmX  (ppvoid li, pvoid i1, pvoid i2);
pvoid ctl_list_copyX(ppvoid li, pvoid i1, pvoid i2, ppvoid out);
pvoid ctl_list_moveX(ppvoid li, pvoid i1, pvoid i2, ppvoid out);
int   ctl_list_swapX(ppvoid li, pvoid i1, pvoid i2,
                     ppvoid lj, pvoid j1, pvoid j2);

pvoid ctl_list_iterGetEntryX(pvoid i);
pvoid ctl_list_iterGetNextX (pvoid i);
pvoid ctl_list_iterGetPrevX (pvoid i);

pvoid ctl_list_iterSetEntryX(pvoid  i, pcvoid data);

pvoid ctl_list_iterDelX    (pvoid i);
pvoid ctl_list_iterDelPrevX(pvoid i);
pvoid ctl_list_iterDelNextX(pvoid i);

#define ctl_list_init(X,Y,Z) ctl_list_initX(ppVoid(X),Y,Z)
#define ctl_list_free(X)     ctl_list_freeX(ppVoid(X))

#define ctl_list_getSize(X)      ctl_list_getSizeX     (ppcVoid(X))
#define ctl_list_getEntrySize(X) ctl_list_getEntrySizeX(ppcVoid(X))
#define ctl_list_getFront(X)     ctl_list_getFrontX    (ppcVoid(X))
#define ctl_list_getBack(X)      ctl_list_getBackX     (ppcVoid(X))
#define ctl_list_getBegin(X)     ctl_list_getBeginX    (ppcVoid(X))
#define ctl_list_getEnd(X)       ctl_list_getEndX      (ppcVoid(X))

#define ctl_list_setSize(X,Y)  ctl_list_setSizeX (ppVoid(X),Y)
#define ctl_list_setFront(X,Y) ctl_list_setFrontX(ppVoid(X),pcVoid(Y))
#define ctl_list_setBack(X,Y)  ctl_list_setBackX (ppVoid(X),pcVoid(Y))

#define ctl_list_addFront(X,Y) ctl_list_addFrontX(ppVoid(X),pcVoid(Y))
#define ctl_list_delFront(X)   ctl_list_delFrontX(ppVoid(X))
#define ctl_list_addBack(X,Y)  ctl_list_addBackX (ppVoid(X),pcVoid(Y))
#define ctl_list_delBack(X)    ctl_list_delBackX (ppVoid(X))


#define ctl_list_rm(X,Y,Z)         ctl_list_rmX  (ppVoid(X),pVoid(Y),pVoid(Z))
#define ctl_list_copy(X,Y,Z,A)     ctl_list_copyX(ppVoid(X),pVoid(Y),pVoid(Z),ppVoid(A))
#define ctl_list_move(X,Y,Z,A)     ctl_list_moveX(ppVoid(X),pVoid(Y),pVoid(Z),ppVoid(A))
#define ctl_list_swap(X,Y,Z,A,B,C) ctl_list_swapX(ppVoid(X),pVoid(Y),pVoid(Z),ppVoid(A),pVoid(B),pVoid(C))

#define ctl_list_iterGetEntry(X)  ctl_list_iterGetEntryX(pcVoid(X))
#define ctl_list_iterGetNext(X)   ctl_list_iterGetNextX (pcVoid(X))
#define ctl_list_iterGetPrev(X)   ctl_list_iterGetPrevX (pcVoid(X))

#define ctl_list_iterSetEntry(X,Y) ctl_list_iterSetEntryX(pVoid(X),pcVoid(Y))

#define ctl_list_iterDel(X)     ctl_list_iterDelX    (pVoid(X))
#define ctl_list_iterDelPrev(X) ctl_list_iterDelPrevX(pVoid(X))
#define ctl_list_iterDelNext(X) ctl_list_iterDelNextX(pVoid(X))

#endif  /* __list_h__ */