Commit a04eeb44 authored by jehan's avatar jehan
Browse files

use lists and logs from bctoolbox

parent 6e0c52b0
......@@ -18,42 +18,37 @@
#ifndef BELLE_SIP_LIST_H_
#define BELLE_SIP_LIST_H_
BELLE_SIP_BEGIN_DECLS
struct _belle_sip_list {
struct _belle_sip_list *next;
struct _belle_sip_list *prev;
void *data;
};
typedef struct _belle_sip_list belle_sip_list_t;
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_append(belle_sip_list_t * elem, void * data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_prepend(belle_sip_list_t * elem, void * data);
BELLESIP_EXPORT belle_sip_list_t* belle_sip_list_prepend_link(belle_sip_list_t* elem, belle_sip_list_t *new_elem);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_last_elem(const belle_sip_list_t *l);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_free(belle_sip_list_t * elem);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_concat(belle_sip_list_t * first, belle_sip_list_t * second);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_remove(belle_sip_list_t * first, void *data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_pop_front(belle_sip_list_t *list, void **front_data);
BELLESIP_EXPORT int belle_sip_list_size(const belle_sip_list_t * first);
BELLESIP_EXPORT void belle_sip_list_for_each(const belle_sip_list_t * list, void (*func)(void *));
BELLESIP_EXPORT void belle_sip_list_for_each2(const belle_sip_list_t * list, void (*func)(void *, void *), void *user_data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_remove_link(belle_sip_list_t * list, belle_sip_list_t * elem);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_delete_link(belle_sip_list_t * list, belle_sip_list_t * elem);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_find(belle_sip_list_t * list, void *data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_free(belle_sip_list_t *list);
/*frees list elements and associated data, using the supplied function pointer*/
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_free_with_data(belle_sip_list_t *list, void (*freefunc)(void*));
typedef int (*belle_sip_compare_func)(const void *, const void*);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_find_custom(const belle_sip_list_t * list, belle_sip_compare_func cmp, const void *user_data);
BELLESIP_EXPORT void * belle_sip_list_nth_data(const belle_sip_list_t * list, int index);
BELLESIP_EXPORT int belle_sip_list_position(const belle_sip_list_t * list, belle_sip_list_t * elem);
BELLESIP_EXPORT int belle_sip_list_index(const belle_sip_list_t * list, void *data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_insert_sorted(belle_sip_list_t * list, void *data, belle_sip_compare_func cmp);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_insert(belle_sip_list_t * list, belle_sip_list_t * before, void *data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_copy(const belle_sip_list_t * list);
/*copy list elements and associated data, using the supplied function pointer*/
BELLESIP_EXPORT belle_sip_list_t* belle_sip_list_copy_with_data(const belle_sip_list_t* list, void* (*copyfunc)(void*));
BELLE_SIP_END_DECLS
#include "bctoolbox/list.h"
typedef struct _bctbx_list belle_sip_list_t;
#define belle_sip_list_new bctbx_list_new
#define belle_sip_list_append bctbx_list_append
#define belle_sip_list_prepend bctbx_list_prepend
#define belle_sip_list_prepend_link bctbx_list_prepend_link
#define belle_sip_list_last_elem bctbx_list_last_elem
#define belle_sip_list_free bctbx_list_free
#define belle_sip_list_concat bctbx_list_concat
#define belle_sip_list_remove bctbx_list_remove
#define belle_sip_list_pop_front bctbx_list_pop_front
#define belle_sip_list_size bctbx_list_size
#define belle_sip_list_for_each bctbx_list_for_each
#define belle_sip_list_for_each2 bctbx_list_for_each2
#define belle_sip_list_remove_link bctbx_list_remove_link
#define belle_sip_list_delete_link bctbx_list_delete_link
#define belle_sip_list_find bctbx_list_find
#define belle_sip_list_free bctbx_list_free
#define belle_sip_list_free_with_data bctbx_list_free_with_data
#define belle_sip_compare_func bctbx_compare_func
#define belle_sip_list_find_custom bctbx_list_find_custom
#define belle_sip_list_nth_data bctbx_list_nth_data
#define belle_sip_list_position bctbx_list_position
#define belle_sip_list_index bctbx_list_index
#define belle_sip_list_insert_sorted bctbx_list_insert_sorted
#define belle_sip_list_insert bctbx_list_insert
#define belle_sip_list_copy bctbx_list_copy
#define belle_sip_list_copy_with_data bctbx_list_copy_with_data
#endif /* BELLE_SIP_LIST_H_ */
......@@ -21,6 +21,7 @@
#include "belle-sip/defs.h"
#include "belle-sip/utils.h"
#include "belle-sip/list.h"
/*
* typedefs, macros and functions for object definition and manipulation.
......@@ -151,8 +152,8 @@ struct _belle_sip_object{
char* name;
struct weak_ref *weak_refs;
struct belle_sip_object_pool *pool;
struct _belle_sip_list *pool_iterator;
struct _belle_sip_list *data_store;
belle_sip_list_t *pool_iterator;
belle_sip_list_t *data_store;
};
......
......@@ -25,14 +25,25 @@
#include <errno.h>
#include "belle-sip/defs.h"
#ifdef BCTBX_LOG_DOMAIN
#undef BCTBX_LOG_DOMAIN
#endif
#ifndef BELLE_SIP_LOG_DOMAIN
#define BELLE_SIP_LOG_DOMAIN "belle-sip"
#endif
#define BCTBX_LOG_DOMAIN BELLE_SIP_LOG_DOMAIN
#include "bctoolbox/logging.h"
BELLE_SIP_BEGIN_DECLS
BELLESIP_EXPORT void *belle_sip_malloc(size_t size);
BELLESIP_EXPORT void *belle_sip_malloc0(size_t size);
BELLESIP_EXPORT void *belle_sip_realloc(void *ptr, size_t size);
BELLESIP_EXPORT void belle_sip_free(void *ptr);
BELLESIP_EXPORT char * belle_sip_strdup(const char *s);
#define belle_sip_malloc bctbx_malloc
#define belle_sip_malloc0 bctbx_malloc0
#define belle_sip_realloc bctbx_realloc
#define belle_sip_free bctbx_free
#define belle_sip_strdup bctbx_strdup
BELLE_SIP_END_DECLS
......@@ -40,17 +51,15 @@ BELLE_SIP_END_DECLS
/* logging api */
/***************/
typedef enum {
BELLE_SIP_LOG_FATAL=1,
BELLE_SIP_LOG_ERROR=1<<1,
BELLE_SIP_LOG_WARNING=1<<2,
BELLE_SIP_LOG_MESSAGE=1<<3,
BELLE_SIP_LOG_DEBUG=1<<4,
BELLE_SIP_LOG_END=1<<5
} belle_sip_log_level;
#define BELLE_SIP_LOG_FATAL BCTBX_LOG_FATAL
#define BELLE_SIP_LOG_ERROR BCTBX_LOG_ERROR
#define BELLE_SIP_LOG_WARNING BCTBX_LOG_WARNING
#define BELLE_SIP_LOG_MESSAGE BCTBX_LOG_MESSAGE
#define BELLE_SIP_LOG_DEBUG BCTBX_LOG_DEBUG
#define BELLE_SIP_LOG_END BCTBX_LOG_END
#define belle_sip_log_level BctbxLogLevel
typedef void (*belle_sip_log_function_t)(belle_sip_log_level lev, const char *fmt, va_list args);
#define belle_sip_log_function_t BctoolboxLogFunc
typedef enum {
......@@ -68,31 +77,10 @@ typedef enum {
BELLE_SIP_BEGIN_DECLS
BELLESIP_VAR_EXPORT belle_sip_log_function_t belle_sip_logv_out;
BELLESIP_VAR_EXPORT unsigned int __belle_sip_log_mask;
#define belle_sip_log_level_enabled(level) (__belle_sip_log_mask & (level))
#if !defined(_WIN32) && !defined(_WIN32_WCE)
static BELLESIP_INLINE void belle_sip_logv(belle_sip_log_level level, const char *fmt, va_list args) {
if (belle_sip_logv_out!=NULL && belle_sip_log_level_enabled(level))
belle_sip_logv_out(level,fmt,args);
if (level==BELLE_SIP_LOG_FATAL) abort();
}
#else
BELLESIP_EXPORT void belle_sip_logv(int level, const char *fmt, va_list args);
#endif
#define belle_sip_log_level_enabled(level) bctbx_log_level_enabled(BELLE_SIP_LOG_DOMAIN,level)
#ifdef BELLE_SIP_DEBUG_MODE
static BELLESIP_INLINE void belle_sip_debug(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_DEBUG, fmt, args);
va_end (args);
}
#define belle_sip_deb(...) bctbx_debug(...)
#else
#define belle_sip_debug(...)
......@@ -107,61 +95,27 @@ static BELLESIP_INLINE void belle_sip_debug(const char *fmt,...)
#else
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(2,3) belle_sip_log(belle_sip_log_level lev, const char *fmt,...){
va_list args;
va_start (args, fmt);
belle_sip_logv(lev, fmt, args);
va_end (args);
}
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_message(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_MESSAGE, fmt, args);
va_end (args);
}
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_warning(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_WARNING, fmt, args);
va_end (args);
}
#define belle_sip_log bctbx_log
#define belle_sip_message bctbx_message
#define belle_sip_warning bctbx_warning
#define belle_sip_error bctbx_error
#define belle_sip_fatal bctbx_fatal
#define belle_sip_logv bctbx_logv
#endif
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_error(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_ERROR, fmt, args);
va_end (args);
}
static BELLESIP_INLINE void BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_fatal(const char *fmt,...)
{
va_list args;
va_start (args, fmt);
belle_sip_logv(BELLE_SIP_LOG_FATAL, fmt, args);
va_end (args);
}
BELLESIP_EXPORT void belle_sip_set_log_file(FILE *file);
BELLESIP_EXPORT void belle_sip_set_log_handler(belle_sip_log_function_t func);
BELLESIP_EXPORT belle_sip_log_function_t belle_sip_get_log_handler(void);
#define belle_sip_set_log_file bctbx_set_log_file
#define belle_sip_set_log_handler bctbx_set_log_handler
#define belle_sip_get_log_handler bctbx_get_log_handler
BELLESIP_EXPORT char * BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_strdup_printf(const char *fmt,...);
BELLESIP_EXPORT char * belle_sip_strcat_vprintf(char* dst, const char *fmt, va_list ap);
BELLESIP_EXPORT char * BELLE_SIP_CHECK_FORMAT_ARGS(2,3) belle_sip_strcat_printf(char* dst, const char *fmt,...);
#define belle_sip_strdup_printf bctbx_strdup_printf
#define belle_sip_strcat_vprintf bctbx_strcat_vprintf
#define belle_sip_strcat_printf bctbx_strcat_printf
BELLESIP_EXPORT belle_sip_error_code BELLE_SIP_CHECK_FORMAT_ARGS(4,5) belle_sip_snprintf(char *buff, size_t buff_size, size_t *offset, const char *fmt, ...);
BELLESIP_EXPORT belle_sip_error_code belle_sip_snprintf_valist(char *buff, size_t buff_size, size_t *offset, const char *fmt, va_list args);
BELLESIP_EXPORT void belle_sip_set_log_level(int level);
#define belle_sip_set_log_level(level) bctbx_set_log_level(BELLE_SIP_LOG_DOMAIN,level);
BELLESIP_EXPORT char * belle_sip_random_token(char *ret, size_t size);
......
......@@ -284,7 +284,7 @@ struct belle_sip_dict {
#define MAX(a,b) ((a)>(b) ? (a) : (b))
BELLESIP_INTERNAL_EXPORT char * belle_sip_concat (const char *str, ...);
#define belle_sip_concat bctbx_concat
/*parameters accessors*/
......
......@@ -449,7 +449,7 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
next=elem->next;
if (!s->cancelled){
if (s->timeout > 0 && (__belle_sip_log_mask & BELLE_SIP_LOG_DEBUG)) {
if (s->timeout > 0 && belle_sip_log_level_enabled(BELLE_SIP_LOG_DEBUG)) {
/*to avoid too many traces*/
char *objdesc=belle_sip_object_to_string((belle_sip_object_t*)s);
belle_sip_debug("source %s notified revents=%u, timeout=%i",objdesc,revents,s->timeout);
......
......@@ -53,7 +53,10 @@ static void add_new_object(belle_sip_object_t *obj){
static void remove_free_object(belle_sip_object_t *obj){
if (belle_sip_leak_detector_enabled && !belle_sip_leak_detector_inhibited){
all_objects=_belle_sip_list_remove(all_objects,obj,FALSE); /*it may fail if the leak detector was inhibitted at the time the object was created*/
belle_sip_list_t* it;
it=belle_sip_list_find(all_objects,obj);
if (it)
all_objects = belle_sip_list_delete_link(all_objects,it); /*it may fail if the leak detector was inhibitted at the time the object was created*/
}
}
......@@ -304,7 +307,7 @@ static void belle_sip_object_data_destroy(void* data)
int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void* data, belle_sip_data_destroy destroy_func )
{
int ret = 0;
struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
belle_sip_list_t* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
if( entry == NULL){
......@@ -330,7 +333,7 @@ int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void*
void* belle_sip_object_data_get( belle_sip_object_t *obj, const char* name )
{
struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
belle_sip_list_t *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
return entry? entry->data : NULL;
......@@ -338,7 +341,7 @@ void* belle_sip_object_data_get( belle_sip_object_t *obj, const char* name )
int belle_sip_object_data_remove( belle_sip_object_t *obj, const char* name)
{
struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
belle_sip_list_t *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
if( entry ){
belle_sip_free(entry->name);
......@@ -357,7 +360,7 @@ int belle_sip_object_data_exists( const belle_sip_object_t *obj, const char* nam
void* belle_sip_object_data_grab( belle_sip_object_t* obj, const char* name)
{
struct _belle_sip_list* list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
belle_sip_list_t *list_entry = belle_sip_list_find_custom(obj->data_store, belle_sip_object_data_find, name);
struct belle_sip_object_data* entry = (list_entry)? list_entry->data : NULL;
void* data =NULL;
......@@ -385,7 +388,7 @@ void belle_sip_object_data_clone( const belle_sip_object_t* src, belle_sip_objec
void belle_sip_object_data_merge( const belle_sip_object_t* src, belle_sip_object_t* dst, belle_sip_data_clone clone_func)
{
struct _belle_sip_list* list = src->data_store;
belle_sip_list_t *list = src->data_store;
struct belle_sip_object_data* it = NULL;
void* cloned_data = NULL;
......
......@@ -33,122 +33,6 @@
#include <direct.h>
#endif
static FILE *__log_file=0;
/**
*@param file a FILE pointer where to output the belle logs.
*
**/
void belle_sip_set_log_file(FILE *file)
{
__log_file=file;
}
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args);
belle_sip_log_function_t belle_sip_logv_out=__belle_sip_logv_out;
/**
*@param func: your logging function, compatible with the OrtpLogFunc prototype.
*
**/
void belle_sip_set_log_handler(belle_sip_log_function_t func){
belle_sip_logv_out=func;
}
belle_sip_log_function_t belle_sip_get_log_handler(){
return belle_sip_logv_out;
}
unsigned int __belle_sip_log_mask=BELLE_SIP_LOG_WARNING|BELLE_SIP_LOG_ERROR|BELLE_SIP_LOG_FATAL;
/**
* @ param level: either BELLE_SIP_LOG_DEBUG, BELLE_SIP_LOG_MESSAGE, BELLE_SIP_LOG_WARNING, BELLE_SIP_LOG_ERROR
* BELLE_SIP_LOG_FATAL .
**/
void belle_sip_set_log_level(int level){
__belle_sip_log_mask=(level<<1)-1;
}
char * belle_sip_strdup_vprintf(const char *fmt, va_list ap)
{
/* Guess we need no more than 100 bytes. */
int n, size = 200;
char *p,*np;
#ifndef _WIN32
va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
#endif
if ((p = (char *) malloc (size)) == NULL)
return NULL;
while (1)
{
/* Try to print in the allocated space. */
#ifndef _WIN32
va_copy(cap,ap);
n = vsnprintf (p, size, fmt, cap);
va_end(cap);
#else
/*this works on 32 bits, luckily*/
n = vsnprintf (p, size, fmt, ap);
#endif
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
//printf("Reallocing space.\n");
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((np = (char *) realloc (p, size)) == NULL)
{
free(p);
return NULL;
}
else
{
p = np;
}
}
}
char *belle_sip_strdup_printf(const char *fmt,...){
char *ret;
va_list args;
va_start (args, fmt);
ret=belle_sip_strdup_vprintf(fmt, args);
va_end (args);
return ret;
}
char * belle_sip_strcat_vprintf(char* dst, const char *fmt, va_list ap){
char *ret;
unsigned long dstlen, retlen;
ret=belle_sip_strdup_vprintf(fmt, ap);
dstlen = strlen(dst);
retlen = strlen(ret);
if ((dst = belle_sip_realloc(dst, dstlen+retlen+1)) != NULL){
strncat(dst,ret,retlen);
dst[dstlen+retlen] = '\0';
belle_sip_free(ret);
return dst;
} else {
belle_sip_free(ret);
return NULL;
}
}
char *belle_sip_strcat_printf(char* dst, const char *fmt,...){
char *ret;
va_list args;
va_start (args, fmt);
ret=belle_sip_strcat_vprintf(dst, fmt, args);
va_end (args);
return ret;
}
belle_sip_error_code belle_sip_snprintf(char *buff, size_t buff_size, size_t *offset, const char *fmt, ...) {
belle_sip_error_code ret;
va_list args;
......@@ -179,16 +63,6 @@ belle_sip_error_code belle_sip_snprintf_valist(char *buff, size_t buff_size, siz
#define ENDLINE "\n"
#endif
#if defined(_WIN32) || defined(_WIN32_WCE)
void belle_sip_logv(int level, const char *fmt, va_list args)
{
if (belle_sip_logv_out!=NULL && belle_sip_log_level_enabled(level))
belle_sip_logv_out(level,fmt,args);
if ((level)==BELLE_SIP_LOG_FATAL) abort();
}
#endif
#ifdef _WIN32
static int belle_sip_gettimeofday (struct timeval *tv, void* tz)
{
......@@ -207,402 +81,7 @@ static int belle_sip_gettimeofday (struct timeval *tv, void* tz)
#define belle_sip_gettimeofday gettimeofday
#endif
static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args){
const char *lname="undef";
char *msg;
struct timeval tp;
struct tm *lt;
#ifndef _WIN32
struct tm tmstorage;
#endif
time_t curtime;
belle_sip_gettimeofday(&tp,NULL);
curtime=tp.tv_sec;
#ifdef _WIN32
lt = localtime(&curtime);
#else
lt = localtime_r(&curtime,&tmstorage);
#endif
if (__log_file==NULL) __log_file=stderr;
switch(lev){
case BELLE_SIP_LOG_DEBUG:
lname="debug";
break;
case BELLE_SIP_LOG_MESSAGE:
lname="message";
break;
case BELLE_SIP_LOG_WARNING:
lname="warning";
break;
case BELLE_SIP_LOG_ERROR:
lname="error";
break;
case BELLE_SIP_LOG_FATAL:
lname="fatal";
break;
default:
belle_sip_fatal("Bad level !");
}
msg=belle_sip_strdup_vprintf(fmt,args);
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
#ifndef _UNICODE
OutputDebugStringA(msg);
OutputDebugStringA("\r\n");
#else
{
int len=strlen(msg);
wchar_t *tmp=(wchar_t*)belle_sip_malloc0((len+1)*sizeof(wchar_t));
mbstowcs(tmp,msg,len);
OutputDebugStringW(tmp);
OutputDebugStringW(L"\r\n");
belle_sip_free(tmp);
}
#endif
#endif
fprintf(__log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(__log_file);
// fatal messages should go to stderr too, even if we are using a file since application will abort right after
if (__log_file != stderr && lev == BELLE_SIP_LOG_FATAL) {
fprintf(stderr,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg);
fflush(stderr);
}
free(msg);
}
belle_sip_list_t* belle_sip_list_new(void *data){
belle_sip_list_t* new_elem=belle_sip_new0(belle_sip_list_t);
new_elem->data=data;
return new_elem;
}
belle_sip_list_t* belle_sip_list_append_link(belle_sip_list_t* elem,belle_sip_list_t *new_elem){
belle_sip_list_t* it=elem;
if (elem==NULL) return new_elem;
if (new_elem==NULL) return elem;
while (it->next!=NULL) it=belle_sip_list_next(it);
it->next=new_elem;
new_elem->prev=it;
return elem;
}
belle_sip_list_t* belle_sip_list_append(belle_sip_list_t* elem, void * data){
belle_sip_list_t* new_elem=belle_sip_list_new(data);
return belle_sip_list_append_link(elem,new_elem);
}
belle_sip_list_t* belle_sip_list_prepend_link(belle_sip_list_t* elem, belle_sip_list_t *new_elem){
if (elem!=NULL) {
new_elem->next=elem;
elem->prev=new_elem;
}
return new_elem;
}
belle_sip_list_t* belle_sip_list_prepend(belle_sip_list_t* elem, void *data){
return belle_sip_list_prepend_link(elem,belle_sip_list_new(data));
}
belle_sip_list_t * belle_sip_list_last_elem(const belle_sip_list_t *l){
if (l==NULL) return NULL;
while(l->next){
l=l->next;
}
return (belle_sip_list_t*)l;
}
belle_sip_list_t* belle_sip_list_concat(belle_sip_list_t* first, belle_sip_list_t* second){
belle_sip_list_t* it=first;
if (it==NULL) return second;
if (second==NULL) return first;
while(it->next!=NULL) it=belle_sip_list_next(it);
it->next=second;
second->prev=it;
return first;
}
belle_sip_list_t* belle_sip_list_free(belle_sip_list_t* list){
belle_sip_list_t* elem = list;
belle_sip_list_t* tmp;
if (list==NULL) return NULL;
while(elem->next!=NULL) {
tmp = elem;
elem = elem->next;
belle_sip_free(tmp);
}
belle_sip_free(elem);
return NULL;
}
belle_sip_list_t * belle_sip_list_free_with_data(belle_sip_list_t *list, void (*freefunc)(void*)){
belle_sip_list_t* elem = list;
belle_sip_list_t* tmp;
if (list==NULL) return NULL;