uthash
(https://github.com/troydhanson/uthash) 같은 공개프로젝트에서 제공되는 utlist.h header를 한번쯤 보면 좋다. 물론 필자가 아래에 구현한 예제는 utlist.h 가 바라보는 pointer의 시점과 약간 다르지만 문맥은 거의 비슷하다.
/* 주어진 구조체 자료형 _m_type의 멤머변수 _m_member의 offset 을 반환 */
#define hwport_offsetof(_m_type,_m_member) ((size_t)(&((_m_type *)0)->_m_member))
#define hwport_peek_vector(m_cast,m_base,m_sign,m_offset) ((m_cast)((void *)(((hwport_uint8_t *)(m_base)) m_sign ((size_t)(m_offset)))))
#define hwport_peek_f(m_cast,m_base,m_offset) hwport_peek_vector(m_cast,m_base,+,m_offset)
/* pointer m_from으로부터 m_offset(byte단위) 위치의 값을 m_cast만큼 얻는다 */
#define hwport_peek_type(m_cast,m_from,m_offset) (*(hwport_peek_f(m_cast *,m_from,m_offset)))
/* pointer m_from으로부터 m_offset(byte단위) 위치에 m_value값을 m_cast만큼 저장 */
#define hwport_poke_type(m_cast,m_to,m_offset,m_value) do{hwport_peek_type(m_cast,m_to,m_offset)=(m_cast)(m_value);}while(0)
/* sort와 search에 필요한 자료의 조건을 판단하기 위한 callback 함수 pointer */
#if !defined(hwport_compare_linked_list_handler_t)
/* result = left - right; => 결과값이 음수인 경우 left 가 선두로 배치되는 운영방식 */
typedef int (*__hwport_compare_linked_list_handler_t)(void * /* s_left_element */, void * /* s_right_element */);
# define hwport_compare_linked_list_handler_t __hwport_compare_linked_list_handler_t
#endif
#define __hwport_singly_linked_list_prepend(_m_head_ptr,_m_tail_ptr,_m_element,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_poke_type(void *,_m_element,(_m_next_offset),*(_m_head_ptr));\
if(_sm_tail_ptr != ((void **)0)) {\
if((*(_m_head_ptr)) == ((void *)0)) { *_sm_tail_ptr = (_m_element); }\
}\
*(_m_head_ptr) = (_m_element);\
}while(0)
#define __hwport_singly_linked_list_append(_m_head_ptr,_m_tail_ptr,_m_element,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
if(_sm_tail_ptr != ((void **)0)) {\
if((*_sm_tail_ptr) == ((void *)0)) { *(_m_head_ptr) = (_m_element); }\
else { hwport_poke_type(void *,*_sm_tail_ptr,(_m_next_offset),(_m_element)); }\
*_sm_tail_ptr = (_m_element);\
}\
else if((*(_m_head_ptr)) == ((void *)0)) { *(_m_head_ptr) = (_m_element); }\
else {\
void *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) { break; }\
_sm_trace = _sm_next;\
}\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_element));\
}\
}while(0)
#define __hwport_singly_linked_list_delete(_m_head_ptr,_m_tail_ptr,_m_element,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
if((*(_m_head_ptr)) == (_m_element)) {\
*(_m_head_ptr) = hwport_peek_type(void *,(_m_element),(_m_next_offset));\
if(_sm_tail_ptr != ((void **)0)) {\
if((*(_m_tail_ptr)) == (_m_element)) { *_sm_tail_ptr = (void *)0; }\
}\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
}\
else {\
void *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) { break; }\
if(_sm_next == ((void *)(_m_element))) {\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),hwport_peek_type(void *,(_m_element),(_m_next_offset)));\
if(_sm_tail_ptr != ((void **)0)) {\
if((*_sm_tail_ptr) == (_m_element)) { *_sm_tail_ptr = _sm_trace; }\
}\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
break;\
}\
_sm_trace = _sm_next;\
}\
}\
}while(0)
#define __hwport_singly_linked_list_replace(_m_head_ptr,_m_tail_ptr,_m_element,_m_new_element,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),hwport_peek_type(void *,(_m_element),(_m_next_offset)));\
if((*(_m_head_ptr)) == (_m_element)) {\
*(_m_head_ptr) = (_m_new_element);\
if(_sm_tail_ptr != ((void **)0)) {\
if((*(_m_tail_ptr)) == (_m_element)) { *_sm_tail_ptr = (_m_new_element); }\
}\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
}\
else {\
void *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) { break; }\
if(_sm_next == ((void *)(_m_element))) {\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_new_element));\
if(_sm_tail_ptr != ((void **)0)) {\
if((*_sm_tail_ptr) == (_m_element)) { *_sm_tail_ptr = (_m_new_element); }\
}\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
break;\
}\
_sm_trace = _sm_next;\
}\
}\
}while(0)
#define __hwport_singly_linked_list_insert(_m_head_ptr,_m_tail_ptr,_m_element,_m_new_element,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
(void)_sm_tail_ptr;\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(_m_element));\
if((*(_m_head_ptr)) == (_m_element)) { *(_m_head_ptr) = (_m_new_element); }\
else {\
void *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) { break; }\
if(_sm_next == ((void *)(_m_element))) {\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_new_element));\
break;\
}\
_sm_trace = _sm_next;\
}\
}\
}while(0)
#define __hwport_singly_linked_list_sort_insert(_m_head_ptr,_m_tail_ptr,_m_new_element,_m_next_offset,_m_compare_handler) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_compare_linked_list_handler_t _sm_compare_handler = (_m_compare_handler);\
if((*(_m_head_ptr)) == ((void *)0)) {\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(void *)0);\
*(_m_head_ptr) = (_m_new_element);\
if(_sm_tail_ptr != ((void **)0)) { *(_sm_tail_ptr) = (_m_new_element); }\
}\
else {\
void *_sm_prev, *_sm_next, *_sm_trace;\
for(_sm_prev = (void *)0, _sm_trace = (*(_m_head_ptr));;) {\
if((*_sm_compare_handler)((_m_new_element),_sm_trace) < 0) {\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),_sm_trace);\
if(_sm_prev == ((void *)0)) { *(_m_head_ptr) = (_m_new_element); }\
else { hwport_poke_type(void *,_sm_prev,(_m_next_offset),(_m_new_element)); }\
break;\
}\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) {\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(void *)0);\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_new_element));\
if(_sm_tail_ptr != ((void **)0)) { *(_sm_tail_ptr) = (_m_new_element); }\
break;\
}\
_sm_prev = _sm_trace;\
_sm_trace = _sm_next;\
}\
}\
}while(0)
#define __hwport_singly_linked_list_sort(_m_head_ptr,_m_tail_ptr,_m_next_offset,_m_compare_handler) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
if((*(_m_head_ptr)) != ((void *)0)) {\
void *_sm_trace, *_sm_trace_prev, *_sm_trace_next, *_sm_trace_next_next;\
int _sm_is_swapped;\
do {\
_sm_is_swapped = 0; _sm_trace = *(_m_head_ptr); _sm_trace_prev = (void *)0;\
for(;;) {\
_sm_trace_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_trace_next == ((void *)0)) { break; }\
if((_m_compare_handler)(_sm_trace,_sm_trace_next) > 0) {\
_sm_is_swapped = 1;\
_sm_trace_next_next = hwport_peek_type(void *,_sm_trace_next,(_m_next_offset));\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),_sm_trace_next_next);\
hwport_poke_type(void *,_sm_trace_next,(_m_next_offset),_sm_trace);\
if(_sm_trace_prev != ((void *)0)) { hwport_poke_type(void *,_sm_trace_prev,(_m_next_offset),_sm_trace_next); }\
_sm_trace_prev = _sm_trace_next;\
if((*(_m_head_ptr)) == _sm_trace) { *(_m_head_ptr) = _sm_trace_next; }\
if(_sm_tail_ptr != ((void **)0)) {\
if(_sm_trace_next_next == ((void *)0)) { *_sm_tail_ptr = _sm_trace; }\
}\
}\
else { _sm_trace_prev = _sm_trace; _sm_trace = _sm_trace_next; }\
}\
}while(_sm_is_swapped != 0);\
}\
}while(0)
#define __hwport_doubly_linked_list_prepend(_m_head_ptr,_m_tail_ptr,_m_element,_m_prev_offset,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_poke_type(void *,_m_element,(_m_prev_offset),(void *)0);\
hwport_poke_type(void *,_m_element,(_m_next_offset),*(_m_head_ptr));\
if((*(_m_head_ptr)) != ((void *)0)) { hwport_poke_type(void *,*(_m_head_ptr),(_m_prev_offset),(_m_element)); }\
if(_sm_tail_ptr != ((void **)0)) {\
if((*(_m_head_ptr)) == ((void *)0)) { *_sm_tail_ptr = (_m_element); }\
}\
*(_m_head_ptr) = (_m_element);\
}while(0)
#define __hwport_doubly_linked_list_append(_m_head_ptr,_m_tail_ptr,_m_element,_m_prev_offset,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
if(_sm_tail_ptr != ((void **)0)) {\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),*_sm_tail_ptr);\
if((*_sm_tail_ptr) == ((void *)0)) { *(_m_head_ptr) = (_m_element); }\
else { hwport_poke_type(void *,*_sm_tail_ptr,(_m_next_offset),(_m_element)); }\
*_sm_tail_ptr = (_m_element);\
}\
else if((*(_m_head_ptr)) == ((void *)0)) {\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),(void *)0);\
*(_m_head_ptr) = (_m_element);\
}\
else {\
void *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) { break; }\
_sm_trace = _sm_next;\
}\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),_sm_trace);\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_element));\
}\
}while(0)
#define __hwport_doubly_linked_list_delete(_m_head_ptr,_m_tail_ptr,_m_element,_m_prev_offset,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
void *_sm_prev = hwport_peek_type(void *,(_m_element),(_m_prev_offset)), *_sm_next = hwport_peek_type(void *,(_m_element),(_m_next_offset));\
if(_sm_prev == ((void *)0)) { *(_m_head_ptr) = _sm_next; }\
else { hwport_poke_type(void *,_sm_prev,(_m_next_offset),_sm_next); }\
if(_sm_next == ((void *)0)) {\
if(_sm_tail_ptr != ((void **)0)) { *_sm_tail_ptr = _sm_prev; }\
}\
else { hwport_poke_type(void *,_sm_next,(_m_prev_offset),_sm_prev); }\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),(void *)0);\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
}while(0)
#define __hwport_doubly_linked_list_replace(_m_head_ptr,_m_tail_ptr,_m_element,_m_new_element,_m_prev_offset,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
void *_sm_prev = hwport_peek_type(void *,(_m_element),(_m_prev_offset)), *_sm_next = hwport_peek_type(void *,(_m_element),(_m_next_offset));\
hwport_poke_type(void *,(_m_new_element),(_m_prev_offset),_sm_prev);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),_sm_next);\
if(_sm_prev == ((void *)0)) { *(_m_head_ptr) = (_m_new_element); }\
else { hwport_poke_type(void *,_sm_prev,(_m_next_offset),(_m_new_element)); }\
if(_sm_next == ((void *)0)) {\
if(_sm_tail_ptr != ((void **)0)) { *_sm_tail_ptr = (_m_new_element); }\
}\
else { hwport_poke_type(void *,_sm_next,(_m_prev_offset),(_m_new_element)); }\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),(void *)0);\
hwport_poke_type(void *,(_m_element),(_m_next_offset),(void *)0);\
}while(0)
#define __hwport_doubly_linked_list_insert(_m_head_ptr,_m_tail_ptr,_m_element,_m_new_element,_m_prev_offset,_m_next_offset) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
void *_sm_prev = hwport_peek_type(void *,(_m_element),(_m_prev_offset));\
(void)_sm_tail_ptr;\
hwport_poke_type(void *,(_m_element),(_m_prev_offset),(_m_new_element));\
hwport_poke_type(void *,(_m_new_element),(_m_prev_offset),_sm_prev);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(_m_element));\
if(_sm_prev == ((void *)0)) { *(_m_head_ptr) = (_m_new_element); }\
else { hwport_poke_type(void *,_sm_prev,(_m_next_offset),(_m_new_element)); }\
}while(0)
#define __hwport_doubly_linked_list_sort_insert(_m_head_ptr,_m_tail_ptr,_m_new_element,_m_prev_offset,_m_next_offset,_m_compare_handler) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
hwport_compare_linked_list_handler_t _sm_compare_handler = (_m_compare_handler);\
if((*(_m_head_ptr)) == ((void *)0)) {\
hwport_poke_type(void *,(_m_new_element),(_m_prev_offset),(void *)0);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(void *)0);\
*(_m_head_ptr) = (_m_new_element);\
if(_sm_tail_ptr != ((void **)0)) { *(_sm_tail_ptr) = (_m_new_element); }\
}\
else {\
void *_sm_prev, *_sm_next, *_sm_trace;\
for(_sm_trace = (*(_m_head_ptr));;) {\
if((*_sm_compare_handler)((_m_new_element),_sm_trace) < 0) {\
_sm_prev = hwport_peek_type(void *,_sm_trace,(_m_prev_offset));\
hwport_poke_type(void *,(_m_new_element),(_m_prev_offset),_sm_prev);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),_sm_trace);\
if(_sm_prev == ((void *)0)) { *(_m_head_ptr) = (_m_new_element); }\
else { hwport_poke_type(void *,_sm_prev,(_m_next_offset),(_m_new_element)); }\
hwport_poke_type(void *,_sm_trace,(_m_prev_offset),(_m_new_element));\
break;\
}\
_sm_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_next == ((void *)0)) {\
hwport_poke_type(void *,(_m_new_element),(_m_prev_offset),_sm_trace);\
hwport_poke_type(void *,(_m_new_element),(_m_next_offset),(void *)0);\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),(_m_new_element));\
if(_sm_tail_ptr != ((void **)0)) { *(_sm_tail_ptr) = (_m_new_element); }\
break;\
}\
_sm_trace = _sm_next;\
}\
}\
}while(0)
#define __hwport_doubly_linked_list_sort(_m_head_ptr,_m_tail_ptr,_m_prev_offset,_m_next_offset,_m_compare_handler) \
do {\
void **_sm_tail_ptr = (void **)(_m_tail_ptr);\
if((*(_m_head_ptr)) != ((void *)0)) {\
void *_sm_trace, *_sm_trace_prev, *_sm_trace_next, *_sm_trace_next_next;\
int _sm_is_swapped;\
do {\
_sm_is_swapped = 0; _sm_trace = *(_m_head_ptr); _sm_trace_prev = (void *)0;\
for(;;) {\
_sm_trace_next = hwport_peek_type(void *,_sm_trace,(_m_next_offset));\
if(_sm_trace_next == ((void *)0)) { break; }\
if((_m_compare_handler)(_sm_trace,_sm_trace_next) > 0) {\
_sm_is_swapped = 1;\
_sm_trace_next_next = hwport_peek_type(void *,_sm_trace_next,(_m_next_offset));\
if(_sm_trace_next_next != ((void *)0)) { hwport_poke_type(void *,_sm_trace_next_next,(_m_prev_offset),_sm_trace); }\
hwport_poke_type(void *,_sm_trace,(_m_next_offset),_sm_trace_next_next);\
hwport_poke_type(void *,_sm_trace,(_m_prev_offset),_sm_trace_next);\
hwport_poke_type(void *,_sm_trace_next,(_m_next_offset),_sm_trace);\
hwport_poke_type(void *,_sm_trace_next,(_m_prev_offset),_sm_trace_prev);\
if(_sm_trace_prev != ((void *)0)) { hwport_poke_type(void *,_sm_trace_prev,(_m_next_offset),_sm_trace_next); }\
_sm_trace_prev = _sm_trace_next;\
if((*(_m_head_ptr)) == _sm_trace) { *(_m_head_ptr) = _sm_trace_next; }\
if(_sm_tail_ptr != ((void **)0)) {\
if(_sm_trace_next_next == ((void *)0)) { *_sm_tail_ptr = _sm_trace; }\
}\
}\
else { _sm_trace_prev = _sm_trace; _sm_trace = _sm_trace_next; }\
}\
}while(_sm_is_swapped != 0);\
}\
}while(0);
/* ... */
/* ... */
/* ... */
/* ... */
/* ... */
/* ... */
static int __hwport_compare(void *s_left, void *s_right)
{
return(hwport_strcmp(hwport_peek_type(char *, s_left, 0), hwport_peek_type(char *, s_right, 0));
}
static ssize_t hwport_linked_list_index(void **s_head_or_tail_ptr, void *s_element, size_t s_next_or_prev_offset)
{
ssize_t s_index;
void *s_trace;
for(s_index = (ssize_t)0, s_trace = (*s_head_or_tail_ptr);s_trace != ((void *)0);s_trace = hwport_peek_type(void *, s_trace, s_next_or_prev_offset), s_index++) {
if(s_trace == s_element) {
return(s_index);
}
}
return((ssize_t)(-1));
}
static ssize_t hwport_linked_list_count(void **s_head_or_tail_ptr, size_t s_next_or_prev_offset, const char *s_file)
{
ssize_t s_index;
void *s_trace;
for(s_index = (ssize_t)0, s_trace = (*s_head_or_tail_ptr);s_trace != ((void *)0);s_trace = hwport_peek_type(void *, s_trace, s_next_or_prev_offset), s_index++);
return(s_index);
}
struct hwport_singly_linked_list_test_ts {
const char *m_string;
struct hwport_singly_linked_list_test_ts *m_next;
} *s_head = (struct hwport_singly_linked_list_test_ts *)0, *s_tail = (struct hwport_singly_linked_list_test_ts *)0, s_node[6], *s_trace;
size_t s_next_offset = hwport_offsetof(struct hwport_singly_linked_list_test_ts, m_next);
s_node[0].m_string = "hello";
s_node[1].m_string = "a world";
s_node[2].m_string = "test";
s_node[3].m_string = "singlylist";
s_node[4].m_string = "insertitem";
s_node[5].m_string = "insertitem2";
hwport_singly_linked_list_append(&s_head, &s_tail, &s_node[0], s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[0])));
hwport_singly_linked_list_append(&s_head, &s_tail, &s_node[1], s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[1])));
hwport_singly_linked_list_append(&s_head, &s_tail, &s_node[2], s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[2])));
hwport_singly_linked_list_prepend(&s_head, &s_tail, &s_node[3], s_next_offset);
ASSERT((s_head == (&s_node[3])) && (s_tail == (&s_node[2])));
hwport_singly_linked_list_delete(&s_head, &s_tail, &s_node[2], s_next_offset);
ASSERT((s_head == (&s_node[3])) && (s_tail == (&s_node[1])));
ASSERT(s_node[2].m_next == ((struct hwport_singly_linked_list_test_ts *)0));
hwport_singly_linked_list_replace(&s_head, &s_tail, &s_node[0], &s_node[2], s_next_offset);
ASSERT(s_node[0].m_next == ((struct hwport_singly_linked_list_test_ts *)0));
hwport_singly_linked_list_replace(&s_head, &s_tail, &s_node[2], &s_node[0], s_next_offset);
ASSERT(s_node[2].m_next == ((struct hwport_singly_linked_list_test_ts *)0));
hwport_singly_linked_list_insert(&s_head, &s_tail, &s_node[0], &s_node[4], s_next_offset);
hwport_singly_linked_list_insert(&s_head, &s_tail, &s_node[3], &s_node[5], s_next_offset);
ASSERT((s_head == (&s_node[5])) && (s_tail == (&s_node[1])));
for(s_trace = s_head;s_trace != ((struct hwport_singly_linked_list_test_ts *)0);s_trace = s_trace->m_next) {
(void)printf("forward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
hwport_singly_linked_list_sort(&s_head, &s_tail, s_next_offset, (hwport_compare_linked_list_handler_t)__hwport_compare);
for(s_trace = s_head;s_trace != ((struct hwport_singly_linked_list_test_ts *)0);s_trace = s_trace->m_next) {
(void)printf("sorted forward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
s_trace = s_tail;
(void)printf("sorted tail data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
(void)printf("total singly linked list : %ld\n", (long)hwport_linked_list_count(&s_head, s_next_offset));
struct hwport_doubly_linked_list_test_ts {
const char *m_string;
struct hwport_doubly_linked_list_test_ts *m_prev;
struct hwport_doubly_linked_list_test_ts *m_next;
} *s_head = (struct hwport_doubly_linked_list_test_ts *)0, *s_tail = (struct hwport_doubly_linked_list_test_ts *)0, s_node[6], *s_trace;
size_t s_prev_offset = hwport_offsetof(struct hwport_doubly_linked_list_test_ts, m_prev);
size_t s_next_offset = hwport_offsetof(struct hwport_doubly_linked_list_test_ts, m_next);
s_node[0].m_string = "hello";
s_node[1].m_string = "a world";
s_node[2].m_string = "test";
s_node[3].m_string = "doublylist";
s_node[4].m_string = "insertitem";
s_node[5].m_string = "insertitem2";
hwport_doubly_linked_list_append(&s_head, &s_tail, &s_node[0], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[0])));
hwport_doubly_linked_list_append(&s_head, &s_tail, &s_node[1], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[1])));
hwport_doubly_linked_list_append(&s_head, &s_tail, &s_node[2], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[0])) && (s_tail == (&s_node[2])));
hwport_doubly_linked_list_prepend(&s_head, &s_tail, &s_node[3], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[3])) && (s_tail == (&s_node[2])));
hwport_doubly_linked_list_delete(&s_head, &s_tail, &s_node[2], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[3])) && (s_tail == (&s_node[1])));
ASSERT(s_node[2].m_next == ((struct hwport_doubly_linked_list_test_ts *)0));
hwport_doubly_linked_list_replace(&s_head, &s_tail, &s_node[0], &s_node[2], s_prev_offset, s_next_offset);
ASSERT(s_node[0].m_next == ((struct hwport_doubly_linked_list_test_ts *)0));
hwport_doubly_linked_list_replace(&s_head, &s_tail, &s_node[2], &s_node[0], s_prev_offset, s_next_offset);
ASSERT(s_node[2].m_next == ((struct hwport_doubly_linked_list_test_ts *)0));
hwport_doubly_linked_list_insert(&s_head, &s_tail, &s_node[0], &s_node[4], s_prev_offset, s_next_offset);
hwport_doubly_linked_list_insert(&s_head, &s_tail, &s_node[3], &s_node[5], s_prev_offset, s_next_offset);
ASSERT((s_head == (&s_node[5])) && (s_tail == (&s_node[1])));
for(s_trace = s_head;s_trace != ((struct hwport_doubly_linked_list_test_ts *)0);s_trace = s_trace->m_next) {
(void)printf("forward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
for(s_trace = s_tail;s_trace != ((struct hwport_doubly_linked_list_test_ts *)0);s_trace = s_trace->m_prev) {
(void)printf("backward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
hwport_doubly_linked_list_sort(&s_head, &s_tail, s_prev_offset, s_next_offset, (hwport_compare_linked_list_handler_t)__hwport_compare);
for(s_trace = s_head;s_trace != ((struct hwport_doubly_linked_list_test_ts *)0);s_trace = s_trace->m_next) {
(void)printf("sorted forward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
for(s_trace = s_tail;s_trace != ((struct hwport_doubly_linked_list_test_ts *)0);s_trace = s_trace->m_prev) {
(void)printf("sorted backward data[%ld]: \"%s\"\n", (long)hwport_linked_list_index(&s_head, s_trace, s_next_offset), s_trace->m_string);
}
(void)printf("total doubly linked list : %ld\n", (long)hwport_linked_list_count(&s_head, s_next_offset));
(void)printf("total doubly linked list(r) : %ld\n", (long)hwport_linked_list_count(&s_tail, s_prev_offset));