summaryrefslogtreecommitdiffstats
path: root/tinySAK/src/tsk_list.h
blob: bc0d4d46d315994435ccd03a4f11c448fdeb68d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/* Copyright (C) 2010-2013 Mamadou Diop.
* Copyright (C) 2013 Doubango Telecom <http://doubango.org>
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*	
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*	
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/

/**@file tsk_list.h
 * @brief Linked list. For more information about linked list you can check @ref _Page_TinySAK_AnsiC_Linked_List "this page".
 */
#ifndef _TINYSAK_LIST_H_
#define _TINYSAK_LIST_H_

#include "tinysak_config.h"
#include "tsk_mutex.h"
#include "tsk_object.h"

TSK_BEGIN_DECLS

#define TSK_LIST_IS_EMPTY(list)				((list) ? (!(list)->head) : tsk_true)
/**@ingroup tsk_list_group
* @def TSK_LIST_IS_EMPTY
* Checks if the the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" is empty or not.
* @param list The @ref tsk_list_t "list" to check.
* @return @ref tsk_true if the list is empty, othersise @ref tsk_false.
*/


/**@ingroup tsk_list_group
* @def TSK_LIST_IS_FIRST
* Checks whether the @a item is the first element in the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" or not.
* @param list The @ref tsk_list_t "list" to check.
* @param item The @ref tsk_list_item_t "item" to check.
* @return @ref tsk_true if the item is the first element in the list, othersise @ref tsk_false.
*/
/**@ingroup tsk_list_group
* @def TSK_LIST_IS_LAST
* Checks whether the @a item is the last element in the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" or not.
* @param list The @ref tsk_list_t "list" to check.
* @param item The @ref tsk_list_item_t "item" to check.
* @return @ref tsk_true if the item is the last element in the list, othersise @ref tsk_false.
*/
#define TSK_LIST_IS_FIRST(list, item)		((list) ? ((list)->head == item) : tsk_false)
#define TSK_LIST_IS_LAST(list, item)		((list) ? ((list)->tail == item) : tsk_false)

/**@ingroup tsk_list_group
* @def TSK_LIST_FIRST_DATA
* Gets the first data element in the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref tsk_list_t "list" from which to get the first data element.
* @return The first @ref tsk_object_t "data" element. The @ref tsk_object_t "data" element is a @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object.
*/
/**@ingroup tsk_list_group
* @def TSK_LIST_LAST_DATA
* Gets the last data element in the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref tsk_list_t "list" from which to get the last data element.
* @return The last @ref tsk_object_t "data" element. The @ref tsk_object_t "data" element is a @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object.
*/
#define TSK_LIST_FIRST_DATA(list)			(((list) && (list)->head) ? (list)->head->data : tsk_null)
#define TSK_LIST_LAST_DATA(list)			(((list) && (list)->tail) ? (list)->tail->data : tsk_null)

/**@ingroup tsk_list_group
* Item for @ref tsk_list_t "linked list". 
*/
typedef struct tsk_list_item_s
{
	TSK_DECLARE_OBJECT;
	void* data; /**< Opaque data. <b>Must</b> be a @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object. */
	struct tsk_list_item_s* next; /**< Next item. */
}
tsk_list_item_t;

/**@ingroup tsk_list_group
* A @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
*/
typedef struct tsk_list_s
{
	TSK_DECLARE_OBJECT;
	
	tsk_list_item_t* head; /**< The head of the linked list. */
	tsk_list_item_t* tail; /**< The tail of the linked list. */
	tsk_mutex_handle_t* mutex; /**< on-demand mutex. */
}
tsk_list_t;

/**@ingroup tsk_list_group 
* Function predicate used to match an item. <br />
* For example, see @ref _Anchor_TinySAK_Linked_List_Find_Items "here" for more information on how to use this function to find items.
* @param item The current item to match.
* @param data Arbitrary data holding the data to compare.
* @return 0 if match, <0 if first<second, >0 otherwise.
*/
typedef int (*tsk_list_func_predicate)(const tsk_list_item_t* item, const void* data);


/**@ingroup tsk_list_group
* @def tsk_list_foreach
* Loop through the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list". <br />
* For example, see @ref _Anchor_TinySAK_Linked_List_Dump_Items "here" for more information on how to use this function.
* @param item The current tsk_list_item_t "item".
* @param list Pointer to the @ref tsk_list_t "list" for which we want to get items.
*/
#define tsk_list_foreach(item, list) for(item = list ? list->head : tsk_null; item; item = item->next)

TINYSAK_API tsk_list_t* tsk_list_create();
TINYSAK_API tsk_list_item_t* tsk_list_item_create();

TINYSAK_API int tsk_list_lock(tsk_list_t* list);
TINYSAK_API int tsk_list_unlock(tsk_list_t* list);


/**@ingroup tsk_list_group
* @def tsk_list_remove_first_item
* Removes the first tsk_list_item_t "item" from a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list". @ref tsk_object_unref() will be called on the data held by the item.
* @param list The @ref tsk_list_t "list" from which to remove the item.
*/
/**@ingroup tsk_list_group
* @def tsk_list_remove_last_item
* Removes the last tsk_list_item_t "item" from a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list". @ref tsk_object_unref() will be called on the data held by the item.
* @param list The @ref tsk_list_t "list" from which to remove the item.
*/
TINYSAK_API tsk_bool_t tsk_list_remove_item(tsk_list_t* list, tsk_list_item_t* item);
#define tsk_list_remove_first_item(list) tsk_list_remove_item((list), (list) ? (list)->head : tsk_null)
#define tsk_list_remove_last_item(list) tsk_list_remove_item((list), (list) ? (list)->tail : tsk_null)
TINYSAK_API tsk_list_item_t* tsk_list_pop_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj);
TINYSAK_API tsk_bool_t tsk_list_remove_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj);
TINYSAK_API tsk_bool_t tsk_list_remove_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data);
TINYSAK_API tsk_list_item_t* tsk_list_pop_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data);
TINYSAK_API void tsk_list_clear_items(tsk_list_t* list);


/**@ingroup tsk_list_group
* @def tsk_list_push_back_item
* Adds a new tsk_list_item_t "item" at the end of the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref tsk_list_t "list" into which to add the item.
* @param item A reference (@ref tsk_list_item_t **) to the tsk_list_item_t "item" to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the item.
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_front_item
* Adds a new tsk_list_item_t "item" at the beginning of the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" into which to add the item. Must be a @ref tsk_list_t object.
* @param item A reference (@ref tsk_list_item_t **) to the item to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the item.
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_ascending_item
* Inserts a new item in a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" while keeping the list in ascending order. Note that this function will not sort the list if it's not already sorted. <br />
* For more information on how to sort items check @ref _Anchor_TinySAK_Linked_List_Sort_Items "here".
* @param list The @ref tsk_list_t "list" into which to insert the item.
* @param item The @ref tsk_list_item_t "item" to insert.
* @sa @ref tsk_list_push_descending_item()
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_descending_item
* Inserts a new item in a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" while keeping the list in descending order. Note that this function will not sort the list if it's not already sorted. <br />
* For more information on how to sort items check @ref _Anchor_TinySAK_Linked_List_Sort_Items "here".
* @param list The @ref tsk_list_t "list" into which to insert the item.
* @param item The @ref tsk_list_item_t "item" to insert.
* @sa @ref tsk_list_push_ascending_item()
*/
TINYSAK_API tsk_list_item_t* tsk_list_pop_first_item(tsk_list_t* list);
TINYSAK_API void tsk_list_push_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t back);
#define tsk_list_push_back_item(list, item) tsk_list_push_item(list, item, tsk_true)
#define tsk_list_push_front_item(list, item) tsk_list_push_item(list, item, tsk_false)
TINYSAK_API void tsk_list_push_filtered_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t ascending);
#define tsk_list_push_ascending_item(list, item) tsk_list_pushfiltered_item(list, item, tsk_true)
#define tsk_list_push_descending_item(list, item) tsk_list_pushfiltered_item(list, item, tsk_false)

/**@ingroup tsk_list_group
* @def tsk_list_pushback_list
* Inserts all items from one @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" at the end of another one. The reference counter for all items to be added will be incremented (+1). <br />
* For more information on how to add items check @ref _Anchor_TinySAK_Linked_List_Add_Remove "here".
* @param destination The destination @ref tsk_list_t "list" into which to insert the items.
* @param source The source @ref tsk_list_t "list" from which to get the items to be inserted in @a destination.
* @sa @ref tsk_list_pushfront_list()
*/
/**@ingroup tsk_list_group
* @def tsk_list_pushfront_list
* Inserts all items from one @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" at the beginning of another one. The reference counter for all items to be added will be incremented (+1). <br />
* For more information on how to add items check @ref _Anchor_TinySAK_Linked_List_Add_Remove "here".
* @param destination The destination @ref tsk_list_t "list" into which to insert the items.
* @param source The source @ref tsk_list_t "list" from which to get the items to be inserted in @a destination.
* @sa @ref tsk_list_pushback_list()
*/
TINYSAK_API int tsk_list_push_list(tsk_list_t* destination, const tsk_list_t* source, tsk_bool_t back);
#define tsk_list_pushback_list(destination, source) tsk_list_push_list(destination, source, tsk_true)
#define tsk_list_pushfront_list(destination, source) tsk_list_push_list(destination, source, tsk_false)

/**@ingroup tsk_list_group
* @def tsk_list_push_back_data
* Adds a new @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object at the end of the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref tsk_list_t "list" into which to add the object.
* @param tskobj A reference (@ref tsk_object_t **) to the @ref tsk_object_t "object" to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the object.
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_front_data
* Adds a new @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object at the beginning of the @ref _Page_TinySAK_AnsiC_Linked_List "linked-list".
* @param list The @ref tsk_list_t "list" into which to add the object.
* @param tskobj A reference (@ref tsk_object_t **) to the @ref tsk_object_t "object" to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the object.
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_ascending_data
* Inserts a new @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" object in a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" while keeping the list in ascending order. Note that this function will not sort the list if it's not already sorted. <br />
* For more information on how to insert items check @ref _Anchor_TinySAK_Linked_List_Add_Remove "here".
* @param list The @ref tsk_list_t "list" into which to insert the item.
* @param tskobj A reference (@ref tsk_object_t **) to the @ref tsk_object_t "object" to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the object.
* @sa @ref tsk_list_push_descending_data()
*/
/**@ingroup tsk_list_group
* @def tsk_list_push_descending_data
* Inserts a new @ref _Page_TinySAK_AnsiC_Object_Programming "well-defined" in a @ref _Page_TinySAK_AnsiC_Linked_List "linked-list" while keeping the list in descending order. Note that this function will not sort the list if it's not already sorted. <br />
* For more information on how to insert items check @ref _Anchor_TinySAK_Linked_List_Add_Remove "here".
* @param list The @ref tsk_list_t "list" into which to insert the item.
* @param tskobj A reference (@ref tsk_object_t **) to the @ref tsk_object_t "object" to add. The reference will be stolen (set to @ref tsk_null). You must increment the reference counter using @ref tsk_object_ref() if you want to continue to use the object.
* @sa @ref tsk_list_push_ascending_data()
*/

TINYSAK_API int tsk_list_push_data(tsk_list_t* list, tsk_object_t** tskobj, tsk_bool_t back);
#define tsk_list_push_back_data(list, data) tsk_list_push_data(list, data, tsk_true)
#define tsk_list_push_front_data(list, data) tsk_list_push_data(list, data, tsk_false)
TINYSAK_API int tsk_list_push_filtered_data(tsk_list_t* list, tsk_object_t** tskobj, tsk_bool_t ascending);
#define tsk_list_push_ascending_data(list, tskobj) tsk_list_push_filtered_data(list, tskobj, tsk_true)
#define tsk_list_push_descending_data(list, tskobj) tsk_list_push_filtered_data(list, tskobj, tsk_false)

TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_data(const tsk_list_t* list, const tsk_object_t * tskobj);
TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
TINYSAK_API const tsk_object_t* tsk_list_find_object_by_data(const tsk_list_t* list, const tsk_object_t* tskobj);
TINYSAK_API const tsk_object_t* tsk_list_find_object_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
TINYSAK_API const tsk_object_t* tsk_list_find_object_by_pred_at_index(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data, tsk_size_t index);
TINYSAK_API int tsk_list_find_index_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);

TINYSAK_API tsk_list_t* tsk_list_clone(const tsk_list_t* list);

TINYSAK_API tsk_size_t tsk_list_count(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
#define tsk_list_count_all(list) tsk_list_count((list), tsk_null, tsk_null)

TINYSAK_GEXTERN const tsk_object_def_t *tsk_list_def_t;
TINYSAK_GEXTERN const tsk_object_def_t *tsk_list_item_def_t;


TSK_END_DECLS

#endif /* _TINYSAK_LIST_H_ */

OpenPOWER on IntegriCloud