Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjlib / include / pj / list_i.h
1 /* $Id$ */
2 /* 
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19  */
20
21
22 /* Internal */
23 PJ_INLINE(void) pj_link_node(pj_list_type *prev, pj_list_type *next)
24 {
25     ((pj_list*)prev)->next = next;
26     ((pj_list*)next)->prev = prev;
27 }
28
29 PJ_IDEF(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node)
30 {
31     ((pj_list*)node)->prev = pos;
32     ((pj_list*)node)->next = ((pj_list*)pos)->next;
33     ((pj_list*) ((pj_list*)pos)->next) ->prev = node;
34     ((pj_list*)pos)->next = node;
35 }
36
37
38 PJ_IDEF(void) pj_list_insert_before(pj_list_type *pos, pj_list_type *node)
39 {
40     pj_list_insert_after(((pj_list*)pos)->prev, node);
41 }
42
43
44 PJ_IDEF(void) pj_list_insert_nodes_after(pj_list_type *pos, pj_list_type *lst)
45 {
46     pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;
47     pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;
48
49     pj_link_node(pos, lst);
50     pj_link_node(lst_last, pos_next);
51 }
52
53 PJ_IDEF(void) pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst)
54 {
55     pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst);
56 }
57
58 PJ_IDEF(void) pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2)
59 {
60     if (!pj_list_empty(lst2)) {
61         pj_link_node(((pj_list*)lst1)->prev, ((pj_list*)lst2)->next);
62         pj_link_node(((pj_list*)lst2)->prev, lst1);
63         pj_list_init(lst2);
64     }
65 }
66
67 PJ_IDEF(void) pj_list_merge_first(pj_list_type *lst1, pj_list_type *lst2)
68 {
69     if (!pj_list_empty(lst2)) {
70         pj_link_node(((pj_list*)lst2)->prev, ((pj_list*)lst1)->next);
71         pj_link_node(((pj_list*)lst1), ((pj_list*)lst2)->next);
72         pj_list_init(lst2);
73     }
74 }
75
76 PJ_IDEF(void) pj_list_erase(pj_list_type *node)
77 {
78     pj_link_node( ((pj_list*)node)->prev, ((pj_list*)node)->next);
79
80     /* It'll be safer to init the next/prev fields to itself, to
81      * prevent multiple erase() from corrupting the list. See
82      * ticket #520 for one sample bug.
83      */
84     pj_list_init(node);
85 }
86
87
88 PJ_IDEF(pj_list_type*) pj_list_find_node(pj_list_type *list, pj_list_type *node)
89 {
90     pj_list *p = (pj_list *) ((pj_list*)list)->next;
91     while (p != list && p != node)
92         p = (pj_list *) p->next;
93
94     return p==node ? p : NULL;
95 }
96
97
98 PJ_IDEF(pj_list_type*) pj_list_search(pj_list_type *list, void *value,
99                         int (*comp)(void *value, const pj_list_type *node))
100 {
101     pj_list *p = (pj_list *) ((pj_list*)list)->next;
102     while (p != list && (*comp)(value, p) != 0)
103         p = (pj_list *) p->next;
104
105     return p==list ? NULL : p;
106 }
107
108
109 PJ_IDEF(pj_size_t) pj_list_size(const pj_list_type *list)
110 {
111     const pj_list *node = (const pj_list*) ((const pj_list*)list)->next;
112     pj_size_t count = 0;
113
114     while (node != list) {
115         ++count;
116         node = (pj_list*)node->next;
117     }
118
119     return count;
120 }
121