Mstdlib-1.24.0
m_llist.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_LLIST_H__
25#define __M_LLIST_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_sort.h>
32
33/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
34
35__BEGIN_DECLS
36
37/*! \defgroup m_llist Linked List
38 * \ingroup m_datastructures
39 */
40
41/*! \addtogroup m_llist_generic Linked List (Generic)
42 * \ingroup m_llist
43 * Linked list for storing values.
44 *
45 * This should not be used directly. It is a base implementation that should
46 * be used by a type safe wrapper. For example: M_llist_str.
47 *
48 * The list can uses a set of callback functions to determine behavior. Such
49 * as if it should duplicate or free values.
50 *
51 * The list can be used in multiple ways:
52 * - Unsorted.
53 * - Sorted.
54 * - Queue (FIFO) (really just unsorted).
55 * - Priority Queue (really just sorted).
56 *
57 * A linked list is not indexable. Iteration and find are supported.
58 *
59 * Sorted notes:
60 * - Sorting is implemented as a skip list. This should provide near O(long(n)) performance.
61 * Performance nearing a sorted M_list_t.
62 * - Sorting is stable. If an element with a matching value is already in the list then it
63 * will be inserted after. Find will always find the first matching element in the list.
64 * - The Skip List implementation does not use a fixed maximum level size (a fixed maximum
65 * number of elements). The level cap will be increased when the number of elements
66 * increases past the optimum number of elements for a given level count.
67 * - Level growth is bounded to one more than the current number of levels unless that
68 * would exceed the cap for the current number of elements.
69 * - When removing elements any empty levels will be removed.
70 *
71 * @{
72 */
73
74struct M_llist;
75typedef struct M_llist M_llist_t;
76
77struct M_llist_node;
78typedef struct M_llist_node M_llist_node_t;
79
80
81/*! Function definition to duplicate a value. */
82typedef void *(*M_llist_duplicate_func)(const void *);
83
84
85/*! Function definition to free a value. */
86typedef void (*M_llist_free_func)(void *);
87
88
89/*! Structure of callbacks that can be registered to override default
90 * behavior for llist implementation. */
92 M_sort_compar_t equality; /*!< Callback to check if two items in the list are equal.
93 If NULL unsorted list */
94 M_llist_duplicate_func duplicate_insert; /*!< Callback to duplicate a value on insert.
95 If NULL is pass-thru pointer */
96 M_llist_duplicate_func duplicate_copy; /*!< Callback to duplicate a value on copy.
97 If NULL is pass-thru pointer */
98 M_llist_free_func value_free; /*!< Callback to free a value.
99 If NULL is pass-thru pointer */
100};
101
102
103/*! Flags for controlling the behavior of the list. */
104typedef enum {
105 M_LLIST_NONE = 0, /*!< LList mode (unsorted). */
106 M_LLIST_SORTED = 1 << 0, /*!< Whether the data in the list should be kept in sorted order. callbacks cannot
107 be NULL and the equality function must be set if this is M_TRUE. */
108 M_LLIST_CIRCULAR = 1 << 1 /*!< Whether the nodes are linked in a circular manner. Last node points to first.
109 This cannot be used while sorted. */
111
112
113/*! Type of matching that should be used when searching/modifying a value in the list. */
114typedef enum {
115 M_LLIST_MATCH_VAL = 0, /*!< Match based on the value (equality function). */
116 M_LLIST_MATCH_PTR = 1 << 0, /*!< Math the pointer itself. */
117 M_LLIST_MATCH_ALL = 1 << 1 /*!< Include all instances. */
119
120
121/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
122
123/*! Create a new list.
124 *
125 * A list is a linked list. The list can be, optionally, kept in sorted
126 * order. The sorted order is determined by the equality callback function if
127 * sorting is enabled.
128 *
129 * \param[in] callbacks Register callbacks for overriding default behavior. May pass NULL
130 * if not overriding default behavior.
131 * \param[in] flags M_llist_flags_t flags controlling behavior.
132 *
133 * \return Allocated linked list.
134 *
135 * \see M_llist_destroy
136 */
137M_API M_llist_t *M_llist_create(const struct M_llist_callbacks *callbacks, M_uint32 flags) M_MALLOC;
138
139
140/*! Use the provided callback and thunk for sorting.
141 *
142 * \warning
143 * This function will only succeed if the original linked list was created with sort enabled (M_LLIST_SORTED),
144 * and no items have been added to the list yet.
145 *
146 * \param d the llist to update
147 * \param equality_cb callback that should be used for sorting
148 * \param equality_thunk thunk to pass to callback, may be \c NULL. Ownership of thunk remains with caller.
149 * \return M_TRUE on success, M_FALSE if error
150 */
151M_API M_bool M_llist_change_sorting(M_llist_t *d, M_sort_compar_t equality_cb, void *equality_thunk);
152
153
154/*! Destroy the list.
155 *
156 * \param[in] d The llist to destory.
157 * \param[in] destroy_vals Whether the values held in the list should be destroyed.
158 * If the list is not duplicating the values it holds then
159 * destroying values may not be desirable.
160 */
161M_API void M_llist_destroy(M_llist_t *d, M_bool destroy_vals) M_FREE(1);
162
163
164/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
165
166/*! Insert a value into the list.
167 *
168 * If sorted the value will be inserted in sorted order. Otherwise it will be
169 * appended to the end of the list.
170 *
171 * \param[in,out] d The list.
172 * \param[in] val The value to insert.
173 *
174 * \return Pointer to M_llist_node_t container object of new node on success,
175 * otherwise NULL.
176 *
177 * \see M_llist_insert_first
178 */
179M_API M_llist_node_t *M_llist_insert(M_llist_t *d, const void *val);
180
181
182/*! Insert a value into the list as the first node.
183 *
184 * Only applies to unsorted lists.
185 *
186 * \param[in,out] d The list.
187 * \param[in] val The value to insert.
188 *
189 * \return Pointer to M_llist_node_t container object of new node on success,
190 * otherwise NULL
191 *
192 * \see M_llist_insert
193 */
195
196
197/*! Insert a value into the list before a given node.
198 *
199 * Only applies to unsorted lists.
200 *
201 * \param[in,out] n The node to insert before. Cannot be NULL.
202 * \param[in] val The value to insert.
203 *
204 * \return Pointer to M_llist_node_t container object of new node on success,
205 * otherwise NULL
206 *
207 * \see M_llist_insert_after
208 */
210
211
212/*! Insert a value into the list after a given node.
213 *
214 * Only applies to unsorted lists.
215 *
216 * \param[in,out] n The node to insert after. Cannot be NULL.
217 * \param[in] val The value to insert.
218 *
219 * \return Pointer to M_llist_node_t container object of new node on success,
220 * otherwise NULL
221 *
222 * \see M_llist_insert_before
223 */
225
226
227/*! Set the node as the first node.
228 *
229 * Only applies to unsorted or circular lists.
230 *
231 * \param[in] n The node that should be considered first.
232 */
234
235
236/*! Set the node as the last node.
237 *
238 * Only applies to unsorted or circular lists.
239 *
240 * \param[in] n The node that should be considered last.
241 */
243
244
245/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
246
247/*! Move a node before another node in the list.
248 *
249 * \param[in] move The node to move.
250 * \param[in] before The node that move should be placed before.
251 *
252 * \return M_TRUE on sucess, otherwise M_FALSE.
253 */
255
256
257/*! Move a node after another node in the list.
258 *
259 * \param[in] move The node to move.
260 * \param[in] after The node that move should be placed after.
261 *
262 * \return M_TRUE on sucess, otherwise M_FALSE.
263 */
265
266
267/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
268
269/*! The length of the list.
270 *
271 * \param[in] d The list.
272 *
273 * \return the length of the list.
274 */
275M_API size_t M_llist_len(const M_llist_t *d);
276
277
278/*! Count the number of times a value occurs in the list.
279 *
280 * \param[in] d The list.
281 * \param[in] val The value to search for.
282 * \param[in] type M_llist_match_type_t type of how the val should be matched.
283 * valid values are:
284 * - M_LLIST_MATCH_VAL
285 * - M_LLIST_MATCH_PTR
286 *
287 * \return The number of times val appears in the list.
288 */
289M_API size_t M_llist_count(const M_llist_t *d, const void *val, M_uint32 type);
290
291
292/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
293
294/*! Get the first node in the list.
295 *
296 * \param[in] d The list.
297 *
298 * \return Node or NULL.
299 *
300 * \see M_llist_last
301 * \see M_llist_find
302 */
304
305
306/*! Get the last node in the list.
307 *
308 * \param[in] d The list.
309 *
310 * \return Node or NULL.
311 *
312 * \see M_llist_first
313 * \see M_llist_find
314 */
316
317
318/*! Find a node for the given value in the list.
319 *
320 * \param[in] d The list.
321 * \param[in] val The value to search for.
322 * \param[in] type M_llist_match_type_t type of how the val should be matched.
323 * valid values are:
324 * - M_LLIST_MATCH_VAL
325 * - M_LLIST_MATCH_PTR
326 *
327 * \return Node or NULL.
328 *
329 * \see M_llist_first
330 * \see M_llist_last
331 */
332M_API M_llist_node_t *M_llist_find(const M_llist_t *d, const void *val, M_uint32 type);
333
334
335/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
336
337/*! Take the node from the list and return its value.
338 *
339 * The element will be removed from the list and its value returned. The caller is
340 * responsible for freeing the value.
341 *
342 * \param[in] n The node.
343 *
344 * \return The node's value.
345 *
346 * \see M_llist_node_val
347 */
349
350
351/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
352
353/*! Remove a node from the list.
354 *
355 * The value will be free'd using the value_free callback.
356 *
357 * \param[in] n The node.
358 *
359 * \return M_TRUE on success otherwise M_FALSE.
360 *
361 * \see M_llist_remove_val
362 */
364
365
366/*! Remove node(s) from the list matching a given value.
367 *
368 * The value will be free'd using the value_free callback.
369 *
370 * \param[in,out] d The list.
371 * \param[in] val The value to search for.
372 * \param[in] type M_llist_match_type_t type of how the val should be matched.
373 * valid values are:
374 * - M_LLIST_MATCH_VAL
375 * - M_LLIST_MATCH_PTR
376 * - M_LLIST_MATCH_ALL
377 *
378 * \return M_TRUE on success otherwise M_FALSE.
379 *
380 * \see M_llist_remove_node
381 */
382M_API size_t M_llist_remove_val(M_llist_t *d, const void *val, M_uint32 type);
383
384
385/*! Remove duplicate values from the list.
386 *
387 * Requires the equality callback to be set.
388 * The values will be free'd using the value_free callback.
389 *
390 * \param[in] d The list.
391 * \param[in] type M_llist_match_type_t type of how the val should be matched.
392 * valid values are:
393 * - M_LLIST_MATCH_VAL
394 * - M_LLIST_MATCH_PTR
395 */
396M_API void M_llist_remove_duplicates(M_llist_t *d, M_uint32 type);
397
398
399/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
400
401/*! Get the next node, the one after a given node.
402 *
403 * \param[in] n The node.
404 *
405 * \return Node or NULL.
406 *
407 * \see M_llist_node_prev
408 */
410
411
412/*! Get the previous node, the one before a given node.
413 *
414 * \param[in] n The node.
415 *
416 * \return Node or NULL.
417 *
418 * \see M_llist_node_next
419 */
421
422
423/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
424
425/*! Get the value for a node.
426 *
427 * \param[in] n The node.
428 *
429 * \return The node's value.
430 *
431 * \see M_llist_take_node
432 */
433M_API void *M_llist_node_val(const M_llist_node_t *n);
434
435
436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
437
438/*! Duplicate an existing list. Will copy all elements of the list as well as
439 * any callbacks, etc.
440 *
441 * \param[in] d list to duplicate.
442 *
443 * \return New list.
444 */
445M_API M_llist_t *M_llist_duplicate(const M_llist_t *d) M_MALLOC;
446
447
448/*! Merge two lists together.
449 *
450 * The second (src) list will be destroyed automatically upon completion of this function. Any value pointers for the
451 * list will be directly copied over to the destination list, they will not be duplicated.
452 *
453 * \param[in,out] dest Pointer by reference to the list receiving the values.
454 * if this is NULL, the pointer will simply be switched out for src.
455 * \param[in,out] src Pointer to the list giving up its values.
456 * \param[in] include_duplicates When M_TRUE any values in 'dest' that also exist in
457 * 'src' will be included in 'dest'. When M_FALSE any
458 * duplicate values will not be added to 'dest'.
459 * \param[in] type M_llist_match_type_t type of how the val should be matched.
460 * valid values are:
461 * - M_LLIST_MATCH_VAL
462 * - M_LLIST_MATCH_PTR
463 */
464M_API void M_llist_merge(M_llist_t **dest, M_llist_t *src, M_bool include_duplicates, M_uint32 type) M_FREE(2);
465
466/*! @} */
467
468__END_DECLS
469
470#endif /* __M_LLIST_H__ */
M_llist_duplicate_func duplicate_copy
Definition: m_llist.h:96
M_sort_compar_t equality
Definition: m_llist.h:92
M_llist_duplicate_func duplicate_insert
Definition: m_llist.h:94
M_llist_free_func value_free
Definition: m_llist.h:98
M_llist_node_t * M_llist_node_prev(const M_llist_node_t *n)
M_llist_node_t * M_llist_insert_after(M_llist_node_t *n, const void *val)
M_llist_node_t * M_llist_insert_first(M_llist_t *d, const void *val)
M_bool M_llist_move_after(M_llist_node_t *move, M_llist_node_t *after)
struct M_llist M_llist_t
Definition: m_llist.h:75
M_llist_node_t * M_llist_node_next(const M_llist_node_t *n)
void(* M_llist_free_func)(void *)
Definition: m_llist.h:86
M_llist_node_t * M_llist_insert_before(M_llist_node_t *n, const void *val)
size_t M_llist_count(const M_llist_t *d, const void *val, M_uint32 type)
void M_llist_set_last(M_llist_node_t *n)
M_llist_node_t * M_llist_find(const M_llist_t *d, const void *val, M_uint32 type)
size_t M_llist_len(const M_llist_t *d)
void *(* M_llist_duplicate_func)(const void *)
Definition: m_llist.h:82
void M_llist_merge(M_llist_t **dest, M_llist_t *src, M_bool include_duplicates, M_uint32 type) M_FREE(2)
M_bool M_llist_change_sorting(M_llist_t *d, M_sort_compar_t equality_cb, void *equality_thunk)
void M_llist_destroy(M_llist_t *d, M_bool destroy_vals) M_FREE(1)
M_llist_node_t * M_llist_last(const M_llist_t *d)
M_llist_node_t * M_llist_insert(M_llist_t *d, const void *val)
M_llist_flags_t
Definition: m_llist.h:104
M_llist_t * M_llist_create(const struct M_llist_callbacks *callbacks, M_uint32 flags) M_MALLOC
struct M_llist_node M_llist_node_t
Definition: m_llist.h:78
M_bool M_llist_move_before(M_llist_node_t *move, M_llist_node_t *before)
M_llist_t * M_llist_duplicate(const M_llist_t *d) M_MALLOC
void M_llist_set_first(M_llist_node_t *n)
void M_llist_remove_duplicates(M_llist_t *d, M_uint32 type)
M_llist_match_type_t
Definition: m_llist.h:114
void * M_llist_take_node(M_llist_node_t *n)
size_t M_llist_remove_val(M_llist_t *d, const void *val, M_uint32 type)
M_llist_node_t * M_llist_first(const M_llist_t *d)
M_bool M_llist_remove_node(M_llist_node_t *n)
void * M_llist_node_val(const M_llist_node_t *n)
@ M_LLIST_NONE
Definition: m_llist.h:105
@ M_LLIST_CIRCULAR
Definition: m_llist.h:108
@ M_LLIST_SORTED
Definition: m_llist.h:106
@ M_LLIST_MATCH_PTR
Definition: m_llist.h:116
@ M_LLIST_MATCH_VAL
Definition: m_llist.h:115
@ M_LLIST_MATCH_ALL
Definition: m_llist.h:117
Definition: m_llist.h:91
int(* M_sort_compar_t)(const void *arg1, const void *arg2, void *thunk)
Definition: m_sort.h:78