/**
******************************************************************************************************************************************************************************************
*@file                       btlist.h
*@author         
*@data                       
*@version                    v1.0
*@par Copyright(c):
*
*@par History:
*     version:author,date,desc
*     v1.0   :create this file
*
*******************************************************************************************************************************************************************************************
*/
#ifndef BT_LIST_H
#define BT_LIST_H

/*---------------------------------------------------------------------------
Module Name:
	Pre-Pointer, Variable Preload List management
Abstract:
	This module defines the Bi-Direction and Single-Direction List manage functions.
---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* 								Pre 2 PTR * List 						     */
/*---------------------------------------------------------------------------*/
struct list_stru {/* New List Structure */
	void *head;
	void *tail;
};

struct list_to_stru {
	void *p[2];
};

/* Bidirection List Node */
#define LGET(n)			((void **)(n) + (1 * 2))/* From memory start ptr go to userdata */
#define LSTART(n)		((void **)(n) - (1 * 2))/* From userdata get back to memory start ptr */
#define LNEXT(n)		(*((void **)(n) - (1 * 2)))/* a story of http://www.googies.info/blog/945.html */
#define LPREV(n)		(*((void **)(n) - 1))
#define LP(n, k)		(*((void **)(n) - (1 * (k + 1))))/* k=0 is LPREV, k=1 is LNEXT */
#define LHT(l, k)		(((struct list_to_stru *)(l))->p[k])/* k=0 is Head or k=1 is Tail */
#define LFREE(n)		(FREE(LSTART(n)))/* Input ListNode userdata Ptr, Free it */

#ifdef CONFIG_DEBUG
/* Single Direction List Node */
#define SGET(n)			((void **)(n) + 1)/* From memory start ptr go to userdata */
#define SSTART(n)		((void **)(n) - 1)/* From userdata get back to memory start ptr */
#define SNEXT(n)		(*((void **)(n) - 1))
#define SFREE(n)		(FREE(SSTART(n)))/* Input ListNode userdata Ptr, Free it */

/* 4 direction List Node */
#define QGET(n)			((void **)(n) + (1 * 4))/* From memory start ptr go to userdata */
#define QSTART(n)		((void **)(n) - (1 * 4))/* From userdata get back to memory start ptr */
#define QFATHER(n)		(*((void **)(n) - (1 * 4)))
#define QCHILD(n)		(*((void **)(n) - (1 * 3)))
#define QNEXT(n)		(*((void **)(n) - (1 * 2)))
#define QPREV(n)		(*((void **)(n) - 1))
#define QFREE(n)		(FREE(QSTART(n)))/* Input ListNode userdata Ptr, Free it */
#endif /* CONFIG_OS_WIN32*/

#define LIST_STRUOFF(stru_, mem_)				((UINT32)(&(((stru_)(NULL))->mem_)))
#define LIST_STRUMEMLEN(stru_, mem_)			sizeof((((stru_)(NULL))->mem_))
void *List_Find_(struct list_stru *list, UINT32 off, UINT32 len, UINT8 *val);/* Shall not be used by UI */

#define VARLEN(stru_, mem_, len_)				(((UINT32)(&(((stru_)(NULL))->mem_))) + (len_))
#define NEWVARLEN(stru_, mem_, len_)			NEW(VARLEN(stru_, mem_, len_))

/*---------------------------------------------------------------------------
Example:
	LIST_FIND(&L2CAP_CID_LIST, struct L2CAP_CIDListStru *, cid, val);
---------------------------------------------------------------------------*/
#define LIST_FIND(list_, stru_, mem_, val_)				List_Find_(list_, LIST_STRUOFF(stru_, mem_), LIST_STRUMEMLEN(stru_, mem_), (UINT8 *)(&(val_)))/* This is UI */
#define LIST_FINDLEN(list_, stru_, mem_, len_, pval_)	List_Find_(list_, LIST_STRUOFF(stru_, mem_), (len_), (UINT8 *)(pval_))
#define LIST_FINDLENOFF0(list_, len_, pval_)			List_Find_(list_, 0, (len_), (UINT8 *)(pval_))

UINT32 List_Count(struct list_stru *list);
void *List_NodeExist(struct list_stru *list, void *p);

void *_List_NodeNew(UINT32 len);/* DONOT use this, see below */
void List_InsertAt(struct list_stru *list, void *pos, void *node);

//void List_AddNew(struct list_stru *list, void **node, UINT32 len);
#define List_AddNew(list, node, len) List_AddTail(list, (*node = List_NodeNew(len)))
void List_AddSide(struct list_stru *list, void *node, UINT8 i);
#define List_AddHead(list_, node_)	List_AddSide((list_), (node_), 0)
#define List_AddTail(list_, node_)	List_AddSide((list_), (node_), 1)

void *List_RemoveSide(struct list_stru *list, UINT8 i);
#define List_RemoveHead(list_)	List_RemoveSide((list_), 0)
#define List_RemoveTail(list_)	List_RemoveSide((list_), 1)

void List_RemoveAt(struct list_stru *list, void *node);
void List_RemoveAll(struct list_stru *list);

#ifdef CONFIG_DEBUG
UINT32 List_SCount(struct list_stru *list);
void *_List_SNodeNew(UINT32 len);
void List_SAddTail(struct list_stru *list, void *node);
void List_SAddHead(struct list_stru *list, void *node);
void *List_SInsertAt(struct list_stru *list, void *pos, void *node, UINT32 len);
void *List_SRemoveHead(struct list_stru *list);
void List_SRemoveAll(struct list_stru *list);
void *List_SRemoveAtNext(struct list_stru *list, void *prev);

typedef void (List_QEnumCbk)(void *node, void *context);

void *_List_QNodeNew(UINT32 len);/* DONOT use this, see below */
void List_QAddLeft(void *pos, void *node);
void List_QAddRight(void *pos, void *node);
void List_QAddHead(void *father, void *node);
void List_QAddTail(void *father, void *node);
void *List_QRemoveHead(void *father);
void *List_QRemoveTail(void *father);
void List_QRemoveAt(void *node);
void List_QRemoveAll(void *father);
void List_QEnum(void *root, void *cbk, void *context);
void *List_QBack2Root(void *node);
void *List_QBack2FirstChild(void *node);

#ifdef CONFIG_MEMORY_LEAK_DETECT
	#define List_SNodeNew(l)	DBG_Memory_LeakNew(_List_SNodeNew(l), sizeof(void *)/* offset Patch */, l/* Not include header */, MEMORY_LEAK_POSINFO)
	#define List_QNodeNew(l)	DBG_Memory_LeakNew(_List_QNodeNew(l), (sizeof(void *) << 2)/* offset Patch */, l/* Not include header */, MEMORY_LEAK_POSINFO)
#else /* CONFIG_MEMORY_LEAK_DETECT */
	#define List_SNodeNew(l)	_List_SNodeNew(l)
	#define List_QNodeNew(l)	_List_QNodeNew(l)
#endif /* CONFIG_MEMORY_LEAK_DETECT */
#endif /* CONFIG_DEBUG */

#ifdef CONFIG_MEMORY_LEAK_DETECT
	#define List_NodeNew(l)		DBG_Memory_LeakNew(_List_NodeNew(l), (sizeof(void *) << 1)/* offset Patch */, l/* Not include header */, MEMORY_LEAK_POSINFO)
#else
	#define List_NodeNew(l)		_List_NodeNew(l)
#endif

#endif

